Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec...
[linux-2.6-block.git] / drivers / net / ethernet / mellanox / mlx5 / core / en_dcbnl.c
CommitLineData
08fb1dac
SM
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 "en.h"
35
36#define MLX5E_MAX_PRIORITY 8
37
d8880795
TT
38#define MLX5E_100MB (100000)
39#define MLX5E_1GB (1000000)
40
3a6a931d
HN
41#define MLX5E_CEE_STATE_UP 1
42#define MLX5E_CEE_STATE_DOWN 0
43
e207b7e9
HN
44/* If dcbx mode is non-host set the dcbx mode to host.
45 */
46static int mlx5e_dcbnl_set_dcbx_mode(struct mlx5e_priv *priv,
47 enum mlx5_dcbx_oper_mode mode)
48{
49 struct mlx5_core_dev *mdev = priv->mdev;
50 u32 param[MLX5_ST_SZ_DW(dcbx_param)];
51 int err;
52
53 err = mlx5_query_port_dcbx_param(mdev, param);
54 if (err)
55 return err;
56
57 MLX5_SET(dcbx_param, param, version_admin, mode);
58 if (mode != MLX5E_DCBX_PARAM_VER_OPER_HOST)
59 MLX5_SET(dcbx_param, param, willing_admin, 1);
60
61 return mlx5_set_port_dcbx_param(mdev, param);
62}
63
64static int mlx5e_dcbnl_switch_to_host_mode(struct mlx5e_priv *priv)
65{
66 struct mlx5e_dcbx *dcbx = &priv->dcbx;
67 int err;
68
69 if (!MLX5_CAP_GEN(priv->mdev, dcbx))
70 return 0;
71
72 if (dcbx->mode == MLX5E_DCBX_PARAM_VER_OPER_HOST)
73 return 0;
74
75 err = mlx5e_dcbnl_set_dcbx_mode(priv, MLX5E_DCBX_PARAM_VER_OPER_HOST);
76 if (err)
77 return err;
78
79 dcbx->mode = MLX5E_DCBX_PARAM_VER_OPER_HOST;
80 return 0;
81}
82
08fb1dac
SM
83static int mlx5e_dcbnl_ieee_getets(struct net_device *netdev,
84 struct ieee_ets *ets)
85{
86 struct mlx5e_priv *priv = netdev_priv(netdev);
820c2c5e
HN
87 struct mlx5_core_dev *mdev = priv->mdev;
88 int err = 0;
89 int i;
08fb1dac
SM
90
91 if (!MLX5_CAP_GEN(priv->mdev, ets))
92 return -ENOTSUPP;
93
820c2c5e
HN
94 ets->ets_cap = mlx5_max_tc(priv->mdev) + 1;
95 for (i = 0; i < ets->ets_cap; i++) {
96 err = mlx5_query_port_prio_tc(mdev, i, &ets->prio_tc[i]);
97 if (err)
98 return err;
99 }
100
101 for (i = 0; i < ets->ets_cap; i++) {
102 err = mlx5_query_port_tc_bw_alloc(mdev, i, &ets->tc_tx_bw[i]);
103 if (err)
104 return err;
105 if (ets->tc_tx_bw[i] < MLX5E_MAX_BW_ALLOC)
106 priv->dcbx.tc_tsa[i] = IEEE_8021QAZ_TSA_ETS;
107 }
108
109 memcpy(ets->tc_tsa, priv->dcbx.tc_tsa, sizeof(ets->tc_tsa));
110
111 return err;
08fb1dac
SM
112}
113
114enum {
115 MLX5E_VENDOR_TC_GROUP_NUM = 7,
116 MLX5E_ETS_TC_GROUP_NUM = 0,
117};
118
119static void mlx5e_build_tc_group(struct ieee_ets *ets, u8 *tc_group, int max_tc)
120{
121 bool any_tc_mapped_to_ets = false;
122 int strict_group;
123 int i;
124
125 for (i = 0; i <= max_tc; i++)
126 if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_ETS)
127 any_tc_mapped_to_ets = true;
128
129 strict_group = any_tc_mapped_to_ets ? 1 : 0;
130
131 for (i = 0; i <= max_tc; i++) {
132 switch (ets->tc_tsa[i]) {
133 case IEEE_8021QAZ_TSA_VENDOR:
134 tc_group[i] = MLX5E_VENDOR_TC_GROUP_NUM;
135 break;
136 case IEEE_8021QAZ_TSA_STRICT:
137 tc_group[i] = strict_group++;
138 break;
139 case IEEE_8021QAZ_TSA_ETS:
140 tc_group[i] = MLX5E_ETS_TC_GROUP_NUM;
141 break;
142 }
143 }
144}
145
146static void mlx5e_build_tc_tx_bw(struct ieee_ets *ets, u8 *tc_tx_bw,
147 u8 *tc_group, int max_tc)
148{
149 int i;
150
151 for (i = 0; i <= max_tc; i++) {
152 switch (ets->tc_tsa[i]) {
153 case IEEE_8021QAZ_TSA_VENDOR:
154 tc_tx_bw[i] = MLX5E_MAX_BW_ALLOC;
155 break;
156 case IEEE_8021QAZ_TSA_STRICT:
157 tc_tx_bw[i] = MLX5E_MAX_BW_ALLOC;
158 break;
159 case IEEE_8021QAZ_TSA_ETS:
cdcf1121 160 tc_tx_bw[i] = ets->tc_tx_bw[i];
08fb1dac
SM
161 break;
162 }
163 }
164}
165
166int mlx5e_dcbnl_ieee_setets_core(struct mlx5e_priv *priv, struct ieee_ets *ets)
167{
168 struct mlx5_core_dev *mdev = priv->mdev;
169 u8 tc_tx_bw[IEEE_8021QAZ_MAX_TCS];
170 u8 tc_group[IEEE_8021QAZ_MAX_TCS];
171 int max_tc = mlx5_max_tc(mdev);
172 int err;
173
08fb1dac
SM
174 mlx5e_build_tc_group(ets, tc_group, max_tc);
175 mlx5e_build_tc_tx_bw(ets, tc_tx_bw, tc_group, max_tc);
176
177 err = mlx5_set_port_prio_tc(mdev, ets->prio_tc);
178 if (err)
179 return err;
180
181 err = mlx5_set_port_tc_group(mdev, tc_group);
182 if (err)
183 return err;
184
820c2c5e
HN
185 err = mlx5_set_port_tc_bw_alloc(mdev, tc_tx_bw);
186
187 if (err)
188 return err;
189
190 memcpy(priv->dcbx.tc_tsa, ets->tc_tsa, sizeof(ets->tc_tsa));
191
192 return err;
08fb1dac
SM
193}
194
1722b969
EBE
195static int mlx5e_dbcnl_validate_ets(struct net_device *netdev,
196 struct ieee_ets *ets)
08fb1dac
SM
197{
198 int bw_sum = 0;
199 int i;
200
201 /* Validate Priority */
202 for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
1722b969
EBE
203 if (ets->prio_tc[i] >= MLX5E_MAX_PRIORITY) {
204 netdev_err(netdev,
205 "Failed to validate ETS: priority value greater than max(%d)\n",
206 MLX5E_MAX_PRIORITY);
08fb1dac 207 return -EINVAL;
1722b969 208 }
08fb1dac
SM
209 }
210
211 /* Validate Bandwidth Sum */
212 for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
cdcf1121 213 if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_ETS) {
1722b969
EBE
214 if (!ets->tc_tx_bw[i]) {
215 netdev_err(netdev,
216 "Failed to validate ETS: BW 0 is illegal\n");
cdcf1121 217 return -EINVAL;
1722b969 218 }
cdcf1121 219
08fb1dac 220 bw_sum += ets->tc_tx_bw[i];
cdcf1121 221 }
08fb1dac
SM
222 }
223
1722b969
EBE
224 if (bw_sum != 0 && bw_sum != 100) {
225 netdev_err(netdev,
226 "Failed to validate ETS: BW sum is illegal\n");
08fb1dac 227 return -EINVAL;
1722b969 228 }
08fb1dac
SM
229 return 0;
230}
231
232static int mlx5e_dcbnl_ieee_setets(struct net_device *netdev,
233 struct ieee_ets *ets)
234{
235 struct mlx5e_priv *priv = netdev_priv(netdev);
236 int err;
237
820c2c5e
HN
238 if (!MLX5_CAP_GEN(priv->mdev, ets))
239 return -ENOTSUPP;
240
1722b969 241 err = mlx5e_dbcnl_validate_ets(netdev, ets);
08fb1dac
SM
242 if (err)
243 return err;
244
245 err = mlx5e_dcbnl_ieee_setets_core(priv, ets);
246 if (err)
247 return err;
248
08fb1dac
SM
249 return 0;
250}
251
ef918433
AS
252static int mlx5e_dcbnl_ieee_getpfc(struct net_device *dev,
253 struct ieee_pfc *pfc)
254{
255 struct mlx5e_priv *priv = netdev_priv(dev);
256 struct mlx5_core_dev *mdev = priv->mdev;
cf678570
GP
257 struct mlx5e_pport_stats *pstats = &priv->stats.pport;
258 int i;
ef918433
AS
259
260 pfc->pfc_cap = mlx5_max_tc(mdev) + 1;
cf678570
GP
261 for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
262 pfc->requests[i] = PPORT_PER_PRIO_GET(pstats, i, tx_pause);
263 pfc->indications[i] = PPORT_PER_PRIO_GET(pstats, i, rx_pause);
264 }
ef918433
AS
265
266 return mlx5_query_port_pfc(mdev, &pfc->pfc_en, NULL);
267}
268
269static int mlx5e_dcbnl_ieee_setpfc(struct net_device *dev,
270 struct ieee_pfc *pfc)
271{
272 struct mlx5e_priv *priv = netdev_priv(dev);
273 struct mlx5_core_dev *mdev = priv->mdev;
ef918433
AS
274 u8 curr_pfc_en;
275 int ret;
276
277 mlx5_query_port_pfc(mdev, &curr_pfc_en, NULL);
278
279 if (pfc->pfc_en == curr_pfc_en)
280 return 0;
281
ef918433 282 ret = mlx5_set_port_pfc(mdev, pfc->pfc_en, pfc->pfc_en);
667daeda 283 mlx5_toggle_port_link(mdev);
ef918433
AS
284
285 return ret;
286}
287
08fb1dac
SM
288static u8 mlx5e_dcbnl_getdcbx(struct net_device *dev)
289{
0eca995f
HN
290 struct mlx5e_priv *priv = netdev_priv(dev);
291 struct mlx5e_dcbx *dcbx = &priv->dcbx;
292 u8 mode = DCB_CAP_DCBX_VER_IEEE | DCB_CAP_DCBX_VER_CEE;
293
294 if (dcbx->mode == MLX5E_DCBX_PARAM_VER_OPER_HOST)
295 mode |= DCB_CAP_DCBX_HOST;
296
297 return mode;
08fb1dac
SM
298}
299
300static u8 mlx5e_dcbnl_setdcbx(struct net_device *dev, u8 mode)
301{
0eca995f
HN
302 struct mlx5e_priv *priv = netdev_priv(dev);
303 struct mlx5e_dcbx *dcbx = &priv->dcbx;
304
305 if ((!mode) && MLX5_CAP_GEN(priv->mdev, dcbx)) {
306 if (dcbx->mode == MLX5E_DCBX_PARAM_VER_OPER_AUTO)
307 return 0;
308
309 /* set dcbx to fw controlled */
310 if (!mlx5e_dcbnl_set_dcbx_mode(priv, MLX5E_DCBX_PARAM_VER_OPER_AUTO)) {
311 dcbx->mode = MLX5E_DCBX_PARAM_VER_OPER_AUTO;
312 return 0;
313 }
314
315 return 1;
316 }
317
e207b7e9
HN
318 if (mlx5e_dcbnl_switch_to_host_mode(netdev_priv(dev)))
319 return 1;
320
08fb1dac 321 if ((mode & DCB_CAP_DCBX_LLD_MANAGED) ||
3a6a931d 322 !(mode & DCB_CAP_DCBX_VER_CEE) ||
08fb1dac
SM
323 !(mode & DCB_CAP_DCBX_VER_IEEE) ||
324 !(mode & DCB_CAP_DCBX_HOST))
325 return 1;
326
327 return 0;
328}
329
d8880795
TT
330static int mlx5e_dcbnl_ieee_getmaxrate(struct net_device *netdev,
331 struct ieee_maxrate *maxrate)
332{
333 struct mlx5e_priv *priv = netdev_priv(netdev);
334 struct mlx5_core_dev *mdev = priv->mdev;
335 u8 max_bw_value[IEEE_8021QAZ_MAX_TCS];
336 u8 max_bw_unit[IEEE_8021QAZ_MAX_TCS];
337 int err;
338 int i;
339
340 err = mlx5_query_port_ets_rate_limit(mdev, max_bw_value, max_bw_unit);
341 if (err)
342 return err;
343
344 memset(maxrate->tc_maxrate, 0, sizeof(maxrate->tc_maxrate));
345
346 for (i = 0; i <= mlx5_max_tc(mdev); i++) {
347 switch (max_bw_unit[i]) {
348 case MLX5_100_MBPS_UNIT:
349 maxrate->tc_maxrate[i] = max_bw_value[i] * MLX5E_100MB;
350 break;
351 case MLX5_GBPS_UNIT:
352 maxrate->tc_maxrate[i] = max_bw_value[i] * MLX5E_1GB;
353 break;
354 case MLX5_BW_NO_LIMIT:
355 break;
356 default:
357 WARN(true, "non-supported BW unit");
358 break;
359 }
360 }
361
362 return 0;
363}
364
365static int mlx5e_dcbnl_ieee_setmaxrate(struct net_device *netdev,
366 struct ieee_maxrate *maxrate)
367{
368 struct mlx5e_priv *priv = netdev_priv(netdev);
369 struct mlx5_core_dev *mdev = priv->mdev;
370 u8 max_bw_value[IEEE_8021QAZ_MAX_TCS];
371 u8 max_bw_unit[IEEE_8021QAZ_MAX_TCS];
372 __u64 upper_limit_mbps = roundup(255 * MLX5E_100MB, MLX5E_1GB);
373 int i;
374
375 memset(max_bw_value, 0, sizeof(max_bw_value));
376 memset(max_bw_unit, 0, sizeof(max_bw_unit));
377
378 for (i = 0; i <= mlx5_max_tc(mdev); i++) {
379 if (!maxrate->tc_maxrate[i]) {
380 max_bw_unit[i] = MLX5_BW_NO_LIMIT;
381 continue;
382 }
383 if (maxrate->tc_maxrate[i] < upper_limit_mbps) {
384 max_bw_value[i] = div_u64(maxrate->tc_maxrate[i],
385 MLX5E_100MB);
386 max_bw_value[i] = max_bw_value[i] ? max_bw_value[i] : 1;
387 max_bw_unit[i] = MLX5_100_MBPS_UNIT;
388 } else {
389 max_bw_value[i] = div_u64(maxrate->tc_maxrate[i],
390 MLX5E_1GB);
391 max_bw_unit[i] = MLX5_GBPS_UNIT;
392 }
393 }
394
395 return mlx5_modify_port_ets_rate_limit(mdev, max_bw_value, max_bw_unit);
396}
397
3a6a931d
HN
398static u8 mlx5e_dcbnl_setall(struct net_device *netdev)
399{
400 struct mlx5e_priv *priv = netdev_priv(netdev);
401 struct mlx5e_cee_config *cee_cfg = &priv->dcbx.cee_cfg;
402 struct mlx5_core_dev *mdev = priv->mdev;
403 struct ieee_ets ets;
404 struct ieee_pfc pfc;
820c2c5e 405 int err = -ENOTSUPP;
3a6a931d
HN
406 int i;
407
820c2c5e
HN
408 if (!MLX5_CAP_GEN(mdev, ets))
409 goto out;
410
3a6a931d
HN
411 memset(&ets, 0, sizeof(ets));
412 memset(&pfc, 0, sizeof(pfc));
413
414 ets.ets_cap = IEEE_8021QAZ_MAX_TCS;
415 for (i = 0; i < CEE_DCBX_MAX_PGS; i++) {
416 ets.tc_tx_bw[i] = cee_cfg->pg_bw_pct[i];
417 ets.tc_rx_bw[i] = cee_cfg->pg_bw_pct[i];
418 ets.tc_tsa[i] = IEEE_8021QAZ_TSA_ETS;
419 ets.prio_tc[i] = cee_cfg->prio_to_pg_map[i];
420 }
421
422 err = mlx5e_dbcnl_validate_ets(netdev, &ets);
423 if (err) {
424 netdev_err(netdev,
425 "%s, Failed to validate ETS: %d\n", __func__, err);
426 goto out;
427 }
428
429 err = mlx5e_dcbnl_ieee_setets_core(priv, &ets);
430 if (err) {
431 netdev_err(netdev,
432 "%s, Failed to set ETS: %d\n", __func__, err);
433 goto out;
434 }
435
436 /* Set PFC */
437 pfc.pfc_cap = mlx5_max_tc(mdev) + 1;
438 if (!cee_cfg->pfc_enable)
439 pfc.pfc_en = 0;
440 else
441 for (i = 0; i < CEE_DCBX_MAX_PRIO; i++)
442 pfc.pfc_en |= cee_cfg->pfc_setting[i] << i;
443
444 err = mlx5e_dcbnl_ieee_setpfc(netdev, &pfc);
445 if (err) {
446 netdev_err(netdev,
447 "%s, Failed to set PFC: %d\n", __func__, err);
448 goto out;
449 }
450out:
451 return err ? MLX5_DCB_NO_CHG : MLX5_DCB_CHG_RESET;
452}
453
454static u8 mlx5e_dcbnl_getstate(struct net_device *netdev)
455{
456 return MLX5E_CEE_STATE_UP;
457}
458
459static void mlx5e_dcbnl_getpermhwaddr(struct net_device *netdev,
460 u8 *perm_addr)
461{
462 struct mlx5e_priv *priv = netdev_priv(netdev);
463
464 if (!perm_addr)
465 return;
466
467 mlx5_query_nic_vport_mac_address(priv->mdev, 0, perm_addr);
468}
469
470static void mlx5e_dcbnl_setpgtccfgtx(struct net_device *netdev,
471 int priority, u8 prio_type,
472 u8 pgid, u8 bw_pct, u8 up_map)
473{
474 struct mlx5e_priv *priv = netdev_priv(netdev);
475 struct mlx5e_cee_config *cee_cfg = &priv->dcbx.cee_cfg;
476
477 if (priority >= CEE_DCBX_MAX_PRIO) {
478 netdev_err(netdev,
479 "%s, priority is out of range\n", __func__);
480 return;
481 }
482
483 if (pgid >= CEE_DCBX_MAX_PGS) {
484 netdev_err(netdev,
485 "%s, priority group is out of range\n", __func__);
486 return;
487 }
488
489 cee_cfg->prio_to_pg_map[priority] = pgid;
490}
491
492static void mlx5e_dcbnl_setpgbwgcfgtx(struct net_device *netdev,
493 int pgid, u8 bw_pct)
494{
495 struct mlx5e_priv *priv = netdev_priv(netdev);
496 struct mlx5e_cee_config *cee_cfg = &priv->dcbx.cee_cfg;
497
498 if (pgid >= CEE_DCBX_MAX_PGS) {
499 netdev_err(netdev,
500 "%s, priority group is out of range\n", __func__);
501 return;
502 }
503
504 cee_cfg->pg_bw_pct[pgid] = bw_pct;
505}
506
507static void mlx5e_dcbnl_getpgtccfgtx(struct net_device *netdev,
508 int priority, u8 *prio_type,
509 u8 *pgid, u8 *bw_pct, u8 *up_map)
510{
511 struct mlx5e_priv *priv = netdev_priv(netdev);
512 struct mlx5_core_dev *mdev = priv->mdev;
513
514 if (priority >= CEE_DCBX_MAX_PRIO) {
515 netdev_err(netdev,
516 "%s, priority is out of range\n", __func__);
517 return;
518 }
519
520 *prio_type = 0;
521 *bw_pct = 0;
522 *up_map = 0;
523
524 if (mlx5_query_port_prio_tc(mdev, priority, pgid))
525 *pgid = 0;
526}
527
528static void mlx5e_dcbnl_getpgbwgcfgtx(struct net_device *netdev,
529 int pgid, u8 *bw_pct)
530{
531 struct mlx5e_priv *priv = netdev_priv(netdev);
532 struct mlx5_core_dev *mdev = priv->mdev;
533
534 if (pgid >= CEE_DCBX_MAX_PGS) {
535 netdev_err(netdev,
536 "%s, priority group is out of range\n", __func__);
537 return;
538 }
539
540 if (mlx5_query_port_tc_bw_alloc(mdev, pgid, bw_pct))
541 *bw_pct = 0;
542}
543
544static void mlx5e_dcbnl_setpfccfg(struct net_device *netdev,
545 int priority, u8 setting)
546{
547 struct mlx5e_priv *priv = netdev_priv(netdev);
548 struct mlx5e_cee_config *cee_cfg = &priv->dcbx.cee_cfg;
549
550 if (priority >= CEE_DCBX_MAX_PRIO) {
551 netdev_err(netdev,
552 "%s, priority is out of range\n", __func__);
553 return;
554 }
555
556 if (setting > 1)
557 return;
558
559 cee_cfg->pfc_setting[priority] = setting;
560}
561
562static int
563mlx5e_dcbnl_get_priority_pfc(struct net_device *netdev,
564 int priority, u8 *setting)
565{
566 struct ieee_pfc pfc;
567 int err;
568
569 err = mlx5e_dcbnl_ieee_getpfc(netdev, &pfc);
570
571 if (err)
572 *setting = 0;
573 else
574 *setting = (pfc.pfc_en >> priority) & 0x01;
575
576 return err;
577}
578
579static void mlx5e_dcbnl_getpfccfg(struct net_device *netdev,
580 int priority, u8 *setting)
581{
582 if (priority >= CEE_DCBX_MAX_PRIO) {
583 netdev_err(netdev,
584 "%s, priority is out of range\n", __func__);
585 return;
586 }
587
588 if (!setting)
589 return;
590
591 mlx5e_dcbnl_get_priority_pfc(netdev, priority, setting);
592}
593
594static u8 mlx5e_dcbnl_getcap(struct net_device *netdev,
595 int capid, u8 *cap)
596{
597 struct mlx5e_priv *priv = netdev_priv(netdev);
598 struct mlx5_core_dev *mdev = priv->mdev;
599 u8 rval = 0;
600
601 switch (capid) {
602 case DCB_CAP_ATTR_PG:
603 *cap = true;
604 break;
605 case DCB_CAP_ATTR_PFC:
606 *cap = true;
607 break;
608 case DCB_CAP_ATTR_UP2TC:
609 *cap = false;
610 break;
611 case DCB_CAP_ATTR_PG_TCS:
612 *cap = 1 << mlx5_max_tc(mdev);
613 break;
614 case DCB_CAP_ATTR_PFC_TCS:
615 *cap = 1 << mlx5_max_tc(mdev);
616 break;
617 case DCB_CAP_ATTR_GSP:
618 *cap = false;
619 break;
620 case DCB_CAP_ATTR_BCN:
621 *cap = false;
622 break;
623 case DCB_CAP_ATTR_DCBX:
624 *cap = (DCB_CAP_DCBX_LLD_MANAGED |
625 DCB_CAP_DCBX_VER_CEE |
626 DCB_CAP_DCBX_STATIC);
627 break;
628 default:
629 *cap = 0;
630 rval = 1;
631 break;
632 }
633
634 return rval;
635}
636
637static int mlx5e_dcbnl_getnumtcs(struct net_device *netdev,
638 int tcs_id, u8 *num)
639{
640 struct mlx5e_priv *priv = netdev_priv(netdev);
641 struct mlx5_core_dev *mdev = priv->mdev;
642
643 switch (tcs_id) {
644 case DCB_NUMTCS_ATTR_PG:
645 case DCB_NUMTCS_ATTR_PFC:
646 *num = mlx5_max_tc(mdev) + 1;
647 break;
648 default:
649 return -EINVAL;
650 }
651
652 return 0;
653}
654
655static u8 mlx5e_dcbnl_getpfcstate(struct net_device *netdev)
656{
657 struct ieee_pfc pfc;
658
659 if (mlx5e_dcbnl_ieee_getpfc(netdev, &pfc))
660 return MLX5E_CEE_STATE_DOWN;
661
662 return pfc.pfc_en ? MLX5E_CEE_STATE_UP : MLX5E_CEE_STATE_DOWN;
663}
664
665static void mlx5e_dcbnl_setpfcstate(struct net_device *netdev, u8 state)
666{
667 struct mlx5e_priv *priv = netdev_priv(netdev);
668 struct mlx5e_cee_config *cee_cfg = &priv->dcbx.cee_cfg;
669
670 if ((state != MLX5E_CEE_STATE_UP) && (state != MLX5E_CEE_STATE_DOWN))
671 return;
672
673 cee_cfg->pfc_enable = state;
674}
675
08fb1dac
SM
676const struct dcbnl_rtnl_ops mlx5e_dcbnl_ops = {
677 .ieee_getets = mlx5e_dcbnl_ieee_getets,
678 .ieee_setets = mlx5e_dcbnl_ieee_setets,
d8880795
TT
679 .ieee_getmaxrate = mlx5e_dcbnl_ieee_getmaxrate,
680 .ieee_setmaxrate = mlx5e_dcbnl_ieee_setmaxrate,
ef918433
AS
681 .ieee_getpfc = mlx5e_dcbnl_ieee_getpfc,
682 .ieee_setpfc = mlx5e_dcbnl_ieee_setpfc,
08fb1dac
SM
683 .getdcbx = mlx5e_dcbnl_getdcbx,
684 .setdcbx = mlx5e_dcbnl_setdcbx,
3a6a931d
HN
685
686/* CEE interfaces */
687 .setall = mlx5e_dcbnl_setall,
688 .getstate = mlx5e_dcbnl_getstate,
689 .getpermhwaddr = mlx5e_dcbnl_getpermhwaddr,
690
691 .setpgtccfgtx = mlx5e_dcbnl_setpgtccfgtx,
692 .setpgbwgcfgtx = mlx5e_dcbnl_setpgbwgcfgtx,
693 .getpgtccfgtx = mlx5e_dcbnl_getpgtccfgtx,
694 .getpgbwgcfgtx = mlx5e_dcbnl_getpgbwgcfgtx,
695
696 .setpfccfg = mlx5e_dcbnl_setpfccfg,
697 .getpfccfg = mlx5e_dcbnl_getpfccfg,
698 .getcap = mlx5e_dcbnl_getcap,
699 .getnumtcs = mlx5e_dcbnl_getnumtcs,
700 .getpfcstate = mlx5e_dcbnl_getpfcstate,
701 .setpfcstate = mlx5e_dcbnl_setpfcstate,
08fb1dac 702};
e207b7e9
HN
703
704static void mlx5e_dcbnl_query_dcbx_mode(struct mlx5e_priv *priv,
705 enum mlx5_dcbx_oper_mode *mode)
706{
707 u32 out[MLX5_ST_SZ_DW(dcbx_param)];
708
709 *mode = MLX5E_DCBX_PARAM_VER_OPER_HOST;
710
711 if (!mlx5_query_port_dcbx_param(priv->mdev, out))
712 *mode = MLX5_GET(dcbx_param, out, version_oper);
713
714 /* From driver's point of view, we only care if the mode
715 * is host (HOST) or non-host (AUTO)
716 */
717 if (*mode != MLX5E_DCBX_PARAM_VER_OPER_HOST)
718 *mode = MLX5E_DCBX_PARAM_VER_OPER_AUTO;
719}
720
721static void mlx5e_ets_init(struct mlx5e_priv *priv)
722{
723 int i;
724 struct ieee_ets ets;
725
4525a45b
HN
726 if (!MLX5_CAP_GEN(priv->mdev, ets))
727 return;
728
e207b7e9
HN
729 memset(&ets, 0, sizeof(ets));
730 ets.ets_cap = mlx5_max_tc(priv->mdev) + 1;
731 for (i = 0; i < ets.ets_cap; i++) {
732 ets.tc_tx_bw[i] = MLX5E_MAX_BW_ALLOC;
733 ets.tc_tsa[i] = IEEE_8021QAZ_TSA_VENDOR;
734 ets.prio_tc[i] = i;
735 }
736
737 memcpy(priv->dcbx.tc_tsa, ets.tc_tsa, sizeof(ets.tc_tsa));
738
739 /* tclass[prio=0]=1, tclass[prio=1]=0, tclass[prio=i]=i (for i>1) */
740 ets.prio_tc[0] = 1;
741 ets.prio_tc[1] = 0;
742
743 mlx5e_dcbnl_ieee_setets_core(priv, &ets);
744}
745
746void mlx5e_dcbnl_initialize(struct mlx5e_priv *priv)
747{
748 struct mlx5e_dcbx *dcbx = &priv->dcbx;
749
750 if (MLX5_CAP_GEN(priv->mdev, dcbx))
751 mlx5e_dcbnl_query_dcbx_mode(priv, &dcbx->mode);
752
753 mlx5e_ets_init(priv);
754}