soc: fsl: dpio: add a device_link at dpaa2_io_service_register
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)
Automatically add a device link between the actual device requesting the
dpaa2_io_service_register and the underlying dpaa2_io used. This link
will ensure that when a DPIO device, which is indirectly used by other
devices, is unbound any consumer devices will be also unbound from their
drivers.

For example, any DPNI, bound to the dpaa2-eth driver, which is using
DPIO devices will be unbound before its supplier device.

Also, add a new parameter to the dpaa2_io_service_[de]register functions
to specify the requesting device (ie the consumer).

Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com>
Reviewed-by: Horia Geanta <horia.geanta@nxp.com>
Reviewed-by: Ioana Radulescu <ruxandra.radulescu@nxp.com>
Signed-off-by: Li Yang <leoyang.li@nxp.com>
drivers/crypto/caam/caamalg_qi2.c
drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
drivers/soc/fsl/dpio/dpio-service.c
include/soc/fsl/dpaa2-io.h

index 425d5d97461311277d925585d7f2eec3ccbcd967..77f4c0045de2972f3eb010f4f81022cf908b5ee2 100644 (file)
@@ -4503,7 +4503,7 @@ static int __cold dpaa2_dpseci_dpio_setup(struct dpaa2_caam_priv *priv)
                nctx->cb = dpaa2_caam_fqdan_cb;
 
                /* Register notification callbacks */
