[PATCH] atm: eni: stop IRQ tasklet during device removal
From: Jiale Yao
Date: Sun Sep 20 2026 - 13:34:43 EST
eni_int() schedules eni_dev->task, but eni_remove_one() frees the
device state without unregistering the IRQ or draining the tasklet. An
interrupt during device unbind or hot unplug can therefore leave work
that runs after eni_dev has been freed.
Mask device interrupts, free the IRQ, and kill the tasklet before
releasing its resources. Apply the same ordering to the initialization
error path after the tasklet has been initialized.
Fixes: 126a3fd251b2 ("eni: fix driver remove function and driver probe error path.")
Signed-off-by: Jiale Yao <yaojiale02@xxxxxxx>
---
drivers/atm/eni.c | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/drivers/atm/eni.c b/drivers/atm/eni.c
index 3011cf1a84a9..44e6b3ceaf11 100644
--- a/drivers/atm/eni.c
+++ b/drivers/atm/eni.c
@@ -1881,7 +1881,11 @@ static int eni_start(struct atm_dev *dev)
return 0;
free_list:
+ eni_out(0, MID_IE);
+ free_irq(eni_dev->irq, dev);
+ tasklet_kill(&eni_dev->task);
kfree(eni_dev->free_list);
+ goto out;
free_irq:
free_irq(eni_dev->irq, dev);
@@ -2287,13 +2291,16 @@ MODULE_DEVICE_TABLE(pci,eni_pci_tbl);
static void eni_remove_one(struct pci_dev *pdev)
{
struct atm_dev *dev = pci_get_drvdata(pdev);
- struct eni_dev *ed = ENI_DEV(dev);
- struct eni_zero *zero = &ed->zero;
+ struct eni_dev *eni_dev = ENI_DEV(dev);
+ struct eni_zero *zero = &eni_dev->zero;
+ eni_out(0, MID_IE);
+ free_irq(eni_dev->irq, dev);
+ tasklet_kill(&eni_dev->task);
eni_do_release(dev);
atm_dev_deregister(dev);
dma_free_coherent(&pdev->dev, ENI_ZEROES_SIZE, zero->addr, zero->dma);
- kfree(ed);
+ kfree(eni_dev);
pci_disable_device(pdev);
}
--
2.34.1