* [PATCH 0/3] gpio: shared: close remaining gaps
@ 2025-12-22 10:01 Bartosz Golaszewski
2025-12-22 10:01 ` [PATCH 1/3] gpiolib: allow multiple lookup tables per consumer Bartosz Golaszewski
` (3 more replies)
0 siblings, 4 replies; 17+ messages in thread
From: Bartosz Golaszewski @ 2025-12-22 10:01 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski
Cc: linux-gpio, linux-kernel, Linus Walleij, Bartosz Golaszewski
This series fixes some remaining issues and corner-cases in the shared
GPIO management. In order to address multiple shared GPIOs per consumer
as well as the reset-gpio interaction, we need to support multiple
lookup tables per consumer device.
This is targetting v6.19 as it effectively fixes the code that went
upstream during the v6.19 merge window.
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
---
Bartosz Golaszewski (3):
gpiolib: allow multiple lookup tables per consumer
gpio: shared: verify con_id when adding proxy lookup
gpio: shared: allow sharing a reset-gpios pin between reset-gpio and gpiolib
drivers/gpio/gpiolib-shared.c | 187 ++++++++++++++++++++++++++++++------------
drivers/gpio/gpiolib-shared.h | 4 +-
drivers/gpio/gpiolib.c | 94 +++++++++++++--------
3 files changed, 195 insertions(+), 90 deletions(-)
---
base-commit: d97963ce4531fd378752953fdf076d12bcf98837
change-id: 20251203-gpio-shared-reset-gpio-proxy-ee3b722891db
Best regards,
--
Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
^ permalink raw reply [flat|nested] 17+ messages in thread* [PATCH 1/3] gpiolib: allow multiple lookup tables per consumer 2025-12-22 10:01 [PATCH 0/3] gpio: shared: close remaining gaps Bartosz Golaszewski @ 2025-12-22 10:01 ` Bartosz Golaszewski 2025-12-22 10:01 ` [PATCH 2/3] gpio: shared: verify con_id when adding proxy lookup Bartosz Golaszewski ` (2 subsequent siblings) 3 siblings, 0 replies; 17+ messages in thread From: Bartosz Golaszewski @ 2025-12-22 10:01 UTC (permalink / raw) To: Linus Walleij, Bartosz Golaszewski Cc: linux-gpio, linux-kernel, Linus Walleij, Bartosz Golaszewski The GPIO machine lookup mechanism dates back to old ARM board files where lookup tables would all be defined in a single place. Since then, lookup tables have also been used to address various DT and ACPI quirks like missing GPIOs and - as of recently - setting up shared GPIO proxy devices. The lookup itself stops when we find the first matching table for a consumer and - if it doesn't contain the right entry - the lookup fails. Since the tables can now be defined in multiple places and we can't know how many there are, effectively limiting a consumer to only a single lookup table is no longer viable. Rework the code to always look through all tables matching the consumer. Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com> --- drivers/gpio/gpiolib.c | 91 +++++++++++++++++++++++++++++++------------------- 1 file changed, 56 insertions(+), 35 deletions(-) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 91e0c384f34ae5c0ed61ccd3a978685d4f72e867..6d583b3b07bb5c3e5886ced53deca7cd02460890 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -4508,45 +4508,41 @@ void gpiod_remove_hogs(struct gpiod_hog *hogs) } EXPORT_SYMBOL_GPL(gpiod_remove_hogs); -static struct gpiod_lookup_table *gpiod_find_lookup_table(struct device *dev) +static bool gpiod_match_lookup_table(struct device *dev, + const struct gpiod_lookup_table *table) { const char *dev_id = dev ? dev_name(dev) : NULL; - struct gpiod_lookup_table *table; - list_for_each_entry(table, &gpio_lookup_list, list) { - if (table->dev_id && dev_id) { - /* - * Valid strings on both ends, must be identical to have - * a match - */ - if (!strcmp(table->dev_id, dev_id)) - return table; - } else { - /* - * One of the pointers is NULL, so both must be to have - * a match - */ - if (dev_id == table->dev_id) - return table; - } + lockdep_assert_held(&gpio_lookup_lock); + + if (table->dev_id && dev_id) { + /* + * Valid strings on both ends, must be identical to have + * a match + */ + if (!strcmp(table->dev_id, dev_id)) + return true; + } else { + /* + * One of the pointers is NULL, so both must be to have + * a match + */ + if (dev_id == table->dev_id) + return true; } - return NULL; + return false; } -static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id, - unsigned int idx, unsigned long *flags) +static struct gpio_desc *gpio_desc_table_match(struct device *dev, const char *con_id, + unsigned int idx, unsigned long *flags, + struct gpiod_lookup_table *table) { - struct gpio_desc *desc = ERR_PTR(-ENOENT); - struct gpiod_lookup_table *table; + struct gpio_desc *desc; struct gpiod_lookup *p; struct gpio_chip *gc; - guard(mutex)(&gpio_lookup_lock); - - table = gpiod_find_lookup_table(dev); - if (!table) - return desc; + lockdep_assert_held(&gpio_lookup_lock); for (p = &table->table[0]; p->key; p++) { /* idx must always match exactly */ @@ -4600,6 +4596,29 @@ static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id, return desc; } + return NULL; +} + +static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id, + unsigned int idx, unsigned long *flags) +{ + struct gpio_desc *desc = ERR_PTR(-ENOENT); + struct gpiod_lookup_table *table; + + guard(mutex)(&gpio_lookup_lock); + + list_for_each_entry(table, &gpio_lookup_list, list) { + if (!gpiod_match_lookup_table(dev, table)) + continue; + + desc = gpio_desc_table_match(dev, con_id, idx, flags, table); + if (!desc) + continue; + + /* On IS_ERR() or match. */ + return desc; + } + return desc; } @@ -4610,14 +4629,16 @@ static int platform_gpio_count(struct device *dev, const char *con_id) unsigned int count = 0; scoped_guard(mutex, &gpio_lookup_lock) { - table = gpiod_find_lookup_table(dev); - if (!table) - return -ENOENT; + list_for_each_entry(table, &gpio_lookup_list, list) { + if (!gpiod_match_lookup_table(dev, table)) + continue; - for (p = &table->table[0]; p->key; p++) { - if ((con_id && p->con_id && !strcmp(con_id, p->con_id)) || - (!con_id && !p->con_id)) - count++; + for (p = &table->table[0]; p->key; p++) { + if ((con_id && p->con_id && + !strcmp(con_id, p->con_id)) || + (!con_id && !p->con_id)) + count++; + } } } -- 2.47.3 ^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 2/3] gpio: shared: verify con_id when adding proxy lookup 2025-12-22 10:01 [PATCH 0/3] gpio: shared: close remaining gaps Bartosz Golaszewski 2025-12-22 10:01 ` [PATCH 1/3] gpiolib: allow multiple lookup tables per consumer Bartosz Golaszewski @ 2025-12-22 10:01 ` Bartosz Golaszewski 2025-12-22 10:01 ` [PATCH 3/3] gpio: shared: allow sharing a reset-gpios pin between reset-gpio and gpiolib Bartosz Golaszewski 2026-01-02 9:34 ` [PATCH 0/3] gpio: shared: close remaining gaps Bartosz Golaszewski 3 siblings, 0 replies; 17+ messages in thread From: Bartosz Golaszewski @ 2025-12-22 10:01 UTC (permalink / raw) To: Linus Walleij, Bartosz Golaszewski Cc: linux-gpio, linux-kernel, Linus Walleij, Bartosz Golaszewski When matching the firmware node with the potential consumer, we currently omit the con_id string. This can lead to false positives in the unlikely case of the consumer having been assigned more than one shared GPIO. Check the connector ID before proceeding. Fixes: a060b8c511ab ("gpiolib: implement low-level, shared GPIO support") Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com> --- drivers/gpio/gpiolib-shared.c | 7 ++++++- drivers/gpio/gpiolib-shared.h | 4 +++- drivers/gpio/gpiolib.c | 3 ++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/gpio/gpiolib-shared.c b/drivers/gpio/gpiolib-shared.c index ba4b718d40a087608fc06f59d242932df1d117e9..f589109590c7c6bc9c0c1828ea15ab9003846523 100644 --- a/drivers/gpio/gpiolib-shared.c +++ b/drivers/gpio/gpiolib-shared.c @@ -365,7 +365,8 @@ static bool gpio_shared_dev_is_reset_gpio(struct device *consumer, } #endif /* CONFIG_RESET_GPIO */ -int gpio_shared_add_proxy_lookup(struct device *consumer, unsigned long lflags) +int gpio_shared_add_proxy_lookup(struct device *consumer, const char *con_id, + unsigned long lflags) { const char *dev_id = dev_name(consumer); struct gpio_shared_entry *entry; @@ -384,6 +385,10 @@ int gpio_shared_add_proxy_lookup(struct device *consumer, unsigned long lflags) guard(mutex)(&ref->lock); + if ((!con_id && ref->con_id) || (con_id && !ref->con_id) || + (con_id && ref->con_id && strcmp(con_id, ref->con_id) != 0)) + continue; + /* We've already done that on a previous request. */ if (ref->lookup) return 0; diff --git a/drivers/gpio/gpiolib-shared.h b/drivers/gpio/gpiolib-shared.h index 667dbdff3585066b7cbe2ebe476725fe7d683d84..40568ef7364ccbf08b7f583e279a7d5b572af477 100644 --- a/drivers/gpio/gpiolib-shared.h +++ b/drivers/gpio/gpiolib-shared.h @@ -16,7 +16,8 @@ struct device; int gpio_device_setup_shared(struct gpio_device *gdev); void gpio_device_teardown_shared(struct gpio_device *gdev); -int gpio_shared_add_proxy_lookup(struct device *consumer, unsigned long lflags); +int gpio_shared_add_proxy_lookup(struct device *consumer, const char *con_id, + unsigned long lflags); #else @@ -28,6 +29,7 @@ static inline int gpio_device_setup_shared(struct gpio_device *gdev) static inline void gpio_device_teardown_shared(struct gpio_device *gdev) { } static inline int gpio_shared_add_proxy_lookup(struct device *consumer, + const char *con_id, unsigned long lflags) { return 0; diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 6d583b3b07bb5c3e5886ced53deca7cd02460890..9ccfb7af67cca61207e8479842b78942a22cb919 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -4717,7 +4717,8 @@ struct gpio_desc *gpiod_find_and_request(struct device *consumer, * lookup table for the proxy device as previously * we only knew the consumer's fwnode. */ - ret = gpio_shared_add_proxy_lookup(consumer, lookupflags); + ret = gpio_shared_add_proxy_lookup(consumer, con_id, + lookupflags); if (ret) return ERR_PTR(ret); -- 2.47.3 ^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 3/3] gpio: shared: allow sharing a reset-gpios pin between reset-gpio and gpiolib 2025-12-22 10:01 [PATCH 0/3] gpio: shared: close remaining gaps Bartosz Golaszewski 2025-12-22 10:01 ` [PATCH 1/3] gpiolib: allow multiple lookup tables per consumer Bartosz Golaszewski 2025-12-22 10:01 ` [PATCH 2/3] gpio: shared: verify con_id when adding proxy lookup Bartosz Golaszewski @ 2025-12-22 10:01 ` Bartosz Golaszewski [not found] ` <CGME20260105115023eucas1p1af1f8e80041f94843beb664966894fb9@eucas1p1.samsung.com> 2026-01-08 15:46 ` Mark Brown 2026-01-02 9:34 ` [PATCH 0/3] gpio: shared: close remaining gaps Bartosz Golaszewski 3 siblings, 2 replies; 17+ messages in thread From: Bartosz Golaszewski @ 2025-12-22 10:01 UTC (permalink / raw) To: Linus Walleij, Bartosz Golaszewski Cc: linux-gpio, linux-kernel, Linus Walleij, Bartosz Golaszewski We currently support sharing GPIOs between multiple devices whose drivers use either the GPIOLIB API *OR* the reset control API but not both at the same time. There's an unlikely corner-case where a reset-gpios pin can be shared by one driver using the GPIOLIB API and a second using the reset API. This will currently not work as the reset-gpio consumers are not described in firmware at the time of scanning so the shared GPIO just chooses one of the proxies created for the consumers when the reset-gpio driver performs the lookup. This can of course conflict in the case described above. In order to fix it: if we deal with the "reset-gpios" pin that's shared acconding to the firmware node setup, create a proxy for each described consumer as well as another one for the potential reset-gpio device. To that end: rework the matching to take this into account. Fixes: 7b78b26757e0 ("gpio: shared: handle the reset-gpios corner case") Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com> --- drivers/gpio/gpiolib-shared.c | 182 ++++++++++++++++++++++++++++++------------ 1 file changed, 129 insertions(+), 53 deletions(-) diff --git a/drivers/gpio/gpiolib-shared.c b/drivers/gpio/gpiolib-shared.c index f589109590c7c6bc9c0c1828ea15ab9003846523..baf7e07a3bb887dab8155078666a15779e304409 100644 --- a/drivers/gpio/gpiolib-shared.c +++ b/drivers/gpio/gpiolib-shared.c @@ -76,6 +76,56 @@ gpio_shared_find_entry(struct fwnode_handle *controller_node, return NULL; } +static struct gpio_shared_ref *gpio_shared_make_ref(struct fwnode_handle *fwnode, + const char *con_id, + enum gpiod_flags flags) +{ + char *con_id_cpy __free(kfree) = NULL; + + struct gpio_shared_ref *ref __free(kfree) = kzalloc(sizeof(*ref), GFP_KERNEL); + if (!ref) + return NULL; + + if (con_id) { + con_id_cpy = kstrdup(con_id, GFP_KERNEL); + if (!con_id_cpy) + return NULL; + } + + ref->dev_id = ida_alloc(&gpio_shared_ida, GFP_KERNEL); + if (ref->dev_id < 0) + return NULL; + + ref->flags = flags; + ref->con_id = no_free_ptr(con_id_cpy); + ref->fwnode = fwnode; + mutex_init(&ref->lock); + + return no_free_ptr(ref); +} + +static int gpio_shared_setup_reset_proxy(struct gpio_shared_entry *entry, + enum gpiod_flags flags) +{ + struct gpio_shared_ref *ref; + + list_for_each_entry(ref, &entry->refs, list) { + if (!ref->fwnode && ref->con_id && strcmp(ref->con_id, "reset") == 0) + return 0; + } + + ref = gpio_shared_make_ref(NULL, "reset", flags); + if (!ref) + return -ENOMEM; + + list_add_tail(&ref->list, &entry->refs); + + pr_debug("Created a secondary shared GPIO reference for potential reset-gpio device for GPIO %u at %s\n", + entry->offset, fwnode_get_name(entry->fwnode)); + + return 0; +} + /* Handle all special nodes that we should ignore. */ static bool gpio_shared_of_node_ignore(struct device_node *node) { @@ -106,6 +156,7 @@ static int gpio_shared_of_traverse(struct device_node *curr) size_t con_id_len, suffix_len; struct fwnode_handle *fwnode; struct of_phandle_args args; + struct gpio_shared_ref *ref; struct property *prop; unsigned int offset; const char *suffix; @@ -138,6 +189,7 @@ static int gpio_shared_of_traverse(struct device_node *curr) for (i = 0; i < count; i++) { struct device_node *np __free(device_node) = NULL; + char *con_id __free(kfree) = NULL; ret = of_parse_phandle_with_args(curr, prop->name, "#gpio-cells", i, @@ -182,15 +234,6 @@ static int gpio_shared_of_traverse(struct device_node *curr) list_add_tail(&entry->list, &gpio_shared_list); } - struct gpio_shared_ref *ref __free(kfree) = - kzalloc(sizeof(*ref), GFP_KERNEL); - if (!ref) - return -ENOMEM; - - ref->fwnode = fwnode_handle_get(of_fwnode_handle(curr)); - ref->flags = args.args[1]; - mutex_init(&ref->lock); - if (strends(prop->name, "gpios")) suffix = "-gpios"; else if (strends(prop->name, "gpio")) @@ -202,27 +245,32 @@ static int gpio_shared_of_traverse(struct device_node *curr) /* We only set con_id if there's actually one. */ if (strcmp(prop->name, "gpios") && strcmp(prop->name, "gpio")) { - ref->con_id = kstrdup(prop->name, GFP_KERNEL); - if (!ref->con_id) + con_id = kstrdup(prop->name, GFP_KERNEL); + if (!con_id) return -ENOMEM; - con_id_len = strlen(ref->con_id); + con_id_len = strlen(con_id); suffix_len = strlen(suffix); - ref->con_id[con_id_len - suffix_len] = '\0'; + con_id[con_id_len - suffix_len] = '\0'; } - ref->dev_id = ida_alloc(&gpio_shared_ida, GFP_KERNEL); - if (ref->dev_id < 0) { - kfree(ref->con_id); + ref = gpio_shared_make_ref(fwnode_handle_get(of_fwnode_handle(curr)), + con_id, args.args[1]); + if (!ref) return -ENOMEM; - } if (!list_empty(&entry->refs)) pr_debug("GPIO %u at %s is shared by multiple firmware nodes\n", entry->offset, fwnode_get_name(entry->fwnode)); - list_add_tail(&no_free_ptr(ref)->list, &entry->refs); + list_add_tail(&ref->list, &entry->refs); + + if (strcmp(prop->name, "reset-gpios") == 0) { + ret = gpio_shared_setup_reset_proxy(entry, args.args[1]); + if (ret) + return ret; + } } } @@ -306,20 +354,16 @@ static bool gpio_shared_dev_is_reset_gpio(struct device *consumer, struct fwnode_handle *reset_fwnode = dev_fwnode(consumer); struct fwnode_reference_args ref_args, aux_args; struct device *parent = consumer->parent; + struct gpio_shared_ref *real_ref; bool match; int ret; + lockdep_assert_held(&ref->lock); + /* The reset-gpio device must have a parent AND a firmware node. */ if (!parent || !reset_fwnode) return false; - /* - * FIXME: use device_is_compatible() once the reset-gpio drivers gains - * a compatible string which it currently does not have. - */ - if (!strstarts(dev_name(consumer), "reset.gpio.")) - return false; - /* * Parent of the reset-gpio auxiliary device is the GPIO chip whose * fwnode we stored in the entry structure. @@ -328,33 +372,56 @@ static bool gpio_shared_dev_is_reset_gpio(struct device *consumer, return false; /* - * The device associated with the shared reference's firmware node is - * the consumer of the reset control exposed by the reset-gpio device. - * It must have a "reset-gpios" property that's referencing the entry's - * firmware node. - * - * The reference args must agree between the real consumer and the - * auxiliary reset-gpio device. + * Now we need to find the actual pin we want to assign to this + * reset-gpio device. To that end: iterate over the list of references + * of this entry and see if there's one, whose reset-gpios property's + * arguments match the ones from this consumer's node. */ - ret = fwnode_property_get_reference_args(ref->fwnode, "reset-gpios", - NULL, 2, 0, &ref_args); - if (ret) - return false; + list_for_each_entry(real_ref, &entry->refs, list) { + if (!real_ref->fwnode) + continue; + + /* + * The device associated with the shared reference's firmware + * node is the consumer of the reset control exposed by the + * reset-gpio device. It must have a "reset-gpios" property + * that's referencing the entry's firmware node. + * + * The reference args must agree between the real consumer and + * the auxiliary reset-gpio device. + */ + ret = fwnode_property_get_reference_args(real_ref->fwnode, + "reset-gpios", + NULL, 2, 0, &ref_args); + if (ret) + continue; + + ret = fwnode_property_get_reference_args(reset_fwnode, "reset-gpios", + NULL, 2, 0, &aux_args); + if (ret) { + fwnode_handle_put(ref_args.fwnode); + continue; + } + + match = ((ref_args.fwnode == entry->fwnode) && + (aux_args.fwnode == entry->fwnode) && + (ref_args.args[0] == aux_args.args[0])); - ret = fwnode_property_get_reference_args(reset_fwnode, "reset-gpios", - NULL, 2, 0, &aux_args); - if (ret) { fwnode_handle_put(ref_args.fwnode); - return false; - } + fwnode_handle_put(aux_args.fwnode); + + if (!match) + continue; - match = ((ref_args.fwnode == entry->fwnode) && - (aux_args.fwnode == entry->fwnode) && - (ref_args.args[0] == aux_args.args[0])); + /* + * Reuse the fwnode of the real device, next time we'll use it + * in the normal path. + */ + ref->fwnode = fwnode_handle_get(real_ref->fwnode); + return true; + } - fwnode_handle_put(ref_args.fwnode); - fwnode_handle_put(aux_args.fwnode); - return match; + return false; } #else static bool gpio_shared_dev_is_reset_gpio(struct device *consumer, @@ -379,12 +446,20 @@ int gpio_shared_add_proxy_lookup(struct device *consumer, const char *con_id, list_for_each_entry(entry, &gpio_shared_list, list) { list_for_each_entry(ref, &entry->refs, list) { - if (!device_match_fwnode(consumer, ref->fwnode) && - !gpio_shared_dev_is_reset_gpio(consumer, entry, ref)) - continue; - guard(mutex)(&ref->lock); + /* + * FIXME: use device_is_compatible() once the reset-gpio + * drivers gains a compatible string which it currently + * does not have. + */ + if (!ref->fwnode && strstarts(dev_name(consumer), "reset.gpio.")) { + if (!gpio_shared_dev_is_reset_gpio(consumer, entry, ref)) + continue; + } else if (!device_match_fwnode(consumer, ref->fwnode)) { + continue; + } + if ((!con_id && ref->con_id) || (con_id && !ref->con_id) || (con_id && ref->con_id && strcmp(con_id, ref->con_id) != 0)) continue; @@ -471,8 +546,9 @@ int gpio_device_setup_shared(struct gpio_device *gdev) entry->offset, gpio_device_get_label(gdev)); list_for_each_entry(ref, &entry->refs, list) { - pr_debug("Setting up a shared GPIO entry for %s\n", - fwnode_get_name(ref->fwnode)); + pr_debug("Setting up a shared GPIO entry for %s (con_id: '%s')\n", + fwnode_get_name(ref->fwnode) ?: "(no fwnode)", + ref->con_id ?: "(none)"); ret = gpio_shared_make_adev(gdev, entry, ref); if (ret) -- 2.47.3 ^ permalink raw reply [flat|nested] 17+ messages in thread
[parent not found: <CGME20260105115023eucas1p1af1f8e80041f94843beb664966894fb9@eucas1p1.samsung.com>]
* Re: [PATCH 3/3] gpio: shared: allow sharing a reset-gpios pin between reset-gpio and gpiolib [not found] ` <CGME20260105115023eucas1p1af1f8e80041f94843beb664966894fb9@eucas1p1.samsung.com> @ 2026-01-05 11:50 ` Marek Szyprowski 2026-01-05 12:28 ` Bartosz Golaszewski ` (2 more replies) 0 siblings, 3 replies; 17+ messages in thread From: Marek Szyprowski @ 2026-01-05 11:50 UTC (permalink / raw) To: Bartosz Golaszewski, Linus Walleij, Bartosz Golaszewski Cc: linux-gpio, linux-kernel, Linus Walleij On 22.12.2025 11:01, Bartosz Golaszewski wrote: > We currently support sharing GPIOs between multiple devices whose drivers > use either the GPIOLIB API *OR* the reset control API but not both at > the same time. > > There's an unlikely corner-case where a reset-gpios pin can be shared by > one driver using the GPIOLIB API and a second using the reset API. This > will currently not work as the reset-gpio consumers are not described in > firmware at the time of scanning so the shared GPIO just chooses one of > the proxies created for the consumers when the reset-gpio driver performs > the lookup. This can of course conflict in the case described above. > > In order to fix it: if we deal with the "reset-gpios" pin that's shared > acconding to the firmware node setup, create a proxy for each described > consumer as well as another one for the potential reset-gpio device. To > that end: rework the matching to take this into account. > > Fixes: 7b78b26757e0 ("gpio: shared: handle the reset-gpios corner case") > Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com> This patch landed in linux-next as commit 49416483a953 ("gpio: shared: allow sharing a reset-gpios pin between reset-gpio and gpiolib"). In my tests I found that it breaks booting and triggers warnings on some of my test boards. Reverting it on top of next-20260105 fixes those issues. Let me know if I can help debugging this issue. Here are relevant logs from my 3 test systems: 1. Samsung TM2e - arch/arm64/boot/dts/exynos/exynos5433-tm2e.dts exynos-dsi 13900000.dsi: [drm:samsung_dsim_host_attach] Attached s6e3hf2 device (lanes:4 bpp:24 mode-flags:0x6e0) Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000 Mem abort info: ... Internal error: Oops: 0000000096000004 [#1] SMP Modules linked in: brcmfmac(+) panel_samsung_s6e3ha2(+) brcmutil backlight sha256 snd_soc_hdmi_codec cfg80211 phy_exynos5_usbdrd snd_soc_tm2_wm5110 s5p_mfc typec snd_soc_wm5110 hci_uart btqca s3fwrn5_i2c snd_soc_wm_adsp btbcm s3fwrn5 cs_dsp snd_soc_i2s nci bluetooth snd_soc_arizona arizona_micsupp s5p_jpeg exynos_gsc arizona_ldo1 nfc v4l2_mem2mem snd_soc_max98504 snd_soc_idma snd_soc_s3c_dma videobuf2_dma_contig max77693_haptic snd_soc_core ntc_thermistor ir_spi snd_compress videobuf2_memops ecdh_generic panfrost snd_pcm_dmaengine ecc videobuf2_v4l2 drm_shmem_helper videodev rfkill snd_pcm pwrseq_core gpu_sched gpio_shared_proxy videobuf2_common mc snd_timer snd soundcore ipv6 libsha1 CPU: 5 UID: 0 PID: 241 Comm: systemd-udevd Not tainted 6.19.0-rc1+ #16358 PREEMPT Hardware name: Samsung TM2E board (DT) pstate: 80000005 (Nzcv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : gpiod_direction_input_nonotify+0x20/0x39c lr : gpiod_configure_flags+0x23c/0x480 ... Call trace: gpiod_direction_input_nonotify+0x20/0x39c (P) gpiod_configure_flags+0x23c/0x480 gpiod_find_and_request+0x1a0/0x574 gpiod_get_index+0x58/0x84 devm_gpiod_get_index+0x20/0xb4 devm_gpiod_get_optional+0x18/0x30 samsung_dsim_host_attach+0x1c8/0x284 mipi_dsi_attach+0x30/0x54 s6e3ha2_probe+0x148/0x200 [panel_samsung_s6e3ha2] mipi_dsi_drv_probe+0x20/0x2c really_probe+0xbc/0x298 __driver_probe_device+0x78/0x12c driver_probe_device+0xdc/0x164 __driver_attach+0x9c/0x1ac bus_for_each_dev+0x74/0xd0 driver_attach+0x24/0x30 bus_add_driver+0xe4/0x208 driver_register+0x60/0x128 mipi_dsi_driver_register_full+0x5c/0x68 s6e3ha2_driver_init+0x20/0x1000 [panel_samsung_s6e3ha2] do_one_initcall+0x64/0x308 do_init_module+0x58/0x23c load_module+0x1b48/0x1dc4 init_module_from_file+0xd4/0xec idempotent_init_module+0x188/0x280 __arm64_sys_finit_module+0x68/0xac invoke_syscall+0x48/0x10c el0_svc_common.constprop.0+0xc8/0xe8 do_el0_svc+0x20/0x2c el0_svc+0x50/0x2e8 el0t_64_sync_handler+0xa0/0xe4 el0t_64_sync+0x198/0x19c Code: a90153f3 aa0003f3 a9025bf5 a90363f7 (f9400014) ---[ end trace 0000000000000000 ]--- Kernel panic - not syncing: Oops: Fatal exception SMP: stopping secondary CPUs Kernel Offset: disabled CPU features: 0x20c000,1061e001,00008000,0400421b Memory Limit: none ---[ end Kernel panic - not syncing: Oops: Fatal exception ]--- 2. Raspberrry Pi 3B+ - arch/arm64/boot/dts/broadcom/bcm2837-rpi-3-b.dts reset_gpio reset.gpio.0: cannot find GPIO chip gpiolib_shared.proxy.4, deferring ------------[ cut here ]------------ WARNING: drivers/gpio/gpiolib-shared.c:493 at gpio_shared_add_proxy_lookup+0x15c/0x224, CPU#1: kworker/u16:1/40 Modules linked in: ecc reset_gpio snd gpio_shared_proxy(+) raspberrypi_cpufreq(+) raspberrypi_hwmon rfkill soundcore pwrseq_core bcm2835_thermal pwm_bcm2835 vchiq i2c_bcm2835 fuse dm_mod ipv6 libsha1 CPU: 1 UID: 0 PID: 40 Comm: kworker/u16:1 Not tainted 6.19.0-rc4-next-20260105+ #11963 PREEMPT Hardware name: Raspberry Pi 3 Model B (DT) Workqueue: events_unbound deferred_probe_work_func pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : gpio_shared_add_proxy_lookup+0x15c/0x224 lr : gpio_shared_add_proxy_lookup+0x138/0x224 ... Call trace: gpio_shared_add_proxy_lookup+0x15c/0x224 (P) gpiod_find_and_request+0x200/0x574 gpiod_get_index+0x58/0x84 devm_gpiod_get_index+0x20/0xb4 devm_gpiod_get+0x18/0x24 reset_gpio_probe+0x4c/0x14c [reset_gpio] auxiliary_bus_probe+0x44/0x90 really_probe+0xbc/0x298 __driver_probe_device+0x78/0x12c driver_probe_device+0xdc/0x164 __device_attach_driver+0xb8/0x138 bus_for_each_drv+0x80/0xdc __device_attach+0xa8/0x1b0 device_initial_probe+0x50/0x54 bus_probe_device+0x38/0xa8 deferred_probe_work_func+0x8c/0xc8 process_one_work+0x208/0x604 worker_thread+0x244/0x388 kthread+0x140/0x14c ret_from_fork+0x10/0x20 irq event stamp: 82552 hardirqs last enabled at (82551): [<ffff8000813a1d60>] __schedule+0xc08/0x1204 hardirqs last disabled at (82552): [<ffff800081397194>] el1_brk64+0x20/0x60 softirqs last enabled at (81674): [<ffff8000800c71b4>] handle_softirqs+0x4c4/0x4dc softirqs last disabled at (81665): [<ffff800080010674>] __do_softirq+0x14/0x20 ---[ end trace 0000000000000000 ]--- 3. Khadas VIM3 - arch/arm64/boot/dts/amlogic/meson-g12b-a311d-khadas-vim3.dtb BUG: sleeping function called from invalid context at kernel/locking/mutex.c:591 in_atomic(): 1, irqs_disabled(): 1, non_block: 0, pid: 142, name: kworker/u25:3 preempt_count: 1, expected: 0 RCU nest depth: 0, expected: 0 INFO: lockdep is turned off. irq event stamp: 46379 hardirqs last enabled at (46379): [<ffff8000813acb24>] _raw_spin_unlock_irqrestore+0x74/0x78 hardirqs last disabled at (46378): [<ffff8000813abf38>] _raw_spin_lock_irqsave+0x84/0x88 softirqs last enabled at (46330): [<ffff8000800c71b4>] handle_softirqs+0x4c4/0x4dc softirqs last disabled at (46295): [<ffff800080010674>] __do_softirq+0x14/0x20 CPU: 1 UID: 0 PID: 142 Comm: kworker/u25:3 Tainted: G C 6.19.0-rc4-next-20260105+ #11963 PREEMPT Tainted: [C]=CRAP Hardware name: Khadas VIM3 (DT) Workqueue: events_unbound deferred_probe_work_func Call trace: show_stack+0x18/0x24 (C) dump_stack_lvl+0x90/0xd0 dump_stack+0x18/0x24 __might_resched+0x144/0x248 __might_sleep+0x48/0x98 __mutex_lock+0x5c/0x894 mutex_lock_nested+0x24/0x30 pinctrl_get_device_gpio_range+0x44/0x128 pinctrl_gpio_set_config+0x40/0xdc gpiochip_generic_config+0x28/0x3c gpio_do_set_config+0xa8/0x194 gpiod_set_config+0x34/0xfc gpio_shared_proxy_set_config+0x6c/0xfc [gpio_shared_proxy] gpio_do_set_config+0xa8/0x194 gpiod_set_transitory+0x4c/0xf0 gpiod_configure_flags+0xa4/0x480 gpiod_find_and_request+0x1a0/0x574 gpiod_get_index+0x58/0x84 devm_gpiod_get_index+0x20/0xb4 devm_gpiod_get+0x18/0x24 mmc_pwrseq_emmc_probe+0x40/0xb8 platform_probe+0x5c/0xac really_probe+0xbc/0x298 __driver_probe_device+0x78/0x12c driver_probe_device+0xdc/0x164 __device_attach_driver+0xb8/0x138 bus_for_each_drv+0x80/0xdc __device_attach+0xa8/0x1b0 > --- > drivers/gpio/gpiolib-shared.c | 182 ++++++++++++++++++++++++++++++------------ > 1 file changed, 129 insertions(+), 53 deletions(-) > > diff --git a/drivers/gpio/gpiolib-shared.c b/drivers/gpio/gpiolib-shared.c > index f589109590c7c6bc9c0c1828ea15ab9003846523..baf7e07a3bb887dab8155078666a15779e304409 100644 > --- a/drivers/gpio/gpiolib-shared.c > +++ b/drivers/gpio/gpiolib-shared.c > @@ -76,6 +76,56 @@ gpio_shared_find_entry(struct fwnode_handle *controller_node, > return NULL; > } > > +static struct gpio_shared_ref *gpio_shared_make_ref(struct fwnode_handle *fwnode, > + const char *con_id, > + enum gpiod_flags flags) > +{ > + char *con_id_cpy __free(kfree) = NULL; > + > + struct gpio_shared_ref *ref __free(kfree) = kzalloc(sizeof(*ref), GFP_KERNEL); > + if (!ref) > + return NULL; > + > + if (con_id) { > + con_id_cpy = kstrdup(con_id, GFP_KERNEL); > + if (!con_id_cpy) > + return NULL; > + } > + > + ref->dev_id = ida_alloc(&gpio_shared_ida, GFP_KERNEL); > + if (ref->dev_id < 0) > + return NULL; > + > + ref->flags = flags; > + ref->con_id = no_free_ptr(con_id_cpy); > + ref->fwnode = fwnode; > + mutex_init(&ref->lock); > + > + return no_free_ptr(ref); > +} > + > +static int gpio_shared_setup_reset_proxy(struct gpio_shared_entry *entry, > + enum gpiod_flags flags) > +{ > + struct gpio_shared_ref *ref; > + > + list_for_each_entry(ref, &entry->refs, list) { > + if (!ref->fwnode && ref->con_id && strcmp(ref->con_id, "reset") == 0) > + return 0; > + } > + > + ref = gpio_shared_make_ref(NULL, "reset", flags); > + if (!ref) > + return -ENOMEM; > + > + list_add_tail(&ref->list, &entry->refs); > + > + pr_debug("Created a secondary shared GPIO reference for potential reset-gpio device for GPIO %u at %s\n", > + entry->offset, fwnode_get_name(entry->fwnode)); > + > + return 0; > +} > + > /* Handle all special nodes that we should ignore. */ > static bool gpio_shared_of_node_ignore(struct device_node *node) > { > @@ -106,6 +156,7 @@ static int gpio_shared_of_traverse(struct device_node *curr) > size_t con_id_len, suffix_len; > struct fwnode_handle *fwnode; > struct of_phandle_args args; > + struct gpio_shared_ref *ref; > struct property *prop; > unsigned int offset; > const char *suffix; > @@ -138,6 +189,7 @@ static int gpio_shared_of_traverse(struct device_node *curr) > > for (i = 0; i < count; i++) { > struct device_node *np __free(device_node) = NULL; > + char *con_id __free(kfree) = NULL; > > ret = of_parse_phandle_with_args(curr, prop->name, > "#gpio-cells", i, > @@ -182,15 +234,6 @@ static int gpio_shared_of_traverse(struct device_node *curr) > list_add_tail(&entry->list, &gpio_shared_list); > } > > - struct gpio_shared_ref *ref __free(kfree) = > - kzalloc(sizeof(*ref), GFP_KERNEL); > - if (!ref) > - return -ENOMEM; > - > - ref->fwnode = fwnode_handle_get(of_fwnode_handle(curr)); > - ref->flags = args.args[1]; > - mutex_init(&ref->lock); > - > if (strends(prop->name, "gpios")) > suffix = "-gpios"; > else if (strends(prop->name, "gpio")) > @@ -202,27 +245,32 @@ static int gpio_shared_of_traverse(struct device_node *curr) > > /* We only set con_id if there's actually one. */ > if (strcmp(prop->name, "gpios") && strcmp(prop->name, "gpio")) { > - ref->con_id = kstrdup(prop->name, GFP_KERNEL); > - if (!ref->con_id) > + con_id = kstrdup(prop->name, GFP_KERNEL); > + if (!con_id) > return -ENOMEM; > > - con_id_len = strlen(ref->con_id); > + con_id_len = strlen(con_id); > suffix_len = strlen(suffix); > > - ref->con_id[con_id_len - suffix_len] = '\0'; > + con_id[con_id_len - suffix_len] = '\0'; > } > > - ref->dev_id = ida_alloc(&gpio_shared_ida, GFP_KERNEL); > - if (ref->dev_id < 0) { > - kfree(ref->con_id); > + ref = gpio_shared_make_ref(fwnode_handle_get(of_fwnode_handle(curr)), > + con_id, args.args[1]); > + if (!ref) > return -ENOMEM; > - } > > if (!list_empty(&entry->refs)) > pr_debug("GPIO %u at %s is shared by multiple firmware nodes\n", > entry->offset, fwnode_get_name(entry->fwnode)); > > - list_add_tail(&no_free_ptr(ref)->list, &entry->refs); > + list_add_tail(&ref->list, &entry->refs); > + > + if (strcmp(prop->name, "reset-gpios") == 0) { > + ret = gpio_shared_setup_reset_proxy(entry, args.args[1]); > + if (ret) > + return ret; > + } > } > } > > @@ -306,20 +354,16 @@ static bool gpio_shared_dev_is_reset_gpio(struct device *consumer, > struct fwnode_handle *reset_fwnode = dev_fwnode(consumer); > struct fwnode_reference_args ref_args, aux_args; > struct device *parent = consumer->parent; > + struct gpio_shared_ref *real_ref; > bool match; > int ret; > > + lockdep_assert_held(&ref->lock); > + > /* The reset-gpio device must have a parent AND a firmware node. */ > if (!parent || !reset_fwnode) > return false; > > - /* > - * FIXME: use device_is_compatible() once the reset-gpio drivers gains > - * a compatible string which it currently does not have. > - */ > - if (!strstarts(dev_name(consumer), "reset.gpio.")) > - return false; > - > /* > * Parent of the reset-gpio auxiliary device is the GPIO chip whose > * fwnode we stored in the entry structure. > @@ -328,33 +372,56 @@ static bool gpio_shared_dev_is_reset_gpio(struct device *consumer, > return false; > > /* > - * The device associated with the shared reference's firmware node is > - * the consumer of the reset control exposed by the reset-gpio device. > - * It must have a "reset-gpios" property that's referencing the entry's > - * firmware node. > - * > - * The reference args must agree between the real consumer and the > - * auxiliary reset-gpio device. > + * Now we need to find the actual pin we want to assign to this > + * reset-gpio device. To that end: iterate over the list of references > + * of this entry and see if there's one, whose reset-gpios property's > + * arguments match the ones from this consumer's node. > */ > - ret = fwnode_property_get_reference_args(ref->fwnode, "reset-gpios", > - NULL, 2, 0, &ref_args); > - if (ret) > - return false; > + list_for_each_entry(real_ref, &entry->refs, list) { > + if (!real_ref->fwnode) > + continue; > + > + /* > + * The device associated with the shared reference's firmware > + * node is the consumer of the reset control exposed by the > + * reset-gpio device. It must have a "reset-gpios" property > + * that's referencing the entry's firmware node. > + * > + * The reference args must agree between the real consumer and > + * the auxiliary reset-gpio device. > + */ > + ret = fwnode_property_get_reference_args(real_ref->fwnode, > + "reset-gpios", > + NULL, 2, 0, &ref_args); > + if (ret) > + continue; > + > + ret = fwnode_property_get_reference_args(reset_fwnode, "reset-gpios", > + NULL, 2, 0, &aux_args); > + if (ret) { > + fwnode_handle_put(ref_args.fwnode); > + continue; > + } > + > + match = ((ref_args.fwnode == entry->fwnode) && > + (aux_args.fwnode == entry->fwnode) && > + (ref_args.args[0] == aux_args.args[0])); > > - ret = fwnode_property_get_reference_args(reset_fwnode, "reset-gpios", > - NULL, 2, 0, &aux_args); > - if (ret) { > fwnode_handle_put(ref_args.fwnode); > - return false; > - } > + fwnode_handle_put(aux_args.fwnode); > + > + if (!match) > + continue; > > - match = ((ref_args.fwnode == entry->fwnode) && > - (aux_args.fwnode == entry->fwnode) && > - (ref_args.args[0] == aux_args.args[0])); > + /* > + * Reuse the fwnode of the real device, next time we'll use it > + * in the normal path. > + */ > + ref->fwnode = fwnode_handle_get(real_ref->fwnode); > + return true; > + } > > - fwnode_handle_put(ref_args.fwnode); > - fwnode_handle_put(aux_args.fwnode); > - return match; > + return false; > } > #else > static bool gpio_shared_dev_is_reset_gpio(struct device *consumer, > @@ -379,12 +446,20 @@ int gpio_shared_add_proxy_lookup(struct device *consumer, const char *con_id, > > list_for_each_entry(entry, &gpio_shared_list, list) { > list_for_each_entry(ref, &entry->refs, list) { > - if (!device_match_fwnode(consumer, ref->fwnode) && > - !gpio_shared_dev_is_reset_gpio(consumer, entry, ref)) > - continue; > - > guard(mutex)(&ref->lock); > > + /* > + * FIXME: use device_is_compatible() once the reset-gpio > + * drivers gains a compatible string which it currently > + * does not have. > + */ > + if (!ref->fwnode && strstarts(dev_name(consumer), "reset.gpio.")) { > + if (!gpio_shared_dev_is_reset_gpio(consumer, entry, ref)) > + continue; > + } else if (!device_match_fwnode(consumer, ref->fwnode)) { > + continue; > + } > + > if ((!con_id && ref->con_id) || (con_id && !ref->con_id) || > (con_id && ref->con_id && strcmp(con_id, ref->con_id) != 0)) > continue; > @@ -471,8 +546,9 @@ int gpio_device_setup_shared(struct gpio_device *gdev) > entry->offset, gpio_device_get_label(gdev)); > > list_for_each_entry(ref, &entry->refs, list) { > - pr_debug("Setting up a shared GPIO entry for %s\n", > - fwnode_get_name(ref->fwnode)); > + pr_debug("Setting up a shared GPIO entry for %s (con_id: '%s')\n", > + fwnode_get_name(ref->fwnode) ?: "(no fwnode)", > + ref->con_id ?: "(none)"); > > ret = gpio_shared_make_adev(gdev, entry, ref); > if (ret) > Best regards -- Marek Szyprowski, PhD Samsung R&D Institute Poland ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 3/3] gpio: shared: allow sharing a reset-gpios pin between reset-gpio and gpiolib 2026-01-05 11:50 ` Marek Szyprowski @ 2026-01-05 12:28 ` Bartosz Golaszewski 2026-01-05 17:26 ` Marek Szyprowski 2026-01-05 15:53 ` Bartosz Golaszewski 2026-01-06 12:21 ` Mark Brown 2 siblings, 1 reply; 17+ messages in thread From: Bartosz Golaszewski @ 2026-01-05 12:28 UTC (permalink / raw) To: Marek Szyprowski Cc: Bartosz Golaszewski, Linus Walleij, linux-gpio, linux-kernel, Linus Walleij On Mon, Jan 5, 2026 at 12:50 PM Marek Szyprowski <m.szyprowski@samsung.com> wrote: > > On 22.12.2025 11:01, Bartosz Golaszewski wrote: > > We currently support sharing GPIOs between multiple devices whose drivers > > use either the GPIOLIB API *OR* the reset control API but not both at > > the same time. > > > > There's an unlikely corner-case where a reset-gpios pin can be shared by > > one driver using the GPIOLIB API and a second using the reset API. This > > will currently not work as the reset-gpio consumers are not described in > > firmware at the time of scanning so the shared GPIO just chooses one of > > the proxies created for the consumers when the reset-gpio driver performs > > the lookup. This can of course conflict in the case described above. > > > > In order to fix it: if we deal with the "reset-gpios" pin that's shared > > acconding to the firmware node setup, create a proxy for each described > > consumer as well as another one for the potential reset-gpio device. To > > that end: rework the matching to take this into account. > > > > Fixes: 7b78b26757e0 ("gpio: shared: handle the reset-gpios corner case") > > Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com> > > This patch landed in linux-next as commit 49416483a953 ("gpio: shared: > allow sharing a reset-gpios pin between reset-gpio and gpiolib"). In my > tests I found that it breaks booting and triggers warnings on some of my > test boards. Reverting it on top of next-20260105 fixes those issues. > Let me know if I can help debugging this issue. > > > Here are relevant logs from my 3 test systems: > Thanks for the report. Nice combo, it looks like these are three separate bugs... > > 1. Samsung TM2e - arch/arm64/boot/dts/exynos/exynos5433-tm2e.dts > > exynos-dsi 13900000.dsi: [drm:samsung_dsim_host_attach] Attached s6e3hf2 > device (lanes:4 bpp:24 mode-flags:0x6e0) > Unable to handle kernel NULL pointer dereference at virtual address Could you use faddr2line to point me to the exact offending line? This would speed up the debugging. > 0000000000000000 > Mem abort info: > ... > Internal error: Oops: 0000000096000004 [#1] SMP > Modules linked in: brcmfmac(+) panel_samsung_s6e3ha2(+) brcmutil > backlight sha256 snd_soc_hdmi_codec cfg80211 phy_exynos5_usbdrd > snd_soc_tm2_wm5110 s5p_mfc typec snd_soc_wm5110 hci_uart btqca > s3fwrn5_i2c snd_soc_wm_adsp btbcm s3fwrn5 cs_dsp snd_soc_i2s nci > bluetooth snd_soc_arizona arizona_micsupp s5p_jpeg exynos_gsc > arizona_ldo1 nfc v4l2_mem2mem snd_soc_max98504 snd_soc_idma > snd_soc_s3c_dma videobuf2_dma_contig max77693_haptic snd_soc_core > ntc_thermistor ir_spi snd_compress videobuf2_memops ecdh_generic > panfrost snd_pcm_dmaengine ecc videobuf2_v4l2 drm_shmem_helper videodev > rfkill snd_pcm pwrseq_core gpu_sched gpio_shared_proxy videobuf2_common > mc snd_timer snd soundcore ipv6 libsha1 > CPU: 5 UID: 0 PID: 241 Comm: systemd-udevd Not tainted 6.19.0-rc1+ > #16358 PREEMPT > Hardware name: Samsung TM2E board (DT) > pstate: 80000005 (Nzcv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) > pc : gpiod_direction_input_nonotify+0x20/0x39c > lr : gpiod_configure_flags+0x23c/0x480 > ... > Call trace: > gpiod_direction_input_nonotify+0x20/0x39c (P) > gpiod_configure_flags+0x23c/0x480 > gpiod_find_and_request+0x1a0/0x574 > gpiod_get_index+0x58/0x84 > devm_gpiod_get_index+0x20/0xb4 > devm_gpiod_get_optional+0x18/0x30 > samsung_dsim_host_attach+0x1c8/0x284 > mipi_dsi_attach+0x30/0x54 > s6e3ha2_probe+0x148/0x200 [panel_samsung_s6e3ha2] > mipi_dsi_drv_probe+0x20/0x2c > really_probe+0xbc/0x298 > __driver_probe_device+0x78/0x12c > driver_probe_device+0xdc/0x164 > __driver_attach+0x9c/0x1ac > bus_for_each_dev+0x74/0xd0 > driver_attach+0x24/0x30 > bus_add_driver+0xe4/0x208 > driver_register+0x60/0x128 > mipi_dsi_driver_register_full+0x5c/0x68 > s6e3ha2_driver_init+0x20/0x1000 [panel_samsung_s6e3ha2] > do_one_initcall+0x64/0x308 > do_init_module+0x58/0x23c > load_module+0x1b48/0x1dc4 > init_module_from_file+0xd4/0xec > idempotent_init_module+0x188/0x280 > __arm64_sys_finit_module+0x68/0xac > invoke_syscall+0x48/0x10c > el0_svc_common.constprop.0+0xc8/0xe8 > do_el0_svc+0x20/0x2c > el0_svc+0x50/0x2e8 > el0t_64_sync_handler+0xa0/0xe4 > el0t_64_sync+0x198/0x19c > Code: a90153f3 aa0003f3 a9025bf5 a90363f7 (f9400014) > ---[ end trace 0000000000000000 ]--- > Kernel panic - not syncing: Oops: Fatal exception > SMP: stopping secondary CPUs > Kernel Offset: disabled > CPU features: 0x20c000,1061e001,00008000,0400421b > Memory Limit: none > ---[ end Kernel panic - not syncing: Oops: Fatal exception ]--- > > > 2. Raspberrry Pi 3B+ - arch/arm64/boot/dts/broadcom/bcm2837-rpi-3-b.dts > Could you please enable CONFIG_DEBUG_GPIO and post the entire kernel log somewhere? Looks like there's invalid logic with creating the proxies somewhere. > reset_gpio reset.gpio.0: cannot find GPIO chip gpiolib_shared.proxy.4, > deferring > ------------[ cut here ]------------ > WARNING: drivers/gpio/gpiolib-shared.c:493 at > gpio_shared_add_proxy_lookup+0x15c/0x224, CPU#1: kworker/u16:1/40 > Modules linked in: ecc reset_gpio snd gpio_shared_proxy(+) > raspberrypi_cpufreq(+) raspberrypi_hwmon rfkill soundcore pwrseq_core > bcm2835_thermal pwm_bcm2835 vchiq i2c_bcm2835 fuse dm_mod ipv6 libsha1 > CPU: 1 UID: 0 PID: 40 Comm: kworker/u16:1 Not tainted > 6.19.0-rc4-next-20260105+ #11963 PREEMPT > Hardware name: Raspberry Pi 3 Model B (DT) > Workqueue: events_unbound deferred_probe_work_func > pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) > pc : gpio_shared_add_proxy_lookup+0x15c/0x224 > lr : gpio_shared_add_proxy_lookup+0x138/0x224 > ... > Call trace: > gpio_shared_add_proxy_lookup+0x15c/0x224 (P) > gpiod_find_and_request+0x200/0x574 > gpiod_get_index+0x58/0x84 > devm_gpiod_get_index+0x20/0xb4 > devm_gpiod_get+0x18/0x24 > reset_gpio_probe+0x4c/0x14c [reset_gpio] > auxiliary_bus_probe+0x44/0x90 > really_probe+0xbc/0x298 > __driver_probe_device+0x78/0x12c > driver_probe_device+0xdc/0x164 > __device_attach_driver+0xb8/0x138 > bus_for_each_drv+0x80/0xdc > __device_attach+0xa8/0x1b0 > device_initial_probe+0x50/0x54 > bus_probe_device+0x38/0xa8 > deferred_probe_work_func+0x8c/0xc8 > process_one_work+0x208/0x604 > worker_thread+0x244/0x388 > kthread+0x140/0x14c > ret_from_fork+0x10/0x20 > irq event stamp: 82552 > hardirqs last enabled at (82551): [<ffff8000813a1d60>] > __schedule+0xc08/0x1204 > hardirqs last disabled at (82552): [<ffff800081397194>] el1_brk64+0x20/0x60 > softirqs last enabled at (81674): [<ffff8000800c71b4>] > handle_softirqs+0x4c4/0x4dc > softirqs last disabled at (81665): [<ffff800080010674>] > __do_softirq+0x14/0x20 > ---[ end trace 0000000000000000 ]--- > > > 3. Khadas VIM3 - > arch/arm64/boot/dts/amlogic/meson-g12b-a311d-khadas-vim3.dtb > > BUG: sleeping function called from invalid context at > kernel/locking/mutex.c:591 Can you post the output of gpiodetect and gpioinfo? I believe this to be a buggy GPIO driver which says the controller can't sleep but it then uses sleeping pinctrl interfaces. We had a similar bug uncovered by this series with qualcomm boards. > in_atomic(): 1, irqs_disabled(): 1, non_block: 0, pid: 142, name: > kworker/u25:3 > preempt_count: 1, expected: 0 > RCU nest depth: 0, expected: 0 > INFO: lockdep is turned off. > irq event stamp: 46379 > hardirqs last enabled at (46379): [<ffff8000813acb24>] > _raw_spin_unlock_irqrestore+0x74/0x78 > hardirqs last disabled at (46378): [<ffff8000813abf38>] > _raw_spin_lock_irqsave+0x84/0x88 > softirqs last enabled at (46330): [<ffff8000800c71b4>] > handle_softirqs+0x4c4/0x4dc > softirqs last disabled at (46295): [<ffff800080010674>] > __do_softirq+0x14/0x20 > CPU: 1 UID: 0 PID: 142 Comm: kworker/u25:3 Tainted: G C > 6.19.0-rc4-next-20260105+ #11963 PREEMPT > Tainted: [C]=CRAP > Hardware name: Khadas VIM3 (DT) > Workqueue: events_unbound deferred_probe_work_func > Call trace: > show_stack+0x18/0x24 (C) > dump_stack_lvl+0x90/0xd0 > dump_stack+0x18/0x24 > __might_resched+0x144/0x248 > __might_sleep+0x48/0x98 > __mutex_lock+0x5c/0x894 > mutex_lock_nested+0x24/0x30 > pinctrl_get_device_gpio_range+0x44/0x128 > pinctrl_gpio_set_config+0x40/0xdc > gpiochip_generic_config+0x28/0x3c > gpio_do_set_config+0xa8/0x194 > gpiod_set_config+0x34/0xfc > gpio_shared_proxy_set_config+0x6c/0xfc [gpio_shared_proxy] > gpio_do_set_config+0xa8/0x194 > gpiod_set_transitory+0x4c/0xf0 > gpiod_configure_flags+0xa4/0x480 > gpiod_find_and_request+0x1a0/0x574 > gpiod_get_index+0x58/0x84 > devm_gpiod_get_index+0x20/0xb4 > devm_gpiod_get+0x18/0x24 > mmc_pwrseq_emmc_probe+0x40/0xb8 > platform_probe+0x5c/0xac > really_probe+0xbc/0x298 > __driver_probe_device+0x78/0x12c > driver_probe_device+0xdc/0x164 > __device_attach_driver+0xb8/0x138 > bus_for_each_drv+0x80/0xdc > __device_attach+0xa8/0x1b0 > Thanks in advance for the help! Bart ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 3/3] gpio: shared: allow sharing a reset-gpios pin between reset-gpio and gpiolib 2026-01-05 12:28 ` Bartosz Golaszewski @ 2026-01-05 17:26 ` Marek Szyprowski 2026-01-05 18:16 ` Marek Szyprowski 0 siblings, 1 reply; 17+ messages in thread From: Marek Szyprowski @ 2026-01-05 17:26 UTC (permalink / raw) To: Bartosz Golaszewski Cc: Bartosz Golaszewski, Linus Walleij, linux-gpio, linux-kernel On 05.01.2026 13:28, Bartosz Golaszewski wrote: > On Mon, Jan 5, 2026 at 12:50 PM Marek Szyprowski > <m.szyprowski@samsung.com> wrote: >> On 22.12.2025 11:01, Bartosz Golaszewski wrote: >>> We currently support sharing GPIOs between multiple devices whose drivers >>> use either the GPIOLIB API *OR* the reset control API but not both at >>> the same time. >>> >>> There's an unlikely corner-case where a reset-gpios pin can be shared by >>> one driver using the GPIOLIB API and a second using the reset API. This >>> will currently not work as the reset-gpio consumers are not described in >>> firmware at the time of scanning so the shared GPIO just chooses one of >>> the proxies created for the consumers when the reset-gpio driver performs >>> the lookup. This can of course conflict in the case described above. >>> >>> In order to fix it: if we deal with the "reset-gpios" pin that's shared >>> acconding to the firmware node setup, create a proxy for each described >>> consumer as well as another one for the potential reset-gpio device. To >>> that end: rework the matching to take this into account. >>> >>> Fixes: 7b78b26757e0 ("gpio: shared: handle the reset-gpios corner case") >>> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com> >> This patch landed in linux-next as commit 49416483a953 ("gpio: shared: >> allow sharing a reset-gpios pin between reset-gpio and gpiolib"). In my >> tests I found that it breaks booting and triggers warnings on some of my >> test boards. Reverting it on top of next-20260105 fixes those issues. >> Let me know if I can help debugging this issue. >> >> >> Here are relevant logs from my 3 test systems: >> > Thanks for the report. > > Nice combo, it looks like these are three separate bugs... > >> 1. Samsung TM2e - arch/arm64/boot/dts/exynos/exynos5433-tm2e.dts >> >> exynos-dsi 13900000.dsi: [drm:samsung_dsim_host_attach] Attached s6e3hf2 >> device (lanes:4 bpp:24 mode-flags:0x6e0) >> Unable to handle kernel NULL pointer dereference at virtual address > Could you use faddr2line to point me to the exact offending line? This > would speed up the debugging. I need some time to get that output, but this issue is caused by a devm_gpiod_get_optional() call for a gpio that is not defined for that board. > > ... Best regards -- Marek Szyprowski, PhD Samsung R&D Institute Poland ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 3/3] gpio: shared: allow sharing a reset-gpios pin between reset-gpio and gpiolib 2026-01-05 17:26 ` Marek Szyprowski @ 2026-01-05 18:16 ` Marek Szyprowski 2026-01-06 10:55 ` Bartosz Golaszewski 0 siblings, 1 reply; 17+ messages in thread From: Marek Szyprowski @ 2026-01-05 18:16 UTC (permalink / raw) To: Bartosz Golaszewski Cc: Bartosz Golaszewski, Linus Walleij, linux-gpio, linux-kernel On 05.01.2026 18:26, Marek Szyprowski wrote: > On 05.01.2026 13:28, Bartosz Golaszewski wrote: >> On Mon, Jan 5, 2026 at 12:50 PM Marek Szyprowski >> <m.szyprowski@samsung.com> wrote: >>> On 22.12.2025 11:01, Bartosz Golaszewski wrote: >>>> We currently support sharing GPIOs between multiple devices whose >>>> drivers >>>> use either the GPIOLIB API *OR* the reset control API but not both at >>>> the same time. >>>> >>>> There's an unlikely corner-case where a reset-gpios pin can be >>>> shared by >>>> one driver using the GPIOLIB API and a second using the reset API. >>>> This >>>> will currently not work as the reset-gpio consumers are not >>>> described in >>>> firmware at the time of scanning so the shared GPIO just chooses >>>> one of >>>> the proxies created for the consumers when the reset-gpio driver >>>> performs >>>> the lookup. This can of course conflict in the case described above. >>>> >>>> In order to fix it: if we deal with the "reset-gpios" pin that's >>>> shared >>>> acconding to the firmware node setup, create a proxy for each >>>> described >>>> consumer as well as another one for the potential reset-gpio >>>> device. To >>>> that end: rework the matching to take this into account. >>>> >>>> Fixes: 7b78b26757e0 ("gpio: shared: handle the reset-gpios corner >>>> case") >>>> Signed-off-by: Bartosz Golaszewski >>>> <bartosz.golaszewski@oss.qualcomm.com> >>> This patch landed in linux-next as commit 49416483a953 ("gpio: shared: >>> allow sharing a reset-gpios pin between reset-gpio and gpiolib"). In my >>> tests I found that it breaks booting and triggers warnings on some >>> of my >>> test boards. Reverting it on top of next-20260105 fixes those issues. >>> Let me know if I can help debugging this issue. >>> >>> >>> Here are relevant logs from my 3 test systems: >>> >> Thanks for the report. >> >> Nice combo, it looks like these are three separate bugs... >> >>> 1. Samsung TM2e - arch/arm64/boot/dts/exynos/exynos5433-tm2e.dts >>> >>> exynos-dsi 13900000.dsi: [drm:samsung_dsim_host_attach] Attached >>> s6e3hf2 >>> device (lanes:4 bpp:24 mode-flags:0x6e0) >>> Unable to handle kernel NULL pointer dereference at virtual address >> Could you use faddr2line to point me to the exact offending line? This >> would speed up the debugging. > > I need some time to get that output, but this issue is caused by a > devm_gpiod_get_optional() call for a gpio that is not defined for that > board. > I think that everything is in the call stack: Call trace: gpiod_direction_input_nonotify+0x20/0x39c (P) gpiod_configure_flags+0x23c/0x480 gpiod_find_and_request+0x1a0/0x574 gpiod_get_index+0x58/0x84 devm_gpiod_get_index+0x20/0xb4 devm_gpiod_get_optional+0x18/0x30 samsung_dsim_host_attach+0x1c8/0x284 mipi_dsi_attach+0x30/0x54 s6e3ha2_probe+0x148/0x200 [panel_samsung_s6e3ha2] ... The issue is in gpiod_direction_input_nonotify+0x20/0x39c: $ grep gpiod_direction_input_nonotify System.map ffff800080810360 T gpiod_direction_input_nonotify $ aarch64-linux-gnu-addr2line -f -e vmlinux ffff800080810380 class_gpio_chip_guard_constructor /home/m.szyprowski/dev/kernel/linux-next/drivers/gpio/gpiolib.h:231 IMHO it looks that gpiod_configure_flags() is called for NULL gpio_chip. Best regards -- Marek Szyprowski, PhD Samsung R&D Institute Poland ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 3/3] gpio: shared: allow sharing a reset-gpios pin between reset-gpio and gpiolib 2026-01-05 18:16 ` Marek Szyprowski @ 2026-01-06 10:55 ` Bartosz Golaszewski 0 siblings, 0 replies; 17+ messages in thread From: Bartosz Golaszewski @ 2026-01-06 10:55 UTC (permalink / raw) To: Marek Szyprowski Cc: Bartosz Golaszewski, Linus Walleij, linux-gpio, linux-kernel On Mon, Jan 5, 2026 at 7:16 PM Marek Szyprowski <m.szyprowski@samsung.com> wrote: > > >> > >>> 1. Samsung TM2e - arch/arm64/boot/dts/exynos/exynos5433-tm2e.dts > >>> > >>> exynos-dsi 13900000.dsi: [drm:samsung_dsim_host_attach] Attached > >>> s6e3hf2 > >>> device (lanes:4 bpp:24 mode-flags:0x6e0) > >>> Unable to handle kernel NULL pointer dereference at virtual address > >> Could you use faddr2line to point me to the exact offending line? This > >> would speed up the debugging. > > > > I need some time to get that output, but this issue is caused by a > > devm_gpiod_get_optional() call for a gpio that is not defined for that > > board. > > > I think that everything is in the call stack: > > Call trace: > gpiod_direction_input_nonotify+0x20/0x39c (P) > gpiod_configure_flags+0x23c/0x480 > gpiod_find_and_request+0x1a0/0x574 > gpiod_get_index+0x58/0x84 > devm_gpiod_get_index+0x20/0xb4 > devm_gpiod_get_optional+0x18/0x30 > samsung_dsim_host_attach+0x1c8/0x284 > mipi_dsi_attach+0x30/0x54 > s6e3ha2_probe+0x148/0x200 [panel_samsung_s6e3ha2] > > ... > > > The issue is in gpiod_direction_input_nonotify+0x20/0x39c: > > $ grep gpiod_direction_input_nonotify System.map > ffff800080810360 T gpiod_direction_input_nonotify > > $ aarch64-linux-gnu-addr2line -f -e vmlinux ffff800080810380 > class_gpio_chip_guard_constructor > /home/m.szyprowski/dev/kernel/linux-next/drivers/gpio/gpiolib.h:231 > > IMHO it looks that gpiod_configure_flags() is called for NULL gpio_chip. > The whole point of this macro is to make sure the chip is not NULL. It dereferences gdev->chip under SRCU for that reason. Is it the descriptor (struct gpio_desc *desc) pointer passed to gpiod_direction_input_nonotify() that is NULL by any chance? It shouldn't be possible but I want to rule it out. Also: it doesn't really look like it has anything to do with shared GPIO management. I looked into the DTS and there are no shared GPIOs. Can you enable CONFIG_DEBUG_GPIO and post the entire kernel log just to make sure? Is the issue reproducible and goes away when that commit is reverted? Bartosz ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 3/3] gpio: shared: allow sharing a reset-gpios pin between reset-gpio and gpiolib 2026-01-05 11:50 ` Marek Szyprowski 2026-01-05 12:28 ` Bartosz Golaszewski @ 2026-01-05 15:53 ` Bartosz Golaszewski 2026-01-06 12:21 ` Mark Brown 2 siblings, 0 replies; 17+ messages in thread From: Bartosz Golaszewski @ 2026-01-05 15:53 UTC (permalink / raw) To: Marek Szyprowski Cc: Bartosz Golaszewski, Linus Walleij, linux-gpio, linux-kernel, Linus Walleij On Mon, Jan 5, 2026 at 12:50 PM Marek Szyprowski <m.szyprowski@samsung.com> wrote: > > On 22.12.2025 11:01, Bartosz Golaszewski wrote: > > We currently support sharing GPIOs between multiple devices whose drivers > > use either the GPIOLIB API *OR* the reset control API but not both at > > the same time. > > > > There's an unlikely corner-case where a reset-gpios pin can be shared by > > one driver using the GPIOLIB API and a second using the reset API. This > > will currently not work as the reset-gpio consumers are not described in > > firmware at the time of scanning so the shared GPIO just chooses one of > > the proxies created for the consumers when the reset-gpio driver performs > > the lookup. This can of course conflict in the case described above. > > > > In order to fix it: if we deal with the "reset-gpios" pin that's shared > > acconding to the firmware node setup, create a proxy for each described > > consumer as well as another one for the potential reset-gpio device. To > > that end: rework the matching to take this into account. > > > > Fixes: 7b78b26757e0 ("gpio: shared: handle the reset-gpios corner case") > > Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com> > > This patch landed in linux-next as commit 49416483a953 ("gpio: shared: > allow sharing a reset-gpios pin between reset-gpio and gpiolib"). In my > tests I found that it breaks booting and triggers warnings on some of my > test boards. Reverting it on top of next-20260105 fixes those issues. > Let me know if I can help debugging this issue. > > > Here are relevant logs from my 3 test systems: > Hi! I've just sent out fixes for problems #2 and #3 with you in Cc. For #1 - are you sure this is really the commit that causes it? It doesn't seem to have anything to do with shared GPIOs. Bartosz ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 3/3] gpio: shared: allow sharing a reset-gpios pin between reset-gpio and gpiolib 2026-01-05 11:50 ` Marek Szyprowski 2026-01-05 12:28 ` Bartosz Golaszewski 2026-01-05 15:53 ` Bartosz Golaszewski @ 2026-01-06 12:21 ` Mark Brown 2026-01-06 12:25 ` Bartosz Golaszewski 2 siblings, 1 reply; 17+ messages in thread From: Mark Brown @ 2026-01-06 12:21 UTC (permalink / raw) To: Marek Szyprowski Cc: Bartosz Golaszewski, Linus Walleij, Bartosz Golaszewski, linux-gpio, linux-kernel, Linus Walleij [-- Attachment #1: Type: text/plain, Size: 1295 bytes --] On Mon, Jan 05, 2026 at 12:50:22PM +0100, Marek Szyprowski wrote: > On 22.12.2025 11:01, Bartosz Golaszewski wrote: > > We currently support sharing GPIOs between multiple devices whose drivers > > use either the GPIOLIB API *OR* the reset control API but not both at > > the same time. > This patch landed in linux-next as commit 49416483a953 ("gpio: shared: > allow sharing a reset-gpios pin between reset-gpio and gpiolib"). In my > tests I found that it breaks booting and triggers warnings on some of my > test boards. Reverting it on top of next-20260105 fixes those issues. > Let me know if I can help debugging this issue. Not sure if it's this specific patch (one of the bisects identified it, but I'm seeing others going to the merge commit for the gpio fixes branch) but I'm also seeing issues with gpios. pwrseq is affected on several platforms after backtraces that look a lot like the one that Marek is seeing on Raspberry Pi 3B+ (which I also see). This breaks at least the WiFi: [ 13.475670] platform wifi-pwrseq: deferred probe pending: pwrseq_simple: reset control not ready Raspberry Pi 4: https://lava.sirena.org.uk/scheduler/job/2335022#L1200 Toradax Mallow (TI K3): https://lava.sirena.org.uk/scheduler/job/2335415#L1457 [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 488 bytes --] ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 3/3] gpio: shared: allow sharing a reset-gpios pin between reset-gpio and gpiolib 2026-01-06 12:21 ` Mark Brown @ 2026-01-06 12:25 ` Bartosz Golaszewski 0 siblings, 0 replies; 17+ messages in thread From: Bartosz Golaszewski @ 2026-01-06 12:25 UTC (permalink / raw) To: Mark Brown Cc: Marek Szyprowski, Bartosz Golaszewski, Linus Walleij, linux-gpio, linux-kernel, Linus Walleij On Tue, Jan 6, 2026 at 1:21 PM Mark Brown <broonie@kernel.org> wrote: > > On Mon, Jan 05, 2026 at 12:50:22PM +0100, Marek Szyprowski wrote: > > On 22.12.2025 11:01, Bartosz Golaszewski wrote: > > > We currently support sharing GPIOs between multiple devices whose drivers > > > use either the GPIOLIB API *OR* the reset control API but not both at > > > the same time. > > > This patch landed in linux-next as commit 49416483a953 ("gpio: shared: > > allow sharing a reset-gpios pin between reset-gpio and gpiolib"). In my > > tests I found that it breaks booting and triggers warnings on some of my > > test boards. Reverting it on top of next-20260105 fixes those issues. > > Let me know if I can help debugging this issue. > > Not sure if it's this specific patch (one of the bisects identified it, > but I'm seeing others going to the merge commit for the gpio fixes > branch) but I'm also seeing issues with gpios. pwrseq is affected on > several platforms after backtraces that look a lot like the one that > Marek is seeing on Raspberry Pi 3B+ (which I also see). This breaks at > least the WiFi: > > [ 13.475670] platform wifi-pwrseq: deferred probe pending: pwrseq_simple: reset control not ready > > Raspberry Pi 4: > > https://lava.sirena.org.uk/scheduler/job/2335022#L1200 > > Toradax Mallow (TI K3): > > https://lava.sirena.org.uk/scheduler/job/2335415#L1457 Hi! These two should be fixed by the following series: https://lore.kernel.org/all/20260106-gpio-shared-fixes-v2-0-c7091d2f7581@oss.qualcomm.com/ Could you please give it a try and possibly add your T-b? Bart ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 3/3] gpio: shared: allow sharing a reset-gpios pin between reset-gpio and gpiolib 2025-12-22 10:01 ` [PATCH 3/3] gpio: shared: allow sharing a reset-gpios pin between reset-gpio and gpiolib Bartosz Golaszewski [not found] ` <CGME20260105115023eucas1p1af1f8e80041f94843beb664966894fb9@eucas1p1.samsung.com> @ 2026-01-08 15:46 ` Mark Brown 2026-01-08 15:52 ` Bartosz Golaszewski 1 sibling, 1 reply; 17+ messages in thread From: Mark Brown @ 2026-01-08 15:46 UTC (permalink / raw) To: Bartosz Golaszewski Cc: Linus Walleij, Bartosz Golaszewski, linux-gpio, linux-kernel, Linus Walleij, Aishwarya.TCV [-- Attachment #1: Type: text/plain, Size: 3594 bytes --] On Mon, Dec 22, 2025 at 11:01:28AM +0100, Bartosz Golaszewski wrote: > We currently support sharing GPIOs between multiple devices whose drivers > use either the GPIOLIB API *OR* the reset control API but not both at > the same time. We're seeing futher issues which bisect to this patch in today's next/pending-fixes on db845c: <1>[ 18.348426] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000008 ... <4>[ 18.799534] Call trace: <4>[ 18.799536] gpiod_direction_output_nonotify+0x14/0x194 (P) <4>[ 18.799541] gpiod_configure_flags+0xb0/0x364 <4>[ 18.799543] gpiod_find_and_request+0x144/0x504 <4>[ 18.832617] gpiod_get_index+0x58/0x90 <4>[ 18.836657] devm_gpiod_get_index+0x20/0xb0 <4>[ 18.841139] devm_gpiod_get_optional+0x18/0x34 <4>[ 18.845881] lt9611_probe+0x130/0x488 [lontium_lt9611] Some prior instances were fixed by: https://lore.kernel.org/all/20260106-gpio-shared-fixes-v2-0-c7091d2f7581@oss.qualcomm.com/ but that's only in next/master, not next/pending-fixes, and in any case the issue also appears in next/master which should include them. git bisect start # status: waiting for both good and bad commits # bad: [fc4e91c639c0af93d63c3d5bc0ee45515dd7504a] Add linux-next specific files for 20260108 git bisect bad fc4e91c639c0af93d63c3d5bc0ee45515dd7504a # status: waiting for good commit(s), bad commit known # bad: [53ebf42e14b480288f52fa86811bf68703fece4e] Merge branch 'for-linux-next-fixes' of https://gitlab.freedesktop.org/drm/misc/kernel.git git bisect bad 53ebf42e14b480288f52fa86811bf68703fece4e # status: waiting for good commit(s), bad commit known # good: [f0b9d8eb98dfee8d00419aa07543bdc2c1a44fb1] Merge tag 'nfsd-6.19-3' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux git bisect good f0b9d8eb98dfee8d00419aa07543bdc2c1a44fb1 # good: [a64e2a609fbd406cc424ba13bfcf1941c3b004ea] Merge branch 'for-linus' of https://git.kernel.org/pub/scm/linux/kernel/git/pci/pci.git git bisect good a64e2a609fbd406cc424ba13bfcf1941c3b004ea # good: [1d1d206d257d645c8e3b910d69a1d4b0105de146] Merge branch 'fixes' of git://linuxtv.org/media-ci/media-pending.git git bisect good 1d1d206d257d645c8e3b910d69a1d4b0105de146 # good: [fc6818ad09fcdcd3670755c8dbe9785561f8ef1e] Merge branch 'riscv-dt-fixes' of https://git.kernel.org/pub/scm/linux/kernel/git/conor/linux.git git bisect good fc6818ad09fcdcd3670755c8dbe9785561f8ef1e # bad: [158eb9119b536341cf39b07c6f9408c15516f77e] Merge branch 'rust-fixes' of https://github.com/Rust-for-Linux/linux.git git bisect bad 158eb9119b536341cf39b07c6f9408c15516f77e # bad: [51018b3e4652074f726aea6cd66e89edcef34e76] Merge branch 'gpio/for-current' of https://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux.git git bisect bad 51018b3e4652074f726aea6cd66e89edcef34e76 # bad: [014a17deb41201449f76df2b20c857a9c3294a7c] gpio: pca953x: handle short interrupt pulses on PCAL devices git bisect bad 014a17deb41201449f76df2b20c857a9c3294a7c # good: [cb0451e33be047fff7137f58d9996370e11fb344] gpio: shared: verify con_id when adding proxy lookup git bisect good cb0451e33be047fff7137f58d9996370e11fb344 # bad: [a7ac22d53d0990152b108c3f4fe30df45fcb0181] gpiolib: fix race condition for gdev->srcu git bisect bad a7ac22d53d0990152b108c3f4fe30df45fcb0181 # bad: [49416483a953662aa53c6d9bef651757d4a95ba5] gpio: shared: allow sharing a reset-gpios pin between reset-gpio and gpiolib git bisect bad 49416483a953662aa53c6d9bef651757d4a95ba5 # first bad commit: [49416483a953662aa53c6d9bef651757d4a95ba5] gpio: shared: allow sharing a reset-gpios pin between reset-gpio and gpiolib [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 488 bytes --] ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 3/3] gpio: shared: allow sharing a reset-gpios pin between reset-gpio and gpiolib 2026-01-08 15:46 ` Mark Brown @ 2026-01-08 15:52 ` Bartosz Golaszewski 2026-01-08 16:29 ` Mark Brown 0 siblings, 1 reply; 17+ messages in thread From: Bartosz Golaszewski @ 2026-01-08 15:52 UTC (permalink / raw) To: Mark Brown Cc: Bartosz Golaszewski, Linus Walleij, linux-gpio, linux-kernel, Linus Walleij, Aishwarya.TCV On Thu, Jan 8, 2026 at 4:46 PM Mark Brown <broonie@kernel.org> wrote: > > On Mon, Dec 22, 2025 at 11:01:28AM +0100, Bartosz Golaszewski wrote: > > We currently support sharing GPIOs between multiple devices whose drivers > > use either the GPIOLIB API *OR* the reset control API but not both at > > the same time. > > We're seeing futher issues which bisect to this patch in today's > next/pending-fixes on db845c: > > <1>[ 18.348426] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000008 > > ... > > <4>[ 18.799534] Call trace: > <4>[ 18.799536] gpiod_direction_output_nonotify+0x14/0x194 (P) > <4>[ 18.799541] gpiod_configure_flags+0xb0/0x364 > <4>[ 18.799543] gpiod_find_and_request+0x144/0x504 > <4>[ 18.832617] gpiod_get_index+0x58/0x90 > <4>[ 18.836657] devm_gpiod_get_index+0x20/0xb0 > <4>[ 18.841139] devm_gpiod_get_optional+0x18/0x34 > <4>[ 18.845881] lt9611_probe+0x130/0x488 [lontium_lt9611] > > Some prior instances were fixed by: > > https://lore.kernel.org/all/20260106-gpio-shared-fixes-v2-0-c7091d2f7581@oss.qualcomm.com/ > > but that's only in next/master, not next/pending-fixes, and in any case > the issue also appears in next/master which should include them. > Does the following fix it by any chance? https://lore.kernel.org/all/20260108102314.18816-1-bartosz.golaszewski@oss.qualcomm.com Bart ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 3/3] gpio: shared: allow sharing a reset-gpios pin between reset-gpio and gpiolib 2026-01-08 15:52 ` Bartosz Golaszewski @ 2026-01-08 16:29 ` Mark Brown 2026-01-08 18:04 ` Bartosz Golaszewski 0 siblings, 1 reply; 17+ messages in thread From: Mark Brown @ 2026-01-08 16:29 UTC (permalink / raw) To: Bartosz Golaszewski Cc: Bartosz Golaszewski, Linus Walleij, linux-gpio, linux-kernel, Linus Walleij, Aishwarya.TCV [-- Attachment #1: Type: text/plain, Size: 416 bytes --] On Thu, Jan 08, 2026 at 04:52:24PM +0100, Bartosz Golaszewski wrote: > On Thu, Jan 8, 2026 at 4:46 PM Mark Brown <broonie@kernel.org> wrote: > > We're seeing futher issues which bisect to this patch in today's > > next/pending-fixes on db845c: > Does the following fix it by any chance? > https://lore.kernel.org/all/20260108102314.18816-1-bartosz.golaszewski@oss.qualcomm.com Seems to, yes thanks. [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 488 bytes --] ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 3/3] gpio: shared: allow sharing a reset-gpios pin between reset-gpio and gpiolib 2026-01-08 16:29 ` Mark Brown @ 2026-01-08 18:04 ` Bartosz Golaszewski 0 siblings, 0 replies; 17+ messages in thread From: Bartosz Golaszewski @ 2026-01-08 18:04 UTC (permalink / raw) To: Mark Brown Cc: Bartosz Golaszewski, Linus Walleij, linux-gpio, linux-kernel, Linus Walleij, Aishwarya.TCV On Thu, Jan 8, 2026 at 5:29 PM Mark Brown <broonie@kernel.org> wrote: > > On Thu, Jan 08, 2026 at 04:52:24PM +0100, Bartosz Golaszewski wrote: > > On Thu, Jan 8, 2026 at 4:46 PM Mark Brown <broonie@kernel.org> wrote: > > > > We're seeing futher issues which bisect to this patch in today's > > > next/pending-fixes on db845c: > > > Does the following fix it by any chance? > > > https://lore.kernel.org/all/20260108102314.18816-1-bartosz.golaszewski@oss.qualcomm.com > > Seems to, yes thanks. Good, sorry for the fallout. There's one more patch[1] that fixes the issue that actually caused so many people to be affected. If you could give it a spin as well and leave your T-b, that would be great. Thanks, Bartosz [1] https://lore.kernel.org/all/20260108-gpio-shared-false-positive-v1-1-5dbf8d1b2f7d@oss.qualcomm.com/ ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 0/3] gpio: shared: close remaining gaps 2025-12-22 10:01 [PATCH 0/3] gpio: shared: close remaining gaps Bartosz Golaszewski ` (2 preceding siblings ...) 2025-12-22 10:01 ` [PATCH 3/3] gpio: shared: allow sharing a reset-gpios pin between reset-gpio and gpiolib Bartosz Golaszewski @ 2026-01-02 9:34 ` Bartosz Golaszewski 3 siblings, 0 replies; 17+ messages in thread From: Bartosz Golaszewski @ 2026-01-02 9:34 UTC (permalink / raw) To: Linus Walleij, Bartosz Golaszewski, Bartosz Golaszewski Cc: linux-gpio, linux-kernel, Linus Walleij On Mon, 22 Dec 2025 11:01:25 +0100, Bartosz Golaszewski wrote: > This series fixes some remaining issues and corner-cases in the shared > GPIO management. In order to address multiple shared GPIOs per consumer > as well as the reset-gpio interaction, we need to support multiple > lookup tables per consumer device. > > This is targetting v6.19 as it effectively fixes the code that went > upstream during the v6.19 merge window. > > [...] Applied, thanks! [1/3] gpiolib: allow multiple lookup tables per consumer commit: 9700b0fccf386b671e6f8401ddea6c5669cd0914 [2/3] gpio: shared: verify con_id when adding proxy lookup commit: cb0451e33be047fff7137f58d9996370e11fb344 [3/3] gpio: shared: allow sharing a reset-gpios pin between reset-gpio and gpiolib commit: 49416483a953662aa53c6d9bef651757d4a95ba5 Best regards, -- Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com> ^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2026-01-08 18:04 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-12-22 10:01 [PATCH 0/3] gpio: shared: close remaining gaps Bartosz Golaszewski
2025-12-22 10:01 ` [PATCH 1/3] gpiolib: allow multiple lookup tables per consumer Bartosz Golaszewski
2025-12-22 10:01 ` [PATCH 2/3] gpio: shared: verify con_id when adding proxy lookup Bartosz Golaszewski
2025-12-22 10:01 ` [PATCH 3/3] gpio: shared: allow sharing a reset-gpios pin between reset-gpio and gpiolib Bartosz Golaszewski
[not found] ` <CGME20260105115023eucas1p1af1f8e80041f94843beb664966894fb9@eucas1p1.samsung.com>
2026-01-05 11:50 ` Marek Szyprowski
2026-01-05 12:28 ` Bartosz Golaszewski
2026-01-05 17:26 ` Marek Szyprowski
2026-01-05 18:16 ` Marek Szyprowski
2026-01-06 10:55 ` Bartosz Golaszewski
2026-01-05 15:53 ` Bartosz Golaszewski
2026-01-06 12:21 ` Mark Brown
2026-01-06 12:25 ` Bartosz Golaszewski
2026-01-08 15:46 ` Mark Brown
2026-01-08 15:52 ` Bartosz Golaszewski
2026-01-08 16:29 ` Mark Brown
2026-01-08 18:04 ` Bartosz Golaszewski
2026-01-02 9:34 ` [PATCH 0/3] gpio: shared: close remaining gaps Bartosz Golaszewski
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®