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 /**
6627d9be98SAvinash Dayanand  * ice_dcb_get_mode - gets the DCB mode
6727d9be98SAvinash Dayanand  * @port_info: pointer to port info structure
6827d9be98SAvinash Dayanand  * @host: if set it's HOST if not it's MANAGED
6927d9be98SAvinash Dayanand  */
7027d9be98SAvinash Dayanand static u8 ice_dcb_get_mode(struct ice_port_info *port_info, bool host)
7127d9be98SAvinash Dayanand {
7227d9be98SAvinash Dayanand 	u8 mode;
7327d9be98SAvinash Dayanand 
7427d9be98SAvinash Dayanand 	if (host)
7527d9be98SAvinash Dayanand 		mode = DCB_CAP_DCBX_HOST;
7627d9be98SAvinash Dayanand 	else
7727d9be98SAvinash Dayanand 		mode = DCB_CAP_DCBX_LLD_MANAGED;
7827d9be98SAvinash Dayanand 
7927d9be98SAvinash Dayanand 	if (port_info->local_dcbx_cfg.dcbx_mode & ICE_DCBX_MODE_CEE)
80f3beaf24SJeff Kirsher 		return mode | DCB_CAP_DCBX_VER_CEE;
8127d9be98SAvinash Dayanand 	else
82f3beaf24SJeff Kirsher 		return mode | DCB_CAP_DCBX_VER_IEEE;
8327d9be98SAvinash Dayanand }
8427d9be98SAvinash Dayanand 
8527d9be98SAvinash Dayanand /**
867b9ffc76SAnirudh Venkataramanan  * ice_dcb_get_num_tc - Get the number of TCs from DCBX config
877b9ffc76SAnirudh Venkataramanan  * @dcbcfg: config to retrieve number of TCs from
887b9ffc76SAnirudh Venkataramanan  */
897b9ffc76SAnirudh Venkataramanan u8 ice_dcb_get_num_tc(struct ice_dcbx_cfg *dcbcfg)
907b9ffc76SAnirudh Venkataramanan {
917b9ffc76SAnirudh Venkataramanan 	bool tc_unused = false;
927b9ffc76SAnirudh Venkataramanan 	u8 num_tc = 0;
937b9ffc76SAnirudh Venkataramanan 	u8 ret = 0;
947b9ffc76SAnirudh Venkataramanan 	int i;
957b9ffc76SAnirudh Venkataramanan 
967b9ffc76SAnirudh Venkataramanan 	/* Scan the ETS Config Priority Table to find traffic classes
977b9ffc76SAnirudh Venkataramanan 	 * enabled and create a bitmask of enabled TCs
987b9ffc76SAnirudh Venkataramanan 	 */
997b9ffc76SAnirudh Venkataramanan 	for (i = 0; i < CEE_DCBX_MAX_PRIO; i++)
1007b9ffc76SAnirudh Venkataramanan 		num_tc |= BIT(dcbcfg->etscfg.prio_table[i]);
1017b9ffc76SAnirudh Venkataramanan 
1027b9ffc76SAnirudh Venkataramanan 	/* Scan bitmask for contiguous TCs starting with TC0 */
1037b9ffc76SAnirudh Venkataramanan 	for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
1047b9ffc76SAnirudh Venkataramanan 		if (num_tc & BIT(i)) {
1057b9ffc76SAnirudh Venkataramanan 			if (!tc_unused) {
1067b9ffc76SAnirudh Venkataramanan 				ret++;
1077b9ffc76SAnirudh Venkataramanan 			} else {
1087b9ffc76SAnirudh Venkataramanan 				pr_err("Non-contiguous TCs - Disabling DCB\n");
1097b9ffc76SAnirudh Venkataramanan 				return 1;
1107b9ffc76SAnirudh Venkataramanan 			}
1117b9ffc76SAnirudh Venkataramanan 		} else {
1127b9ffc76SAnirudh Venkataramanan 			tc_unused = true;
1137b9ffc76SAnirudh Venkataramanan 		}
1147b9ffc76SAnirudh Venkataramanan 	}
1157b9ffc76SAnirudh Venkataramanan 
1167b9ffc76SAnirudh Venkataramanan 	/* There is always at least 1 TC */
1177b9ffc76SAnirudh Venkataramanan 	if (!ret)
1187b9ffc76SAnirudh Venkataramanan 		ret = 1;
1197b9ffc76SAnirudh Venkataramanan 
1207b9ffc76SAnirudh Venkataramanan 	return ret;
1217b9ffc76SAnirudh Venkataramanan }
1227b9ffc76SAnirudh Venkataramanan 
1237b9ffc76SAnirudh Venkataramanan /**
1241ddef455SUsha Ketineni  * ice_dcb_get_tc - Get the TC associated with the queue
1251ddef455SUsha Ketineni  * @vsi: ptr to the VSI
1261ddef455SUsha Ketineni  * @queue_index: queue number associated with VSI
1271ddef455SUsha Ketineni  */
1281ddef455SUsha Ketineni u8 ice_dcb_get_tc(struct ice_vsi *vsi, int queue_index)
1291ddef455SUsha Ketineni {
1301ddef455SUsha Ketineni 	return vsi->tx_rings[queue_index]->dcb_tc;
1311ddef455SUsha Ketineni }
1321ddef455SUsha Ketineni 
1331ddef455SUsha Ketineni /**
134a629cf0aSAnirudh Venkataramanan  * ice_vsi_cfg_dcb_rings - Update rings to reflect DCB TC
135a629cf0aSAnirudh Venkataramanan  * @vsi: VSI owner of rings being updated
136a629cf0aSAnirudh Venkataramanan  */
137a629cf0aSAnirudh Venkataramanan void ice_vsi_cfg_dcb_rings(struct ice_vsi *vsi)
138a629cf0aSAnirudh Venkataramanan {
139a629cf0aSAnirudh Venkataramanan 	struct ice_ring *tx_ring, *rx_ring;
140a629cf0aSAnirudh Venkataramanan 	u16 qoffset, qcount;
141a629cf0aSAnirudh Venkataramanan 	int i, n;
142a629cf0aSAnirudh Venkataramanan 
143a629cf0aSAnirudh Venkataramanan 	if (!test_bit(ICE_FLAG_DCB_ENA, vsi->back->flags)) {
144a629cf0aSAnirudh Venkataramanan 		/* Reset the TC information */
145a629cf0aSAnirudh Venkataramanan 		for (i = 0; i < vsi->num_txq; i++) {
146a629cf0aSAnirudh Venkataramanan 			tx_ring = vsi->tx_rings[i];
147a629cf0aSAnirudh Venkataramanan 			tx_ring->dcb_tc = 0;
148a629cf0aSAnirudh Venkataramanan 		}
149a629cf0aSAnirudh Venkataramanan 		for (i = 0; i < vsi->num_rxq; i++) {
150a629cf0aSAnirudh Venkataramanan 			rx_ring = vsi->rx_rings[i];
151a629cf0aSAnirudh Venkataramanan 			rx_ring->dcb_tc = 0;
152a629cf0aSAnirudh Venkataramanan 		}
153a629cf0aSAnirudh Venkataramanan 		return;
154a629cf0aSAnirudh Venkataramanan 	}
155a629cf0aSAnirudh Venkataramanan 
156a629cf0aSAnirudh Venkataramanan 	ice_for_each_traffic_class(n) {
157a629cf0aSAnirudh Venkataramanan 		if (!(vsi->tc_cfg.ena_tc & BIT(n)))
158a629cf0aSAnirudh Venkataramanan 			break;
159a629cf0aSAnirudh Venkataramanan 
160a629cf0aSAnirudh Venkataramanan 		qoffset = vsi->tc_cfg.tc_info[n].qoffset;
161a629cf0aSAnirudh Venkataramanan 		qcount = vsi->tc_cfg.tc_info[n].qcount_tx;
162a629cf0aSAnirudh Venkataramanan 		for (i = qoffset; i < (qoffset + qcount); i++) {
163a629cf0aSAnirudh Venkataramanan 			tx_ring = vsi->tx_rings[i];
164a629cf0aSAnirudh Venkataramanan 			rx_ring = vsi->rx_rings[i];
165a629cf0aSAnirudh Venkataramanan 			tx_ring->dcb_tc = n;
166a629cf0aSAnirudh Venkataramanan 			rx_ring->dcb_tc = n;
167a629cf0aSAnirudh Venkataramanan 		}
168a629cf0aSAnirudh Venkataramanan 	}
169a629cf0aSAnirudh Venkataramanan }
170a629cf0aSAnirudh Venkataramanan 
171a629cf0aSAnirudh Venkataramanan /**
172a29a912dSAvinash Dayanand  * ice_dcb_bwchk - check if ETS bandwidth input parameters are correct
173a29a912dSAvinash Dayanand  * @pf: pointer to the PF struct
174a29a912dSAvinash Dayanand  * @dcbcfg: pointer to DCB config structure
175a29a912dSAvinash Dayanand  */
176a29a912dSAvinash Dayanand int ice_dcb_bwchk(struct ice_pf *pf, struct ice_dcbx_cfg *dcbcfg)
177a29a912dSAvinash Dayanand {
178a29a912dSAvinash Dayanand 	struct ice_dcb_ets_cfg *etscfg = &dcbcfg->etscfg;
179a29a912dSAvinash Dayanand 	u8 num_tc, total_bw = 0;
180a29a912dSAvinash Dayanand 	int i;
181a29a912dSAvinash Dayanand 
182a29a912dSAvinash Dayanand 	/* returns number of contigous TCs and 1 TC for non-contigous TCs,
183a29a912dSAvinash Dayanand 	 * since at least 1 TC has to be configured
184a29a912dSAvinash Dayanand 	 */
185a29a912dSAvinash Dayanand 	num_tc = ice_dcb_get_num_tc(dcbcfg);
186a29a912dSAvinash Dayanand 
187a29a912dSAvinash Dayanand 	/* no bandwidth checks required if there's only one TC, so assign
188a29a912dSAvinash Dayanand 	 * all bandwidth to TC0 and return
189a29a912dSAvinash Dayanand 	 */
190a29a912dSAvinash Dayanand 	if (num_tc == 1) {
191a29a912dSAvinash Dayanand 		etscfg->tcbwtable[0] = ICE_TC_MAX_BW;
192a29a912dSAvinash Dayanand 		return 0;
193a29a912dSAvinash Dayanand 	}
194a29a912dSAvinash Dayanand 
195a29a912dSAvinash Dayanand 	for (i = 0; i < num_tc; i++)
196a29a912dSAvinash Dayanand 		total_bw += etscfg->tcbwtable[i];
197a29a912dSAvinash Dayanand 
198a29a912dSAvinash Dayanand 	if (!total_bw) {
199a29a912dSAvinash Dayanand 		etscfg->tcbwtable[0] = ICE_TC_MAX_BW;
200a29a912dSAvinash Dayanand 	} else if (total_bw != ICE_TC_MAX_BW) {
201a29a912dSAvinash Dayanand 		dev_err(ice_pf_to_dev(pf), "Invalid config, total bandwidth must equal 100\n");
202a29a912dSAvinash Dayanand 		return -EINVAL;
203a29a912dSAvinash Dayanand 	}
204a29a912dSAvinash Dayanand 
205a29a912dSAvinash Dayanand 	return 0;
206a29a912dSAvinash Dayanand }
207a29a912dSAvinash Dayanand 
208a29a912dSAvinash Dayanand /**
2097b9ffc76SAnirudh Venkataramanan  * ice_pf_dcb_cfg - Apply new DCB configuration
2107b9ffc76SAnirudh Venkataramanan  * @pf: pointer to the PF struct
2117b9ffc76SAnirudh Venkataramanan  * @new_cfg: DCBX config to apply
212e223eaecSDave Ertman  * @locked: is the RTNL held
2137b9ffc76SAnirudh Venkataramanan  */
214e223eaecSDave Ertman int ice_pf_dcb_cfg(struct ice_pf *pf, struct ice_dcbx_cfg *new_cfg, bool locked)
2157b9ffc76SAnirudh Venkataramanan {
2167b9ffc76SAnirudh Venkataramanan 	struct ice_aqc_port_ets_elem buf = { 0 };
217b94b013eSDave Ertman 	struct ice_dcbx_cfg *old_cfg, *curr_cfg;
2184015d11eSBrett Creeley 	struct device *dev = ice_pf_to_dev(pf);
219b94b013eSDave Ertman 	int ret = ICE_DCB_NO_HW_CHG;
2209d614b64SAnirudh Venkataramanan 	struct ice_vsi *pf_vsi;
2217b9ffc76SAnirudh Venkataramanan 
2227b9ffc76SAnirudh Venkataramanan 	curr_cfg = &pf->hw.port_info->local_dcbx_cfg;
2237b9ffc76SAnirudh Venkataramanan 
224b94b013eSDave Ertman 	/* FW does not care if change happened */
225b94b013eSDave Ertman 	if (!pf->hw.port_info->is_sw_lldp)
226b94b013eSDave Ertman 		ret = ICE_DCB_HW_CHG_RST;
227b94b013eSDave Ertman 
2287b9ffc76SAnirudh Venkataramanan 	/* Enable DCB tagging only when more than one TC */
2297b9ffc76SAnirudh Venkataramanan 	if (ice_dcb_get_num_tc(new_cfg) > 1) {
2304015d11eSBrett Creeley 		dev_dbg(dev, "DCB tagging enabled (num TC > 1)\n");
2317b9ffc76SAnirudh Venkataramanan 		set_bit(ICE_FLAG_DCB_ENA, pf->flags);
2327b9ffc76SAnirudh Venkataramanan 	} else {
2334015d11eSBrett Creeley 		dev_dbg(dev, "DCB tagging disabled (num TC = 1)\n");
2347b9ffc76SAnirudh Venkataramanan 		clear_bit(ICE_FLAG_DCB_ENA, pf->flags);
2357b9ffc76SAnirudh Venkataramanan 	}
2367b9ffc76SAnirudh Venkataramanan 
2377b9ffc76SAnirudh Venkataramanan 	if (!memcmp(new_cfg, curr_cfg, sizeof(*new_cfg))) {
2384015d11eSBrett Creeley 		dev_dbg(dev, "No change in DCB config required\n");
2397b9ffc76SAnirudh Venkataramanan 		return ret;
2407b9ffc76SAnirudh Venkataramanan 	}
2417b9ffc76SAnirudh Venkataramanan 
242a29a912dSAvinash Dayanand 	if (ice_dcb_bwchk(pf, new_cfg))
243a29a912dSAvinash Dayanand 		return -EINVAL;
244a29a912dSAvinash Dayanand 
2457b9ffc76SAnirudh Venkataramanan 	/* Store old config in case FW config fails */
2469d614b64SAnirudh Venkataramanan 	old_cfg = kmemdup(curr_cfg, sizeof(*old_cfg), GFP_KERNEL);
2479d614b64SAnirudh Venkataramanan 	if (!old_cfg)
2489d614b64SAnirudh Venkataramanan 		return -ENOMEM;
2499d614b64SAnirudh Venkataramanan 
2504015d11eSBrett Creeley 	dev_info(dev, "Commit DCB Configuration to the hardware\n");
2519d614b64SAnirudh Venkataramanan 	pf_vsi = ice_get_main_vsi(pf);
2529d614b64SAnirudh Venkataramanan 	if (!pf_vsi) {
2534015d11eSBrett Creeley 		dev_dbg(dev, "PF VSI doesn't exist\n");
2549d614b64SAnirudh Venkataramanan 		ret = -EINVAL;
2559d614b64SAnirudh Venkataramanan 		goto free_cfg;
2569d614b64SAnirudh Venkataramanan 	}
2577b9ffc76SAnirudh Venkataramanan 
2587b9ffc76SAnirudh Venkataramanan 	/* avoid race conditions by holding the lock while disabling and
2597b9ffc76SAnirudh Venkataramanan 	 * re-enabling the VSI
2607b9ffc76SAnirudh Venkataramanan 	 */
261e223eaecSDave Ertman 	if (!locked)
2627b9ffc76SAnirudh Venkataramanan 		rtnl_lock();
2639d614b64SAnirudh Venkataramanan 	ice_dis_vsi(pf_vsi, true);
2647b9ffc76SAnirudh Venkataramanan 
2657b9ffc76SAnirudh Venkataramanan 	memcpy(curr_cfg, new_cfg, sizeof(*curr_cfg));
2667b9ffc76SAnirudh Venkataramanan 	memcpy(&curr_cfg->etsrec, &curr_cfg->etscfg, sizeof(curr_cfg->etsrec));
267b94b013eSDave Ertman 	memcpy(&new_cfg->etsrec, &curr_cfg->etscfg, sizeof(curr_cfg->etsrec));
2687b9ffc76SAnirudh Venkataramanan 
2697b9ffc76SAnirudh Venkataramanan 	/* Only send new config to HW if we are in SW LLDP mode. Otherwise,
2707b9ffc76SAnirudh Venkataramanan 	 * the new config came from the HW in the first place.
2717b9ffc76SAnirudh Venkataramanan 	 */
2727b9ffc76SAnirudh Venkataramanan 	if (pf->hw.port_info->is_sw_lldp) {
2737b9ffc76SAnirudh Venkataramanan 		ret = ice_set_dcb_cfg(pf->hw.port_info);
2747b9ffc76SAnirudh Venkataramanan 		if (ret) {
2754015d11eSBrett Creeley 			dev_err(dev, "Set DCB Config failed\n");
2767b9ffc76SAnirudh Venkataramanan 			/* Restore previous settings to local config */
2777b9ffc76SAnirudh Venkataramanan 			memcpy(curr_cfg, old_cfg, sizeof(*curr_cfg));
2787b9ffc76SAnirudh Venkataramanan 			goto out;
2797b9ffc76SAnirudh Venkataramanan 		}
2807b9ffc76SAnirudh Venkataramanan 	}
2817b9ffc76SAnirudh Venkataramanan 
2827b9ffc76SAnirudh Venkataramanan 	ret = ice_query_port_ets(pf->hw.port_info, &buf, sizeof(buf), NULL);
2837b9ffc76SAnirudh Venkataramanan 	if (ret) {
2844015d11eSBrett Creeley 		dev_err(dev, "Query Port ETS failed\n");
2857b9ffc76SAnirudh Venkataramanan 		goto out;
2867b9ffc76SAnirudh Venkataramanan 	}
2877b9ffc76SAnirudh Venkataramanan 
2887b9ffc76SAnirudh Venkataramanan 	ice_pf_dcb_recfg(pf);
2897b9ffc76SAnirudh Venkataramanan 
2907b9ffc76SAnirudh Venkataramanan out:
2919d614b64SAnirudh Venkataramanan 	ice_ena_vsi(pf_vsi, true);
292e223eaecSDave Ertman 	if (!locked)
2937b9ffc76SAnirudh Venkataramanan 		rtnl_unlock();
2949d614b64SAnirudh Venkataramanan free_cfg:
2959d614b64SAnirudh Venkataramanan 	kfree(old_cfg);
2967b9ffc76SAnirudh Venkataramanan 	return ret;
2977b9ffc76SAnirudh Venkataramanan }
2987b9ffc76SAnirudh Venkataramanan 
2997b9ffc76SAnirudh Venkataramanan /**
3007829570eSUsha Ketineni  * ice_cfg_etsrec_defaults - Set default ETS recommended DCB config
3017829570eSUsha Ketineni  * @pi: port information structure
3027829570eSUsha Ketineni  */
3037829570eSUsha Ketineni static void ice_cfg_etsrec_defaults(struct ice_port_info *pi)
3047829570eSUsha Ketineni {
3057829570eSUsha Ketineni 	struct ice_dcbx_cfg *dcbcfg = &pi->local_dcbx_cfg;
3067829570eSUsha Ketineni 	u8 i;
3077829570eSUsha Ketineni 
3087829570eSUsha Ketineni 	/* Ensure ETS recommended DCB configuration is not already set */
3097829570eSUsha Ketineni 	if (dcbcfg->etsrec.maxtcs)
3107829570eSUsha Ketineni 		return;
3117829570eSUsha Ketineni 
3127829570eSUsha Ketineni 	/* In CEE mode, set the default to 1 TC */
3137829570eSUsha Ketineni 	dcbcfg->etsrec.maxtcs = 1;
3147829570eSUsha Ketineni 	for (i = 0; i < ICE_MAX_TRAFFIC_CLASS; i++) {
3157829570eSUsha Ketineni 		dcbcfg->etsrec.tcbwtable[i] = i ? 0 : 100;
3167829570eSUsha Ketineni 		dcbcfg->etsrec.tsatable[i] = i ? ICE_IEEE_TSA_STRICT :
3177829570eSUsha Ketineni 						 ICE_IEEE_TSA_ETS;
3187829570eSUsha Ketineni 	}
3197829570eSUsha Ketineni }
3207829570eSUsha Ketineni 
3217829570eSUsha Ketineni /**
3227829570eSUsha Ketineni  * ice_dcb_need_recfg - Check if DCB needs reconfig
3237829570eSUsha Ketineni  * @pf: board private structure
3247829570eSUsha Ketineni  * @old_cfg: current DCB config
3257829570eSUsha Ketineni  * @new_cfg: new DCB config
3267829570eSUsha Ketineni  */
3277829570eSUsha Ketineni static bool
3287829570eSUsha Ketineni ice_dcb_need_recfg(struct ice_pf *pf, struct ice_dcbx_cfg *old_cfg,
3297829570eSUsha Ketineni 		   struct ice_dcbx_cfg *new_cfg)
3307829570eSUsha Ketineni {
3314015d11eSBrett Creeley 	struct device *dev = ice_pf_to_dev(pf);
3327829570eSUsha Ketineni 	bool need_reconfig = false;
3337829570eSUsha Ketineni 
3347829570eSUsha Ketineni 	/* Check if ETS configuration has changed */
3357829570eSUsha Ketineni 	if (memcmp(&new_cfg->etscfg, &old_cfg->etscfg,
3367829570eSUsha Ketineni 		   sizeof(new_cfg->etscfg))) {
3377829570eSUsha Ketineni 		/* If Priority Table has changed reconfig is needed */
3387829570eSUsha Ketineni 		if (memcmp(&new_cfg->etscfg.prio_table,
3397829570eSUsha Ketineni 			   &old_cfg->etscfg.prio_table,
3407829570eSUsha Ketineni 			   sizeof(new_cfg->etscfg.prio_table))) {
3417829570eSUsha Ketineni 			need_reconfig = true;
3424015d11eSBrett Creeley 			dev_dbg(dev, "ETS UP2TC changed.\n");
3437829570eSUsha Ketineni 		}
3447829570eSUsha Ketineni 
3457829570eSUsha Ketineni 		if (memcmp(&new_cfg->etscfg.tcbwtable,
3467829570eSUsha Ketineni 			   &old_cfg->etscfg.tcbwtable,
3477829570eSUsha Ketineni 			   sizeof(new_cfg->etscfg.tcbwtable)))
3484015d11eSBrett Creeley 			dev_dbg(dev, "ETS TC BW Table changed.\n");
3497829570eSUsha Ketineni 
3507829570eSUsha Ketineni 		if (memcmp(&new_cfg->etscfg.tsatable,
3517829570eSUsha Ketineni 			   &old_cfg->etscfg.tsatable,
3527829570eSUsha Ketineni 			   sizeof(new_cfg->etscfg.tsatable)))
3534015d11eSBrett Creeley 			dev_dbg(dev, "ETS TSA Table changed.\n");
3547829570eSUsha Ketineni 	}
3557829570eSUsha Ketineni 
3567829570eSUsha Ketineni 	/* Check if PFC configuration has changed */
3577829570eSUsha Ketineni 	if (memcmp(&new_cfg->pfc, &old_cfg->pfc, sizeof(new_cfg->pfc))) {
3587829570eSUsha Ketineni 		need_reconfig = true;
3594015d11eSBrett Creeley 		dev_dbg(dev, "PFC config change detected.\n");
3607829570eSUsha Ketineni 	}
3617829570eSUsha Ketineni 
3627829570eSUsha Ketineni 	/* Check if APP Table has changed */
3637829570eSUsha Ketineni 	if (memcmp(&new_cfg->app, &old_cfg->app, sizeof(new_cfg->app))) {
3647829570eSUsha Ketineni 		need_reconfig = true;
3654015d11eSBrett Creeley 		dev_dbg(dev, "APP Table change detected.\n");
3667829570eSUsha Ketineni 	}
3677829570eSUsha Ketineni 
3684015d11eSBrett Creeley 	dev_dbg(dev, "dcb need_reconfig=%d\n", need_reconfig);
3697829570eSUsha Ketineni 	return need_reconfig;
3707829570eSUsha Ketineni }
3717829570eSUsha Ketineni 
3727829570eSUsha Ketineni /**
373b832c2f6SAnirudh Venkataramanan  * ice_dcb_rebuild - rebuild DCB post reset
374b832c2f6SAnirudh Venkataramanan  * @pf: physical function instance
375b832c2f6SAnirudh Venkataramanan  */
376b832c2f6SAnirudh Venkataramanan void ice_dcb_rebuild(struct ice_pf *pf)
377b832c2f6SAnirudh Venkataramanan {
378b832c2f6SAnirudh Venkataramanan 	struct ice_aqc_port_ets_elem buf = { 0 };
3794015d11eSBrett Creeley 	struct device *dev = ice_pf_to_dev(pf);
380242b5e06SDave Ertman 	struct ice_dcbx_cfg *err_cfg;
381b832c2f6SAnirudh Venkataramanan 	enum ice_status ret;
382b832c2f6SAnirudh Venkataramanan 
383b832c2f6SAnirudh Venkataramanan 	ret = ice_query_port_ets(pf->hw.port_info, &buf, sizeof(buf), NULL);
384b832c2f6SAnirudh Venkataramanan 	if (ret) {
3854015d11eSBrett Creeley 		dev_err(dev, "Query Port ETS failed\n");
386b832c2f6SAnirudh Venkataramanan 		goto dcb_error;
387b832c2f6SAnirudh Venkataramanan 	}
388b832c2f6SAnirudh Venkataramanan 
389b832c2f6SAnirudh Venkataramanan 	/* If DCB was not enabled previously, we are done */
390b832c2f6SAnirudh Venkataramanan 	if (!test_bit(ICE_FLAG_DCB_ENA, pf->flags))
391b832c2f6SAnirudh Venkataramanan 		return;
392b832c2f6SAnirudh Venkataramanan 
393242b5e06SDave Ertman 	mutex_lock(&pf->tc_mutex);
3947829570eSUsha Ketineni 
395242b5e06SDave Ertman 	if (!pf->hw.port_info->is_sw_lldp)
3967829570eSUsha Ketineni 		ice_cfg_etsrec_defaults(pf->hw.port_info);
397242b5e06SDave Ertman 
398b832c2f6SAnirudh Venkataramanan 	ret = ice_set_dcb_cfg(pf->hw.port_info);
399b832c2f6SAnirudh Venkataramanan 	if (ret) {
400242b5e06SDave Ertman 		dev_err(dev, "Failed to set DCB config in rebuild\n");
401b832c2f6SAnirudh Venkataramanan 		goto dcb_error;
402b832c2f6SAnirudh Venkataramanan 	}
403b832c2f6SAnirudh Venkataramanan 
404242b5e06SDave Ertman 	if (!pf->hw.port_info->is_sw_lldp) {
405242b5e06SDave Ertman 		ret = ice_cfg_lldp_mib_change(&pf->hw, true);
406242b5e06SDave Ertman 		if (ret && !pf->hw.port_info->is_sw_lldp) {
407242b5e06SDave Ertman 			dev_err(dev, "Failed to register for MIB changes\n");
408b832c2f6SAnirudh Venkataramanan 			goto dcb_error;
409b832c2f6SAnirudh Venkataramanan 		}
410b832c2f6SAnirudh Venkataramanan 	}
411242b5e06SDave Ertman 
4124015d11eSBrett Creeley 	dev_info(dev, "DCB restored after reset\n");
413b832c2f6SAnirudh Venkataramanan 	ret = ice_query_port_ets(pf->hw.port_info, &buf, sizeof(buf), NULL);
414b832c2f6SAnirudh Venkataramanan 	if (ret) {
4154015d11eSBrett Creeley 		dev_err(dev, "Query Port ETS failed\n");
416b832c2f6SAnirudh Venkataramanan 		goto dcb_error;
417b832c2f6SAnirudh Venkataramanan 	}
418b832c2f6SAnirudh Venkataramanan 
419242b5e06SDave Ertman 	mutex_unlock(&pf->tc_mutex);
420242b5e06SDave Ertman 
421b832c2f6SAnirudh Venkataramanan 	return;
422b832c2f6SAnirudh Venkataramanan 
423b832c2f6SAnirudh Venkataramanan dcb_error:
4244015d11eSBrett Creeley 	dev_err(dev, "Disabling DCB until new settings occur\n");
425242b5e06SDave Ertman 	err_cfg = kzalloc(sizeof(*err_cfg), GFP_KERNEL);
426242b5e06SDave Ertman 	if (!err_cfg) {
427242b5e06SDave Ertman 		mutex_unlock(&pf->tc_mutex);
4289efe35d0STony Nguyen 		return;
429242b5e06SDave Ertman 	}
4309efe35d0STony Nguyen 
431242b5e06SDave Ertman 	err_cfg->etscfg.willing = true;
432242b5e06SDave Ertman 	err_cfg->etscfg.tcbwtable[0] = ICE_TC_MAX_BW;
433242b5e06SDave Ertman 	err_cfg->etscfg.tsatable[0] = ICE_IEEE_TSA_ETS;
434242b5e06SDave Ertman 	memcpy(&err_cfg->etsrec, &err_cfg->etscfg, sizeof(err_cfg->etsrec));
435ac614b13SBruce Allan 	/* Coverity warns the return code of ice_pf_dcb_cfg() is not checked
436ac614b13SBruce Allan 	 * here as is done for other calls to that function. That check is
437ac614b13SBruce Allan 	 * not necessary since this is in this function's error cleanup path.
438ac614b13SBruce Allan 	 * Suppress the Coverity warning with the following comment...
439ac614b13SBruce Allan 	 */
440ac614b13SBruce Allan 	/* coverity[check_return] */
441242b5e06SDave Ertman 	ice_pf_dcb_cfg(pf, err_cfg, false);
442242b5e06SDave Ertman 	kfree(err_cfg);
443242b5e06SDave Ertman 
444242b5e06SDave Ertman 	mutex_unlock(&pf->tc_mutex);
445b832c2f6SAnirudh Venkataramanan }
446b832c2f6SAnirudh Venkataramanan 
447b832c2f6SAnirudh Venkataramanan /**
4487b9ffc76SAnirudh Venkataramanan  * ice_dcb_init_cfg - set the initial DCB config in SW
4492f2da36eSAnirudh Venkataramanan  * @pf: PF to apply config to
450e223eaecSDave Ertman  * @locked: Is the RTNL held
4517b9ffc76SAnirudh Venkataramanan  */
452e223eaecSDave Ertman static int ice_dcb_init_cfg(struct ice_pf *pf, bool locked)
4537b9ffc76SAnirudh Venkataramanan {
4547b9ffc76SAnirudh Venkataramanan 	struct ice_dcbx_cfg *newcfg;
4557b9ffc76SAnirudh Venkataramanan 	struct ice_port_info *pi;
4567b9ffc76SAnirudh Venkataramanan 	int ret = 0;
4577b9ffc76SAnirudh Venkataramanan 
4587b9ffc76SAnirudh Venkataramanan 	pi = pf->hw.port_info;
4599efe35d0STony Nguyen 	newcfg = kmemdup(&pi->local_dcbx_cfg, sizeof(*newcfg), GFP_KERNEL);
4607b9ffc76SAnirudh Venkataramanan 	if (!newcfg)
4617b9ffc76SAnirudh Venkataramanan 		return -ENOMEM;
4627b9ffc76SAnirudh Venkataramanan 
4637b9ffc76SAnirudh Venkataramanan 	memset(&pi->local_dcbx_cfg, 0, sizeof(*newcfg));
4647b9ffc76SAnirudh Venkataramanan 
4654015d11eSBrett Creeley 	dev_info(ice_pf_to_dev(pf), "Configuring initial DCB values\n");
466e223eaecSDave Ertman 	if (ice_pf_dcb_cfg(pf, newcfg, locked))
4677b9ffc76SAnirudh Venkataramanan 		ret = -EINVAL;
4687b9ffc76SAnirudh Venkataramanan 
4699efe35d0STony Nguyen 	kfree(newcfg);
4707b9ffc76SAnirudh Venkataramanan 
4717b9ffc76SAnirudh Venkataramanan 	return ret;
4727b9ffc76SAnirudh Venkataramanan }
4737b9ffc76SAnirudh Venkataramanan 
4747b9ffc76SAnirudh Venkataramanan /**
4754ee656bbSTony Nguyen  * ice_dcb_sw_dflt_cfg - Apply a default DCB config
4762f2da36eSAnirudh Venkataramanan  * @pf: PF to apply config to
4774ee656bbSTony Nguyen  * @ets_willing: configure ETS willing
478e223eaecSDave Ertman  * @locked: was this function called with RTNL held
4790deab659SAnirudh Venkataramanan  */
480cfbf1367SPaul Greenwalt static int ice_dcb_sw_dflt_cfg(struct ice_pf *pf, bool ets_willing, bool locked)
4810deab659SAnirudh Venkataramanan {
4820deab659SAnirudh Venkataramanan 	struct ice_aqc_port_ets_elem buf = { 0 };
4830deab659SAnirudh Venkataramanan 	struct ice_dcbx_cfg *dcbcfg;
4840deab659SAnirudh Venkataramanan 	struct ice_port_info *pi;
4850deab659SAnirudh Venkataramanan 	struct ice_hw *hw;
4860deab659SAnirudh Venkataramanan 	int ret;
4870deab659SAnirudh Venkataramanan 
4880deab659SAnirudh Venkataramanan 	hw = &pf->hw;
4890deab659SAnirudh Venkataramanan 	pi = hw->port_info;
4909efe35d0STony Nguyen 	dcbcfg = kzalloc(sizeof(*dcbcfg), GFP_KERNEL);
4919efe35d0STony Nguyen 	if (!dcbcfg)
4929efe35d0STony Nguyen 		return -ENOMEM;
4930deab659SAnirudh Venkataramanan 
4940deab659SAnirudh Venkataramanan 	memset(&pi->local_dcbx_cfg, 0, sizeof(*dcbcfg));
4950deab659SAnirudh Venkataramanan 
496cfbf1367SPaul Greenwalt 	dcbcfg->etscfg.willing = ets_willing ? 1 : 0;
497a257f188SUsha Ketineni 	dcbcfg->etscfg.maxtcs = hw->func_caps.common_cap.maxtc;
4980deab659SAnirudh Venkataramanan 	dcbcfg->etscfg.tcbwtable[0] = 100;
4990deab659SAnirudh Venkataramanan 	dcbcfg->etscfg.tsatable[0] = ICE_IEEE_TSA_ETS;
5000deab659SAnirudh Venkataramanan 
5010deab659SAnirudh Venkataramanan 	memcpy(&dcbcfg->etsrec, &dcbcfg->etscfg,
5020deab659SAnirudh Venkataramanan 	       sizeof(dcbcfg->etsrec));
5030deab659SAnirudh Venkataramanan 	dcbcfg->etsrec.willing = 0;
5040deab659SAnirudh Venkataramanan 
5050deab659SAnirudh Venkataramanan 	dcbcfg->pfc.willing = 1;
506a257f188SUsha Ketineni 	dcbcfg->pfc.pfccap = hw->func_caps.common_cap.maxtc;
5070deab659SAnirudh Venkataramanan 
5080deab659SAnirudh Venkataramanan 	dcbcfg->numapps = 1;
5090deab659SAnirudh Venkataramanan 	dcbcfg->app[0].selector = ICE_APP_SEL_ETHTYPE;
5100deab659SAnirudh Venkataramanan 	dcbcfg->app[0].priority = 3;
5110deab659SAnirudh Venkataramanan 	dcbcfg->app[0].prot_id = ICE_APP_PROT_ID_FCOE;
5120deab659SAnirudh Venkataramanan 
513e223eaecSDave Ertman 	ret = ice_pf_dcb_cfg(pf, dcbcfg, locked);
5149efe35d0STony Nguyen 	kfree(dcbcfg);
5150deab659SAnirudh Venkataramanan 	if (ret)
5160deab659SAnirudh Venkataramanan 		return ret;
5170deab659SAnirudh Venkataramanan 
5180deab659SAnirudh Venkataramanan 	return ice_query_port_ets(pi, &buf, sizeof(buf), NULL);
5190deab659SAnirudh Venkataramanan }
5200deab659SAnirudh Venkataramanan 
5210deab659SAnirudh Venkataramanan /**
522cfbf1367SPaul Greenwalt  * ice_dcb_tc_contig - Check that TCs are contiguous
523cfbf1367SPaul Greenwalt  * @prio_table: pointer to priority table
524cfbf1367SPaul Greenwalt  *
525cfbf1367SPaul Greenwalt  * Check if TCs begin with TC0 and are contiguous
526cfbf1367SPaul Greenwalt  */
527cfbf1367SPaul Greenwalt static bool ice_dcb_tc_contig(u8 *prio_table)
528cfbf1367SPaul Greenwalt {
529cfbf1367SPaul Greenwalt 	u8 max_tc = 0;
530cfbf1367SPaul Greenwalt 	int i;
531cfbf1367SPaul Greenwalt 
532cfbf1367SPaul Greenwalt 	for (i = 0; i < CEE_DCBX_MAX_PRIO; i++) {
533cfbf1367SPaul Greenwalt 		u8 cur_tc = prio_table[i];
534cfbf1367SPaul Greenwalt 
535cfbf1367SPaul Greenwalt 		if (cur_tc > max_tc)
536cfbf1367SPaul Greenwalt 			return false;
537cfbf1367SPaul Greenwalt 		else if (cur_tc == max_tc)
538cfbf1367SPaul Greenwalt 			max_tc++;
539cfbf1367SPaul Greenwalt 	}
540cfbf1367SPaul Greenwalt 
541cfbf1367SPaul Greenwalt 	return true;
542cfbf1367SPaul Greenwalt }
543cfbf1367SPaul Greenwalt 
544cfbf1367SPaul Greenwalt /**
545cfbf1367SPaul Greenwalt  * ice_dcb_noncontig_cfg - Configure DCB for non-contiguous TCs
546cfbf1367SPaul Greenwalt  * @pf: pointer to the PF struct
547cfbf1367SPaul Greenwalt  *
548cfbf1367SPaul Greenwalt  * If non-contiguous TCs, then configure SW DCB with TC0 and ETS non-willing
549cfbf1367SPaul Greenwalt  */
550cfbf1367SPaul Greenwalt static int ice_dcb_noncontig_cfg(struct ice_pf *pf)
551cfbf1367SPaul Greenwalt {
552cfbf1367SPaul Greenwalt 	struct ice_dcbx_cfg *dcbcfg = &pf->hw.port_info->local_dcbx_cfg;
5534015d11eSBrett Creeley 	struct device *dev = ice_pf_to_dev(pf);
554cfbf1367SPaul Greenwalt 	int ret;
555cfbf1367SPaul Greenwalt 
556cfbf1367SPaul Greenwalt 	/* Configure SW DCB default with ETS non-willing */
557cfbf1367SPaul Greenwalt 	ret = ice_dcb_sw_dflt_cfg(pf, false, true);
558cfbf1367SPaul Greenwalt 	if (ret) {
5594015d11eSBrett Creeley 		dev_err(dev, "Failed to set local DCB config %d\n", ret);
560cfbf1367SPaul Greenwalt 		return ret;
561cfbf1367SPaul Greenwalt 	}
562cfbf1367SPaul Greenwalt 
563cfbf1367SPaul Greenwalt 	/* Reconfigure with ETS willing so that FW will send LLDP MIB event */
564cfbf1367SPaul Greenwalt 	dcbcfg->etscfg.willing = 1;
565cfbf1367SPaul Greenwalt 	ret = ice_set_dcb_cfg(pf->hw.port_info);
566cfbf1367SPaul Greenwalt 	if (ret)
5674015d11eSBrett Creeley 		dev_err(dev, "Failed to set DCB to unwilling\n");
568cfbf1367SPaul Greenwalt 
569cfbf1367SPaul Greenwalt 	return ret;
570cfbf1367SPaul Greenwalt }
571cfbf1367SPaul Greenwalt 
572cfbf1367SPaul Greenwalt /**
573cfbf1367SPaul Greenwalt  * ice_pf_dcb_recfg - Reconfigure all VEBs and VSIs
574cfbf1367SPaul Greenwalt  * @pf: pointer to the PF struct
575cfbf1367SPaul Greenwalt  *
576cfbf1367SPaul Greenwalt  * Assumed caller has already disabled all VSIs before
577cfbf1367SPaul Greenwalt  * calling this function. Reconfiguring DCB based on
578cfbf1367SPaul Greenwalt  * local_dcbx_cfg.
579cfbf1367SPaul Greenwalt  */
58087324e74SHenry Tieman void ice_pf_dcb_recfg(struct ice_pf *pf)
581cfbf1367SPaul Greenwalt {
582cfbf1367SPaul Greenwalt 	struct ice_dcbx_cfg *dcbcfg = &pf->hw.port_info->local_dcbx_cfg;
583cfbf1367SPaul Greenwalt 	u8 tc_map = 0;
584cfbf1367SPaul Greenwalt 	int v, ret;
585cfbf1367SPaul Greenwalt 
586cfbf1367SPaul Greenwalt 	/* Update each VSI */
587cfbf1367SPaul Greenwalt 	ice_for_each_vsi(pf, v) {
5884015d11eSBrett Creeley 		struct ice_vsi *vsi = pf->vsi[v];
5894015d11eSBrett Creeley 
5904015d11eSBrett Creeley 		if (!vsi)
591cfbf1367SPaul Greenwalt 			continue;
592cfbf1367SPaul Greenwalt 
5934015d11eSBrett Creeley 		if (vsi->type == ICE_VSI_PF) {
594cfbf1367SPaul Greenwalt 			tc_map = ice_dcb_get_ena_tc(dcbcfg);
595cfbf1367SPaul Greenwalt 
596cfbf1367SPaul Greenwalt 			/* If DCBX request non-contiguous TC, then configure
597cfbf1367SPaul Greenwalt 			 * default TC
598cfbf1367SPaul Greenwalt 			 */
599cfbf1367SPaul Greenwalt 			if (!ice_dcb_tc_contig(dcbcfg->etscfg.prio_table)) {
600cfbf1367SPaul Greenwalt 				tc_map = ICE_DFLT_TRAFFIC_CLASS;
601cfbf1367SPaul Greenwalt 				ice_dcb_noncontig_cfg(pf);
602cfbf1367SPaul Greenwalt 			}
603cfbf1367SPaul Greenwalt 		} else {
604cfbf1367SPaul Greenwalt 			tc_map = ICE_DFLT_TRAFFIC_CLASS;
605cfbf1367SPaul Greenwalt 		}
606cfbf1367SPaul Greenwalt 
6074015d11eSBrett Creeley 		ret = ice_vsi_cfg_tc(vsi, tc_map);
608cfbf1367SPaul Greenwalt 		if (ret) {
6094015d11eSBrett Creeley 			dev_err(ice_pf_to_dev(pf), "Failed to config TC for VSI index: %d\n",
6104015d11eSBrett Creeley 				vsi->idx);
611cfbf1367SPaul Greenwalt 			continue;
612cfbf1367SPaul Greenwalt 		}
613cfbf1367SPaul Greenwalt 
6144015d11eSBrett Creeley 		ice_vsi_map_rings_to_vectors(vsi);
6154015d11eSBrett Creeley 		if (vsi->type == ICE_VSI_PF)
6164015d11eSBrett Creeley 			ice_dcbnl_set_all(vsi);
617cfbf1367SPaul Greenwalt 	}
618cfbf1367SPaul Greenwalt }
619cfbf1367SPaul Greenwalt 
620cfbf1367SPaul Greenwalt /**
62137b6f646SAnirudh Venkataramanan  * ice_init_pf_dcb - initialize DCB for a PF
6222f2da36eSAnirudh Venkataramanan  * @pf: PF to initialize DCB for
623e223eaecSDave Ertman  * @locked: Was function called with RTNL held
62437b6f646SAnirudh Venkataramanan  */
625e223eaecSDave Ertman int ice_init_pf_dcb(struct ice_pf *pf, bool locked)
62637b6f646SAnirudh Venkataramanan {
6274015d11eSBrett Creeley 	struct device *dev = ice_pf_to_dev(pf);
62837b6f646SAnirudh Venkataramanan 	struct ice_port_info *port_info;
62937b6f646SAnirudh Venkataramanan 	struct ice_hw *hw = &pf->hw;
6307b9ffc76SAnirudh Venkataramanan 	int err;
63137b6f646SAnirudh Venkataramanan 
63237b6f646SAnirudh Venkataramanan 	port_info = hw->port_info;
63337b6f646SAnirudh Venkataramanan 
634ea300f41SDave Ertman 	err = ice_init_dcb(hw, false);
635473ca574SDave Ertman 	if (err && !port_info->is_sw_lldp) {
6364015d11eSBrett Creeley 		dev_err(dev, "Error initializing DCB %d\n", err);
637473ca574SDave Ertman 		goto dcb_init_err;
638473ca574SDave Ertman 	}
639473ca574SDave Ertman 
64019cce2c6SAnirudh Venkataramanan 	dev_info(dev, "DCB is enabled in the hardware, max number of TCs supported on this port are %d\n",
641a257f188SUsha Ketineni 		 pf->hw.func_caps.common_cap.maxtc);
642473ca574SDave Ertman 	if (err) {
643241c8cf0SPaul Greenwalt 		struct ice_vsi *pf_vsi;
644241c8cf0SPaul Greenwalt 
645473ca574SDave Ertman 		/* FW LLDP is disabled, activate SW DCBX/LLDP mode */
6464015d11eSBrett Creeley 		dev_info(dev, "FW LLDP is disabled, DCBx/LLDP in SW mode.\n");
64784a118abSDave Ertman 		clear_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags);
648cfbf1367SPaul Greenwalt 		err = ice_dcb_sw_dflt_cfg(pf, true, locked);
6490deab659SAnirudh Venkataramanan 		if (err) {
65019cce2c6SAnirudh Venkataramanan 			dev_err(dev, "Failed to set local DCB config %d\n",
65119cce2c6SAnirudh Venkataramanan 				err);
6520deab659SAnirudh Venkataramanan 			err = -EIO;
6537b9ffc76SAnirudh Venkataramanan 			goto dcb_init_err;
6540deab659SAnirudh Venkataramanan 		}
6550deab659SAnirudh Venkataramanan 
656241c8cf0SPaul Greenwalt 		/* If the FW DCBX engine is not running then Rx LLDP packets
657241c8cf0SPaul Greenwalt 		 * need to be redirected up the stack.
658241c8cf0SPaul Greenwalt 		 */
659241c8cf0SPaul Greenwalt 		pf_vsi = ice_get_main_vsi(pf);
660241c8cf0SPaul Greenwalt 		if (!pf_vsi) {
6614015d11eSBrett Creeley 			dev_err(dev, "Failed to set local DCB config\n");
662241c8cf0SPaul Greenwalt 			err = -EIO;
663241c8cf0SPaul Greenwalt 			goto dcb_init_err;
664241c8cf0SPaul Greenwalt 		}
665241c8cf0SPaul Greenwalt 
666241c8cf0SPaul Greenwalt 		ice_cfg_sw_lldp(pf_vsi, false, true);
667241c8cf0SPaul Greenwalt 
66827d9be98SAvinash Dayanand 		pf->dcbx_cap = ice_dcb_get_mode(port_info, true);
6690deab659SAnirudh Venkataramanan 		return 0;
6700deab659SAnirudh Venkataramanan 	}
6717b9ffc76SAnirudh Venkataramanan 
67284a118abSDave Ertman 	set_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags);
6731b0c3247SDave Ertman 
67427d9be98SAvinash Dayanand 	/* DCBX/LLDP enabled in FW, set DCBNL mode advertisement */
67527d9be98SAvinash Dayanand 	pf->dcbx_cap = ice_dcb_get_mode(port_info, false);
6767b9ffc76SAnirudh Venkataramanan 
677e223eaecSDave Ertman 	err = ice_dcb_init_cfg(pf, locked);
6787b9ffc76SAnirudh Venkataramanan 	if (err)
6797b9ffc76SAnirudh Venkataramanan 		goto dcb_init_err;
6807b9ffc76SAnirudh Venkataramanan 
6817b9ffc76SAnirudh Venkataramanan 	return err;
6827b9ffc76SAnirudh Venkataramanan 
6837b9ffc76SAnirudh Venkataramanan dcb_init_err:
6847b9ffc76SAnirudh Venkataramanan 	dev_err(dev, "DCB init failed\n");
6857b9ffc76SAnirudh Venkataramanan 	return err;
68637b6f646SAnirudh Venkataramanan }
68700cc3f1bSAnirudh Venkataramanan 
68800cc3f1bSAnirudh Venkataramanan /**
6894b0fdcebSAnirudh Venkataramanan  * ice_update_dcb_stats - Update DCB stats counters
6904b0fdcebSAnirudh Venkataramanan  * @pf: PF whose stats needs to be updated
6914b0fdcebSAnirudh Venkataramanan  */
6924b0fdcebSAnirudh Venkataramanan void ice_update_dcb_stats(struct ice_pf *pf)
6934b0fdcebSAnirudh Venkataramanan {
6944b0fdcebSAnirudh Venkataramanan 	struct ice_hw_port_stats *prev_ps, *cur_ps;
6954b0fdcebSAnirudh Venkataramanan 	struct ice_hw *hw = &pf->hw;
6969e7a5d17SUsha Ketineni 	u8 port;
6974b0fdcebSAnirudh Venkataramanan 	int i;
6984b0fdcebSAnirudh Venkataramanan 
6999e7a5d17SUsha Ketineni 	port = hw->port_info->lport;
7004b0fdcebSAnirudh Venkataramanan 	prev_ps = &pf->stats_prev;
7014b0fdcebSAnirudh Venkataramanan 	cur_ps = &pf->stats;
7024b0fdcebSAnirudh Venkataramanan 
7034b0fdcebSAnirudh Venkataramanan 	for (i = 0; i < 8; i++) {
7049e7a5d17SUsha Ketineni 		ice_stat_update32(hw, GLPRT_PXOFFRXC(port, i),
7054b0fdcebSAnirudh Venkataramanan 				  pf->stat_prev_loaded,
7064b0fdcebSAnirudh Venkataramanan 				  &prev_ps->priority_xoff_rx[i],
7074b0fdcebSAnirudh Venkataramanan 				  &cur_ps->priority_xoff_rx[i]);
7089e7a5d17SUsha Ketineni 		ice_stat_update32(hw, GLPRT_PXONRXC(port, i),
7094b0fdcebSAnirudh Venkataramanan 				  pf->stat_prev_loaded,
7104b0fdcebSAnirudh Venkataramanan 				  &prev_ps->priority_xon_rx[i],
7114b0fdcebSAnirudh Venkataramanan 				  &cur_ps->priority_xon_rx[i]);
7129e7a5d17SUsha Ketineni 		ice_stat_update32(hw, GLPRT_PXONTXC(port, i),
7134b0fdcebSAnirudh Venkataramanan 				  pf->stat_prev_loaded,
7144b0fdcebSAnirudh Venkataramanan 				  &prev_ps->priority_xon_tx[i],
7154b0fdcebSAnirudh Venkataramanan 				  &cur_ps->priority_xon_tx[i]);
7169e7a5d17SUsha Ketineni 		ice_stat_update32(hw, GLPRT_PXOFFTXC(port, i),
7174b0fdcebSAnirudh Venkataramanan 				  pf->stat_prev_loaded,
7184b0fdcebSAnirudh Venkataramanan 				  &prev_ps->priority_xoff_tx[i],
7194b0fdcebSAnirudh Venkataramanan 				  &cur_ps->priority_xoff_tx[i]);
7209e7a5d17SUsha Ketineni 		ice_stat_update32(hw, GLPRT_RXON2OFFCNT(port, i),
7214b0fdcebSAnirudh Venkataramanan 				  pf->stat_prev_loaded,
7224b0fdcebSAnirudh Venkataramanan 				  &prev_ps->priority_xon_2_xoff[i],
7234b0fdcebSAnirudh Venkataramanan 				  &cur_ps->priority_xon_2_xoff[i]);
7244b0fdcebSAnirudh Venkataramanan 	}
7254b0fdcebSAnirudh Venkataramanan }
7264b0fdcebSAnirudh Venkataramanan 
7274b0fdcebSAnirudh Venkataramanan /**
7285f6aa50eSAnirudh Venkataramanan  * ice_tx_prepare_vlan_flags_dcb - prepare VLAN tagging for DCB
7295f6aa50eSAnirudh Venkataramanan  * @tx_ring: ring to send buffer on
7305f6aa50eSAnirudh Venkataramanan  * @first: pointer to struct ice_tx_buf
7315f6aa50eSAnirudh Venkataramanan  */
7325f6aa50eSAnirudh Venkataramanan int
7335f6aa50eSAnirudh Venkataramanan ice_tx_prepare_vlan_flags_dcb(struct ice_ring *tx_ring,
7345f6aa50eSAnirudh Venkataramanan 			      struct ice_tx_buf *first)
7355f6aa50eSAnirudh Venkataramanan {
7365f6aa50eSAnirudh Venkataramanan 	struct sk_buff *skb = first->skb;
7375f6aa50eSAnirudh Venkataramanan 
7385f6aa50eSAnirudh Venkataramanan 	if (!test_bit(ICE_FLAG_DCB_ENA, tx_ring->vsi->back->flags))
7395f6aa50eSAnirudh Venkataramanan 		return 0;
7405f6aa50eSAnirudh Venkataramanan 
7415f6aa50eSAnirudh Venkataramanan 	/* Insert 802.1p priority into VLAN header */
7425f6aa50eSAnirudh Venkataramanan 	if ((first->tx_flags & (ICE_TX_FLAGS_HW_VLAN | ICE_TX_FLAGS_SW_VLAN)) ||
7435f6aa50eSAnirudh Venkataramanan 	    skb->priority != TC_PRIO_CONTROL) {
7445f6aa50eSAnirudh Venkataramanan 		first->tx_flags &= ~ICE_TX_FLAGS_VLAN_PR_M;
7455f6aa50eSAnirudh Venkataramanan 		/* Mask the lower 3 bits to set the 802.1p priority */
7465f6aa50eSAnirudh Venkataramanan 		first->tx_flags |= (skb->priority & 0x7) <<
7475f6aa50eSAnirudh Venkataramanan 				   ICE_TX_FLAGS_VLAN_PR_S;
7485f6aa50eSAnirudh Venkataramanan 		if (first->tx_flags & ICE_TX_FLAGS_SW_VLAN) {
7495f6aa50eSAnirudh Venkataramanan 			struct vlan_ethhdr *vhdr;
7505f6aa50eSAnirudh Venkataramanan 			int rc;
7515f6aa50eSAnirudh Venkataramanan 
7525f6aa50eSAnirudh Venkataramanan 			rc = skb_cow_head(skb, 0);
7535f6aa50eSAnirudh Venkataramanan 			if (rc < 0)
7545f6aa50eSAnirudh Venkataramanan 				return rc;
7555f6aa50eSAnirudh Venkataramanan 			vhdr = (struct vlan_ethhdr *)skb->data;
7565f6aa50eSAnirudh Venkataramanan 			vhdr->h_vlan_TCI = htons(first->tx_flags >>
7575f6aa50eSAnirudh Venkataramanan 						 ICE_TX_FLAGS_VLAN_S);
7585f6aa50eSAnirudh Venkataramanan 		} else {
7595f6aa50eSAnirudh Venkataramanan 			first->tx_flags |= ICE_TX_FLAGS_HW_VLAN;
7605f6aa50eSAnirudh Venkataramanan 		}
7615f6aa50eSAnirudh Venkataramanan 	}
7625f6aa50eSAnirudh Venkataramanan 
7635f6aa50eSAnirudh Venkataramanan 	return 0;
7645f6aa50eSAnirudh Venkataramanan }
7655f6aa50eSAnirudh Venkataramanan 
7665f6aa50eSAnirudh Venkataramanan /**
76700cc3f1bSAnirudh Venkataramanan  * ice_dcb_process_lldp_set_mib_change - Process MIB change
76800cc3f1bSAnirudh Venkataramanan  * @pf: ptr to ice_pf
76900cc3f1bSAnirudh Venkataramanan  * @event: pointer to the admin queue receive event
77000cc3f1bSAnirudh Venkataramanan  */
77100cc3f1bSAnirudh Venkataramanan void
77200cc3f1bSAnirudh Venkataramanan ice_dcb_process_lldp_set_mib_change(struct ice_pf *pf,
77300cc3f1bSAnirudh Venkataramanan 				    struct ice_rq_event_info *event)
77400cc3f1bSAnirudh Venkataramanan {
775a17a5ff6SUsha Ketineni 	struct ice_aqc_port_ets_elem buf = { 0 };
7764015d11eSBrett Creeley 	struct device *dev = ice_pf_to_dev(pf);
777a17a5ff6SUsha Ketineni 	struct ice_aqc_lldp_get_mib *mib;
778a17a5ff6SUsha Ketineni 	struct ice_dcbx_cfg tmp_dcbx_cfg;
779a17a5ff6SUsha Ketineni 	bool need_reconfig = false;
780a17a5ff6SUsha Ketineni 	struct ice_port_info *pi;
7819d614b64SAnirudh Venkataramanan 	struct ice_vsi *pf_vsi;
782a17a5ff6SUsha Ketineni 	u8 type;
783a17a5ff6SUsha Ketineni 	int ret;
78400cc3f1bSAnirudh Venkataramanan 
785a17a5ff6SUsha Ketineni 	/* Not DCB capable or capability disabled */
786a17a5ff6SUsha Ketineni 	if (!(test_bit(ICE_FLAG_DCB_CAPABLE, pf->flags)))
78700cc3f1bSAnirudh Venkataramanan 		return;
78800cc3f1bSAnirudh Venkataramanan 
789a17a5ff6SUsha Ketineni 	if (pf->dcbx_cap & DCB_CAP_DCBX_HOST) {
7904015d11eSBrett Creeley 		dev_dbg(dev, "MIB Change Event in HOST mode\n");
791a17a5ff6SUsha Ketineni 		return;
79200cc3f1bSAnirudh Venkataramanan 	}
793a17a5ff6SUsha Ketineni 
794a17a5ff6SUsha Ketineni 	pi = pf->hw.port_info;
795a17a5ff6SUsha Ketineni 	mib = (struct ice_aqc_lldp_get_mib *)&event->desc.params.raw;
796a17a5ff6SUsha Ketineni 	/* Ignore if event is not for Nearest Bridge */
797a17a5ff6SUsha Ketineni 	type = ((mib->type >> ICE_AQ_LLDP_BRID_TYPE_S) &
798a17a5ff6SUsha Ketineni 		ICE_AQ_LLDP_BRID_TYPE_M);
7994015d11eSBrett Creeley 	dev_dbg(dev, "LLDP event MIB bridge type 0x%x\n", type);
800a17a5ff6SUsha Ketineni 	if (type != ICE_AQ_LLDP_BRID_TYPE_NEAREST_BRID)
801a17a5ff6SUsha Ketineni 		return;
802a17a5ff6SUsha Ketineni 
803a17a5ff6SUsha Ketineni 	/* Check MIB Type and return if event for Remote MIB update */
804a17a5ff6SUsha Ketineni 	type = mib->type & ICE_AQ_LLDP_MIB_TYPE_M;
8054015d11eSBrett Creeley 	dev_dbg(dev, "LLDP event mib type %s\n", type ? "remote" : "local");
806a17a5ff6SUsha Ketineni 	if (type == ICE_AQ_LLDP_MIB_REMOTE) {
807a17a5ff6SUsha Ketineni 		/* Update the remote cached instance and return */
808a17a5ff6SUsha Ketineni 		ret = ice_aq_get_dcb_cfg(pi->hw, ICE_AQ_LLDP_MIB_REMOTE,
809a17a5ff6SUsha Ketineni 					 ICE_AQ_LLDP_BRID_TYPE_NEAREST_BRID,
810a17a5ff6SUsha Ketineni 					 &pi->remote_dcbx_cfg);
811a17a5ff6SUsha Ketineni 		if (ret) {
8124015d11eSBrett Creeley 			dev_err(dev, "Failed to get remote DCB config\n");
813a17a5ff6SUsha Ketineni 			return;
814a17a5ff6SUsha Ketineni 		}
815a17a5ff6SUsha Ketineni 	}
816a17a5ff6SUsha Ketineni 
817242b5e06SDave Ertman 	mutex_lock(&pf->tc_mutex);
818242b5e06SDave Ertman 
819a17a5ff6SUsha Ketineni 	/* store the old configuration */
820a17a5ff6SUsha Ketineni 	tmp_dcbx_cfg = pf->hw.port_info->local_dcbx_cfg;
821a17a5ff6SUsha Ketineni 
8222f2da36eSAnirudh Venkataramanan 	/* Reset the old DCBX configuration data */
823a17a5ff6SUsha Ketineni 	memset(&pi->local_dcbx_cfg, 0, sizeof(pi->local_dcbx_cfg));
824a17a5ff6SUsha Ketineni 
8252f2da36eSAnirudh Venkataramanan 	/* Get updated DCBX data from firmware */
826a17a5ff6SUsha Ketineni 	ret = ice_get_dcb_cfg(pf->hw.port_info);
827a17a5ff6SUsha Ketineni 	if (ret) {
8284015d11eSBrett Creeley 		dev_err(dev, "Failed to get DCB config\n");
829242b5e06SDave Ertman 		goto out;
830a17a5ff6SUsha Ketineni 	}
831a17a5ff6SUsha Ketineni 
832a17a5ff6SUsha Ketineni 	/* No change detected in DCBX configs */
833a17a5ff6SUsha Ketineni 	if (!memcmp(&tmp_dcbx_cfg, &pi->local_dcbx_cfg, sizeof(tmp_dcbx_cfg))) {
8344015d11eSBrett Creeley 		dev_dbg(dev, "No change detected in DCBX configuration.\n");
835242b5e06SDave Ertman 		goto out;
836a17a5ff6SUsha Ketineni 	}
837a17a5ff6SUsha Ketineni 
8381f454e06SAvinash JD 	pf->dcbx_cap = ice_dcb_get_mode(pi, false);
8391f454e06SAvinash JD 
840a17a5ff6SUsha Ketineni 	need_reconfig = ice_dcb_need_recfg(pf, &tmp_dcbx_cfg,
841a17a5ff6SUsha Ketineni 					   &pi->local_dcbx_cfg);
842b94b013eSDave Ertman 	ice_dcbnl_flush_apps(pf, &tmp_dcbx_cfg, &pi->local_dcbx_cfg);
843a17a5ff6SUsha Ketineni 	if (!need_reconfig)
844242b5e06SDave Ertman 		goto out;
845a17a5ff6SUsha Ketineni 
846a17a5ff6SUsha Ketineni 	/* Enable DCB tagging only when more than one TC */
847a17a5ff6SUsha Ketineni 	if (ice_dcb_get_num_tc(&pi->local_dcbx_cfg) > 1) {
8484015d11eSBrett Creeley 		dev_dbg(dev, "DCB tagging enabled (num TC > 1)\n");
849a17a5ff6SUsha Ketineni 		set_bit(ICE_FLAG_DCB_ENA, pf->flags);
850a17a5ff6SUsha Ketineni 	} else {
8514015d11eSBrett Creeley 		dev_dbg(dev, "DCB tagging disabled (num TC = 1)\n");
852a17a5ff6SUsha Ketineni 		clear_bit(ICE_FLAG_DCB_ENA, pf->flags);
853a17a5ff6SUsha Ketineni 	}
854a17a5ff6SUsha Ketineni 
8559d614b64SAnirudh Venkataramanan 	pf_vsi = ice_get_main_vsi(pf);
8569d614b64SAnirudh Venkataramanan 	if (!pf_vsi) {
8574015d11eSBrett Creeley 		dev_dbg(dev, "PF VSI doesn't exist\n");
858242b5e06SDave Ertman 		goto out;
8599d614b64SAnirudh Venkataramanan 	}
8609d614b64SAnirudh Venkataramanan 
861a17a5ff6SUsha Ketineni 	rtnl_lock();
8629d614b64SAnirudh Venkataramanan 	ice_dis_vsi(pf_vsi, true);
863a17a5ff6SUsha Ketineni 
864a17a5ff6SUsha Ketineni 	ret = ice_query_port_ets(pf->hw.port_info, &buf, sizeof(buf), NULL);
865a17a5ff6SUsha Ketineni 	if (ret) {
8664015d11eSBrett Creeley 		dev_err(dev, "Query Port ETS failed\n");
867242b5e06SDave Ertman 		goto unlock_rtnl;
868a17a5ff6SUsha Ketineni 	}
869a17a5ff6SUsha Ketineni 
870a17a5ff6SUsha Ketineni 	/* changes in configuration update VSI */
871a17a5ff6SUsha Ketineni 	ice_pf_dcb_recfg(pf);
872a17a5ff6SUsha Ketineni 
8739d614b64SAnirudh Venkataramanan 	ice_ena_vsi(pf_vsi, true);
874242b5e06SDave Ertman unlock_rtnl:
875a17a5ff6SUsha Ketineni 	rtnl_unlock();
876242b5e06SDave Ertman out:
877242b5e06SDave Ertman 	mutex_unlock(&pf->tc_mutex);
87800cc3f1bSAnirudh Venkataramanan }
879