Skip to content

Commit 7e8d852

Browse files
committed
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
2 parents 99e4472 + fbd0358 commit 7e8d852

5 files changed

Lines changed: 82 additions & 55 deletions

File tree

drivers/gpio/gpio-amd-fch.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
*
99
*/
1010

11+
#include <linux/bitfield.h>
1112
#include <linux/err.h>
1213
#include <linux/io.h>
1314
#include <linux/kernel.h>
@@ -120,15 +121,15 @@ static int amd_fch_gpio_get(struct gpio_chip *gc,
120121
unsigned int offset)
121122
{
122123
unsigned long flags;
123-
int ret;
124+
u32 val;
124125
struct amd_fch_gpio_priv *priv = gpiochip_get_data(gc);
125126
void __iomem *ptr = amd_fch_gpio_addr(priv, offset);
126127

127128
spin_lock_irqsave(&priv->lock, flags);
128-
ret = (readl_relaxed(ptr) & AMD_FCH_GPIO_FLAG_READ);
129+
val = readl_relaxed(ptr);
129130
spin_unlock_irqrestore(&priv->lock, flags);
130131

131-
return ret;
132+
return FIELD_GET(AMD_FCH_GPIO_FLAG_READ, val);
132133
}
133134

134135
static int amd_fch_gpio_request(struct gpio_chip *chip,

drivers/gpio/gpio-nomadik.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,9 @@ void nmk_gpio_dbg_show_one(struct seq_file *s, struct pinctrl_dev *pctldev,
430430
#ifdef CONFIG_PINCTRL_NOMADIK
431431
if (mode == NMK_GPIO_ALT_C && pctldev) {
432432
desc = gpio_device_get_desc(chip->gpiodev, offset);
433+
if (IS_ERR(desc))
434+
return;
435+
433436
mode = nmk_prcm_gpiocr_get_mode(pctldev, desc_to_gpio(desc));
434437
}
435438
#endif

drivers/gpio/gpiolib-cdev.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -388,7 +388,7 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip)
388388
fd_publish(fdf);
389389

390390
dev_dbg(&gdev->dev, "registered chardev handle for %d lines\n",
391-
lh->num_descs);
391+
handlereq.lines);
392392

393393
return 0;
394394
}

drivers/gpio/gpiolib-swnode.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,25 @@ static struct gpio_device *swnode_get_gpio_device(struct fwnode_handle *fwnode)
4242

4343
fwnode_lookup:
4444
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+
4564
return gdev ?: ERR_PTR(-EPROBE_DEFER);
4665
}
4766

drivers/gpio/gpiolib-sysfs.c

Lines changed: 55 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -919,63 +919,68 @@ int gpiod_export_link(struct device *dev, const char *name,
919919
}
920920
EXPORT_SYMBOL_GPL(gpiod_export_link);
921921

