137b6f646SAnirudh Venkataramanan // SPDX-License-Identifier: GPL-2.0 237b6f646SAnirudh Venkataramanan /* Copyright (c) 2019, Intel Corporation. */ 337b6f646SAnirudh Venkataramanan 437b6f646SAnirudh Venkataramanan #include "ice_dcb_lib.h" 537b6f646SAnirudh Venkataramanan 637b6f646SAnirudh Venkataramanan /** 77b9ffc76SAnirudh Venkataramanan * ice_dcb_get_ena_tc - return bitmap of enabled TCs 87b9ffc76SAnirudh Venkataramanan * @dcbcfg: DCB config to evaluate for enabled TCs 97b9ffc76SAnirudh Venkataramanan */ 107b9ffc76SAnirudh Venkataramanan u8 ice_dcb_get_ena_tc(struct ice_dcbx_cfg *dcbcfg) 117b9ffc76SAnirudh Venkataramanan { 127b9ffc76SAnirudh Venkataramanan u8 i, num_tc, ena_tc = 1; 137b9ffc76SAnirudh Venkataramanan 147b9ffc76SAnirudh Venkataramanan num_tc = ice_dcb_get_num_tc(dcbcfg); 157b9ffc76SAnirudh Venkataramanan 167b9ffc76SAnirudh Venkataramanan for (i = 0; i < num_tc; i++) 177b9ffc76SAnirudh Venkataramanan ena_tc |= BIT(i); 187b9ffc76SAnirudh Venkataramanan 197b9ffc76SAnirudh Venkataramanan return ena_tc; 207b9ffc76SAnirudh Venkataramanan } 217b9ffc76SAnirudh Venkataramanan 227b9ffc76SAnirudh Venkataramanan /** 237b9ffc76SAnirudh Venkataramanan * ice_dcb_get_num_tc - Get the number of TCs from DCBX config 247b9ffc76SAnirudh Venkataramanan * @dcbcfg: config to retrieve number of TCs from 257b9ffc76SAnirudh Venkataramanan */ 267b9ffc76SAnirudh Venkataramanan u8 ice_dcb_get_num_tc(struct ice_dcbx_cfg *dcbcfg) 277b9ffc76SAnirudh Venkataramanan { 287b9ffc76SAnirudh Venkataramanan bool tc_unused = false; 297b9ffc76SAnirudh Venkataramanan u8 num_tc = 0; 307b9ffc76SAnirudh Venkataramanan u8 ret = 0; 317b9ffc76SAnirudh Venkataramanan int i; 327b9ffc76SAnirudh Venkataramanan 337b9ffc76SAnirudh Venkataramanan /* Scan the ETS Config Priority Table to find traffic classes 347b9ffc76SAnirudh Venkataramanan * enabled and create a bitmask of enabled TCs 357b9ffc76SAnirudh Venkataramanan */ 367b9ffc76SAnirudh Venkataramanan for (i = 0; i < CEE_DCBX_MAX_PRIO; i++) 377b9ffc76SAnirudh Venkataramanan num_tc |= BIT(dcbcfg->etscfg.prio_table[i]); 387b9ffc76SAnirudh Venkataramanan 397b9ffc76SAnirudh Venkataramanan /* Scan bitmask for contiguous TCs starting with TC0 */ 407b9ffc76SAnirudh Venkataramanan for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { 417b9ffc76SAnirudh Venkataramanan if (num_tc & BIT(i)) { 427b9ffc76SAnirudh Venkataramanan if (!tc_unused) { 437b9ffc76SAnirudh Venkataramanan ret++; 447b9ffc76SAnirudh Venkataramanan } else { 457b9ffc76SAnirudh Venkataramanan pr_err("Non-contiguous TCs - Disabling DCB\n"); 467b9ffc76SAnirudh Venkataramanan return 1; 477b9ffc76SAnirudh Venkataramanan } 487b9ffc76SAnirudh Venkataramanan } else { 497b9ffc76SAnirudh Venkataramanan tc_unused = true; 507b9ffc76SAnirudh Venkataramanan } 517b9ffc76SAnirudh Venkataramanan } 527b9ffc76SAnirudh Venkataramanan 537b9ffc76SAnirudh Venkataramanan /* There is always at least 1 TC */ 547b9ffc76SAnirudh Venkataramanan if (!ret) 557b9ffc76SAnirudh Venkataramanan ret = 1; 567b9ffc76SAnirudh Venkataramanan 577b9ffc76SAnirudh Venkataramanan return ret; 587b9ffc76SAnirudh Venkataramanan } 597b9ffc76SAnirudh Venkataramanan 607b9ffc76SAnirudh Venkataramanan /** 61a629cf0aSAnirudh Venkataramanan * ice_vsi_cfg_dcb_rings - Update rings to reflect DCB TC 62a629cf0aSAnirudh Venkataramanan * @vsi: VSI owner of rings being updated 63a629cf0aSAnirudh Venkataramanan */ 64a629cf0aSAnirudh Venkataramanan void ice_vsi_cfg_dcb_rings(struct ice_vsi *vsi) 65a629cf0aSAnirudh Venkataramanan { 66a629cf0aSAnirudh Venkataramanan struct ice_ring *tx_ring, *rx_ring; 67a629cf0aSAnirudh Venkataramanan u16 qoffset, qcount; 68a629cf0aSAnirudh Venkataramanan int i, n; 69a629cf0aSAnirudh Venkataramanan 70a629cf0aSAnirudh Venkataramanan if (!test_bit(ICE_FLAG_DCB_ENA, vsi->back->flags)) { 71a629cf0aSAnirudh Venkataramanan /* Reset the TC information */ 72a629cf0aSAnirudh Venkataramanan for (i = 0; i < vsi->num_txq; i++) { 73a629cf0aSAnirudh Venkataramanan tx_ring = vsi->tx_rings[i]; 74a629cf0aSAnirudh Venkataramanan tx_ring->dcb_tc = 0; 75a629cf0aSAnirudh Venkataramanan } 76a629cf0aSAnirudh Venkataramanan for (i = 0; i < vsi->num_rxq; i++) { 77a629cf0aSAnirudh Venkataramanan rx_ring = vsi->rx_rings[i]; 78a629cf0aSAnirudh Venkataramanan rx_ring->dcb_tc = 0; 79a629cf0aSAnirudh Venkataramanan } 80a629cf0aSAnirudh Venkataramanan return; 81a629cf0aSAnirudh Venkataramanan } 82a629cf0aSAnirudh Venkataramanan 83a629cf0aSAnirudh Venkataramanan ice_for_each_traffic_class(n) { 84a629cf0aSAnirudh Venkataramanan if (!(vsi->tc_cfg.ena_tc & BIT(n))) 85a629cf0aSAnirudh Venkataramanan break; 86a629cf0aSAnirudh Venkataramanan 87a629cf0aSAnirudh Venkataramanan qoffset = vsi->tc_cfg.tc_info[n].qoffset; 88a629cf0aSAnirudh Venkataramanan qcount = vsi->tc_cfg.tc_info[n].qcount_tx; 89a629cf0aSAnirudh Venkataramanan for (i = qoffset; i < (qoffset + qcount); i++) { 90a629cf0aSAnirudh Venkataramanan tx_ring = vsi->tx_rings[i]; 91a629cf0aSAnirudh Venkataramanan rx_ring = vsi->rx_rings[i]; 92a629cf0aSAnirudh Venkataramanan tx_ring->dcb_tc = n; 93a629cf0aSAnirudh Venkataramanan rx_ring->dcb_tc = n; 94a629cf0aSAnirudh Venkataramanan } 95a629cf0aSAnirudh Venkataramanan } 96a629cf0aSAnirudh Venkataramanan } 97a629cf0aSAnirudh Venkataramanan 98a629cf0aSAnirudh Venkataramanan /** 997b9ffc76SAnirudh Venkataramanan * ice_pf_dcb_recfg - Reconfigure all VEBs and VSIs 1007b9ffc76SAnirudh Venkataramanan * @pf: pointer to the PF struct 1017b9ffc76SAnirudh Venkataramanan * 1027b9ffc76SAnirudh Venkataramanan * Assumed caller has already disabled all VSIs before 1037b9ffc76SAnirudh Venkataramanan * calling this function. Reconfiguring DCB based on 1047b9ffc76SAnirudh Venkataramanan * local_dcbx_cfg. 1057b9ffc76SAnirudh Venkataramanan */ 1067b9ffc76SAnirudh Venkataramanan static void ice_pf_dcb_recfg(struct ice_pf *pf) 1077b9ffc76SAnirudh Venkataramanan { 1087b9ffc76SAnirudh Venkataramanan struct ice_dcbx_cfg *dcbcfg = &pf->hw.port_info->local_dcbx_cfg; 1097b9ffc76SAnirudh Venkataramanan u8 tc_map = 0; 1107b9ffc76SAnirudh Venkataramanan int v, ret; 1117b9ffc76SAnirudh Venkataramanan 1127b9ffc76SAnirudh Venkataramanan /* Update each VSI */ 1137b9ffc76SAnirudh Venkataramanan ice_for_each_vsi(pf, v) { 1147b9ffc76SAnirudh Venkataramanan if (!pf->vsi[v]) 1157b9ffc76SAnirudh Venkataramanan continue; 1167b9ffc76SAnirudh Venkataramanan 1177b9ffc76SAnirudh Venkataramanan if (pf->vsi[v]->type == ICE_VSI_PF) 1187b9ffc76SAnirudh Venkataramanan tc_map = ice_dcb_get_ena_tc(dcbcfg); 1197b9ffc76SAnirudh Venkataramanan else 1207b9ffc76SAnirudh Venkataramanan tc_map = ICE_DFLT_TRAFFIC_CLASS; 1217b9ffc76SAnirudh Venkataramanan 1227b9ffc76SAnirudh Venkataramanan ret = ice_vsi_cfg_tc(pf->vsi[v], tc_map); 1237b9ffc76SAnirudh Venkataramanan if (ret) 1247b9ffc76SAnirudh Venkataramanan dev_err(&pf->pdev->dev, 1257b9ffc76SAnirudh Venkataramanan "Failed to config TC for VSI index: %d\n", 1267b9ffc76SAnirudh Venkataramanan pf->vsi[v]->idx); 1277b9ffc76SAnirudh Venkataramanan else 1287b9ffc76SAnirudh Venkataramanan ice_vsi_map_rings_to_vectors(pf->vsi[v]); 1297b9ffc76SAnirudh Venkataramanan } 1307b9ffc76SAnirudh Venkataramanan } 1317b9ffc76SAnirudh Venkataramanan 1327b9ffc76SAnirudh Venkataramanan /** 1337b9ffc76SAnirudh Venkataramanan * ice_pf_dcb_cfg - Apply new DCB configuration 1347b9ffc76SAnirudh Venkataramanan * @pf: pointer to the PF struct 1357b9ffc76SAnirudh Venkataramanan * @new_cfg: DCBX config to apply 1367b9ffc76SAnirudh Venkataramanan */ 1377b9ffc76SAnirudh Venkataramanan static int ice_pf_dcb_cfg(struct ice_pf *pf, struct ice_dcbx_cfg *new_cfg) 1387b9ffc76SAnirudh Venkataramanan { 1397b9ffc76SAnirudh Venkataramanan struct ice_dcbx_cfg *old_cfg, *curr_cfg; 1407b9ffc76SAnirudh Venkataramanan struct ice_aqc_port_ets_elem buf = { 0 }; 1417b9ffc76SAnirudh Venkataramanan int ret = 0; 1427b9ffc76SAnirudh Venkataramanan 1437b9ffc76SAnirudh Venkataramanan curr_cfg = &pf->hw.port_info->local_dcbx_cfg; 1447b9ffc76SAnirudh Venkataramanan 1457b9ffc76SAnirudh Venkataramanan /* Enable DCB tagging only when more than one TC */ 1467b9ffc76SAnirudh Venkataramanan if (ice_dcb_get_num_tc(new_cfg) > 1) { 1477b9ffc76SAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, "DCB tagging enabled (num TC > 1)\n"); 1487b9ffc76SAnirudh Venkataramanan set_bit(ICE_FLAG_DCB_ENA, pf->flags); 1497b9ffc76SAnirudh Venkataramanan } else { 1507b9ffc76SAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, "DCB tagging disabled (num TC = 1)\n"); 1517b9ffc76SAnirudh Venkataramanan clear_bit(ICE_FLAG_DCB_ENA, pf->flags); 1527b9ffc76SAnirudh Venkataramanan } 1537b9ffc76SAnirudh Venkataramanan 1547b9ffc76SAnirudh Venkataramanan if (!memcmp(new_cfg, curr_cfg, sizeof(*new_cfg))) { 1557b9ffc76SAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, "No change in DCB config required\n"); 1567b9ffc76SAnirudh Venkataramanan return ret; 1577b9ffc76SAnirudh Venkataramanan } 1587b9ffc76SAnirudh Venkataramanan 1597b9ffc76SAnirudh Venkataramanan /* Store old config in case FW config fails */ 1607b9ffc76SAnirudh Venkataramanan old_cfg = devm_kzalloc(&pf->pdev->dev, sizeof(*old_cfg), GFP_KERNEL); 1617b9ffc76SAnirudh Venkataramanan memcpy(old_cfg, curr_cfg, sizeof(*old_cfg)); 1627b9ffc76SAnirudh Venkataramanan 1637b9ffc76SAnirudh Venkataramanan /* avoid race conditions by holding the lock while disabling and 1647b9ffc76SAnirudh Venkataramanan * re-enabling the VSI 1657b9ffc76SAnirudh Venkataramanan */ 1667b9ffc76SAnirudh Venkataramanan rtnl_lock(); 1677b9ffc76SAnirudh Venkataramanan ice_pf_dis_all_vsi(pf, true); 1687b9ffc76SAnirudh Venkataramanan 1697b9ffc76SAnirudh Venkataramanan memcpy(curr_cfg, new_cfg, sizeof(*curr_cfg)); 1707b9ffc76SAnirudh Venkataramanan memcpy(&curr_cfg->etsrec, &curr_cfg->etscfg, sizeof(curr_cfg->etsrec)); 1717b9ffc76SAnirudh Venkataramanan 1727b9ffc76SAnirudh Venkataramanan /* Only send new config to HW if we are in SW LLDP mode. Otherwise, 1737b9ffc76SAnirudh Venkataramanan * the new config came from the HW in the first place. 1747b9ffc76SAnirudh Venkataramanan */ 1757b9ffc76SAnirudh Venkataramanan if (pf->hw.port_info->is_sw_lldp) { 1767b9ffc76SAnirudh Venkataramanan ret = ice_set_dcb_cfg(pf->hw.port_info); 1777b9ffc76SAnirudh Venkataramanan if (ret) { 1787b9ffc76SAnirudh Venkataramanan dev_err(&pf->pdev->dev, "Set DCB Config failed\n"); 1797b9ffc76SAnirudh Venkataramanan /* Restore previous settings to local config */ 1807b9ffc76SAnirudh Venkataramanan memcpy(curr_cfg, old_cfg, sizeof(*curr_cfg)); 1817b9ffc76SAnirudh Venkataramanan goto out; 1827b9ffc76SAnirudh Venkataramanan } 1837b9ffc76SAnirudh Venkataramanan } 1847b9ffc76SAnirudh Venkataramanan 1857b9ffc76SAnirudh Venkataramanan ret = ice_query_port_ets(pf->hw.port_info, &buf, sizeof(buf), NULL); 1867b9ffc76SAnirudh Venkataramanan if (ret) { 1877b9ffc76SAnirudh Venkataramanan dev_err(&pf->pdev->dev, "Query Port ETS failed\n"); 1887b9ffc76SAnirudh Venkataramanan goto out; 1897b9ffc76SAnirudh Venkataramanan } 1907b9ffc76SAnirudh Venkataramanan 1917b9ffc76SAnirudh Venkataramanan ice_pf_dcb_recfg(pf); 1927b9ffc76SAnirudh Venkataramanan 1937b9ffc76SAnirudh Venkataramanan out: 1947b9ffc76SAnirudh Venkataramanan ice_pf_ena_all_vsi(pf, true); 1957b9ffc76SAnirudh Venkataramanan rtnl_unlock(); 1967b9ffc76SAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, old_cfg); 1977b9ffc76SAnirudh Venkataramanan return ret; 1987b9ffc76SAnirudh Venkataramanan } 1997b9ffc76SAnirudh Venkataramanan 2007b9ffc76SAnirudh Venkataramanan /** 201b832c2f6SAnirudh Venkataramanan * ice_dcb_rebuild - rebuild DCB post reset 202b832c2f6SAnirudh Venkataramanan * @pf: physical function instance 203b832c2f6SAnirudh Venkataramanan */ 204b832c2f6SAnirudh Venkataramanan void ice_dcb_rebuild(struct ice_pf *pf) 205b832c2f6SAnirudh Venkataramanan { 206b832c2f6SAnirudh Venkataramanan struct ice_aqc_port_ets_elem buf = { 0 }; 207b832c2f6SAnirudh Venkataramanan struct ice_dcbx_cfg *prev_cfg; 208b832c2f6SAnirudh Venkataramanan enum ice_status ret; 209b832c2f6SAnirudh Venkataramanan u8 willing; 210b832c2f6SAnirudh Venkataramanan 211b832c2f6SAnirudh Venkataramanan ret = ice_query_port_ets(pf->hw.port_info, &buf, sizeof(buf), NULL); 212b832c2f6SAnirudh Venkataramanan if (ret) { 213b832c2f6SAnirudh Venkataramanan dev_err(&pf->pdev->dev, "Query Port ETS failed\n"); 214b832c2f6SAnirudh Venkataramanan goto dcb_error; 215b832c2f6SAnirudh Venkataramanan } 216b832c2f6SAnirudh Venkataramanan 217b832c2f6SAnirudh Venkataramanan /* If DCB was not enabled previously, we are done */ 218b832c2f6SAnirudh Venkataramanan if (!test_bit(ICE_FLAG_DCB_ENA, pf->flags)) 219b832c2f6SAnirudh Venkataramanan return; 220b832c2f6SAnirudh Venkataramanan 221b832c2f6SAnirudh Venkataramanan /* Save current willing state and force FW to unwilling */ 222b832c2f6SAnirudh Venkataramanan willing = pf->hw.port_info->local_dcbx_cfg.etscfg.willing; 223b832c2f6SAnirudh Venkataramanan pf->hw.port_info->local_dcbx_cfg.etscfg.willing = 0x0; 224b832c2f6SAnirudh Venkataramanan ret = ice_set_dcb_cfg(pf->hw.port_info); 225b832c2f6SAnirudh Venkataramanan if (ret) { 226b832c2f6SAnirudh Venkataramanan dev_err(&pf->pdev->dev, "Failed to set DCB to unwilling\n"); 227b832c2f6SAnirudh Venkataramanan goto dcb_error; 228b832c2f6SAnirudh Venkataramanan } 229b832c2f6SAnirudh Venkataramanan 230b832c2f6SAnirudh Venkataramanan /* Retrieve DCB config and ensure same as current in SW */ 231b832c2f6SAnirudh Venkataramanan prev_cfg = devm_kmemdup(&pf->pdev->dev, 232b832c2f6SAnirudh Venkataramanan &pf->hw.port_info->local_dcbx_cfg, 233b832c2f6SAnirudh Venkataramanan sizeof(*prev_cfg), GFP_KERNEL); 234b832c2f6SAnirudh Venkataramanan if (!prev_cfg) { 235b832c2f6SAnirudh Venkataramanan dev_err(&pf->pdev->dev, "Failed to alloc space for DCB cfg\n"); 236b832c2f6SAnirudh Venkataramanan goto dcb_error; 237b832c2f6SAnirudh Venkataramanan } 238b832c2f6SAnirudh Venkataramanan 239b832c2f6SAnirudh Venkataramanan ice_init_dcb(&pf->hw); 240b832c2f6SAnirudh Venkataramanan if (memcmp(prev_cfg, &pf->hw.port_info->local_dcbx_cfg, 241b832c2f6SAnirudh Venkataramanan sizeof(*prev_cfg))) { 242b832c2f6SAnirudh Venkataramanan /* difference in cfg detected - disable DCB till next MIB */ 243b832c2f6SAnirudh Venkataramanan dev_err(&pf->pdev->dev, "Set local MIB not accurate\n"); 244b832c2f6SAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, prev_cfg); 245b832c2f6SAnirudh Venkataramanan goto dcb_error; 246b832c2f6SAnirudh Venkataramanan } 247b832c2f6SAnirudh Venkataramanan 248b832c2f6SAnirudh Venkataramanan /* fetched config congruent to previous configuration */ 249b832c2f6SAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, prev_cfg); 250b832c2f6SAnirudh Venkataramanan 251b832c2f6SAnirudh Venkataramanan /* Configuration replayed - reset willing state to previous */ 252b832c2f6SAnirudh Venkataramanan pf->hw.port_info->local_dcbx_cfg.etscfg.willing = willing; 253b832c2f6SAnirudh Venkataramanan ret = ice_set_dcb_cfg(pf->hw.port_info); 254b832c2f6SAnirudh Venkataramanan if (ret) { 255b832c2f6SAnirudh Venkataramanan dev_err(&pf->pdev->dev, "Fail restoring prev willing state\n"); 256b832c2f6SAnirudh Venkataramanan goto dcb_error; 257b832c2f6SAnirudh Venkataramanan } 258b832c2f6SAnirudh Venkataramanan dev_info(&pf->pdev->dev, "DCB restored after reset\n"); 259b832c2f6SAnirudh Venkataramanan ret = ice_query_port_ets(pf->hw.port_info, &buf, sizeof(buf), NULL); 260b832c2f6SAnirudh Venkataramanan if (ret) { 261b832c2f6SAnirudh Venkataramanan dev_err(&pf->pdev->dev, "Query Port ETS failed\n"); 262b832c2f6SAnirudh Venkataramanan goto dcb_error; 263b832c2f6SAnirudh Venkataramanan } 264b832c2f6SAnirudh Venkataramanan 265b832c2f6SAnirudh Venkataramanan return; 266b832c2f6SAnirudh Venkataramanan 267b832c2f6SAnirudh Venkataramanan dcb_error: 268b832c2f6SAnirudh Venkataramanan dev_err(&pf->pdev->dev, "Disabling DCB until new settings occur\n"); 269b832c2f6SAnirudh Venkataramanan prev_cfg = devm_kzalloc(&pf->pdev->dev, sizeof(*prev_cfg), GFP_KERNEL); 270b832c2f6SAnirudh Venkataramanan prev_cfg->etscfg.willing = true; 271b832c2f6SAnirudh Venkataramanan prev_cfg->etscfg.tcbwtable[0] = ICE_TC_MAX_BW; 272b832c2f6SAnirudh Venkataramanan prev_cfg->etscfg.tsatable[0] = ICE_IEEE_TSA_ETS; 273b832c2f6SAnirudh Venkataramanan memcpy(&prev_cfg->etsrec, &prev_cfg->etscfg, sizeof(prev_cfg->etsrec)); 274b832c2f6SAnirudh Venkataramanan ice_pf_dcb_cfg(pf, prev_cfg); 275b832c2f6SAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, prev_cfg); 276b832c2f6SAnirudh Venkataramanan } 277b832c2f6SAnirudh Venkataramanan 278b832c2f6SAnirudh Venkataramanan /** 2797b9ffc76SAnirudh Venkataramanan * ice_dcb_init_cfg - set the initial DCB config in SW 2807b9ffc76SAnirudh Venkataramanan * @pf: pf to apply config to 2817b9ffc76SAnirudh Venkataramanan */ 2827b9ffc76SAnirudh Venkataramanan static int ice_dcb_init_cfg(struct ice_pf *pf) 2837b9ffc76SAnirudh Venkataramanan { 2847b9ffc76SAnirudh Venkataramanan struct ice_dcbx_cfg *newcfg; 2857b9ffc76SAnirudh Venkataramanan struct ice_port_info *pi; 2867b9ffc76SAnirudh Venkataramanan int ret = 0; 2877b9ffc76SAnirudh Venkataramanan 2887b9ffc76SAnirudh Venkataramanan pi = pf->hw.port_info; 2897b9ffc76SAnirudh Venkataramanan newcfg = devm_kzalloc(&pf->pdev->dev, sizeof(*newcfg), GFP_KERNEL); 2907b9ffc76SAnirudh Venkataramanan if (!newcfg) 2917b9ffc76SAnirudh Venkataramanan return -ENOMEM; 2927b9ffc76SAnirudh Venkataramanan 2937b9ffc76SAnirudh Venkataramanan memcpy(newcfg, &pi->local_dcbx_cfg, sizeof(*newcfg)); 2947b9ffc76SAnirudh Venkataramanan memset(&pi->local_dcbx_cfg, 0, sizeof(*newcfg)); 2957b9ffc76SAnirudh Venkataramanan 2967b9ffc76SAnirudh Venkataramanan dev_info(&pf->pdev->dev, "Configuring initial DCB values\n"); 2977b9ffc76SAnirudh Venkataramanan if (ice_pf_dcb_cfg(pf, newcfg)) 2987b9ffc76SAnirudh Venkataramanan ret = -EINVAL; 2997b9ffc76SAnirudh Venkataramanan 3007b9ffc76SAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, newcfg); 3017b9ffc76SAnirudh Venkataramanan 3027b9ffc76SAnirudh Venkataramanan return ret; 3037b9ffc76SAnirudh Venkataramanan } 3047b9ffc76SAnirudh Venkataramanan 3057b9ffc76SAnirudh Venkataramanan /** 3060deab659SAnirudh Venkataramanan * ice_dcb_sw_default_config - Apply a default DCB config 3070deab659SAnirudh Venkataramanan * @pf: pf to apply config to 3080deab659SAnirudh Venkataramanan */ 3090deab659SAnirudh Venkataramanan static int ice_dcb_sw_dflt_cfg(struct ice_pf *pf) 3100deab659SAnirudh Venkataramanan { 3110deab659SAnirudh Venkataramanan struct ice_aqc_port_ets_elem buf = { 0 }; 3120deab659SAnirudh Venkataramanan struct ice_dcbx_cfg *dcbcfg; 3130deab659SAnirudh Venkataramanan struct ice_port_info *pi; 3140deab659SAnirudh Venkataramanan struct ice_hw *hw; 3150deab659SAnirudh Venkataramanan int ret; 3160deab659SAnirudh Venkataramanan 3170deab659SAnirudh Venkataramanan hw = &pf->hw; 3180deab659SAnirudh Venkataramanan pi = hw->port_info; 3190deab659SAnirudh Venkataramanan dcbcfg = devm_kzalloc(&pf->pdev->dev, sizeof(*dcbcfg), GFP_KERNEL); 3200deab659SAnirudh Venkataramanan 3210deab659SAnirudh Venkataramanan memset(dcbcfg, 0, sizeof(*dcbcfg)); 3220deab659SAnirudh Venkataramanan memset(&pi->local_dcbx_cfg, 0, sizeof(*dcbcfg)); 3230deab659SAnirudh Venkataramanan 3240deab659SAnirudh Venkataramanan dcbcfg->etscfg.willing = 1; 3250deab659SAnirudh Venkataramanan dcbcfg->etscfg.maxtcs = 8; 3260deab659SAnirudh Venkataramanan dcbcfg->etscfg.tcbwtable[0] = 100; 3270deab659SAnirudh Venkataramanan dcbcfg->etscfg.tsatable[0] = ICE_IEEE_TSA_ETS; 3280deab659SAnirudh Venkataramanan 3290deab659SAnirudh Venkataramanan memcpy(&dcbcfg->etsrec, &dcbcfg->etscfg, 3300deab659SAnirudh Venkataramanan sizeof(dcbcfg->etsrec)); 3310deab659SAnirudh Venkataramanan dcbcfg->etsrec.willing = 0; 3320deab659SAnirudh Venkataramanan 3330deab659SAnirudh Venkataramanan dcbcfg->pfc.willing = 1; 3340deab659SAnirudh Venkataramanan dcbcfg->pfc.pfccap = IEEE_8021QAZ_MAX_TCS; 3350deab659SAnirudh Venkataramanan 3360deab659SAnirudh Venkataramanan dcbcfg->numapps = 1; 3370deab659SAnirudh Venkataramanan dcbcfg->app[0].selector = ICE_APP_SEL_ETHTYPE; 3380deab659SAnirudh Venkataramanan dcbcfg->app[0].priority = 3; 3390deab659SAnirudh Venkataramanan dcbcfg->app[0].prot_id = ICE_APP_PROT_ID_FCOE; 3400deab659SAnirudh Venkataramanan 3410deab659SAnirudh Venkataramanan ret = ice_pf_dcb_cfg(pf, dcbcfg); 3420deab659SAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, dcbcfg); 3430deab659SAnirudh Venkataramanan if (ret) 3440deab659SAnirudh Venkataramanan return ret; 3450deab659SAnirudh Venkataramanan 3460deab659SAnirudh Venkataramanan return ice_query_port_ets(pi, &buf, sizeof(buf), NULL); 3470deab659SAnirudh Venkataramanan } 3480deab659SAnirudh Venkataramanan 3490deab659SAnirudh Venkataramanan /** 35037b6f646SAnirudh Venkataramanan * ice_init_pf_dcb - initialize DCB for a PF 35137b6f646SAnirudh Venkataramanan * @pf: pf to initiialize DCB for 35237b6f646SAnirudh Venkataramanan */ 35337b6f646SAnirudh Venkataramanan int ice_init_pf_dcb(struct ice_pf *pf) 35437b6f646SAnirudh Venkataramanan { 35537b6f646SAnirudh Venkataramanan struct device *dev = &pf->pdev->dev; 35637b6f646SAnirudh Venkataramanan struct ice_port_info *port_info; 35737b6f646SAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 3580deab659SAnirudh Venkataramanan int sw_default = 0; 3597b9ffc76SAnirudh Venkataramanan int err; 36037b6f646SAnirudh Venkataramanan 36137b6f646SAnirudh Venkataramanan port_info = hw->port_info; 36237b6f646SAnirudh Venkataramanan 36337b6f646SAnirudh Venkataramanan /* check if device is DCB capable */ 36437b6f646SAnirudh Venkataramanan if (!hw->func_caps.common_cap.dcb) { 36537b6f646SAnirudh Venkataramanan dev_dbg(dev, "DCB not supported\n"); 36637b6f646SAnirudh Venkataramanan return -EOPNOTSUPP; 36737b6f646SAnirudh Venkataramanan } 36837b6f646SAnirudh Venkataramanan 36937b6f646SAnirudh Venkataramanan /* Best effort to put DCBx and LLDP into a good state */ 37037b6f646SAnirudh Venkataramanan port_info->dcbx_status = ice_get_dcbx_status(hw); 37137b6f646SAnirudh Venkataramanan if (port_info->dcbx_status != ICE_DCBX_STATUS_DONE && 37237b6f646SAnirudh Venkataramanan port_info->dcbx_status != ICE_DCBX_STATUS_IN_PROGRESS) { 37337b6f646SAnirudh Venkataramanan bool dcbx_status; 37437b6f646SAnirudh Venkataramanan 37537b6f646SAnirudh Venkataramanan /* Attempt to start LLDP engine. Ignore errors 37637b6f646SAnirudh Venkataramanan * as this will error if it is already started 37737b6f646SAnirudh Venkataramanan */ 37837b6f646SAnirudh Venkataramanan ice_aq_start_lldp(hw, NULL); 37937b6f646SAnirudh Venkataramanan 38037b6f646SAnirudh Venkataramanan /* Attempt to start DCBX. Ignore errors as this 38137b6f646SAnirudh Venkataramanan * will error if it is already started 38237b6f646SAnirudh Venkataramanan */ 38337b6f646SAnirudh Venkataramanan ice_aq_start_stop_dcbx(hw, true, &dcbx_status, NULL); 38437b6f646SAnirudh Venkataramanan } 38537b6f646SAnirudh Venkataramanan 3867b9ffc76SAnirudh Venkataramanan err = ice_init_dcb(hw); 3870deab659SAnirudh Venkataramanan if (err) { 3880deab659SAnirudh Venkataramanan /* FW LLDP not in usable state, default to SW DCBx/LLDP */ 3890deab659SAnirudh Venkataramanan dev_info(&pf->pdev->dev, "FW LLDP not in usable state\n"); 3900deab659SAnirudh Venkataramanan hw->port_info->dcbx_status = ICE_DCBX_STATUS_NOT_STARTED; 3910deab659SAnirudh Venkataramanan hw->port_info->is_sw_lldp = true; 3920deab659SAnirudh Venkataramanan } 3930deab659SAnirudh Venkataramanan 3940deab659SAnirudh Venkataramanan if (port_info->dcbx_status == ICE_DCBX_STATUS_DIS) 3950deab659SAnirudh Venkataramanan dev_info(&pf->pdev->dev, "DCBX disabled\n"); 3960deab659SAnirudh Venkataramanan 3970deab659SAnirudh Venkataramanan /* LLDP disabled in FW */ 3980deab659SAnirudh Venkataramanan if (port_info->is_sw_lldp) { 3990deab659SAnirudh Venkataramanan sw_default = 1; 4000deab659SAnirudh Venkataramanan dev_info(&pf->pdev->dev, "DCBx/LLDP in SW mode.\n"); 4010deab659SAnirudh Venkataramanan } 4020deab659SAnirudh Venkataramanan 4030deab659SAnirudh Venkataramanan if (port_info->dcbx_status == ICE_DCBX_STATUS_NOT_STARTED) { 4040deab659SAnirudh Venkataramanan sw_default = 1; 4050deab659SAnirudh Venkataramanan dev_info(&pf->pdev->dev, "DCBX not started\n"); 4060deab659SAnirudh Venkataramanan } 4070deab659SAnirudh Venkataramanan 4080deab659SAnirudh Venkataramanan if (sw_default) { 4090deab659SAnirudh Venkataramanan err = ice_dcb_sw_dflt_cfg(pf); 4100deab659SAnirudh Venkataramanan if (err) { 4110deab659SAnirudh Venkataramanan dev_err(&pf->pdev->dev, 4120deab659SAnirudh Venkataramanan "Failed to set local DCB config %d\n", err); 4130deab659SAnirudh Venkataramanan err = -EIO; 4147b9ffc76SAnirudh Venkataramanan goto dcb_init_err; 4150deab659SAnirudh Venkataramanan } 4160deab659SAnirudh Venkataramanan 4170deab659SAnirudh Venkataramanan pf->dcbx_cap = DCB_CAP_DCBX_HOST | DCB_CAP_DCBX_VER_IEEE; 4180deab659SAnirudh Venkataramanan set_bit(ICE_FLAG_DCB_CAPABLE, pf->flags); 4190deab659SAnirudh Venkataramanan set_bit(ICE_FLAG_DCB_ENA, pf->flags); 4200deab659SAnirudh Venkataramanan return 0; 4210deab659SAnirudh Venkataramanan } 4227b9ffc76SAnirudh Venkataramanan 4237b9ffc76SAnirudh Venkataramanan /* DCBX in FW and LLDP enabled in FW */ 4247b9ffc76SAnirudh Venkataramanan pf->dcbx_cap = DCB_CAP_DCBX_LLD_MANAGED | DCB_CAP_DCBX_VER_IEEE; 4257b9ffc76SAnirudh Venkataramanan 4267b9ffc76SAnirudh Venkataramanan set_bit(ICE_FLAG_DCB_CAPABLE, pf->flags); 4277b9ffc76SAnirudh Venkataramanan 4287b9ffc76SAnirudh Venkataramanan err = ice_dcb_init_cfg(pf); 4297b9ffc76SAnirudh Venkataramanan if (err) 4307b9ffc76SAnirudh Venkataramanan goto dcb_init_err; 4317b9ffc76SAnirudh Venkataramanan 4327b9ffc76SAnirudh Venkataramanan dev_info(&pf->pdev->dev, "DCBX offload supported\n"); 4337b9ffc76SAnirudh Venkataramanan return err; 4347b9ffc76SAnirudh Venkataramanan 4357b9ffc76SAnirudh Venkataramanan dcb_init_err: 4367b9ffc76SAnirudh Venkataramanan dev_err(dev, "DCB init failed\n"); 4377b9ffc76SAnirudh Venkataramanan return err; 43837b6f646SAnirudh Venkataramanan } 43900cc3f1bSAnirudh Venkataramanan 44000cc3f1bSAnirudh Venkataramanan /** 4414b0fdcebSAnirudh Venkataramanan * ice_update_dcb_stats - Update DCB stats counters 4424b0fdcebSAnirudh Venkataramanan * @pf: PF whose stats needs to be updated 4434b0fdcebSAnirudh Venkataramanan */ 4444b0fdcebSAnirudh Venkataramanan void ice_update_dcb_stats(struct ice_pf *pf) 4454b0fdcebSAnirudh Venkataramanan { 4464b0fdcebSAnirudh Venkataramanan struct ice_hw_port_stats *prev_ps, *cur_ps; 4474b0fdcebSAnirudh Venkataramanan struct ice_hw *hw = &pf->hw; 4484b0fdcebSAnirudh Venkataramanan u8 pf_id = hw->pf_id; 4494b0fdcebSAnirudh Venkataramanan int i; 4504b0fdcebSAnirudh Venkataramanan 4514b0fdcebSAnirudh Venkataramanan prev_ps = &pf->stats_prev; 4524b0fdcebSAnirudh Venkataramanan cur_ps = &pf->stats; 4534b0fdcebSAnirudh Venkataramanan 4544b0fdcebSAnirudh Venkataramanan for (i = 0; i < 8; i++) { 4554b0fdcebSAnirudh Venkataramanan ice_stat_update32(hw, GLPRT_PXOFFRXC(pf_id, i), 4564b0fdcebSAnirudh Venkataramanan pf->stat_prev_loaded, 4574b0fdcebSAnirudh Venkataramanan &prev_ps->priority_xoff_rx[i], 4584b0fdcebSAnirudh Venkataramanan &cur_ps->priority_xoff_rx[i]); 4594b0fdcebSAnirudh Venkataramanan ice_stat_update32(hw, GLPRT_PXONRXC(pf_id, i), 4604b0fdcebSAnirudh Venkataramanan pf->stat_prev_loaded, 4614b0fdcebSAnirudh Venkataramanan &prev_ps->priority_xon_rx[i], 4624b0fdcebSAnirudh Venkataramanan &cur_ps->priority_xon_rx[i]); 4634b0fdcebSAnirudh Venkataramanan ice_stat_update32(hw, GLPRT_PXONTXC(pf_id, i), 4644b0fdcebSAnirudh Venkataramanan pf->stat_prev_loaded, 4654b0fdcebSAnirudh Venkataramanan &prev_ps->priority_xon_tx[i], 4664b0fdcebSAnirudh Venkataramanan &cur_ps->priority_xon_tx[i]); 4674b0fdcebSAnirudh Venkataramanan ice_stat_update32(hw, GLPRT_PXOFFTXC(pf_id, i), 4684b0fdcebSAnirudh Venkataramanan pf->stat_prev_loaded, 4694b0fdcebSAnirudh Venkataramanan &prev_ps->priority_xoff_tx[i], 4704b0fdcebSAnirudh Venkataramanan &cur_ps->priority_xoff_tx[i]); 4714b0fdcebSAnirudh Venkataramanan ice_stat_update32(hw, GLPRT_RXON2OFFCNT(pf_id, i), 4724b0fdcebSAnirudh Venkataramanan pf->stat_prev_loaded, 4734b0fdcebSAnirudh Venkataramanan &prev_ps->priority_xon_2_xoff[i], 4744b0fdcebSAnirudh Venkataramanan &cur_ps->priority_xon_2_xoff[i]); 4754b0fdcebSAnirudh Venkataramanan } 4764b0fdcebSAnirudh Venkataramanan } 4774b0fdcebSAnirudh Venkataramanan 4784b0fdcebSAnirudh Venkataramanan /** 4795f6aa50eSAnirudh Venkataramanan * ice_tx_prepare_vlan_flags_dcb - prepare VLAN tagging for DCB 4805f6aa50eSAnirudh Venkataramanan * @tx_ring: ring to send buffer on 4815f6aa50eSAnirudh Venkataramanan * @first: pointer to struct ice_tx_buf 4825f6aa50eSAnirudh Venkataramanan */ 4835f6aa50eSAnirudh Venkataramanan int 4845f6aa50eSAnirudh Venkataramanan ice_tx_prepare_vlan_flags_dcb(struct ice_ring *tx_ring, 4855f6aa50eSAnirudh Venkataramanan struct ice_tx_buf *first) 4865f6aa50eSAnirudh Venkataramanan { 4875f6aa50eSAnirudh Venkataramanan struct sk_buff *skb = first->skb; 4885f6aa50eSAnirudh Venkataramanan 4895f6aa50eSAnirudh Venkataramanan if (!test_bit(ICE_FLAG_DCB_ENA, tx_ring->vsi->back->flags)) 4905f6aa50eSAnirudh Venkataramanan return 0; 4915f6aa50eSAnirudh Venkataramanan 4925f6aa50eSAnirudh Venkataramanan /* Insert 802.1p priority into VLAN header */ 4935f6aa50eSAnirudh Venkataramanan if ((first->tx_flags & (ICE_TX_FLAGS_HW_VLAN | ICE_TX_FLAGS_SW_VLAN)) || 4945f6aa50eSAnirudh Venkataramanan skb->priority != TC_PRIO_CONTROL) { 4955f6aa50eSAnirudh Venkataramanan first->tx_flags &= ~ICE_TX_FLAGS_VLAN_PR_M; 4965f6aa50eSAnirudh Venkataramanan /* Mask the lower 3 bits to set the 802.1p priority */ 4975f6aa50eSAnirudh Venkataramanan first->tx_flags |= (skb->priority & 0x7) << 4985f6aa50eSAnirudh Venkataramanan ICE_TX_FLAGS_VLAN_PR_S; 4995f6aa50eSAnirudh Venkataramanan if (first->tx_flags & ICE_TX_FLAGS_SW_VLAN) { 5005f6aa50eSAnirudh Venkataramanan struct vlan_ethhdr *vhdr; 5015f6aa50eSAnirudh Venkataramanan int rc; 5025f6aa50eSAnirudh Venkataramanan 5035f6aa50eSAnirudh Venkataramanan rc = skb_cow_head(skb, 0); 5045f6aa50eSAnirudh Venkataramanan if (rc < 0) 5055f6aa50eSAnirudh Venkataramanan return rc; 5065f6aa50eSAnirudh Venkataramanan vhdr = (struct vlan_ethhdr *)skb->data; 5075f6aa50eSAnirudh Venkataramanan vhdr->h_vlan_TCI = htons(first->tx_flags >> 5085f6aa50eSAnirudh Venkataramanan ICE_TX_FLAGS_VLAN_S); 5095f6aa50eSAnirudh Venkataramanan } else { 5105f6aa50eSAnirudh Venkataramanan first->tx_flags |= ICE_TX_FLAGS_HW_VLAN; 5115f6aa50eSAnirudh Venkataramanan } 5125f6aa50eSAnirudh Venkataramanan } 5135f6aa50eSAnirudh Venkataramanan 5145f6aa50eSAnirudh Venkataramanan return 0; 5155f6aa50eSAnirudh Venkataramanan } 5165f6aa50eSAnirudh Venkataramanan 5175f6aa50eSAnirudh Venkataramanan /** 51800cc3f1bSAnirudh Venkataramanan * ice_dcb_process_lldp_set_mib_change - Process MIB change 51900cc3f1bSAnirudh Venkataramanan * @pf: ptr to ice_pf 52000cc3f1bSAnirudh Venkataramanan * @event: pointer to the admin queue receive event 52100cc3f1bSAnirudh Venkataramanan */ 52200cc3f1bSAnirudh Venkataramanan void 52300cc3f1bSAnirudh Venkataramanan ice_dcb_process_lldp_set_mib_change(struct ice_pf *pf, 52400cc3f1bSAnirudh Venkataramanan struct ice_rq_event_info *event) 52500cc3f1bSAnirudh Venkataramanan { 52600cc3f1bSAnirudh Venkataramanan if (pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) { 52700cc3f1bSAnirudh Venkataramanan struct ice_dcbx_cfg *dcbcfg, *prev_cfg; 52800cc3f1bSAnirudh Venkataramanan int err; 52900cc3f1bSAnirudh Venkataramanan 53000cc3f1bSAnirudh Venkataramanan prev_cfg = &pf->hw.port_info->local_dcbx_cfg; 53100cc3f1bSAnirudh Venkataramanan dcbcfg = devm_kmemdup(&pf->pdev->dev, prev_cfg, 53200cc3f1bSAnirudh Venkataramanan sizeof(*dcbcfg), GFP_KERNEL); 53300cc3f1bSAnirudh Venkataramanan if (!dcbcfg) 53400cc3f1bSAnirudh Venkataramanan return; 53500cc3f1bSAnirudh Venkataramanan 53600cc3f1bSAnirudh Venkataramanan err = ice_lldp_to_dcb_cfg(event->msg_buf, dcbcfg); 53700cc3f1bSAnirudh Venkataramanan if (!err) 53800cc3f1bSAnirudh Venkataramanan ice_pf_dcb_cfg(pf, dcbcfg); 53900cc3f1bSAnirudh Venkataramanan 54000cc3f1bSAnirudh Venkataramanan devm_kfree(&pf->pdev->dev, dcbcfg); 54100cc3f1bSAnirudh Venkataramanan 54200cc3f1bSAnirudh Venkataramanan /* Get updated DCBx data from firmware */ 54300cc3f1bSAnirudh Venkataramanan err = ice_get_dcb_cfg(pf->hw.port_info); 54400cc3f1bSAnirudh Venkataramanan if (err) 54500cc3f1bSAnirudh Venkataramanan dev_err(&pf->pdev->dev, 54600cc3f1bSAnirudh Venkataramanan "Failed to get DCB config\n"); 54700cc3f1bSAnirudh Venkataramanan } else { 54800cc3f1bSAnirudh Venkataramanan dev_dbg(&pf->pdev->dev, 54900cc3f1bSAnirudh Venkataramanan "MIB Change Event in HOST mode\n"); 55000cc3f1bSAnirudh Venkataramanan } 55100cc3f1bSAnirudh Venkataramanan } 552