* [PATCH] qed: drain slowpath tasklets during teardown
@ 2026-10-28 4:55 Jiale Yao
2026-10-28 5:00 ` netdev-bot+sinfo
2026-10-30 7:56 ` netdev-bot+sashiko
0 siblings, 2 replies; 3+ messages in thread
From: Jiale Yao @ 2026-10-28 4:55 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Ariel Elior, Yuval Mintz, netdev, linux-kernel
Cc: stable
qed_nic_stop() disables each slowpath tasklet before freeing the
interrupt and status block resources. Disabling waits for a running
tasklet, but it does not remove a pending tasklet from the tasklet
queue. A pending tasklet can therefore retain a pointer to the freed
qed_hwfn and its status blocks.
Kill the tasklet during the final slowpath teardown so pending work is
removed before the resources it accesses are released.
Fixes: fe56b9e6a8d9 ("qed: Add module with basic common support")
Cc: stable@vger.kernel.org
Signed-off-by: Jiale Yao <yaojiale02@163.com>
---
drivers/net/ethernet/qlogic/qed/qed_main.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c
index 28a8a2b9d501..abe8a841b277 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_main.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_main.c
@@ -833,10 +833,10 @@ static int qed_nic_stop(struct qed_dev *cdev)
struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
if (p_hwfn->b_sp_dpc_enabled) {
- tasklet_disable(&p_hwfn->sp_dpc);
+ tasklet_kill(&p_hwfn->sp_dpc);
p_hwfn->b_sp_dpc_enabled = false;
DP_VERBOSE(cdev, NETIF_MSG_IFDOWN,
- "Disabled sp tasklet [hwfn %d] at %p\n",
+ "Killed sp tasklet [hwfn %d] at %p\n",
i, &p_hwfn->sp_dpc);
}
}
--
2.34.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH] qed: drain slowpath tasklets during teardown
2026-10-28 4:55 [PATCH] qed: drain slowpath tasklets during teardown Jiale Yao
@ 2026-10-28 5:00 ` netdev-bot+sinfo
2026-10-30 7:56 ` netdev-bot+sashiko
1 sibling, 0 replies; 3+ messages in thread
From: netdev-bot+sinfo @ 2026-10-28 5:00 UTC (permalink / raw)
To: Jiale Yao
Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Ariel Elior, Yuval Mintz, netdev, linux-kernel,
stable
Hi!
This is an automated message. This series looks like a fix, but its
commit messages seem to be missing some information:
- How the issue was discovered, e.g. hit in production, hit during
development, syzbot report, manual code inspection, LLM or static
analysis tool scan.
- Whether the issue was actually triggered, or is only theoretical
(e.g. found by code inspection). If it was triggered please include
the symptoms, like the stack trace or error messages.
- What hardware the change was tested on. For driver fixes please
mention the device (and if relevant firmware version) used for
testing, or say that the change was not tested on real hardware.
Please do not repost the series just to address the above. Instead,
reply to this email with the missing information, so that reviewers
can take it into account. If the series needs another revision for
other reasons, please include the information in the commit messages
then.
The evaluation is done by an LLM so it may be wrong, if you think
that is the case please reply and explain.
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] qed: drain slowpath tasklets during teardown
2026-10-28 4:55 [PATCH] qed: drain slowpath tasklets during teardown Jiale Yao
2026-10-28 5:00 ` netdev-bot+sinfo
@ 2026-10-30 7:56 ` netdev-bot+sashiko
1 sibling, 0 replies; 3+ messages in thread
From: netdev-bot+sashiko @ 2026-10-30 7:56 UTC (permalink / raw)
To: yaojiale02
Cc: andrew+netdev, davem, edumazet, kuba, pabeni, Ariel.Elior,
Yuval.Mintz, netdev, linux-kernel, stable
Thank you for your contribution! Sashiko AI review found 2 potential
issue(s) to consider.
Critical: 0 · High: 1 · Medium: 1 · Low: 0
If you believe none of the issues are legitimate, please reply to each
issue of Medium severity or higher and explain why the AI is wrong.
If any of them are legitimate and you plan to respin, please let patchwork
know by including "pw-bot: cr" as a separate line at the end of your reply
(one such reply per series is enough).
- [High] The fix covers only the normal stop path.
- [Medium] In qed_slowpath_stop() (qed_main.c:1412-1419) the order is
qed_nic_stop(), which now calls tasklet_kill(), then…
--
qed: drain slowpath tasklets during teardown
This patch replaces tasklet_disable() with tasklet_kill() for the per-hwfn
sp_dpc tasklet in qed_nic_stop(). The intent is that a pending slowpath
tasklet is removed from the queue before qed_slowpath_stop() frees the
interrupt and status block resources.
> diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c
> index 28a8a2b9d501c..abe8a841b2773 100644
> --- a/drivers/net/ethernet/qlogic/qed/qed_main.c
> +++ b/drivers/net/ethernet/qlogic/qed/qed_main.c
> @@ -833,10 +833,10 @@ static int qed_nic_stop(struct qed_dev *cdev)
> struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
>
> if (p_hwfn->b_sp_dpc_enabled) {
> - tasklet_disable(&p_hwfn->sp_dpc);
> + tasklet_kill(&p_hwfn->sp_dpc);
[Severity: High]
Only qed_slowpath_stop() reaches qed_nic_stop(). What about the error
unwind in qed_slowpath_start()?
By the time any of its error labels can be taken, the tasklet is set up
and the slowpath IRQ is live:
qed_nic_setup()->qed_resc_setup()->qed_int_setup()->qed_int_sp_dpc_setup()
tasklet_setup(&p_hwfn->sp_dpc, qed_int_sp_dpc);
p_hwfn->b_sp_dpc_enabled = true;
qed_hw_init()->qed_hw_init_pf()
qed_int_igu_enable(p_hwfn, p_ptt, int_mode);
...
rc = qed_sp_pf_start(p_hwfn, p_ptt, p_tunn,
qed_sp_pf_start(), qed_mcp_load_done(), the DCBX mcp cmd,
qed_ll2_alloc_if() or qed_mcp_send_drv_version() can fail after that
point. When one does, qed_slowpath_start() unwinds through:
err3:
qed_hw_stop(cdev);
err2:
qed_hw_timers_stop_all(cdev);
if (IS_PF(cdev))
qed_slowpath_irq_free(cdev);
qed_free_stream_mem(cdev);
qed_disable_msix(cdev);
err1:
qed_resc_free(cdev);
Nothing on this path calls tasklet_kill(&p_hwfn->sp_dpc).
free_irq() waits for the hardirq handler but not for the tasklet. The
flush in qed_hw_stop() is only a disable/enable, so a pending tasklet
stays pending.
Next, qed_resc_free()->qed_int_free()->qed_int_sp_sb_free() frees the
status block that qed_int_sp_dpc() dereferences:
dma_free_coherent(&p_hwfn->cdev->pdev->dev,
SB_ALIGNED_SIZE(p_hwfn),
p_sb->sb_info.sb_virt,
p_sb->sb_info.sb_phys);
kfree(p_sb);
After that, __qede_probe() takes its err1 label and calls
qed_ops->common->remove()->qed_remove()->qed_free_cdev(). That kfree()s
the qed_dev that embeds hwfns[i].sp_dpc.
Suppose the last interrupt scheduled sp_dpc and it hasn't run yet. Can
qed_int_sp_dpc() then run against the freed status blocks? Could a freed
tasklet_struct also be left on the per-CPU tasklet list?
Would it make sense to kill the tasklet in a common teardown helper, for
example after free_irq() in qed_slowpath_irq_free()? That would cover
both the stop path and the qed_slowpath_start() unwind.
> p_hwfn->b_sp_dpc_enabled = false;
[Severity: Medium]
Is this ordering safe with respect to the slowpath IRQ? qed_slowpath_stop()
does:
qed_nic_stop(cdev);
if (IS_PF(cdev))
qed_slowpath_irq_free(cdev);
qed_disable_msix(cdev);
qed_resc_free(cdev);
This means the handlers that schedule sp_dpc are still registered when
tasklet_kill() returns:
qed_msix_sp_int()
tasklet_schedule((struct tasklet_struct *)tasklet);
qed_single_int()
if (unlikely(status & 0x1)) {
tasklet_schedule(&hwfn->sp_dpc);
In INTA mode, qed_single_int() is registered with IRQF_SHARED and reads
the SISR over MMIO. On a surprise-removed device that read returns
all-ones.
qed_hw_stop() calls qed_slowpath_irq_sync() only once, before
qed_sp_pf_stop() and qed_int_igu_disable_int(). qed_int_igu_disable_int()
only writes IGU_REG_PF_CONFIGURATION and does not wait for in-flight
handlers. No synchronize_irq() follows it.
The old tasklet_disable() left t->count at 1, so a late tasklet_schedule()
could queue the tasklet but it would not run. After tasklet_kill() the
count is 0. An interrupt that arrives between tasklet_kill() and
free_irq() therefore queues an enabled tasklet again. Nothing kills it a
second time after free_irq().
Can qed_int_sp_dpc() then run on another CPU during or after
qed_resc_free()->qed_int_sp_sb_free()? It reads p_sp_sb, sb_virt and
p_sb_attn. It also calls qed_sb_ack(sb_info, IGU_INT_ENABLE, 1) on a PF
that has already been stopped.
Would it close this window to call tasklet_kill() only after the IRQ
source is gone, for example after free_irq() in qed_slowpath_irq_free()?
[ ... ]
--
Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20261028045535.110688-1-yaojiale02%40163.com
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-10-30 7:56 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-28 4:55 [PATCH] qed: drain slowpath tasklets during teardown Jiale Yao
2026-10-28 5:00 ` netdev-bot+sinfo
2026-10-30 7:56 ` netdev-bot+sashiko
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox