diff options
Diffstat (limited to 'drivers/net/ethernet/intel/ice/ice_lag.c')
-rw-r--r-- | drivers/net/ethernet/intel/ice/ice_lag.c | 105 |
1 files changed, 76 insertions, 29 deletions
diff --git a/drivers/net/ethernet/intel/ice/ice_lag.c b/drivers/net/ethernet/intel/ice/ice_lag.c index 165a9d512ce2..cd065ec48c87 100644 --- a/drivers/net/ethernet/intel/ice/ice_lag.c +++ b/drivers/net/ethernet/intel/ice/ice_lag.c @@ -19,8 +19,11 @@ static const u8 lacp_train_pkt[LACP_TRAIN_PKT_LEN] = { 0, 0, 0, 0, 0, 0, static const u8 ice_dflt_vsi_rcp[ICE_RECIPE_LEN] = { 0x05, 0, 0, 0, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x85, 0, 0x01, 0, 0, 0, 0xff, 0xff, 0x08, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0x30, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + 0, 0, 0, 0, 0, 0, 0x30 }; +static const u8 ice_lport_rcp[ICE_RECIPE_LEN] = { + 0x05, 0, 0, 0, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0x85, 0, 0x16, 0, 0, 0, 0xff, 0xff, 0x07, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0x30 }; /** * ice_lag_set_primary - set PF LAG state as Primary @@ -173,18 +176,22 @@ static struct ice_lag *ice_lag_find_primary(struct ice_lag *lag) } /** - * ice_lag_cfg_dflt_fltr - Add/Remove default VSI rule for LAG + * ice_lag_cfg_fltr - Add/Remove rule for LAG * @lag: lag struct for local interface + * @act: rule action + * @recipe_id: recipe id for the new rule + * @rule_idx: pointer to rule index * @add: boolean on whether we are adding filters */ static int -ice_lag_cfg_dflt_fltr(struct ice_lag *lag, bool add) +ice_lag_cfg_fltr(struct ice_lag *lag, u32 act, u16 recipe_id, u16 *rule_idx, + bool add) { struct ice_sw_rule_lkup_rx_tx *s_rule; u16 s_rule_sz, vsi_num; struct ice_hw *hw; - u32 act, opc; u8 *eth_hdr; + u32 opc; int err; hw = &lag->pf->hw; @@ -193,7 +200,7 @@ ice_lag_cfg_dflt_fltr(struct ice_lag *lag, bool add) s_rule_sz = ICE_SW_RULE_RX_TX_ETH_HDR_SIZE(s_rule); s_rule = kzalloc(s_rule_sz, GFP_KERNEL); if (!s_rule) { - dev_err(ice_pf_to_dev(lag->pf), "error allocating rule for LAG default VSI\n"); + dev_err(ice_pf_to_dev(lag->pf), "error allocating rule for LAG\n"); return -ENOMEM; } @@ -201,19 +208,17 @@ ice_lag_cfg_dflt_fltr(struct ice_lag *lag, bool add) eth_hdr = s_rule->hdr_data; ice_fill_eth_hdr(eth_hdr); - act = (vsi_num << ICE_SINGLE_ACT_VSI_ID_S) & + act |= (vsi_num << ICE_SINGLE_ACT_VSI_ID_S) & ICE_SINGLE_ACT_VSI_ID_M; - act |= ICE_SINGLE_ACT_VSI_FORWARDING | - ICE_SINGLE_ACT_VALID_BIT | ICE_SINGLE_ACT_LAN_ENABLE; s_rule->hdr.type = cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_RX); - s_rule->recipe_id = cpu_to_le16(lag->pf_recipe); + s_rule->recipe_id = cpu_to_le16(recipe_id); s_rule->src = cpu_to_le16(hw->port_info->lport); s_rule->act = cpu_to_le32(act); s_rule->hdr_len = cpu_to_le16(DUMMY_ETH_HDR_LEN); opc = ice_aqc_opc_add_sw_rules; } else { - s_rule->index = cpu_to_le16(lag->pf_rule_id); + s_rule->index = cpu_to_le16(*rule_idx); opc = ice_aqc_opc_remove_sw_rules; } @@ -222,9 +227,9 @@ ice_lag_cfg_dflt_fltr(struct ice_lag *lag, bool add) goto dflt_fltr_free; if (add) - lag->pf_rule_id = le16_to_cpu(s_rule->index); + *rule_idx = le16_to_cpu(s_rule->index); else - lag->pf_rule_id = 0; + *rule_idx = 0; dflt_fltr_free: kfree(s_rule); @@ -232,6 +237,37 @@ dflt_fltr_free: } /** + * ice_lag_cfg_dflt_fltr - Add/Remove default VSI rule for LAG + * @lag: lag struct for local interface + * @add: boolean on whether to add filter + */ +static int +ice_lag_cfg_dflt_fltr(struct ice_lag *lag, bool add) +{ + u32 act = ICE_SINGLE_ACT_VSI_FORWARDING | + ICE_SINGLE_ACT_VALID_BIT | ICE_SINGLE_ACT_LAN_ENABLE; + + return ice_lag_cfg_fltr(lag, act, lag->pf_recipe, + &lag->pf_rule_id, add); +} + +/** + * ice_lag_cfg_drop_fltr - Add/Remove lport drop rule + * @lag: lag struct for local interface + * @add: boolean on whether to add filter + */ +static int +ice_lag_cfg_drop_fltr(struct ice_lag *lag, bool add) +{ + u32 act = ICE_SINGLE_ACT_VSI_FORWARDING | + ICE_SINGLE_ACT_VALID_BIT | + ICE_SINGLE_ACT_DROP; + + return ice_lag_cfg_fltr(lag, act, lag->lport_recipe, + &lag->lport_rule_idx, add); +} + +/** * ice_lag_cfg_pf_fltrs - set filters up for new active port * @lag: local interfaces lag struct * @ptr: opaque data containing notifier event @@ -257,13 +293,18 @@ ice_lag_cfg_pf_fltrs(struct ice_lag *lag, void *ptr) if (bonding_info->slave.state && lag->pf_rule_id) { if (ice_lag_cfg_dflt_fltr(lag, false)) dev_err(dev, "Error removing old default VSI filter\n"); + if (ice_lag_cfg_drop_fltr(lag, true)) + dev_err(dev, "Error adding new drop filter\n"); return; } /* interface becoming active - add new default VSI rule */ - if (!bonding_info->slave.state && !lag->pf_rule_id) + if (!bonding_info->slave.state && !lag->pf_rule_id) { if (ice_lag_cfg_dflt_fltr(lag, true)) dev_err(dev, "Error adding new default VSI filter\n"); + if (lag->lport_rule_idx && ice_lag_cfg_drop_fltr(lag, false)) + dev_err(dev, "Error removing old drop filter\n"); + } } /** @@ -587,7 +628,7 @@ void ice_lag_move_new_vf_nodes(struct ice_vf *vf) INIT_LIST_HEAD(&ndlist.node); rcu_read_lock(); for_each_netdev_in_bond_rcu(lag->upper_netdev, tmp_nd) { - nl = kzalloc(sizeof(*nl), GFP_KERNEL); + nl = kzalloc(sizeof(*nl), GFP_ATOMIC); if (!nl) break; @@ -1179,6 +1220,7 @@ static void ice_lag_changeupper_event(struct ice_lag *lag, void *ptr) swid = primary_lag->pf->hw.port_info->sw_id; ice_lag_set_swid(swid, lag, true); ice_lag_add_prune_list(primary_lag, lag->pf); + ice_lag_cfg_drop_fltr(lag, true); } /* add filter for primary control packets */ ice_lag_cfg_cp_fltr(lag, true); @@ -1513,18 +1555,12 @@ static void ice_lag_chk_disabled_bond(struct ice_lag *lag, void *ptr) */ static void ice_lag_disable_sriov_bond(struct ice_lag *lag) { - struct ice_lag_netdev_list *entry; struct ice_netdev_priv *np; - struct net_device *netdev; struct ice_pf *pf; - list_for_each_entry(entry, lag->netdev_head, node) { - netdev = entry->netdev; - np = netdev_priv(netdev); - pf = np->vsi->back; - - ice_clear_feature_support(pf, ICE_F_SRIOV_LAG); - } + np = netdev_priv(lag->netdev); + pf = np->vsi->back; + ice_clear_feature_support(pf, ICE_F_SRIOV_LAG); } /** @@ -1656,7 +1692,7 @@ ice_lag_event_handler(struct notifier_block *notif_blk, unsigned long event, rcu_read_lock(); for_each_netdev_in_bond_rcu(upper_netdev, tmp_nd) { - nd_list = kzalloc(sizeof(*nd_list), GFP_KERNEL); + nd_list = kzalloc(sizeof(*nd_list), GFP_ATOMIC); if (!nd_list) break; @@ -1929,11 +1965,16 @@ int ice_init_lag(struct ice_pf *pf) goto lag_error; } - err = ice_create_lag_recipe(&pf->hw, &lag->pf_recipe, ice_dflt_vsi_rcp, - 1); + err = ice_create_lag_recipe(&pf->hw, &lag->pf_recipe, + ice_dflt_vsi_rcp, 1); if (err) goto lag_error; + err = ice_create_lag_recipe(&pf->hw, &lag->lport_recipe, + ice_lport_rcp, 3); + if (err) + goto free_rcp_res; + /* associate recipes to profiles */ for (n = 0; n < ICE_PROFID_IPV6_GTPU_IPV6_TCP_INNER; n++) { err = ice_aq_get_recipe_to_profile(&pf->hw, n, @@ -1942,7 +1983,8 @@ int ice_init_lag(struct ice_pf *pf) continue; if (recipe_bits & BIT(ICE_SW_LKUP_DFLT)) { - recipe_bits |= BIT(lag->pf_recipe); + recipe_bits |= BIT(lag->pf_recipe) | + BIT(lag->lport_recipe); ice_aq_map_recipe_to_profile(&pf->hw, n, (u8 *)&recipe_bits, NULL); } @@ -1953,6 +1995,9 @@ int ice_init_lag(struct ice_pf *pf) dev_dbg(dev, "INIT LAG complete\n"); return 0; +free_rcp_res: + ice_free_hw_res(&pf->hw, ICE_AQC_RES_TYPE_RECIPE, 1, + &pf->lag->pf_recipe); lag_error: kfree(lag); pf->lag = NULL; @@ -1982,6 +2027,8 @@ void ice_deinit_lag(struct ice_pf *pf) ice_free_hw_res(&pf->hw, ICE_AQC_RES_TYPE_RECIPE, 1, &pf->lag->pf_recipe); + ice_free_hw_res(&pf->hw, ICE_AQC_RES_TYPE_RECIPE, 1, + &pf->lag->lport_recipe); kfree(lag); @@ -2022,7 +2069,7 @@ void ice_lag_rebuild(struct ice_pf *pf) INIT_LIST_HEAD(&ndlist.node); rcu_read_lock(); for_each_netdev_in_bond_rcu(lag->upper_netdev, tmp_nd) { - nl = kzalloc(sizeof(*nl), GFP_KERNEL); + nl = kzalloc(sizeof(*nl), GFP_ATOMIC); if (!nl) break; |