public inbox for netdev@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH rdma] RDMA/mana_ib: Disable RX steering on RSS QP destroy
@ 2026-03-21  0:28 Long Li
  2026-03-22 18:48 ` Leon Romanovsky
  0 siblings, 1 reply; 3+ messages in thread
From: Long Li @ 2026-03-21  0:28 UTC (permalink / raw)
  To: Long Li, Konstantin Taranov, Jakub Kicinski, David S . Miller,
	Paolo Abeni, Eric Dumazet, Andrew Lunn, Jason Gunthorpe,
	Leon Romanovsky, Haiyang Zhang, K . Y . Srinivasan, Wei Liu,
	Dexuan Cui
  Cc: Simon Horman, netdev, linux-rdma, linux-hyperv, linux-kernel,
	stable

When an RSS QP is destroyed (e.g. DPDK exit), mana_ib_destroy_qp_rss()
destroys the RX WQ objects but does not disable vPort RX steering in
firmware. This leaves stale steering configuration that still points to
the destroyed RX objects.

If traffic continues to arrive (e.g. peer VM is still transmitting) and
the VF interface is subsequently brought up (mana_open), the firmware
may deliver completions using stale CQ IDs from the old RX objects.
These CQ IDs can be reused by the ethernet driver for new TX CQs,
causing RX completions to land on TX CQs:

  WARNING: mana_poll_tx_cq+0x1b8/0x220 [mana]  (is_sq == false)
  WARNING: mana_gd_process_eq_events+0x209/0x290 (cq_table lookup fails)

Fix this by disabling vPort RX steering before destroying RX WQ objects.
Note that mana_fence_rqs() cannot be used here because the fence
completion is delivered on the CQ, which is polled by user-mode (e.g.
DPDK) and not visible to the kernel driver.

Refactor the disable logic into a shared mana_disable_vport_rx() in
mana_en, exported for use by mana_ib, replacing the duplicate code.
The ethernet driver's mana_dealloc_queues() is also updated to call
this common function.

Fixes: 0266a177631d ("RDMA/mana_ib: Add a driver for Microsoft Azure Network Adapter")
Cc: stable@vger.kernel.org
Signed-off-by: Long Li <longli@microsoft.com>
---
 drivers/infiniband/hw/mana/qp.c               | 17 ++++++++++++++++-
 drivers/net/ethernet/microsoft/mana/mana_en.c | 11 ++++++++++-
 include/net/mana/mana.h                       |  1 +
 3 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/drivers/infiniband/hw/mana/qp.c b/drivers/infiniband/hw/mana/qp.c
index 80cf4ade4b75..b27084c53a14 100644
--- a/drivers/infiniband/hw/mana/qp.c
+++ b/drivers/infiniband/hw/mana/qp.c
@@ -829,11 +829,26 @@ static int mana_ib_destroy_qp_rss(struct mana_ib_qp *qp,
 	struct net_device *ndev;
 	struct mana_ib_wq *wq;
 	struct ib_wq *ibwq;
-	int i;
+	int i, err;
 
 	ndev = mana_ib_get_netdev(qp->ibqp.device, qp->port);
 	mpc = netdev_priv(ndev);
 
+	/* Disable vPort RX steering before destroying RX WQ objects.
+	 * Otherwise firmware still routes traffic to the destroyed queues,
+	 * which can cause bogus completions on reused CQ IDs when the
+	 * ethernet driver later creates new queues on mana_open().
+	 *
+	 * Unlike the ethernet teardown path, mana_fence_rqs() cannot be
+	 * used here because the fence completion CQE is delivered on the
+	 * CQ which is polled by userspace (e.g. DPDK), so there is no way
+	 * for the kernel to wait for fence completion.
+	 */
+	err = mana_disable_vport_rx(mpc);
+	if (err)
+		ibdev_err(&mdev->ib_dev,
+			  "Failed to disable vPort RX: %d\n", err);
+
 	for (i = 0; i < (1 << ind_tbl->log_ind_tbl_size); i++) {
 		ibwq = ind_tbl->ind_tbl[i];
 		wq = container_of(ibwq, struct mana_ib_wq, ibwq);
diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
index 22444c7530a5..51719ef1c09b 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
@@ -2934,6 +2934,13 @@ static void mana_rss_table_init(struct mana_port_context *apc)
 			ethtool_rxfh_indir_default(i, apc->num_queues);
 }
 
+int mana_disable_vport_rx(struct mana_port_context *apc)
+{
+	return mana_cfg_vport_steering(apc, TRI_STATE_FALSE, false, false,
+				       false);
+}
+EXPORT_SYMBOL_NS(mana_disable_vport_rx, "NET_MANA");
+
 int mana_config_rss(struct mana_port_context *apc, enum TRI_STATE rx,
 		    bool update_hash, bool update_tab)
 {
@@ -3339,10 +3346,12 @@ static int mana_dealloc_queues(struct net_device *ndev)
 	 */
 
 	apc->rss_state = TRI_STATE_FALSE;
-	err = mana_config_rss(apc, TRI_STATE_FALSE, false, false);
+	err = mana_disable_vport_rx(apc);
 	if (err && mana_en_need_log(apc, err))
 		netdev_err(ndev, "Failed to disable vPort: %d\n", err);
 
+	mana_fence_rqs(apc);
+
 	/* Even in err case, still need to cleanup the vPort */
 	mana_destroy_rxqs(apc);
 	mana_destroy_txq(apc);
diff --git a/include/net/mana/mana.h b/include/net/mana/mana.h
index 204c2b612a62..2634e9135eed 100644
--- a/include/net/mana/mana.h
+++ b/include/net/mana/mana.h
@@ -574,6 +574,7 @@ struct mana_port_context {
 netdev_tx_t mana_start_xmit(struct sk_buff *skb, struct net_device *ndev);
 int mana_config_rss(struct mana_port_context *ac, enum TRI_STATE rx,
 		    bool update_hash, bool update_tab);
+int mana_disable_vport_rx(struct mana_port_context *apc);
 
 int mana_alloc_queues(struct net_device *ndev);
 int mana_attach(struct net_device *ndev);
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH rdma] RDMA/mana_ib: Disable RX steering on RSS QP destroy
  2026-03-21  0:28 [PATCH rdma] RDMA/mana_ib: Disable RX steering on RSS QP destroy Long Li
@ 2026-03-22 18:48 ` Leon Romanovsky
  2026-03-23 18:03   ` [EXTERNAL] " Long Li
  0 siblings, 1 reply; 3+ messages in thread
From: Leon Romanovsky @ 2026-03-22 18:48 UTC (permalink / raw)
  To: Long Li
  Cc: Konstantin Taranov, Jakub Kicinski, David S . Miller, Paolo Abeni,
	Eric Dumazet, Andrew Lunn, Jason Gunthorpe, Haiyang Zhang,
	K . Y . Srinivasan, Wei Liu, Dexuan Cui, Simon Horman, netdev,
	linux-rdma, linux-hyperv, linux-kernel, stable

On Fri, Mar 20, 2026 at 05:28:42PM -0700, Long Li wrote:
> When an RSS QP is destroyed (e.g. DPDK exit), mana_ib_destroy_qp_rss()
> destroys the RX WQ objects but does not disable vPort RX steering in
> firmware. This leaves stale steering configuration that still points to
> the destroyed RX objects.
> 
> If traffic continues to arrive (e.g. peer VM is still transmitting) and
> the VF interface is subsequently brought up (mana_open), the firmware
> may deliver completions using stale CQ IDs from the old RX objects.
> These CQ IDs can be reused by the ethernet driver for new TX CQs,
> causing RX completions to land on TX CQs:
> 
>   WARNING: mana_poll_tx_cq+0x1b8/0x220 [mana]  (is_sq == false)
>   WARNING: mana_gd_process_eq_events+0x209/0x290 (cq_table lookup fails)
> 
> Fix this by disabling vPort RX steering before destroying RX WQ objects.
> Note that mana_fence_rqs() cannot be used here because the fence
> completion is delivered on the CQ, which is polled by user-mode (e.g.
> DPDK) and not visible to the kernel driver.
> 
> Refactor the disable logic into a shared mana_disable_vport_rx() in
> mana_en, exported for use by mana_ib, replacing the duplicate code.
> The ethernet driver's mana_dealloc_queues() is also updated to call
> this common function.
> 
> Fixes: 0266a177631d ("RDMA/mana_ib: Add a driver for Microsoft Azure Network Adapter")
> Cc: stable@vger.kernel.org
> Signed-off-by: Long Li <longli@microsoft.com>
> ---
>  drivers/infiniband/hw/mana/qp.c               | 17 ++++++++++++++++-
>  drivers/net/ethernet/microsoft/mana/mana_en.c | 11 ++++++++++-
>  include/net/mana/mana.h                       |  1 +
>  3 files changed, 27 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/infiniband/hw/mana/qp.c b/drivers/infiniband/hw/mana/qp.c
> index 80cf4ade4b75..b27084c53a14 100644
> --- a/drivers/infiniband/hw/mana/qp.c
> +++ b/drivers/infiniband/hw/mana/qp.c
> @@ -829,11 +829,26 @@ static int mana_ib_destroy_qp_rss(struct mana_ib_qp *qp,
>  	struct net_device *ndev;
>  	struct mana_ib_wq *wq;
>  	struct ib_wq *ibwq;
> -	int i;
> +	int i, err;
>  
>  	ndev = mana_ib_get_netdev(qp->ibqp.device, qp->port);
>  	mpc = netdev_priv(ndev);
>  
> +	/* Disable vPort RX steering before destroying RX WQ objects.
> +	 * Otherwise firmware still routes traffic to the destroyed queues,
> +	 * which can cause bogus completions on reused CQ IDs when the
> +	 * ethernet driver later creates new queues on mana_open().
> +	 *
> +	 * Unlike the ethernet teardown path, mana_fence_rqs() cannot be
> +	 * used here because the fence completion CQE is delivered on the
> +	 * CQ which is polled by userspace (e.g. DPDK), so there is no way
> +	 * for the kernel to wait for fence completion.
> +	 */
> +	err = mana_disable_vport_rx(mpc);
> +	if (err)
> +		ibdev_err(&mdev->ib_dev,
> +			  "Failed to disable vPort RX: %d\n", err);

mana_cfg_vport_steering() is already prints in all failure scenarios.

Thanks

> +
>  	for (i = 0; i < (1 << ind_tbl->log_ind_tbl_size); i++) {
>  		ibwq = ind_tbl->ind_tbl[i];
>  		wq = container_of(ibwq, struct mana_ib_wq, ibwq);
> diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
> index 22444c7530a5..51719ef1c09b 100644
> --- a/drivers/net/ethernet/microsoft/mana/mana_en.c
> +++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
> @@ -2934,6 +2934,13 @@ static void mana_rss_table_init(struct mana_port_context *apc)
>  			ethtool_rxfh_indir_default(i, apc->num_queues);
>  }
>  
> +int mana_disable_vport_rx(struct mana_port_context *apc)
> +{
> +	return mana_cfg_vport_steering(apc, TRI_STATE_FALSE, false, false,
> +				       false);
> +}
> +EXPORT_SYMBOL_NS(mana_disable_vport_rx, "NET_MANA");
> +
>  int mana_config_rss(struct mana_port_context *apc, enum TRI_STATE rx,
>  		    bool update_hash, bool update_tab)
>  {
> @@ -3339,10 +3346,12 @@ static int mana_dealloc_queues(struct net_device *ndev)
>  	 */
>  
>  	apc->rss_state = TRI_STATE_FALSE;
> -	err = mana_config_rss(apc, TRI_STATE_FALSE, false, false);
> +	err = mana_disable_vport_rx(apc);
>  	if (err && mana_en_need_log(apc, err))
>  		netdev_err(ndev, "Failed to disable vPort: %d\n", err);
>  
> +	mana_fence_rqs(apc);
> +
>  	/* Even in err case, still need to cleanup the vPort */
>  	mana_destroy_rxqs(apc);
>  	mana_destroy_txq(apc);
> diff --git a/include/net/mana/mana.h b/include/net/mana/mana.h
> index 204c2b612a62..2634e9135eed 100644
> --- a/include/net/mana/mana.h
> +++ b/include/net/mana/mana.h
> @@ -574,6 +574,7 @@ struct mana_port_context {
>  netdev_tx_t mana_start_xmit(struct sk_buff *skb, struct net_device *ndev);
>  int mana_config_rss(struct mana_port_context *ac, enum TRI_STATE rx,
>  		    bool update_hash, bool update_tab);
> +int mana_disable_vport_rx(struct mana_port_context *apc);
>  
>  int mana_alloc_queues(struct net_device *ndev);
>  int mana_attach(struct net_device *ndev);
> -- 
> 2.43.0
> 

^ permalink raw reply	[flat|nested] 3+ messages in thread

* RE: [EXTERNAL] Re: [PATCH rdma] RDMA/mana_ib: Disable RX steering on RSS QP destroy
  2026-03-22 18:48 ` Leon Romanovsky
