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

gpio: shared: undo the vote of the proxy on GPIO free

When the user of a shared GPIO managed by gpio-shared-proxy calls
gpiod_put() to release it, we never undo the potential "vote" for
driving the shared line "high". In the free() callback, check if this
proxy voted for "high" and - if so - decrease the number of votes and
potentially revert the value to low if this is the last user.

Cc: stable@vger.kernel.org
Fixes: e992d54c ("gpio: shared-proxy: implement the shared GPIO proxy driver")
Closes: https://sashiko.dev/#/patchset/20260513-gpio-shared-dynamic-voting-v1-1-8e1c49961b7d%40oss.qualcomm.com


Reviewed-by: default avatarLinus Walleij <linusw@kernel.org>
Link: https://patch.msgid.link/20260522-gpio-shared-free-vote-v3-1-8a4fddc6bedb@oss.qualcomm.com


Signed-off-by: default avatarBartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
parent dac917ed
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -103,9 +103,18 @@ static void gpio_shared_proxy_free(struct gpio_chip *gc, unsigned int offset)
{
	struct gpio_shared_proxy_data *proxy = gpiochip_get_data(gc);
	struct gpio_shared_desc *shared_desc = proxy->shared_desc;
	int ret;

	guard(gpio_shared_desc_lock)(shared_desc);

	if (proxy->voted_high) {
		ret = gpio_shared_proxy_set_unlocked(proxy,
			shared_desc->can_sleep ? gpiod_set_value_cansleep : gpiod_set_value, 0);
		if (ret)
			dev_err(proxy->dev,
				"Failed to unset the shared GPIO value on release: %d\n", ret);
	}

	proxy->shared_desc->usecnt--;

	dev_dbg(proxy->dev, "Shared GPIO freed, number of users: %u\n",