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  */
ice_dcb_get_ena_tc(struct ice_dcbx_cfg * dcbcfg)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  */
ice_is_pfc_causing_hung_q(struct ice_pf * pf,unsigned int txqueue)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  */
ice_dcb_get_mode(struct ice_port_info * port_info,bool host)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  */
ice_dcb_get_num_tc(struct ice_dcbx_cfg * dcbcfg)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  */
ice_get_first_droptc(struct ice_vsi * vsi)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  */
ice_vsi_set_dcb_tc_cfg(struct ice_vsi * vsi)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  */
ice_dcb_get_tc(struct ice_vsi * vsi,int queue_index)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  */
ice_vsi_cfg_dcb_rings(struct ice_vsi * vsi)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  */
ice_dcb_ena_dis_vsi(struct ice_pf * pf,bool ena,bool locked)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  */
ice_dcb_bwchk(struct ice_pf * pf,struct ice_dcbx_cfg * dcbcfg)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  */
ice_pf_dcb_cfg(struct ice_pf * pf,struct ice_dcbx_cfg * new_cfg,bool locked)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 
444a6a0974aSDave Ertman 	ice_pf_dcb_recfg(pf, false);
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  */
ice_cfg_etsrec_defaults(struct ice_port_info * pi)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
ice_dcb_need_recfg(struct ice_pf * pf,struct ice_dcbx_cfg * old_cfg,struct ice_dcbx_cfg * new_cfg)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  */
ice_dcb_rebuild(struct ice_pf * pf)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  */
ice_dcb_init_cfg(struct ice_pf * pf,bool locked)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  */
ice_dcb_sw_dflt_cfg(struct ice_pf * pf,bool ets_willing,bool locked)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  */
ice_dcb_tc_contig(u8 * prio_table)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  */
ice_dcb_noncontig_cfg(struct ice_pf * pf)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
734a6a0974aSDave Ertman  * @locked: is adev device lock held
735cfbf1367SPaul Greenwalt  *
736cfbf1367SPaul Greenwalt  * Assumed caller has already disabled all VSIs before
737cfbf1367SPaul Greenwalt  * calling this function. Reconfiguring DCB based on
738cfbf1367SPaul Greenwalt  * local_dcbx_cfg.
739cfbf1367SPaul Greenwalt  */
ice_pf_dcb_recfg(struct ice_pf * pf,bool locked)740a6a0974aSDave Ertman void ice_pf_dcb_recfg(struct ice_pf *pf, bool locked)
741cfbf1367SPaul Greenwalt {
742fc2d1165SChinh T Cao 	struct ice_dcbx_cfg *dcbcfg = &pf->hw.port_info->qos_cfg.local_dcbx_cfg;
743348048e7SDave Ertman 	struct iidc_event *event;
744cfbf1367SPaul Greenwalt 	u8 tc_map = 0;
745cfbf1367SPaul Greenwalt 	int v, ret;
746cfbf1367SPaul Greenwalt 
747cfbf1367SPaul Greenwalt 	/* Update each VSI */
748cfbf1367SPaul Greenwalt 	ice_for_each_vsi(pf, v) {
7494015d11eSBrett Creeley 		struct ice_vsi *vsi = pf->vsi[v];
7504015d11eSBrett Creeley 
7514015d11eSBrett Creeley 		if (!vsi)
752cfbf1367SPaul Greenwalt 			continue;
753cfbf1367SPaul Greenwalt 
7544015d11eSBrett Creeley 		if (vsi->type == ICE_VSI_PF) {
755cfbf1367SPaul Greenwalt 			tc_map = ice_dcb_get_ena_tc(dcbcfg);
756cfbf1367SPaul Greenwalt 
757cfbf1367SPaul Greenwalt 			/* If DCBX request non-contiguous TC, then configure
758cfbf1367SPaul Greenwalt 			 * default TC
759cfbf1367SPaul Greenwalt 			 */
760cfbf1367SPaul Greenwalt 			if (!ice_dcb_tc_contig(dcbcfg->etscfg.prio_table)) {
761cfbf1367SPaul Greenwalt 				tc_map = ICE_DFLT_TRAFFIC_CLASS;
762cfbf1367SPaul Greenwalt 				ice_dcb_noncontig_cfg(pf);
763cfbf1367SPaul Greenwalt 			}
7640754d65bSKiran Patil 		} else if (vsi->type == ICE_VSI_CHNL) {
7650754d65bSKiran Patil 			tc_map = BIT(ice_get_first_droptc(vsi));
766cfbf1367SPaul Greenwalt 		} else {
767cfbf1367SPaul Greenwalt 			tc_map = ICE_DFLT_TRAFFIC_CLASS;
768cfbf1367SPaul Greenwalt 		}
769cfbf1367SPaul Greenwalt 
7704015d11eSBrett Creeley 		ret = ice_vsi_cfg_tc(vsi, tc_map);
771cfbf1367SPaul Greenwalt 		if (ret) {
7724015d11eSBrett Creeley 			dev_err(ice_pf_to_dev(pf), "Failed to config TC for VSI index: %d\n",
7734015d11eSBrett Creeley 				vsi->idx);
774cfbf1367SPaul Greenwalt 			continue;
775cfbf1367SPaul Greenwalt 		}
7760754d65bSKiran Patil 		/* no need to proceed with remaining cfg if it is CHNL
7770754d65bSKiran Patil 		 * or switchdev VSI
7787aae80ceSWojciech Drewek 		 */
7790754d65bSKiran Patil 		if (vsi->type == ICE_VSI_CHNL ||
7800754d65bSKiran Patil 		    vsi->type == ICE_VSI_SWITCHDEV_CTRL)
7817aae80ceSWojciech Drewek 			continue;
782cfbf1367SPaul Greenwalt 
7834015d11eSBrett Creeley 		ice_vsi_map_rings_to_vectors(vsi);
7844015d11eSBrett Creeley 		if (vsi->type == ICE_VSI_PF)
7854015d11eSBrett Creeley 			ice_dcbnl_set_all(vsi);
786cfbf1367SPaul Greenwalt 	}
787a6a0974aSDave Ertman 	if (!locked) {
788348048e7SDave Ertman 		/* Notify the AUX drivers that TC change is finished */
789348048e7SDave Ertman 		event = kzalloc(sizeof(*event), GFP_KERNEL);
790348048e7SDave Ertman 		if (!event)
791348048e7SDave Ertman 			return;
792348048e7SDave Ertman 
793348048e7SDave Ertman 		set_bit(IIDC_EVENT_AFTER_TC_CHANGE, event->type);
794348048e7SDave Ertman 		ice_send_event_to_aux(pf, event);
795348048e7SDave Ertman 		kfree(event);
796cfbf1367SPaul Greenwalt 	}
797a6a0974aSDave Ertman }
798cfbf1367SPaul Greenwalt 
799cfbf1367SPaul Greenwalt /**
80037b6f646SAnirudh Venkataramanan  * ice_init_pf_dcb - initialize DCB for a PF
8012f2da36eSAnirudh Venkataramanan  * @pf: PF to initialize DCB for
802e223eaecSDave Ertman  * @locked: Was function called with RTNL held
80337b6f646SAnirudh Venkataramanan  */
ice_init_pf_dcb(struct ice_pf * pf,bool locked)804e223eaecSDave Ertman int ice_init_pf_dcb(struct ice_pf *pf, bool locked)
80537b6f646SAnirudh Venkataramanan {
8064015d11eSBrett Creeley 	struct device *dev = ice_pf_to_dev(pf);
80737b6f646SAnirudh Venkataramanan 	struct ice_port_info *port_info;
80837b6f646SAnirudh Venkataramanan 	struct ice_hw *hw = &pf->hw;
8097b9ffc76SAnirudh Venkataramanan 	int err;
81037b6f646SAnirudh Venkataramanan 
81137b6f646SAnirudh Venkataramanan 	port_info = hw->port_info;
81237b6f646SAnirudh Venkataramanan 
813ea300f41SDave Ertman 	err = ice_init_dcb(hw, false);
814fc2d1165SChinh T Cao 	if (err && !port_info->qos_cfg.is_sw_lldp) {
8154015d11eSBrett Creeley 		dev_err(dev, "Error initializing DCB %d\n", err);
816473ca574SDave Ertman 		goto dcb_init_err;
817473ca574SDave Ertman 	}
818473ca574SDave Ertman 
81919cce2c6SAnirudh Venkataramanan 	dev_info(dev, "DCB is enabled in the hardware, max number of TCs supported on this port are %d\n",
820a257f188SUsha Ketineni 		 pf->hw.func_caps.common_cap.maxtc);
821473ca574SDave Ertman 	if (err) {
822241c8cf0SPaul Greenwalt 		struct ice_vsi *pf_vsi;
823241c8cf0SPaul Greenwalt 
824473ca574SDave Ertman 		/* FW LLDP is disabled, activate SW DCBX/LLDP mode */
8254015d11eSBrett Creeley 		dev_info(dev, "FW LLDP is disabled, DCBx/LLDP in SW mode.\n");
82684a118abSDave Ertman 		clear_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags);
8272a87bd73SDave Ertman 		err = ice_aq_set_pfc_mode(&pf->hw, ICE_AQC_PFC_VLAN_BASED_PFC,
8282a87bd73SDave Ertman 					  NULL);
8292a87bd73SDave Ertman 		if (err)
8302a87bd73SDave Ertman 			dev_info(dev, "Failed to set VLAN PFC mode\n");
8312a87bd73SDave Ertman 
832cfbf1367SPaul Greenwalt 		err = ice_dcb_sw_dflt_cfg(pf, true, locked);
8330deab659SAnirudh Venkataramanan 		if (err) {
83419cce2c6SAnirudh Venkataramanan 			dev_err(dev, "Failed to set local DCB config %d\n",
83519cce2c6SAnirudh Venkataramanan 				err);
8360deab659SAnirudh Venkataramanan 			err = -EIO;
8377b9ffc76SAnirudh Venkataramanan 			goto dcb_init_err;
8380deab659SAnirudh Venkataramanan 		}
8390deab659SAnirudh Venkataramanan 
840241c8cf0SPaul Greenwalt 		/* If the FW DCBX engine is not running then Rx LLDP packets
841241c8cf0SPaul Greenwalt 		 * need to be redirected up the stack.
842241c8cf0SPaul Greenwalt 		 */
843241c8cf0SPaul Greenwalt 		pf_vsi = ice_get_main_vsi(pf);
844241c8cf0SPaul Greenwalt 		if (!pf_vsi) {
8454015d11eSBrett Creeley 			dev_err(dev, "Failed to set local DCB config\n");
846241c8cf0SPaul Greenwalt 			err = -EIO;
847241c8cf0SPaul Greenwalt 			goto dcb_init_err;
848241c8cf0SPaul Greenwalt 		}
849241c8cf0SPaul Greenwalt 
850241c8cf0SPaul Greenwalt 		ice_cfg_sw_lldp(pf_vsi, false, true);
851241c8cf0SPaul Greenwalt 
85227d9be98SAvinash Dayanand 		pf->dcbx_cap = ice_dcb_get_mode(port_info, true);
8530deab659SAnirudh Venkataramanan 		return 0;
8540deab659SAnirudh Venkataramanan 	}
8557b9ffc76SAnirudh Venkataramanan 
85684a118abSDave Ertman 	set_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags);
8571b0c3247SDave Ertman 
85827d9be98SAvinash Dayanand 	/* DCBX/LLDP enabled in FW, set DCBNL mode advertisement */
85927d9be98SAvinash Dayanand 	pf->dcbx_cap = ice_dcb_get_mode(port_info, false);
8607b9ffc76SAnirudh Venkataramanan 
861e223eaecSDave Ertman 	err = ice_dcb_init_cfg(pf, locked);
8627b9ffc76SAnirudh Venkataramanan 	if (err)
8637b9ffc76SAnirudh Venkataramanan 		goto dcb_init_err;
8647b9ffc76SAnirudh Venkataramanan 
86591dbcb91STony Nguyen 	return 0;
8667b9ffc76SAnirudh Venkataramanan 
8677b9ffc76SAnirudh Venkataramanan dcb_init_err:
8687b9ffc76SAnirudh Venkataramanan 	dev_err(dev, "DCB init failed\n");
8697b9ffc76SAnirudh Venkataramanan 	return err;
87037b6f646SAnirudh Venkataramanan }
87100cc3f1bSAnirudh Venkataramanan 
87200cc3f1bSAnirudh Venkataramanan /**
8734b0fdcebSAnirudh Venkataramanan  * ice_update_dcb_stats - Update DCB stats counters
8744b0fdcebSAnirudh Venkataramanan  * @pf: PF whose stats needs to be updated
8754b0fdcebSAnirudh Venkataramanan  */
ice_update_dcb_stats(struct ice_pf * pf)8764b0fdcebSAnirudh Venkataramanan void ice_update_dcb_stats(struct ice_pf *pf)
8774b0fdcebSAnirudh Venkataramanan {
8784b0fdcebSAnirudh Venkataramanan 	struct ice_hw_port_stats *prev_ps, *cur_ps;
8794b0fdcebSAnirudh Venkataramanan 	struct ice_hw *hw = &pf->hw;
8809e7a5d17SUsha Ketineni 	u8 port;
8814b0fdcebSAnirudh Venkataramanan 	int i;
8824b0fdcebSAnirudh Venkataramanan 
8839e7a5d17SUsha Ketineni 	port = hw->port_info->lport;
8844b0fdcebSAnirudh Venkataramanan 	prev_ps = &pf->stats_prev;
8854b0fdcebSAnirudh Venkataramanan 	cur_ps = &pf->stats;
8864b0fdcebSAnirudh Venkataramanan 
8872fd5e433SBenjamin Mikailenko 	if (ice_is_reset_in_progress(pf->state))
8882fd5e433SBenjamin Mikailenko 		pf->stat_prev_loaded = false;
8892fd5e433SBenjamin Mikailenko 
8904b0fdcebSAnirudh Venkataramanan 	for (i = 0; i < 8; i++) {
8919e7a5d17SUsha Ketineni 		ice_stat_update32(hw, GLPRT_PXOFFRXC(port, i),
8924b0fdcebSAnirudh Venkataramanan 				  pf->stat_prev_loaded,
8934b0fdcebSAnirudh Venkataramanan 				  &prev_ps->priority_xoff_rx[i],
8944b0fdcebSAnirudh Venkataramanan 				  &cur_ps->priority_xoff_rx[i]);
8959e7a5d17SUsha Ketineni 		ice_stat_update32(hw, GLPRT_PXONRXC(port, i),
8964b0fdcebSAnirudh Venkataramanan 				  pf->stat_prev_loaded,
8974b0fdcebSAnirudh Venkataramanan 				  &prev_ps->priority_xon_rx[i],
8984b0fdcebSAnirudh Venkataramanan 				  &cur_ps->priority_xon_rx[i]);
8999e7a5d17SUsha Ketineni 		ice_stat_update32(hw, GLPRT_PXONTXC(port, i),
9004b0fdcebSAnirudh Venkataramanan 				  pf->stat_prev_loaded,
9014b0fdcebSAnirudh Venkataramanan 				  &prev_ps->priority_xon_tx[i],
9024b0fdcebSAnirudh Venkataramanan 				  &cur_ps->priority_xon_tx[i]);
9039e7a5d17SUsha Ketineni 		ice_stat_update32(hw, GLPRT_PXOFFTXC(port, i),
9044b0fdcebSAnirudh Venkataramanan 				  pf->stat_prev_loaded,
9054b0fdcebSAnirudh Venkataramanan 				  &prev_ps->priority_xoff_tx[i],
9064b0fdcebSAnirudh Venkataramanan 				  &cur_ps->priority_xoff_tx[i]);
9079e7a5d17SUsha Ketineni 		ice_stat_update32(hw, GLPRT_RXON2OFFCNT(port, i),
9084b0fdcebSAnirudh Venkataramanan 				  pf->stat_prev_loaded,
9094b0fdcebSAnirudh Venkataramanan 				  &prev_ps->priority_xon_2_xoff[i],
9104b0fdcebSAnirudh Venkataramanan 				  &cur_ps->priority_xon_2_xoff[i]);
9114b0fdcebSAnirudh Venkataramanan 	}
9124b0fdcebSAnirudh Venkataramanan }
9134b0fdcebSAnirudh Venkataramanan 
9144b0fdcebSAnirudh Venkataramanan /**
9155f6aa50eSAnirudh Venkataramanan  * ice_tx_prepare_vlan_flags_dcb - prepare VLAN tagging for DCB
9165f6aa50eSAnirudh Venkataramanan  * @tx_ring: ring to send buffer on
9175f6aa50eSAnirudh Venkataramanan  * @first: pointer to struct ice_tx_buf
9182bb19d6eSBrett Creeley  *
9192bb19d6eSBrett Creeley  * This should not be called if the outer VLAN is software offloaded as the VLAN
9202bb19d6eSBrett Creeley  * tag will already be configured with the correct ID and priority bits
9215f6aa50eSAnirudh Venkataramanan  */
9222bb19d6eSBrett Creeley void
ice_tx_prepare_vlan_flags_dcb(struct ice_tx_ring * tx_ring,struct ice_tx_buf * first)923e72bba21SMaciej Fijalkowski ice_tx_prepare_vlan_flags_dcb(struct ice_tx_ring *tx_ring,
9245f6aa50eSAnirudh Venkataramanan 			      struct ice_tx_buf *first)
9255f6aa50eSAnirudh Venkataramanan {
9265f6aa50eSAnirudh Venkataramanan 	struct sk_buff *skb = first->skb;
9275f6aa50eSAnirudh Venkataramanan 
9285f6aa50eSAnirudh Venkataramanan 	if (!test_bit(ICE_FLAG_DCB_ENA, tx_ring->vsi->back->flags))
9292bb19d6eSBrett Creeley 		return;
9305f6aa50eSAnirudh Venkataramanan 
9315f6aa50eSAnirudh Venkataramanan 	/* Insert 802.1p priority into VLAN header */
9320d54d8f7SBrett Creeley 	if ((first->tx_flags & ICE_TX_FLAGS_HW_VLAN ||
9330d54d8f7SBrett Creeley 	     first->tx_flags & ICE_TX_FLAGS_HW_OUTER_SINGLE_VLAN) ||
9345f6aa50eSAnirudh Venkataramanan 	    skb->priority != TC_PRIO_CONTROL) {
935*9113302bSJan Sokolowski 		first->vid &= ~VLAN_PRIO_MASK;
9365f6aa50eSAnirudh Venkataramanan 		/* Mask the lower 3 bits to set the 802.1p priority */
937*9113302bSJan Sokolowski 		first->vid |= (skb->priority << VLAN_PRIO_SHIFT) & VLAN_PRIO_MASK;
9382bb19d6eSBrett Creeley 		/* if this is not already set it means a VLAN 0 + priority needs
9392bb19d6eSBrett Creeley 		 * to be offloaded
9402bb19d6eSBrett Creeley 		 */
9410d54d8f7SBrett Creeley 		if (tx_ring->flags & ICE_TX_FLAGS_RING_VLAN_L2TAG2)
9420d54d8f7SBrett Creeley 			first->tx_flags |= ICE_TX_FLAGS_HW_OUTER_SINGLE_VLAN;
9430d54d8f7SBrett Creeley 		else
9445f6aa50eSAnirudh Venkataramanan 			first->tx_flags |= ICE_TX_FLAGS_HW_VLAN;
9455f6aa50eSAnirudh Venkataramanan 	}
9465f6aa50eSAnirudh Venkataramanan }
9475f6aa50eSAnirudh Venkataramanan 
9485f6aa50eSAnirudh Venkataramanan /**
9497d8d7754SAnatolii Gerasymenko  * ice_dcb_is_mib_change_pending - Check if MIB change is pending
9507d8d7754SAnatolii Gerasymenko  * @state: MIB change state
9517d8d7754SAnatolii Gerasymenko  */
ice_dcb_is_mib_change_pending(u8 state)9527d8d7754SAnatolii Gerasymenko static bool ice_dcb_is_mib_change_pending(u8 state)
9537d8d7754SAnatolii Gerasymenko {
9547d8d7754SAnatolii Gerasymenko 	return ICE_AQ_LLDP_MIB_CHANGE_PENDING ==
9557d8d7754SAnatolii Gerasymenko 		FIELD_GET(ICE_AQ_LLDP_MIB_CHANGE_STATE_M, state);
9567d8d7754SAnatolii Gerasymenko }
9577d8d7754SAnatolii Gerasymenko 
9587d8d7754SAnatolii Gerasymenko /**
95900cc3f1bSAnirudh Venkataramanan  * ice_dcb_process_lldp_set_mib_change - Process MIB change
96000cc3f1bSAnirudh Venkataramanan  * @pf: ptr to ice_pf
96100cc3f1bSAnirudh Venkataramanan  * @event: pointer to the admin queue receive event
96200cc3f1bSAnirudh Venkataramanan  */
96300cc3f1bSAnirudh Venkataramanan void
ice_dcb_process_lldp_set_mib_change(struct ice_pf * pf,struct ice_rq_event_info * event)96400cc3f1bSAnirudh Venkataramanan ice_dcb_process_lldp_set_mib_change(struct ice_pf *pf,
96500cc3f1bSAnirudh Venkataramanan 				    struct ice_rq_event_info *event)
96600cc3f1bSAnirudh Venkataramanan {
967a17a5ff6SUsha Ketineni 	struct ice_aqc_port_ets_elem buf = { 0 };
9684015d11eSBrett Creeley 	struct device *dev = ice_pf_to_dev(pf);
969a17a5ff6SUsha Ketineni 	struct ice_aqc_lldp_get_mib *mib;
970a17a5ff6SUsha Ketineni 	struct ice_dcbx_cfg tmp_dcbx_cfg;
9717d8d7754SAnatolii Gerasymenko 	bool pending_handled = true;
972a17a5ff6SUsha Ketineni 	bool need_reconfig = false;
973a17a5ff6SUsha Ketineni 	struct ice_port_info *pi;
9746dae8aa0SBruce Allan 	u8 mib_type;
975a17a5ff6SUsha Ketineni 	int ret;
97600cc3f1bSAnirudh Venkataramanan 
977a17a5ff6SUsha Ketineni 	/* Not DCB capable or capability disabled */
978a17a5ff6SUsha Ketineni 	if (!(test_bit(ICE_FLAG_DCB_CAPABLE, pf->flags)))
97900cc3f1bSAnirudh Venkataramanan 		return;
98000cc3f1bSAnirudh Venkataramanan 
981a17a5ff6SUsha Ketineni 	if (pf->dcbx_cap & DCB_CAP_DCBX_HOST) {
9824015d11eSBrett Creeley 		dev_dbg(dev, "MIB Change Event in HOST mode\n");
983a17a5ff6SUsha Ketineni 		return;
98400cc3f1bSAnirudh Venkataramanan 	}
985a17a5ff6SUsha Ketineni 
986a17a5ff6SUsha Ketineni 	pi = pf->hw.port_info;
987a17a5ff6SUsha Ketineni 	mib = (struct ice_aqc_lldp_get_mib *)&event->desc.params.raw;
9887d8d7754SAnatolii Gerasymenko 
989a17a5ff6SUsha Ketineni 	/* Ignore if event is not for Nearest Bridge */
9907d8d7754SAnatolii Gerasymenko 	mib_type = FIELD_GET(ICE_AQ_LLDP_BRID_TYPE_M, mib->type);
9916dae8aa0SBruce Allan 	dev_dbg(dev, "LLDP event MIB bridge type 0x%x\n", mib_type);
9926dae8aa0SBruce Allan 	if (mib_type != ICE_AQ_LLDP_BRID_TYPE_NEAREST_BRID)
993a17a5ff6SUsha Ketineni 		return;
994a17a5ff6SUsha Ketineni 
9957d8d7754SAnatolii Gerasymenko 	/* A pending change event contains accurate config information, and
9967d8d7754SAnatolii Gerasymenko 	 * the FW setting has not been updaed yet, so detect if change is
9977d8d7754SAnatolii Gerasymenko 	 * pending to determine where to pull config information from
9987d8d7754SAnatolii Gerasymenko 	 * (FW vs event)
9997d8d7754SAnatolii Gerasymenko 	 */
10007d8d7754SAnatolii Gerasymenko 	if (ice_dcb_is_mib_change_pending(mib->state))
10017d8d7754SAnatolii Gerasymenko 		pending_handled = false;
10027d8d7754SAnatolii Gerasymenko 
1003a17a5ff6SUsha Ketineni 	/* Check MIB Type and return if event for Remote MIB update */
10047d8d7754SAnatolii Gerasymenko 	mib_type = FIELD_GET(ICE_AQ_LLDP_MIB_TYPE_M, mib->type);
10056dae8aa0SBruce Allan 	dev_dbg(dev, "LLDP event mib type %s\n", mib_type ? "remote" : "local");
10066dae8aa0SBruce Allan 	if (mib_type == ICE_AQ_LLDP_MIB_REMOTE) {
1007a17a5ff6SUsha Ketineni 		/* Update the remote cached instance and return */
10087d8d7754SAnatolii Gerasymenko 		if (!pending_handled) {
10097d8d7754SAnatolii Gerasymenko 			ice_get_dcb_cfg_from_mib_change(pi, event);
10107d8d7754SAnatolii Gerasymenko 		} else {
10117d8d7754SAnatolii Gerasymenko 			ret =
10127d8d7754SAnatolii Gerasymenko 			  ice_aq_get_dcb_cfg(pi->hw, ICE_AQ_LLDP_MIB_REMOTE,
1013a17a5ff6SUsha Ketineni 					     ICE_AQ_LLDP_BRID_TYPE_NEAREST_BRID,
1014fc2d1165SChinh T Cao 					     &pi->qos_cfg.remote_dcbx_cfg);
10157d8d7754SAnatolii Gerasymenko 			if (ret)
10167d8d7754SAnatolii Gerasymenko 				dev_dbg(dev, "Failed to get remote DCB config\n");
10177d8d7754SAnatolii Gerasymenko 		}
1018a17a5ff6SUsha Ketineni 		return;
1019a17a5ff6SUsha Ketineni 	}
1020a17a5ff6SUsha Ketineni 
10217d8d7754SAnatolii Gerasymenko 	/* That a DCB change has happened is now determined */
1022242b5e06SDave Ertman 	mutex_lock(&pf->tc_mutex);
1023242b5e06SDave Ertman 
1024a17a5ff6SUsha Ketineni 	/* store the old configuration */
10257d8d7754SAnatolii Gerasymenko 	tmp_dcbx_cfg = pi->qos_cfg.local_dcbx_cfg;
1026a17a5ff6SUsha Ketineni 
10272f2da36eSAnirudh Venkataramanan 	/* Reset the old DCBX configuration data */
1028fc2d1165SChinh T Cao 	memset(&pi->qos_cfg.local_dcbx_cfg, 0,
1029fc2d1165SChinh T Cao 	       sizeof(pi->qos_cfg.local_dcbx_cfg));
1030a17a5ff6SUsha Ketineni 
10312f2da36eSAnirudh Venkataramanan 	/* Get updated DCBX data from firmware */
10327d8d7754SAnatolii Gerasymenko 	if (!pending_handled) {
10337d8d7754SAnatolii Gerasymenko 		ice_get_dcb_cfg_from_mib_change(pi, event);
10347d8d7754SAnatolii Gerasymenko 	} else {
10357d8d7754SAnatolii Gerasymenko 		ret = ice_get_dcb_cfg(pi);
1036a17a5ff6SUsha Ketineni 		if (ret) {
10374015d11eSBrett Creeley 			dev_err(dev, "Failed to get DCB config\n");
1038242b5e06SDave Ertman 			goto out;
1039a17a5ff6SUsha Ketineni 		}
10407d8d7754SAnatolii Gerasymenko 	}
1041a17a5ff6SUsha Ketineni 
1042a17a5ff6SUsha Ketineni 	/* No change detected in DCBX configs */
1043fc2d1165SChinh T Cao 	if (!memcmp(&tmp_dcbx_cfg, &pi->qos_cfg.local_dcbx_cfg,
1044fc2d1165SChinh T Cao 		    sizeof(tmp_dcbx_cfg))) {
10454015d11eSBrett Creeley 		dev_dbg(dev, "No change detected in DCBX configuration.\n");
1046242b5e06SDave Ertman 		goto out;
1047a17a5ff6SUsha Ketineni 	}
1048a17a5ff6SUsha Ketineni 
10491f454e06SAvinash JD 	pf->dcbx_cap = ice_dcb_get_mode(pi, false);
10501f454e06SAvinash JD 
1051a17a5ff6SUsha Ketineni 	need_reconfig = ice_dcb_need_recfg(pf, &tmp_dcbx_cfg,
1052fc2d1165SChinh T Cao 					   &pi->qos_cfg.local_dcbx_cfg);
1053fc2d1165SChinh T Cao 	ice_dcbnl_flush_apps(pf, &tmp_dcbx_cfg, &pi->qos_cfg.local_dcbx_cfg);
1054a17a5ff6SUsha Ketineni 	if (!need_reconfig)
1055242b5e06SDave Ertman 		goto out;
1056a17a5ff6SUsha Ketineni 
1057a17a5ff6SUsha Ketineni 	/* Enable DCB tagging only when more than one TC */
1058fc2d1165SChinh T Cao 	if (ice_dcb_get_num_tc(&pi->qos_cfg.local_dcbx_cfg) > 1) {
10594015d11eSBrett Creeley 		dev_dbg(dev, "DCB tagging enabled (num TC > 1)\n");
1060a17a5ff6SUsha Ketineni 		set_bit(ICE_FLAG_DCB_ENA, pf->flags);
1061a17a5ff6SUsha Ketineni 	} else {
10624015d11eSBrett Creeley 		dev_dbg(dev, "DCB tagging disabled (num TC = 1)\n");
1063a17a5ff6SUsha Ketineni 		clear_bit(ICE_FLAG_DCB_ENA, pf->flags);
1064a17a5ff6SUsha Ketineni 	}
1065a17a5ff6SUsha Ketineni 
10667d8d7754SAnatolii Gerasymenko 	/* Send Execute Pending MIB Change event if it is a Pending event */
10677d8d7754SAnatolii Gerasymenko 	if (!pending_handled) {
10687d8d7754SAnatolii Gerasymenko 		ice_lldp_execute_pending_mib(&pf->hw);
10697d8d7754SAnatolii Gerasymenko 		pending_handled = true;
10707d8d7754SAnatolii Gerasymenko 	}
10717d8d7754SAnatolii Gerasymenko 
1072a17a5ff6SUsha Ketineni 	rtnl_lock();
10730754d65bSKiran Patil 	/* disable VSIs affected by DCB changes */
10740754d65bSKiran Patil 	ice_dcb_ena_dis_vsi(pf, false, true);
1075a17a5ff6SUsha Ketineni 
10767d8d7754SAnatolii Gerasymenko 	ret = ice_query_port_ets(pi, &buf, sizeof(buf), NULL);
1077a17a5ff6SUsha Ketineni 	if (ret) {
10784015d11eSBrett Creeley 		dev_err(dev, "Query Port ETS failed\n");
1079242b5e06SDave Ertman 		goto unlock_rtnl;
1080a17a5ff6SUsha Ketineni 	}
1081a17a5ff6SUsha Ketineni 
1082a17a5ff6SUsha Ketineni 	/* changes in configuration update VSI */
1083a6a0974aSDave Ertman 	ice_pf_dcb_recfg(pf, false);
1084a17a5ff6SUsha Ketineni 
10850754d65bSKiran Patil 	/* enable previously downed VSIs */
10860754d65bSKiran Patil 	ice_dcb_ena_dis_vsi(pf, true, true);
1087242b5e06SDave Ertman unlock_rtnl:
1088a17a5ff6SUsha Ketineni 	rtnl_unlock();
1089242b5e06SDave Ertman out:
1090242b5e06SDave Ertman 	mutex_unlock(&pf->tc_mutex);
10917d8d7754SAnatolii Gerasymenko 
10927d8d7754SAnatolii Gerasymenko 	/* Send Execute Pending MIB Change event if it is a Pending event */
10937d8d7754SAnatolii Gerasymenko 	if (!pending_handled)
10947d8d7754SAnatolii Gerasymenko 		ice_lldp_execute_pending_mib(&pf->hw);
109500cc3f1bSAnirudh Venkataramanan }
1096