xref: /linux/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c (revision e7ee89740800a1cf253713e9249c3ee9203ebe91)
1 /*
2  * Copyright (c) 2016, Mellanox Technologies. All rights reserved.
3  *
4  * This software is available to you under a choice of one of two
5  * licenses.  You may choose to be licensed under the terms of the GNU
6  * General Public License (GPL) Version 2, available from the file
7  * COPYING in the main directory of this source tree, or the
8  * OpenIB.org BSD license below:
9  *
10  *     Redistribution and use in source and binary forms, with or
11  *     without modification, are permitted provided that the following
12  *     conditions are met:
13  *
14  *      - Redistributions of source code must retain the above
15  *        copyright notice, this list of conditions and the following
16  *        disclaimer.
17  *
18  *      - Redistributions in binary form must reproduce the above
19  *        copyright notice, this list of conditions and the following
20  *        disclaimer in the documentation and/or other materials
21  *        provided with the distribution.
22  *
23  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30  * SOFTWARE.
31  */
32 #include <linux/device.h>
33 #include <linux/netdevice.h>
34 #include <linux/units.h>
35 #include "en.h"
36 #include "en/port.h"
37 #include "en/port_buffer.h"
38 
39 #define MLX5E_MAX_BW_ALLOC 100 /* Max percentage of BW allocation */
40 
41 #define MLX5E_100MB_TO_KB (100 * MEGA / KILO)
42 #define MLX5E_1GB_TO_KB   (GIGA / KILO)
43 
44 #define MLX5E_CEE_STATE_UP    1
45 #define MLX5E_CEE_STATE_DOWN  0
46 
47 /* Max supported cable length is 1000 meters */
48 #define MLX5E_MAX_CABLE_LENGTH 1000
49 
50 enum {
51 	MLX5E_VENDOR_TC_GROUP_NUM = 7,
52 	MLX5E_LOWEST_PRIO_GROUP   = 0,
53 };
54 
55 enum {
56 	MLX5_DCB_CHG_RESET,
57 	MLX5_DCB_NO_CHG,
58 	MLX5_DCB_CHG_NO_RESET,
59 };
60 
61 static const struct {
62 	int scale;
63 	const char *units_str;
64 } mlx5e_bw_units[] = {
65 	[MLX5_100_MBPS_UNIT] = {
66 		.scale = 100,
67 		.units_str = "Mbps",
68 	},
69 	[MLX5_GBPS_UNIT] = {
70 		.scale = 1,
71 		.units_str = "Gbps",
72 	},
73 };
74 
75 #define MLX5_DSCP_SUPPORTED(mdev) (MLX5_CAP_GEN(mdev, qcam_reg)  && \
76 				   MLX5_CAP_QCAM_REG(mdev, qpts) && \
77 				   MLX5_CAP_QCAM_REG(mdev, qpdpm))
78 
79 static int mlx5e_set_trust_state(struct mlx5e_priv *priv, u8 trust_state);
80 static int mlx5e_set_dscp2prio(struct mlx5e_priv *priv, u8 dscp, u8 prio);
81 
82 /* If dcbx mode is non-host set the dcbx mode to host.
83  */
84 static int mlx5e_dcbnl_set_dcbx_mode(struct mlx5e_priv *priv,
85 				     enum mlx5_dcbx_oper_mode mode)
86 {
87 	struct mlx5_core_dev *mdev = priv->mdev;
88 	u32 param[MLX5_ST_SZ_DW(dcbx_param)];
89 	int err;
90 
91 	err = mlx5_query_port_dcbx_param(mdev, param);
92 	if (err)
93 		return err;
94 
95 	MLX5_SET(dcbx_param, param, version_admin, mode);
96 	if (mode != MLX5E_DCBX_PARAM_VER_OPER_HOST)
97 		MLX5_SET(dcbx_param, param, willing_admin, 1);
98 
99 	return mlx5_set_port_dcbx_param(mdev, param);
100 }
101 
102 static int mlx5e_dcbnl_switch_to_host_mode(struct mlx5e_priv *priv)
103 {
104 	struct mlx5e_dcbx *dcbx = &priv->dcbx;
105 	int err;
106 
107 	if (!MLX5_CAP_GEN(priv->mdev, dcbx))
108 		return 0;
109 
110 	if (dcbx->mode == MLX5E_DCBX_PARAM_VER_OPER_HOST)
111 		return 0;
112 
113 	err = mlx5e_dcbnl_set_dcbx_mode(priv, MLX5E_DCBX_PARAM_VER_OPER_HOST);
114 	if (err)
115 		return err;
116 
117 	dcbx->mode = MLX5E_DCBX_PARAM_VER_OPER_HOST;
118 	return 0;
119 }
120 
121 static int mlx5e_dcbnl_ieee_getets(struct net_device *netdev,
122 				   struct ieee_ets *ets)
123 {
124 	struct mlx5e_priv *priv = netdev_priv(netdev);
125 	struct mlx5_core_dev *mdev = priv->mdev;
126 	u8 tc_group[IEEE_8021QAZ_MAX_TCS];
127 	bool is_tc_group_6_exist = false;
128 	bool is_zero_bw_ets_tc = false;
129 	int err = 0;
130 	int i;
131 
132 	if (!MLX5_CAP_GEN(priv->mdev, ets))
133 		return -EOPNOTSUPP;
134 
135 	for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
136 		err = mlx5_query_port_prio_tc(mdev, i, &ets->prio_tc[i]);
137 		if (err)
138 			return err;
139 	}
140 
141 	ets->ets_cap = mlx5_max_tc(priv->mdev) + 1;
142 	for (i = 0; i < ets->ets_cap; i++) {
143 		err = mlx5_query_port_tc_group(mdev, i, &tc_group[i]);
144 		if (err)
145 			return err;
146 
147 		err = mlx5_query_port_tc_bw_alloc(mdev, i, &ets->tc_tx_bw[i]);
148 		if (err)
149 			return err;
150 
151 		if (priv->dcbx.tc_tsa[i] == IEEE_8021QAZ_TSA_ETS &&
152 		    tc_group[i] == (MLX5E_LOWEST_PRIO_GROUP + 1))
153 			is_zero_bw_ets_tc = true;
154 
155 		if (tc_group[i] == (MLX5E_VENDOR_TC_GROUP_NUM - 1))
156 			is_tc_group_6_exist = true;
157 	}
158 
159 	/* Report 0% ets tc if exits*/
160 	if (is_zero_bw_ets_tc) {
161 		for (i = 0; i < ets->ets_cap; i++)
162 			if (tc_group[i] == MLX5E_LOWEST_PRIO_GROUP)
163 				ets->tc_tx_bw[i] = 0;
164 	}
165 
166 	/* Update tc_tsa based on fw setting*/
167 	for (i = 0; i < ets->ets_cap; i++) {
168 		if (ets->tc_tx_bw[i] < MLX5E_MAX_BW_ALLOC)
169 			priv->dcbx.tc_tsa[i] = IEEE_8021QAZ_TSA_ETS;
170 		else if (tc_group[i] == MLX5E_VENDOR_TC_GROUP_NUM &&
171 			 !is_tc_group_6_exist)
172 			priv->dcbx.tc_tsa[i] = IEEE_8021QAZ_TSA_VENDOR;
173 	}
174 	memcpy(ets->tc_tsa, priv->dcbx.tc_tsa, sizeof(ets->tc_tsa));
175 
176 	/* Report 0 for non ETS TSA */
177 	for (i = 0; i < ets->ets_cap; i++) {
178 		if (ets->tc_tx_bw[i] == MLX5E_MAX_BW_ALLOC &&
179 		    priv->dcbx.tc_tsa[i] != IEEE_8021QAZ_TSA_ETS)
180 			ets->tc_tx_bw[i] = 0;
181 	}
182 
183 	return err;
184 }
185 
186 static void mlx5e_build_tc_group(struct ieee_ets *ets, u8 *tc_group, int max_tc)
187 {
188 	bool any_tc_mapped_to_ets = false;
189 	bool ets_zero_bw = false;
190 	int strict_group;
191 	int i;
192 
193 	for (i = 0; i <= max_tc; i++) {
194 		if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_ETS) {
195 			any_tc_mapped_to_ets = true;
196 			if (!ets->tc_tx_bw[i])
197 				ets_zero_bw = true;
198 		}
199 	}
200 
201 	/* strict group has higher priority than ets group */
202 	strict_group = MLX5E_LOWEST_PRIO_GROUP;
203 	if (any_tc_mapped_to_ets)
204 		strict_group++;
205 	if (ets_zero_bw)
206 		strict_group++;
207 
208 	for (i = 0; i <= max_tc; i++) {
209 		switch (ets->tc_tsa[i]) {
210 		case IEEE_8021QAZ_TSA_VENDOR:
211 			tc_group[i] = MLX5E_VENDOR_TC_GROUP_NUM;
212 			break;
213 		case IEEE_8021QAZ_TSA_STRICT:
214 			tc_group[i] = strict_group++;
215 			break;
216 		case IEEE_8021QAZ_TSA_ETS:
217 			tc_group[i] = MLX5E_LOWEST_PRIO_GROUP;
218 			if (ets->tc_tx_bw[i] && ets_zero_bw)
219 				tc_group[i] = MLX5E_LOWEST_PRIO_GROUP + 1;
220 			break;
221 		}
222 	}
223 }
224 
225 static void mlx5e_build_tc_tx_bw(struct ieee_ets *ets, u8 *tc_tx_bw,
226 				 u8 *tc_group, int max_tc)
227 {
228 	int bw_for_ets_zero_bw_tc = 0;
229 	int last_ets_zero_bw_tc = -1;
230 	int num_ets_zero_bw = 0;
231 	int i;
232 
233 	for (i = 0; i <= max_tc; i++) {
234 		if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_ETS &&
235 		    !ets->tc_tx_bw[i]) {
236 			num_ets_zero_bw++;
237 			last_ets_zero_bw_tc = i;
238 		}
239 	}
240 
241 	if (num_ets_zero_bw)
242 		bw_for_ets_zero_bw_tc = MLX5E_MAX_BW_ALLOC / num_ets_zero_bw;
243 
244 	for (i = 0; i <= max_tc; i++) {
245 		switch (ets->tc_tsa[i]) {
246 		case IEEE_8021QAZ_TSA_VENDOR:
247 			tc_tx_bw[i] = MLX5E_MAX_BW_ALLOC;
248 			break;
249 		case IEEE_8021QAZ_TSA_STRICT:
250 			tc_tx_bw[i] = MLX5E_MAX_BW_ALLOC;
251 			break;
252 		case IEEE_8021QAZ_TSA_ETS:
253 			tc_tx_bw[i] = ets->tc_tx_bw[i] ?
254 				      ets->tc_tx_bw[i] :
255 				      bw_for_ets_zero_bw_tc;
256 			break;
257 		}
258 	}
259 
260 	/* Make sure the total bw for ets zero bw group is 100% */
261 	if (last_ets_zero_bw_tc != -1)
262 		tc_tx_bw[last_ets_zero_bw_tc] +=
263 			MLX5E_MAX_BW_ALLOC % num_ets_zero_bw;
264 }
265 
266 /* If there are ETS BW 0,
267  *   Set ETS group # to 1 for all ETS non zero BW tcs. Their sum must be 100%.
268  *   Set group #0 to all the ETS BW 0 tcs and
269  *     equally splits the 100% BW between them
270  *   Report both group #0 and #1 as ETS type.
271  *     All the tcs in group #0 will be reported with 0% BW.
272  */
273 static int mlx5e_dcbnl_ieee_setets_core(struct mlx5e_priv *priv, struct ieee_ets *ets)
274 {
275 	struct mlx5_core_dev *mdev = priv->mdev;
276 	u8 tc_tx_bw[IEEE_8021QAZ_MAX_TCS];
277 	u8 tc_group[IEEE_8021QAZ_MAX_TCS];
278 	int max_tc = mlx5_max_tc(mdev);
279 	int err, i;
280 
281 	mlx5e_build_tc_group(ets, tc_group, max_tc);
282 	mlx5e_build_tc_tx_bw(ets, tc_tx_bw, tc_group, max_tc);
283 
284 	err = mlx5_set_port_prio_tc(mdev, ets->prio_tc);
285 	if (err)
286 		return err;
287 
288 	err = mlx5_set_port_tc_group(mdev, tc_group);
289 	if (err)
290 		return err;
291 
292 	err = mlx5_set_port_tc_bw_alloc(mdev, tc_tx_bw);
293 
294 	if (err)
295 		return err;
296 
297 	memcpy(priv->dcbx.tc_tsa, ets->tc_tsa, sizeof(ets->tc_tsa));
298 
299 	for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
300 		netdev_dbg(priv->netdev, "%s: prio_%d <=> tc_%d\n",
301 			   __func__, i, ets->prio_tc[i]);
302 		netdev_dbg(priv->netdev, "%s: tc_%d <=> tx_bw_%d%%, group_%d\n",
303 			   __func__, i, tc_tx_bw[i], tc_group[i]);
304 	}
305 
306 	return err;
307 }
308 
309 static int mlx5e_dbcnl_validate_ets(struct net_device *netdev,
310 				    struct ieee_ets *ets,
311 				    bool zero_sum_allowed)
312 {
313 	bool have_ets_tc = false;
314 	int bw_sum = 0;
315 	int i;
316 
317 	/* Validate Priority */
318 	for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
319 		if (ets->prio_tc[i] >= MLX5E_MAX_PRIORITY) {
320 			netdev_err(netdev,
321 				   "Failed to validate ETS: priority value greater than max(%d)\n",
322 				    MLX5E_MAX_PRIORITY);
323 			return -EINVAL;
324 		}
325 	}
326 
327 	for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
328 		if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_CB_SHAPER) {
329 			netdev_err(netdev,
330 				   "Failed to validate ETS: CB Shaper is not supported\n");
331 			return -EOPNOTSUPP;
332 		}
333 	}
334 
335 	/* Validate Bandwidth Sum */
336 	for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
337 		if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_ETS) {
338 			have_ets_tc = true;
339 			bw_sum += ets->tc_tx_bw[i];
340 		}
341 	}
342 
343 	if (have_ets_tc && bw_sum != 100) {
344 		if (bw_sum || (!bw_sum && !zero_sum_allowed))
345 			netdev_err(netdev,
346 				   "Failed to validate ETS: BW sum is illegal\n");
347 		return -EINVAL;
348 	}
349 	return 0;
350 }
351 
352 static int mlx5e_dcbnl_ieee_setets(struct net_device *netdev,
353 				   struct ieee_ets *ets)
354 {
355 	struct mlx5e_priv *priv = netdev_priv(netdev);
356 	int err;
357 
358 	if (!MLX5_CAP_GEN(priv->mdev, ets))
359 		return -EOPNOTSUPP;
360 
361 	err = mlx5e_dbcnl_validate_ets(netdev, ets, false);
362 	if (err)
363 		return err;
364 
365 	err = mlx5e_dcbnl_ieee_setets_core(priv, ets);
366 	if (err)
367 		return err;
368 
369 	return 0;
370 }
371 
372 static int mlx5e_dcbnl_ieee_getpfc(struct net_device *dev,
373 				   struct ieee_pfc *pfc)
374 {
375 	struct mlx5e_priv *priv = netdev_priv(dev);
376 	struct mlx5_core_dev *mdev = priv->mdev;
377 	struct mlx5e_pport_stats *pstats = &priv->stats.pport;
378 	int i;
379 
380 	pfc->pfc_cap = mlx5_max_tc(mdev) + 1;
381 	for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
382 		pfc->requests[i]    = PPORT_PER_PRIO_GET(pstats, i, tx_pause);
383 		pfc->indications[i] = PPORT_PER_PRIO_GET(pstats, i, rx_pause);
384 	}
385 
386 	if (MLX5_BUFFER_SUPPORTED(mdev))
387 		pfc->delay = priv->dcbx.cable_len;
388 
389 	return mlx5_query_port_pfc(mdev, &pfc->pfc_en, NULL);
390 }
391 
392 static int mlx5e_dcbnl_ieee_setpfc(struct net_device *dev,
393 				   struct ieee_pfc *pfc)
394 {
395 	u8 buffer_ownership = MLX5_BUF_OWNERSHIP_UNKNOWN;
396 	struct mlx5e_priv *priv = netdev_priv(dev);
397 	struct mlx5_core_dev *mdev = priv->mdev;
398 	u32 old_cable_len = priv->dcbx.cable_len;
399 	struct ieee_pfc pfc_new;
400 	u32 changed = 0;
401 	u8 curr_pfc_en;
402 	int ret = 0;
403 
404 	/* pfc_en */
405 	mlx5_query_port_pfc(mdev, &curr_pfc_en, NULL);
406 	if (pfc->pfc_en != curr_pfc_en) {
407 		ret = mlx5_set_port_pfc(mdev, pfc->pfc_en, pfc->pfc_en);
408 		if (ret)
409 			return ret;
410 		mlx5_toggle_port_link(mdev);
411 		changed |= MLX5E_PORT_BUFFER_PFC;
412 	}
413 
414 	if (pfc->delay &&
415 	    pfc->delay < MLX5E_MAX_CABLE_LENGTH &&
416 	    pfc->delay != priv->dcbx.cable_len) {
417 		priv->dcbx.cable_len = pfc->delay;
418 		changed |= MLX5E_PORT_BUFFER_CABLE_LEN;
419 	}
420 
421 	if (MLX5_BUFFER_SUPPORTED(mdev)) {
422 		pfc_new.pfc_en = (changed & MLX5E_PORT_BUFFER_PFC) ? pfc->pfc_en : curr_pfc_en;
423 		ret = mlx5_query_port_buffer_ownership(mdev,
424 						       &buffer_ownership);
425 		if (ret)
426 			netdev_err(dev,
427 				   "%s, Failed to get buffer ownership: %d\n",
428 				   __func__, ret);
429 
430 		if (buffer_ownership == MLX5_BUF_OWNERSHIP_SW_OWNED)
431 			ret = mlx5e_port_manual_buffer_config(priv, changed,
432 							      dev->mtu, &pfc_new,
433 							      NULL, NULL);
434 
435 		if (ret && (changed & MLX5E_PORT_BUFFER_CABLE_LEN))
436 			priv->dcbx.cable_len = old_cable_len;
437 	}
438 
439 	if (!ret) {
440 		netdev_dbg(dev,
441 			   "%s: PFC per priority bit mask: 0x%x\n",
442 			   __func__, pfc->pfc_en);
443 	}
444 	return ret;
445 }
446 
447 static u8 mlx5e_dcbnl_getdcbx(struct net_device *dev)
448 {
449 	struct mlx5e_priv *priv = netdev_priv(dev);
450 
451 	return priv->dcbx.cap;
452 }
453 
454 static u8 mlx5e_dcbnl_setdcbx(struct net_device *dev, u8 mode)
455 {
456 	struct mlx5e_priv *priv = netdev_priv(dev);
457 	struct mlx5e_dcbx *dcbx = &priv->dcbx;
458 
459 	if (mode & DCB_CAP_DCBX_LLD_MANAGED)
460 		return 1;
461 
462 	if ((!mode) && MLX5_CAP_GEN(priv->mdev, dcbx)) {
463 		if (dcbx->mode == MLX5E_DCBX_PARAM_VER_OPER_AUTO)
464 			return 0;
465 
466 		/* set dcbx to fw controlled */
467 		if (!mlx5e_dcbnl_set_dcbx_mode(priv, MLX5E_DCBX_PARAM_VER_OPER_AUTO)) {
468 			dcbx->mode = MLX5E_DCBX_PARAM_VER_OPER_AUTO;
469 			dcbx->cap &= ~DCB_CAP_DCBX_HOST;
470 			return 0;
471 		}
472 
473 		return 1;
474 	}
475 
476 	if (!(mode & DCB_CAP_DCBX_HOST))
477 		return 1;
478 
479 	if (mlx5e_dcbnl_switch_to_host_mode(netdev_priv(dev)))
480 		return 1;
481 
482 	dcbx->cap = mode;
483 
484 	return 0;
485 }
486 
487 static int mlx5e_dcbnl_ieee_setapp(struct net_device *dev, struct dcb_app *app)
488 {
489 	struct mlx5e_priv *priv = netdev_priv(dev);
490 	struct dcb_app temp;
491 	bool is_new;
492 	int err;
493 
494 	if (!MLX5_CAP_GEN(priv->mdev, vport_group_manager) ||
495 	    !MLX5_DSCP_SUPPORTED(priv->mdev))
496 		return -EOPNOTSUPP;
497 
498 	if ((app->selector != IEEE_8021QAZ_APP_SEL_DSCP) ||
499 	    (app->protocol >= MLX5E_MAX_DSCP))
500 		return -EINVAL;
501 
502 	/* Save the old entry info */
503 	temp.selector = IEEE_8021QAZ_APP_SEL_DSCP;
504 	temp.protocol = app->protocol;
505 	temp.priority = priv->dcbx_dp.dscp2prio[app->protocol];
506 
507 	/* Check if need to switch to dscp trust state */
508 	if (!priv->dcbx.dscp_app_cnt) {
509 		err =  mlx5e_set_trust_state(priv, MLX5_QPTS_TRUST_DSCP);
510 		if (err)
511 			return err;
512 	}
513 
514 	/* Skip the fw command if new and old mapping are the same */
515 	if (app->priority != priv->dcbx_dp.dscp2prio[app->protocol]) {
516 		err = mlx5e_set_dscp2prio(priv, app->protocol, app->priority);
517 		if (err)
518 			goto fw_err;
519 	}
520 
521 	/* Delete the old entry if exists */
522 	is_new = false;
523 	err = dcb_ieee_delapp(dev, &temp);
524 	if (err)
525 		is_new = true;
526 
527 	/* Add new entry and update counter */
528 	err = dcb_ieee_setapp(dev, app);
529 	if (err)
530 		return err;
531 
532 	if (is_new)
533 		priv->dcbx.dscp_app_cnt++;
534 
535 	return err;
536 
537 fw_err:
538 	mlx5e_set_trust_state(priv, MLX5_QPTS_TRUST_PCP);
539 	return err;
540 }
541 
542 static int mlx5e_dcbnl_ieee_delapp(struct net_device *dev, struct dcb_app *app)
543 {
544 	struct mlx5e_priv *priv = netdev_priv(dev);
545 	int err;
546 
547 	if  (!MLX5_CAP_GEN(priv->mdev, vport_group_manager) ||
548 	     !MLX5_DSCP_SUPPORTED(priv->mdev))
549 		return -EOPNOTSUPP;
550 
551 	if ((app->selector != IEEE_8021QAZ_APP_SEL_DSCP) ||
552 	    (app->protocol >= MLX5E_MAX_DSCP))
553 		return -EINVAL;
554 
555 	/* Skip if no dscp app entry */
556 	if (!priv->dcbx.dscp_app_cnt)
557 		return -ENOENT;
558 
559 	/* Check if the entry matches fw setting */
560 	if (app->priority != priv->dcbx_dp.dscp2prio[app->protocol])
561 		return -ENOENT;
562 
563 	/* Delete the app entry */
564 	err = dcb_ieee_delapp(dev, app);
565 	if (err)
566 		return err;
567 
568 	/* Reset the priority mapping back to zero */
569 	err = mlx5e_set_dscp2prio(priv, app->protocol, 0);
570 	if (err)
571 		goto fw_err;
572 
573 	priv->dcbx.dscp_app_cnt--;
574 
575 	/* Check if need to switch to pcp trust state */
576 	if (!priv->dcbx.dscp_app_cnt)
577 		err = mlx5e_set_trust_state(priv, MLX5_QPTS_TRUST_PCP);
578 
579 	return err;
580 
581 fw_err:
582 	mlx5e_set_trust_state(priv, MLX5_QPTS_TRUST_PCP);
583 	return err;
584 }
585 
586 static int mlx5e_dcbnl_ieee_getmaxrate(struct net_device *netdev,
587 				       struct ieee_maxrate *maxrate)
588 {
589 	struct mlx5e_priv *priv    = netdev_priv(netdev);
590 	struct mlx5_core_dev *mdev = priv->mdev;
591 	u16 max_bw_value[IEEE_8021QAZ_MAX_TCS];
592 	u8 max_bw_unit[IEEE_8021QAZ_MAX_TCS];
593 	int err;
594 	int i;
595 
596 	err = mlx5_query_port_ets_rate_limit(mdev, max_bw_value, max_bw_unit);
597 	if (err)
598 		return err;
599 
600 	memset(maxrate->tc_maxrate, 0, sizeof(maxrate->tc_maxrate));
601 
602 	for (i = 0; i <= mlx5_max_tc(mdev); i++) {
603 		switch (max_bw_unit[i]) {
604 		case MLX5_100_MBPS_UNIT:
605 			maxrate->tc_maxrate[i] = max_bw_value[i] * MLX5E_100MB_TO_KB;
606 			break;
607 		case MLX5_GBPS_UNIT:
608 			maxrate->tc_maxrate[i] = max_bw_value[i] * MLX5E_1GB_TO_KB;
609 			break;
610 		case MLX5_BW_NO_LIMIT:
611 			break;
612 		default:
613 			WARN(true, "non-supported BW unit");
614 			break;
615 		}
616 	}
617 
618 	return 0;
619 }
620 
621 static int mlx5e_dcbnl_ieee_setmaxrate(struct net_device *netdev,
622 				       struct ieee_maxrate *maxrate)
623 {
624 	struct mlx5e_priv *priv    = netdev_priv(netdev);
625 	struct mlx5_core_dev *mdev = priv->mdev;
626 	u16 max_bw_value[IEEE_8021QAZ_MAX_TCS];
627 	u8 max_bw_unit[IEEE_8021QAZ_MAX_TCS];
628 	int i;
629 
630 	memset(max_bw_value, 0, sizeof(max_bw_value));
631 	memset(max_bw_unit, 0, sizeof(max_bw_unit));
632 
633 	for (i = 0; i <= mlx5_max_tc(mdev); i++) {
634 		u64 rate = maxrate->tc_maxrate[i];
635 
636 		if (!rate) {
637 			max_bw_unit[i]  = MLX5_BW_NO_LIMIT;
638 			continue;
639 		}
640 		if (rate <= priv->dcbx.upper_limit_100mbps) {
641 			max_bw_value[i] = div_u64(rate, MLX5E_100MB_TO_KB);
642 			max_bw_value[i] = max_bw_value[i] ? max_bw_value[i] : 1;
643 			max_bw_unit[i]  = MLX5_100_MBPS_UNIT;
644 		} else if (rate <= priv->dcbx.upper_limit_gbps) {
645 			max_bw_value[i] = div_u64(rate, MLX5E_1GB_TO_KB);
646 			max_bw_unit[i]  = MLX5_GBPS_UNIT;
647 		} else {
648 			netdev_err(netdev,
649 				   "tc_%d maxrate %llu Kbps exceeds limit %llu\n",
650 				   i, rate, priv->dcbx.upper_limit_gbps);
651 			return -EINVAL;
652 		}
653 	}
654 
655 	for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
656 		u8 unit = max_bw_unit[i];
657 
658 		netdev_dbg(netdev, "%s: tc_%d <=> max_bw %u %s\n", __func__, i,
659 			   max_bw_value[i] * mlx5e_bw_units[unit].scale,
660 			   mlx5e_bw_units[unit].units_str);
661 	}
662 
663 	return mlx5_modify_port_ets_rate_limit(mdev, max_bw_value, max_bw_unit);
664 }
665 
666 static u8 mlx5e_dcbnl_setall(struct net_device *netdev)
667 {
668 	struct mlx5e_priv *priv = netdev_priv(netdev);
669 	struct mlx5e_cee_config *cee_cfg = &priv->dcbx.cee_cfg;
670 	struct mlx5_core_dev *mdev = priv->mdev;
671 	struct ieee_ets ets;
672 	struct ieee_pfc pfc;
673 	int err = -EOPNOTSUPP;
674 	int i;
675 
676 	if (!MLX5_CAP_GEN(mdev, ets))
677 		goto out;
678 
679 	memset(&ets, 0, sizeof(ets));
680 	memset(&pfc, 0, sizeof(pfc));
681 
682 	ets.ets_cap = IEEE_8021QAZ_MAX_TCS;
683 	for (i = 0; i < CEE_DCBX_MAX_PGS; i++) {
684 		ets.tc_tx_bw[i] = cee_cfg->pg_bw_pct[i];
685 		ets.tc_rx_bw[i] = cee_cfg->pg_bw_pct[i];
686 		ets.tc_tsa[i]   = IEEE_8021QAZ_TSA_ETS;
687 		ets.prio_tc[i]  = cee_cfg->prio_to_pg_map[i];
688 		netdev_dbg(netdev,
689 			   "%s: Priority group %d: tx_bw %d, rx_bw %d, prio_tc %d\n",
690 			   __func__, i, ets.tc_tx_bw[i], ets.tc_rx_bw[i],
691 			   ets.prio_tc[i]);
692 	}
693 
694 	err = mlx5e_dbcnl_validate_ets(netdev, &ets, true);
695 	if (err)
696 		goto out;
697 
698 	err = mlx5e_dcbnl_ieee_setets_core(priv, &ets);
699 	if (err) {
700 		netdev_err(netdev,
701 			   "%s, Failed to set ETS: %d\n", __func__, err);
702 		goto out;
703 	}
704 
705 	/* Set PFC */
706 	pfc.pfc_cap = mlx5_max_tc(mdev) + 1;
707 	if (!cee_cfg->pfc_enable)
708 		pfc.pfc_en = 0;
709 	else
710 		for (i = 0; i < CEE_DCBX_MAX_PRIO; i++)
711 			pfc.pfc_en |= cee_cfg->pfc_setting[i] << i;
712 
713 	err = mlx5e_dcbnl_ieee_setpfc(netdev, &pfc);
714 	if (err) {
715 		netdev_err(netdev,
716 			   "%s, Failed to set PFC: %d\n", __func__, err);
717 		goto out;
718 	}
719 out:
720 	return err ? MLX5_DCB_NO_CHG : MLX5_DCB_CHG_RESET;
721 }
722 
723 static u8 mlx5e_dcbnl_getstate(struct net_device *netdev)
724 {
725 	return MLX5E_CEE_STATE_UP;
726 }
727 
728 static void mlx5e_dcbnl_getpermhwaddr(struct net_device *netdev,
729 				      u8 *perm_addr)
730 {
731 	struct mlx5e_priv *priv = netdev_priv(netdev);
732 
733 	if (!perm_addr)
734 		return;
735 
736 	memset(perm_addr, 0xff, MAX_ADDR_LEN);
737 
738 	mlx5_query_mac_address(priv->mdev, perm_addr);
739 }
740 
741 static void mlx5e_dcbnl_setpgtccfgtx(struct net_device *netdev,
742 				     int priority, u8 prio_type,
743 				     u8 pgid, u8 bw_pct, u8 up_map)
744 {
745 	struct mlx5e_priv *priv = netdev_priv(netdev);
746 	struct mlx5e_cee_config *cee_cfg = &priv->dcbx.cee_cfg;
747 
748 	if (priority >= CEE_DCBX_MAX_PRIO) {
749 		netdev_err(netdev,
750 			   "%s, priority is out of range\n", __func__);
751 		return;
752 	}
753 
754 	if (pgid >= CEE_DCBX_MAX_PGS) {
755 		netdev_err(netdev,
756 			   "%s, priority group is out of range\n", __func__);
757 		return;
758 	}
759 
760 	cee_cfg->prio_to_pg_map[priority] = pgid;
761 }
762 
763 static void mlx5e_dcbnl_setpgbwgcfgtx(struct net_device *netdev,
764 				      int pgid, u8 bw_pct)
765 {
766 	struct mlx5e_priv *priv = netdev_priv(netdev);
767 	struct mlx5e_cee_config *cee_cfg = &priv->dcbx.cee_cfg;
768 
769 	if (pgid >= CEE_DCBX_MAX_PGS) {
770 		netdev_err(netdev,
771 			   "%s, priority group is out of range\n", __func__);
772 		return;
773 	}
774 
775 	cee_cfg->pg_bw_pct[pgid] = bw_pct;
776 }
777 
778 static void mlx5e_dcbnl_getpgtccfgtx(struct net_device *netdev,
779 				     int priority, u8 *prio_type,
780 				     u8 *pgid, u8 *bw_pct, u8 *up_map)
781 {
782 	struct mlx5e_priv *priv = netdev_priv(netdev);
783 	struct mlx5_core_dev *mdev = priv->mdev;
784 
785 	if (!MLX5_CAP_GEN(priv->mdev, ets)) {
786 		netdev_err(netdev, "%s, ets is not supported\n", __func__);
787 		return;
788 	}
789 
790 	if (priority >= CEE_DCBX_MAX_PRIO) {
791 		netdev_err(netdev,
792 			   "%s, priority is out of range\n", __func__);
793 		return;
794 	}
795 
796 	*prio_type = 0;
797 	*bw_pct = 0;
798 	*up_map = 0;
799 
800 	if (mlx5_query_port_prio_tc(mdev, priority, pgid))
801 		*pgid = 0;
802 }
803 
804 static void mlx5e_dcbnl_getpgbwgcfgtx(struct net_device *netdev,
805 				      int pgid, u8 *bw_pct)
806 {
807 	struct ieee_ets ets;
808 
809 	if (pgid >= CEE_DCBX_MAX_PGS) {
810 		netdev_err(netdev,
811 			   "%s, priority group is out of range\n", __func__);
812 		return;
813 	}
814 
815 	mlx5e_dcbnl_ieee_getets(netdev, &ets);
816 	*bw_pct = ets.tc_tx_bw[pgid];
817 }
818 
819 static void mlx5e_dcbnl_setpfccfg(struct net_device *netdev,
820 				  int priority, u8 setting)
821 {
822 	struct mlx5e_priv *priv = netdev_priv(netdev);
823 	struct mlx5e_cee_config *cee_cfg = &priv->dcbx.cee_cfg;
824 
825 	if (priority >= CEE_DCBX_MAX_PRIO) {
826 		netdev_err(netdev,
827 			   "%s, priority is out of range\n", __func__);
828 		return;
829 	}
830 
831 	if (setting > 1)
832 		return;
833 
834 	cee_cfg->pfc_setting[priority] = setting;
835 }
836 
837 static int
838 mlx5e_dcbnl_get_priority_pfc(struct net_device *netdev,
839 			     int priority, u8 *setting)
840 {
841 	struct ieee_pfc pfc;
842 	int err;
843 
844 	err = mlx5e_dcbnl_ieee_getpfc(netdev, &pfc);
845 
846 	if (err)
847 		*setting = 0;
848 	else
849 		*setting = (pfc.pfc_en >> priority) & 0x01;
850 
851 	return err;
852 }
853 
854 static void mlx5e_dcbnl_getpfccfg(struct net_device *netdev,
855 				  int priority, u8 *setting)
856 {
857 	if (priority >= CEE_DCBX_MAX_PRIO) {
858 		netdev_err(netdev,
859 			   "%s, priority is out of range\n", __func__);
860 		return;
861 	}
862 
863 	if (!setting)
864 		return;
865 
866 	mlx5e_dcbnl_get_priority_pfc(netdev, priority, setting);
867 }
868 
869 static u8 mlx5e_dcbnl_getcap(struct net_device *netdev,
870 			     int capid, u8 *cap)
871 {
872 	struct mlx5e_priv *priv = netdev_priv(netdev);
873 	struct mlx5_core_dev *mdev = priv->mdev;
874 	u8 rval = 0;
875 
876 	switch (capid) {
877 	case DCB_CAP_ATTR_PG:
878 		*cap = true;
879 		break;
880 	case DCB_CAP_ATTR_PFC:
881 		*cap = true;
882 		break;
883 	case DCB_CAP_ATTR_UP2TC:
884 		*cap = false;
885 		break;
886 	case DCB_CAP_ATTR_PG_TCS:
887 		*cap = 1 << mlx5_max_tc(mdev);
888 		break;
889 	case DCB_CAP_ATTR_PFC_TCS:
890 		*cap = 1 << mlx5_max_tc(mdev);
891 		break;
892 	case DCB_CAP_ATTR_GSP:
893 		*cap = false;
894 		break;
895 	case DCB_CAP_ATTR_BCN:
896 		*cap = false;
897 		break;
898 	case DCB_CAP_ATTR_DCBX:
899 		*cap = priv->dcbx.cap |
900 		       DCB_CAP_DCBX_VER_CEE |
901 		       DCB_CAP_DCBX_VER_IEEE;
902 		break;
903 	default:
904 		*cap = 0;
905 		rval = 1;
906 		break;
907 	}
908 
909 	return rval;
910 }
911 
912 static int mlx5e_dcbnl_getnumtcs(struct net_device *netdev,
913 				 int tcs_id, u8 *num)
914 {
915 	struct mlx5e_priv *priv = netdev_priv(netdev);
916 	struct mlx5_core_dev *mdev = priv->mdev;
917 
918 	switch (tcs_id) {
919 	case DCB_NUMTCS_ATTR_PG:
920 	case DCB_NUMTCS_ATTR_PFC:
921 		*num = mlx5_max_tc(mdev) + 1;
922 		break;
923 	default:
924 		return -EINVAL;
925 	}
926 
927 	return 0;
928 }
929 
930 static u8 mlx5e_dcbnl_getpfcstate(struct net_device *netdev)
931 {
932 	struct ieee_pfc pfc;
933 
934 	if (mlx5e_dcbnl_ieee_getpfc(netdev, &pfc))
935 		return MLX5E_CEE_STATE_DOWN;
936 
937 	return pfc.pfc_en ? MLX5E_CEE_STATE_UP : MLX5E_CEE_STATE_DOWN;
938 }
939 
940 static void mlx5e_dcbnl_setpfcstate(struct net_device *netdev, u8 state)
941 {
942 	struct mlx5e_priv *priv = netdev_priv(netdev);
943 	struct mlx5e_cee_config *cee_cfg = &priv->dcbx.cee_cfg;
944 
945 	if ((state != MLX5E_CEE_STATE_UP) && (state != MLX5E_CEE_STATE_DOWN))
946 		return;
947 
948 	cee_cfg->pfc_enable = state;
949 }
950 
951 static int mlx5e_dcbnl_getbuffer(struct net_device *dev,
952 				 struct dcbnl_buffer *dcb_buffer)
953 {
954 	struct mlx5e_priv *priv = netdev_priv(dev);
955 	struct mlx5_core_dev *mdev = priv->mdev;
956 	struct mlx5e_port_buffer port_buffer;
957 	u8 buffer[MLX5E_MAX_PRIORITY];
958 	int i, err;
959 
960 	if (!MLX5_BUFFER_SUPPORTED(mdev))
961 		return -EOPNOTSUPP;
962 
963 	err = mlx5e_port_query_priority2buffer(mdev, buffer);
964 	if (err)
965 		return err;
966 
967 	for (i = 0; i < MLX5E_MAX_PRIORITY; i++)
968 		dcb_buffer->prio2buffer[i] = buffer[i];
969 
970 	err = mlx5e_port_query_buffer(priv, &port_buffer);
971 	if (err)
972 		return err;
973 
974 	for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++)
975 		dcb_buffer->buffer_size[i] = port_buffer.buffer[i].size;
976 	dcb_buffer->total_size = port_buffer.port_buffer_size -
977 				 port_buffer.internal_buffers_size;
978 
979 	return 0;
980 }
981 
982 static int mlx5e_dcbnl_setbuffer(struct net_device *dev,
983 				 struct dcbnl_buffer *dcb_buffer)
984 {
985 	struct mlx5e_priv *priv = netdev_priv(dev);
986 	struct mlx5_core_dev *mdev = priv->mdev;
987 	struct mlx5e_port_buffer port_buffer;
988 	u8 old_prio2buffer[MLX5E_MAX_PRIORITY];
989 	u32 *buffer_size = NULL;
990 	u8 *prio2buffer = NULL;
991 	u32 changed = 0;
992 	int i, err;
993 
994 	if (!MLX5_BUFFER_SUPPORTED(mdev))
995 		return -EOPNOTSUPP;
996 
997 	for (i = 0; i < DCBX_MAX_BUFFERS; i++)
998 		mlx5_core_dbg(mdev, "buffer[%d]=%d\n", i, dcb_buffer->buffer_size[i]);
999 
1000 	for (i = 0; i < MLX5E_MAX_PRIORITY; i++)
1001 		mlx5_core_dbg(mdev, "priority %d buffer%d\n", i, dcb_buffer->prio2buffer[i]);
1002 
1003 	err = mlx5e_port_query_priority2buffer(mdev, old_prio2buffer);
1004 	if (err)
1005 		return err;
1006 
1007 	for (i = 0; i < MLX5E_MAX_PRIORITY; i++) {
1008 		if (dcb_buffer->prio2buffer[i] != old_prio2buffer[i]) {
1009 			changed |= MLX5E_PORT_BUFFER_PRIO2BUFFER;
1010 			prio2buffer = dcb_buffer->prio2buffer;
1011 			break;
1012 		}
1013 	}
1014 
1015 	err = mlx5e_port_query_buffer(priv, &port_buffer);
1016 	if (err)
1017 		return err;
1018 
1019 	for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++) {
1020 		if (port_buffer.buffer[i].size != dcb_buffer->buffer_size[i]) {
1021 			changed |= MLX5E_PORT_BUFFER_SIZE;
1022 			buffer_size = dcb_buffer->buffer_size;
1023 			break;
1024 		}
1025 	}
1026 
1027 	if (!changed)
1028 		return 0;
1029 
1030 	err = mlx5e_port_manual_buffer_config(priv, changed, dev->mtu, NULL,
1031 					      buffer_size, prio2buffer);
1032 	return err;
1033 }
1034 
1035 static const struct dcbnl_rtnl_ops mlx5e_dcbnl_ops = {
1036 	.ieee_getets	= mlx5e_dcbnl_ieee_getets,
1037 	.ieee_setets	= mlx5e_dcbnl_ieee_setets,
1038 	.ieee_getmaxrate = mlx5e_dcbnl_ieee_getmaxrate,
1039 	.ieee_setmaxrate = mlx5e_dcbnl_ieee_setmaxrate,
1040 	.ieee_getpfc	= mlx5e_dcbnl_ieee_getpfc,
1041 	.ieee_setpfc	= mlx5e_dcbnl_ieee_setpfc,
1042 	.ieee_setapp    = mlx5e_dcbnl_ieee_setapp,
1043 	.ieee_delapp    = mlx5e_dcbnl_ieee_delapp,
1044 	.getdcbx	= mlx5e_dcbnl_getdcbx,
1045 	.setdcbx	= mlx5e_dcbnl_setdcbx,
1046 	.dcbnl_getbuffer = mlx5e_dcbnl_getbuffer,
1047 	.dcbnl_setbuffer = mlx5e_dcbnl_setbuffer,
1048 
1049 /* CEE interfaces */
1050 	.setall         = mlx5e_dcbnl_setall,
1051 	.getstate       = mlx5e_dcbnl_getstate,
1052 	.getpermhwaddr  = mlx5e_dcbnl_getpermhwaddr,
1053 
1054 	.setpgtccfgtx   = mlx5e_dcbnl_setpgtccfgtx,
1055 	.setpgbwgcfgtx  = mlx5e_dcbnl_setpgbwgcfgtx,
1056 	.getpgtccfgtx   = mlx5e_dcbnl_getpgtccfgtx,
1057 	.getpgbwgcfgtx  = mlx5e_dcbnl_getpgbwgcfgtx,
1058 
1059 	.setpfccfg      = mlx5e_dcbnl_setpfccfg,
1060 	.getpfccfg      = mlx5e_dcbnl_getpfccfg,
1061 	.getcap         = mlx5e_dcbnl_getcap,
1062 	.getnumtcs      = mlx5e_dcbnl_getnumtcs,
1063 	.getpfcstate    = mlx5e_dcbnl_getpfcstate,
1064 	.setpfcstate    = mlx5e_dcbnl_setpfcstate,
1065 };
1066 
1067 void mlx5e_dcbnl_build_netdev(struct net_device *netdev)
1068 {
1069 	struct mlx5e_priv *priv = netdev_priv(netdev);
1070 	struct mlx5_core_dev *mdev = priv->mdev;
1071 
1072 	if (MLX5_CAP_GEN(mdev, vport_group_manager) && MLX5_CAP_GEN(mdev, qos))
1073 		netdev->dcbnl_ops = &mlx5e_dcbnl_ops;
1074 }
1075 
1076 static void mlx5e_dcbnl_query_dcbx_mode(struct mlx5e_priv *priv,
1077 					enum mlx5_dcbx_oper_mode *mode)
1078 {
1079 	u32 out[MLX5_ST_SZ_DW(dcbx_param)];
1080 
1081 	*mode = MLX5E_DCBX_PARAM_VER_OPER_HOST;
1082 
1083 	if (!mlx5_query_port_dcbx_param(priv->mdev, out))
1084 		*mode = MLX5_GET(dcbx_param, out, version_oper);
1085 
1086 	/* From driver's point of view, we only care if the mode
1087 	 * is host (HOST) or non-host (AUTO)
1088 	 */
1089 	if (*mode != MLX5E_DCBX_PARAM_VER_OPER_HOST)
1090 		*mode = MLX5E_DCBX_PARAM_VER_OPER_AUTO;
1091 }
1092 
1093 static void mlx5e_ets_init(struct mlx5e_priv *priv)
1094 {
1095 	struct ieee_ets ets;
1096 	int err;
1097 	int i;
1098 
1099 	if (!MLX5_CAP_GEN(priv->mdev, ets))
1100 		return;
1101 
1102 	memset(&ets, 0, sizeof(ets));
1103 	ets.ets_cap = mlx5_max_tc(priv->mdev) + 1;
1104 	for (i = 0; i < ets.ets_cap; i++) {
1105 		ets.tc_tx_bw[i] = MLX5E_MAX_BW_ALLOC;
1106 		ets.tc_tsa[i] = IEEE_8021QAZ_TSA_VENDOR;
1107 		ets.prio_tc[i] = i;
1108 	}
1109 
1110 	if (ets.ets_cap > 1) {
1111 		/* tclass[prio=0]=1, tclass[prio=1]=0, tclass[prio=i]=i (for i>1) */
1112 		ets.prio_tc[0] = 1;
1113 		ets.prio_tc[1] = 0;
1114 	}
1115 
1116 	err = mlx5e_dcbnl_ieee_setets_core(priv, &ets);
1117 	if (err)
1118 		netdev_err(priv->netdev,
1119 			   "%s, Failed to init ETS: %d\n", __func__, err);
1120 }
1121 
1122 enum {
1123 	INIT,
1124 	DELETE,
1125 };
1126 
1127 static void mlx5e_dcbnl_dscp_app(struct mlx5e_priv *priv, int action)
1128 {
1129 	struct dcb_app temp;
1130 	int i;
1131 
1132 	if (!MLX5_CAP_GEN(priv->mdev, vport_group_manager))
1133 		return;
1134 
1135 	if (!MLX5_DSCP_SUPPORTED(priv->mdev))
1136 		return;
1137 
1138 	/* No SEL_DSCP entry in non DSCP state */
1139 	if (priv->dcbx_dp.trust_state != MLX5_QPTS_TRUST_DSCP)
1140 		return;
1141 
1142 	temp.selector = IEEE_8021QAZ_APP_SEL_DSCP;
1143 	for (i = 0; i < MLX5E_MAX_DSCP; i++) {
1144 		temp.protocol = i;
1145 		temp.priority = priv->dcbx_dp.dscp2prio[i];
1146 		if (action == INIT)
1147 			dcb_ieee_setapp(priv->netdev, &temp);
1148 		else
1149 			dcb_ieee_delapp(priv->netdev, &temp);
1150 	}
1151 
1152 	priv->dcbx.dscp_app_cnt = (action == INIT) ? MLX5E_MAX_DSCP : 0;
1153 }
1154 
1155 void mlx5e_dcbnl_init_app(struct mlx5e_priv *priv)
1156 {
1157 	mlx5e_dcbnl_dscp_app(priv, INIT);
1158 }
1159 
1160 void mlx5e_dcbnl_delete_app(struct mlx5e_priv *priv)
1161 {
1162 	mlx5e_dcbnl_dscp_app(priv, DELETE);
1163 }
1164 
1165 static void mlx5e_params_calc_trust_tx_min_inline_mode(struct mlx5_core_dev *mdev,
1166 						       struct mlx5e_params *params,
1167 						       u8 trust_state)
1168 {
1169 	mlx5_query_min_inline(mdev, &params->tx_min_inline_mode);
1170 	if (trust_state == MLX5_QPTS_TRUST_DSCP &&
1171 	    params->tx_min_inline_mode == MLX5_INLINE_MODE_L2)
1172 		params->tx_min_inline_mode = MLX5_INLINE_MODE_IP;
1173 }
1174 
1175 static int mlx5e_update_trust_state_hw(struct mlx5e_priv *priv, void *context)
1176 {
1177 	u8 *trust_state = context;
1178 	int err;
1179 
1180 	err = mlx5_set_trust_state(priv->mdev, *trust_state);
1181 	if (err)
1182 		return err;
1183 	WRITE_ONCE(priv->dcbx_dp.trust_state, *trust_state);
1184 
1185 	return 0;
1186 }
1187 
1188 static int mlx5e_set_trust_state(struct mlx5e_priv *priv, u8 trust_state)
1189 {
1190 	struct mlx5e_params new_params;
1191 	bool reset = true;
1192 	int err;
1193 
1194 	netdev_lock(priv->netdev);
1195 	mutex_lock(&priv->state_lock);
1196 
1197 	new_params = priv->channels.params;
1198 	mlx5e_params_calc_trust_tx_min_inline_mode(priv->mdev, &new_params,
1199 						   trust_state);
1200 
1201 	/* Skip if tx_min_inline is the same */
1202 	if (new_params.tx_min_inline_mode == priv->channels.params.tx_min_inline_mode)
1203 		reset = false;
1204 
1205 	err = mlx5e_safe_switch_params(priv, &new_params,
1206 				       mlx5e_update_trust_state_hw,
1207 				       &trust_state, reset);
1208 
1209 	mutex_unlock(&priv->state_lock);
1210 	netdev_unlock(priv->netdev);
1211 
1212 	return err;
1213 }
1214 
1215 static int mlx5e_set_dscp2prio(struct mlx5e_priv *priv, u8 dscp, u8 prio)
1216 {
1217 	int err;
1218 
1219 	err = mlx5_set_dscp2prio(priv->mdev, dscp, prio);
1220 	if (err)
1221 		return err;
1222 
1223 	priv->dcbx_dp.dscp2prio[dscp] = prio;
1224 	return err;
1225 }
1226 
1227 static int mlx5e_trust_initialize(struct mlx5e_priv *priv)
1228 {
1229 	struct mlx5_core_dev *mdev = priv->mdev;
1230 	u8 trust_state;
1231 	int err;
1232 
1233 	if (!MLX5_DSCP_SUPPORTED(mdev)) {
1234 		WRITE_ONCE(priv->dcbx_dp.trust_state, MLX5_QPTS_TRUST_PCP);
1235 		return 0;
1236 	}
1237 
1238 	err = mlx5_query_trust_state(priv->mdev, &trust_state);
1239 	if (err)
1240 		return err;
1241 	WRITE_ONCE(priv->dcbx_dp.trust_state, trust_state);
1242 
1243 	if (priv->dcbx_dp.trust_state == MLX5_QPTS_TRUST_PCP && priv->dcbx.dscp_app_cnt) {
1244 		/*
1245 		 * Align the driver state with the register state.
1246 		 * Temporary state change is required to enable the app list reset.
1247 		 */
1248 		priv->dcbx_dp.trust_state = MLX5_QPTS_TRUST_DSCP;
1249 		mlx5e_dcbnl_delete_app(priv);
1250 		priv->dcbx_dp.trust_state = MLX5_QPTS_TRUST_PCP;
1251 	}
1252 
1253 	mlx5e_params_calc_trust_tx_min_inline_mode(priv->mdev, &priv->channels.params,
1254 						   priv->dcbx_dp.trust_state);
1255 
1256 	err = mlx5_query_dscp2prio(priv->mdev, priv->dcbx_dp.dscp2prio);
1257 	if (err)
1258 		return err;
1259 
1260 	return 0;
1261 }
1262 
1263 #define MLX5E_BUFFER_CELL_SHIFT 7
1264 
1265 static u16 mlx5e_query_port_buffers_cell_size(struct mlx5e_priv *priv)
1266 {
1267 	struct mlx5_core_dev *mdev = priv->mdev;
1268 	u32 out[MLX5_ST_SZ_DW(sbcam_reg)] = {};
1269 	u32 in[MLX5_ST_SZ_DW(sbcam_reg)] = {};
1270 
1271 	if (!MLX5_CAP_GEN(mdev, sbcam_reg))
1272 		return (1 << MLX5E_BUFFER_CELL_SHIFT);
1273 
1274 	if (mlx5_core_access_reg(mdev, in, sizeof(in), out, sizeof(out),
1275 				 MLX5_REG_SBCAM, 0, 0))
1276 		return (1 << MLX5E_BUFFER_CELL_SHIFT);
1277 
1278 	return MLX5_GET(sbcam_reg, out, cap_cell_size);
1279 }
1280 
1281 void mlx5e_dcbnl_initialize(struct mlx5e_priv *priv)
1282 {
1283 	struct mlx5e_dcbx *dcbx = &priv->dcbx;
1284 	bool max_bw_msb_supported;
1285 	u16 type_max;
1286 
1287 	mlx5e_trust_initialize(priv);
1288 
1289 	if (!MLX5_CAP_GEN(priv->mdev, qos))
1290 		return;
1291 
1292 	if (MLX5_CAP_GEN(priv->mdev, dcbx))
1293 		mlx5e_dcbnl_query_dcbx_mode(priv, &dcbx->mode);
1294 
1295 	priv->dcbx.cap = DCB_CAP_DCBX_VER_CEE |
1296 			 DCB_CAP_DCBX_VER_IEEE;
1297 	if (priv->dcbx.mode == MLX5E_DCBX_PARAM_VER_OPER_HOST)
1298 		priv->dcbx.cap |= DCB_CAP_DCBX_HOST;
1299 
1300 	priv->dcbx.port_buff_cell_sz = mlx5e_query_port_buffers_cell_size(priv);
1301 	priv->dcbx.cable_len = MLX5E_DEFAULT_CABLE_LEN;
1302 
1303 	max_bw_msb_supported = MLX5_CAP_QCAM_FEATURE(priv->mdev,
1304 						     qetcr_qshr_max_bw_val_msb);
1305 	type_max = max_bw_msb_supported ? U16_MAX : U8_MAX;
1306 	priv->dcbx.upper_limit_100mbps = type_max * MLX5E_100MB_TO_KB;
1307 	priv->dcbx.upper_limit_gbps = type_max * MLX5E_1GB_TO_KB;
1308 
1309 	mlx5e_ets_init(priv);
1310 }
1311