From 47441f7f73b7cf0c2d6e7d6372f026ea81193fd6 Mon Sep 17 00:00:00 2001 From: Ioana Ciornei Date: Mon, 10 Dec 2018 16:50:19 +0000 Subject: [PATCH] soc: fsl: dpio: add a device_link at dpaa2_io_service_register 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 Reviewed-by: Horia Geanta Reviewed-by: Ioana Radulescu Signed-off-by: Li Yang --- drivers/crypto/caam/caamalg_qi2.c | 6 +++--- drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c | 9 +++++---- drivers/soc/fsl/dpio/dpio-service.c | 16 ++++++++++++++-- include/soc/fsl/dpaa2-io.h | 6 ++++-- 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/drivers/crypto/caam/caamalg_qi2.c b/drivers/crypto/caam/caamalg_qi2.c index 425d5d974613..77f4c0045de2 100644 --- a/drivers/crypto/caam/caamalg_qi2.c +++ b/drivers/crypto/caam/caamalg_qi2.c @@ -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) diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c index 1ca9a18139ec..c500ea77aaa0 100644 --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c @@ -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); } } diff --git a/drivers/soc/fsl/dpio/dpio-service.c b/drivers/soc/fsl/dpio/dpio-service.c index 52d800aa4774..bc801934602a 100644 --- a/drivers/soc/fsl/dpio/dpio-service.c +++ b/drivers/soc/fsl/dpio/dpio-service.c @@ -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); diff --git a/include/soc/fsl/dpaa2-io.h b/include/soc/fsl/dpaa2-io.h index e252066d1f43..3447fd10a3e6 100644 --- a/include/soc/fsl/dpaa2-io.h +++ b/include/soc/fsl/dpaa2-io.h @@ -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);