[PATCH v7 2/5] gpio: shared: factor out per-entry setup helper

From: Bartosz Golaszewski

Date: Wed Oct 28 2026 - 10:48:58 EST


Move the per-entry part of gpiochip_setup_shared() into
gpio_shared_setup_entry(). This is a preparation for making the setup
all-or-nothing, which requires handling the failure of a single entry
in isolation. No functional change.

Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@xxxxxxxxxxxxxxxx>
---
drivers/gpio/gpiolib-shared.c | 112 ++++++++++++++++++++++++------------------
1 file changed, 63 insertions(+), 49 deletions(-)

diff --git a/drivers/gpio/gpiolib-shared.c b/drivers/gpio/gpiolib-shared.c
index 64bb450f0a8461d214a45aa97e2474ff0d1857ce..47b434db72f1ebd35ec36ebdb35f30809f4522f2 100644
--- a/drivers/gpio/gpiolib-shared.c
+++ b/drivers/gpio/gpiolib-shared.c
@@ -538,12 +538,71 @@ static void gpio_shared_teardown_entry(struct gpio_device *gdev,
}
}

+static int gpio_shared_setup_entry(struct gpio_chip *gc,
+ struct gpio_shared_entry *entry)
+{
+ struct gpio_device *gdev = gc->gpiodev;
+ struct gpio_shared_ref *ref;
+ struct gpio_desc *desc;
+ int ret;
+
+ scoped_guard(mutex, &entry->lock) {
+#if IS_ENABLED(CONFIG_OF)
+ if (is_of_node(entry->fwnode) && gc->of_xlate) {
+ /*
+ * This is the earliest that we can tranlate the
+ * devicetree offset to the chip offset.
+ */
+ struct of_phandle_args gpiospec = { };
+
+ gpiospec.np = to_of_node(entry->fwnode);
+ gpiospec.args_count = 2;
+ gpiospec.args[0] = entry->offset;
+
+ ret = gc->of_xlate(gc, &gpiospec, NULL);
+ if (ret < 0)
+ return ret;
+
+ entry->offset = ret;
+ }
+#endif /* CONFIG_OF */
+
+ desc = &gdev->descs[entry->offset];
+
+ __set_bit(GPIOD_FLAG_SHARED, &desc->flags);
+ /*
+ * Shared GPIOs are not requested via the normal path. Make
+ * them inaccessible to anyone even before we register the
+ * chip.
+ */
+ ret = gpiod_request_commit(desc, "shared");
+ if (ret)
+ return ret;
+
+ pr_debug("GPIO %u owned by %s is shared by multiple consumers\n",
+ 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 (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) {
+ gpiod_free_commit(desc);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
int gpiochip_setup_shared(struct gpio_chip *gc)
{
struct gpio_device *gdev = gc->gpiodev;
struct gpio_shared_entry *entry;
struct gpio_shared_ref *ref;
- struct gpio_desc *desc;
int ret;

list_for_each_entry(entry, &gpio_shared_list, list) {
@@ -571,54 +630,9 @@ int gpiochip_setup_shared(struct gpio_chip *gc)
if (list_count_nodes(&entry->refs) <= 1)
continue;

- scoped_guard(mutex, &entry->lock) {
-#if IS_ENABLED(CONFIG_OF)
- if (is_of_node(entry->fwnode) && gc->of_xlate) {
- /*
- * This is the earliest that we can tranlate the
- * devicetree offset to the chip offset.
- */
- struct of_phandle_args gpiospec = { };
-
- gpiospec.np = to_of_node(entry->fwnode);
- gpiospec.args_count = 2;
- gpiospec.args[0] = entry->offset;
-
- ret = gc->of_xlate(gc, &gpiospec, NULL);
- if (ret < 0)
- return ret;
-
- entry->offset = ret;
- }
-#endif /* CONFIG_OF */
-
- desc = &gdev->descs[entry->offset];
-
- __set_bit(GPIOD_FLAG_SHARED, &desc->flags);
- /*
- * Shared GPIOs are not requested via the normal path. Make
- * them inaccessible to anyone even before we register the
- * chip.
- */
- ret = gpiod_request_commit(desc, "shared");
- if (ret)
- return ret;
-
- pr_debug("GPIO %u owned by %s is shared by multiple consumers\n",
- 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 (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) {
- gpiod_free_commit(desc);
- return ret;
- }
- }
+ ret = gpio_shared_setup_entry(gc, entry);
+ if (ret)
+ return ret;
}

return 0;

--
2.47.3