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 bool zero = false; 437 u8 max_tc = 0; 438 int i; 439 440 for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { 441 if (ets->prio_tc[i] > bp->max_tc) { 442 netdev_err(bp->dev, "priority to TC mapping exceeds TC count %d\n", 443 ets->prio_tc[i]); 444 return -EINVAL; 445 } 446 if (ets->prio_tc[i] > max_tc) 447 max_tc = ets->prio_tc[i]; 448 449 if ((ets->tc_tx_bw[i] || ets->tc_tsa[i]) && i > bp->max_tc) 450 return -EINVAL; 451 452 switch (ets->tc_tsa[i]) { 453 case IEEE_8021QAZ_TSA_STRICT: 454 break; 455 case IEEE_8021QAZ_TSA_ETS: 456 total_ets_bw += ets->tc_tx_bw[i]; 457 zero = zero || !ets->tc_tx_bw[i]; 458 break; 459 default: 460 return -ENOTSUPP; 461 } 462 } 463 if (total_ets_bw > 100) { 464 netdev_warn(bp->dev, "rejecting ETS config exceeding available bandwidth\n"); 465 return -EINVAL; 466 } 467 if (zero && total_ets_bw == 100) { 468 netdev_warn(bp->dev, "rejecting ETS config starving a TC\n"); 469 return -EINVAL; 470 } 471 472 if (max_tc >= bp->max_tc) 473 *tc = bp->max_tc; 474 else 475 *tc = max_tc + 1; 476 return 0; 477 } 478 479 static int bnxt_dcbnl_ieee_getets(struct net_device *dev, struct ieee_ets *ets) 480 { 481 struct bnxt *bp = netdev_priv(dev); 482 struct ieee_ets *my_ets = bp->ieee_ets; 483 int rc; 484 485 ets->ets_cap = bp->max_tc; 486 487 if (!my_ets) { 488 if (bp->dcbx_cap & DCB_CAP_DCBX_HOST) 489 return 0; 490 491 my_ets = kzalloc(sizeof(*my_ets), GFP_KERNEL); 492 if (!my_ets) 493 return -ENOMEM; 494 rc = bnxt_hwrm_queue_cos2bw_qcfg(bp, my_ets); 495 if (rc) 496 goto error; 497 rc = bnxt_hwrm_queue_pri2cos_qcfg(bp, my_ets); 498 if (rc) 499 goto error; 500 501 /* cache result */ 502 bp->ieee_ets = my_ets; 503 } 504 505 ets->cbs = my_ets->cbs; 506 memcpy(ets->tc_tx_bw, my_ets->tc_tx_bw, sizeof(ets->tc_tx_bw)); 507 memcpy(ets->tc_rx_bw, my_ets->tc_rx_bw, sizeof(ets->tc_rx_bw)); 508 memcpy(ets->tc_tsa, my_ets->tc_tsa, sizeof(ets->tc_tsa)); 509 memcpy(ets->prio_tc, my_ets->prio_tc, sizeof(ets->prio_tc)); 510 return 0; 511 error: 512 kfree(my_ets); 513 return rc; 514 } 515 516 static int bnxt_dcbnl_ieee_setets(struct net_device *dev, struct ieee_ets *ets) 517 { 518 struct bnxt *bp = netdev_priv(dev); 519 struct ieee_ets *my_ets = bp->ieee_ets; 520 u8 max_tc = 0; 521 int rc, i; 522 523 if (!(bp->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) || 524 !(bp->dcbx_cap & DCB_CAP_DCBX_HOST)) 525 return -EINVAL; 526 527 rc = bnxt_ets_validate(bp, ets, &max_tc); 528 if (!rc) { 529 if (!my_ets) { 530 my_ets = kzalloc(sizeof(*my_ets), GFP_KERNEL); 531 if (!my_ets) 532 return -ENOMEM; 533 /* initialize PRI2TC mappings to invalid value */ 534 for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) 535 my_ets->prio_tc[i] = IEEE_8021QAZ_MAX_TCS; 536 bp->ieee_ets = my_ets; 537 } 538 rc = bnxt_setup_mq_tc(dev, max_tc); 539 if (rc) 540 return rc; 541 rc = bnxt_hwrm_queue_cos2bw_cfg(bp, ets, max_tc); 542 if (rc) 543 return rc; 544 rc = bnxt_hwrm_queue_pri2cos_cfg(bp, ets); 545 if (rc) 546 return rc; 547 memcpy(my_ets, ets, sizeof(*my_ets)); 548 } 549 return rc; 550 } 551 552 static int bnxt_dcbnl_ieee_getpfc(struct net_device *dev, struct ieee_pfc *pfc) 553 { 554 struct bnxt *bp = netdev_priv(dev); 555 __le64 *stats = bp->port_stats.hw_stats; 556 struct ieee_pfc *my_pfc = bp->ieee_pfc; 557 long rx_off, tx_off; 558 int i, rc; 559 560 pfc->pfc_cap = bp->max_lltc; 561 562 if (!my_pfc) { 563 if (bp->dcbx_cap & DCB_CAP_DCBX_HOST) 564 return 0; 565 566 my_pfc = kzalloc(sizeof(*my_pfc), GFP_KERNEL); 567 if (!my_pfc) 568 return 0; 569 bp->ieee_pfc = my_pfc; 570 rc = bnxt_hwrm_queue_pfc_qcfg(bp, my_pfc); 571 if (rc) 572 return 0; 573 } 574 575 pfc->pfc_en = my_pfc->pfc_en; 576 pfc->mbc = my_pfc->mbc; 577 pfc->delay = my_pfc->delay; 578 579 if (!stats) 580 return 0; 581 582 rx_off = BNXT_RX_STATS_OFFSET(rx_pfc_ena_frames_pri0); 583 tx_off = BNXT_TX_STATS_OFFSET(tx_pfc_ena_frames_pri0); 584 for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++, rx_off++, tx_off++) { 585 pfc->requests[i] = le64_to_cpu(*(stats + tx_off)); 586 pfc->indications[i] = le64_to_cpu(*(stats + rx_off)); 587 } 588 589 return 0; 590 } 591 592 static int bnxt_dcbnl_ieee_setpfc(struct net_device *dev, struct ieee_pfc *pfc) 593 { 594 struct bnxt *bp = netdev_priv(dev); 595 struct ieee_pfc *my_pfc = bp->ieee_pfc; 596 int rc; 597 598 if (!(bp->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) || 599 !(bp->dcbx_cap & DCB_CAP_DCBX_HOST)) 600 return -EINVAL; 601 602 if (!my_pfc) { 603 my_pfc = kzalloc(sizeof(*my_pfc), GFP_KERNEL); 604 if (!my_pfc) 605 return -ENOMEM; 606 bp->ieee_pfc = my_pfc; 607 } 608 rc = bnxt_hwrm_queue_pfc_cfg(bp, pfc); 609 if (!rc) 610 memcpy(my_pfc, pfc, sizeof(*my_pfc)); 611 612 return rc; 613 } 614 615 static int bnxt_dcbnl_ieee_dscp_app_prep(struct bnxt *bp, struct dcb_app *app) 616 { 617 if (app->selector == IEEE_8021QAZ_APP_SEL_DSCP) { 618 if (!bp->max_dscp_value) 619 return -ENOTSUPP; 620 if (app->protocol > bp->max_dscp_value) 621 return -EINVAL; 622 } 623 return 0; 624 } 625 626 static int bnxt_dcbnl_ieee_setapp(struct net_device *dev, struct dcb_app *app) 627 { 628 struct bnxt *bp = netdev_priv(dev); 629 int rc; 630 631 if (!(bp->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) || 632 !(bp->dcbx_cap & DCB_CAP_DCBX_HOST)) 633 return -EINVAL; 634 635 rc = bnxt_dcbnl_ieee_dscp_app_prep(bp, app); 636 if (rc) 637 return rc; 638 639 rc = dcb_ieee_setapp(dev, app); 640 if (rc) 641 return rc; 642 643 if ((app->selector == IEEE_8021QAZ_APP_SEL_ETHERTYPE && 644 app->protocol == ETH_P_IBOE) || 645 (app->selector == IEEE_8021QAZ_APP_SEL_DGRAM && 646 app->protocol == ROCE_V2_UDP_DPORT)) 647 rc = bnxt_hwrm_set_dcbx_app(bp, app, true); 648 649 if (app->selector == IEEE_8021QAZ_APP_SEL_DSCP) 650 rc = bnxt_hwrm_queue_dscp2pri_cfg(bp, app, true); 651 652 return rc; 653 } 654 655 static int bnxt_dcbnl_ieee_delapp(struct net_device *dev, struct dcb_app *app) 656 { 657 struct bnxt *bp = netdev_priv(dev); 658 int rc; 659 660 if (!(bp->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) || 661 !(bp->dcbx_cap & DCB_CAP_DCBX_HOST)) 662 return -EINVAL; 663 664 rc = bnxt_dcbnl_ieee_dscp_app_prep(bp, app); 665 if (rc) 666 return rc; 667 668 rc = dcb_ieee_delapp(dev, app); 669 if (rc) 670 return rc; 671 if ((app->selector == IEEE_8021QAZ_APP_SEL_ETHERTYPE && 672 app->protocol == ETH_P_IBOE) || 673 (app->selector == IEEE_8021QAZ_APP_SEL_DGRAM && 674 app->protocol == ROCE_V2_UDP_DPORT)) 675 rc = bnxt_hwrm_set_dcbx_app(bp, app, false); 676 677 if (app->selector == IEEE_8021QAZ_APP_SEL_DSCP) 678 rc = bnxt_hwrm_queue_dscp2pri_cfg(bp, app, false); 679 680 return rc; 681 } 682 683 static u8 bnxt_dcbnl_getdcbx(struct net_device *dev) 684 { 685 struct bnxt *bp = netdev_priv(dev); 686 687 return bp->dcbx_cap; 688 } 689 690 static u8 bnxt_dcbnl_setdcbx(struct net_device *dev, u8 mode) 691 { 692 struct bnxt *bp = netdev_priv(dev); 693 694 /* All firmware DCBX settings are set in NVRAM */ 695 if (bp->dcbx_cap & DCB_CAP_DCBX_LLD_MANAGED) 696 return 1; 697 698 if (mode & DCB_CAP_DCBX_HOST) { 699 if (BNXT_VF(bp) || (bp->fw_cap & BNXT_FW_CAP_LLDP_AGENT)) 700 return 1; 701 702 /* only support IEEE */ 703 if ((mode & DCB_CAP_DCBX_VER_CEE) || 704 !(mode & DCB_CAP_DCBX_VER_IEEE)) 705 return 1; 706 } 707 708 if (mode == bp->dcbx_cap) 709 return 0; 710 711 bp->dcbx_cap = mode; 712 return 0; 713 } 714 715 static const struct dcbnl_rtnl_ops dcbnl_ops = { 716 .ieee_getets = bnxt_dcbnl_ieee_getets, 717 .ieee_setets = bnxt_dcbnl_ieee_setets, 718 .ieee_getpfc = bnxt_dcbnl_ieee_getpfc, 719 .ieee_setpfc = bnxt_dcbnl_ieee_setpfc, 720 .ieee_setapp = bnxt_dcbnl_ieee_setapp, 721 .ieee_delapp = bnxt_dcbnl_ieee_delapp, 722 .getdcbx = bnxt_dcbnl_getdcbx, 723 .setdcbx = bnxt_dcbnl_setdcbx, 724 }; 725 726 void bnxt_dcb_init(struct bnxt *bp) 727 { 728 bp->dcbx_cap = 0; 729 if (bp->hwrm_spec_code < 0x10501) 730 return; 731 732 bnxt_hwrm_queue_dscp_qcaps(bp); 733 bp->dcbx_cap = DCB_CAP_DCBX_VER_IEEE; 734 if (BNXT_PF(bp) && !(bp->fw_cap & BNXT_FW_CAP_LLDP_AGENT)) 735 bp->dcbx_cap |= DCB_CAP_DCBX_HOST; 736 else if (bp->fw_cap & BNXT_FW_CAP_DCBX_AGENT) 737 bp->dcbx_cap |= DCB_CAP_DCBX_LLD_MANAGED; 738 bp->dev->dcbnl_ops = &dcbnl_ops; 739 } 740 741 void bnxt_dcb_free(struct bnxt *bp) 742 { 743 kfree(bp->ieee_pfc); 744 kfree(bp->ieee_ets); 745 bp->ieee_pfc = NULL; 746 bp->ieee_ets = NULL; 747 } 748 749 #else 750 751 void bnxt_dcb_init(struct bnxt *bp) 752 { 753 } 754 755 void bnxt_dcb_free(struct bnxt *bp) 756 { 757 } 758 759 #endif 760