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