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, health_status; 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 health_status = val & 0xffff; 55 56 if (health_status < BNXT_FW_STATUS_HEALTHY) { 57 rc = devlink_fmsg_string_pair_put(fmsg, "Description", 58 "Not yet completed initialization"); 59 if (rc) 60 return rc; 61 } else if (health_status > BNXT_FW_STATUS_HEALTHY) { 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 = {0}; 359 union bnxt_nvm_data *data; 360 dma_addr_t data_dma_addr; 361 int rc; 362 363 bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_NVM_GET_VARIABLE, -1, -1); 364 data = dma_alloc_coherent(&bp->pdev->dev, sizeof(*data), 365 &data_dma_addr, GFP_KERNEL); 366 if (!data) 367 return -ENOMEM; 368 369 req.dest_data_addr = cpu_to_le64(data_dma_addr); 370 req.data_len = cpu_to_le16(BNXT_NVM_CFG_VER_BITS); 371 req.option_num = cpu_to_le16(NVM_OFF_NVM_CFG_VER); 372 373 rc = hwrm_send_message_silent(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); 374 if (!rc) 375 bnxt_copy_from_nvm_data(nvm_cfg_ver, data, 376 BNXT_NVM_CFG_VER_BITS, 377 BNXT_NVM_CFG_VER_BYTES); 378 379 dma_free_coherent(&bp->pdev->dev, sizeof(*data), data, data_dma_addr); 380 return rc; 381 } 382 383 static int bnxt_dl_info_put(struct bnxt *bp, struct devlink_info_req *req, 384 enum bnxt_dl_version_type type, const char *key, 385 char *buf) 386 { 387 if (!strlen(buf)) 388 return 0; 389 390 if ((bp->flags & BNXT_FLAG_CHIP_P5) && 391 (!strcmp(key, DEVLINK_INFO_VERSION_GENERIC_FW_NCSI) || 392 !strcmp(key, DEVLINK_INFO_VERSION_GENERIC_FW_ROCE))) 393 return 0; 394 395 switch (type) { 396 case BNXT_VERSION_FIXED: 397 return devlink_info_version_fixed_put(req, key, buf); 398 case BNXT_VERSION_RUNNING: 399 return devlink_info_version_running_put(req, key, buf); 400 case BNXT_VERSION_STORED: 401 return devlink_info_version_stored_put(req, key, buf); 402 } 403 return 0; 404 } 405 406 #define HWRM_FW_VER_STR_LEN 16 407 408 static int bnxt_dl_info_get(struct devlink *dl, struct devlink_info_req *req, 409 struct netlink_ext_ack *extack) 410 { 411 struct hwrm_nvm_get_dev_info_output nvm_dev_info; 412 struct bnxt *bp = bnxt_get_bp_from_dl(dl); 413 union devlink_param_value nvm_cfg_ver; 414 struct hwrm_ver_get_output *ver_resp; 415 char mgmt_ver[FW_VER_STR_LEN]; 416 char roce_ver[FW_VER_STR_LEN]; 417 char ncsi_ver[FW_VER_STR_LEN]; 418 char buf[32]; 419 int rc; 420 421 rc = devlink_info_driver_name_put(req, DRV_MODULE_NAME); 422 if (rc) 423 return rc; 424 425 if (BNXT_PF(bp) && (bp->flags & BNXT_FLAG_DSN_VALID)) { 426 sprintf(buf, "%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X", 427 bp->dsn[7], bp->dsn[6], bp->dsn[5], bp->dsn[4], 428 bp->dsn[3], bp->dsn[2], bp->dsn[1], bp->dsn[0]); 429 rc = devlink_info_serial_number_put(req, buf); 430 if (rc) 431 return rc; 432 } 433 434 if (strlen(bp->board_serialno)) { 435 rc = devlink_info_board_serial_number_put(req, bp->board_serialno); 436 if (rc) 437 return rc; 438 } 439 440 rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_FIXED, 441 DEVLINK_INFO_VERSION_GENERIC_BOARD_ID, 442 bp->board_partno); 443 if (rc) 444 return rc; 445 446 sprintf(buf, "%X", bp->chip_num); 447 rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_FIXED, 448 DEVLINK_INFO_VERSION_GENERIC_ASIC_ID, buf); 449 if (rc) 450 return rc; 451 452 ver_resp = &bp->ver_resp; 453 sprintf(buf, "%X", ver_resp->chip_rev); 454 rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_FIXED, 455 DEVLINK_INFO_VERSION_GENERIC_ASIC_REV, buf); 456 if (rc) 457 return rc; 458 459 rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_RUNNING, 460 DEVLINK_INFO_VERSION_GENERIC_FW_PSID, 461 bp->nvm_cfg_ver); 462 if (rc) 463 return rc; 464 465 buf[0] = 0; 466 strncat(buf, ver_resp->active_pkg_name, HWRM_FW_VER_STR_LEN); 467 rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_RUNNING, 468 DEVLINK_INFO_VERSION_GENERIC_FW, buf); 469 if (rc) 470 return rc; 471 472 if (BNXT_PF(bp) && !bnxt_hwrm_get_nvm_cfg_ver(bp, &nvm_cfg_ver)) { 473 u32 ver = nvm_cfg_ver.vu32; 474 475 sprintf(buf, "%X.%X.%X", (ver >> 16) & 0xF, (ver >> 8) & 0xF, 476 ver & 0xF); 477 rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_STORED, 478 DEVLINK_INFO_VERSION_GENERIC_FW_PSID, 479 buf); 480 if (rc) 481 return rc; 482 } 483 484 if (ver_resp->flags & VER_GET_RESP_FLAGS_EXT_VER_AVAIL) { 485 snprintf(mgmt_ver, FW_VER_STR_LEN, "%d.%d.%d.%d", 486 ver_resp->hwrm_fw_major, ver_resp->hwrm_fw_minor, 487 ver_resp->hwrm_fw_build, ver_resp->hwrm_fw_patch); 488 489 snprintf(ncsi_ver, FW_VER_STR_LEN, "%d.%d.%d.%d", 490 ver_resp->mgmt_fw_major, ver_resp->mgmt_fw_minor, 491 ver_resp->mgmt_fw_build, ver_resp->mgmt_fw_patch); 492 493 snprintf(roce_ver, FW_VER_STR_LEN, "%d.%d.%d.%d", 494 ver_resp->roce_fw_major, ver_resp->roce_fw_minor, 495 ver_resp->roce_fw_build, ver_resp->roce_fw_patch); 496 } else { 497 snprintf(mgmt_ver, FW_VER_STR_LEN, "%d.%d.%d.%d", 498 ver_resp->hwrm_fw_maj_8b, ver_resp->hwrm_fw_min_8b, 499 ver_resp->hwrm_fw_bld_8b, ver_resp->hwrm_fw_rsvd_8b); 500 501 snprintf(ncsi_ver, FW_VER_STR_LEN, "%d.%d.%d.%d", 502 ver_resp->mgmt_fw_maj_8b, ver_resp->mgmt_fw_min_8b, 503 ver_resp->mgmt_fw_bld_8b, ver_resp->mgmt_fw_rsvd_8b); 504 505 snprintf(roce_ver, FW_VER_STR_LEN, "%d.%d.%d.%d", 506 ver_resp->roce_fw_maj_8b, ver_resp->roce_fw_min_8b, 507 ver_resp->roce_fw_bld_8b, ver_resp->roce_fw_rsvd_8b); 508 } 509 rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_RUNNING, 510 DEVLINK_INFO_VERSION_GENERIC_FW_MGMT, mgmt_ver); 511 if (rc) 512 return rc; 513 514 rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_RUNNING, 515 DEVLINK_INFO_VERSION_GENERIC_FW_MGMT_API, 516 bp->hwrm_ver_supp); 517 if (rc) 518 return rc; 519 520 rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_RUNNING, 521 DEVLINK_INFO_VERSION_GENERIC_FW_NCSI, ncsi_ver); 522 if (rc) 523 return rc; 524 525 rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_RUNNING, 526 DEVLINK_INFO_VERSION_GENERIC_FW_ROCE, roce_ver); 527 if (rc) 528 return rc; 529 530 rc = bnxt_hwrm_nvm_get_dev_info(bp, &nvm_dev_info); 531 if (rc || 532 !(nvm_dev_info.flags & NVM_GET_DEV_INFO_RESP_FLAGS_FW_VER_VALID)) 533 return 0; 534 535 buf[0] = 0; 536 strncat(buf, nvm_dev_info.pkg_name, HWRM_FW_VER_STR_LEN); 537 rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_STORED, 538 DEVLINK_INFO_VERSION_GENERIC_FW, buf); 539 if (rc) 540 return rc; 541 542 snprintf(mgmt_ver, FW_VER_STR_LEN, "%d.%d.%d.%d", 543 nvm_dev_info.hwrm_fw_major, nvm_dev_info.hwrm_fw_minor, 544 nvm_dev_info.hwrm_fw_build, nvm_dev_info.hwrm_fw_patch); 545 rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_STORED, 546 DEVLINK_INFO_VERSION_GENERIC_FW_MGMT, mgmt_ver); 547 if (rc) 548 return rc; 549 550 snprintf(ncsi_ver, FW_VER_STR_LEN, "%d.%d.%d.%d", 551 nvm_dev_info.mgmt_fw_major, nvm_dev_info.mgmt_fw_minor, 552 nvm_dev_info.mgmt_fw_build, nvm_dev_info.mgmt_fw_patch); 553 rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_STORED, 554 DEVLINK_INFO_VERSION_GENERIC_FW_NCSI, ncsi_ver); 555 if (rc) 556 return rc; 557 558 snprintf(roce_ver, FW_VER_STR_LEN, "%d.%d.%d.%d", 559 nvm_dev_info.roce_fw_major, nvm_dev_info.roce_fw_minor, 560 nvm_dev_info.roce_fw_build, nvm_dev_info.roce_fw_patch); 561 return bnxt_dl_info_put(bp, req, BNXT_VERSION_STORED, 562 DEVLINK_INFO_VERSION_GENERIC_FW_ROCE, roce_ver); 563 } 564 565 static int bnxt_hwrm_nvm_req(struct bnxt *bp, u32 param_id, void *msg, 566 int msg_len, union devlink_param_value *val) 567 { 568 struct hwrm_nvm_get_variable_input *req = msg; 569 struct bnxt_dl_nvm_param nvm_param; 570 union bnxt_nvm_data *data; 571 dma_addr_t data_dma_addr; 572 int idx = 0, rc, i; 573 574 /* Get/Set NVM CFG parameter is supported only on PFs */ 575 if (BNXT_VF(bp)) 576 return -EPERM; 577 578 for (i = 0; i < ARRAY_SIZE(nvm_params); i++) { 579 if (nvm_params[i].id == param_id) { 580 nvm_param = nvm_params[i]; 581 break; 582 } 583 } 584 585 if (i == ARRAY_SIZE(nvm_params)) 586 return -EOPNOTSUPP; 587 588 if (nvm_param.dir_type == BNXT_NVM_PORT_CFG) 589 idx = bp->pf.port_id; 590 else if (nvm_param.dir_type == BNXT_NVM_FUNC_CFG) 591 idx = bp->pf.fw_fid - BNXT_FIRST_PF_FID; 592 593 data = dma_alloc_coherent(&bp->pdev->dev, sizeof(*data), 594 &data_dma_addr, GFP_KERNEL); 595 if (!data) 596 return -ENOMEM; 597 598 req->dest_data_addr = cpu_to_le64(data_dma_addr); 599 req->data_len = cpu_to_le16(nvm_param.nvm_num_bits); 600 req->option_num = cpu_to_le16(nvm_param.offset); 601 req->index_0 = cpu_to_le16(idx); 602 if (idx) 603 req->dimensions = cpu_to_le16(1); 604 605 if (req->req_type == cpu_to_le16(HWRM_NVM_SET_VARIABLE)) { 606 bnxt_copy_to_nvm_data(data, val, nvm_param.nvm_num_bits, 607 nvm_param.dl_num_bytes); 608 rc = hwrm_send_message(bp, msg, msg_len, HWRM_CMD_TIMEOUT); 609 } else { 610 rc = hwrm_send_message_silent(bp, msg, msg_len, 611 HWRM_CMD_TIMEOUT); 612 if (!rc) { 613 bnxt_copy_from_nvm_data(val, data, 614 nvm_param.nvm_num_bits, 615 nvm_param.dl_num_bytes); 616 } else { 617 struct hwrm_err_output *resp = bp->hwrm_cmd_resp_addr; 618 619 if (resp->cmd_err == 620 NVM_GET_VARIABLE_CMD_ERR_CODE_VAR_NOT_EXIST) 621 rc = -EOPNOTSUPP; 622 } 623 } 624 dma_free_coherent(&bp->pdev->dev, sizeof(*data), data, data_dma_addr); 625 if (rc == -EACCES) 626 netdev_err(bp->dev, "PF does not have admin privileges to modify NVM config\n"); 627 return rc; 628 } 629 630 static int bnxt_dl_nvm_param_get(struct devlink *dl, u32 id, 631 struct devlink_param_gset_ctx *ctx) 632 { 633 struct hwrm_nvm_get_variable_input req = {0}; 634 struct bnxt *bp = bnxt_get_bp_from_dl(dl); 635 int rc; 636 637 bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_NVM_GET_VARIABLE, -1, -1); 638 rc = bnxt_hwrm_nvm_req(bp, id, &req, sizeof(req), &ctx->val); 639 if (!rc) 640 if (id == BNXT_DEVLINK_PARAM_ID_GRE_VER_CHECK) 641 ctx->val.vbool = !ctx->val.vbool; 642 643 return rc; 644 } 645 646 static int bnxt_dl_nvm_param_set(struct devlink *dl, u32 id, 647 struct devlink_param_gset_ctx *ctx) 648 { 649 struct hwrm_nvm_set_variable_input req = {0}; 650 struct bnxt *bp = bnxt_get_bp_from_dl(dl); 651 652 bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_NVM_SET_VARIABLE, -1, -1); 653 654 if (id == BNXT_DEVLINK_PARAM_ID_GRE_VER_CHECK) 655 ctx->val.vbool = !ctx->val.vbool; 656 657 return bnxt_hwrm_nvm_req(bp, id, &req, sizeof(req), &ctx->val); 658 } 659 660 static int bnxt_dl_msix_validate(struct devlink *dl, u32 id, 661 union devlink_param_value val, 662 struct netlink_ext_ack *extack) 663 { 664 int max_val = -1; 665 666 if (id == DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MAX) 667 max_val = BNXT_MSIX_VEC_MAX; 668 669 if (id == DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MIN) 670 max_val = BNXT_MSIX_VEC_MIN_MAX; 671 672 if (val.vu32 > max_val) { 673 NL_SET_ERR_MSG_MOD(extack, "MSIX value is exceeding the range"); 674 return -EINVAL; 675 } 676 677 return 0; 678 } 679 680 static const struct devlink_param bnxt_dl_params[] = { 681 DEVLINK_PARAM_GENERIC(ENABLE_SRIOV, 682 BIT(DEVLINK_PARAM_CMODE_PERMANENT), 683 bnxt_dl_nvm_param_get, bnxt_dl_nvm_param_set, 684 NULL), 685 DEVLINK_PARAM_GENERIC(IGNORE_ARI, 686 BIT(DEVLINK_PARAM_CMODE_PERMANENT), 687 bnxt_dl_nvm_param_get, bnxt_dl_nvm_param_set, 688 NULL), 689 DEVLINK_PARAM_GENERIC(MSIX_VEC_PER_PF_MAX, 690 BIT(DEVLINK_PARAM_CMODE_PERMANENT), 691 bnxt_dl_nvm_param_get, bnxt_dl_nvm_param_set, 692 bnxt_dl_msix_validate), 693 DEVLINK_PARAM_GENERIC(MSIX_VEC_PER_PF_MIN, 694 BIT(DEVLINK_PARAM_CMODE_PERMANENT), 695 bnxt_dl_nvm_param_get, bnxt_dl_nvm_param_set, 696 bnxt_dl_msix_validate), 697 DEVLINK_PARAM_DRIVER(BNXT_DEVLINK_PARAM_ID_GRE_VER_CHECK, 698 "gre_ver_check", DEVLINK_PARAM_TYPE_BOOL, 699 BIT(DEVLINK_PARAM_CMODE_PERMANENT), 700 bnxt_dl_nvm_param_get, bnxt_dl_nvm_param_set, 701 NULL), 702 }; 703 704 static const struct devlink_param bnxt_dl_port_params[] = { 705 }; 706 707 static int bnxt_dl_params_register(struct bnxt *bp) 708 { 709 int rc; 710 711 if (bp->hwrm_spec_code < 0x10600) 712 return 0; 713 714 rc = devlink_params_register(bp->dl, bnxt_dl_params, 715 ARRAY_SIZE(bnxt_dl_params)); 716 if (rc) { 717 netdev_warn(bp->dev, "devlink_params_register failed. rc=%d\n", 718 rc); 719 return rc; 720 } 721 rc = devlink_port_params_register(&bp->dl_port, bnxt_dl_port_params, 722 ARRAY_SIZE(bnxt_dl_port_params)); 723 if (rc) { 724 netdev_err(bp->dev, "devlink_port_params_register failed\n"); 725 devlink_params_unregister(bp->dl, bnxt_dl_params, 726 ARRAY_SIZE(bnxt_dl_params)); 727 return rc; 728 } 729 devlink_params_publish(bp->dl); 730 731 return 0; 732 } 733 734 static void bnxt_dl_params_unregister(struct bnxt *bp) 735 { 736 if (bp->hwrm_spec_code < 0x10600) 737 return; 738 739 devlink_params_unregister(bp->dl, bnxt_dl_params, 740 ARRAY_SIZE(bnxt_dl_params)); 741 devlink_port_params_unregister(&bp->dl_port, bnxt_dl_port_params, 742 ARRAY_SIZE(bnxt_dl_port_params)); 743 } 744 745 int bnxt_dl_register(struct bnxt *bp) 746 { 747 struct devlink_port_attrs attrs = {}; 748 struct devlink *dl; 749 int rc; 750 751 if (BNXT_PF(bp)) 752 dl = devlink_alloc(&bnxt_dl_ops, sizeof(struct bnxt_dl)); 753 else 754 dl = devlink_alloc(&bnxt_vf_dl_ops, sizeof(struct bnxt_dl)); 755 if (!dl) { 756 netdev_warn(bp->dev, "devlink_alloc failed\n"); 757 return -ENOMEM; 758 } 759 760 bnxt_link_bp_to_dl(bp, dl); 761 762 /* Add switchdev eswitch mode setting, if SRIOV supported */ 763 if (pci_find_ext_capability(bp->pdev, PCI_EXT_CAP_ID_SRIOV) && 764 bp->hwrm_spec_code > 0x10803) 765 bp->eswitch_mode = DEVLINK_ESWITCH_MODE_LEGACY; 766 767 rc = devlink_register(dl, &bp->pdev->dev); 768 if (rc) { 769 netdev_warn(bp->dev, "devlink_register failed. rc=%d\n", rc); 770 goto err_dl_free; 771 } 772 773 if (!BNXT_PF(bp)) 774 return 0; 775 776 attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL; 777 attrs.phys.port_number = bp->pf.port_id; 778 memcpy(attrs.switch_id.id, bp->dsn, sizeof(bp->dsn)); 779 attrs.switch_id.id_len = sizeof(bp->dsn); 780 devlink_port_attrs_set(&bp->dl_port, &attrs); 781 rc = devlink_port_register(dl, &bp->dl_port, bp->pf.port_id); 782 if (rc) { 783 netdev_err(bp->dev, "devlink_port_register failed\n"); 784 goto err_dl_unreg; 785 } 786 787 rc = bnxt_dl_params_register(bp); 788 if (rc) 789 goto err_dl_port_unreg; 790 791 return 0; 792 793 err_dl_port_unreg: 794 devlink_port_unregister(&bp->dl_port); 795 err_dl_unreg: 796 devlink_unregister(dl); 797 err_dl_free: 798 bnxt_link_bp_to_dl(bp, NULL); 799 devlink_free(dl); 800 return rc; 801 } 802 803 void bnxt_dl_unregister(struct bnxt *bp) 804 { 805 struct devlink *dl = bp->dl; 806 807 if (!dl) 808 return; 809 810 if (BNXT_PF(bp)) { 811 bnxt_dl_params_unregister(bp); 812 devlink_port_unregister(&bp->dl_port); 813 } 814 devlink_unregister(dl); 815 devlink_free(dl); 816 } 817