Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

Tony Nguyen says:

====================
ice: implement SRIOV VF Active-Active LAG

Dave Ertman says:

Implement support for SRIOV VFs over an Active-Active link aggregate.
The same restrictions apply as are in place for the support of
Active-Backup bonds.

- the two interfaces must be on the same NIC
- the FW LLDP engine needs to be disabled
- the DDP package that supports VF LAG must be loaded on device
- the two interfaces must have the same QoS config
- only the first interface added to the bond will have VF support
- the interface with VFs must be in switchdev mode

With the additional requirement of
- the version of the FW on the NIC needs to have VF Active/Active support

The balancing of traffic between the two interfaces is done on a queue
basis. Taking the queues allocated to all of the VFs as a whole, one
half of them will be distributed to each interface. When a link goes
down, then the queues allocated to the down interface will migrate to
the active port. When the down port comes back up, then the same
queues as were originally assigned there will be moved back.

Patch 1 cleans up void pointer casts
Patch 2 utilizes bool over u8 when appropriate
Patch 3 adds a driver prefix to a LAG define
Patch 4 pre-move a function to reduce delta in implementation patch
Patch 5 cleanup variable initialization in declaration block
Patch 6 cleanup capability parsing for LAG feature
Patch 7 is the implementation of the new functionality

* '100GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue:
ice: Implement support for SRIOV VFs across Active/Active bonds
ice: cleanup capabilities evaluation
ice: Cleanup variable initialization in LAG code
ice: move LAG function in code to prepare for Active-Active
ice: Add driver specific prefix to LAG defines
ice: replace u8 elements with bool where appropriate
ice: Remove casts on void pointers in LAG code
====================

