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