Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/gpio Before trying to attach a child device driver, ...



details:   https://anonhg.NetBSD.org/src/rev/1180cd623daa
branches:  trunk
changeset: 746847:1180cd623daa
user:      mbalmer <mbalmer%NetBSD.org@localhost>
date:      Fri Aug 21 12:53:42 2009 +0000

description:
Before trying to attach a child device driver, make sure the GPIO pins can
be mapped.  This prevents drivers from later failing in the attach routine.
Problem found by me, solution suggested by jmcneill.

diffstat:

 sys/dev/gpio/gpio.c    |  35 ++++++++++++++++++++++++++++++++---
 sys/dev/gpio/gpiovar.h |   3 ++-
 2 files changed, 34 insertions(+), 4 deletions(-)

diffs (81 lines):

diff -r 05a4bd9939fa -r 1180cd623daa sys/dev/gpio/gpio.c
--- a/sys/dev/gpio/gpio.c       Fri Aug 21 10:01:25 2009 +0000
+++ b/sys/dev/gpio/gpio.c       Fri Aug 21 12:53:42 2009 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: gpio.c,v 1.26 2009/08/17 12:44:44 mbalmer Exp $ */
+/* $NetBSD: gpio.c,v 1.27 2009/08/21 12:53:42 mbalmer Exp $ */
 /*     $OpenBSD: gpio.c,v 1.6 2006/01/14 12:33:49 grange Exp $ */
 
 /*
@@ -19,7 +19,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: gpio.c,v 1.26 2009/08/17 12:44:44 mbalmer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: gpio.c,v 1.27 2009/08/21 12:53:42 mbalmer Exp $");
 
 /*
  * General Purpose Input/Output framework.
@@ -217,6 +217,30 @@
        return UNCONF;
 }
 
+/* return 1 if all pins can be mapped, 0 if not */
+
+int
+gpio_pin_can_map(void *gpio, int offset, u_int32_t mask)
+{
+       struct gpio_softc *sc = gpio;
+       int npins, pin, i;
+
+       npins = gpio_npins(mask);
+       if (npins > sc->sc_npins)
+               return 0;
+
+       for (npins = 0, i = 0; i < 32; i++)
+               if (mask & (1 << i)) {
+                       pin = offset + i;
+                       if (pin < 0 || pin >= sc->sc_npins)
+                               return 0;
+                       if (sc->sc_pins[pin].pin_mapped)
+                               return 0;
+               }
+
+       return 1;
+}
+
 int
 gpio_pin_map(void *gpio, int offset, u_int32_t mask, struct gpio_pinmap *map)
 {
@@ -483,8 +507,13 @@
                if (kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
                    NULL, NULL, NULL, NULL))
                        return EPERM;
-                        
+
                attach = (struct gpio_attach *)data;
+
+               /* do not try to attach if the pins are already mapped */
+               if (!gpio_pin_can_map(sc, attach->ga_offset, attach->ga_mask))
+                       return EBUSY;
+
                ga.ga_gpio = sc;
                ga.ga_dvname = attach->ga_dvname;
                ga.ga_offset = attach->ga_offset;
diff -r 05a4bd9939fa -r 1180cd623daa sys/dev/gpio/gpiovar.h
--- a/sys/dev/gpio/gpiovar.h    Fri Aug 21 10:01:25 2009 +0000
+++ b/sys/dev/gpio/gpiovar.h    Fri Aug 21 12:53:42 2009 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: gpiovar.h,v 1.9 2009/07/25 16:30:44 mbalmer Exp $ */
+/* $NetBSD: gpiovar.h,v 1.10 2009/08/21 12:53:42 mbalmer Exp $ */
 /*     $OpenBSD: gpiovar.h,v 1.3 2006/01/14 12:33:49 grange Exp $      */
 
 /*
@@ -88,6 +88,7 @@
        LIST_ENTRY(gpio_name)   gp_next;
 };
 
+int    gpio_pin_can_map(void *, int, u_int32_t);
 int    gpio_pin_map(void *, int, u_int32_t, struct gpio_pinmap *);
 void   gpio_pin_unmap(void *, struct gpio_pinmap *);
 int    gpio_pin_read(void *, struct gpio_pinmap *, int);



Home | Main Index | Thread Index | Old Index