-               err = dpaa2_io_service_register(NULL, nctx);
+               err = dpaa2_io_service_register(NULL, nctx, dev);
                if (unlikely(err)) {
                        dev_dbg(dev, "No affine DPIO for cpu %d\n", cpu);
                        nctx->cb = NULL;
@@ -4536,7 +4536,7 @@ err:
                ppriv = per_cpu_ptr(priv->ppriv, cpu);
                if (!ppriv->nctx.cb)
                        break;
-               dpaa2_io_service_deregister(NULL, &ppriv->nctx);
+               dpaa2_io_service_deregister(NULL, &ppriv->nctx, dev);
        }
 
        for_each_online_cpu(cpu) {
@@ -4556,7 +4556,7 @@ static void __cold dpaa2_dpseci_dpio_free(struct dpaa2_caam_priv *priv)
 
        for_each_online_cpu(cpu) {
                ppriv = per_cpu_ptr(priv->ppriv, cpu);
-               dpaa2_io_service_deregister(NULL, &ppriv->nctx);
+               dpaa2_io_service_deregister(NULL, &ppriv->nctx, priv->dev);
                dpaa2_io_store_destroy(ppriv->store);
 
                if (++i == priv->num_pairs)
index 1ca9a18139ec5b3b63c6a655a4bc19a3d4bb8428..c500ea77aaa05014588d7e7b5089539e545e618b 100644 (file)
@@ -1902,7 +1902,7 @@ static int setup_dpio(struct dpaa2_eth_priv *priv)
 
                /* Register the new context */
                channel->dpio = dpaa2_io_service_select(i);
-               err = dpaa2_io_service_register(channel->dpio, nctx);
+               err = dpaa2_io_service_register(channel->dpio, nctx, dev);
                if (err) {
                        dev_dbg(dev, "No affine DPIO for cpu %d\n", i);
                        /* If no affine DPIO for this core, there's probably
@@ -1942,7 +1942,7 @@ static int setup_dpio(struct dpaa2_eth_priv *priv)
        return 0;
 
 err_set_cdan:
-       dpaa2_io_service_deregister(channel->dpio, nctx);
+       dpaa2_io_service_deregister(channel->dpio, nctx, dev);
 err_service_reg:
        free_channel(priv, channel);
 err_alloc_ch:
@@ -1962,13 +1962,14 @@ err_alloc_ch:
 
 static void free_dpio(struct dpaa2_eth_priv *priv)
 {
-       int i;
+       struct device *dev = priv->net_dev->dev.parent;
        struct dpaa2_eth_channel *ch;
+       int i;
 
        /* deregister CDAN notifications and free channels */
        for (i = 0; i < priv->num_channels; i++) {
                ch = priv->channel[i];
-               dpaa2_io_service_deregister(ch->dpio, &ch->nctx);
+               dpaa2_io_service_deregister(ch->dpio, &ch->nctx, dev);
                free_channel(priv, ch);
        }
 }
index 52d800aa47747bf99d12f8731ae71e6f90123f75..bc801934602a9407f5b1889a0927c39447e425ae 100644 (file)
@@ -237,6 +237,7 @@ EXPORT_SYMBOL(dpaa2_io_get_cpu);
  *                               notifications on the given DPIO service.
  * @d:   the given DPIO service.
  * @ctx: the notification context.
+ * @dev: the device that requests the register
  *
  * The caller should make the MC command to attach a DPAA2 object to
  * a DPIO after this function completes successfully.  In that way:
@@ -251,14 +252,20 @@ EXPORT_SYMBOL(dpaa2_io_get_cpu);
  * Return 0 for success, or -ENODEV for failure.
  */
 int dpaa2_io_service_register(struct dpaa2_io *d,
-                             struct dpaa2_io_notification_ctx *ctx)
+                             struct dpaa2_io_notification_ctx *ctx,
+                             struct device *dev)
 {
+       struct device_link *link;
        unsigned long irqflags;
 
        d = service_select_by_cpu(d, ctx->desired_cpu);
        if (!d)
                return -ENODEV;
 
+       link = device_link_add(dev, d->dev, DL_FLAG_AUTOREMOVE_CONSUMER);
+       if (!link)
+               return -EINVAL;
+
        ctx->dpio_id = d->dpio_desc.dpio_id;
        ctx->qman64 = (u64)(uintptr_t)ctx;
        ctx->dpio_private = d;
@@ -279,12 +286,14 @@ EXPORT_SYMBOL_GPL(dpaa2_io_service_register);
  * dpaa2_io_service_deregister - The opposite of 'register'.
  * @service: the given DPIO service.
  * @ctx: the notification context.
+ * @dev: the device that requests to be deregistered
  *
  * This function should be called only after sending the MC command to
  * to detach the notification-producing device from the DPIO.
  */
 void dpaa2_io_service_deregister(struct dpaa2_io *service,
-                                struct dpaa2_io_notification_ctx *ctx)
+                                struct dpaa2_io_notification_ctx *ctx,
+                                struct device *dev)
 {
        struct dpaa2_io *d = ctx->dpio_private;
        unsigned long irqflags;
@@ -295,6 +304,9 @@ void dpaa2_io_service_deregister(struct dpaa2_io *service,
        spin_lock_irqsave(&d->lock_notifications, irqflags);
        list_del(&ctx->node);
        spin_unlock_irqrestore(&d->lock_notifications, irqflags);
+
+       if (dev)
+               device_link_remove(dev, d->dev);
 }
 EXPORT_SYMBOL_GPL(dpaa2_io_service_deregister);
 
index e252066d1f438f2c95aa08fc598a1785399f2660..3447fd10a3e6809093a3611b9e1171fdac9c7ea0 100644 (file)
@@ -94,9 +94,11 @@ struct dpaa2_io_notification_ctx {
 int dpaa2_io_get_cpu(struct dpaa2_io *d);
 
 int dpaa2_io_service_register(struct dpaa2_io *service,
-                             struct dpaa2_io_notification_ctx *ctx);
+                             struct dpaa2_io_notification_ctx *ctx,
+                             struct device *dev);
 void dpaa2_io_service_deregister(struct dpaa2_io *service,
-                                struct dpaa2_io_notification_ctx *ctx);
+                                struct dpaa2_io_notification_ctx *ctx,
+                                struct device *dev);
 int dpaa2_io_service_rearm(struct dpaa2_io *service,
                           struct dpaa2_io_notification_ctx *ctx);