[PATCH 2/2] crypto: img-hash: fix IRQ teardown ordering and fetch clocks early
Rosen Penev <[email protected]>
| Newsgroups | org.kernel.vger.linux-crypto,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
The IRQ handler schedules tasklets, so free_irq must run before tasklet_kill in img_hash_remove(). devm_request_irq only freed the IRQ during devm unwind, after remove() returned, leaving a race in which the handler could re-schedule a tasklet during teardown. Replace it with request_irq and free the IRQ explicitly in remove() and in the probe error path. Assisted-by: opencode:deepseek-v4-flash-free Signed-off-by: Rosen Penev <[email protected]> --- drivers/crypto/img-hash.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/crypto/img-hash.c b/drivers/crypto/img-hash.c index f7265347901c..4153972ec3e7 100644 --- a/drivers/crypto/img-hash.c +++ b/drivers/crypto/img-hash.c @@ -125,6 +125,7 @@ struct img_hash_dev { spinlock_t lock; int err; + int irq; struct tasklet_struct done_task; struct tasklet_struct dma_task; @@ -978,16 +979,16 @@ static int img_hash_probe(struct platform_device *pdev) hdev->bus_addr = hash_res->start; hdev->hash_clk = hash_clk; hdev->sys_clk = sys_clk; + hdev->irq = irq; - err = devm_request_irq(dev, irq, img_irq_handler, 0, - dev_name(dev), hdev); + err = request_irq(hdev->irq, img_irq_handler, 0, dev_name(dev), hdev); if (err) goto res_err; dev_dbg(dev, "using IRQ channel %d\n", irq); err = img_hash_dma_init(hdev); if (err) - goto res_err; + goto err_irq; dev_dbg(dev, "using %s for DMA transfers\n", dma_chan_name(hdev->dma_lch)); @@ -1008,6 +1009,8 @@ static int img_hash_probe(struct platform_device *pdev) list_del(&hdev->list); spin_unlock(&img_hash.lock); dma_release_channel(hdev->dma_lch); +err_irq: + free_irq(hdev->irq, hdev); res_err: tasklet_kill(&hdev->done_task); tasklet_kill(&hdev->dma_task); @@ -1026,6 +1029,7 @@ static void img_hash_remove(struct platform_device *pdev) img_unregister_algs(hdev); + free_irq(hdev->irq, hdev); tasklet_kill(&hdev->done_task); tasklet_kill(&hdev->dma_task); -- 2.55.0