Commit 47441f7f authored by Ioana Ciornei's avatar Ioana Ciornei Committed by Li Yang

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: default avatarIoana Ciornei <ioana.ciornei@nxp.com>
Reviewed-by: default avatarHoria Geanta <horia.geanta@nxp.com>
Reviewed-by: default avatarIoana Radulescu <ruxandra.radulescu@nxp.com>
Signed-off-by: default avatarLi Yang <leoyang.li@nxp.com>
parent cf9ff75d
...@@ -4503,7 +4503,7 @@ static int __cold dpaa2_dpseci_dpio_setup(struct dpaa2_caam_priv *priv) ...@@ -4503,7 +4503,7 @@ static int __cold dpaa2_dpseci_dpio_setup(struct dpaa2_caam_priv *priv)
nctx->cb = dpaa2_caam_fqdan_cb; nctx->cb = dpaa2_caam_fqdan_cb;
/* Register notification callbacks */ /* Register notification callbacks */
err = dpaa2_io_service_register(NULL, nctx); err = dpaa2_io_service_register(NULL, nctx, dev);
if (unlikely(err)) { if (unlikely(err)) {
dev_dbg(dev, "No affine DPIO for cpu %d\n", cpu); dev_dbg(dev, "No affine DPIO for cpu %d\n", cpu);
nctx->cb = NULL; nctx->cb = NULL;
...@@ -4536,7 +4536,7 @@ static int __cold dpaa2_dpseci_dpio_setup(struct dpaa2_caam_priv *priv) ...@@ -4536,7 +4536,7 @@ static int __cold dpaa2_dpseci_dpio_setup(struct dpaa2_caam_priv *priv)
ppriv = per_cpu_ptr(priv->ppriv, cpu); ppriv = per_cpu_ptr(priv->ppriv, cpu);
if (!ppriv->nctx.cb) if (!ppriv->nctx.cb)
break; break;
dpaa2_io_service_deregister(NULL, &ppriv->nctx); dpaa2_io_service_deregister(NULL, &ppriv->nctx, dev);
} }
for_each_online_cpu(cpu) { for_each_online_cpu(cpu) {
...@@ -4556,7 +4556,7 @@ static void __cold dpaa2_dpseci_dpio_free(struct dpaa2_caam_priv *priv) ...@@ -4556,7 +4556,7 @@ static void __cold dpaa2_dpseci_dpio_free(struct dpaa2_caam_priv *priv)
for_each_online_cpu(cpu) { for_each_online_cpu(cpu) {
ppriv = per_cpu_ptr(priv->ppriv, 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); dpaa2_io_store_destroy(ppriv->store);
if (++i == priv->num_pairs) if (++i == priv->num_pairs)
......
...@@ -1902,7 +1902,7 @@ static int setup_dpio(struct dpaa2_eth_priv *priv) ...@@ -1902,7 +1902,7 @@ static int setup_dpio(struct dpaa2_eth_priv *priv)
/* Register the new context */ /* Register the new context */
channel->dpio = dpaa2_io_service_select(i); 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) { if (err) {
dev_dbg(dev, "No affine DPIO for cpu %d\n", i); dev_dbg(dev, "No affine DPIO for cpu %d\n", i);
/* If no affine DPIO for this core, there's probably /* If no affine DPIO for this core, there's probably
...@@ -1942,7 +1942,7 @@ static int setup_dpio(struct dpaa2_eth_priv *priv) ...@@ -1942,7 +1942,7 @@ static int setup_dpio(struct dpaa2_eth_priv *priv)
return 0; return 0;
err_set_cdan: err_set_cdan:
dpaa2_io_service_deregister(channel->dpio, nctx); dpaa2_io_service_deregister(channel->dpio, nctx, dev);
err_service_reg: err_service_reg:
free_channel(priv, channel); free_channel(priv, channel);
err_alloc_ch: err_alloc_ch:
...@@ -1962,13 +1962,14 @@ static int setup_dpio(struct dpaa2_eth_priv *priv) ...@@ -1962,13 +1962,14 @@ static int setup_dpio(struct dpaa2_eth_priv *priv)
static void free_dpio(struct dpaa2_eth_priv *priv) static void free_dpio(struct dpaa2_eth_priv *priv)
{ {
int i; struct device *dev = priv->net_dev->dev.parent;
struct dpaa2_eth_channel *ch; struct dpaa2_eth_channel *ch;
int i;
/* deregister CDAN notifications and free channels */ /* deregister CDAN notifications and free channels */
for (i = 0; i < priv->num_channels; i++) { for (i = 0; i < priv->num_channels; i++) {
ch = priv->channel[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); free_channel(priv, ch);
} }
} }
......
...@@ -237,6 +237,7 @@ EXPORT_SYMBOL(dpaa2_io_get_cpu); ...@@ -237,6 +237,7 @@ EXPORT_SYMBOL(dpaa2_io_get_cpu);
* notifications on the given DPIO service. * notifications on the given DPIO service.
* @d: the given DPIO service. * @d: the given DPIO service.
* @ctx: the notification context. * @ctx: the notification context.
* @dev: the device that requests the register
* *
* The caller should make the MC command to attach a DPAA2 object to * The caller should make the MC command to attach a DPAA2 object to
* a DPIO after this function completes successfully. In that way: * a DPIO after this function completes successfully. In that way:
...@@ -251,14 +252,20 @@ EXPORT_SYMBOL(dpaa2_io_get_cpu); ...@@ -251,14 +252,20 @@ EXPORT_SYMBOL(dpaa2_io_get_cpu);
* Return 0 for success, or -ENODEV for failure. * Return 0 for success, or -ENODEV for failure.
*/ */
int dpaa2_io_service_register(struct dpaa2_io *d, 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; unsigned long irqflags;
d = service_select_by_cpu(d, ctx->desired_cpu); d = service_select_by_cpu(d, ctx->desired_cpu);
if (!d) if (!d)
return -ENODEV; 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->dpio_id = d->dpio_desc.dpio_id;
ctx->qman64 = (u64)(uintptr_t)ctx; ctx->qman64 = (u64)(uintptr_t)ctx;
ctx->dpio_private = d; ctx->dpio_private = d;
...@@ -279,12 +286,14 @@ EXPORT_SYMBOL_GPL(dpaa2_io_service_register); ...@@ -279,12 +286,14 @@ EXPORT_SYMBOL_GPL(dpaa2_io_service_register);
* dpaa2_io_service_deregister - The opposite of 'register'. * dpaa2_io_service_deregister - The opposite of 'register'.
* @service: the given DPIO service. * @service: the given DPIO service.
* @ctx: the notification context. * @ctx: the notification context.
* @dev: the device that requests to be deregistered
* *
* This function should be called only after sending the MC command to * This function should be called only after sending the MC command to
* to detach the notification-producing device from the DPIO. * to detach the notification-producing device from the DPIO.
*/ */
void dpaa2_io_service_deregister(struct dpaa2_io *service, 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; struct dpaa2_io *d = ctx->dpio_private;
unsigned long irqflags; unsigned long irqflags;
...@@ -295,6 +304,9 @@ void dpaa2_io_service_deregister(struct dpaa2_io *service, ...@@ -295,6 +304,9 @@ void dpaa2_io_service_deregister(struct dpaa2_io *service,
spin_lock_irqsave(&d->lock_notifications, irqflags); spin_lock_irqsave(&d->lock_notifications, irqflags);
list_del(&ctx->node); list_del(&ctx->node);
spin_unlock_irqrestore(&d->lock_notifications, irqflags); spin_unlock_irqrestore(&d->lock_notifications, irqflags);
if (dev)
device_link_remove(dev, d->dev);
} }
EXPORT_SYMBOL_GPL(dpaa2_io_service_deregister); EXPORT_SYMBOL_GPL(dpaa2_io_service_deregister);
......
...@@ -94,9 +94,11 @@ struct dpaa2_io_notification_ctx { ...@@ -94,9 +94,11 @@ struct dpaa2_io_notification_ctx {
int dpaa2_io_get_cpu(struct dpaa2_io *d); int dpaa2_io_get_cpu(struct dpaa2_io *d);
int dpaa2_io_service_register(struct dpaa2_io *service, 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, 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, int dpaa2_io_service_rearm(struct dpaa2_io *service,
struct dpaa2_io_notification_ctx *ctx); struct dpaa2_io_notification_ctx *ctx);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment