From owner-svn-src-head@freebsd.org Sat Sep 16 14:08:21 2017 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 63D89E18BAB; Sat, 16 Sep 2017 14:08:21 +0000 (UTC) (envelope-from manu@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 3DFF17743E; Sat, 16 Sep 2017 14:08:21 +0000 (UTC) (envelope-from manu@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v8GE8K14090094; Sat, 16 Sep 2017 14:08:20 GMT (envelope-from manu@FreeBSD.org) Received: (from manu@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v8GE8KEX090093; Sat, 16 Sep 2017 14:08:20 GMT (envelope-from manu@FreeBSD.org) Message-Id: <201709161408.v8GE8KEX090093@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: manu set sender to manu@FreeBSD.org using -f From: Emmanuel Vadot Date: Sat, 16 Sep 2017 14:08:20 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r323639 - head/sys/arm/allwinner X-SVN-Group: head X-SVN-Commit-Author: manu X-SVN-Commit-Paths: head/sys/arm/allwinner X-SVN-Commit-Revision: 323639 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 16 Sep 2017 14:08:21 -0000 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