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]>
---
Changes in v2:
- New patch.
drivers/gpio/gpio-delay.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/drivers/gpio/gpio-delay.c b/drivers/gpio/gpio-delay.c
index f6c9c7efb0b..78e79176f3e 100644
--- a/drivers/gpio/gpio-delay.c
+++ b/drivers/gpio/gpio-delay.c
@@ -90,6 +90,20 @@ static int gpio_delay_xlate(struct udevice *dev, struct
gpio_desc *desc,
return 0;
}
+static int gpio_delay_remove(struct udevice *dev)
+{
+ struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+ struct gpio_delay_priv *priv = dev_get_priv(dev);
+ int i;
+
+ for (i = 0; i < uc_priv->gpio_count; i++) {
+ if (device_active(priv->descs[i].real_gpio.dev))
+ dm_gpio_free(dev, &priv->descs[i].real_gpio);
+ }
+
+ 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 +156,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