[PATCH] scsi: megaraid_sas: kill tasklet after free_irq in teardown paths

From: Fan Wu

Date: Tue Aug 18 2026 - 20:52:09 EST


On MFI-series adapters the interrupt handler arms instance->isr_tasklet
for as long as the interrupt is registered, so the tasklet can be armed
again after tasklet_kill() has returned. megasas_detach_one() and
megasas_suspend() kill the tasklet before unregistering the interrupts,
and the probe error paths skip the kill entirely, so the completion
callback can run after the teardown frees the buffers it dereferences,
or a tasklet pending across suspend is re-initialized by resume's
tasklet_init() while still queued.

Kill the tasklet after megasas_destroy_irqs(), which drains the handler
via free_irq(), and add the missing kills in the probe error paths.

This issue was found by an in-house static analysis tool.

Fixes: 5d018ad05734 ("[SCSI] megaraid_sas: adds tasklet for cmd completion")
Cc: stable@xxxxxxxxxxxxxxx
Assisted-by: Codex:gpt-5.6
Signed-off-by: Fan Wu <fanwu01@xxxxxxxxxx>
---
drivers/scsi/megaraid/megaraid_sas_base.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
index ecd365d78ae3..627bcba720cd 100644
--- a/drivers/scsi/megaraid/megaraid_sas_base.c
+++ b/drivers/scsi/megaraid/megaraid_sas_base.c
@@ -6536,6 +6536,7 @@ static int megasas_init_fw(struct megasas_instance *instance)
fail_get_ld_pd_list:
instance->instancet->disable_intr(instance);
megasas_destroy_irqs(instance);
+ tasklet_kill(&instance->isr_tasklet);
fail_init_adapter:
if (instance->msix_vectors)
pci_free_irq_vectors(instance->pdev);
@@ -7618,6 +7619,7 @@ static int megasas_probe_one(struct pci_dev *pdev,

instance->instancet->disable_intr(instance);
megasas_destroy_irqs(instance);
+ tasklet_kill(&instance->isr_tasklet);

if (instance->adapter_type != MFI_SERIES)
megasas_release_fusion(instance);
@@ -7770,12 +7772,11 @@ megasas_suspend(struct device *dev)
instance->ev = NULL;
}

- tasklet_kill(&instance->isr_tasklet);
-
pci_set_drvdata(instance->pdev, instance);
instance->instancet->disable_intr(instance);

megasas_destroy_irqs(instance);
+ tasklet_kill(&instance->isr_tasklet);

if (instance->msix_vectors)
pci_free_irq_vectors(instance->pdev);
@@ -8010,8 +8011,6 @@ static void megasas_detach_one(struct pci_dev *pdev)
/* cancel all wait events */
wake_up_all(&instance->int_cmd_wait_q);

- tasklet_kill(&instance->isr_tasklet);
-
/*
* Take the instance off the instance array. Note that we will not
* decrement the max_index. We let this array be sparse array
@@ -8028,6 +8027,7 @@ static void megasas_detach_one(struct pci_dev *pdev)
instance->instancet->disable_intr(instance);

megasas_destroy_irqs(instance);
+ tasklet_kill(&instance->isr_tasklet);

if (instance->msix_vectors)
pci_free_irq_vectors(instance->pdev);