Link: https://patch.msgid.link/20250814230855.128068-1-anthony.l.nguyen@intel.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+806 -225
+1
drivers/net/ethernet/intel/ice/ice.h
··· 203 203 ICE_F_GCS, 204 204 ICE_F_ROCE_LAG, 205 205 ICE_F_SRIOV_LAG, 206 + ICE_F_SRIOV_AA_LAG, 206 207 ICE_F_MBX_LIMIT, 207 208 ICE_F_MAX 208 209 };
+4
drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
··· 2060 2060 #define ICE_AQC_Q_CFG_SRC_PRT_M 0x7 2061 2061 #define ICE_AQC_Q_CFG_DST_PRT_S 3 2062 2062 #define ICE_AQC_Q_CFG_DST_PRT_M (0x7 << ICE_AQC_Q_CFG_DST_PRT_S) 2063 + #define ICE_AQC_Q_CFG_MODE_M GENMASK(7, 6) 2064 + #define ICE_AQC_Q_CFG_MODE_SAME_PF 0x0 2065 + #define ICE_AQC_Q_CFG_MODE_GIVE_OWN 0x1 2066 + #define ICE_AQC_Q_CFG_MODE_KEEP_OWN 0x2 2063 2067 u8 time_out; 2064 2068 #define ICE_AQC_Q_CFG_TIMEOUT_S 2 2065 2069 #define ICE_AQC_Q_CFG_TIMEOUT_M (0x1F << ICE_AQC_Q_CFG_TIMEOUT_S)
+12 -7
drivers/net/ethernet/intel/ice/ice_common.c
··· 2418 2418 caps->reset_restrict_support); 2419 2419 break; 2420 2420 case LIBIE_AQC_CAPS_FW_LAG_SUPPORT: 2421 - caps->roce_lag = !!(number & LIBIE_AQC_BIT_ROCEV2_LAG); 2421 + caps->roce_lag = number & LIBIE_AQC_BIT_ROCEV2_LAG; 2422 2422 ice_debug(hw, ICE_DBG_INIT, "%s: roce_lag = %u\n", 2423 2423 prefix, caps->roce_lag); 2424 - caps->sriov_lag = !!(number & LIBIE_AQC_BIT_SRIOV_LAG); 2424 + caps->sriov_lag = number & LIBIE_AQC_BIT_SRIOV_LAG; 2425 2425 ice_debug(hw, ICE_DBG_INIT, "%s: sriov_lag = %u\n", 2426 2426 prefix, caps->sriov_lag); 2427 + caps->sriov_aa_lag = number & LIBIE_AQC_BIT_SRIOV_AA_LAG; 2428 + ice_debug(hw, ICE_DBG_INIT, "%s: sriov_aa_lag = %u\n", 2429 + prefix, caps->sriov_aa_lag); 2427 2430 break; 2428 2431 case LIBIE_AQC_CAPS_TX_SCHED_TOPO_COMP_MODE: 2429 2432 caps->tx_sched_topo_comp_mode_en = (number == 1); ··· 4715 4712 } 4716 4713 4717 4714 /** 4718 - * ice_aq_cfg_lan_txq 4715 + * ice_aq_cfg_lan_txq - send AQ command 0x0C32 to FW 4719 4716 * @hw: pointer to the hardware structure 4720 4717 * @buf: buffer for command 4721 4718 * @buf_size: size of buffer in bytes 4722 4719 * @num_qs: number of queues being configured 4723 4720 * @oldport: origination lport 4724 4721 * @newport: destination lport 4722 + * @mode: cmd_type for move to use 4725 4723 * @cd: pointer to command details structure or NULL 4726 4724 * 4727 4725 * Move/Configure LAN Tx queue (0x0C32) 4728 4726 * 4729 - * There is a better AQ command to use for moving nodes, so only coding 4730 - * this one for configuring the node. 4727 + * Return: Zero on success, associated error code on failure. 4731 4728 */ 4732 4729 int 4733 4730 ice_aq_cfg_lan_txq(struct ice_hw *hw, struct ice_aqc_cfg_txqs_buf *buf, 4734 4731 u16 buf_size, u16 num_qs, u8 oldport, u8 newport, 4735 - struct ice_sq_cd *cd) 4732 + u8 mode, struct ice_sq_cd *cd) 4736 4733 { 4737 4734 struct ice_aqc_cfg_txqs *cmd; 4738 4735 struct libie_aq_desc desc; ··· 4745 4742 if (!buf) 4746 4743 return -EINVAL; 4747 4744 4748 - cmd->cmd_type = ICE_AQC_Q_CFG_TC_CHNG; 4745 + cmd->cmd_type = mode; 4749 4746 cmd->num_qs = num_qs; 4750 4747 cmd->port_num_chng = (oldport & ICE_AQC_Q_CFG_SRC_PRT_M); 4751 4748 cmd->port_num_chng |= FIELD_PREP(ICE_AQC_Q_CFG_DST_PRT_M, newport); 4749 + cmd->port_num_chng |= FIELD_PREP(ICE_AQC_Q_CFG_MODE_M, 4750 + ICE_AQC_Q_CFG_MODE_KEEP_OWN); 4752 4751 cmd->time_out = FIELD_PREP(ICE_AQC_Q_CFG_TIMEOUT_M, 5); 4753 4752 cmd->blocked_cgds = 0; 4754 4753
+1 -1
drivers/net/ethernet/intel/ice/ice_common.h
··· 270 270 int 271 271 ice_aq_cfg_lan_txq(struct ice_hw *hw, struct ice_aqc_cfg_txqs_buf *buf, 272 272 u16 buf_size, u16 num_qs, u8 oldport, u8 newport, 273 - struct ice_sq_cd *cd); 273 + u8 mode, struct ice_sq_cd *cd); 274 274 int ice_replay_vsi(struct ice_hw *hw, u16 vsi_handle); 275 275 void ice_replay_post(struct ice_hw *hw); 276 276 struct ice_q_ctx *
+761 -212
drivers/net/ethernet/intel/ice/ice_lag.c
··· 10 10 #define ICE_LAG_RES_SHARED BIT(14) 11 11 #define ICE_LAG_RES_VALID BIT(15) 12 12 13 - #define LACP_TRAIN_PKT_LEN 16 14 - static const u8 lacp_train_pkt[LACP_TRAIN_PKT_LEN] = { 0, 0, 0, 0, 0, 0, 15 - 0, 0, 0, 0, 0, 0, 16 - 0x88, 0x09, 0, 0 }; 13 + #define ICE_TRAIN_PKT_LEN 16 14 + static const u8 lacp_train_pkt[ICE_TRAIN_PKT_LEN] = { 0, 0, 0, 0, 0, 0, 15 + 0, 0, 0, 0, 0, 0, 16 + 0x88, 0x09, 0, 0 }; 17 + static const u8 act_act_train_pkt[ICE_TRAIN_PKT_LEN] = { 0, 0, 0, 0, 0, 0, 18 + 0, 0, 0, 0, 0, 0, 19 + 0, 0, 0, 0 }; 17 20 18 21 #define ICE_RECIPE_LEN 64 22 + #define ICE_LAG_SRIOV_CP_RECIPE 10 23 + 19 24 static const u8 ice_dflt_vsi_rcp[ICE_RECIPE_LEN] = { 20 25 0x05, 0, 0, 0, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21 26 0x85, 0, 0x01, 0, 0, 0, 0xff, 0xff, 0x08, 0, 0, 0, 0, 0, 0, 0, ··· 51 46 } 52 47 53 48 /** 54 - * ice_lag_set_backup - set PF LAG state to Backup 49 + * ice_lag_set_bkup - set PF LAG state to Backup 55 50 * @lag: LAG info struct 56 51 */ 57 - static void ice_lag_set_backup(struct ice_lag *lag) 52 + static void ice_lag_set_bkup(struct ice_lag *lag) 58 53 { 59 54 struct ice_pf *pf = lag->pf; 60 55 ··· 101 96 return false; 102 97 103 98 return true; 99 + } 100 + 101 + /** 102 + * ice_lag_config_eswitch - configure eswitch to work with LAG 103 + * @lag: lag info struct 104 + * @netdev: active network interface device struct 105 + * 106 + * Updates all port representors in eswitch to use @netdev for Tx. 107 + * 108 + * Configures the netdev to keep dst metadata (also used in representor Tx). 109 + * This is required for an uplink without switchdev mode configured. 110 + */ 111 + static void ice_lag_config_eswitch(struct ice_lag *lag, 112 + struct net_device *netdev) 113 + { 114 + struct ice_repr *repr; 115 + unsigned long id; 116 + 117 + xa_for_each(&lag->pf->eswitch.reprs, id, repr) 118 + repr->dst->u.port_info.lower_dev = netdev; 119 + 120 + netif_keep_dst(netdev); 104 121 } 105 122 106 123 /** ··· 237 210 u8 direction, bool add) 238 211 { 239 212 struct ice_sw_rule_lkup_rx_tx *s_rule; 213 + struct ice_hw *hw = &lag->pf->hw; 240 214 u16 s_rule_sz, vsi_num; 241 - struct ice_hw *hw; 242 215 u8 *eth_hdr; 243 216 u32 opc; 244 217 int err; 245 218 246 - hw = &lag->pf->hw; 247 219 vsi_num = ice_get_hw_vsi_num(hw, 0); 248 220 249 221 s_rule_sz = ICE_SW_RULE_RX_TX_ETH_HDR_SIZE(s_rule); ··· 340 314 } 341 315 342 316 /** 343 - * ice_lag_cfg_pf_fltrs - set filters up for new active port 317 + * ice_lag_cfg_pf_fltrs_act_bkup - set filters up for new active port 344 318 * @lag: local interfaces lag struct 345 - * @ptr: opaque data containing notifier event 319 + * @bonding_info: netdev event bonding info 346 320 */ 347 321 static void 348 - ice_lag_cfg_pf_fltrs(struct ice_lag *lag, void *ptr) 322 + ice_lag_cfg_pf_fltrs_act_bkup(struct ice_lag *lag, 323 + struct netdev_bonding_info *bonding_info) 349 324 { 350 - struct netdev_notifier_bonding_info *info; 351 - struct netdev_bonding_info *bonding_info; 352 - struct net_device *event_netdev; 353 - struct device *dev; 354 - 355 - event_netdev = netdev_notifier_info_to_dev(ptr); 356 - /* not for this netdev */ 357 - if (event_netdev != lag->netdev) 358 - return; 359 - 360 - info = (struct netdev_notifier_bonding_info *)ptr; 361 - bonding_info = &info->bonding_info; 362 - dev = ice_pf_to_dev(lag->pf); 325 + struct device *dev = ice_pf_to_dev(lag->pf); 363 326 364 327 /* interface not active - remove old default VSI rule */ 365 328 if (bonding_info->slave.state && lag->pf_rx_rule_id) { ··· 365 350 dev_err(dev, "Error adding new default VSI filter\n"); 366 351 if (lag->lport_rule_idx && ice_lag_cfg_drop_fltr(lag, false)) 367 352 dev_err(dev, "Error removing old drop filter\n"); 353 + } 354 + } 355 + 356 + /** 357 + * ice_lag_cfg_lp_fltr - configure lport filters 358 + * @lag: local interface's lag struct 359 + * @add: add or remove rule 360 + * @cp: control packet only or general PF lport rule 361 + */ 362 + static void 363 + ice_lag_cfg_lp_fltr(struct ice_lag *lag, bool add, bool cp) 364 + { 365 + struct ice_sw_rule_lkup_rx_tx *s_rule; 366 + struct ice_vsi *vsi = lag->pf->vsi[0]; 367 + u16 buf_len, opc; 368 + 369 + buf_len = ICE_SW_RULE_RX_TX_HDR_SIZE(s_rule, ICE_TRAIN_PKT_LEN); 370 + s_rule = kzalloc(buf_len, GFP_KERNEL); 371 + if (!s_rule) { 372 + netdev_warn(lag->netdev, "-ENOMEM error configuring CP filter\n"); 373 + return; 374 + } 375 + 376 + if (add) { 377 + if (cp) { 378 + s_rule->recipe_id = 379 + cpu_to_le16(ICE_LAG_SRIOV_CP_RECIPE); 380 + memcpy(s_rule->hdr_data, lacp_train_pkt, 381 + ICE_TRAIN_PKT_LEN); 382 + } else { 383 + s_rule->recipe_id = cpu_to_le16(lag->act_act_recipe); 384 + memcpy(s_rule->hdr_data, act_act_train_pkt, 385 + ICE_TRAIN_PKT_LEN); 386 + } 387 + 388 + s_rule->src = cpu_to_le16(vsi->port_info->lport); 389 + s_rule->act = cpu_to_le32(ICE_FWD_TO_VSI | 390 + ICE_SINGLE_ACT_LAN_ENABLE | 391 + ICE_SINGLE_ACT_VALID_BIT | 392 + FIELD_PREP(ICE_SINGLE_ACT_VSI_ID_M, 393 + vsi->vsi_num)); 394 + s_rule->hdr_len = cpu_to_le16(ICE_TRAIN_PKT_LEN); 395 + s_rule->hdr.type = cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_RX); 396 + opc = ice_aqc_opc_add_sw_rules; 397 + } else { 398 + opc = ice_aqc_opc_remove_sw_rules; 399 + if (cp) 400 + s_rule->index = cpu_to_le16(lag->cp_rule_idx); 401 + else 402 + s_rule->index = cpu_to_le16(lag->act_act_rule_idx); 403 + } 404 + if (ice_aq_sw_rules(&lag->pf->hw, s_rule, buf_len, 1, opc, NULL)) { 405 + netdev_warn(lag->netdev, "Error %s %s rule for aggregate\n", 406 + add ? "ADDING" : "REMOVING", 407 + cp ? "CONTROL PACKET" : "LPORT"); 408 + goto err_cp_free; 409 + } 410 + 411 + if (add) { 412 + if (cp) 413 + lag->cp_rule_idx = le16_to_cpu(s_rule->index); 414 + else 415 + lag->act_act_rule_idx = le16_to_cpu(s_rule->index); 416 + } else { 417 + if (cp) 418 + lag->cp_rule_idx = 0; 419 + else 420 + lag->act_act_rule_idx = 0; 421 + } 422 + 423 + err_cp_free: 424 + kfree(s_rule); 425 + } 426 + 427 + /** 428 + * ice_lag_cfg_pf_fltrs - set filters up for PF traffic 429 + * @lag: local interfaces lag struct 430 + * @ptr: opaque data containing notifier event 431 + */ 432 + static void 433 + ice_lag_cfg_pf_fltrs(struct ice_lag *lag, void *ptr) 434 + { 435 + struct netdev_notifier_bonding_info *info = ptr; 436 + struct netdev_bonding_info *bonding_info; 437 + struct net_device *event_netdev; 438 + 439 + event_netdev = netdev_notifier_info_to_dev(ptr); 440 + if (event_netdev != lag->netdev) 441 + return; 442 + 443 + bonding_info = &info->bonding_info; 444 + 445 + if (lag->bond_aa) { 446 + if (lag->need_fltr_cfg) { 447 + ice_lag_cfg_lp_fltr(lag, true, false); 448 + lag->need_fltr_cfg = false; 449 + } 450 + } else { 451 + ice_lag_cfg_pf_fltrs_act_bkup(lag, bonding_info); 368 452 } 369 453 } 370 454 ··· 516 402 ice_lag_qbuf_recfg(struct ice_hw *hw, struct ice_aqc_cfg_txqs_buf *qbuf, 517 403 u16 vsi_num, u16 numq, u8 tc) 518 404 { 405 + struct ice_pf *pf = hw->back; 519 406 struct ice_q_ctx *q_ctx; 520 407 u16 qid, count = 0; 521 - struct ice_pf *pf; 522 408 int i; 523 409 524 - pf = hw->back; 525 410 for (i = 0; i < numq; i++) { 526 411 q_ctx = ice_get_lan_q_ctx(hw, vsi_num, tc, i); 527 412 if (!q_ctx) { ··· 690 577 } 691 578 692 579 if (ice_aq_cfg_lan_txq(&lag->pf->hw, qbuf, qbuf_size, valq, oldport, 693 - newport, NULL)) { 580 + newport, ICE_AQC_Q_CFG_TC_CHNG, NULL)) { 694 581 dev_warn(dev, "Failure to configure queues for LAG failover\n"); 695 582 goto qbuf_err; 696 583 } ··· 826 713 if (lag->upper_netdev) 827 714 ice_lag_build_netdev_list(lag, &ndlist); 828 715 829 - if (ice_is_feature_supported(pf, ICE_F_SRIOV_LAG) && 830 - lag->bonded && lag->primary && pri_port != act_port && 831 - !list_empty(lag->netdev_head)) 832 - ice_lag_move_single_vf_nodes(lag, pri_port, act_port, vsi->idx); 716 + if (lag->bonded && lag->primary && !list_empty(lag->netdev_head)) { 717 + if (lag->bond_aa && 718 + ice_is_feature_supported(pf, ICE_F_SRIOV_AA_LAG)) 719 + ice_lag_aa_failover(lag, ICE_LAGS_IDX, NULL); 720 + 721 + if (!lag->bond_aa && 722 + ice_is_feature_supported(pf, ICE_F_SRIOV_LAG) && 723 + pri_port != act_port) 724 + ice_lag_move_single_vf_nodes(lag, pri_port, act_port, 725 + vsi->idx); 726 + } 833 727 834 728 ice_lag_destroy_netdev_list(lag, &ndlist); 835 729 ··· 887 767 ice_lag_destroy_netdev_list(lag, &ndlist); 888 768 } 889 769 890 - #define ICE_LAG_SRIOV_CP_RECIPE 10 891 - #define ICE_LAG_SRIOV_TRAIN_PKT_LEN 16 892 - 893 - /** 894 - * ice_lag_cfg_cp_fltr - configure filter for control packets 895 - * @lag: local interface's lag struct 896 - * @add: add or remove rule 897 - */ 898 - static void 899 - ice_lag_cfg_cp_fltr(struct ice_lag *lag, bool add) 900 - { 901 - struct ice_sw_rule_lkup_rx_tx *s_rule = NULL; 902 - struct ice_vsi *vsi; 903 - u16 buf_len, opc; 904 - 905 - vsi = lag->pf->vsi[0]; 906 - 907 - buf_len = ICE_SW_RULE_RX_TX_HDR_SIZE(s_rule, 908 - ICE_LAG_SRIOV_TRAIN_PKT_LEN); 909 - s_rule = kzalloc(buf_len, GFP_KERNEL); 910 - if (!s_rule) { 911 - netdev_warn(lag->netdev, "-ENOMEM error configuring CP filter\n"); 912 - return; 913 - } 914 - 915 - if (add) { 916 - s_rule->hdr.type = cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_RX); 917 - s_rule->recipe_id = cpu_to_le16(ICE_LAG_SRIOV_CP_RECIPE); 918 - s_rule->src = cpu_to_le16(vsi->port_info->lport); 919 - s_rule->act = cpu_to_le32(ICE_FWD_TO_VSI | 920 - ICE_SINGLE_ACT_LAN_ENABLE | 921 - ICE_SINGLE_ACT_VALID_BIT | 922 - FIELD_PREP(ICE_SINGLE_ACT_VSI_ID_M, vsi->vsi_num)); 923 - s_rule->hdr_len = cpu_to_le16(ICE_LAG_SRIOV_TRAIN_PKT_LEN); 924 - memcpy(s_rule->hdr_data, lacp_train_pkt, LACP_TRAIN_PKT_LEN); 925 - opc = ice_aqc_opc_add_sw_rules; 926 - } else { 927 - opc = ice_aqc_opc_remove_sw_rules; 928 - s_rule->index = cpu_to_le16(lag->cp_rule_idx); 929 - } 930 - if (ice_aq_sw_rules(&lag->pf->hw, s_rule, buf_len, 1, opc, NULL)) { 931 - netdev_warn(lag->netdev, "Error %s CP rule for fail-over\n", 932 - add ? "ADDING" : "REMOVING"); 933 - goto cp_free; 934 - } 935 - 936 - if (add) 937 - lag->cp_rule_idx = le16_to_cpu(s_rule->index); 938 - else 939 - lag->cp_rule_idx = 0; 940 - 941 - cp_free: 942 - kfree(s_rule); 943 - } 944 - 945 770 /** 946 771 * ice_lag_prepare_vf_reset - helper to adjust vf lag for reset 947 772 * @lag: lag struct for interface that owns VF ··· 900 835 u8 pri_prt, act_prt; 901 836 902 837 if (lag && lag->bonded && lag->primary && lag->upper_netdev) { 903 - pri_prt = lag->pf->hw.port_info->lport; 904 - act_prt = lag->active_port; 905 - if (act_prt != pri_prt && act_prt != ICE_LAG_INVALID_PORT) { 906 - ice_lag_move_vf_nodes_cfg(lag, act_prt, pri_prt); 907 - return act_prt; 838 + if (!lag->bond_aa) { 839 + pri_prt = lag->pf->hw.port_info->lport; 840 + act_prt = lag->active_port; 841 + if (act_prt != pri_prt && 842 + act_prt != ICE_LAG_INVALID_PORT) { 843 + ice_lag_move_vf_nodes_cfg(lag, act_prt, pri_prt); 844 + return act_prt; 845 + } 846 + } else { 847 + if (lag->port_bitmap & ICE_LAGS_M) { 848 + lag->port_bitmap &= ~ICE_LAGS_M; 849 + ice_lag_aa_failover(lag, ICE_LAGP_IDX, NULL); 850 + lag->port_bitmap |= ICE_LAGS_M; 851 + } 908 852 } 909 853 } 910 854 ··· 931 857 { 932 858 u8 pri_prt; 933 859 934 - if (lag && lag->bonded && lag->primary && 935 - act_prt != ICE_LAG_INVALID_PORT) { 936 - pri_prt = lag->pf->hw.port_info->lport; 937 - ice_lag_move_vf_nodes_cfg(lag, pri_prt, act_prt); 860 + if (lag && lag->bonded && lag->primary) { 861 + if (!lag->bond_aa) { 862 + pri_prt = lag->pf->hw.port_info->lport; 863 + if (act_prt != ICE_LAG_INVALID_PORT) 864 + ice_lag_move_vf_nodes_cfg(lag, pri_prt, 865 + act_prt); 866 + } else { 867 + ice_lag_aa_failover(lag, ICE_LAGS_IDX, NULL); 868 + } 938 869 } 939 870 } 940 871 ··· 952 873 */ 953 874 static void ice_lag_info_event(struct ice_lag *lag, void *ptr) 954 875 { 955 - struct netdev_notifier_bonding_info *info; 876 + struct netdev_notifier_bonding_info *info = ptr; 956 877 struct netdev_bonding_info *bonding_info; 957 878 struct net_device *event_netdev; 958 879 const char *lag_netdev_name; 959 880 960 881 event_netdev = netdev_notifier_info_to_dev(ptr); 961 - info = ptr; 962 882 lag_netdev_name = netdev_name(lag->netdev); 963 883 bonding_info = &info->bonding_info; 964 884 ··· 975 897 } 976 898 977 899 if (bonding_info->slave.state) 978 - ice_lag_set_backup(lag); 900 + ice_lag_set_bkup(lag); 979 901 else 980 902 ice_lag_set_primary(lag); 981 903 982 904 lag_out: 983 905 ice_display_lag_info(lag); 906 + } 907 + 908 + /** 909 + * ice_lag_aa_qbuf_recfg - fill a single queue buffer for recfg cmd 910 + * @hw: HW struct that contains the queue context 911 + * @qbuf: pointer to single queue buffer 912 + * @vsi_num: index of the VF VSI in PF space 913 + * @qnum: queue index 914 + * 915 + * Return: Zero on success, error code on failure. 916 + */ 917 + static int 918 + ice_lag_aa_qbuf_recfg(struct ice_hw *hw, struct ice_aqc_cfg_txqs_buf *qbuf, 919 + u16 vsi_num, int qnum) 920 + { 921 + struct ice_pf *pf = hw->back; 922 + struct ice_q_ctx *q_ctx; 923 + u16 q_id; 924 + 925 + q_ctx = ice_get_lan_q_ctx(hw, vsi_num, 0, qnum); 926 + if (!q_ctx) { 927 + dev_dbg(ice_hw_to_dev(hw), "LAG queue %d no Q context\n", qnum); 928 + return -ENOENT; 929 + } 930 + 931 + if (q_ctx->q_teid == ICE_INVAL_TEID) { 932 + dev_dbg(ice_hw_to_dev(hw), "LAG queue %d INVAL TEID\n", qnum); 933 + return -EINVAL; 934 + } 935 + 936 + if (q_ctx->q_handle == ICE_INVAL_Q_HANDLE) { 937 + dev_dbg(ice_hw_to_dev(hw), "LAG queue %d INVAL Q HANDLE\n", qnum); 938 + return -EINVAL; 939 + } 940 + 941 + q_id = pf->vsi[vsi_num]->txq_map[q_ctx->q_handle]; 942 + qbuf->queue_info[0].q_handle = cpu_to_le16(q_id); 943 + qbuf->queue_info[0].tc = 0; 944 + qbuf->queue_info[0].q_teid = cpu_to_le32(q_ctx->q_teid); 945 + 946 + return 0; 947 + } 948 + 949 + /** 950 + * ice_lag_aa_move_vf_qs - Move some/all VF queues to destination 951 + * @lag: primary interface's lag struct 952 + * @dest: index of destination port 953 + * @vsi_num: index of VF VSI in PF space 954 + * @all: if true move all queues to destination 955 + * @odd: VF wide q indicator for odd/even 956 + * @e_pf: PF struct for the event interface 957 + * 958 + * the parameter "all" is to control whether we are splitting the queues 959 + * between two interfaces or moving them all to the destination interface 960 + */ 961 + static void ice_lag_aa_move_vf_qs(struct ice_lag *lag, u8 dest, u16 vsi_num, 962 + bool all, bool *odd, struct ice_pf *e_pf) 963 + { 964 + DEFINE_RAW_FLEX(struct ice_aqc_cfg_txqs_buf, qbuf, queue_info, 1); 965 + struct ice_hw *old_hw, *new_hw, *pri_hw, *sec_hw; 966 + struct device *dev = ice_pf_to_dev(lag->pf); 967 + struct ice_vsi_ctx *pv_ctx, *sv_ctx; 968 + struct ice_lag_netdev_list ndlist; 969 + u16 num_q, qbuf_size, sec_vsi_num; 970 + u8 pri_lport, sec_lport; 971 + u32 pvf_teid, svf_teid; 972 + u16 vf_id; 973 + 974 + vf_id = lag->pf->vsi[vsi_num]->vf->vf_id; 975 + /* If sec_vf[] not defined, then no second interface to share with */ 976 + if (lag->sec_vf[vf_id]) 977 + sec_vsi_num = lag->sec_vf[vf_id]->idx; 978 + else 979 + return; 980 + 981 + pri_lport = lag->bond_lport_pri; 982 + sec_lport = lag->bond_lport_sec; 983 + 984 + if (pri_lport == ICE_LAG_INVALID_PORT || 985 + sec_lport == ICE_LAG_INVALID_PORT) 986 + return; 987 + 988 + if (!e_pf) 989 + ice_lag_build_netdev_list(lag, &ndlist); 990 + 991 + pri_hw = &lag->pf->hw; 992 + if (e_pf && lag->pf != e_pf) 993 + sec_hw = &e_pf->hw; 994 + else 995 + sec_hw = ice_lag_find_hw_by_lport(lag, sec_lport); 996 + 997 + if (!pri_hw || !sec_hw) 998 + return; 999 + 1000 + if (dest == ICE_LAGP_IDX) { 1001 + struct ice_vsi *vsi; 1002 + 1003 + vsi = ice_get_main_vsi(lag->pf); 1004 + if (!vsi) 1005 + return; 1006 + 1007 + old_hw = sec_hw; 1008 + new_hw = pri_hw; 1009 + ice_lag_config_eswitch(lag, vsi->netdev); 1010 + } else { 1011 + struct ice_pf *sec_pf = sec_hw->back; 1012 + struct ice_vsi *vsi; 1013 + 1014 + vsi = ice_get_main_vsi(sec_pf); 1015 + if (!vsi) 1016 + return; 1017 + 1018 + old_hw = pri_hw; 1019 + new_hw = sec_hw; 1020 + ice_lag_config_eswitch(lag, vsi->netdev); 1021 + } 1022 + 1023 + pv_ctx = ice_get_vsi_ctx(pri_hw, vsi_num); 1024 + if (!pv_ctx) { 1025 + dev_warn(dev, "Unable to locate primary VSI %d context for LAG failover\n", 1026 + vsi_num); 1027 + return; 1028 + } 1029 + 1030 + sv_ctx = ice_get_vsi_ctx(sec_hw, sec_vsi_num); 1031 + if (!sv_ctx) { 1032 + dev_warn(dev, "Unable to locate secondary VSI %d context for LAG failover\n", 1033 + vsi_num); 1034 + return; 1035 + } 1036 + 1037 + num_q = pv_ctx->num_lan_q_entries[0]; 1038 + qbuf_size = __struct_size(qbuf); 1039 + 1040 + /* Suspend traffic for primary VSI VF */ 1041 + pvf_teid = le32_to_cpu(pv_ctx->sched.vsi_node[0]->info.node_teid); 1042 + ice_sched_suspend_resume_elems(pri_hw, 1, &pvf_teid, true); 1043 + 1044 + /* Suspend traffic for secondary VSI VF */ 1045 + svf_teid = le32_to_cpu(sv_ctx->sched.vsi_node[0]->info.node_teid); 1046 + ice_sched_suspend_resume_elems(sec_hw, 1, &svf_teid, true); 1047 + 1048 + for (int i = 0; i < num_q; i++) { 1049 + struct ice_sched_node *n_prt, *q_node, *parent; 1050 + struct ice_port_info *pi, *new_pi; 1051 + struct ice_vsi_ctx *src_ctx; 1052 + struct ice_sched_node *p; 1053 + struct ice_q_ctx *q_ctx; 1054 + u16 dst_vsi_num; 1055 + 1056 + pi = old_hw->port_info; 1057 + new_pi = new_hw->port_info; 1058 + 1059 + *odd = !(*odd); 1060 + if ((dest == ICE_LAGP_IDX && *odd && !all) || 1061 + (dest == ICE_LAGS_IDX && !(*odd) && !all) || 1062 + lag->q_home[vf_id][i] == dest) 1063 + continue; 1064 + 1065 + if (dest == ICE_LAGP_IDX) 1066 + dst_vsi_num = vsi_num; 1067 + else 1068 + dst_vsi_num = sec_vsi_num; 1069 + 1070 + n_prt = ice_sched_get_free_qparent(new_hw->port_info, 1071 + dst_vsi_num, 0, 1072 + ICE_SCHED_NODE_OWNER_LAN); 1073 + if (!n_prt) 1074 + continue; 1075 + 1076 + q_ctx = ice_get_lan_q_ctx(pri_hw, vsi_num, 0, i); 1077 + if (!q_ctx) 1078 + continue; 1079 + 1080 + if (dest == ICE_LAGP_IDX) 1081 + src_ctx = sv_ctx; 1082 + else 1083 + src_ctx = pv_ctx; 1084 + 1085 + q_node = ice_sched_find_node_by_teid(src_ctx->sched.vsi_node[0], 1086 + q_ctx->q_teid); 1087 + if (!q_node) 1088 + continue; 1089 + 1090 + qbuf->src_parent_teid = q_node->info.parent_teid; 1091 + qbuf->dst_parent_teid = n_prt->info.node_teid; 1092 + 1093 + /* Move the node in the HW/FW */ 1094 + if (ice_lag_aa_qbuf_recfg(pri_hw, qbuf, vsi_num, i)) 1095 + continue; 1096 + 1097 + if (dest == ICE_LAGP_IDX) 1098 + ice_aq_cfg_lan_txq(pri_hw, qbuf, qbuf_size, 1, 1099 + sec_lport, pri_lport, 1100 + ICE_AQC_Q_CFG_MOVE_TC_CHNG, 1101 + NULL); 1102 + else 1103 + ice_aq_cfg_lan_txq(pri_hw, qbuf, qbuf_size, 1, 1104 + pri_lport, sec_lport, 1105 + ICE_AQC_Q_CFG_MOVE_TC_CHNG, 1106 + NULL); 1107 + 1108 + /* Move the node in the SW */ 1109 + parent = q_node->parent; 1110 + if (!parent) 1111 + continue; 1112 + 1113 + for (int n = 0; n < parent->num_children; n++) { 1114 + int j; 1115 + 1116 + if (parent->children[n] != q_node) 1117 + continue; 1118 + 1119 + for (j = n + 1; j < parent->num_children; 1120 + j++) { 1121 + parent->children[j - 1] = 1122 + parent->children[j]; 1123 + } 1124 + parent->children[j] = NULL; 1125 + parent->num_children--; 1126 + break; 1127 + } 1128 + 1129 + p = pi->sib_head[0][q_node->tx_sched_layer]; 1130 + while (p) { 1131 + if (p->sibling == q_node) { 1132 + p->sibling = q_node->sibling; 1133 + break; 1134 + } 1135 + p = p->sibling; 1136 + } 1137 + 1138 + if (pi->sib_head[0][q_node->tx_sched_layer] == q_node) 1139 + pi->sib_head[0][q_node->tx_sched_layer] = 1140 + q_node->sibling; 1141 + 1142 + q_node->parent = n_prt; 1143 + q_node->info.parent_teid = n_prt->info.node_teid; 1144 + q_node->sibling = NULL; 1145 + p = new_pi->sib_head[0][q_node->tx_sched_layer]; 1146 + if (p) { 1147 + while (p) { 1148 + if (!p->sibling) { 1149 + p->sibling = q_node; 1150 + break; 1151 + } 1152 + p = p->sibling; 1153 + } 1154 + } else { 1155 + new_pi->sib_head[0][q_node->tx_sched_layer] = 1156 + q_node; 1157 + } 1158 + 1159 + n_prt->children[n_prt->num_children++] = q_node; 1160 + lag->q_home[vf_id][i] = dest; 1161 + } 1162 + 1163 + ice_sched_suspend_resume_elems(pri_hw, 1, &pvf_teid, false); 1164 + ice_sched_suspend_resume_elems(sec_hw, 1, &svf_teid, false); 1165 + 1166 + if (!e_pf) 1167 + ice_lag_destroy_netdev_list(lag, &ndlist); 1168 + } 1169 + 1170 + /** 1171 + * ice_lag_aa_failover - move VF queues in A/A mode 1172 + * @lag: primary lag struct 1173 + * @dest: index of destination port 1174 + * @e_pf: PF struct for event port 1175 + */ 1176 + void ice_lag_aa_failover(struct ice_lag *lag, u8 dest, struct ice_pf *e_pf) 1177 + { 1178 + bool odd = true, all = false; 1179 + int i; 1180 + 1181 + /* Primary can be a target if down (cleanup), but secondary can't */ 1182 + if (dest == ICE_LAGS_IDX && !(lag->port_bitmap & ICE_LAGS_M)) 1183 + return; 1184 + 1185 + /* Move all queues to a destination if only one port is active, 1186 + * or no ports are active and dest is primary. 1187 + */ 1188 + if ((lag->port_bitmap ^ (ICE_LAGP_M | ICE_LAGS_M)) || 1189 + (!lag->port_bitmap && dest == ICE_LAGP_IDX)) 1190 + all = true; 1191 + 1192 + ice_for_each_vsi(lag->pf, i) 1193 + if (lag->pf->vsi[i] && lag->pf->vsi[i]->type == ICE_VSI_VF) 1194 + ice_lag_aa_move_vf_qs(lag, dest, i, all, &odd, e_pf); 984 1195 } 985 1196 986 1197 /** ··· 1288 921 u16 numq, valq, num_moved, qbuf_size; 1289 922 u16 buf_size = __struct_size(buf); 1290 923 struct ice_aqc_cfg_txqs_buf *qbuf; 924 + struct ice_hw *hw = &lag->pf->hw; 1291 925 struct ice_sched_node *n_prt; 1292 926 __le32 teid, parent_teid; 1293 927 struct ice_vsi_ctx *ctx; 1294 - struct ice_hw *hw; 1295 928 u32 tmp_teid; 1296 929 1297 - hw = &lag->pf->hw; 1298 930 ctx = ice_get_vsi_ctx(hw, vsi_num); 1299 931 if (!ctx) { 1300 932 dev_warn(dev, "Unable to locate VSI context for LAG reclaim\n"); ··· 1334 968 1335 969 if (ice_aq_cfg_lan_txq(hw, qbuf, qbuf_size, numq, 1336 970 src_hw->port_info->lport, hw->port_info->lport, 1337 - NULL)) { 971 + ICE_AQC_Q_CFG_TC_CHNG, NULL)) { 1338 972 dev_warn(dev, "Failure to configure queues for LAG failover\n"); 1339 973 goto reclaim_qerr; 1340 974 } ··· 1405 1039 1406 1040 lag->bonded = true; 1407 1041 lag->role = ICE_LAG_UNSET; 1042 + lag->need_fltr_cfg = true; 1408 1043 netdev_info(lag->netdev, "Shared SR-IOV resources in bond are active\n"); 1409 1044 } 1410 1045 1411 1046 /** 1412 - * ice_lag_config_eswitch - configure eswitch to work with LAG 1413 - * @lag: lag info struct 1414 - * @netdev: active network interface device struct 1415 - * 1416 - * Updates all port representors in eswitch to use @netdev for Tx. 1417 - * 1418 - * Configures the netdev to keep dst metadata (also used in representor Tx). 1419 - * This is required for an uplink without switchdev mode configured. 1420 - */ 1421 - static void ice_lag_config_eswitch(struct ice_lag *lag, 1422 - struct net_device *netdev) 1423 - { 1424 - struct ice_repr *repr; 1425 - unsigned long id; 1426 - 1427 - xa_for_each(&lag->pf->eswitch.reprs, id, repr) 1428 - repr->dst->u.port_info.lower_dev = netdev; 1429 - 1430 - netif_keep_dst(netdev); 1431 - } 1432 - 1433 - /** 1434 - * ice_lag_unlink - handle unlink event 1047 + * ice_lag_act_bkup_unlink - handle unlink event for A/B bond 1435 1048 * @lag: LAG info struct 1436 1049 */ 1437 - static void ice_lag_unlink(struct ice_lag *lag) 1050 + static void ice_lag_act_bkup_unlink(struct ice_lag *lag) 1438 1051 { 1439 1052 u8 pri_port, act_port, loc_port; 1440 1053 struct ice_pf *pf = lag->pf; ··· 1449 1104 } 1450 1105 } 1451 1106 } 1107 + } 1452 1108 1453 - lag->bonded = false; 1454 - lag->role = ICE_LAG_NONE; 1455 - lag->upper_netdev = NULL; 1109 + /** 1110 + * ice_lag_aa_unlink - handle unlink event for Active-Active bond 1111 + * @lag: LAG info struct 1112 + */ 1113 + static void ice_lag_aa_unlink(struct ice_lag *lag) 1114 + { 1115 + struct ice_lag *pri_lag; 1116 + 1117 + if (lag->primary) { 1118 + pri_lag = lag; 1119 + lag->port_bitmap &= ~ICE_LAGP_M; 1120 + } else { 1121 + pri_lag = ice_lag_find_primary(lag); 1122 + if (pri_lag) 1123 + pri_lag->port_bitmap &= ICE_LAGS_M; 1124 + } 1125 + 1126 + if (pri_lag) { 1127 + ice_lag_aa_failover(pri_lag, ICE_LAGP_IDX, lag->pf); 1128 + if (lag->primary) 1129 + pri_lag->bond_lport_pri = ICE_LAG_INVALID_PORT; 1130 + else 1131 + pri_lag->bond_lport_sec = ICE_LAG_INVALID_PORT; 1132 + } 1456 1133 } 1457 1134 1458 1135 /** ··· 1490 1123 if (netdev != lag->netdev) 1491 1124 return; 1492 1125 1493 - if (info->linking) 1126 + if (info->linking) { 1494 1127 ice_lag_link(lag); 1495 - else 1496 - ice_lag_unlink(lag); 1128 + } else { 1129 + if (lag->bond_aa) 1130 + ice_lag_aa_unlink(lag); 1131 + else 1132 + ice_lag_act_bkup_unlink(lag); 1133 + 1134 + lag->bonded = false; 1135 + lag->role = ICE_LAG_NONE; 1136 + lag->upper_netdev = NULL; 1137 + lag->bond_aa = false; 1138 + lag->need_fltr_cfg = false; 1139 + } 1497 1140 } 1498 1141 1499 1142 /** ··· 1601 1224 */ 1602 1225 static void ice_lag_primary_swid(struct ice_lag *lag, bool link) 1603 1226 { 1604 - struct ice_hw *hw; 1605 - u16 swid; 1606 - 1607 - hw = &lag->pf->hw; 1608 - swid = hw->port_info->sw_id; 1227 + struct ice_hw *hw = &lag->pf->hw; 1228 + u16 swid = hw->port_info->sw_id; 1609 1229 1610 1230 if (ice_share_res(hw, ICE_AQC_RES_TYPE_SWID, link, swid)) 1611 1231 dev_warn(ice_pf_to_dev(lag->pf), "Failure to set primary interface shared status\n"); ··· 1615 1241 */ 1616 1242 static void ice_lag_add_prune_list(struct ice_lag *lag, struct ice_pf *event_pf) 1617 1243 { 1618 - u16 num_vsi, rule_buf_sz, vsi_list_id, event_vsi_num, prim_vsi_idx; 1619 - struct ice_sw_rule_vsi_list *s_rule = NULL; 1244 + u16 rule_buf_sz, vsi_list_id, event_vsi_num, prim_vsi_idx, num_vsi = 1; 1245 + struct ice_sw_rule_vsi_list *s_rule; 1620 1246 struct device *dev; 1621 - 1622 - num_vsi = 1; 1623 1247 1624 1248 dev = ice_pf_to_dev(lag->pf); 1625 1249 event_vsi_num = event_pf->vsi[0]->vsi_num; ··· 1654 1282 */ 1655 1283 static void ice_lag_del_prune_list(struct ice_lag *lag, struct ice_pf *event_pf) 1656 1284 { 1657 - u16 num_vsi, vsi_num, vsi_idx, rule_buf_sz, vsi_list_id; 1658 - struct ice_sw_rule_vsi_list *s_rule = NULL; 1285 + u16 vsi_num, vsi_idx, rule_buf_sz, vsi_list_id, num_vsi = 1; 1286 + struct ice_sw_rule_vsi_list *s_rule; 1659 1287 struct device *dev; 1660 - 1661 - num_vsi = 1; 1662 1288 1663 1289 dev = ice_pf_to_dev(lag->pf); 1664 1290 vsi_num = event_pf->vsi[0]->vsi_num; ··· 1705 1335 ice_set_feature_support(pf, ICE_F_SRIOV_LAG); 1706 1336 else 1707 1337 ice_clear_feature_support(pf, ICE_F_SRIOV_LAG); 1338 + 1339 + if (caps->sriov_aa_lag && ice_pkg_has_lport_extract(&pf->hw)) 1340 + ice_set_feature_support(pf, ICE_F_SRIOV_AA_LAG); 1341 + else 1342 + ice_clear_feature_support(pf, ICE_F_SRIOV_AA_LAG); 1708 1343 } 1709 1344 1710 1345 /** ··· 1719 1344 */ 1720 1345 static void ice_lag_changeupper_event(struct ice_lag *lag, void *ptr) 1721 1346 { 1722 - struct netdev_notifier_changeupper_info *info; 1347 + struct netdev_notifier_changeupper_info *info = ptr; 1723 1348 struct ice_lag *primary_lag; 1724 1349 struct net_device *netdev; 1725 1350 1726 - info = ptr; 1727 1351 netdev = netdev_notifier_info_to_dev(ptr); 1728 1352 1729 1353 /* not for this netdev */ ··· 1743 1369 /* Configure primary's SWID to be shared */ 1744 1370 ice_lag_primary_swid(lag, true); 1745 1371 primary_lag = lag; 1372 + lag->bond_lport_pri = lag->pf->hw.port_info->lport; 1373 + lag->bond_lport_sec = ICE_LAG_INVALID_PORT; 1374 + lag->port_bitmap = 0; 1746 1375 } else { 1747 1376 u16 swid; 1748 1377 ··· 1755 1378 swid = primary_lag->pf->hw.port_info->sw_id; 1756 1379 ice_lag_set_swid(swid, lag, true); 1757 1380 ice_lag_add_prune_list(primary_lag, lag->pf); 1758 - ice_lag_cfg_drop_fltr(lag, true); 1381 + primary_lag->bond_lport_sec = 1382 + lag->pf->hw.port_info->lport; 1759 1383 } 1760 1384 /* add filter for primary control packets */ 1761 - ice_lag_cfg_cp_fltr(lag, true); 1385 + ice_lag_cfg_lp_fltr(lag, true, true); 1762 1386 } else { 1763 1387 if (!primary_lag && lag->primary) 1764 1388 primary_lag = lag; 1765 1389 1390 + if (primary_lag) { 1391 + for (int i = 0; i < ICE_MAX_SRIOV_VFS; i++) { 1392 + if (primary_lag->sec_vf[i]) { 1393 + ice_vsi_release(primary_lag->sec_vf[i]); 1394 + primary_lag->sec_vf[i] = NULL; 1395 + } 1396 + } 1397 + } 1398 + 1766 1399 if (!lag->primary) { 1767 1400 ice_lag_set_swid(0, lag, false); 1401 + if (primary_lag) 1402 + primary_lag->bond_lport_sec = 1403 + ICE_LAG_INVALID_PORT; 1768 1404 } else { 1769 1405 if (primary_lag && lag->primary) { 1770 1406 ice_lag_primary_swid(lag, false); ··· 1785 1395 } 1786 1396 } 1787 1397 /* remove filter for control packets */ 1788 - ice_lag_cfg_cp_fltr(lag, false); 1398 + ice_lag_cfg_lp_fltr(lag, false, !lag->bond_aa); 1789 1399 } 1790 1400 } 1791 1401 ··· 1798 1408 */ 1799 1409 static void ice_lag_monitor_link(struct ice_lag *lag, void *ptr) 1800 1410 { 1801 - struct netdev_notifier_changeupper_info *info; 1411 + struct netdev_notifier_changeupper_info *info = ptr; 1802 1412 struct ice_hw *prim_hw, *active_hw; 1803 1413 struct net_device *event_netdev; 1804 1414 struct ice_pf *pf; ··· 1811 1421 if (!netif_is_same_ice(lag->pf, event_netdev)) 1812 1422 return; 1813 1423 1424 + if (info->upper_dev != lag->upper_netdev) 1425 + return; 1426 + 1427 + if (info->linking) 1428 + return; 1429 + 1814 1430 pf = lag->pf; 1815 1431 prim_hw = &pf->hw; 1816 1432 prim_port = prim_hw->port_info->lport; 1817 1433 1818 - info = (struct netdev_notifier_changeupper_info *)ptr; 1819 - if (info->upper_dev != lag->upper_netdev) 1820 - return; 1434 + /* Since there are only two interfaces allowed in SRIOV+LAG, if 1435 + * one port is leaving, then nodes need to be on primary 1436 + * interface. 1437 + */ 1438 + if (lag->bond_aa) { 1439 + struct ice_netdev_priv *e_ndp; 1440 + struct ice_pf *e_pf; 1821 1441 1822 - if (!info->linking) { 1823 - /* Since there are only two interfaces allowed in SRIOV+LAG, if 1824 - * one port is leaving, then nodes need to be on primary 1825 - * interface. 1826 - */ 1442 + e_ndp = netdev_priv(event_netdev); 1443 + e_pf = e_ndp->vsi->back; 1444 + 1445 + if (lag->bond_lport_pri != ICE_LAG_INVALID_PORT && 1446 + lag->port_bitmap & ICE_LAGS_M) { 1447 + lag->port_bitmap &= ~ICE_LAGS_M; 1448 + ice_lag_aa_failover(lag, ICE_LAGP_IDX, e_pf); 1449 + lag->bond_lport_sec = ICE_LAG_INVALID_PORT; 1450 + } 1451 + } else { 1827 1452 if (prim_port != lag->active_port && 1828 1453 lag->active_port != ICE_LAG_INVALID_PORT) { 1829 1454 active_hw = ice_lag_find_hw_by_lport(lag, ··· 1850 1445 } 1851 1446 1852 1447 /** 1853 - * ice_lag_monitor_active - main PF keep track of which port is active 1448 + * ice_lag_monitor_act_bkup - keep track of which port is active in A/B LAG 1854 1449 * @lag: lag info struct 1855 - * @ptr: opaque data containing notifier event 1450 + * @b_info: bonding info 1451 + * @event_netdev: net_device got target netdev 1856 1452 * 1857 1453 * This function is for the primary PF to monitor changes in which port is 1858 1454 * active and handle changes for SRIOV VF functionality 1859 1455 */ 1860 - static void ice_lag_monitor_active(struct ice_lag *lag, void *ptr) 1456 + static void ice_lag_monitor_act_bkup(struct ice_lag *lag, 1457 + struct netdev_bonding_info *b_info, 1458 + struct net_device *event_netdev) 1861 1459 { 1862 - struct net_device *event_netdev, *event_upper; 1863 - struct netdev_notifier_bonding_info *info; 1864 - struct netdev_bonding_info *bonding_info; 1865 1460 struct ice_netdev_priv *event_np; 1866 1461 struct ice_pf *pf, *event_pf; 1867 1462 u8 prim_port, event_port; 1868 1463 1869 - if (!lag->primary) 1870 - return; 1871 - 1872 1464 pf = lag->pf; 1873 1465 if (!pf) 1874 - return; 1875 - 1876 - event_netdev = netdev_notifier_info_to_dev(ptr); 1877 - rcu_read_lock(); 1878 - event_upper = netdev_master_upper_dev_get_rcu(event_netdev); 1879 - rcu_read_unlock(); 1880 - if (!netif_is_ice(event_netdev) || event_upper != lag->upper_netdev) 1881 1466 return; 1882 1467 1883 1468 event_np = netdev_priv(event_netdev); ··· 1875 1480 event_port = event_pf->hw.port_info->lport; 1876 1481 prim_port = pf->hw.port_info->lport; 1877 1482 1878 - info = (struct netdev_notifier_bonding_info *)ptr; 1879 - bonding_info = &info->bonding_info; 1880 - 1881 - if (!bonding_info->slave.state) { 1483 + if (!b_info->slave.state) { 1882 1484 /* if no port is currently active, then nodes and filters exist 1883 1485 * on primary port, check if we need to move them 1884 1486 */ ··· 1912 1520 } 1913 1521 1914 1522 /** 1523 + * ice_lag_aa_clear_spoof - adjust the placeholder VSI spoofing for A/A LAG 1524 + * @vsi: placeholder VSI to adjust 1525 + */ 1526 + static void ice_lag_aa_clear_spoof(struct ice_vsi *vsi) 1527 + { 1528 + ice_vsi_update_security(vsi, ice_vsi_ctx_clear_antispoof); 1529 + } 1530 + 1531 + /** 1532 + * ice_lag_monitor_act_act - Keep track of active ports in A/A LAG 1533 + * @lag: lag struct for primary interface 1534 + * @b_info: bonding_info for event 1535 + * @event_netdev: net_device for target netdev 1536 + */ 1537 + static void ice_lag_monitor_act_act(struct ice_lag *lag, 1538 + struct netdev_bonding_info *b_info, 1539 + struct net_device *event_netdev) 1540 + { 1541 + struct ice_netdev_priv *event_np; 1542 + u8 prim_port, event_port; 1543 + struct ice_pf *event_pf; 1544 + 1545 + event_np = netdev_priv(event_netdev); 1546 + event_pf = event_np->vsi->back; 1547 + event_port = event_pf->hw.port_info->lport; 1548 + prim_port = lag->pf->hw.port_info->lport; 1549 + 1550 + if (b_info->slave.link == BOND_LINK_UP) { 1551 + /* Port is coming up */ 1552 + if (prim_port == event_port) { 1553 + /* Processing event for primary interface */ 1554 + if (lag->bond_lport_pri == ICE_LAG_INVALID_PORT) 1555 + return; 1556 + 1557 + if (!(lag->port_bitmap & ICE_LAGP_M)) { 1558 + /* Primary port was not marked up before, move 1559 + * some|all VF queues to it and mark as up 1560 + */ 1561 + lag->port_bitmap |= ICE_LAGP_M; 1562 + ice_lag_aa_failover(lag, ICE_LAGP_IDX, event_pf); 1563 + } 1564 + } else { 1565 + if (lag->bond_lport_sec == ICE_LAG_INVALID_PORT) 1566 + return; 1567 + 1568 + /* Create placeholder VSIs on secondary PF. 1569 + * The placeholder is necessary so that we have 1570 + * an element that represents the VF on the secondary 1571 + * interface's scheduling tree. This will be a tree 1572 + * root for scheduling nodes when they are moved to 1573 + * the secondary interface. 1574 + */ 1575 + if (!lag->sec_vf[0]) { 1576 + struct ice_vsi_cfg_params params = {}; 1577 + struct ice_vsi *nvsi; 1578 + struct ice_vf *vf; 1579 + unsigned int bkt; 1580 + 1581 + params.type = ICE_VSI_VF; 1582 + params.port_info = event_pf->hw.port_info; 1583 + params.flags = ICE_VSI_FLAG_INIT; 1584 + 1585 + ice_for_each_vf(lag->pf, bkt, vf) { 1586 + params.vf = vf; 1587 + nvsi = ice_vsi_setup(event_pf, 1588 + &params); 1589 + ice_lag_aa_clear_spoof(nvsi); 1590 + lag->sec_vf[vf->vf_id] = nvsi; 1591 + } 1592 + } 1593 + 1594 + if (!(lag->port_bitmap & ICE_LAGS_M)) { 1595 + /* Secondary port was not marked up before, 1596 + * move some|all VF queues to it and mark as up 1597 + */ 1598 + lag->port_bitmap |= ICE_LAGS_M; 1599 + ice_lag_aa_failover(lag, ICE_LAGS_IDX, event_pf); 1600 + } 1601 + } 1602 + } else { 1603 + /* Port is going down */ 1604 + if (prim_port == event_port) { 1605 + lag->port_bitmap &= ~ICE_LAGP_M; 1606 + ice_lag_aa_failover(lag, ICE_LAGS_IDX, event_pf); 1607 + } else { 1608 + lag->port_bitmap &= ~ICE_LAGS_M; 1609 + ice_lag_aa_failover(lag, ICE_LAGP_IDX, event_pf); 1610 + } 1611 + } 1612 + } 1613 + 1614 + /** 1615 + * ice_lag_monitor_info - Calls relevant A/A or A/B monitoring function 1616 + * @lag: lag info struct 1617 + * @ptr: opaque data containing notifier event 1618 + * 1619 + * This function is for the primary PF to monitor changes in which port is 1620 + * active and handle changes for SRIOV VF functionality 1621 + */ 1622 + static void ice_lag_monitor_info(struct ice_lag *lag, void *ptr) 1623 + { 1624 + struct netdev_notifier_bonding_info *info = ptr; 1625 + struct net_device *event_netdev, *event_upper; 1626 + struct netdev_bonding_info *bonding_info; 1627 + 1628 + if (!lag->primary) 1629 + return; 1630 + 1631 + event_netdev = netdev_notifier_info_to_dev(ptr); 1632 + bonding_info = &info->bonding_info; 1633 + rcu_read_lock(); 1634 + event_upper = netdev_master_upper_dev_get_rcu(event_netdev); 1635 + rcu_read_unlock(); 1636 + if (!netif_is_ice(event_netdev) || event_upper != lag->upper_netdev) 1637 + return; 1638 + 1639 + if (lag->bond_aa) 1640 + ice_lag_monitor_act_act(lag, bonding_info, event_netdev); 1641 + else 1642 + ice_lag_monitor_act_bkup(lag, bonding_info, event_netdev); 1643 + } 1644 + /** 1915 1645 * ice_lag_chk_comp - evaluate bonded interface for feature support 1916 1646 * @lag: lag info struct 1917 1647 * @ptr: opaque data for netdev event info ··· 2041 1527 static bool 2042 1528 ice_lag_chk_comp(struct ice_lag *lag, void *ptr) 2043 1529 { 1530 + struct netdev_notifier_bonding_info *info = ptr; 2044 1531 struct net_device *event_netdev, *event_upper; 2045 - struct netdev_notifier_bonding_info *info; 2046 1532 struct netdev_bonding_info *bonding_info; 2047 1533 struct list_head *tmp; 2048 1534 struct device *dev; 2049 1535 int count = 0; 1536 + 1537 + /* All members need to know if bond A/A or A/B */ 1538 + bonding_info = &info->bonding_info; 1539 + lag->bond_mode = bonding_info->master.bond_mode; 1540 + if (lag->bond_mode != BOND_MODE_ACTIVEBACKUP) 1541 + lag->bond_aa = true; 1542 + else 1543 + lag->bond_aa = false; 2050 1544 2051 1545 if (!lag->primary) 2052 1546 return true; ··· 2076 1554 return false; 2077 1555 } 2078 1556 2079 - info = (struct netdev_notifier_bonding_info *)ptr; 2080 - bonding_info = &info->bonding_info; 2081 - lag->bond_mode = bonding_info->master.bond_mode; 2082 - if (lag->bond_mode != BOND_MODE_ACTIVEBACKUP) { 2083 - dev_info(dev, "Bond Mode not ACTIVE-BACKUP - VF LAG disabled\n"); 1557 + if (lag->bond_aa && !ice_is_feature_supported(lag->pf, 1558 + ICE_F_SRIOV_AA_LAG)) 2084 1559 return false; 2085 - } 2086 1560 2087 1561 list_for_each(tmp, lag->netdev_head) { 2088 1562 struct ice_dcbx_cfg *dcb_cfg, *peer_dcb_cfg; ··· 2182 1664 static void 2183 1665 ice_lag_monitor_rdma(struct ice_lag *lag, void *ptr) 2184 1666 { 2185 - struct netdev_notifier_changeupper_info *info; 1667 + struct netdev_notifier_changeupper_info *info = ptr; 2186 1668 struct net_device *netdev; 2187 1669 2188 - info = ptr; 2189 1670 netdev = netdev_notifier_info_to_dev(ptr); 2190 1671 2191 1672 if (netdev != lag->netdev) ··· 2232 1715 */ 2233 1716 static void ice_lag_disable_sriov_bond(struct ice_lag *lag) 2234 1717 { 2235 - struct ice_netdev_priv *np; 2236 - struct ice_pf *pf; 1718 + struct ice_netdev_priv *np = netdev_priv(lag->netdev); 1719 + struct ice_pf *pf = np->vsi->back; 2237 1720 2238 - np = netdev_priv(lag->netdev); 2239 - pf = np->vsi->back; 2240 1721 ice_clear_feature_support(pf, ICE_F_SRIOV_LAG); 1722 + ice_clear_feature_support(pf, ICE_F_SRIOV_AA_LAG); 1723 + } 1724 + 1725 + /** 1726 + * ice_lag_preset_drop_fltr - preset drop filter for A/B bonds 1727 + * @lag: local lag struct 1728 + * @ptr: opaque data containing event 1729 + * 1730 + * Sets the initial drop filter for secondary interface in an 1731 + * active-backup bond 1732 + */ 1733 + static void ice_lag_preset_drop_fltr(struct ice_lag *lag, void *ptr) 1734 + { 1735 + struct net_device *netdev = netdev_notifier_info_to_dev(ptr); 1736 + 1737 + if (netdev != lag->netdev || lag->primary || !lag->need_fltr_cfg) 1738 + return; 1739 + 1740 + ice_lag_cfg_drop_fltr(lag, true); 1741 + lag->need_fltr_cfg = false; 2241 1742 } 2242 1743 2243 1744 /** ··· 2296 1761 ice_lag_unregister(lag_work->lag, netdev); 2297 1762 goto lag_cleanup; 2298 1763 } 2299 - ice_lag_monitor_active(lag_work->lag, 2300 - &lag_work->info.bonding_info); 2301 1764 ice_lag_cfg_pf_fltrs(lag_work->lag, 1765 + &lag_work->info.bonding_info); 1766 + ice_lag_preset_drop_fltr(lag_work->lag, 1767 + &lag_work->info.bonding_info); 1768 + ice_lag_monitor_info(lag_work->lag, 2302 1769 &lag_work->info.bonding_info); 2303 1770 } 2304 1771 ice_lag_info_event(lag_work->lag, &lag_work->info.bonding_info); ··· 2374 1837 lag_work->lag = lag; 2375 1838 lag_work->event = event; 2376 1839 if (event == NETDEV_CHANGEUPPER) { 2377 - struct netdev_notifier_changeupper_info *info; 1840 + struct netdev_notifier_changeupper_info *info = ptr; 2378 1841 2379 - info = ptr; 2380 1842 upper_netdev = info->upper_dev; 2381 1843 } else { 2382 1844 upper_netdev = netdev_master_upper_dev_get(netdev); ··· 2425 1889 */ 2426 1890 static int ice_register_lag_handler(struct ice_lag *lag) 2427 1891 { 1892 + struct notifier_block *notif_blk = &lag->notif_block; 2428 1893 struct device *dev = ice_pf_to_dev(lag->pf); 2429 - struct notifier_block *notif_blk; 2430 - 2431 - notif_blk = &lag->notif_block; 2432 1894 2433 1895 if (!notif_blk->notifier_call) { 2434 1896 notif_blk->notifier_call = ice_lag_event_handler; ··· 2446 1912 */ 2447 1913 static void ice_unregister_lag_handler(struct ice_lag *lag) 2448 1914 { 1915 + struct notifier_block *notif_blk = &lag->notif_block; 2449 1916 struct device *dev = ice_pf_to_dev(lag->pf); 2450 - struct notifier_block *notif_blk; 2451 1917 2452 - notif_blk = &lag->notif_block; 2453 1918 if (notif_blk->notifier_call) { 2454 1919 unregister_netdevice_notifier(notif_blk); 2455 1920 dev_dbg(dev, "LAG event handler unregistered\n"); ··· 2510 1977 u16 numq, valq, num_moved, qbuf_size; 2511 1978 u16 buf_size = __struct_size(buf); 2512 1979 struct ice_aqc_cfg_txqs_buf *qbuf; 1980 + struct ice_hw *hw = &lag->pf->hw; 2513 1981 struct ice_sched_node *n_prt; 2514 1982 __le32 teid, parent_teid; 2515 1983 struct ice_vsi_ctx *ctx; 2516 - struct ice_hw *hw; 2517 1984 u32 tmp_teid; 2518 1985 2519 - hw = &lag->pf->hw; 2520 1986 ctx = ice_get_vsi_ctx(hw, vsi_num); 2521 1987 if (!ctx) { 2522 1988 dev_warn(dev, "LAG rebuild failed after reset due to VSI Context failure\n"); ··· 2552 2020 } 2553 2021 2554 2022 if (ice_aq_cfg_lan_txq(hw, qbuf, qbuf_size, numq, hw->port_info->lport, 2555 - dest_hw->port_info->lport, NULL)) { 2023 + dest_hw->port_info->lport, 2024 + ICE_AQC_Q_CFG_TC_CHNG, NULL)) { 2556 2025 dev_warn(dev, "Failure to configure queues for LAG reset rebuild\n"); 2557 2026 goto sync_qerr; 2558 2027 } ··· 2649 2116 lag->netdev = vsi->netdev; 2650 2117 lag->role = ICE_LAG_NONE; 2651 2118 lag->active_port = ICE_LAG_INVALID_PORT; 2119 + lag->port_bitmap = 0x0; 2652 2120 lag->bonded = false; 2121 + lag->bond_aa = false; 2122 + lag->need_fltr_cfg = false; 2653 2123 lag->upper_netdev = NULL; 2654 2124 lag->notif_block.notifier_call = NULL; 2125 + memset(lag->sec_vf, 0, sizeof(lag->sec_vf)); 2655 2126 2656 2127 err = ice_register_lag_handler(lag); 2657 2128 if (err) { ··· 2673 2136 if (err) 2674 2137 goto free_rcp_res; 2675 2138 2139 + err = ice_create_lag_recipe(&pf->hw, &lag->act_act_recipe, 2140 + ice_lport_rcp, 1); 2141 + if (err) 2142 + goto free_lport_res; 2143 + 2676 2144 /* associate recipes to profiles */ 2677 2145 for (n = 0; n < ICE_PROFID_IPV6_GTPU_IPV6_TCP_INNER; n++) { 2678 2146 err = ice_aq_get_recipe_to_profile(&pf->hw, n, ··· 2687 2145 2688 2146 if (recipe_bits & BIT(ICE_SW_LKUP_DFLT)) { 2689 2147 recipe_bits |= BIT(lag->pf_recipe) | 2690 - BIT(lag->lport_recipe); 2148 + BIT(lag->lport_recipe) | 2149 + BIT(lag->act_act_recipe); 2691 2150 ice_aq_map_recipe_to_profile(&pf->hw, n, 2692 2151 recipe_bits, NULL); 2693 2152 } ··· 2699 2156 dev_dbg(dev, "INIT LAG complete\n"); 2700 2157 return 0; 2701 2158 2159 + free_lport_res: 2160 + ice_free_hw_res(&pf->hw, ICE_AQC_RES_TYPE_RECIPE, 1, 2161 + &lag->lport_recipe); 2162 + 2702 2163 free_rcp_res: 2703 2164 ice_free_hw_res(&pf->hw, ICE_AQC_RES_TYPE_RECIPE, 1, 2704 - &pf->lag->pf_recipe); 2165 + &lag->pf_recipe); 2705 2166 lag_error: 2706 2167 kfree(lag); 2707 2168 pf->lag = NULL; ··· 2721 2174 */ 2722 2175 void ice_deinit_lag(struct ice_pf *pf) 2723 2176 { 2724 - struct ice_lag *lag; 2725 - 2726 - lag = pf->lag; 2177 + struct ice_lag *lag = pf->lag; 2727 2178 2728 2179 if (!lag) 2729 2180 return; ··· 2790 2245 ice_lag_move_vf_nodes_sync(prim_lag, &pf->hw); 2791 2246 } 2792 2247 2793 - ice_lag_cfg_cp_fltr(lag, true); 2248 + if (!lag->bond_aa) { 2249 + ice_lag_cfg_lp_fltr(lag, true, true); 2250 + if (lag->pf_rx_rule_id) 2251 + if (ice_lag_cfg_dflt_fltr(lag, true)) 2252 + dev_err(ice_pf_to_dev(pf), "Error adding default VSI rule in rebuild\n"); 2253 + } else { 2254 + ice_lag_cfg_lp_fltr(lag, true, false); 2255 + } 2794 2256 2795 - if (lag->pf_rx_rule_id) 2796 - if (ice_lag_cfg_dflt_fltr(lag, true)) 2797 - dev_err(ice_pf_to_dev(pf), "Error adding default VSI rule in rebuild\n"); 2798 2257 2799 2258 ice_clear_rdma_cap(pf); 2800 2259 lag_rebuild_out:
+20 -1
drivers/net/ethernet/intel/ice/ice_lag.h
··· 14 14 ICE_LAG_UNSET 15 15 }; 16 16 17 - #define ICE_LAG_INVALID_PORT 0xFF 17 + #define ICE_LAG_INVALID_PORT 0xFF 18 + #define ICE_LAGP_IDX 0 19 + #define ICE_LAGS_IDX 1 20 + #define ICE_LAGP_M 0x1 21 + #define ICE_LAGS_M 0x2 18 22 19 23 #define ICE_LAG_RESET_RETRIES 5 20 24 #define ICE_SW_DEFAULT_PROFILE 0 ··· 45 41 u8 active_port; /* lport value for the current active port */ 46 42 u8 bonded:1; /* currently bonded */ 47 43 u8 primary:1; /* this is primary */ 44 + u8 bond_aa:1; /* is this bond active-active */ 45 + u8 need_fltr_cfg:1; /* fltrs for A/A bond still need to be make */ 46 + u8 port_bitmap:2; /* bitmap of active ports */ 47 + u8 bond_lport_pri; /* lport values for primary PF */ 48 + u8 bond_lport_sec; /* lport values for secondary PF */ 49 + 50 + /* q_home keeps track of which interface the q is currently on */ 51 + u8 q_home[ICE_MAX_SRIOV_VFS][ICE_MAX_RSS_QS_PER_VF]; 52 + 53 + /* placeholder VSI for hanging VF queues from on secondary interface */ 54 + struct ice_vsi *sec_vf[ICE_MAX_SRIOV_VFS]; 55 + 48 56 u16 pf_recipe; 49 57 u16 lport_recipe; 58 + u16 act_act_recipe; 50 59 u16 pf_rx_rule_id; 51 60 u16 pf_tx_rule_id; 52 61 u16 cp_rule_idx; 53 62 u16 lport_rule_idx; 63 + u16 act_act_rule_idx; 54 64 u8 role; 55 65 }; 56 66 ··· 83 65 }; 84 66 85 67 void ice_lag_move_new_vf_nodes(struct ice_vf *vf); 68 + void ice_lag_aa_failover(struct ice_lag *lag, u8 dest, struct ice_pf *e_pf); 86 69 int ice_init_lag(struct ice_pf *pf); 87 70 void ice_deinit_lag(struct ice_pf *pf); 88 71 void ice_lag_rebuild(struct ice_pf *pf);
+4 -2
drivers/net/ethernet/intel/ice/ice_type.h
··· 293 293 u8 dcb; 294 294 u8 ieee_1588; 295 295 u8 rdma; 296 - u8 roce_lag; 297 - u8 sriov_lag; 296 + 297 + bool roce_lag; 298 + bool sriov_lag; 299 + bool sriov_aa_lag; 298 300 299 301 bool nvm_update_pending_nvm; 300 302 bool nvm_update_pending_orom;
+3 -2
include/linux/net/intel/libie/adminq.h
··· 192 192 #define LIBIE_AQC_CAPS_TX_SCHED_TOPO_COMP_MODE 0x0085 193 193 #define LIBIE_AQC_CAPS_NAC_TOPOLOGY 0x0087 194 194 #define LIBIE_AQC_CAPS_FW_LAG_SUPPORT 0x0092 195 - #define LIBIE_AQC_BIT_ROCEV2_LAG 0x01 196 - #define LIBIE_AQC_BIT_SRIOV_LAG 0x02 195 + #define LIBIE_AQC_BIT_ROCEV2_LAG BIT(0) 196 + #define LIBIE_AQC_BIT_SRIOV_LAG BIT(1) 197 + #define LIBIE_AQC_BIT_SRIOV_AA_LAG BIT(2) 197 198 #define LIBIE_AQC_CAPS_FLEX10 0x00F1 198 199 #define LIBIE_AQC_CAPS_CEM 0x00F2 199 200