137b6f646SAnirudh Venkataramanan // SPDX-License-Identifier: GPL-2.0 237b6f646SAnirudh Venkataramanan /* Copyright (c) 2019, Intel Corporation. */ 337b6f646SAnirudh Venkataramanan 437b6f646SAnirudh Venkataramanan #include "ice_dcb_lib.h" 5b94b013eSDave Ertman #include "ice_dcb_nl.h" 637b6f646SAnirudh Venkataramanan 737b6f646SAnirudh Venkataramanan /** 87b9ffc76SAnirudh Venkataramanan * ice_dcb_get_ena_tc - return bitmap of enabled TCs 97b9ffc76SAnirudh Venkataramanan * @dcbcfg: DCB config to evaluate for enabled TCs 107b9ffc76SAnirudh Venkataramanan */ 11*0754d65bSKiran Patil static u8 ice_dcb_get_ena_tc(struct ice_dcbx_cfg *dcbcfg) 127b9ffc76SAnirudh Venkataramanan { 137b9ffc76SAnirudh Venkataramanan u8 i, num_tc, ena_tc = 1; 147b9ffc76SAnirudh Venkataramanan 157b9ffc76SAnirudh Venkataramanan num_tc = ice_dcb_get_num_tc(dcbcfg); 167b9ffc76SAnirudh Venkataramanan 177b9ffc76SAnirudh Venkataramanan for (i = 0; i < num_tc; i++) 187b9ffc76SAnirudh Venkataramanan ena_tc |= BIT(i); 197b9ffc76SAnirudh Venkataramanan 207b9ffc76SAnirudh Venkataramanan return ena_tc; 217b9ffc76SAnirudh Venkataramanan } 227b9ffc76SAnirudh Venkataramanan 237b9ffc76SAnirudh Venkataramanan /** 24610ed0e9SAvinash JD * ice_is_pfc_causing_hung_q 25610ed0e9SAvinash JD * @pf: pointer to PF structure 26610ed0e9SAvinash JD * @txqueue: Tx queue which is supposedly hung queue 27610ed0e9SAvinash JD * 28610ed0e9SAvinash JD * find if PFC is causing the hung queue, if yes return true else false 29610ed0e9SAvinash JD */ 30610ed0e9SAvinash JD bool ice_is_pfc_causing_hung_q(struct ice_pf *pf, unsigned int txqueue) 31610ed0e9SAvinash JD { 32610ed0e9SAvinash JD u8 num_tcs = 0, i, tc, up_mapped_tc, up_in_tc = 0; 33610ed0e9SAvinash JD u64 ref_prio_xoff[ICE_MAX_UP]; 34610ed0e9SAvinash JD struct ice_vsi *vsi; 35610ed0e9SAvinash JD u32 up2tc; 36610ed0e9SAvinash JD 37610ed0e9SAvinash JD vsi = ice_get_main_vsi(pf); 38610ed0e9SAvinash JD if (!vsi) 39610ed0e9SAvinash JD return false; 40610ed0e9SAvinash JD 41610ed0e9SAvinash JD ice_for_each_traffic_class(i) 42610ed0e9SAvinash JD if (vsi->tc_cfg.ena_tc & BIT(i)) 43610ed0e9SAvinash JD num_tcs++; 44610ed0e9SAvinash JD 45610ed0e9SAvinash JD /* first find out the TC to which the hung queue belongs to */ 46610ed0e9SAvinash JD for (tc = 0; tc < num_tcs - 1; tc++) 47610ed0e9SAvinash JD if (ice_find_q_in_range(vsi->tc_cfg.tc_info[tc].qoffset, 48610ed0e9SAvinash JD vsi->tc_cfg.tc_info[tc + 1].qoffset, 49610ed0e9SAvinash JD txqueue)) 50610ed0e9SAvinash JD break; 51610ed0e9SAvinash JD 52610ed0e9SAvinash JD /* Build a bit map of all UPs associated to the suspect hung queue TC, 53610ed0e9SAvinash JD * so that we check for its counter increment. 54610ed0e9SAvinash JD */ 55610ed0e9SAvinash JD up2tc = rd32(&pf->hw, PRTDCB_TUP2TC); 56610ed0e9SAvinash JD for (i = 0; i < ICE_MAX_UP; i++) { 57610ed0e9SAvinash JD up_mapped_tc = (up2tc >> (i * 3)) & 0x7; 58610ed0e9SAvinash JD if (up_mapped_tc == tc) 59610ed0e9SAvinash JD up_in_tc |= BIT(i); 60610ed0e9SAvinash JD } 61610ed0e9SAvinash JD 62610ed0e9SAvinash JD /* Now that we figured out that hung queue is PFC enabled, still the 63610ed0e9SAvinash JD * Tx timeout can be legitimate. So to make sure Tx timeout is 64610ed0e9SAvinash JD * absolutely caused by PFC storm, check if the counters are 65610ed0e9SAvinash JD * incrementing. 66610ed0e9SAvinash JD */ 67610ed0e9SAvinash JD for (i = 0; i < ICE_MAX_UP; i++) 68610ed0e9SAvinash JD if (up_in_tc & BIT(i)) 69610ed0e9SAvinash JD ref_prio_xoff[i] = pf->stats.priority_xoff_rx[i]; 70610ed0e9SAvinash JD 71610ed0e9SAvinash JD ice_update_dcb_stats(pf); 72610ed0e9SAvinash JD 73610ed0e9SAvinash JD for (i = 0; i < ICE_MAX_UP; i++) 74610ed0e9SAvinash JD if (up_in_tc & BIT(i)) 75610ed0e9SAvinash JD if (pf->stats.priority_xoff_rx[i] > ref_prio_xoff[i]) 76610ed0e9SAvinash JD return true; 77610ed0e9SAvinash JD 78610ed0e9SAvinash JD return false; 79610ed0e9SAvinash JD } 80610ed0e9SAvinash JD 81610ed0e9SAvinash JD /** 8227d9be98SAvinash Dayanand * ice_dcb_get_mode - gets the DCB mode 8327d9be98SAvinash Dayanand * @port_info: pointer to port info structure 8427d9be98SAvinash Dayanand * @host: if set it's HOST if not it's MANAGED 8527d9be98SAvinash Dayanand */ 8627d9be98SAvinash Dayanand static u8 ice_dcb_get_mode(struct ice_port_info *port_info, bool host) 8727d9be98SAvinash Dayanand { 8827d9be98SAvinash Dayanand u8 mode; 8927d9be98SAvinash Dayanand 9027d9be98SAvinash Dayanand if (host) 9127d9be98SAvinash Dayanand mode = DCB_CAP_DCBX_HOST; 9227d9be98SAvinash Dayanand else 9327d9be98SAvinash Dayanand mode = DCB_CAP_DCBX_LLD_MANAGED; 9427d9be98SAvinash Dayanand 95fc2d1165SChinh T Cao if (port_info->qos_cfg.local_dcbx_cfg.dcbx_mode & ICE_DCBX_MODE_CEE) 96f3beaf24SJeff Kirsher return mode | DCB_CAP_DCBX_VER_CEE; 9727d9be98SAvinash Dayanand else 98f3beaf24SJeff Kirsher return mode | DCB_CAP_DCBX_VER_IEEE; 9927d9be98SAvinash Dayanand } 10027d9be98SAvinash Dayanand 10127d9be98SAvinash Dayanand /** 1027b9ffc76SAnirudh Venkataramanan * ice_dcb_get_num_tc - Get the number of TCs from DCBX config 1037b9ffc76SAnirudh Venkataramanan * @dcbcfg: config to retrieve number of TCs from 1047b9ffc76SAnirudh Venkataramanan */ 1057b9ffc76SAnirudh Venkataramanan u8 ice_dcb_get_num_tc(struct ice_dcbx_cfg *dcbcfg) 1067b9ffc76SAnirudh Venkataramanan { 1077b9ffc76SAnirudh Venkataramanan bool tc_unused = false; 1087b9ffc76SAnirudh Venkataramanan u8 num_tc = 0; 1097b9ffc76SAnirudh Venkataramanan u8 ret = 0; 1107b9ffc76SAnirudh Venkataramanan int i; 1117b9ffc76SAnirudh Venkataramanan 1127b9ffc76SAnirudh Venkataramanan /* Scan the ETS Config Priority Table to find traffic classes 1137b9ffc76SAnirudh Venkataramanan * enabled and create a bitmask of enabled TCs 1147b9ffc76SAnirudh Venkataramanan */ 1157b9ffc76SAnirudh Venkataramanan for (i = 0; i < CEE_DCBX_MAX_PRIO; i++) 1167b9ffc76SAnirudh Venkataramanan num_tc |= BIT(dcbcfg->etscfg.prio_table[i]); 1177b9ffc76SAnirudh Venkataramanan 1187b9ffc76SAnirudh Venkataramanan /* Scan bitmask for contiguous TCs starting with TC0 */ 1197b9ffc76SAnirudh Venkataramanan for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { 1207b9ffc76SAnirudh Venkataramanan if (num_tc & BIT(i)) { 1217b9ffc76SAnirudh Venkataramanan if (!tc_unused) { 1227b9ffc76SAnirudh Venkataramanan ret++; 1237b9ffc76SAnirudh Venkataramanan } else { 1247b9ffc76SAnirudh Venkataramanan pr_err("Non-contiguous TCs - Disabling DCB\n"); 1257b9ffc76SAnirudh Venkataramanan return 1; 1267b9ffc76SAnirudh Venkataramanan } 1277b9ffc76SAnirudh Venkataramanan } else { 1287b9ffc76SAnirudh Venkataramanan tc_unused = true; 1297b9ffc76SAnirudh Venkataramanan } 1307b9ffc76SAnirudh Venkataramanan } 1317b9ffc76SAnirudh Venkataramanan 1327b9ffc76SAnirudh Venkataramanan /* There is always at least 1 TC */ 1337b9ffc76SAnirudh Venkataramanan if (!ret) 1347b9ffc76SAnirudh Venkataramanan ret = 1; 1357b9ffc76SAnirudh Venkataramanan 1367b9ffc76SAnirudh Venkataramanan return ret; 1377b9ffc76SAnirudh Venkataramanan } 1387b9ffc76SAnirudh Venkataramanan 1397b9ffc76SAnirudh Venkataramanan /** 140*0754d65bSKiran Patil * ice_get_first_droptc - returns number of first droptc 141*0754d65bSKiran Patil * @vsi: used to find the first droptc 142*0754d65bSKiran Patil * 143*0754d65bSKiran Patil * This function returns the value of first_droptc. 144*0754d65bSKiran Patil * When DCB is enabled, first droptc information is derived from enabled_tc 145*0754d65bSKiran Patil * and PFC enabled bits. otherwise this function returns 0 as there is one 146*0754d65bSKiran Patil * TC without DCB (tc0) 147*0754d65bSKiran Patil */ 148*0754d65bSKiran Patil static u8 ice_get_first_droptc(struct ice_vsi *vsi) 149*0754d65bSKiran Patil { 150*0754d65bSKiran Patil struct ice_dcbx_cfg *cfg = &vsi->port_info->qos_cfg.local_dcbx_cfg; 151*0754d65bSKiran Patil struct device *dev = ice_pf_to_dev(vsi->back); 152*0754d65bSKiran Patil u8 num_tc, ena_tc_map, pfc_ena_map; 153*0754d65bSKiran Patil u8 i; 154*0754d65bSKiran Patil 155*0754d65bSKiran Patil num_tc = ice_dcb_get_num_tc(cfg); 156*0754d65bSKiran Patil 157*0754d65bSKiran Patil /* get bitmap of enabled TCs */ 158*0754d65bSKiran Patil ena_tc_map = ice_dcb_get_ena_tc(cfg); 159*0754d65bSKiran Patil 160*0754d65bSKiran Patil /* get bitmap of PFC enabled TCs */ 161*0754d65bSKiran Patil pfc_ena_map = cfg->pfc.pfcena; 162*0754d65bSKiran Patil 163*0754d65bSKiran Patil /* get first TC that is not PFC enabled */ 164*0754d65bSKiran Patil for (i = 0; i < num_tc; i++) { 165*0754d65bSKiran Patil if ((ena_tc_map & BIT(i)) && (!(pfc_ena_map & BIT(i)))) { 166*0754d65bSKiran Patil dev_dbg(dev, "first drop tc = %d\n", i); 167*0754d65bSKiran Patil return i; 168*0754d65bSKiran Patil } 169*0754d65bSKiran Patil } 170*0754d65bSKiran Patil 171*0754d65bSKiran Patil dev_dbg(dev, "first drop tc = 0\n"); 172*0754d65bSKiran Patil return 0; 173*0754d65bSKiran Patil } 174*0754d65bSKiran Patil 175*0754d65bSKiran Patil /** 176*0754d65bSKiran Patil * ice_vsi_set_dcb_tc_cfg - Set VSI's TC based on DCB configuration 177*0754d65bSKiran Patil * @vsi: pointer to the VSI instance 178*0754d65bSKiran Patil */ 179*0754d65bSKiran Patil void ice_vsi_set_dcb_tc_cfg(struct ice_vsi *vsi) 180*0754d65bSKiran Patil { 181*0754d65bSKiran Patil struct ice_dcbx_cfg *cfg = &vsi->port_info->qos_cfg.local_dcbx_cfg; 182*0754d65bSKiran Patil 183*0754d65bSKiran Patil switch (vsi->type) { 184*0754d65bSKiran Patil case ICE_VSI_PF: 185*0754d65bSKiran Patil vsi->tc_cfg.ena_tc = ice_dcb_get_ena_tc(cfg); 186*0754d65bSKiran Patil vsi->tc_cfg.numtc = ice_dcb_get_num_tc(cfg); 187*0754d65bSKiran Patil break; 188*0754d65bSKiran Patil case ICE_VSI_CHNL: 189*0754d65bSKiran Patil vsi->tc_cfg.ena_tc = BIT(ice_get_first_droptc(vsi)); 190*0754d65bSKiran Patil vsi->tc_cfg.numtc = 1; 191*0754d65bSKiran Patil break; 192*0754d65bSKiran Patil case ICE_VSI_CTRL: 193*0754d65bSKiran Patil case ICE_VSI_LB: 194*0754d65bSKiran Patil default: 195*0754d65bSKiran Patil vsi->tc_cfg.ena_tc = ICE_DFLT_TRAFFIC_CLASS; 196*0754d65bSKiran Patil vsi->tc_cfg.numtc = 1; 197*0754d65bSKiran Patil } 198*0754d65bSKiran Patil } 199*0754d65bSKiran Patil 200*0754d65bSKiran Patil /** 2011ddef455SUsha Ketineni * ice_dcb_get_tc - Get the TC associated with the queue 2021ddef455SUsha Ketineni * @vsi: ptr to the VSI 2031ddef455SUsha Ketineni * @queue_index: queue number associated with VSI 2041ddef455SUsha Ketineni */ 2051ddef455SUsha Ketineni u8 ice_dcb_get_tc(struct ice_vsi *vsi, int queue_index) 2061ddef455SUsha Ketineni { 2071ddef455SUsha Ketineni return vsi->tx_rings[queue_index]->dcb_tc; 2081ddef455SUsha Ketineni } 2091ddef455SUsha Ketineni 2101ddef455SUsha Ketineni /** 211a629cf0aSAnirudh Venkataramanan * ice_vsi_cfg_dcb_rings - Update rings to reflect DCB TC 212a629cf0aSAnirudh Venkataramanan * @vsi: VSI owner of rings being updated 213a629cf0aSAnirudh Venkataramanan */ 214a629cf0aSAnirudh Venkataramanan void ice_vsi_cfg_dcb_rings(struct ice_vsi *vsi) 215a629cf0aSAnirudh Venkataramanan { 216e72bba21SMaciej Fijalkowski struct ice_tx_ring *tx_ring; 217e72bba21SMaciej Fijalkowski struct ice_rx_ring *rx_ring; 218a629cf0aSAnirudh Venkataramanan u16 qoffset, qcount; 219a629cf0aSAnirudh Venkataramanan int i, n; 220a629cf0aSAnirudh Venkataramanan 221a629cf0aSAnirudh Venkataramanan if (!test_bit(ICE_FLAG_DCB_ENA, vsi->back->flags)) { 222a629cf0aSAnirudh Venkataramanan /* Reset the TC information */ 2232faf63b6SMaciej Fijalkowski ice_for_each_txq(vsi, i) { 224a629cf0aSAnirudh Venkataramanan tx_ring = vsi->tx_rings[i]; 225a629cf0aSAnirudh Venkataramanan tx_ring->dcb_tc = 0; 226a629cf0aSAnirudh Venkataramanan } 2272faf63b6SMaciej Fijalkowski ice_for_each_rxq(vsi, i) { 228a629cf0aSAnirudh Venkataramanan rx_ring = vsi->rx_rings[i]; 229a629cf0aSAnirudh Venkataramanan rx_ring->dcb_tc = 0; 230a629cf0aSAnirudh Venkataramanan } 231a629cf0aSAnirudh Venkataramanan return; 232a629cf0aSAnirudh Venkataramanan } 233a629cf0aSAnirudh Venkataramanan 234a629cf0aSAnirudh Venkataramanan ice_for_each_traffic_class(n) { 235a629cf0aSAnirudh Venkataramanan if (!(vsi->tc_cfg.ena_tc & BIT(n))) 236a629cf0aSAnirudh Venkataramanan break; 237a629cf0aSAnirudh Venkataramanan 238a629cf0aSAnirudh Venkataramanan qoffset = vsi->tc_cfg.tc_info[n].qoffset; 239a629cf0aSAnirudh Venkataramanan qcount = vsi->tc_cfg.tc_info[n].qcount_tx; 240*0754d65bSKiran Patil for (i = qoffset; i < (qoffset + qcount); i++) 241*0754d65bSKiran Patil vsi->tx_rings[i]->dcb_tc = n; 242*0754d65bSKiran Patil 243*0754d65bSKiran Patil qcount = vsi->tc_cfg.tc_info[n].qcount_rx; 244*0754d65bSKiran Patil for (i = qoffset; i < (qoffset + qcount); i++) 245*0754d65bSKiran Patil vsi->rx_rings[i]->dcb_tc = n; 246*0754d65bSKiran Patil } 247*0754d65bSKiran Patil /* applicable only if "all_enatc" is set, which will be set from 248*0754d65bSKiran Patil * setup_tc method as part of configuring channels 249*0754d65bSKiran Patil */ 250*0754d65bSKiran Patil if (vsi->all_enatc) { 251*0754d65bSKiran Patil u8 first_droptc = ice_get_first_droptc(vsi); 252*0754d65bSKiran Patil 253*0754d65bSKiran Patil /* When DCB is configured, TC for ADQ queues (which are really 254*0754d65bSKiran Patil * PF queues) should be the first drop TC of the main VSI 255*0754d65bSKiran Patil */ 256*0754d65bSKiran Patil ice_for_each_chnl_tc(n) { 257*0754d65bSKiran Patil if (!(vsi->all_enatc & BIT(n))) 258*0754d65bSKiran Patil break; 259*0754d65bSKiran Patil 260*0754d65bSKiran Patil qoffset = vsi->mqprio_qopt.qopt.offset[n]; 261*0754d65bSKiran Patil qcount = vsi->mqprio_qopt.qopt.count[n]; 262a629cf0aSAnirudh Venkataramanan for (i = qoffset; i < (qoffset + qcount); i++) { 263*0754d65bSKiran Patil vsi->tx_rings[i]->dcb_tc = first_droptc; 264*0754d65bSKiran Patil vsi->rx_rings[i]->dcb_tc = first_droptc; 265*0754d65bSKiran Patil } 266*0754d65bSKiran Patil } 267*0754d65bSKiran Patil } 268*0754d65bSKiran Patil } 269*0754d65bSKiran Patil 270*0754d65bSKiran Patil /** 271*0754d65bSKiran Patil * ice_dcb_ena_dis_vsi - disable certain VSIs for DCB config/reconfig 272*0754d65bSKiran Patil * @pf: pointer to the PF instance 273*0754d65bSKiran Patil * @ena: true to enable VSIs, false to disable 274*0754d65bSKiran Patil * @locked: true if caller holds RTNL lock, false otherwise 275*0754d65bSKiran Patil * 276*0754d65bSKiran Patil * Before a new DCB configuration can be applied, VSIs of type PF, SWITCHDEV 277*0754d65bSKiran Patil * and CHNL need to be brought down. Following completion of DCB configuration 278*0754d65bSKiran Patil * the VSIs that were downed need to be brought up again. This helper function 279*0754d65bSKiran Patil * does both. 280*0754d65bSKiran Patil */ 281*0754d65bSKiran Patil static void ice_dcb_ena_dis_vsi(struct ice_pf *pf, bool ena, bool locked) 282*0754d65bSKiran Patil { 283*0754d65bSKiran Patil int i; 284*0754d65bSKiran Patil 285*0754d65bSKiran Patil ice_for_each_vsi(pf, i) { 286*0754d65bSKiran Patil struct ice_vsi *vsi = pf->vsi[i]; 287*0754d65bSKiran Patil 288*0754d65bSKiran Patil if (!vsi) 289*0754d65bSKiran Patil continue; 290*0754d65bSKiran Patil 291*0754d65bSKiran Patil switch (vsi->type) { 292*0754d65bSKiran Patil case ICE_VSI_CHNL: 293*0754d65bSKiran Patil case ICE_VSI_SWITCHDEV_CTRL: 294*0754d65bSKiran Patil case ICE_VSI_PF: 295*0754d65bSKiran Patil if (ena) 296*0754d65bSKiran Patil ice_ena_vsi(vsi, locked); 297*0754d65bSKiran Patil else 298*0754d65bSKiran Patil ice_dis_vsi(vsi, locked); 299*0754d65bSKiran Patil break; 300*0754d65bSKiran Patil default: 301*0754d65bSKiran Patil continue; 302a629cf0aSAnirudh Venkataramanan } 303a629cf0aSAnirudh Venkataramanan } 304a629cf0aSAnirudh Venkataramanan } 305a629cf0aSAnirudh Venkataramanan 306a629cf0aSAnirudh Venkataramanan /** 307a29a912dSAvinash Dayanand * ice_dcb_bwchk - check if ETS bandwidth input parameters are correct 308a29a912dSAvinash Dayanand * @pf: pointer to the PF struct 309a29a912dSAvinash Dayanand * @dcbcfg: pointer to DCB config structure 310a29a912dSAvinash Dayanand */ 311a29a912dSAvinash Dayanand int ice_dcb_bwchk(struct ice_pf *pf, struct ice_dcbx_cfg *dcbcfg) 312a29a912dSAvinash Dayanand { 313a29a912dSAvinash Dayanand struct ice_dcb_ets_cfg *etscfg = &dcbcfg->etscfg; 314a29a912dSAvinash Dayanand u8 num_tc, total_bw = 0; 315a29a912dSAvinash Dayanand int i; 316a29a912dSAvinash Dayanand 317a29a912dSAvinash Dayanand /* returns number of contigous TCs and 1 TC for non-contigous TCs, 318a29a912dSAvinash Dayanand * since at least 1 TC has to be configured 319a29a912dSAvinash Dayanand */ 320a29a912dSAvinash Dayanand num_tc = ice_dcb_get_num_tc(dcbcfg); 321a29a912dSAvinash Dayanand 322a29a912dSAvinash Dayanand /* no bandwidth checks required if there's only one TC, so assign 323a29a912dSAvinash Dayanand * all bandwidth to TC0 and return 324a29a912dSAvinash Dayanand */ 325a29a912dSAvinash Dayanand if (num_tc == 1) { 326a29a912dSAvinash Dayanand etscfg->tcbwtable[0] = ICE_TC_MAX_BW; 327a29a912dSAvinash Dayanand return 0; 328a29a912dSAvinash Dayanand } 329a29a912dSAvinash Dayanand 330a29a912dSAvinash Dayanand for (i = 0; i < num_tc; i++) 331a29a912dSAvinash Dayanand total_bw += etscfg->tcbwtable[i]; 332a29a912dSAvinash Dayanand 333a29a912dSAvinash Dayanand if (!total_bw) { 334a29a912dSAvinash Dayanand etscfg->tcbwtable[0] = ICE_TC_MAX_BW; 335a29a912dSAvinash Dayanand } else if (total_bw != ICE_TC_MAX_BW) { 336a29a912dSAvinash Dayanand dev_err(ice_pf_to_dev(pf), "Invalid config, total bandwidth must equal 100\n"); 337a29a912dSAvinash Dayanand return -EINVAL; 338a29a912dSAvinash Dayanand } 339a29a912dSAvinash Dayanand 340a29a912dSAvinash Dayanand return 0; 341a29a912dSAvinash Dayanand } 342a29a912dSAvinash Dayanand 343a29a912dSAvinash Dayanand /** 3447b9ffc76SAnirudh Venkataramanan * ice_pf_dcb_cfg - Apply new DCB configuration 3457b9ffc76SAnirudh Venkataramanan * @pf: pointer to the PF struct 3467b9ffc76SAnirudh Venkataramanan * @new_cfg: DCBX config to apply 347e223eaecSDave Ertman * @locked: is the RTNL held 3487b9ffc76SAnirudh Venkataramanan */ 349e223eaecSDave Ertman int ice_pf_dcb_cfg(struct ice_pf *pf, struct ice_dcbx_cfg *new_cfg, bool locked) 3507b9ffc76SAnirudh Venkataramanan { 3517b9ffc76SAnirudh Venkataramanan struct ice_aqc_port_ets_elem buf = { 0 }; 352b94b013eSDave Ertman struct ice_dcbx_cfg *old_cfg, *curr_cfg; 3534015d11eSBrett Creeley struct device *dev = ice_pf_to_dev(pf); 354b94b013eSDave Ertman int ret = ICE_DCB_NO_HW_CHG; 355348048e7SDave Ertman struct iidc_event *event; 3569d614b64SAnirudh Venkataramanan struct ice_vsi *pf_vsi; 3577b9ffc76SAnirudh Venkataramanan 358fc2d1165SChinh T Cao curr_cfg = &pf->hw.port_info->qos_cfg.local_dcbx_cfg; 3597b9ffc76SAnirudh Venkataramanan 360b94b013eSDave Ertman /* FW does not care if change happened */ 361fc2d1165SChinh T Cao if (!pf->hw.port_info->qos_cfg.is_sw_lldp) 362b94b013eSDave Ertman ret = ICE_DCB_HW_CHG_RST; 363b94b013eSDave Ertman 3647b9ffc76SAnirudh Venkataramanan /* Enable DCB tagging only when more than one TC */ 3657b9ffc76SAnirudh Venkataramanan if (ice_dcb_get_num_tc(new_cfg) > 1) { 3664015d11eSBrett Creeley dev_dbg(dev, "DCB tagging enabled (num TC > 1)\n"); 3677b9ffc76SAnirudh Venkataramanan set_bit(ICE_FLAG_DCB_ENA, pf->flags); 3687b9ffc76SAnirudh Venkataramanan } else { 3694015d11eSBrett Creeley dev_dbg(dev, "DCB tagging disabled (num TC = 1)\n"); 3707b9ffc76SAnirudh Venkataramanan clear_bit(ICE_FLAG_DCB_ENA, pf->flags); 3717b9ffc76SAnirudh Venkataramanan } 3727b9ffc76SAnirudh Venkataramanan 3737b9ffc76SAnirudh Venkataramanan if (!memcmp(new_cfg, curr_cfg, sizeof(*new_cfg))) { 3744015d11eSBrett Creeley dev_dbg(dev, "No change in DCB config required\n"); 3757b9ffc76SAnirudh Venkataramanan return ret; 3767b9ffc76SAnirudh Venkataramanan } 3777b9ffc76SAnirudh Venkataramanan 378a29a912dSAvinash Dayanand if (ice_dcb_bwchk(pf, new_cfg)) 379a29a912dSAvinash Dayanand return -EINVAL; 380a29a912dSAvinash Dayanand 3817b9ffc76SAnirudh Venkataramanan /* Store old config in case FW config fails */ 3829d614b64SAnirudh Venkataramanan old_cfg = kmemdup(curr_cfg, sizeof(*old_cfg), GFP_KERNEL); 3839d614b64SAnirudh Venkataramanan if (!old_cfg) 3849d614b64SAnirudh Venkataramanan return -ENOMEM; 3859d614b64SAnirudh Venkataramanan 3864015d11eSBrett Creeley dev_info(dev, "Commit DCB Configuration to the hardware\n"); 3879d614b64SAnirudh Venkataramanan pf_vsi = ice_get_main_vsi(pf); 3889d614b64SAnirudh Venkataramanan if (!pf_vsi) { 3894015d11eSBrett Creeley dev_dbg(dev, "PF VSI doesn't exist\n"); 3909d614b64SAnirudh Venkataramanan ret = -EINVAL; 3919d614b64SAnirudh Venkataramanan goto free_cfg; 3929d614b64SAnirudh Venkataramanan } 3937b9ffc76SAnirudh Venkataramanan 394348048e7SDave Ertman /* Notify AUX drivers about impending change to TCs */ 395348048e7SDave Ertman event = kzalloc(sizeof(*event), GFP_KERNEL); 396b81c191cSChristophe JAILLET if (!event) { 397b81c191cSChristophe JAILLET ret = -ENOMEM; 398b81c191cSChristophe JAILLET goto free_cfg; 399b81c191cSChristophe JAILLET } 400348048e7SDave Ertman 401348048e7SDave Ertman set_bit(IIDC_EVENT_BEFORE_TC_CHANGE, event->type); 402348048e7SDave Ertman ice_send_event_to_aux(pf, event); 403348048e7SDave Ertman kfree(event); 404348048e7SDave Ertman 4057b9ffc76SAnirudh Venkataramanan /* avoid race conditions by holding the lock while disabling and 4067b9ffc76SAnirudh Venkataramanan * re-enabling the VSI 4077b9ffc76SAnirudh Venkataramanan */ 408e223eaecSDave Ertman if (!locked) 4097b9ffc76SAnirudh Venkataramanan rtnl_lock(); 410*0754d65bSKiran Patil 411*0754d65bSKiran Patil /* disable VSIs affected by DCB changes */ 412*0754d65bSKiran Patil ice_dcb_ena_dis_vsi(pf, false, true); 4137b9ffc76SAnirudh Venkataramanan 4147b9ffc76SAnirudh Venkataramanan memcpy(curr_cfg, new_cfg, sizeof(*curr_cfg)); 4157b9ffc76SAnirudh Venkataramanan memcpy(&curr_cfg->etsrec, &curr_cfg->etscfg, sizeof(curr_cfg->etsrec)); 416b94b013eSDave Ertman memcpy(&new_cfg->etsrec, &curr_cfg->etscfg, sizeof(curr_cfg->etsrec)); 4177b9ffc76SAnirudh Venkataramanan 4187b9ffc76SAnirudh Venkataramanan /* Only send new config to HW if we are in SW LLDP mode. Otherwise, 4197b9ffc76SAnirudh Venkataramanan * the new config came from the HW in the first place. 4207b9ffc76SAnirudh Venkataramanan */ 421fc2d1165SChinh T Cao if (pf->hw.port_info->qos_cfg.is_sw_lldp) { 4227b9ffc76SAnirudh Venkataramanan ret = ice_set_dcb_cfg(pf->hw.port_info); 4237b9ffc76SAnirudh Venkataramanan if (ret) { 4244015d11eSBrett Creeley dev_err(dev, "Set DCB Config failed\n"); 4257b9ffc76SAnirudh Venkataramanan /* Restore previous settings to local config */ 4267b9ffc76SAnirudh Venkataramanan memcpy(curr_cfg, old_cfg, sizeof(*curr_cfg)); 4277b9ffc76SAnirudh Venkataramanan goto out; 4287b9ffc76SAnirudh Venkataramanan } 4297b9ffc76SAnirudh Venkataramanan } 4307b9ffc76SAnirudh Venkataramanan 4317b9ffc76SAnirudh Venkataramanan ret = ice_query_port_ets(pf->hw.port_info, &buf, sizeof(buf), NULL); 4327b9ffc76SAnirudh Venkataramanan if (ret) { 4334015d11eSBrett Creeley dev_err(dev, "Query Port ETS failed\n"); 4347b9ffc76SAnirudh Venkataramanan goto out; 4357b9ffc76SAnirudh Venkataramanan } 4367b9ffc76SAnirudh Venkataramanan 4377b9ffc76SAnirudh Venkataramanan ice_pf_dcb_recfg(pf); 4387b9ffc76SAnirudh Venkataramanan 4397b9ffc76SAnirudh Venkataramanan out: 440*0754d65bSKiran Patil /* enable previously downed VSIs */ 441*0754d65bSKiran Patil ice_dcb_ena_dis_vsi(pf, true, true); 442e223eaecSDave Ertman if (!locked) 4437b9ffc76SAnirudh Venkataramanan rtnl_unlock(); 4449d614b64SAnirudh Venkataramanan free_cfg: 4459d614b64SAnirudh Venkataramanan kfree(old_cfg); 4467b9ffc76SAnirudh Venkataramanan return ret; 4477b9ffc76SAnirudh Venkataramanan } 4487b9ffc76SAnirudh Venkataramanan 4497b9ffc76SAnirudh Venkataramanan /** 4507829570eSUsha Ketineni * ice_cfg_etsrec_defaults - Set default ETS recommended DCB config 4517829570eSUsha Ketineni * @pi: port information structure 4527829570eSUsha Ketineni */ 4537829570eSUsha Ketineni static void ice_cfg_etsrec_defaults(struct ice_port_info *pi) 4547829570eSUsha Ketineni { 455fc2d1165SChinh T Cao struct ice_dcbx_cfg *dcbcfg = &pi->qos_cfg.local_dcbx_cfg; 4567829570eSUsha Ketineni u8 i; 4577829570eSUsha Ketineni 4587829570eSUsha Ketineni /* Ensure ETS recommended DCB configuration is not already set */ 4597829570eSUsha Ketineni if (dcbcfg->etsrec.maxtcs) 4607829570eSUsha Ketineni return; 4617829570eSUsha Ketineni 4627829570eSUsha Ketineni /* In CEE mode, set the default to 1 TC */ 4637829570eSUsha Ketineni dcbcfg->etsrec.maxtcs = 1; 4647829570eSUsha Ketineni for (i = 0; i < ICE_MAX_TRAFFIC_CLASS; i++) { 4657829570eSUsha Ketineni dcbcfg->etsrec.tcbwtable[i] = i ? 0 : 100; 4667829570eSUsha Ketineni dcbcfg->etsrec.tsatable[i] = i ? ICE_IEEE_TSA_STRICT : 4677829570eSUsha Ketineni ICE_IEEE_TSA_ETS; 4687829570eSUsha Ketineni } 4697829570eSUsha Ketineni } 4707829570eSUsha Ketineni 4717829570eSUsha Ketineni /** 4727829570eSUsha Ketineni * ice_dcb_need_recfg - Check if DCB needs reconfig 4737829570eSUsha Ketineni * @pf: board private structure 4747829570eSUsha Ketineni * @old_cfg: current DCB config 4757829570eSUsha Ketineni * @new_cfg: new DCB config 4767829570eSUsha Ketineni */ 4777829570eSUsha Ketineni static bool 4787829570eSUsha Ketineni ice_dcb_need_recfg(struct ice_pf *pf, struct ice_dcbx_cfg *old_cfg, 4797829570eSUsha Ketineni struct ice_dcbx_cfg *new_cfg) 4807829570eSUsha Ketineni { 4814015d11eSBrett Creeley struct device *dev = ice_pf_to_dev(pf); 4827829570eSUsha Ketineni bool need_reconfig = false; 4837829570eSUsha Ketineni 4847829570eSUsha Ketineni /* Check if ETS configuration has changed */ 4857829570eSUsha Ketineni if (memcmp(&new_cfg->etscfg, &old_cfg->etscfg, 4867829570eSUsha Ketineni sizeof(new_cfg->etscfg))) { 4877829570eSUsha Ketineni /* If Priority Table has changed reconfig is needed */ 4887829570eSUsha Ketineni if (memcmp(&new_cfg->etscfg.prio_table, 4897829570eSUsha Ketineni &old_cfg->etscfg.prio_table, 4907829570eSUsha Ketineni sizeof(new_cfg->etscfg.prio_table))) { 4917829570eSUsha Ketineni need_reconfig = true; 4924015d11eSBrett Creeley dev_dbg(dev, "ETS UP2TC changed.\n"); 4937829570eSUsha Ketineni } 4947829570eSUsha Ketineni 4957829570eSUsha Ketineni if (memcmp(&new_cfg->etscfg.tcbwtable, 4967829570eSUsha Ketineni &old_cfg->etscfg.tcbwtable, 4977829570eSUsha Ketineni sizeof(new_cfg->etscfg.tcbwtable))) 4984015d11eSBrett Creeley dev_dbg(dev, "ETS TC BW Table changed.\n"); 4997829570eSUsha Ketineni 5007829570eSUsha Ketineni if (memcmp(&new_cfg->etscfg.tsatable, 5017829570eSUsha Ketineni &old_cfg->etscfg.tsatable, 5027829570eSUsha Ketineni sizeof(new_cfg->etscfg.tsatable))) 5034015d11eSBrett Creeley dev_dbg(dev, "ETS TSA Table changed.\n"); 5047829570eSUsha Ketineni } 5057829570eSUsha Ketineni 5067829570eSUsha Ketineni /* Check if PFC configuration has changed */ 5077829570eSUsha Ketineni if (memcmp(&new_cfg->pfc, &old_cfg->pfc, sizeof(new_cfg->pfc))) { 5087829570eSUsha Ketineni need_reconfig = true; 5094015d11eSBrett Creeley dev_dbg(dev, "PFC config change detected.\n"); 5107829570eSUsha Ketineni } 5117829570eSUsha Ketineni 5127829570eSUsha Ketineni /* Check if APP Table has changed */ 5137829570eSUsha Ketineni if (memcmp(&new_cfg->app, &old_cfg->app, sizeof(new_cfg->app))) { 5147829570eSUsha Ketineni need_reconfig = true; 5154015d11eSBrett Creeley dev_dbg(dev, "APP Table change detected.\n"); 5167829570eSUsha Ketineni } 5177829570eSUsha Ketineni 5184015d11eSBrett Creeley dev_dbg(dev, "dcb need_reconfig=%d\n", need_reconfig); 5197829570eSUsha Ketineni return need_reconfig; 5207829570eSUsha Ketineni } 5217829570eSUsha Ketineni 5227829570eSUsha Ketineni /** 523b832c2f6SAnirudh Venkataramanan * ice_dcb_rebuild - rebuild DCB post reset 524b832c2f6SAnirudh Venkataramanan * @pf: physical function instance 525b832c2f6SAnirudh Venkataramanan */ 526b832c2f6SAnirudh Venkataramanan void ice_dcb_rebuild(struct ice_pf *pf) 527b832c2f6SAnirudh Venkataramanan { 528b832c2f6SAnirudh Venkataramanan struct ice_aqc_port_ets_elem buf = { 0 }; 5294015d11eSBrett Creeley struct device *dev = ice_pf_to_dev(pf); 530242b5e06SDave Ertman struct ice_dcbx_cfg *err_cfg; 531b832c2f6SAnirudh Venkataramanan enum ice_status ret; 532b832c2f6SAnirudh Venkataramanan 533b832c2f6SAnirudh Venkataramanan ret = ice_query_port_ets(pf->hw.port_info, &buf, sizeof(buf), NULL); 534b832c2f6SAnirudh Venkataramanan if (ret) { 5354015d11eSBrett Creeley dev_err(dev, "Query Port ETS failed\n"); 536b832c2f6SAnirudh Venkataramanan goto dcb_error; 537b832c2f6SAnirudh Venkataramanan } 538b832c2f6SAnirudh Venkataramanan 539242b5e06SDave Ertman mutex_lock(&pf->tc_mutex); 5407829570eSUsha Ketineni 541fc2d1165SChinh T Cao if (!pf->hw.port_info->qos_cfg.is_sw_lldp) 5427829570eSUsha Ketineni ice_cfg_etsrec_defaults(pf->hw.port_info); 543242b5e06SDave Ertman 544b832c2f6SAnirudh Venkataramanan ret = ice_set_dcb_cfg(pf->hw.port_info); 545b832c2f6SAnirudh Venkataramanan if (ret) { 546242b5e06SDave Ertman dev_err(dev, "Failed to set DCB config in rebuild\n"); 547b832c2f6SAnirudh Venkataramanan goto dcb_error; 548b832c2f6SAnirudh Venkataramanan } 549b832c2f6SAnirudh Venkataramanan 550fc2d1165SChinh T Cao if (!pf->hw.port_info->qos_cfg.is_sw_lldp) { 551242b5e06SDave Ertman ret = ice_cfg_lldp_mib_change(&pf->hw, true); 552fc2d1165SChinh T Cao if (ret && !pf->hw.port_info->qos_cfg.is_sw_lldp) { 553242b5e06SDave Ertman dev_err(dev, "Failed to register for MIB changes\n"); 554b832c2f6SAnirudh Venkataramanan goto dcb_error; 555b832c2f6SAnirudh Venkataramanan } 556b832c2f6SAnirudh Venkataramanan } 557242b5e06SDave Ertman 5580ce6c34aSDave Ertman dev_info(dev, "DCB info restored\n"); 559b832c2f6SAnirudh Venkataramanan ret = ice_query_port_ets(pf->hw.port_info, &buf, sizeof(buf), NULL); 560b832c2f6SAnirudh Venkataramanan if (ret) { 5614015d11eSBrett Creeley dev_err(dev, "Query Port ETS failed\n"); 562b832c2f6SAnirudh Venkataramanan goto dcb_error; 563b832c2f6SAnirudh Venkataramanan } 564b832c2f6SAnirudh Venkataramanan 565242b5e06SDave Ertman mutex_unlock(&pf->tc_mutex); 566242b5e06SDave Ertman 567b832c2f6SAnirudh Venkataramanan return; 568b832c2f6SAnirudh Venkataramanan 569b832c2f6SAnirudh Venkataramanan dcb_error: 5704015d11eSBrett Creeley dev_err(dev, "Disabling DCB until new settings occur\n"); 571242b5e06SDave Ertman err_cfg = kzalloc(sizeof(*err_cfg), GFP_KERNEL); 572242b5e06SDave Ertman if (!err_cfg) { 573242b5e06SDave Ertman mutex_unlock(&pf->tc_mutex); 5749efe35d0STony Nguyen return; 575242b5e06SDave Ertman } 5769efe35d0STony Nguyen 577242b5e06SDave Ertman err_cfg->etscfg.willing = true; 578242b5e06SDave Ertman err_cfg->etscfg.tcbwtable[0] = ICE_TC_MAX_BW; 579242b5e06SDave Ertman err_cfg->etscfg.tsatable[0] = ICE_IEEE_TSA_ETS; 580242b5e06SDave Ertman memcpy(&err_cfg->etsrec, &err_cfg->etscfg, sizeof(err_cfg->etsrec)); 581ac614b13SBruce Allan /* Coverity warns the return code of ice_pf_dcb_cfg() is not checked 582ac614b13SBruce Allan * here as is done for other calls to that function. That check is 583ac614b13SBruce Allan * not necessary since this is in this function's error cleanup path. 584ac614b13SBruce Allan * Suppress the Coverity warning with the following comment... 585ac614b13SBruce Allan */ 586ac614b13SBruce Allan /* coverity[check_return] */ 587242b5e06SDave Ertman ice_pf_dcb_cfg(pf, err_cfg, false); 588242b5e06SDave Ertman kfree(err_cfg); 589242b5e06SDave Ertman 590242b5e06SDave Ertman mutex_unlock(&pf->tc_mutex); 591b832c2f6SAnirudh Venkataramanan } 592b832c2f6SAnirudh Venkataramanan 593b832c2f6SAnirudh Venkataramanan /** 5947b9ffc76SAnirudh Venkataramanan * ice_dcb_init_cfg - set the initial DCB config in SW 5952f2da36eSAnirudh Venkataramanan * @pf: PF to apply config to 596e223eaecSDave Ertman * @locked: Is the RTNL held 5977b9ffc76SAnirudh Venkataramanan */ 598e223eaecSDave Ertman static int ice_dcb_init_cfg(struct ice_pf *pf, bool locked) 5997b9ffc76SAnirudh Venkataramanan { 6007b9ffc76SAnirudh Venkataramanan struct ice_dcbx_cfg *newcfg; 6017b9ffc76SAnirudh Venkataramanan struct ice_port_info *pi; 6027b9ffc76SAnirudh Venkataramanan int ret = 0; 6037b9ffc76SAnirudh Venkataramanan 6047b9ffc76SAnirudh Venkataramanan pi = pf->hw.port_info; 605fc2d1165SChinh T Cao newcfg = kmemdup(&pi->qos_cfg.local_dcbx_cfg, sizeof(*newcfg), 606fc2d1165SChinh T Cao GFP_KERNEL); 6077b9ffc76SAnirudh Venkataramanan if (!newcfg) 6087b9ffc76SAnirudh Venkataramanan return -ENOMEM; 6097b9ffc76SAnirudh Venkataramanan 610fc2d1165SChinh T Cao memset(&pi->qos_cfg.local_dcbx_cfg, 0, sizeof(*newcfg)); 6117b9ffc76SAnirudh Venkataramanan 6124015d11eSBrett Creeley dev_info(ice_pf_to_dev(pf), "Configuring initial DCB values\n"); 613e223eaecSDave Ertman if (ice_pf_dcb_cfg(pf, newcfg, locked)) 6147b9ffc76SAnirudh Venkataramanan ret = -EINVAL; 6157b9ffc76SAnirudh Venkataramanan 6169efe35d0STony Nguyen kfree(newcfg); 6177b9ffc76SAnirudh Venkataramanan 6187b9ffc76SAnirudh Venkataramanan return ret; 6197b9ffc76SAnirudh Venkataramanan } 6207b9ffc76SAnirudh Venkataramanan 6217b9ffc76SAnirudh Venkataramanan /** 6224ee656bbSTony Nguyen * ice_dcb_sw_dflt_cfg - Apply a default DCB config 6232f2da36eSAnirudh Venkataramanan * @pf: PF to apply config to 6244ee656bbSTony Nguyen * @ets_willing: configure ETS willing 625e223eaecSDave Ertman * @locked: was this function called with RTNL held 6260deab659SAnirudh Venkataramanan */ 6272a87bd73SDave Ertman int ice_dcb_sw_dflt_cfg(struct ice_pf *pf, bool ets_willing, bool locked) 6280deab659SAnirudh Venkataramanan { 6290deab659SAnirudh Venkataramanan struct ice_aqc_port_ets_elem buf = { 0 }; 6300deab659SAnirudh Venkataramanan struct ice_dcbx_cfg *dcbcfg; 6310deab659SAnirudh Venkataramanan struct ice_port_info *pi; 6320deab659SAnirudh Venkataramanan struct ice_hw *hw; 6330deab659SAnirudh Venkataramanan int ret; 6340deab659SAnirudh Venkataramanan 6350deab659SAnirudh Venkataramanan hw = &pf->hw; 6360deab659SAnirudh Venkataramanan pi = hw->port_info; 6379efe35d0STony Nguyen dcbcfg = kzalloc(sizeof(*dcbcfg), GFP_KERNEL); 6389efe35d0STony Nguyen if (!dcbcfg) 6399efe35d0STony Nguyen return -ENOMEM; 6400deab659SAnirudh Venkataramanan 641fc2d1165SChinh T Cao memset(&pi->qos_cfg.local_dcbx_cfg, 0, sizeof(*dcbcfg)); 6420deab659SAnirudh Venkataramanan 643cfbf1367SPaul Greenwalt dcbcfg->etscfg.willing = ets_willing ? 1 : 0; 644a257f188SUsha Ketineni dcbcfg->etscfg.maxtcs = hw->func_caps.common_cap.maxtc; 6450deab659SAnirudh Venkataramanan dcbcfg->etscfg.tcbwtable[0] = 100; 6460deab659SAnirudh Venkataramanan dcbcfg->etscfg.tsatable[0] = ICE_IEEE_TSA_ETS; 6470deab659SAnirudh Venkataramanan 6480deab659SAnirudh Venkataramanan memcpy(&dcbcfg->etsrec, &dcbcfg->etscfg, 6490deab659SAnirudh Venkataramanan sizeof(dcbcfg->etsrec)); 6500deab659SAnirudh Venkataramanan dcbcfg->etsrec.willing = 0; 6510deab659SAnirudh Venkataramanan 6520deab659SAnirudh Venkataramanan dcbcfg->pfc.willing = 1; 653a257f188SUsha Ketineni dcbcfg->pfc.pfccap = hw->func_caps.common_cap.maxtc; 6540deab659SAnirudh Venkataramanan 6550deab659SAnirudh Venkataramanan dcbcfg->numapps = 1; 6560deab659SAnirudh Venkataramanan dcbcfg->app[0].selector = ICE_APP_SEL_ETHTYPE; 6570deab659SAnirudh Venkataramanan dcbcfg->app[0].priority = 3; 658d41f26b5SBruce Allan dcbcfg->app[0].prot_id = ETH_P_FCOE; 6590deab659SAnirudh Venkataramanan 660e223eaecSDave Ertman ret = ice_pf_dcb_cfg(pf, dcbcfg, locked); 6619efe35d0STony Nguyen kfree(dcbcfg); 6620deab659SAnirudh Venkataramanan if (ret) 6630deab659SAnirudh Venkataramanan return ret; 6640deab659SAnirudh Venkataramanan 6650deab659SAnirudh Venkataramanan return ice_query_port_ets(pi, &buf, sizeof(buf), NULL); 6660deab659SAnirudh Venkataramanan } 6670deab659SAnirudh Venkataramanan 6680deab659SAnirudh Venkataramanan /** 669cfbf1367SPaul Greenwalt * ice_dcb_tc_contig - Check that TCs are contiguous 670cfbf1367SPaul Greenwalt * @prio_table: pointer to priority table 671cfbf1367SPaul Greenwalt * 672cfbf1367SPaul Greenwalt * Check if TCs begin with TC0 and are contiguous 673cfbf1367SPaul Greenwalt */ 674cfbf1367SPaul Greenwalt static bool ice_dcb_tc_contig(u8 *prio_table) 675cfbf1367SPaul Greenwalt { 67689154002SDave Ertman bool found_empty = false; 67789154002SDave Ertman u8 used_tc = 0; 678cfbf1367SPaul Greenwalt int i; 679cfbf1367SPaul Greenwalt 68089154002SDave Ertman /* Create a bitmap of used TCs */ 68189154002SDave Ertman for (i = 0; i < CEE_DCBX_MAX_PRIO; i++) 68289154002SDave Ertman used_tc |= BIT(prio_table[i]); 683cfbf1367SPaul Greenwalt 68489154002SDave Ertman for (i = 0; i < CEE_DCBX_MAX_PRIO; i++) { 68589154002SDave Ertman if (used_tc & BIT(i)) { 68689154002SDave Ertman if (found_empty) 687cfbf1367SPaul Greenwalt return false; 68889154002SDave Ertman } else { 68989154002SDave Ertman found_empty = true; 69089154002SDave Ertman } 691cfbf1367SPaul Greenwalt } 692cfbf1367SPaul Greenwalt 693cfbf1367SPaul Greenwalt return true; 694cfbf1367SPaul Greenwalt } 695cfbf1367SPaul Greenwalt 696cfbf1367SPaul Greenwalt /** 697cfbf1367SPaul Greenwalt * ice_dcb_noncontig_cfg - Configure DCB for non-contiguous TCs 698cfbf1367SPaul Greenwalt * @pf: pointer to the PF struct 699cfbf1367SPaul Greenwalt * 700cfbf1367SPaul Greenwalt * If non-contiguous TCs, then configure SW DCB with TC0 and ETS non-willing 701cfbf1367SPaul Greenwalt */ 702cfbf1367SPaul Greenwalt static int ice_dcb_noncontig_cfg(struct ice_pf *pf) 703cfbf1367SPaul Greenwalt { 704fc2d1165SChinh T Cao struct ice_dcbx_cfg *dcbcfg = &pf->hw.port_info->qos_cfg.local_dcbx_cfg; 7054015d11eSBrett Creeley struct device *dev = ice_pf_to_dev(pf); 706cfbf1367SPaul Greenwalt int ret; 707cfbf1367SPaul Greenwalt 708cfbf1367SPaul Greenwalt /* Configure SW DCB default with ETS non-willing */ 709cfbf1367SPaul Greenwalt ret = ice_dcb_sw_dflt_cfg(pf, false, true); 710cfbf1367SPaul Greenwalt if (ret) { 7114015d11eSBrett Creeley dev_err(dev, "Failed to set local DCB config %d\n", ret); 712cfbf1367SPaul Greenwalt return ret; 713cfbf1367SPaul Greenwalt } 714cfbf1367SPaul Greenwalt 715cfbf1367SPaul Greenwalt /* Reconfigure with ETS willing so that FW will send LLDP MIB event */ 716cfbf1367SPaul Greenwalt dcbcfg->etscfg.willing = 1; 717cfbf1367SPaul Greenwalt ret = ice_set_dcb_cfg(pf->hw.port_info); 718cfbf1367SPaul Greenwalt if (ret) 7194015d11eSBrett Creeley dev_err(dev, "Failed to set DCB to unwilling\n"); 720cfbf1367SPaul Greenwalt 721cfbf1367SPaul Greenwalt return ret; 722cfbf1367SPaul Greenwalt } 723cfbf1367SPaul Greenwalt 724cfbf1367SPaul Greenwalt /** 725cfbf1367SPaul Greenwalt * ice_pf_dcb_recfg - Reconfigure all VEBs and VSIs 726cfbf1367SPaul Greenwalt * @pf: pointer to the PF struct 727cfbf1367SPaul Greenwalt * 728cfbf1367SPaul Greenwalt * Assumed caller has already disabled all VSIs before 729cfbf1367SPaul Greenwalt * calling this function. Reconfiguring DCB based on 730cfbf1367SPaul Greenwalt * local_dcbx_cfg. 731cfbf1367SPaul Greenwalt */ 73287324e74SHenry Tieman void ice_pf_dcb_recfg(struct ice_pf *pf) 733cfbf1367SPaul Greenwalt { 734fc2d1165SChinh T Cao struct ice_dcbx_cfg *dcbcfg = &pf->hw.port_info->qos_cfg.local_dcbx_cfg; 735348048e7SDave Ertman struct iidc_event *event; 736cfbf1367SPaul Greenwalt u8 tc_map = 0; 737cfbf1367SPaul Greenwalt int v, ret; 738cfbf1367SPaul Greenwalt 739cfbf1367SPaul Greenwalt /* Update each VSI */ 740cfbf1367SPaul Greenwalt ice_for_each_vsi(pf, v) { 7414015d11eSBrett Creeley struct ice_vsi *vsi = pf->vsi[v]; 7424015d11eSBrett Creeley 7434015d11eSBrett Creeley if (!vsi) 744cfbf1367SPaul Greenwalt continue; 745cfbf1367SPaul Greenwalt 7464015d11eSBrett Creeley if (vsi->type == ICE_VSI_PF) { 747cfbf1367SPaul Greenwalt tc_map = ice_dcb_get_ena_tc(dcbcfg); 748cfbf1367SPaul Greenwalt 749cfbf1367SPaul Greenwalt /* If DCBX request non-contiguous TC, then configure 750cfbf1367SPaul Greenwalt * default TC 751cfbf1367SPaul Greenwalt */ 752cfbf1367SPaul Greenwalt if (!ice_dcb_tc_contig(dcbcfg->etscfg.prio_table)) { 753cfbf1367SPaul Greenwalt tc_map = ICE_DFLT_TRAFFIC_CLASS; 754cfbf1367SPaul Greenwalt ice_dcb_noncontig_cfg(pf); 755cfbf1367SPaul Greenwalt } 756*0754d65bSKiran Patil } else if (vsi->type == ICE_VSI_CHNL) { 757*0754d65bSKiran Patil tc_map = BIT(ice_get_first_droptc(vsi)); 758cfbf1367SPaul Greenwalt } else { 759cfbf1367SPaul Greenwalt tc_map = ICE_DFLT_TRAFFIC_CLASS; 760cfbf1367SPaul Greenwalt } 761cfbf1367SPaul Greenwalt 7624015d11eSBrett Creeley ret = ice_vsi_cfg_tc(vsi, tc_map); 763cfbf1367SPaul Greenwalt if (ret) { 7644015d11eSBrett Creeley dev_err(ice_pf_to_dev(pf), "Failed to config TC for VSI index: %d\n", 7654015d11eSBrett Creeley vsi->idx); 766cfbf1367SPaul Greenwalt continue; 767cfbf1367SPaul Greenwalt } 768*0754d65bSKiran Patil /* no need to proceed with remaining cfg if it is CHNL 769*0754d65bSKiran Patil * or switchdev VSI 7707aae80ceSWojciech Drewek */ 771*0754d65bSKiran Patil if (vsi->type == ICE_VSI_CHNL || 772*0754d65bSKiran Patil vsi->type == ICE_VSI_SWITCHDEV_CTRL) 7737aae80ceSWojciech Drewek continue; 774cfbf1367SPaul Greenwalt 7754015d11eSBrett Creeley ice_vsi_map_rings_to_vectors(vsi); 7764015d11eSBrett Creeley if (vsi->type == ICE_VSI_PF) 7774015d11eSBrett Creeley ice_dcbnl_set_all(vsi); 778cfbf1367SPaul Greenwalt } 779348048e7SDave Ertman /* Notify the AUX drivers that TC change is finished */ 780348048e7SDave Ertman event = kzalloc(sizeof(*event), GFP_KERNEL); 781348048e7SDave Ertman if (!event) 782348048e7SDave Ertman return; 783348048e7SDave Ertman 784348048e7SDave Ertman set_bit(IIDC_EVENT_AFTER_TC_CHANGE, event->type); 785348048e7SDave Ertman ice_send_event_to_aux(pf, event); 786348048e7SDave Ertman kfree(event); 787cfbf1367SPaul Greenwalt } 788cfbf1367SPaul Greenwalt 789cfbf1367SPaul Greenwalt /** 79037b6f646SAnirudh Venkataramanan * ice_init_pf_dcb - initialize DCB for a PF 7912f2da36eSAnirudh Venkataramanan * @pf: PF to initialize DCB for 792e223eaecSDave Ertman * @locked: Was function called with RTNL held 79337b6f646SAnirudh Venkataramanan */ 794e223eaecSDave Ertman int ice_init_pf_dcb(struct ice_pf *pf, bool locked) 79537b6f646SAnirudh Venkataramanan { 7964015d11eSBrett Creeley struct device *dev = ice_pf_to_dev(pf); 79737b6f646SAnirudh Venkataramanan struct ice_port_info *port_info; 79837b6f646SAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 7997b9ffc76SAnirudh Venkataramanan int err; 80037b6f646SAnirudh Venkataramanan 80137b6f646SAnirudh Venkataramanan port_info = hw->port_info; 80237b6f646SAnirudh Venkataramanan 803ea300f41SDave Ertman err = ice_init_dcb(hw, false); 804fc2d1165SChinh T Cao if (err && !port_info->qos_cfg.is_sw_lldp) { 8054015d11eSBrett Creeley dev_err(dev, "Error initializing DCB %d\n", err); 806473ca574SDave Ertman goto dcb_init_err; 807473ca574SDave Ertman } 808473ca574SDave Ertman 80919cce2c6SAnirudh Venkataramanan dev_info(dev, "DCB is enabled in the hardware, max number of TCs supported on this port are %d\n", 810a257f188SUsha Ketineni pf->hw.func_caps.common_cap.maxtc); 811473ca574SDave Ertman if (err) { 812241c8cf0SPaul Greenwalt struct ice_vsi *pf_vsi; 813241c8cf0SPaul Greenwalt 814473ca574SDave Ertman /* FW LLDP is disabled, activate SW DCBX/LLDP mode */ 8154015d11eSBrett Creeley dev_info(dev, "FW LLDP is disabled, DCBx/LLDP in SW mode.\n"); 81684a118abSDave Ertman clear_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags); 8172a87bd73SDave Ertman err = ice_aq_set_pfc_mode(&pf->hw, ICE_AQC_PFC_VLAN_BASED_PFC, 8182a87bd73SDave Ertman NULL); 8192a87bd73SDave Ertman if (err) 8202a87bd73SDave Ertman dev_info(dev, "Failed to set VLAN PFC mode\n"); 8212a87bd73SDave Ertman 822cfbf1367SPaul Greenwalt err = ice_dcb_sw_dflt_cfg(pf, true, locked); 8230deab659SAnirudh Venkataramanan if (err) { 82419cce2c6SAnirudh Venkataramanan dev_err(dev, "Failed to set local DCB config %d\n", 82519cce2c6SAnirudh Venkataramanan err); 8260deab659SAnirudh Venkataramanan err = -EIO; 8277b9ffc76SAnirudh Venkataramanan goto dcb_init_err; 8280deab659SAnirudh Venkataramanan } 8290deab659SAnirudh Venkataramanan 830241c8cf0SPaul Greenwalt /* If the FW DCBX engine is not running then Rx LLDP packets 831241c8cf0SPaul Greenwalt * need to be redirected up the stack. 832241c8cf0SPaul Greenwalt */ 833241c8cf0SPaul Greenwalt pf_vsi = ice_get_main_vsi(pf); 834241c8cf0SPaul Greenwalt if (!pf_vsi) { 8354015d11eSBrett Creeley dev_err(dev, "Failed to set local DCB config\n"); 836241c8cf0SPaul Greenwalt err = -EIO; 837241c8cf0SPaul Greenwalt goto dcb_init_err; 838241c8cf0SPaul Greenwalt } 839241c8cf0SPaul Greenwalt 840241c8cf0SPaul Greenwalt ice_cfg_sw_lldp(pf_vsi, false, true); 841241c8cf0SPaul Greenwalt 84227d9be98SAvinash Dayanand pf->dcbx_cap = ice_dcb_get_mode(port_info, true); 8430deab659SAnirudh Venkataramanan return 0; 8440deab659SAnirudh Venkataramanan } 8457b9ffc76SAnirudh Venkataramanan 84684a118abSDave Ertman set_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags); 8471b0c3247SDave Ertman 84827d9be98SAvinash Dayanand /* DCBX/LLDP enabled in FW, set DCBNL mode advertisement */ 84927d9be98SAvinash Dayanand pf->dcbx_cap = ice_dcb_get_mode(port_info, false); 8507b9ffc76SAnirudh Venkataramanan 851e223eaecSDave Ertman err = ice_dcb_init_cfg(pf, locked); 8527b9ffc76SAnirudh Venkataramanan if (err) 8537b9ffc76SAnirudh Venkataramanan goto dcb_init_err; 8547b9ffc76SAnirudh Venkataramanan 8557b9ffc76SAnirudh Venkataramanan return err; 8567b9ffc76SAnirudh Venkataramanan 8577b9ffc76SAnirudh Venkataramanan dcb_init_err: 8587b9ffc76SAnirudh Venkataramanan dev_err(dev, "DCB init failed\n"); 8597b9ffc76SAnirudh Venkataramanan return err; 86037b6f646SAnirudh Venkataramanan } 86100cc3f1bSAnirudh Venkataramanan 86200cc3f1bSAnirudh Venkataramanan /** 8634b0fdcebSAnirudh Venkataramanan * ice_update_dcb_stats - Update DCB stats counters 8644b0fdcebSAnirudh Venkataramanan * @pf: PF whose stats needs to be updated 8654b0fdcebSAnirudh Venkataramanan */ 8664b0fdcebSAnirudh Venkataramanan void ice_update_dcb_stats(struct ice_pf *pf) 8674b0fdcebSAnirudh Venkataramanan { 8684b0fdcebSAnirudh Venkataramanan struct ice_hw_port_stats *prev_ps, *cur_ps; 8694b0fdcebSAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 8709e7a5d17SUsha Ketineni u8 port; 8714b0fdcebSAnirudh Venkataramanan int i; 8724b0fdcebSAnirudh Venkataramanan 8739e7a5d17SUsha Ketineni port = hw->port_info->lport; 8744b0fdcebSAnirudh Venkataramanan prev_ps = &pf->stats_prev; 8754b0fdcebSAnirudh Venkataramanan cur_ps = &pf->stats; 8764b0fdcebSAnirudh Venkataramanan 8774b0fdcebSAnirudh Venkataramanan for (i = 0; i < 8; i++) { 8789e7a5d17SUsha Ketineni ice_stat_update32(hw, GLPRT_PXOFFRXC(port, i), 8794b0fdcebSAnirudh Venkataramanan pf->stat_prev_loaded, 8804b0fdcebSAnirudh Venkataramanan &prev_ps->priority_xoff_rx[i], 8814b0fdcebSAnirudh Venkataramanan &cur_ps->priority_xoff_rx[i]); 8829e7a5d17SUsha Ketineni ice_stat_update32(hw, GLPRT_PXONRXC(port, i), 8834b0fdcebSAnirudh Venkataramanan pf->stat_prev_loaded, 8844b0fdcebSAnirudh Venkataramanan &prev_ps->priority_xon_rx[i], 8854b0fdcebSAnirudh Venkataramanan &cur_ps->priority_xon_rx[i]); 8869e7a5d17SUsha Ketineni ice_stat_update32(hw, GLPRT_PXONTXC(port, i), 8874b0fdcebSAnirudh Venkataramanan pf->stat_prev_loaded, 8884b0fdcebSAnirudh Venkataramanan &prev_ps->priority_xon_tx[i], 8894b0fdcebSAnirudh Venkataramanan &cur_ps->priority_xon_tx[i]); 8909e7a5d17SUsha Ketineni ice_stat_update32(hw, GLPRT_PXOFFTXC(port, i), 8914b0fdcebSAnirudh Venkataramanan pf->stat_prev_loaded, 8924b0fdcebSAnirudh Venkataramanan &prev_ps->priority_xoff_tx[i], 8934b0fdcebSAnirudh Venkataramanan &cur_ps->priority_xoff_tx[i]); 8949e7a5d17SUsha Ketineni ice_stat_update32(hw, GLPRT_RXON2OFFCNT(port, i), 8954b0fdcebSAnirudh Venkataramanan pf->stat_prev_loaded, 8964b0fdcebSAnirudh Venkataramanan &prev_ps->priority_xon_2_xoff[i], 8974b0fdcebSAnirudh Venkataramanan &cur_ps->priority_xon_2_xoff[i]); 8984b0fdcebSAnirudh Venkataramanan } 8994b0fdcebSAnirudh Venkataramanan } 9004b0fdcebSAnirudh Venkataramanan 9014b0fdcebSAnirudh Venkataramanan /** 9025f6aa50eSAnirudh Venkataramanan * ice_tx_prepare_vlan_flags_dcb - prepare VLAN tagging for DCB 9035f6aa50eSAnirudh Venkataramanan * @tx_ring: ring to send buffer on 9045f6aa50eSAnirudh Venkataramanan * @first: pointer to struct ice_tx_buf 9052bb19d6eSBrett Creeley * 9062bb19d6eSBrett Creeley * This should not be called if the outer VLAN is software offloaded as the VLAN 9072bb19d6eSBrett Creeley * tag will already be configured with the correct ID and priority bits 9085f6aa50eSAnirudh Venkataramanan */ 9092bb19d6eSBrett Creeley void 910e72bba21SMaciej Fijalkowski ice_tx_prepare_vlan_flags_dcb(struct ice_tx_ring *tx_ring, 9115f6aa50eSAnirudh Venkataramanan struct ice_tx_buf *first) 9125f6aa50eSAnirudh Venkataramanan { 9135f6aa50eSAnirudh Venkataramanan struct sk_buff *skb = first->skb; 9145f6aa50eSAnirudh Venkataramanan 9155f6aa50eSAnirudh Venkataramanan if (!test_bit(ICE_FLAG_DCB_ENA, tx_ring->vsi->back->flags)) 9162bb19d6eSBrett Creeley return; 9175f6aa50eSAnirudh Venkataramanan 9185f6aa50eSAnirudh Venkataramanan /* Insert 802.1p priority into VLAN header */ 9192bb19d6eSBrett Creeley if ((first->tx_flags & ICE_TX_FLAGS_HW_VLAN) || 9205f6aa50eSAnirudh Venkataramanan skb->priority != TC_PRIO_CONTROL) { 9215f6aa50eSAnirudh Venkataramanan first->tx_flags &= ~ICE_TX_FLAGS_VLAN_PR_M; 9225f6aa50eSAnirudh Venkataramanan /* Mask the lower 3 bits to set the 802.1p priority */ 9235f6aa50eSAnirudh Venkataramanan first->tx_flags |= (skb->priority & 0x7) << 9245f6aa50eSAnirudh Venkataramanan ICE_TX_FLAGS_VLAN_PR_S; 9252bb19d6eSBrett Creeley /* if this is not already set it means a VLAN 0 + priority needs 9262bb19d6eSBrett Creeley * to be offloaded 9272bb19d6eSBrett Creeley */ 9285f6aa50eSAnirudh Venkataramanan first->tx_flags |= ICE_TX_FLAGS_HW_VLAN; 9295f6aa50eSAnirudh Venkataramanan } 9305f6aa50eSAnirudh Venkataramanan } 9315f6aa50eSAnirudh Venkataramanan 9325f6aa50eSAnirudh Venkataramanan /** 93300cc3f1bSAnirudh Venkataramanan * ice_dcb_process_lldp_set_mib_change - Process MIB change 93400cc3f1bSAnirudh Venkataramanan * @pf: ptr to ice_pf 93500cc3f1bSAnirudh Venkataramanan * @event: pointer to the admin queue receive event 93600cc3f1bSAnirudh Venkataramanan */ 93700cc3f1bSAnirudh Venkataramanan void 93800cc3f1bSAnirudh Venkataramanan ice_dcb_process_lldp_set_mib_change(struct ice_pf *pf, 93900cc3f1bSAnirudh Venkataramanan struct ice_rq_event_info *event) 94000cc3f1bSAnirudh Venkataramanan { 941a17a5ff6SUsha Ketineni struct ice_aqc_port_ets_elem buf = { 0 }; 9424015d11eSBrett Creeley struct device *dev = ice_pf_to_dev(pf); 943a17a5ff6SUsha Ketineni struct ice_aqc_lldp_get_mib *mib; 944a17a5ff6SUsha Ketineni struct ice_dcbx_cfg tmp_dcbx_cfg; 945a17a5ff6SUsha Ketineni bool need_reconfig = false; 946a17a5ff6SUsha Ketineni struct ice_port_info *pi; 9476dae8aa0SBruce Allan u8 mib_type; 948a17a5ff6SUsha Ketineni int ret; 94900cc3f1bSAnirudh Venkataramanan 950a17a5ff6SUsha Ketineni /* Not DCB capable or capability disabled */ 951a17a5ff6SUsha Ketineni if (!(test_bit(ICE_FLAG_DCB_CAPABLE, pf->flags))) 95200cc3f1bSAnirudh Venkataramanan return; 95300cc3f1bSAnirudh Venkataramanan 954a17a5ff6SUsha Ketineni if (pf->dcbx_cap & DCB_CAP_DCBX_HOST) { 9554015d11eSBrett Creeley dev_dbg(dev, "MIB Change Event in HOST mode\n"); 956a17a5ff6SUsha Ketineni return; 95700cc3f1bSAnirudh Venkataramanan } 958a17a5ff6SUsha Ketineni 959a17a5ff6SUsha Ketineni pi = pf->hw.port_info; 960a17a5ff6SUsha Ketineni mib = (struct ice_aqc_lldp_get_mib *)&event->desc.params.raw; 961a17a5ff6SUsha Ketineni /* Ignore if event is not for Nearest Bridge */ 9626dae8aa0SBruce Allan mib_type = ((mib->type >> ICE_AQ_LLDP_BRID_TYPE_S) & 963a17a5ff6SUsha Ketineni ICE_AQ_LLDP_BRID_TYPE_M); 9646dae8aa0SBruce Allan dev_dbg(dev, "LLDP event MIB bridge type 0x%x\n", mib_type); 9656dae8aa0SBruce Allan if (mib_type != ICE_AQ_LLDP_BRID_TYPE_NEAREST_BRID) 966a17a5ff6SUsha Ketineni return; 967a17a5ff6SUsha Ketineni 968a17a5ff6SUsha Ketineni /* Check MIB Type and return if event for Remote MIB update */ 9696dae8aa0SBruce Allan mib_type = mib->type & ICE_AQ_LLDP_MIB_TYPE_M; 9706dae8aa0SBruce Allan dev_dbg(dev, "LLDP event mib type %s\n", mib_type ? "remote" : "local"); 9716dae8aa0SBruce Allan if (mib_type == ICE_AQ_LLDP_MIB_REMOTE) { 972a17a5ff6SUsha Ketineni /* Update the remote cached instance and return */ 973a17a5ff6SUsha Ketineni ret = ice_aq_get_dcb_cfg(pi->hw, ICE_AQ_LLDP_MIB_REMOTE, 974a17a5ff6SUsha Ketineni ICE_AQ_LLDP_BRID_TYPE_NEAREST_BRID, 975fc2d1165SChinh T Cao &pi->qos_cfg.remote_dcbx_cfg); 976a17a5ff6SUsha Ketineni if (ret) { 9774015d11eSBrett Creeley dev_err(dev, "Failed to get remote DCB config\n"); 978a17a5ff6SUsha Ketineni return; 979a17a5ff6SUsha Ketineni } 980a17a5ff6SUsha Ketineni } 981a17a5ff6SUsha Ketineni 982242b5e06SDave Ertman mutex_lock(&pf->tc_mutex); 983242b5e06SDave Ertman 984a17a5ff6SUsha Ketineni /* store the old configuration */ 985fc2d1165SChinh T Cao tmp_dcbx_cfg = pf->hw.port_info->qos_cfg.local_dcbx_cfg; 986a17a5ff6SUsha Ketineni 9872f2da36eSAnirudh Venkataramanan /* Reset the old DCBX configuration data */ 988fc2d1165SChinh T Cao memset(&pi->qos_cfg.local_dcbx_cfg, 0, 989fc2d1165SChinh T Cao sizeof(pi->qos_cfg.local_dcbx_cfg)); 990a17a5ff6SUsha Ketineni 9912f2da36eSAnirudh Venkataramanan /* Get updated DCBX data from firmware */ 992a17a5ff6SUsha Ketineni ret = ice_get_dcb_cfg(pf->hw.port_info); 993a17a5ff6SUsha Ketineni if (ret) { 9944015d11eSBrett Creeley dev_err(dev, "Failed to get DCB config\n"); 995242b5e06SDave Ertman goto out; 996a17a5ff6SUsha Ketineni } 997a17a5ff6SUsha Ketineni 998a17a5ff6SUsha Ketineni /* No change detected in DCBX configs */ 999fc2d1165SChinh T Cao if (!memcmp(&tmp_dcbx_cfg, &pi->qos_cfg.local_dcbx_cfg, 1000fc2d1165SChinh T Cao sizeof(tmp_dcbx_cfg))) { 10014015d11eSBrett Creeley dev_dbg(dev, "No change detected in DCBX configuration.\n"); 1002242b5e06SDave Ertman goto out; 1003a17a5ff6SUsha Ketineni } 1004a17a5ff6SUsha Ketineni 10051f454e06SAvinash JD pf->dcbx_cap = ice_dcb_get_mode(pi, false); 10061f454e06SAvinash JD 1007a17a5ff6SUsha Ketineni need_reconfig = ice_dcb_need_recfg(pf, &tmp_dcbx_cfg, 1008fc2d1165SChinh T Cao &pi->qos_cfg.local_dcbx_cfg); 1009fc2d1165SChinh T Cao ice_dcbnl_flush_apps(pf, &tmp_dcbx_cfg, &pi->qos_cfg.local_dcbx_cfg); 1010a17a5ff6SUsha Ketineni if (!need_reconfig) 1011242b5e06SDave Ertman goto out; 1012a17a5ff6SUsha Ketineni 1013a17a5ff6SUsha Ketineni /* Enable DCB tagging only when more than one TC */ 1014fc2d1165SChinh T Cao if (ice_dcb_get_num_tc(&pi->qos_cfg.local_dcbx_cfg) > 1) { 10154015d11eSBrett Creeley dev_dbg(dev, "DCB tagging enabled (num TC > 1)\n"); 1016a17a5ff6SUsha Ketineni set_bit(ICE_FLAG_DCB_ENA, pf->flags); 1017a17a5ff6SUsha Ketineni } else { 10184015d11eSBrett Creeley dev_dbg(dev, "DCB tagging disabled (num TC = 1)\n"); 1019a17a5ff6SUsha Ketineni clear_bit(ICE_FLAG_DCB_ENA, pf->flags); 1020a17a5ff6SUsha Ketineni } 1021a17a5ff6SUsha Ketineni 1022a17a5ff6SUsha Ketineni rtnl_lock(); 1023*0754d65bSKiran Patil /* disable VSIs affected by DCB changes */ 1024*0754d65bSKiran Patil ice_dcb_ena_dis_vsi(pf, false, true); 1025a17a5ff6SUsha Ketineni 1026a17a5ff6SUsha Ketineni ret = ice_query_port_ets(pf->hw.port_info, &buf, sizeof(buf), NULL); 1027a17a5ff6SUsha Ketineni if (ret) { 10284015d11eSBrett Creeley dev_err(dev, "Query Port ETS failed\n"); 1029242b5e06SDave Ertman goto unlock_rtnl; 1030a17a5ff6SUsha Ketineni } 1031a17a5ff6SUsha Ketineni 1032a17a5ff6SUsha Ketineni /* changes in configuration update VSI */ 1033a17a5ff6SUsha Ketineni ice_pf_dcb_recfg(pf); 1034a17a5ff6SUsha Ketineni 1035*0754d65bSKiran Patil /* enable previously downed VSIs */ 1036*0754d65bSKiran Patil ice_dcb_ena_dis_vsi(pf, true, true); 1037242b5e06SDave Ertman unlock_rtnl: 1038a17a5ff6SUsha Ketineni rtnl_unlock(); 1039242b5e06SDave Ertman out: 1040242b5e06SDave Ertman mutex_unlock(&pf->tc_mutex); 104100cc3f1bSAnirudh Venkataramanan } 1042