137b6f646SAnirudh Venkataramanan // SPDX-License-Identifier: GPL-2.0
237b6f646SAnirudh Venkataramanan /* Copyright (c) 2019, Intel Corporation. */
337b6f646SAnirudh Venkataramanan 
437b6f646SAnirudh Venkataramanan #include "ice_dcb_lib.h"
5b94b013eSDave Ertman #include "ice_dcb_nl.h"
637b6f646SAnirudh Venkataramanan 
737b6f646SAnirudh Venkataramanan /**
8462acf6aSTony Nguyen  * ice_vsi_cfg_netdev_tc - Setup the netdev TC configuration
9462acf6aSTony Nguyen  * @vsi: the VSI being configured
10462acf6aSTony Nguyen  * @ena_tc: TC map to be enabled
11462acf6aSTony Nguyen  */
12462acf6aSTony Nguyen void ice_vsi_cfg_netdev_tc(struct ice_vsi *vsi, u8 ena_tc)
13462acf6aSTony Nguyen {
14462acf6aSTony Nguyen 	struct net_device *netdev = vsi->netdev;
15462acf6aSTony Nguyen 	struct ice_pf *pf = vsi->back;
16462acf6aSTony Nguyen 	struct ice_dcbx_cfg *dcbcfg;
17462acf6aSTony Nguyen 	u8 netdev_tc;
18462acf6aSTony Nguyen 	int i;
19462acf6aSTony Nguyen 
20462acf6aSTony Nguyen 	if (!netdev)
21462acf6aSTony Nguyen 		return;
22462acf6aSTony Nguyen 
23462acf6aSTony Nguyen 	if (!ena_tc) {
24462acf6aSTony Nguyen 		netdev_reset_tc(netdev);
25462acf6aSTony Nguyen 		return;
26462acf6aSTony Nguyen 	}
27462acf6aSTony Nguyen 
28462acf6aSTony Nguyen 	if (netdev_set_num_tc(netdev, vsi->tc_cfg.numtc))
29462acf6aSTony Nguyen 		return;
30462acf6aSTony Nguyen 
31462acf6aSTony Nguyen 	dcbcfg = &pf->hw.port_info->local_dcbx_cfg;
32462acf6aSTony Nguyen 
33462acf6aSTony Nguyen 	ice_for_each_traffic_class(i)
34462acf6aSTony Nguyen 		if (vsi->tc_cfg.ena_tc & BIT(i))
35462acf6aSTony Nguyen 			netdev_set_tc_queue(netdev,
36462acf6aSTony Nguyen 					    vsi->tc_cfg.tc_info[i].netdev_tc,
37462acf6aSTony Nguyen 					    vsi->tc_cfg.tc_info[i].qcount_tx,
38462acf6aSTony Nguyen 					    vsi->tc_cfg.tc_info[i].qoffset);
39462acf6aSTony Nguyen 
40462acf6aSTony Nguyen 	for (i = 0; i < ICE_MAX_USER_PRIORITY; i++) {
41462acf6aSTony Nguyen 		u8 ets_tc = dcbcfg->etscfg.prio_table[i];
42462acf6aSTony Nguyen 
43462acf6aSTony Nguyen 		/* Get the mapped netdev TC# for the UP */
44462acf6aSTony Nguyen 		netdev_tc = vsi->tc_cfg.tc_info[ets_tc].netdev_tc;
45462acf6aSTony Nguyen 		netdev_set_prio_tc_map(netdev, i, netdev_tc);
46462acf6aSTony Nguyen 	}
47462acf6aSTony Nguyen }
48462acf6aSTony Nguyen 
49462acf6aSTony Nguyen /**
507b9ffc76SAnirudh Venkataramanan  * ice_dcb_get_ena_tc - return bitmap of enabled TCs
517b9ffc76SAnirudh Venkataramanan  * @dcbcfg: DCB config to evaluate for enabled TCs
527b9ffc76SAnirudh Venkataramanan  */
537b9ffc76SAnirudh Venkataramanan u8 ice_dcb_get_ena_tc(struct ice_dcbx_cfg *dcbcfg)
547b9ffc76SAnirudh Venkataramanan {
557b9ffc76SAnirudh Venkataramanan 	u8 i, num_tc, ena_tc = 1;
567b9ffc76SAnirudh Venkataramanan 
577b9ffc76SAnirudh Venkataramanan 	num_tc = ice_dcb_get_num_tc(dcbcfg);
587b9ffc76SAnirudh Venkataramanan 
597b9ffc76SAnirudh Venkataramanan 	for (i = 0; i < num_tc; i++)
607b9ffc76SAnirudh Venkataramanan 		ena_tc |= BIT(i);
617b9ffc76SAnirudh Venkataramanan 
627b9ffc76SAnirudh Venkataramanan 	return ena_tc;
637b9ffc76SAnirudh Venkataramanan }
647b9ffc76SAnirudh Venkataramanan 
657b9ffc76SAnirudh Venkataramanan /**
667b9ffc76SAnirudh Venkataramanan  * ice_dcb_get_num_tc - Get the number of TCs from DCBX config
677b9ffc76SAnirudh Venkataramanan  * @dcbcfg: config to retrieve number of TCs from
687b9ffc76SAnirudh Venkataramanan  */
697b9ffc76SAnirudh Venkataramanan u8 ice_dcb_get_num_tc(struct ice_dcbx_cfg *dcbcfg)
707b9ffc76SAnirudh Venkataramanan {
717b9ffc76SAnirudh Venkataramanan 	bool tc_unused = false;
727b9ffc76SAnirudh Venkataramanan 	u8 num_tc = 0;
737b9ffc76SAnirudh Venkataramanan 	u8 ret = 0;
747b9ffc76SAnirudh Venkataramanan 	int i;
757b9ffc76SAnirudh Venkataramanan 
767b9ffc76SAnirudh Venkataramanan 	/* Scan the ETS Config Priority Table to find traffic classes
777b9ffc76SAnirudh Venkataramanan 	 * enabled and create a bitmask of enabled TCs
787b9ffc76SAnirudh Venkataramanan 	 */
797b9ffc76SAnirudh Venkataramanan 	for (i = 0; i < CEE_DCBX_MAX_PRIO; i++)
807b9ffc76SAnirudh Venkataramanan 		num_tc |= BIT(dcbcfg->etscfg.prio_table[i]);
817b9ffc76SAnirudh Venkataramanan 
827b9ffc76SAnirudh Venkataramanan 	/* Scan bitmask for contiguous TCs starting with TC0 */
837b9ffc76SAnirudh Venkataramanan 	for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
847b9ffc76SAnirudh Venkataramanan 		if (num_tc & BIT(i)) {
857b9ffc76SAnirudh Venkataramanan 			if (!tc_unused) {
867b9ffc76SAnirudh Venkataramanan 				ret++;
877b9ffc76SAnirudh Venkataramanan 			} else {
887b9ffc76SAnirudh Venkataramanan 				pr_err("Non-contiguous TCs - Disabling DCB\n");
897b9ffc76SAnirudh Venkataramanan 				return 1;
907b9ffc76SAnirudh Venkataramanan 			}
917b9ffc76SAnirudh Venkataramanan 		} else {
927b9ffc76SAnirudh Venkataramanan 			tc_unused = true;
937b9ffc76SAnirudh Venkataramanan 		}
947b9ffc76SAnirudh Venkataramanan 	}
957b9ffc76SAnirudh Venkataramanan 
967b9ffc76SAnirudh Venkataramanan 	/* There is always at least 1 TC */
977b9ffc76SAnirudh Venkataramanan 	if (!ret)
987b9ffc76SAnirudh Venkataramanan 		ret = 1;
997b9ffc76SAnirudh Venkataramanan 
1007b9ffc76SAnirudh Venkataramanan 	return ret;
1017b9ffc76SAnirudh Venkataramanan }
1027b9ffc76SAnirudh Venkataramanan 
1037b9ffc76SAnirudh Venkataramanan /**
1041ddef455SUsha Ketineni  * ice_dcb_get_tc - Get the TC associated with the queue
1051ddef455SUsha Ketineni  * @vsi: ptr to the VSI
1061ddef455SUsha Ketineni  * @queue_index: queue number associated with VSI
1071ddef455SUsha Ketineni  */
1081ddef455SUsha Ketineni u8 ice_dcb_get_tc(struct ice_vsi *vsi, int queue_index)
1091ddef455SUsha Ketineni {
1101ddef455SUsha Ketineni 	return vsi->tx_rings[queue_index]->dcb_tc;
1111ddef455SUsha Ketineni }
1121ddef455SUsha Ketineni 
1131ddef455SUsha Ketineni /**
114a629cf0aSAnirudh Venkataramanan  * ice_vsi_cfg_dcb_rings - Update rings to reflect DCB TC
115a629cf0aSAnirudh Venkataramanan  * @vsi: VSI owner of rings being updated
116a629cf0aSAnirudh Venkataramanan  */
117a629cf0aSAnirudh Venkataramanan void ice_vsi_cfg_dcb_rings(struct ice_vsi *vsi)
118a629cf0aSAnirudh Venkataramanan {
119a629cf0aSAnirudh Venkataramanan 	struct ice_ring *tx_ring, *rx_ring;
120a629cf0aSAnirudh Venkataramanan 	u16 qoffset, qcount;
121a629cf0aSAnirudh Venkataramanan 	int i, n;
122a629cf0aSAnirudh Venkataramanan 
123a629cf0aSAnirudh Venkataramanan 	if (!test_bit(ICE_FLAG_DCB_ENA, vsi->back->flags)) {
124a629cf0aSAnirudh Venkataramanan 		/* Reset the TC information */
125a629cf0aSAnirudh Venkataramanan 		for (i = 0; i < vsi->num_txq; i++) {
126a629cf0aSAnirudh Venkataramanan 			tx_ring = vsi->tx_rings[i];
127a629cf0aSAnirudh Venkataramanan 			tx_ring->dcb_tc = 0;
128a629cf0aSAnirudh Venkataramanan 		}
129a629cf0aSAnirudh Venkataramanan 		for (i = 0; i < vsi->num_rxq; i++) {
130a629cf0aSAnirudh Venkataramanan 			rx_ring = vsi->rx_rings[i];
131a629cf0aSAnirudh Venkataramanan 			rx_ring->dcb_tc = 0;
132a629cf0aSAnirudh Venkataramanan 		}
133a629cf0aSAnirudh Venkataramanan 		return;
134a629cf0aSAnirudh Venkataramanan 	}
135a629cf0aSAnirudh Venkataramanan 
136a629cf0aSAnirudh Venkataramanan 	ice_for_each_traffic_class(n) {
137a629cf0aSAnirudh Venkataramanan 		if (!(vsi->tc_cfg.ena_tc & BIT(n)))
138a629cf0aSAnirudh Venkataramanan 			break;
139a629cf0aSAnirudh Venkataramanan 
140a629cf0aSAnirudh Venkataramanan 		qoffset = vsi->tc_cfg.tc_info[n].qoffset;
141a629cf0aSAnirudh Venkataramanan 		qcount = vsi->tc_cfg.tc_info[n].qcount_tx;
142a629cf0aSAnirudh Venkataramanan 		for (i = qoffset; i < (qoffset + qcount); i++) {
143a629cf0aSAnirudh Venkataramanan 			tx_ring = vsi->tx_rings[i];
144a629cf0aSAnirudh Venkataramanan 			rx_ring = vsi->rx_rings[i];
145a629cf0aSAnirudh Venkataramanan 			tx_ring->dcb_tc = n;
146a629cf0aSAnirudh Venkataramanan 			rx_ring->dcb_tc = n;
147a629cf0aSAnirudh Venkataramanan 		}
148a629cf0aSAnirudh Venkataramanan 	}
149a629cf0aSAnirudh Venkataramanan }
150a629cf0aSAnirudh Venkataramanan 
151a629cf0aSAnirudh Venkataramanan /**
1527b9ffc76SAnirudh Venkataramanan  * ice_pf_dcb_cfg - Apply new DCB configuration
1537b9ffc76SAnirudh Venkataramanan  * @pf: pointer to the PF struct
1547b9ffc76SAnirudh Venkataramanan  * @new_cfg: DCBX config to apply
155e223eaecSDave Ertman  * @locked: is the RTNL held
1567b9ffc76SAnirudh Venkataramanan  */
157e223eaecSDave Ertman int ice_pf_dcb_cfg(struct ice_pf *pf, struct ice_dcbx_cfg *new_cfg, bool locked)
1587b9ffc76SAnirudh Venkataramanan {
1597b9ffc76SAnirudh Venkataramanan 	struct ice_aqc_port_ets_elem buf = { 0 };
160b94b013eSDave Ertman 	struct ice_dcbx_cfg *old_cfg, *curr_cfg;
1614015d11eSBrett Creeley 	struct device *dev = ice_pf_to_dev(pf);
162b94b013eSDave Ertman 	int ret = ICE_DCB_NO_HW_CHG;
1639d614b64SAnirudh Venkataramanan 	struct ice_vsi *pf_vsi;
1647b9ffc76SAnirudh Venkataramanan 
1657b9ffc76SAnirudh Venkataramanan 	curr_cfg = &pf->hw.port_info->local_dcbx_cfg;
1667b9ffc76SAnirudh Venkataramanan 
167b94b013eSDave Ertman 	/* FW does not care if change happened */
168b94b013eSDave Ertman 	if (!pf->hw.port_info->is_sw_lldp)
169b94b013eSDave Ertman 		ret = ICE_DCB_HW_CHG_RST;
170b94b013eSDave Ertman 
1717b9ffc76SAnirudh Venkataramanan 	/* Enable DCB tagging only when more than one TC */
1727b9ffc76SAnirudh Venkataramanan 	if (ice_dcb_get_num_tc(new_cfg) > 1) {
1734015d11eSBrett Creeley 		dev_dbg(dev, "DCB tagging enabled (num TC > 1)\n");
1747b9ffc76SAnirudh Venkataramanan 		set_bit(ICE_FLAG_DCB_ENA, pf->flags);
1757b9ffc76SAnirudh Venkataramanan 	} else {
1764015d11eSBrett Creeley 		dev_dbg(dev, "DCB tagging disabled (num TC = 1)\n");
1777b9ffc76SAnirudh Venkataramanan 		clear_bit(ICE_FLAG_DCB_ENA, pf->flags);
1787b9ffc76SAnirudh Venkataramanan 	}
1797b9ffc76SAnirudh Venkataramanan 
1807b9ffc76SAnirudh Venkataramanan 	if (!memcmp(new_cfg, curr_cfg, sizeof(*new_cfg))) {
1814015d11eSBrett Creeley 		dev_dbg(dev, "No change in DCB config required\n");
1827b9ffc76SAnirudh Venkataramanan 		return ret;
1837b9ffc76SAnirudh Venkataramanan 	}
1847b9ffc76SAnirudh Venkataramanan 
1857b9ffc76SAnirudh Venkataramanan 	/* Store old config in case FW config fails */
1869d614b64SAnirudh Venkataramanan 	old_cfg = kmemdup(curr_cfg, sizeof(*old_cfg), GFP_KERNEL);
1879d614b64SAnirudh Venkataramanan 	if (!old_cfg)
1889d614b64SAnirudh Venkataramanan 		return -ENOMEM;
1899d614b64SAnirudh Venkataramanan 
1904015d11eSBrett Creeley 	dev_info(dev, "Commit DCB Configuration to the hardware\n");
1919d614b64SAnirudh Venkataramanan 	pf_vsi = ice_get_main_vsi(pf);
1929d614b64SAnirudh Venkataramanan 	if (!pf_vsi) {
1934015d11eSBrett Creeley 		dev_dbg(dev, "PF VSI doesn't exist\n");
1949d614b64SAnirudh Venkataramanan 		ret = -EINVAL;
1959d614b64SAnirudh Venkataramanan 		goto free_cfg;
1969d614b64SAnirudh Venkataramanan 	}
1977b9ffc76SAnirudh Venkataramanan 
1987b9ffc76SAnirudh Venkataramanan 	/* avoid race conditions by holding the lock while disabling and
1997b9ffc76SAnirudh Venkataramanan 	 * re-enabling the VSI
2007b9ffc76SAnirudh Venkataramanan 	 */
201e223eaecSDave Ertman 	if (!locked)
2027b9ffc76SAnirudh Venkataramanan 		rtnl_lock();
2039d614b64SAnirudh Venkataramanan 	ice_dis_vsi(pf_vsi, true);
2047b9ffc76SAnirudh Venkataramanan 
2057b9ffc76SAnirudh Venkataramanan 	memcpy(curr_cfg, new_cfg, sizeof(*curr_cfg));
2067b9ffc76SAnirudh Venkataramanan 	memcpy(&curr_cfg->etsrec, &curr_cfg->etscfg, sizeof(curr_cfg->etsrec));
207b94b013eSDave Ertman 	memcpy(&new_cfg->etsrec, &curr_cfg->etscfg, sizeof(curr_cfg->etsrec));
2087b9ffc76SAnirudh Venkataramanan 
2097b9ffc76SAnirudh Venkataramanan 	/* Only send new config to HW if we are in SW LLDP mode. Otherwise,
2107b9ffc76SAnirudh Venkataramanan 	 * the new config came from the HW in the first place.
2117b9ffc76SAnirudh Venkataramanan 	 */
2127b9ffc76SAnirudh Venkataramanan 	if (pf->hw.port_info->is_sw_lldp) {
2137b9ffc76SAnirudh Venkataramanan 		ret = ice_set_dcb_cfg(pf->hw.port_info);
2147b9ffc76SAnirudh Venkataramanan 		if (ret) {
2154015d11eSBrett Creeley 			dev_err(dev, "Set DCB Config failed\n");
2167b9ffc76SAnirudh Venkataramanan 			/* Restore previous settings to local config */
2177b9ffc76SAnirudh Venkataramanan 			memcpy(curr_cfg, old_cfg, sizeof(*curr_cfg));
2187b9ffc76SAnirudh Venkataramanan 			goto out;
2197b9ffc76SAnirudh Venkataramanan 		}
2207b9ffc76SAnirudh Venkataramanan 	}
2217b9ffc76SAnirudh Venkataramanan 
2227b9ffc76SAnirudh Venkataramanan 	ret = ice_query_port_ets(pf->hw.port_info, &buf, sizeof(buf), NULL);
2237b9ffc76SAnirudh Venkataramanan 	if (ret) {
2244015d11eSBrett Creeley 		dev_err(dev, "Query Port ETS failed\n");
2257b9ffc76SAnirudh Venkataramanan 		goto out;
2267b9ffc76SAnirudh Venkataramanan 	}
2277b9ffc76SAnirudh Venkataramanan 
2287b9ffc76SAnirudh Venkataramanan 	ice_pf_dcb_recfg(pf);
2297b9ffc76SAnirudh Venkataramanan 
2307b9ffc76SAnirudh Venkataramanan out:
2319d614b64SAnirudh Venkataramanan 	ice_ena_vsi(pf_vsi, true);
232e223eaecSDave Ertman 	if (!locked)
2337b9ffc76SAnirudh Venkataramanan 		rtnl_unlock();
2349d614b64SAnirudh Venkataramanan free_cfg:
2359d614b64SAnirudh Venkataramanan 	kfree(old_cfg);
2367b9ffc76SAnirudh Venkataramanan 	return ret;
2377b9ffc76SAnirudh Venkataramanan }
2387b9ffc76SAnirudh Venkataramanan 
2397b9ffc76SAnirudh Venkataramanan /**
2407829570eSUsha Ketineni  * ice_cfg_etsrec_defaults - Set default ETS recommended DCB config
2417829570eSUsha Ketineni  * @pi: port information structure
2427829570eSUsha Ketineni  */
2437829570eSUsha Ketineni static void ice_cfg_etsrec_defaults(struct ice_port_info *pi)
2447829570eSUsha Ketineni {
2457829570eSUsha Ketineni 	struct ice_dcbx_cfg *dcbcfg = &pi->local_dcbx_cfg;
2467829570eSUsha Ketineni 	u8 i;
2477829570eSUsha Ketineni 
2487829570eSUsha Ketineni 	/* Ensure ETS recommended DCB configuration is not already set */
2497829570eSUsha Ketineni 	if (dcbcfg->etsrec.maxtcs)
2507829570eSUsha Ketineni 		return;
2517829570eSUsha Ketineni 
2527829570eSUsha Ketineni 	/* In CEE mode, set the default to 1 TC */
2537829570eSUsha Ketineni 	dcbcfg->etsrec.maxtcs = 1;
2547829570eSUsha Ketineni 	for (i = 0; i < ICE_MAX_TRAFFIC_CLASS; i++) {
2557829570eSUsha Ketineni 		dcbcfg->etsrec.tcbwtable[i] = i ? 0 : 100;
2567829570eSUsha Ketineni 		dcbcfg->etsrec.tsatable[i] = i ? ICE_IEEE_TSA_STRICT :
2577829570eSUsha Ketineni 						 ICE_IEEE_TSA_ETS;
2587829570eSUsha Ketineni 	}
2597829570eSUsha Ketineni }
2607829570eSUsha Ketineni 
2617829570eSUsha Ketineni /**
2627829570eSUsha Ketineni  * ice_dcb_need_recfg - Check if DCB needs reconfig
2637829570eSUsha Ketineni  * @pf: board private structure
2647829570eSUsha Ketineni  * @old_cfg: current DCB config
2657829570eSUsha Ketineni  * @new_cfg: new DCB config
2667829570eSUsha Ketineni  */
2677829570eSUsha Ketineni static bool
2687829570eSUsha Ketineni ice_dcb_need_recfg(struct ice_pf *pf, struct ice_dcbx_cfg *old_cfg,
2697829570eSUsha Ketineni 		   struct ice_dcbx_cfg *new_cfg)
2707829570eSUsha Ketineni {
2714015d11eSBrett Creeley 	struct device *dev = ice_pf_to_dev(pf);
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;
2824015d11eSBrett Creeley 			dev_dbg(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)))
2884015d11eSBrett Creeley 			dev_dbg(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)))
2934015d11eSBrett Creeley 			dev_dbg(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;
2994015d11eSBrett Creeley 		dev_dbg(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;
3054015d11eSBrett Creeley 		dev_dbg(dev, "APP Table change detected.\n");
3067829570eSUsha Ketineni 	}
3077829570eSUsha Ketineni 
3084015d11eSBrett Creeley 	dev_dbg(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 };
3204015d11eSBrett Creeley 	struct device *dev = ice_pf_to_dev(pf);
321b832c2f6SAnirudh Venkataramanan 	enum ice_status ret;
322b832c2f6SAnirudh Venkataramanan 
323b832c2f6SAnirudh Venkataramanan 	ret = ice_query_port_ets(pf->hw.port_info, &buf, sizeof(buf), NULL);
324b832c2f6SAnirudh Venkataramanan 	if (ret) {
3254015d11eSBrett Creeley 		dev_err(dev, "Query Port ETS failed\n");
326b832c2f6SAnirudh Venkataramanan 		goto dcb_error;
327b832c2f6SAnirudh Venkataramanan 	}
328b832c2f6SAnirudh Venkataramanan 
329b832c2f6SAnirudh Venkataramanan 	/* If DCB was not enabled previously, we are done */
330b832c2f6SAnirudh Venkataramanan 	if (!test_bit(ICE_FLAG_DCB_ENA, pf->flags))
331b832c2f6SAnirudh Venkataramanan 		return;
332b832c2f6SAnirudh Venkataramanan 
3337829570eSUsha Ketineni 	local_dcbx_cfg = &pf->hw.port_info->local_dcbx_cfg;
3347829570eSUsha Ketineni 	desired_dcbx_cfg = &pf->hw.port_info->desired_dcbx_cfg;
3357829570eSUsha Ketineni 
336b832c2f6SAnirudh Venkataramanan 	/* Save current willing state and force FW to unwilling */
3377829570eSUsha Ketineni 	local_dcbx_cfg->etscfg.willing = 0x0;
3387829570eSUsha Ketineni 	local_dcbx_cfg->pfc.willing = 0x0;
3397829570eSUsha Ketineni 	local_dcbx_cfg->app_mode = ICE_DCBX_APPS_NON_WILLING;
3407829570eSUsha Ketineni 
3417829570eSUsha Ketineni 	ice_cfg_etsrec_defaults(pf->hw.port_info);
342b832c2f6SAnirudh Venkataramanan 	ret = ice_set_dcb_cfg(pf->hw.port_info);
343b832c2f6SAnirudh Venkataramanan 	if (ret) {
3444015d11eSBrett Creeley 		dev_err(dev, "Failed to set DCB to unwilling\n");
345b832c2f6SAnirudh Venkataramanan 		goto dcb_error;
346b832c2f6SAnirudh Venkataramanan 	}
347b832c2f6SAnirudh Venkataramanan 
348b832c2f6SAnirudh Venkataramanan 	/* Retrieve DCB config and ensure same as current in SW */
3499efe35d0STony Nguyen 	prev_cfg = kmemdup(local_dcbx_cfg, sizeof(*prev_cfg), GFP_KERNEL);
3504015d11eSBrett Creeley 	if (!prev_cfg)
351b832c2f6SAnirudh Venkataramanan 		goto dcb_error;
352b832c2f6SAnirudh Venkataramanan 
353ea300f41SDave Ertman 	ice_init_dcb(&pf->hw, true);
3541b0c3247SDave Ertman 	if (pf->hw.port_info->dcbx_status == ICE_DCBX_STATUS_DIS)
3551b0c3247SDave Ertman 		pf->hw.port_info->is_sw_lldp = true;
3561b0c3247SDave Ertman 	else
3571b0c3247SDave Ertman 		pf->hw.port_info->is_sw_lldp = false;
3581b0c3247SDave Ertman 
3597829570eSUsha Ketineni 	if (ice_dcb_need_recfg(pf, prev_cfg, local_dcbx_cfg)) {
360b832c2f6SAnirudh Venkataramanan 		/* difference in cfg detected - disable DCB till next MIB */
3614015d11eSBrett Creeley 		dev_err(dev, "Set local MIB not accurate\n");
3629efe35d0STony Nguyen 		kfree(prev_cfg);
363b832c2f6SAnirudh Venkataramanan 		goto dcb_error;
364b832c2f6SAnirudh Venkataramanan 	}
365b832c2f6SAnirudh Venkataramanan 
366b832c2f6SAnirudh Venkataramanan 	/* fetched config congruent to previous configuration */
3679efe35d0STony Nguyen 	kfree(prev_cfg);
368b832c2f6SAnirudh Venkataramanan 
3697829570eSUsha Ketineni 	/* Set the local desired config */
37042a179c8SMichal Swiatkowski 	if (local_dcbx_cfg->dcbx_mode == ICE_DCBX_MODE_CEE)
37142a179c8SMichal Swiatkowski 		memcpy(local_dcbx_cfg, desired_dcbx_cfg,
37242a179c8SMichal Swiatkowski 		       sizeof(*local_dcbx_cfg));
37342a179c8SMichal Swiatkowski 
3747829570eSUsha Ketineni 	ice_cfg_etsrec_defaults(pf->hw.port_info);
375b832c2f6SAnirudh Venkataramanan 	ret = ice_set_dcb_cfg(pf->hw.port_info);
376b832c2f6SAnirudh Venkataramanan 	if (ret) {
3774015d11eSBrett Creeley 		dev_err(dev, "Failed to set desired config\n");
378b832c2f6SAnirudh Venkataramanan 		goto dcb_error;
379b832c2f6SAnirudh Venkataramanan 	}
3804015d11eSBrett Creeley 	dev_info(dev, "DCB restored after reset\n");
381b832c2f6SAnirudh Venkataramanan 	ret = ice_query_port_ets(pf->hw.port_info, &buf, sizeof(buf), NULL);
382b832c2f6SAnirudh Venkataramanan 	if (ret) {
3834015d11eSBrett Creeley 		dev_err(dev, "Query Port ETS failed\n");
384b832c2f6SAnirudh Venkataramanan 		goto dcb_error;
385b832c2f6SAnirudh Venkataramanan 	}
386b832c2f6SAnirudh Venkataramanan 
387b832c2f6SAnirudh Venkataramanan 	return;
388b832c2f6SAnirudh Venkataramanan 
389b832c2f6SAnirudh Venkataramanan dcb_error:
3904015d11eSBrett Creeley 	dev_err(dev, "Disabling DCB until new settings occur\n");
3919efe35d0STony Nguyen 	prev_cfg = kzalloc(sizeof(*prev_cfg), GFP_KERNEL);
3929efe35d0STony Nguyen 	if (!prev_cfg)
3939efe35d0STony Nguyen 		return;
3949efe35d0STony Nguyen 
395b832c2f6SAnirudh Venkataramanan 	prev_cfg->etscfg.willing = true;
396b832c2f6SAnirudh Venkataramanan 	prev_cfg->etscfg.tcbwtable[0] = ICE_TC_MAX_BW;
397b832c2f6SAnirudh Venkataramanan 	prev_cfg->etscfg.tsatable[0] = ICE_IEEE_TSA_ETS;
398b832c2f6SAnirudh Venkataramanan 	memcpy(&prev_cfg->etsrec, &prev_cfg->etscfg, sizeof(prev_cfg->etsrec));
399e223eaecSDave Ertman 	ice_pf_dcb_cfg(pf, prev_cfg, false);
4009efe35d0STony Nguyen 	kfree(prev_cfg);
401b832c2f6SAnirudh Venkataramanan }
402b832c2f6SAnirudh Venkataramanan 
403b832c2f6SAnirudh Venkataramanan /**
4047b9ffc76SAnirudh Venkataramanan  * ice_dcb_init_cfg - set the initial DCB config in SW
4052f2da36eSAnirudh Venkataramanan  * @pf: PF to apply config to
406e223eaecSDave Ertman  * @locked: Is the RTNL held
4077b9ffc76SAnirudh Venkataramanan  */
408e223eaecSDave Ertman static int ice_dcb_init_cfg(struct ice_pf *pf, bool locked)
4097b9ffc76SAnirudh Venkataramanan {
4107b9ffc76SAnirudh Venkataramanan 	struct ice_dcbx_cfg *newcfg;
4117b9ffc76SAnirudh Venkataramanan 	struct ice_port_info *pi;
4127b9ffc76SAnirudh Venkataramanan 	int ret = 0;
4137b9ffc76SAnirudh Venkataramanan 
4147b9ffc76SAnirudh Venkataramanan 	pi = pf->hw.port_info;
4159efe35d0STony Nguyen 	newcfg = kmemdup(&pi->local_dcbx_cfg, sizeof(*newcfg), GFP_KERNEL);
4167b9ffc76SAnirudh Venkataramanan 	if (!newcfg)
4177b9ffc76SAnirudh Venkataramanan 		return -ENOMEM;
4187b9ffc76SAnirudh Venkataramanan 
4197b9ffc76SAnirudh Venkataramanan 	memset(&pi->local_dcbx_cfg, 0, sizeof(*newcfg));
4207b9ffc76SAnirudh Venkataramanan 
4214015d11eSBrett Creeley 	dev_info(ice_pf_to_dev(pf), "Configuring initial DCB values\n");
422e223eaecSDave Ertman 	if (ice_pf_dcb_cfg(pf, newcfg, locked))
4237b9ffc76SAnirudh Venkataramanan 		ret = -EINVAL;
4247b9ffc76SAnirudh Venkataramanan 
4259efe35d0STony Nguyen 	kfree(newcfg);
4267b9ffc76SAnirudh Venkataramanan 
4277b9ffc76SAnirudh Venkataramanan 	return ret;
4287b9ffc76SAnirudh Venkataramanan }
4297b9ffc76SAnirudh Venkataramanan 
4307b9ffc76SAnirudh Venkataramanan /**
4310deab659SAnirudh Venkataramanan  * ice_dcb_sw_default_config - Apply a default DCB config
4322f2da36eSAnirudh Venkataramanan  * @pf: PF to apply config to
433cfbf1367SPaul Greenwalt  * @ets_willing: configure ets willing
434e223eaecSDave Ertman  * @locked: was this function called with RTNL held
4350deab659SAnirudh Venkataramanan  */
436cfbf1367SPaul Greenwalt static int ice_dcb_sw_dflt_cfg(struct ice_pf *pf, bool ets_willing, bool locked)
4370deab659SAnirudh Venkataramanan {
4380deab659SAnirudh Venkataramanan 	struct ice_aqc_port_ets_elem buf = { 0 };
4390deab659SAnirudh Venkataramanan 	struct ice_dcbx_cfg *dcbcfg;
4400deab659SAnirudh Venkataramanan 	struct ice_port_info *pi;
4410deab659SAnirudh Venkataramanan 	struct ice_hw *hw;
4420deab659SAnirudh Venkataramanan 	int ret;
4430deab659SAnirudh Venkataramanan 
4440deab659SAnirudh Venkataramanan 	hw = &pf->hw;
4450deab659SAnirudh Venkataramanan 	pi = hw->port_info;
4469efe35d0STony Nguyen 	dcbcfg = kzalloc(sizeof(*dcbcfg), GFP_KERNEL);
4479efe35d0STony Nguyen 	if (!dcbcfg)
4489efe35d0STony Nguyen 		return -ENOMEM;
4490deab659SAnirudh Venkataramanan 
4500deab659SAnirudh Venkataramanan 	memset(&pi->local_dcbx_cfg, 0, sizeof(*dcbcfg));
4510deab659SAnirudh Venkataramanan 
452cfbf1367SPaul Greenwalt 	dcbcfg->etscfg.willing = ets_willing ? 1 : 0;
453a257f188SUsha Ketineni 	dcbcfg->etscfg.maxtcs = hw->func_caps.common_cap.maxtc;
4540deab659SAnirudh Venkataramanan 	dcbcfg->etscfg.tcbwtable[0] = 100;
4550deab659SAnirudh Venkataramanan 	dcbcfg->etscfg.tsatable[0] = ICE_IEEE_TSA_ETS;
4560deab659SAnirudh Venkataramanan 
4570deab659SAnirudh Venkataramanan 	memcpy(&dcbcfg->etsrec, &dcbcfg->etscfg,
4580deab659SAnirudh Venkataramanan 	       sizeof(dcbcfg->etsrec));
4590deab659SAnirudh Venkataramanan 	dcbcfg->etsrec.willing = 0;
4600deab659SAnirudh Venkataramanan 
4610deab659SAnirudh Venkataramanan 	dcbcfg->pfc.willing = 1;
462a257f188SUsha Ketineni 	dcbcfg->pfc.pfccap = hw->func_caps.common_cap.maxtc;
4630deab659SAnirudh Venkataramanan 
4640deab659SAnirudh Venkataramanan 	dcbcfg->numapps = 1;
4650deab659SAnirudh Venkataramanan 	dcbcfg->app[0].selector = ICE_APP_SEL_ETHTYPE;
4660deab659SAnirudh Venkataramanan 	dcbcfg->app[0].priority = 3;
4670deab659SAnirudh Venkataramanan 	dcbcfg->app[0].prot_id = ICE_APP_PROT_ID_FCOE;
4680deab659SAnirudh Venkataramanan 
469e223eaecSDave Ertman 	ret = ice_pf_dcb_cfg(pf, dcbcfg, locked);
4709efe35d0STony Nguyen 	kfree(dcbcfg);
4710deab659SAnirudh Venkataramanan 	if (ret)
4720deab659SAnirudh Venkataramanan 		return ret;
4730deab659SAnirudh Venkataramanan 
4740deab659SAnirudh Venkataramanan 	return ice_query_port_ets(pi, &buf, sizeof(buf), NULL);
4750deab659SAnirudh Venkataramanan }
4760deab659SAnirudh Venkataramanan 
4770deab659SAnirudh Venkataramanan /**
478cfbf1367SPaul Greenwalt  * ice_dcb_tc_contig - Check that TCs are contiguous
479cfbf1367SPaul Greenwalt  * @prio_table: pointer to priority table
480cfbf1367SPaul Greenwalt  *
481cfbf1367SPaul Greenwalt  * Check if TCs begin with TC0 and are contiguous
482cfbf1367SPaul Greenwalt  */
483cfbf1367SPaul Greenwalt static bool ice_dcb_tc_contig(u8 *prio_table)
484cfbf1367SPaul Greenwalt {
485cfbf1367SPaul Greenwalt 	u8 max_tc = 0;
486cfbf1367SPaul Greenwalt 	int i;
487cfbf1367SPaul Greenwalt 
488cfbf1367SPaul Greenwalt 	for (i = 0; i < CEE_DCBX_MAX_PRIO; i++) {
489cfbf1367SPaul Greenwalt 		u8 cur_tc = prio_table[i];
490cfbf1367SPaul Greenwalt 
491cfbf1367SPaul Greenwalt 		if (cur_tc > max_tc)
492cfbf1367SPaul Greenwalt 			return false;
493cfbf1367SPaul Greenwalt 		else if (cur_tc == max_tc)
494cfbf1367SPaul Greenwalt 			max_tc++;
495cfbf1367SPaul Greenwalt 	}
496cfbf1367SPaul Greenwalt 
497cfbf1367SPaul Greenwalt 	return true;
498cfbf1367SPaul Greenwalt }
499cfbf1367SPaul Greenwalt 
500cfbf1367SPaul Greenwalt /**
501cfbf1367SPaul Greenwalt  * ice_dcb_noncontig_cfg - Configure DCB for non-contiguous TCs
502cfbf1367SPaul Greenwalt  * @pf: pointer to the PF struct
503cfbf1367SPaul Greenwalt  *
504cfbf1367SPaul Greenwalt  * If non-contiguous TCs, then configure SW DCB with TC0 and ETS non-willing
505cfbf1367SPaul Greenwalt  */
506cfbf1367SPaul Greenwalt static int ice_dcb_noncontig_cfg(struct ice_pf *pf)
507cfbf1367SPaul Greenwalt {
508cfbf1367SPaul Greenwalt 	struct ice_dcbx_cfg *dcbcfg = &pf->hw.port_info->local_dcbx_cfg;
5094015d11eSBrett Creeley 	struct device *dev = ice_pf_to_dev(pf);
510cfbf1367SPaul Greenwalt 	int ret;
511cfbf1367SPaul Greenwalt 
512cfbf1367SPaul Greenwalt 	/* Configure SW DCB default with ETS non-willing */
513cfbf1367SPaul Greenwalt 	ret = ice_dcb_sw_dflt_cfg(pf, false, true);
514cfbf1367SPaul Greenwalt 	if (ret) {
5154015d11eSBrett Creeley 		dev_err(dev, "Failed to set local DCB config %d\n", ret);
516cfbf1367SPaul Greenwalt 		return ret;
517cfbf1367SPaul Greenwalt 	}
518cfbf1367SPaul Greenwalt 
519cfbf1367SPaul Greenwalt 	/* Reconfigure with ETS willing so that FW will send LLDP MIB event */
520cfbf1367SPaul Greenwalt 	dcbcfg->etscfg.willing = 1;
521cfbf1367SPaul Greenwalt 	ret = ice_set_dcb_cfg(pf->hw.port_info);
522cfbf1367SPaul Greenwalt 	if (ret)
5234015d11eSBrett Creeley 		dev_err(dev, "Failed to set DCB to unwilling\n");
524cfbf1367SPaul Greenwalt 
525cfbf1367SPaul Greenwalt 	return ret;
526cfbf1367SPaul Greenwalt }
527cfbf1367SPaul Greenwalt 
528cfbf1367SPaul Greenwalt /**
529cfbf1367SPaul Greenwalt  * ice_pf_dcb_recfg - Reconfigure all VEBs and VSIs
530cfbf1367SPaul Greenwalt  * @pf: pointer to the PF struct
531cfbf1367SPaul Greenwalt  *
532cfbf1367SPaul Greenwalt  * Assumed caller has already disabled all VSIs before
533cfbf1367SPaul Greenwalt  * calling this function. Reconfiguring DCB based on
534cfbf1367SPaul Greenwalt  * local_dcbx_cfg.
535cfbf1367SPaul Greenwalt  */
53687324e74SHenry Tieman void ice_pf_dcb_recfg(struct ice_pf *pf)
537cfbf1367SPaul Greenwalt {
538cfbf1367SPaul Greenwalt 	struct ice_dcbx_cfg *dcbcfg = &pf->hw.port_info->local_dcbx_cfg;
539cfbf1367SPaul Greenwalt 	u8 tc_map = 0;
540cfbf1367SPaul Greenwalt 	int v, ret;
541cfbf1367SPaul Greenwalt 
542cfbf1367SPaul Greenwalt 	/* Update each VSI */
543cfbf1367SPaul Greenwalt 	ice_for_each_vsi(pf, v) {
5444015d11eSBrett Creeley 		struct ice_vsi *vsi = pf->vsi[v];
5454015d11eSBrett Creeley 
5464015d11eSBrett Creeley 		if (!vsi)
547cfbf1367SPaul Greenwalt 			continue;
548cfbf1367SPaul Greenwalt 
5494015d11eSBrett Creeley 		if (vsi->type == ICE_VSI_PF) {
550cfbf1367SPaul Greenwalt 			tc_map = ice_dcb_get_ena_tc(dcbcfg);
551cfbf1367SPaul Greenwalt 
552cfbf1367SPaul Greenwalt 			/* If DCBX request non-contiguous TC, then configure
553cfbf1367SPaul Greenwalt 			 * default TC
554cfbf1367SPaul Greenwalt 			 */
555cfbf1367SPaul Greenwalt 			if (!ice_dcb_tc_contig(dcbcfg->etscfg.prio_table)) {
556cfbf1367SPaul Greenwalt 				tc_map = ICE_DFLT_TRAFFIC_CLASS;
557cfbf1367SPaul Greenwalt 				ice_dcb_noncontig_cfg(pf);
558cfbf1367SPaul Greenwalt 			}
559cfbf1367SPaul Greenwalt 		} else {
560cfbf1367SPaul Greenwalt 			tc_map = ICE_DFLT_TRAFFIC_CLASS;
561cfbf1367SPaul Greenwalt 		}
562cfbf1367SPaul Greenwalt 
5634015d11eSBrett Creeley 		ret = ice_vsi_cfg_tc(vsi, tc_map);
564cfbf1367SPaul Greenwalt 		if (ret) {
5654015d11eSBrett Creeley 			dev_err(ice_pf_to_dev(pf), "Failed to config TC for VSI index: %d\n",
5664015d11eSBrett Creeley 				vsi->idx);
567cfbf1367SPaul Greenwalt 			continue;
568cfbf1367SPaul Greenwalt 		}
569cfbf1367SPaul Greenwalt 
5704015d11eSBrett Creeley 		ice_vsi_map_rings_to_vectors(vsi);
5714015d11eSBrett Creeley 		if (vsi->type == ICE_VSI_PF)
5724015d11eSBrett Creeley 			ice_dcbnl_set_all(vsi);
573cfbf1367SPaul Greenwalt 	}
574cfbf1367SPaul Greenwalt }
575cfbf1367SPaul Greenwalt 
576cfbf1367SPaul Greenwalt /**
57737b6f646SAnirudh Venkataramanan  * ice_init_pf_dcb - initialize DCB for a PF
5782f2da36eSAnirudh Venkataramanan  * @pf: PF to initialize DCB for
579e223eaecSDave Ertman  * @locked: Was function called with RTNL held
58037b6f646SAnirudh Venkataramanan  */
581e223eaecSDave Ertman int ice_init_pf_dcb(struct ice_pf *pf, bool locked)
58237b6f646SAnirudh Venkataramanan {
5834015d11eSBrett Creeley 	struct device *dev = ice_pf_to_dev(pf);
58437b6f646SAnirudh Venkataramanan 	struct ice_port_info *port_info;
58537b6f646SAnirudh Venkataramanan 	struct ice_hw *hw = &pf->hw;
5867b9ffc76SAnirudh Venkataramanan 	int err;
58737b6f646SAnirudh Venkataramanan 
58837b6f646SAnirudh Venkataramanan 	port_info = hw->port_info;
58937b6f646SAnirudh Venkataramanan 
590ea300f41SDave Ertman 	err = ice_init_dcb(hw, false);
591473ca574SDave Ertman 	if (err && !port_info->is_sw_lldp) {
5924015d11eSBrett Creeley 		dev_err(dev, "Error initializing DCB %d\n", err);
593473ca574SDave Ertman 		goto dcb_init_err;
594473ca574SDave Ertman 	}
595473ca574SDave Ertman 
5964015d11eSBrett Creeley 	dev_info(dev,
597a257f188SUsha Ketineni 		 "DCB is enabled in the hardware, max number of TCs supported on this port are %d\n",
598a257f188SUsha Ketineni 		 pf->hw.func_caps.common_cap.maxtc);
599473ca574SDave Ertman 	if (err) {
600241c8cf0SPaul Greenwalt 		struct ice_vsi *pf_vsi;
601241c8cf0SPaul Greenwalt 
602473ca574SDave Ertman 		/* FW LLDP is disabled, activate SW DCBX/LLDP mode */
6034015d11eSBrett Creeley 		dev_info(dev, "FW LLDP is disabled, DCBx/LLDP in SW mode.\n");
60484a118abSDave Ertman 		clear_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags);
605cfbf1367SPaul Greenwalt 		err = ice_dcb_sw_dflt_cfg(pf, true, locked);
6060deab659SAnirudh Venkataramanan 		if (err) {
6074015d11eSBrett Creeley 			dev_err(dev,
6080deab659SAnirudh Venkataramanan 				"Failed to set local DCB config %d\n", err);
6090deab659SAnirudh Venkataramanan 			err = -EIO;
6107b9ffc76SAnirudh Venkataramanan 			goto dcb_init_err;
6110deab659SAnirudh Venkataramanan 		}
6120deab659SAnirudh Venkataramanan 
613241c8cf0SPaul Greenwalt 		/* If the FW DCBX engine is not running then Rx LLDP packets
614241c8cf0SPaul Greenwalt 		 * need to be redirected up the stack.
615241c8cf0SPaul Greenwalt 		 */
616241c8cf0SPaul Greenwalt 		pf_vsi = ice_get_main_vsi(pf);
617241c8cf0SPaul Greenwalt 		if (!pf_vsi) {
6184015d11eSBrett Creeley 			dev_err(dev, "Failed to set local DCB config\n");
619241c8cf0SPaul Greenwalt 			err = -EIO;
620241c8cf0SPaul Greenwalt 			goto dcb_init_err;
621241c8cf0SPaul Greenwalt 		}
622241c8cf0SPaul Greenwalt 
623241c8cf0SPaul Greenwalt 		ice_cfg_sw_lldp(pf_vsi, false, true);
624241c8cf0SPaul Greenwalt 
6250deab659SAnirudh Venkataramanan 		pf->dcbx_cap = DCB_CAP_DCBX_HOST | DCB_CAP_DCBX_VER_IEEE;
6260deab659SAnirudh Venkataramanan 		return 0;
6270deab659SAnirudh Venkataramanan 	}
6287b9ffc76SAnirudh Venkataramanan 
62984a118abSDave Ertman 	set_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags);
6301b0c3247SDave Ertman 
6317b9ffc76SAnirudh Venkataramanan 	/* DCBX in FW and LLDP enabled in FW */
6327b9ffc76SAnirudh Venkataramanan 	pf->dcbx_cap = DCB_CAP_DCBX_LLD_MANAGED | DCB_CAP_DCBX_VER_IEEE;
6337b9ffc76SAnirudh Venkataramanan 
634e223eaecSDave Ertman 	err = ice_dcb_init_cfg(pf, locked);
6357b9ffc76SAnirudh Venkataramanan 	if (err)
6367b9ffc76SAnirudh Venkataramanan 		goto dcb_init_err;
6377b9ffc76SAnirudh Venkataramanan 
6387b9ffc76SAnirudh Venkataramanan 	return err;
6397b9ffc76SAnirudh Venkataramanan 
6407b9ffc76SAnirudh Venkataramanan dcb_init_err:
6417b9ffc76SAnirudh Venkataramanan 	dev_err(dev, "DCB init failed\n");
6427b9ffc76SAnirudh Venkataramanan 	return err;
64337b6f646SAnirudh Venkataramanan }
64400cc3f1bSAnirudh Venkataramanan 
64500cc3f1bSAnirudh Venkataramanan /**
6464b0fdcebSAnirudh Venkataramanan  * ice_update_dcb_stats - Update DCB stats counters
6474b0fdcebSAnirudh Venkataramanan  * @pf: PF whose stats needs to be updated
6484b0fdcebSAnirudh Venkataramanan  */
6494b0fdcebSAnirudh Venkataramanan void ice_update_dcb_stats(struct ice_pf *pf)
6504b0fdcebSAnirudh Venkataramanan {
6514b0fdcebSAnirudh Venkataramanan 	struct ice_hw_port_stats *prev_ps, *cur_ps;
6524b0fdcebSAnirudh Venkataramanan 	struct ice_hw *hw = &pf->hw;
6539e7a5d17SUsha Ketineni 	u8 port;
6544b0fdcebSAnirudh Venkataramanan 	int i;
6554b0fdcebSAnirudh Venkataramanan 
6569e7a5d17SUsha Ketineni 	port = hw->port_info->lport;
6574b0fdcebSAnirudh Venkataramanan 	prev_ps = &pf->stats_prev;
6584b0fdcebSAnirudh Venkataramanan 	cur_ps = &pf->stats;
6594b0fdcebSAnirudh Venkataramanan 
6604b0fdcebSAnirudh Venkataramanan 	for (i = 0; i < 8; i++) {
6619e7a5d17SUsha Ketineni 		ice_stat_update32(hw, GLPRT_PXOFFRXC(port, i),
6624b0fdcebSAnirudh Venkataramanan 				  pf->stat_prev_loaded,
6634b0fdcebSAnirudh Venkataramanan 				  &prev_ps->priority_xoff_rx[i],
6644b0fdcebSAnirudh Venkataramanan 				  &cur_ps->priority_xoff_rx[i]);
6659e7a5d17SUsha Ketineni 		ice_stat_update32(hw, GLPRT_PXONRXC(port, i),
6664b0fdcebSAnirudh Venkataramanan 				  pf->stat_prev_loaded,
6674b0fdcebSAnirudh Venkataramanan 				  &prev_ps->priority_xon_rx[i],
6684b0fdcebSAnirudh Venkataramanan 				  &cur_ps->priority_xon_rx[i]);
6699e7a5d17SUsha Ketineni 		ice_stat_update32(hw, GLPRT_PXONTXC(port, i),
6704b0fdcebSAnirudh Venkataramanan 				  pf->stat_prev_loaded,
6714b0fdcebSAnirudh Venkataramanan 				  &prev_ps->priority_xon_tx[i],
6724b0fdcebSAnirudh Venkataramanan 				  &cur_ps->priority_xon_tx[i]);
6739e7a5d17SUsha Ketineni 		ice_stat_update32(hw, GLPRT_PXOFFTXC(port, i),
6744b0fdcebSAnirudh Venkataramanan 				  pf->stat_prev_loaded,
6754b0fdcebSAnirudh Venkataramanan 				  &prev_ps->priority_xoff_tx[i],
6764b0fdcebSAnirudh Venkataramanan 				  &cur_ps->priority_xoff_tx[i]);
6779e7a5d17SUsha Ketineni 		ice_stat_update32(hw, GLPRT_RXON2OFFCNT(port, i),
6784b0fdcebSAnirudh Venkataramanan 				  pf->stat_prev_loaded,
6794b0fdcebSAnirudh Venkataramanan 				  &prev_ps->priority_xon_2_xoff[i],
6804b0fdcebSAnirudh Venkataramanan 				  &cur_ps->priority_xon_2_xoff[i]);
6814b0fdcebSAnirudh Venkataramanan 	}
6824b0fdcebSAnirudh Venkataramanan }
6834b0fdcebSAnirudh Venkataramanan 
6844b0fdcebSAnirudh Venkataramanan /**
6855f6aa50eSAnirudh Venkataramanan  * ice_tx_prepare_vlan_flags_dcb - prepare VLAN tagging for DCB
6865f6aa50eSAnirudh Venkataramanan  * @tx_ring: ring to send buffer on
6875f6aa50eSAnirudh Venkataramanan  * @first: pointer to struct ice_tx_buf
6885f6aa50eSAnirudh Venkataramanan  */
6895f6aa50eSAnirudh Venkataramanan int
6905f6aa50eSAnirudh Venkataramanan ice_tx_prepare_vlan_flags_dcb(struct ice_ring *tx_ring,
6915f6aa50eSAnirudh Venkataramanan 			      struct ice_tx_buf *first)
6925f6aa50eSAnirudh Venkataramanan {
6935f6aa50eSAnirudh Venkataramanan 	struct sk_buff *skb = first->skb;
6945f6aa50eSAnirudh Venkataramanan 
6955f6aa50eSAnirudh Venkataramanan 	if (!test_bit(ICE_FLAG_DCB_ENA, tx_ring->vsi->back->flags))
6965f6aa50eSAnirudh Venkataramanan 		return 0;
6975f6aa50eSAnirudh Venkataramanan 
6985f6aa50eSAnirudh Venkataramanan 	/* Insert 802.1p priority into VLAN header */
6995f6aa50eSAnirudh Venkataramanan 	if ((first->tx_flags & (ICE_TX_FLAGS_HW_VLAN | ICE_TX_FLAGS_SW_VLAN)) ||
7005f6aa50eSAnirudh Venkataramanan 	    skb->priority != TC_PRIO_CONTROL) {
7015f6aa50eSAnirudh Venkataramanan 		first->tx_flags &= ~ICE_TX_FLAGS_VLAN_PR_M;
7025f6aa50eSAnirudh Venkataramanan 		/* Mask the lower 3 bits to set the 802.1p priority */
7035f6aa50eSAnirudh Venkataramanan 		first->tx_flags |= (skb->priority & 0x7) <<
7045f6aa50eSAnirudh Venkataramanan 				   ICE_TX_FLAGS_VLAN_PR_S;
7055f6aa50eSAnirudh Venkataramanan 		if (first->tx_flags & ICE_TX_FLAGS_SW_VLAN) {
7065f6aa50eSAnirudh Venkataramanan 			struct vlan_ethhdr *vhdr;
7075f6aa50eSAnirudh Venkataramanan 			int rc;
7085f6aa50eSAnirudh Venkataramanan 
7095f6aa50eSAnirudh Venkataramanan 			rc = skb_cow_head(skb, 0);
7105f6aa50eSAnirudh Venkataramanan 			if (rc < 0)
7115f6aa50eSAnirudh Venkataramanan 				return rc;
7125f6aa50eSAnirudh Venkataramanan 			vhdr = (struct vlan_ethhdr *)skb->data;
7135f6aa50eSAnirudh Venkataramanan 			vhdr->h_vlan_TCI = htons(first->tx_flags >>
7145f6aa50eSAnirudh Venkataramanan 						 ICE_TX_FLAGS_VLAN_S);
7155f6aa50eSAnirudh Venkataramanan 		} else {
7165f6aa50eSAnirudh Venkataramanan 			first->tx_flags |= ICE_TX_FLAGS_HW_VLAN;
7175f6aa50eSAnirudh Venkataramanan 		}
7185f6aa50eSAnirudh Venkataramanan 	}
7195f6aa50eSAnirudh Venkataramanan 
7205f6aa50eSAnirudh Venkataramanan 	return 0;
7215f6aa50eSAnirudh Venkataramanan }
7225f6aa50eSAnirudh Venkataramanan 
7235f6aa50eSAnirudh Venkataramanan /**
72400cc3f1bSAnirudh Venkataramanan  * ice_dcb_process_lldp_set_mib_change - Process MIB change
72500cc3f1bSAnirudh Venkataramanan  * @pf: ptr to ice_pf
72600cc3f1bSAnirudh Venkataramanan  * @event: pointer to the admin queue receive event
72700cc3f1bSAnirudh Venkataramanan  */
72800cc3f1bSAnirudh Venkataramanan void
72900cc3f1bSAnirudh Venkataramanan ice_dcb_process_lldp_set_mib_change(struct ice_pf *pf,
73000cc3f1bSAnirudh Venkataramanan 				    struct ice_rq_event_info *event)
73100cc3f1bSAnirudh Venkataramanan {
732a17a5ff6SUsha Ketineni 	struct ice_aqc_port_ets_elem buf = { 0 };
7334015d11eSBrett Creeley 	struct device *dev = ice_pf_to_dev(pf);
734a17a5ff6SUsha Ketineni 	struct ice_aqc_lldp_get_mib *mib;
735a17a5ff6SUsha Ketineni 	struct ice_dcbx_cfg tmp_dcbx_cfg;
736a17a5ff6SUsha Ketineni 	bool need_reconfig = false;
737a17a5ff6SUsha Ketineni 	struct ice_port_info *pi;
7389d614b64SAnirudh Venkataramanan 	struct ice_vsi *pf_vsi;
739a17a5ff6SUsha Ketineni 	u8 type;
740a17a5ff6SUsha Ketineni 	int ret;
74100cc3f1bSAnirudh Venkataramanan 
742a17a5ff6SUsha Ketineni 	/* Not DCB capable or capability disabled */
743a17a5ff6SUsha Ketineni 	if (!(test_bit(ICE_FLAG_DCB_CAPABLE, pf->flags)))
74400cc3f1bSAnirudh Venkataramanan 		return;
74500cc3f1bSAnirudh Venkataramanan 
746a17a5ff6SUsha Ketineni 	if (pf->dcbx_cap & DCB_CAP_DCBX_HOST) {
7474015d11eSBrett Creeley 		dev_dbg(dev, "MIB Change Event in HOST mode\n");
748a17a5ff6SUsha Ketineni 		return;
74900cc3f1bSAnirudh Venkataramanan 	}
750a17a5ff6SUsha Ketineni 
751a17a5ff6SUsha Ketineni 	pi = pf->hw.port_info;
752a17a5ff6SUsha Ketineni 	mib = (struct ice_aqc_lldp_get_mib *)&event->desc.params.raw;
753a17a5ff6SUsha Ketineni 	/* Ignore if event is not for Nearest Bridge */
754a17a5ff6SUsha Ketineni 	type = ((mib->type >> ICE_AQ_LLDP_BRID_TYPE_S) &
755a17a5ff6SUsha Ketineni 		ICE_AQ_LLDP_BRID_TYPE_M);
7564015d11eSBrett Creeley 	dev_dbg(dev, "LLDP event MIB bridge type 0x%x\n", type);
757a17a5ff6SUsha Ketineni 	if (type != ICE_AQ_LLDP_BRID_TYPE_NEAREST_BRID)
758a17a5ff6SUsha Ketineni 		return;
759a17a5ff6SUsha Ketineni 
760a17a5ff6SUsha Ketineni 	/* Check MIB Type and return if event for Remote MIB update */
761a17a5ff6SUsha Ketineni 	type = mib->type & ICE_AQ_LLDP_MIB_TYPE_M;
7624015d11eSBrett Creeley 	dev_dbg(dev, "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) {
7694015d11eSBrett Creeley 			dev_err(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) {
7834015d11eSBrett Creeley 		dev_err(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))) {
7894015d11eSBrett Creeley 		dev_dbg(dev, "No change detected in DCBX configuration.\n");
790a17a5ff6SUsha Ketineni 		return;
791a17a5ff6SUsha Ketineni 	}
792a17a5ff6SUsha Ketineni 
793a17a5ff6SUsha Ketineni 	need_reconfig = ice_dcb_need_recfg(pf, &tmp_dcbx_cfg,
794a17a5ff6SUsha Ketineni 					   &pi->local_dcbx_cfg);
795b94b013eSDave Ertman 	ice_dcbnl_flush_apps(pf, &tmp_dcbx_cfg, &pi->local_dcbx_cfg);
796a17a5ff6SUsha Ketineni 	if (!need_reconfig)
797a17a5ff6SUsha Ketineni 		return;
798a17a5ff6SUsha Ketineni 
799a17a5ff6SUsha Ketineni 	/* Enable DCB tagging only when more than one TC */
800a17a5ff6SUsha Ketineni 	if (ice_dcb_get_num_tc(&pi->local_dcbx_cfg) > 1) {
8014015d11eSBrett Creeley 		dev_dbg(dev, "DCB tagging enabled (num TC > 1)\n");
802a17a5ff6SUsha Ketineni 		set_bit(ICE_FLAG_DCB_ENA, pf->flags);
803a17a5ff6SUsha Ketineni 	} else {
8044015d11eSBrett Creeley 		dev_dbg(dev, "DCB tagging disabled (num TC = 1)\n");
805a17a5ff6SUsha Ketineni 		clear_bit(ICE_FLAG_DCB_ENA, pf->flags);
806a17a5ff6SUsha Ketineni 	}
807a17a5ff6SUsha Ketineni 
8089d614b64SAnirudh Venkataramanan 	pf_vsi = ice_get_main_vsi(pf);
8099d614b64SAnirudh Venkataramanan 	if (!pf_vsi) {
8104015d11eSBrett Creeley 		dev_dbg(dev, "PF VSI doesn't exist\n");
8119d614b64SAnirudh Venkataramanan 		return;
8129d614b64SAnirudh Venkataramanan 	}
8139d614b64SAnirudh Venkataramanan 
814a17a5ff6SUsha Ketineni 	rtnl_lock();
8159d614b64SAnirudh Venkataramanan 	ice_dis_vsi(pf_vsi, true);
816a17a5ff6SUsha Ketineni 
817a17a5ff6SUsha Ketineni 	ret = ice_query_port_ets(pf->hw.port_info, &buf, sizeof(buf), NULL);
818a17a5ff6SUsha Ketineni 	if (ret) {
8194015d11eSBrett Creeley 		dev_err(dev, "Query Port ETS failed\n");
820a17a5ff6SUsha Ketineni 		rtnl_unlock();
821a17a5ff6SUsha Ketineni 		return;
822a17a5ff6SUsha Ketineni 	}
823a17a5ff6SUsha Ketineni 
824a17a5ff6SUsha Ketineni 	/* changes in configuration update VSI */
825a17a5ff6SUsha Ketineni 	ice_pf_dcb_recfg(pf);
826a17a5ff6SUsha Ketineni 
8279d614b64SAnirudh Venkataramanan 	ice_ena_vsi(pf_vsi, true);
828a17a5ff6SUsha Ketineni 	rtnl_unlock();
82900cc3f1bSAnirudh Venkataramanan }
830