提交 3a7c114d 编写于 作者: L Linus Torvalds

Merge tag 'gpio-v4.7-3' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio

Pull GPIO fixes from Linus Walleij:
 "A new bunch of GPIO fixes for v4.7.

  This time I am very grateful that Ricardo Ribalda Delgado went in and
  fixed my stupid refcounting mistakes in the removal path for GPIO
  chips.  I had a feeling something was wrong here and so it was.  It
  exploded on OMAP and it fixes their problem.  Now it should be (more)
  solid.

  The rest i compilation, Kconfig and driver fixes.  Some tagged for
  stable.

  Summary:

   - Fix a NULL pointer dereference when we are searching the GPIO
     device list but one of the devices have been removed (struct
     gpio_chip pointer is NULL).

   - Fix unaligned reference counters: we were ending on +3 after all
     said and done.  It should be 0.  Remove an extraneous get_device(),
     and call cdev_del() followed by device_del() in gpiochip_remove()
     instead and the count goes to zero and calls the release() function
     properly.

   - Fix a compile warning due to a missing #include in the OF/device
     tree portions.

   - Select ANON_INODES for GPIOLIB, we're using that for our character
     device.  Some randconfig tests disclosed the problem.

   - Make sure the Zynq driver clock runs also without CONFIG_PM enabled

   - Fix an off-by-one error in the 104-DIO-48E driver

   - Fix warnings in bcm_kona_gpio_reset()"

* tag 'gpio-v4.7-3' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio:
  gpio: bcm-kona: fix bcm_kona_gpio_reset() warnings
  gpio: select ANON_INODES
  gpio: include <linux/io-mapping.h> in gpiolib-of
  gpiolib: Fix unaligned used of reference counters
  gpiolib: Fix NULL pointer deference
  gpio: zynq: initialize clock even without CONFIG_PM
  gpio: 104-dio-48e: Fix control port offset computation off-by-one error