@ 2026-03-23 18:03   ` Long Li
  0 siblings, 0 replies; 3+ messages in thread
From: Long Li @ 2026-03-23 18:03 UTC (permalink / raw)
  To: Leon Romanovsky
  Cc: Konstantin Taranov, Jakub Kicinski, David S . Miller, Paolo Abeni,
	Eric Dumazet, Andrew Lunn, Jason Gunthorpe, Haiyang Zhang,
	KY Srinivasan, Wei Liu, Dexuan Cui, Simon Horman,
	netdev@vger.kernel.org, linux-rdma@vger.kernel.org,
	linux-hyperv@vger.kernel.org, linux-kernel@vger.kernel.org,
	stable@vger.kernel.org

> On Fri, Mar 20, 2026 at 05:28:42PM -0700, Long Li wrote:
> > When an RSS QP is destroyed (e.g. DPDK exit), mana_ib_destroy_qp_rss()
> > destroys the RX WQ objects but does not disable vPort RX steering in
> > firmware. This leaves stale steering configuration that still points
> > to the destroyed RX objects.
> >
> > If traffic continues to arrive (e.g. peer VM is still transmitting)
> > and the VF interface is subsequently brought up (mana_open), the
> > firmware may deliver completions using stale CQ IDs from the old RX objects.
> > These CQ IDs can be reused by the ethernet driver for new TX CQs,
> > causing RX completions to land on TX CQs:
> >
> >   WARNING: mana_poll_tx_cq+0x1b8/0x220 [mana]  (is_sq == false)
> >   WARNING: mana_gd_process_eq_events+0x209/0x290 (cq_table lookup
> > fails)
> >
> > Fix this by disabling vPort RX steering before destroying RX WQ objects.
> > Note that mana_fence_rqs() cannot be used here because the fence
> > completion is delivered on the CQ, which is polled by user-mode (e.g.
> > DPDK) and not visible to the kernel driver.
> >
> > Refactor the disable logic into a shared mana_disable_vport_rx() in
> > mana_en, exported for use by mana_ib, replacing the duplicate code.
> > The ethernet driver's mana_dealloc_queues() is also updated to call
> > this common function.
> >
> > Fixes: 0266a177631d ("RDMA/mana_ib: Add a driver for Microsoft Azure
> > Network Adapter")
> > Cc: stable@vger.kernel.org
> > Signed-off-by: Long Li <longli@microsoft.com>
> > ---
> >  drivers/infiniband/hw/mana/qp.c               | 17 ++++++++++++++++-
> >  drivers/net/ethernet/microsoft/mana/mana_en.c | 11 ++++++++++-
> >  include/net/mana/mana.h                       |  1 +
> >  3 files changed, 27 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/infiniband/hw/mana/qp.c
> > b/drivers/infiniband/hw/mana/qp.c index 80cf4ade4b75..b27084c53a14
> > 100644
> > --- a/drivers/infiniband/hw/mana/qp.c
> > +++ b/drivers/infiniband/hw/mana/qp.c
> > @@ -829,11 +829,26 @@ static int mana_ib_destroy_qp_rss(struct
> mana_ib_qp *qp,
> >  	struct net_device *ndev;
> >  	struct mana_ib_wq *wq;
> >  	struct ib_wq *ibwq;
> > -	int i;
> > +	int i, err;
> >
> >  	ndev = mana_ib_get_netdev(qp->ibqp.device, qp->port);
> >  	mpc = netdev_priv(ndev);
> >
> > +	/* Disable vPort RX steering before destroying RX WQ objects.
> > +	 * Otherwise firmware still routes traffic to the destroyed queues,
> > +	 * which can cause bogus completions on reused CQ IDs when the
> > +	 * ethernet driver later creates new queues on mana_open().
> > +	 *
> > +	 * Unlike the ethernet teardown path, mana_fence_rqs() cannot be
> > +	 * used here because the fence completion CQE is delivered on the
> > +	 * CQ which is polled by userspace (e.g. DPDK), so there is no way
> > +	 * for the kernel to wait for fence completion.
> > +	 */
> > +	err = mana_disable_vport_rx(mpc);
> > +	if (err)
> > +		ibdev_err(&mdev->ib_dev,
> > +			  "Failed to disable vPort RX: %d\n", err);
> 
> mana_cfg_vport_steering() is already prints in all failure scenarios.
> 
> Thanks

I'm sending v2 with this message removed.

Thanks,
Long

> 
> > +
> >  	for (i = 0; i < (1 << ind_tbl->log_ind_tbl_size); i++) {
> >  		ibwq = ind_tbl->ind_tbl[i];
> >  		wq = container_of(ibwq, struct mana_ib_wq, ibwq); diff --git
> > a/drivers/net/ethernet/microsoft/mana/mana_en.c
> > b/drivers/net/ethernet/microsoft/mana/mana_en.c
> > index 22444c7530a5..51719ef1c09b 100644
> > --- a/drivers/net/ethernet/microsoft/mana/mana_en.c
> > +++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
> > @@ -2934,6 +2934,13 @@ static void mana_rss_table_init(struct
> mana_port_context *apc)
> >  			ethtool_rxfh_indir_default(i, apc->num_queues);  }
> >
> > +int mana_disable_vport_rx(struct mana_port_context *apc) {
> > +	return mana_cfg_vport_steering(apc, TRI_STATE_FALSE, false, false,
> > +				       false);
> > +}
> > +EXPORT_SYMBOL_NS(mana_disable_vport_rx, "NET_MANA");
> > +
> >  int mana_config_rss(struct mana_port_context *apc, enum TRI_STATE rx,
> >  		    bool update_hash, bool update_tab)  { @@ -3339,10 +3346,12
> @@
> > static int mana_dealloc_queues(struct net_device *ndev)
> >  	 */
> >
> >  	apc->rss_state = TRI_STATE_FALSE;
> > -	err = mana_config_rss(apc, TRI_STATE_FALSE, false, false);
> > +	err = mana_disable_vport_rx(apc);
> >  	if (err && mana_en_need_log(apc, err))
> >  		netdev_err(ndev, "Failed to disable vPort: %d\n", err);
> >
> > +	mana_fence_rqs(apc);
> > +
> >  	/* Even in err case, still need to cleanup the vPort */
> >  	mana_destroy_rxqs(apc);
> >  	mana_destroy_txq(apc);
> > diff --git a/include/net/mana/mana.h b/include/net/mana/mana.h index
> > 204c2b612a62..2634e9135eed 100644
> > --- a/include/net/mana/mana.h
> > +++ b/include/net/mana/mana.h
> > @@ -574,6 +574,7 @@ struct mana_port_context {  netdev_tx_t
> > mana_start_xmit(struct sk_buff *skb, struct net_device *ndev);  int
> > mana_config_rss(struct mana_port_context *ac, enum TRI_STATE rx,
> >  		    bool update_hash, bool update_tab);
> > +int mana_disable_vport_rx(struct mana_port_context *apc);
> >
> >  int mana_alloc_queues(struct net_device *ndev);  int
> > mana_attach(struct net_device *ndev);
> > --
> > 2.43.0
> >

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-03-23 18:03 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-21  0:28 [PATCH rdma] RDMA/mana_ib: Disable RX steering on RSS QP destroy Long Li
2026-03-22 18:48 ` Leon Romanovsky
2026-03-23 18:03   ` [EXTERNAL] " Long Li

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox