Commit 8ec91c0f authored by Linus Torvalds's avatar Linus Torvalds

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

Pull GPIO fixes from Linus Walleij:
 "Some GPIO fixes for v5.7, slightly overdue. Been learning MMUs and
  KASan that is why it's late. Bartosz helped me out, luckily!

   - Fix pin configuration in the PCA953x driver

   - Ruggedize the watch/unwatch ioctl()

   - Possible call to a sleeping function when holding a spinlock, avoid
     this

   - Fix UML builds with DT overlays

   - Mask Tegra GPIO IRQs during shutdown()"

* tag 'gpio-v5.7-2' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio:
  gpio: tegra: mask GPIO IRQs during IRQ shutdown
  gpio: of: Build fails if CONFIG_OF_DYNAMIC enabled without CONFIG_OF_GPIO
  gpiolib: don't call sleeping functions with a spinlock taken
  gpiolib: improve the robustness of watch/unwatch ioctl()
  gpio: pca953x: Fix pca953x_gpio_set_config
parents e719340f 0cf253ee
...@@ -531,7 +531,7 @@ static int pca953x_gpio_set_config(struct gpio_chip *gc, unsigned int offset, ...@@ -531,7 +531,7 @@ static int pca953x_gpio_set_config(struct gpio_chip *gc, unsigned int offset,
{ {
struct pca953x_chip *chip = gpiochip_get_data(gc); struct pca953x_chip *chip = gpiochip_get_data(gc);
switch (config) { switch (pinconf_to_config_param(config)) {
case PIN_CONFIG_BIAS_PULL_UP: case PIN_CONFIG_BIAS_PULL_UP:
case PIN_CONFIG_BIAS_PULL_DOWN: case PIN_CONFIG_BIAS_PULL_DOWN:
return pca953x_gpio_set_pull_up_down(chip, offset, config); return pca953x_gpio_set_pull_up_down(chip, offset, config);
......
...@@ -368,6 +368,7 @@ static void tegra_gpio_irq_shutdown(struct irq_data *d) ...@@ -368,6 +368,7 @@ static void tegra_gpio_irq_shutdown(struct irq_data *d)
struct tegra_gpio_info *tgi = bank->tgi; struct tegra_gpio_info *tgi = bank->tgi;
unsigned int gpio = d->hwirq; unsigned int gpio = d->hwirq;
tegra_gpio_irq_mask(d);
gpiochip_unlock_as_irq(&tgi->gc, gpio); gpiochip_unlock_as_irq(&tgi->gc, gpio);
} }
......
...@@ -1158,8 +1158,19 @@ static void gpio_desc_to_lineinfo(struct gpio_desc *desc, ...@@ -1158,8 +1158,19 @@ static void gpio_desc_to_lineinfo(struct gpio_desc *desc,
struct gpioline_info *info) struct gpioline_info *info)
{ {
struct gpio_chip *gc = desc->gdev->chip; struct gpio_chip *gc = desc->gdev->chip;
bool ok_for_pinctrl;
unsigned long flags; unsigned long flags;
/*
* This function takes a mutex so we must check this before taking
* the spinlock.
*
* FIXME: find a non-racy way to retrieve this information. Maybe a
* lock common to both frameworks?
*/
ok_for_pinctrl =
pinctrl_gpio_can_use_line(gc->base + info->line_offset);
spin_lock_irqsave(&gpio_lock, flags); spin_lock_irqsave(&gpio_lock, flags);
if (desc->name) { if (desc->name) {
...@@ -1186,7 +1197,7 @@ static void gpio_desc_to_lineinfo(struct gpio_desc *desc, ...@@ -1186,7 +1197,7 @@ static void gpio_desc_to_lineinfo(struct gpio_desc *desc,
test_bit(FLAG_USED_AS_IRQ, &desc->flags) || test_bit(FLAG_USED_AS_IRQ, &desc->flags) ||
test_bit(FLAG_EXPORT, &desc->flags) || test_bit(FLAG_EXPORT, &desc->flags) ||
test_bit(FLAG_SYSFS, &desc->flags) || test_bit(FLAG_SYSFS, &desc->flags) ||
!pinctrl_gpio_can_use_line(gc->base + info->line_offset)) !ok_for_pinctrl)
info->flags |= GPIOLINE_FLAG_KERNEL; info->flags |= GPIOLINE_FLAG_KERNEL;
if (test_bit(FLAG_IS_OUT, &desc->flags)) if (test_bit(FLAG_IS_OUT, &desc->flags))
info->flags |= GPIOLINE_FLAG_IS_OUT; info->flags |= GPIOLINE_FLAG_IS_OUT;
...@@ -1227,6 +1238,7 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ...@@ -1227,6 +1238,7 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
void __user *ip = (void __user *)arg; void __user *ip = (void __user *)arg;
struct gpio_desc *desc; struct gpio_desc *desc;
__u32 offset; __u32 offset;
int hwgpio;
/* We fail any subsequent ioctl():s when the chip is gone */ /* We fail any subsequent ioctl():s when the chip is gone */
if (!gc) if (!gc)
...@@ -1259,13 +1271,19 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ...@@ -1259,13 +1271,19 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
if (IS_ERR(desc)) if (IS_ERR(desc))
return PTR_ERR(desc); return PTR_ERR(desc);
hwgpio = gpio_chip_hwgpio(desc);
if (cmd == GPIO_GET_LINEINFO_WATCH_IOCTL &&
test_bit(hwgpio, priv->watched_lines))
return -EBUSY;
gpio_desc_to_lineinfo(desc, &lineinfo); gpio_desc_to_lineinfo(desc, &lineinfo);
if (copy_to_user(ip, &lineinfo, sizeof(lineinfo))) if (copy_to_user(ip, &lineinfo, sizeof(lineinfo)))
return -EFAULT; return -EFAULT;
if (cmd == GPIO_GET_LINEINFO_WATCH_IOCTL) if (cmd == GPIO_GET_LINEINFO_WATCH_IOCTL)
set_bit(gpio_chip_hwgpio(desc), priv->watched_lines); set_bit(hwgpio, priv->watched_lines);
return 0; return 0;
} else if (cmd == GPIO_GET_LINEHANDLE_IOCTL) { } else if (cmd == GPIO_GET_LINEHANDLE_IOCTL) {
...@@ -1280,7 +1298,12 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ...@@ -1280,7 +1298,12 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
if (IS_ERR(desc)) if (IS_ERR(desc))
return PTR_ERR(desc); return PTR_ERR(desc);
clear_bit(gpio_chip_hwgpio(desc), priv->watched_lines); hwgpio = gpio_chip_hwgpio(desc);
if (!test_bit(hwgpio, priv->watched_lines))
return -EBUSY;
clear_bit(hwgpio, priv->watched_lines);
return 0; return 0;
} }
return -EINVAL; return -EINVAL;
...@@ -5289,8 +5312,9 @@ static int __init gpiolib_dev_init(void) ...@@ -5289,8 +5312,9 @@ static int __init gpiolib_dev_init(void)
gpiolib_initialized = true; gpiolib_initialized = true;
gpiochip_setup_devs(); gpiochip_setup_devs();
if (IS_ENABLED(CONFIG_OF_DYNAMIC)) #if IS_ENABLED(CONFIG_OF_DYNAMIC) && IS_ENABLED(CONFIG_OF_GPIO)
WARN_ON(of_reconfig_notifier_register(&gpio_of_notifier)); WARN_ON(of_reconfig_notifier_register(&gpio_of_notifier));
#endif /* CONFIG_OF_DYNAMIC && CONFIG_OF_GPIO */
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment