Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'gpio-fixes-for-v7.0-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux

Pull gpio fixes from Bartosz Golaszewski:

- add a missing IS_ERR() check in gpio-nomadik

- fix a NULL-pointer dereference in GPIO character device code

- restore label matching in swnode-lookup due to reported regressions
in existing users (this will get removed again once we audit and
update all drivers)

- fix remove path in GPIO sysfs code

- normalize the return value of gpio_chip::get() in gpio-amd-fch

* tag 'gpio-fixes-for-v7.0-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux:
gpio: amd-fch: ionly return allowed values from amd_fch_gpio_get()
gpio: sysfs: fix chip removal with GPIOs exported over sysfs
gpio: swnode: restore the swnode-name-against-chip-label matching
gpio: cdev: Avoid NULL dereference in linehandle_create()
gpio: nomadik: Add missing IS_ERR() check

+85 -58
+4 -3
drivers/gpio/gpio-amd-fch.c
··· 8 8 * 9 9 */ 10 10 11 + #include <linux/bitfield.h> 11 12 #include <linux/err.h> 12 13 #include <linux/io.h> 13 14 #include <linux/kernel.h> ··· 121 120 unsigned int offset) 122 121 { 123 122 unsigned long flags; 124 - int ret; 123 + u32 val; 125 124 struct amd_fch_gpio_priv *priv = gpiochip_get_data(gc); 126 125 void __iomem *ptr = amd_fch_gpio_addr(priv, offset); 127 126 128 127 spin_lock_irqsave(&priv->lock, flags); 129 - ret = (readl_relaxed(ptr) & AMD_FCH_GPIO_FLAG_READ); 128 + val = readl_relaxed(ptr); 130 129 spin_unlock_irqrestore(&priv->lock, flags); 131 130 132 - return ret; 131 + return FIELD_GET(AMD_FCH_GPIO_FLAG_READ, val); 133 132 } 134 133 135 134 static int amd_fch_gpio_request(struct gpio_chip *chip,
+3
drivers/gpio/gpio-nomadik.c
··· 430 430 #ifdef CONFIG_PINCTRL_NOMADIK 431 431 if (mode == NMK_GPIO_ALT_C && pctldev) { 432 432 desc = gpio_device_get_desc(chip->gpiodev, offset); 433 + if (IS_ERR(desc)) 434 + return; 435 + 433 436 mode = nmk_prcm_gpiocr_get_mode(pctldev, desc_to_gpio(desc)); 434 437 } 435 438 #endif
+1 -1
drivers/gpio/gpiolib-cdev.c
··· 388 388 fd_publish(fdf); 389 389 390 390 dev_dbg(&gdev->dev, "registered chardev handle for %d lines\n", 391 - lh->num_descs); 391 + handlereq.lines); 392 392 393 393 return 0; 394 394 }
+19
drivers/gpio/gpiolib-swnode.c
··· 42 42 43 43 fwnode_lookup: 44 44 gdev = gpio_device_find_by_fwnode(fwnode); 45 + if (!gdev && gdev_node && gdev_node->name) 46 + /* 47 + * FIXME: We shouldn't need to compare the GPIO controller's 48 + * label against the software node that is supposedly attached 49 + * to it. However there are currently GPIO users that - knowing 50 + * the expected label of the GPIO chip whose pins they want to 51 + * control - set up dummy software nodes named after those GPIO 52 + * controllers, which aren't actually attached to them. In this 53 + * case gpio_device_find_by_fwnode() will fail as no device on 54 + * the GPIO bus is actually associated with the fwnode we're 55 + * looking for. 56 + * 57 + * As a fallback: continue checking the label if we have no 58 + * match. However, the situation described above is an abuse 59 + * of the software node API and should be phased out and the 60 + * following line - eventually removed. 61 + */ 62 + gdev = gpio_device_find_by_label(gdev_node->name); 63 + 45 64 return gdev ?: ERR_PTR(-EPROBE_DEFER); 46 65 } 47 66
+58 -54
drivers/gpio/gpiolib-sysfs.c
··· 919 919 } 920 920 EXPORT_SYMBOL_GPL(gpiod_export_link); 921 921 922 + static void gpiod_unexport_unlocked(struct gpio_desc *desc) 923 + { 924 + struct gpiod_data *tmp, *desc_data = NULL; 925 + struct gpiodev_data *gdev_data; 926 + struct gpio_device *gdev; 927 + 928 + if (!test_bit(GPIOD_FLAG_EXPORT, &desc->flags)) 929 + return; 930 + 931 + gdev = gpiod_to_gpio_device(desc); 932 + gdev_data = gdev_get_data(gdev); 933 + if (!gdev_data) 934 + return; 935 + 936 + list_for_each_entry(tmp, &gdev_data->exported_lines, list) { 937 + if (gpiod_is_equal(desc, tmp->desc)) { 938 + desc_data = tmp; 939 + break; 940 + } 941 + } 942 + 943 + if (!desc_data) 944 + return; 945 + 946 + list_del(&desc_data->list); 947 + clear_bit(GPIOD_FLAG_EXPORT, &desc->flags); 948 + #if IS_ENABLED(CONFIG_GPIO_SYSFS_LEGACY) 949 + sysfs_put(desc_data->value_kn); 950 + device_unregister(desc_data->dev); 951 + 952 + /* 953 + * Release irq after deregistration to prevent race with 954 + * edge_store. 955 + */ 956 + if (desc_data->irq_flags) 957 + gpio_sysfs_free_irq(desc_data); 958 + #endif /* CONFIG_GPIO_SYSFS_LEGACY */ 959 + 960 + sysfs_remove_groups(desc_data->parent, 961 + desc_data->chip_attr_groups); 962 + 963 + mutex_destroy(&desc_data->mutex); 964 + kfree(desc_data); 965 + } 966 + 922 967 /** 923 968 * gpiod_unexport - reverse effect of gpiod_export() 924 969 * @desc: GPIO to make unavailable ··· 972 927 */ 973 928 void gpiod_unexport(struct gpio_desc *desc) 974 929 { 975 - struct gpiod_data *tmp, *desc_data = NULL; 976 - struct gpiodev_data *gdev_data; 977 - struct gpio_device *gdev; 978 - 979 930 if (!desc) { 980 931 pr_warn("%s: invalid GPIO\n", __func__); 981 932 return; 982 933 } 983 934 984 - scoped_guard(mutex, &sysfs_lock) { 985 - if (!test_bit(GPIOD_FLAG_EXPORT, &desc->flags)) 986 - return; 935 + guard(mutex)(&sysfs_lock); 987 936 988 - gdev = gpiod_to_gpio_device(desc); 989 - gdev_data = gdev_get_data(gdev); 990 - if (!gdev_data) 991 - return; 992 - 993 - list_for_each_entry(tmp, &gdev_data->exported_lines, list) { 994 - if (gpiod_is_equal(desc, tmp->desc)) { 995 - desc_data = tmp; 996 - break; 997 - } 998 - } 999 - 1000 - if (!desc_data) 1001 - return; 1002 - 1003 - list_del(&desc_data->list); 1004 - clear_bit(GPIOD_FLAG_EXPORT, &desc->flags); 1005 - #if IS_ENABLED(CONFIG_GPIO_SYSFS_LEGACY) 1006 - sysfs_put(desc_data->value_kn); 1007 - device_unregister(desc_data->dev); 1008 - 1009 - /* 1010 - * Release irq after deregistration to prevent race with 1011 - * edge_store. 1012 - */ 1013 - if (desc_data->irq_flags) 1014 - gpio_sysfs_free_irq(desc_data); 1015 - #endif /* CONFIG_GPIO_SYSFS_LEGACY */ 1016 - 1017 - sysfs_remove_groups(desc_data->parent, 1018 - desc_data->chip_attr_groups); 1019 - } 1020 - 1021 - mutex_destroy(&desc_data->mutex); 1022 - kfree(desc_data); 937 + gpiod_unexport_unlocked(desc); 1023 938 } 1024 939 EXPORT_SYMBOL_GPL(gpiod_unexport); 1025 940 ··· 1059 1054 struct gpio_desc *desc; 1060 1055 struct gpio_chip *chip; 1061 1056 1062 - scoped_guard(mutex, &sysfs_lock) { 1063 - data = gdev_get_data(gdev); 1064 - if (!data) 1065 - return; 1057 + guard(mutex)(&sysfs_lock); 1066 1058 1067 - #if IS_ENABLED(CONFIG_GPIO_SYSFS_LEGACY) 1068 - device_unregister(data->cdev_base); 1069 - #endif /* CONFIG_GPIO_SYSFS_LEGACY */ 1070 - device_unregister(data->cdev_id); 1071 - kfree(data); 1072 - } 1059 + data = gdev_get_data(gdev); 1060 + if (!data) 1061 + return; 1073 1062 1074 1063 guard(srcu)(&gdev->srcu); 1075 - 1076 1064 chip = srcu_dereference(gdev->chip, &gdev->srcu); 1077 1065 if (!chip) 1078 1066 return; 1079 1067 1080 1068 /* unregister gpiod class devices owned by sysfs */ 1081 1069 for_each_gpio_desc_with_flag(chip, desc, GPIOD_FLAG_SYSFS) { 1082 - gpiod_unexport(desc); 1070 + gpiod_unexport_unlocked(desc); 1083 1071 gpiod_free(desc); 1084 1072 } 1073 + 1074 + #if IS_ENABLED(CONFIG_GPIO_SYSFS_LEGACY) 1075 + device_unregister(data->cdev_base); 1076 + #endif /* CONFIG_GPIO_SYSFS_LEGACY */ 1077 + device_unregister(data->cdev_id); 1078 + kfree(data); 1085 1079 } 1086 1080 1087 1081 /*