OSDN Git Service

bus: fsl-mc: automatically add a device_link on fsl_mc_[portal,object]_allocate
authorIoana Ciornei <ioana.ciornei@nxp.com>
Mon, 10 Dec 2018 16:50:19 +0000 (16:50 +0000)
committerLi Yang <leoyang.li@nxp.com>
Fri, 11 Jan 2019 21:06:54 +0000 (15:06 -0600)
Allocatable devices can be acquired by drivers on the fsl-mc bus using
the fsl_mc_portal_allocate or fsl_mc_object_allocate functions. Add a
device link between the consumer device and the supplier device so that
proper resource management is achieved.
Also, adding a link between these devices ensures that a proper unbind
order is respected (ie before the supplier device is unbound from its
respective driver all consumer devices will be notified and unbound
first).

Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com>
Reviewed-by: Laurentiu Tudor <laurentiu.tudor@nxp.com>
Signed-off-by: Li Yang <leoyang.li@nxp.com>
drivers/bus/fsl-mc/fsl-mc-allocator.c
drivers/bus/fsl-mc/mc-io.c
include/linux/fsl/mc.h

index e906ecf..8ad7724 100644 (file)
@@ -295,6 +295,14 @@ int __must_check fsl_mc_object_allocate(struct fsl_mc_device *mc_dev,
        if (!mc_adev)
                goto error;
 
+       mc_adev->consumer_link = device_link_add(&mc_dev->dev,
+                                                &mc_adev->dev,
+                                                DL_FLAG_AUTOREMOVE_CONSUMER);
+       if (!mc_adev->consumer_link) {
+               error = -EINVAL;
+               goto error;
+       }
+
        *new_mc_adev = mc_adev;
        return 0;
 error:
@@ -321,6 +329,9 @@ void fsl_mc_object_free(struct fsl_mc_device *mc_adev)
                return;
 
        fsl_mc_resource_free(resource);
+
+       device_link_del(mc_adev->consumer_link);
+       mc_adev->consumer_link = NULL;
 }
 EXPORT_SYMBOL_GPL(fsl_mc_object_free);
 
index 7226cfc..3ae574a 100644 (file)
@@ -209,9 +209,19 @@ int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev,
        if (error < 0)
                goto error_cleanup_resource;
 
+       dpmcp_dev->consumer_link = device_link_add(&mc_dev->dev,
+                                                  &dpmcp_dev->dev,
+                                                  DL_FLAG_AUTOREMOVE_CONSUMER);
+       if (!dpmcp_dev->consumer_link) {
+               error = -EINVAL;
+               goto error_cleanup_mc_io;
+       }
+
        *new_mc_io = mc_io;
        return 0;
 
+error_cleanup_mc_io:
+       fsl_destroy_mc_io(mc_io);
 error_cleanup_resource:
        fsl_mc_resource_free(resource);
        return error;
@@ -244,6 +254,9 @@ void fsl_mc_portal_free(struct fsl_mc_io *mc_io)
 
        fsl_destroy_mc_io(mc_io);
        fsl_mc_resource_free(resource);
+
+       device_link_del(dpmcp_dev->consumer_link);
+       dpmcp_dev->consumer_link = NULL;
 }
 EXPORT_SYMBOL_GPL(fsl_mc_portal_free);
 
index 741f567..975553a 100644 (file)
@@ -193,6 +193,7 @@ struct fsl_mc_device {
        struct resource *regions;
        struct fsl_mc_device_irq **irqs;
        struct fsl_mc_resource *resource;
+       struct device_link *consumer_link;
 };
 
 #define to_fsl_mc_device(_dev) \