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 <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>
This commit is contained in:
parent
cf9ff75d15
commit
47441f7f73
|
@ -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 @@ err:
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
/* 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)
|
||||||
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 @@ err_alloc_ch:
|
||||||
|
|
||||||
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);
|
||||||
* 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);
|
||||||
* 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);
|
||||||
* 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,
|
||||||
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 {
|
||||||
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);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue