> 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: [email protected]
> > Signed-off-by: Long Li <[email protected]>
> > ---
> >  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
> >

Reply via email to