1 /* Broadcom NetXtreme-C/E network driver. 2 * 3 * Copyright (c) 2017 Broadcom Limited 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation. 8 */ 9 10 #include <linux/pci.h> 11 #include <linux/netdevice.h> 12 #include <net/devlink.h> 13 #include "bnxt_hsi.h" 14 #include "bnxt.h" 15 #include "bnxt_hwrm.h" 16 #include "bnxt_vfr.h" 17 #include "bnxt_devlink.h" 18 #include "bnxt_ethtool.h" 19 20 static int 21 bnxt_dl_flash_update(struct devlink *dl, 22 struct devlink_flash_update_params *params, 23 struct netlink_ext_ack *extack) 24 { 25 struct bnxt *bp = bnxt_get_bp_from_dl(dl); 26 int rc; 27 28 if (!BNXT_PF(bp)) { 29 NL_SET_ERR_MSG_MOD(extack, 30 "flash update not supported from a VF"); 31 return -EPERM; 32 } 33 34 devlink_flash_update_status_notify(dl, "Preparing to flash", NULL, 0, 0); 35 rc = bnxt_flash_package_from_fw_obj(bp->dev, params->fw, 0); 36 if (!rc) 37 devlink_flash_update_status_notify(dl, "Flashing done", NULL, 0, 0); 38 else 39 devlink_flash_update_status_notify(dl, "Flashing failed", NULL, 0, 0); 40 return rc; 41 } 42 43 static int bnxt_fw_reporter_diagnose(struct devlink_health_reporter *reporter, 44 struct devlink_fmsg *fmsg, 45 struct netlink_ext_ack *extack) 46 { 47 struct bnxt *bp = devlink_health_reporter_priv(reporter); 48 u32 val; 49 int rc; 50 51 if (test_bit(BNXT_STATE_IN_FW_RESET, &bp->state)) 52 return 0; 53 54 val = bnxt_fw_health_readl(bp, BNXT_FW_HEALTH_REG); 55 56 if (BNXT_FW_IS_BOOTING(val)) { 57 rc = devlink_fmsg_string_pair_put(fmsg, "Description", 58 "Not yet completed initialization"); 59 if (rc) 60 return rc; 61 } else if (BNXT_FW_IS_ERR(val)) { 62 rc = devlink_fmsg_string_pair_put(fmsg, "Description", 63 "Encountered fatal error and cannot recover"); 64 if (rc) 65 return rc; 66 } 67 68 if (val >> 16) { 69 rc = devlink_fmsg_u32_pair_put(fmsg, "Error code", val >> 16); 70 if (rc) 71 return rc; 72 } 73 74 val = bnxt_fw_health_readl(bp, BNXT_FW_RESET_CNT_REG); 75 rc = devlink_fmsg_u32_pair_put(fmsg, "Reset count", val); 76 if (rc) 77 return rc; 78 79 return 0; 80 } 81 82 static const struct devlink_health_reporter_ops bnxt_dl_fw_reporter_ops = { 83 .name = "fw", 84 .diagnose = bnxt_fw_reporter_diagnose, 85 }; 86 87 static int bnxt_fw_reset_recover(struct devlink_health_reporter *reporter, 88 void *priv_ctx, 89 struct netlink_ext_ack *extack) 90 { 91 struct bnxt *bp = devlink_health_reporter_priv(reporter); 92 93 if (!priv_ctx) 94 return -EOPNOTSUPP; 95 96 bnxt_fw_reset(bp); 97 return -EINPROGRESS; 98 } 99 100 static const 101 struct devlink_health_reporter_ops bnxt_dl_fw_reset_reporter_ops = { 102 .name = "fw_reset", 103 .recover = bnxt_fw_reset_recover, 104 }; 105 106 static int bnxt_fw_fatal_recover(struct devlink_health_reporter *reporter, 107 void *priv_ctx, 108 struct netlink_ext_ack *extack) 109 { 110 struct bnxt *bp = devlink_health_reporter_priv(reporter); 111 struct bnxt_fw_reporter_ctx *fw_reporter_ctx = priv_ctx; 112 unsigned long event; 113 114 if (!priv_ctx) 115 return -EOPNOTSUPP; 116 117 bp->fw_health->fatal = true; 118 event = fw_reporter_ctx->sp_event; 119 if (event == BNXT_FW_RESET_NOTIFY_SP_EVENT) 120 bnxt_fw_reset(bp); 121 else if (event == BNXT_FW_EXCEPTION_SP_EVENT) 122 bnxt_fw_exception(bp); 123 124 return -EINPROGRESS; 125 } 126 127 static const 128 struct devlink_health_reporter_ops bnxt_dl_fw_fatal_reporter_ops = { 129 .name = "fw_fatal", 130 .recover = bnxt_fw_fatal_recover, 131 }; 132 133 void bnxt_dl_fw_reporters_create(struct bnxt *bp) 134 { 135 struct bnxt_fw_health *health = bp->fw_health; 136 137 if (!bp->dl || !health) 138 return; 139 140 if (!(bp->fw_cap & BNXT_FW_CAP_HOT_RESET) || health->fw_reset_reporter) 141 goto err_recovery; 142 143 health->fw_reset_reporter = 144 devlink_health_reporter_create(bp->dl, 145 &bnxt_dl_fw_reset_reporter_ops, 146 0, bp); 147 if (IS_ERR(health->fw_reset_reporter)) { 148 netdev_warn(bp->dev, "Failed to create FW fatal health reporter, rc = %ld\n", 149 PTR_ERR(health->fw_reset_reporter)); 150 health->fw_reset_reporter = NULL; 151 bp->fw_cap &= ~BNXT_FW_CAP_HOT_RESET; 152 } 153 154 err_recovery: 155 if (!(bp->fw_cap & BNXT_FW_CAP_ERROR_RECOVERY)) 156 return; 157 158 if (!health->fw_reporter) { 159 health->fw_reporter = 160 devlink_health_reporter_create(bp->dl, 161 &bnxt_dl_fw_reporter_ops, 162 0, bp); 163 if (IS_ERR(health->fw_reporter)) { 164 netdev_warn(bp->dev, "Failed to create FW health reporter, rc = %ld\n", 165 PTR_ERR(health->fw_reporter)); 166 health->fw_reporter = NULL; 167 bp->fw_cap &= ~BNXT_FW_CAP_ERROR_RECOVERY; 168 return; 169 } 170 } 171 172 if (health->fw_fatal_reporter) 173 return; 174 175 health->fw_fatal_reporter = 176 devlink_health_reporter_create(bp->dl, 177 &bnxt_dl_fw_fatal_reporter_ops, 178 0, bp); 179 if (IS_ERR(health->fw_fatal_reporter)) { 180 netdev_warn(bp->dev, "Failed to create FW fatal health reporter, rc = %ld\n", 181 PTR_ERR(health->fw_fatal_reporter)); 182 health->fw_fatal_reporter = NULL; 183 bp->fw_cap &= ~BNXT_FW_CAP_ERROR_RECOVERY; 184 } 185 } 186 187 void bnxt_dl_fw_reporters_destroy(struct bnxt *bp, bool all) 188 { 189 struct bnxt_fw_health *health = bp->fw_health; 190 191 if (!bp->dl || !health) 192 return; 193 194 if ((all || !(bp->fw_cap & BNXT_FW_CAP_HOT_RESET)) && 195 health->fw_reset_reporter) { 196 devlink_health_reporter_destroy(health->fw_reset_reporter); 197 health->fw_reset_reporter = NULL; 198 } 199 200 if ((bp->fw_cap & BNXT_FW_CAP_ERROR_RECOVERY) && !all) 201 return; 202 203 if (health->fw_reporter) { 204 devlink_health_reporter_destroy(health->fw_reporter); 205 health->fw_reporter = NULL; 206 } 207 208 if (health->fw_fatal_reporter) { 209 devlink_health_reporter_destroy(health->fw_fatal_reporter); 210 health->fw_fatal_reporter = NULL; 211 } 212 } 213 214 void bnxt_devlink_health_report(struct bnxt *bp, unsigned long event) 215 { 216 struct bnxt_fw_health *fw_health = bp->fw_health; 217 struct bnxt_fw_reporter_ctx fw_reporter_ctx; 218 219 fw_reporter_ctx.sp_event = event; 220 switch (event) { 221 case BNXT_FW_RESET_NOTIFY_SP_EVENT: 222 if (test_bit(BNXT_STATE_FW_FATAL_COND, &bp->state)) { 223 if (!fw_health->fw_fatal_reporter) 224 return; 225 226 devlink_health_report(fw_health->fw_fatal_reporter, 227 "FW fatal async event received", 228 &fw_reporter_ctx); 229 return; 230 } 231 if (!fw_health->fw_reset_reporter) 232 return; 233 234 devlink_health_report(fw_health->fw_reset_reporter, 235 "FW non-fatal reset event received", 236 &fw_reporter_ctx); 237 return; 238 239 case BNXT_FW_EXCEPTION_SP_EVENT: 240 if (!fw_health->fw_fatal_reporter) 241 return; 242 243 devlink_health_report(fw_health->fw_fatal_reporter, 244 "FW fatal error reported", 245 &fw_reporter_ctx); 246 return; 247 } 248 } 249 250 void bnxt_dl_health_status_update(struct bnxt *bp, bool healthy) 251 { 252 struct bnxt_fw_health *health = bp->fw_health; 253 u8 state; 254 255 if (healthy) 256 state = DEVLINK_HEALTH_REPORTER_STATE_HEALTHY; 257 else 258 state = DEVLINK_HEALTH_REPORTER_STATE_ERROR; 259 260 if (health->fatal) 261 devlink_health_reporter_state_update(health->fw_fatal_reporter, 262 state); 263 else 264 devlink_health_reporter_state_update(health->fw_reset_reporter, 265 state); 266 267 health->fatal = false; 268 } 269 270 void bnxt_dl_health_recovery_done(struct bnxt *bp) 271 { 272 struct bnxt_fw_health *hlth = bp->fw_health; 273 274 if (hlth->fatal) 275 devlink_health_reporter_recovery_done(hlth->fw_fatal_reporter); 276 else 277 devlink_health_reporter_recovery_done(hlth->fw_reset_reporter); 278 } 279 280 static int bnxt_dl_info_get(struct devlink *dl, struct devlink_info_req *req, 281 struct netlink_ext_ack *extack); 282 283 static const struct devlink_ops bnxt_dl_ops = { 284 #ifdef CONFIG_BNXT_SRIOV 285 .eswitch_mode_set = bnxt_dl_eswitch_mode_set, 286 .eswitch_mode_get = bnxt_dl_eswitch_mode_get, 287 #endif /* CONFIG_BNXT_SRIOV */ 288 .info_get = bnxt_dl_info_get, 289 .flash_update = bnxt_dl_flash_update, 290 }; 291 292 static const struct devlink_ops bnxt_vf_dl_ops; 293 294 enum bnxt_dl_param_id { 295 BNXT_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX, 296 BNXT_DEVLINK_PARAM_ID_GRE_VER_CHECK, 297 }; 298 299 static const struct bnxt_dl_nvm_param nvm_params[] = { 300 {DEVLINK_PARAM_GENERIC_ID_ENABLE_SRIOV, NVM_OFF_ENABLE_SRIOV, 301 BNXT_NVM_SHARED_CFG, 1, 1}, 302 {DEVLINK_PARAM_GENERIC_ID_IGNORE_ARI, NVM_OFF_IGNORE_ARI, 303 BNXT_NVM_SHARED_CFG, 1, 1}, 304 {DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MAX, 305 NVM_OFF_MSIX_VEC_PER_PF_MAX, BNXT_NVM_SHARED_CFG, 10, 4}, 306 {DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MIN, 307 NVM_OFF_MSIX_VEC_PER_PF_MIN, BNXT_NVM_SHARED_CFG, 7, 4}, 308 {BNXT_DEVLINK_PARAM_ID_GRE_VER_CHECK, NVM_OFF_DIS_GRE_VER_CHECK, 309 BNXT_NVM_SHARED_CFG, 1, 1}, 310 }; 311 312 union bnxt_nvm_data { 313 u8 val8; 314 __le32 val32; 315 }; 316 317 static void bnxt_copy_to_nvm_data(union bnxt_nvm_data *dst, 318 union devlink_param_value *src, 319 int nvm_num_bits, int dl_num_bytes) 320 { 321 u32 val32 = 0; 322 323 if (nvm_num_bits == 1) { 324 dst->val8 = src->vbool; 325 return; 326 } 327 if (dl_num_bytes == 4) 328 val32 = src->vu32; 329 else if (dl_num_bytes == 2) 330 val32 = (u32)src->vu16; 331 else if (dl_num_bytes == 1) 332 val32 = (u32)src->vu8; 333 dst->val32 = cpu_to_le32(val32); 334 } 335 336 static void bnxt_copy_from_nvm_data(union devlink_param_value *dst, 337 union bnxt_nvm_data *src, 338 int nvm_num_bits, int dl_num_bytes) 339 { 340 u32 val32; 341 342 if (nvm_num_bits == 1) { 343 dst->vbool = src->val8; 344 return; 345 } 346 val32 = le32_to_cpu(src->val32); 347 if (dl_num_bytes == 4) 348 dst->vu32 = val32; 349 else if (dl_num_bytes == 2) 350 dst->vu16 = (u16)val32; 351 else if (dl_num_bytes == 1) 352 dst->vu8 = (u8)val32; 353 } 354 355 static int bnxt_hwrm_get_nvm_cfg_ver(struct bnxt *bp, 356 union devlink_param_value *nvm_cfg_ver) 357 { 358 struct hwrm_nvm_get_variable_input *req; 359 union bnxt_nvm_data *data; 360 dma_addr_t data_dma_addr; 361 int rc; 362 363 rc = hwrm_req_init(bp, req, HWRM_NVM_GET_VARIABLE); 364 if (rc) 365 return rc; 366 367 data = hwrm_req_dma_slice(bp, req, sizeof(*data), &data_dma_addr); 368 if (!data) { 369 rc = -ENOMEM; 370 goto exit; 371 } 372 373 hwrm_req_hold(bp, req); 374 req->dest_data_addr = cpu_to_le64(data_dma_addr); 375 req->data_len = cpu_to_le16(BNXT_NVM_CFG_VER_BITS); 376 req->option_num = cpu_to_le16(NVM_OFF_NVM_CFG_VER); 377 378 rc = hwrm_req_send_silent(bp, req); 379 if (!rc) 380 bnxt_copy_from_nvm_data(nvm_cfg_ver, data, 381 BNXT_NVM_CFG_VER_BITS, 382 BNXT_NVM_CFG_VER_BYTES); 383 384 exit: 385 hwrm_req_drop(bp, req); 386 return rc; 387 } 388 389 static int bnxt_dl_info_put(struct bnxt *bp, struct devlink_info_req *req, 390 enum bnxt_dl_version_type type, const char *key, 391 char *buf) 392 { 393 if (!strlen(buf)) 394 return 0; 395 396 if ((bp->flags & BNXT_FLAG_CHIP_P5) && 397 (!strcmp(key, DEVLINK_INFO_VERSION_GENERIC_FW_NCSI) || 398 !strcmp(key, DEVLINK_INFO_VERSION_GENERIC_FW_ROCE))) 399 return 0; 400 401 switch (type) { 402 case BNXT_VERSION_FIXED: 403 return devlink_info_version_fixed_put(req, key, buf); 404 case BNXT_VERSION_RUNNING: 405 return devlink_info_version_running_put(req, key, buf); 406 case BNXT_VERSION_STORED: 407 return devlink_info_version_stored_put(req, key, buf); 408 } 409 return 0; 410 } 411 412 #define HWRM_FW_VER_STR_LEN 16 413 414 static int bnxt_dl_info_get(struct devlink *dl, struct devlink_info_req *req, 415 struct netlink_ext_ack *extack) 416 { 417 struct hwrm_nvm_get_dev_info_output nvm_dev_info; 418 struct bnxt *bp = bnxt_get_bp_from_dl(dl); 419 union devlink_param_value nvm_cfg_ver; 420 struct hwrm_ver_get_output *ver_resp; 421 char mgmt_ver[FW_VER_STR_LEN]; 422 char roce_ver[FW_VER_STR_LEN]; 423 char ncsi_ver[FW_VER_STR_LEN]; 424 char buf[32]; 425 int rc; 426 427 rc = devlink_info_driver_name_put(req, DRV_MODULE_NAME); 428 if (rc) 429 return rc; 430 431 if (BNXT_PF(bp) && (bp->flags & BNXT_FLAG_DSN_VALID)) { 432 sprintf(buf, "%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X", 433 bp->dsn[7], bp->dsn[6], bp->dsn[5], bp->dsn[4], 434 bp->dsn[3], bp->dsn[2], bp->dsn[1], bp->dsn[0]); 435 rc = devlink_info_serial_number_put(req, buf); 436 if (rc) 437 return rc; 438 } 439 440 if (strlen(bp->board_serialno)) { 441 rc = devlink_info_board_serial_number_put(req, bp->board_serialno); 442 if (rc) 443 return rc; 444 } 445 446 rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_FIXED, 447 DEVLINK_INFO_VERSION_GENERIC_BOARD_ID, 448 bp->board_partno); 449 if (rc) 450 return rc; 451 452 sprintf(buf, "%X", bp->chip_num); 453 rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_FIXED, 454 DEVLINK_INFO_VERSION_GENERIC_ASIC_ID, buf); 455 if (rc) 456 return rc; 457 458 ver_resp = &bp->ver_resp; 459 sprintf(buf, "%X", ver_resp->chip_rev); 460 rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_FIXED, 461 DEVLINK_INFO_VERSION_GENERIC_ASIC_REV, buf); 462 if (rc) 463 return rc; 464 465 rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_RUNNING, 466 DEVLINK_INFO_VERSION_GENERIC_FW_PSID, 467 bp->nvm_cfg_ver); 468 if (rc) 469 return rc; 470 471 buf[0] = 0; 472 strncat(buf, ver_resp->active_pkg_name, HWRM_FW_VER_STR_LEN); 473 rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_RUNNING, 474 DEVLINK_INFO_VERSION_GENERIC_FW, buf); 475 if (rc) 476 return rc; 477 478 if (BNXT_PF(bp) && !bnxt_hwrm_get_nvm_cfg_ver(bp, &nvm_cfg_ver)) { 479 u32 ver = nvm_cfg_ver.vu32; 480 481 sprintf(buf, "%d.%d.%d", (ver >> 16) & 0xf, (ver >> 8) & 0xf, 482 ver & 0xf); 483 rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_STORED, 484 DEVLINK_INFO_VERSION_GENERIC_FW_PSID, 485 buf); 486 if (rc) 487 return rc; 488 } 489 490 if (ver_resp->flags & VER_GET_RESP_FLAGS_EXT_VER_AVAIL) { 491 snprintf(mgmt_ver, FW_VER_STR_LEN, "%d.%d.%d.%d", 492 ver_resp->hwrm_fw_major, ver_resp->hwrm_fw_minor, 493 ver_resp->hwrm_fw_build, ver_resp->hwrm_fw_patch); 494 495 snprintf(ncsi_ver, FW_VER_STR_LEN, "%d.%d.%d.%d", 496 ver_resp->mgmt_fw_major, ver_resp->mgmt_fw_minor, 497 ver_resp->mgmt_fw_build, ver_resp->mgmt_fw_patch); 498 499 snprintf(roce_ver, FW_VER_STR_LEN, "%d.%d.%d.%d", 500 ver_resp->roce_fw_major, ver_resp->roce_fw_minor, 501 ver_resp->roce_fw_build, ver_resp->roce_fw_patch); 502 } else { 503 snprintf(mgmt_ver, FW_VER_STR_LEN, "%d.%d.%d.%d", 504 ver_resp->hwrm_fw_maj_8b, ver_resp->hwrm_fw_min_8b, 505 ver_resp->hwrm_fw_bld_8b, ver_resp->hwrm_fw_rsvd_8b); 506 507 snprintf(ncsi_ver, FW_VER_STR_LEN, "%d.%d.%d.%d", 508 ver_resp->mgmt_fw_maj_8b, ver_resp->mgmt_fw_min_8b, 509 ver_resp->mgmt_fw_bld_8b, ver_resp->mgmt_fw_rsvd_8b); 510 511 snprintf(roce_ver, FW_VER_STR_LEN, "%d.%d.%d.%d", 512 ver_resp->roce_fw_maj_8b, ver_resp->roce_fw_min_8b, 513 ver_resp->roce_fw_bld_8b, ver_resp->roce_fw_rsvd_8b); 514 } 515 rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_RUNNING, 516 DEVLINK_INFO_VERSION_GENERIC_FW_MGMT, mgmt_ver); 517 if (rc) 518 return rc; 519 520 rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_RUNNING, 521 DEVLINK_INFO_VERSION_GENERIC_FW_MGMT_API, 522 bp->hwrm_ver_supp); 523 if (rc) 524 return rc; 525 526 rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_RUNNING, 527 DEVLINK_INFO_VERSION_GENERIC_FW_NCSI, ncsi_ver); 528 if (rc) 529 return rc; 530 531 rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_RUNNING, 532 DEVLINK_INFO_VERSION_GENERIC_FW_ROCE, roce_ver); 533 if (rc) 534 return rc; 535 536 rc = bnxt_hwrm_nvm_get_dev_info(bp, &nvm_dev_info); 537 if (rc || 538 !(nvm_dev_info.flags & NVM_GET_DEV_INFO_RESP_FLAGS_FW_VER_VALID)) 539 return 0; 540 541 buf[0] = 0; 542 strncat(buf, nvm_dev_info.pkg_name, HWRM_FW_VER_STR_LEN); 543 rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_STORED, 544 DEVLINK_INFO_VERSION_GENERIC_FW, buf); 545 if (rc) 546 return rc; 547 548 snprintf(mgmt_ver, FW_VER_STR_LEN, "%d.%d.%d.%d", 549 nvm_dev_info.hwrm_fw_major, nvm_dev_info.hwrm_fw_minor, 550 nvm_dev_info.hwrm_fw_build, nvm_dev_info.hwrm_fw_patch); 551 rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_STORED, 552 DEVLINK_INFO_VERSION_GENERIC_FW_MGMT, mgmt_ver); 553 if (rc) 554 return rc; 555 556 snprintf(ncsi_ver, FW_VER_STR_LEN, "%d.%d.%d.%d", 557 nvm_dev_info.mgmt_fw_major, nvm_dev_info.mgmt_fw_minor, 558 nvm_dev_info.mgmt_fw_build, nvm_dev_info.mgmt_fw_patch); 559 rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_STORED, 560 DEVLINK_INFO_VERSION_GENERIC_FW_NCSI, ncsi_ver); 561 if (rc) 562 return rc; 563 564 snprintf(roce_ver, FW_VER_STR_LEN, "%d.%d.%d.%d", 565 nvm_dev_info.roce_fw_major, nvm_dev_info.roce_fw_minor, 566 nvm_dev_info.roce_fw_build, nvm_dev_info.roce_fw_patch); 567 return bnxt_dl_info_put(bp, req, BNXT_VERSION_STORED, 568 DEVLINK_INFO_VERSION_GENERIC_FW_ROCE, roce_ver); 569 } 570 571 static int bnxt_hwrm_nvm_req(struct bnxt *bp, u32 param_id, void *msg, 572 union devlink_param_value *val) 573 { 574 struct hwrm_nvm_get_variable_input *req = msg; 575 struct bnxt_dl_nvm_param nvm_param; 576 struct hwrm_err_output *resp; 577 union bnxt_nvm_data *data; 578 dma_addr_t data_dma_addr; 579 int idx = 0, rc, i; 580 581 /* Get/Set NVM CFG parameter is supported only on PFs */ 582 if (BNXT_VF(bp)) { 583 hwrm_req_drop(bp, req); 584 return -EPERM; 585 } 586 587 for (i = 0; i < ARRAY_SIZE(nvm_params); i++) { 588 if (nvm_params[i].id == param_id) { 589 nvm_param = nvm_params[i]; 590 break; 591 } 592 } 593 594 if (i == ARRAY_SIZE(nvm_params)) { 595 hwrm_req_drop(bp, req); 596 return -EOPNOTSUPP; 597 } 598 599 if (nvm_param.dir_type == BNXT_NVM_PORT_CFG) 600 idx = bp->pf.port_id; 601 else if (nvm_param.dir_type == BNXT_NVM_FUNC_CFG) 602 idx = bp->pf.fw_fid - BNXT_FIRST_PF_FID; 603 604 data = hwrm_req_dma_slice(bp, req, sizeof(*data), &data_dma_addr); 605 606 if (!data) { 607 hwrm_req_drop(bp, req); 608 return -ENOMEM; 609 } 610 611 req->dest_data_addr = cpu_to_le64(data_dma_addr); 612 req->data_len = cpu_to_le16(nvm_param.nvm_num_bits); 613 req->option_num = cpu_to_le16(nvm_param.offset); 614 req->index_0 = cpu_to_le16(idx); 615 if (idx) 616 req->dimensions = cpu_to_le16(1); 617 618 resp = hwrm_req_hold(bp, req); 619 if (req->req_type == cpu_to_le16(HWRM_NVM_SET_VARIABLE)) { 620 bnxt_copy_to_nvm_data(data, val, nvm_param.nvm_num_bits, 621 nvm_param.dl_num_bytes); 622 rc = hwrm_req_send(bp, msg); 623 } else { 624 rc = hwrm_req_send_silent(bp, msg); 625 if (!rc) { 626 bnxt_copy_from_nvm_data(val, data, 627 nvm_param.nvm_num_bits, 628 nvm_param.dl_num_bytes); 629 } else { 630 if (resp->cmd_err == 631 NVM_GET_VARIABLE_CMD_ERR_CODE_VAR_NOT_EXIST) 632 rc = -EOPNOTSUPP; 633 } 634 } 635 hwrm_req_drop(bp, req); 636 if (rc == -EACCES) 637 netdev_err(bp->dev, "PF does not have admin privileges to modify NVM config\n"); 638 return rc; 639 } 640 641 static int bnxt_dl_nvm_param_get(struct devlink *dl, u32 id, 642 struct devlink_param_gset_ctx *ctx) 643 { 644 struct bnxt *bp = bnxt_get_bp_from_dl(dl); 645 struct hwrm_nvm_get_variable_input *req; 646 int rc; 647 648 rc = hwrm_req_init(bp, req, HWRM_NVM_GET_VARIABLE); 649 if (rc) 650 return rc; 651 652 rc = bnxt_hwrm_nvm_req(bp, id, req, &ctx->val); 653 if (!rc && id == BNXT_DEVLINK_PARAM_ID_GRE_VER_CHECK) 654 ctx->val.vbool = !ctx->val.vbool; 655 656 return rc; 657 } 658 659 static int bnxt_dl_nvm_param_set(struct devlink *dl, u32 id, 660 struct devlink_param_gset_ctx *ctx) 661 { 662 struct bnxt *bp = bnxt_get_bp_from_dl(dl); 663 struct hwrm_nvm_set_variable_input *req; 664 int rc; 665 666 rc = hwrm_req_init(bp, req, HWRM_NVM_SET_VARIABLE); 667 if (rc) 668 return rc; 669 670 if (id == BNXT_DEVLINK_PARAM_ID_GRE_VER_CHECK) 671 ctx->val.vbool = !ctx->val.vbool; 672 673 return bnxt_hwrm_nvm_req(bp, id, req, &ctx->val); 674 } 675 676 static int bnxt_dl_msix_validate(struct devlink *dl, u32 id, 677 union devlink_param_value val, 678 struct netlink_ext_ack *extack) 679 { 680 int max_val = -1; 681 682 if (id == DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MAX) 683 max_val = BNXT_MSIX_VEC_MAX; 684 685 if (id == DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MIN) 686 max_val = BNXT_MSIX_VEC_MIN_MAX; 687 688 if (val.vu32 > max_val) { 689 NL_SET_ERR_MSG_MOD(extack, "MSIX value is exceeding the range"); 690 return -EINVAL; 691 } 692 693 return 0; 694 } 695 696 static const struct devlink_param bnxt_dl_params[] = { 697 DEVLINK_PARAM_GENERIC(ENABLE_SRIOV, 698 BIT(DEVLINK_PARAM_CMODE_PERMANENT), 699 bnxt_dl_nvm_param_get, bnxt_dl_nvm_param_set, 700 NULL), 701 DEVLINK_PARAM_GENERIC(IGNORE_ARI, 702 BIT(DEVLINK_PARAM_CMODE_PERMANENT), 703 bnxt_dl_nvm_param_get, bnxt_dl_nvm_param_set, 704 NULL), 705 DEVLINK_PARAM_GENERIC(MSIX_VEC_PER_PF_MAX, 706 BIT(DEVLINK_PARAM_CMODE_PERMANENT), 707 bnxt_dl_nvm_param_get, bnxt_dl_nvm_param_set, 708 bnxt_dl_msix_validate), 709 DEVLINK_PARAM_GENERIC(MSIX_VEC_PER_PF_MIN, 710 BIT(DEVLINK_PARAM_CMODE_PERMANENT), 711 bnxt_dl_nvm_param_get, bnxt_dl_nvm_param_set, 712 bnxt_dl_msix_validate), 713 DEVLINK_PARAM_DRIVER(BNXT_DEVLINK_PARAM_ID_GRE_VER_CHECK, 714 "gre_ver_check", DEVLINK_PARAM_TYPE_BOOL, 715 BIT(DEVLINK_PARAM_CMODE_PERMANENT), 716 bnxt_dl_nvm_param_get, bnxt_dl_nvm_param_set, 717 NULL), 718 }; 719 720 static const struct devlink_param bnxt_dl_port_params[] = { 721 }; 722 723 static int bnxt_dl_params_register(struct bnxt *bp) 724 { 725 int rc; 726 727 if (bp->hwrm_spec_code < 0x10600) 728 return 0; 729 730 rc = devlink_params_register(bp->dl, bnxt_dl_params, 731 ARRAY_SIZE(bnxt_dl_params)); 732 if (rc) { 733 netdev_warn(bp->dev, "devlink_params_register failed. rc=%d\n", 734 rc); 735 return rc; 736 } 737 rc = devlink_port_params_register(&bp->dl_port, bnxt_dl_port_params, 738 ARRAY_SIZE(bnxt_dl_port_params)); 739 if (rc) { 740 netdev_err(bp->dev, "devlink_port_params_register failed\n"); 741 devlink_params_unregister(bp->dl, bnxt_dl_params, 742 ARRAY_SIZE(bnxt_dl_params)); 743 return rc; 744 } 745 devlink_params_publish(bp->dl); 746 747 return 0; 748 } 749 750 static void bnxt_dl_params_unregister(struct bnxt *bp) 751 { 752 if (bp->hwrm_spec_code < 0x10600) 753 return; 754 755 devlink_params_unregister(bp->dl, bnxt_dl_params, 756 ARRAY_SIZE(bnxt_dl_params)); 757 devlink_port_params_unregister(&bp->dl_port, bnxt_dl_port_params, 758 ARRAY_SIZE(bnxt_dl_port_params)); 759 } 760 761 int bnxt_dl_register(struct bnxt *bp) 762 { 763 const struct devlink_ops *devlink_ops; 764 struct devlink_port_attrs attrs = {}; 765 struct devlink *dl; 766 int rc; 767 768 if (BNXT_PF(bp)) 769 devlink_ops = &bnxt_dl_ops; 770 else 771 devlink_ops = &bnxt_vf_dl_ops; 772 773 dl = devlink_alloc(devlink_ops, sizeof(struct bnxt_dl), &bp->pdev->dev); 774 if (!dl) { 775 netdev_warn(bp->dev, "devlink_alloc failed\n"); 776 return -ENOMEM; 777 } 778 779 bnxt_link_bp_to_dl(bp, dl); 780 781 /* Add switchdev eswitch mode setting, if SRIOV supported */ 782 if (pci_find_ext_capability(bp->pdev, PCI_EXT_CAP_ID_SRIOV) && 783 bp->hwrm_spec_code > 0x10803) 784 bp->eswitch_mode = DEVLINK_ESWITCH_MODE_LEGACY; 785 786 rc = devlink_register(dl); 787 if (rc) { 788 netdev_warn(bp->dev, "devlink_register failed. rc=%d\n", rc); 789 goto err_dl_free; 790 } 791 792 if (!BNXT_PF(bp)) 793 return 0; 794 795 attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL; 796 attrs.phys.port_number = bp->pf.port_id; 797 memcpy(attrs.switch_id.id, bp->dsn, sizeof(bp->dsn)); 798 attrs.switch_id.id_len = sizeof(bp->dsn); 799 devlink_port_attrs_set(&bp->dl_port, &attrs); 800 rc = devlink_port_register(dl, &bp->dl_port, bp->pf.port_id); 801 if (rc) { 802 netdev_err(bp->dev, "devlink_port_register failed\n"); 803 goto err_dl_unreg; 804 } 805 806 rc = bnxt_dl_params_register(bp); 807 if (rc) 808 goto err_dl_port_unreg; 809 810 return 0; 811 812 err_dl_port_unreg: 813 devlink_port_unregister(&bp->dl_port); 814 err_dl_unreg: 815 devlink_unregister(dl); 816 err_dl_free: 817 bnxt_link_bp_to_dl(bp, NULL); 818 devlink_free(dl); 819 return rc; 820 } 821 822 void bnxt_dl_unregister(struct bnxt *bp) 823 { 824 struct devlink *dl = bp->dl; 825 826 if (!dl) 827 return; 828 829 if (BNXT_PF(bp)) { 830 bnxt_dl_params_unregister(bp); 831 devlink_port_unregister(&bp->dl_port); 832 } 833 devlink_unregister(dl); 834 devlink_free(dl); 835 } 836