...@@ -33,6 +33,7 @@ config ARCH_REQUIRE_GPIOLIB ...@@ -33,6 +33,7 @@ config ARCH_REQUIRE_GPIOLIB
menuconfig GPIOLIB menuconfig GPIOLIB
bool "GPIO Support" bool "GPIO Support"
select ANON_INODES
help help
This enables GPIO support through the generic GPIO library. This enables GPIO support through the generic GPIO library.
You only need to enable this, if you also want to enable You only need to enable this, if you also want to enable
......
...@@ -75,7 +75,7 @@ static int dio48e_gpio_direction_input(struct gpio_chip *chip, unsigned offset) ...@@ -75,7 +75,7 @@ static int dio48e_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
{ {
struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip); struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip);
const unsigned io_port = offset / 8; const unsigned io_port = offset / 8;
const unsigned control_port = io_port / 2; const unsigned int control_port = io_port / 3;
const unsigned control_addr = dio48egpio->base + 3 + control_port*4; const unsigned control_addr = dio48egpio->base + 3 + control_port*4;
unsigned long flags; unsigned long flags;
unsigned control; unsigned control;
...@@ -115,7 +115,7 @@ static int dio48e_gpio_direction_output(struct gpio_chip *chip, unsigned offset, ...@@ -115,7 +115,7 @@ static int dio48e_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
{ {
struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip); struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip);
const unsigned io_port = offset / 8; const unsigned io_port = offset / 8;
const unsigned control_port = io_port / 2; const unsigned int control_port = io_port / 3;
const unsigned mask = BIT(offset % 8); const unsigned mask = BIT(offset % 8);
const unsigned control_addr = dio48egpio->base + 3 + control_port*4; const unsigned control_addr = dio48egpio->base + 3 + control_port*4;
const unsigned out_port = (io_port > 2) ? io_port + 1 : io_port; const unsigned out_port = (io_port > 2) ? io_port + 1 : io_port;
......
...@@ -547,11 +547,11 @@ static void bcm_kona_gpio_reset(struct bcm_kona_gpio *kona_gpio) ...@@ -547,11 +547,11 @@ static void bcm_kona_gpio_reset(struct bcm_kona_gpio *kona_gpio)
/* disable interrupts and clear status */ /* disable interrupts and clear status */
for (i = 0; i < kona_gpio->num_bank; i++) { for (i = 0; i < kona_gpio->num_bank; i++) {
/* Unlock the entire bank first */ /* Unlock the entire bank first */
bcm_kona_gpio_write_lock_regs(kona_gpio, i, UNLOCK_CODE); bcm_kona_gpio_write_lock_regs(reg_base, i, UNLOCK_CODE);
writel(0xffffffff, reg_base + GPIO_INT_MASK(i)); writel(0xffffffff, reg_base + GPIO_INT_MASK(i));
writel(0xffffffff, reg_base + GPIO_INT_STATUS(i)); writel(0xffffffff, reg_base + GPIO_INT_STATUS(i));
/* Now re-lock the bank */ /* Now re-lock the bank */
bcm_kona_gpio_write_lock_regs(kona_gpio, i, LOCK_CODE); bcm_kona_gpio_write_lock_regs(reg_base, i, LOCK_CODE);
} }
} }
......
...@@ -709,7 +709,13 @@ static int zynq_gpio_probe(struct platform_device *pdev) ...@@ -709,7 +709,13 @@ static int zynq_gpio_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "input clock not found.\n"); dev_err(&pdev->dev, "input clock not found.\n");
return PTR_ERR(gpio->clk); return PTR_ERR(gpio->clk);
} }
ret = clk_prepare_enable(gpio->clk);
if (ret) {
dev_err(&pdev->dev, "Unable to enable clock.\n");
return ret;
}
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev); pm_runtime_enable(&pdev->dev);
ret = pm_runtime_get_sync(&pdev->dev); ret = pm_runtime_get_sync(&pdev->dev);
if (ret < 0) if (ret < 0)
...@@ -747,6 +753,7 @@ static int zynq_gpio_probe(struct platform_device *pdev) ...@@ -747,6 +753,7 @@ static int zynq_gpio_probe(struct platform_device *pdev)
pm_runtime_put(&pdev->dev); pm_runtime_put(&pdev->dev);
err_pm_dis: err_pm_dis:
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
clk_disable_unprepare(gpio->clk);
return ret; return ret;
} }
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/io-mapping.h>
#include <linux/gpio/consumer.h> #include <linux/gpio/consumer.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_address.h> #include <linux/of_address.h>
......
...@@ -449,7 +449,6 @@ static void gpiodevice_release(struct device *dev) ...@@ -449,7 +449,6 @@ static void gpiodevice_release(struct device *dev)
{ {
struct gpio_device *gdev = dev_get_drvdata(dev); struct gpio_device *gdev = dev_get_drvdata(dev);
cdev_del(&gdev->chrdev);
list_del(&gdev->list); list_del(&gdev->list);
ida_simple_remove(&gpio_ida, gdev->id); ida_simple_remove(&gpio_ida, gdev->id);
kfree(gdev->label); kfree(gdev->label);
...@@ -482,7 +481,6 @@ static int gpiochip_setup_dev(struct gpio_device *gdev) ...@@ -482,7 +481,6 @@ static int gpiochip_setup_dev(struct gpio_device *gdev)
/* From this point, the .release() function cleans up gpio_device */ /* From this point, the .release() function cleans up gpio_device */
gdev->dev.release = gpiodevice_release; gdev->dev.release = gpiodevice_release;
get_device(&gdev->dev);
pr_debug("%s: registered GPIOs %d to %d on device: %s (%s)\n", pr_debug("%s: registered GPIOs %d to %d on device: %s (%s)\n",
__func__, gdev->base, gdev->base + gdev->ngpio - 1, __func__, gdev->base, gdev->base + gdev->ngpio - 1,
dev_name(&gdev->dev), gdev->chip->label ? : "generic"); dev_name(&gdev->dev), gdev->chip->label ? : "generic");
...@@ -770,6 +768,8 @@ void gpiochip_remove(struct gpio_chip *chip) ...@@ -770,6 +768,8 @@ void gpiochip_remove(struct gpio_chip *chip)
* be removed, else it will be dangling until the last user is * be removed, else it will be dangling until the last user is
* gone. * gone.
*/ */
cdev_del(&gdev->chrdev);
device_del(&gdev->dev);
put_device(&gdev->dev); put_device(&gdev->dev);
} }
EXPORT_SYMBOL_GPL(gpiochip_remove); EXPORT_SYMBOL_GPL(gpiochip_remove);
...@@ -869,7 +869,7 @@ struct gpio_chip *gpiochip_find(void *data, ...@@ -869,7 +869,7 @@ struct gpio_chip *gpiochip_find(void *data,
spin_lock_irqsave(&gpio_lock, flags); spin_lock_irqsave(&gpio_lock, flags);
list_for_each_entry(gdev, &gpio_devices, list) list_for_each_entry(gdev, &gpio_devices, list)
if (match(gdev->chip, data)) if (gdev->chip && match(gdev->chip, data))
break; break;
/* No match? */ /* No match? */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册