From 20483d04ae6f373858f3ca28cd7e26b66106d937 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 13 Jul 2015 23:22:44 +0200 Subject: gpio/davinci: Fix race in installing chained irq handler Fix a race where a pending interrupt could be received and the handler called before the handler's data has been setup, by converting to irq_set_chained_handler_and_data(). Search and conversion was done with coccinelle. Reported-by: Russell King Signed-off-by: Thomas Gleixner Cc: Julia Lawall Cc: Linus Walleij Cc: Alexandre Courbot --- drivers/gpio/gpio-davinci.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c index c5e05c82d67c..c246ac3dda7c 100644 --- a/drivers/gpio/gpio-davinci.c +++ b/drivers/gpio/gpio-davinci.c @@ -578,15 +578,13 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev) writel_relaxed(~0, &g->clr_falling); writel_relaxed(~0, &g->clr_rising); - /* set up all irqs in this bank */ - irq_set_chained_handler(bank_irq, gpio_irq_handler); - /* * Each chip handles 32 gpios, and each irq bank consists of 16 * gpio irqs. Pass the irq bank's corresponding controller to * the chained irq handler. */ - irq_set_handler_data(bank_irq, &chips[gpio / 32]); + irq_set_chained_handler_and_data(bank_irq, gpio_irq_handler, + &chips[gpio / 32]); binten |= BIT(bank); } -- cgit v1.2.3-70-g09d2 From 2252607d327d5219a6331b50e6ec266d56402be0 Mon Sep 17 00:00:00 2001 From: Gregory Fong Date: Wed, 17 Jun 2015 18:00:40 -0700 Subject: 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(-) (limited to 'drivers/gpio') 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: -- cgit v1.2.3-70-g09d2 From 977bd8a94c40851a843e9186b9eb823bdfa5ace2 Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Wed, 24 Jun 2015 17:54:17 +0300 Subject: 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(-) (limited to 'drivers/gpio') 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); -- cgit v1.2.3-70-g09d2 From 6b956af0807a88c79d53e0cb2a3170a2b03e3230 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 25 Jun 2015 10:29:19 +0200 Subject: 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(+) (limited to 'drivers/gpio') 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; } -- cgit v1.2.3-70-g09d2 From 5b2c9121ef7cf9745f0c1df10544fd0ba6a6a38c Mon Sep 17 00:00:00 2001 From: Raphaël Teysseyre Date: Wed, 24 Jun 2015 09:19:45 +0200 Subject: 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(-) (limited to 'drivers/gpio') 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]); } -- cgit v1.2.3-70-g09d2 From 34ab54edbef902f31842b428dce9530f3283847c Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 30 Jun 2015 20:04:18 +0200 Subject: 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(+) (limited to 'drivers/gpio') 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; -- cgit v1.2.3-70-g09d2 From c23837ce73a0cb84ab046a6c0aace30fdd1e26f0 Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Thu, 25 Jun 2015 18:13:33 +0300 Subject: 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(+) (limited to 'drivers/gpio') 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; -- cgit v1.2.3-70-g09d2 From fdd50409c8b9ce4cdd757ce10bf2e39e9c172de6 Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Tue, 7 Jul 2015 17:34:49 +0300 Subject: 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(+) (limited to 'drivers/gpio') 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; -- cgit v1.2.3-70-g09d2