ice: Add AdminQ commands for FW update

Add structures, identifiers, and helper functions for several AdminQ
commands related to performing a firmware update for the ice hardware.
These will be used in future code for implementing the devlink
.flash_update handler.

Signed-off-by: Cudzilo, Szymon T <szymon.t.cudzilo@intel.com>
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Cudzilo, Szymon T 2020-07-23 17:22:01 -07:00 committed by David S. Miller
parent de9b277ee0
commit 544cd2ac13
5 changed files with 281 additions and 2 deletions

View File

@ -1299,7 +1299,14 @@ struct ice_aqc_nvm {
#define ICE_AQC_NVM_PRESERVATION_M (3 << ICE_AQC_NVM_PRESERVATION_S)
#define ICE_AQC_NVM_NO_PRESERVATION (0 << ICE_AQC_NVM_PRESERVATION_S)
#define ICE_AQC_NVM_PRESERVE_ALL BIT(1)
#define ICE_AQC_NVM_FACTORY_DEFAULT (2 << ICE_AQC_NVM_PRESERVATION_S)
#define ICE_AQC_NVM_PRESERVE_SELECTED (3 << ICE_AQC_NVM_PRESERVATION_S)
#define ICE_AQC_NVM_ACTIV_SEL_NVM BIT(3) /* Write Activate/SR Dump only */
#define ICE_AQC_NVM_ACTIV_SEL_OROM BIT(4)
#define ICE_AQC_NVM_ACTIV_SEL_NETLIST BIT(5)
#define ICE_AQC_NVM_SPECIAL_UPDATE BIT(6)
#define ICE_AQC_NVM_REVERT_LAST_ACTIV BIT(6) /* Write Activate only */
#define ICE_AQC_NVM_ACTIV_SEL_MASK ICE_M(0x7, 3)
#define ICE_AQC_NVM_FLASH_ONLY BIT(7)
__le16 module_typeid;
__le16 length;
@ -1348,6 +1355,67 @@ struct ice_aqc_nvm_checksum {
#define ICE_AQC_NVM_NETLIST_ID_BLK_SHA_HASH 0xA
#define ICE_AQC_NVM_NETLIST_ID_BLK_CUST_VER 0x2F
/* Used for NVM Set Package Data command - 0x070A */
struct ice_aqc_nvm_pkg_data {
u8 reserved[3];
u8 cmd_flags;
#define ICE_AQC_NVM_PKG_DELETE BIT(0) /* used for command call */
#define ICE_AQC_NVM_PKG_SKIPPED BIT(0) /* used for command response */
u32 reserved1;
__le32 addr_high;
__le32 addr_low;
};
/* Used for Pass Component Table command - 0x070B */
struct ice_aqc_nvm_pass_comp_tbl {
u8 component_response; /* Response only */
#define ICE_AQ_NVM_PASS_COMP_CAN_BE_UPDATED 0x0
#define ICE_AQ_NVM_PASS_COMP_CAN_MAY_BE_UPDATEABLE 0x1
#define ICE_AQ_NVM_PASS_COMP_CAN_NOT_BE_UPDATED 0x2
u8 component_response_code; /* Response only */
#define ICE_AQ_NVM_PASS_COMP_CAN_BE_UPDATED_CODE 0x0
#define ICE_AQ_NVM_PASS_COMP_STAMP_IDENTICAL_CODE 0x1
#define ICE_AQ_NVM_PASS_COMP_STAMP_LOWER 0x2
#define ICE_AQ_NVM_PASS_COMP_INVALID_STAMP_CODE 0x3
#define ICE_AQ_NVM_PASS_COMP_CONFLICT_CODE 0x4
#define ICE_AQ_NVM_PASS_COMP_PRE_REQ_NOT_MET_CODE 0x5
#define ICE_AQ_NVM_PASS_COMP_NOT_SUPPORTED_CODE 0x6
#define ICE_AQ_NVM_PASS_COMP_CANNOT_DOWNGRADE_CODE 0x7
#define ICE_AQ_NVM_PASS_COMP_INCOMPLETE_IMAGE_CODE 0x8
#define ICE_AQ_NVM_PASS_COMP_VER_STR_IDENTICAL_CODE 0xA
#define ICE_AQ_NVM_PASS_COMP_VER_STR_LOWER_CODE 0xB
u8 reserved;
u8 transfer_flag;
#define ICE_AQ_NVM_PASS_COMP_TBL_START 0x1
#define ICE_AQ_NVM_PASS_COMP_TBL_MIDDLE 0x2
#define ICE_AQ_NVM_PASS_COMP_TBL_END 0x4
#define ICE_AQ_NVM_PASS_COMP_TBL_START_AND_END 0x5
__le32 reserved1;
__le32 addr_high;
__le32 addr_low;
};
struct ice_aqc_nvm_comp_tbl {
__le16 comp_class;
#define NVM_COMP_CLASS_ALL_FW 0x000A
__le16 comp_id;
#define NVM_COMP_ID_OROM 0x5
#define NVM_COMP_ID_NVM 0x6
#define NVM_COMP_ID_NETLIST 0x8
u8 comp_class_idx;
#define FWU_COMP_CLASS_IDX_NOT_USE 0x0
__le32 comp_cmp_stamp;
u8 cvs_type;
#define NVM_CVS_TYPE_ASCII 0x1
u8 cvs_len;
u8 cvs[]; /* Component Version String */
} __packed;
/**
* Send to PF command (indirect 0x0801) ID is only used by PF
*
@ -1795,6 +1863,8 @@ struct ice_aq_desc {
struct ice_aqc_rl_profile rl_profile;
struct ice_aqc_nvm nvm;
struct ice_aqc_nvm_checksum nvm_checksum;
struct ice_aqc_nvm_pkg_data pkg_data;
struct ice_aqc_nvm_pass_comp_tbl pass_comp_tbl;
struct ice_aqc_pf_vf_msg virt;
struct ice_aqc_lldp_get_mib lldp_get_mib;
struct ice_aqc_lldp_set_mib_change lldp_set_event;
@ -1923,7 +1993,13 @@ enum ice_adminq_opc {
/* NVM commands */
ice_aqc_opc_nvm_read = 0x0701,
ice_aqc_opc_nvm_erase = 0x0702,
ice_aqc_opc_nvm_write = 0x0703,
ice_aqc_opc_nvm_checksum = 0x0706,
ice_aqc_opc_nvm_write_activate = 0x0707,
ice_aqc_opc_nvm_update_empr = 0x0709,
ice_aqc_opc_nvm_pkg_data = 0x070A,
ice_aqc_opc_nvm_pass_component_tbl = 0x070B,
/* PF/VF mailbox commands */
ice_mbx_opc_send_msg_to_pf = 0x0801,

View File

@ -11,8 +11,6 @@
#include "ice_switch.h"
#include <linux/avf/virtchnl.h>
enum ice_status ice_nvm_validate_checksum(struct ice_hw *hw);
enum ice_status ice_init_hw(struct ice_hw *hw);
void ice_deinit_hw(struct ice_hw *hw);
enum ice_status ice_check_reset(struct ice_hw *hw);

View File

@ -107,6 +107,76 @@ ice_read_flat_nvm(struct ice_hw *hw, u32 offset, u32 *length, u8 *data,
return status;
}
/**
* ice_aq_update_nvm
* @hw: pointer to the HW struct
* @module_typeid: module pointer location in words from the NVM beginning
* @offset: byte offset from the module beginning
* @length: length of the section to be written (in bytes from the offset)
* @data: command buffer (size [bytes] = length)
* @last_command: tells if this is the last command in a series
* @command_flags: command parameters
* @cd: pointer to command details structure or NULL
*
* Update the NVM using the admin queue commands (0x0703)
*/
enum ice_status
ice_aq_update_nvm(struct ice_hw *hw, u16 module_typeid, u32 offset,
u16 length, void *data, bool last_command, u8 command_flags,
struct ice_sq_cd *cd)
{
struct ice_aq_desc desc;
struct ice_aqc_nvm *cmd;
cmd = &desc.params.nvm;
/* In offset the highest byte must be zeroed. */
if (offset & 0xFF000000)
return ICE_ERR_PARAM;
ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_nvm_write);
cmd->cmd_flags |= command_flags;
/* If this is the last command in a series, set the proper flag. */
if (last_command)
cmd->cmd_flags |= ICE_AQC_NVM_LAST_CMD;
cmd->module_typeid = cpu_to_le16(module_typeid);
cmd->offset_low = cpu_to_le16(offset & 0xFFFF);
cmd->offset_high = (offset >> 16) & 0xFF;
cmd->length = cpu_to_le16(length);
desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
return ice_aq_send_cmd(hw, &desc, data, length, cd);
}
/**
* ice_aq_erase_nvm
* @hw: pointer to the HW struct
* @module_typeid: module pointer location in words from the NVM beginning
* @cd: pointer to command details structure or NULL
*
* Erase the NVM sector using the admin queue commands (0x0702)
*/
enum ice_status
ice_aq_erase_nvm(struct ice_hw *hw, u16 module_typeid, struct ice_sq_cd *cd)
{
struct ice_aq_desc desc;
struct ice_aqc_nvm *cmd;
cmd = &desc.params.nvm;
ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_nvm_erase);
cmd->module_typeid = cpu_to_le16(module_typeid);
cmd->length = cpu_to_le16(ICE_AQC_NVM_ERASE_LEN);
cmd->offset_low = 0;
cmd->offset_high = 0;
return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
}
/**
* ice_read_sr_word_aq - Reads Shadow RAM via AQ
* @hw: pointer to the HW structure
@ -634,3 +704,119 @@ enum ice_status ice_nvm_validate_checksum(struct ice_hw *hw)
return status;
}
/**
* ice_nvm_write_activate
* @hw: pointer to the HW struct
* @cmd_flags: NVM activate admin command bits (banks to be validated)
*
* Update the control word with the required banks' validity bits
* and dumps the Shadow RAM to flash (0x0707)
*/
enum ice_status ice_nvm_write_activate(struct ice_hw *hw, u8 cmd_flags)
{
struct ice_aqc_nvm *cmd;
struct ice_aq_desc desc;
cmd = &desc.params.nvm;
ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_nvm_write_activate);
cmd->cmd_flags = cmd_flags;
return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
}
/**
* ice_aq_nvm_update_empr
* @hw: pointer to the HW struct
*
* Update empr (0x0709). This command allows SW to
* request an EMPR to activate new FW.
*/
enum ice_status ice_aq_nvm_update_empr(struct ice_hw *hw)
{
struct ice_aq_desc desc;
ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_nvm_update_empr);
return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
}
/* ice_nvm_set_pkg_data
* @hw: pointer to the HW struct
* @del_pkg_data_flag: If is set then the current pkg_data store by FW
* is deleted.
* If bit is set to 1, then buffer should be size 0.
* @data: pointer to buffer
* @length: length of the buffer
* @cd: pointer to command details structure or NULL
*
* Set package data (0x070A). This command is equivalent to the reception
* of a PLDM FW Update GetPackageData cmd. This command should be sent
* as part of the NVM update as the first cmd in the flow.
*/
enum ice_status
ice_nvm_set_pkg_data(struct ice_hw *hw, bool del_pkg_data_flag, u8 *data,
u16 length, struct ice_sq_cd *cd)
{
struct ice_aqc_nvm_pkg_data *cmd;
struct ice_aq_desc desc;
if (length != 0 && !data)
return ICE_ERR_PARAM;
cmd = &desc.params.pkg_data;
ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_nvm_pkg_data);
desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
if (del_pkg_data_flag)
cmd->cmd_flags |= ICE_AQC_NVM_PKG_DELETE;
return ice_aq_send_cmd(hw, &desc, data, length, cd);
}
/* ice_nvm_pass_component_tbl
* @hw: pointer to the HW struct
* @data: pointer to buffer
* @length: length of the buffer
* @transfer_flag: parameter for determining stage of the update
* @comp_response: a pointer to the response from the 0x070B AQC.
* @comp_response_code: a pointer to the response code from the 0x070B AQC.
* @cd: pointer to command details structure or NULL
*
* Pass component table (0x070B). This command is equivalent to the reception
* of a PLDM FW Update PassComponentTable cmd. This command should be sent once
* per component. It can be only sent after Set Package Data cmd and before
* actual update. FW will assume these commands are going to be sent until
* the TransferFlag is set to End or StartAndEnd.
*/
enum ice_status
ice_nvm_pass_component_tbl(struct ice_hw *hw, u8 *data, u16 length,
u8 transfer_flag, u8 *comp_response,
u8 *comp_response_code, struct ice_sq_cd *cd)
{
struct ice_aqc_nvm_pass_comp_tbl *cmd;
struct ice_aq_desc desc;
enum ice_status status;
if (!data || !comp_response || !comp_response_code)
return ICE_ERR_PARAM;
cmd = &desc.params.pass_comp_tbl;
ice_fill_dflt_direct_cmd_desc(&desc,
ice_aqc_opc_nvm_pass_component_tbl);
desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
cmd->transfer_flag = transfer_flag;
status = ice_aq_send_cmd(hw, &desc, data, length, cd);
if (!status) {
*comp_response = cmd->component_response;
*comp_response_code = cmd->component_response_code;
}
return status;
}

