Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

bnxt_en: implement firmware live patching

Live patches are activated by using the 'limit no_reset' option when
performing a devlink dev reload fw_activate operation. These packages
must first be installed on the device in the usual way. For example,
via devlink dev flash or ethtool -f.

The devlink device info has also been enhanced to render stored and
running live patch versions.

Signed-off-by: Edwin Peer <edwin.peer@broadcom.com>
Signed-off-by: Michael Chan <michael.chan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Edwin Peer and committed by
David S. Miller
3c415339 21e70778

+174 -2
+2
drivers/net/ethernet/broadcom/bnxt/bnxt.c
··· 7490 7490 bp->fw_cap |= BNXT_FW_CAP_PTP_PPS; 7491 7491 if (BNXT_PF(bp) && (flags_ext & FUNC_QCAPS_RESP_FLAGS_EXT_HOT_RESET_IF_SUPPORT)) 7492 7492 bp->fw_cap |= BNXT_FW_CAP_HOT_RESET_IF; 7493 + if (BNXT_PF(bp) && (flags_ext & FUNC_QCAPS_RESP_FLAGS_EXT_FW_LIVEPATCH_SUPPORTED)) 7494 + bp->fw_cap |= BNXT_FW_CAP_LIVEPATCH; 7493 7495 7494 7496 bp->tx_push_thresh = 0; 7495 7497 if ((flags & FUNC_QCAPS_RESP_FLAGS_PUSH_MODE_SUPPORTED) &&
+1
drivers/net/ethernet/broadcom/bnxt/bnxt.h
··· 1958 1958 #define BNXT_FW_CAP_VLAN_RX_STRIP 0x01000000 1959 1959 #define BNXT_FW_CAP_VLAN_TX_INSERT 0x02000000 1960 1960 #define BNXT_FW_CAP_EXT_HW_STATS_SUPPORTED 0x04000000 1961 + #define BNXT_FW_CAP_LIVEPATCH 0x08000000 1961 1962 #define BNXT_FW_CAP_PTP_PPS 0x10000000 1962 1963 #define BNXT_FW_CAP_HOT_RESET_IF 0x20000000 1963 1964 #define BNXT_FW_CAP_RING_MONITOR 0x40000000
+171 -2
drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
··· 326 326 static int bnxt_dl_info_get(struct devlink *dl, struct devlink_info_req *req, 327 327 struct netlink_ext_ack *extack); 328 328 329 + static void 330 + bnxt_dl_livepatch_report_err(struct bnxt *bp, struct netlink_ext_ack *extack, 331 + struct hwrm_fw_livepatch_output *resp) 332 + { 333 + int err = ((struct hwrm_err_output *)resp)->cmd_err; 334 + 335 + switch (err) { 336 + case FW_LIVEPATCH_CMD_ERR_CODE_INVALID_OPCODE: 337 + netdev_err(bp->dev, "Illegal live patch opcode"); 338 + NL_SET_ERR_MSG_MOD(extack, "Invalid opcode"); 339 + break; 340 + case FW_LIVEPATCH_CMD_ERR_CODE_NOT_SUPPORTED: 341 + NL_SET_ERR_MSG_MOD(extack, "Live patch operation not supported"); 342 + break; 343 + case FW_LIVEPATCH_CMD_ERR_CODE_NOT_INSTALLED: 344 + NL_SET_ERR_MSG_MOD(extack, "Live patch not found"); 345 + break; 346 + case FW_LIVEPATCH_CMD_ERR_CODE_NOT_PATCHED: 347 + NL_SET_ERR_MSG_MOD(extack, 348 + "Live patch deactivation failed. Firmware not patched."); 349 + break; 350 + case FW_LIVEPATCH_CMD_ERR_CODE_AUTH_FAIL: 351 + NL_SET_ERR_MSG_MOD(extack, "Live patch not authenticated"); 352 + break; 353 + case FW_LIVEPATCH_CMD_ERR_CODE_INVALID_HEADER: 354 + NL_SET_ERR_MSG_MOD(extack, "Incompatible live patch"); 355 + break; 356 + case FW_LIVEPATCH_CMD_ERR_CODE_INVALID_SIZE: 357 + NL_SET_ERR_MSG_MOD(extack, "Live patch has invalid size"); 358 + break; 359 + case FW_LIVEPATCH_CMD_ERR_CODE_ALREADY_PATCHED: 360 + NL_SET_ERR_MSG_MOD(extack, "Live patch already applied"); 361 + break; 362 + default: 363 + netdev_err(bp->dev, "Unexpected live patch error: %hhd\n", err); 364 + NL_SET_ERR_MSG_MOD(extack, "Failed to activate live patch"); 365 + break; 366 + } 367 + } 368 + 369 + static int 370 + bnxt_dl_livepatch_activate(struct bnxt *bp, struct netlink_ext_ack *extack) 371 + { 372 + struct hwrm_fw_livepatch_query_output *query_resp; 373 + struct hwrm_fw_livepatch_query_input *query_req; 374 + struct hwrm_fw_livepatch_output *patch_resp; 375 + struct hwrm_fw_livepatch_input *patch_req; 376 + u32 installed = 0; 377 + u16 flags; 378 + u8 target; 379 + int rc; 380 + 381 + if (~bp->fw_cap & BNXT_FW_CAP_LIVEPATCH) { 382 + NL_SET_ERR_MSG_MOD(extack, "Device does not support live patch"); 383 + return -EOPNOTSUPP; 384 + } 385 + 386 + rc = hwrm_req_init(bp, query_req, HWRM_FW_LIVEPATCH_QUERY); 387 + if (rc) 388 + return rc; 389 + query_resp = hwrm_req_hold(bp, query_req); 390 + 391 + rc = hwrm_req_init(bp, patch_req, HWRM_FW_LIVEPATCH); 392 + if (rc) { 393 + hwrm_req_drop(bp, query_req); 394 + return rc; 395 + } 396 + patch_req->opcode = FW_LIVEPATCH_REQ_OPCODE_ACTIVATE; 397 + patch_req->loadtype = FW_LIVEPATCH_REQ_LOADTYPE_NVM_INSTALL; 398 + patch_resp = hwrm_req_hold(bp, patch_req); 399 + 400 + for (target = 1; target <= FW_LIVEPATCH_REQ_FW_TARGET_LAST; target++) { 401 + query_req->fw_target = target; 402 + rc = hwrm_req_send(bp, query_req); 403 + if (rc) { 404 + NL_SET_ERR_MSG_MOD(extack, "Failed to query packages"); 405 + break; 406 + } 407 + 408 + flags = le16_to_cpu(query_resp->status_flags); 409 + if (~flags & FW_LIVEPATCH_QUERY_RESP_STATUS_FLAGS_INSTALL) 410 + continue; 411 + if ((flags & FW_LIVEPATCH_QUERY_RESP_STATUS_FLAGS_ACTIVE) && 412 + !strncmp(query_resp->active_ver, query_resp->install_ver, 413 + sizeof(query_resp->active_ver))) 414 + continue; 415 + 416 + patch_req->fw_target = target; 417 + rc = hwrm_req_send(bp, patch_req); 418 + if (rc) { 419 + bnxt_dl_livepatch_report_err(bp, extack, patch_resp); 420 + break; 421 + } 422 + installed++; 423 + } 424 + 425 + if (!rc && !installed) { 426 + NL_SET_ERR_MSG_MOD(extack, "No live patches found"); 427 + rc = -ENOENT; 428 + } 429 + hwrm_req_drop(bp, query_req); 430 + hwrm_req_drop(bp, patch_req); 431 + return rc; 432 + } 433 + 329 434 static int bnxt_dl_reload_down(struct devlink *dl, bool netns_change, 330 435 enum devlink_reload_action action, 331 436 enum devlink_reload_limit limit, ··· 477 372 break; 478 373 } 479 374 case DEVLINK_RELOAD_ACTION_FW_ACTIVATE: { 375 + if (limit == DEVLINK_RELOAD_LIMIT_NO_RESET) 376 + return bnxt_dl_livepatch_activate(bp, extack); 480 377 if (~bp->fw_cap & BNXT_FW_CAP_HOT_RESET) { 481 378 NL_SET_ERR_MSG_MOD(extack, "Device not capable, requires reboot"); 482 379 return -EOPNOTSUPP; ··· 539 432 unsigned long start = jiffies; 540 433 unsigned long timeout = start + BNXT_DFLT_FW_RST_MAX_DSECS * HZ / 10; 541 434 435 + if (limit == DEVLINK_RELOAD_LIMIT_NO_RESET) 436 + break; 542 437 if (bp->fw_cap & BNXT_FW_CAP_ERROR_RECOVERY) 543 438 timeout = start + bp->fw_health->normal_func_wait_dsecs * HZ / 10; 544 439 if (!netif_running(bp->dev)) ··· 594 485 .flash_update = bnxt_dl_flash_update, 595 486 .reload_actions = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT) | 596 487 BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE), 488 + .reload_limits = BIT(DEVLINK_RELOAD_LIMIT_NO_RESET), 597 489 .reload_down = bnxt_dl_reload_down, 598 490 .reload_up = bnxt_dl_reload_up, 599 491 }; ··· 738 628 return devlink_info_version_stored_put(req, key, buf); 739 629 } 740 630 return 0; 631 + } 632 + 633 + #define BNXT_FW_SRT_PATCH "fw.srt.patch" 634 + #define BNXT_FW_CRT_PATCH "fw.crt.patch" 635 + 636 + static int bnxt_dl_livepatch_info_put(struct bnxt *bp, 637 + struct devlink_info_req *req, 638 + const char *key) 639 + { 640 + struct hwrm_fw_livepatch_query_input *query; 641 + struct hwrm_fw_livepatch_query_output *resp; 642 + u16 flags; 643 + int rc; 644 + 645 + if (~bp->fw_cap & BNXT_FW_CAP_LIVEPATCH) 646 + return 0; 647 + 648 + rc = hwrm_req_init(bp, query, HWRM_FW_LIVEPATCH_QUERY); 649 + if (rc) 650 + return rc; 651 + 652 + if (!strcmp(key, BNXT_FW_SRT_PATCH)) 653 + query->fw_target = FW_LIVEPATCH_QUERY_REQ_FW_TARGET_SECURE_FW; 654 + else if (!strcmp(key, BNXT_FW_CRT_PATCH)) 655 + query->fw_target = FW_LIVEPATCH_QUERY_REQ_FW_TARGET_COMMON_FW; 656 + else 657 + goto exit; 658 + 659 + resp = hwrm_req_hold(bp, query); 660 + rc = hwrm_req_send(bp, query); 661 + if (rc) 662 + goto exit; 663 + 664 + flags = le16_to_cpu(resp->status_flags); 665 + if (flags & FW_LIVEPATCH_QUERY_RESP_STATUS_FLAGS_ACTIVE) { 666 + resp->active_ver[sizeof(resp->active_ver) - 1] = '\0'; 667 + rc = devlink_info_version_running_put(req, key, resp->active_ver); 668 + if (rc) 669 + goto exit; 670 + } 671 + 672 + if (flags & FW_LIVEPATCH_QUERY_RESP_STATUS_FLAGS_INSTALL) { 673 + resp->install_ver[sizeof(resp->install_ver) - 1] = '\0'; 674 + rc = devlink_info_version_stored_put(req, key, resp->install_ver); 675 + if (rc) 676 + goto exit; 677 + } 678 + 679 + exit: 680 + hwrm_req_drop(bp, query); 681 + return rc; 741 682 } 742 683 743 684 #define HWRM_FW_VER_STR_LEN 16 ··· 944 783 snprintf(roce_ver, FW_VER_STR_LEN, "%d.%d.%d.%d", 945 784 nvm_dev_info.roce_fw_major, nvm_dev_info.roce_fw_minor, 946 785 nvm_dev_info.roce_fw_build, nvm_dev_info.roce_fw_patch); 947 - return bnxt_dl_info_put(bp, req, BNXT_VERSION_STORED, 948 - DEVLINK_INFO_VERSION_GENERIC_FW_ROCE, roce_ver); 786 + rc = bnxt_dl_info_put(bp, req, BNXT_VERSION_STORED, 787 + DEVLINK_INFO_VERSION_GENERIC_FW_ROCE, roce_ver); 788 + if (rc) 789 + return rc; 790 + 791 + rc = bnxt_dl_livepatch_info_put(bp, req, BNXT_FW_SRT_PATCH); 792 + if (rc) 793 + return rc; 794 + return bnxt_dl_livepatch_info_put(bp, req, BNXT_FW_CRT_PATCH); 795 + 949 796 } 950 797 951 798 static int bnxt_hwrm_nvm_req(struct bnxt *bp, u32 param_id, void *msg,