From: sashiko-bot@kernel.org
To: "Tariq Toukan" <tariqt@nvidia.com>
Cc: bpf@vger.kernel.org, linux-rdma@vger.kernel.org
Subject: Re: [PATCH net-next V2 1/2] net/mlx5e: Batch NAPI RCU grace periods on channel close
Date: Wed, 11 Nov 2026 18:51:55 +0000 [thread overview]
Message-ID: <sashiko-outbox-209498@kernel.org> (raw)
In-Reply-To: <20261110185005.2932568-2-tariqt@nvidia.com>
Thank you for your contribution! Sashiko AI review found 2 potential
issues to consider:
- [High] net/mlx5e: missing grace period after page_pool_destroy() in
channel close
- [Low] net/mlx5e: redundant pre/post_sync open-coding and duplicated
queue teardown
--
commit 2f06177c661abed7fd45e14fc9a588083535c8b2
Author: Carolina Jubran <cjubran@nvidia.com>
net/mlx5e: Batch NAPI RCU grace periods on channel close
This commit splits channel deactivation and teardown into pre_sync and
post_sync phases so that synchronize_net() grace periods are batched
across all channels during channel close.
> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
> index c3c2c5720c6f3..73b504ba8c8c6 100644
> --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
> +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
[ ... ]
> @@ -2749,6 +2785,27 @@ static void mlx5e_close_queues(struct mlx5e_channel *c)
> mlx5e_close_cq(&c->icosq.cq);
> }
>
> +static void mlx5e_close_queues_post_sync(struct mlx5e_channel *c)
> +{
> + if (c->xdp)
> + mlx5e_close_xdpsq_post_sync(&c->rq_xdpsq);
> + /* The same ICOSQ is used for UMRs for both RQ and XSKRQ. */
> + cancel_work_sync(&c->icosq.recover_work);
> + mlx5e_close_rq(&c->rq);
> + mlx5e_close_sqs(c);
> + mlx5e_close_icosq(&c->icosq);
> + mutex_destroy(&c->icosq_recovery_lock);
> + if (c->async_icosq)
> + mlx5e_close_async_icosq(c->async_icosq);
> + if (c->xdp)
> + mlx5e_close_cq(&c->rq_xdpsq.cq);
> + mlx5e_close_cq(&c->rq.cq);
> + if (c->xdpsq)
> + mlx5e_close_xdpredirect_sq_post_sync(c->xdpsq);
> + mlx5e_close_tx_cqs(c);
> + mlx5e_close_cq(&c->icosq.cq);
> +}
[ ... ]
> @@ -3060,32 +3144,67 @@ static int mlx5e_wait_channels_min_rx_wqes(struct mlx5e_channels *chs)
[ ... ]
> +static void mlx5e_close_channels_pre_sync(struct mlx5e_channels *chs)
> +{
> + int i;
> +
> + if (chs->ptp)
> + __netif_napi_del_locked(&chs->ptp->napi);
> +
> + for (i = 0; i < chs->num; i++) {
> + mlx5e_close_channel_pre_sync(chs->c[i]);
> + __netif_napi_del_locked(&chs->c[i]->napi);
> + }
> +}
> +
> +static void mlx5e_close_channels_post_sync(struct mlx5e_channels *chs)
> +{
> + int i;
> +
> + if (chs->ptp) {
> + mlx5e_ptp_close_queues(chs->ptp);
> + kvfree(chs->ptp);
> + chs->ptp = NULL;
> + }
> +
> + for (i = 0; i < chs->num; i++) {
> + mlx5e_close_channel_post_sync(chs->c[i]);
> + kvfree(chs->c[i]);
> + }
>
> kfree(chs->c);
> chs->num = 0;
> }
>
> +void mlx5e_close_channels(struct mlx5e_channels *chs)
> +{
> + mlx5e_close_channels_pre_sync(chs);
> + synchronize_net();
> + mlx5e_close_channels_post_sync(chs);
> +}
[Severity: High]
Can freeing chs->ptp and chs->c[i] in mlx5e_close_channels_post_sync()
cause a use-after-free on &c->napi (or &ptp->napi) in
page_pool_napi_local()?
rq->page_pool is created with pool->p.napi pointing to the NAPI struct
embedded in struct mlx5e_channel or struct mlx5e_ptp. That pointer is
only cleared when mlx5e_close_rq() -> mlx5e_free_rq() ->
xdp_rxq_info_unreg() calls page_pool_destroy():
net/core/page_pool.c:page_pool_disable_direct_recycling() {
...
WRITE_ONCE(pool->p.napi, NULL);
}
Before this patch, mlx5e_close_queues() and mlx5e_ptp_close_queues() ran
before netif_napi_del_locked(), so synchronize_net() waited for any
concurrent softirq running page_pool_napi_local() to finish before
kvfree() freed the channel. Moving queue teardown into
mlx5e_close_channels_post_sync() places page_pool_destroy() after
synchronize_net(), and page_pool_scrub() skips its own synchronize_net()
when dma_dev_need_sync() is false:
CPU0 CPU1 (<softirq>)
mlx5e_close_channels()
mlx5e_close_channels_pre_sync()
synchronize_net()
mlx5e_close_channels_post_sync()
mlx5e_close_channel_post_sync()
...
napi_consume_skb()
...
page_pool_napi_local()
napi = READ_ONCE(pool->p.napi);
page_pool_destroy()
WRITE_ONCE(pool->p.napi, NULL);
kvfree(chs->c[i])
READ_ONCE(napi->list_owner)
<-- use-after-free
Closing the queues before synchronize_net() (or waiting for a grace period
after page_pool_destroy() before kvfree()) would avoid freeing the channel
while a softirq still holds the NAPI pointer.
[ ... ]
> @@ -3610,8 +3742,14 @@ int mlx5e_close_locked(struct net_device *netdev)
> clear_bit(MLX5E_STATE_OPENED, &priv->state);
>
> netif_carrier_off(priv->netdev);
> - mlx5e_deactivate_priv_channels(priv);
> - mlx5e_close_channels(&priv->channels);
> +
> + mlx5e_deactivate_priv_channels_pre_sync(priv);
> + synchronize_net();
> + mlx5e_deactivate_priv_channels_post_sync(priv);
> +
> + mlx5e_close_channels_pre_sync(&priv->channels);
> + synchronize_net();
> + mlx5e_close_channels_post_sync(&priv->channels);
>
> return 0;
> }
[Severity: Low]
This isn't a bug, but mlx5e_close_locked() open-codes the exact bodies of
mlx5e_deactivate_priv_channels() and mlx5e_close_channels() without
combining their synchronize_net() calls, so it could keep calling those
two helpers directly. Similarly, mlx5e_close_queues_post_sync()
duplicates mlx5e_close_queues(); mlx5e_close_queues() could run the
pre_sync steps, call synchronize_net(), and call
mlx5e_close_queues_post_sync() like mlx5e_close_channel() does.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261110185005.2932568-1-tariqt@nvidia.com?part=1
next prev parent reply other threads:[~2026-11-11 18:51 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-10 18:50 [PATCH net-next V2 0/2] net/mlx5e: Batch RCU grace periods on channel open and close Tariq Toukan
2026-11-10 18:50 ` [PATCH net-next V2 1/2] net/mlx5e: Batch NAPI RCU grace periods on channel close Tariq Toukan
2026-11-11 18:51 ` sashiko-bot [this message]
2026-11-10 18:50 ` [PATCH net-next V2 2/2] net/mlx5e: Batch ICOSQ trigger RCU synchronization Tariq Toukan
2026-11-11 18:51 ` sashiko-bot
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-209498@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=linux-rdma@vger.kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
--cc=tariqt@nvidia.com \
/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