922-
/**
923-
* gpiod_unexport - reverse effect of gpiod_export()
924-
* @desc: GPIO to make unavailable
925-
*
926-
* This is implicit on gpiod_free().
927-
*/
928-
void gpiod_unexport(struct gpio_desc *desc)
922+
static void gpiod_unexport_unlocked(struct gpio_desc *desc)
929923
{
930924
struct gpiod_data *tmp, *desc_data = NULL;
931925
struct gpiodev_data *gdev_data;
932926
struct gpio_device *gdev;
933927

934-
if (!desc) {
935-
pr_warn("%s: invalid GPIO\n", __func__);
928+
if (!test_bit(GPIOD_FLAG_EXPORT, &desc->flags))
936929
return;
937-
}
938930

939-
scoped_guard(mutex, &sysfs_lock) {
940-
if (!test_bit(GPIOD_FLAG_EXPORT, &desc->flags))
941-
return;
942-
943-
gdev = gpiod_to_gpio_device(desc);
944-
gdev_data = gdev_get_data(gdev);
945-
if (!gdev_data)
946-
return;
931+
gdev = gpiod_to_gpio_device(desc);
932+
gdev_data = gdev_get_data(gdev);
933+
if (!gdev_data)
934+
return;
947935

948-
list_for_each_entry(tmp, &gdev_data->exported_lines, list) {
949-
if (gpiod_is_equal(desc, tmp->desc)) {
950-
desc_data = tmp;
951-
break;
952-
}
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;
953940
}
941+
}
954942

955-
if (!desc_data)
956-
return;
943+
if (!desc_data)
944+
return;
957945

958-
list_del(&desc_data->list);
959-
clear_bit(GPIOD_FLAG_EXPORT, &desc->flags);
946+
list_del(&desc_data->list);
947+
clear_bit(GPIOD_FLAG_EXPORT, &desc->flags);
960948
#if IS_ENABLED(CONFIG_GPIO_SYSFS_LEGACY)
961-
sysfs_put(desc_data->value_kn);
962-
device_unregister(desc_data->dev);
963-
964-
/*
965-
* Release irq after deregistration to prevent race with
966-
* edge_store.
967-
*/
968-
if (desc_data->irq_flags)
969-
gpio_sysfs_free_irq(desc_data);
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);
970958
#endif /* CONFIG_GPIO_SYSFS_LEGACY */
971959

972-
sysfs_remove_groups(desc_data->parent,
973-
desc_data->chip_attr_groups);
974-
}
960+
sysfs_remove_groups(desc_data->parent,
961+
desc_data->chip_attr_groups);
975962

976963
mutex_destroy(&desc_data->mutex);
977964
kfree(desc_data);
978965
}
966+
967+
/**
968+
* gpiod_unexport - reverse effect of gpiod_export()
969+
* @desc: GPIO to make unavailable
970+
*
971+
* This is implicit on gpiod_free().
972+
*/
973+
void gpiod_unexport(struct gpio_desc *desc)
974+
{
975+
if (!desc) {
976+
pr_warn("%s: invalid GPIO\n", __func__);
977+
return;
978+
}
979+
980+
guard(mutex)(&sysfs_lock);
981+
982+
gpiod_unexport_unlocked(desc);
983+
}
979984
EXPORT_SYMBOL_GPL(gpiod_unexport);
980985

981986
int gpiochip_sysfs_register(struct gpio_device *gdev)
@@ -1054,29 +1059,28 @@ void gpiochip_sysfs_unregister(struct gpio_device *gdev)
10541059
struct gpio_desc *desc;
10551060
struct gpio_chip *chip;
10561061

1057-
scoped_guard(mutex, &sysfs_lock) {
1058-
data = gdev_get_data(gdev);
1059-
if (!data)
1060-
return;
1062+
guard(mutex)(&sysfs_lock);
10611063

1062-
#if IS_ENABLED(CONFIG_GPIO_SYSFS_LEGACY)
1063-
device_unregister(data->cdev_base);
1064-
#endif /* CONFIG_GPIO_SYSFS_LEGACY */
1065-
device_unregister(data->cdev_id);
1066-
kfree(data);
1067-
}
1064+
data = gdev_get_data(gdev);
1065+
if (!data)
1066+
return;
10681067

10691068
guard(srcu)(&gdev->srcu);
1070-
10711069
chip = srcu_dereference(gdev->chip, &gdev->srcu);
10721070
if (!chip)
10731071
return;
10741072

10751073
/* unregister gpiod class devices owned by sysfs */
10761074
for_each_gpio_desc_with_flag(chip, desc, GPIOD_FLAG_SYSFS) {
1077-
gpiod_unexport(desc);
1075+
gpiod_unexport_unlocked(desc);
10781076
gpiod_free(desc);
10791077
}
1078+
1079+
#if IS_ENABLED(CONFIG_GPIO_SYSFS_LEGACY)
1080+
device_unregister(data->cdev_base);
1081+
#endif /* CONFIG_GPIO_SYSFS_LEGACY */
1082+
device_unregister(data->cdev_id);
1083+
kfree(data);
10801084
}
10811085

10821086
/*

0 commit comments

Comments
 (0)