Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost
[sfrench/cifs-2.6.git] / drivers / net / ethernet / mellanox / mlx5 / core / en_dcbnl.c
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
38 #define MLX5E_100MB (100000)
39 #define MLX5E_1GB   (1000000)
40
41 #define MLX5E_CEE_STATE_UP    1
42 #define MLX5E_CEE_STATE_DOWN  0
43
44 enum {
45         MLX5E_VENDOR_TC_GROUP_NUM = 7,
46         MLX5E_LOWEST_PRIO_GROUP   = 0,
47 };
48
49 #define MLX5_DSCP_SUPPORTED(mdev) (MLX5_CAP_GEN(mdev, qcam_reg)  && \
50                                    MLX5_CAP_QCAM_REG(mdev, qpts) && \
51                                    MLX5_CAP_QCAM_REG(mdev, qpdpm))
52
53 static int mlx5e_set_trust_state(struct mlx5e_priv *priv, u8 trust_state);
54 static int mlx5e_set_dscp2prio(struct mlx5e_priv *priv, u8 dscp, u8 prio);
55
56 /* If dcbx mode is non-host set the dcbx mode to host.
57  */
58 static int mlx5e_dcbnl_set_dcbx_mode(struct mlx5e_priv *priv,
59                                      enum mlx5_dcbx_oper_mode mode)
60 {
61         struct mlx5_core_dev *mdev = priv->mdev;
62         u32 param[MLX5_ST_SZ_DW(dcbx_param)];
63         int err;
64
65         err = mlx5_query_port_dcbx_param(mdev, param);
66         if (err)
67                 return err;
68
69         MLX5_SET(dcbx_param, param, version_admin, mode);
70         if (mode != MLX5E_DCBX_PARAM_VER_OPER_HOST)
71                 MLX5_SET(dcbx_param, param, willing_admin, 1);
72
73         return mlx5_set_port_dcbx_param(mdev, param);
74 }
75
76 static int mlx5e_dcbnl_switch_to_host_mode(struct mlx5e_priv *priv)
77 {
78         struct mlx5e_dcbx *dcbx = &priv->dcbx;
79         int err;
80
81         if (!MLX5_CAP_GEN(priv->mdev, dcbx))
82                 return 0;
83
84         if (dcbx->mode == MLX5E_DCBX_PARAM_VER_OPER_HOST)
85                 return 0;
86
87         err = mlx5e_dcbnl_set_dcbx_mode(priv, MLX5E_DCBX_PARAM_VER_OPER_HOST);
88         if (err)
89                 return err;
90
91         dcbx->mode = MLX5E_DCBX_PARAM_VER_OPER_HOST;
92         return 0;
93 }
94
95 static int mlx5e_dcbnl_ieee_getets(struct net_device *netdev,
96                                    struct ieee_ets *ets)
97 {
98         struct mlx5e_priv *priv = netdev_priv(netdev);
99         struct mlx5_core_dev *mdev = priv->mdev;
100         u8 tc_group[IEEE_8021QAZ_MAX_TCS];
101         bool is_tc_group_6_exist = false;
102         bool is_zero_bw_ets_tc = false;
103         int err = 0;
104         int i;
105
106         if (!MLX5_CAP_GEN(priv->mdev, ets))
107                 return -EOPNOTSUPP;
108
109         ets->ets_cap = mlx5_max_tc(priv->mdev) + 1;
110         for (i = 0; i < ets->ets_cap; i++) {
111                 err = mlx5_query_port_prio_tc(mdev, i, &ets->prio_tc[i]);
112                 if (err)
113                         return err;
114
115                 err = mlx5_query_port_tc_group(mdev, i, &tc_group[i]);
116                 if (err)
117                         return err;
118
119                 err = mlx5_query_port_tc_bw_alloc(mdev, i, &ets->tc_tx_bw[i]);
120                 if (err)
121                         return err;
122
123                 if (ets->tc_tx_bw[i] < MLX5E_MAX_BW_ALLOC &&
124                     tc_group[i] == (MLX5E_LOWEST_PRIO_GROUP + 1))
125                         is_zero_bw_ets_tc = true;
126
127                 if (tc_group[i] == (MLX5E_VENDOR_TC_GROUP_NUM - 1))
128                         is_tc_group_6_exist = true;
129         }
130
131         /* Report 0% ets tc if exits*/
132         if (is_zero_bw_ets_tc) {
133                 for (i = 0; i < ets->ets_cap; i++)
134                         if (tc_group[i] == MLX5E_LOWEST_PRIO_GROUP)
135                                 ets->tc_tx_bw[i] = 0;
136         }
137
138         /* Update tc_tsa based on fw setting*/
139         for (i = 0; i < ets->ets_cap; i++) {
140                 if (ets->tc_tx_bw[i] < MLX5E_MAX_BW_ALLOC)
141                         priv->dcbx.tc_tsa[i] = IEEE_8021QAZ_TSA_ETS;
142                 else if (tc_group[i] == MLX5E_VENDOR_TC_GROUP_NUM &&
143                          !is_tc_group_6_exist)
144                         priv->dcbx.tc_tsa[i] = IEEE_8021QAZ_TSA_VENDOR;
145         }
146         memcpy(ets->tc_tsa, priv->dcbx.tc_tsa, sizeof(ets->tc_tsa));
147
148         return err;
149 }
150
151 static void mlx5e_build_tc_group(struct ieee_ets *ets, u8 *tc_group, int max_tc)
152 {
153         bool any_tc_mapped_to_ets = false;
154         bool ets_zero_bw = false;
155         int strict_group;
156         int i;
157
158         for (i = 0; i <= max_tc; i++) {
159                 if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_ETS) {
160                         any_tc_mapped_to_ets = true;
161                         if (!ets->tc_tx_bw[i])
162                                 ets_zero_bw = true;
163                 }
164         }
165
166         /* strict group has higher priority than ets group */
167         strict_group = MLX5E_LOWEST_PRIO_GROUP;
168         if (any_tc_mapped_to_ets)
169                 strict_group++;
170         if (ets_zero_bw)
171                 strict_group++;
172
173         for (i = 0; i <= max_tc; i++) {
174                 switch (ets->tc_tsa[i]) {
175                 case IEEE_8021QAZ_TSA_VENDOR:
176                         tc_group[i] = MLX5E_VENDOR_TC_GROUP_NUM;
177                         break;
178                 case IEEE_8021QAZ_TSA_STRICT:
179                         tc_group[i] = strict_group++;
180                         break;
181                 case IEEE_8021QAZ_TSA_ETS:
182                         tc_group[i] = MLX5E_LOWEST_PRIO_GROUP;
183                         if (ets->tc_tx_bw[i] && ets_zero_bw)
184                                 tc_group[i] = MLX5E_LOWEST_PRIO_GROUP + 1;
185                         break;
186                 }
187         }
188 }
189
190 static void mlx5e_build_tc_tx_bw(struct ieee_ets *ets, u8 *tc_tx_bw,
191                                  u8 *tc_group, int max_tc)
192 {
193         int bw_for_ets_zero_bw_tc = 0;
194         int last_ets_zero_bw_tc = -1;
195         int num_ets_zero_bw = 0;
196         int i;
197
198         for (i = 0; i <= max_tc; i++) {
199                 if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_ETS &&
200                     !ets->tc_tx_bw[i]) {
201                         num_ets_zero_bw++;
202                         last_ets_zero_bw_tc = i;
203                 }
204         }
205
206         if (num_ets_zero_bw)
207                 bw_for_ets_zero_bw_tc = MLX5E_MAX_BW_ALLOC / num_ets_zero_bw;
208
209         for (i = 0; i <= max_tc; i++) {
210                 switch (ets->tc_tsa[i]) {
211                 case IEEE_8021QAZ_TSA_VENDOR:
212                         tc_tx_bw[i] = MLX5E_MAX_BW_ALLOC;
213                         break;
214                 case IEEE_8021QAZ_TSA_STRICT:
215                         tc_tx_bw[i] = MLX5E_MAX_BW_ALLOC;
216                         break;
217                 case IEEE_8021QAZ_TSA_ETS:
218                         tc_tx_bw[i] = ets->tc_tx_bw[i] ?
219                                       ets->tc_tx_bw[i] :
220                                       bw_for_ets_zero_bw_tc;
221                         break;
222                 }
223         }
224
225         /* Make sure the total bw for ets zero bw group is 100% */
226         if (last_ets_zero_bw_tc != -1)
227                 tc_tx_bw[last_ets_zero_bw_tc] +=
228                         MLX5E_MAX_BW_ALLOC % num_ets_zero_bw;
229 }
230
231 /* If there are ETS BW 0,
232  *   Set ETS group # to 1 for all ETS non zero BW tcs. Their sum must be 100%.
233  *   Set group #0 to all the ETS BW 0 tcs and
234  *     equally splits the 100% BW between them
235  *   Report both group #0 and #1 as ETS type.
236  *     All the tcs in group #0 will be reported with 0% BW.
237  */
238 int mlx5e_dcbnl_ieee_setets_core(struct mlx5e_priv *priv, struct ieee_ets *ets)
239 {
240         struct mlx5_core_dev *mdev = priv->mdev;
241         u8 tc_tx_bw[IEEE_8021QAZ_MAX_TCS];
242         u8 tc_group[IEEE_8021QAZ_MAX_TCS];
243         int max_tc = mlx5_max_tc(mdev);
244         int err, i;
245
246         mlx5e_build_tc_group(ets, tc_group, max_tc);
247         mlx5e_build_tc_tx_bw(ets, tc_tx_bw, tc_group, max_tc);
248
249         err = mlx5_set_port_prio_tc(mdev, ets->prio_tc);
250         if (err)
251                 return err;
252
253         err = mlx5_set_port_tc_group(mdev, tc_group);
254         if (err)
255                 return err;
256
257         err = mlx5_set_port_tc_bw_alloc(mdev, tc_tx_bw);
258
259         if (err)
260                 return err;
261
262         memcpy(priv->dcbx.tc_tsa, ets->tc_tsa, sizeof(ets->tc_tsa));
263
264         for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
265                 mlx5e_dbg(HW, priv, "%s: prio_%d <=> tc_%d\n",
266                           __func__, i, ets->prio_tc[i]);
267                 mlx5e_dbg(HW, priv, "%s: tc_%d <=> tx_bw_%d%%, group_%d\n",
268                           __func__, i, tc_tx_bw[i], tc_group[i]);
269         }
270
271         return err;
272 }
273
274 static int mlx5e_dbcnl_validate_ets(struct net_device *netdev,
275                                     struct ieee_ets *ets)
276 {
277         int bw_sum = 0;
278         int i;
279
280         /* Validate Priority */
281         for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
282                 if (ets->prio_tc[i] >= MLX5E_MAX_PRIORITY) {
283                         netdev_err(netdev,
284                                    "Failed to validate ETS: priority value greater than max(%d)\n",
285                                     MLX5E_MAX_PRIORITY);
286                         return -EINVAL;
287                 }
288         }
289
290         /* Validate Bandwidth Sum */
291         for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++)
292                 if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_ETS)
293                         bw_sum += ets->tc_tx_bw[i];
294
295         if (bw_sum != 0 && bw_sum != 100) {
296                 netdev_err(netdev,
297                            "Failed to validate ETS: BW sum is illegal\n");
298                 return -EINVAL;
299         }
300         return 0;
301 }
302
303 static int mlx5e_dcbnl_ieee_setets(struct net_device *netdev,
304                                    struct ieee_ets *ets)
305 {
306         struct mlx5e_priv *priv = netdev_priv(netdev);
307         int err;
308
309         if (!MLX5_CAP_GEN(priv->mdev, ets))
310                 return -EOPNOTSUPP;
311
312         err = mlx5e_dbcnl_validate_ets(netdev, ets);
313         if (err)
314                 return err;
315
316         err = mlx5e_dcbnl_ieee_setets_core(priv, ets);
317         if (err)
318                 return err;
319
320         return 0;
321 }
322
323 static int mlx5e_dcbnl_ieee_getpfc(struct net_device *dev,
324                                    struct ieee_pfc *pfc)
325 {
326         struct mlx5e_priv *priv = netdev_priv(dev);
327         struct mlx5_core_dev *mdev = priv->mdev;
328         struct mlx5e_pport_stats *pstats = &priv->stats.pport;
329         int i;
330
331         pfc->pfc_cap = mlx5_max_tc(mdev) + 1;
332         for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
333                 pfc->requests[i]    = PPORT_PER_PRIO_GET(pstats, i, tx_pause);
334                 pfc->indications[i] = PPORT_PER_PRIO_GET(pstats, i, rx_pause);
335         }
336
337         return mlx5_query_port_pfc(mdev, &pfc->pfc_en, NULL);
338 }
339
340 static int mlx5e_dcbnl_ieee_setpfc(struct net_device *dev,
341                                    struct ieee_pfc *pfc)
342 {
343         struct mlx5e_priv *priv = netdev_priv(dev);
344         struct mlx5_core_dev *mdev = priv->mdev;
345         u8 curr_pfc_en;
346         int ret;
347
348         mlx5_query_port_pfc(mdev, &curr_pfc_en, NULL);
349
350         if (pfc->pfc_en == curr_pfc_en)
351                 return 0;
352
353         ret = mlx5_set_port_pfc(mdev, pfc->pfc_en, pfc->pfc_en);
354         mlx5_toggle_port_link(mdev);
355
356         if (!ret) {
357                 mlx5e_dbg(HW, priv,
358                           "%s: PFC per priority bit mask: 0x%x\n",
359                           __func__, pfc->pfc_en);
360         }
361         return ret;
362 }
363
364 static u8 mlx5e_dcbnl_getdcbx(struct net_device *dev)
365 {
366         struct mlx5e_priv *priv = netdev_priv(dev);
367
368         return priv->dcbx.cap;
369 }
370
371 static u8 mlx5e_dcbnl_setdcbx(struct net_device *dev, u8 mode)
372 {
373         struct mlx5e_priv *priv = netdev_priv(dev);
374         struct mlx5e_dcbx *dcbx = &priv->dcbx;
375
376         if (mode & DCB_CAP_DCBX_LLD_MANAGED)
377                 return 1;
378
379         if ((!mode) && MLX5_CAP_GEN(priv->mdev, dcbx)) {
380                 if (dcbx->mode == MLX5E_DCBX_PARAM_VER_OPER_AUTO)
381                         return 0;
382
383                 /* set dcbx to fw controlled */
384                 if (!mlx5e_dcbnl_set_dcbx_mode(priv, MLX5E_DCBX_PARAM_VER_OPER_AUTO)) {
385                         dcbx->mode = MLX5E_DCBX_PARAM_VER_OPER_AUTO;
386                         dcbx->cap &= ~DCB_CAP_DCBX_HOST;
387                         return 0;
388                 }
389
390                 return 1;
391         }
392
393         if (!(mode & DCB_CAP_DCBX_HOST))
394                 return 1;
395
396         if (mlx5e_dcbnl_switch_to_host_mode(netdev_priv(dev)))
397                 return 1;
398
399         dcbx->cap = mode;
400
401         return 0;
402 }
403
404 static int mlx5e_dcbnl_ieee_setapp(struct net_device *dev, struct dcb_app *app)
405 {
406         struct mlx5e_priv *priv = netdev_priv(dev);
407         struct dcb_app temp;
408         bool is_new;
409         int err;
410
411         if (app->selector != IEEE_8021QAZ_APP_SEL_DSCP)
412                 return -EINVAL;
413
414         if (!MLX5_CAP_GEN(priv->mdev, vport_group_manager))
415                 return -EINVAL;
416
417         if (!MLX5_DSCP_SUPPORTED(priv->mdev))
418                 return -EINVAL;
419
420         if (app->protocol >= MLX5E_MAX_DSCP)
421                 return -EINVAL;
422
423         /* Save the old entry info */
424         temp.selector = IEEE_8021QAZ_APP_SEL_DSCP;
425         temp.protocol = app->protocol;
426         temp.priority = priv->dcbx_dp.dscp2prio[app->protocol];
427
428         /* Check if need to switch to dscp trust state */
429         if (!priv->dcbx.dscp_app_cnt) {
430                 err =  mlx5e_set_trust_state(priv, MLX5_QPTS_TRUST_DSCP);
431                 if (err)
432                         return err;
433         }
434
435         /* Skip the fw command if new and old mapping are the same */
436         if (app->priority != priv->dcbx_dp.dscp2prio[app->protocol]) {
437                 err = mlx5e_set_dscp2prio(priv, app->protocol, app->priority);
438                 if (err)
439                         goto fw_err;
440         }
441
442         /* Delete the old entry if exists */
443         is_new = false;
444         err = dcb_ieee_delapp(dev, &temp);
445         if (err)
446                 is_new = true;
447
448         /* Add new entry and update counter */
449         err = dcb_ieee_setapp(dev, app);
450         if (err)
451                 return err;
452
453         if (is_new)
454                 priv->dcbx.dscp_app_cnt++;
455
456         return err;
457
458 fw_err:
459         mlx5e_set_trust_state(priv, MLX5_QPTS_TRUST_PCP);
460         return err;
461 }
462
463 static int mlx5e_dcbnl_ieee_delapp(struct net_device *dev, struct dcb_app *app)
464 {
465         struct mlx5e_priv *priv = netdev_priv(dev);
466         int err;
467
468         if (app->selector != IEEE_8021QAZ_APP_SEL_DSCP)
469                 return -EINVAL;
470
471         if (!MLX5_CAP_GEN(priv->mdev, vport_group_manager))
472                 return -EINVAL;
473
474         if (!MLX5_DSCP_SUPPORTED(priv->mdev))
475                 return -EINVAL;
476
477         if (app->protocol >= MLX5E_MAX_DSCP)
478                 return -EINVAL;
479
480         /* Skip if no dscp app entry */
481         if (!priv->dcbx.dscp_app_cnt)
482                 return -ENOENT;
483
484         /* Check if the entry matches fw setting */
485         if (app->priority != priv->dcbx_dp.dscp2prio[app->protocol])
486                 return -ENOENT;
487
488         /* Delete the app entry */
489         err = dcb_ieee_delapp(dev, app);
490         if (err)
491                 return err;
492
493         /* Reset the priority mapping back to zero */
494         err = mlx5e_set_dscp2prio(priv, app->protocol, 0);
495         if (err)
496                 goto fw_err;
497
498         priv->dcbx.dscp_app_cnt--;
499
500         /* Check if need to switch to pcp trust state */
501         if (!priv->dcbx.dscp_app_cnt)
502                 err = mlx5e_set_trust_state(priv, MLX5_QPTS_TRUST_PCP);
503
504         return err;
505
506 fw_err:
507         mlx5e_set_trust_state(priv, MLX5_QPTS_TRUST_PCP);
508         return err;
509 }
510
511 static int mlx5e_dcbnl_ieee_getmaxrate(struct net_device *netdev,
512                                        struct ieee_maxrate *maxrate)
513 {
514         struct mlx5e_priv *priv    = netdev_priv(netdev);
515         struct mlx5_core_dev *mdev = priv->mdev;
516         u8 max_bw_value[IEEE_8021QAZ_MAX_TCS];
517         u8 max_bw_unit[IEEE_8021QAZ_MAX_TCS];
518         int err;
519         int i;
520
521         err = mlx5_query_port_ets_rate_limit(mdev, max_bw_value, max_bw_unit);
522         if (err)
523                 return err;
524
525         memset(maxrate->tc_maxrate, 0, sizeof(maxrate->tc_maxrate));
526
527         for (i = 0; i <= mlx5_max_tc(mdev); i++) {
528                 switch (max_bw_unit[i]) {
529                 case MLX5_100_MBPS_UNIT:
530                         maxrate->tc_maxrate[i] = max_bw_value[i] * MLX5E_100MB;
531                         break;
532                 case MLX5_GBPS_UNIT:
533                         maxrate->tc_maxrate[i] = max_bw_value[i] * MLX5E_1GB;
534                         break;
535                 case MLX5_BW_NO_LIMIT:
536                         break;
537                 default:
538                         WARN(true, "non-supported BW unit");
539                         break;
540                 }
541         }
542
543         return 0;
544 }
545
546 static int mlx5e_dcbnl_ieee_setmaxrate(struct net_device *netdev,
547                                        struct ieee_maxrate *maxrate)
548 {
549         struct mlx5e_priv *priv    = netdev_priv(netdev);
550         struct mlx5_core_dev *mdev = priv->mdev;
551         u8 max_bw_value[IEEE_8021QAZ_MAX_TCS];
552         u8 max_bw_unit[IEEE_8021QAZ_MAX_TCS];
553         __u64 upper_limit_mbps = roundup(255 * MLX5E_100MB, MLX5E_1GB);
554         int i;
555
556         memset(max_bw_value, 0, sizeof(max_bw_value));
557         memset(max_bw_unit, 0, sizeof(max_bw_unit));
558
559         for (i = 0; i <= mlx5_max_tc(mdev); i++) {
560                 if (!maxrate->tc_maxrate[i]) {
561                         max_bw_unit[i]  = MLX5_BW_NO_LIMIT;
562                         continue;
563                 }
564                 if (maxrate->tc_maxrate[i] < upper_limit_mbps) {
565                         max_bw_value[i] = div_u64(maxrate->tc_maxrate[i],
566                                                   MLX5E_100MB);
567                         max_bw_value[i] = max_bw_value[i] ? max_bw_value[i] : 1;
568                         max_bw_unit[i]  = MLX5_100_MBPS_UNIT;
569                 } else {
570                         max_bw_value[i] = div_u64(maxrate->tc_maxrate[i],
571                                                   MLX5E_1GB);
572                         max_bw_unit[i]  = MLX5_GBPS_UNIT;
573                 }
574         }
575
576         for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
577                 mlx5e_dbg(HW, priv, "%s: tc_%d <=> max_bw %d Gbps\n",
578                           __func__, i, max_bw_value[i]);
579         }
580
581         return mlx5_modify_port_ets_rate_limit(mdev, max_bw_value, max_bw_unit);
582 }
583
584 static u8 mlx5e_dcbnl_setall(struct net_device *netdev)
585 {
586         struct mlx5e_priv *priv = netdev_priv(netdev);
587         struct mlx5e_cee_config *cee_cfg = &priv->dcbx.cee_cfg;
588         struct mlx5_core_dev *mdev = priv->mdev;
589         struct ieee_ets ets;
590         struct ieee_pfc pfc;
591         int err = -EOPNOTSUPP;
592         int i;
593
594         if (!MLX5_CAP_GEN(mdev, ets))
595                 goto out;
596
597         memset(&ets, 0, sizeof(ets));
598         memset(&pfc, 0, sizeof(pfc));
599
600         ets.ets_cap = IEEE_8021QAZ_MAX_TCS;
601         for (i = 0; i < CEE_DCBX_MAX_PGS; i++) {
602                 ets.tc_tx_bw[i] = cee_cfg->pg_bw_pct[i];
603                 ets.tc_rx_bw[i] = cee_cfg->pg_bw_pct[i];
604                 ets.tc_tsa[i]   = IEEE_8021QAZ_TSA_ETS;
605                 ets.prio_tc[i]  = cee_cfg->prio_to_pg_map[i];
606                 mlx5e_dbg(HW, priv,
607                           "%s: Priority group %d: tx_bw %d, rx_bw %d, prio_tc %d\n",
608                           __func__, i, ets.tc_tx_bw[i], ets.tc_rx_bw[i],
609                           ets.prio_tc[i]);
610         }
611
612         err = mlx5e_dbcnl_validate_ets(netdev, &ets);
613         if (err) {
614                 netdev_err(netdev,
615                            "%s, Failed to validate ETS: %d\n", __func__, err);
616                 goto out;
617         }
618
619         err = mlx5e_dcbnl_ieee_setets_core(priv, &ets);
620         if (err) {
621                 netdev_err(netdev,
622                            "%s, Failed to set ETS: %d\n", __func__, err);
623                 goto out;
624         }
625
626         /* Set PFC */
627         pfc.pfc_cap = mlx5_max_tc(mdev) + 1;
628         if (!cee_cfg->pfc_enable)
629                 pfc.pfc_en = 0;
630         else
631                 for (i = 0; i < CEE_DCBX_MAX_PRIO; i++)
632                         pfc.pfc_en |= cee_cfg->pfc_setting[i] << i;
633
634         err = mlx5e_dcbnl_ieee_setpfc(netdev, &pfc);
635         if (err) {
636                 netdev_err(netdev,
637                            "%s, Failed to set PFC: %d\n", __func__, err);
638                 goto out;
639         }
640 out:
641         return err ? MLX5_DCB_NO_CHG : MLX5_DCB_CHG_RESET;
642 }
643
644 static u8 mlx5e_dcbnl_getstate(struct net_device *netdev)
645 {
646         return MLX5E_CEE_STATE_UP;
647 }
648
649 static void mlx5e_dcbnl_getpermhwaddr(struct net_device *netdev,
650                                       u8 *perm_addr)
651 {
652         struct mlx5e_priv *priv = netdev_priv(netdev);
653
654         if (!perm_addr)
655                 return;
656
657         memset(perm_addr, 0xff, MAX_ADDR_LEN);
658
659         mlx5_query_nic_vport_mac_address(priv->mdev, 0, perm_addr);
660 }
661
662 static void mlx5e_dcbnl_setpgtccfgtx(struct net_device *netdev,
663                                      int priority, u8 prio_type,
664                                      u8 pgid, u8 bw_pct, u8 up_map)
665 {
666         struct mlx5e_priv *priv = netdev_priv(netdev);
667         struct mlx5e_cee_config *cee_cfg = &priv->dcbx.cee_cfg;
668
669         if (priority >= CEE_DCBX_MAX_PRIO) {
670                 netdev_err(netdev,
671                            "%s, priority is out of range\n", __func__);
672                 return;
673         }
674
675         if (pgid >= CEE_DCBX_MAX_PGS) {
676                 netdev_err(netdev,
677                            "%s, priority group is out of range\n", __func__);
678                 return;
679         }
680
681         cee_cfg->prio_to_pg_map[priority] = pgid;
682 }
683
684 static void mlx5e_dcbnl_setpgbwgcfgtx(struct net_device *netdev,
685                                       int pgid, u8 bw_pct)
686 {
687         struct mlx5e_priv *priv = netdev_priv(netdev);
688         struct mlx5e_cee_config *cee_cfg = &priv->dcbx.cee_cfg;
689
690         if (pgid >= CEE_DCBX_MAX_PGS) {
691                 netdev_err(netdev,
692                            "%s, priority group is out of range\n", __func__);
693                 return;
694         }
695
696         cee_cfg->pg_bw_pct[pgid] = bw_pct;
697 }
698
699 static void mlx5e_dcbnl_getpgtccfgtx(struct net_device *netdev,
700                                      int priority, u8 *prio_type,
701                                      u8 *pgid, u8 *bw_pct, u8 *up_map)
702 {
703         struct mlx5e_priv *priv = netdev_priv(netdev);
704         struct mlx5_core_dev *mdev = priv->mdev;
705
706         if (!MLX5_CAP_GEN(priv->mdev, ets)) {
707                 netdev_err(netdev, "%s, ets is not supported\n", __func__);
708                 return;
709         }
710
711         if (priority >= CEE_DCBX_MAX_PRIO) {
712                 netdev_err(netdev,
713                            "%s, priority is out of range\n", __func__);
714                 return;
715         }
716
717         *prio_type = 0;
718         *bw_pct = 0;
719         *up_map = 0;
720
721         if (mlx5_query_port_prio_tc(mdev, priority, pgid))
722                 *pgid = 0;
723 }
724
725 static void mlx5e_dcbnl_getpgbwgcfgtx(struct net_device *netdev,
726                                       int pgid, u8 *bw_pct)
727 {
728         struct ieee_ets ets;
729
730         if (pgid >= CEE_DCBX_MAX_PGS) {
731                 netdev_err(netdev,
732                            "%s, priority group is out of range\n", __func__);
733                 return;
734         }
735
736         mlx5e_dcbnl_ieee_getets(netdev, &ets);
737         *bw_pct = ets.tc_tx_bw[pgid];
738 }
739
740 static void mlx5e_dcbnl_setpfccfg(struct net_device *netdev,
741                                   int priority, u8 setting)
742 {
743         struct mlx5e_priv *priv = netdev_priv(netdev);
744         struct mlx5e_cee_config *cee_cfg = &priv->dcbx.cee_cfg;
745
746         if (priority >= CEE_DCBX_MAX_PRIO) {
747                 netdev_err(netdev,
748                            "%s, priority is out of range\n", __func__);
749                 return;
750         }
751
752         if (setting > 1)
753                 return;
754
755         cee_cfg->pfc_setting[priority] = setting;
756 }
757
758 static int
759 mlx5e_dcbnl_get_priority_pfc(struct net_device *netdev,
760                              int priority, u8 *setting)
761 {
762         struct ieee_pfc pfc;
763         int err;
764
765         err = mlx5e_dcbnl_ieee_getpfc(netdev, &pfc);
766
767         if (err)
768                 *setting = 0;
769         else
770                 *setting = (pfc.pfc_en >> priority) & 0x01;
771
772         return err;
773 }
774
775 static void mlx5e_dcbnl_getpfccfg(struct net_device *netdev,
776                                   int priority, u8 *setting)
777 {
778         if (priority >= CEE_DCBX_MAX_PRIO) {
779                 netdev_err(netdev,
780                            "%s, priority is out of range\n", __func__);
781                 return;
782         }
783
784         if (!setting)
785                 return;
786
787         mlx5e_dcbnl_get_priority_pfc(netdev, priority, setting);
788 }
789
790 static u8 mlx5e_dcbnl_getcap(struct net_device *netdev,
791                              int capid, u8 *cap)
792 {
793         struct mlx5e_priv *priv = netdev_priv(netdev);
794         struct mlx5_core_dev *mdev = priv->mdev;
795         u8 rval = 0;
796
797         switch (capid) {
798         case DCB_CAP_ATTR_PG:
799                 *cap = true;
800                 break;
801         case DCB_CAP_ATTR_PFC:
802                 *cap = true;
803                 break;
804         case DCB_CAP_ATTR_UP2TC:
805                 *cap = false;
806                 break;
807         case DCB_CAP_ATTR_PG_TCS:
808                 *cap = 1 << mlx5_max_tc(mdev);
809                 break;
810         case DCB_CAP_ATTR_PFC_TCS:
811                 *cap = 1 << mlx5_max_tc(mdev);
812                 break;
813         case DCB_CAP_ATTR_GSP:
814                 *cap = false;
815                 break;
816         case DCB_CAP_ATTR_BCN:
817                 *cap = false;
818                 break;
819         case DCB_CAP_ATTR_DCBX:
820                 *cap = priv->dcbx.cap |
821                        DCB_CAP_DCBX_VER_CEE |
822                        DCB_CAP_DCBX_VER_IEEE;
823                 break;
824         default:
825                 *cap = 0;
826                 rval = 1;
827                 break;
828         }
829
830         return rval;
831 }
832
833 static int mlx5e_dcbnl_getnumtcs(struct net_device *netdev,
834                                  int tcs_id, u8 *num)
835 {
836         struct mlx5e_priv *priv = netdev_priv(netdev);
837         struct mlx5_core_dev *mdev = priv->mdev;
838
839         switch (tcs_id) {
840         case DCB_NUMTCS_ATTR_PG:
841         case DCB_NUMTCS_ATTR_PFC:
842                 *num = mlx5_max_tc(mdev) + 1;
843                 break;
844         default:
845                 return -EINVAL;
846         }
847
848         return 0;
849 }
850
851 static u8 mlx5e_dcbnl_getpfcstate(struct net_device *netdev)
852 {
853         struct ieee_pfc pfc;
854
855         if (mlx5e_dcbnl_ieee_getpfc(netdev, &pfc))
856                 return MLX5E_CEE_STATE_DOWN;
857
858         return pfc.pfc_en ? MLX5E_CEE_STATE_UP : MLX5E_CEE_STATE_DOWN;
859 }
860
861 static void mlx5e_dcbnl_setpfcstate(struct net_device *netdev, u8 state)
862 {
863         struct mlx5e_priv *priv = netdev_priv(netdev);
864         struct mlx5e_cee_config *cee_cfg = &priv->dcbx.cee_cfg;
865
866         if ((state != MLX5E_CEE_STATE_UP) && (state != MLX5E_CEE_STATE_DOWN))
867                 return;
868
869         cee_cfg->pfc_enable = state;
870 }
871
872 const struct dcbnl_rtnl_ops mlx5e_dcbnl_ops = {
873         .ieee_getets    = mlx5e_dcbnl_ieee_getets,
874         .ieee_setets    = mlx5e_dcbnl_ieee_setets,
875         .ieee_getmaxrate = mlx5e_dcbnl_ieee_getmaxrate,
876         .ieee_setmaxrate = mlx5e_dcbnl_ieee_setmaxrate,
877         .ieee_getpfc    = mlx5e_dcbnl_ieee_getpfc,
878         .ieee_setpfc    = mlx5e_dcbnl_ieee_setpfc,
879         .ieee_setapp    = mlx5e_dcbnl_ieee_setapp,
880         .ieee_delapp    = mlx5e_dcbnl_ieee_delapp,
881         .getdcbx        = mlx5e_dcbnl_getdcbx,
882         .setdcbx        = mlx5e_dcbnl_setdcbx,
883
884 /* CEE interfaces */
885         .setall         = mlx5e_dcbnl_setall,
886         .getstate       = mlx5e_dcbnl_getstate,
887         .getpermhwaddr  = mlx5e_dcbnl_getpermhwaddr,
888
889         .setpgtccfgtx   = mlx5e_dcbnl_setpgtccfgtx,
890         .setpgbwgcfgtx  = mlx5e_dcbnl_setpgbwgcfgtx,
891         .getpgtccfgtx   = mlx5e_dcbnl_getpgtccfgtx,
892         .getpgbwgcfgtx  = mlx5e_dcbnl_getpgbwgcfgtx,
893
894         .setpfccfg      = mlx5e_dcbnl_setpfccfg,
895         .getpfccfg      = mlx5e_dcbnl_getpfccfg,
896         .getcap         = mlx5e_dcbnl_getcap,
897         .getnumtcs      = mlx5e_dcbnl_getnumtcs,
898         .getpfcstate    = mlx5e_dcbnl_getpfcstate,
899         .setpfcstate    = mlx5e_dcbnl_setpfcstate,
900 };
901
902 static void mlx5e_dcbnl_query_dcbx_mode(struct mlx5e_priv *priv,
903                                         enum mlx5_dcbx_oper_mode *mode)
904 {
905         u32 out[MLX5_ST_SZ_DW(dcbx_param)];
906
907         *mode = MLX5E_DCBX_PARAM_VER_OPER_HOST;
908
909         if (!mlx5_query_port_dcbx_param(priv->mdev, out))
910                 *mode = MLX5_GET(dcbx_param, out, version_oper);
911
912         /* From driver's point of view, we only care if the mode
913          * is host (HOST) or non-host (AUTO)
914          */
915         if (*mode != MLX5E_DCBX_PARAM_VER_OPER_HOST)
916                 *mode = MLX5E_DCBX_PARAM_VER_OPER_AUTO;
917 }
918
919 static void mlx5e_ets_init(struct mlx5e_priv *priv)
920 {
921         int i;
922         struct ieee_ets ets;
923
924         if (!MLX5_CAP_GEN(priv->mdev, ets))
925                 return;
926
927         memset(&ets, 0, sizeof(ets));
928         ets.ets_cap = mlx5_max_tc(priv->mdev) + 1;
929         for (i = 0; i < ets.ets_cap; i++) {
930                 ets.tc_tx_bw[i] = MLX5E_MAX_BW_ALLOC;
931                 ets.tc_tsa[i] = IEEE_8021QAZ_TSA_VENDOR;
932                 ets.prio_tc[i] = i;
933         }
934
935         /* tclass[prio=0]=1, tclass[prio=1]=0, tclass[prio=i]=i (for i>1) */
936         ets.prio_tc[0] = 1;
937         ets.prio_tc[1] = 0;
938
939         mlx5e_dcbnl_ieee_setets_core(priv, &ets);
940 }
941
942 enum {
943         INIT,
944         DELETE,
945 };
946
947 static void mlx5e_dcbnl_dscp_app(struct mlx5e_priv *priv, int action)
948 {
949         struct dcb_app temp;
950         int i;
951
952         if (!MLX5_CAP_GEN(priv->mdev, vport_group_manager))
953                 return;
954
955         if (!MLX5_DSCP_SUPPORTED(priv->mdev))
956                 return;
957
958         /* No SEL_DSCP entry in non DSCP state */
959         if (priv->dcbx_dp.trust_state != MLX5_QPTS_TRUST_DSCP)
960                 return;
961
962         temp.selector = IEEE_8021QAZ_APP_SEL_DSCP;
963         for (i = 0; i < MLX5E_MAX_DSCP; i++) {
964                 temp.protocol = i;
965                 temp.priority = priv->dcbx_dp.dscp2prio[i];
966                 if (action == INIT)
967                         dcb_ieee_setapp(priv->netdev, &temp);
968                 else
969                         dcb_ieee_delapp(priv->netdev, &temp);
970         }
971
972         priv->dcbx.dscp_app_cnt = (action == INIT) ? MLX5E_MAX_DSCP : 0;
973 }
974
975 void mlx5e_dcbnl_init_app(struct mlx5e_priv *priv)
976 {
977         mlx5e_dcbnl_dscp_app(priv, INIT);
978 }
979
980 void mlx5e_dcbnl_delete_app(struct mlx5e_priv *priv)
981 {
982         mlx5e_dcbnl_dscp_app(priv, DELETE);
983 }
984
985 static void mlx5e_trust_update_tx_min_inline_mode(struct mlx5e_priv *priv,
986                                                   struct mlx5e_params *params)
987 {
988         params->tx_min_inline_mode = mlx5e_params_calculate_tx_min_inline(priv->mdev);
989         if (priv->dcbx_dp.trust_state == MLX5_QPTS_TRUST_DSCP &&
990             params->tx_min_inline_mode == MLX5_INLINE_MODE_L2)
991                 params->tx_min_inline_mode = MLX5_INLINE_MODE_IP;
992 }
993
994 static void mlx5e_trust_update_sq_inline_mode(struct mlx5e_priv *priv)
995 {
996         struct mlx5e_channels new_channels = {};
997
998         mutex_lock(&priv->state_lock);
999
1000         if (!test_bit(MLX5E_STATE_OPENED, &priv->state))
1001                 goto out;
1002
1003         new_channels.params = priv->channels.params;
1004         mlx5e_trust_update_tx_min_inline_mode(priv, &new_channels.params);
1005
1006         /* Skip if tx_min_inline is the same */
1007         if (new_channels.params.tx_min_inline_mode ==
1008             priv->channels.params.tx_min_inline_mode)
1009                 goto out;
1010
1011         if (mlx5e_open_channels(priv, &new_channels))
1012                 goto out;
1013         mlx5e_switch_priv_channels(priv, &new_channels, NULL);
1014
1015 out:
1016         mutex_unlock(&priv->state_lock);
1017 }
1018
1019 static int mlx5e_set_trust_state(struct mlx5e_priv *priv, u8 trust_state)
1020 {
1021         int err;
1022
1023         err =  mlx5_set_trust_state(priv->mdev, trust_state);
1024         if (err)
1025                 return err;
1026         priv->dcbx_dp.trust_state = trust_state;
1027         mlx5e_trust_update_sq_inline_mode(priv);
1028
1029         return err;
1030 }
1031
1032 static int mlx5e_set_dscp2prio(struct mlx5e_priv *priv, u8 dscp, u8 prio)
1033 {
1034         int err;
1035
1036         err = mlx5_set_dscp2prio(priv->mdev, dscp, prio);
1037         if (err)
1038                 return err;
1039
1040         priv->dcbx_dp.dscp2prio[dscp] = prio;
1041         return err;
1042 }
1043
1044 static int mlx5e_trust_initialize(struct mlx5e_priv *priv)
1045 {
1046         struct mlx5_core_dev *mdev = priv->mdev;
1047         int err;
1048
1049         if (!MLX5_DSCP_SUPPORTED(mdev))
1050                 return 0;
1051
1052         err = mlx5_query_trust_state(priv->mdev, &priv->dcbx_dp.trust_state);
1053         if (err)
1054                 return err;
1055
1056         mlx5e_trust_update_tx_min_inline_mode(priv, &priv->channels.params);
1057
1058         err = mlx5_query_dscp2prio(priv->mdev, priv->dcbx_dp.dscp2prio);
1059         if (err)
1060                 return err;
1061
1062         return 0;
1063 }
1064
1065 void mlx5e_dcbnl_initialize(struct mlx5e_priv *priv)
1066 {
1067         struct mlx5e_dcbx *dcbx = &priv->dcbx;
1068
1069         mlx5e_trust_initialize(priv);
1070
1071         if (!MLX5_CAP_GEN(priv->mdev, qos))
1072                 return;
1073
1074         if (MLX5_CAP_GEN(priv->mdev, dcbx))
1075                 mlx5e_dcbnl_query_dcbx_mode(priv, &dcbx->mode);
1076
1077         priv->dcbx.cap = DCB_CAP_DCBX_VER_CEE |
1078                          DCB_CAP_DCBX_VER_IEEE;
1079         if (priv->dcbx.mode == MLX5E_DCBX_PARAM_VER_OPER_HOST)
1080                 priv->dcbx.cap |= DCB_CAP_DCBX_HOST;
1081
1082         mlx5e_ets_init(priv);
1083 }