aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/intel/ice/ice_switch.c
diff options
context:
space:
mode:
authorJacob Keller <jacob.e.keller@intel.com>2019-02-08 15:50:33 -0500
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2019-02-25 11:56:01 -0500
commitf9264dd687f8d3f9104c9900f8f3e5e419f27c55 (patch)
treea7bc9d853146924656a5383aa4173aa16e803056 /drivers/net/ethernet/intel/ice/ice_switch.c
parent198a666a4543be1a6e48f4b701dd3bd9387d37c3 (diff)
ice: fix ice_remove_rule_internal vsi_list handling
When adding multiple VLANs to the same VSI, the ice_add_vlan code will share the VSI list, so as not to create multiple unnecessary VSI lists. Consider the following flow ice_add_vlan(hw, <VSI 0 VID 7, VSI 0 VID 8, VSI 0 VID 9>) Where we add three VLAN filters for VIDs 7, 8, and 9, all for VSI 0. The ice_add_vlan will create a single vsi_list and share it among all the filters. Later, if we try to remove a VLAN, ice_remove_vlan(hw, <VSI 0 VID 7>) Then the removal code will update the vsi_list and remove VSI 0 from it. But, since the vsi_list is shared, this breaks the list for the other users who reference it. We actually even free the VSI list memory, and may result in segmentation faults. This is due to the way that VLAN rule share VSI lists with reference counts, and is caused because we call ice_rem_update_vsi_list even when the ref_cnt is greater than one. To fix this, handle the case where ref_cnt is greater than one separately. In this case, we need to remove the associated rule without modifying the vsi_list, since it is currently being referenced by another rule. Instead, we just need to decrement the VSI list ref_cnt. The case for handling sharing of VSI lists with multiple VSIs is not currently supported by this code. No such rules will be created today, and this code will require changes if/when such code is added. Signed-off-by: Jacob Keller <jacob.e.keller@intel.com> Reviewed-by: Bruce Allan <bruce.w.allan@intel.com> Signed-off-by: Anirudh Venkataramanan <anirudh.venkataramanan@intel.com> Tested-by: Andrew Bowers <andrewx.bowers@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net/ethernet/intel/ice/ice_switch.c')
-rw-r--r--drivers/net/ethernet/intel/ice/ice_switch.c15
1 files changed, 13 insertions, 2 deletions
diff --git a/drivers/net/ethernet/intel/ice/ice_switch.c b/drivers/net/ethernet/intel/ice/ice_switch.c
index d560a8aa5015..09d1c314b68f 100644
--- a/drivers/net/ethernet/intel/ice/ice_switch.c
+++ b/drivers/net/ethernet/intel/ice/ice_switch.c
@@ -1538,9 +1538,20 @@ ice_remove_rule_internal(struct ice_hw *hw, u8 recp_id,
1538 } else if (!list_elem->vsi_list_info) { 1538 } else if (!list_elem->vsi_list_info) {
1539 status = ICE_ERR_DOES_NOT_EXIST; 1539 status = ICE_ERR_DOES_NOT_EXIST;
1540 goto exit; 1540 goto exit;
1541 } else if (list_elem->vsi_list_info->ref_cnt > 1) {
1542 /* a ref_cnt > 1 indicates that the vsi_list is being
1543 * shared by multiple rules. Decrement the ref_cnt and
1544 * remove this rule, but do not modify the list, as it
1545 * is in-use by other rules.
1546 */
1547 list_elem->vsi_list_info->ref_cnt--;
1548 remove_rule = true;
1541 } else { 1549 } else {
1542 if (list_elem->vsi_list_info->ref_cnt > 1) 1550 /* a ref_cnt of 1 indicates the vsi_list is only used
1543 list_elem->vsi_list_info->ref_cnt--; 1551 * by one rule. However, the original removal request is only
1552 * for a single VSI. Update the vsi_list first, and only
1553 * remove the rule if there are no further VSIs in this list.
1554 */
1544 vsi_handle = f_entry->fltr_info.vsi_handle; 1555 vsi_handle = f_entry->fltr_info.vsi_handle;
1545 status = ice_rem_update_vsi_list(hw, vsi_handle, list_elem); 1556 status = ice_rem_update_vsi_list(hw, vsi_handle, list_elem);
1546 if (status) 1557 if (status)