Commit 1278d17a authored by Kalesh AP's avatar Kalesh AP Committed by David S. Miller

bnxt_en: Fix devlink fw_activate

To install a livepatch, first flash the package to NVM, and then
activate the patch through the "HWRM_FW_LIVEPATCH" fw command.
To uninstall a patch from NVM, flash the removal package and then
activate it through the "HWRM_FW_LIVEPATCH" fw command.

The "HWRM_FW_LIVEPATCH" fw command has to consider following scenarios:

1. no patch in NVM and no patch active. Do nothing.
2. patch in NVM, but not active. Activate the patch currently in NVM.
3. patch is not in NVM, but active. Deactivate the patch.
4. patch in NVM and the patch active. Do nothing.

Fix the code to handle these scenarios during devlink "fw_activate".

To install and activate a live patch:
devlink dev flash pci/0000:c1:00.0 file thor_patch.pkg
devlink -f dev reload pci/0000:c1:00.0 action fw_activate limit no_reset

To remove and deactivate a live patch:
devlink dev flash pci/0000:c1:00.0 file thor_patch_rem.pkg
devlink -f dev reload pci/0000:c1:00.0 action fw_activate limit no_reset

Fixes: 3c415339 ("bnxt_en: implement firmware live patching")
Reviewed-by: default avatarVikas Gupta <vikas.gupta@broadcom.com>
Reviewed-by: default avatarSomnath Kotur <somnath.kotur@broadcom.com>
Signed-off-by: default avatarKalesh AP <kalesh-anakkur.purayil@broadcom.com>
Signed-off-by: default avatarMichael Chan <michael.chan@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b891106d
...@@ -367,6 +367,16 @@ bnxt_dl_livepatch_report_err(struct bnxt *bp, struct netlink_ext_ack *extack, ...@@ -367,6 +367,16 @@ bnxt_dl_livepatch_report_err(struct bnxt *bp, struct netlink_ext_ack *extack,
} }
} }
/* Live patch status in NVM */
#define BNXT_LIVEPATCH_NOT_INSTALLED 0
#define BNXT_LIVEPATCH_INSTALLED FW_LIVEPATCH_QUERY_RESP_STATUS_FLAGS_INSTALL
#define BNXT_LIVEPATCH_REMOVED FW_LIVEPATCH_QUERY_RESP_STATUS_FLAGS_ACTIVE
#define BNXT_LIVEPATCH_MASK (FW_LIVEPATCH_QUERY_RESP_STATUS_FLAGS_INSTALL | \
FW_LIVEPATCH_QUERY_RESP_STATUS_FLAGS_ACTIVE)
#define BNXT_LIVEPATCH_ACTIVATED BNXT_LIVEPATCH_MASK
#define BNXT_LIVEPATCH_STATE(flags) ((flags) & BNXT_LIVEPATCH_MASK)
static int static int
bnxt_dl_livepatch_activate(struct bnxt *bp, struct netlink_ext_ack *extack) bnxt_dl_livepatch_activate(struct bnxt *bp, struct netlink_ext_ack *extack)
{ {
...@@ -374,8 +384,9 @@ bnxt_dl_livepatch_activate(struct bnxt *bp, struct netlink_ext_ack *extack) ...@@ -374,8 +384,9 @@ bnxt_dl_livepatch_activate(struct bnxt *bp, struct netlink_ext_ack *extack)
struct hwrm_fw_livepatch_query_input *query_req; struct hwrm_fw_livepatch_query_input *query_req;
struct hwrm_fw_livepatch_output *patch_resp; struct hwrm_fw_livepatch_output *patch_resp;
struct hwrm_fw_livepatch_input *patch_req; struct hwrm_fw_livepatch_input *patch_req;
u16 flags, live_patch_state;
bool activated = false;
u32 installed = 0; u32 installed = 0;
u16 flags;
u8 target; u8 target;
int rc; int rc;
...@@ -394,7 +405,6 @@ bnxt_dl_livepatch_activate(struct bnxt *bp, struct netlink_ext_ack *extack) ...@@ -394,7 +405,6 @@ bnxt_dl_livepatch_activate(struct bnxt *bp, struct netlink_ext_ack *extack)
hwrm_req_drop(bp, query_req); hwrm_req_drop(bp, query_req);
return rc; return rc;
} }
patch_req->opcode = FW_LIVEPATCH_REQ_OPCODE_ACTIVATE;
patch_req->loadtype = FW_LIVEPATCH_REQ_LOADTYPE_NVM_INSTALL; patch_req->loadtype = FW_LIVEPATCH_REQ_LOADTYPE_NVM_INSTALL;
patch_resp = hwrm_req_hold(bp, patch_req); patch_resp = hwrm_req_hold(bp, patch_req);
...@@ -407,12 +417,20 @@ bnxt_dl_livepatch_activate(struct bnxt *bp, struct netlink_ext_ack *extack) ...@@ -407,12 +417,20 @@ bnxt_dl_livepatch_activate(struct bnxt *bp, struct netlink_ext_ack *extack)
} }
flags = le16_to_cpu(query_resp->status_flags); flags = le16_to_cpu(query_resp->status_flags);
if (~flags & FW_LIVEPATCH_QUERY_RESP_STATUS_FLAGS_INSTALL) live_patch_state = BNXT_LIVEPATCH_STATE(flags);
if (live_patch_state == BNXT_LIVEPATCH_NOT_INSTALLED)
continue; continue;
if ((flags & FW_LIVEPATCH_QUERY_RESP_STATUS_FLAGS_ACTIVE) &&
!strncmp(query_resp->active_ver, query_resp->install_ver, if (live_patch_state == BNXT_LIVEPATCH_ACTIVATED) {
sizeof(query_resp->active_ver))) activated = true;
continue; continue;
}
if (live_patch_state == BNXT_LIVEPATCH_INSTALLED)
patch_req->opcode = FW_LIVEPATCH_REQ_OPCODE_ACTIVATE;
else if (live_patch_state == BNXT_LIVEPATCH_REMOVED)
patch_req->opcode = FW_LIVEPATCH_REQ_OPCODE_DEACTIVATE;
patch_req->fw_target = target; patch_req->fw_target = target;
rc = hwrm_req_send(bp, patch_req); rc = hwrm_req_send(bp, patch_req);
...@@ -424,9 +442,14 @@ bnxt_dl_livepatch_activate(struct bnxt *bp, struct netlink_ext_ack *extack) ...@@ -424,9 +442,14 @@ bnxt_dl_livepatch_activate(struct bnxt *bp, struct netlink_ext_ack *extack)
} }
if (!rc && !installed) { if (!rc && !installed) {
if (activated) {
NL_SET_ERR_MSG_MOD(extack, "Live patch already activated");
rc = -EEXIST;
} else {
NL_SET_ERR_MSG_MOD(extack, "No live patches found"); NL_SET_ERR_MSG_MOD(extack, "No live patches found");
rc = -ENOENT; rc = -ENOENT;
} }
}
hwrm_req_drop(bp, query_req); hwrm_req_drop(bp, query_req);
hwrm_req_drop(bp, patch_req); hwrm_req_drop(bp, patch_req);
return rc; return rc;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment