]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
RDMA/mana_ib: Disable RX steering on RSS QP destroy
authorLong Li <longli@microsoft.com>
Wed, 25 Mar 2026 19:40:57 +0000 (12:40 -0700)
committerLeon Romanovsky <leon@kernel.org>
Mon, 30 Mar 2026 17:47:45 +0000 (13:47 -0400)
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>
Link: https://patch.msgid.link/20260325194100.1929056-1-longli@microsoft.com
Signed-off-by: Leon Romanovsky <leon@kernel.org>
drivers/infiniband/hw/mana/qp.c
drivers/net/ethernet/microsoft/mana/mana_en.c
include/net/mana/mana.h

index f3bb1edc7f79ff229bec6c9a616068d16ae99ae0..e6fc3cc10795ff75bf58741037b22949e2972178 100644 (file)
@@ -799,6 +799,21 @@ static int mana_ib_destroy_qp_rss(struct mana_ib_qp *qp,
        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.
+        *
+        * This is best effort — if it fails there is not much we can do,
+        * and mana_cfg_vport_steering() already logs the error.
+        */
+       mana_disable_vport_rx(mpc);
+
        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);
index dca62fb9a3a9ef42500b40463647ca346b426601..af2a35c09773679ccfb5a21502bbaad0dab418b6 100644 (file)
@@ -2882,6 +2882,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)
 {
@@ -3266,10 +3273,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_vport(apc);
 
index a078af283bddbb625eb59127d35c3d968fb4c62c..743bfa8ad8e36868a4de45807f10852cb709f024 100644 (file)
@@ -568,6 +568,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);