137b6f646SAnirudh Venkataramanan // SPDX-License-Identifier: GPL-2.0
237b6f646SAnirudh Venkataramanan /* Copyright (c) 2019, Intel Corporation. */
337b6f646SAnirudh Venkataramanan 
437b6f646SAnirudh Venkataramanan #include "ice_dcb_lib.h"
5b94b013eSDave Ertman #include "ice_dcb_nl.h"
637b6f646SAnirudh Venkataramanan 
737b6f646SAnirudh Venkataramanan /**
8462acf6aSTony Nguyen  * ice_vsi_cfg_netdev_tc - Setup the netdev TC configuration
9462acf6aSTony Nguyen  * @vsi: the VSI being configured
10462acf6aSTony Nguyen  * @ena_tc: TC map to be enabled
11462acf6aSTony Nguyen  */
12462acf6aSTony Nguyen void ice_vsi_cfg_netdev_tc(struct ice_vsi *vsi, u8 ena_tc)
13462acf6aSTony Nguyen {
14462acf6aSTony Nguyen 	struct net_device *netdev = vsi->netdev;
15462acf6aSTony Nguyen 	struct ice_pf *pf = vsi->back;
16462acf6aSTony Nguyen 	struct ice_dcbx_cfg *dcbcfg;
17462acf6aSTony Nguyen 	u8 netdev_tc;
18462acf6aSTony Nguyen 	int i;
19462acf6aSTony Nguyen 
20462acf6aSTony Nguyen 	if (!netdev)
21462acf6aSTony Nguyen 		return;
22462acf6aSTony Nguyen 
23462acf6aSTony Nguyen 	if (!ena_tc) {
24462acf6aSTony Nguyen 		netdev_reset_tc(netdev);
25462acf6aSTony Nguyen 		return;
26462acf6aSTony Nguyen 	}
27462acf6aSTony Nguyen 
28462acf6aSTony Nguyen 	if (netdev_set_num_tc(netdev, vsi->tc_cfg.numtc))
29462acf6aSTony Nguyen 		return;
30462acf6aSTony Nguyen 
31462acf6aSTony Nguyen 	dcbcfg = &pf->hw.port_info->local_dcbx_cfg;
32462acf6aSTony Nguyen 
33462acf6aSTony Nguyen 	ice_for_each_traffic_class(i)
34462acf6aSTony Nguyen 		if (vsi->tc_cfg.ena_tc & BIT(i))
35462acf6aSTony Nguyen 			netdev_set_tc_queue(netdev,
36462acf6aSTony Nguyen 					    vsi->tc_cfg.tc_info[i].netdev_tc,
37462acf6aSTony Nguyen 					    vsi->tc_cfg.tc_info[i].qcount_tx,
38462acf6aSTony Nguyen 					    vsi->tc_cfg.tc_info[i].qoffset);
39462acf6aSTony Nguyen 
40462acf6aSTony Nguyen 	for (i = 0; i < ICE_MAX_USER_PRIORITY; i++) {
41462acf6aSTony Nguyen 		u8 ets_tc = dcbcfg->etscfg.prio_table[i];
42462acf6aSTony Nguyen 
43462acf6aSTony Nguyen 		/* Get the mapped netdev TC# for the UP */
44462acf6aSTony Nguyen 		netdev_tc = vsi->tc_cfg.tc_info[ets_tc].netdev_tc;
45462acf6aSTony Nguyen 		netdev_set_prio_tc_map(netdev, i, netdev_tc);
46462acf6aSTony Nguyen 	}
47462acf6aSTony Nguyen }
48462acf6aSTony Nguyen 
49462acf6aSTony Nguyen /**
507b9ffc76SAnirudh Venkataramanan  * ice_dcb_get_ena_tc - return bitmap of enabled TCs
517b9ffc76SAnirudh Venkataramanan  * @dcbcfg: DCB config to evaluate for enabled TCs
527b9ffc76SAnirudh Venkataramanan  */
537b9ffc76SAnirudh Venkataramanan u8 ice_dcb_get_ena_tc(struct ice_dcbx_cfg *dcbcfg)
547b9ffc76SAnirudh Venkataramanan {
557b9ffc76SAnirudh Venkataramanan 	u8 i, num_tc, ena_tc = 1;
567b9ffc76SAnirudh Venkataramanan 
577b9ffc76SAnirudh Venkataramanan 	num_tc = ice_dcb_get_num_tc(dcbcfg);
587b9ffc76SAnirudh Venkataramanan 
597b9ffc76SAnirudh Venkataramanan 	for (i = 0; i < num_tc; i++)
607b9ffc76SAnirudh Venkataramanan 		ena_tc |= BIT(i);
617b9ffc76SAnirudh Venkataramanan 
627b9ffc76SAnirudh Venkataramanan 	return ena_tc;
637b9ffc76SAnirudh Venkataramanan }
647b9ffc76SAnirudh Venkataramanan 
657b9ffc76SAnirudh Venkataramanan /**
667b9ffc76SAnirudh Venkataramanan  * ice_dcb_get_num_tc - Get the number of TCs from DCBX config
677b9ffc76SAnirudh Venkataramanan  * @dcbcfg: config to retrieve number of TCs from
687b9ffc76SAnirudh Venkataramanan  */
697b9ffc76SAnirudh Venkataramanan u8 ice_dcb_get_num_tc(struct ice_dcbx_cfg *dcbcfg)
707b9ffc76SAnirudh Venkataramanan {
717b9ffc76SAnirudh Venkataramanan 	bool tc_unused = false;
727b9ffc76SAnirudh Venkataramanan 	u8 num_tc = 0;
737b9ffc76SAnirudh Venkataramanan 	u8 ret = 0;
747b9ffc76SAnirudh Venkataramanan 	int i;
757b9ffc76SAnirudh Venkataramanan 
767b9ffc76SAnirudh Venkataramanan 	/* Scan the ETS Config Priority Table to find traffic classes
777b9ffc76SAnirudh Venkataramanan 	 * enabled and create a bitmask of enabled TCs
787b9ffc76SAnirudh Venkataramanan 	 */
797b9ffc76SAnirudh Venkataramanan 	for (i = 0; i < CEE_DCBX_MAX_PRIO; i++)
807b9ffc76SAnirudh Venkataramanan 		num_tc |= BIT(dcbcfg->etscfg.prio_table[i]);
817b9ffc76SAnirudh Venkataramanan 
827b9ffc76SAnirudh Venkataramanan 	/* Scan bitmask for contiguous TCs starting with TC0 */
837b9ffc76SAnirudh Venkataramanan 	for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
847b9ffc76SAnirudh Venkataramanan 		if (num_tc & BIT(i)) {
857b9ffc76SAnirudh Venkataramanan 			if (!tc_unused) {
867b9ffc76SAnirudh Venkataramanan 				ret++;
877b9ffc76SAnirudh Venkataramanan 			} else {
887b9ffc76SAnirudh Venkataramanan 				pr_err("Non-contiguous TCs - Disabling DCB\n");
897b9ffc76SAnirudh Venkataramanan 				return 1;
907b9ffc76SAnirudh Venkataramanan 			}
917b9ffc76SAnirudh Venkataramanan 		} else {
927b9ffc76SAnirudh Venkataramanan 			tc_unused = true;
937b9ffc76SAnirudh Venkataramanan 		}
947b9ffc76SAnirudh Venkataramanan 	}
957b9ffc76SAnirudh Venkataramanan 
967b9ffc76SAnirudh Venkataramanan 	/* There is always at least 1 TC */
977b9ffc76SAnirudh Venkataramanan 	if (!ret)
987b9ffc76SAnirudh Venkataramanan 		ret = 1;
997b9ffc76SAnirudh Venkataramanan 
1007b9ffc76SAnirudh Venkataramanan 	return ret;
1017b9ffc76SAnirudh Venkataramanan }
1027b9ffc76SAnirudh Venkataramanan 
1037b9ffc76SAnirudh Venkataramanan /**
1041ddef455SUsha Ketineni  * ice_dcb_get_tc - Get the TC associated with the queue
1051ddef455SUsha Ketineni  * @vsi: ptr to the VSI
1061ddef455SUsha Ketineni  * @queue_index: queue number associated with VSI
1071ddef455SUsha Ketineni  */
1081ddef455SUsha Ketineni u8 ice_dcb_get_tc(struct ice_vsi *vsi, int queue_index)
1091ddef455SUsha Ketineni {
1101ddef455SUsha Ketineni 	return vsi->tx_rings[queue_index]->dcb_tc;
1111ddef455SUsha Ketineni }
1121ddef455SUsha Ketineni 
1131ddef455SUsha Ketineni /**
114a629cf0aSAnirudh Venkataramanan  * ice_vsi_cfg_dcb_rings - Update rings to reflect DCB TC
115a629cf0aSAnirudh Venkataramanan  * @vsi: VSI owner of rings being updated
116a629cf0aSAnirudh Venkataramanan  */
117a629cf0aSAnirudh Venkataramanan void ice_vsi_cfg_dcb_rings(struct ice_vsi *vsi)
118a629cf0aSAnirudh Venkataramanan {
119a629cf0aSAnirudh Venkataramanan 	struct ice_ring *tx_ring, *rx_ring;
120a629cf0aSAnirudh Venkataramanan 	u16 qoffset, qcount;
121a629cf0aSAnirudh Venkataramanan 	int i, n;
122a629cf0aSAnirudh Venkataramanan 
123a629cf0aSAnirudh Venkataramanan 	if (!test_bit(ICE_FLAG_DCB_ENA, vsi->back->flags)) {
124a629cf0aSAnirudh Venkataramanan 		/* Reset the TC information */
125a629cf0aSAnirudh Venkataramanan 		for (i = 0; i < vsi->num_txq; i++) {
126a629cf0aSAnirudh Venkataramanan 			tx_ring = vsi->tx_rings[i];
127a629cf0aSAnirudh Venkataramanan 			tx_ring->dcb_tc = 0;
128a629cf0aSAnirudh Venkataramanan 		}
129a629cf0aSAnirudh Venkataramanan 		for (i = 0; i < vsi->num_rxq; i++) {
130a629cf0aSAnirudh Venkataramanan 			rx_ring = vsi->rx_rings[i];
131a629cf0aSAnirudh Venkataramanan 			rx_ring->dcb_tc = 0;
132a629cf0aSAnirudh Venkataramanan 		}
133a629cf0aSAnirudh Venkataramanan 		return;
134a629cf0aSAnirudh Venkataramanan 	}
135a629cf0aSAnirudh Venkataramanan 
136a629cf0aSAnirudh Venkataramanan 	ice_for_each_traffic_class(n) {
137a629cf0aSAnirudh Venkataramanan 		if (!(vsi->tc_cfg.ena_tc & BIT(n)))
138a629cf0aSAnirudh Venkataramanan 			break;
139a629cf0aSAnirudh Venkataramanan 
140a629cf0aSAnirudh Venkataramanan 		qoffset = vsi->tc_cfg.tc_info[n].qoffset;
141a629cf0aSAnirudh Venkataramanan 		qcount = vsi->tc_cfg.tc_info[n].qcount_tx;
142a629cf0aSAnirudh Venkataramanan 		for (i = qoffset; i < (qoffset + qcount); i++) {
143a629cf0aSAnirudh Venkataramanan 			tx_ring = vsi->tx_rings[i];
144a629cf0aSAnirudh Venkataramanan 			rx_ring = vsi->rx_rings[i];
145a629cf0aSAnirudh Venkataramanan 			tx_ring->dcb_tc = n;
146a629cf0aSAnirudh Venkataramanan 			rx_ring->dcb_tc = n;
147a629cf0aSAnirudh Venkataramanan 		}
148a629cf0aSAnirudh Venkataramanan 	}
149a629cf0aSAnirudh Venkataramanan }
150a629cf0aSAnirudh Venkataramanan 
151a629cf0aSAnirudh Venkataramanan /**
152a29a912dSAvinash Dayanand  * ice_dcb_bwchk - check if ETS bandwidth input parameters are correct
153a29a912dSAvinash Dayanand  * @pf: pointer to the PF struct
154a29a912dSAvinash Dayanand  * @dcbcfg: pointer to DCB config structure
155a29a912dSAvinash Dayanand  */
156a29a912dSAvinash Dayanand int ice_dcb_bwchk(struct ice_pf *pf, struct ice_dcbx_cfg *dcbcfg)
157a29a912dSAvinash Dayanand {
158a29a912dSAvinash Dayanand 	struct ice_dcb_ets_cfg *etscfg = &dcbcfg->etscfg;
159a29a912dSAvinash Dayanand 	u8 num_tc, total_bw = 0;
160a29a912dSAvinash Dayanand 	int i;
161a29a912dSAvinash Dayanand 
162a29a912dSAvinash Dayanand 	/* returns number of contigous TCs and 1 TC for non-contigous TCs,
163a29a912dSAvinash Dayanand 	 * since at least 1 TC has to be configured
164a29a912dSAvinash Dayanand 	 */
165a29a912dSAvinash Dayanand 	num_tc = ice_dcb_get_num_tc(dcbcfg);
166a29a912dSAvinash Dayanand 
167a29a912dSAvinash Dayanand 	/* no bandwidth checks required if there's only one TC, so assign
168a29a912dSAvinash Dayanand 	 * all bandwidth to TC0 and return
169a29a912dSAvinash Dayanand 	 */
170a29a912dSAvinash Dayanand 	if (num_tc == 1) {
171a29a912dSAvinash Dayanand 		etscfg->tcbwtable[0] = ICE_TC_MAX_BW;
172a29a912dSAvinash Dayanand 		return 0;
173a29a912dSAvinash Dayanand 	}
174a29a912dSAvinash Dayanand 
175a29a912dSAvinash Dayanand 	for (i = 0; i < num_tc; i++)
176a29a912dSAvinash Dayanand 		total_bw += etscfg->tcbwtable[i];
177a29a912dSAvinash Dayanand 
178a29a912dSAvinash Dayanand 	if (!total_bw) {
179a29a912dSAvinash Dayanand 		etscfg->tcbwtable[0] = ICE_TC_MAX_BW;
180a29a912dSAvinash Dayanand 	} else if (total_bw != ICE_TC_MAX_BW) {
181a29a912dSAvinash Dayanand 		dev_err(ice_pf_to_dev(pf), "Invalid config, total bandwidth must equal 100\n");
182a29a912dSAvinash Dayanand 		return -EINVAL;
183a29a912dSAvinash Dayanand 	}
184a29a912dSAvinash Dayanand 
185a29a912dSAvinash Dayanand 	return 0;
186a29a912dSAvinash Dayanand }
187a29a912dSAvinash Dayanand 
188a29a912dSAvinash Dayanand /**
1897b9ffc76SAnirudh Venkataramanan  * ice_pf_dcb_cfg - Apply new DCB configuration
1907b9ffc76SAnirudh Venkataramanan  * @pf: pointer to the PF struct
1917b9ffc76SAnirudh Venkataramanan  * @new_cfg: DCBX config to apply
192e223eaecSDave Ertman  * @locked: is the RTNL held
1937b9ffc76SAnirudh Venkataramanan  */
194e223eaecSDave Ertman int ice_pf_dcb_cfg(struct ice_pf *pf, struct ice_dcbx_cfg *new_cfg, bool locked)
1957b9ffc76SAnirudh Venkataramanan {
1967b9ffc76SAnirudh Venkataramanan 	struct ice_aqc_port_ets_elem buf = { 0 };
197b94b013eSDave Ertman 	struct ice_dcbx_cfg *old_cfg, *curr_cfg;
1984015d11eSBrett Creeley 	struct device *dev = ice_pf_to_dev(pf);
199b94b013eSDave Ertman 	int ret = ICE_DCB_NO_HW_CHG;
2009d614b64SAnirudh Venkataramanan 	struct ice_vsi *pf_vsi;
2017b9ffc76SAnirudh Venkataramanan 
2027b9ffc76SAnirudh Venkataramanan 	curr_cfg = &pf->hw.port_info->local_dcbx_cfg;
2037b9ffc76SAnirudh Venkataramanan 
204b94b013eSDave Ertman 	/* FW does not care if change happened */
205b94b013eSDave Ertman 	if (!pf->hw.port_info->is_sw_lldp)
206b94b013eSDave Ertman 		ret = ICE_DCB_HW_CHG_RST;
207b94b013eSDave Ertman 
2087b9ffc76SAnirudh Venkataramanan 	/* Enable DCB tagging only when more than one TC */
2097b9ffc76SAnirudh Venkataramanan 	if (ice_dcb_get_num_tc(new_cfg) > 1) {
2104015d11eSBrett Creeley 		dev_dbg(dev, "DCB tagging enabled (num TC > 1)\n");
2117b9ffc76SAnirudh Venkataramanan 		set_bit(ICE_FLAG_DCB_ENA, pf->flags);
2127b9ffc76SAnirudh Venkataramanan 	} else {
2134015d11eSBrett Creeley 		dev_dbg(dev, "DCB tagging disabled (num TC = 1)\n");
2147b9ffc76SAnirudh Venkataramanan 		clear_bit(ICE_FLAG_DCB_ENA, pf->flags);
2157b9ffc76SAnirudh Venkataramanan 	}
2167b9ffc76SAnirudh Venkataramanan 
2177b9ffc76SAnirudh Venkataramanan 	if (!memcmp(new_cfg, curr_cfg, sizeof(*new_cfg))) {
2184015d11eSBrett Creeley 		dev_dbg(dev, "No change in DCB config required\n");
2197b9ffc76SAnirudh Venkataramanan 		return ret;
2207b9ffc76SAnirudh Venkataramanan 	}
2217b9ffc76SAnirudh Venkataramanan 
222a29a912dSAvinash Dayanand 	if (ice_dcb_bwchk(pf, new_cfg))
223a29a912dSAvinash Dayanand 		return -EINVAL;
224a29a912dSAvinash Dayanand 
2257b9ffc76SAnirudh Venkataramanan 	/* Store old config in case FW config fails */
2269d614b64SAnirudh Venkataramanan 	old_cfg = kmemdup(curr_cfg, sizeof(*old_cfg), GFP_KERNEL);
2279d614b64SAnirudh Venkataramanan 	if (!old_cfg)
2289d614b64SAnirudh Venkataramanan 		return -ENOMEM;
2299d614b64SAnirudh Venkataramanan 
2304015d11eSBrett Creeley 	dev_info(dev, "Commit DCB Configuration to the hardware\n");
2319d614b64SAnirudh Venkataramanan 	pf_vsi = ice_get_main_vsi(pf);
2329d614b64SAnirudh Venkataramanan 	if (!pf_vsi) {
2334015d11eSBrett Creeley 		dev_dbg(dev, "PF VSI doesn't exist\n");
2349d614b64SAnirudh Venkataramanan 		ret = -EINVAL;
2359d614b64SAnirudh Venkataramanan 		goto free_cfg;
2369d614b64SAnirudh Venkataramanan 	}
2377b9ffc76SAnirudh Venkataramanan 
2387b9ffc76SAnirudh Venkataramanan 	/* avoid race conditions by holding the lock while disabling and
2397b9ffc76SAnirudh Venkataramanan 	 * re-enabling the VSI
2407b9ffc76SAnirudh Venkataramanan 	 */
241e223eaecSDave Ertman 	if (!locked)
2427b9ffc76SAnirudh Venkataramanan 		rtnl_lock();
2439d614b64SAnirudh Venkataramanan 	ice_dis_vsi(pf_vsi, true);
2447b9ffc76SAnirudh Venkataramanan 
2457b9ffc76SAnirudh Venkataramanan 	memcpy(curr_cfg, new_cfg, sizeof(*curr_cfg));
2467b9ffc76SAnirudh Venkataramanan 	memcpy(&curr_cfg->etsrec, &curr_cfg->etscfg, sizeof(curr_cfg->etsrec));
247b94b013eSDave Ertman 	memcpy(&new_cfg->etsrec, &curr_cfg->etscfg, sizeof(curr_cfg->etsrec));
2487b9ffc76SAnirudh Venkataramanan 
2497b9ffc76SAnirudh Venkataramanan 	/* Only send new config to HW if we are in SW LLDP mode. Otherwise,
2507b9ffc76SAnirudh Venkataramanan 	 * the new config came from the HW in the first place.
2517b9ffc76SAnirudh Venkataramanan 	 */
2527b9ffc76SAnirudh Venkataramanan 	if (pf->hw.port_info->is_sw_lldp) {
2537b9ffc76SAnirudh Venkataramanan 		ret = ice_set_dcb_cfg(pf->hw.port_info);
2547b9ffc76SAnirudh Venkataramanan 		if (ret) {
2554015d11eSBrett Creeley 			dev_err(dev, "Set DCB Config failed\n");
2567b9ffc76SAnirudh Venkataramanan 			/* Restore previous settings to local config */
2577b9ffc76SAnirudh Venkataramanan 			memcpy(curr_cfg, old_cfg, sizeof(*curr_cfg));
2587b9ffc76SAnirudh Venkataramanan 			goto out;
2597b9ffc76SAnirudh Venkataramanan 		}
2607b9ffc76SAnirudh Venkataramanan 	}
2617b9ffc76SAnirudh Venkataramanan 
2627b9ffc76SAnirudh Venkataramanan 	ret = ice_query_port_ets(pf->hw.port_info, &buf, sizeof(buf), NULL);
2637b9ffc76SAnirudh Venkataramanan 	if (ret) {
2644015d11eSBrett Creeley 		dev_err(dev, "Query Port ETS failed\n");
2657b9ffc76SAnirudh Venkataramanan 		goto out;
2667b9ffc76SAnirudh Venkataramanan 	}
2677b9ffc76SAnirudh Venkataramanan 
2687b9ffc76SAnirudh Venkataramanan 	ice_pf_dcb_recfg(pf);
2697b9ffc76SAnirudh Venkataramanan 
2707b9ffc76SAnirudh Venkataramanan out:
2719d614b64SAnirudh Venkataramanan 	ice_ena_vsi(pf_vsi, true);
272e223eaecSDave Ertman 	if (!locked)
2737b9ffc76SAnirudh Venkataramanan 		rtnl_unlock();
2749d614b64SAnirudh Venkataramanan free_cfg:
2759d614b64SAnirudh Venkataramanan 	kfree(old_cfg);
2767b9ffc76SAnirudh Venkataramanan 	return ret;
2777b9ffc76SAnirudh Venkataramanan }
2787b9ffc76SAnirudh Venkataramanan 
2797b9ffc76SAnirudh Venkataramanan /**
2807829570eSUsha Ketineni  * ice_cfg_etsrec_defaults - Set default ETS recommended DCB config
2817829570eSUsha Ketineni  * @pi: port information structure
2827829570eSUsha Ketineni  */
2837829570eSUsha Ketineni static void ice_cfg_etsrec_defaults(struct ice_port_info *pi)
2847829570eSUsha Ketineni {
2857829570eSUsha Ketineni 	struct ice_dcbx_cfg *dcbcfg = &pi->local_dcbx_cfg;
2867829570eSUsha Ketineni 	u8 i;
2877829570eSUsha Ketineni 
2887829570eSUsha Ketineni 	/* Ensure ETS recommended DCB configuration is not already set */
2897829570eSUsha Ketineni 	if (dcbcfg->etsrec.maxtcs)
2907829570eSUsha Ketineni 		return;
2917829570eSUsha Ketineni 
2927829570eSUsha Ketineni 	/* In CEE mode, set the default to 1 TC */
2937829570eSUsha Ketineni 	dcbcfg->etsrec.maxtcs = 1;
2947829570eSUsha Ketineni 	for (i = 0; i < ICE_MAX_TRAFFIC_CLASS; i++) {
2957829570eSUsha Ketineni 		dcbcfg->etsrec.tcbwtable[i] = i ? 0 : 100;
2967829570eSUsha Ketineni 		dcbcfg->etsrec.tsatable[i] = i ? ICE_IEEE_TSA_STRICT :
2977829570eSUsha Ketineni 						 ICE_IEEE_TSA_ETS;
2987829570eSUsha Ketineni 	}
2997829570eSUsha Ketineni }
3007829570eSUsha Ketineni 
3017829570eSUsha Ketineni /**
3027829570eSUsha Ketineni  * ice_dcb_need_recfg - Check if DCB needs reconfig
3037829570eSUsha Ketineni  * @pf: board private structure
3047829570eSUsha Ketineni  * @old_cfg: current DCB config
3057829570eSUsha Ketineni  * @new_cfg: new DCB config
3067829570eSUsha Ketineni  */
3077829570eSUsha Ketineni static bool
3087829570eSUsha Ketineni ice_dcb_need_recfg(struct ice_pf *pf, struct ice_dcbx_cfg *old_cfg,
3097829570eSUsha Ketineni 		   struct ice_dcbx_cfg *new_cfg)
3107829570eSUsha Ketineni {
3114015d11eSBrett Creeley 	struct device *dev = ice_pf_to_dev(pf);
3127829570eSUsha Ketineni 	bool need_reconfig = false;
3137829570eSUsha Ketineni 
3147829570eSUsha Ketineni 	/* Check if ETS configuration has changed */
3157829570eSUsha Ketineni 	if (memcmp(&new_cfg->etscfg, &old_cfg->etscfg,
3167829570eSUsha Ketineni 		   sizeof(new_cfg->etscfg))) {
3177829570eSUsha Ketineni 		/* If Priority Table has changed reconfig is needed */
3187829570eSUsha Ketineni 		if (memcmp(&new_cfg->etscfg.prio_table,
3197829570eSUsha Ketineni 			   &old_cfg->etscfg.prio_table,
3207829570eSUsha Ketineni 			   sizeof(new_cfg->etscfg.prio_table))) {
3217829570eSUsha Ketineni 			need_reconfig = true;
3224015d11eSBrett Creeley 			dev_dbg(dev, "ETS UP2TC changed.\n");
3237829570eSUsha Ketineni 		}
3247829570eSUsha Ketineni 
3257829570eSUsha Ketineni 		if (memcmp(&new_cfg->etscfg.tcbwtable,
3267829570eSUsha Ketineni 			   &old_cfg->etscfg.tcbwtable,
3277829570eSUsha Ketineni 			   sizeof(new_cfg->etscfg.tcbwtable)))
3284015d11eSBrett Creeley 			dev_dbg(dev, "ETS TC BW Table changed.\n");
3297829570eSUsha Ketineni 
3307829570eSUsha Ketineni 		if (memcmp(&new_cfg->etscfg.tsatable,
3317829570eSUsha Ketineni 			   &old_cfg->etscfg.tsatable,
3327829570eSUsha Ketineni 			   sizeof(new_cfg->etscfg.tsatable)))
3334015d11eSBrett Creeley 			dev_dbg(dev, "ETS TSA Table changed.\n");
3347829570eSUsha Ketineni 	}
3357829570eSUsha Ketineni 
3367829570eSUsha Ketineni 	/* Check if PFC configuration has changed */
3377829570eSUsha Ketineni 	if (memcmp(&new_cfg->pfc, &old_cfg->pfc, sizeof(new_cfg->pfc))) {
3387829570eSUsha Ketineni 		need_reconfig = true;
3394015d11eSBrett Creeley 		dev_dbg(dev, "PFC config change detected.\n");
3407829570eSUsha Ketineni 	}
3417829570eSUsha Ketineni 
3427829570eSUsha Ketineni 	/* Check if APP Table has changed */
3437829570eSUsha Ketineni 	if (memcmp(&new_cfg->app, &old_cfg->app, sizeof(new_cfg->app))) {
3447829570eSUsha Ketineni 		need_reconfig = true;
3454015d11eSBrett Creeley 		dev_dbg(dev, "APP Table change detected.\n");
3467829570eSUsha Ketineni 	}
3477829570eSUsha Ketineni 
3484015d11eSBrett Creeley 	dev_dbg(dev, "dcb need_reconfig=%d\n", need_reconfig);
3497829570eSUsha Ketineni 	return need_reconfig;
3507829570eSUsha Ketineni }
3517829570eSUsha Ketineni 
3527829570eSUsha Ketineni /**
353b832c2f6SAnirudh Venkataramanan  * ice_dcb_rebuild - rebuild DCB post reset
354b832c2f6SAnirudh Venkataramanan  * @pf: physical function instance
355b832c2f6SAnirudh Venkataramanan  */
356b832c2f6SAnirudh Venkataramanan void ice_dcb_rebuild(struct ice_pf *pf)
357b832c2f6SAnirudh Venkataramanan {
358b832c2f6SAnirudh Venkataramanan 	struct ice_aqc_port_ets_elem buf = { 0 };
3594015d11eSBrett Creeley 	struct device *dev = ice_pf_to_dev(pf);
360242b5e06SDave Ertman 	struct ice_dcbx_cfg *err_cfg;
361b832c2f6SAnirudh Venkataramanan 	enum ice_status ret;
362b832c2f6SAnirudh Venkataramanan 
363b832c2f6SAnirudh Venkataramanan 	ret = ice_query_port_ets(pf->hw.port_info, &buf, sizeof(buf), NULL);
364b832c2f6SAnirudh Venkataramanan 	if (ret) {
3654015d11eSBrett Creeley 		dev_err(dev, "Query Port ETS failed\n");
366b832c2f6SAnirudh Venkataramanan 		goto dcb_error;
367b832c2f6SAnirudh Venkataramanan 	}
368b832c2f6SAnirudh Venkataramanan 
369b832c2f6SAnirudh Venkataramanan 	/* If DCB was not enabled previously, we are done */
370b832c2f6SAnirudh Venkataramanan 	if (!test_bit(ICE_FLAG_DCB_ENA, pf->flags))
371b832c2f6SAnirudh Venkataramanan 		return;
372b832c2f6SAnirudh Venkataramanan 
373242b5e06SDave Ertman 	mutex_lock(&pf->tc_mutex);
3747829570eSUsha Ketineni 
375242b5e06SDave Ertman 	if (!pf->hw.port_info->is_sw_lldp)
3767829570eSUsha Ketineni 		ice_cfg_etsrec_defaults(pf->hw.port_info);
377242b5e06SDave Ertman 
378b832c2f6SAnirudh Venkataramanan 	ret = ice_set_dcb_cfg(pf->hw.port_info);
379b832c2f6SAnirudh Venkataramanan 	if (ret) {
380242b5e06SDave Ertman 		dev_err(dev, "Failed to set DCB config in rebuild\n");
381b832c2f6SAnirudh Venkataramanan 		goto dcb_error;
382b832c2f6SAnirudh Venkataramanan 	}
383b832c2f6SAnirudh Venkataramanan 
384242b5e06SDave Ertman 	if (!pf->hw.port_info->is_sw_lldp) {
385242b5e06SDave Ertman 		ret = ice_cfg_lldp_mib_change(&pf->hw, true);
386242b5e06SDave Ertman 		if (ret && !pf->hw.port_info->is_sw_lldp) {
387242b5e06SDave Ertman 			dev_err(dev, "Failed to register for MIB changes\n");
388b832c2f6SAnirudh Venkataramanan 			goto dcb_error;
389b832c2f6SAnirudh Venkataramanan 		}
390b832c2f6SAnirudh Venkataramanan 	}
391242b5e06SDave Ertman 
3924015d11eSBrett Creeley 	dev_info(dev, "DCB restored after reset\n");
393b832c2f6SAnirudh Venkataramanan 	ret = ice_query_port_ets(pf->hw.port_info, &buf, sizeof(buf), NULL);
394b832c2f6SAnirudh Venkataramanan 	if (ret) {
3954015d11eSBrett Creeley 		dev_err(dev, "Query Port ETS failed\n");
396b832c2f6SAnirudh Venkataramanan 		goto dcb_error;
397b832c2f6SAnirudh Venkataramanan 	}
398b832c2f6SAnirudh Venkataramanan 
399242b5e06SDave Ertman 	mutex_unlock(&pf->tc_mutex);
400242b5e06SDave Ertman 
401b832c2f6SAnirudh Venkataramanan 	return;
402b832c2f6SAnirudh Venkataramanan 
403b832c2f6SAnirudh Venkataramanan dcb_error:
4044015d11eSBrett Creeley 	dev_err(dev, "Disabling DCB until new settings occur\n");
405242b5e06SDave Ertman 	err_cfg = kzalloc(sizeof(*err_cfg), GFP_KERNEL);
406242b5e06SDave Ertman 	if (!err_cfg) {
407242b5e06SDave Ertman 		mutex_unlock(&pf->tc_mutex);
4089efe35d0STony Nguyen 		return;
409242b5e06SDave Ertman 	}
4109efe35d0STony Nguyen 
411242b5e06SDave Ertman 	err_cfg->etscfg.willing = true;
412242b5e06SDave Ertman 	err_cfg->etscfg.tcbwtable[0] = ICE_TC_MAX_BW;
413242b5e06SDave Ertman 	err_cfg->etscfg.tsatable[0] = ICE_IEEE_TSA_ETS;
414242b5e06SDave Ertman 	memcpy(&err_cfg->etsrec, &err_cfg->etscfg, sizeof(err_cfg->etsrec));
415ac614b13SBruce Allan 	/* Coverity warns the return code of ice_pf_dcb_cfg() is not checked
416ac614b13SBruce Allan 	 * here as is done for other calls to that function. That check is
417ac614b13SBruce Allan 	 * not necessary since this is in this function's error cleanup path.
418ac614b13SBruce Allan 	 * Suppress the Coverity warning with the following comment...
419ac614b13SBruce Allan 	 */
420ac614b13SBruce Allan 	/* coverity[check_return] */
421242b5e06SDave Ertman 	ice_pf_dcb_cfg(pf, err_cfg, false);
422242b5e06SDave Ertman 	kfree(err_cfg);
423242b5e06SDave Ertman 
424242b5e06SDave Ertman 	mutex_unlock(&pf->tc_mutex);
425b832c2f6SAnirudh Venkataramanan }
426b832c2f6SAnirudh Venkataramanan 
427b832c2f6SAnirudh Venkataramanan /**
4287b9ffc76SAnirudh Venkataramanan  * ice_dcb_init_cfg - set the initial DCB config in SW
4292f2da36eSAnirudh Venkataramanan  * @pf: PF to apply config to
430e223eaecSDave Ertman  * @locked: Is the RTNL held
4317b9ffc76SAnirudh Venkataramanan  */
432e223eaecSDave Ertman static int ice_dcb_init_cfg(struct ice_pf *pf, bool locked)
4337b9ffc76SAnirudh Venkataramanan {
4347b9ffc76SAnirudh Venkataramanan 	struct ice_dcbx_cfg *newcfg;
4357b9ffc76SAnirudh Venkataramanan 	struct ice_port_info *pi;
4367b9ffc76SAnirudh Venkataramanan 	int ret = 0;
4377b9ffc76SAnirudh Venkataramanan 
4387b9ffc76SAnirudh Venkataramanan 	pi = pf->hw.port_info;
4399efe35d0STony Nguyen 	newcfg = kmemdup(&pi->local_dcbx_cfg, sizeof(*newcfg), GFP_KERNEL);
4407b9ffc76SAnirudh Venkataramanan 	if (!newcfg)
4417b9ffc76SAnirudh Venkataramanan 		return -ENOMEM;
4427b9ffc76SAnirudh Venkataramanan 
4437b9ffc76SAnirudh Venkataramanan 	memset(&pi->local_dcbx_cfg, 0, sizeof(*newcfg));
4447b9ffc76SAnirudh Venkataramanan 
4454015d11eSBrett Creeley 	dev_info(ice_pf_to_dev(pf), "Configuring initial DCB values\n");
446e223eaecSDave Ertman 	if (ice_pf_dcb_cfg(pf, newcfg, locked))
4477b9ffc76SAnirudh Venkataramanan 		ret = -EINVAL;
4487b9ffc76SAnirudh Venkataramanan 
4499efe35d0STony Nguyen 	kfree(newcfg);
4507b9ffc76SAnirudh Venkataramanan 
4517b9ffc76SAnirudh Venkataramanan 	return ret;
4527b9ffc76SAnirudh Venkataramanan }
4537b9ffc76SAnirudh Venkataramanan 
4547b9ffc76SAnirudh Venkataramanan /**
4554ee656bbSTony Nguyen  * ice_dcb_sw_dflt_cfg - Apply a default DCB config
4562f2da36eSAnirudh Venkataramanan  * @pf: PF to apply config to
4574ee656bbSTony Nguyen  * @ets_willing: configure ETS willing
458e223eaecSDave Ertman  * @locked: was this function called with RTNL held
4590deab659SAnirudh Venkataramanan  */
460cfbf1367SPaul Greenwalt static int ice_dcb_sw_dflt_cfg(struct ice_pf *pf, bool ets_willing, bool locked)
4610deab659SAnirudh Venkataramanan {
4620deab659SAnirudh Venkataramanan 	struct ice_aqc_port_ets_elem buf = { 0 };
4630deab659SAnirudh Venkataramanan 	struct ice_dcbx_cfg *dcbcfg;
4640deab659SAnirudh Venkataramanan 	struct ice_port_info *pi;
4650deab659SAnirudh Venkataramanan 	struct ice_hw *hw;
4660deab659SAnirudh Venkataramanan 	int ret;
4670deab659SAnirudh Venkataramanan 
4680deab659SAnirudh Venkataramanan 	hw = &pf->hw;
4690deab659SAnirudh Venkataramanan 	pi = hw->port_info;
4709efe35d0STony Nguyen 	dcbcfg = kzalloc(sizeof(*dcbcfg), GFP_KERNEL);
4719efe35d0STony Nguyen 	if (!dcbcfg)
4729efe35d0STony Nguyen 		return -ENOMEM;
4730deab659SAnirudh Venkataramanan 
4740deab659SAnirudh Venkataramanan 	memset(&pi->local_dcbx_cfg, 0, sizeof(*dcbcfg));
4750deab659SAnirudh Venkataramanan 
476cfbf1367SPaul Greenwalt 	dcbcfg->etscfg.willing = ets_willing ? 1 : 0;
477a257f188SUsha Ketineni 	dcbcfg->etscfg.maxtcs = hw->func_caps.common_cap.maxtc;
4780deab659SAnirudh Venkataramanan 	dcbcfg->etscfg.tcbwtable[0] = 100;
4790deab659SAnirudh Venkataramanan 	dcbcfg->etscfg.tsatable[0] = ICE_IEEE_TSA_ETS;
4800deab659SAnirudh Venkataramanan 
4810deab659SAnirudh Venkataramanan 	memcpy(&dcbcfg->etsrec, &dcbcfg->etscfg,
4820deab659SAnirudh Venkataramanan 	       sizeof(dcbcfg->etsrec));
4830deab659SAnirudh Venkataramanan 	dcbcfg->etsrec.willing = 0;
4840deab659SAnirudh Venkataramanan 
4850deab659SAnirudh Venkataramanan 	dcbcfg->pfc.willing = 1;
486a257f188SUsha Ketineni 	dcbcfg->pfc.pfccap = hw->func_caps.common_cap.maxtc;
4870deab659SAnirudh Venkataramanan 
4880deab659SAnirudh Venkataramanan 	dcbcfg->numapps = 1;
4890deab659SAnirudh Venkataramanan 	dcbcfg->app[0].selector = ICE_APP_SEL_ETHTYPE;
4900deab659SAnirudh Venkataramanan 	dcbcfg->app[0].priority = 3;
4910deab659SAnirudh Venkataramanan 	dcbcfg->app[0].prot_id = ICE_APP_PROT_ID_FCOE;
4920deab659SAnirudh Venkataramanan 
493e223eaecSDave Ertman 	ret = ice_pf_dcb_cfg(pf, dcbcfg, locked);
4949efe35d0STony Nguyen 	kfree(dcbcfg);
4950deab659SAnirudh Venkataramanan 	if (ret)
4960deab659SAnirudh Venkataramanan 		return ret;
4970deab659SAnirudh Venkataramanan 
4980deab659SAnirudh Venkataramanan 	return ice_query_port_ets(pi, &buf, sizeof(buf), NULL);
4990deab659SAnirudh Venkataramanan }
5000deab659SAnirudh Venkataramanan 
5010deab659SAnirudh Venkataramanan /**
502cfbf1367SPaul Greenwalt  * ice_dcb_tc_contig - Check that TCs are contiguous
503cfbf1367SPaul Greenwalt  * @prio_table: pointer to priority table
504cfbf1367SPaul Greenwalt  *
505cfbf1367SPaul Greenwalt  * Check if TCs begin with TC0 and are contiguous
506cfbf1367SPaul Greenwalt  */
507cfbf1367SPaul Greenwalt static bool ice_dcb_tc_contig(u8 *prio_table)
508cfbf1367SPaul Greenwalt {
509cfbf1367SPaul Greenwalt 	u8 max_tc = 0;
510cfbf1367SPaul Greenwalt 	int i;
511cfbf1367SPaul Greenwalt 
512cfbf1367SPaul Greenwalt 	for (i = 0; i < CEE_DCBX_MAX_PRIO; i++) {
513cfbf1367SPaul Greenwalt 		u8 cur_tc = prio_table[i];
514cfbf1367SPaul Greenwalt 
515cfbf1367SPaul Greenwalt 		if (cur_tc > max_tc)
516cfbf1367SPaul Greenwalt 			return false;
517cfbf1367SPaul Greenwalt 		else if (cur_tc == max_tc)
518cfbf1367SPaul Greenwalt 			max_tc++;
519cfbf1367SPaul Greenwalt 	}
520cfbf1367SPaul Greenwalt 
521cfbf1367SPaul Greenwalt 	return true;
522cfbf1367SPaul Greenwalt }
523cfbf1367SPaul Greenwalt 
524cfbf1367SPaul Greenwalt /**
525cfbf1367SPaul Greenwalt  * ice_dcb_noncontig_cfg - Configure DCB for non-contiguous TCs
526cfbf1367SPaul Greenwalt  * @pf: pointer to the PF struct
527cfbf1367SPaul Greenwalt  *
528cfbf1367SPaul Greenwalt  * If non-contiguous TCs, then configure SW DCB with TC0 and ETS non-willing
529cfbf1367SPaul Greenwalt  */
530cfbf1367SPaul Greenwalt static int ice_dcb_noncontig_cfg(struct ice_pf *pf)
531cfbf1367SPaul Greenwalt {
532cfbf1367SPaul Greenwalt 	struct ice_dcbx_cfg *dcbcfg = &pf->hw.port_info->local_dcbx_cfg;
5334015d11eSBrett Creeley 	struct device *dev = ice_pf_to_dev(pf);
534cfbf1367SPaul Greenwalt 	int ret;
535cfbf1367SPaul Greenwalt 
536cfbf1367SPaul Greenwalt 	/* Configure SW DCB default with ETS non-willing */
537cfbf1367SPaul Greenwalt 	ret = ice_dcb_sw_dflt_cfg(pf, false, true);
538cfbf1367SPaul Greenwalt 	if (ret) {
5394015d11eSBrett Creeley 		dev_err(dev, "Failed to set local DCB config %d\n", ret);
540cfbf1367SPaul Greenwalt 		return ret;
541cfbf1367SPaul Greenwalt 	}
542cfbf1367SPaul Greenwalt 
543cfbf1367SPaul Greenwalt 	/* Reconfigure with ETS willing so that FW will send LLDP MIB event */
544cfbf1367SPaul Greenwalt 	dcbcfg->etscfg.willing = 1;
545cfbf1367SPaul Greenwalt 	ret = ice_set_dcb_cfg(pf->hw.port_info);
546cfbf1367SPaul Greenwalt 	if (ret)
5474015d11eSBrett Creeley 		dev_err(dev, "Failed to set DCB to unwilling\n");
548cfbf1367SPaul Greenwalt 
549cfbf1367SPaul Greenwalt 	return ret;
550cfbf1367SPaul Greenwalt }
551cfbf1367SPaul Greenwalt 
552cfbf1367SPaul Greenwalt /**
553cfbf1367SPaul Greenwalt  * ice_pf_dcb_recfg - Reconfigure all VEBs and VSIs
554cfbf1367SPaul Greenwalt  * @pf: pointer to the PF struct
555cfbf1367SPaul Greenwalt  *
556cfbf1367SPaul Greenwalt  * Assumed caller has already disabled all VSIs before
557cfbf1367SPaul Greenwalt  * calling this function. Reconfiguring DCB based on
558cfbf1367SPaul Greenwalt  * local_dcbx_cfg.
559cfbf1367SPaul Greenwalt  */
56087324e74SHenry Tieman void ice_pf_dcb_recfg(struct ice_pf *pf)
561cfbf1367SPaul Greenwalt {
562cfbf1367SPaul Greenwalt 	struct ice_dcbx_cfg *dcbcfg = &pf->hw.port_info->local_dcbx_cfg;
563cfbf1367SPaul Greenwalt 	u8 tc_map = 0;
564cfbf1367SPaul Greenwalt 	int v, ret;
565cfbf1367SPaul Greenwalt 
566cfbf1367SPaul Greenwalt 	/* Update each VSI */
567cfbf1367SPaul Greenwalt 	ice_for_each_vsi(pf, v) {
5684015d11eSBrett Creeley 		struct ice_vsi *vsi = pf->vsi[v];
5694015d11eSBrett Creeley 
5704015d11eSBrett Creeley 		if (!vsi)
571cfbf1367SPaul Greenwalt 			continue;
572cfbf1367SPaul Greenwalt 
5734015d11eSBrett Creeley 		if (vsi->type == ICE_VSI_PF) {
574cfbf1367SPaul Greenwalt 			tc_map = ice_dcb_get_ena_tc(dcbcfg);
575cfbf1367SPaul Greenwalt 
576cfbf1367SPaul Greenwalt 			/* If DCBX request non-contiguous TC, then configure
577cfbf1367SPaul Greenwalt 			 * default TC
578cfbf1367SPaul Greenwalt 			 */
579cfbf1367SPaul Greenwalt 			if (!ice_dcb_tc_contig(dcbcfg->etscfg.prio_table)) {
580cfbf1367SPaul Greenwalt 				tc_map = ICE_DFLT_TRAFFIC_CLASS;
581cfbf1367SPaul Greenwalt 				ice_dcb_noncontig_cfg(pf);
582cfbf1367SPaul Greenwalt 			}
583cfbf1367SPaul Greenwalt 		} else {
584cfbf1367SPaul Greenwalt 			tc_map = ICE_DFLT_TRAFFIC_CLASS;
585cfbf1367SPaul Greenwalt 		}
586cfbf1367SPaul Greenwalt 
5874015d11eSBrett Creeley 		ret = ice_vsi_cfg_tc(vsi, tc_map);
588cfbf1367SPaul Greenwalt 		if (ret) {
5894015d11eSBrett Creeley 			dev_err(ice_pf_to_dev(pf), "Failed to config TC for VSI index: %d\n",
5904015d11eSBrett Creeley 				vsi->idx);
591cfbf1367SPaul Greenwalt 			continue;
592cfbf1367SPaul Greenwalt 		}
593cfbf1367SPaul Greenwalt 
5944015d11eSBrett Creeley 		ice_vsi_map_rings_to_vectors(vsi);
5954015d11eSBrett Creeley 		if (vsi->type == ICE_VSI_PF)
5964015d11eSBrett Creeley 			ice_dcbnl_set_all(vsi);
597cfbf1367SPaul Greenwalt 	}
598cfbf1367SPaul Greenwalt }
599cfbf1367SPaul Greenwalt 
600cfbf1367SPaul Greenwalt /**
60137b6f646SAnirudh Venkataramanan  * ice_init_pf_dcb - initialize DCB for a PF
6022f2da36eSAnirudh Venkataramanan  * @pf: PF to initialize DCB for
603e223eaecSDave Ertman  * @locked: Was function called with RTNL held
60437b6f646SAnirudh Venkataramanan  */
605e223eaecSDave Ertman int ice_init_pf_dcb(struct ice_pf *pf, bool locked)
60637b6f646SAnirudh Venkataramanan {
6074015d11eSBrett Creeley 	struct device *dev = ice_pf_to_dev(pf);
60837b6f646SAnirudh Venkataramanan 	struct ice_port_info *port_info;
60937b6f646SAnirudh Venkataramanan 	struct ice_hw *hw = &pf->hw;
6107b9ffc76SAnirudh Venkataramanan 	int err;
61137b6f646SAnirudh Venkataramanan 
61237b6f646SAnirudh Venkataramanan 	port_info = hw->port_info;
61337b6f646SAnirudh Venkataramanan 
614ea300f41SDave Ertman 	err = ice_init_dcb(hw, false);
615473ca574SDave Ertman 	if (err && !port_info->is_sw_lldp) {
6164015d11eSBrett Creeley 		dev_err(dev, "Error initializing DCB %d\n", err);
617473ca574SDave Ertman 		goto dcb_init_err;
618473ca574SDave Ertman 	}
619473ca574SDave Ertman 
62019cce2c6SAnirudh Venkataramanan 	dev_info(dev, "DCB is enabled in the hardware, max number of TCs supported on this port are %d\n",
621a257f188SUsha Ketineni 		 pf->hw.func_caps.common_cap.maxtc);
622473ca574SDave Ertman 	if (err) {
623241c8cf0SPaul Greenwalt 		struct ice_vsi *pf_vsi;
624241c8cf0SPaul Greenwalt 
625473ca574SDave Ertman 		/* FW LLDP is disabled, activate SW DCBX/LLDP mode */
6264015d11eSBrett Creeley 		dev_info(dev, "FW LLDP is disabled, DCBx/LLDP in SW mode.\n");
62784a118abSDave Ertman 		clear_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags);
628cfbf1367SPaul Greenwalt 		err = ice_dcb_sw_dflt_cfg(pf, true, locked);
6290deab659SAnirudh Venkataramanan 		if (err) {
63019cce2c6SAnirudh Venkataramanan 			dev_err(dev, "Failed to set local DCB config %d\n",
63119cce2c6SAnirudh Venkataramanan 				err);
6320deab659SAnirudh Venkataramanan 			err = -EIO;
6337b9ffc76SAnirudh Venkataramanan 			goto dcb_init_err;
6340deab659SAnirudh Venkataramanan 		}
6350deab659SAnirudh Venkataramanan 
636241c8cf0SPaul Greenwalt 		/* If the FW DCBX engine is not running then Rx LLDP packets
637241c8cf0SPaul Greenwalt 		 * need to be redirected up the stack.
638241c8cf0SPaul Greenwalt 		 */
639241c8cf0SPaul Greenwalt 		pf_vsi = ice_get_main_vsi(pf);
640241c8cf0SPaul Greenwalt 		if (!pf_vsi) {
6414015d11eSBrett Creeley 			dev_err(dev, "Failed to set local DCB config\n");
642241c8cf0SPaul Greenwalt 			err = -EIO;
643241c8cf0SPaul Greenwalt 			goto dcb_init_err;
644241c8cf0SPaul Greenwalt 		}
645241c8cf0SPaul Greenwalt 
646241c8cf0SPaul Greenwalt 		ice_cfg_sw_lldp(pf_vsi, false, true);
647241c8cf0SPaul Greenwalt 
6480deab659SAnirudh Venkataramanan 		pf->dcbx_cap = DCB_CAP_DCBX_HOST | DCB_CAP_DCBX_VER_IEEE;
6490deab659SAnirudh Venkataramanan 		return 0;
6500deab659SAnirudh Venkataramanan 	}
6517b9ffc76SAnirudh Venkataramanan 
65284a118abSDave Ertman 	set_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags);
6531b0c3247SDave Ertman 
6547b9ffc76SAnirudh Venkataramanan 	/* DCBX in FW and LLDP enabled in FW */
6557b9ffc76SAnirudh Venkataramanan 	pf->dcbx_cap = DCB_CAP_DCBX_LLD_MANAGED | DCB_CAP_DCBX_VER_IEEE;
6567b9ffc76SAnirudh Venkataramanan 
657e223eaecSDave Ertman 	err = ice_dcb_init_cfg(pf, locked);
6587b9ffc76SAnirudh Venkataramanan 	if (err)
6597b9ffc76SAnirudh Venkataramanan 		goto dcb_init_err;
6607b9ffc76SAnirudh Venkataramanan 
6617b9ffc76SAnirudh Venkataramanan 	return err;
6627b9ffc76SAnirudh Venkataramanan 
6637b9ffc76SAnirudh Venkataramanan dcb_init_err:
6647b9ffc76SAnirudh Venkataramanan 	dev_err(dev, "DCB init failed\n");
6657b9ffc76SAnirudh Venkataramanan 	return err;
66637b6f646SAnirudh Venkataramanan }
66700cc3f1bSAnirudh Venkataramanan 
66800cc3f1bSAnirudh Venkataramanan /**
6694b0fdcebSAnirudh Venkataramanan  * ice_update_dcb_stats - Update DCB stats counters
6704b0fdcebSAnirudh Venkataramanan  * @pf: PF whose stats needs to be updated
6714b0fdcebSAnirudh Venkataramanan  */
6724b0fdcebSAnirudh Venkataramanan void ice_update_dcb_stats(struct ice_pf *pf)
6734b0fdcebSAnirudh Venkataramanan {
6744b0fdcebSAnirudh Venkataramanan 	struct ice_hw_port_stats *prev_ps, *cur_ps;
6754b0fdcebSAnirudh Venkataramanan 	struct ice_hw *hw = &pf->hw;
6769e7a5d17SUsha Ketineni 	u8 port;
6774b0fdcebSAnirudh Venkataramanan 	int i;
6784b0fdcebSAnirudh Venkataramanan 
6799e7a5d17SUsha Ketineni 	port = hw->port_info->lport;
6804b0fdcebSAnirudh Venkataramanan 	prev_ps = &pf->stats_prev;
6814b0fdcebSAnirudh Venkataramanan 	cur_ps = &pf->stats;
6824b0fdcebSAnirudh Venkataramanan 
6834b0fdcebSAnirudh Venkataramanan 	for (i = 0; i < 8; i++) {
6849e7a5d17SUsha Ketineni 		ice_stat_update32(hw, GLPRT_PXOFFRXC(port, i),
6854b0fdcebSAnirudh Venkataramanan 				  pf->stat_prev_loaded,
6864b0fdcebSAnirudh Venkataramanan 				  &prev_ps->priority_xoff_rx[i],
6874b0fdcebSAnirudh Venkataramanan 				  &cur_ps->priority_xoff_rx[i]);
6889e7a5d17SUsha Ketineni 		ice_stat_update32(hw, GLPRT_PXONRXC(port, i),
6894b0fdcebSAnirudh Venkataramanan 				  pf->stat_prev_loaded,
6904b0fdcebSAnirudh Venkataramanan 				  &prev_ps->priority_xon_rx[i],
6914b0fdcebSAnirudh Venkataramanan 				  &cur_ps->priority_xon_rx[i]);
6929e7a5d17SUsha Ketineni 		ice_stat_update32(hw, GLPRT_PXONTXC(port, i),
6934b0fdcebSAnirudh Venkataramanan 				  pf->stat_prev_loaded,
6944b0fdcebSAnirudh Venkataramanan 				  &prev_ps->priority_xon_tx[i],
6954b0fdcebSAnirudh Venkataramanan 				  &cur_ps->priority_xon_tx[i]);
6969e7a5d17SUsha Ketineni 		ice_stat_update32(hw, GLPRT_PXOFFTXC(port, i),
6974b0fdcebSAnirudh Venkataramanan 				  pf->stat_prev_loaded,
6984b0fdcebSAnirudh Venkataramanan 				  &prev_ps->priority_xoff_tx[i],
6994b0fdcebSAnirudh Venkataramanan 				  &cur_ps->priority_xoff_tx[i]);
7009e7a5d17SUsha Ketineni 		ice_stat_update32(hw, GLPRT_RXON2OFFCNT(port, i),
7014b0fdcebSAnirudh Venkataramanan 				  pf->stat_prev_loaded,
7024b0fdcebSAnirudh Venkataramanan 				  &prev_ps->priority_xon_2_xoff[i],
7034b0fdcebSAnirudh Venkataramanan 				  &cur_ps->priority_xon_2_xoff[i]);
7044b0fdcebSAnirudh Venkataramanan 	}
7054b0fdcebSAnirudh Venkataramanan }
7064b0fdcebSAnirudh Venkataramanan 
7074b0fdcebSAnirudh Venkataramanan /**
7085f6aa50eSAnirudh Venkataramanan  * ice_tx_prepare_vlan_flags_dcb - prepare VLAN tagging for DCB
7095f6aa50eSAnirudh Venkataramanan  * @tx_ring: ring to send buffer on
7105f6aa50eSAnirudh Venkataramanan  * @first: pointer to struct ice_tx_buf
7115f6aa50eSAnirudh Venkataramanan  */
7125f6aa50eSAnirudh Venkataramanan int
7135f6aa50eSAnirudh Venkataramanan ice_tx_prepare_vlan_flags_dcb(struct ice_ring *tx_ring,
7145f6aa50eSAnirudh Venkataramanan 			      struct ice_tx_buf *first)
7155f6aa50eSAnirudh Venkataramanan {
7165f6aa50eSAnirudh Venkataramanan 	struct sk_buff *skb = first->skb;
7175f6aa50eSAnirudh Venkataramanan 
7185f6aa50eSAnirudh Venkataramanan 	if (!test_bit(ICE_FLAG_DCB_ENA, tx_ring->vsi->back->flags))
7195f6aa50eSAnirudh Venkataramanan 		return 0;
7205f6aa50eSAnirudh Venkataramanan 
7215f6aa50eSAnirudh Venkataramanan 	/* Insert 802.1p priority into VLAN header */
7225f6aa50eSAnirudh Venkataramanan 	if ((first->tx_flags & (ICE_TX_FLAGS_HW_VLAN | ICE_TX_FLAGS_SW_VLAN)) ||
7235f6aa50eSAnirudh Venkataramanan 	    skb->priority != TC_PRIO_CONTROL) {
7245f6aa50eSAnirudh Venkataramanan 		first->tx_flags &= ~ICE_TX_FLAGS_VLAN_PR_M;
7255f6aa50eSAnirudh Venkataramanan 		/* Mask the lower 3 bits to set the 802.1p priority */
7265f6aa50eSAnirudh Venkataramanan 		first->tx_flags |= (skb->priority & 0x7) <<
7275f6aa50eSAnirudh Venkataramanan 				   ICE_TX_FLAGS_VLAN_PR_S;
7285f6aa50eSAnirudh Venkataramanan 		if (first->tx_flags & ICE_TX_FLAGS_SW_VLAN) {
7295f6aa50eSAnirudh Venkataramanan 			struct vlan_ethhdr *vhdr;
7305f6aa50eSAnirudh Venkataramanan 			int rc;
7315f6aa50eSAnirudh Venkataramanan 
7325f6aa50eSAnirudh Venkataramanan 			rc = skb_cow_head(skb, 0);
7335f6aa50eSAnirudh Venkataramanan 			if (rc < 0)
7345f6aa50eSAnirudh Venkataramanan 				return rc;
7355f6aa50eSAnirudh Venkataramanan 			vhdr = (struct vlan_ethhdr *)skb->data;
7365f6aa50eSAnirudh Venkataramanan 			vhdr->h_vlan_TCI = htons(first->tx_flags >>
7375f6aa50eSAnirudh Venkataramanan 						 ICE_TX_FLAGS_VLAN_S);
7385f6aa50eSAnirudh Venkataramanan 		} else {
7395f6aa50eSAnirudh Venkataramanan 			first->tx_flags |= ICE_TX_FLAGS_HW_VLAN;
7405f6aa50eSAnirudh Venkataramanan 		}
7415f6aa50eSAnirudh Venkataramanan 	}
7425f6aa50eSAnirudh Venkataramanan 
7435f6aa50eSAnirudh Venkataramanan 	return 0;
7445f6aa50eSAnirudh Venkataramanan }
7455f6aa50eSAnirudh Venkataramanan 
7465f6aa50eSAnirudh Venkataramanan /**
74700cc3f1bSAnirudh Venkataramanan  * ice_dcb_process_lldp_set_mib_change - Process MIB change
74800cc3f1bSAnirudh Venkataramanan  * @pf: ptr to ice_pf
74900cc3f1bSAnirudh Venkataramanan  * @event: pointer to the admin queue receive event
75000cc3f1bSAnirudh Venkataramanan  */
75100cc3f1bSAnirudh Venkataramanan void
75200cc3f1bSAnirudh Venkataramanan ice_dcb_process_lldp_set_mib_change(struct ice_pf *pf,
75300cc3f1bSAnirudh Venkataramanan 				    struct ice_rq_event_info *event)
75400cc3f1bSAnirudh Venkataramanan {
755a17a5ff6SUsha Ketineni 	struct ice_aqc_port_ets_elem buf = { 0 };
7564015d11eSBrett Creeley 	struct device *dev = ice_pf_to_dev(pf);
757a17a5ff6SUsha Ketineni 	struct ice_aqc_lldp_get_mib *mib;
758a17a5ff6SUsha Ketineni 	struct ice_dcbx_cfg tmp_dcbx_cfg;
759a17a5ff6SUsha Ketineni 	bool need_reconfig = false;
760a17a5ff6SUsha Ketineni 	struct ice_port_info *pi;
7619d614b64SAnirudh Venkataramanan 	struct ice_vsi *pf_vsi;
762a17a5ff6SUsha Ketineni 	u8 type;
763a17a5ff6SUsha Ketineni 	int ret;
76400cc3f1bSAnirudh Venkataramanan 
765a17a5ff6SUsha Ketineni 	/* Not DCB capable or capability disabled */
766a17a5ff6SUsha Ketineni 	if (!(test_bit(ICE_FLAG_DCB_CAPABLE, pf->flags)))
76700cc3f1bSAnirudh Venkataramanan 		return;
76800cc3f1bSAnirudh Venkataramanan 
769a17a5ff6SUsha Ketineni 	if (pf->dcbx_cap & DCB_CAP_DCBX_HOST) {
7704015d11eSBrett Creeley 		dev_dbg(dev, "MIB Change Event in HOST mode\n");
771a17a5ff6SUsha Ketineni 		return;
77200cc3f1bSAnirudh Venkataramanan 	}
773a17a5ff6SUsha Ketineni 
774a17a5ff6SUsha Ketineni 	pi = pf->hw.port_info;
775a17a5ff6SUsha Ketineni 	mib = (struct ice_aqc_lldp_get_mib *)&event->desc.params.raw;
776a17a5ff6SUsha Ketineni 	/* Ignore if event is not for Nearest Bridge */
777a17a5ff6SUsha Ketineni 	type = ((mib->type >> ICE_AQ_LLDP_BRID_TYPE_S) &
778a17a5ff6SUsha Ketineni 		ICE_AQ_LLDP_BRID_TYPE_M);
7794015d11eSBrett Creeley 	dev_dbg(dev, "LLDP event MIB bridge type 0x%x\n", type);
780a17a5ff6SUsha Ketineni 	if (type != ICE_AQ_LLDP_BRID_TYPE_NEAREST_BRID)
781a17a5ff6SUsha Ketineni 		return;
782a17a5ff6SUsha Ketineni 
783a17a5ff6SUsha Ketineni 	/* Check MIB Type and return if event for Remote MIB update */
784a17a5ff6SUsha Ketineni 	type = mib->type & ICE_AQ_LLDP_MIB_TYPE_M;
7854015d11eSBrett Creeley 	dev_dbg(dev, "LLDP event mib type %s\n", type ? "remote" : "local");
786a17a5ff6SUsha Ketineni 	if (type == ICE_AQ_LLDP_MIB_REMOTE) {
787a17a5ff6SUsha Ketineni 		/* Update the remote cached instance and return */
788a17a5ff6SUsha Ketineni 		ret = ice_aq_get_dcb_cfg(pi->hw, ICE_AQ_LLDP_MIB_REMOTE,
789a17a5ff6SUsha Ketineni 					 ICE_AQ_LLDP_BRID_TYPE_NEAREST_BRID,
790a17a5ff6SUsha Ketineni 					 &pi->remote_dcbx_cfg);
791a17a5ff6SUsha Ketineni 		if (ret) {
7924015d11eSBrett Creeley 			dev_err(dev, "Failed to get remote DCB config\n");
793a17a5ff6SUsha Ketineni 			return;
794a17a5ff6SUsha Ketineni 		}
795a17a5ff6SUsha Ketineni 	}
796a17a5ff6SUsha Ketineni 
797242b5e06SDave Ertman 	mutex_lock(&pf->tc_mutex);
798242b5e06SDave Ertman 
799a17a5ff6SUsha Ketineni 	/* store the old configuration */
800a17a5ff6SUsha Ketineni 	tmp_dcbx_cfg = pf->hw.port_info->local_dcbx_cfg;
801a17a5ff6SUsha Ketineni 
8022f2da36eSAnirudh Venkataramanan 	/* Reset the old DCBX configuration data */
803a17a5ff6SUsha Ketineni 	memset(&pi->local_dcbx_cfg, 0, sizeof(pi->local_dcbx_cfg));
804a17a5ff6SUsha Ketineni 
8052f2da36eSAnirudh Venkataramanan 	/* Get updated DCBX data from firmware */
806a17a5ff6SUsha Ketineni 	ret = ice_get_dcb_cfg(pf->hw.port_info);
807a17a5ff6SUsha Ketineni 	if (ret) {
8084015d11eSBrett Creeley 		dev_err(dev, "Failed to get DCB config\n");
809242b5e06SDave Ertman 		goto out;
810a17a5ff6SUsha Ketineni 	}
811a17a5ff6SUsha Ketineni 
812a17a5ff6SUsha Ketineni 	/* No change detected in DCBX configs */
813a17a5ff6SUsha Ketineni 	if (!memcmp(&tmp_dcbx_cfg, &pi->local_dcbx_cfg, sizeof(tmp_dcbx_cfg))) {
8144015d11eSBrett Creeley 		dev_dbg(dev, "No change detected in DCBX configuration.\n");
815242b5e06SDave Ertman 		goto out;
816a17a5ff6SUsha Ketineni 	}
817a17a5ff6SUsha Ketineni 
818a17a5ff6SUsha Ketineni 	need_reconfig = ice_dcb_need_recfg(pf, &tmp_dcbx_cfg,
819a17a5ff6SUsha Ketineni 					   &pi->local_dcbx_cfg);
820b94b013eSDave Ertman 	ice_dcbnl_flush_apps(pf, &tmp_dcbx_cfg, &pi->local_dcbx_cfg);
821a17a5ff6SUsha Ketineni 	if (!need_reconfig)
822242b5e06SDave Ertman 		goto out;
823a17a5ff6SUsha Ketineni 
824a17a5ff6SUsha Ketineni 	/* Enable DCB tagging only when more than one TC */
825a17a5ff6SUsha Ketineni 	if (ice_dcb_get_num_tc(&pi->local_dcbx_cfg) > 1) {
8264015d11eSBrett Creeley 		dev_dbg(dev, "DCB tagging enabled (num TC > 1)\n");
827a17a5ff6SUsha Ketineni 		set_bit(ICE_FLAG_DCB_ENA, pf->flags);
828a17a5ff6SUsha Ketineni 	} else {
8294015d11eSBrett Creeley 		dev_dbg(dev, "DCB tagging disabled (num TC = 1)\n");
830a17a5ff6SUsha Ketineni 		clear_bit(ICE_FLAG_DCB_ENA, pf->flags);
831a17a5ff6SUsha Ketineni 	}
832a17a5ff6SUsha Ketineni 
8339d614b64SAnirudh Venkataramanan 	pf_vsi = ice_get_main_vsi(pf);
8349d614b64SAnirudh Venkataramanan 	if (!pf_vsi) {
8354015d11eSBrett Creeley 		dev_dbg(dev, "PF VSI doesn't exist\n");
836242b5e06SDave Ertman 		goto out;
8379d614b64SAnirudh Venkataramanan 	}
8389d614b64SAnirudh Venkataramanan 
839a17a5ff6SUsha Ketineni 	rtnl_lock();
8409d614b64SAnirudh Venkataramanan 	ice_dis_vsi(pf_vsi, true);
841a17a5ff6SUsha Ketineni 
842a17a5ff6SUsha Ketineni 	ret = ice_query_port_ets(pf->hw.port_info, &buf, sizeof(buf), NULL);
843a17a5ff6SUsha Ketineni 	if (ret) {
8444015d11eSBrett Creeley 		dev_err(dev, "Query Port ETS failed\n");
845242b5e06SDave Ertman 		goto unlock_rtnl;
846a17a5ff6SUsha Ketineni 	}
847a17a5ff6SUsha Ketineni 
848a17a5ff6SUsha Ketineni 	/* changes in configuration update VSI */
849a17a5ff6SUsha Ketineni 	ice_pf_dcb_recfg(pf);
850a17a5ff6SUsha Ketineni 
8519d614b64SAnirudh Venkataramanan 	ice_ena_vsi(pf_vsi, true);
852242b5e06SDave Ertman unlock_rtnl:
853a17a5ff6SUsha Ketineni 	rtnl_unlock();
854242b5e06SDave Ertman out:
855242b5e06SDave Ertman 	mutex_unlock(&pf->tc_mutex);
85600cc3f1bSAnirudh Venkataramanan }
857