When host1x_device_parse_dt() fails, host1x_device_add() only frees the
host1x_device and leaves the subdevs collected by host1x_subdev_add()
on device->subdevs. Each of those subdevs still holds an OF node
reference acquired with of_node_get(), which is normally dropped by
host1x_subdev_del().

Remove all stale subdevs, dropping their device node references, before
freeing the device.

Fixes: 776dc3840367 ("drm/tegra: Move subdevice infrastructure to host1x")
Cc: [email protected]
Signed-off-by: Wentao Liang <[email protected]>
---
 drivers/gpu/host1x/bus.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/host1x/bus.c b/drivers/gpu/host1x/bus.c
index f814eb4941c0..8dbab96b7f5a 100644
--- a/drivers/gpu/host1x/bus.c
+++ b/drivers/gpu/host1x/bus.c
@@ -455,7 +455,7 @@ static int host1x_device_add(struct host1x *host1x,
                             struct host1x_driver *driver)
 {
        struct host1x_client *client, *tmp;
-       struct host1x_subdev *subdev;
+       struct host1x_subdev *subdev, *sd;
        struct host1x_device *device;
        int err;
 
@@ -485,6 +485,10 @@ static int host1x_device_add(struct host1x *host1x,
 
        err = host1x_device_parse_dt(device, driver);
        if (err < 0) {
+               mutex_lock(&device->subdevs_lock);
+               list_for_each_entry_safe(subdev, sd, &device->subdevs, list)
+                       host1x_subdev_del(subdev);
+               mutex_unlock(&device->subdevs_lock);
                kfree(device);
                return err;
        }
-- 
2.34.1

Reply via email to