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 611