Commit 310a4a9c authored by Bartosz Golaszewski's avatar Bartosz Golaszewski
Browse files

gpio: shared: shorten the critical section in gpiochip_setup_shared()



Commit 710abda5 ("gpio: shared: call gpio_chip::of_xlate() if set")
introduced a critical section around the adjustmenet of entry->offset.
However this may cause a deadlock if we create the auxiliary shared
proxy devices with this lock taken. We only need to protect
entry->offset while it's read/written so shorten the critical section
and release the lock before creating the proxy device as the field in
question is no longer accessed at this point.

Fixes: 710abda5 ("gpio: shared: call gpio_chip::of_xlate() if set")
Reported-by: default avatarDmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Link: https://patch.msgid.link/20260325-gpio-shared-deadlock-v1-1-e4e7a5319e95@oss.qualcomm.com


Signed-off-by: default avatarBartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
parent c720fb57
Loading
Loading
Loading
Loading
+28 −28
Original line number Diff line number Diff line
@@ -533,14 +533,13 @@ int gpiochip_setup_shared(struct gpio_chip *gc)
	 * exposing shared pins. Find them and create the proxy devices.
	 */
	list_for_each_entry(entry, &gpio_shared_list, list) {
		guard(mutex)(&entry->lock);

		if (!device_match_fwnode(&gdev->dev, entry->fwnode))
			continue;

		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) {
				/*
@@ -575,6 +574,7 @@ int gpiochip_setup_shared(struct gpio_chip *gc)

			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",