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 */
mlx5e_dcbnl_set_dcbx_mode(struct mlx5e_priv * priv,enum mlx5_dcbx_oper_mode mode)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
mlx5e_dcbnl_switch_to_host_mode(struct mlx5e_priv * priv)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
mlx5e_dcbnl_ieee_getets(struct net_device * netdev,struct ieee_ets * ets)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
mlx5e_build_tc_group(struct ieee_ets * ets,u8 * tc_group,int max_tc)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
mlx5e_build_tc_tx_bw(struct ieee_ets * ets,u8 * tc_tx_bw,u8 * tc_group,int max_tc)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 */
mlx5e_dcbnl_ieee_setets_core(struct mlx5e_priv * priv,struct ieee_ets * ets)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
mlx5e_dbcnl_validate_ets(struct net_device * netdev,struct ieee_ets * ets,bool zero_sum_allowed)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
mlx5e_dcbnl_ieee_setets(struct net_device * netdev,struct ieee_ets * ets)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
mlx5e_dcbnl_ieee_getpfc(struct net_device * dev,struct ieee_pfc * pfc)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
mlx5e_dcbnl_ieee_setpfc(struct net_device * dev,struct ieee_pfc * pfc)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
mlx5e_dcbnl_getdcbx(struct net_device * dev)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
mlx5e_dcbnl_setdcbx(struct net_device * dev,u8 mode)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
mlx5e_dcbnl_ieee_setapp(struct net_device * dev,struct dcb_app * app)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
mlx5e_dcbnl_ieee_delapp(struct net_device * dev,struct dcb_app * app)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
mlx5e_dcbnl_ieee_getmaxrate(struct net_device * netdev,struct ieee_maxrate * maxrate)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
mlx5e_dcbnl_ieee_setmaxrate(struct net_device * netdev,struct ieee_maxrate * maxrate)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
mlx5e_dcbnl_setall(struct net_device * netdev)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
mlx5e_dcbnl_getstate(struct net_device * netdev)723 static u8 mlx5e_dcbnl_getstate(struct net_device *netdev)
724 {
725 return MLX5E_CEE_STATE_UP;
726 }
727
mlx5e_dcbnl_getpermhwaddr(struct net_device * netdev,u8 * perm_addr)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
mlx5e_dcbnl_setpgtccfgtx(struct net_device * netdev,int priority,u8 prio_type,u8 pgid,u8 bw_pct,u8 up_map)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
mlx5e_dcbnl_setpgbwgcfgtx(struct net_device * netdev,int pgid,u8 bw_pct)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
mlx5e_dcbnl_getpgtccfgtx(struct net_device * netdev,int priority,u8 * prio_type,u8 * pgid,u8 * bw_pct,u8 * up_map)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
mlx5e_dcbnl_getpgbwgcfgtx(struct net_device * netdev,int pgid,u8 * bw_pct)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
mlx5e_dcbnl_setpfccfg(struct net_device * netdev,int priority,u8 setting)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
mlx5e_dcbnl_get_priority_pfc(struct net_device * netdev,int priority,u8 * setting)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
mlx5e_dcbnl_getpfccfg(struct net_device * netdev,int priority,u8 * setting)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
mlx5e_dcbnl_getcap(struct net_device * netdev,int capid,u8 * cap)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
mlx5e_dcbnl_getnumtcs(struct net_device * netdev,int tcs_id,u8 * num)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
mlx5e_dcbnl_getpfcstate(struct net_device * netdev)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
mlx5e_dcbnl_setpfcstate(struct net_device * netdev,u8 state)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
mlx5e_dcbnl_getbuffer(struct net_device * dev,struct dcbnl_buffer * dcb_buffer)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
mlx5e_dcbnl_setbuffer(struct net_device * dev,struct dcbnl_buffer * dcb_buffer)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
mlx5e_dcbnl_build_netdev(struct net_device * netdev)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
mlx5e_dcbnl_query_dcbx_mode(struct mlx5e_priv * priv,enum mlx5_dcbx_oper_mode * mode)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
mlx5e_ets_init(struct mlx5e_priv * priv)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
mlx5e_dcbnl_dscp_app(struct mlx5e_priv * priv,int action)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
mlx5e_dcbnl_init_app(struct mlx5e_priv * priv)1155 void mlx5e_dcbnl_init_app(struct mlx5e_priv *priv)
1156 {
1157 mlx5e_dcbnl_dscp_app(priv, INIT);
1158 }
1159
mlx5e_dcbnl_delete_app(struct mlx5e_priv * priv)1160 void mlx5e_dcbnl_delete_app(struct mlx5e_priv *priv)
1161 {
1162 mlx5e_dcbnl_dscp_app(priv, DELETE);
1163 }
1164
mlx5e_params_calc_trust_tx_min_inline_mode(struct mlx5_core_dev * mdev,struct mlx5e_params * params,u8 trust_state)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, ¶ms->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
mlx5e_update_trust_state_hw(struct mlx5e_priv * priv,void * context)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
mlx5e_set_trust_state(struct mlx5e_priv * priv,u8 trust_state)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
mlx5e_set_dscp2prio(struct mlx5e_priv * priv,u8 dscp,u8 prio)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
mlx5e_trust_initialize(struct mlx5e_priv * priv)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
mlx5e_query_port_buffers_cell_size(struct mlx5e_priv * priv)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
mlx5e_dcbnl_initialize(struct mlx5e_priv * priv)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