Skip to content

Commit e6ba527

Browse files
bcreeley13anguy11
authored andcommitted
ice: Fix race conditions between virtchnl handling and VF ndo ops
The VF can be configured via the PF's ndo ops at the same time the PF is receiving/handling virtchnl messages. This has many issues, with one of them being the ndo op could be actively resetting a VF (i.e. resetting it to the default state and deleting/re-adding the VF's VSI) while a virtchnl message is being handled. The following error was seen because a VF ndo op was used to change a VF's trust setting while the VIRTCHNL_OP_CONFIG_VSI_QUEUES was ongoing: [35274.192484] ice 0000:88:00.0: Failed to set LAN Tx queue context, error: ICE_ERR_PARAM [35274.193074] ice 0000:88:00.0: VF 0 failed opcode 6, retval: -5 [35274.193640] iavf 0000:88:01.0: PF returned error -5 (IAVF_ERR_PARAM) to our request 6 Fix this by making sure the virtchnl handling and VF ndo ops that trigger VF resets cannot run concurrently. This is done by adding a struct mutex cfg_lock to each VF structure. For VF ndo ops, the mutex will be locked around the critical operations and VFR. Since the ndo ops will trigger a VFR, the virtchnl thread will use mutex_trylock(). This is done because if any other thread (i.e. VF ndo op) has the mutex, then that means the current VF message being handled is no longer valid, so just ignore it. This issue can be seen using the following commands: for i in {0..50}; do rmmod ice modprobe ice sleep 1 echo 1 > /sys/class/net/ens785f0/device/sriov_numvfs echo 1 > /sys/class/net/ens785f1/device/sriov_numvfs ip link set ens785f1 vf 0 trust on ip link set ens785f0 vf 0 trust on sleep 2 echo 0 > /sys/class/net/ens785f0/device/sriov_numvfs echo 0 > /sys/class/net/ens785f1/device/sriov_numvfs sleep 1 echo 1 > /sys/class/net/ens785f0/device/sriov_numvfs echo 1 > /sys/class/net/ens785f1/device/sriov_numvfs ip link set ens785f1 vf 0 trust on ip link set ens785f0 vf 0 trust on done Fixes: 7c71086 ("ice: Add handlers for VF netdevice operations") Signed-off-by: Brett Creeley <[email protected]> Tested-by: Konrad Jankowski <[email protected]> Signed-off-by: Tony Nguyen <[email protected]>
1 parent b385cca commit e6ba527

File tree

2 files changed

+30
-0
lines changed

2 files changed

+30
-0
lines changed

drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,8 @@ void ice_free_vfs(struct ice_pf *pf)
650650
set_bit(ICE_VF_STATE_DIS, pf->vf[i].vf_states);
651651
ice_free_vf_res(&pf->vf[i]);
652652
}
653+
654+
mutex_destroy(&pf->vf[i].cfg_lock);
653655
}
654656

655657
if (ice_sriov_free_msix_res(pf))
@@ -1946,6 +1948,8 @@ static void ice_set_dflt_settings_vfs(struct ice_pf *pf)
19461948
ice_vf_fdir_init(vf);
19471949

19481950
ice_vc_set_dflt_vf_ops(&vf->vc_ops);
1951+
1952+
mutex_init(&vf->cfg_lock);
19491953
}
19501954
}
19511955

@@ -4135,6 +4139,8 @@ ice_set_vf_port_vlan(struct net_device *netdev, int vf_id, u16 vlan_id, u8 qos,
41354139
return 0;
41364140
}
41374141

4142+
mutex_lock(&vf->cfg_lock);
4143+
41384144
vf->port_vlan_info = vlanprio;
41394145

41404146
if (vf->port_vlan_info)
@@ -4144,6 +4150,7 @@ ice_set_vf_port_vlan(struct net_device *netdev, int vf_id, u16 vlan_id, u8 qos,
41444150
dev_info(dev, "Clearing port VLAN on VF %d\n", vf_id);
41454151

41464152
ice_vc_reset_vf(vf);
4153+
mutex_unlock(&vf->cfg_lock);
41474154

41484155
return 0;
41494156
}
@@ -4683,6 +4690,15 @@ void ice_vc_process_vf_msg(struct ice_pf *pf, struct ice_rq_event_info *event)
46834690
return;
46844691
}
46854692

4693+
/* VF is being configured in another context that triggers a VFR, so no
4694+
* need to process this message
4695+
*/
4696+
if (!mutex_trylock(&vf->cfg_lock)) {
4697+
dev_info(dev, "VF %u is being configured in another context that will trigger a VFR, so there is no need to handle this message\n",
4698+
vf->vf_id);
4699+
return;
4700+
}
4701+
46864702
switch (v_opcode) {
46874703
case VIRTCHNL_OP_VERSION:
46884704
err = ops->get_ver_msg(vf, msg);
@@ -4771,6 +4787,8 @@ void ice_vc_process_vf_msg(struct ice_pf *pf, struct ice_rq_event_info *event)
47714787
dev_info(dev, "PF failed to honor VF %d, opcode %d, error %d\n",
47724788
vf_id, v_opcode, err);
47734789
}
4790+
4791+
mutex_unlock(&vf->cfg_lock);
47744792
}
47754793

47764794
/**
@@ -4886,6 +4904,8 @@ int ice_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
48864904
return -EINVAL;
48874905
}
48884906

4907+
mutex_lock(&vf->cfg_lock);
4908+
48894909
/* VF is notified of its new MAC via the PF's response to the
48904910
* VIRTCHNL_OP_GET_VF_RESOURCES message after the VF has been reset
48914911
*/
@@ -4904,6 +4924,7 @@ int ice_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
49044924
}
49054925

49064926
ice_vc_reset_vf(vf);
4927+
mutex_unlock(&vf->cfg_lock);
49074928
return 0;
49084929
}
49094930

@@ -4938,11 +4959,15 @@ int ice_set_vf_trust(struct net_device *netdev, int vf_id, bool trusted)
49384959
if (trusted == vf->trusted)
49394960
return 0;
49404961

4962+
mutex_lock(&vf->cfg_lock);
4963+
49414964
vf->trusted = trusted;
49424965
ice_vc_reset_vf(vf);
49434966
dev_info(ice_pf_to_dev(pf), "VF %u is now %strusted\n",
49444967
vf_id, trusted ? "" : "un");
49454968

4969+
mutex_unlock(&vf->cfg_lock);
4970+
49464971
return 0;
49474972
}
49484973

drivers/net/ethernet/intel/ice/ice_virtchnl_pf.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,11 @@ struct ice_vc_vf_ops {
100100
struct ice_vf {
101101
struct ice_pf *pf;
102102

103+
/* Used during virtchnl message handling and NDO ops against the VF
104+
* that will trigger a VFR
105+
*/
106+
struct mutex cfg_lock;
107+
103108
u16 vf_id; /* VF ID in the PF space */
104109
u16 lan_vsi_idx; /* index into PF struct */
105110
u16 ctrl_vsi_idx;

0 commit comments

Comments
 (0)