Merge branch 'for-viro' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi...
[cascardo/linux.git] / drivers / net / ethernet / mellanox / mlx4 / en_dcb_nl.c
1 /*
2  * Copyright (c) 2011 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  */
33
34 #include <linux/dcbnl.h>
35 #include <linux/math64.h>
36
37 #include "mlx4_en.h"
38 #include "fw_qos.h"
39
40 enum {
41         MLX4_CEE_STATE_DOWN   = 0,
42         MLX4_CEE_STATE_UP     = 1,
43 };
44
45 /* Definitions for QCN
46  */
47
48 struct mlx4_congestion_control_mb_prio_802_1_qau_params {
49         __be32 modify_enable_high;
50         __be32 modify_enable_low;
51         __be32 reserved1;
52         __be32 extended_enable;
53         __be32 rppp_max_rps;
54         __be32 rpg_time_reset;
55         __be32 rpg_byte_reset;
56         __be32 rpg_threshold;
57         __be32 rpg_max_rate;
58         __be32 rpg_ai_rate;
59         __be32 rpg_hai_rate;
60         __be32 rpg_gd;
61         __be32 rpg_min_dec_fac;
62         __be32 rpg_min_rate;
63         __be32 max_time_rise;
64         __be32 max_byte_rise;
65         __be32 max_qdelta;
66         __be32 min_qoffset;
67         __be32 gd_coefficient;
68         __be32 reserved2[5];
69         __be32 cp_sample_base;
70         __be32 reserved3[39];
71 };
72
73 struct mlx4_congestion_control_mb_prio_802_1_qau_statistics {
74         __be64 rppp_rp_centiseconds;
75         __be32 reserved1;
76         __be32 ignored_cnm;
77         __be32 rppp_created_rps;
78         __be32 estimated_total_rate;
79         __be32 max_active_rate_limiter_index;
80         __be32 dropped_cnms_busy_fw;
81         __be32 reserved2;
82         __be32 cnms_handled_successfully;
83         __be32 min_total_limiters_rate;
84         __be32 max_total_limiters_rate;
85         __be32 reserved3[4];
86 };
87
88 static u8 mlx4_en_dcbnl_getcap(struct net_device *dev, int capid, u8 *cap)
89 {
90         struct mlx4_en_priv *priv = netdev_priv(dev);
91
92         switch (capid) {
93         case DCB_CAP_ATTR_PFC:
94                 *cap = true;
95                 break;
96         case DCB_CAP_ATTR_DCBX:
97                 *cap = priv->cee_params.dcbx_cap;
98                 break;
99         case DCB_CAP_ATTR_PFC_TCS:
100                 *cap = 1 <<  mlx4_max_tc(priv->mdev->dev);
101                 break;
102         default:
103                 *cap = false;
104                 break;
105         }
106
107         return 0;
108 }
109
110 static u8 mlx4_en_dcbnl_getpfcstate(struct net_device *netdev)
111 {
112         struct mlx4_en_priv *priv = netdev_priv(netdev);
113
114         return priv->cee_params.dcb_cfg.pfc_state;
115 }
116
117 static void mlx4_en_dcbnl_setpfcstate(struct net_device *netdev, u8 state)
118 {
119         struct mlx4_en_priv *priv = netdev_priv(netdev);
120
121         priv->cee_params.dcb_cfg.pfc_state = state;
122 }
123
124 static void mlx4_en_dcbnl_get_pfc_cfg(struct net_device *netdev, int priority,
125                                       u8 *setting)
126 {
127         struct mlx4_en_priv *priv = netdev_priv(netdev);
128
129         *setting = priv->cee_params.dcb_cfg.tc_config[priority].dcb_pfc;
130 }
131
132 static void mlx4_en_dcbnl_set_pfc_cfg(struct net_device *netdev, int priority,
133                                       u8 setting)
134 {
135         struct mlx4_en_priv *priv = netdev_priv(netdev);
136
137         priv->cee_params.dcb_cfg.tc_config[priority].dcb_pfc = setting;
138         priv->cee_params.dcb_cfg.pfc_state = true;
139 }
140
141 static int mlx4_en_dcbnl_getnumtcs(struct net_device *netdev, int tcid, u8 *num)
142 {
143         struct mlx4_en_priv *priv = netdev_priv(netdev);
144
145         if (!(priv->flags & MLX4_EN_FLAG_DCB_ENABLED))
146                 return -EINVAL;
147
148         if (tcid == DCB_NUMTCS_ATTR_PFC)
149                 *num = mlx4_max_tc(priv->mdev->dev);
150         else
151                 *num = 0;
152
153         return 0;
154 }
155
156 static u8 mlx4_en_dcbnl_set_all(struct net_device *netdev)
157 {
158         struct mlx4_en_priv *priv = netdev_priv(netdev);
159         struct mlx4_en_dev *mdev = priv->mdev;
160         struct mlx4_en_cee_config *dcb_cfg = &priv->cee_params.dcb_cfg;
161         int err = 0;
162
163         if (!(priv->cee_params.dcbx_cap & DCB_CAP_DCBX_VER_CEE))
164                 return -EINVAL;
165
166         if (dcb_cfg->pfc_state) {
167                 int tc;
168
169                 priv->prof->rx_pause = 0;
170                 priv->prof->tx_pause = 0;
171                 for (tc = 0; tc < CEE_DCBX_MAX_PRIO; tc++) {
172                         u8 tc_mask = 1 << tc;
173
174                         switch (dcb_cfg->tc_config[tc].dcb_pfc) {
175                         case pfc_disabled:
176                                 priv->prof->tx_ppp &= ~tc_mask;
177                                 priv->prof->rx_ppp &= ~tc_mask;
178                                 break;
179                         case pfc_enabled_full:
180                                 priv->prof->tx_ppp |= tc_mask;
181                                 priv->prof->rx_ppp |= tc_mask;
182                                 break;
183                         case pfc_enabled_tx:
184                                 priv->prof->tx_ppp |= tc_mask;
185                                 priv->prof->rx_ppp &= ~tc_mask;
186                                 break;
187                         case pfc_enabled_rx:
188                                 priv->prof->tx_ppp &= ~tc_mask;
189                                 priv->prof->rx_ppp |= tc_mask;
190                                 break;
191                         default:
192                                 break;
193                         }
194                 }
195                 en_dbg(DRV, priv, "Set pfc on\n");
196         } else {
197                 priv->prof->rx_pause = 1;
198                 priv->prof->tx_pause = 1;
199                 en_dbg(DRV, priv, "Set pfc off\n");
200         }
201
202         err = mlx4_SET_PORT_general(mdev->dev, priv->port,
203                                     priv->rx_skb_size + ETH_FCS_LEN,
204                                     priv->prof->tx_pause,
205                                     priv->prof->tx_ppp,
206                                     priv->prof->rx_pause,
207                                     priv->prof->rx_ppp);
208         if (err)
209                 en_err(priv, "Failed setting pause params\n");
210         return err;
211 }
212
213 static u8 mlx4_en_dcbnl_get_state(struct net_device *dev)
214 {
215         struct mlx4_en_priv *priv = netdev_priv(dev);
216
217         if (priv->flags & MLX4_EN_FLAG_DCB_ENABLED)
218                 return MLX4_CEE_STATE_UP;
219
220         return MLX4_CEE_STATE_DOWN;
221 }
222
223 static u8 mlx4_en_dcbnl_set_state(struct net_device *dev, u8 state)
224 {
225         struct mlx4_en_priv *priv = netdev_priv(dev);
226         int num_tcs = 0;
227
228         if (!(priv->cee_params.dcbx_cap & DCB_CAP_DCBX_VER_CEE))
229                 return 1;
230
231         if (!!(state) == !!(priv->flags & MLX4_EN_FLAG_DCB_ENABLED))
232                 return 0;
233
234         if (state) {
235                 priv->flags |= MLX4_EN_FLAG_DCB_ENABLED;
236                 num_tcs = IEEE_8021QAZ_MAX_TCS;
237         } else {
238                 priv->flags &= ~MLX4_EN_FLAG_DCB_ENABLED;
239         }
240
241         return mlx4_en_setup_tc(dev, num_tcs);
242 }
243
244 /* On success returns a non-zero 802.1p user priority bitmap
245  * otherwise returns 0 as the invalid user priority bitmap to
246  * indicate an error.
247  */
248 static int mlx4_en_dcbnl_getapp(struct net_device *netdev, u8 idtype, u16 id)
249 {
250         struct mlx4_en_priv *priv = netdev_priv(netdev);
251         struct dcb_app app = {
252                                 .selector = idtype,
253                                 .protocol = id,
254                              };
255         if (!(priv->cee_params.dcbx_cap & DCB_CAP_DCBX_VER_CEE))
256                 return 0;
257
258         return dcb_getapp(netdev, &app);
259 }
260
261 static int mlx4_en_dcbnl_setapp(struct net_device *netdev, u8 idtype,
262                                 u16 id, u8 up)
263 {
264         struct mlx4_en_priv *priv = netdev_priv(netdev);
265         struct dcb_app app;
266
267         if (!(priv->cee_params.dcbx_cap & DCB_CAP_DCBX_VER_CEE))
268                 return -EINVAL;
269
270         memset(&app, 0, sizeof(struct dcb_app));
271         app.selector = idtype;
272         app.protocol = id;
273         app.priority = up;
274
275         return dcb_setapp(netdev, &app);
276 }
277
278 static int mlx4_en_dcbnl_ieee_getets(struct net_device *dev,
279                                    struct ieee_ets *ets)
280 {
281         struct mlx4_en_priv *priv = netdev_priv(dev);
282         struct ieee_ets *my_ets = &priv->ets;
283
284         if (!my_ets)
285                 return -EINVAL;
286
287         ets->ets_cap = IEEE_8021QAZ_MAX_TCS;
288         ets->cbs = my_ets->cbs;
289         memcpy(ets->tc_tx_bw, my_ets->tc_tx_bw, sizeof(ets->tc_tx_bw));
290         memcpy(ets->tc_tsa, my_ets->tc_tsa, sizeof(ets->tc_tsa));
291         memcpy(ets->prio_tc, my_ets->prio_tc, sizeof(ets->prio_tc));
292
293         return 0;
294 }
295
296 static int mlx4_en_ets_validate(struct mlx4_en_priv *priv, struct ieee_ets *ets)
297 {
298         int i;
299         int total_ets_bw = 0;
300         int has_ets_tc = 0;
301
302         for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
303                 if (ets->prio_tc[i] >= MLX4_EN_NUM_UP) {
304                         en_err(priv, "Bad priority in UP <=> TC mapping. TC: %d, UP: %d\n",
305                                         i, ets->prio_tc[i]);
306                         return -EINVAL;
307                 }
308
309                 switch (ets->tc_tsa[i]) {
310                 case IEEE_8021QAZ_TSA_STRICT:
311                         break;
312                 case IEEE_8021QAZ_TSA_ETS:
313                         has_ets_tc = 1;
314                         total_ets_bw += ets->tc_tx_bw[i];
315                         break;
316                 default:
317                         en_err(priv, "TC[%d]: Not supported TSA: %d\n",
318                                         i, ets->tc_tsa[i]);
319                         return -ENOTSUPP;
320                 }
321         }
322
323         if (has_ets_tc && total_ets_bw != MLX4_EN_BW_MAX) {
324                 en_err(priv, "Bad ETS BW sum: %d. Should be exactly 100%%\n",
325                                 total_ets_bw);
326                 return -EINVAL;
327         }
328
329         return 0;
330 }
331
332 static int mlx4_en_config_port_scheduler(struct mlx4_en_priv *priv,
333                 struct ieee_ets *ets, u16 *ratelimit)
334 {
335         struct mlx4_en_dev *mdev = priv->mdev;
336         int num_strict = 0;
337         int i;
338         __u8 tc_tx_bw[IEEE_8021QAZ_MAX_TCS] = { 0 };
339         __u8 pg[IEEE_8021QAZ_MAX_TCS] = { 0 };
340
341         ets = ets ?: &priv->ets;
342         ratelimit = ratelimit ?: priv->maxrate;
343
344         /* higher TC means higher priority => lower pg */
345         for (i = IEEE_8021QAZ_MAX_TCS - 1; i >= 0; i--) {
346                 switch (ets->tc_tsa[i]) {
347                 case IEEE_8021QAZ_TSA_STRICT:
348                         pg[i] = num_strict++;
349                         tc_tx_bw[i] = MLX4_EN_BW_MAX;
350                         break;
351                 case IEEE_8021QAZ_TSA_ETS:
352                         pg[i] = MLX4_EN_TC_ETS;
353                         tc_tx_bw[i] = ets->tc_tx_bw[i] ?: MLX4_EN_BW_MIN;
354                         break;
355                 }
356         }
357
358         return mlx4_SET_PORT_SCHEDULER(mdev->dev, priv->port, tc_tx_bw, pg,
359                         ratelimit);
360 }
361
362 static int
363 mlx4_en_dcbnl_ieee_setets(struct net_device *dev, struct ieee_ets *ets)
364 {
365         struct mlx4_en_priv *priv = netdev_priv(dev);
366         struct mlx4_en_dev *mdev = priv->mdev;
367         int err;
368
369         err = mlx4_en_ets_validate(priv, ets);
370         if (err)
371                 return err;
372
373         err = mlx4_SET_PORT_PRIO2TC(mdev->dev, priv->port, ets->prio_tc);
374         if (err)
375                 return err;
376
377         err = mlx4_en_config_port_scheduler(priv, ets, NULL);
378         if (err)
379                 return err;
380
381         memcpy(&priv->ets, ets, sizeof(priv->ets));
382
383         return 0;
384 }
385
386 static int mlx4_en_dcbnl_ieee_getpfc(struct net_device *dev,
387                 struct ieee_pfc *pfc)
388 {
389         struct mlx4_en_priv *priv = netdev_priv(dev);
390
391         pfc->pfc_cap = IEEE_8021QAZ_MAX_TCS;
392         pfc->pfc_en = priv->prof->tx_ppp;
393
394         return 0;
395 }
396
397 static int mlx4_en_dcbnl_ieee_setpfc(struct net_device *dev,
398                 struct ieee_pfc *pfc)
399 {
400         struct mlx4_en_priv *priv = netdev_priv(dev);
401         struct mlx4_en_port_profile *prof = priv->prof;
402         struct mlx4_en_dev *mdev = priv->mdev;
403         int err;
404
405         en_dbg(DRV, priv, "cap: 0x%x en: 0x%x mbc: 0x%x delay: %d\n",
406                         pfc->pfc_cap,
407                         pfc->pfc_en,
408                         pfc->mbc,
409                         pfc->delay);
410
411         prof->rx_pause = !pfc->pfc_en;
412         prof->tx_pause = !pfc->pfc_en;
413         prof->rx_ppp = pfc->pfc_en;
414         prof->tx_ppp = pfc->pfc_en;
415
416         err = mlx4_SET_PORT_general(mdev->dev, priv->port,
417                                     priv->rx_skb_size + ETH_FCS_LEN,
418                                     prof->tx_pause,
419                                     prof->tx_ppp,
420                                     prof->rx_pause,
421                                     prof->rx_ppp);
422         if (err)
423                 en_err(priv, "Failed setting pause params\n");
424         else
425                 mlx4_en_update_pfc_stats_bitmap(mdev->dev, &priv->stats_bitmap,
426                                                 prof->rx_ppp, prof->rx_pause,
427                                                 prof->tx_ppp, prof->tx_pause);
428
429         return err;
430 }
431
432 static u8 mlx4_en_dcbnl_getdcbx(struct net_device *dev)
433 {
434         struct mlx4_en_priv *priv = netdev_priv(dev);
435
436         return priv->cee_params.dcbx_cap;
437 }
438
439 static u8 mlx4_en_dcbnl_setdcbx(struct net_device *dev, u8 mode)
440 {
441         struct mlx4_en_priv *priv = netdev_priv(dev);
442         struct ieee_ets ets = {0};
443         struct ieee_pfc pfc = {0};
444
445         if (mode == priv->cee_params.dcbx_cap)
446                 return 0;
447
448         if ((mode & DCB_CAP_DCBX_LLD_MANAGED) ||
449             ((mode & DCB_CAP_DCBX_VER_IEEE) &&
450              (mode & DCB_CAP_DCBX_VER_CEE)) ||
451             !(mode & DCB_CAP_DCBX_HOST))
452                 goto err;
453
454         priv->cee_params.dcbx_cap = mode;
455
456         ets.ets_cap = IEEE_8021QAZ_MAX_TCS;
457         pfc.pfc_cap = IEEE_8021QAZ_MAX_TCS;
458
459         if (mode & DCB_CAP_DCBX_VER_IEEE) {
460                 if (mlx4_en_dcbnl_ieee_setets(dev, &ets))
461                         goto err;
462                 if (mlx4_en_dcbnl_ieee_setpfc(dev, &pfc))
463                         goto err;
464         } else if (mode & DCB_CAP_DCBX_VER_CEE) {
465                 if (mlx4_en_dcbnl_set_all(dev))
466                         goto err;
467         } else {
468                 if (mlx4_en_dcbnl_ieee_setets(dev, &ets))
469                         goto err;
470                 if (mlx4_en_dcbnl_ieee_setpfc(dev, &pfc))
471                         goto err;
472                 if (mlx4_en_setup_tc(dev, 0))
473                         goto err;
474         }
475
476         return 0;
477 err:
478         return 1;
479 }
480
481 #define MLX4_RATELIMIT_UNITS_IN_KB 100000 /* rate-limit HW unit in Kbps */
482 static int mlx4_en_dcbnl_ieee_getmaxrate(struct net_device *dev,
483                                    struct ieee_maxrate *maxrate)
484 {
485         struct mlx4_en_priv *priv = netdev_priv(dev);
486         int i;
487
488         for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++)
489                 maxrate->tc_maxrate[i] =
490                         priv->maxrate[i] * MLX4_RATELIMIT_UNITS_IN_KB;
491
492         return 0;
493 }
494
495 static int mlx4_en_dcbnl_ieee_setmaxrate(struct net_device *dev,
496                 struct ieee_maxrate *maxrate)
497 {
498         struct mlx4_en_priv *priv = netdev_priv(dev);
499         u16 tmp[IEEE_8021QAZ_MAX_TCS];
500         int i, err;
501
502         for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
503                 /* Convert from Kbps into HW units, rounding result up.
504                  * Setting to 0, means unlimited BW.
505                  */
506                 tmp[i] = div_u64(maxrate->tc_maxrate[i] +
507                                  MLX4_RATELIMIT_UNITS_IN_KB - 1,
508                                  MLX4_RATELIMIT_UNITS_IN_KB);
509         }
510
511         err = mlx4_en_config_port_scheduler(priv, NULL, tmp);
512         if (err)
513                 return err;
514
515         memcpy(priv->maxrate, tmp, sizeof(priv->maxrate));
516
517         return 0;
518 }
519
520 #define RPG_ENABLE_BIT  31
521 #define CN_TAG_BIT      30
522
523 static int mlx4_en_dcbnl_ieee_getqcn(struct net_device *dev,
524                                      struct ieee_qcn *qcn)
525 {
526         struct mlx4_en_priv *priv = netdev_priv(dev);
527         struct mlx4_congestion_control_mb_prio_802_1_qau_params *hw_qcn;
528         struct mlx4_cmd_mailbox *mailbox_out = NULL;
529         u64 mailbox_in_dma = 0;
530         u32 inmod = 0;
531         int i, err;
532
533         if (!(priv->mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_QCN))
534                 return -EOPNOTSUPP;
535
536         mailbox_out = mlx4_alloc_cmd_mailbox(priv->mdev->dev);
537         if (IS_ERR(mailbox_out))
538                 return -ENOMEM;
539         hw_qcn =
540         (struct mlx4_congestion_control_mb_prio_802_1_qau_params *)
541         mailbox_out->buf;
542
543         for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
544                 inmod = priv->port | ((1 << i) << 8) |
545                          (MLX4_CTRL_ALGO_802_1_QAU_REACTION_POINT << 16);
546                 err = mlx4_cmd_box(priv->mdev->dev, mailbox_in_dma,
547                                    mailbox_out->dma,
548                                    inmod, MLX4_CONGESTION_CONTROL_GET_PARAMS,
549                                    MLX4_CMD_CONGESTION_CTRL_OPCODE,
550                                    MLX4_CMD_TIME_CLASS_C,
551                                    MLX4_CMD_NATIVE);
552                 if (err) {
553                         mlx4_free_cmd_mailbox(priv->mdev->dev, mailbox_out);
554                         return err;
555                 }
556
557                 qcn->rpg_enable[i] =
558                         be32_to_cpu(hw_qcn->extended_enable) >> RPG_ENABLE_BIT;
559                 qcn->rppp_max_rps[i] =
560                         be32_to_cpu(hw_qcn->rppp_max_rps);
561                 qcn->rpg_time_reset[i] =
562                         be32_to_cpu(hw_qcn->rpg_time_reset);
563                 qcn->rpg_byte_reset[i] =
564                         be32_to_cpu(hw_qcn->rpg_byte_reset);
565                 qcn->rpg_threshold[i] =
566                         be32_to_cpu(hw_qcn->rpg_threshold);
567                 qcn->rpg_max_rate[i] =
568                         be32_to_cpu(hw_qcn->rpg_max_rate);
569                 qcn->rpg_ai_rate[i] =
570                         be32_to_cpu(hw_qcn->rpg_ai_rate);
571                 qcn->rpg_hai_rate[i] =
572                         be32_to_cpu(hw_qcn->rpg_hai_rate);
573                 qcn->rpg_gd[i] =
574                         be32_to_cpu(hw_qcn->rpg_gd);
575                 qcn->rpg_min_dec_fac[i] =
576                         be32_to_cpu(hw_qcn->rpg_min_dec_fac);
577                 qcn->rpg_min_rate[i] =
578                         be32_to_cpu(hw_qcn->rpg_min_rate);
579                 qcn->cndd_state_machine[i] =
580                         priv->cndd_state[i];
581         }
582         mlx4_free_cmd_mailbox(priv->mdev->dev, mailbox_out);
583         return 0;
584 }
585
586 static int mlx4_en_dcbnl_ieee_setqcn(struct net_device *dev,
587                                      struct ieee_qcn *qcn)
588 {
589         struct mlx4_en_priv *priv = netdev_priv(dev);
590         struct mlx4_congestion_control_mb_prio_802_1_qau_params *hw_qcn;
591         struct mlx4_cmd_mailbox *mailbox_in = NULL;
592         u64 mailbox_in_dma = 0;
593         u32 inmod = 0;
594         int i, err;
595 #define MODIFY_ENABLE_HIGH_MASK 0xc0000000
596 #define MODIFY_ENABLE_LOW_MASK 0xffc00000
597
598         if (!(priv->mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_QCN))
599                 return -EOPNOTSUPP;
600
601         mailbox_in = mlx4_alloc_cmd_mailbox(priv->mdev->dev);
602         if (IS_ERR(mailbox_in))
603                 return -ENOMEM;
604
605         mailbox_in_dma = mailbox_in->dma;
606         hw_qcn =
607         (struct mlx4_congestion_control_mb_prio_802_1_qau_params *)mailbox_in->buf;
608         for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
609                 inmod = priv->port | ((1 << i) << 8) |
610                          (MLX4_CTRL_ALGO_802_1_QAU_REACTION_POINT << 16);
611
612                 /* Before updating QCN parameter,
613                  * need to set it's modify enable bit to 1
614                  */
615
616                 hw_qcn->modify_enable_high = cpu_to_be32(
617                                                 MODIFY_ENABLE_HIGH_MASK);
618                 hw_qcn->modify_enable_low = cpu_to_be32(MODIFY_ENABLE_LOW_MASK);
619
620                 hw_qcn->extended_enable = cpu_to_be32(qcn->rpg_enable[i] << RPG_ENABLE_BIT);
621                 hw_qcn->rppp_max_rps = cpu_to_be32(qcn->rppp_max_rps[i]);
622                 hw_qcn->rpg_time_reset = cpu_to_be32(qcn->rpg_time_reset[i]);
623                 hw_qcn->rpg_byte_reset = cpu_to_be32(qcn->rpg_byte_reset[i]);
624                 hw_qcn->rpg_threshold = cpu_to_be32(qcn->rpg_threshold[i]);
625                 hw_qcn->rpg_max_rate = cpu_to_be32(qcn->rpg_max_rate[i]);
626                 hw_qcn->rpg_ai_rate = cpu_to_be32(qcn->rpg_ai_rate[i]);
627                 hw_qcn->rpg_hai_rate = cpu_to_be32(qcn->rpg_hai_rate[i]);
628                 hw_qcn->rpg_gd = cpu_to_be32(qcn->rpg_gd[i]);
629                 hw_qcn->rpg_min_dec_fac = cpu_to_be32(qcn->rpg_min_dec_fac[i]);
630                 hw_qcn->rpg_min_rate = cpu_to_be32(qcn->rpg_min_rate[i]);
631                 priv->cndd_state[i] = qcn->cndd_state_machine[i];
632                 if (qcn->cndd_state_machine[i] == DCB_CNDD_INTERIOR_READY)
633                         hw_qcn->extended_enable |= cpu_to_be32(1 << CN_TAG_BIT);
634
635                 err = mlx4_cmd(priv->mdev->dev, mailbox_in_dma, inmod,
636                                MLX4_CONGESTION_CONTROL_SET_PARAMS,
637                                MLX4_CMD_CONGESTION_CTRL_OPCODE,
638                                MLX4_CMD_TIME_CLASS_C,
639                                MLX4_CMD_NATIVE);
640                 if (err) {
641                         mlx4_free_cmd_mailbox(priv->mdev->dev, mailbox_in);
642                         return err;
643                 }
644         }
645         mlx4_free_cmd_mailbox(priv->mdev->dev, mailbox_in);
646         return 0;
647 }
648
649 static int mlx4_en_dcbnl_ieee_getqcnstats(struct net_device *dev,
650                                           struct ieee_qcn_stats *qcn_stats)
651 {
652         struct mlx4_en_priv *priv = netdev_priv(dev);
653         struct mlx4_congestion_control_mb_prio_802_1_qau_statistics *hw_qcn_stats;
654         struct mlx4_cmd_mailbox *mailbox_out = NULL;
655         u64 mailbox_in_dma = 0;
656         u32 inmod = 0;
657         int i, err;
658
659         if (!(priv->mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_QCN))
660                 return -EOPNOTSUPP;
661
662         mailbox_out = mlx4_alloc_cmd_mailbox(priv->mdev->dev);
663         if (IS_ERR(mailbox_out))
664                 return -ENOMEM;
665
666         hw_qcn_stats =
667         (struct mlx4_congestion_control_mb_prio_802_1_qau_statistics *)
668         mailbox_out->buf;
669
670         for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
671                 inmod = priv->port | ((1 << i) << 8) |
672                          (MLX4_CTRL_ALGO_802_1_QAU_REACTION_POINT << 16);
673                 err = mlx4_cmd_box(priv->mdev->dev, mailbox_in_dma,
674                                    mailbox_out->dma, inmod,
675                                    MLX4_CONGESTION_CONTROL_GET_STATISTICS,
676                                    MLX4_CMD_CONGESTION_CTRL_OPCODE,
677                                    MLX4_CMD_TIME_CLASS_C,
678                                    MLX4_CMD_NATIVE);
679                 if (err) {
680                         mlx4_free_cmd_mailbox(priv->mdev->dev, mailbox_out);
681                         return err;
682                 }
683                 qcn_stats->rppp_rp_centiseconds[i] =
684                         be64_to_cpu(hw_qcn_stats->rppp_rp_centiseconds);
685                 qcn_stats->rppp_created_rps[i] =
686                         be32_to_cpu(hw_qcn_stats->rppp_created_rps);
687         }
688         mlx4_free_cmd_mailbox(priv->mdev->dev, mailbox_out);
689         return 0;
690 }
691
692 const struct dcbnl_rtnl_ops mlx4_en_dcbnl_ops = {
693         .ieee_getets            = mlx4_en_dcbnl_ieee_getets,
694         .ieee_setets            = mlx4_en_dcbnl_ieee_setets,
695         .ieee_getmaxrate        = mlx4_en_dcbnl_ieee_getmaxrate,
696         .ieee_setmaxrate        = mlx4_en_dcbnl_ieee_setmaxrate,
697         .ieee_getqcn            = mlx4_en_dcbnl_ieee_getqcn,
698         .ieee_setqcn            = mlx4_en_dcbnl_ieee_setqcn,
699         .ieee_getqcnstats       = mlx4_en_dcbnl_ieee_getqcnstats,
700         .ieee_getpfc            = mlx4_en_dcbnl_ieee_getpfc,
701         .ieee_setpfc            = mlx4_en_dcbnl_ieee_setpfc,
702
703         .getstate       = mlx4_en_dcbnl_get_state,
704         .setstate       = mlx4_en_dcbnl_set_state,
705         .getpfccfg      = mlx4_en_dcbnl_get_pfc_cfg,
706         .setpfccfg      = mlx4_en_dcbnl_set_pfc_cfg,
707         .setall         = mlx4_en_dcbnl_set_all,
708         .getcap         = mlx4_en_dcbnl_getcap,
709         .getnumtcs      = mlx4_en_dcbnl_getnumtcs,
710         .getpfcstate    = mlx4_en_dcbnl_getpfcstate,
711         .setpfcstate    = mlx4_en_dcbnl_setpfcstate,
712         .getapp         = mlx4_en_dcbnl_getapp,
713         .setapp         = mlx4_en_dcbnl_setapp,
714
715         .getdcbx        = mlx4_en_dcbnl_getdcbx,
716         .setdcbx        = mlx4_en_dcbnl_setdcbx,
717 };
718
719 const struct dcbnl_rtnl_ops mlx4_en_dcbnl_pfc_ops = {
720         .ieee_getpfc    = mlx4_en_dcbnl_ieee_getpfc,
721         .ieee_setpfc    = mlx4_en_dcbnl_ieee_setpfc,
722
723         .setstate       = mlx4_en_dcbnl_set_state,
724         .getpfccfg      = mlx4_en_dcbnl_get_pfc_cfg,
725         .setpfccfg      = mlx4_en_dcbnl_set_pfc_cfg,
726         .setall         = mlx4_en_dcbnl_set_all,
727         .getnumtcs      = mlx4_en_dcbnl_getnumtcs,
728         .getpfcstate    = mlx4_en_dcbnl_getpfcstate,
729         .setpfcstate    = mlx4_en_dcbnl_setpfcstate,
730         .getapp         = mlx4_en_dcbnl_getapp,
731         .setapp         = mlx4_en_dcbnl_setapp,
732
733         .getdcbx        = mlx4_en_dcbnl_getdcbx,
734         .setdcbx        = mlx4_en_dcbnl_setdcbx,
735 };