Commit cb0451e3 authored by Bartosz Golaszewski's avatar Bartosz Golaszewski
Browse files

gpio: shared: verify con_id when adding proxy lookup

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: a060b8c5 ("gpiolib: implement low-level, shared GPIO support")
Link: https://lore.kernel.org/r/20251222-gpio-shared-reset-gpio-proxy-v1-2-8d4bba7d8c14@oss.qualcomm.com


Signed-off-by: default avatarBartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
parent 9700b0fc
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -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;
+3 −1
Original line number Diff line number Diff line
@@ -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;
+2 −1
Original line number Diff line number Diff line
@@ -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);