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
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEFp3rbAvDxGAT0sefEacuoBRx13IFAl6hu14ACgkQEacuoBRx
 13KESg//SGOW6MigYFT+b/kl7rfhcvYn+iQQApsPu8a8uRBZHmzo/7Hb/a+UHScZ
 m8s7UW8ddoDo0lZ2iBD1P5Gns4Uu/iMJ1kdztOJtsUqDDfx8G71Qhty3yOuCRcsJ
 Q85i6MPitRSDbLm/lWOasf+N0C99HK52xf1AUHF5jqY3ITqEKM8I3lzZdWL+M3ab
 RkZbSYMGLq/szOY+9G8xquvIsfKRzdn7ATI6IbGUssBsASTKu1j46EbrqWKcdA+E
 MwVVCIf/yvnfhMsx26sKeRcedx15sFpDwjg044hFjv3nfmPYfvlGy7HGpidhqxn5
 c1mRxaEI/oUr934XaNop0HqR9+0UbyY2f8x0Ely3N4pVcKOuHGqNKWU1kBfw8R3j
 TkNB2o6yzwFtfIRR6W49MNUFZGYw4xDOuq5HUmAeJvMN8oVadrAD5Ar7HsYHgrLA
 tqyYlyp1tvmIksHrl2gef+qugixTyFo0l3puEl8XaAV8AoSb723MO63lz8CxQY4+
 Nqqi/g+YVUNnZRdstkBCoD9VdZ+XObLi1Hp5wum2ceP7TeWTn0W2TbN0lVT+XNfP
 nIDKwgs+QB6uXQHV0AwkpENVhD2/6yQqbWZlz3LKfbAsE9ECKPA3++6f5sgtuNh5
 bPznzav0tAB5fdHAGByY4LkJIsExwUxOE9TbVICZF47SXM93rqw=
 =/p1V
 -----END PGP SIGNATURE-----

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
This commit is contained in:
Linus Walleij 2020-04-28 13:38:47 +02:00
commit 8312d50b3f
2 changed files with 27 additions and 4 deletions

View File

@ -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);

View File

@ -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;