From 30bb6fb39e5c08b9db5bc592d6cbc9a5fc5e67a4 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 15 Jun 2015 13:31:33 +0200 Subject: [PATCH 1/8] gpio: Remove double "base" in comment Signed-off-by: Geert Uytterhoeven Signed-off-by: Linus Walleij --- include/linux/gpio/driver.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h index cc7ec129b329..c8393cd4d44f 100644 --- a/include/linux/gpio/driver.h +++ b/include/linux/gpio/driver.h @@ -45,7 +45,7 @@ struct seq_file; * @base: identifies the first GPIO number handled by this chip; * or, if negative during registration, requests dynamic ID allocation. * DEPRECATION: providing anything non-negative and nailing the base - * base offset of GPIO chips is deprecated. Please pass -1 as base to + * offset of GPIO chips is deprecated. Please pass -1 as base to * let gpiolib select the chip base in all possible cases. We want to * get rid of the static GPIO number space in the long run. * @ngpio: the number of GPIOs handled by this controller; the last GPIO From 2252607d327d5219a6331b50e6ec266d56402be0 Mon Sep 17 00:00:00 2001 From: Gregory Fong Date: Wed, 17 Jun 2015 18:00:40 -0700 Subject: [PATCH 2/8] gpio: brcmstb: fix null ptr dereference in driver remove If a failure occurs during probe, brcmstb_gpio_remove() is called. In remove, we call platform_get_drvdata(), but at the time of failure in the probe the driver data hadn't yet been set which leads to a NULL ptr dereference in the remove's list_for_each. Call platform_set_drvdata() and set up list head right after allocating the priv struct to both avoid the null pointer dereference that could occur today. To guard against potential future changes, check for null pointer in remove. Reported-by: Tim Ross Signed-off-by: Gregory Fong Signed-off-by: Linus Walleij --- drivers/gpio/gpio-brcmstb.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpio-brcmstb.c b/drivers/gpio/gpio-brcmstb.c index 7a3cb1fa0a76..4630a8133ea6 100644 --- a/drivers/gpio/gpio-brcmstb.c +++ b/drivers/gpio/gpio-brcmstb.c @@ -87,6 +87,15 @@ static int brcmstb_gpio_remove(struct platform_device *pdev) struct brcmstb_gpio_bank *bank; int ret = 0; + if (!priv) { + dev_err(&pdev->dev, "called %s without drvdata!\n", __func__); + return -EFAULT; + } + + /* + * You can lose return values below, but we report all errors, and it's + * more important to actually perform all of the steps. + */ list_for_each(pos, &priv->bank_list) { bank = list_entry(pos, struct brcmstb_gpio_bank, node); ret = bgpio_remove(&bank->bgc); @@ -143,6 +152,8 @@ static int brcmstb_gpio_probe(struct platform_device *pdev) priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; + platform_set_drvdata(pdev, priv); + INIT_LIST_HEAD(&priv->bank_list); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); reg_base = devm_ioremap_resource(dev, res); @@ -153,7 +164,6 @@ static int brcmstb_gpio_probe(struct platform_device *pdev) priv->reg_base = reg_base; priv->pdev = pdev; - INIT_LIST_HEAD(&priv->bank_list); if (brcmstb_gpio_sanity_check_banks(dev, np, res)) return -EINVAL; @@ -221,8 +231,6 @@ static int brcmstb_gpio_probe(struct platform_device *pdev) dev_info(dev, "Registered %d banks (GPIO(s): %d-%d)\n", priv->num_banks, priv->gpio_base, gpio_base - 1); - platform_set_drvdata(pdev, priv); - return 0; fail: From 977bd8a94c40851a843e9186b9eb823bdfa5ace2 Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Wed, 24 Jun 2015 17:54:17 +0300 Subject: [PATCH 3/8] gpio: omap: add missed spin_unlock_irqrestore in omap_gpio_irq_type Add missed spin_unlock_irqrestore in omap_gpio_irq_type when omap_set_gpio_triggering() is failed. It fixes static checker warning: drivers/gpio/gpio-omap.c:523 omap_gpio_irq_type() warn: inconsistent returns 'spin_lock:&bank->lock'. This fixes commit: 1562e4618ded ('gpio: omap: fix error handling in omap_gpio_irq_type') Reported-by: Javier Martinez Canillas Signed-off-by: Grygorii Strashko Signed-off-by: Linus Walleij --- drivers/gpio/gpio-omap.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index b0c57d505be7..a0ad8030a7ef 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -500,8 +500,10 @@ static int omap_gpio_irq_type(struct irq_data *d, unsigned type) spin_lock_irqsave(&bank->lock, flags); retval = omap_set_gpio_triggering(bank, offset, type); - if (retval) + if (retval) { + spin_unlock_irqrestore(&bank->lock, flags); goto error; + } omap_gpio_init_irq(bank, offset); if (!omap_gpio_is_input(bank, offset)) { spin_unlock_irqrestore(&bank->lock, flags); From 6b956af0807a88c79d53e0cb2a3170a2b03e3230 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 25 Jun 2015 10:29:19 +0200 Subject: [PATCH 4/8] gpio: zynq: Fix problem with unbalanced pm_runtime_enable Add missing pm_runtime_disabled to remove(). Error log: root@zynqmp:~# modprobe gpio_zynq root@zynqmp:~# lsmod Not tainted gpio_zynq 7086 0 - Live 0xffffffbffc00a000 root@zynqmp:~# rmmod gpio_zynq root@zynqmp:~# lsmod Not tainted root@zynqmp:~# modprobe gpio_zynq [ 246.924438] zynq-gpio ff0a0000.gpio: Unbalanced pm_runtime_enable! root@zynqmp:~# rmmod gpio_zynq root@zynqmp:~# lsmod Not tainted Signed-off-by: Michal Simek Reviewed-by: Alexandre Courbot Signed-off-by: Linus Walleij --- drivers/gpio/gpio-zynq.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c index 2e87c4b8da26..a78882389836 100644 --- a/drivers/gpio/gpio-zynq.c +++ b/drivers/gpio/gpio-zynq.c @@ -757,6 +757,7 @@ static int zynq_gpio_remove(struct platform_device *pdev) gpiochip_remove(&gpio->chip); clk_disable_unprepare(gpio->clk); device_set_wakeup_capable(&pdev->dev, 0); + pm_runtime_disable(&pdev->dev); return 0; } From 5b2c9121ef7cf9745f0c1df10544fd0ba6a6a38c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Teysseyre?= Date: Wed, 24 Jun 2015 09:19:45 +0200 Subject: [PATCH 5/8] gpio/xilinx: Use correct address when setting initial values. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit xgpio_save_regs() is used in this driver to setup the initial values of the registers in the hardware. The relevant registers at that time are: 0x0 -> channel 0 data (32 bits, one for each GPIO on this channel). 0x4 -> channel 0 tri, controls in/out status for each GPIO of this channel. 0x8 -> channel 1 data 0xC -> channel 1 tri gpio-xilinx.c defines these: XGPIO_DATA_OFFSET (0x0) XGPIO_TRI_OFFSET (0x4) XGPIO_CHANNEL_OFFSET 0x8 Before this patch, the "data" register value of channel 1 was written at 0x4 intead of 0x8 (overwriting the channel 0 "tri" register), and the "tri" register value for channel 1 was written at 0x8 instead of 0xC. Signed-off-by: Raphaël Teysseyre Reviewed-by: Michal Simek Reviewed-by: Alexandre Courbot Signed-off-by: Linus Walleij --- drivers/gpio/gpio-xilinx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/gpio-xilinx.c b/drivers/gpio/gpio-xilinx.c index 77fe5d3cb105..d5284dfe01fe 100644 --- a/drivers/gpio/gpio-xilinx.c +++ b/drivers/gpio/gpio-xilinx.c @@ -220,9 +220,9 @@ static void xgpio_save_regs(struct of_mm_gpio_chip *mm_gc) if (!chip->gpio_width[1]) return; - xgpio_writereg(mm_gc->regs + XGPIO_DATA_OFFSET + XGPIO_TRI_OFFSET, + xgpio_writereg(mm_gc->regs + XGPIO_DATA_OFFSET + XGPIO_CHANNEL_OFFSET, chip->gpio_state[1]); - xgpio_writereg(mm_gc->regs + XGPIO_TRI_OFFSET + XGPIO_TRI_OFFSET, + xgpio_writereg(mm_gc->regs + XGPIO_TRI_OFFSET + XGPIO_CHANNEL_OFFSET, chip->gpio_dir[1]); } From 34ab54edbef902f31842b428dce9530f3283847c Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 30 Jun 2015 20:04:18 +0200 Subject: [PATCH 6/8] gpio: max732x: Add missing dev reference to gpiochip In case the gpiochip doesn't have the .dev field set, as is the case in here, it is not possible to reference this device in DT as a GPIO controller. A good example of this problem is that gpio-leds can not be used when connected to this chip, the gpio-leds driver bails out with -EPROBE_DEFER. Fix this problem by setting the .dev field of the gpio_chip to the parent i2c device. Signed-off-by: Marek Vasut Cc: Alexandre Courbot Cc: Linus Walleij Cc: Mans Rullgard Cc: Olaf Mandel Cc: Semen Protsenko Signed-off-by: Linus Walleij --- drivers/gpio/gpio-max732x.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpio/gpio-max732x.c b/drivers/gpio/gpio-max732x.c index aed4ca9338bc..7d3c90e9da71 100644 --- a/drivers/gpio/gpio-max732x.c +++ b/drivers/gpio/gpio-max732x.c @@ -603,6 +603,7 @@ static int max732x_setup_gpio(struct max732x_chip *chip, gc->base = gpio_start; gc->ngpio = port; gc->label = chip->client->name; + gc->dev = &chip->client->dev; gc->owner = THIS_MODULE; return port; From c23837ce73a0cb84ab046a6c0aace30fdd1e26f0 Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Thu, 25 Jun 2015 18:13:33 +0300 Subject: [PATCH 7/8] gpio: omap: prevent module from being unloaded while in use OMAP GPIO driver allowed to be built as loadable module, but it doesn't set owner field in GPIO chip structure. As result, module_get/put() API is not working and it's possible to unload OMAP driver while in use: omap_gpio 48051000.gpio: REMOVING GPIOCHIP WITH GPIOS STILL REQUESTED Hence, add missing configuration. Cc: Tony Lindgren Fixes: cac089f9026e ('gpio: omap: Allow building as a loadable module') Signed-off-by: Grygorii Strashko Acked-by: Alexandre Courbot Signed-off-by: Linus Walleij --- drivers/gpio/gpio-omap.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index a0ad8030a7ef..61a731ff9a07 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -1187,6 +1187,7 @@ static int omap_gpio_probe(struct platform_device *pdev) bank->irq = res->start; bank->dev = dev; bank->chip.dev = dev; + bank->chip.owner = THIS_MODULE; bank->dbck_flag = pdata->dbck_flag; bank->stride = pdata->bank_stride; bank->width = pdata->bank_width; From fdd50409c8b9ce4cdd757ce10bf2e39e9c172de6 Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Tue, 7 Jul 2015 17:34:49 +0300 Subject: [PATCH 8/8] gpio: pca953x: fix nested irqs rescheduling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pca953x interrupt controller functionality is implemented using nested threaded IRQs which require parent_irq to be configured properly otherwise below warning can be seen if IRQ core will try re-schedule nested IRQ: ------------[ cut here ]------------ WARNING: CPU: 1 PID: 12 at kernel/irq/manage.c:696 irq_nested_primary_handler+0x30/0x38() Primary handler called for nested irq 301 Modules linked in: uinput ipv6 smsc95xx usbnet mii imx2_wdt etnaviv(C) matrix_keypad matrix_keymap ar1021_i2c CPU: 1 PID: 12 Comm: ksoftirqd/1 Tainted: G WC 4.1.1 #9 Hardware name: Freescale i.MX6 Quad/DualLite (Device Tree) Backtrace: [] (dump_backtrace) from [] (show_stack+0x20/0x24) [] (show_stack) from [] (dump_stack+0x70/0xc0) [] (dump_stack) from [] (warn_slowpath_common+0x88/0xc0) [] (warn_slowpath_common) from [] (warn_slowpath_fmt+0x40/0x48) [] (warn_slowpath_fmt) from [] (irq_nested_primary_handler+0x30/0x38) [] (irq_nested_primary_handler) from [] (handle_irq_event_percpu+0x70/0x2d0) [] (handle_irq_event_percpu) from [] (handle_irq_event+0x4c/0x6c) [] (handle_irq_event) from [] (handle_simple_irq+0xa4/0xc8) [] (handle_simple_irq) from [] (resend_irqs+0x50/0x7c) [] (resend_irqs) from [] (tasklet_action+0x94/0x140) [] (tasklet_action) from [] (__do_softirq+0xa0/0x3c8) [] (__do_softirq) from [] (run_ksoftirqd+0x38/0x54) [] (run_ksoftirqd) from [] (smpboot_thread_fn+0x1f8/0x2f0) [] (smpboot_thread_fn) from [] (kthread+0xe8/0x104) [] (kthread) from [] (ret_from_fork+0x14/0x2c) ---[ end trace 96052cda48865769 ]--- The issue was reported and described in details by Lothar Waßmann and Christian Gmeiner in https://lkml.org/lkml/2014/9/9/123. Fix it by adding missed call of gpiochip_set_chained_irqchip() so GPIO IRQ chip helpers will set parent_irq for nested IRQs properly. Reported-by: Lothar Waßmann Tested-by: Christian Gmeiner Signed-off-by: Grygorii Strashko Signed-off-by: Linus Walleij --- drivers/gpio/gpio-pca953x.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index d233eb3b8132..50caeb1ee350 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -570,6 +570,10 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, "could not connect irqchip to gpiochip\n"); return ret; } + + gpiochip_set_chained_irqchip(&chip->gpio_chip, + &pca953x_irq_chip, + client->irq, NULL); } return 0;