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