Date: Sat, 16 Sep 2017 14:08:20 +0000 (UTC) From: Emmanuel Vadot <manu@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r323639 - head/sys/arm/allwinner Message-ID: <201709161408.v8GE8KEX090093@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: manu Date: Sat Sep 16 14:08:20 2017 New Revision: 323639 URL: https://svnweb.freebsd.org/changeset/base/323639 Log: Allwinner: a10_gpio Fix panic on multiple lock r323392 introduce gpio_pin_get/gpio_pin_set for a10_gpio driver. When called via gpio method they must aquire the device lock while when they are called via gpio_pin_configure the lock is already aquire. Introduce a10_gpio_pin_{s,g}et_locked and call them in pin_gpio_configure instead. Tested On: BananaPi (A20) Reported by: Richard Puga richard@puga.net Modified: head/sys/arm/allwinner/a10_gpio.c Modified: head/sys/arm/allwinner/a10_gpio.c ============================================================================== --- head/sys/arm/allwinner/a10_gpio.c Sat Sep 16 13:49:26 2017 (r323638) +++ head/sys/arm/allwinner/a10_gpio.c Sat Sep 16 14:08:20 2017 (r323639) @@ -197,6 +197,8 @@ struct a10_gpio_softc { static int a10_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *value); static int a10_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value); +static int a10_gpio_pin_get_locked(struct a10_gpio_softc *sc, uint32_t pin, unsigned int *value); +static int a10_gpio_pin_set_locked(struct a10_gpio_softc *sc, uint32_t pin, unsigned int value); #define A10_GPIO_WRITE(_sc, _off, _val) \ bus_space_write_4(_sc->sc_bst, _sc->sc_bsh, _off, _val) @@ -333,15 +335,15 @@ a10_gpio_pin_configure(struct a10_gpio_softc *sc, uint err = a10_gpio_set_function(sc, pin, A10_GPIO_INPUT); } else if (flags & GPIO_PIN_OUTPUT) { if (flags & GPIO_PIN_PRESET_LOW) { - a10_gpio_pin_set(sc->sc_dev, pin, 0); + a10_gpio_pin_set_locked(sc, pin, 0); } else if (flags & GPIO_PIN_PRESET_HIGH) { - a10_gpio_pin_set(sc->sc_dev, pin, 1); + a10_gpio_pin_set_locked(sc, pin, 1); } else { /* Read the pin and preset output to current state. */ err = a10_gpio_set_function(sc, pin, A10_GPIO_INPUT); if (err == 0) { - a10_gpio_pin_get(sc->sc_dev, pin, &val); - a10_gpio_pin_set(sc->sc_dev, pin, val); + a10_gpio_pin_get_locked(sc, pin, &val); + a10_gpio_pin_set_locked(sc, pin, val); } } if (err == 0) @@ -473,49 +475,77 @@ a10_gpio_pin_setflags(device_t dev, uint32_t pin, uint } static int -a10_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value) +a10_gpio_pin_set_locked(struct a10_gpio_softc *sc, uint32_t pin, + unsigned int value) { - struct a10_gpio_softc *sc; uint32_t bank, data; - sc = device_get_softc(dev); + A10_GPIO_LOCK_ASSERT(sc); + if (pin > sc->padconf->npins) return (EINVAL); bank = sc->padconf->pins[pin].port; pin = sc->padconf->pins[pin].pin; - A10_GPIO_LOCK(sc); data = A10_GPIO_READ(sc, A10_GPIO_GP_DAT(bank)); if (value) data |= (1 << pin); else data &= ~(1 << pin); A10_GPIO_WRITE(sc, A10_GPIO_GP_DAT(bank), data); - A10_GPIO_UNLOCK(sc); return (0); } static int -a10_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val) +a10_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value) { struct a10_gpio_softc *sc; - uint32_t bank, reg_data; + int ret; sc = device_get_softc(dev); + + A10_GPIO_LOCK(sc); + ret = a10_gpio_pin_set_locked(sc, pin, value); + A10_GPIO_UNLOCK(sc); + + return (ret); +} + +static int +a10_gpio_pin_get_locked(struct a10_gpio_softc *sc,uint32_t pin, + unsigned int *val) +{ + uint32_t bank, reg_data; + + A10_GPIO_LOCK_ASSERT(sc); + if (pin > sc->padconf->npins) return (EINVAL); bank = sc->padconf->pins[pin].port; pin = sc->padconf->pins[pin].pin; - A10_GPIO_LOCK(sc); reg_data = A10_GPIO_READ(sc, A10_GPIO_GP_DAT(bank)); - A10_GPIO_UNLOCK(sc); *val = (reg_data & (1 << pin)) ? 1 : 0; return (0); +} + +static int +a10_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val) +{ + struct a10_gpio_softc *sc; + int ret; + + sc = device_get_softc(dev); + + A10_GPIO_LOCK(sc); + ret = a10_gpio_pin_get_locked(sc, pin, val); + A10_GPIO_UNLOCK(sc); + + return (ret); } static int
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201709161408.v8GE8KEX090093>