Commit a5bda908 authored by Jakub Kicinski's avatar Jakub Kicinski

Merge branch '100GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/net-queue

Tony Nguyen says:

====================
Intel Wired LAN Driver Updates 2021-11-03

Brett fixes issues with promiscuous mode settings not being properly
enabled and removes setting of VF antispoof along with promiscuous
mode. He also ensures that VF Tx queues are always disabled and resolves
a race between virtchnl handling and VF related ndo ops.

Sylwester fixes an issue where a VF MAC could not be set to its primary
MAC if the address is already present.

* '100GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/net-queue:
  ice: Fix race conditions between virtchnl handling and VF ndo ops
  ice: Fix not stopping Tx queues for VFs
  ice: Fix replacing VF hardware MAC to existing MAC filter
  ice: Remove toggling of antispoof for VF trusted promiscuous mode
  ice: Fix VF true promiscuous mode
====================

Link: https://lore.kernel.org/r/20211103161935.2997369-1-anthony.l.nguyen@intel.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents a4db9055 e6ba5273
...@@ -165,13 +165,10 @@ ...@@ -165,13 +165,10 @@
#define ice_for_each_chnl_tc(i) \ #define ice_for_each_chnl_tc(i) \
for ((i) = ICE_CHNL_START_TC; (i) < ICE_CHNL_MAX_TC; (i)++) for ((i) = ICE_CHNL_START_TC; (i) < ICE_CHNL_MAX_TC; (i)++)
#define ICE_UCAST_PROMISC_BITS (ICE_PROMISC_UCAST_TX | ICE_PROMISC_MCAST_TX | \ #define ICE_UCAST_PROMISC_BITS (ICE_PROMISC_UCAST_TX | ICE_PROMISC_UCAST_RX)
ICE_PROMISC_UCAST_RX | ICE_PROMISC_MCAST_RX)
#define ICE_UCAST_VLAN_PROMISC_BITS (ICE_PROMISC_UCAST_TX | \ #define ICE_UCAST_VLAN_PROMISC_BITS (ICE_PROMISC_UCAST_TX | \
ICE_PROMISC_MCAST_TX | \
ICE_PROMISC_UCAST_RX | \ ICE_PROMISC_UCAST_RX | \
ICE_PROMISC_MCAST_RX | \
ICE_PROMISC_VLAN_TX | \ ICE_PROMISC_VLAN_TX | \
ICE_PROMISC_VLAN_RX) ICE_PROMISC_VLAN_RX)
......
...@@ -962,7 +962,7 @@ ice_vsi_stop_tx_ring(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src, ...@@ -962,7 +962,7 @@ ice_vsi_stop_tx_ring(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src,
} else if (status == ICE_ERR_DOES_NOT_EXIST) { } else if (status == ICE_ERR_DOES_NOT_EXIST) {
dev_dbg(ice_pf_to_dev(vsi->back), "LAN Tx queues do not exist, nothing to disable\n"); dev_dbg(ice_pf_to_dev(vsi->back), "LAN Tx queues do not exist, nothing to disable\n");
} else if (status) { } else if (status) {
dev_err(ice_pf_to_dev(vsi->back), "Failed to disable LAN Tx queues, error: %s\n", dev_dbg(ice_pf_to_dev(vsi->back), "Failed to disable LAN Tx queues, error: %s\n",
ice_stat_str(status)); ice_stat_str(status));
return -ENODEV; return -ENODEV;
} }
......
...@@ -638,8 +638,7 @@ void ice_free_vfs(struct ice_pf *pf) ...@@ -638,8 +638,7 @@ void ice_free_vfs(struct ice_pf *pf)
/* Avoid wait time by stopping all VFs at the same time */ /* Avoid wait time by stopping all VFs at the same time */
ice_for_each_vf(pf, i) ice_for_each_vf(pf, i)
if (test_bit(ICE_VF_STATE_QS_ENA, pf->vf[i].vf_states)) ice_dis_vf_qs(&pf->vf[i]);
ice_dis_vf_qs(&pf->vf[i]);
tmp = pf->num_alloc_vfs; tmp = pf->num_alloc_vfs;
pf->num_qps_per_vf = 0; pf->num_qps_per_vf = 0;
...@@ -651,6 +650,8 @@ void ice_free_vfs(struct ice_pf *pf) ...@@ -651,6 +650,8 @@ void ice_free_vfs(struct ice_pf *pf)
set_bit(ICE_VF_STATE_DIS, pf->vf[i].vf_states); set_bit(ICE_VF_STATE_DIS, pf->vf[i].vf_states);
ice_free_vf_res(&pf->vf[i]); ice_free_vf_res(&pf->vf[i]);
} }
mutex_destroy(&pf->vf[i].cfg_lock);
} }
if (ice_sriov_free_msix_res(pf)) if (ice_sriov_free_msix_res(pf))
...@@ -1695,8 +1696,7 @@ bool ice_reset_vf(struct ice_vf *vf, bool is_vflr) ...@@ -1695,8 +1696,7 @@ bool ice_reset_vf(struct ice_vf *vf, bool is_vflr)
vsi = ice_get_vf_vsi(vf); vsi = ice_get_vf_vsi(vf);
if (test_bit(ICE_VF_STATE_QS_ENA, vf->vf_states)) ice_dis_vf_qs(vf);
ice_dis_vf_qs(vf);
/* Call Disable LAN Tx queue AQ whether or not queues are /* Call Disable LAN Tx queue AQ whether or not queues are
* enabled. This is needed for successful completion of VFR. * enabled. This is needed for successful completion of VFR.
...@@ -1948,6 +1948,8 @@ static void ice_set_dflt_settings_vfs(struct ice_pf *pf) ...@@ -1948,6 +1948,8 @@ static void ice_set_dflt_settings_vfs(struct ice_pf *pf)
ice_vf_fdir_init(vf); ice_vf_fdir_init(vf);
ice_vc_set_dflt_vf_ops(&vf->vc_ops); ice_vc_set_dflt_vf_ops(&vf->vc_ops);
mutex_init(&vf->cfg_lock);
} }
} }
...@@ -3013,6 +3015,7 @@ bool ice_is_any_vf_in_promisc(struct ice_pf *pf) ...@@ -3013,6 +3015,7 @@ bool ice_is_any_vf_in_promisc(struct ice_pf *pf)
static int ice_vc_cfg_promiscuous_mode_msg(struct ice_vf *vf, u8 *msg) static int ice_vc_cfg_promiscuous_mode_msg(struct ice_vf *vf, u8 *msg)
{ {
enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS; enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
enum ice_status mcast_status = 0, ucast_status = 0;
bool rm_promisc, alluni = false, allmulti = false; bool rm_promisc, alluni = false, allmulti = false;
struct virtchnl_promisc_info *info = struct virtchnl_promisc_info *info =
(struct virtchnl_promisc_info *)msg; (struct virtchnl_promisc_info *)msg;
...@@ -3054,24 +3057,6 @@ static int ice_vc_cfg_promiscuous_mode_msg(struct ice_vf *vf, u8 *msg) ...@@ -3054,24 +3057,6 @@ static int ice_vc_cfg_promiscuous_mode_msg(struct ice_vf *vf, u8 *msg)
rm_promisc = !allmulti && !alluni; rm_promisc = !allmulti && !alluni;
if (vsi->num_vlan || vf->port_vlan_info) { if (vsi->num_vlan || vf->port_vlan_info) {
struct ice_vsi *pf_vsi = ice_get_main_vsi(pf);
struct net_device *pf_netdev;
if (!pf_vsi) {
v_ret = VIRTCHNL_STATUS_ERR_PARAM;
goto error_param;
}
pf_netdev = pf_vsi->netdev;
ret = ice_set_vf_spoofchk(pf_netdev, vf->vf_id, rm_promisc);
if (ret) {
dev_err(dev, "Failed to update spoofchk to %s for VF %d VSI %d when setting promiscuous mode\n",
rm_promisc ? "ON" : "OFF", vf->vf_id,
vsi->vsi_num);
v_ret = VIRTCHNL_STATUS_ERR_PARAM;
}
if (rm_promisc) if (rm_promisc)
ret = ice_cfg_vlan_pruning(vsi, true); ret = ice_cfg_vlan_pruning(vsi, true);
else else
...@@ -3105,52 +3090,51 @@ static int ice_vc_cfg_promiscuous_mode_msg(struct ice_vf *vf, u8 *msg) ...@@ -3105,52 +3090,51 @@ static int ice_vc_cfg_promiscuous_mode_msg(struct ice_vf *vf, u8 *msg)
goto error_param; goto error_param;
} }
} else { } else {
enum ice_status status; u8 mcast_m, ucast_m;
u8 promisc_m;
if (vf->port_vlan_info || vsi->num_vlan > 1) {
if (alluni) { mcast_m = ICE_MCAST_VLAN_PROMISC_BITS;
if (vf->port_vlan_info || vsi->num_vlan) ucast_m = ICE_UCAST_VLAN_PROMISC_BITS;
promisc_m = ICE_UCAST_VLAN_PROMISC_BITS;
else
promisc_m = ICE_UCAST_PROMISC_BITS;
} else if (allmulti) {
if (vf->port_vlan_info || vsi->num_vlan)
promisc_m = ICE_MCAST_VLAN_PROMISC_BITS;
else
promisc_m = ICE_MCAST_PROMISC_BITS;
} else { } else {
if (vf->port_vlan_info || vsi->num_vlan) mcast_m = ICE_MCAST_PROMISC_BITS;
promisc_m = ICE_UCAST_VLAN_PROMISC_BITS; ucast_m = ICE_UCAST_PROMISC_BITS;
else
promisc_m = ICE_UCAST_PROMISC_BITS;
} }
/* Configure multicast/unicast with or without VLAN promiscuous ucast_status = ice_vf_set_vsi_promisc(vf, vsi, ucast_m,
* mode !alluni);
*/ if (ucast_status) {
status = ice_vf_set_vsi_promisc(vf, vsi, promisc_m, rm_promisc); dev_err(dev, "%sable Tx/Rx filter promiscuous mode on VF-%d failed\n",
if (status) { alluni ? "en" : "dis", vf->vf_id);
dev_err(dev, "%sable Tx/Rx filter promiscuous mode on VF-%d failed, error: %s\n", v_ret = ice_err_to_virt_err(ucast_status);
rm_promisc ? "dis" : "en", vf->vf_id, }
ice_stat_str(status));
v_ret = ice_err_to_virt_err(status); mcast_status = ice_vf_set_vsi_promisc(vf, vsi, mcast_m,
goto error_param; !allmulti);
} else { if (mcast_status) {
dev_dbg(dev, "%sable Tx/Rx filter promiscuous mode on VF-%d succeeded\n", dev_err(dev, "%sable Tx/Rx filter promiscuous mode on VF-%d failed\n",
rm_promisc ? "dis" : "en", vf->vf_id); allmulti ? "en" : "dis", vf->vf_id);
v_ret = ice_err_to_virt_err(mcast_status);
} }
} }
if (allmulti && if (!mcast_status) {
!test_and_set_bit(ICE_VF_STATE_MC_PROMISC, vf->vf_states)) if (allmulti &&
dev_info(dev, "VF %u successfully set multicast promiscuous mode\n", vf->vf_id); !test_and_set_bit(ICE_VF_STATE_MC_PROMISC, vf->vf_states))
else if (!allmulti && test_and_clear_bit(ICE_VF_STATE_MC_PROMISC, vf->vf_states)) dev_info(dev, "VF %u successfully set multicast promiscuous mode\n",
dev_info(dev, "VF %u successfully unset multicast promiscuous mode\n", vf->vf_id); vf->vf_id);
else if (!allmulti && test_and_clear_bit(ICE_VF_STATE_MC_PROMISC, vf->vf_states))
dev_info(dev, "VF %u successfully unset multicast promiscuous mode\n",
vf->vf_id);
}
if (alluni && !test_and_set_bit(ICE_VF_STATE_UC_PROMISC, vf->vf_states)) if (!ucast_status) {
dev_info(dev, "VF %u successfully set unicast promiscuous mode\n", vf->vf_id); if (alluni && !test_and_set_bit(ICE_VF_STATE_UC_PROMISC, vf->vf_states))
else if (!alluni && test_and_clear_bit(ICE_VF_STATE_UC_PROMISC, vf->vf_states)) dev_info(dev, "VF %u successfully set unicast promiscuous mode\n",
dev_info(dev, "VF %u successfully unset unicast promiscuous mode\n", vf->vf_id); vf->vf_id);
else if (!alluni && test_and_clear_bit(ICE_VF_STATE_UC_PROMISC, vf->vf_states))
dev_info(dev, "VF %u successfully unset unicast promiscuous mode\n",
vf->vf_id);
}
error_param: error_param:
return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE, return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE,
...@@ -3824,6 +3808,7 @@ ice_vc_add_mac_addr(struct ice_vf *vf, struct ice_vsi *vsi, ...@@ -3824,6 +3808,7 @@ ice_vc_add_mac_addr(struct ice_vf *vf, struct ice_vsi *vsi,
struct device *dev = ice_pf_to_dev(vf->pf); struct device *dev = ice_pf_to_dev(vf->pf);
u8 *mac_addr = vc_ether_addr->addr; u8 *mac_addr = vc_ether_addr->addr;
enum ice_status status; enum ice_status status;
int ret = 0;
/* device MAC already added */ /* device MAC already added */
if (ether_addr_equal(mac_addr, vf->dev_lan_addr.addr)) if (ether_addr_equal(mac_addr, vf->dev_lan_addr.addr))
...@@ -3836,20 +3821,23 @@ ice_vc_add_mac_addr(struct ice_vf *vf, struct ice_vsi *vsi, ...@@ -3836,20 +3821,23 @@ ice_vc_add_mac_addr(struct ice_vf *vf, struct ice_vsi *vsi,
status = ice_fltr_add_mac(vsi, mac_addr, ICE_FWD_TO_VSI); status = ice_fltr_add_mac(vsi, mac_addr, ICE_FWD_TO_VSI);
if (status == ICE_ERR_ALREADY_EXISTS) { if (status == ICE_ERR_ALREADY_EXISTS) {
dev_err(dev, "MAC %pM already exists for VF %d\n", mac_addr, dev_dbg(dev, "MAC %pM already exists for VF %d\n", mac_addr,
vf->vf_id); vf->vf_id);
return -EEXIST; /* don't return since we might need to update
* the primary MAC in ice_vfhw_mac_add() below
*/
ret = -EEXIST;
} else if (status) { } else if (status) {
dev_err(dev, "Failed to add MAC %pM for VF %d\n, error %s\n", dev_err(dev, "Failed to add MAC %pM for VF %d\n, error %s\n",
mac_addr, vf->vf_id, ice_stat_str(status)); mac_addr, vf->vf_id, ice_stat_str(status));
return -EIO; return -EIO;
} else {
vf->num_mac++;
} }
ice_vfhw_mac_add(vf, vc_ether_addr); ice_vfhw_mac_add(vf, vc_ether_addr);
vf->num_mac++; return ret;
return 0;
} }
/** /**
...@@ -4151,6 +4139,8 @@ ice_set_vf_port_vlan(struct net_device *netdev, int vf_id, u16 vlan_id, u8 qos, ...@@ -4151,6 +4139,8 @@ ice_set_vf_port_vlan(struct net_device *netdev, int vf_id, u16 vlan_id, u8 qos,
return 0; return 0;
} }
mutex_lock(&vf->cfg_lock);
vf->port_vlan_info = vlanprio; vf->port_vlan_info = vlanprio;
if (vf->port_vlan_info) if (vf->port_vlan_info)
...@@ -4160,6 +4150,7 @@ ice_set_vf_port_vlan(struct net_device *netdev, int vf_id, u16 vlan_id, u8 qos, ...@@ -4160,6 +4150,7 @@ ice_set_vf_port_vlan(struct net_device *netdev, int vf_id, u16 vlan_id, u8 qos,
dev_info(dev, "Clearing port VLAN on VF %d\n", vf_id); dev_info(dev, "Clearing port VLAN on VF %d\n", vf_id);
ice_vc_reset_vf(vf); ice_vc_reset_vf(vf);
mutex_unlock(&vf->cfg_lock);
return 0; return 0;
} }
...@@ -4699,6 +4690,15 @@ void ice_vc_process_vf_msg(struct ice_pf *pf, struct ice_rq_event_info *event) ...@@ -4699,6 +4690,15 @@ void ice_vc_process_vf_msg(struct ice_pf *pf, struct ice_rq_event_info *event)
return; return;
} }
/* VF is being configured in another context that triggers a VFR, so no
* need to process this message
*/
if (!mutex_trylock(&vf->cfg_lock)) {
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",
vf->vf_id);
return;
}
switch (v_opcode) { switch (v_opcode) {
case VIRTCHNL_OP_VERSION: case VIRTCHNL_OP_VERSION:
err = ops->get_ver_msg(vf, msg); err = ops->get_ver_msg(vf, msg);
...@@ -4787,6 +4787,8 @@ void ice_vc_process_vf_msg(struct ice_pf *pf, struct ice_rq_event_info *event) ...@@ -4787,6 +4787,8 @@ void ice_vc_process_vf_msg(struct ice_pf *pf, struct ice_rq_event_info *event)
dev_info(dev, "PF failed to honor VF %d, opcode %d, error %d\n", dev_info(dev, "PF failed to honor VF %d, opcode %d, error %d\n",
vf_id, v_opcode, err); vf_id, v_opcode, err);
} }
mutex_unlock(&vf->cfg_lock);
} }
/** /**
...@@ -4902,6 +4904,8 @@ int ice_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac) ...@@ -4902,6 +4904,8 @@ int ice_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
return -EINVAL; return -EINVAL;
} }
mutex_lock(&vf->cfg_lock);
/* VF is notified of its new MAC via the PF's response to the /* VF is notified of its new MAC via the PF's response to the
* VIRTCHNL_OP_GET_VF_RESOURCES message after the VF has been reset * VIRTCHNL_OP_GET_VF_RESOURCES message after the VF has been reset
*/ */
...@@ -4920,6 +4924,7 @@ int ice_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac) ...@@ -4920,6 +4924,7 @@ int ice_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
} }
ice_vc_reset_vf(vf); ice_vc_reset_vf(vf);
mutex_unlock(&vf->cfg_lock);
return 0; return 0;
} }
...@@ -4954,11 +4959,15 @@ int ice_set_vf_trust(struct net_device *netdev, int vf_id, bool trusted) ...@@ -4954,11 +4959,15 @@ int ice_set_vf_trust(struct net_device *netdev, int vf_id, bool trusted)
if (trusted == vf->trusted) if (trusted == vf->trusted)
return 0; return 0;
mutex_lock(&vf->cfg_lock);
vf->trusted = trusted; vf->trusted = trusted;
ice_vc_reset_vf(vf); ice_vc_reset_vf(vf);
dev_info(ice_pf_to_dev(pf), "VF %u is now %strusted\n", dev_info(ice_pf_to_dev(pf), "VF %u is now %strusted\n",
vf_id, trusted ? "" : "un"); vf_id, trusted ? "" : "un");
mutex_unlock(&vf->cfg_lock);
return 0; return 0;
} }
......
...@@ -100,6 +100,11 @@ struct ice_vc_vf_ops { ...@@ -100,6 +100,11 @@ struct ice_vc_vf_ops {
struct ice_vf { struct ice_vf {
struct ice_pf *pf; struct ice_pf *pf;
/* Used during virtchnl message handling and NDO ops against the VF
* that will trigger a VFR
*/
struct mutex cfg_lock;
u16 vf_id; /* VF ID in the PF space */ u16 vf_id; /* VF ID in the PF space */
u16 lan_vsi_idx; /* index into PF struct */ u16 lan_vsi_idx; /* index into PF struct */
u16 ctrl_vsi_idx; u16 ctrl_vsi_idx;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment