From: Thierry Reding <tred...@nvidia.com>

When a driver's ->probe() function fails, the host1x bus must not call
its ->remove() function because the driver will already have cleaned up
in the error handling path in ->probe().

Signed-off-by: Thierry Reding <treding at nvidia.com>
---
 drivers/gpu/host1x/bus.c | 9 +++++++--
 include/linux/host1x.h   | 2 ++
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/host1x/bus.c b/drivers/gpu/host1x/bus.c
index aaf54859adb0..e4182e68e29c 100644
--- a/drivers/gpu/host1x/bus.c
+++ b/drivers/gpu/host1x/bus.c
@@ -116,7 +116,10 @@ static void host1x_subdev_register(struct host1x_device 
*device,
        if (list_empty(&device->subdevs)) {
                err = device->driver->probe(device);
                if (err < 0)
-                       dev_err(&device->dev, "probe failed: %d\n", err);
+                       dev_err(&device->dev, "probe failed for %ps: %d\n",
+                               device->driver, err);
+               else
+                       device->bound = true;
        }
 }

@@ -130,10 +133,12 @@ static void __host1x_subdev_unregister(struct 
host1x_device *device,
         * If all subdevices have been activated, we're about to remove the
         * first active subdevice, so unload the driver first.
         */
-       if (list_empty(&device->subdevs)) {
+       if (list_empty(&device->subdevs) && device->bound) {
                err = device->driver->remove(device);
                if (err < 0)
                        dev_err(&device->dev, "remove failed: %d\n", err);
+
+               device->bound = false;
        }

        /*
diff --git a/include/linux/host1x.h b/include/linux/host1x.h
index bb9840fd1e18..7890b553d12e 100644
--- a/include/linux/host1x.h
+++ b/include/linux/host1x.h
@@ -272,6 +272,8 @@ struct host1x_device {

        struct mutex clients_lock;
        struct list_head clients;
+
+       bool bound;
 };

 static inline struct host1x_device *to_host1x_device(struct device *dev)
-- 
2.1.3

Reply via email to