diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index 57b60cf7194c..ee6542491279 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c @@ -3034,6 +3034,18 @@ static void __init d40_chan_init(struct d40_base *base, struct dma_device *dma, } } +static void d40_kill_tasklets(void *data) +{ + struct dma_device *dma = data; + struct d40_chan *d40c; + struct dma_chan *chan; + + list_for_each_entry(chan, &dma->channels, device_node) { + d40c = container_of(chan, struct d40_chan, chan); + tasklet_kill(&d40c->tasklet); + } +} + static void d40_ops_init(struct d40_base *base, struct dma_device *dev) { if (dma_has_cap(DMA_SLAVE, dev->cap_mask)) { @@ -3080,6 +3092,11 @@ static int __init d40_dmaengine_init(struct d40_base *base, d40_ops_init(base, &base->dma_slave); + err = devm_add_action(base->dev, d40_kill_tasklets, + &base->dma_slave); + if (err) + goto exit; + err = dmaenginem_async_device_register(&base->dma_slave); if (err) { @@ -3095,6 +3112,11 @@ static int __init d40_dmaengine_init(struct d40_base *base, d40_ops_init(base, &base->dma_memcpy); + err = devm_add_action(base->dev, d40_kill_tasklets, + &base->dma_memcpy); + if (err) + goto exit; + err = dmaenginem_async_device_register(&base->dma_memcpy); if (err) { @@ -3112,6 +3134,12 @@ static int __init d40_dmaengine_init(struct d40_base *base, dma_cap_set(DMA_CYCLIC, base->dma_both.cap_mask); d40_ops_init(base, &base->dma_both); + + err = devm_add_action(base->dev, d40_kill_tasklets, + &base->dma_both); + if (err) + goto exit; + err = dmaenginem_async_device_register(&base->dma_both); if (err) { @@ -3709,6 +3737,7 @@ static int __init d40_probe(struct platform_device *pdev) struct d40_base *base; struct resource *res; struct resource res_lcpa; + void *dmaenginem_reg_group; int num_reserved_chans; u32 val; int ret; @@ -3839,20 +3868,32 @@ static int __init d40_probe(struct platform_device *pdev) d40_err(dev, "No IRQ defined\n"); goto destroy_cache; } + + dmaenginem_reg_group = devres_open_group(dev, NULL, GFP_KERNEL); + if (!dmaenginem_reg_group) { + ret = -ENOMEM; + goto release_irq; + } + ret = d40_dmaengine_init(base, num_reserved_chans); if (ret) - goto release_irq; + goto release_dmaenginem; ret = of_dma_controller_register(np, d40_xlate, NULL); if (ret) { dev_err(dev, "could not register of_dma_controller\n"); - goto release_irq; + goto release_dmaenginem; } + devres_remove_group(dev, dmaenginem_reg_group); dev_info(base->dev, "initialized\n"); return 0; + release_dmaenginem: + free_irq(base->irq, base); + devres_release_group(dev, dmaenginem_reg_group); + goto destroy_cache; release_irq: free_irq(base->irq, base); destroy_cache: