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; | ||||
| 
 | ||||
| 		/* 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) | ||||
|  | ||||
| @ -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); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -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); | ||||
| 
 | ||||
|  | ||||
| @ -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); | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user