GNU Linux-libre 4.14.290-gnu1
[releases.git] / drivers / net / ethernet / broadcom / bnxt / bnxt_dcb.c
1 /* Broadcom NetXtreme-C/E network driver.
2  *
3  * Copyright (c) 2014-2016 Broadcom Corporation
4  * Copyright (c) 2016-2017 Broadcom Limited
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation.
9  */
10
11 #include <linux/netdevice.h>
12 #include <linux/types.h>
13 #include <linux/errno.h>
14 #include <linux/rtnetlink.h>
15 #include <linux/interrupt.h>
16 #include <linux/pci.h>
17 #include <linux/etherdevice.h>
18 #include <rdma/ib_verbs.h>
19 #include "bnxt_hsi.h"
20 #include "bnxt.h"
21 #include "bnxt_dcb.h"
22
23 #ifdef CONFIG_BNXT_DCB
24 static int bnxt_hwrm_queue_pri2cos_cfg(struct bnxt *bp, struct ieee_ets *ets)
25 {
26         struct hwrm_queue_pri2cos_cfg_input req = {0};
27         int rc = 0, i;
28         u8 *pri2cos;
29
30         bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_PRI2COS_CFG, -1, -1);
31         req.flags = cpu_to_le32(QUEUE_PRI2COS_CFG_REQ_FLAGS_PATH_BIDIR |
32                                 QUEUE_PRI2COS_CFG_REQ_FLAGS_IVLAN);
33
34         pri2cos = &req.pri0_cos_queue_id;
35         for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
36                 req.enables |= cpu_to_le32(
37                         QUEUE_PRI2COS_CFG_REQ_ENABLES_PRI0_COS_QUEUE_ID << i);
38
39                 pri2cos[i] = bp->q_info[ets->prio_tc[i]].queue_id;
40         }
41         rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
42         return rc;
43 }
44
45 static int bnxt_hwrm_queue_pri2cos_qcfg(struct bnxt *bp, struct ieee_ets *ets)
46 {
47         struct hwrm_queue_pri2cos_qcfg_output *resp = bp->hwrm_cmd_resp_addr;
48         struct hwrm_queue_pri2cos_qcfg_input req = {0};
49         int rc = 0;
50
51         bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_PRI2COS_QCFG, -1, -1);
52         req.flags = cpu_to_le32(QUEUE_PRI2COS_QCFG_REQ_FLAGS_IVLAN);
53
54         mutex_lock(&bp->hwrm_cmd_lock);
55         rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
56         if (!rc) {
57                 u8 *pri2cos = &resp->pri0_cos_queue_id;
58                 int i, j;
59
60                 for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
61                         u8 queue_id = pri2cos[i];
62
63                         for (j = 0; j < bp->max_tc; j++) {
64                                 if (bp->q_info[j].queue_id == queue_id) {
65                                         ets->prio_tc[i] = j;
66                                         break;
67                                 }
68                         }
69                 }
70         }
71         mutex_unlock(&bp->hwrm_cmd_lock);
72         return rc;
73 }
74
75 static int bnxt_hwrm_queue_cos2bw_cfg(struct bnxt *bp, struct ieee_ets *ets,
76                                       u8 max_tc)
77 {
78         struct hwrm_queue_cos2bw_cfg_input req = {0};
79         struct bnxt_cos2bw_cfg cos2bw;
80         int rc = 0, i;
81         void *data;
82
83         bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_COS2BW_CFG, -1, -1);
84         data = &req.unused_0;
85         for (i = 0; i < max_tc; i++, data += sizeof(cos2bw) - 4) {
86                 req.enables |= cpu_to_le32(
87                         QUEUE_COS2BW_CFG_REQ_ENABLES_COS_QUEUE_ID0_VALID << i);
88
89                 memset(&cos2bw, 0, sizeof(cos2bw));
90                 cos2bw.queue_id = bp->q_info[i].queue_id;
91                 if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_STRICT) {
92                         cos2bw.tsa =
93                                 QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_TSA_ASSIGN_SP;
94                         cos2bw.pri_lvl = i;
95                 } else {
96                         cos2bw.tsa =
97                                 QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_TSA_ASSIGN_ETS;
98                         cos2bw.bw_weight = ets->tc_tx_bw[i];
99                         /* older firmware requires min_bw to be set to the
100                          * same weight value in percent.
101                          */
102                         cos2bw.min_bw =
103                                 cpu_to_le32((ets->tc_tx_bw[i] * 100) |
104                                             BW_VALUE_UNIT_PERCENT1_100);
105                 }
106                 memcpy(data, &cos2bw.queue_id, sizeof(cos2bw) - 4);
107                 if (i == 0) {
108                         req.queue_id0 = cos2bw.queue_id;
109                         req.unused_0 = 0;
110                 }
111         }
112         rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
113         return rc;
114 }
115
116 static int bnxt_hwrm_queue_cos2bw_qcfg(struct bnxt *bp, struct ieee_ets *ets)
117 {
118         struct hwrm_queue_cos2bw_qcfg_output *resp = bp->hwrm_cmd_resp_addr;
119         struct hwrm_queue_cos2bw_qcfg_input req = {0};
120         struct bnxt_cos2bw_cfg cos2bw;
121         void *data;
122         int rc, i;
123
124         bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_COS2BW_QCFG, -1, -1);
125
126         mutex_lock(&bp->hwrm_cmd_lock);
127         rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
128         if (rc) {
129                 mutex_unlock(&bp->hwrm_cmd_lock);
130                 return rc;
131         }
132
133         data = &resp->queue_id0 + offsetof(struct bnxt_cos2bw_cfg, queue_id);
134         for (i = 0; i < bp->max_tc; i++, data += sizeof(cos2bw) - 4) {
135                 int j;
136
137                 memcpy(&cos2bw.queue_id, data, sizeof(cos2bw) - 4);
138                 if (i == 0)
139                         cos2bw.queue_id = resp->queue_id0;
140
141                 for (j = 0; j < bp->max_tc; j++) {
142                         if (bp->q_info[j].queue_id != cos2bw.queue_id)
143                                 continue;
144                         if (cos2bw.tsa ==
145                             QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_TSA_ASSIGN_SP) {
146                                 ets->tc_tsa[j] = IEEE_8021QAZ_TSA_STRICT;
147                         } else {
148                                 ets->tc_tsa[j] = IEEE_8021QAZ_TSA_ETS;
149                                 ets->tc_tx_bw[j] = cos2bw.bw_weight;
150                         }
151                 }
152         }
153         mutex_unlock(&bp->hwrm_cmd_lock);
154         return 0;
155 }
156
157 static int bnxt_hwrm_queue_cfg(struct bnxt *bp, unsigned int lltc_mask)
158 {
159         struct hwrm_queue_cfg_input req = {0};
160         int i;
161
162         if (netif_running(bp->dev))
163                 bnxt_tx_disable(bp);
164
165         bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_CFG, -1, -1);
166         req.flags = cpu_to_le32(QUEUE_CFG_REQ_FLAGS_PATH_BIDIR);
167         req.enables = cpu_to_le32(QUEUE_CFG_REQ_ENABLES_SERVICE_PROFILE);
168
169         /* Configure lossless queues to lossy first */
170         req.service_profile = QUEUE_CFG_REQ_SERVICE_PROFILE_LOSSY;
171         for (i = 0; i < bp->max_tc; i++) {
172                 if (BNXT_LLQ(bp->q_info[i].queue_profile)) {
173                         req.queue_id = cpu_to_le32(bp->q_info[i].queue_id);
174                         hwrm_send_message(bp, &req, sizeof(req),
175                                           HWRM_CMD_TIMEOUT);
176                         bp->q_info[i].queue_profile =
177                                 QUEUE_CFG_REQ_SERVICE_PROFILE_LOSSY;
178                 }
179         }
180
181         /* Now configure desired queues to lossless */
182         req.service_profile = QUEUE_CFG_REQ_SERVICE_PROFILE_LOSSLESS;
183         for (i = 0; i < bp->max_tc; i++) {
184                 if (lltc_mask & (1 << i)) {
185                         req.queue_id = cpu_to_le32(bp->q_info[i].queue_id);
186                         hwrm_send_message(bp, &req, sizeof(req),
187                                           HWRM_CMD_TIMEOUT);
188                         bp->q_info[i].queue_profile =
189                                 QUEUE_CFG_REQ_SERVICE_PROFILE_LOSSLESS;
190                 }
191         }
192         if (netif_running(bp->dev))
193                 bnxt_tx_enable(bp);
194
195         return 0;
196 }
197
198 static int bnxt_hwrm_queue_pfc_cfg(struct bnxt *bp, struct ieee_pfc *pfc)
199 {
200         struct hwrm_queue_pfcenable_cfg_input req = {0};
201         struct ieee_ets *my_ets = bp->ieee_ets;
202         unsigned int tc_mask = 0, pri_mask = 0;
203         u8 i, pri, lltc_count = 0;
204         bool need_q_recfg = false;
205         int rc;
206
207         if (!my_ets)
208                 return -EINVAL;
209
210         for (i = 0; i < bp->max_tc; i++) {
211                 for (pri = 0; pri < IEEE_8021QAZ_MAX_TCS; pri++) {
212                         if ((pfc->pfc_en & (1 << pri)) &&
213                             (my_ets->prio_tc[pri] == i)) {
214                                 pri_mask |= 1 << pri;
215                                 tc_mask |= 1 << i;
216                         }
217                 }
218                 if (tc_mask & (1 << i))
219                         lltc_count++;
220         }
221         if (lltc_count > bp->max_lltc)
222                 return -EINVAL;
223
224         bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_PFCENABLE_CFG, -1, -1);
225         req.flags = cpu_to_le32(pri_mask);
226         rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
227         if (rc)
228                 return rc;
229
230         for (i = 0; i < bp->max_tc; i++) {
231                 if (tc_mask & (1 << i)) {
232                         if (!BNXT_LLQ(bp->q_info[i].queue_profile))
233                                 need_q_recfg = true;
234                 }
235         }
236
237         if (need_q_recfg)
238                 rc = bnxt_hwrm_queue_cfg(bp, tc_mask);
239
240         return rc;
241 }
242
243 static int bnxt_hwrm_queue_pfc_qcfg(struct bnxt *bp, struct ieee_pfc *pfc)
244 {
245         struct hwrm_queue_pfcenable_qcfg_output *resp = bp->hwrm_cmd_resp_addr;
246         struct hwrm_queue_pfcenable_qcfg_input req = {0};
247         u8 pri_mask;
248         int rc;
249
250         bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_PFCENABLE_QCFG, -1, -1);
251
252         mutex_lock(&bp->hwrm_cmd_lock);
253         rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
254         if (rc) {
255                 mutex_unlock(&bp->hwrm_cmd_lock);
256                 return rc;
257         }
258
259         pri_mask = le32_to_cpu(resp->flags);
260         pfc->pfc_en = pri_mask;
261         mutex_unlock(&bp->hwrm_cmd_lock);
262         return 0;
263 }
264
265 static int bnxt_hwrm_set_dcbx_app(struct bnxt *bp, struct dcb_app *app,
266                                   bool add)
267 {
268         struct hwrm_fw_set_structured_data_input set = {0};
269         struct hwrm_fw_get_structured_data_input get = {0};
270         struct hwrm_struct_data_dcbx_app *fw_app;
271         struct hwrm_struct_hdr *data;
272         dma_addr_t mapping;
273         size_t data_len;
274         int rc, n, i;
275
276         if (bp->hwrm_spec_code < 0x10601)
277                 return 0;
278
279         n = IEEE_8021QAZ_MAX_TCS;
280         data_len = sizeof(*data) + sizeof(*fw_app) * n;
281         data = dma_alloc_coherent(&bp->pdev->dev, data_len, &mapping,
282                                   GFP_KERNEL);
283         if (!data)
284                 return -ENOMEM;
285
286         memset(data, 0, data_len);
287         bnxt_hwrm_cmd_hdr_init(bp, &get, HWRM_FW_GET_STRUCTURED_DATA, -1, -1);
288         get.dest_data_addr = cpu_to_le64(mapping);
289         get.structure_id = cpu_to_le16(STRUCT_HDR_STRUCT_ID_DCBX_APP);
290         get.subtype = cpu_to_le16(HWRM_STRUCT_DATA_SUBTYPE_HOST_OPERATIONAL);
291         get.count = 0;
292         rc = hwrm_send_message(bp, &get, sizeof(get), HWRM_CMD_TIMEOUT);
293         if (rc)
294                 goto set_app_exit;
295
296         fw_app = (struct hwrm_struct_data_dcbx_app *)(data + 1);
297
298         if (data->struct_id != cpu_to_le16(STRUCT_HDR_STRUCT_ID_DCBX_APP)) {
299                 rc = -ENODEV;
300                 goto set_app_exit;
301         }
302
303         n = data->count;
304         for (i = 0; i < n; i++, fw_app++) {
305                 if (fw_app->protocol_id == cpu_to_be16(app->protocol) &&
306                     fw_app->protocol_selector == app->selector &&
307                     fw_app->priority == app->priority) {
308                         if (add)
309                                 goto set_app_exit;
310                         else
311                                 break;
312                 }
313         }
314         if (add) {
315                 /* append */
316                 n++;
317                 fw_app->protocol_id = cpu_to_be16(app->protocol);
318                 fw_app->protocol_selector = app->selector;
319                 fw_app->priority = app->priority;
320                 fw_app->valid = 1;
321         } else {
322                 size_t len = 0;
323
324                 /* not found, nothing to delete */
325                 if (n == i)
326                         goto set_app_exit;
327
328                 len = (n - 1 - i) * sizeof(*fw_app);
329                 if (len)
330                         memmove(fw_app, fw_app + 1, len);
331                 n--;
332                 memset(fw_app + n, 0, sizeof(*fw_app));
333         }
334         data->count = n;
335         data->len = cpu_to_le16(sizeof(*fw_app) * n);
336         data->subtype = cpu_to_le16(HWRM_STRUCT_DATA_SUBTYPE_HOST_OPERATIONAL);
337
338         bnxt_hwrm_cmd_hdr_init(bp, &set, HWRM_FW_SET_STRUCTURED_DATA, -1, -1);
339         set.src_data_addr = cpu_to_le64(mapping);
340         set.data_len = cpu_to_le16(sizeof(*data) + sizeof(*fw_app) * n);
341         set.hdr_cnt = 1;
342         rc = hwrm_send_message(bp, &set, sizeof(set), HWRM_CMD_TIMEOUT);
343         if (rc)
344                 rc = -EIO;
345
346 set_app_exit:
347         dma_free_coherent(&bp->pdev->dev, data_len, data, mapping);
348         return rc;
349 }
350
351 static int bnxt_ets_validate(struct bnxt *bp, struct ieee_ets *ets, u8 *tc)
352 {
353         int total_ets_bw = 0;
354         u8 max_tc = 0;
355         int i;
356
357         for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
358                 if (ets->prio_tc[i] > bp->max_tc) {
359                         netdev_err(bp->dev, "priority to TC mapping exceeds TC count %d\n",
360                                    ets->prio_tc[i]);
361                         return -EINVAL;
362                 }
363                 if (ets->prio_tc[i] > max_tc)
364                         max_tc = ets->prio_tc[i];
365
366                 if ((ets->tc_tx_bw[i] || ets->tc_tsa[i]) && i > bp->max_tc)
367                         return -EINVAL;
368
369                 switch (ets->tc_tsa[i]) {
370                 case IEEE_8021QAZ_TSA_STRICT:
371                         break;
372                 case IEEE_8021QAZ_TSA_ETS:
373                         total_ets_bw += ets->tc_tx_bw[i];
374                         break;
375                 default:
376                         return -ENOTSUPP;
377                 }
378         }
379         if (total_ets_bw > 100)
380                 return -EINVAL;
381
382         *tc = max_tc + 1;
383         return 0;
384 }
385
386 static int bnxt_dcbnl_ieee_getets(struct net_device *dev, struct ieee_ets *ets)
387 {
388         struct bnxt *bp = netdev_priv(dev);
389         struct ieee_ets *my_ets = bp->ieee_ets;
390         int rc;
391
392         ets->ets_cap = bp->max_tc;
393
394         if (!my_ets) {
395                 if (bp->dcbx_cap & DCB_CAP_DCBX_HOST)
396                         return 0;
397
398                 my_ets = kzalloc(sizeof(*my_ets), GFP_KERNEL);
399                 if (!my_ets)
400                         return -ENOMEM;
401                 rc = bnxt_hwrm_queue_cos2bw_qcfg(bp, my_ets);
402                 if (rc)
403                         goto error;
404                 rc = bnxt_hwrm_queue_pri2cos_qcfg(bp, my_ets);
405                 if (rc)
406                         goto error;
407
408                 /* cache result */
409                 bp->ieee_ets = my_ets;
410         }
411
412         ets->cbs = my_ets->cbs;
413         memcpy(ets->tc_tx_bw, my_ets->tc_tx_bw, sizeof(ets->tc_tx_bw));
414         memcpy(ets->tc_rx_bw, my_ets->tc_rx_bw, sizeof(ets->tc_rx_bw));
415         memcpy(ets->tc_tsa, my_ets->tc_tsa, sizeof(ets->tc_tsa));
416         memcpy(ets->prio_tc, my_ets->prio_tc, sizeof(ets->prio_tc));
417         return 0;
418 error:
419         kfree(my_ets);
420         return rc;
421 }
422
423 static int bnxt_dcbnl_ieee_setets(struct net_device *dev, struct ieee_ets *ets)
424 {
425         struct bnxt *bp = netdev_priv(dev);
426         struct ieee_ets *my_ets = bp->ieee_ets;
427         u8 max_tc = 0;
428         int rc, i;
429
430         if (!(bp->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) ||
431             !(bp->dcbx_cap & DCB_CAP_DCBX_HOST))
432                 return -EINVAL;
433
434         rc = bnxt_ets_validate(bp, ets, &max_tc);
435         if (!rc) {
436                 if (!my_ets) {
437                         my_ets = kzalloc(sizeof(*my_ets), GFP_KERNEL);
438                         if (!my_ets)
439                                 return -ENOMEM;
440                         /* initialize PRI2TC mappings to invalid value */
441                         for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++)
442                                 my_ets->prio_tc[i] = IEEE_8021QAZ_MAX_TCS;
443                         bp->ieee_ets = my_ets;
444                 }
445                 rc = bnxt_setup_mq_tc(dev, max_tc);
446                 if (rc)
447                         return rc;
448                 rc = bnxt_hwrm_queue_cos2bw_cfg(bp, ets, max_tc);
449                 if (rc)
450                         return rc;
451                 rc = bnxt_hwrm_queue_pri2cos_cfg(bp, ets);
452                 if (rc)
453                         return rc;
454                 memcpy(my_ets, ets, sizeof(*my_ets));
455         }
456         return rc;
457 }
458
459 static int bnxt_dcbnl_ieee_getpfc(struct net_device *dev, struct ieee_pfc *pfc)
460 {
461         struct bnxt *bp = netdev_priv(dev);
462         __le64 *stats = (__le64 *)bp->hw_rx_port_stats;
463         struct ieee_pfc *my_pfc = bp->ieee_pfc;
464         long rx_off, tx_off;
465         int i, rc;
466
467         pfc->pfc_cap = bp->max_lltc;
468
469         if (!my_pfc) {
470                 if (bp->dcbx_cap & DCB_CAP_DCBX_HOST)
471                         return 0;
472
473                 my_pfc = kzalloc(sizeof(*my_pfc), GFP_KERNEL);
474                 if (!my_pfc)
475                         return 0;
476                 bp->ieee_pfc = my_pfc;
477                 rc = bnxt_hwrm_queue_pfc_qcfg(bp, my_pfc);
478                 if (rc)
479                         return 0;
480         }
481
482         pfc->pfc_en = my_pfc->pfc_en;
483         pfc->mbc = my_pfc->mbc;
484         pfc->delay = my_pfc->delay;
485
486         if (!stats)
487                 return 0;
488
489         rx_off = BNXT_RX_STATS_OFFSET(rx_pfc_ena_frames_pri0);
490         tx_off = BNXT_TX_STATS_OFFSET(tx_pfc_ena_frames_pri0);
491         for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++, rx_off++, tx_off++) {
492                 pfc->requests[i] = le64_to_cpu(*(stats + tx_off));
493                 pfc->indications[i] = le64_to_cpu(*(stats + rx_off));
494         }
495
496         return 0;
497 }
498
499 static int bnxt_dcbnl_ieee_setpfc(struct net_device *dev, struct ieee_pfc *pfc)
500 {
501         struct bnxt *bp = netdev_priv(dev);
502         struct ieee_pfc *my_pfc = bp->ieee_pfc;
503         int rc;
504
505         if (!(bp->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) ||
506             !(bp->dcbx_cap & DCB_CAP_DCBX_HOST))
507                 return -EINVAL;
508
509         if (!my_pfc) {
510                 my_pfc = kzalloc(sizeof(*my_pfc), GFP_KERNEL);
511                 if (!my_pfc)
512                         return -ENOMEM;
513                 bp->ieee_pfc = my_pfc;
514         }
515         rc = bnxt_hwrm_queue_pfc_cfg(bp, pfc);
516         if (!rc)
517                 memcpy(my_pfc, pfc, sizeof(*my_pfc));
518
519         return rc;
520 }
521
522 static int bnxt_dcbnl_ieee_setapp(struct net_device *dev, struct dcb_app *app)
523 {
524         struct bnxt *bp = netdev_priv(dev);
525         int rc = -EINVAL;
526
527         if (!(bp->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) ||
528             !(bp->dcbx_cap & DCB_CAP_DCBX_HOST))
529                 return -EINVAL;
530
531         rc = dcb_ieee_setapp(dev, app);
532         if (rc)
533                 return rc;
534
535         if ((app->selector == IEEE_8021QAZ_APP_SEL_ETHERTYPE &&
536              app->protocol == ETH_P_IBOE) ||
537             (app->selector == IEEE_8021QAZ_APP_SEL_DGRAM &&
538              app->protocol == ROCE_V2_UDP_DPORT))
539                 rc = bnxt_hwrm_set_dcbx_app(bp, app, true);
540
541         return rc;
542 }
543
544 static int bnxt_dcbnl_ieee_delapp(struct net_device *dev, struct dcb_app *app)
545 {
546         struct bnxt *bp = netdev_priv(dev);
547         int rc;
548
549         if (!(bp->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) ||
550             !(bp->dcbx_cap & DCB_CAP_DCBX_HOST))
551                 return -EINVAL;
552
553         rc = dcb_ieee_delapp(dev, app);
554         if (rc)
555                 return rc;
556         if ((app->selector == IEEE_8021QAZ_APP_SEL_ETHERTYPE &&
557              app->protocol == ETH_P_IBOE) ||
558             (app->selector == IEEE_8021QAZ_APP_SEL_DGRAM &&
559              app->protocol == ROCE_V2_UDP_DPORT))
560                 rc = bnxt_hwrm_set_dcbx_app(bp, app, false);
561
562         return rc;
563 }
564
565 static u8 bnxt_dcbnl_getdcbx(struct net_device *dev)
566 {
567         struct bnxt *bp = netdev_priv(dev);
568
569         return bp->dcbx_cap;
570 }
571
572 static u8 bnxt_dcbnl_setdcbx(struct net_device *dev, u8 mode)
573 {
574         struct bnxt *bp = netdev_priv(dev);
575
576         /* All firmware DCBX settings are set in NVRAM */
577         if (bp->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED)
578                 return 1;
579
580         if (mode & DCB_CAP_DCBX_HOST) {
581                 if (BNXT_VF(bp) || (bp->flags & BNXT_FLAG_FW_LLDP_AGENT))
582                         return 1;
583
584                 /* only support IEEE */
585                 if ((mode & DCB_CAP_DCBX_VER_CEE) ||
586                     !(mode & DCB_CAP_DCBX_VER_IEEE))
587                         return 1;
588         }
589
590         if (mode == bp->dcbx_cap)
591                 return 0;
592
593         bp->dcbx_cap = mode;
594         return 0;
595 }
596
597 static const struct dcbnl_rtnl_ops dcbnl_ops = {
598         .ieee_getets    = bnxt_dcbnl_ieee_getets,
599         .ieee_setets    = bnxt_dcbnl_ieee_setets,
600         .ieee_getpfc    = bnxt_dcbnl_ieee_getpfc,
601         .ieee_setpfc    = bnxt_dcbnl_ieee_setpfc,
602         .ieee_setapp    = bnxt_dcbnl_ieee_setapp,
603         .ieee_delapp    = bnxt_dcbnl_ieee_delapp,
604         .getdcbx        = bnxt_dcbnl_getdcbx,
605         .setdcbx        = bnxt_dcbnl_setdcbx,
606 };
607
608 void bnxt_dcb_init(struct bnxt *bp)
609 {
610         if (bp->hwrm_spec_code < 0x10501)
611                 return;
612
613         bp->dcbx_cap = DCB_CAP_DCBX_VER_IEEE;
614         if (BNXT_PF(bp) && !(bp->flags & BNXT_FLAG_FW_LLDP_AGENT))
615                 bp->dcbx_cap |= DCB_CAP_DCBX_HOST;
616         else if (bp->flags & BNXT_FLAG_FW_DCBX_AGENT)
617                 bp->dcbx_cap |= DCB_CAP_DCBX_LLD_MANAGED;
618         bp->dev->dcbnl_ops = &dcbnl_ops;
619 }
620
621 void bnxt_dcb_free(struct bnxt *bp)
622 {
623         kfree(bp->ieee_pfc);
624         kfree(bp->ieee_ets);
625         bp->ieee_pfc = NULL;
626         bp->ieee_ets = NULL;
627 }
628
629 #else
630
631 void bnxt_dcb_init(struct bnxt *bp)
632 {
633 }
634
635 void bnxt_dcb_free(struct bnxt *bp)
636 {
637 }
638
639 #endif