Skip to content

Commit 4918cc0

Browse files
author
Bartosz Golaszewski
committed
gpio: shared: propagate configuration to pinctrl
Just toggling the descriptor's "requested" flag is not enough. We need to properly request it in order to potentially propagate any configuration to pinctrl via the .request() callback. We must not take the reference to the device at this point (the device is not ready but we're also requesting the device's own descriptor) so make the _commit() variants of request and free functions available to GPIO core in order to use them instead of their regular counterparts. This fixes an audio issue reported on one of the Qualcomm platforms. Fixes: a060b8c ("gpiolib: implement low-level, shared GPIO support") Reviewed-by: Linus Walleij <linusw@kernel.org> Tested-by: Ravi Hothi <ravi.hothi@oss.qualcomm.com> Link: https://lore.kernel.org/r/20260120154913.61991-1-bartosz.golaszewski@oss.qualcomm.com Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
1 parent 8a8c942 commit 4918cc0

3 files changed

Lines changed: 15 additions & 7 deletions

File tree

drivers/gpio/gpiolib-shared.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,7 @@ int gpio_device_setup_shared(struct gpio_device *gdev)
515515
{
516516
struct gpio_shared_entry *entry;
517517
struct gpio_shared_ref *ref;
518-
unsigned long *flags;
518+
struct gpio_desc *desc;
519519
int ret;
520520

521521
list_for_each_entry(entry, &gpio_shared_list, list) {
@@ -543,15 +543,17 @@ int gpio_device_setup_shared(struct gpio_device *gdev)
543543
if (list_count_nodes(&entry->refs) <= 1)
544544
continue;
545545

546-
flags = &gdev->descs[entry->offset].flags;
546+
desc = &gdev->descs[entry->offset];
547547

548-
__set_bit(GPIOD_FLAG_SHARED, flags);
548+
__set_bit(GPIOD_FLAG_SHARED, &desc->flags);
549549
/*
550550
* Shared GPIOs are not requested via the normal path. Make
551551
* them inaccessible to anyone even before we register the
552552
* chip.
553553
*/
554-
__set_bit(GPIOD_FLAG_REQUESTED, flags);
554+
ret = gpiod_request_commit(desc, "shared");
555+
if (ret)
556+
return ret;
555557

556558
pr_debug("GPIO %u owned by %s is shared by multiple consumers\n",
557559
entry->offset, gpio_device_get_label(gdev));
@@ -562,8 +564,10 @@ int gpio_device_setup_shared(struct gpio_device *gdev)
562564
ref->con_id ?: "(none)");
563565

564566
ret = gpio_shared_make_adev(gdev, entry, ref);
565-
if (ret)
567+
if (ret) {
568+
gpiod_free_commit(desc);
566569
return ret;
570+
}
567571
}
568572
}
569573

@@ -579,6 +583,8 @@ void gpio_device_teardown_shared(struct gpio_device *gdev)
579583
if (!device_match_fwnode(&gdev->dev, entry->fwnode))
580584
continue;
581585

586+
gpiod_free_commit(&gdev->descs[entry->offset]);
587+
582588
list_for_each_entry(ref, &entry->refs, list) {
583589
guard(mutex)(&ref->lock);
584590

drivers/gpio/gpiolib.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2453,7 +2453,7 @@ EXPORT_SYMBOL_GPL(gpiochip_remove_pin_ranges);
24532453
* on each other, and help provide better diagnostics in debugfs.
24542454
* They're called even less than the "set direction" calls.
24552455
*/
2456-
static int gpiod_request_commit(struct gpio_desc *desc, const char *label)
2456+
int gpiod_request_commit(struct gpio_desc *desc, const char *label)
24572457
{
24582458
unsigned int offset;
24592459
int ret;
@@ -2515,7 +2515,7 @@ int gpiod_request(struct gpio_desc *desc, const char *label)
25152515
return ret;
25162516
}
25172517

2518-
static void gpiod_free_commit(struct gpio_desc *desc)
2518+
void gpiod_free_commit(struct gpio_desc *desc)
25192519
{
25202520
unsigned long flags;
25212521

drivers/gpio/gpiolib.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,9 @@ DEFINE_CLASS(gpio_chip_guard,
244244
struct gpio_desc *desc)
245245

246246
int gpiod_request(struct gpio_desc *desc, const char *label);
247+
int gpiod_request_commit(struct gpio_desc *desc, const char *label);
247248
void gpiod_free(struct gpio_desc *desc);
249+
void gpiod_free_commit(struct gpio_desc *desc);
248250

249251
static inline int gpiod_request_user(struct gpio_desc *desc, const char *label)
250252
{

0 commit comments

Comments
 (0)