[PATCH v3 5/6] gpio: delay: free wrapped real GPIOs on remove

Pranav Sanwal <[email protected]>
Newsgroups org.u-boot-project.lists.u-boot
Message-ID <[email protected]>
gpio_delay_probe() requests the real GPIOs it wraps via
gpio_request_by_name_nodev(), which strdup()s a label into the real
GPIO device's own uc_priv->name[] array. The driver had no .remove
hook, so those requests, and their strdup'd labels, were never
released when the gpio-delay device was torn down.

Add gpio_delay_remove() to free each wrapped real GPIO. Guard each
free with device_active() on the real GPIO's device: generic DM
teardown (e.g. dm_leak_check_end()'s uclass-by-uclass destroy) does
not guarantee a consumer is removed before the provider it wraps, so
the real GPIO device may already be inactive with its uclass_priv
freed by the time this runs.

Fixes: c866f2f197e2 ("gpio: Add GPIO delay driver")
Signed-off-by: Pranav Sanwal <[email protected]>
Reviewed-by: Simon Glass <[email protected]>
---
 drivers/gpio/gpio-delay.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/drivers/gpio/gpio-delay.c b/drivers/gpio/gpio-delay.c
index f6c9c7efb0b..27fc59b5ee4 100644
--- a/drivers/gpio/gpio-delay.c
+++ b/drivers/gpio/gpio-delay.c
@@ -90,6 +90,33 @@ static int gpio_delay_xlate(struct udevice *dev, struct gpio_desc *desc,
 	return 0;
 }
 
+static void gpio_delay_free_wrapped(struct udevice *dev, int count)
+{
+	struct gpio_delay_priv *priv = dev_get_priv(dev);
+	int i;
+
+	for (i = 0; i < count; i++) {
+		/*
+		 * Generic DM teardown (e.g. dm_leak_check_end()'s
+		 * uclass-by-uclass destroy) does not guarantee a consumer is
+		 * removed before the provider it wraps, so the real GPIO
+		 * device may already be inactive with its uclass_priv freed
+		 * by the time this runs.
+		 */
+		if (device_active(priv->descs[i].real_gpio.dev))
+			dm_gpio_free(dev, &priv->descs[i].real_gpio);
+	}
+}
+
+static int gpio_delay_remove(struct udevice *dev)
+{
+	struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+
+	gpio_delay_free_wrapped(dev, uc_priv->gpio_count);
+
+	return 0;
+}
+
 static const struct dm_gpio_ops gpio_delay_ops = {
 	.direction_output = gpio_delay_direction_output,
 	.direction_input = gpio_delay_direction_input,
@@ -142,4 +169,5 @@ U_BOOT_DRIVER(gpio_delay) = {
 	.ops = &gpio_delay_ops,
 	.priv_auto = sizeof(struct gpio_delay_priv),
 	.probe = gpio_delay_probe,
+	.remove = gpio_delay_remove,
 };
-- 
2.43.7
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.