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 
7cfbf1367SPaul Greenwalt static void ice_pf_dcb_recfg(struct ice_pf *pf);
8cfbf1367SPaul Greenwalt 
937b6f646SAnirudh Venkataramanan /**
10462acf6aSTony Nguyen  * ice_vsi_cfg_netdev_tc - Setup the netdev TC configuration
11462acf6aSTony Nguyen  * @vsi: the VSI being configured
12462acf6aSTony Nguyen  * @ena_tc: TC map to be enabled
13462acf6aSTony Nguyen  */
14462acf6aSTony Nguyen void ice_vsi_cfg_netdev_tc(struct ice_vsi *vsi, u8 ena_tc)
15462acf6aSTony Nguyen {
16462acf6aSTony Nguyen 	struct net_device *netdev = vsi->netdev;
17462acf6aSTony Nguyen 	struct ice_pf *pf = vsi->back;
18462acf6aSTony Nguyen 	struct ice_dcbx_cfg *dcbcfg;
19462acf6aSTony Nguyen 	u8 netdev_tc;
20462acf6aSTony Nguyen 	int i;
21462acf6aSTony Nguyen 
22462acf6aSTony Nguyen 	if (!netdev)
23462acf6aSTony Nguyen 		return;
24462acf6aSTony Nguyen 
25462acf6aSTony Nguyen 	if (!ena_tc) {
26462acf6aSTony Nguyen 		netdev_reset_tc(netdev);
27462acf6aSTony Nguyen 		return;
28462acf6aSTony Nguyen 	}
29462acf6aSTony Nguyen 
30462acf6aSTony Nguyen 	if (netdev_set_num_tc(netdev, vsi->tc_cfg.numtc))
31462acf6aSTony Nguyen 		return;
32462acf6aSTony Nguyen 
33462acf6aSTony Nguyen 	dcbcfg = &pf->hw.port_info->local_dcbx_cfg;
34462acf6aSTony Nguyen 
35462acf6aSTony Nguyen 	ice_for_each_traffic_class(i)
36462acf6aSTony Nguyen 		if (vsi->tc_cfg.ena_tc & BIT(i))
37462acf6aSTony Nguyen 			netdev_set_tc_queue(netdev,
38462acf6aSTony Nguyen 					    vsi->tc_cfg.tc_info[i].netdev_tc,
39462acf6aSTony Nguyen 					    vsi->tc_cfg.tc_info[i].qcount_tx,
40462acf6aSTony Nguyen 					    vsi->tc_cfg.tc_info[i].qoffset);
41462acf6aSTony Nguyen 
42462acf6aSTony Nguyen 	for (i = 0; i < ICE_MAX_USER_PRIORITY; i++) {
43462acf6aSTony Nguyen 		u8 ets_tc = dcbcfg->etscfg.prio_table[i];
44462acf6aSTony Nguyen 
45462acf6aSTony Nguyen 		/* Get the mapped netdev TC# for the UP */
46462acf6aSTony Nguyen 		netdev_tc = vsi->tc_cfg.tc_info[ets_tc].netdev_tc;
47462acf6aSTony Nguyen 		netdev_set_prio_tc_map(netdev, i, netdev_tc);
48462acf6aSTony Nguyen 	}
49462acf6aSTony Nguyen }
50462acf6aSTony Nguyen 
51462acf6aSTony Nguyen /**
527b9ffc76SAnirudh Venkataramanan  * ice_dcb_get_ena_tc - return bitmap of enabled TCs
537b9ffc76SAnirudh Venkataramanan  * @dcbcfg: DCB config to evaluate for enabled TCs
547b9ffc76SAnirudh Venkataramanan  */
557b9ffc76SAnirudh Venkataramanan u8 ice_dcb_get_ena_tc(struct ice_dcbx_cfg *dcbcfg)
567b9ffc76SAnirudh Venkataramanan {
577b9ffc76SAnirudh Venkataramanan 	u8 i, num_tc, ena_tc = 1;
587b9ffc76SAnirudh Venkataramanan 
597b9ffc76SAnirudh Venkataramanan 	num_tc = ice_dcb_get_num_tc(dcbcfg);
607b9ffc76SAnirudh Venkataramanan 
617b9ffc76SAnirudh Venkataramanan 	for (i = 0; i < num_tc; i++)
627b9ffc76SAnirudh Venkataramanan 		ena_tc |= BIT(i);
637b9ffc76SAnirudh Venkataramanan 
647b9ffc76SAnirudh Venkataramanan 	return ena_tc;
657b9ffc76SAnirudh Venkataramanan }
667b9ffc76SAnirudh Venkataramanan 
677b9ffc76SAnirudh Venkataramanan /**
687b9ffc76SAnirudh Venkataramanan  * ice_dcb_get_num_tc - Get the number of TCs from DCBX config
697b9ffc76SAnirudh Venkataramanan  * @dcbcfg: config to retrieve number of TCs from
707b9ffc76SAnirudh Venkataramanan  */
717b9ffc76SAnirudh Venkataramanan u8 ice_dcb_get_num_tc(struct ice_dcbx_cfg *dcbcfg)
727b9ffc76SAnirudh Venkataramanan {
737b9ffc76SAnirudh Venkataramanan 	bool tc_unused = false;
747b9ffc76SAnirudh Venkataramanan 	u8 num_tc = 0;
757b9ffc76SAnirudh Venkataramanan 	u8 ret = 0;
767b9ffc76SAnirudh Venkataramanan 	int i;
777b9ffc76SAnirudh Venkataramanan 
787b9ffc76SAnirudh Venkataramanan 	/* Scan the ETS Config Priority Table to find traffic classes
797b9ffc76SAnirudh Venkataramanan 	 * enabled and create a bitmask of enabled TCs
807b9ffc76SAnirudh Venkataramanan 	 */
817b9ffc76SAnirudh Venkataramanan 	for (i = 0; i < CEE_DCBX_MAX_PRIO; i++)
827b9ffc76SAnirudh Venkataramanan 		num_tc |= BIT(dcbcfg->etscfg.prio_table[i]);
837b9ffc76SAnirudh Venkataramanan 
847b9ffc76SAnirudh Venkataramanan 	/* Scan bitmask for contiguous TCs starting with TC0 */
857b9ffc76SAnirudh Venkataramanan 	for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
867b9ffc76SAnirudh Venkataramanan 		if (num_tc & BIT(i)) {
877b9ffc76SAnirudh Venkataramanan 			if (!tc_unused) {
887b9ffc76SAnirudh Venkataramanan 				ret++;
897b9ffc76SAnirudh Venkataramanan 			} else {
907b9ffc76SAnirudh Venkataramanan 				pr_err("Non-contiguous TCs - Disabling DCB\n");
917b9ffc76SAnirudh Venkataramanan 				return 1;
927b9ffc76SAnirudh Venkataramanan 			}
937b9ffc76SAnirudh Venkataramanan 		} else {
947b9ffc76SAnirudh Venkataramanan 			tc_unused = true;
957b9ffc76SAnirudh Venkataramanan 		}
967b9ffc76SAnirudh Venkataramanan 	}
977b9ffc76SAnirudh Venkataramanan 
987b9ffc76SAnirudh Venkataramanan 	/* There is always at least 1 TC */
997b9ffc76SAnirudh Venkataramanan 	if (!ret)
1007b9ffc76SAnirudh Venkataramanan 		ret = 1;
1017b9ffc76SAnirudh Venkataramanan 
1027b9ffc76SAnirudh Venkataramanan 	return ret;
1037b9ffc76SAnirudh Venkataramanan }
1047b9ffc76SAnirudh Venkataramanan 
1057b9ffc76SAnirudh Venkataramanan /**
1061ddef455SUsha Ketineni  * ice_dcb_get_tc - Get the TC associated with the queue
1071ddef455SUsha Ketineni  * @vsi: ptr to the VSI
1081ddef455SUsha Ketineni  * @queue_index: queue number associated with VSI
1091ddef455SUsha Ketineni  */
1101ddef455SUsha Ketineni u8 ice_dcb_get_tc(struct ice_vsi *vsi, int queue_index)
1111ddef455SUsha Ketineni {
1121ddef455SUsha Ketineni 	return vsi->tx_rings[queue_index]->dcb_tc;
1131ddef455SUsha Ketineni }
1141ddef455SUsha Ketineni 
1151ddef455SUsha Ketineni /**
116a629cf0aSAnirudh Venkataramanan  * ice_vsi_cfg_dcb_rings - Update rings to reflect DCB TC
117a629cf0aSAnirudh Venkataramanan  * @vsi: VSI owner of rings being updated
118a629cf0aSAnirudh Venkataramanan  */
119a629cf0aSAnirudh Venkataramanan void ice_vsi_cfg_dcb_rings(struct ice_vsi *vsi)
120a629cf0aSAnirudh Venkataramanan {
121a629cf0aSAnirudh Venkataramanan 	struct ice_ring *tx_ring, *rx_ring;
122a629cf0aSAnirudh Venkataramanan 	u16 qoffset, qcount;
123a629cf0aSAnirudh Venkataramanan 	int i, n;
124a629cf0aSAnirudh Venkataramanan 
125a629cf0aSAnirudh Venkataramanan 	if (!test_bit(ICE_FLAG_DCB_ENA, vsi->back->flags)) {
126a629cf0aSAnirudh Venkataramanan 		/* Reset the TC information */
127a629cf0aSAnirudh Venkataramanan 		for (i = 0; i < vsi->num_txq; i++) {
128a629cf0aSAnirudh Venkataramanan 			tx_ring = vsi->tx_rings[i];
129a629cf0aSAnirudh Venkataramanan 			tx_ring->dcb_tc = 0;
130a629cf0aSAnirudh Venkataramanan 		}
131a629cf0aSAnirudh Venkataramanan 		for (i = 0; i < vsi->num_rxq; i++) {
132a629cf0aSAnirudh Venkataramanan 			rx_ring = vsi->rx_rings[i];
133a629cf0aSAnirudh Venkataramanan 			rx_ring->dcb_tc = 0;
134a629cf0aSAnirudh Venkataramanan 		}
135a629cf0aSAnirudh Venkataramanan 		return;
136a629cf0aSAnirudh Venkataramanan 	}
137a629cf0aSAnirudh Venkataramanan 
138a629cf0aSAnirudh Venkataramanan 	ice_for_each_traffic_class(n) {
139a629cf0aSAnirudh Venkataramanan 		if (!(vsi->tc_cfg.ena_tc & BIT(n)))
140a629cf0aSAnirudh Venkataramanan 			break;
141a629cf0aSAnirudh Venkataramanan 
142a629cf0aSAnirudh Venkataramanan 		qoffset = vsi->tc_cfg.tc_info[n].qoffset;
143a629cf0aSAnirudh Venkataramanan 		qcount = vsi->tc_cfg.tc_info[n].qcount_tx;
144a629cf0aSAnirudh Venkataramanan 		for (i = qoffset; i < (qoffset + qcount); i++) {
145a629cf0aSAnirudh Venkataramanan 			tx_ring = vsi->tx_rings[i];
146a629cf0aSAnirudh Venkataramanan 			rx_ring = vsi->rx_rings[i];
147a629cf0aSAnirudh Venkataramanan 			tx_ring->dcb_tc = n;
148a629cf0aSAnirudh Venkataramanan 			rx_ring->dcb_tc = n;
149a629cf0aSAnirudh Venkataramanan 		}
150a629cf0aSAnirudh Venkataramanan 	}
151a629cf0aSAnirudh Venkataramanan }
152a629cf0aSAnirudh Venkataramanan 
153a629cf0aSAnirudh Venkataramanan /**
1547b9ffc76SAnirudh Venkataramanan  * ice_pf_dcb_cfg - Apply new DCB configuration
1557b9ffc76SAnirudh Venkataramanan  * @pf: pointer to the PF struct
1567b9ffc76SAnirudh Venkataramanan  * @new_cfg: DCBX config to apply
157e223eaecSDave Ertman  * @locked: is the RTNL held
1587b9ffc76SAnirudh Venkataramanan  */
159e223eaecSDave Ertman int ice_pf_dcb_cfg(struct ice_pf *pf, struct ice_dcbx_cfg *new_cfg, bool locked)
1607b9ffc76SAnirudh Venkataramanan {
1617b9ffc76SAnirudh Venkataramanan 	struct ice_aqc_port_ets_elem buf = { 0 };
162b94b013eSDave Ertman 	struct ice_dcbx_cfg *old_cfg, *curr_cfg;
163b94b013eSDave Ertman 	int ret = ICE_DCB_NO_HW_CHG;
1649d614b64SAnirudh Venkataramanan 	struct ice_vsi *pf_vsi;
1657b9ffc76SAnirudh Venkataramanan 
1667b9ffc76SAnirudh Venkataramanan 	curr_cfg = &pf->hw.port_info->local_dcbx_cfg;
1677b9ffc76SAnirudh Venkataramanan 
168b94b013eSDave Ertman 	/* FW does not care if change happened */
169b94b013eSDave Ertman 	if (!pf->hw.port_info->is_sw_lldp)
170b94b013eSDave Ertman 		ret = ICE_DCB_HW_CHG_RST;
171b94b013eSDave Ertman 
1727b9ffc76SAnirudh Venkataramanan 	/* Enable DCB tagging only when more than one TC */
1737b9ffc76SAnirudh Venkataramanan 	if (ice_dcb_get_num_tc(new_cfg) > 1) {
1747b9ffc76SAnirudh Venkataramanan 		dev_dbg(&pf->pdev->dev, "DCB tagging enabled (num TC > 1)\n");
1757b9ffc76SAnirudh Venkataramanan 		set_bit(ICE_FLAG_DCB_ENA, pf->flags);
1767b9ffc76SAnirudh Venkataramanan 	} else {
1777b9ffc76SAnirudh Venkataramanan 		dev_dbg(&pf->pdev->dev, "DCB tagging disabled (num TC = 1)\n");
1787b9ffc76SAnirudh Venkataramanan 		clear_bit(ICE_FLAG_DCB_ENA, pf->flags);
1797b9ffc76SAnirudh Venkataramanan 	}
1807b9ffc76SAnirudh Venkataramanan 
1817b9ffc76SAnirudh Venkataramanan 	if (!memcmp(new_cfg, curr_cfg, sizeof(*new_cfg))) {
1827b9ffc76SAnirudh Venkataramanan 		dev_dbg(&pf->pdev->dev, "No change in DCB config required\n");
1837b9ffc76SAnirudh Venkataramanan 		return ret;
1847b9ffc76SAnirudh Venkataramanan 	}
1857b9ffc76SAnirudh Venkataramanan 
1867b9ffc76SAnirudh Venkataramanan 	/* Store old config in case FW config fails */
1879d614b64SAnirudh Venkataramanan 	old_cfg = kmemdup(curr_cfg, sizeof(*old_cfg), GFP_KERNEL);
1889d614b64SAnirudh Venkataramanan 	if (!old_cfg)
1899d614b64SAnirudh Venkataramanan 		return -ENOMEM;
1909d614b64SAnirudh Venkataramanan 
191b94b013eSDave Ertman 	dev_info(&pf->pdev->dev, "Commit DCB Configuration to the hardware\n");
1929d614b64SAnirudh Venkataramanan 	pf_vsi = ice_get_main_vsi(pf);
1939d614b64SAnirudh Venkataramanan 	if (!pf_vsi) {
1949d614b64SAnirudh Venkataramanan 		dev_dbg(&pf->pdev->dev, "PF VSI doesn't exist\n");
1959d614b64SAnirudh Venkataramanan 		ret = -EINVAL;
1969d614b64SAnirudh Venkataramanan 		goto free_cfg;
1979d614b64SAnirudh Venkataramanan 	}
1987b9ffc76SAnirudh Venkataramanan 
1997b9ffc76SAnirudh Venkataramanan 	/* avoid race conditions by holding the lock while disabling and
2007b9ffc76SAnirudh Venkataramanan 	 * re-enabling the VSI
2017b9ffc76SAnirudh Venkataramanan 	 */
202e223eaecSDave Ertman 	if (!locked)
2037b9ffc76SAnirudh Venkataramanan 		rtnl_lock();
2049d614b64SAnirudh Venkataramanan 	ice_dis_vsi(pf_vsi, true);
2057b9ffc76SAnirudh Venkataramanan 
2067b9ffc76SAnirudh Venkataramanan 	memcpy(curr_cfg, new_cfg, sizeof(*curr_cfg));
2077b9ffc76SAnirudh Venkataramanan 	memcpy(&curr_cfg->etsrec, &curr_cfg->etscfg, sizeof(curr_cfg->etsrec));
208b94b013eSDave Ertman 	memcpy(&new_cfg->etsrec, &curr_cfg->etscfg, sizeof(curr_cfg->etsrec));
2097b9ffc76SAnirudh Venkataramanan 
2107b9ffc76SAnirudh Venkataramanan 	/* Only send new config to HW if we are in SW LLDP mode. Otherwise,
2117b9ffc76SAnirudh Venkataramanan 	 * the new config came from the HW in the first place.
2127b9ffc76SAnirudh Venkataramanan 	 */
2137b9ffc76SAnirudh Venkataramanan 	if (pf->hw.port_info->is_sw_lldp) {
2147b9ffc76SAnirudh Venkataramanan 		ret = ice_set_dcb_cfg(pf->hw.port_info);
2157b9ffc76SAnirudh Venkataramanan 		if (ret) {
2167b9ffc76SAnirudh Venkataramanan 			dev_err(&pf->pdev->dev, "Set DCB Config failed\n");
2177b9ffc76SAnirudh Venkataramanan 			/* Restore previous settings to local config */
2187b9ffc76SAnirudh Venkataramanan 			memcpy(curr_cfg, old_cfg, sizeof(*curr_cfg));
2197b9ffc76SAnirudh Venkataramanan 			goto out;
2207b9ffc76SAnirudh Venkataramanan 		}
2217b9ffc76SAnirudh Venkataramanan 	}
2227b9ffc76SAnirudh Venkataramanan 
2237b9ffc76SAnirudh Venkataramanan 	ret = ice_query_port_ets(pf->hw.port_info, &buf, sizeof(buf), NULL);
2247b9ffc76SAnirudh Venkataramanan 	if (ret) {
2257b9ffc76SAnirudh Venkataramanan 		dev_err(&pf->pdev->dev, "Query Port ETS failed\n");
2267b9ffc76SAnirudh Venkataramanan 		goto out;
2277b9ffc76SAnirudh Venkataramanan 	}
2287b9ffc76SAnirudh Venkataramanan 
2297b9ffc76SAnirudh Venkataramanan 	ice_pf_dcb_recfg(pf);
2307b9ffc76SAnirudh Venkataramanan 
2317b9ffc76SAnirudh Venkataramanan out:
2329d614b64SAnirudh Venkataramanan 	ice_ena_vsi(pf_vsi, true);
233e223eaecSDave Ertman 	if (!locked)
2347b9ffc76SAnirudh Venkataramanan 		rtnl_unlock();
2359d614b64SAnirudh Venkataramanan free_cfg:
2369d614b64SAnirudh Venkataramanan 	kfree(old_cfg);
2377b9ffc76SAnirudh Venkataramanan 	return ret;
2387b9ffc76SAnirudh Venkataramanan }
2397b9ffc76SAnirudh Venkataramanan 
2407b9ffc76SAnirudh Venkataramanan /**
2417829570eSUsha Ketineni  * ice_cfg_etsrec_defaults - Set default ETS recommended DCB config
2427829570eSUsha Ketineni  * @pi: port information structure
2437829570eSUsha Ketineni  */
2447829570eSUsha Ketineni static void ice_cfg_etsrec_defaults(struct ice_port_info *pi)
2457829570eSUsha Ketineni {
2467829570eSUsha Ketineni 	struct ice_dcbx_cfg *dcbcfg = &pi->local_dcbx_cfg;
2477829570eSUsha Ketineni 	u8 i;
2487829570eSUsha Ketineni 
2497829570eSUsha Ketineni 	/* Ensure ETS recommended DCB configuration is not already set */
2507829570eSUsha Ketineni 	if (dcbcfg->etsrec.maxtcs)
2517829570eSUsha Ketineni 		return;
2527829570eSUsha Ketineni 
2537829570eSUsha Ketineni 	/* In CEE mode, set the default to 1 TC */
2547829570eSUsha Ketineni 	dcbcfg->etsrec.maxtcs = 1;
2557829570eSUsha Ketineni 	for (i = 0; i < ICE_MAX_TRAFFIC_CLASS; i++) {
2567829570eSUsha Ketineni 		dcbcfg->etsrec.tcbwtable[i] = i ? 0 : 100;
2577829570eSUsha Ketineni 		dcbcfg->etsrec.tsatable[i] = i ? ICE_IEEE_TSA_STRICT :
2587829570eSUsha Ketineni 						 ICE_IEEE_TSA_ETS;
2597829570eSUsha Ketineni 	}
2607829570eSUsha Ketineni }
2617829570eSUsha Ketineni 
2627829570eSUsha Ketineni /**
2637829570eSUsha Ketineni  * ice_dcb_need_recfg - Check if DCB needs reconfig
2647829570eSUsha Ketineni  * @pf: board private structure
2657829570eSUsha Ketineni  * @old_cfg: current DCB config
2667829570eSUsha Ketineni  * @new_cfg: new DCB config
2677829570eSUsha Ketineni  */
2687829570eSUsha Ketineni static bool
2697829570eSUsha Ketineni ice_dcb_need_recfg(struct ice_pf *pf, struct ice_dcbx_cfg *old_cfg,
2707829570eSUsha Ketineni 		   struct ice_dcbx_cfg *new_cfg)
2717829570eSUsha Ketineni {
2727829570eSUsha Ketineni 	bool need_reconfig = false;
2737829570eSUsha Ketineni 
2747829570eSUsha Ketineni 	/* Check if ETS configuration has changed */
2757829570eSUsha Ketineni 	if (memcmp(&new_cfg->etscfg, &old_cfg->etscfg,
2767829570eSUsha Ketineni 		   sizeof(new_cfg->etscfg))) {
2777829570eSUsha Ketineni 		/* If Priority Table has changed reconfig is needed */
2787829570eSUsha Ketineni 		if (memcmp(&new_cfg->etscfg.prio_table,
2797829570eSUsha Ketineni 			   &old_cfg->etscfg.prio_table,
2807829570eSUsha Ketineni 			   sizeof(new_cfg->etscfg.prio_table))) {
2817829570eSUsha Ketineni 			need_reconfig = true;
2827829570eSUsha Ketineni 			dev_dbg(&pf->pdev->dev, "ETS UP2TC changed.\n");
2837829570eSUsha Ketineni 		}
2847829570eSUsha Ketineni 
2857829570eSUsha Ketineni 		if (memcmp(&new_cfg->etscfg.tcbwtable,
2867829570eSUsha Ketineni 			   &old_cfg->etscfg.tcbwtable,
2877829570eSUsha Ketineni 			   sizeof(new_cfg->etscfg.tcbwtable)))
2887829570eSUsha Ketineni 			dev_dbg(&pf->pdev->dev, "ETS TC BW Table changed.\n");
2897829570eSUsha Ketineni 
2907829570eSUsha Ketineni 		if (memcmp(&new_cfg->etscfg.tsatable,
2917829570eSUsha Ketineni 			   &old_cfg->etscfg.tsatable,
2927829570eSUsha Ketineni 			   sizeof(new_cfg->etscfg.tsatable)))
2937829570eSUsha Ketineni 			dev_dbg(&pf->pdev->dev, "ETS TSA Table changed.\n");
2947829570eSUsha Ketineni 	}
2957829570eSUsha Ketineni 
2967829570eSUsha Ketineni 	/* Check if PFC configuration has changed */
2977829570eSUsha Ketineni 	if (memcmp(&new_cfg->pfc, &old_cfg->pfc, sizeof(new_cfg->pfc))) {
2987829570eSUsha Ketineni 		need_reconfig = true;
2997829570eSUsha Ketineni 		dev_dbg(&pf->pdev->dev, "PFC config change detected.\n");
3007829570eSUsha Ketineni 	}
3017829570eSUsha Ketineni 
3027829570eSUsha Ketineni 	/* Check if APP Table has changed */
3037829570eSUsha Ketineni 	if (memcmp(&new_cfg->app, &old_cfg->app, sizeof(new_cfg->app))) {
3047829570eSUsha Ketineni 		need_reconfig = true;
3057829570eSUsha Ketineni 		dev_dbg(&pf->pdev->dev, "APP Table change detected.\n");
3067829570eSUsha Ketineni 	}
3077829570eSUsha Ketineni 
3087829570eSUsha Ketineni 	dev_dbg(&pf->pdev->dev, "dcb need_reconfig=%d\n", need_reconfig);
3097829570eSUsha Ketineni 	return need_reconfig;
3107829570eSUsha Ketineni }
3117829570eSUsha Ketineni 
3127829570eSUsha Ketineni /**
313b832c2f6SAnirudh Venkataramanan  * ice_dcb_rebuild - rebuild DCB post reset
314b832c2f6SAnirudh Venkataramanan  * @pf: physical function instance
315b832c2f6SAnirudh Venkataramanan  */
316b832c2f6SAnirudh Venkataramanan void ice_dcb_rebuild(struct ice_pf *pf)
317b832c2f6SAnirudh Venkataramanan {
3187829570eSUsha Ketineni 	struct ice_dcbx_cfg *local_dcbx_cfg, *desired_dcbx_cfg, *prev_cfg;
319b832c2f6SAnirudh Venkataramanan 	struct ice_aqc_port_ets_elem buf = { 0 };
320b832c2f6SAnirudh Venkataramanan 	enum ice_status ret;
321b832c2f6SAnirudh Venkataramanan 
322b832c2f6SAnirudh Venkataramanan 	ret = ice_query_port_ets(pf->hw.port_info, &buf, sizeof(buf), NULL);
323b832c2f6SAnirudh Venkataramanan 	if (ret) {
324b832c2f6SAnirudh Venkataramanan 		dev_err(&pf->pdev->dev, "Query Port ETS failed\n");
325b832c2f6SAnirudh Venkataramanan 		goto dcb_error;
326b832c2f6SAnirudh Venkataramanan 	}
327b832c2f6SAnirudh Venkataramanan 
328b832c2f6SAnirudh Venkataramanan 	/* If DCB was not enabled previously, we are done */
329b832c2f6SAnirudh Venkataramanan 	if (!test_bit(ICE_FLAG_DCB_ENA, pf->flags))
330b832c2f6SAnirudh Venkataramanan 		return;
331b832c2f6SAnirudh Venkataramanan 
3327829570eSUsha Ketineni 	local_dcbx_cfg = &pf->hw.port_info->local_dcbx_cfg;
3337829570eSUsha Ketineni 	desired_dcbx_cfg = &pf->hw.port_info->desired_dcbx_cfg;
3347829570eSUsha Ketineni 
335b832c2f6SAnirudh Venkataramanan 	/* Save current willing state and force FW to unwilling */
3367829570eSUsha Ketineni 	local_dcbx_cfg->etscfg.willing = 0x0;
3377829570eSUsha Ketineni 	local_dcbx_cfg->pfc.willing = 0x0;
3387829570eSUsha Ketineni 	local_dcbx_cfg->app_mode = ICE_DCBX_APPS_NON_WILLING;
3397829570eSUsha Ketineni 
3407829570eSUsha Ketineni 	ice_cfg_etsrec_defaults(pf->hw.port_info);
341b832c2f6SAnirudh Venkataramanan 	ret = ice_set_dcb_cfg(pf->hw.port_info);
342b832c2f6SAnirudh Venkataramanan 	if (ret) {
343b832c2f6SAnirudh Venkataramanan 		dev_err(&pf->pdev->dev, "Failed to set DCB to unwilling\n");
344b832c2f6SAnirudh Venkataramanan 		goto dcb_error;
345b832c2f6SAnirudh Venkataramanan 	}
346b832c2f6SAnirudh Venkataramanan 
347b832c2f6SAnirudh Venkataramanan 	/* Retrieve DCB config and ensure same as current in SW */
3487829570eSUsha Ketineni 	prev_cfg = devm_kmemdup(&pf->pdev->dev, local_dcbx_cfg,
349b832c2f6SAnirudh Venkataramanan 				sizeof(*prev_cfg), GFP_KERNEL);
350b832c2f6SAnirudh Venkataramanan 	if (!prev_cfg) {
351b832c2f6SAnirudh Venkataramanan 		dev_err(&pf->pdev->dev, "Failed to alloc space for DCB cfg\n");
352b832c2f6SAnirudh Venkataramanan 		goto dcb_error;
353b832c2f6SAnirudh Venkataramanan 	}
354b832c2f6SAnirudh Venkataramanan 
355ea300f41SDave Ertman 	ice_init_dcb(&pf->hw, true);
3561b0c3247SDave Ertman 	if (pf->hw.port_info->dcbx_status == ICE_DCBX_STATUS_DIS)
3571b0c3247SDave Ertman 		pf->hw.port_info->is_sw_lldp = true;
3581b0c3247SDave Ertman 	else
3591b0c3247SDave Ertman 		pf->hw.port_info->is_sw_lldp = false;
3601b0c3247SDave Ertman 
3617829570eSUsha Ketineni 	if (ice_dcb_need_recfg(pf, prev_cfg, local_dcbx_cfg)) {
362b832c2f6SAnirudh Venkataramanan 		/* difference in cfg detected - disable DCB till next MIB */
363b832c2f6SAnirudh Venkataramanan 		dev_err(&pf->pdev->dev, "Set local MIB not accurate\n");
364b832c2f6SAnirudh Venkataramanan 		goto dcb_error;
365b832c2f6SAnirudh Venkataramanan 	}
366b832c2f6SAnirudh Venkataramanan 
367b832c2f6SAnirudh Venkataramanan 	/* fetched config congruent to previous configuration */
368b832c2f6SAnirudh Venkataramanan 	devm_kfree(&pf->pdev->dev, prev_cfg);
369b832c2f6SAnirudh Venkataramanan 
3707829570eSUsha Ketineni 	/* Set the local desired config */
37142a179c8SMichal Swiatkowski 	if (local_dcbx_cfg->dcbx_mode == ICE_DCBX_MODE_CEE)
37242a179c8SMichal Swiatkowski 		memcpy(local_dcbx_cfg, desired_dcbx_cfg,
37342a179c8SMichal Swiatkowski 		       sizeof(*local_dcbx_cfg));
37442a179c8SMichal Swiatkowski 
3757829570eSUsha Ketineni 	ice_cfg_etsrec_defaults(pf->hw.port_info);
376b832c2f6SAnirudh Venkataramanan 	ret = ice_set_dcb_cfg(pf->hw.port_info);
377b832c2f6SAnirudh Venkataramanan 	if (ret) {
3787829570eSUsha Ketineni 		dev_err(&pf->pdev->dev, "Failed to set desired config\n");
379b832c2f6SAnirudh Venkataramanan 		goto dcb_error;
380b832c2f6SAnirudh Venkataramanan 	}
381b832c2f6SAnirudh Venkataramanan 	dev_info(&pf->pdev->dev, "DCB restored after reset\n");
382b832c2f6SAnirudh Venkataramanan 	ret = ice_query_port_ets(pf->hw.port_info, &buf, sizeof(buf), NULL);
383b832c2f6SAnirudh Venkataramanan 	if (ret) {
384b832c2f6SAnirudh Venkataramanan 		dev_err(&pf->pdev->dev, "Query Port ETS failed\n");
385b832c2f6SAnirudh Venkataramanan 		goto dcb_error;
386b832c2f6SAnirudh Venkataramanan 	}
387b832c2f6SAnirudh Venkataramanan 
388b832c2f6SAnirudh Venkataramanan 	return;
389b832c2f6SAnirudh Venkataramanan 
390b832c2f6SAnirudh Venkataramanan dcb_error:
391b832c2f6SAnirudh Venkataramanan 	dev_err(&pf->pdev->dev, "Disabling DCB until new settings occur\n");
392b832c2f6SAnirudh Venkataramanan 	prev_cfg = devm_kzalloc(&pf->pdev->dev, sizeof(*prev_cfg), GFP_KERNEL);
393b832c2f6SAnirudh Venkataramanan 	prev_cfg->etscfg.willing = true;
394b832c2f6SAnirudh Venkataramanan 	prev_cfg->etscfg.tcbwtable[0] = ICE_TC_MAX_BW;
395b832c2f6SAnirudh Venkataramanan 	prev_cfg->etscfg.tsatable[0] = ICE_IEEE_TSA_ETS;
396b832c2f6SAnirudh Venkataramanan 	memcpy(&prev_cfg->etsrec, &prev_cfg->etscfg, sizeof(prev_cfg->etsrec));
397e223eaecSDave Ertman 	ice_pf_dcb_cfg(pf, prev_cfg, false);
398b832c2f6SAnirudh Venkataramanan 	devm_kfree(&pf->pdev->dev, prev_cfg);
399b832c2f6SAnirudh Venkataramanan }
400b832c2f6SAnirudh Venkataramanan 
401b832c2f6SAnirudh Venkataramanan /**
4027b9ffc76SAnirudh Venkataramanan  * ice_dcb_init_cfg - set the initial DCB config in SW
4032f2da36eSAnirudh Venkataramanan  * @pf: PF to apply config to
404e223eaecSDave Ertman  * @locked: Is the RTNL held
4057b9ffc76SAnirudh Venkataramanan  */
406e223eaecSDave Ertman static int ice_dcb_init_cfg(struct ice_pf *pf, bool locked)
4077b9ffc76SAnirudh Venkataramanan {
4087b9ffc76SAnirudh Venkataramanan 	struct ice_dcbx_cfg *newcfg;
4097b9ffc76SAnirudh Venkataramanan 	struct ice_port_info *pi;
4107b9ffc76SAnirudh Venkataramanan 	int ret = 0;
4117b9ffc76SAnirudh Venkataramanan 
4127b9ffc76SAnirudh Venkataramanan 	pi = pf->hw.port_info;
4137b9ffc76SAnirudh Venkataramanan 	newcfg = devm_kzalloc(&pf->pdev->dev, sizeof(*newcfg), GFP_KERNEL);
4147b9ffc76SAnirudh Venkataramanan 	if (!newcfg)
4157b9ffc76SAnirudh Venkataramanan 		return -ENOMEM;
4167b9ffc76SAnirudh Venkataramanan 
4177b9ffc76SAnirudh Venkataramanan 	memcpy(newcfg, &pi->local_dcbx_cfg, sizeof(*newcfg));
4187b9ffc76SAnirudh Venkataramanan 	memset(&pi->local_dcbx_cfg, 0, sizeof(*newcfg));
4197b9ffc76SAnirudh Venkataramanan 
4207b9ffc76SAnirudh Venkataramanan 	dev_info(&pf->pdev->dev, "Configuring initial DCB values\n");
421e223eaecSDave Ertman 	if (ice_pf_dcb_cfg(pf, newcfg, locked))
4227b9ffc76SAnirudh Venkataramanan 		ret = -EINVAL;
4237b9ffc76SAnirudh Venkataramanan 
4247b9ffc76SAnirudh Venkataramanan 	devm_kfree(&pf->pdev->dev, newcfg);
4257b9ffc76SAnirudh Venkataramanan 
4267b9ffc76SAnirudh Venkataramanan 	return ret;
4277b9ffc76SAnirudh Venkataramanan }
4287b9ffc76SAnirudh Venkataramanan 
4297b9ffc76SAnirudh Venkataramanan /**
4300deab659SAnirudh Venkataramanan  * ice_dcb_sw_default_config - Apply a default DCB config
4312f2da36eSAnirudh Venkataramanan  * @pf: PF to apply config to
432cfbf1367SPaul Greenwalt  * @ets_willing: configure ets willing
433e223eaecSDave Ertman  * @locked: was this function called with RTNL held
4340deab659SAnirudh Venkataramanan  */
435cfbf1367SPaul Greenwalt static int ice_dcb_sw_dflt_cfg(struct ice_pf *pf, bool ets_willing, bool locked)
4360deab659SAnirudh Venkataramanan {
4370deab659SAnirudh Venkataramanan 	struct ice_aqc_port_ets_elem buf = { 0 };
4380deab659SAnirudh Venkataramanan 	struct ice_dcbx_cfg *dcbcfg;
4390deab659SAnirudh Venkataramanan 	struct ice_port_info *pi;
4400deab659SAnirudh Venkataramanan 	struct ice_hw *hw;
4410deab659SAnirudh Venkataramanan 	int ret;
4420deab659SAnirudh Venkataramanan 
4430deab659SAnirudh Venkataramanan 	hw = &pf->hw;
4440deab659SAnirudh Venkataramanan 	pi = hw->port_info;
4450deab659SAnirudh Venkataramanan 	dcbcfg = devm_kzalloc(&pf->pdev->dev, sizeof(*dcbcfg), GFP_KERNEL);
4460deab659SAnirudh Venkataramanan 
4470deab659SAnirudh Venkataramanan 	memset(dcbcfg, 0, sizeof(*dcbcfg));
4480deab659SAnirudh Venkataramanan 	memset(&pi->local_dcbx_cfg, 0, sizeof(*dcbcfg));
4490deab659SAnirudh Venkataramanan 
450cfbf1367SPaul Greenwalt 	dcbcfg->etscfg.willing = ets_willing ? 1 : 0;
451a257f188SUsha Ketineni 	dcbcfg->etscfg.maxtcs = hw->func_caps.common_cap.maxtc;
4520deab659SAnirudh Venkataramanan 	dcbcfg->etscfg.tcbwtable[0] = 100;
4530deab659SAnirudh Venkataramanan 	dcbcfg->etscfg.tsatable[0] = ICE_IEEE_TSA_ETS;
4540deab659SAnirudh Venkataramanan 
4550deab659SAnirudh Venkataramanan 	memcpy(&dcbcfg->etsrec, &dcbcfg->etscfg,
4560deab659SAnirudh Venkataramanan 	       sizeof(dcbcfg->etsrec));
4570deab659SAnirudh Venkataramanan 	dcbcfg->etsrec.willing = 0;
4580deab659SAnirudh Venkataramanan 
4590deab659SAnirudh Venkataramanan 	dcbcfg->pfc.willing = 1;
460a257f188SUsha Ketineni 	dcbcfg->pfc.pfccap = hw->func_caps.common_cap.maxtc;
4610deab659SAnirudh Venkataramanan 
4620deab659SAnirudh Venkataramanan 	dcbcfg->numapps = 1;
4630deab659SAnirudh Venkataramanan 	dcbcfg->app[0].selector = ICE_APP_SEL_ETHTYPE;
4640deab659SAnirudh Venkataramanan 	dcbcfg->app[0].priority = 3;
4650deab659SAnirudh Venkataramanan 	dcbcfg->app[0].prot_id = ICE_APP_PROT_ID_FCOE;
4660deab659SAnirudh Venkataramanan 
467e223eaecSDave Ertman 	ret = ice_pf_dcb_cfg(pf, dcbcfg, locked);
4680deab659SAnirudh Venkataramanan 	devm_kfree(&pf->pdev->dev, dcbcfg);
4690deab659SAnirudh Venkataramanan 	if (ret)
4700deab659SAnirudh Venkataramanan 		return ret;
4710deab659SAnirudh Venkataramanan 
4720deab659SAnirudh Venkataramanan 	return ice_query_port_ets(pi, &buf, sizeof(buf), NULL);
4730deab659SAnirudh Venkataramanan }
4740deab659SAnirudh Venkataramanan 
4750deab659SAnirudh Venkataramanan /**
476cfbf1367SPaul Greenwalt  * ice_dcb_tc_contig - Check that TCs are contiguous
477cfbf1367SPaul Greenwalt  * @prio_table: pointer to priority table
478cfbf1367SPaul Greenwalt  *
479cfbf1367SPaul Greenwalt  * Check if TCs begin with TC0 and are contiguous
480cfbf1367SPaul Greenwalt  */
481cfbf1367SPaul Greenwalt static bool ice_dcb_tc_contig(u8 *prio_table)
482cfbf1367SPaul Greenwalt {
483cfbf1367SPaul Greenwalt 	u8 max_tc = 0;
484cfbf1367SPaul Greenwalt 	int i;
485cfbf1367SPaul Greenwalt 
486cfbf1367SPaul Greenwalt 	for (i = 0; i < CEE_DCBX_MAX_PRIO; i++) {
487cfbf1367SPaul Greenwalt 		u8 cur_tc = prio_table[i];
488cfbf1367SPaul Greenwalt 
489cfbf1367SPaul Greenwalt 		if (cur_tc > max_tc)
490cfbf1367SPaul Greenwalt 			return false;
491cfbf1367SPaul Greenwalt 		else if (cur_tc == max_tc)
492cfbf1367SPaul Greenwalt 			max_tc++;
493cfbf1367SPaul Greenwalt 	}
494cfbf1367SPaul Greenwalt 
495cfbf1367SPaul Greenwalt 	return true;
496cfbf1367SPaul Greenwalt }
497cfbf1367SPaul Greenwalt 
498cfbf1367SPaul Greenwalt /**
499cfbf1367SPaul Greenwalt  * ice_dcb_noncontig_cfg - Configure DCB for non-contiguous TCs
500cfbf1367SPaul Greenwalt  * @pf: pointer to the PF struct
501cfbf1367SPaul Greenwalt  *
502cfbf1367SPaul Greenwalt  * If non-contiguous TCs, then configure SW DCB with TC0 and ETS non-willing
503cfbf1367SPaul Greenwalt  */
504cfbf1367SPaul Greenwalt static int ice_dcb_noncontig_cfg(struct ice_pf *pf)
505cfbf1367SPaul Greenwalt {
506cfbf1367SPaul Greenwalt 	struct ice_dcbx_cfg *dcbcfg = &pf->hw.port_info->local_dcbx_cfg;
507cfbf1367SPaul Greenwalt 	int ret;
508cfbf1367SPaul Greenwalt 
509cfbf1367SPaul Greenwalt 	/* Configure SW DCB default with ETS non-willing */
510cfbf1367SPaul Greenwalt 	ret = ice_dcb_sw_dflt_cfg(pf, false, true);
511cfbf1367SPaul Greenwalt 	if (ret) {
512cfbf1367SPaul Greenwalt 		dev_err(&pf->pdev->dev,
513cfbf1367SPaul Greenwalt 			"Failed to set local DCB config %d\n", ret);
514cfbf1367SPaul Greenwalt 		return ret;
515cfbf1367SPaul Greenwalt 	}
516cfbf1367SPaul Greenwalt 
517cfbf1367SPaul Greenwalt 	/* Reconfigure with ETS willing so that FW will send LLDP MIB event */
518cfbf1367SPaul Greenwalt 	dcbcfg->etscfg.willing = 1;
519cfbf1367SPaul Greenwalt 	ret = ice_set_dcb_cfg(pf->hw.port_info);
520cfbf1367SPaul Greenwalt 	if (ret)
521cfbf1367SPaul Greenwalt 		dev_err(&pf->pdev->dev, "Failed to set DCB to unwilling\n");
522cfbf1367SPaul Greenwalt 
523cfbf1367SPaul Greenwalt 	return ret;
524cfbf1367SPaul Greenwalt }
525cfbf1367SPaul Greenwalt 
526cfbf1367SPaul Greenwalt /**
527cfbf1367SPaul Greenwalt  * ice_pf_dcb_recfg - Reconfigure all VEBs and VSIs
528cfbf1367SPaul Greenwalt  * @pf: pointer to the PF struct
529cfbf1367SPaul Greenwalt  *
530cfbf1367SPaul Greenwalt  * Assumed caller has already disabled all VSIs before
531cfbf1367SPaul Greenwalt  * calling this function. Reconfiguring DCB based on
532cfbf1367SPaul Greenwalt  * local_dcbx_cfg.
533cfbf1367SPaul Greenwalt  */
534cfbf1367SPaul Greenwalt static void ice_pf_dcb_recfg(struct ice_pf *pf)
535cfbf1367SPaul Greenwalt {
536cfbf1367SPaul Greenwalt 	struct ice_dcbx_cfg *dcbcfg = &pf->hw.port_info->local_dcbx_cfg;
537cfbf1367SPaul Greenwalt 	u8 tc_map = 0;
538cfbf1367SPaul Greenwalt 	int v, ret;
539cfbf1367SPaul Greenwalt 
540cfbf1367SPaul Greenwalt 	/* Update each VSI */
541cfbf1367SPaul Greenwalt 	ice_for_each_vsi(pf, v) {
542cfbf1367SPaul Greenwalt 		if (!pf->vsi[v])
543cfbf1367SPaul Greenwalt 			continue;
544cfbf1367SPaul Greenwalt 
545cfbf1367SPaul Greenwalt 		if (pf->vsi[v]->type == ICE_VSI_PF) {
546cfbf1367SPaul Greenwalt 			tc_map = ice_dcb_get_ena_tc(dcbcfg);
547cfbf1367SPaul Greenwalt 
548cfbf1367SPaul Greenwalt 			/* If DCBX request non-contiguous TC, then configure
549cfbf1367SPaul Greenwalt 			 * default TC
550cfbf1367SPaul Greenwalt 			 */
551cfbf1367SPaul Greenwalt 			if (!ice_dcb_tc_contig(dcbcfg->etscfg.prio_table)) {
552cfbf1367SPaul Greenwalt 				tc_map = ICE_DFLT_TRAFFIC_CLASS;
553cfbf1367SPaul Greenwalt 				ice_dcb_noncontig_cfg(pf);
554cfbf1367SPaul Greenwalt 			}
555cfbf1367SPaul Greenwalt 		} else {
556cfbf1367SPaul Greenwalt 			tc_map = ICE_DFLT_TRAFFIC_CLASS;
557cfbf1367SPaul Greenwalt 		}
558cfbf1367SPaul Greenwalt 
559cfbf1367SPaul Greenwalt 		ret = ice_vsi_cfg_tc(pf->vsi[v], tc_map);
560cfbf1367SPaul Greenwalt 		if (ret) {
561cfbf1367SPaul Greenwalt 			dev_err(&pf->pdev->dev,
562cfbf1367SPaul Greenwalt 				"Failed to config TC for VSI index: %d\n",
563cfbf1367SPaul Greenwalt 				pf->vsi[v]->idx);
564cfbf1367SPaul Greenwalt 			continue;
565cfbf1367SPaul Greenwalt 		}
566cfbf1367SPaul Greenwalt 
567cfbf1367SPaul Greenwalt 		ice_vsi_map_rings_to_vectors(pf->vsi[v]);
568b94b013eSDave Ertman 		if (pf->vsi[v]->type == ICE_VSI_PF)
569b94b013eSDave Ertman 			ice_dcbnl_set_all(pf->vsi[v]);
570cfbf1367SPaul Greenwalt 	}
571cfbf1367SPaul Greenwalt }
572cfbf1367SPaul Greenwalt 
573cfbf1367SPaul Greenwalt /**
57437b6f646SAnirudh Venkataramanan  * ice_init_pf_dcb - initialize DCB for a PF
5752f2da36eSAnirudh Venkataramanan  * @pf: PF to initialize DCB for
576e223eaecSDave Ertman  * @locked: Was function called with RTNL held
57737b6f646SAnirudh Venkataramanan  */
578e223eaecSDave Ertman int ice_init_pf_dcb(struct ice_pf *pf, bool locked)
57937b6f646SAnirudh Venkataramanan {
58037b6f646SAnirudh Venkataramanan 	struct device *dev = &pf->pdev->dev;
58137b6f646SAnirudh Venkataramanan 	struct ice_port_info *port_info;
58237b6f646SAnirudh Venkataramanan 	struct ice_hw *hw = &pf->hw;
5837b9ffc76SAnirudh Venkataramanan 	int err;
58437b6f646SAnirudh Venkataramanan 
58537b6f646SAnirudh Venkataramanan 	port_info = hw->port_info;
58637b6f646SAnirudh Venkataramanan 
587ea300f41SDave Ertman 	err = ice_init_dcb(hw, false);
588473ca574SDave Ertman 	if (err && !port_info->is_sw_lldp) {
589473ca574SDave Ertman 		dev_err(&pf->pdev->dev, "Error initializing DCB %d\n", err);
590473ca574SDave Ertman 		goto dcb_init_err;
591473ca574SDave Ertman 	}
592473ca574SDave Ertman 
5931b0c3247SDave Ertman 	dev_info(&pf->pdev->dev,
594a257f188SUsha Ketineni 		 "DCB is enabled in the hardware, max number of TCs supported on this port are %d\n",
595a257f188SUsha Ketineni 		 pf->hw.func_caps.common_cap.maxtc);
596473ca574SDave Ertman 	if (err) {
597241c8cf0SPaul Greenwalt 		struct ice_vsi *pf_vsi;
598241c8cf0SPaul Greenwalt 
599473ca574SDave Ertman 		/* FW LLDP is disabled, activate SW DCBX/LLDP mode */
600a257f188SUsha Ketineni 		dev_info(&pf->pdev->dev,
6011b0c3247SDave Ertman 			 "FW LLDP is disabled, DCBx/LLDP in SW mode.\n");
60284a118abSDave Ertman 		clear_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags);
603cfbf1367SPaul Greenwalt 		err = ice_dcb_sw_dflt_cfg(pf, true, locked);
6040deab659SAnirudh Venkataramanan 		if (err) {
6050deab659SAnirudh Venkataramanan 			dev_err(&pf->pdev->dev,
6060deab659SAnirudh Venkataramanan 				"Failed to set local DCB config %d\n", err);
6070deab659SAnirudh Venkataramanan 			err = -EIO;
6087b9ffc76SAnirudh Venkataramanan 			goto dcb_init_err;
6090deab659SAnirudh Venkataramanan 		}
6100deab659SAnirudh Venkataramanan 
611241c8cf0SPaul Greenwalt 		/* If the FW DCBX engine is not running then Rx LLDP packets
612241c8cf0SPaul Greenwalt 		 * need to be redirected up the stack.
613241c8cf0SPaul Greenwalt 		 */
614241c8cf0SPaul Greenwalt 		pf_vsi = ice_get_main_vsi(pf);
615241c8cf0SPaul Greenwalt 		if (!pf_vsi) {
616241c8cf0SPaul Greenwalt 			dev_err(&pf->pdev->dev,
617241c8cf0SPaul Greenwalt 				"Failed to set local DCB config\n");
618241c8cf0SPaul Greenwalt 			err = -EIO;
619241c8cf0SPaul Greenwalt 			goto dcb_init_err;
620241c8cf0SPaul Greenwalt 		}
621241c8cf0SPaul Greenwalt 
622241c8cf0SPaul Greenwalt 		ice_cfg_sw_lldp(pf_vsi, false, true);
623241c8cf0SPaul Greenwalt 
6240deab659SAnirudh Venkataramanan 		pf->dcbx_cap = DCB_CAP_DCBX_HOST | DCB_CAP_DCBX_VER_IEEE;
6250deab659SAnirudh Venkataramanan 		return 0;
6260deab659SAnirudh Venkataramanan 	}
6277b9ffc76SAnirudh Venkataramanan 
62884a118abSDave Ertman 	set_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags);
6291b0c3247SDave Ertman 
6307b9ffc76SAnirudh Venkataramanan 	/* DCBX in FW and LLDP enabled in FW */
6317b9ffc76SAnirudh Venkataramanan 	pf->dcbx_cap = DCB_CAP_DCBX_LLD_MANAGED | DCB_CAP_DCBX_VER_IEEE;
6327b9ffc76SAnirudh Venkataramanan 
633e223eaecSDave Ertman 	err = ice_dcb_init_cfg(pf, locked);
6347b9ffc76SAnirudh Venkataramanan 	if (err)
6357b9ffc76SAnirudh Venkataramanan 		goto dcb_init_err;
6367b9ffc76SAnirudh Venkataramanan 
6377b9ffc76SAnirudh Venkataramanan 	return err;
6387b9ffc76SAnirudh Venkataramanan 
6397b9ffc76SAnirudh Venkataramanan dcb_init_err:
6407b9ffc76SAnirudh Venkataramanan 	dev_err(dev, "DCB init failed\n");
6417b9ffc76SAnirudh Venkataramanan 	return err;
64237b6f646SAnirudh Venkataramanan }
64300cc3f1bSAnirudh Venkataramanan 
64400cc3f1bSAnirudh Venkataramanan /**
6454b0fdcebSAnirudh Venkataramanan  * ice_update_dcb_stats - Update DCB stats counters
6464b0fdcebSAnirudh Venkataramanan  * @pf: PF whose stats needs to be updated
6474b0fdcebSAnirudh Venkataramanan  */
6484b0fdcebSAnirudh Venkataramanan void ice_update_dcb_stats(struct ice_pf *pf)
6494b0fdcebSAnirudh Venkataramanan {
6504b0fdcebSAnirudh Venkataramanan 	struct ice_hw_port_stats *prev_ps, *cur_ps;
6514b0fdcebSAnirudh Venkataramanan 	struct ice_hw *hw = &pf->hw;
6529e7a5d17SUsha Ketineni 	u8 port;
6534b0fdcebSAnirudh Venkataramanan 	int i;
6544b0fdcebSAnirudh Venkataramanan 
6559e7a5d17SUsha Ketineni 	port = hw->port_info->lport;
6564b0fdcebSAnirudh Venkataramanan 	prev_ps = &pf->stats_prev;
6574b0fdcebSAnirudh Venkataramanan 	cur_ps = &pf->stats;
6584b0fdcebSAnirudh Venkataramanan 
6594b0fdcebSAnirudh Venkataramanan 	for (i = 0; i < 8; i++) {
6609e7a5d17SUsha Ketineni 		ice_stat_update32(hw, GLPRT_PXOFFRXC(port, i),
6614b0fdcebSAnirudh Venkataramanan 				  pf->stat_prev_loaded,
6624b0fdcebSAnirudh Venkataramanan 				  &prev_ps->priority_xoff_rx[i],
6634b0fdcebSAnirudh Venkataramanan 				  &cur_ps->priority_xoff_rx[i]);
6649e7a5d17SUsha Ketineni 		ice_stat_update32(hw, GLPRT_PXONRXC(port, i),
6654b0fdcebSAnirudh Venkataramanan 				  pf->stat_prev_loaded,
6664b0fdcebSAnirudh Venkataramanan 				  &prev_ps->priority_xon_rx[i],
6674b0fdcebSAnirudh Venkataramanan 				  &cur_ps->priority_xon_rx[i]);
6689e7a5d17SUsha Ketineni 		ice_stat_update32(hw, GLPRT_PXONTXC(port, i),
6694b0fdcebSAnirudh Venkataramanan 				  pf->stat_prev_loaded,
6704b0fdcebSAnirudh Venkataramanan 				  &prev_ps->priority_xon_tx[i],
6714b0fdcebSAnirudh Venkataramanan 				  &cur_ps->priority_xon_tx[i]);
6729e7a5d17SUsha Ketineni 		ice_stat_update32(hw, GLPRT_PXOFFTXC(port, i),
6734b0fdcebSAnirudh Venkataramanan 				  pf->stat_prev_loaded,
6744b0fdcebSAnirudh Venkataramanan 				  &prev_ps->priority_xoff_tx[i],
6754b0fdcebSAnirudh Venkataramanan 				  &cur_ps->priority_xoff_tx[i]);
6769e7a5d17SUsha Ketineni 		ice_stat_update32(hw, GLPRT_RXON2OFFCNT(port, i),
6774b0fdcebSAnirudh Venkataramanan 				  pf->stat_prev_loaded,
6784b0fdcebSAnirudh Venkataramanan 				  &prev_ps->priority_xon_2_xoff[i],
6794b0fdcebSAnirudh Venkataramanan 				  &cur_ps->priority_xon_2_xoff[i]);
6804b0fdcebSAnirudh Venkataramanan 	}
6814b0fdcebSAnirudh Venkataramanan }
6824b0fdcebSAnirudh Venkataramanan 
6834b0fdcebSAnirudh Venkataramanan /**
6845f6aa50eSAnirudh Venkataramanan  * ice_tx_prepare_vlan_flags_dcb - prepare VLAN tagging for DCB
6855f6aa50eSAnirudh Venkataramanan  * @tx_ring: ring to send buffer on
6865f6aa50eSAnirudh Venkataramanan  * @first: pointer to struct ice_tx_buf
6875f6aa50eSAnirudh Venkataramanan  */
6885f6aa50eSAnirudh Venkataramanan int
6895f6aa50eSAnirudh Venkataramanan ice_tx_prepare_vlan_flags_dcb(struct ice_ring *tx_ring,
6905f6aa50eSAnirudh Venkataramanan 			      struct ice_tx_buf *first)
6915f6aa50eSAnirudh Venkataramanan {
6925f6aa50eSAnirudh Venkataramanan 	struct sk_buff *skb = first->skb;
6935f6aa50eSAnirudh Venkataramanan 
6945f6aa50eSAnirudh Venkataramanan 	if (!test_bit(ICE_FLAG_DCB_ENA, tx_ring->vsi->back->flags))
6955f6aa50eSAnirudh Venkataramanan 		return 0;
6965f6aa50eSAnirudh Venkataramanan 
6975f6aa50eSAnirudh Venkataramanan 	/* Insert 802.1p priority into VLAN header */
6985f6aa50eSAnirudh Venkataramanan 	if ((first->tx_flags & (ICE_TX_FLAGS_HW_VLAN | ICE_TX_FLAGS_SW_VLAN)) ||
6995f6aa50eSAnirudh Venkataramanan 	    skb->priority != TC_PRIO_CONTROL) {
7005f6aa50eSAnirudh Venkataramanan 		first->tx_flags &= ~ICE_TX_FLAGS_VLAN_PR_M;
7015f6aa50eSAnirudh Venkataramanan 		/* Mask the lower 3 bits to set the 802.1p priority */
7025f6aa50eSAnirudh Venkataramanan 		first->tx_flags |= (skb->priority & 0x7) <<
7035f6aa50eSAnirudh Venkataramanan 				   ICE_TX_FLAGS_VLAN_PR_S;
7045f6aa50eSAnirudh Venkataramanan 		if (first->tx_flags & ICE_TX_FLAGS_SW_VLAN) {
7055f6aa50eSAnirudh Venkataramanan 			struct vlan_ethhdr *vhdr;
7065f6aa50eSAnirudh Venkataramanan 			int rc;
7075f6aa50eSAnirudh Venkataramanan 
7085f6aa50eSAnirudh Venkataramanan 			rc = skb_cow_head(skb, 0);
7095f6aa50eSAnirudh Venkataramanan 			if (rc < 0)
7105f6aa50eSAnirudh Venkataramanan 				return rc;
7115f6aa50eSAnirudh Venkataramanan 			vhdr = (struct vlan_ethhdr *)skb->data;
7125f6aa50eSAnirudh Venkataramanan 			vhdr->h_vlan_TCI = htons(first->tx_flags >>
7135f6aa50eSAnirudh Venkataramanan 						 ICE_TX_FLAGS_VLAN_S);
7145f6aa50eSAnirudh Venkataramanan 		} else {
7155f6aa50eSAnirudh Venkataramanan 			first->tx_flags |= ICE_TX_FLAGS_HW_VLAN;
7165f6aa50eSAnirudh Venkataramanan 		}
7175f6aa50eSAnirudh Venkataramanan 	}
7185f6aa50eSAnirudh Venkataramanan 
7195f6aa50eSAnirudh Venkataramanan 	return 0;
7205f6aa50eSAnirudh Venkataramanan }
7215f6aa50eSAnirudh Venkataramanan 
7225f6aa50eSAnirudh Venkataramanan /**
72300cc3f1bSAnirudh Venkataramanan  * ice_dcb_process_lldp_set_mib_change - Process MIB change
72400cc3f1bSAnirudh Venkataramanan  * @pf: ptr to ice_pf
72500cc3f1bSAnirudh Venkataramanan  * @event: pointer to the admin queue receive event
72600cc3f1bSAnirudh Venkataramanan  */
72700cc3f1bSAnirudh Venkataramanan void
72800cc3f1bSAnirudh Venkataramanan ice_dcb_process_lldp_set_mib_change(struct ice_pf *pf,
72900cc3f1bSAnirudh Venkataramanan 				    struct ice_rq_event_info *event)
73000cc3f1bSAnirudh Venkataramanan {
731a17a5ff6SUsha Ketineni 	struct ice_aqc_port_ets_elem buf = { 0 };
732a17a5ff6SUsha Ketineni 	struct ice_aqc_lldp_get_mib *mib;
733a17a5ff6SUsha Ketineni 	struct ice_dcbx_cfg tmp_dcbx_cfg;
734a17a5ff6SUsha Ketineni 	bool need_reconfig = false;
735a17a5ff6SUsha Ketineni 	struct ice_port_info *pi;
7369d614b64SAnirudh Venkataramanan 	struct ice_vsi *pf_vsi;
737a17a5ff6SUsha Ketineni 	u8 type;
738a17a5ff6SUsha Ketineni 	int ret;
73900cc3f1bSAnirudh Venkataramanan 
740a17a5ff6SUsha Ketineni 	/* Not DCB capable or capability disabled */
741a17a5ff6SUsha Ketineni 	if (!(test_bit(ICE_FLAG_DCB_CAPABLE, pf->flags)))
74200cc3f1bSAnirudh Venkataramanan 		return;
74300cc3f1bSAnirudh Venkataramanan 
744a17a5ff6SUsha Ketineni 	if (pf->dcbx_cap & DCB_CAP_DCBX_HOST) {
74500cc3f1bSAnirudh Venkataramanan 		dev_dbg(&pf->pdev->dev,
74600cc3f1bSAnirudh Venkataramanan 			"MIB Change Event in HOST mode\n");
747a17a5ff6SUsha Ketineni 		return;
74800cc3f1bSAnirudh Venkataramanan 	}
749a17a5ff6SUsha Ketineni 
750a17a5ff6SUsha Ketineni 	pi = pf->hw.port_info;
751a17a5ff6SUsha Ketineni 	mib = (struct ice_aqc_lldp_get_mib *)&event->desc.params.raw;
752a17a5ff6SUsha Ketineni 	/* Ignore if event is not for Nearest Bridge */
753a17a5ff6SUsha Ketineni 	type = ((mib->type >> ICE_AQ_LLDP_BRID_TYPE_S) &
754a17a5ff6SUsha Ketineni 		ICE_AQ_LLDP_BRID_TYPE_M);
755a17a5ff6SUsha Ketineni 	dev_dbg(&pf->pdev->dev, "LLDP event MIB bridge type 0x%x\n", type);
756a17a5ff6SUsha Ketineni 	if (type != ICE_AQ_LLDP_BRID_TYPE_NEAREST_BRID)
757a17a5ff6SUsha Ketineni 		return;
758a17a5ff6SUsha Ketineni 
759a17a5ff6SUsha Ketineni 	/* Check MIB Type and return if event for Remote MIB update */
760a17a5ff6SUsha Ketineni 	type = mib->type & ICE_AQ_LLDP_MIB_TYPE_M;
761a17a5ff6SUsha Ketineni 	dev_dbg(&pf->pdev->dev,
762a17a5ff6SUsha Ketineni 		"LLDP event mib type %s\n", type ? "remote" : "local");
763a17a5ff6SUsha Ketineni 	if (type == ICE_AQ_LLDP_MIB_REMOTE) {
764a17a5ff6SUsha Ketineni 		/* Update the remote cached instance and return */
765a17a5ff6SUsha Ketineni 		ret = ice_aq_get_dcb_cfg(pi->hw, ICE_AQ_LLDP_MIB_REMOTE,
766a17a5ff6SUsha Ketineni 					 ICE_AQ_LLDP_BRID_TYPE_NEAREST_BRID,
767a17a5ff6SUsha Ketineni 					 &pi->remote_dcbx_cfg);
768a17a5ff6SUsha Ketineni 		if (ret) {
769a17a5ff6SUsha Ketineni 			dev_err(&pf->pdev->dev, "Failed to get remote DCB config\n");
770a17a5ff6SUsha Ketineni 			return;
771a17a5ff6SUsha Ketineni 		}
772a17a5ff6SUsha Ketineni 	}
773a17a5ff6SUsha Ketineni 
774a17a5ff6SUsha Ketineni 	/* store the old configuration */
775a17a5ff6SUsha Ketineni 	tmp_dcbx_cfg = pf->hw.port_info->local_dcbx_cfg;
776a17a5ff6SUsha Ketineni 
7772f2da36eSAnirudh Venkataramanan 	/* Reset the old DCBX configuration data */
778a17a5ff6SUsha Ketineni 	memset(&pi->local_dcbx_cfg, 0, sizeof(pi->local_dcbx_cfg));
779a17a5ff6SUsha Ketineni 
7802f2da36eSAnirudh Venkataramanan 	/* Get updated DCBX data from firmware */
781a17a5ff6SUsha Ketineni 	ret = ice_get_dcb_cfg(pf->hw.port_info);
782a17a5ff6SUsha Ketineni 	if (ret) {
783a17a5ff6SUsha Ketineni 		dev_err(&pf->pdev->dev, "Failed to get DCB config\n");
784a17a5ff6SUsha Ketineni 		return;
785a17a5ff6SUsha Ketineni 	}
786a17a5ff6SUsha Ketineni 
787a17a5ff6SUsha Ketineni 	/* No change detected in DCBX configs */
788a17a5ff6SUsha Ketineni 	if (!memcmp(&tmp_dcbx_cfg, &pi->local_dcbx_cfg, sizeof(tmp_dcbx_cfg))) {
789a17a5ff6SUsha Ketineni 		dev_dbg(&pf->pdev->dev,
790a17a5ff6SUsha Ketineni 			"No change detected in DCBX configuration.\n");
791a17a5ff6SUsha Ketineni 		return;
792a17a5ff6SUsha Ketineni 	}
793a17a5ff6SUsha Ketineni 
794a17a5ff6SUsha Ketineni 	need_reconfig = ice_dcb_need_recfg(pf, &tmp_dcbx_cfg,
795a17a5ff6SUsha Ketineni 					   &pi->local_dcbx_cfg);
796b94b013eSDave Ertman 	ice_dcbnl_flush_apps(pf, &tmp_dcbx_cfg, &pi->local_dcbx_cfg);
797a17a5ff6SUsha Ketineni 	if (!need_reconfig)
798a17a5ff6SUsha Ketineni 		return;
799a17a5ff6SUsha Ketineni 
800a17a5ff6SUsha Ketineni 	/* Enable DCB tagging only when more than one TC */
801a17a5ff6SUsha Ketineni 	if (ice_dcb_get_num_tc(&pi->local_dcbx_cfg) > 1) {
802a17a5ff6SUsha Ketineni 		dev_dbg(&pf->pdev->dev, "DCB tagging enabled (num TC > 1)\n");
803a17a5ff6SUsha Ketineni 		set_bit(ICE_FLAG_DCB_ENA, pf->flags);
804a17a5ff6SUsha Ketineni 	} else {
805a17a5ff6SUsha Ketineni 		dev_dbg(&pf->pdev->dev, "DCB tagging disabled (num TC = 1)\n");
806a17a5ff6SUsha Ketineni 		clear_bit(ICE_FLAG_DCB_ENA, pf->flags);
807a17a5ff6SUsha Ketineni 	}
808a17a5ff6SUsha Ketineni 
8099d614b64SAnirudh Venkataramanan 	pf_vsi = ice_get_main_vsi(pf);
8109d614b64SAnirudh Venkataramanan 	if (!pf_vsi) {
8119d614b64SAnirudh Venkataramanan 		dev_dbg(&pf->pdev->dev, "PF VSI doesn't exist\n");
8129d614b64SAnirudh Venkataramanan 		return;
8139d614b64SAnirudh Venkataramanan 	}
8149d614b64SAnirudh Venkataramanan 
815a17a5ff6SUsha Ketineni 	rtnl_lock();
8169d614b64SAnirudh Venkataramanan 	ice_dis_vsi(pf_vsi, true);
817a17a5ff6SUsha Ketineni 
818a17a5ff6SUsha Ketineni 	ret = ice_query_port_ets(pf->hw.port_info, &buf, sizeof(buf), NULL);
819a17a5ff6SUsha Ketineni 	if (ret) {
820a17a5ff6SUsha Ketineni 		dev_err(&pf->pdev->dev, "Query Port ETS failed\n");
821a17a5ff6SUsha Ketineni 		rtnl_unlock();
822a17a5ff6SUsha Ketineni 		return;
823a17a5ff6SUsha Ketineni 	}
824a17a5ff6SUsha Ketineni 
825a17a5ff6SUsha Ketineni 	/* changes in configuration update VSI */
826a17a5ff6SUsha Ketineni 	ice_pf_dcb_recfg(pf);
827a17a5ff6SUsha Ketineni 
8289d614b64SAnirudh Venkataramanan 	ice_ena_vsi(pf_vsi, true);
829a17a5ff6SUsha Ketineni 	rtnl_unlock();
83000cc3f1bSAnirudh Venkataramanan }
831