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 {
318b832c2f6SAnirudh Venkataramanan 	struct ice_aqc_port_ets_elem buf = { 0 };
3194015d11eSBrett Creeley 	struct device *dev = ice_pf_to_dev(pf);
320242b5e06SDave Ertman 	struct ice_dcbx_cfg *err_cfg;
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 
333242b5e06SDave Ertman 	mutex_lock(&pf->tc_mutex);
3347829570eSUsha Ketineni 
335242b5e06SDave Ertman 	if (!pf->hw.port_info->is_sw_lldp)
3367829570eSUsha Ketineni 		ice_cfg_etsrec_defaults(pf->hw.port_info);
337242b5e06SDave Ertman 
338b832c2f6SAnirudh Venkataramanan 	ret = ice_set_dcb_cfg(pf->hw.port_info);
339b832c2f6SAnirudh Venkataramanan 	if (ret) {
340242b5e06SDave Ertman 		dev_err(dev, "Failed to set DCB config in rebuild\n");
341b832c2f6SAnirudh Venkataramanan 		goto dcb_error;
342b832c2f6SAnirudh Venkataramanan 	}
343b832c2f6SAnirudh Venkataramanan 
344242b5e06SDave Ertman 	if (!pf->hw.port_info->is_sw_lldp) {
345242b5e06SDave Ertman 		ret = ice_cfg_lldp_mib_change(&pf->hw, true);
346242b5e06SDave Ertman 		if (ret && !pf->hw.port_info->is_sw_lldp) {
347242b5e06SDave Ertman 			dev_err(dev, "Failed to register for MIB changes\n");
348b832c2f6SAnirudh Venkataramanan 			goto dcb_error;
349b832c2f6SAnirudh Venkataramanan 		}
350b832c2f6SAnirudh Venkataramanan 	}
351242b5e06SDave Ertman 
3524015d11eSBrett Creeley 	dev_info(dev, "DCB restored after reset\n");
353b832c2f6SAnirudh Venkataramanan 	ret = ice_query_port_ets(pf->hw.port_info, &buf, sizeof(buf), NULL);
354b832c2f6SAnirudh Venkataramanan 	if (ret) {
3554015d11eSBrett Creeley 		dev_err(dev, "Query Port ETS failed\n");
356b832c2f6SAnirudh Venkataramanan 		goto dcb_error;
357b832c2f6SAnirudh Venkataramanan 	}
358b832c2f6SAnirudh Venkataramanan 
359242b5e06SDave Ertman 	mutex_unlock(&pf->tc_mutex);
360242b5e06SDave Ertman 
361b832c2f6SAnirudh Venkataramanan 	return;
362b832c2f6SAnirudh Venkataramanan 
363b832c2f6SAnirudh Venkataramanan dcb_error:
3644015d11eSBrett Creeley 	dev_err(dev, "Disabling DCB until new settings occur\n");
365242b5e06SDave Ertman 	err_cfg = kzalloc(sizeof(*err_cfg), GFP_KERNEL);
366242b5e06SDave Ertman 	if (!err_cfg) {
367242b5e06SDave Ertman 		mutex_unlock(&pf->tc_mutex);
3689efe35d0STony Nguyen 		return;
369242b5e06SDave Ertman 	}
3709efe35d0STony Nguyen 
371242b5e06SDave Ertman 	err_cfg->etscfg.willing = true;
372242b5e06SDave Ertman 	err_cfg->etscfg.tcbwtable[0] = ICE_TC_MAX_BW;
373242b5e06SDave Ertman 	err_cfg->etscfg.tsatable[0] = ICE_IEEE_TSA_ETS;
374242b5e06SDave Ertman 	memcpy(&err_cfg->etsrec, &err_cfg->etscfg, sizeof(err_cfg->etsrec));
375ac614b13SBruce Allan 	/* Coverity warns the return code of ice_pf_dcb_cfg() is not checked
376ac614b13SBruce Allan 	 * here as is done for other calls to that function. That check is
377ac614b13SBruce Allan 	 * not necessary since this is in this function's error cleanup path.
378ac614b13SBruce Allan 	 * Suppress the Coverity warning with the following comment...
379ac614b13SBruce Allan 	 */
380ac614b13SBruce Allan 	/* coverity[check_return] */
381242b5e06SDave Ertman 	ice_pf_dcb_cfg(pf, err_cfg, false);
382242b5e06SDave Ertman 	kfree(err_cfg);
383242b5e06SDave Ertman 
384242b5e06SDave Ertman 	mutex_unlock(&pf->tc_mutex);
385b832c2f6SAnirudh Venkataramanan }
386b832c2f6SAnirudh Venkataramanan 
387b832c2f6SAnirudh Venkataramanan /**
3887b9ffc76SAnirudh Venkataramanan  * ice_dcb_init_cfg - set the initial DCB config in SW
3892f2da36eSAnirudh Venkataramanan  * @pf: PF to apply config to
390e223eaecSDave Ertman  * @locked: Is the RTNL held
3917b9ffc76SAnirudh Venkataramanan  */
392e223eaecSDave Ertman static int ice_dcb_init_cfg(struct ice_pf *pf, bool locked)
3937b9ffc76SAnirudh Venkataramanan {
3947b9ffc76SAnirudh Venkataramanan 	struct ice_dcbx_cfg *newcfg;
3957b9ffc76SAnirudh Venkataramanan 	struct ice_port_info *pi;
3967b9ffc76SAnirudh Venkataramanan 	int ret = 0;
3977b9ffc76SAnirudh Venkataramanan 
3987b9ffc76SAnirudh Venkataramanan 	pi = pf->hw.port_info;
3999efe35d0STony Nguyen 	newcfg = kmemdup(&pi->local_dcbx_cfg, sizeof(*newcfg), GFP_KERNEL);
4007b9ffc76SAnirudh Venkataramanan 	if (!newcfg)
4017b9ffc76SAnirudh Venkataramanan 		return -ENOMEM;
4027b9ffc76SAnirudh Venkataramanan 
4037b9ffc76SAnirudh Venkataramanan 	memset(&pi->local_dcbx_cfg, 0, sizeof(*newcfg));
4047b9ffc76SAnirudh Venkataramanan 
4054015d11eSBrett Creeley 	dev_info(ice_pf_to_dev(pf), "Configuring initial DCB values\n");
406e223eaecSDave Ertman 	if (ice_pf_dcb_cfg(pf, newcfg, locked))
4077b9ffc76SAnirudh Venkataramanan 		ret = -EINVAL;
4087b9ffc76SAnirudh Venkataramanan 
4099efe35d0STony Nguyen 	kfree(newcfg);
4107b9ffc76SAnirudh Venkataramanan 
4117b9ffc76SAnirudh Venkataramanan 	return ret;
4127b9ffc76SAnirudh Venkataramanan }
4137b9ffc76SAnirudh Venkataramanan 
4147b9ffc76SAnirudh Venkataramanan /**
4150deab659SAnirudh Venkataramanan  * ice_dcb_sw_default_config - Apply a default DCB config
4162f2da36eSAnirudh Venkataramanan  * @pf: PF to apply config to
417cfbf1367SPaul Greenwalt  * @ets_willing: configure ets willing
418e223eaecSDave Ertman  * @locked: was this function called with RTNL held
4190deab659SAnirudh Venkataramanan  */
420cfbf1367SPaul Greenwalt static int ice_dcb_sw_dflt_cfg(struct ice_pf *pf, bool ets_willing, bool locked)
4210deab659SAnirudh Venkataramanan {
4220deab659SAnirudh Venkataramanan 	struct ice_aqc_port_ets_elem buf = { 0 };
4230deab659SAnirudh Venkataramanan 	struct ice_dcbx_cfg *dcbcfg;
4240deab659SAnirudh Venkataramanan 	struct ice_port_info *pi;
4250deab659SAnirudh Venkataramanan 	struct ice_hw *hw;
4260deab659SAnirudh Venkataramanan 	int ret;
4270deab659SAnirudh Venkataramanan 
4280deab659SAnirudh Venkataramanan 	hw = &pf->hw;
4290deab659SAnirudh Venkataramanan 	pi = hw->port_info;
4309efe35d0STony Nguyen 	dcbcfg = kzalloc(sizeof(*dcbcfg), GFP_KERNEL);
4319efe35d0STony Nguyen 	if (!dcbcfg)
4329efe35d0STony Nguyen 		return -ENOMEM;
4330deab659SAnirudh Venkataramanan 
4340deab659SAnirudh Venkataramanan 	memset(&pi->local_dcbx_cfg, 0, sizeof(*dcbcfg));
4350deab659SAnirudh Venkataramanan 
436cfbf1367SPaul Greenwalt 	dcbcfg->etscfg.willing = ets_willing ? 1 : 0;
437a257f188SUsha Ketineni 	dcbcfg->etscfg.maxtcs = hw->func_caps.common_cap.maxtc;
4380deab659SAnirudh Venkataramanan 	dcbcfg->etscfg.tcbwtable[0] = 100;
4390deab659SAnirudh Venkataramanan 	dcbcfg->etscfg.tsatable[0] = ICE_IEEE_TSA_ETS;
4400deab659SAnirudh Venkataramanan 
4410deab659SAnirudh Venkataramanan 	memcpy(&dcbcfg->etsrec, &dcbcfg->etscfg,
4420deab659SAnirudh Venkataramanan 	       sizeof(dcbcfg->etsrec));
4430deab659SAnirudh Venkataramanan 	dcbcfg->etsrec.willing = 0;
4440deab659SAnirudh Venkataramanan 
4450deab659SAnirudh Venkataramanan 	dcbcfg->pfc.willing = 1;
446a257f188SUsha Ketineni 	dcbcfg->pfc.pfccap = hw->func_caps.common_cap.maxtc;
4470deab659SAnirudh Venkataramanan 
4480deab659SAnirudh Venkataramanan 	dcbcfg->numapps = 1;
4490deab659SAnirudh Venkataramanan 	dcbcfg->app[0].selector = ICE_APP_SEL_ETHTYPE;
4500deab659SAnirudh Venkataramanan 	dcbcfg->app[0].priority = 3;
4510deab659SAnirudh Venkataramanan 	dcbcfg->app[0].prot_id = ICE_APP_PROT_ID_FCOE;
4520deab659SAnirudh Venkataramanan 
453e223eaecSDave Ertman 	ret = ice_pf_dcb_cfg(pf, dcbcfg, locked);
4549efe35d0STony Nguyen 	kfree(dcbcfg);
4550deab659SAnirudh Venkataramanan 	if (ret)
4560deab659SAnirudh Venkataramanan 		return ret;
4570deab659SAnirudh Venkataramanan 
4580deab659SAnirudh Venkataramanan 	return ice_query_port_ets(pi, &buf, sizeof(buf), NULL);
4590deab659SAnirudh Venkataramanan }
4600deab659SAnirudh Venkataramanan 
4610deab659SAnirudh Venkataramanan /**
462cfbf1367SPaul Greenwalt  * ice_dcb_tc_contig - Check that TCs are contiguous
463cfbf1367SPaul Greenwalt  * @prio_table: pointer to priority table
464cfbf1367SPaul Greenwalt  *
465cfbf1367SPaul Greenwalt  * Check if TCs begin with TC0 and are contiguous
466cfbf1367SPaul Greenwalt  */
467cfbf1367SPaul Greenwalt static bool ice_dcb_tc_contig(u8 *prio_table)
468cfbf1367SPaul Greenwalt {
469cfbf1367SPaul Greenwalt 	u8 max_tc = 0;
470cfbf1367SPaul Greenwalt 	int i;
471cfbf1367SPaul Greenwalt 
472cfbf1367SPaul Greenwalt 	for (i = 0; i < CEE_DCBX_MAX_PRIO; i++) {
473cfbf1367SPaul Greenwalt 		u8 cur_tc = prio_table[i];
474cfbf1367SPaul Greenwalt 
475cfbf1367SPaul Greenwalt 		if (cur_tc > max_tc)
476cfbf1367SPaul Greenwalt 			return false;
477cfbf1367SPaul Greenwalt 		else if (cur_tc == max_tc)
478cfbf1367SPaul Greenwalt 			max_tc++;
479cfbf1367SPaul Greenwalt 	}
480cfbf1367SPaul Greenwalt 
481cfbf1367SPaul Greenwalt 	return true;
482cfbf1367SPaul Greenwalt }
483cfbf1367SPaul Greenwalt 
484cfbf1367SPaul Greenwalt /**
485cfbf1367SPaul Greenwalt  * ice_dcb_noncontig_cfg - Configure DCB for non-contiguous TCs
486cfbf1367SPaul Greenwalt  * @pf: pointer to the PF struct
487cfbf1367SPaul Greenwalt  *
488cfbf1367SPaul Greenwalt  * If non-contiguous TCs, then configure SW DCB with TC0 and ETS non-willing
489cfbf1367SPaul Greenwalt  */
490cfbf1367SPaul Greenwalt static int ice_dcb_noncontig_cfg(struct ice_pf *pf)
491cfbf1367SPaul Greenwalt {
492cfbf1367SPaul Greenwalt 	struct ice_dcbx_cfg *dcbcfg = &pf->hw.port_info->local_dcbx_cfg;
4934015d11eSBrett Creeley 	struct device *dev = ice_pf_to_dev(pf);
494cfbf1367SPaul Greenwalt 	int ret;
495cfbf1367SPaul Greenwalt 
496cfbf1367SPaul Greenwalt 	/* Configure SW DCB default with ETS non-willing */
497cfbf1367SPaul Greenwalt 	ret = ice_dcb_sw_dflt_cfg(pf, false, true);
498cfbf1367SPaul Greenwalt 	if (ret) {
4994015d11eSBrett Creeley 		dev_err(dev, "Failed to set local DCB config %d\n", ret);
500cfbf1367SPaul Greenwalt 		return ret;
501cfbf1367SPaul Greenwalt 	}
502cfbf1367SPaul Greenwalt 
503cfbf1367SPaul Greenwalt 	/* Reconfigure with ETS willing so that FW will send LLDP MIB event */
504cfbf1367SPaul Greenwalt 	dcbcfg->etscfg.willing = 1;
505cfbf1367SPaul Greenwalt 	ret = ice_set_dcb_cfg(pf->hw.port_info);
506cfbf1367SPaul Greenwalt 	if (ret)
5074015d11eSBrett Creeley 		dev_err(dev, "Failed to set DCB to unwilling\n");
508cfbf1367SPaul Greenwalt 
509cfbf1367SPaul Greenwalt 	return ret;
510cfbf1367SPaul Greenwalt }
511cfbf1367SPaul Greenwalt 
512cfbf1367SPaul Greenwalt /**
513cfbf1367SPaul Greenwalt  * ice_pf_dcb_recfg - Reconfigure all VEBs and VSIs
514cfbf1367SPaul Greenwalt  * @pf: pointer to the PF struct
515cfbf1367SPaul Greenwalt  *
516cfbf1367SPaul Greenwalt  * Assumed caller has already disabled all VSIs before
517cfbf1367SPaul Greenwalt  * calling this function. Reconfiguring DCB based on
518cfbf1367SPaul Greenwalt  * local_dcbx_cfg.
519cfbf1367SPaul Greenwalt  */
52087324e74SHenry Tieman void ice_pf_dcb_recfg(struct ice_pf *pf)
521cfbf1367SPaul Greenwalt {
522cfbf1367SPaul Greenwalt 	struct ice_dcbx_cfg *dcbcfg = &pf->hw.port_info->local_dcbx_cfg;
523cfbf1367SPaul Greenwalt 	u8 tc_map = 0;
524cfbf1367SPaul Greenwalt 	int v, ret;
525cfbf1367SPaul Greenwalt 
526cfbf1367SPaul Greenwalt 	/* Update each VSI */
527cfbf1367SPaul Greenwalt 	ice_for_each_vsi(pf, v) {
5284015d11eSBrett Creeley 		struct ice_vsi *vsi = pf->vsi[v];
5294015d11eSBrett Creeley 
5304015d11eSBrett Creeley 		if (!vsi)
531cfbf1367SPaul Greenwalt 			continue;
532cfbf1367SPaul Greenwalt 
5334015d11eSBrett Creeley 		if (vsi->type == ICE_VSI_PF) {
534cfbf1367SPaul Greenwalt 			tc_map = ice_dcb_get_ena_tc(dcbcfg);
535cfbf1367SPaul Greenwalt 
536cfbf1367SPaul Greenwalt 			/* If DCBX request non-contiguous TC, then configure
537cfbf1367SPaul Greenwalt 			 * default TC
538cfbf1367SPaul Greenwalt 			 */
539cfbf1367SPaul Greenwalt 			if (!ice_dcb_tc_contig(dcbcfg->etscfg.prio_table)) {
540cfbf1367SPaul Greenwalt 				tc_map = ICE_DFLT_TRAFFIC_CLASS;
541cfbf1367SPaul Greenwalt 				ice_dcb_noncontig_cfg(pf);
542cfbf1367SPaul Greenwalt 			}
543cfbf1367SPaul Greenwalt 		} else {
544cfbf1367SPaul Greenwalt 			tc_map = ICE_DFLT_TRAFFIC_CLASS;
545cfbf1367SPaul Greenwalt 		}
546cfbf1367SPaul Greenwalt 
5474015d11eSBrett Creeley 		ret = ice_vsi_cfg_tc(vsi, tc_map);
548cfbf1367SPaul Greenwalt 		if (ret) {
5494015d11eSBrett Creeley 			dev_err(ice_pf_to_dev(pf), "Failed to config TC for VSI index: %d\n",
5504015d11eSBrett Creeley 				vsi->idx);
551cfbf1367SPaul Greenwalt 			continue;
552cfbf1367SPaul Greenwalt 		}
553cfbf1367SPaul Greenwalt 
5544015d11eSBrett Creeley 		ice_vsi_map_rings_to_vectors(vsi);
5554015d11eSBrett Creeley 		if (vsi->type == ICE_VSI_PF)
5564015d11eSBrett Creeley 			ice_dcbnl_set_all(vsi);
557cfbf1367SPaul Greenwalt 	}
558cfbf1367SPaul Greenwalt }
559cfbf1367SPaul Greenwalt 
560cfbf1367SPaul Greenwalt /**
56137b6f646SAnirudh Venkataramanan  * ice_init_pf_dcb - initialize DCB for a PF
5622f2da36eSAnirudh Venkataramanan  * @pf: PF to initialize DCB for
563e223eaecSDave Ertman  * @locked: Was function called with RTNL held
56437b6f646SAnirudh Venkataramanan  */
565e223eaecSDave Ertman int ice_init_pf_dcb(struct ice_pf *pf, bool locked)
56637b6f646SAnirudh Venkataramanan {
5674015d11eSBrett Creeley 	struct device *dev = ice_pf_to_dev(pf);
56837b6f646SAnirudh Venkataramanan 	struct ice_port_info *port_info;
56937b6f646SAnirudh Venkataramanan 	struct ice_hw *hw = &pf->hw;
5707b9ffc76SAnirudh Venkataramanan 	int err;
57137b6f646SAnirudh Venkataramanan 
57237b6f646SAnirudh Venkataramanan 	port_info = hw->port_info;
57337b6f646SAnirudh Venkataramanan 
574ea300f41SDave Ertman 	err = ice_init_dcb(hw, false);
575473ca574SDave Ertman 	if (err && !port_info->is_sw_lldp) {
5764015d11eSBrett Creeley 		dev_err(dev, "Error initializing DCB %d\n", err);
577473ca574SDave Ertman 		goto dcb_init_err;
578473ca574SDave Ertman 	}
579473ca574SDave Ertman 
5804015d11eSBrett Creeley 	dev_info(dev,
581a257f188SUsha Ketineni 		 "DCB is enabled in the hardware, max number of TCs supported on this port are %d\n",
582a257f188SUsha Ketineni 		 pf->hw.func_caps.common_cap.maxtc);
583473ca574SDave Ertman 	if (err) {
584241c8cf0SPaul Greenwalt 		struct ice_vsi *pf_vsi;
585241c8cf0SPaul Greenwalt 
586473ca574SDave Ertman 		/* FW LLDP is disabled, activate SW DCBX/LLDP mode */
5874015d11eSBrett Creeley 		dev_info(dev, "FW LLDP is disabled, DCBx/LLDP in SW mode.\n");
58884a118abSDave Ertman 		clear_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags);
589cfbf1367SPaul Greenwalt 		err = ice_dcb_sw_dflt_cfg(pf, true, locked);
5900deab659SAnirudh Venkataramanan 		if (err) {
5914015d11eSBrett Creeley 			dev_err(dev,
5920deab659SAnirudh Venkataramanan 				"Failed to set local DCB config %d\n", err);
5930deab659SAnirudh Venkataramanan 			err = -EIO;
5947b9ffc76SAnirudh Venkataramanan 			goto dcb_init_err;
5950deab659SAnirudh Venkataramanan 		}
5960deab659SAnirudh Venkataramanan 
597241c8cf0SPaul Greenwalt 		/* If the FW DCBX engine is not running then Rx LLDP packets
598241c8cf0SPaul Greenwalt 		 * need to be redirected up the stack.
599241c8cf0SPaul Greenwalt 		 */
600241c8cf0SPaul Greenwalt 		pf_vsi = ice_get_main_vsi(pf);
601241c8cf0SPaul Greenwalt 		if (!pf_vsi) {
6024015d11eSBrett Creeley 			dev_err(dev, "Failed to set local DCB config\n");
603241c8cf0SPaul Greenwalt 			err = -EIO;
604241c8cf0SPaul Greenwalt 			goto dcb_init_err;
605241c8cf0SPaul Greenwalt 		}
606241c8cf0SPaul Greenwalt 
607241c8cf0SPaul Greenwalt 		ice_cfg_sw_lldp(pf_vsi, false, true);
608241c8cf0SPaul Greenwalt 
6090deab659SAnirudh Venkataramanan 		pf->dcbx_cap = DCB_CAP_DCBX_HOST | DCB_CAP_DCBX_VER_IEEE;
6100deab659SAnirudh Venkataramanan 		return 0;
6110deab659SAnirudh Venkataramanan 	}
6127b9ffc76SAnirudh Venkataramanan 
61384a118abSDave Ertman 	set_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags);
6141b0c3247SDave Ertman 
6157b9ffc76SAnirudh Venkataramanan 	/* DCBX in FW and LLDP enabled in FW */
6167b9ffc76SAnirudh Venkataramanan 	pf->dcbx_cap = DCB_CAP_DCBX_LLD_MANAGED | DCB_CAP_DCBX_VER_IEEE;
6177b9ffc76SAnirudh Venkataramanan 
618e223eaecSDave Ertman 	err = ice_dcb_init_cfg(pf, locked);
6197b9ffc76SAnirudh Venkataramanan 	if (err)
6207b9ffc76SAnirudh Venkataramanan 		goto dcb_init_err;
6217b9ffc76SAnirudh Venkataramanan 
6227b9ffc76SAnirudh Venkataramanan 	return err;
6237b9ffc76SAnirudh Venkataramanan 
6247b9ffc76SAnirudh Venkataramanan dcb_init_err:
6257b9ffc76SAnirudh Venkataramanan 	dev_err(dev, "DCB init failed\n");
6267b9ffc76SAnirudh Venkataramanan 	return err;
62737b6f646SAnirudh Venkataramanan }
62800cc3f1bSAnirudh Venkataramanan 
62900cc3f1bSAnirudh Venkataramanan /**
6304b0fdcebSAnirudh Venkataramanan  * ice_update_dcb_stats - Update DCB stats counters
6314b0fdcebSAnirudh Venkataramanan  * @pf: PF whose stats needs to be updated
6324b0fdcebSAnirudh Venkataramanan  */
6334b0fdcebSAnirudh Venkataramanan void ice_update_dcb_stats(struct ice_pf *pf)
6344b0fdcebSAnirudh Venkataramanan {
6354b0fdcebSAnirudh Venkataramanan 	struct ice_hw_port_stats *prev_ps, *cur_ps;
6364b0fdcebSAnirudh Venkataramanan 	struct ice_hw *hw = &pf->hw;
6379e7a5d17SUsha Ketineni 	u8 port;
6384b0fdcebSAnirudh Venkataramanan 	int i;
6394b0fdcebSAnirudh Venkataramanan 
6409e7a5d17SUsha Ketineni 	port = hw->port_info->lport;
6414b0fdcebSAnirudh Venkataramanan 	prev_ps = &pf->stats_prev;
6424b0fdcebSAnirudh Venkataramanan 	cur_ps = &pf->stats;
6434b0fdcebSAnirudh Venkataramanan 
6444b0fdcebSAnirudh Venkataramanan 	for (i = 0; i < 8; i++) {
6459e7a5d17SUsha Ketineni 		ice_stat_update32(hw, GLPRT_PXOFFRXC(port, i),
6464b0fdcebSAnirudh Venkataramanan 				  pf->stat_prev_loaded,
6474b0fdcebSAnirudh Venkataramanan 				  &prev_ps->priority_xoff_rx[i],
6484b0fdcebSAnirudh Venkataramanan 				  &cur_ps->priority_xoff_rx[i]);
6499e7a5d17SUsha Ketineni 		ice_stat_update32(hw, GLPRT_PXONRXC(port, i),
6504b0fdcebSAnirudh Venkataramanan 				  pf->stat_prev_loaded,
6514b0fdcebSAnirudh Venkataramanan 				  &prev_ps->priority_xon_rx[i],
6524b0fdcebSAnirudh Venkataramanan 				  &cur_ps->priority_xon_rx[i]);
6539e7a5d17SUsha Ketineni 		ice_stat_update32(hw, GLPRT_PXONTXC(port, i),
6544b0fdcebSAnirudh Venkataramanan 				  pf->stat_prev_loaded,
6554b0fdcebSAnirudh Venkataramanan 				  &prev_ps->priority_xon_tx[i],
6564b0fdcebSAnirudh Venkataramanan 				  &cur_ps->priority_xon_tx[i]);
6579e7a5d17SUsha Ketineni 		ice_stat_update32(hw, GLPRT_PXOFFTXC(port, i),
6584b0fdcebSAnirudh Venkataramanan 				  pf->stat_prev_loaded,
6594b0fdcebSAnirudh Venkataramanan 				  &prev_ps->priority_xoff_tx[i],
6604b0fdcebSAnirudh Venkataramanan 				  &cur_ps->priority_xoff_tx[i]);
6619e7a5d17SUsha Ketineni 		ice_stat_update32(hw, GLPRT_RXON2OFFCNT(port, i),
6624b0fdcebSAnirudh Venkataramanan 				  pf->stat_prev_loaded,
6634b0fdcebSAnirudh Venkataramanan 				  &prev_ps->priority_xon_2_xoff[i],
6644b0fdcebSAnirudh Venkataramanan 				  &cur_ps->priority_xon_2_xoff[i]);
6654b0fdcebSAnirudh Venkataramanan 	}
6664b0fdcebSAnirudh Venkataramanan }
6674b0fdcebSAnirudh Venkataramanan 
6684b0fdcebSAnirudh Venkataramanan /**
6695f6aa50eSAnirudh Venkataramanan  * ice_tx_prepare_vlan_flags_dcb - prepare VLAN tagging for DCB
6705f6aa50eSAnirudh Venkataramanan  * @tx_ring: ring to send buffer on
6715f6aa50eSAnirudh Venkataramanan  * @first: pointer to struct ice_tx_buf
6725f6aa50eSAnirudh Venkataramanan  */
6735f6aa50eSAnirudh Venkataramanan int
6745f6aa50eSAnirudh Venkataramanan ice_tx_prepare_vlan_flags_dcb(struct ice_ring *tx_ring,
6755f6aa50eSAnirudh Venkataramanan 			      struct ice_tx_buf *first)
6765f6aa50eSAnirudh Venkataramanan {
6775f6aa50eSAnirudh Venkataramanan 	struct sk_buff *skb = first->skb;
6785f6aa50eSAnirudh Venkataramanan 
6795f6aa50eSAnirudh Venkataramanan 	if (!test_bit(ICE_FLAG_DCB_ENA, tx_ring->vsi->back->flags))
6805f6aa50eSAnirudh Venkataramanan 		return 0;
6815f6aa50eSAnirudh Venkataramanan 
6825f6aa50eSAnirudh Venkataramanan 	/* Insert 802.1p priority into VLAN header */
6835f6aa50eSAnirudh Venkataramanan 	if ((first->tx_flags & (ICE_TX_FLAGS_HW_VLAN | ICE_TX_FLAGS_SW_VLAN)) ||
6845f6aa50eSAnirudh Venkataramanan 	    skb->priority != TC_PRIO_CONTROL) {
6855f6aa50eSAnirudh Venkataramanan 		first->tx_flags &= ~ICE_TX_FLAGS_VLAN_PR_M;
6865f6aa50eSAnirudh Venkataramanan 		/* Mask the lower 3 bits to set the 802.1p priority */
6875f6aa50eSAnirudh Venkataramanan 		first->tx_flags |= (skb->priority & 0x7) <<
6885f6aa50eSAnirudh Venkataramanan 				   ICE_TX_FLAGS_VLAN_PR_S;
6895f6aa50eSAnirudh Venkataramanan 		if (first->tx_flags & ICE_TX_FLAGS_SW_VLAN) {
6905f6aa50eSAnirudh Venkataramanan 			struct vlan_ethhdr *vhdr;
6915f6aa50eSAnirudh Venkataramanan 			int rc;
6925f6aa50eSAnirudh Venkataramanan 
6935f6aa50eSAnirudh Venkataramanan 			rc = skb_cow_head(skb, 0);
6945f6aa50eSAnirudh Venkataramanan 			if (rc < 0)
6955f6aa50eSAnirudh Venkataramanan 				return rc;
6965f6aa50eSAnirudh Venkataramanan 			vhdr = (struct vlan_ethhdr *)skb->data;
6975f6aa50eSAnirudh Venkataramanan 			vhdr->h_vlan_TCI = htons(first->tx_flags >>
6985f6aa50eSAnirudh Venkataramanan 						 ICE_TX_FLAGS_VLAN_S);
6995f6aa50eSAnirudh Venkataramanan 		} else {
7005f6aa50eSAnirudh Venkataramanan 			first->tx_flags |= ICE_TX_FLAGS_HW_VLAN;
7015f6aa50eSAnirudh Venkataramanan 		}
7025f6aa50eSAnirudh Venkataramanan 	}
7035f6aa50eSAnirudh Venkataramanan 
7045f6aa50eSAnirudh Venkataramanan 	return 0;
7055f6aa50eSAnirudh Venkataramanan }
7065f6aa50eSAnirudh Venkataramanan 
7075f6aa50eSAnirudh Venkataramanan /**
70800cc3f1bSAnirudh Venkataramanan  * ice_dcb_process_lldp_set_mib_change - Process MIB change
70900cc3f1bSAnirudh Venkataramanan  * @pf: ptr to ice_pf
71000cc3f1bSAnirudh Venkataramanan  * @event: pointer to the admin queue receive event
71100cc3f1bSAnirudh Venkataramanan  */
71200cc3f1bSAnirudh Venkataramanan void
71300cc3f1bSAnirudh Venkataramanan ice_dcb_process_lldp_set_mib_change(struct ice_pf *pf,
71400cc3f1bSAnirudh Venkataramanan 				    struct ice_rq_event_info *event)
71500cc3f1bSAnirudh Venkataramanan {
716a17a5ff6SUsha Ketineni 	struct ice_aqc_port_ets_elem buf = { 0 };
7174015d11eSBrett Creeley 	struct device *dev = ice_pf_to_dev(pf);
718a17a5ff6SUsha Ketineni 	struct ice_aqc_lldp_get_mib *mib;
719a17a5ff6SUsha Ketineni 	struct ice_dcbx_cfg tmp_dcbx_cfg;
720a17a5ff6SUsha Ketineni 	bool need_reconfig = false;
721a17a5ff6SUsha Ketineni 	struct ice_port_info *pi;
7229d614b64SAnirudh Venkataramanan 	struct ice_vsi *pf_vsi;
723a17a5ff6SUsha Ketineni 	u8 type;
724a17a5ff6SUsha Ketineni 	int ret;
72500cc3f1bSAnirudh Venkataramanan 
726a17a5ff6SUsha Ketineni 	/* Not DCB capable or capability disabled */
727a17a5ff6SUsha Ketineni 	if (!(test_bit(ICE_FLAG_DCB_CAPABLE, pf->flags)))
72800cc3f1bSAnirudh Venkataramanan 		return;
72900cc3f1bSAnirudh Venkataramanan 
730a17a5ff6SUsha Ketineni 	if (pf->dcbx_cap & DCB_CAP_DCBX_HOST) {
7314015d11eSBrett Creeley 		dev_dbg(dev, "MIB Change Event in HOST mode\n");
732a17a5ff6SUsha Ketineni 		return;
73300cc3f1bSAnirudh Venkataramanan 	}
734a17a5ff6SUsha Ketineni 
735a17a5ff6SUsha Ketineni 	pi = pf->hw.port_info;
736a17a5ff6SUsha Ketineni 	mib = (struct ice_aqc_lldp_get_mib *)&event->desc.params.raw;
737a17a5ff6SUsha Ketineni 	/* Ignore if event is not for Nearest Bridge */
738a17a5ff6SUsha Ketineni 	type = ((mib->type >> ICE_AQ_LLDP_BRID_TYPE_S) &
739a17a5ff6SUsha Ketineni 		ICE_AQ_LLDP_BRID_TYPE_M);
7404015d11eSBrett Creeley 	dev_dbg(dev, "LLDP event MIB bridge type 0x%x\n", type);
741a17a5ff6SUsha Ketineni 	if (type != ICE_AQ_LLDP_BRID_TYPE_NEAREST_BRID)
742a17a5ff6SUsha Ketineni 		return;
743a17a5ff6SUsha Ketineni 
744a17a5ff6SUsha Ketineni 	/* Check MIB Type and return if event for Remote MIB update */
745a17a5ff6SUsha Ketineni 	type = mib->type & ICE_AQ_LLDP_MIB_TYPE_M;
7464015d11eSBrett Creeley 	dev_dbg(dev, "LLDP event mib type %s\n", type ? "remote" : "local");
747a17a5ff6SUsha Ketineni 	if (type == ICE_AQ_LLDP_MIB_REMOTE) {
748a17a5ff6SUsha Ketineni 		/* Update the remote cached instance and return */
749a17a5ff6SUsha Ketineni 		ret = ice_aq_get_dcb_cfg(pi->hw, ICE_AQ_LLDP_MIB_REMOTE,
750a17a5ff6SUsha Ketineni 					 ICE_AQ_LLDP_BRID_TYPE_NEAREST_BRID,
751a17a5ff6SUsha Ketineni 					 &pi->remote_dcbx_cfg);
752a17a5ff6SUsha Ketineni 		if (ret) {
7534015d11eSBrett Creeley 			dev_err(dev, "Failed to get remote DCB config\n");
754a17a5ff6SUsha Ketineni 			return;
755a17a5ff6SUsha Ketineni 		}
756a17a5ff6SUsha Ketineni 	}
757a17a5ff6SUsha Ketineni 
758242b5e06SDave Ertman 	mutex_lock(&pf->tc_mutex);
759242b5e06SDave Ertman 
760a17a5ff6SUsha Ketineni 	/* store the old configuration */
761a17a5ff6SUsha Ketineni 	tmp_dcbx_cfg = pf->hw.port_info->local_dcbx_cfg;
762a17a5ff6SUsha Ketineni 
7632f2da36eSAnirudh Venkataramanan 	/* Reset the old DCBX configuration data */
764a17a5ff6SUsha Ketineni 	memset(&pi->local_dcbx_cfg, 0, sizeof(pi->local_dcbx_cfg));
765a17a5ff6SUsha Ketineni 
7662f2da36eSAnirudh Venkataramanan 	/* Get updated DCBX data from firmware */
767a17a5ff6SUsha Ketineni 	ret = ice_get_dcb_cfg(pf->hw.port_info);
768a17a5ff6SUsha Ketineni 	if (ret) {
7694015d11eSBrett Creeley 		dev_err(dev, "Failed to get DCB config\n");
770242b5e06SDave Ertman 		goto out;
771a17a5ff6SUsha Ketineni 	}
772a17a5ff6SUsha Ketineni 
773a17a5ff6SUsha Ketineni 	/* No change detected in DCBX configs */
774a17a5ff6SUsha Ketineni 	if (!memcmp(&tmp_dcbx_cfg, &pi->local_dcbx_cfg, sizeof(tmp_dcbx_cfg))) {
7754015d11eSBrett Creeley 		dev_dbg(dev, "No change detected in DCBX configuration.\n");
776242b5e06SDave Ertman 		goto out;
777a17a5ff6SUsha Ketineni 	}
778a17a5ff6SUsha Ketineni 
779a17a5ff6SUsha Ketineni 	need_reconfig = ice_dcb_need_recfg(pf, &tmp_dcbx_cfg,
780a17a5ff6SUsha Ketineni 					   &pi->local_dcbx_cfg);
781b94b013eSDave Ertman 	ice_dcbnl_flush_apps(pf, &tmp_dcbx_cfg, &pi->local_dcbx_cfg);
782a17a5ff6SUsha Ketineni 	if (!need_reconfig)
783242b5e06SDave Ertman 		goto out;
784a17a5ff6SUsha Ketineni 
785a17a5ff6SUsha Ketineni 	/* Enable DCB tagging only when more than one TC */
786a17a5ff6SUsha Ketineni 	if (ice_dcb_get_num_tc(&pi->local_dcbx_cfg) > 1) {
7874015d11eSBrett Creeley 		dev_dbg(dev, "DCB tagging enabled (num TC > 1)\n");
788a17a5ff6SUsha Ketineni 		set_bit(ICE_FLAG_DCB_ENA, pf->flags);
789a17a5ff6SUsha Ketineni 	} else {
7904015d11eSBrett Creeley 		dev_dbg(dev, "DCB tagging disabled (num TC = 1)\n");
791a17a5ff6SUsha Ketineni 		clear_bit(ICE_FLAG_DCB_ENA, pf->flags);
792a17a5ff6SUsha Ketineni 	}
793a17a5ff6SUsha Ketineni 
7949d614b64SAnirudh Venkataramanan 	pf_vsi = ice_get_main_vsi(pf);
7959d614b64SAnirudh Venkataramanan 	if (!pf_vsi) {
7964015d11eSBrett Creeley 		dev_dbg(dev, "PF VSI doesn't exist\n");
797242b5e06SDave Ertman 		goto out;
7989d614b64SAnirudh Venkataramanan 	}
7999d614b64SAnirudh Venkataramanan 
800a17a5ff6SUsha Ketineni 	rtnl_lock();
8019d614b64SAnirudh Venkataramanan 	ice_dis_vsi(pf_vsi, true);
802a17a5ff6SUsha Ketineni 
803a17a5ff6SUsha Ketineni 	ret = ice_query_port_ets(pf->hw.port_info, &buf, sizeof(buf), NULL);
804a17a5ff6SUsha Ketineni 	if (ret) {
8054015d11eSBrett Creeley 		dev_err(dev, "Query Port ETS failed\n");
806242b5e06SDave Ertman 		goto unlock_rtnl;
807a17a5ff6SUsha Ketineni 	}
808a17a5ff6SUsha Ketineni 
809a17a5ff6SUsha Ketineni 	/* changes in configuration update VSI */
810a17a5ff6SUsha Ketineni 	ice_pf_dcb_recfg(pf);
811a17a5ff6SUsha Ketineni 
8129d614b64SAnirudh Venkataramanan 	ice_ena_vsi(pf_vsi, true);
813242b5e06SDave Ertman unlock_rtnl:
814a17a5ff6SUsha Ketineni 	rtnl_unlock();
815242b5e06SDave Ertman out:
816242b5e06SDave Ertman 	mutex_unlock(&pf->tc_mutex);
81700cc3f1bSAnirudh Venkataramanan }
818