i40e_vsi_setup() limits the queue pairs of an SRIOV VSI to
pf->num_lan_msix and fills info.queue_mapping[] only for that many
entries, leaving the rest zeroed. i40e_vc_get_pf_queue_id() resolves
such an entry to absolute queue 0, which belongs to the PF itself.

i40e_config_vsi_tx_queue() then overwrites the PF's queue 0 context
with the VF's ring and re-programs QTX_CTL(0) into VF mode. The PF's
next transmit on queue 0 wedges the queue: the device stops it,
reports a Malicious Driver Detection event without a valid event ID,
sets both PF_MDET_TX and VP_MDET_TX and the PF enters a NETDEV
WATCHDOG / reset loop.

alloc_queue_pairs is set to pf->num_vf_qps, so GET_VF_RESOURCES
advertises the full count and a VF with more online CPUs than the
PF's num_lan_msix (e.g. a 4-CPU guest on a 3-CPU host) configures
the extra queue pair and hits the unprogrammed mapping entry.

Clamp alloc_queue_pairs by num_lan_msix like i40e_vsi_setup() does,
so the VF is only offered queue pairs whose mapping was programmed.

Fixes: 1563f2d2e012 ("i40e: Do not allow use more TC queue pairs than MSI-X 
vectors exist")
Signed-off-by: Tian Run <[email protected]>
---
 drivers/net/ethernet/intel/i40e/i40e_main.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c 
b/drivers/net/ethernet/intel/i40e/i40e_main.c
index abbc71e81..2934862da 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -11443,6 +11443,12 @@ static int i40e_set_num_rings_in_vsi(struct i40e_vsi 
*vsi)
 
        case I40E_VSI_SRIOV:
                vsi->alloc_queue_pairs = pf->num_vf_qps;
+               /* i40e_vsi_setup() limits queue pairs to num_lan_msix;
+                * keep alloc_queue_pairs consistent with that limit.
+                */
+               if (test_bit(I40E_FLAG_MSIX_ENA, pf->flags))
+                       vsi->alloc_queue_pairs =
+                               min_t(u16, pf->num_vf_qps, pf->num_lan_msix);
                if (!vsi->num_tx_desc)
                        vsi->num_tx_desc = ALIGN(I40E_DEFAULT_NUM_DESCRIPTORS,
                                                 I40E_REQ_DESCRIPTOR_MULTIPLE);
-- 
2.43.0

Reply via email to