Commit 8312d50b authored by Linus Walleij's avatar Linus Walleij
Browse files

Merge tag 'gpio-fixes-for-v5.7-rc3' of...

Merge tag 'gpio-fixes-for-v5.7-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux into fixes

gpio fixes for v5.7-rc3

- fix set_config in pca953x
- improve robustness of the new line watch/unwatch ioctl()
- fix a bug with caling a sleeping function with spinlock taken
parents ae83d0b4 6409d049
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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);

	switch (config) {
	switch (pinconf_to_config_param(config)) {
	case PIN_CONFIG_BIAS_PULL_UP:
	case PIN_CONFIG_BIAS_PULL_DOWN:
		return pca953x_gpio_set_pull_up_down(chip, offset, config);
+26 −3
Original line number Diff line number Diff line
@@ -1158,8 +1158,19 @@ static void gpio_desc_to_lineinfo(struct gpio_desc *desc,
				  struct gpioline_info *info)
{
	struct gpio_chip *gc = desc->gdev->chip;
	bool ok_for_pinctrl;
	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);

	if (desc->name) {
@@ -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_EXPORT, &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;
	if (test_bit(FLAG_IS_OUT, &desc->flags))
		info->flags |= GPIOLINE_FLAG_IS_OUT;
@@ -1227,6 +1238,7 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
	void __user *ip = (void __user *)arg;
	struct gpio_desc *desc;
	__u32 offset;
	int hwgpio;

	/* We fail any subsequent ioctl():s when the chip is gone */
	if (!gc)
@@ -1259,13 +1271,19 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
		if (IS_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);

		if (copy_to_user(ip, &lineinfo, sizeof(lineinfo)))
			return -EFAULT;

		if (cmd == GPIO_GET_LINEINFO_WATCH_IOCTL)
			set_bit(gpio_chip_hwgpio(desc), priv->watched_lines);
			set_bit(hwgpio, priv->watched_lines);

		return 0;
	} else if (cmd == GPIO_GET_LINEHANDLE_IOCTL) {
@@ -1280,7 +1298,12 @@ static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
		if (IS_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 -EINVAL;