1b94b013eSDave Ertman // SPDX-License-Identifier: GPL-2.0
2b94b013eSDave Ertman /* Copyright (c) 2019, Intel Corporation. */
3b94b013eSDave Ertman 
4b94b013eSDave Ertman #include "ice.h"
5b94b013eSDave Ertman #include "ice_dcb.h"
6b94b013eSDave Ertman #include "ice_dcb_lib.h"
7b94b013eSDave Ertman #include "ice_dcb_nl.h"
8b94b013eSDave Ertman #include <net/dcbnl.h>
9b94b013eSDave Ertman 
10b94b013eSDave Ertman /**
11b94b013eSDave Ertman  * ice_dcbnl_devreset - perform enough of a ifdown/ifup to sync DCBNL info
12b94b013eSDave Ertman  * @netdev: device associated with interface that needs reset
13b94b013eSDave Ertman  */
ice_dcbnl_devreset(struct net_device * netdev)14b94b013eSDave Ertman static void ice_dcbnl_devreset(struct net_device *netdev)
15b94b013eSDave Ertman {
16b94b013eSDave Ertman 	struct ice_pf *pf = ice_netdev_to_pf(netdev);
17b94b013eSDave Ertman 
18b94b013eSDave Ertman 	while (ice_is_reset_in_progress(pf->state))
19b94b013eSDave Ertman 		usleep_range(1000, 2000);
20b94b013eSDave Ertman 
21b94b013eSDave Ertman 	dev_close(netdev);
22b94b013eSDave Ertman 	netdev_state_change(netdev);
23b94b013eSDave Ertman 	dev_open(netdev, NULL);
24b94b013eSDave Ertman 	netdev_state_change(netdev);
25b94b013eSDave Ertman }
26b94b013eSDave Ertman 
27b94b013eSDave Ertman /**
28b94b013eSDave Ertman  * ice_dcbnl_getets - retrieve local ETS configuration
29b94b013eSDave Ertman  * @netdev: the relevant netdev
30b94b013eSDave Ertman  * @ets: struct to hold ETS configuration
31b94b013eSDave Ertman  */
ice_dcbnl_getets(struct net_device * netdev,struct ieee_ets * ets)32b94b013eSDave Ertman static int ice_dcbnl_getets(struct net_device *netdev, struct ieee_ets *ets)
33b94b013eSDave Ertman {
34b94b013eSDave Ertman 	struct ice_dcbx_cfg *dcbxcfg;
35b94b013eSDave Ertman 	struct ice_pf *pf;
36b94b013eSDave Ertman 
37b94b013eSDave Ertman 	pf = ice_netdev_to_pf(netdev);
38fc2d1165SChinh T Cao 	dcbxcfg = &pf->hw.port_info->qos_cfg.local_dcbx_cfg;
39b94b013eSDave Ertman 
40b94b013eSDave Ertman 	ets->willing = dcbxcfg->etscfg.willing;
41b94b013eSDave Ertman 	ets->ets_cap = dcbxcfg->etscfg.maxtcs;
42b94b013eSDave Ertman 	ets->cbs = dcbxcfg->etscfg.cbs;
43b94b013eSDave Ertman 	memcpy(ets->tc_tx_bw, dcbxcfg->etscfg.tcbwtable, sizeof(ets->tc_tx_bw));
44b94b013eSDave Ertman 	memcpy(ets->tc_rx_bw, dcbxcfg->etscfg.tcbwtable, sizeof(ets->tc_rx_bw));
45b94b013eSDave Ertman 	memcpy(ets->tc_tsa, dcbxcfg->etscfg.tsatable, sizeof(ets->tc_tsa));
46b94b013eSDave Ertman 	memcpy(ets->prio_tc, dcbxcfg->etscfg.prio_table, sizeof(ets->prio_tc));
47b94b013eSDave Ertman 	memcpy(ets->tc_reco_bw, dcbxcfg->etsrec.tcbwtable,
48b94b013eSDave Ertman 	       sizeof(ets->tc_reco_bw));
49b94b013eSDave Ertman 	memcpy(ets->tc_reco_tsa, dcbxcfg->etsrec.tsatable,
50b94b013eSDave Ertman 	       sizeof(ets->tc_reco_tsa));
51b94b013eSDave Ertman 	memcpy(ets->reco_prio_tc, dcbxcfg->etscfg.prio_table,
52b94b013eSDave Ertman 	       sizeof(ets->reco_prio_tc));
53b94b013eSDave Ertman 
54b94b013eSDave Ertman 	return 0;
55b94b013eSDave Ertman }
56b94b013eSDave Ertman 
57b94b013eSDave Ertman /**
58b94b013eSDave Ertman  * ice_dcbnl_setets - set IEEE ETS configuration
59b94b013eSDave Ertman  * @netdev: pointer to relevant netdev
60b94b013eSDave Ertman  * @ets: struct to hold ETS configuration
61b94b013eSDave Ertman  */
ice_dcbnl_setets(struct net_device * netdev,struct ieee_ets * ets)62b94b013eSDave Ertman static int ice_dcbnl_setets(struct net_device *netdev, struct ieee_ets *ets)
63b94b013eSDave Ertman {
64b94b013eSDave Ertman 	struct ice_pf *pf = ice_netdev_to_pf(netdev);
65b94b013eSDave Ertman 	struct ice_dcbx_cfg *new_cfg;
66b94b013eSDave Ertman 	int bwcfg = 0, bwrec = 0;
672a87bd73SDave Ertman 	int err, i;
68b94b013eSDave Ertman 
69b94b013eSDave Ertman 	if ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) ||
70b94b013eSDave Ertman 	    !(pf->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
71b94b013eSDave Ertman 		return -EINVAL;
72b94b013eSDave Ertman 
73*ab2ed5d7SDave Ertman 	if (pf->lag && pf->lag->bonded) {
74*ab2ed5d7SDave Ertman 		netdev_err(netdev, "DCB changes not allowed when in a bond\n");
75*ab2ed5d7SDave Ertman 		return -EINVAL;
76*ab2ed5d7SDave Ertman 	}
77*ab2ed5d7SDave Ertman 
78fc2d1165SChinh T Cao 	new_cfg = &pf->hw.port_info->qos_cfg.desired_dcbx_cfg;
79b94b013eSDave Ertman 
80b94b013eSDave Ertman 	mutex_lock(&pf->tc_mutex);
81b94b013eSDave Ertman 
82b94b013eSDave Ertman 	new_cfg->etscfg.willing = ets->willing;
83b94b013eSDave Ertman 	new_cfg->etscfg.cbs = ets->cbs;
84b94b013eSDave Ertman 	ice_for_each_traffic_class(i) {
85b94b013eSDave Ertman 		new_cfg->etscfg.tcbwtable[i] = ets->tc_tx_bw[i];
86b94b013eSDave Ertman 		bwcfg += ets->tc_tx_bw[i];
87b94b013eSDave Ertman 		new_cfg->etscfg.tsatable[i] = ets->tc_tsa[i];
882a87bd73SDave Ertman 		if (new_cfg->pfc_mode == ICE_QOS_MODE_VLAN) {
892a87bd73SDave Ertman 			/* in DSCP mode up->tc mapping cannot change */
90b94b013eSDave Ertman 			new_cfg->etscfg.prio_table[i] = ets->prio_tc[i];
912a87bd73SDave Ertman 			new_cfg->etsrec.prio_table[i] = ets->reco_prio_tc[i];
922a87bd73SDave Ertman 		}
93b94b013eSDave Ertman 		new_cfg->etsrec.tcbwtable[i] = ets->tc_reco_bw[i];
94b94b013eSDave Ertman 		bwrec += ets->tc_reco_bw[i];
95b94b013eSDave Ertman 		new_cfg->etsrec.tsatable[i] = ets->tc_reco_tsa[i];
96b94b013eSDave Ertman 	}
97b94b013eSDave Ertman 
98a29a912dSAvinash Dayanand 	if (ice_dcb_bwchk(pf, new_cfg)) {
99a29a912dSAvinash Dayanand 		err = -EINVAL;
100a29a912dSAvinash Dayanand 		goto ets_out;
101a29a912dSAvinash Dayanand 	}
102a29a912dSAvinash Dayanand 
1032a87bd73SDave Ertman 	new_cfg->etscfg.maxtcs = pf->hw.func_caps.common_cap.maxtc;
104b94b013eSDave Ertman 
1056d39ea19SDave Ertman 	if (!bwcfg)
1066d39ea19SDave Ertman 		new_cfg->etscfg.tcbwtable[0] = 100;
1076d39ea19SDave Ertman 
108b94b013eSDave Ertman 	if (!bwrec)
109b94b013eSDave Ertman 		new_cfg->etsrec.tcbwtable[0] = 100;
110b94b013eSDave Ertman 
111b94b013eSDave Ertman 	err = ice_pf_dcb_cfg(pf, new_cfg, true);
112b94b013eSDave Ertman 	/* return of zero indicates new cfg applied */
113b94b013eSDave Ertman 	if (err == ICE_DCB_HW_CHG_RST)
114b94b013eSDave Ertman 		ice_dcbnl_devreset(netdev);
115b94b013eSDave Ertman 	if (err == ICE_DCB_NO_HW_CHG)
116b94b013eSDave Ertman 		err = ICE_DCB_HW_CHG_RST;
117b94b013eSDave Ertman 
118a29a912dSAvinash Dayanand ets_out:
119b94b013eSDave Ertman 	mutex_unlock(&pf->tc_mutex);
120b94b013eSDave Ertman 	return err;
121b94b013eSDave Ertman }
122b94b013eSDave Ertman 
123b94b013eSDave Ertman /**
124b94b013eSDave Ertman  * ice_dcbnl_getnumtcs - Get max number of traffic classes supported
125b94b013eSDave Ertman  * @dev: pointer to netdev struct
126b94b013eSDave Ertman  * @tcid: TC ID
127b94b013eSDave Ertman  * @num: total number of TCs supported by the adapter
128b94b013eSDave Ertman  *
129b94b013eSDave Ertman  * Return the total number of TCs supported
130b94b013eSDave Ertman  */
131b94b013eSDave Ertman static int
ice_dcbnl_getnumtcs(struct net_device * dev,int __always_unused tcid,u8 * num)132b94b013eSDave Ertman ice_dcbnl_getnumtcs(struct net_device *dev, int __always_unused tcid, u8 *num)
133b94b013eSDave Ertman {
134b94b013eSDave Ertman 	struct ice_pf *pf = ice_netdev_to_pf(dev);
135b94b013eSDave Ertman 
136b94b013eSDave Ertman 	if (!test_bit(ICE_FLAG_DCB_CAPABLE, pf->flags))
137b94b013eSDave Ertman 		return -EINVAL;
138b94b013eSDave Ertman 
1397dcf7aa0SDave Ertman 	*num = pf->hw.func_caps.common_cap.maxtc;
140b94b013eSDave Ertman 	return 0;
141b94b013eSDave Ertman }
142b94b013eSDave Ertman 
143b94b013eSDave Ertman /**
144b94b013eSDave Ertman  * ice_dcbnl_getdcbx - retrieve current DCBX capability
145b94b013eSDave Ertman  * @netdev: pointer to the netdev struct
146b94b013eSDave Ertman  */
ice_dcbnl_getdcbx(struct net_device * netdev)147b94b013eSDave Ertman static u8 ice_dcbnl_getdcbx(struct net_device *netdev)
148b94b013eSDave Ertman {
149b94b013eSDave Ertman 	struct ice_pf *pf = ice_netdev_to_pf(netdev);
150b94b013eSDave Ertman 
151b94b013eSDave Ertman 	return pf->dcbx_cap;
152b94b013eSDave Ertman }
153b94b013eSDave Ertman 
154b94b013eSDave Ertman /**
155b94b013eSDave Ertman  * ice_dcbnl_setdcbx - set required DCBX capability
156b94b013eSDave Ertman  * @netdev: the corresponding netdev
157b94b013eSDave Ertman  * @mode: required mode
158b94b013eSDave Ertman  */
ice_dcbnl_setdcbx(struct net_device * netdev,u8 mode)159b94b013eSDave Ertman static u8 ice_dcbnl_setdcbx(struct net_device *netdev, u8 mode)
160b94b013eSDave Ertman {
161b94b013eSDave Ertman 	struct ice_pf *pf = ice_netdev_to_pf(netdev);
162fc2d1165SChinh T Cao 	struct ice_qos_cfg *qos_cfg;
163b94b013eSDave Ertman 
1640d4907f6SDave Ertman 	/* if FW LLDP agent is running, DCBNL not allowed to change mode */
1650d4907f6SDave Ertman 	if (test_bit(ICE_FLAG_FW_LLDP_AGENT, pf->flags))
1660d4907f6SDave Ertman 		return ICE_DCB_NO_HW_CHG;
1670d4907f6SDave Ertman 
168b94b013eSDave Ertman 	/* No support for LLD_MANAGED modes or CEE+IEEE */
169b94b013eSDave Ertman 	if ((mode & DCB_CAP_DCBX_LLD_MANAGED) ||
170b94b013eSDave Ertman 	    ((mode & DCB_CAP_DCBX_VER_IEEE) && (mode & DCB_CAP_DCBX_VER_CEE)) ||
171b94b013eSDave Ertman 	    !(mode & DCB_CAP_DCBX_HOST))
172b94b013eSDave Ertman 		return ICE_DCB_NO_HW_CHG;
173b94b013eSDave Ertman 
174b94b013eSDave Ertman 	/* Already set to the given mode no change */
175b94b013eSDave Ertman 	if (mode == pf->dcbx_cap)
176b94b013eSDave Ertman 		return ICE_DCB_NO_HW_CHG;
177b94b013eSDave Ertman 
178*ab2ed5d7SDave Ertman 	if (pf->lag && pf->lag->bonded) {
179*ab2ed5d7SDave Ertman 		netdev_err(netdev, "DCB changes not allowed when in a bond\n");
180*ab2ed5d7SDave Ertman 		return ICE_DCB_NO_HW_CHG;
181*ab2ed5d7SDave Ertman 	}
182*ab2ed5d7SDave Ertman 
183fc2d1165SChinh T Cao 	qos_cfg = &pf->hw.port_info->qos_cfg;
1846d39ea19SDave Ertman 
1856d39ea19SDave Ertman 	/* DSCP configuration is not DCBx negotiated */
1862a87bd73SDave Ertman 	if (qos_cfg->local_dcbx_cfg.pfc_mode == ICE_QOS_MODE_DSCP)
1872a87bd73SDave Ertman 		return ICE_DCB_NO_HW_CHG;
1886d39ea19SDave Ertman 
1896d39ea19SDave Ertman 	pf->dcbx_cap = mode;
1906d39ea19SDave Ertman 
1916d39ea19SDave Ertman 	if (mode & DCB_CAP_DCBX_VER_CEE)
192fc2d1165SChinh T Cao 		qos_cfg->local_dcbx_cfg.dcbx_mode = ICE_DCBX_MODE_CEE;
1936d39ea19SDave Ertman 	else
194fc2d1165SChinh T Cao 		qos_cfg->local_dcbx_cfg.dcbx_mode = ICE_DCBX_MODE_IEEE;
195b94b013eSDave Ertman 
1964015d11eSBrett Creeley 	dev_info(ice_pf_to_dev(pf), "DCBx mode = 0x%x\n", mode);
197b94b013eSDave Ertman 	return ICE_DCB_HW_CHG_RST;
198b94b013eSDave Ertman }
199b94b013eSDave Ertman 
200b94b013eSDave Ertman /**
201b94b013eSDave Ertman  * ice_dcbnl_get_perm_hw_addr - MAC address used by DCBX
202b94b013eSDave Ertman  * @netdev: pointer to netdev struct
203b94b013eSDave Ertman  * @perm_addr: buffer to return permanent MAC address
204b94b013eSDave Ertman  */
ice_dcbnl_get_perm_hw_addr(struct net_device * netdev,u8 * perm_addr)205b94b013eSDave Ertman static void ice_dcbnl_get_perm_hw_addr(struct net_device *netdev, u8 *perm_addr)
206b94b013eSDave Ertman {
207b94b013eSDave Ertman 	struct ice_pf *pf = ice_netdev_to_pf(netdev);
208b94b013eSDave Ertman 	struct ice_port_info *pi = pf->hw.port_info;
209b94b013eSDave Ertman 	int i, j;
210b94b013eSDave Ertman 
211b94b013eSDave Ertman 	memset(perm_addr, 0xff, MAX_ADDR_LEN);
212b94b013eSDave Ertman 
213b94b013eSDave Ertman 	for (i = 0; i < netdev->addr_len; i++)
214b94b013eSDave Ertman 		perm_addr[i] = pi->mac.perm_addr[i];
215b94b013eSDave Ertman 
216b94b013eSDave Ertman 	for (j = 0; j < netdev->addr_len; j++, i++)
217b94b013eSDave Ertman 		perm_addr[i] = pi->mac.perm_addr[j];
218b94b013eSDave Ertman }
219b94b013eSDave Ertman 
220b94b013eSDave Ertman /**
221b94b013eSDave Ertman  * ice_get_pfc_delay - Retrieve PFC Link Delay
222b94b013eSDave Ertman  * @hw: pointer to HW struct
223b94b013eSDave Ertman  * @delay: holds the PFC Link Delay value
224b94b013eSDave Ertman  */
ice_get_pfc_delay(struct ice_hw * hw,u16 * delay)225b94b013eSDave Ertman static void ice_get_pfc_delay(struct ice_hw *hw, u16 *delay)
226b94b013eSDave Ertman {
227b94b013eSDave Ertman 	u32 val;
228b94b013eSDave Ertman 
229b94b013eSDave Ertman 	val = rd32(hw, PRTDCB_GENC);
230b94b013eSDave Ertman 	*delay = (u16)((val & PRTDCB_GENC_PFCLDA_M) >> PRTDCB_GENC_PFCLDA_S);
231b94b013eSDave Ertman }
232b94b013eSDave Ertman 
233b94b013eSDave Ertman /**
234b94b013eSDave Ertman  * ice_dcbnl_getpfc - retrieve local IEEE PFC config
235b94b013eSDave Ertman  * @netdev: pointer to netdev struct
236b94b013eSDave Ertman  * @pfc: struct to hold PFC info
237b94b013eSDave Ertman  */
ice_dcbnl_getpfc(struct net_device * netdev,struct ieee_pfc * pfc)238b94b013eSDave Ertman static int ice_dcbnl_getpfc(struct net_device *netdev, struct ieee_pfc *pfc)
239b94b013eSDave Ertman {
240b94b013eSDave Ertman 	struct ice_pf *pf = ice_netdev_to_pf(netdev);
241b94b013eSDave Ertman 	struct ice_port_info *pi = pf->hw.port_info;
242b94b013eSDave Ertman 	struct ice_dcbx_cfg *dcbxcfg;
243b94b013eSDave Ertman 	int i;
244b94b013eSDave Ertman 
245fc2d1165SChinh T Cao 	dcbxcfg = &pi->qos_cfg.local_dcbx_cfg;
246b94b013eSDave Ertman 	pfc->pfc_cap = dcbxcfg->pfc.pfccap;
247b94b013eSDave Ertman 	pfc->pfc_en = dcbxcfg->pfc.pfcena;
248b94b013eSDave Ertman 	pfc->mbc = dcbxcfg->pfc.mbc;
249b94b013eSDave Ertman 	ice_get_pfc_delay(&pf->hw, &pfc->delay);
250b94b013eSDave Ertman 
251b94b013eSDave Ertman 	ice_for_each_traffic_class(i) {
252b94b013eSDave Ertman 		pfc->requests[i] = pf->stats.priority_xoff_tx[i];
253b94b013eSDave Ertman 		pfc->indications[i] = pf->stats.priority_xoff_rx[i];
254b94b013eSDave Ertman 	}
255b94b013eSDave Ertman 
256b94b013eSDave Ertman 	return 0;
257b94b013eSDave Ertman }
258b94b013eSDave Ertman 
259b94b013eSDave Ertman /**
260b94b013eSDave Ertman  * ice_dcbnl_setpfc - set local IEEE PFC config
261b94b013eSDave Ertman  * @netdev: pointer to relevant netdev
262b94b013eSDave Ertman  * @pfc: pointer to struct holding PFC config
263b94b013eSDave Ertman  */
ice_dcbnl_setpfc(struct net_device * netdev,struct ieee_pfc * pfc)264b94b013eSDave Ertman static int ice_dcbnl_setpfc(struct net_device *netdev, struct ieee_pfc *pfc)
265b94b013eSDave Ertman {
266b94b013eSDave Ertman 	struct ice_pf *pf = ice_netdev_to_pf(netdev);
267b94b013eSDave Ertman 	struct ice_dcbx_cfg *new_cfg;
268b94b013eSDave Ertman 	int err;
269b94b013eSDave Ertman 
270b94b013eSDave Ertman 	if ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) ||
271b94b013eSDave Ertman 	    !(pf->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
272b94b013eSDave Ertman 		return -EINVAL;
273b94b013eSDave Ertman 
274*ab2ed5d7SDave Ertman 	if (pf->lag && pf->lag->bonded) {
275*ab2ed5d7SDave Ertman 		netdev_err(netdev, "DCB changes not allowed when in a bond\n");
276*ab2ed5d7SDave Ertman 		return -EINVAL;
277*ab2ed5d7SDave Ertman 	}
278*ab2ed5d7SDave Ertman 
279b94b013eSDave Ertman 	mutex_lock(&pf->tc_mutex);
280b94b013eSDave Ertman 
281fc2d1165SChinh T Cao 	new_cfg = &pf->hw.port_info->qos_cfg.desired_dcbx_cfg;
282b94b013eSDave Ertman 
283b94b013eSDave Ertman 	if (pfc->pfc_cap)
284b94b013eSDave Ertman 		new_cfg->pfc.pfccap = pfc->pfc_cap;
285b94b013eSDave Ertman 	else
286b94b013eSDave Ertman 		new_cfg->pfc.pfccap = pf->hw.func_caps.common_cap.maxtc;
287b94b013eSDave Ertman 
288b94b013eSDave Ertman 	new_cfg->pfc.pfcena = pfc->pfc_en;
289b94b013eSDave Ertman 
290b94b013eSDave Ertman 	err = ice_pf_dcb_cfg(pf, new_cfg, true);
291b94b013eSDave Ertman 	if (err == ICE_DCB_HW_CHG_RST)
292b94b013eSDave Ertman 		ice_dcbnl_devreset(netdev);
293b94b013eSDave Ertman 	if (err == ICE_DCB_NO_HW_CHG)
294b94b013eSDave Ertman 		err = ICE_DCB_HW_CHG_RST;
295b94b013eSDave Ertman 	mutex_unlock(&pf->tc_mutex);
296b94b013eSDave Ertman 	return err;
297b94b013eSDave Ertman }
298b94b013eSDave Ertman 
299b94b013eSDave Ertman /**
300b94b013eSDave Ertman  * ice_dcbnl_get_pfc_cfg - Get CEE PFC config
301b94b013eSDave Ertman  * @netdev: pointer to netdev struct
302b94b013eSDave Ertman  * @prio: corresponding user priority
303b94b013eSDave Ertman  * @setting: the PFC setting for given priority
304b94b013eSDave Ertman  */
305b94b013eSDave Ertman static void
ice_dcbnl_get_pfc_cfg(struct net_device * netdev,int prio,u8 * setting)306b94b013eSDave Ertman ice_dcbnl_get_pfc_cfg(struct net_device *netdev, int prio, u8 *setting)
307b94b013eSDave Ertman {
308b94b013eSDave Ertman 	struct ice_pf *pf = ice_netdev_to_pf(netdev);
309b94b013eSDave Ertman 	struct ice_port_info *pi = pf->hw.port_info;
310b94b013eSDave Ertman 
311b94b013eSDave Ertman 	if ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) ||
312b94b013eSDave Ertman 	    !(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
313b94b013eSDave Ertman 		return;
314b94b013eSDave Ertman 
315b94b013eSDave Ertman 	if (prio >= ICE_MAX_USER_PRIORITY)
316b94b013eSDave Ertman 		return;
317b94b013eSDave Ertman 
318fc2d1165SChinh T Cao 	*setting = (pi->qos_cfg.local_dcbx_cfg.pfc.pfcena >> prio) & 0x1;
31919cce2c6SAnirudh Venkataramanan 	dev_dbg(ice_pf_to_dev(pf), "Get PFC Config up=%d, setting=%d, pfcenable=0x%x\n",
320fc2d1165SChinh T Cao 		prio, *setting, pi->qos_cfg.local_dcbx_cfg.pfc.pfcena);
321b94b013eSDave Ertman }
322b94b013eSDave Ertman 
323b94b013eSDave Ertman /**
324b94b013eSDave Ertman  * ice_dcbnl_set_pfc_cfg - Set CEE PFC config
325b94b013eSDave Ertman  * @netdev: the corresponding netdev
326b94b013eSDave Ertman  * @prio: User Priority
327b94b013eSDave Ertman  * @set: PFC setting to apply
328b94b013eSDave Ertman  */
ice_dcbnl_set_pfc_cfg(struct net_device * netdev,int prio,u8 set)329b94b013eSDave Ertman static void ice_dcbnl_set_pfc_cfg(struct net_device *netdev, int prio, u8 set)
330b94b013eSDave Ertman {
331b94b013eSDave Ertman 	struct ice_pf *pf = ice_netdev_to_pf(netdev);
332b94b013eSDave Ertman 	struct ice_dcbx_cfg *new_cfg;
333b94b013eSDave Ertman 
334b94b013eSDave Ertman 	if ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) ||
335b94b013eSDave Ertman 	    !(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
336b94b013eSDave Ertman 		return;
337b94b013eSDave Ertman 
338b94b013eSDave Ertman 	if (prio >= ICE_MAX_USER_PRIORITY)
339b94b013eSDave Ertman 		return;
340b94b013eSDave Ertman 
341*ab2ed5d7SDave Ertman 	if (pf->lag && pf->lag->bonded) {
342*ab2ed5d7SDave Ertman 		netdev_err(netdev, "DCB changes not allowed when in a bond\n");
343*ab2ed5d7SDave Ertman 		return;
344*ab2ed5d7SDave Ertman 	}
345*ab2ed5d7SDave Ertman 
346fc2d1165SChinh T Cao 	new_cfg = &pf->hw.port_info->qos_cfg.desired_dcbx_cfg;
347b94b013eSDave Ertman 
348b94b013eSDave Ertman 	new_cfg->pfc.pfccap = pf->hw.func_caps.common_cap.maxtc;
349b94b013eSDave Ertman 	if (set)
350b94b013eSDave Ertman 		new_cfg->pfc.pfcena |= BIT(prio);
351b94b013eSDave Ertman 	else
352b94b013eSDave Ertman 		new_cfg->pfc.pfcena &= ~BIT(prio);
353b94b013eSDave Ertman 
3544015d11eSBrett Creeley 	dev_dbg(ice_pf_to_dev(pf), "Set PFC config UP:%d set:%d pfcena:0x%x\n",
355b94b013eSDave Ertman 		prio, set, new_cfg->pfc.pfcena);
356b94b013eSDave Ertman }
357b94b013eSDave Ertman 
358b94b013eSDave Ertman /**
359b94b013eSDave Ertman  * ice_dcbnl_getpfcstate - get CEE PFC mode
360b94b013eSDave Ertman  * @netdev: pointer to netdev struct
361b94b013eSDave Ertman  */
ice_dcbnl_getpfcstate(struct net_device * netdev)362b94b013eSDave Ertman static u8 ice_dcbnl_getpfcstate(struct net_device *netdev)
363b94b013eSDave Ertman {
364b94b013eSDave Ertman 	struct ice_pf *pf = ice_netdev_to_pf(netdev);
365b94b013eSDave Ertman 	struct ice_port_info *pi = pf->hw.port_info;
366b94b013eSDave Ertman 
367b94b013eSDave Ertman 	/* Return enabled if any UP enabled for PFC */
368fc2d1165SChinh T Cao 	if (pi->qos_cfg.local_dcbx_cfg.pfc.pfcena)
369b94b013eSDave Ertman 		return 1;
370b94b013eSDave Ertman 
371b94b013eSDave Ertman 	return 0;
372b94b013eSDave Ertman }
373b94b013eSDave Ertman 
374b94b013eSDave Ertman /**
375b94b013eSDave Ertman  * ice_dcbnl_getstate - get DCB enabled state
376b94b013eSDave Ertman  * @netdev: pointer to netdev struct
377b94b013eSDave Ertman  */
ice_dcbnl_getstate(struct net_device * netdev)378b94b013eSDave Ertman static u8 ice_dcbnl_getstate(struct net_device *netdev)
379b94b013eSDave Ertman {
380b94b013eSDave Ertman 	struct ice_pf *pf = ice_netdev_to_pf(netdev);
381b94b013eSDave Ertman 	u8 state = 0;
382b94b013eSDave Ertman 
383b94b013eSDave Ertman 	state = test_bit(ICE_FLAG_DCB_CAPABLE, pf->flags);
384b94b013eSDave Ertman 
3854015d11eSBrett Creeley 	dev_dbg(ice_pf_to_dev(pf), "DCB enabled state = %d\n", state);
386b94b013eSDave Ertman 	return state;
387b94b013eSDave Ertman }
388b94b013eSDave Ertman 
389b94b013eSDave Ertman /**
390b94b013eSDave Ertman  * ice_dcbnl_setstate - Set CEE DCB state
391b94b013eSDave Ertman  * @netdev: pointer to relevant netdev
392b94b013eSDave Ertman  * @state: state value to set
393b94b013eSDave Ertman  */
ice_dcbnl_setstate(struct net_device * netdev,u8 state)394b94b013eSDave Ertman static u8 ice_dcbnl_setstate(struct net_device *netdev, u8 state)
395b94b013eSDave Ertman {
396b94b013eSDave Ertman 	struct ice_pf *pf = ice_netdev_to_pf(netdev);
397b94b013eSDave Ertman 
398b94b013eSDave Ertman 	if ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) ||
399b94b013eSDave Ertman 	    !(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
400b94b013eSDave Ertman 		return ICE_DCB_NO_HW_CHG;
401b94b013eSDave Ertman 
402*ab2ed5d7SDave Ertman 	if (pf->lag && pf->lag->bonded) {
403*ab2ed5d7SDave Ertman 		netdev_err(netdev, "DCB changes not allowed when in a bond\n");
404*ab2ed5d7SDave Ertman 		return ICE_DCB_NO_HW_CHG;
405*ab2ed5d7SDave Ertman 	}
406*ab2ed5d7SDave Ertman 
407b94b013eSDave Ertman 	/* Nothing to do */
408b94b013eSDave Ertman 	if (!!state == test_bit(ICE_FLAG_DCB_ENA, pf->flags))
409b94b013eSDave Ertman 		return ICE_DCB_NO_HW_CHG;
410b94b013eSDave Ertman 
411b94b013eSDave Ertman 	if (state) {
412b94b013eSDave Ertman 		set_bit(ICE_FLAG_DCB_ENA, pf->flags);
413fc2d1165SChinh T Cao 		memcpy(&pf->hw.port_info->qos_cfg.desired_dcbx_cfg,
414fc2d1165SChinh T Cao 		       &pf->hw.port_info->qos_cfg.local_dcbx_cfg,
415b94b013eSDave Ertman 		       sizeof(struct ice_dcbx_cfg));
416b94b013eSDave Ertman 	} else {
417b94b013eSDave Ertman 		clear_bit(ICE_FLAG_DCB_ENA, pf->flags);
418b94b013eSDave Ertman 	}
419b94b013eSDave Ertman 
420b94b013eSDave Ertman 	return ICE_DCB_HW_CHG;
421b94b013eSDave Ertman }
422b94b013eSDave Ertman 
423b94b013eSDave Ertman /**
424b94b013eSDave Ertman  * ice_dcbnl_get_pg_tc_cfg_tx - get CEE PG Tx config
425b94b013eSDave Ertman  * @netdev: pointer to netdev struct
426b94b013eSDave Ertman  * @prio: the corresponding user priority
427b94b013eSDave Ertman  * @prio_type: traffic priority type
428b94b013eSDave Ertman  * @pgid: the BW group ID the traffic class belongs to
429b94b013eSDave Ertman  * @bw_pct: BW percentage for the corresponding BWG
430b94b013eSDave Ertman  * @up_map: prio mapped to corresponding TC
431b94b013eSDave Ertman  */
432b94b013eSDave Ertman static void
ice_dcbnl_get_pg_tc_cfg_tx(struct net_device * netdev,int prio,u8 __always_unused * prio_type,u8 * pgid,u8 __always_unused * bw_pct,u8 __always_unused * up_map)433b94b013eSDave Ertman ice_dcbnl_get_pg_tc_cfg_tx(struct net_device *netdev, int prio,
434b94b013eSDave Ertman 			   u8 __always_unused *prio_type, u8 *pgid,
435b94b013eSDave Ertman 			   u8 __always_unused *bw_pct,
436b94b013eSDave Ertman 			   u8 __always_unused *up_map)
437b94b013eSDave Ertman {
438b94b013eSDave Ertman 	struct ice_pf *pf = ice_netdev_to_pf(netdev);
439b94b013eSDave Ertman 	struct ice_port_info *pi = pf->hw.port_info;
440b94b013eSDave Ertman 
441b94b013eSDave Ertman 	if ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) ||
442b94b013eSDave Ertman 	    !(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
443b94b013eSDave Ertman 		return;
444b94b013eSDave Ertman 
445b94b013eSDave Ertman 	if (prio >= ICE_MAX_USER_PRIORITY)
446b94b013eSDave Ertman 		return;
447b94b013eSDave Ertman 
448fc2d1165SChinh T Cao 	*pgid = pi->qos_cfg.local_dcbx_cfg.etscfg.prio_table[prio];
44919cce2c6SAnirudh Venkataramanan 	dev_dbg(ice_pf_to_dev(pf), "Get PG config prio=%d tc=%d\n", prio,
45019cce2c6SAnirudh Venkataramanan 		*pgid);
451b94b013eSDave Ertman }
452b94b013eSDave Ertman 
453b94b013eSDave Ertman /**
454b94b013eSDave Ertman  * ice_dcbnl_set_pg_tc_cfg_tx - set CEE PG Tx config
455b94b013eSDave Ertman  * @netdev: pointer to relevant netdev
456b94b013eSDave Ertman  * @tc: the corresponding traffic class
457b94b013eSDave Ertman  * @prio_type: the traffic priority type
458b94b013eSDave Ertman  * @bwg_id: the BW group ID the TC belongs to
459b94b013eSDave Ertman  * @bw_pct: the BW perventage for the BWG
460b94b013eSDave Ertman  * @up_map: prio mapped to corresponding TC
461b94b013eSDave Ertman  */
462b94b013eSDave Ertman static void
ice_dcbnl_set_pg_tc_cfg_tx(struct net_device * netdev,int tc,u8 __always_unused prio_type,u8 __always_unused bwg_id,u8 __always_unused bw_pct,u8 up_map)463b94b013eSDave Ertman ice_dcbnl_set_pg_tc_cfg_tx(struct net_device *netdev, int tc,
464b94b013eSDave Ertman 			   u8 __always_unused prio_type,
465b94b013eSDave Ertman 			   u8 __always_unused bwg_id,
466b94b013eSDave Ertman 			   u8 __always_unused bw_pct, u8 up_map)
467b94b013eSDave Ertman {
468b94b013eSDave Ertman 	struct ice_pf *pf = ice_netdev_to_pf(netdev);
469b94b013eSDave Ertman 	struct ice_dcbx_cfg *new_cfg;
470b94b013eSDave Ertman 	int i;
471b94b013eSDave Ertman 
472b94b013eSDave Ertman 	if ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) ||
473b94b013eSDave Ertman 	    !(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
474b94b013eSDave Ertman 		return;
475b94b013eSDave Ertman 
476b94b013eSDave Ertman 	if (tc >= ICE_MAX_TRAFFIC_CLASS)
477b94b013eSDave Ertman 		return;
478b94b013eSDave Ertman 
479*ab2ed5d7SDave Ertman 	if (pf->lag && pf->lag->bonded) {
480*ab2ed5d7SDave Ertman 		netdev_err(netdev, "DCB changes not allowed when in a bond\n");
481*ab2ed5d7SDave Ertman 		return;
482*ab2ed5d7SDave Ertman 	}
483*ab2ed5d7SDave Ertman 
484fc2d1165SChinh T Cao 	new_cfg = &pf->hw.port_info->qos_cfg.desired_dcbx_cfg;
485b94b013eSDave Ertman 
486b94b013eSDave Ertman 	/* prio_type, bwg_id and bw_pct per UP are not supported */
487b94b013eSDave Ertman 
488b94b013eSDave Ertman 	ice_for_each_traffic_class(i) {
489b94b013eSDave Ertman 		if (up_map & BIT(i))
490b94b013eSDave Ertman 			new_cfg->etscfg.prio_table[i] = tc;
491b94b013eSDave Ertman 	}
492b94b013eSDave Ertman 	new_cfg->etscfg.tsatable[tc] = ICE_IEEE_TSA_ETS;
493b94b013eSDave Ertman }
494b94b013eSDave Ertman 
495b94b013eSDave Ertman /**
496b94b013eSDave Ertman  * ice_dcbnl_get_pg_bwg_cfg_tx - Get CEE PGBW config
497b94b013eSDave Ertman  * @netdev: pointer to the netdev struct
498b94b013eSDave Ertman  * @pgid: corresponding traffic class
499b94b013eSDave Ertman  * @bw_pct: the BW percentage for the corresponding TC
500b94b013eSDave Ertman  */
501b94b013eSDave Ertman static void
ice_dcbnl_get_pg_bwg_cfg_tx(struct net_device * netdev,int pgid,u8 * bw_pct)502b94b013eSDave Ertman ice_dcbnl_get_pg_bwg_cfg_tx(struct net_device *netdev, int pgid, u8 *bw_pct)
503b94b013eSDave Ertman {
504b94b013eSDave Ertman 	struct ice_pf *pf = ice_netdev_to_pf(netdev);
505b94b013eSDave Ertman 	struct ice_port_info *pi = pf->hw.port_info;
506b94b013eSDave Ertman 
507b94b013eSDave Ertman 	if ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) ||
508b94b013eSDave Ertman 	    !(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
509b94b013eSDave Ertman 		return;
510b94b013eSDave Ertman 
511b94b013eSDave Ertman 	if (pgid >= ICE_MAX_TRAFFIC_CLASS)
512b94b013eSDave Ertman 		return;
513b94b013eSDave Ertman 
514fc2d1165SChinh T Cao 	*bw_pct = pi->qos_cfg.local_dcbx_cfg.etscfg.tcbwtable[pgid];
5154015d11eSBrett Creeley 	dev_dbg(ice_pf_to_dev(pf), "Get PG BW config tc=%d bw_pct=%d\n",
516b94b013eSDave Ertman 		pgid, *bw_pct);
517b94b013eSDave Ertman }
518b94b013eSDave Ertman 
519b94b013eSDave Ertman /**
520b94b013eSDave Ertman  * ice_dcbnl_set_pg_bwg_cfg_tx - set CEE PG Tx BW config
521b94b013eSDave Ertman  * @netdev: the corresponding netdev
522b94b013eSDave Ertman  * @pgid: Correspongind traffic class
523b94b013eSDave Ertman  * @bw_pct: the BW percentage for the specified TC
524b94b013eSDave Ertman  */
525b94b013eSDave Ertman static void
ice_dcbnl_set_pg_bwg_cfg_tx(struct net_device * netdev,int pgid,u8 bw_pct)526b94b013eSDave Ertman ice_dcbnl_set_pg_bwg_cfg_tx(struct net_device *netdev, int pgid, u8 bw_pct)
527b94b013eSDave Ertman {
528b94b013eSDave Ertman 	struct ice_pf *pf = ice_netdev_to_pf(netdev);
529b94b013eSDave Ertman 	struct ice_dcbx_cfg *new_cfg;
530b94b013eSDave Ertman 
531b94b013eSDave Ertman 	if ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) ||
532b94b013eSDave Ertman 	    !(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
533b94b013eSDave Ertman 		return;
534b94b013eSDave Ertman 
535b94b013eSDave Ertman 	if (pgid >= ICE_MAX_TRAFFIC_CLASS)
536b94b013eSDave Ertman 		return;
537b94b013eSDave Ertman 
538*ab2ed5d7SDave Ertman 	if (pf->lag && pf->lag->bonded) {
539*ab2ed5d7SDave Ertman 		netdev_err(netdev, "DCB changes not allowed when in a bond\n");
540*ab2ed5d7SDave Ertman 		return;
541*ab2ed5d7SDave Ertman 	}
542*ab2ed5d7SDave Ertman 
543fc2d1165SChinh T Cao 	new_cfg = &pf->hw.port_info->qos_cfg.desired_dcbx_cfg;
544b94b013eSDave Ertman 
545b94b013eSDave Ertman 	new_cfg->etscfg.tcbwtable[pgid] = bw_pct;
546b94b013eSDave Ertman }
547b94b013eSDave Ertman 
548b94b013eSDave Ertman /**
549b94b013eSDave Ertman  * ice_dcbnl_get_pg_tc_cfg_rx - Get CEE PG Rx config
550b94b013eSDave Ertman  * @netdev: pointer to netdev struct
551b94b013eSDave Ertman  * @prio: the corresponding user priority
552b94b013eSDave Ertman  * @prio_type: the traffic priority type
553b94b013eSDave Ertman  * @pgid: the PG ID
554b94b013eSDave Ertman  * @bw_pct: the BW percentage for the corresponding BWG
555b94b013eSDave Ertman  * @up_map: prio mapped to corresponding TC
556b94b013eSDave Ertman  */
557b94b013eSDave Ertman static void
ice_dcbnl_get_pg_tc_cfg_rx(struct net_device * netdev,int prio,u8 __always_unused * prio_type,u8 * pgid,u8 __always_unused * bw_pct,u8 __always_unused * up_map)558b94b013eSDave Ertman ice_dcbnl_get_pg_tc_cfg_rx(struct net_device *netdev, int prio,
559b94b013eSDave Ertman 			   u8 __always_unused *prio_type, u8 *pgid,
560b94b013eSDave Ertman 			   u8 __always_unused *bw_pct,
561b94b013eSDave Ertman 			   u8 __always_unused *up_map)
562b94b013eSDave Ertman {
563b94b013eSDave Ertman 	struct ice_pf *pf = ice_netdev_to_pf(netdev);
564b94b013eSDave Ertman 	struct ice_port_info *pi = pf->hw.port_info;
565b94b013eSDave Ertman 
566b94b013eSDave Ertman 	if ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) ||
567b94b013eSDave Ertman 	    !(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
568b94b013eSDave Ertman 		return;
569b94b013eSDave Ertman 
570b94b013eSDave Ertman 	if (prio >= ICE_MAX_USER_PRIORITY)
571b94b013eSDave Ertman 		return;
572b94b013eSDave Ertman 
573fc2d1165SChinh T Cao 	*pgid = pi->qos_cfg.local_dcbx_cfg.etscfg.prio_table[prio];
574b94b013eSDave Ertman }
575b94b013eSDave Ertman 
576b94b013eSDave Ertman /**
577c8608b50SAvinash JD  * ice_dcbnl_set_pg_tc_cfg_rx
578c8608b50SAvinash JD  * @netdev: relevant netdev struct
579c8608b50SAvinash JD  * @prio: corresponding user priority
580c8608b50SAvinash JD  * @prio_type: the traffic priority type
581c8608b50SAvinash JD  * @pgid: the PG ID
582c8608b50SAvinash JD  * @bw_pct: BW percentage for corresponding BWG
583c8608b50SAvinash JD  * @up_map: prio mapped to corresponding TC
584c8608b50SAvinash JD  *
585c8608b50SAvinash JD  * lldpad requires this function pointer to be non-NULL to complete CEE config.
586c8608b50SAvinash JD  */
587c8608b50SAvinash JD static void
ice_dcbnl_set_pg_tc_cfg_rx(struct net_device * netdev,int __always_unused prio,u8 __always_unused prio_type,u8 __always_unused pgid,u8 __always_unused bw_pct,u8 __always_unused up_map)588c8608b50SAvinash JD ice_dcbnl_set_pg_tc_cfg_rx(struct net_device *netdev,
589c8608b50SAvinash JD 			   int __always_unused prio,
590c8608b50SAvinash JD 			   u8 __always_unused prio_type,
591c8608b50SAvinash JD 			   u8 __always_unused pgid,
592c8608b50SAvinash JD 			   u8 __always_unused bw_pct,
593c8608b50SAvinash JD 			   u8 __always_unused up_map)
594c8608b50SAvinash JD {
595c8608b50SAvinash JD 	struct ice_pf *pf = ice_netdev_to_pf(netdev);
596c8608b50SAvinash JD 
597c8608b50SAvinash JD 	dev_dbg(ice_pf_to_dev(pf), "Rx TC PG Config Not Supported.\n");
598c8608b50SAvinash JD }
599c8608b50SAvinash JD 
600c8608b50SAvinash JD /**
601b94b013eSDave Ertman  * ice_dcbnl_get_pg_bwg_cfg_rx - Get CEE PG BW Rx config
602b94b013eSDave Ertman  * @netdev: pointer to netdev struct
603b94b013eSDave Ertman  * @pgid: the corresponding traffic class
604b94b013eSDave Ertman  * @bw_pct: the BW percentage for the corresponding TC
605b94b013eSDave Ertman  */
606b94b013eSDave Ertman static void
ice_dcbnl_get_pg_bwg_cfg_rx(struct net_device * netdev,int __always_unused pgid,u8 * bw_pct)607b94b013eSDave Ertman ice_dcbnl_get_pg_bwg_cfg_rx(struct net_device *netdev, int __always_unused pgid,
608b94b013eSDave Ertman 			    u8 *bw_pct)
609b94b013eSDave Ertman {
610b94b013eSDave Ertman 	struct ice_pf *pf = ice_netdev_to_pf(netdev);
611b94b013eSDave Ertman 
612b94b013eSDave Ertman 	if ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) ||
613b94b013eSDave Ertman 	    !(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
614b94b013eSDave Ertman 		return;
615b94b013eSDave Ertman 
616b94b013eSDave Ertman 	*bw_pct = 0;
617b94b013eSDave Ertman }
618b94b013eSDave Ertman 
619b94b013eSDave Ertman /**
620c8608b50SAvinash JD  * ice_dcbnl_set_pg_bwg_cfg_rx
621c8608b50SAvinash JD  * @netdev: the corresponding netdev
622c8608b50SAvinash JD  * @pgid: corresponding TC
623c8608b50SAvinash JD  * @bw_pct: BW percentage for given TC
624c8608b50SAvinash JD  *
625c8608b50SAvinash JD  * lldpad requires this function pointer to be non-NULL to complete CEE config.
626c8608b50SAvinash JD  */
627c8608b50SAvinash JD static void
ice_dcbnl_set_pg_bwg_cfg_rx(struct net_device * netdev,int __always_unused pgid,u8 __always_unused bw_pct)628c8608b50SAvinash JD ice_dcbnl_set_pg_bwg_cfg_rx(struct net_device *netdev, int __always_unused pgid,
629c8608b50SAvinash JD 			    u8 __always_unused bw_pct)
630c8608b50SAvinash JD {
631c8608b50SAvinash JD 	struct ice_pf *pf = ice_netdev_to_pf(netdev);
632c8608b50SAvinash JD 
633c8608b50SAvinash JD 	dev_dbg(ice_pf_to_dev(pf), "Rx BWG PG Config Not Supported.\n");
634c8608b50SAvinash JD }
635c8608b50SAvinash JD 
636c8608b50SAvinash JD /**
637b94b013eSDave Ertman  * ice_dcbnl_get_cap - Get DCBX capabilities of adapter
638b94b013eSDave Ertman  * @netdev: pointer to netdev struct
639b94b013eSDave Ertman  * @capid: the capability type
640b94b013eSDave Ertman  * @cap: the capability value
641b94b013eSDave Ertman  */
ice_dcbnl_get_cap(struct net_device * netdev,int capid,u8 * cap)642b94b013eSDave Ertman static u8 ice_dcbnl_get_cap(struct net_device *netdev, int capid, u8 *cap)
643b94b013eSDave Ertman {
644b94b013eSDave Ertman 	struct ice_pf *pf = ice_netdev_to_pf(netdev);
645b94b013eSDave Ertman 
646b94b013eSDave Ertman 	if (!(test_bit(ICE_FLAG_DCB_CAPABLE, pf->flags)))
647b94b013eSDave Ertman 		return ICE_DCB_NO_HW_CHG;
648b94b013eSDave Ertman 
649b94b013eSDave Ertman 	switch (capid) {
650b94b013eSDave Ertman 	case DCB_CAP_ATTR_PG:
651b94b013eSDave Ertman 		*cap = true;
652b94b013eSDave Ertman 		break;
653b94b013eSDave Ertman 	case DCB_CAP_ATTR_PFC:
654b94b013eSDave Ertman 		*cap = true;
655b94b013eSDave Ertman 		break;
656b94b013eSDave Ertman 	case DCB_CAP_ATTR_UP2TC:
657b94b013eSDave Ertman 		*cap = false;
658b94b013eSDave Ertman 		break;
659b94b013eSDave Ertman 	case DCB_CAP_ATTR_PG_TCS:
660b94b013eSDave Ertman 		*cap = 0x80;
661b94b013eSDave Ertman 		break;
662b94b013eSDave Ertman 	case DCB_CAP_ATTR_PFC_TCS:
663b94b013eSDave Ertman 		*cap = 0x80;
664b94b013eSDave Ertman 		break;
665b94b013eSDave Ertman 	case DCB_CAP_ATTR_GSP:
666b94b013eSDave Ertman 		*cap = false;
667b94b013eSDave Ertman 		break;
668b94b013eSDave Ertman 	case DCB_CAP_ATTR_BCN:
669b94b013eSDave Ertman 		*cap = false;
670b94b013eSDave Ertman 		break;
671b94b013eSDave Ertman 	case DCB_CAP_ATTR_DCBX:
672b94b013eSDave Ertman 		*cap = pf->dcbx_cap;
673b94b013eSDave Ertman 		break;
674b94b013eSDave Ertman 	default:
675b94b013eSDave Ertman 		*cap = false;
676b94b013eSDave Ertman 		break;
677b94b013eSDave Ertman 	}
678b94b013eSDave Ertman 
6794015d11eSBrett Creeley 	dev_dbg(ice_pf_to_dev(pf), "DCBX Get Capability cap=%d capval=0x%x\n",
680b94b013eSDave Ertman 		capid, *cap);
681b94b013eSDave Ertman 	return 0;
682b94b013eSDave Ertman }
683b94b013eSDave Ertman 
684b94b013eSDave Ertman /**
685b94b013eSDave Ertman  * ice_dcbnl_getapp - get CEE APP
686b94b013eSDave Ertman  * @netdev: pointer to netdev struct
687b94b013eSDave Ertman  * @idtype: the App selector
688b94b013eSDave Ertman  * @id: the App ethtype or port number
689b94b013eSDave Ertman  */
ice_dcbnl_getapp(struct net_device * netdev,u8 idtype,u16 id)690b94b013eSDave Ertman static int ice_dcbnl_getapp(struct net_device *netdev, u8 idtype, u16 id)
691b94b013eSDave Ertman {
692b94b013eSDave Ertman 	struct ice_pf *pf = ice_netdev_to_pf(netdev);
693b94b013eSDave Ertman 	struct dcb_app app = {
694b94b013eSDave Ertman 				.selector = idtype,
695b94b013eSDave Ertman 				.protocol = id,
696b94b013eSDave Ertman 			     };
697b94b013eSDave Ertman 
698b94b013eSDave Ertman 	if ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) ||
699b94b013eSDave Ertman 	    !(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
700b94b013eSDave Ertman 		return -EINVAL;
701b94b013eSDave Ertman 
702b94b013eSDave Ertman 	return dcb_getapp(netdev, &app);
703b94b013eSDave Ertman }
704b94b013eSDave Ertman 
705b94b013eSDave Ertman /**
706b94b013eSDave Ertman  * ice_dcbnl_find_app - Search for APP in given DCB config
707b94b013eSDave Ertman  * @cfg: struct to hold DCBX config
708b94b013eSDave Ertman  * @app: struct to hold app data to look for
709b94b013eSDave Ertman  */
710b94b013eSDave Ertman static bool
ice_dcbnl_find_app(struct ice_dcbx_cfg * cfg,struct ice_dcb_app_priority_table * app)711b94b013eSDave Ertman ice_dcbnl_find_app(struct ice_dcbx_cfg *cfg,
712b94b013eSDave Ertman 		   struct ice_dcb_app_priority_table *app)
713b94b013eSDave Ertman {
714c1e08830SJesse Brandeburg 	unsigned int i;
715b94b013eSDave Ertman 
716b94b013eSDave Ertman 	for (i = 0; i < cfg->numapps; i++) {
717b94b013eSDave Ertman 		if (app->selector == cfg->app[i].selector &&
718b94b013eSDave Ertman 		    app->prot_id == cfg->app[i].prot_id &&
719b94b013eSDave Ertman 		    app->priority == cfg->app[i].priority)
720b94b013eSDave Ertman 			return true;
721b94b013eSDave Ertman 	}
722b94b013eSDave Ertman 
723b94b013eSDave Ertman 	return false;
724b94b013eSDave Ertman }
725b94b013eSDave Ertman 
7262a87bd73SDave Ertman #define ICE_BYTES_PER_DSCP_VAL		8
7272a87bd73SDave Ertman 
728b94b013eSDave Ertman /**
729b94b013eSDave Ertman  * ice_dcbnl_setapp - set local IEEE App config
730b94b013eSDave Ertman  * @netdev: relevant netdev struct
731b94b013eSDave Ertman  * @app: struct to hold app config info
732b94b013eSDave Ertman  */
ice_dcbnl_setapp(struct net_device * netdev,struct dcb_app * app)733b94b013eSDave Ertman static int ice_dcbnl_setapp(struct net_device *netdev, struct dcb_app *app)
734b94b013eSDave Ertman {
735b94b013eSDave Ertman 	struct ice_pf *pf = ice_netdev_to_pf(netdev);
736b94b013eSDave Ertman 	struct ice_dcb_app_priority_table new_app;
737b94b013eSDave Ertman 	struct ice_dcbx_cfg *old_cfg, *new_cfg;
7382a87bd73SDave Ertman 	u8 max_tc;
739b94b013eSDave Ertman 	int ret;
740b94b013eSDave Ertman 
7412a87bd73SDave Ertman 	/* ONLY DSCP APP TLVs have operational significance */
7422a87bd73SDave Ertman 	if (app->selector != IEEE_8021QAZ_APP_SEL_DSCP)
743b94b013eSDave Ertman 		return -EINVAL;
744b94b013eSDave Ertman 
7452a87bd73SDave Ertman 	/* only allow APP TLVs in SW Mode */
7462a87bd73SDave Ertman 	if (pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) {
7472a87bd73SDave Ertman 		netdev_err(netdev, "can't do DSCP QoS when FW DCB agent active\n");
7482a87bd73SDave Ertman 		return -EINVAL;
7492a87bd73SDave Ertman 	}
7502a87bd73SDave Ertman 
7512a87bd73SDave Ertman 	if (!(pf->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
7522a87bd73SDave Ertman 		return -EINVAL;
7532a87bd73SDave Ertman 
75440b24760SAnirudh Venkataramanan 	if (!ice_is_feature_supported(pf, ICE_F_DSCP))
75540b24760SAnirudh Venkataramanan 		return -EOPNOTSUPP;
75640b24760SAnirudh Venkataramanan 
7572a87bd73SDave Ertman 	if (app->protocol >= ICE_DSCP_NUM_VAL) {
7582a87bd73SDave Ertman 		netdev_err(netdev, "DSCP value 0x%04X out of range\n",
7592a87bd73SDave Ertman 			   app->protocol);
7602a87bd73SDave Ertman 		return -EINVAL;
7612a87bd73SDave Ertman 	}
7622a87bd73SDave Ertman 
763*ab2ed5d7SDave Ertman 	if (pf->lag && pf->lag->bonded) {
764*ab2ed5d7SDave Ertman 		netdev_err(netdev, "DCB changes not allowed when in a bond\n");
765*ab2ed5d7SDave Ertman 		return -EINVAL;
766*ab2ed5d7SDave Ertman 	}
767*ab2ed5d7SDave Ertman 
7682a87bd73SDave Ertman 	max_tc = pf->hw.func_caps.common_cap.maxtc;
7692a87bd73SDave Ertman 	if (app->priority >= max_tc) {
7702a87bd73SDave Ertman 		netdev_err(netdev, "TC %d out of range, max TC %d\n",
7712a87bd73SDave Ertman 			   app->priority, max_tc);
7722a87bd73SDave Ertman 		return -EINVAL;
7732a87bd73SDave Ertman 	}
7742a87bd73SDave Ertman 
7752a87bd73SDave Ertman 	/* grab TC mutex */
776b94b013eSDave Ertman 	mutex_lock(&pf->tc_mutex);
777b94b013eSDave Ertman 
778fc2d1165SChinh T Cao 	new_cfg = &pf->hw.port_info->qos_cfg.desired_dcbx_cfg;
779fc2d1165SChinh T Cao 	old_cfg = &pf->hw.port_info->qos_cfg.local_dcbx_cfg;
780b94b013eSDave Ertman 
781b94b013eSDave Ertman 	ret = dcb_ieee_setapp(netdev, app);
782b94b013eSDave Ertman 	if (ret)
783b94b013eSDave Ertman 		goto setapp_out;
784b94b013eSDave Ertman 
7852a87bd73SDave Ertman 	if (test_and_set_bit(app->protocol, new_cfg->dscp_mapped)) {
7862a87bd73SDave Ertman 		netdev_err(netdev, "DSCP value 0x%04X already user mapped\n",
7872a87bd73SDave Ertman 			   app->protocol);
7882a87bd73SDave Ertman 		ret = dcb_ieee_delapp(netdev, app);
7892a87bd73SDave Ertman 		if (ret)
7902a87bd73SDave Ertman 			netdev_err(netdev, "Failed to delete re-mapping TLV\n");
7912a87bd73SDave Ertman 		ret = -EINVAL;
792b94b013eSDave Ertman 		goto setapp_out;
793b94b013eSDave Ertman 	}
794b94b013eSDave Ertman 
7952a87bd73SDave Ertman 	new_app.selector = app->selector;
7962a87bd73SDave Ertman 	new_app.prot_id = app->protocol;
7972a87bd73SDave Ertman 	new_app.priority = app->priority;
7982a87bd73SDave Ertman 
7992a87bd73SDave Ertman 	/* If port is not in DSCP mode, need to set */
8002a87bd73SDave Ertman 	if (old_cfg->pfc_mode == ICE_QOS_MODE_VLAN) {
8012a87bd73SDave Ertman 		int i, j;
8022a87bd73SDave Ertman 
8032a87bd73SDave Ertman 		/* set DSCP mode */
8042a87bd73SDave Ertman 		ret = ice_aq_set_pfc_mode(&pf->hw, ICE_AQC_PFC_DSCP_BASED_PFC,
8052a87bd73SDave Ertman 					  NULL);
8062a87bd73SDave Ertman 		if (ret) {
8072a87bd73SDave Ertman 			netdev_err(netdev, "Failed to set DSCP PFC mode %d\n",
8082a87bd73SDave Ertman 				   ret);
8092a87bd73SDave Ertman 			goto setapp_out;
8102a87bd73SDave Ertman 		}
8112a87bd73SDave Ertman 		netdev_info(netdev, "Switched QoS to L3 DSCP mode\n");
8122a87bd73SDave Ertman 
8132a87bd73SDave Ertman 		new_cfg->pfc_mode = ICE_QOS_MODE_DSCP;
8142a87bd73SDave Ertman 
8152a87bd73SDave Ertman 		/* set default DSCP QoS values */
8162a87bd73SDave Ertman 		new_cfg->etscfg.willing = 0;
8172a87bd73SDave Ertman 		new_cfg->pfc.pfccap = max_tc;
8182a87bd73SDave Ertman 		new_cfg->pfc.willing = 0;
8192a87bd73SDave Ertman 
8202a87bd73SDave Ertman 		for (i = 0; i < max_tc; i++)
8212a87bd73SDave Ertman 			for (j = 0; j < ICE_BYTES_PER_DSCP_VAL; j++) {
8222a87bd73SDave Ertman 				int dscp, offset;
8232a87bd73SDave Ertman 
8242a87bd73SDave Ertman 				dscp = (i * max_tc) + j;
8252a87bd73SDave Ertman 				offset = max_tc * ICE_BYTES_PER_DSCP_VAL;
8262a87bd73SDave Ertman 
8272a87bd73SDave Ertman 				new_cfg->dscp_map[dscp] = i;
8282a87bd73SDave Ertman 				/* if less that 8 TCs supported */
8292a87bd73SDave Ertman 				if (max_tc < ICE_MAX_TRAFFIC_CLASS)
8302a87bd73SDave Ertman 					new_cfg->dscp_map[dscp + offset] = i;
8312a87bd73SDave Ertman 			}
8322a87bd73SDave Ertman 
8332a87bd73SDave Ertman 		new_cfg->etscfg.tcbwtable[0] = 100;
8342a87bd73SDave Ertman 		new_cfg->etscfg.tsatable[0] = ICE_IEEE_TSA_ETS;
8352a87bd73SDave Ertman 		new_cfg->etscfg.prio_table[0] = 0;
8362a87bd73SDave Ertman 
8372a87bd73SDave Ertman 		for (i = 1; i < max_tc; i++) {
8382a87bd73SDave Ertman 			new_cfg->etscfg.tcbwtable[i] = 0;
8392a87bd73SDave Ertman 			new_cfg->etscfg.tsatable[i] = ICE_IEEE_TSA_ETS;
8402a87bd73SDave Ertman 			new_cfg->etscfg.prio_table[i] = i;
8412a87bd73SDave Ertman 		}
8422a87bd73SDave Ertman 	} /* end of switching to DSCP mode */
8432a87bd73SDave Ertman 
8442a87bd73SDave Ertman 	/* apply new mapping for this DSCP value */
8452a87bd73SDave Ertman 	new_cfg->dscp_map[app->protocol] = app->priority;
846b94b013eSDave Ertman 	new_cfg->app[new_cfg->numapps++] = new_app;
8472a87bd73SDave Ertman 
848b94b013eSDave Ertman 	ret = ice_pf_dcb_cfg(pf, new_cfg, true);
849b94b013eSDave Ertman 	/* return of zero indicates new cfg applied */
850b94b013eSDave Ertman 	if (ret == ICE_DCB_HW_CHG_RST)
851b94b013eSDave Ertman 		ice_dcbnl_devreset(netdev);
8522a87bd73SDave Ertman 	else
8532a87bd73SDave Ertman 		ret = ICE_DCB_NO_HW_CHG;
854b94b013eSDave Ertman 
855b94b013eSDave Ertman setapp_out:
856b94b013eSDave Ertman 	mutex_unlock(&pf->tc_mutex);
857b94b013eSDave Ertman 	return ret;
858b94b013eSDave Ertman }
859b94b013eSDave Ertman 
860b94b013eSDave Ertman /**
861b94b013eSDave Ertman  * ice_dcbnl_delapp - Delete local IEEE App config
862b94b013eSDave Ertman  * @netdev: relevant netdev
863b94b013eSDave Ertman  * @app: struct to hold app too delete
864b94b013eSDave Ertman  *
865b94b013eSDave Ertman  * Will not delete first application required by the FW
866b94b013eSDave Ertman  */
ice_dcbnl_delapp(struct net_device * netdev,struct dcb_app * app)867b94b013eSDave Ertman static int ice_dcbnl_delapp(struct net_device *netdev, struct dcb_app *app)
868b94b013eSDave Ertman {
869b94b013eSDave Ertman 	struct ice_pf *pf = ice_netdev_to_pf(netdev);
870b94b013eSDave Ertman 	struct ice_dcbx_cfg *old_cfg, *new_cfg;
871c1e08830SJesse Brandeburg 	unsigned int i, j;
872c1e08830SJesse Brandeburg 	int ret = 0;
873b94b013eSDave Ertman 
8742a87bd73SDave Ertman 	if (pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) {
8752a87bd73SDave Ertman 		netdev_err(netdev, "can't delete DSCP netlink app when FW DCB agent is active\n");
876b94b013eSDave Ertman 		return -EINVAL;
8772a87bd73SDave Ertman 	}
878b94b013eSDave Ertman 
879*ab2ed5d7SDave Ertman 	if (pf->lag && pf->lag->bonded) {
880*ab2ed5d7SDave Ertman 		netdev_err(netdev, "DCB changes not allowed when in a bond\n");
881*ab2ed5d7SDave Ertman 		return -EINVAL;
882*ab2ed5d7SDave Ertman 	}
883*ab2ed5d7SDave Ertman 
884b94b013eSDave Ertman 	mutex_lock(&pf->tc_mutex);
885fc2d1165SChinh T Cao 	old_cfg = &pf->hw.port_info->qos_cfg.local_dcbx_cfg;
886b94b013eSDave Ertman 
88753977ee4SDave Ertman 	ret = dcb_ieee_delapp(netdev, app);
88853977ee4SDave Ertman 	if (ret)
889b94b013eSDave Ertman 		goto delapp_out;
890b94b013eSDave Ertman 
891fc2d1165SChinh T Cao 	new_cfg = &pf->hw.port_info->qos_cfg.desired_dcbx_cfg;
892b94b013eSDave Ertman 
8932a87bd73SDave Ertman 	for (i = 0; i < new_cfg->numapps; i++) {
894b94b013eSDave Ertman 		if (app->selector == new_cfg->app[i].selector &&
895b94b013eSDave Ertman 		    app->protocol == new_cfg->app[i].prot_id &&
896b94b013eSDave Ertman 		    app->priority == new_cfg->app[i].priority) {
897b94b013eSDave Ertman 			new_cfg->app[i].selector = 0;
898b94b013eSDave Ertman 			new_cfg->app[i].prot_id = 0;
899b94b013eSDave Ertman 			new_cfg->app[i].priority = 0;
900b94b013eSDave Ertman 			break;
901b94b013eSDave Ertman 		}
902b94b013eSDave Ertman 	}
903b94b013eSDave Ertman 
904b94b013eSDave Ertman 	/* Did not find DCB App */
905b94b013eSDave Ertman 	if (i == new_cfg->numapps) {
906b94b013eSDave Ertman 		ret = -EINVAL;
907b94b013eSDave Ertman 		goto delapp_out;
908b94b013eSDave Ertman 	}
909b94b013eSDave Ertman 
910b94b013eSDave Ertman 	new_cfg->numapps--;
911b94b013eSDave Ertman 
912b94b013eSDave Ertman 	for (j = i; j < new_cfg->numapps; j++) {
9132a87bd73SDave Ertman 		new_cfg->app[j].selector = old_cfg->app[j + 1].selector;
9142a87bd73SDave Ertman 		new_cfg->app[j].prot_id = old_cfg->app[j + 1].prot_id;
9152a87bd73SDave Ertman 		new_cfg->app[j].priority = old_cfg->app[j + 1].priority;
916b94b013eSDave Ertman 	}
917b94b013eSDave Ertman 
91840b24760SAnirudh Venkataramanan 	/* if not a DSCP APP TLV or DSCP is not supported, we are done */
91940b24760SAnirudh Venkataramanan 	if (app->selector != IEEE_8021QAZ_APP_SEL_DSCP ||
92040b24760SAnirudh Venkataramanan 	    !ice_is_feature_supported(pf, ICE_F_DSCP)) {
9212a87bd73SDave Ertman 		ret = ICE_DCB_HW_CHG;
9222a87bd73SDave Ertman 		goto delapp_out;
9232a87bd73SDave Ertman 	}
9242a87bd73SDave Ertman 
9252a87bd73SDave Ertman 	/* if DSCP TLV, then need to address change in mapping */
9262a87bd73SDave Ertman 	clear_bit(app->protocol, new_cfg->dscp_mapped);
9272a87bd73SDave Ertman 	/* remap this DSCP value to default value */
9282a87bd73SDave Ertman 	new_cfg->dscp_map[app->protocol] = app->protocol %
9292a87bd73SDave Ertman 					   ICE_BYTES_PER_DSCP_VAL;
9302a87bd73SDave Ertman 
9312a87bd73SDave Ertman 	/* if the last DSCP mapping just got deleted, need to switch
9322a87bd73SDave Ertman 	 * to L2 VLAN QoS mode
9332a87bd73SDave Ertman 	 */
9342a87bd73SDave Ertman 	if (bitmap_empty(new_cfg->dscp_mapped, ICE_DSCP_NUM_VAL) &&
9352a87bd73SDave Ertman 	    new_cfg->pfc_mode == ICE_QOS_MODE_DSCP) {
9362a87bd73SDave Ertman 		ret = ice_aq_set_pfc_mode(&pf->hw,
9372a87bd73SDave Ertman 					  ICE_AQC_PFC_VLAN_BASED_PFC,
9382a87bd73SDave Ertman 					  NULL);
9392a87bd73SDave Ertman 		if (ret) {
9402a87bd73SDave Ertman 			netdev_info(netdev, "Failed to set VLAN PFC mode %d\n",
9412a87bd73SDave Ertman 				    ret);
9422a87bd73SDave Ertman 			goto delapp_out;
9432a87bd73SDave Ertman 		}
9442a87bd73SDave Ertman 		netdev_info(netdev, "Switched QoS to L2 VLAN mode\n");
9452a87bd73SDave Ertman 
9462a87bd73SDave Ertman 		new_cfg->pfc_mode = ICE_QOS_MODE_VLAN;
9472a87bd73SDave Ertman 
9482a87bd73SDave Ertman 		ret = ice_dcb_sw_dflt_cfg(pf, true, true);
9492a87bd73SDave Ertman 	} else {
950b94b013eSDave Ertman 		ret = ice_pf_dcb_cfg(pf, new_cfg, true);
9512a87bd73SDave Ertman 	}
9522a87bd73SDave Ertman 
9532a87bd73SDave Ertman 	/* return of ICE_DCB_HW_CHG_RST indicates new cfg applied
9542a87bd73SDave Ertman 	 * and reset needs to be performed
9552a87bd73SDave Ertman 	 */
956b94b013eSDave Ertman 	if (ret == ICE_DCB_HW_CHG_RST)
957b94b013eSDave Ertman 		ice_dcbnl_devreset(netdev);
9582a87bd73SDave Ertman 
9592a87bd73SDave Ertman 	/* if the change was not siginificant enough to actually call
9602a87bd73SDave Ertman 	 * the reconfiguration flow, we still need to tell caller that
9612a87bd73SDave Ertman 	 * their request was successfully handled
9622a87bd73SDave Ertman 	 */
963b94b013eSDave Ertman 	if (ret == ICE_DCB_NO_HW_CHG)
9642a87bd73SDave Ertman 		ret = ICE_DCB_HW_CHG;
965b94b013eSDave Ertman 
966b94b013eSDave Ertman delapp_out:
967b94b013eSDave Ertman 	mutex_unlock(&pf->tc_mutex);
968b94b013eSDave Ertman 	return ret;
969b94b013eSDave Ertman }
970b94b013eSDave Ertman 
971b94b013eSDave Ertman /**
972b94b013eSDave Ertman  * ice_dcbnl_cee_set_all - Commit CEE DCB settings to HW
973b94b013eSDave Ertman  * @netdev: the corresponding netdev
974b94b013eSDave Ertman  */
ice_dcbnl_cee_set_all(struct net_device * netdev)975b94b013eSDave Ertman static u8 ice_dcbnl_cee_set_all(struct net_device *netdev)
976b94b013eSDave Ertman {
977b94b013eSDave Ertman 	struct ice_pf *pf = ice_netdev_to_pf(netdev);
978b94b013eSDave Ertman 	struct ice_dcbx_cfg *new_cfg;
979b94b013eSDave Ertman 	int err;
980b94b013eSDave Ertman 
981b94b013eSDave Ertman 	if ((pf->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) ||
982b94b013eSDave Ertman 	    !(pf->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
983b94b013eSDave Ertman 		return ICE_DCB_NO_HW_CHG;
984b94b013eSDave Ertman 
985*ab2ed5d7SDave Ertman 	if (pf->lag && pf->lag->bonded) {
986*ab2ed5d7SDave Ertman 		netdev_err(netdev, "DCB changes not allowed when in a bond\n");
987*ab2ed5d7SDave Ertman 		return ICE_DCB_NO_HW_CHG;
988*ab2ed5d7SDave Ertman 	}
989*ab2ed5d7SDave Ertman 
990fc2d1165SChinh T Cao 	new_cfg = &pf->hw.port_info->qos_cfg.desired_dcbx_cfg;
991b94b013eSDave Ertman 
992b94b013eSDave Ertman 	mutex_lock(&pf->tc_mutex);
993b94b013eSDave Ertman 
994b94b013eSDave Ertman 	err = ice_pf_dcb_cfg(pf, new_cfg, true);
995b94b013eSDave Ertman 
996b94b013eSDave Ertman 	mutex_unlock(&pf->tc_mutex);
997b94b013eSDave Ertman 	return (err != ICE_DCB_HW_CHG_RST) ? ICE_DCB_NO_HW_CHG : err;
998b94b013eSDave Ertman }
999b94b013eSDave Ertman 
1000b94b013eSDave Ertman static const struct dcbnl_rtnl_ops dcbnl_ops = {
1001b94b013eSDave Ertman 	/* IEEE 802.1Qaz std */
1002b94b013eSDave Ertman 	.ieee_getets = ice_dcbnl_getets,
1003b94b013eSDave Ertman 	.ieee_setets = ice_dcbnl_setets,
1004b94b013eSDave Ertman 	.ieee_getpfc = ice_dcbnl_getpfc,
1005b94b013eSDave Ertman 	.ieee_setpfc = ice_dcbnl_setpfc,
1006b94b013eSDave Ertman 	.ieee_setapp = ice_dcbnl_setapp,
1007b94b013eSDave Ertman 	.ieee_delapp = ice_dcbnl_delapp,
1008b94b013eSDave Ertman 
1009b94b013eSDave Ertman 	/* CEE std */
1010b94b013eSDave Ertman 	.getstate = ice_dcbnl_getstate,
1011b94b013eSDave Ertman 	.setstate = ice_dcbnl_setstate,
1012b94b013eSDave Ertman 	.getpermhwaddr = ice_dcbnl_get_perm_hw_addr,
1013b94b013eSDave Ertman 	.setpgtccfgtx = ice_dcbnl_set_pg_tc_cfg_tx,
1014b94b013eSDave Ertman 	.setpgbwgcfgtx = ice_dcbnl_set_pg_bwg_cfg_tx,
1015c8608b50SAvinash JD 	.setpgtccfgrx = ice_dcbnl_set_pg_tc_cfg_rx,
1016c8608b50SAvinash JD 	.setpgbwgcfgrx = ice_dcbnl_set_pg_bwg_cfg_rx,
1017b94b013eSDave Ertman 	.getpgtccfgtx = ice_dcbnl_get_pg_tc_cfg_tx,
1018b94b013eSDave Ertman 	.getpgbwgcfgtx = ice_dcbnl_get_pg_bwg_cfg_tx,
1019b94b013eSDave Ertman 	.getpgtccfgrx = ice_dcbnl_get_pg_tc_cfg_rx,
1020b94b013eSDave Ertman 	.getpgbwgcfgrx = ice_dcbnl_get_pg_bwg_cfg_rx,
1021b94b013eSDave Ertman 	.setpfccfg = ice_dcbnl_set_pfc_cfg,
1022b94b013eSDave Ertman 	.getpfccfg = ice_dcbnl_get_pfc_cfg,
1023b94b013eSDave Ertman 	.setall = ice_dcbnl_cee_set_all,
1024b94b013eSDave Ertman 	.getcap = ice_dcbnl_get_cap,
1025b94b013eSDave Ertman 	.getnumtcs = ice_dcbnl_getnumtcs,
1026b94b013eSDave Ertman 	.getpfcstate = ice_dcbnl_getpfcstate,
1027b94b013eSDave Ertman 	.getapp = ice_dcbnl_getapp,
1028b94b013eSDave Ertman 
1029b94b013eSDave Ertman 	/* DCBX configuration */
1030b94b013eSDave Ertman 	.getdcbx = ice_dcbnl_getdcbx,
1031b94b013eSDave Ertman 	.setdcbx = ice_dcbnl_setdcbx,
1032b94b013eSDave Ertman };
1033b94b013eSDave Ertman 
1034b94b013eSDave Ertman /**
1035b94b013eSDave Ertman  * ice_dcbnl_set_all - set all the apps and ieee data from DCBX config
1036b94b013eSDave Ertman  * @vsi: pointer to VSI struct
1037b94b013eSDave Ertman  */
ice_dcbnl_set_all(struct ice_vsi * vsi)1038b94b013eSDave Ertman void ice_dcbnl_set_all(struct ice_vsi *vsi)
1039b94b013eSDave Ertman {
1040b94b013eSDave Ertman 	struct net_device *netdev = vsi->netdev;
1041b94b013eSDave Ertman 	struct ice_dcbx_cfg *dcbxcfg;
1042b94b013eSDave Ertman 	struct ice_port_info *pi;
1043b94b013eSDave Ertman 	struct dcb_app sapp;
1044b94b013eSDave Ertman 	struct ice_pf *pf;
1045c1e08830SJesse Brandeburg 	unsigned int i;
1046b94b013eSDave Ertman 
1047b94b013eSDave Ertman 	if (!netdev)
1048b94b013eSDave Ertman 		return;
1049b94b013eSDave Ertman 
1050b94b013eSDave Ertman 	pf = ice_netdev_to_pf(netdev);
1051b94b013eSDave Ertman 	pi = pf->hw.port_info;
1052b94b013eSDave Ertman 
1053b94b013eSDave Ertman 	/* SW DCB taken care of by SW Default Config */
1054b94b013eSDave Ertman 	if (pf->dcbx_cap & DCB_CAP_DCBX_HOST)
1055b94b013eSDave Ertman 		return;
1056b94b013eSDave Ertman 
1057b94b013eSDave Ertman 	/* DCB not enabled */
1058b94b013eSDave Ertman 	if (!test_bit(ICE_FLAG_DCB_ENA, pf->flags))
1059b94b013eSDave Ertman 		return;
1060b94b013eSDave Ertman 
1061fc2d1165SChinh T Cao 	dcbxcfg = &pi->qos_cfg.local_dcbx_cfg;
1062b94b013eSDave Ertman 
1063b94b013eSDave Ertman 	for (i = 0; i < dcbxcfg->numapps; i++) {
1064b94b013eSDave Ertman 		u8 prio, tc_map;
1065b94b013eSDave Ertman 
1066b94b013eSDave Ertman 		prio = dcbxcfg->app[i].priority;
1067b94b013eSDave Ertman 		tc_map = BIT(dcbxcfg->etscfg.prio_table[prio]);
1068b94b013eSDave Ertman 
1069b94b013eSDave Ertman 		/* Add APP only if the TC is enabled for this VSI */
1070b94b013eSDave Ertman 		if (tc_map & vsi->tc_cfg.ena_tc) {
1071b94b013eSDave Ertman 			sapp.selector = dcbxcfg->app[i].selector;
1072b94b013eSDave Ertman 			sapp.protocol = dcbxcfg->app[i].prot_id;
1073b94b013eSDave Ertman 			sapp.priority = prio;
1074b94b013eSDave Ertman 			dcb_ieee_setapp(netdev, &sapp);
1075b94b013eSDave Ertman 		}
1076b94b013eSDave Ertman 	}
1077b94b013eSDave Ertman 	/* Notify user-space of the changes */
1078b94b013eSDave Ertman 	dcbnl_ieee_notify(netdev, RTM_SETDCB, DCB_CMD_IEEE_SET, 0, 0);
1079b94b013eSDave Ertman }
1080b94b013eSDave Ertman 
1081b94b013eSDave Ertman /**
1082b94b013eSDave Ertman  * ice_dcbnl_vsi_del_app - Delete APP on all VSIs
1083b94b013eSDave Ertman  * @vsi: pointer to the main VSI
1084b94b013eSDave Ertman  * @app: APP to delete
1085b94b013eSDave Ertman  *
1086b94b013eSDave Ertman  * Delete given APP from all the VSIs for given PF
1087b94b013eSDave Ertman  */
1088b94b013eSDave Ertman static void
ice_dcbnl_vsi_del_app(struct ice_vsi * vsi,struct ice_dcb_app_priority_table * app)1089b94b013eSDave Ertman ice_dcbnl_vsi_del_app(struct ice_vsi *vsi,
1090b94b013eSDave Ertman 		      struct ice_dcb_app_priority_table *app)
1091b94b013eSDave Ertman {
1092b94b013eSDave Ertman 	struct dcb_app sapp;
1093b94b013eSDave Ertman 	int err;
1094b94b013eSDave Ertman 
1095b94b013eSDave Ertman 	sapp.selector = app->selector;
1096b94b013eSDave Ertman 	sapp.protocol = app->prot_id;
1097b94b013eSDave Ertman 	sapp.priority = app->priority;
1098b94b013eSDave Ertman 	err = ice_dcbnl_delapp(vsi->netdev, &sapp);
109919cce2c6SAnirudh Venkataramanan 	dev_dbg(ice_pf_to_dev(vsi->back), "Deleting app for VSI idx=%d err=%d sel=%d proto=0x%x, prio=%d\n",
1100b94b013eSDave Ertman 		vsi->idx, err, app->selector, app->prot_id, app->priority);
1101b94b013eSDave Ertman }
1102b94b013eSDave Ertman 
1103b94b013eSDave Ertman /**
1104b94b013eSDave Ertman  * ice_dcbnl_flush_apps - Delete all removed APPs
1105b94b013eSDave Ertman  * @pf: the corresponding PF
1106b94b013eSDave Ertman  * @old_cfg: old DCBX configuration data
1107b94b013eSDave Ertman  * @new_cfg: new DCBX configuration data
1108b94b013eSDave Ertman  *
1109b94b013eSDave Ertman  * Find and delete all APPS that are not present in the passed
1110b94b013eSDave Ertman  * DCB configuration
1111b94b013eSDave Ertman  */
1112b94b013eSDave Ertman void
ice_dcbnl_flush_apps(struct ice_pf * pf,struct ice_dcbx_cfg * old_cfg,struct ice_dcbx_cfg * new_cfg)1113b94b013eSDave Ertman ice_dcbnl_flush_apps(struct ice_pf *pf, struct ice_dcbx_cfg *old_cfg,
1114b94b013eSDave Ertman 		     struct ice_dcbx_cfg *new_cfg)
1115b94b013eSDave Ertman {
1116b94b013eSDave Ertman 	struct ice_vsi *main_vsi = ice_get_main_vsi(pf);
1117c1e08830SJesse Brandeburg 	unsigned int i;
1118b94b013eSDave Ertman 
1119b94b013eSDave Ertman 	if (!main_vsi)
1120b94b013eSDave Ertman 		return;
1121b94b013eSDave Ertman 
1122b94b013eSDave Ertman 	for (i = 0; i < old_cfg->numapps; i++) {
1123b94b013eSDave Ertman 		struct ice_dcb_app_priority_table app = old_cfg->app[i];
1124b94b013eSDave Ertman 
1125b94b013eSDave Ertman 		/* The APP is not available anymore delete it */
1126b94b013eSDave Ertman 		if (!ice_dcbnl_find_app(new_cfg, &app))
1127b94b013eSDave Ertman 			ice_dcbnl_vsi_del_app(main_vsi, &app);
1128b94b013eSDave Ertman 	}
1129b94b013eSDave Ertman }
1130b94b013eSDave Ertman 
1131b94b013eSDave Ertman /**
1132b94b013eSDave Ertman  * ice_dcbnl_setup - setup DCBNL
1133b94b013eSDave Ertman  * @vsi: VSI to get associated netdev from
1134b94b013eSDave Ertman  */
ice_dcbnl_setup(struct ice_vsi * vsi)1135b94b013eSDave Ertman void ice_dcbnl_setup(struct ice_vsi *vsi)
1136b94b013eSDave Ertman {
1137b94b013eSDave Ertman 	struct net_device *netdev = vsi->netdev;
1138b94b013eSDave Ertman 	struct ice_pf *pf;
1139b94b013eSDave Ertman 
1140b94b013eSDave Ertman 	pf = ice_netdev_to_pf(netdev);
1141b94b013eSDave Ertman 	if (!test_bit(ICE_FLAG_DCB_CAPABLE, pf->flags))
1142b94b013eSDave Ertman 		return;
1143b94b013eSDave Ertman 
1144b94b013eSDave Ertman 	netdev->dcbnl_ops = &dcbnl_ops;
1145b94b013eSDave Ertman 	ice_dcbnl_set_all(vsi);
1146b94b013eSDave Ertman }
1147