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_queue_to_tc(struct bnxt *bp, u8 queue_id) 25 { 26 int i, j; 27 28 for (i = 0; i < bp->max_tc; i++) { 29 if (bp->q_info[i].queue_id == queue_id) { 30 for (j = 0; j < bp->max_tc; j++) { 31 if (bp->tc_to_qidx[j] == i) 32 return j; 33 } 34 } 35 } 36 return -EINVAL; 37 } 38 39 static int bnxt_hwrm_queue_pri2cos_cfg(struct bnxt *bp, struct ieee_ets *ets) 40 { 41 struct hwrm_queue_pri2cos_cfg_input req = {0}; 42 u8 *pri2cos; 43 int i; 44 45 bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_PRI2COS_CFG, -1, -1); 46 req.flags = cpu_to_le32(QUEUE_PRI2COS_CFG_REQ_FLAGS_PATH_BIDIR | 47 QUEUE_PRI2COS_CFG_REQ_FLAGS_IVLAN); 48 49 pri2cos = &req.pri0_cos_queue_id; 50 for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { 51 u8 qidx; 52 53 req.enables |= cpu_to_le32( 54 QUEUE_PRI2COS_CFG_REQ_ENABLES_PRI0_COS_QUEUE_ID << i); 55 56 qidx = bp->tc_to_qidx[ets->prio_tc[i]]; 57 pri2cos[i] = bp->q_info[qidx].queue_id; 58 } 59 return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); 60 } 61 62 static int bnxt_hwrm_queue_pri2cos_qcfg(struct bnxt *bp, struct ieee_ets *ets) 63 { 64 struct hwrm_queue_pri2cos_qcfg_output *resp = bp->hwrm_cmd_resp_addr; 65 struct hwrm_queue_pri2cos_qcfg_input req = {0}; 66 int rc = 0; 67 68 bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_PRI2COS_QCFG, -1, -1); 69 req.flags = cpu_to_le32(QUEUE_PRI2COS_QCFG_REQ_FLAGS_IVLAN); 70 71 mutex_lock(&bp->hwrm_cmd_lock); 72 rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); 73 if (!rc) { 74 u8 *pri2cos = &resp->pri0_cos_queue_id; 75 int i; 76 77 for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { 78 u8 queue_id = pri2cos[i]; 79 int tc; 80 81 tc = bnxt_queue_to_tc(bp, queue_id); 82 if (tc >= 0) 83 ets->prio_tc[i] = tc; 84 } 85 } 86 mutex_unlock(&bp->hwrm_cmd_lock); 87 return rc; 88 } 89 90 static int bnxt_hwrm_queue_cos2bw_cfg(struct bnxt *bp, struct ieee_ets *ets, 91 u8 max_tc) 92 { 93 struct hwrm_queue_cos2bw_cfg_input req = {0}; 94 struct bnxt_cos2bw_cfg cos2bw; 95 void *data; 96 int i; 97 98 bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_COS2BW_CFG, -1, -1); 99 for (i = 0; i < max_tc; i++) { 100 u8 qidx = bp->tc_to_qidx[i]; 101 102 req.enables |= cpu_to_le32( 103 QUEUE_COS2BW_CFG_REQ_ENABLES_COS_QUEUE_ID0_VALID << 104 qidx); 105 106 memset(&cos2bw, 0, sizeof(cos2bw)); 107 cos2bw.queue_id = bp->q_info[qidx].queue_id; 108 if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_STRICT) { 109 cos2bw.tsa = 110 QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_TSA_ASSIGN_SP; 111 cos2bw.pri_lvl = i; 112 } else { 113 cos2bw.tsa = 114 QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_TSA_ASSIGN_ETS; 115 cos2bw.bw_weight = ets->tc_tx_bw[i]; 116 /* older firmware requires min_bw to be set to the 117 * same weight value in percent. 118 */ 119 cos2bw.min_bw = 120 cpu_to_le32((ets->tc_tx_bw[i] * 100) | 121 BW_VALUE_UNIT_PERCENT1_100); 122 } 123 data = &req.unused_0 + qidx * (sizeof(cos2bw) - 4); 124 memcpy(data, &cos2bw.queue_id, sizeof(cos2bw) - 4); 125 if (qidx == 0) { 126 req.queue_id0 = cos2bw.queue_id; 127 req.unused_0 = 0; 128 } 129 } 130 return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); 131 } 132 133 static int bnxt_hwrm_queue_cos2bw_qcfg(struct bnxt *bp, struct ieee_ets *ets) 134 { 135 struct hwrm_queue_cos2bw_qcfg_output *resp = bp->hwrm_cmd_resp_addr; 136 struct hwrm_queue_cos2bw_qcfg_input req = {0}; 137 struct bnxt_cos2bw_cfg cos2bw; 138 void *data; 139 int rc, i; 140 141 bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_COS2BW_QCFG, -1, -1); 142 143 mutex_lock(&bp->hwrm_cmd_lock); 144 rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); 145 if (rc) { 146 mutex_unlock(&bp->hwrm_cmd_lock); 147 return rc; 148 } 149 150 data = &resp->queue_id0 + offsetof(struct bnxt_cos2bw_cfg, queue_id); 151 for (i = 0; i < bp->max_tc; i++, data += sizeof(cos2bw) - 4) { 152 int tc; 153 154 memcpy(&cos2bw.queue_id, data, sizeof(cos2bw) - 4); 155 if (i == 0) 156 cos2bw.queue_id = resp->queue_id0; 157 158 tc = bnxt_queue_to_tc(bp, cos2bw.queue_id); 159 if (tc < 0) 160 continue; 161 162 if (cos2bw.tsa == 163 QUEUE_COS2BW_QCFG_RESP_QUEUE_ID0_TSA_ASSIGN_SP) { 164 ets->tc_tsa[tc] = IEEE_8021QAZ_TSA_STRICT; 165 } else { 166 ets->tc_tsa[tc] = IEEE_8021QAZ_TSA_ETS; 167 ets->tc_tx_bw[tc] = cos2bw.bw_weight; 168 } 169 } 170 mutex_unlock(&bp->hwrm_cmd_lock); 171 return 0; 172 } 173 174 static int bnxt_queue_remap(struct bnxt *bp, unsigned int lltc_mask) 175 { 176 unsigned long qmap = 0; 177 int max = bp->max_tc; 178 int i, j, rc; 179 180 /* Assign lossless TCs first */ 181 for (i = 0, j = 0; i < max; ) { 182 if (lltc_mask & (1 << i)) { 183 if (BNXT_LLQ(bp->q_info[j].queue_profile)) { 184 bp->tc_to_qidx[i] = j; 185 __set_bit(j, &qmap); 186 i++; 187 } 188 j++; 189 continue; 190 } 191 i++; 192 } 193 194 for (i = 0, j = 0; i < max; i++) { 195 if (lltc_mask & (1 << i)) 196 continue; 197 j = find_next_zero_bit(&qmap, max, j); 198 bp->tc_to_qidx[i] = j; 199 __set_bit(j, &qmap); 200 j++; 201 } 202 203 if (netif_running(bp->dev)) { 204 bnxt_close_nic(bp, false, false); 205 rc = bnxt_open_nic(bp, false, false); 206 if (rc) { 207 netdev_warn(bp->dev, "failed to open NIC, rc = %d\n", rc); 208 return rc; 209 } 210 } 211 if (bp->ieee_ets) { 212 int tc = netdev_get_num_tc(bp->dev); 213 214 if (!tc) 215 tc = 1; 216 rc = bnxt_hwrm_queue_cos2bw_cfg(bp, bp->ieee_ets, tc); 217 if (rc) { 218 netdev_warn(bp->dev, "failed to config BW, rc = %d\n", rc); 219 return rc; 220 } 221 rc = bnxt_hwrm_queue_pri2cos_cfg(bp, bp->ieee_ets); 222 if (rc) { 223 netdev_warn(bp->dev, "failed to config prio, rc = %d\n", rc); 224 return rc; 225 } 226 } 227 return 0; 228 } 229 230 static int bnxt_hwrm_queue_pfc_cfg(struct bnxt *bp, struct ieee_pfc *pfc) 231 { 232 struct hwrm_queue_pfcenable_cfg_input req = {0}; 233 struct ieee_ets *my_ets = bp->ieee_ets; 234 unsigned int tc_mask = 0, pri_mask = 0; 235 u8 i, pri, lltc_count = 0; 236 bool need_q_remap = false; 237 238 if (!my_ets) 239 return -EINVAL; 240 241 for (i = 0; i < bp->max_tc; i++) { 242 for (pri = 0; pri < IEEE_8021QAZ_MAX_TCS; pri++) { 243 if ((pfc->pfc_en & (1 << pri)) && 244 (my_ets->prio_tc[pri] == i)) { 245 pri_mask |= 1 << pri; 246 tc_mask |= 1 << i; 247 } 248 } 249 if (tc_mask & (1 << i)) 250 lltc_count++; 251 } 252 if (lltc_count > bp->max_lltc) 253 return -EINVAL; 254 255 for (i = 0; i < bp->max_tc; i++) { 256 if (tc_mask & (1 << i)) { 257 u8 qidx = bp->tc_to_qidx[i]; 258 259 if (!BNXT_LLQ(bp->q_info[qidx].queue_profile)) { 260 need_q_remap = true; 261 break; 262 } 263 } 264 } 265 266 if (need_q_remap) 267 bnxt_queue_remap(bp, tc_mask); 268 269 bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_PFCENABLE_CFG, -1, -1); 270 req.flags = cpu_to_le32(pri_mask); 271 return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); 272 } 273 274 static int bnxt_hwrm_queue_pfc_qcfg(struct bnxt *bp, struct ieee_pfc *pfc) 275 { 276 struct hwrm_queue_pfcenable_qcfg_output *resp = bp->hwrm_cmd_resp_addr; 277 struct hwrm_queue_pfcenable_qcfg_input req = {0}; 278 u8 pri_mask; 279 int rc; 280 281 bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_PFCENABLE_QCFG, -1, -1); 282 283 mutex_lock(&bp->hwrm_cmd_lock); 284 rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); 285 if (rc) { 286 mutex_unlock(&bp->hwrm_cmd_lock); 287 return rc; 288 } 289 290 pri_mask = le32_to_cpu(resp->flags); 291 pfc->pfc_en = pri_mask; 292 mutex_unlock(&bp->hwrm_cmd_lock); 293 return 0; 294 } 295 296 static int bnxt_hwrm_set_dcbx_app(struct bnxt *bp, struct dcb_app *app, 297 bool add) 298 { 299 struct hwrm_fw_set_structured_data_input set = {0}; 300 struct hwrm_fw_get_structured_data_input get = {0}; 301 struct hwrm_struct_data_dcbx_app *fw_app; 302 struct hwrm_struct_hdr *data; 303 dma_addr_t mapping; 304 size_t data_len; 305 int rc, n, i; 306 307 if (bp->hwrm_spec_code < 0x10601) 308 return 0; 309 310 n = IEEE_8021QAZ_MAX_TCS; 311 data_len = sizeof(*data) + sizeof(*fw_app) * n; 312 data = dma_alloc_coherent(&bp->pdev->dev, data_len, &mapping, 313 GFP_KERNEL); 314 if (!data) 315 return -ENOMEM; 316 317 bnxt_hwrm_cmd_hdr_init(bp, &get, HWRM_FW_GET_STRUCTURED_DATA, -1, -1); 318 get.dest_data_addr = cpu_to_le64(mapping); 319 get.structure_id = cpu_to_le16(STRUCT_HDR_STRUCT_ID_DCBX_APP); 320 get.subtype = cpu_to_le16(HWRM_STRUCT_DATA_SUBTYPE_HOST_OPERATIONAL); 321 get.count = 0; 322 rc = hwrm_send_message(bp, &get, sizeof(get), HWRM_CMD_TIMEOUT); 323 if (rc) 324 goto set_app_exit; 325 326 fw_app = (struct hwrm_struct_data_dcbx_app *)(data + 1); 327 328 if (data->struct_id != cpu_to_le16(STRUCT_HDR_STRUCT_ID_DCBX_APP)) { 329 rc = -ENODEV; 330 goto set_app_exit; 331 } 332 333 n = data->count; 334 for (i = 0; i < n; i++, fw_app++) { 335 if (fw_app->protocol_id == cpu_to_be16(app->protocol) && 336 fw_app->protocol_selector == app->selector && 337 fw_app->priority == app->priority) { 338 if (add) 339 goto set_app_exit; 340 else 341 break; 342 } 343 } 344 if (add) { 345 /* append */ 346 n++; 347 fw_app->protocol_id = cpu_to_be16(app->protocol); 348 fw_app->protocol_selector = app->selector; 349 fw_app->priority = app->priority; 350 fw_app->valid = 1; 351 } else { 352 size_t len = 0; 353 354 /* not found, nothing to delete */ 355 if (n == i) 356 goto set_app_exit; 357 358 len = (n - 1 - i) * sizeof(*fw_app); 359 if (len) 360 memmove(fw_app, fw_app + 1, len); 361 n--; 362 memset(fw_app + n, 0, sizeof(*fw_app)); 363 } 364 data->count = n; 365 data->len = cpu_to_le16(sizeof(*fw_app) * n); 366 data->subtype = cpu_to_le16(HWRM_STRUCT_DATA_SUBTYPE_HOST_OPERATIONAL); 367 368 bnxt_hwrm_cmd_hdr_init(bp, &set, HWRM_FW_SET_STRUCTURED_DATA, -1, -1); 369 set.src_data_addr = cpu_to_le64(mapping); 370 set.data_len = cpu_to_le16(sizeof(*data) + sizeof(*fw_app) * n); 371 set.hdr_cnt = 1; 372 rc = hwrm_send_message(bp, &set, sizeof(set), HWRM_CMD_TIMEOUT); 373 374 set_app_exit: 375 dma_free_coherent(&bp->pdev->dev, data_len, data, mapping); 376 return rc; 377 } 378 379 static int bnxt_hwrm_queue_dscp_qcaps(struct bnxt *bp) 380 { 381 struct hwrm_queue_dscp_qcaps_output *resp = bp->hwrm_cmd_resp_addr; 382 struct hwrm_queue_dscp_qcaps_input req = {0}; 383 int rc; 384 385 bp->max_dscp_value = 0; 386 if (bp->hwrm_spec_code < 0x10800 || BNXT_VF(bp)) 387 return 0; 388 389 bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_DSCP_QCAPS, -1, -1); 390 mutex_lock(&bp->hwrm_cmd_lock); 391 rc = _hwrm_send_message_silent(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); 392 if (!rc) { 393 bp->max_dscp_value = (1 << resp->num_dscp_bits) - 1; 394 if (bp->max_dscp_value < 0x3f) 395 bp->max_dscp_value = 0; 396 } 397 398 mutex_unlock(&bp->hwrm_cmd_lock); 399 return rc; 400 } 401 402 static int bnxt_hwrm_queue_dscp2pri_cfg(struct bnxt *bp, struct dcb_app *app, 403 bool add) 404 { 405 struct hwrm_queue_dscp2pri_cfg_input req = {0}; 406 struct bnxt_dscp2pri_entry *dscp2pri; 407 dma_addr_t mapping; 408 int rc; 409 410 if (bp->hwrm_spec_code < 0x10800) 411 return 0; 412 413 bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_DSCP2PRI_CFG, -1, -1); 414 dscp2pri = dma_alloc_coherent(&bp->pdev->dev, sizeof(*dscp2pri), 415 &mapping, GFP_KERNEL); 416 if (!dscp2pri) 417 return -ENOMEM; 418 419 req.src_data_addr = cpu_to_le64(mapping); 420 dscp2pri->dscp = app->protocol; 421 if (add) 422 dscp2pri->mask = 0x3f; 423 else 424 dscp2pri->mask = 0; 425 dscp2pri->pri = app->priority; 426 req.entry_cnt = cpu_to_le16(1); 427 rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); 428 dma_free_coherent(&bp->pdev->dev, sizeof(*dscp2pri), dscp2pri, 429 mapping); 430 return rc; 431 } 432 433 static int bnxt_ets_validate(struct bnxt *bp, struct ieee_ets *ets, u8 *tc) 434 { 435 int total_ets_bw = 0; 436 u8 max_tc = 0; 437 int i; 438 439 for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { 440 if (ets->prio_tc[i] > bp->max_tc) { 441 netdev_err(bp->dev, "priority to TC mapping exceeds TC count %d\n", 442 ets->prio_tc[i]); 443 return -EINVAL; 444 } 445 if (ets->prio_tc[i] > max_tc) 446 max_tc = ets->prio_tc[i]; 447 448 if ((ets->tc_tx_bw[i] || ets->tc_tsa[i]) && i > bp->max_tc) 449 return -EINVAL; 450 451 switch (ets->tc_tsa[i]) { 452 case IEEE_8021QAZ_TSA_STRICT: 453 break; 454 case IEEE_8021QAZ_TSA_ETS: 455 total_ets_bw += ets->tc_tx_bw[i]; 456 break; 457 default: 458 return -ENOTSUPP; 459 } 460 } 461 if (total_ets_bw > 100) 462 return -EINVAL; 463 464 if (max_tc >= bp->max_tc) 465 *tc = bp->max_tc; 466 else 467 *tc = max_tc + 1; 468 return 0; 469 } 470 471 static int bnxt_dcbnl_ieee_getets(struct net_device *dev, struct ieee_ets *ets) 472 { 473 struct bnxt *bp = netdev_priv(dev); 474 struct ieee_ets *my_ets = bp->ieee_ets; 475 int rc; 476 477 ets->ets_cap = bp->max_tc; 478 479 if (!my_ets) { 480 if (bp->dcbx_cap & DCB_CAP_DCBX_HOST) 481 return 0; 482 483 my_ets = kzalloc(sizeof(*my_ets), GFP_KERNEL); 484 if (!my_ets) 485 return -ENOMEM; 486 rc = bnxt_hwrm_queue_cos2bw_qcfg(bp, my_ets); 487 if (rc) 488 goto error; 489 rc = bnxt_hwrm_queue_pri2cos_qcfg(bp, my_ets); 490 if (rc) 491 goto error; 492 493 /* cache result */ 494 bp->ieee_ets = my_ets; 495 } 496 497 ets->cbs = my_ets->cbs; 498 memcpy(ets->tc_tx_bw, my_ets->tc_tx_bw, sizeof(ets->tc_tx_bw)); 499 memcpy(ets->tc_rx_bw, my_ets->tc_rx_bw, sizeof(ets->tc_rx_bw)); 500 memcpy(ets->tc_tsa, my_ets->tc_tsa, sizeof(ets->tc_tsa)); 501 memcpy(ets->prio_tc, my_ets->prio_tc, sizeof(ets->prio_tc)); 502 return 0; 503 error: 504 kfree(my_ets); 505 return rc; 506 } 507 508 static int bnxt_dcbnl_ieee_setets(struct net_device *dev, struct ieee_ets *ets) 509 { 510 struct bnxt *bp = netdev_priv(dev); 511 struct ieee_ets *my_ets = bp->ieee_ets; 512 u8 max_tc = 0; 513 int rc, i; 514 515 if (!(bp->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) || 516 !(bp->dcbx_cap & DCB_CAP_DCBX_HOST)) 517 return -EINVAL; 518 519 rc = bnxt_ets_validate(bp, ets, &max_tc); 520 if (!rc) { 521 if (!my_ets) { 522 my_ets = kzalloc(sizeof(*my_ets), GFP_KERNEL); 523 if (!my_ets) 524 return -ENOMEM; 525 /* initialize PRI2TC mappings to invalid value */ 526 for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) 527 my_ets->prio_tc[i] = IEEE_8021QAZ_MAX_TCS; 528 bp->ieee_ets = my_ets; 529 } 530 rc = bnxt_setup_mq_tc(dev, max_tc); 531 if (rc) 532 return rc; 533 rc = bnxt_hwrm_queue_cos2bw_cfg(bp, ets, max_tc); 534 if (rc) 535 return rc; 536 rc = bnxt_hwrm_queue_pri2cos_cfg(bp, ets); 537 if (rc) 538 return rc; 539 memcpy(my_ets, ets, sizeof(*my_ets)); 540 } 541 return rc; 542 } 543 544 static int bnxt_dcbnl_ieee_getpfc(struct net_device *dev, struct ieee_pfc *pfc) 545 { 546 struct bnxt *bp = netdev_priv(dev); 547 __le64 *stats = bp->port_stats.hw_stats; 548 struct ieee_pfc *my_pfc = bp->ieee_pfc; 549 long rx_off, tx_off; 550 int i, rc; 551 552 pfc->pfc_cap = bp->max_lltc; 553 554 if (!my_pfc) { 555 if (bp->dcbx_cap & DCB_CAP_DCBX_HOST) 556 return 0; 557 558 my_pfc = kzalloc(sizeof(*my_pfc), GFP_KERNEL); 559 if (!my_pfc) 560 return 0; 561 bp->ieee_pfc = my_pfc; 562 rc = bnxt_hwrm_queue_pfc_qcfg(bp, my_pfc); 563 if (rc) 564 return 0; 565 } 566 567 pfc->pfc_en = my_pfc->pfc_en; 568 pfc->mbc = my_pfc->mbc; 569 pfc->delay = my_pfc->delay; 570 571 if (!stats) 572 return 0; 573 574 rx_off = BNXT_RX_STATS_OFFSET(rx_pfc_ena_frames_pri0); 575 tx_off = BNXT_TX_STATS_OFFSET(tx_pfc_ena_frames_pri0); 576 for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++, rx_off++, tx_off++) { 577 pfc->requests[i] = le64_to_cpu(*(stats + tx_off)); 578 pfc->indications[i] = le64_to_cpu(*(stats + rx_off)); 579 } 580 581 return 0; 582 } 583 584 static int bnxt_dcbnl_ieee_setpfc(struct net_device *dev, struct ieee_pfc *pfc) 585 { 586 struct bnxt *bp = netdev_priv(dev); 587 struct ieee_pfc *my_pfc = bp->ieee_pfc; 588 int rc; 589 590 if (!(bp->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) || 591 !(bp->dcbx_cap & DCB_CAP_DCBX_HOST)) 592 return -EINVAL; 593 594 if (!my_pfc) { 595 my_pfc = kzalloc(sizeof(*my_pfc), GFP_KERNEL); 596 if (!my_pfc) 597 return -ENOMEM; 598 bp->ieee_pfc = my_pfc; 599 } 600 rc = bnxt_hwrm_queue_pfc_cfg(bp, pfc); 601 if (!rc) 602 memcpy(my_pfc, pfc, sizeof(*my_pfc)); 603 604 return rc; 605 } 606 607 static int bnxt_dcbnl_ieee_dscp_app_prep(struct bnxt *bp, struct dcb_app *app) 608 { 609 if (app->selector == IEEE_8021QAZ_APP_SEL_DSCP) { 610 if (!bp->max_dscp_value) 611 return -ENOTSUPP; 612 if (app->protocol > bp->max_dscp_value) 613 return -EINVAL; 614 } 615 return 0; 616 } 617 618 static int bnxt_dcbnl_ieee_setapp(struct net_device *dev, struct dcb_app *app) 619 { 620 struct bnxt *bp = netdev_priv(dev); 621 int rc; 622 623 if (!(bp->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) || 624 !(bp->dcbx_cap & DCB_CAP_DCBX_HOST)) 625 return -EINVAL; 626 627 rc = bnxt_dcbnl_ieee_dscp_app_prep(bp, app); 628 if (rc) 629 return rc; 630 631 rc = dcb_ieee_setapp(dev, app); 632 if (rc) 633 return rc; 634 635 if ((app->selector == IEEE_8021QAZ_APP_SEL_ETHERTYPE && 636 app->protocol == ETH_P_IBOE) || 637 (app->selector == IEEE_8021QAZ_APP_SEL_DGRAM && 638 app->protocol == ROCE_V2_UDP_DPORT)) 639 rc = bnxt_hwrm_set_dcbx_app(bp, app, true); 640 641 if (app->selector == IEEE_8021QAZ_APP_SEL_DSCP) 642 rc = bnxt_hwrm_queue_dscp2pri_cfg(bp, app, true); 643 644 return rc; 645 } 646 647 static int bnxt_dcbnl_ieee_delapp(struct net_device *dev, struct dcb_app *app) 648 { 649 struct bnxt *bp = netdev_priv(dev); 650 int rc; 651 652 if (!(bp->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) || 653 !(bp->dcbx_cap & DCB_CAP_DCBX_HOST)) 654 return -EINVAL; 655 656 rc = bnxt_dcbnl_ieee_dscp_app_prep(bp, app); 657 if (rc) 658 return rc; 659 660 rc = dcb_ieee_delapp(dev, app); 661 if (rc) 662 return rc; 663 if ((app->selector == IEEE_8021QAZ_APP_SEL_ETHERTYPE && 664 app->protocol == ETH_P_IBOE) || 665 (app->selector == IEEE_8021QAZ_APP_SEL_DGRAM && 666 app->protocol == ROCE_V2_UDP_DPORT)) 667 rc = bnxt_hwrm_set_dcbx_app(bp, app, false); 668 669 if (app->selector == IEEE_8021QAZ_APP_SEL_DSCP) 670 rc = bnxt_hwrm_queue_dscp2pri_cfg(bp, app, false); 671 672 return rc; 673 } 674 675 static u8 bnxt_dcbnl_getdcbx(struct net_device *dev) 676 { 677 struct bnxt *bp = netdev_priv(dev); 678 679 return bp->dcbx_cap; 680 } 681 682 static u8 bnxt_dcbnl_setdcbx(struct net_device *dev, u8 mode) 683 { 684 struct bnxt *bp = netdev_priv(dev); 685 686 /* All firmware DCBX settings are set in NVRAM */ 687 if (bp->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) 688 return 1; 689 690 if (mode & DCB_CAP_DCBX_HOST) { 691 if (BNXT_VF(bp) || (bp->fw_cap & BNXT_FW_CAP_LLDP_AGENT)) 692 return 1; 693 694 /* only support IEEE */ 695 if ((mode & DCB_CAP_DCBX_VER_CEE) || 696 !(mode & DCB_CAP_DCBX_VER_IEEE)) 697 return 1; 698 } 699 700 if (mode == bp->dcbx_cap) 701 return 0; 702 703 bp->dcbx_cap = mode; 704 return 0; 705 } 706 707 static const struct dcbnl_rtnl_ops dcbnl_ops = { 708 .ieee_getets = bnxt_dcbnl_ieee_getets, 709 .ieee_setets = bnxt_dcbnl_ieee_setets, 710 .ieee_getpfc = bnxt_dcbnl_ieee_getpfc, 711 .ieee_setpfc = bnxt_dcbnl_ieee_setpfc, 712 .ieee_setapp = bnxt_dcbnl_ieee_setapp, 713 .ieee_delapp = bnxt_dcbnl_ieee_delapp, 714 .getdcbx = bnxt_dcbnl_getdcbx, 715 .setdcbx = bnxt_dcbnl_setdcbx, 716 }; 717 718 void bnxt_dcb_init(struct bnxt *bp) 719 { 720 bp->dcbx_cap = 0; 721 if (bp->hwrm_spec_code < 0x10501) 722 return; 723 724 bnxt_hwrm_queue_dscp_qcaps(bp); 725 bp->dcbx_cap = DCB_CAP_DCBX_VER_IEEE; 726 if (BNXT_PF(bp) && !(bp->fw_cap & BNXT_FW_CAP_LLDP_AGENT)) 727 bp->dcbx_cap |= DCB_CAP_DCBX_HOST; 728 else if (bp->fw_cap & BNXT_FW_CAP_DCBX_AGENT) 729 bp->dcbx_cap |= DCB_CAP_DCBX_LLD_MANAGED; 730 bp->dev->dcbnl_ops = &dcbnl_ops; 731 } 732 733 void bnxt_dcb_free(struct bnxt *bp) 734 { 735 kfree(bp->ieee_pfc); 736 kfree(bp->ieee_ets); 737 bp->ieee_pfc = NULL; 738 bp->ieee_ets = NULL; 739 } 740 741 #else 742 743 void bnxt_dcb_init(struct bnxt *bp) 744 { 745 } 746 747 void bnxt_dcb_free(struct bnxt *bp) 748 { 749 } 750 751 #endif 752