Intel-Wired-Lan Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Tian Xun Ng" <luckilystar08@gmail.com>,
	intel-wired-lan@lists.osuosl.org
Subject: Re: [PATCH iwl-net v5 3/3] idpf: keep the mailbox up while tearing down vports on shutdown
Date: Wed, 14 Oct 2026 12:13:06 +0000	[thread overview]
Message-ID: <sashiko-outbox-171247@kernel.org> (raw)
In-Reply-To: <20261013121224.84482-4-luckilystar08@gmail.com>

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] idpf: NULL pointer dereference in idpf_tx_start during shutdown
- [High] idpf: SW marker consumption race causes cascading timeouts
- [High] idpf: DMA memory corruption on slow CP during shutdown
--

commit 0b30345598a4b0c67b0f2410c2aaf6bf5c4a2f30
Author: Tian Xun Ng <tianxun.ng@bytedance.com>

idpf: keep the mailbox up while tearing down vports on shutdown

Since commit 4c9106f4906a ("idpf: fix adapter NULL pointer dereference
on reboot"), idpf_shutdown() calls idpf_vc_core_deinit() directly instead
of idpf_remove(), so IDPF_REMOVE_IN_PROG is not set on shutdown.
idpf_vc_core_deinit() uses that flag to decide when to shut the virtchnl
transaction manager down. Without it, libie_ctlq_xn_shutdown() runs
before idpf_deinit_task() tears the vports down.

> diff --git a/drivers/net/ethernet/intel/idpf/idpf_main.c b/drivers/net/ethernet/intel/idpf/idpf_main.c
> index 129bccaa6baa8..21be83dc82b1b 100644
> --- a/drivers/net/ethernet/intel/idpf/idpf_main.c
> +++ b/drivers/net/ethernet/intel/idpf/idpf_main.c
> @@ -194,8 +194,18 @@ static void idpf_shutdown(struct pci_dev *pdev)
>  {
>  	struct idpf_adapter *adapter = pci_get_drvdata(pdev);
>  
> +	/* As in idpf_remove(): keep the event task from being requeued, and
> +	 * destroy the vports while the mailbox is still up.
> +	 */
> +	set_bit(IDPF_REMOVE_IN_PROG, adapter->flags);
>  	cancel_delayed_work_sync(&adapter->serv_task);
>  	cancel_delayed_work_sync(&adapter->vc_event_task);
> +
> +	/* Bound the teardown transactions started from here on, so that an
> +	 * unresponsive control plane costs a single timeout. A reset or a
> +	 * transaction that is already running keeps its own timeouts.
> +	 */
> +	WRITE_ONCE(adapter->vc_xn_timeout_ms, IDPF_VC_XN_SHUTDOWN_TIMEOUT_MSEC);
>  	idpf_vc_core_deinit(adapter);

[Severity: High]
If a hardware reset is in progress (IDPF_HR_RESET_IN_PROG is set),
idpf_vport_dealloc() skips calling idpf_vport_stop() and idpf_decfg_netdev().

This leaves the netdev fully registered with active transmit queues, while the
underlying vport is freed and np->vport is set to NULL:

drivers/net/ethernet/intel/idpf/idpf_lib.c:idpf_vport_dealloc() {
    if (!test_bit(IDPF_HR_RESET_IN_PROG, adapter->flags)) {
        idpf_vport_stop(vport, true);
        idpf_decfg_netdev(vport);
    }
    ...
    if (adapter->netdevs[i]) {
        struct idpf_netdev_priv *np = netdev_priv(adapter->netdevs[i]);
        np->vport = NULL;
    }
    idpf_vport_rel(vport);
}

Unlike idpf_remove(), the idpf_shutdown() function lacks a fallback loop to
unregister stale netdevs or detach the device.

If the networking stack transmits a packet before the system finishes halting,
idpf_tx_start() will dereference the NULL vport:

drivers/net/ethernet/intel/idpf/idpf_txrx.c:idpf_tx_start() {
    const struct idpf_vport *vport = idpf_netdev_to_vport(netdev);
    ...
    if (unlikely(skb_get_queue_mapping(skb) >=
                 vport->num_txq - vport->num_xdp_txq)) {

Can this lead to a NULL pointer dereference kernel panic during shutdown?

> diff --git a/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c b/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c
> index 2cfd216ae92b1..331d56faee253 100644
> --- a/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c
> +++ b/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c

[ ... ]

> @@ -218,10 +230,15 @@ int idpf_send_mb_msg(struct idpf_adapter *adapter,
>  	xn_params->xnm = adapter->xnm;
>  	xn_params->ctlq = xn_params->ctlq ? xn_params->ctlq : adapter->asq;
>  	xn_params->rel_tx_buf = kfree;
> +	xn_params->timeout_ms = min_t(u64, xn_params->timeout_ms, timeout_ms);
>  
>  	idpf_mb_clean(xn_params->ctlq, false);
>  
> -	return libie_ctlq_xn_send(xn_params);
> +	err = libie_ctlq_xn_send(xn_params);
> +	if (err == -ETIMEDOUT && timeout_ms < IDPF_VC_XN_DEFAULT_TIMEOUT_MSEC)
> +		WRITE_ONCE(adapter->vc_xn_timeout_ms, 0);
> +
> +	return err;
>  }

[Severity: High]
If a teardown transaction times out on a slow control plane,
adapter->vc_xn_timeout_ms is set to 0.

This causes subsequent teardown messages (like VIRTCHNL2_OP_DEL_QUEUES) to
fail immediately without being sent.

However, idpf_vport_stop() ignores these failures and unconditionally
frees the descriptor rings' DMA memory via idpf_vport_queues_rel():

drivers/net/ethernet/intel/idpf/idpf_lib.c:idpf_vport_stop() {
    if (test_and_clear_bit(IDPF_VPORT_DEL_QUEUES, vport->flags))
        idpf_send_delete_queues_msg(adapter, chunks, vport_id);
    ...
    idpf_vport_queues_rel(vport, rsrc);
}

If the hardware is still active and eventually processes the delayed
disable queues command, it could write SW_MARKER to the unmapped DMA memory.

Could this lead to DMA memory corruption or an IOMMU fault during shutdown?

[ ... ]

> @@ -380,7 +402,8 @@ static int idpf_wait_for_marker_event_set(const struct idpf_queue_set *qs)
>  			netdev = txq->netdev;
>  
>  			idpf_queue_set(SW_MARKER, txq);
> -			idpf_wait_for_sw_marker_completion(txq);
> +			if (markers_rcvd || wait_all)
> +				idpf_wait_for_sw_marker_completion(txq);
>  			markers_rcvd &= !idpf_queue_has(SW_MARKER, txq);
>  			break;

[Severity: High]
When multiple Tx queues share a completion queue,
idpf_wait_for_sw_marker_completion() polls the ring and consumes any
SW markers it encounters, clearing their SW_MARKER flags:

drivers/net/ethernet/intel/idpf/idpf_txrx.c:idpf_wait_for_sw_marker_completion() {
    ...
    target = complq->txq_grp->txqs[id];
    idpf_queue_clear(SW_MARKER, target);
    ...
}

Because idpf_queue_set(SW_MARKER, txq) is set sequentially for each queue
right before waiting, won't the polling loop for an earlier queue consume
the markers for subsequent queues?

Since the subsequent queues haven't had their SW_MARKER flag set yet by
the outer loop, clearing them is a no-op, and their markers are permanently
lost.

Could this amplify a single delayed or out-of-order marker into a massive
timeout cascade for the remaining queues? Would hoisting the
idpf_queue_set(SW_MARKER, ...) calls to a separate loop before the wait
loop prevent this?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261013121224.84482-1-luckilystar08@gmail.com?part=3

  parent reply	other threads:[~2026-10-14 12:13 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-13 12:12 [PATCH iwl-net v5 0/3] idpf: destroy the vports on shutdown Tian Xun Ng
2026-10-13 12:12 ` [PATCH iwl-net v5 1/3] idpf: ignore Tx timestamp replies once removal has started Tian Xun Ng
2026-10-13 16:26   ` Tantilov, Emil S
2026-10-13 12:12 ` [PATCH iwl-net v5 2/3] idpf: ignore link events " Tian Xun Ng
2026-10-13 16:27   ` Tantilov, Emil S
2026-10-13 12:12 ` [PATCH iwl-net v5 3/3] idpf: keep the mailbox up while tearing down vports on shutdown Tian Xun Ng
2026-10-13 16:31   ` Tantilov, Emil S
2026-10-14 12:13   ` sashiko-bot [this message]
2026-10-14 13:30     ` Tian Xun Ng

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=sashiko-outbox-171247@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=intel-wired-lan@lists.osuosl.org \
    --cc=luckilystar08@gmail.com \
    --cc=sashiko-reviews@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox