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" 680fe30a8SMichal Wilczynski #include "ice_devlink.h" 737b6f646SAnirudh Venkataramanan 837b6f646SAnirudh Venkataramanan /** 97b9ffc76SAnirudh Venkataramanan * ice_dcb_get_ena_tc - return bitmap of enabled TCs 107b9ffc76SAnirudh Venkataramanan * @dcbcfg: DCB config to evaluate for enabled TCs 117b9ffc76SAnirudh Venkataramanan */ 120754d65bSKiran Patil static u8 ice_dcb_get_ena_tc(struct ice_dcbx_cfg *dcbcfg) 137b9ffc76SAnirudh Venkataramanan { 147b9ffc76SAnirudh Venkataramanan u8 i, num_tc, ena_tc = 1; 157b9ffc76SAnirudh Venkataramanan 167b9ffc76SAnirudh Venkataramanan num_tc = ice_dcb_get_num_tc(dcbcfg); 177b9ffc76SAnirudh Venkataramanan 187b9ffc76SAnirudh Venkataramanan for (i = 0; i < num_tc; i++) 197b9ffc76SAnirudh Venkataramanan ena_tc |= BIT(i); 207b9ffc76SAnirudh Venkataramanan 217b9ffc76SAnirudh Venkataramanan return ena_tc; 227b9ffc76SAnirudh Venkataramanan } 237b9ffc76SAnirudh Venkataramanan 247b9ffc76SAnirudh Venkataramanan /** 25610ed0e9SAvinash JD * ice_is_pfc_causing_hung_q 26610ed0e9SAvinash JD * @pf: pointer to PF structure 27610ed0e9SAvinash JD * @txqueue: Tx queue which is supposedly hung queue 28610ed0e9SAvinash JD * 29610ed0e9SAvinash JD * find if PFC is causing the hung queue, if yes return true else false 30610ed0e9SAvinash JD */ 31610ed0e9SAvinash JD bool ice_is_pfc_causing_hung_q(struct ice_pf *pf, unsigned int txqueue) 32610ed0e9SAvinash JD { 33610ed0e9SAvinash JD u8 num_tcs = 0, i, tc, up_mapped_tc, up_in_tc = 0; 34610ed0e9SAvinash JD u64 ref_prio_xoff[ICE_MAX_UP]; 35610ed0e9SAvinash JD struct ice_vsi *vsi; 36610ed0e9SAvinash JD u32 up2tc; 37610ed0e9SAvinash JD 38610ed0e9SAvinash JD vsi = ice_get_main_vsi(pf); 39610ed0e9SAvinash JD if (!vsi) 40610ed0e9SAvinash JD return false; 41610ed0e9SAvinash JD 42610ed0e9SAvinash JD ice_for_each_traffic_class(i) 43610ed0e9SAvinash JD if (vsi->tc_cfg.ena_tc & BIT(i)) 44610ed0e9SAvinash JD num_tcs++; 45610ed0e9SAvinash JD 46610ed0e9SAvinash JD /* first find out the TC to which the hung queue belongs to */ 47610ed0e9SAvinash JD for (tc = 0; tc < num_tcs - 1; tc++) 48610ed0e9SAvinash JD if (ice_find_q_in_range(vsi->tc_cfg.tc_info[tc].qoffset, 49610ed0e9SAvinash JD vsi->tc_cfg.tc_info[tc + 1].qoffset, 50610ed0e9SAvinash JD txqueue)) 51610ed0e9SAvinash JD break; 52610ed0e9SAvinash JD 53610ed0e9SAvinash JD /* Build a bit map of all UPs associated to the suspect hung queue TC, 54610ed0e9SAvinash JD * so that we check for its counter increment. 55610ed0e9SAvinash JD */ 56610ed0e9SAvinash JD up2tc = rd32(&pf->hw, PRTDCB_TUP2TC); 57610ed0e9SAvinash JD for (i = 0; i < ICE_MAX_UP; i++) { 58610ed0e9SAvinash JD up_mapped_tc = (up2tc >> (i * 3)) & 0x7; 59610ed0e9SAvinash JD if (up_mapped_tc == tc) 60610ed0e9SAvinash JD up_in_tc |= BIT(i); 61610ed0e9SAvinash JD } 62610ed0e9SAvinash JD 63610ed0e9SAvinash JD /* Now that we figured out that hung queue is PFC enabled, still the 64610ed0e9SAvinash JD * Tx timeout can be legitimate. So to make sure Tx timeout is 65610ed0e9SAvinash JD * absolutely caused by PFC storm, check if the counters are 66610ed0e9SAvinash JD * incrementing. 67610ed0e9SAvinash JD */ 68610ed0e9SAvinash JD for (i = 0; i < ICE_MAX_UP; i++) 69610ed0e9SAvinash JD if (up_in_tc & BIT(i)) 70610ed0e9SAvinash JD ref_prio_xoff[i] = pf->stats.priority_xoff_rx[i]; 71610ed0e9SAvinash JD 72610ed0e9SAvinash JD ice_update_dcb_stats(pf); 73610ed0e9SAvinash JD 74610ed0e9SAvinash JD for (i = 0; i < ICE_MAX_UP; i++) 75610ed0e9SAvinash JD if (up_in_tc & BIT(i)) 76610ed0e9SAvinash JD if (pf->stats.priority_xoff_rx[i] > ref_prio_xoff[i]) 77610ed0e9SAvinash JD return true; 78610ed0e9SAvinash JD 79610ed0e9SAvinash JD return false; 80610ed0e9SAvinash JD } 81610ed0e9SAvinash JD 82610ed0e9SAvinash JD /** 8327d9be98SAvinash Dayanand * ice_dcb_get_mode - gets the DCB mode 8427d9be98SAvinash Dayanand * @port_info: pointer to port info structure 8527d9be98SAvinash Dayanand * @host: if set it's HOST if not it's MANAGED 8627d9be98SAvinash Dayanand */ 8727d9be98SAvinash Dayanand static u8 ice_dcb_get_mode(struct ice_port_info *port_info, bool host) 8827d9be98SAvinash Dayanand { 8927d9be98SAvinash Dayanand u8 mode; 9027d9be98SAvinash Dayanand 9127d9be98SAvinash Dayanand if (host) 9227d9be98SAvinash Dayanand mode = DCB_CAP_DCBX_HOST; 9327d9be98SAvinash Dayanand else 9427d9be98SAvinash Dayanand mode = DCB_CAP_DCBX_LLD_MANAGED; 9527d9be98SAvinash Dayanand 96fc2d1165SChinh T Cao if (port_info->qos_cfg.local_dcbx_cfg.dcbx_mode & ICE_DCBX_MODE_CEE) 97f3beaf24SJeff Kirsher return mode | DCB_CAP_DCBX_VER_CEE; 9827d9be98SAvinash Dayanand else 99f3beaf24SJeff Kirsher return mode | DCB_CAP_DCBX_VER_IEEE; 10027d9be98SAvinash Dayanand } 10127d9be98SAvinash Dayanand 10227d9be98SAvinash Dayanand /** 1037b9ffc76SAnirudh Venkataramanan * ice_dcb_get_num_tc - Get the number of TCs from DCBX config 1047b9ffc76SAnirudh Venkataramanan * @dcbcfg: config to retrieve number of TCs from 1057b9ffc76SAnirudh Venkataramanan */ 1067b9ffc76SAnirudh Venkataramanan u8 ice_dcb_get_num_tc(struct ice_dcbx_cfg *dcbcfg) 1077b9ffc76SAnirudh Venkataramanan { 1087b9ffc76SAnirudh Venkataramanan bool tc_unused = false; 1097b9ffc76SAnirudh Venkataramanan u8 num_tc = 0; 1107b9ffc76SAnirudh Venkataramanan u8 ret = 0; 1117b9ffc76SAnirudh Venkataramanan int i; 1127b9ffc76SAnirudh Venkataramanan 1137b9ffc76SAnirudh Venkataramanan /* Scan the ETS Config Priority Table to find traffic classes 1147b9ffc76SAnirudh Venkataramanan * enabled and create a bitmask of enabled TCs 1157b9ffc76SAnirudh Venkataramanan */ 1167b9ffc76SAnirudh Venkataramanan for (i = 0; i < CEE_DCBX_MAX_PRIO; i++) 1177b9ffc76SAnirudh Venkataramanan num_tc |= BIT(dcbcfg->etscfg.prio_table[i]); 1187b9ffc76SAnirudh Venkataramanan 1197b9ffc76SAnirudh Venkataramanan /* Scan bitmask for contiguous TCs starting with TC0 */ 1207b9ffc76SAnirudh Venkataramanan for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { 1217b9ffc76SAnirudh Venkataramanan if (num_tc & BIT(i)) { 1227b9ffc76SAnirudh Venkataramanan if (!tc_unused) { 1237b9ffc76SAnirudh Venkataramanan ret++; 1247b9ffc76SAnirudh Venkataramanan } else { 1257b9ffc76SAnirudh Venkataramanan pr_err("Non-contiguous TCs - Disabling DCB\n"); 1267b9ffc76SAnirudh Venkataramanan return 1; 1277b9ffc76SAnirudh Venkataramanan } 1287b9ffc76SAnirudh Venkataramanan } else { 1297b9ffc76SAnirudh Venkataramanan tc_unused = true; 1307b9ffc76SAnirudh Venkataramanan } 1317b9ffc76SAnirudh Venkataramanan } 1327b9ffc76SAnirudh Venkataramanan 1337b9ffc76SAnirudh Venkataramanan /* There is always at least 1 TC */ 1347b9ffc76SAnirudh Venkataramanan if (!ret) 1357b9ffc76SAnirudh Venkataramanan ret = 1; 1367b9ffc76SAnirudh Venkataramanan 1377b9ffc76SAnirudh Venkataramanan return ret; 1387b9ffc76SAnirudh Venkataramanan } 1397b9ffc76SAnirudh Venkataramanan 1407b9ffc76SAnirudh Venkataramanan /** 1410754d65bSKiran Patil * ice_get_first_droptc - returns number of first droptc 1420754d65bSKiran Patil * @vsi: used to find the first droptc 1430754d65bSKiran Patil * 1440754d65bSKiran Patil * This function returns the value of first_droptc. 1450754d65bSKiran Patil * When DCB is enabled, first droptc information is derived from enabled_tc 1460754d65bSKiran Patil * and PFC enabled bits. otherwise this function returns 0 as there is one 1470754d65bSKiran Patil * TC without DCB (tc0) 1480754d65bSKiran Patil */ 1490754d65bSKiran Patil static u8 ice_get_first_droptc(struct ice_vsi *vsi) 1500754d65bSKiran Patil { 1510754d65bSKiran Patil struct ice_dcbx_cfg *cfg = &vsi->port_info->qos_cfg.local_dcbx_cfg; 1520754d65bSKiran Patil struct device *dev = ice_pf_to_dev(vsi->back); 1530754d65bSKiran Patil u8 num_tc, ena_tc_map, pfc_ena_map; 1540754d65bSKiran Patil u8 i; 1550754d65bSKiran Patil 1560754d65bSKiran Patil num_tc = ice_dcb_get_num_tc(cfg); 1570754d65bSKiran Patil 1580754d65bSKiran Patil /* get bitmap of enabled TCs */ 1590754d65bSKiran Patil ena_tc_map = ice_dcb_get_ena_tc(cfg); 1600754d65bSKiran Patil 1610754d65bSKiran Patil /* get bitmap of PFC enabled TCs */ 1620754d65bSKiran Patil pfc_ena_map = cfg->pfc.pfcena; 1630754d65bSKiran Patil 1640754d65bSKiran Patil /* get first TC that is not PFC enabled */ 1650754d65bSKiran Patil for (i = 0; i < num_tc; i++) { 1660754d65bSKiran Patil if ((ena_tc_map & BIT(i)) && (!(pfc_ena_map & BIT(i)))) { 1670754d65bSKiran Patil dev_dbg(dev, "first drop tc = %d\n", i); 1680754d65bSKiran Patil return i; 1690754d65bSKiran Patil } 1700754d65bSKiran Patil } 1710754d65bSKiran Patil 1720754d65bSKiran Patil dev_dbg(dev, "first drop tc = 0\n"); 1730754d65bSKiran Patil return 0; 1740754d65bSKiran Patil } 1750754d65bSKiran Patil 1760754d65bSKiran Patil /** 1770754d65bSKiran Patil * ice_vsi_set_dcb_tc_cfg - Set VSI's TC based on DCB configuration 1780754d65bSKiran Patil * @vsi: pointer to the VSI instance 1790754d65bSKiran Patil */ 1800754d65bSKiran Patil void ice_vsi_set_dcb_tc_cfg(struct ice_vsi *vsi) 1810754d65bSKiran Patil { 1820754d65bSKiran Patil struct ice_dcbx_cfg *cfg = &vsi->port_info->qos_cfg.local_dcbx_cfg; 1830754d65bSKiran Patil 1840754d65bSKiran Patil switch (vsi->type) { 1850754d65bSKiran Patil case ICE_VSI_PF: 1860754d65bSKiran Patil vsi->tc_cfg.ena_tc = ice_dcb_get_ena_tc(cfg); 1870754d65bSKiran Patil vsi->tc_cfg.numtc = ice_dcb_get_num_tc(cfg); 1880754d65bSKiran Patil break; 1890754d65bSKiran Patil case ICE_VSI_CHNL: 1900754d65bSKiran Patil vsi->tc_cfg.ena_tc = BIT(ice_get_first_droptc(vsi)); 1910754d65bSKiran Patil vsi->tc_cfg.numtc = 1; 1920754d65bSKiran Patil break; 1930754d65bSKiran Patil case ICE_VSI_CTRL: 1940754d65bSKiran Patil case ICE_VSI_LB: 1950754d65bSKiran Patil default: 1960754d65bSKiran Patil vsi->tc_cfg.ena_tc = ICE_DFLT_TRAFFIC_CLASS; 1970754d65bSKiran Patil vsi->tc_cfg.numtc = 1; 1980754d65bSKiran Patil } 1990754d65bSKiran Patil } 2000754d65bSKiran Patil 2010754d65bSKiran Patil /** 2021ddef455SUsha Ketineni * ice_dcb_get_tc - Get the TC associated with the queue 2031ddef455SUsha Ketineni * @vsi: ptr to the VSI 2041ddef455SUsha Ketineni * @queue_index: queue number associated with VSI 2051ddef455SUsha Ketineni */ 2061ddef455SUsha Ketineni u8 ice_dcb_get_tc(struct ice_vsi *vsi, int queue_index) 2071ddef455SUsha Ketineni { 2081ddef455SUsha Ketineni return vsi->tx_rings[queue_index]->dcb_tc; 2091ddef455SUsha Ketineni } 2101ddef455SUsha Ketineni 2111ddef455SUsha Ketineni /** 212a629cf0aSAnirudh Venkataramanan * ice_vsi_cfg_dcb_rings - Update rings to reflect DCB TC 213a629cf0aSAnirudh Venkataramanan * @vsi: VSI owner of rings being updated 214a629cf0aSAnirudh Venkataramanan */ 215a629cf0aSAnirudh Venkataramanan void ice_vsi_cfg_dcb_rings(struct ice_vsi *vsi) 216a629cf0aSAnirudh Venkataramanan { 217e72bba21SMaciej Fijalkowski struct ice_tx_ring *tx_ring; 218e72bba21SMaciej Fijalkowski struct ice_rx_ring *rx_ring; 219a629cf0aSAnirudh Venkataramanan u16 qoffset, qcount; 220a629cf0aSAnirudh Venkataramanan int i, n; 221a629cf0aSAnirudh Venkataramanan 222a629cf0aSAnirudh Venkataramanan if (!test_bit(ICE_FLAG_DCB_ENA, vsi->back->flags)) { 223a629cf0aSAnirudh Venkataramanan /* Reset the TC information */ 2242faf63b6SMaciej Fijalkowski ice_for_each_txq(vsi, i) { 225a629cf0aSAnirudh Venkataramanan tx_ring = vsi->tx_rings[i]; 226a629cf0aSAnirudh Venkataramanan tx_ring->dcb_tc = 0; 227a629cf0aSAnirudh Venkataramanan } 2282faf63b6SMaciej Fijalkowski ice_for_each_rxq(vsi, i) { 229a629cf0aSAnirudh Venkataramanan rx_ring = vsi->rx_rings[i]; 230a629cf0aSAnirudh Venkataramanan rx_ring->dcb_tc = 0; 231a629cf0aSAnirudh Venkataramanan } 232a629cf0aSAnirudh Venkataramanan return; 233a629cf0aSAnirudh Venkataramanan } 234a629cf0aSAnirudh Venkataramanan 235a629cf0aSAnirudh Venkataramanan ice_for_each_traffic_class(n) { 236a629cf0aSAnirudh Venkataramanan if (!(vsi->tc_cfg.ena_tc & BIT(n))) 237a629cf0aSAnirudh Venkataramanan break; 238a629cf0aSAnirudh Venkataramanan 239a629cf0aSAnirudh Venkataramanan qoffset = vsi->tc_cfg.tc_info[n].qoffset; 240a629cf0aSAnirudh Venkataramanan qcount = vsi->tc_cfg.tc_info[n].qcount_tx; 2410754d65bSKiran Patil for (i = qoffset; i < (qoffset + qcount); i++) 2420754d65bSKiran Patil vsi->tx_rings[i]->dcb_tc = n; 2430754d65bSKiran Patil 2440754d65bSKiran Patil qcount = vsi->tc_cfg.tc_info[n].qcount_rx; 2450754d65bSKiran Patil for (i = qoffset; i < (qoffset + qcount); i++) 2460754d65bSKiran Patil vsi->rx_rings[i]->dcb_tc = n; 2470754d65bSKiran Patil } 2480754d65bSKiran Patil /* applicable only if "all_enatc" is set, which will be set from 2490754d65bSKiran Patil * setup_tc method as part of configuring channels 2500754d65bSKiran Patil */ 2510754d65bSKiran Patil if (vsi->all_enatc) { 2520754d65bSKiran Patil u8 first_droptc = ice_get_first_droptc(vsi); 2530754d65bSKiran Patil 2540754d65bSKiran Patil /* When DCB is configured, TC for ADQ queues (which are really 2550754d65bSKiran Patil * PF queues) should be the first drop TC of the main VSI 2560754d65bSKiran Patil */ 2570754d65bSKiran Patil ice_for_each_chnl_tc(n) { 2580754d65bSKiran Patil if (!(vsi->all_enatc & BIT(n))) 2590754d65bSKiran Patil break; 2600754d65bSKiran Patil 2610754d65bSKiran Patil qoffset = vsi->mqprio_qopt.qopt.offset[n]; 2620754d65bSKiran Patil qcount = vsi->mqprio_qopt.qopt.count[n]; 263a629cf0aSAnirudh Venkataramanan for (i = qoffset; i < (qoffset + qcount); i++) { 2640754d65bSKiran Patil vsi->tx_rings[i]->dcb_tc = first_droptc; 2650754d65bSKiran Patil vsi->rx_rings[i]->dcb_tc = first_droptc; 2660754d65bSKiran Patil } 2670754d65bSKiran Patil } 2680754d65bSKiran Patil } 2690754d65bSKiran Patil } 2700754d65bSKiran Patil 2710754d65bSKiran Patil /** 2720754d65bSKiran Patil * ice_dcb_ena_dis_vsi - disable certain VSIs for DCB config/reconfig 2730754d65bSKiran Patil * @pf: pointer to the PF instance 2740754d65bSKiran Patil * @ena: true to enable VSIs, false to disable 2750754d65bSKiran Patil * @locked: true if caller holds RTNL lock, false otherwise 2760754d65bSKiran Patil * 2770754d65bSKiran Patil * Before a new DCB configuration can be applied, VSIs of type PF, SWITCHDEV 2780754d65bSKiran Patil * and CHNL need to be brought down. Following completion of DCB configuration 2790754d65bSKiran Patil * the VSIs that were downed need to be brought up again. This helper function 2800754d65bSKiran Patil * does both. 2810754d65bSKiran Patil */ 2820754d65bSKiran Patil static void ice_dcb_ena_dis_vsi(struct ice_pf *pf, bool ena, bool locked) 2830754d65bSKiran Patil { 2840754d65bSKiran Patil int i; 2850754d65bSKiran Patil 2860754d65bSKiran Patil ice_for_each_vsi(pf, i) { 2870754d65bSKiran Patil struct ice_vsi *vsi = pf->vsi[i]; 2880754d65bSKiran Patil 2890754d65bSKiran Patil if (!vsi) 2900754d65bSKiran Patil continue; 2910754d65bSKiran Patil 2920754d65bSKiran Patil switch (vsi->type) { 2930754d65bSKiran Patil case ICE_VSI_CHNL: 2940754d65bSKiran Patil case ICE_VSI_SWITCHDEV_CTRL: 2950754d65bSKiran Patil case ICE_VSI_PF: 2960754d65bSKiran Patil if (ena) 2970754d65bSKiran Patil ice_ena_vsi(vsi, locked); 2980754d65bSKiran Patil else 2990754d65bSKiran Patil ice_dis_vsi(vsi, locked); 3000754d65bSKiran Patil break; 3010754d65bSKiran Patil default: 3020754d65bSKiran Patil continue; 303a629cf0aSAnirudh Venkataramanan } 304a629cf0aSAnirudh Venkataramanan } 305a629cf0aSAnirudh Venkataramanan } 306a629cf0aSAnirudh Venkataramanan 307a629cf0aSAnirudh Venkataramanan /** 308a29a912dSAvinash Dayanand * ice_dcb_bwchk - check if ETS bandwidth input parameters are correct 309a29a912dSAvinash Dayanand * @pf: pointer to the PF struct 310a29a912dSAvinash Dayanand * @dcbcfg: pointer to DCB config structure 311a29a912dSAvinash Dayanand */ 312a29a912dSAvinash Dayanand int ice_dcb_bwchk(struct ice_pf *pf, struct ice_dcbx_cfg *dcbcfg) 313a29a912dSAvinash Dayanand { 314a29a912dSAvinash Dayanand struct ice_dcb_ets_cfg *etscfg = &dcbcfg->etscfg; 315a29a912dSAvinash Dayanand u8 num_tc, total_bw = 0; 316a29a912dSAvinash Dayanand int i; 317a29a912dSAvinash Dayanand 318a29a912dSAvinash Dayanand /* returns number of contigous TCs and 1 TC for non-contigous TCs, 319a29a912dSAvinash Dayanand * since at least 1 TC has to be configured 320a29a912dSAvinash Dayanand */ 321a29a912dSAvinash Dayanand num_tc = ice_dcb_get_num_tc(dcbcfg); 322a29a912dSAvinash Dayanand 323a29a912dSAvinash Dayanand /* no bandwidth checks required if there's only one TC, so assign 324a29a912dSAvinash Dayanand * all bandwidth to TC0 and return 325a29a912dSAvinash Dayanand */ 326a29a912dSAvinash Dayanand if (num_tc == 1) { 327a29a912dSAvinash Dayanand etscfg->tcbwtable[0] = ICE_TC_MAX_BW; 328a29a912dSAvinash Dayanand return 0; 329a29a912dSAvinash Dayanand } 330a29a912dSAvinash Dayanand 331a29a912dSAvinash Dayanand for (i = 0; i < num_tc; i++) 332a29a912dSAvinash Dayanand total_bw += etscfg->tcbwtable[i]; 333a29a912dSAvinash Dayanand 334a29a912dSAvinash Dayanand if (!total_bw) { 335a29a912dSAvinash Dayanand etscfg->tcbwtable[0] = ICE_TC_MAX_BW; 336a29a912dSAvinash Dayanand } else if (total_bw != ICE_TC_MAX_BW) { 337a29a912dSAvinash Dayanand dev_err(ice_pf_to_dev(pf), "Invalid config, total bandwidth must equal 100\n"); 338a29a912dSAvinash Dayanand return -EINVAL; 339a29a912dSAvinash Dayanand } 340a29a912dSAvinash Dayanand 341a29a912dSAvinash Dayanand return 0; 342a29a912dSAvinash Dayanand } 343a29a912dSAvinash Dayanand 344a29a912dSAvinash Dayanand /** 3457b9ffc76SAnirudh Venkataramanan * ice_pf_dcb_cfg - Apply new DCB configuration 3467b9ffc76SAnirudh Venkataramanan * @pf: pointer to the PF struct 3477b9ffc76SAnirudh Venkataramanan * @new_cfg: DCBX config to apply 348e223eaecSDave Ertman * @locked: is the RTNL held 3497b9ffc76SAnirudh Venkataramanan */ 350e223eaecSDave Ertman int ice_pf_dcb_cfg(struct ice_pf *pf, struct ice_dcbx_cfg *new_cfg, bool locked) 3517b9ffc76SAnirudh Venkataramanan { 3527b9ffc76SAnirudh Venkataramanan struct ice_aqc_port_ets_elem buf = { 0 }; 353b94b013eSDave Ertman struct ice_dcbx_cfg *old_cfg, *curr_cfg; 3544015d11eSBrett Creeley struct device *dev = ice_pf_to_dev(pf); 355b94b013eSDave Ertman int ret = ICE_DCB_NO_HW_CHG; 356348048e7SDave Ertman struct iidc_event *event; 3579d614b64SAnirudh Venkataramanan struct ice_vsi *pf_vsi; 3587b9ffc76SAnirudh Venkataramanan 359fc2d1165SChinh T Cao curr_cfg = &pf->hw.port_info->qos_cfg.local_dcbx_cfg; 3607b9ffc76SAnirudh Venkataramanan 361b94b013eSDave Ertman /* FW does not care if change happened */ 362fc2d1165SChinh T Cao if (!pf->hw.port_info->qos_cfg.is_sw_lldp) 363b94b013eSDave Ertman ret = ICE_DCB_HW_CHG_RST; 364b94b013eSDave Ertman 3657b9ffc76SAnirudh Venkataramanan /* Enable DCB tagging only when more than one TC */ 3667b9ffc76SAnirudh Venkataramanan if (ice_dcb_get_num_tc(new_cfg) > 1) { 3674015d11eSBrett Creeley dev_dbg(dev, "DCB tagging enabled (num TC > 1)\n"); 36880fe30a8SMichal Wilczynski if (pf->hw.port_info->is_custom_tx_enabled) { 36980fe30a8SMichal Wilczynski dev_err(dev, "Custom Tx scheduler feature enabled, can't configure DCB\n"); 37080fe30a8SMichal Wilczynski return -EBUSY; 37180fe30a8SMichal Wilczynski } 37280fe30a8SMichal Wilczynski ice_tear_down_devlink_rate_tree(pf); 37380fe30a8SMichal Wilczynski 3747b9ffc76SAnirudh Venkataramanan set_bit(ICE_FLAG_DCB_ENA, pf->flags); 3757b9ffc76SAnirudh Venkataramanan } else { 3764015d11eSBrett Creeley dev_dbg(dev, "DCB tagging disabled (num TC = 1)\n"); 3777b9ffc76SAnirudh Venkataramanan clear_bit(ICE_FLAG_DCB_ENA, pf->flags); 3787b9ffc76SAnirudh Venkataramanan } 3797b9ffc76SAnirudh Venkataramanan 3807b9ffc76SAnirudh Venkataramanan if (!memcmp(new_cfg, curr_cfg, sizeof(*new_cfg))) { 3814015d11eSBrett Creeley dev_dbg(dev, "No change in DCB config required\n"); 3827b9ffc76SAnirudh Venkataramanan return ret; 3837b9ffc76SAnirudh Venkataramanan } 3847b9ffc76SAnirudh Venkataramanan 385a29a912dSAvinash Dayanand if (ice_dcb_bwchk(pf, new_cfg)) 386a29a912dSAvinash Dayanand return -EINVAL; 387a29a912dSAvinash Dayanand 3887b9ffc76SAnirudh Venkataramanan /* Store old config in case FW config fails */ 3899d614b64SAnirudh Venkataramanan old_cfg = kmemdup(curr_cfg, sizeof(*old_cfg), GFP_KERNEL); 3909d614b64SAnirudh Venkataramanan if (!old_cfg) 3919d614b64SAnirudh Venkataramanan return -ENOMEM; 3929d614b64SAnirudh Venkataramanan 3934015d11eSBrett Creeley dev_info(dev, "Commit DCB Configuration to the hardware\n"); 3949d614b64SAnirudh Venkataramanan pf_vsi = ice_get_main_vsi(pf); 3959d614b64SAnirudh Venkataramanan if (!pf_vsi) { 3964015d11eSBrett Creeley dev_dbg(dev, "PF VSI doesn't exist\n"); 3979d614b64SAnirudh Venkataramanan ret = -EINVAL; 3989d614b64SAnirudh Venkataramanan goto free_cfg; 3999d614b64SAnirudh Venkataramanan } 4007b9ffc76SAnirudh Venkataramanan 401348048e7SDave Ertman /* Notify AUX drivers about impending change to TCs */ 402348048e7SDave Ertman event = kzalloc(sizeof(*event), GFP_KERNEL); 403b81c191cSChristophe JAILLET if (!event) { 404b81c191cSChristophe JAILLET ret = -ENOMEM; 405b81c191cSChristophe JAILLET goto free_cfg; 406b81c191cSChristophe JAILLET } 407348048e7SDave Ertman 408348048e7SDave Ertman set_bit(IIDC_EVENT_BEFORE_TC_CHANGE, event->type); 409348048e7SDave Ertman ice_send_event_to_aux(pf, event); 410348048e7SDave Ertman kfree(event); 411348048e7SDave Ertman 4127b9ffc76SAnirudh Venkataramanan /* avoid race conditions by holding the lock while disabling and 4137b9ffc76SAnirudh Venkataramanan * re-enabling the VSI 4147b9ffc76SAnirudh Venkataramanan */ 415e223eaecSDave Ertman if (!locked) 4167b9ffc76SAnirudh Venkataramanan rtnl_lock(); 4170754d65bSKiran Patil 4180754d65bSKiran Patil /* disable VSIs affected by DCB changes */ 4190754d65bSKiran Patil ice_dcb_ena_dis_vsi(pf, false, true); 4207b9ffc76SAnirudh Venkataramanan 4217b9ffc76SAnirudh Venkataramanan memcpy(curr_cfg, new_cfg, sizeof(*curr_cfg)); 4227b9ffc76SAnirudh Venkataramanan memcpy(&curr_cfg->etsrec, &curr_cfg->etscfg, sizeof(curr_cfg->etsrec)); 423b94b013eSDave Ertman memcpy(&new_cfg->etsrec, &curr_cfg->etscfg, sizeof(curr_cfg->etsrec)); 4247b9ffc76SAnirudh Venkataramanan 4257b9ffc76SAnirudh Venkataramanan /* Only send new config to HW if we are in SW LLDP mode. Otherwise, 4267b9ffc76SAnirudh Venkataramanan * the new config came from the HW in the first place. 4277b9ffc76SAnirudh Venkataramanan */ 428fc2d1165SChinh T Cao if (pf->hw.port_info->qos_cfg.is_sw_lldp) { 4297b9ffc76SAnirudh Venkataramanan ret = ice_set_dcb_cfg(pf->hw.port_info); 4307b9ffc76SAnirudh Venkataramanan if (ret) { 4314015d11eSBrett Creeley dev_err(dev, "Set DCB Config failed\n"); 4327b9ffc76SAnirudh Venkataramanan /* Restore previous settings to local config */ 4337b9ffc76SAnirudh Venkataramanan memcpy(curr_cfg, old_cfg, sizeof(*curr_cfg)); 4347b9ffc76SAnirudh Venkataramanan goto out; 4357b9ffc76SAnirudh Venkataramanan } 4367b9ffc76SAnirudh Venkataramanan } 4377b9ffc76SAnirudh Venkataramanan 4387b9ffc76SAnirudh Venkataramanan ret = ice_query_port_ets(pf->hw.port_info, &buf, sizeof(buf), NULL); 4397b9ffc76SAnirudh Venkataramanan if (ret) { 4404015d11eSBrett Creeley dev_err(dev, "Query Port ETS failed\n"); 4417b9ffc76SAnirudh Venkataramanan goto out; 4427b9ffc76SAnirudh Venkataramanan } 4437b9ffc76SAnirudh Venkataramanan 4447b9ffc76SAnirudh Venkataramanan ice_pf_dcb_recfg(pf); 4457b9ffc76SAnirudh Venkataramanan 4467b9ffc76SAnirudh Venkataramanan out: 4470754d65bSKiran Patil /* enable previously downed VSIs */ 4480754d65bSKiran Patil ice_dcb_ena_dis_vsi(pf, true, true); 449e223eaecSDave Ertman if (!locked) 4507b9ffc76SAnirudh Venkataramanan rtnl_unlock(); 4519d614b64SAnirudh Venkataramanan free_cfg: 4529d614b64SAnirudh Venkataramanan kfree(old_cfg); 4537b9ffc76SAnirudh Venkataramanan return ret; 4547b9ffc76SAnirudh Venkataramanan } 4557b9ffc76SAnirudh Venkataramanan 4567b9ffc76SAnirudh Venkataramanan /** 4577829570eSUsha Ketineni * ice_cfg_etsrec_defaults - Set default ETS recommended DCB config 4587829570eSUsha Ketineni * @pi: port information structure 4597829570eSUsha Ketineni */ 4607829570eSUsha Ketineni static void ice_cfg_etsrec_defaults(struct ice_port_info *pi) 4617829570eSUsha Ketineni { 462fc2d1165SChinh T Cao struct ice_dcbx_cfg *dcbcfg = &pi->qos_cfg.local_dcbx_cfg; 4637829570eSUsha Ketineni u8 i; 4647829570eSUsha Ketineni 4657829570eSUsha Ketineni /* Ensure ETS recommended DCB configuration is not already set */ 4667829570eSUsha Ketineni if (dcbcfg->etsrec.maxtcs) 4677829570eSUsha Ketineni return; 4687829570eSUsha Ketineni 4697829570eSUsha Ketineni /* In CEE mode, set the default to 1 TC */ 4707829570eSUsha Ketineni dcbcfg->etsrec.maxtcs = 1; 4717829570eSUsha Ketineni for (i = 0; i < ICE_MAX_TRAFFIC_CLASS; i++) { 4727829570eSUsha Ketineni dcbcfg->etsrec.tcbwtable[i] = i ? 0 : 100; 4737829570eSUsha Ketineni dcbcfg->etsrec.tsatable[i] = i ? ICE_IEEE_TSA_STRICT : 4747829570eSUsha Ketineni ICE_IEEE_TSA_ETS; 4757829570eSUsha Ketineni } 4767829570eSUsha Ketineni } 4777829570eSUsha Ketineni 4787829570eSUsha Ketineni /** 4797829570eSUsha Ketineni * ice_dcb_need_recfg - Check if DCB needs reconfig 4807829570eSUsha Ketineni * @pf: board private structure 4817829570eSUsha Ketineni * @old_cfg: current DCB config 4827829570eSUsha Ketineni * @new_cfg: new DCB config 4837829570eSUsha Ketineni */ 4847829570eSUsha Ketineni static bool 4857829570eSUsha Ketineni ice_dcb_need_recfg(struct ice_pf *pf, struct ice_dcbx_cfg *old_cfg, 4867829570eSUsha Ketineni struct ice_dcbx_cfg *new_cfg) 4877829570eSUsha Ketineni { 4884015d11eSBrett Creeley struct device *dev = ice_pf_to_dev(pf); 4897829570eSUsha Ketineni bool need_reconfig = false; 4907829570eSUsha Ketineni 4917829570eSUsha Ketineni /* Check if ETS configuration has changed */ 4927829570eSUsha Ketineni if (memcmp(&new_cfg->etscfg, &old_cfg->etscfg, 4937829570eSUsha Ketineni sizeof(new_cfg->etscfg))) { 4947829570eSUsha Ketineni /* If Priority Table has changed reconfig is needed */ 4957829570eSUsha Ketineni if (memcmp(&new_cfg->etscfg.prio_table, 4967829570eSUsha Ketineni &old_cfg->etscfg.prio_table, 4977829570eSUsha Ketineni sizeof(new_cfg->etscfg.prio_table))) { 4987829570eSUsha Ketineni need_reconfig = true; 4994015d11eSBrett Creeley dev_dbg(dev, "ETS UP2TC changed.\n"); 5007829570eSUsha Ketineni } 5017829570eSUsha Ketineni 5027829570eSUsha Ketineni if (memcmp(&new_cfg->etscfg.tcbwtable, 5037829570eSUsha Ketineni &old_cfg->etscfg.tcbwtable, 5047829570eSUsha Ketineni sizeof(new_cfg->etscfg.tcbwtable))) 5054015d11eSBrett Creeley dev_dbg(dev, "ETS TC BW Table changed.\n"); 5067829570eSUsha Ketineni 5077829570eSUsha Ketineni if (memcmp(&new_cfg->etscfg.tsatable, 5087829570eSUsha Ketineni &old_cfg->etscfg.tsatable, 5097829570eSUsha Ketineni sizeof(new_cfg->etscfg.tsatable))) 5104015d11eSBrett Creeley dev_dbg(dev, "ETS TSA Table changed.\n"); 5117829570eSUsha Ketineni } 5127829570eSUsha Ketineni 5137829570eSUsha Ketineni /* Check if PFC configuration has changed */ 5147829570eSUsha Ketineni if (memcmp(&new_cfg->pfc, &old_cfg->pfc, sizeof(new_cfg->pfc))) { 5157829570eSUsha Ketineni need_reconfig = true; 5164015d11eSBrett Creeley dev_dbg(dev, "PFC config change detected.\n"); 5177829570eSUsha Ketineni } 5187829570eSUsha Ketineni 5197829570eSUsha Ketineni /* Check if APP Table has changed */ 5207829570eSUsha Ketineni if (memcmp(&new_cfg->app, &old_cfg->app, sizeof(new_cfg->app))) { 5217829570eSUsha Ketineni need_reconfig = true; 5224015d11eSBrett Creeley dev_dbg(dev, "APP Table change detected.\n"); 5237829570eSUsha Ketineni } 5247829570eSUsha Ketineni 5254015d11eSBrett Creeley dev_dbg(dev, "dcb need_reconfig=%d\n", need_reconfig); 5267829570eSUsha Ketineni return need_reconfig; 5277829570eSUsha Ketineni } 5287829570eSUsha Ketineni 5297829570eSUsha Ketineni /** 530b832c2f6SAnirudh Venkataramanan * ice_dcb_rebuild - rebuild DCB post reset 531b832c2f6SAnirudh Venkataramanan * @pf: physical function instance 532b832c2f6SAnirudh Venkataramanan */ 533b832c2f6SAnirudh Venkataramanan void ice_dcb_rebuild(struct ice_pf *pf) 534b832c2f6SAnirudh Venkataramanan { 535b832c2f6SAnirudh Venkataramanan struct ice_aqc_port_ets_elem buf = { 0 }; 5364015d11eSBrett Creeley struct device *dev = ice_pf_to_dev(pf); 537242b5e06SDave Ertman struct ice_dcbx_cfg *err_cfg; 5385e24d598STony Nguyen int ret; 539b832c2f6SAnirudh Venkataramanan 540b832c2f6SAnirudh Venkataramanan ret = ice_query_port_ets(pf->hw.port_info, &buf, sizeof(buf), NULL); 541b832c2f6SAnirudh Venkataramanan if (ret) { 5424015d11eSBrett Creeley dev_err(dev, "Query Port ETS failed\n"); 543b832c2f6SAnirudh Venkataramanan goto dcb_error; 544b832c2f6SAnirudh Venkataramanan } 545b832c2f6SAnirudh Venkataramanan 546242b5e06SDave Ertman mutex_lock(&pf->tc_mutex); 5477829570eSUsha Ketineni 548fc2d1165SChinh T Cao if (!pf->hw.port_info->qos_cfg.is_sw_lldp) 5497829570eSUsha Ketineni ice_cfg_etsrec_defaults(pf->hw.port_info); 550242b5e06SDave Ertman 551b832c2f6SAnirudh Venkataramanan ret = ice_set_dcb_cfg(pf->hw.port_info); 552b832c2f6SAnirudh Venkataramanan if (ret) { 553242b5e06SDave Ertman dev_err(dev, "Failed to set DCB config in rebuild\n"); 554b832c2f6SAnirudh Venkataramanan goto dcb_error; 555b832c2f6SAnirudh Venkataramanan } 556b832c2f6SAnirudh Venkataramanan 557fc2d1165SChinh T Cao if (!pf->hw.port_info->qos_cfg.is_sw_lldp) { 558242b5e06SDave Ertman ret = ice_cfg_lldp_mib_change(&pf->hw, true); 559fc2d1165SChinh T Cao if (ret && !pf->hw.port_info->qos_cfg.is_sw_lldp) { 560242b5e06SDave Ertman dev_err(dev, "Failed to register for MIB changes\n"); 561b832c2f6SAnirudh Venkataramanan goto dcb_error; 562b832c2f6SAnirudh Venkataramanan } 563b832c2f6SAnirudh Venkataramanan } 564242b5e06SDave Ertman 5650ce6c34aSDave Ertman dev_info(dev, "DCB info restored\n"); 566b832c2f6SAnirudh Venkataramanan ret = ice_query_port_ets(pf->hw.port_info, &buf, sizeof(buf), NULL); 567b832c2f6SAnirudh Venkataramanan if (ret) { 5684015d11eSBrett Creeley dev_err(dev, "Query Port ETS failed\n"); 569b832c2f6SAnirudh Venkataramanan goto dcb_error; 570b832c2f6SAnirudh Venkataramanan } 571b832c2f6SAnirudh Venkataramanan 572242b5e06SDave Ertman mutex_unlock(&pf->tc_mutex); 573242b5e06SDave Ertman 574b832c2f6SAnirudh Venkataramanan return; 575b832c2f6SAnirudh Venkataramanan 576b832c2f6SAnirudh Venkataramanan dcb_error: 5774015d11eSBrett Creeley dev_err(dev, "Disabling DCB until new settings occur\n"); 578242b5e06SDave Ertman err_cfg = kzalloc(sizeof(*err_cfg), GFP_KERNEL); 579242b5e06SDave Ertman if (!err_cfg) { 580242b5e06SDave Ertman mutex_unlock(&pf->tc_mutex); 5819efe35d0STony Nguyen return; 582242b5e06SDave Ertman } 5839efe35d0STony Nguyen 584242b5e06SDave Ertman err_cfg->etscfg.willing = true; 585242b5e06SDave Ertman err_cfg->etscfg.tcbwtable[0] = ICE_TC_MAX_BW; 586242b5e06SDave Ertman err_cfg->etscfg.tsatable[0] = ICE_IEEE_TSA_ETS; 587242b5e06SDave Ertman memcpy(&err_cfg->etsrec, &err_cfg->etscfg, sizeof(err_cfg->etsrec)); 588ac614b13SBruce Allan /* Coverity warns the return code of ice_pf_dcb_cfg() is not checked 589ac614b13SBruce Allan * here as is done for other calls to that function. That check is 590ac614b13SBruce Allan * not necessary since this is in this function's error cleanup path. 591ac614b13SBruce Allan * Suppress the Coverity warning with the following comment... 592ac614b13SBruce Allan */ 593ac614b13SBruce Allan /* coverity[check_return] */ 594242b5e06SDave Ertman ice_pf_dcb_cfg(pf, err_cfg, false); 595242b5e06SDave Ertman kfree(err_cfg); 596242b5e06SDave Ertman 597242b5e06SDave Ertman mutex_unlock(&pf->tc_mutex); 598b832c2f6SAnirudh Venkataramanan } 599b832c2f6SAnirudh Venkataramanan 600b832c2f6SAnirudh Venkataramanan /** 6017b9ffc76SAnirudh Venkataramanan * ice_dcb_init_cfg - set the initial DCB config in SW 6022f2da36eSAnirudh Venkataramanan * @pf: PF to apply config to 603e223eaecSDave Ertman * @locked: Is the RTNL held 6047b9ffc76SAnirudh Venkataramanan */ 605e223eaecSDave Ertman static int ice_dcb_init_cfg(struct ice_pf *pf, bool locked) 6067b9ffc76SAnirudh Venkataramanan { 6077b9ffc76SAnirudh Venkataramanan struct ice_dcbx_cfg *newcfg; 6087b9ffc76SAnirudh Venkataramanan struct ice_port_info *pi; 6097b9ffc76SAnirudh Venkataramanan int ret = 0; 6107b9ffc76SAnirudh Venkataramanan 6117b9ffc76SAnirudh Venkataramanan pi = pf->hw.port_info; 612fc2d1165SChinh T Cao newcfg = kmemdup(&pi->qos_cfg.local_dcbx_cfg, sizeof(*newcfg), 613fc2d1165SChinh T Cao GFP_KERNEL); 6147b9ffc76SAnirudh Venkataramanan if (!newcfg) 6157b9ffc76SAnirudh Venkataramanan return -ENOMEM; 6167b9ffc76SAnirudh Venkataramanan 617fc2d1165SChinh T Cao memset(&pi->qos_cfg.local_dcbx_cfg, 0, sizeof(*newcfg)); 6187b9ffc76SAnirudh Venkataramanan 6194015d11eSBrett Creeley dev_info(ice_pf_to_dev(pf), "Configuring initial DCB values\n"); 620e223eaecSDave Ertman if (ice_pf_dcb_cfg(pf, newcfg, locked)) 6217b9ffc76SAnirudh Venkataramanan ret = -EINVAL; 6227b9ffc76SAnirudh Venkataramanan 6239efe35d0STony Nguyen kfree(newcfg); 6247b9ffc76SAnirudh Venkataramanan 6257b9ffc76SAnirudh Venkataramanan return ret; 6267b9ffc76SAnirudh Venkataramanan } 6277b9ffc76SAnirudh Venkataramanan 6287b9ffc76SAnirudh Venkataramanan /** 6294ee656bbSTony Nguyen * ice_dcb_sw_dflt_cfg - Apply a default DCB config 6302f2da36eSAnirudh Venkataramanan * @pf: PF to apply config to 6314ee656bbSTony Nguyen * @ets_willing: configure ETS willing 632e223eaecSDave Ertman * @locked: was this function called with RTNL held 6330deab659SAnirudh Venkataramanan */ 6342a87bd73SDave Ertman int ice_dcb_sw_dflt_cfg(struct ice_pf *pf, bool ets_willing, bool locked) 6350deab659SAnirudh Venkataramanan { 6360deab659SAnirudh Venkataramanan struct ice_aqc_port_ets_elem buf = { 0 }; 6370deab659SAnirudh Venkataramanan struct ice_dcbx_cfg *dcbcfg; 6380deab659SAnirudh Venkataramanan struct ice_port_info *pi; 6390deab659SAnirudh Venkataramanan struct ice_hw *hw; 6400deab659SAnirudh Venkataramanan int ret; 6410deab659SAnirudh Venkataramanan 6420deab659SAnirudh Venkataramanan hw = &pf->hw; 6430deab659SAnirudh Venkataramanan pi = hw->port_info; 6449efe35d0STony Nguyen dcbcfg = kzalloc(sizeof(*dcbcfg), GFP_KERNEL); 6459efe35d0STony Nguyen if (!dcbcfg) 6469efe35d0STony Nguyen return -ENOMEM; 6470deab659SAnirudh Venkataramanan 648fc2d1165SChinh T Cao memset(&pi->qos_cfg.local_dcbx_cfg, 0, sizeof(*dcbcfg)); 6490deab659SAnirudh Venkataramanan 650cfbf1367SPaul Greenwalt dcbcfg->etscfg.willing = ets_willing ? 1 : 0; 651a257f188SUsha Ketineni dcbcfg->etscfg.maxtcs = hw->func_caps.common_cap.maxtc; 6520deab659SAnirudh Venkataramanan dcbcfg->etscfg.tcbwtable[0] = 100; 6530deab659SAnirudh Venkataramanan dcbcfg->etscfg.tsatable[0] = ICE_IEEE_TSA_ETS; 6540deab659SAnirudh Venkataramanan 6550deab659SAnirudh Venkataramanan memcpy(&dcbcfg->etsrec, &dcbcfg->etscfg, 6560deab659SAnirudh Venkataramanan sizeof(dcbcfg->etsrec)); 6570deab659SAnirudh Venkataramanan dcbcfg->etsrec.willing = 0; 6580deab659SAnirudh Venkataramanan 6590deab659SAnirudh Venkataramanan dcbcfg->pfc.willing = 1; 660a257f188SUsha Ketineni dcbcfg->pfc.pfccap = hw->func_caps.common_cap.maxtc; 6610deab659SAnirudh Venkataramanan 6620deab659SAnirudh Venkataramanan dcbcfg->numapps = 1; 6630deab659SAnirudh Venkataramanan dcbcfg->app[0].selector = ICE_APP_SEL_ETHTYPE; 6640deab659SAnirudh Venkataramanan dcbcfg->app[0].priority = 3; 665d41f26b5SBruce Allan dcbcfg->app[0].prot_id = ETH_P_FCOE; 6660deab659SAnirudh Venkataramanan 667e223eaecSDave Ertman ret = ice_pf_dcb_cfg(pf, dcbcfg, locked); 6689efe35d0STony Nguyen kfree(dcbcfg); 6690deab659SAnirudh Venkataramanan if (ret) 6700deab659SAnirudh Venkataramanan return ret; 6710deab659SAnirudh Venkataramanan 6720deab659SAnirudh Venkataramanan return ice_query_port_ets(pi, &buf, sizeof(buf), NULL); 6730deab659SAnirudh Venkataramanan } 6740deab659SAnirudh Venkataramanan 6750deab659SAnirudh Venkataramanan /** 676cfbf1367SPaul Greenwalt * ice_dcb_tc_contig - Check that TCs are contiguous 677cfbf1367SPaul Greenwalt * @prio_table: pointer to priority table 678cfbf1367SPaul Greenwalt * 679cfbf1367SPaul Greenwalt * Check if TCs begin with TC0 and are contiguous 680cfbf1367SPaul Greenwalt */ 681cfbf1367SPaul Greenwalt static bool ice_dcb_tc_contig(u8 *prio_table) 682cfbf1367SPaul Greenwalt { 68389154002SDave Ertman bool found_empty = false; 68489154002SDave Ertman u8 used_tc = 0; 685cfbf1367SPaul Greenwalt int i; 686cfbf1367SPaul Greenwalt 68789154002SDave Ertman /* Create a bitmap of used TCs */ 68889154002SDave Ertman for (i = 0; i < CEE_DCBX_MAX_PRIO; i++) 68989154002SDave Ertman used_tc |= BIT(prio_table[i]); 690cfbf1367SPaul Greenwalt 69189154002SDave Ertman for (i = 0; i < CEE_DCBX_MAX_PRIO; i++) { 69289154002SDave Ertman if (used_tc & BIT(i)) { 69389154002SDave Ertman if (found_empty) 694cfbf1367SPaul Greenwalt return false; 69589154002SDave Ertman } else { 69689154002SDave Ertman found_empty = true; 69789154002SDave Ertman } 698cfbf1367SPaul Greenwalt } 699cfbf1367SPaul Greenwalt 700cfbf1367SPaul Greenwalt return true; 701cfbf1367SPaul Greenwalt } 702cfbf1367SPaul Greenwalt 703cfbf1367SPaul Greenwalt /** 704cfbf1367SPaul Greenwalt * ice_dcb_noncontig_cfg - Configure DCB for non-contiguous TCs 705cfbf1367SPaul Greenwalt * @pf: pointer to the PF struct 706cfbf1367SPaul Greenwalt * 707cfbf1367SPaul Greenwalt * If non-contiguous TCs, then configure SW DCB with TC0 and ETS non-willing 708cfbf1367SPaul Greenwalt */ 709cfbf1367SPaul Greenwalt static int ice_dcb_noncontig_cfg(struct ice_pf *pf) 710cfbf1367SPaul Greenwalt { 711fc2d1165SChinh T Cao struct ice_dcbx_cfg *dcbcfg = &pf->hw.port_info->qos_cfg.local_dcbx_cfg; 7124015d11eSBrett Creeley struct device *dev = ice_pf_to_dev(pf); 713cfbf1367SPaul Greenwalt int ret; 714cfbf1367SPaul Greenwalt 715cfbf1367SPaul Greenwalt /* Configure SW DCB default with ETS non-willing */ 716cfbf1367SPaul Greenwalt ret = ice_dcb_sw_dflt_cfg(pf, false, true); 717cfbf1367SPaul Greenwalt if (ret) { 7184015d11eSBrett Creeley dev_err(dev, "Failed to set local DCB config %d\n", ret); 719cfbf1367SPaul Greenwalt return ret; 720cfbf1367SPaul Greenwalt } 721cfbf1367SPaul Greenwalt 722cfbf1367SPaul Greenwalt /* Reconfigure with ETS willing so that FW will send LLDP MIB event */ 723cfbf1367SPaul Greenwalt dcbcfg->etscfg.willing = 1; 724cfbf1367SPaul Greenwalt ret = ice_set_dcb_cfg(pf->hw.port_info); 725cfbf1367SPaul Greenwalt if (ret) 7264015d11eSBrett Creeley dev_err(dev, "Failed to set DCB to unwilling\n"); 727cfbf1367SPaul Greenwalt 728cfbf1367SPaul Greenwalt return ret; 729cfbf1367SPaul Greenwalt } 730cfbf1367SPaul Greenwalt 731cfbf1367SPaul Greenwalt /** 732cfbf1367SPaul Greenwalt * ice_pf_dcb_recfg - Reconfigure all VEBs and VSIs 733cfbf1367SPaul Greenwalt * @pf: pointer to the PF struct 734cfbf1367SPaul Greenwalt * 735cfbf1367SPaul Greenwalt * Assumed caller has already disabled all VSIs before 736cfbf1367SPaul Greenwalt * calling this function. Reconfiguring DCB based on 737cfbf1367SPaul Greenwalt * local_dcbx_cfg. 738cfbf1367SPaul Greenwalt */ 73987324e74SHenry Tieman void ice_pf_dcb_recfg(struct ice_pf *pf) 740cfbf1367SPaul Greenwalt { 741fc2d1165SChinh T Cao struct ice_dcbx_cfg *dcbcfg = &pf->hw.port_info->qos_cfg.local_dcbx_cfg; 742348048e7SDave Ertman struct iidc_event *event; 743cfbf1367SPaul Greenwalt u8 tc_map = 0; 744cfbf1367SPaul Greenwalt int v, ret; 745cfbf1367SPaul Greenwalt 746cfbf1367SPaul Greenwalt /* Update each VSI */ 747cfbf1367SPaul Greenwalt ice_for_each_vsi(pf, v) { 7484015d11eSBrett Creeley struct ice_vsi *vsi = pf->vsi[v]; 7494015d11eSBrett Creeley 7504015d11eSBrett Creeley if (!vsi) 751cfbf1367SPaul Greenwalt continue; 752cfbf1367SPaul Greenwalt 7534015d11eSBrett Creeley if (vsi->type == ICE_VSI_PF) { 754cfbf1367SPaul Greenwalt tc_map = ice_dcb_get_ena_tc(dcbcfg); 755cfbf1367SPaul Greenwalt 756cfbf1367SPaul Greenwalt /* If DCBX request non-contiguous TC, then configure 757cfbf1367SPaul Greenwalt * default TC 758cfbf1367SPaul Greenwalt */ 759cfbf1367SPaul Greenwalt if (!ice_dcb_tc_contig(dcbcfg->etscfg.prio_table)) { 760cfbf1367SPaul Greenwalt tc_map = ICE_DFLT_TRAFFIC_CLASS; 761cfbf1367SPaul Greenwalt ice_dcb_noncontig_cfg(pf); 762cfbf1367SPaul Greenwalt } 7630754d65bSKiran Patil } else if (vsi->type == ICE_VSI_CHNL) { 7640754d65bSKiran Patil tc_map = BIT(ice_get_first_droptc(vsi)); 765cfbf1367SPaul Greenwalt } else { 766cfbf1367SPaul Greenwalt tc_map = ICE_DFLT_TRAFFIC_CLASS; 767cfbf1367SPaul Greenwalt } 768cfbf1367SPaul Greenwalt 7694015d11eSBrett Creeley ret = ice_vsi_cfg_tc(vsi, tc_map); 770cfbf1367SPaul Greenwalt if (ret) { 7714015d11eSBrett Creeley dev_err(ice_pf_to_dev(pf), "Failed to config TC for VSI index: %d\n", 7724015d11eSBrett Creeley vsi->idx); 773cfbf1367SPaul Greenwalt continue; 774cfbf1367SPaul Greenwalt } 7750754d65bSKiran Patil /* no need to proceed with remaining cfg if it is CHNL 7760754d65bSKiran Patil * or switchdev VSI 7777aae80ceSWojciech Drewek */ 7780754d65bSKiran Patil if (vsi->type == ICE_VSI_CHNL || 7790754d65bSKiran Patil vsi->type == ICE_VSI_SWITCHDEV_CTRL) 7807aae80ceSWojciech Drewek continue; 781cfbf1367SPaul Greenwalt 7824015d11eSBrett Creeley ice_vsi_map_rings_to_vectors(vsi); 7834015d11eSBrett Creeley if (vsi->type == ICE_VSI_PF) 7844015d11eSBrett Creeley ice_dcbnl_set_all(vsi); 785cfbf1367SPaul Greenwalt } 786348048e7SDave Ertman /* Notify the AUX drivers that TC change is finished */ 787348048e7SDave Ertman event = kzalloc(sizeof(*event), GFP_KERNEL); 788348048e7SDave Ertman if (!event) 789348048e7SDave Ertman return; 790348048e7SDave Ertman 791348048e7SDave Ertman set_bit(IIDC_EVENT_AFTER_TC_CHANGE, event->type); 792348048e7SDave Ertman ice_send_event_to_aux(pf, event); 793348048e7SDave Ertman kfree(event); 794cfbf1367SPaul Greenwalt } 795cfbf1367SPaul Greenwalt 796cfbf1367SPaul Greenwalt /** 79737b6f646SAnirudh Venkataramanan * ice_init_pf_dcb - initialize DCB for a PF 7982f2da36eSAnirudh Venkataramanan * @pf: PF to initialize DCB for 799e223eaecSDave Ertman * @locked: Was function called with RTNL held 80037b6f646SAnirudh Venkataramanan */ 801e223eaecSDave Ertman int ice_init_pf_dcb(struct ice_pf *pf, bool locked) 80237b6f646SAnirudh Venkataramanan { 8034015d11eSBrett Creeley struct device *dev = ice_pf_to_dev(pf); 80437b6f646SAnirudh Venkataramanan struct ice_port_info *port_info; 80537b6f646SAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 8067b9ffc76SAnirudh Venkataramanan int err; 80737b6f646SAnirudh Venkataramanan 80837b6f646SAnirudh Venkataramanan port_info = hw->port_info; 80937b6f646SAnirudh Venkataramanan 810ea300f41SDave Ertman err = ice_init_dcb(hw, false); 811fc2d1165SChinh T Cao if (err && !port_info->qos_cfg.is_sw_lldp) { 8124015d11eSBrett Creeley dev_err(dev, "Error initializing DCB %d\n", err); 813473ca574SDave Ertman goto dcb_init_err; 814473ca574SDave Ertman } 815473ca574SDave Ertman 81619cce2c6SAnirudh Venkataramanan dev_info(dev, "DCB is enabled in the hardware, max number of TCs supported on this port are %d\n", 817a257f188SUsha Ketineni pf->hw.func_caps.common_cap.maxtc); 818473ca574SDave Ertman if (err) { 819241c8cf0SPaul Greenwalt struct ice_vsi *pf_vsi; 820241c8cf0SPaul Greenwalt 821473ca574SDave Ertman /* FW LLDP is disabled, activate SW DCBX/LLDP mode */ 8224015d11eSBrett Creeley dev_info(dev, "FW LLDP is disabled, DCBx/LLDP in SW mode.\n"); 82384a118abSDave Ertman clear_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags); 8242a87bd73SDave Ertman err = ice_aq_set_pfc_mode(&pf->hw, ICE_AQC_PFC_VLAN_BASED_PFC, 8252a87bd73SDave Ertman NULL); 8262a87bd73SDave Ertman if (err) 8272a87bd73SDave Ertman dev_info(dev, "Failed to set VLAN PFC mode\n"); 8282a87bd73SDave Ertman 829cfbf1367SPaul Greenwalt err = ice_dcb_sw_dflt_cfg(pf, true, locked); 8300deab659SAnirudh Venkataramanan if (err) { 83119cce2c6SAnirudh Venkataramanan dev_err(dev, "Failed to set local DCB config %d\n", 83219cce2c6SAnirudh Venkataramanan err); 8330deab659SAnirudh Venkataramanan err = -EIO; 8347b9ffc76SAnirudh Venkataramanan goto dcb_init_err; 8350deab659SAnirudh Venkataramanan } 8360deab659SAnirudh Venkataramanan 837241c8cf0SPaul Greenwalt /* If the FW DCBX engine is not running then Rx LLDP packets 838241c8cf0SPaul Greenwalt * need to be redirected up the stack. 839241c8cf0SPaul Greenwalt */ 840241c8cf0SPaul Greenwalt pf_vsi = ice_get_main_vsi(pf); 841241c8cf0SPaul Greenwalt if (!pf_vsi) { 8424015d11eSBrett Creeley dev_err(dev, "Failed to set local DCB config\n"); 843241c8cf0SPaul Greenwalt err = -EIO; 844241c8cf0SPaul Greenwalt goto dcb_init_err; 845241c8cf0SPaul Greenwalt } 846241c8cf0SPaul Greenwalt 847241c8cf0SPaul Greenwalt ice_cfg_sw_lldp(pf_vsi, false, true); 848241c8cf0SPaul Greenwalt 84927d9be98SAvinash Dayanand pf->dcbx_cap = ice_dcb_get_mode(port_info, true); 8500deab659SAnirudh Venkataramanan return 0; 8510deab659SAnirudh Venkataramanan } 8527b9ffc76SAnirudh Venkataramanan 85384a118abSDave Ertman set_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags); 8541b0c3247SDave Ertman 85527d9be98SAvinash Dayanand /* DCBX/LLDP enabled in FW, set DCBNL mode advertisement */ 85627d9be98SAvinash Dayanand pf->dcbx_cap = ice_dcb_get_mode(port_info, false); 8577b9ffc76SAnirudh Venkataramanan 858e223eaecSDave Ertman err = ice_dcb_init_cfg(pf, locked); 8597b9ffc76SAnirudh Venkataramanan if (err) 8607b9ffc76SAnirudh Venkataramanan goto dcb_init_err; 8617b9ffc76SAnirudh Venkataramanan 862*91dbcb91STony Nguyen return 0; 8637b9ffc76SAnirudh Venkataramanan 8647b9ffc76SAnirudh Venkataramanan dcb_init_err: 8657b9ffc76SAnirudh Venkataramanan dev_err(dev, "DCB init failed\n"); 8667b9ffc76SAnirudh Venkataramanan return err; 86737b6f646SAnirudh Venkataramanan } 86800cc3f1bSAnirudh Venkataramanan 86900cc3f1bSAnirudh Venkataramanan /** 8704b0fdcebSAnirudh Venkataramanan * ice_update_dcb_stats - Update DCB stats counters 8714b0fdcebSAnirudh Venkataramanan * @pf: PF whose stats needs to be updated 8724b0fdcebSAnirudh Venkataramanan */ 8734b0fdcebSAnirudh Venkataramanan void ice_update_dcb_stats(struct ice_pf *pf) 8744b0fdcebSAnirudh Venkataramanan { 8754b0fdcebSAnirudh Venkataramanan struct ice_hw_port_stats *prev_ps, *cur_ps; 8764b0fdcebSAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 8779e7a5d17SUsha Ketineni u8 port; 8784b0fdcebSAnirudh Venkataramanan int i; 8794b0fdcebSAnirudh Venkataramanan 8809e7a5d17SUsha Ketineni port = hw->port_info->lport; 8814b0fdcebSAnirudh Venkataramanan prev_ps = &pf->stats_prev; 8824b0fdcebSAnirudh Venkataramanan cur_ps = &pf->stats; 8834b0fdcebSAnirudh Venkataramanan 8842fd5e433SBenjamin Mikailenko if (ice_is_reset_in_progress(pf->state)) 8852fd5e433SBenjamin Mikailenko pf->stat_prev_loaded = false; 8862fd5e433SBenjamin Mikailenko 8874b0fdcebSAnirudh Venkataramanan for (i = 0; i < 8; i++) { 8889e7a5d17SUsha Ketineni ice_stat_update32(hw, GLPRT_PXOFFRXC(port, i), 8894b0fdcebSAnirudh Venkataramanan pf->stat_prev_loaded, 8904b0fdcebSAnirudh Venkataramanan &prev_ps->priority_xoff_rx[i], 8914b0fdcebSAnirudh Venkataramanan &cur_ps->priority_xoff_rx[i]); 8929e7a5d17SUsha Ketineni ice_stat_update32(hw, GLPRT_PXONRXC(port, i), 8934b0fdcebSAnirudh Venkataramanan pf->stat_prev_loaded, 8944b0fdcebSAnirudh Venkataramanan &prev_ps->priority_xon_rx[i], 8954b0fdcebSAnirudh Venkataramanan &cur_ps->priority_xon_rx[i]); 8969e7a5d17SUsha Ketineni ice_stat_update32(hw, GLPRT_PXONTXC(port, i), 8974b0fdcebSAnirudh Venkataramanan pf->stat_prev_loaded, 8984b0fdcebSAnirudh Venkataramanan &prev_ps->priority_xon_tx[i], 8994b0fdcebSAnirudh Venkataramanan &cur_ps->priority_xon_tx[i]); 9009e7a5d17SUsha Ketineni ice_stat_update32(hw, GLPRT_PXOFFTXC(port, i), 9014b0fdcebSAnirudh Venkataramanan pf->stat_prev_loaded, 9024b0fdcebSAnirudh Venkataramanan &prev_ps->priority_xoff_tx[i], 9034b0fdcebSAnirudh Venkataramanan &cur_ps->priority_xoff_tx[i]); 9049e7a5d17SUsha Ketineni ice_stat_update32(hw, GLPRT_RXON2OFFCNT(port, i), 9054b0fdcebSAnirudh Venkataramanan pf->stat_prev_loaded, 9064b0fdcebSAnirudh Venkataramanan &prev_ps->priority_xon_2_xoff[i], 9074b0fdcebSAnirudh Venkataramanan &cur_ps->priority_xon_2_xoff[i]); 9084b0fdcebSAnirudh Venkataramanan } 9094b0fdcebSAnirudh Venkataramanan } 9104b0fdcebSAnirudh Venkataramanan 9114b0fdcebSAnirudh Venkataramanan /** 9125f6aa50eSAnirudh Venkataramanan * ice_tx_prepare_vlan_flags_dcb - prepare VLAN tagging for DCB 9135f6aa50eSAnirudh Venkataramanan * @tx_ring: ring to send buffer on 9145f6aa50eSAnirudh Venkataramanan * @first: pointer to struct ice_tx_buf 9152bb19d6eSBrett Creeley * 9162bb19d6eSBrett Creeley * This should not be called if the outer VLAN is software offloaded as the VLAN 9172bb19d6eSBrett Creeley * tag will already be configured with the correct ID and priority bits 9185f6aa50eSAnirudh Venkataramanan */ 9192bb19d6eSBrett Creeley void 920e72bba21SMaciej Fijalkowski ice_tx_prepare_vlan_flags_dcb(struct ice_tx_ring *tx_ring, 9215f6aa50eSAnirudh Venkataramanan struct ice_tx_buf *first) 9225f6aa50eSAnirudh Venkataramanan { 9235f6aa50eSAnirudh Venkataramanan struct sk_buff *skb = first->skb; 9245f6aa50eSAnirudh Venkataramanan 9255f6aa50eSAnirudh Venkataramanan if (!test_bit(ICE_FLAG_DCB_ENA, tx_ring->vsi->back->flags)) 9262bb19d6eSBrett Creeley return; 9275f6aa50eSAnirudh Venkataramanan 9285f6aa50eSAnirudh Venkataramanan /* Insert 802.1p priority into VLAN header */ 9290d54d8f7SBrett Creeley if ((first->tx_flags & ICE_TX_FLAGS_HW_VLAN || 9300d54d8f7SBrett Creeley first->tx_flags & ICE_TX_FLAGS_HW_OUTER_SINGLE_VLAN) || 9315f6aa50eSAnirudh Venkataramanan skb->priority != TC_PRIO_CONTROL) { 9325f6aa50eSAnirudh Venkataramanan first->tx_flags &= ~ICE_TX_FLAGS_VLAN_PR_M; 9335f6aa50eSAnirudh Venkataramanan /* Mask the lower 3 bits to set the 802.1p priority */ 9345f6aa50eSAnirudh Venkataramanan first->tx_flags |= (skb->priority & 0x7) << 9355f6aa50eSAnirudh Venkataramanan ICE_TX_FLAGS_VLAN_PR_S; 9362bb19d6eSBrett Creeley /* if this is not already set it means a VLAN 0 + priority needs 9372bb19d6eSBrett Creeley * to be offloaded 9382bb19d6eSBrett Creeley */ 9390d54d8f7SBrett Creeley if (tx_ring->flags & ICE_TX_FLAGS_RING_VLAN_L2TAG2) 9400d54d8f7SBrett Creeley first->tx_flags |= ICE_TX_FLAGS_HW_OUTER_SINGLE_VLAN; 9410d54d8f7SBrett Creeley else 9425f6aa50eSAnirudh Venkataramanan first->tx_flags |= ICE_TX_FLAGS_HW_VLAN; 9435f6aa50eSAnirudh Venkataramanan } 9445f6aa50eSAnirudh Venkataramanan } 9455f6aa50eSAnirudh Venkataramanan 9465f6aa50eSAnirudh Venkataramanan /** 9477d8d7754SAnatolii Gerasymenko * ice_dcb_is_mib_change_pending - Check if MIB change is pending 9487d8d7754SAnatolii Gerasymenko * @state: MIB change state 9497d8d7754SAnatolii Gerasymenko */ 9507d8d7754SAnatolii Gerasymenko static bool ice_dcb_is_mib_change_pending(u8 state) 9517d8d7754SAnatolii Gerasymenko { 9527d8d7754SAnatolii Gerasymenko return ICE_AQ_LLDP_MIB_CHANGE_PENDING == 9537d8d7754SAnatolii Gerasymenko FIELD_GET(ICE_AQ_LLDP_MIB_CHANGE_STATE_M, state); 9547d8d7754SAnatolii Gerasymenko } 9557d8d7754SAnatolii Gerasymenko 9567d8d7754SAnatolii Gerasymenko /** 95700cc3f1bSAnirudh Venkataramanan * ice_dcb_process_lldp_set_mib_change - Process MIB change 95800cc3f1bSAnirudh Venkataramanan * @pf: ptr to ice_pf 95900cc3f1bSAnirudh Venkataramanan * @event: pointer to the admin queue receive event 96000cc3f1bSAnirudh Venkataramanan */ 96100cc3f1bSAnirudh Venkataramanan void 96200cc3f1bSAnirudh Venkataramanan ice_dcb_process_lldp_set_mib_change(struct ice_pf *pf, 96300cc3f1bSAnirudh Venkataramanan struct ice_rq_event_info *event) 96400cc3f1bSAnirudh Venkataramanan { 965a17a5ff6SUsha Ketineni struct ice_aqc_port_ets_elem buf = { 0 }; 9664015d11eSBrett Creeley struct device *dev = ice_pf_to_dev(pf); 967a17a5ff6SUsha Ketineni struct ice_aqc_lldp_get_mib *mib; 968a17a5ff6SUsha Ketineni struct ice_dcbx_cfg tmp_dcbx_cfg; 9697d8d7754SAnatolii Gerasymenko bool pending_handled = true; 970a17a5ff6SUsha Ketineni bool need_reconfig = false; 971a17a5ff6SUsha Ketineni struct ice_port_info *pi; 9726dae8aa0SBruce Allan u8 mib_type; 973a17a5ff6SUsha Ketineni int ret; 97400cc3f1bSAnirudh Venkataramanan 975a17a5ff6SUsha Ketineni /* Not DCB capable or capability disabled */ 976a17a5ff6SUsha Ketineni if (!(test_bit(ICE_FLAG_DCB_CAPABLE, pf->flags))) 97700cc3f1bSAnirudh Venkataramanan return; 97800cc3f1bSAnirudh Venkataramanan 979a17a5ff6SUsha Ketineni if (pf->dcbx_cap & DCB_CAP_DCBX_HOST) { 9804015d11eSBrett Creeley dev_dbg(dev, "MIB Change Event in HOST mode\n"); 981a17a5ff6SUsha Ketineni return; 98200cc3f1bSAnirudh Venkataramanan } 983a17a5ff6SUsha Ketineni 984a17a5ff6SUsha Ketineni pi = pf->hw.port_info; 985a17a5ff6SUsha Ketineni mib = (struct ice_aqc_lldp_get_mib *)&event->desc.params.raw; 9867d8d7754SAnatolii Gerasymenko 987a17a5ff6SUsha Ketineni /* Ignore if event is not for Nearest Bridge */ 9887d8d7754SAnatolii Gerasymenko mib_type = FIELD_GET(ICE_AQ_LLDP_BRID_TYPE_M, mib->type); 9896dae8aa0SBruce Allan dev_dbg(dev, "LLDP event MIB bridge type 0x%x\n", mib_type); 9906dae8aa0SBruce Allan if (mib_type != ICE_AQ_LLDP_BRID_TYPE_NEAREST_BRID) 991a17a5ff6SUsha Ketineni return; 992a17a5ff6SUsha Ketineni 9937d8d7754SAnatolii Gerasymenko /* A pending change event contains accurate config information, and 9947d8d7754SAnatolii Gerasymenko * the FW setting has not been updaed yet, so detect if change is 9957d8d7754SAnatolii Gerasymenko * pending to determine where to pull config information from 9967d8d7754SAnatolii Gerasymenko * (FW vs event) 9977d8d7754SAnatolii Gerasymenko */ 9987d8d7754SAnatolii Gerasymenko if (ice_dcb_is_mib_change_pending(mib->state)) 9997d8d7754SAnatolii Gerasymenko pending_handled = false; 10007d8d7754SAnatolii Gerasymenko 1001a17a5ff6SUsha Ketineni /* Check MIB Type and return if event for Remote MIB update */ 10027d8d7754SAnatolii Gerasymenko mib_type = FIELD_GET(ICE_AQ_LLDP_MIB_TYPE_M, mib->type); 10036dae8aa0SBruce Allan dev_dbg(dev, "LLDP event mib type %s\n", mib_type ? "remote" : "local"); 10046dae8aa0SBruce Allan if (mib_type == ICE_AQ_LLDP_MIB_REMOTE) { 1005a17a5ff6SUsha Ketineni /* Update the remote cached instance and return */ 10067d8d7754SAnatolii Gerasymenko if (!pending_handled) { 10077d8d7754SAnatolii Gerasymenko ice_get_dcb_cfg_from_mib_change(pi, event); 10087d8d7754SAnatolii Gerasymenko } else { 10097d8d7754SAnatolii Gerasymenko ret = 10107d8d7754SAnatolii Gerasymenko ice_aq_get_dcb_cfg(pi->hw, ICE_AQ_LLDP_MIB_REMOTE, 1011a17a5ff6SUsha Ketineni ICE_AQ_LLDP_BRID_TYPE_NEAREST_BRID, 1012fc2d1165SChinh T Cao &pi->qos_cfg.remote_dcbx_cfg); 10137d8d7754SAnatolii Gerasymenko if (ret) 10147d8d7754SAnatolii Gerasymenko dev_dbg(dev, "Failed to get remote DCB config\n"); 10157d8d7754SAnatolii Gerasymenko } 1016a17a5ff6SUsha Ketineni return; 1017a17a5ff6SUsha Ketineni } 1018a17a5ff6SUsha Ketineni 10197d8d7754SAnatolii Gerasymenko /* That a DCB change has happened is now determined */ 1020242b5e06SDave Ertman mutex_lock(&pf->tc_mutex); 1021242b5e06SDave Ertman 1022a17a5ff6SUsha Ketineni /* store the old configuration */ 10237d8d7754SAnatolii Gerasymenko tmp_dcbx_cfg = pi->qos_cfg.local_dcbx_cfg; 1024a17a5ff6SUsha Ketineni 10252f2da36eSAnirudh Venkataramanan /* Reset the old DCBX configuration data */ 1026fc2d1165SChinh T Cao memset(&pi->qos_cfg.local_dcbx_cfg, 0, 1027fc2d1165SChinh T Cao sizeof(pi->qos_cfg.local_dcbx_cfg)); 1028a17a5ff6SUsha Ketineni 10292f2da36eSAnirudh Venkataramanan /* Get updated DCBX data from firmware */ 10307d8d7754SAnatolii Gerasymenko if (!pending_handled) { 10317d8d7754SAnatolii Gerasymenko ice_get_dcb_cfg_from_mib_change(pi, event); 10327d8d7754SAnatolii Gerasymenko } else { 10337d8d7754SAnatolii Gerasymenko ret = ice_get_dcb_cfg(pi); 1034a17a5ff6SUsha Ketineni if (ret) { 10354015d11eSBrett Creeley dev_err(dev, "Failed to get DCB config\n"); 1036242b5e06SDave Ertman goto out; 1037a17a5ff6SUsha Ketineni } 10387d8d7754SAnatolii Gerasymenko } 1039a17a5ff6SUsha Ketineni 1040a17a5ff6SUsha Ketineni /* No change detected in DCBX configs */ 1041fc2d1165SChinh T Cao if (!memcmp(&tmp_dcbx_cfg, &pi->qos_cfg.local_dcbx_cfg, 1042fc2d1165SChinh T Cao sizeof(tmp_dcbx_cfg))) { 10434015d11eSBrett Creeley dev_dbg(dev, "No change detected in DCBX configuration.\n"); 1044242b5e06SDave Ertman goto out; 1045a17a5ff6SUsha Ketineni } 1046a17a5ff6SUsha Ketineni 10471f454e06SAvinash JD pf->dcbx_cap = ice_dcb_get_mode(pi, false); 10481f454e06SAvinash JD 1049a17a5ff6SUsha Ketineni need_reconfig = ice_dcb_need_recfg(pf, &tmp_dcbx_cfg, 1050fc2d1165SChinh T Cao &pi->qos_cfg.local_dcbx_cfg); 1051fc2d1165SChinh T Cao ice_dcbnl_flush_apps(pf, &tmp_dcbx_cfg, &pi->qos_cfg.local_dcbx_cfg); 1052a17a5ff6SUsha Ketineni if (!need_reconfig) 1053242b5e06SDave Ertman goto out; 1054a17a5ff6SUsha Ketineni 1055a17a5ff6SUsha Ketineni /* Enable DCB tagging only when more than one TC */ 1056fc2d1165SChinh T Cao if (ice_dcb_get_num_tc(&pi->qos_cfg.local_dcbx_cfg) > 1) { 10574015d11eSBrett Creeley dev_dbg(dev, "DCB tagging enabled (num TC > 1)\n"); 1058a17a5ff6SUsha Ketineni set_bit(ICE_FLAG_DCB_ENA, pf->flags); 1059a17a5ff6SUsha Ketineni } else { 10604015d11eSBrett Creeley dev_dbg(dev, "DCB tagging disabled (num TC = 1)\n"); 1061a17a5ff6SUsha Ketineni clear_bit(ICE_FLAG_DCB_ENA, pf->flags); 1062a17a5ff6SUsha Ketineni } 1063a17a5ff6SUsha Ketineni 10647d8d7754SAnatolii Gerasymenko /* Send Execute Pending MIB Change event if it is a Pending event */ 10657d8d7754SAnatolii Gerasymenko if (!pending_handled) { 10667d8d7754SAnatolii Gerasymenko ice_lldp_execute_pending_mib(&pf->hw); 10677d8d7754SAnatolii Gerasymenko pending_handled = true; 10687d8d7754SAnatolii Gerasymenko } 10697d8d7754SAnatolii Gerasymenko 1070a17a5ff6SUsha Ketineni rtnl_lock(); 10710754d65bSKiran Patil /* disable VSIs affected by DCB changes */ 10720754d65bSKiran Patil ice_dcb_ena_dis_vsi(pf, false, true); 1073a17a5ff6SUsha Ketineni 10747d8d7754SAnatolii Gerasymenko ret = ice_query_port_ets(pi, &buf, sizeof(buf), NULL); 1075a17a5ff6SUsha Ketineni if (ret) { 10764015d11eSBrett Creeley dev_err(dev, "Query Port ETS failed\n"); 1077242b5e06SDave Ertman goto unlock_rtnl; 1078a17a5ff6SUsha Ketineni } 1079a17a5ff6SUsha Ketineni 1080a17a5ff6SUsha Ketineni /* changes in configuration update VSI */ 1081a17a5ff6SUsha Ketineni ice_pf_dcb_recfg(pf); 1082a17a5ff6SUsha Ketineni 10830754d65bSKiran Patil /* enable previously downed VSIs */ 10840754d65bSKiran Patil ice_dcb_ena_dis_vsi(pf, true, true); 1085242b5e06SDave Ertman unlock_rtnl: 1086a17a5ff6SUsha Ketineni rtnl_unlock(); 1087242b5e06SDave Ertman out: 1088242b5e06SDave Ertman mutex_unlock(&pf->tc_mutex); 10897d8d7754SAnatolii Gerasymenko 10907d8d7754SAnatolii Gerasymenko /* Send Execute Pending MIB Change event if it is a Pending event */ 10917d8d7754SAnatolii Gerasymenko if (!pending_handled) 10927d8d7754SAnatolii Gerasymenko ice_lldp_execute_pending_mib(&pf->hw); 109300cc3f1bSAnirudh Venkataramanan } 1094