View File

@ -17,4 +17,20 @@ enum ice_status
ice_read_pba_string(struct ice_hw *hw, u8 *pba_num, u32 pba_num_size);
enum ice_status ice_init_nvm(struct ice_hw *hw);
enum ice_status ice_read_sr_word(struct ice_hw *hw, u16 offset, u16 *data);
enum ice_status
ice_aq_update_nvm(struct ice_hw *hw, u16 module_typeid, u32 offset,
u16 length, void *data, bool last_command, u8 command_flags,
struct ice_sq_cd *cd);
enum ice_status
ice_aq_erase_nvm(struct ice_hw *hw, u16 module_typeid, struct ice_sq_cd *cd);
enum ice_status ice_nvm_validate_checksum(struct ice_hw *hw);
enum ice_status ice_nvm_write_activate(struct ice_hw *hw, u8 cmd_flags);
enum ice_status ice_aq_nvm_update_empr(struct ice_hw *hw);
enum ice_status
ice_nvm_set_pkg_data(struct ice_hw *hw, bool del_pkg_data_flag, u8 *data,
u16 length, struct ice_sq_cd *cd);
enum ice_status
ice_nvm_pass_component_tbl(struct ice_hw *hw, u8 *data, u16 length,
u8 transfer_flag, u8 *comp_response,
u8 *comp_response_code, struct ice_sq_cd *cd);
#endif /* _ICE_NVM_H_ */

View File

@ -774,6 +774,9 @@ struct ice_hw_port_stats {
#define ICE_OROM_VER_SHIFT 24
#define ICE_OROM_VER_MASK (0xff << ICE_OROM_VER_SHIFT)
#define ICE_SR_PFA_PTR 0x40
#define ICE_SR_1ST_NVM_BANK_PTR 0x42
#define ICE_SR_1ST_OROM_BANK_PTR 0x44
#define ICE_SR_NETLIST_BANK_PTR 0x46
#define ICE_SR_SECTOR_SIZE_IN_WORDS 0x800
/* Link override related */