be2net: support flashing new regions on Skyhawk-R
Certain new flash regions have been added to Skyhawk-R FW image. The newer FW images specify op_types for each region. A region is flashed only when it's CRC doesn't match that of the region on the HW flash. While upgrading to a new FW image the driver is expected to tolerate certain errors. This patch re-factors code under be_flash() to support the above scheme. Signed-off-by: Vasundhara Volam <vasundhara.volam@emulex.com> Signed-off-by: Sathya Perla <sathya.perla@emulex.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
0f77ba7353
commit
96c9b2e45e
|
@ -133,6 +133,9 @@ static int be_mcc_compl_process(struct be_adapter *adapter,
|
|||
compl_status = (compl->status >> CQE_STATUS_COMPL_SHIFT) &
|
||||
CQE_STATUS_COMPL_MASK;
|
||||
|
||||
extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) &
|
||||
CQE_STATUS_EXTD_MASK;
|
||||
|
||||
resp_hdr = be_decode_resp_hdr(compl->tag0, compl->tag1);
|
||||
|
||||
if (resp_hdr) {
|
||||
|
@ -172,16 +175,25 @@ static int be_mcc_compl_process(struct be_adapter *adapter,
|
|||
adapter->be_get_temp_freq = 0;
|
||||
|
||||
if (compl_status == MCC_STATUS_NOT_SUPPORTED ||
|
||||
compl_status == MCC_STATUS_ILLEGAL_REQUEST)
|
||||
goto done;
|
||||
compl_status == MCC_STATUS_ILLEGAL_REQUEST)
|
||||
return compl_status;
|
||||
|
||||
/* Ignore CRC mismatch error during FW download with old FW */
|
||||
if (opcode == OPCODE_COMMON_WRITE_FLASHROM &&
|
||||
compl_status == MCC_STATUS_FAILED &&
|
||||
extd_status == MCC_ADDL_STS_FLASH_IMAGE_CRC_MISMATCH)
|
||||
return compl_status;
|
||||
|
||||
/* Ignore illegal field error during FW download with old FW */
|
||||
if (opcode == OPCODE_COMMON_WRITE_FLASHROM &&
|
||||
compl_status == MCC_STATUS_ILLEGAL_FIELD)
|
||||
return compl_status;
|
||||
|
||||
if (compl_status == MCC_STATUS_UNAUTHORIZED_REQUEST) {
|
||||
dev_warn(&adapter->pdev->dev,
|
||||
"VF is not privileged to issue opcode %d-%d\n",
|
||||
opcode, subsystem);
|
||||
} else {
|
||||
extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) &
|
||||
CQE_STATUS_EXTD_MASK;
|
||||
dev_err(&adapter->pdev->dev,
|
||||
"opcode %d-%d failed:status %d-%d\n",
|
||||
opcode, subsystem, compl_status, extd_status);
|
||||
|
@ -190,7 +202,6 @@ static int be_mcc_compl_process(struct be_adapter *adapter,
|
|||
return extd_status;
|
||||
}
|
||||
}
|
||||
done:
|
||||
return compl_status;
|
||||
}
|
||||
|
||||
|
@ -2300,7 +2311,7 @@ err_unlock:
|
|||
}
|
||||
|
||||
int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc,
|
||||
int offset)
|
||||
u16 optype, int offset)
|
||||
{
|
||||
struct be_mcc_wrb *wrb;
|
||||
struct be_cmd_read_flash_crc *req;
|
||||
|
@ -2319,7 +2330,7 @@ int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc,
|
|||
OPCODE_COMMON_READ_FLASHROM, sizeof(*req),
|
||||
wrb, NULL);
|
||||
|
||||
req->params.op_type = cpu_to_le32(OPTYPE_REDBOOT);
|
||||
req->params.op_type = cpu_to_le32(optype);
|
||||
req->params.op_code = cpu_to_le32(FLASHROM_OPER_REPORT);
|
||||
req->params.offset = cpu_to_le32(offset);
|
||||
req->params.data_buf_size = cpu_to_le32(0x4);
|
||||
|
|
|
@ -61,6 +61,7 @@ enum {
|
|||
};
|
||||
|
||||
#define MCC_ADDL_STS_INSUFFICIENT_RESOURCES 0x16
|
||||
#define MCC_ADDL_STS_FLASH_IMAGE_CRC_MISMATCH 0x4d
|
||||
|
||||
#define CQE_STATUS_COMPL_MASK 0xFFFF
|
||||
#define CQE_STATUS_COMPL_SHIFT 0 /* bits 0 - 15 */
|
||||
|
@ -1186,7 +1187,8 @@ struct be_cmd_read_flash_crc {
|
|||
struct flashrom_params params;
|
||||
u8 crc[4];
|
||||
u8 rsvd[4];
|
||||
};
|
||||
} __packed;
|
||||
|
||||
/**************** Lancer Firmware Flash ************/
|
||||
struct amap_lancer_write_obj_context {
|
||||
u8 write_length[24];
|
||||
|
@ -2088,7 +2090,7 @@ int lancer_cmd_read_object(struct be_adapter *adapter, struct be_dma_mem *cmd,
|
|||
u32 data_size, u32 data_offset, const char *obj_name,
|
||||
u32 *data_read, u32 *eof, u8 *addn_status);
|
||||
int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc,
|
||||
int offset);
|
||||
u16 optype, int offset);
|
||||
int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac,
|
||||
struct be_dma_mem *nonemb_cmd);
|
||||
int be_cmd_fw_init(struct be_adapter *adapter);
|
||||
|
|
|
@ -188,10 +188,14 @@
|
|||
#define OPTYPE_FCOE_FW_ACTIVE 10
|
||||
#define OPTYPE_FCOE_FW_BACKUP 11
|
||||
#define OPTYPE_NCSI_FW 13
|
||||
#define OPTYPE_REDBOOT_DIR 18
|
||||
#define OPTYPE_REDBOOT_CONFIG 19
|
||||
#define OPTYPE_SH_PHY_FW 21
|
||||
#define OPTYPE_FLASHISM_JUMPVECTOR 22
|
||||
#define OPTYPE_UFI_DIR 23
|
||||
#define OPTYPE_PHY_FW 99
|
||||
#define TN_8022 13
|
||||
|
||||
#define ILLEGAL_IOCTL_REQ 2
|
||||
#define FLASHROM_OPER_PHY_FLASH 9
|
||||
#define FLASHROM_OPER_PHY_SAVE 10
|
||||
#define FLASHROM_OPER_FLASH 1
|
||||
|
@ -250,6 +254,9 @@
|
|||
#define IMAGE_FIRMWARE_BACKUP_FCoE 178
|
||||
#define IMAGE_FIRMWARE_BACKUP_COMP_FCoE 179
|
||||
#define IMAGE_FIRMWARE_PHY 192
|
||||
#define IMAGE_REDBOOT_DIR 208
|
||||
#define IMAGE_REDBOOT_CONFIG 209
|
||||
#define IMAGE_UFI_DIR 210
|
||||
#define IMAGE_BOOT_CODE 224
|
||||
|
||||
/************* Rx Packet Type Encoding **************/
|
||||
|
@ -534,7 +541,8 @@ struct flash_section_entry {
|
|||
u32 image_size;
|
||||
u32 cksum;
|
||||
u32 entry_point;
|
||||
u32 rsvd0;
|
||||
u16 optype;
|
||||
u16 rsvd0;
|
||||
u32 rsvd1;
|
||||
u8 ver_data[32];
|
||||
} __packed;
|
||||
|
|
|
@ -3630,34 +3630,7 @@ static void be_netpoll(struct net_device *netdev)
|
|||
}
|
||||
#endif
|
||||
|
||||
#define FW_FILE_HDR_SIGN "ServerEngines Corp. "
|
||||
static char flash_cookie[2][16] = {"*** SE FLAS", "H DIRECTORY *** "};
|
||||
|
||||
static bool be_flash_redboot(struct be_adapter *adapter,
|
||||
const u8 *p, u32 img_start, int image_size,
|
||||
int hdr_size)
|
||||
{
|
||||
u32 crc_offset;
|
||||
u8 flashed_crc[4];
|
||||
int status;
|
||||
|
||||
crc_offset = hdr_size + img_start + image_size - 4;
|
||||
|
||||
p += crc_offset;
|
||||
|
||||
status = be_cmd_get_flash_crc(adapter, flashed_crc, (image_size - 4));
|
||||
if (status) {
|
||||
dev_err(&adapter->pdev->dev,
|
||||
"could not get crc from flash, not flashing redboot\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
/*update redboot only if crc does not match*/
|
||||
if (!memcmp(flashed_crc, p, 4))
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
static char flash_cookie[2][16] = {"*** SE FLAS", "H DIRECTORY *** "};
|
||||
|
||||
static bool phy_flashing_required(struct be_adapter *adapter)
|
||||
{
|
||||
|
@ -3704,12 +3677,35 @@ static struct flash_section_info *get_fsec_info(struct be_adapter *adapter,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static int be_check_flash_crc(struct be_adapter *adapter, const u8 *p,
|
||||
u32 img_offset, u32 img_size, int hdr_size,
|
||||
u16 img_optype, bool *crc_match)
|
||||
{
|
||||
u32 crc_offset;
|
||||
int status;
|
||||
u8 crc[4];
|
||||
|
||||
status = be_cmd_get_flash_crc(adapter, crc, img_optype, img_size - 4);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
crc_offset = hdr_size + img_offset + img_size - 4;
|
||||
|
||||
/* Skip flashing, if crc of flashed region matches */
|
||||
if (!memcmp(crc, p + crc_offset, 4))
|
||||
*crc_match = true;
|
||||
else
|
||||
*crc_match = false;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int be_flash(struct be_adapter *adapter, const u8 *img,
|
||||
struct be_dma_mem *flash_cmd, int optype, int img_size)
|
||||
{
|
||||
u32 total_bytes = 0, flash_op, num_bytes = 0;
|
||||
int status = 0;
|
||||
struct be_cmd_write_flashrom *req = flash_cmd->va;
|
||||
u32 total_bytes, flash_op, num_bytes;
|
||||
int status;
|
||||
|
||||
total_bytes = img_size;
|
||||
while (total_bytes) {
|
||||
|
@ -3733,14 +3729,11 @@ static int be_flash(struct be_adapter *adapter, const u8 *img,
|
|||
img += num_bytes;
|
||||
status = be_cmd_write_flashrom(adapter, flash_cmd, optype,
|
||||
flash_op, num_bytes);
|
||||
if (status) {
|
||||
if (status == ILLEGAL_IOCTL_REQ &&
|
||||
optype == OPTYPE_PHY_FW)
|
||||
break;
|
||||
dev_err(&adapter->pdev->dev,
|
||||
"cmd to write to flash rom failed.\n");
|
||||
if (status == MCC_STATUS_ILLEGAL_REQUEST &&
|
||||
optype == OPTYPE_PHY_FW)
|
||||
break;
|
||||
else if (status)
|
||||
return status;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -3750,12 +3743,13 @@ static int be_flash_BEx(struct be_adapter *adapter,
|
|||
const struct firmware *fw,
|
||||
struct be_dma_mem *flash_cmd, int num_of_images)
|
||||
{
|
||||
int status = 0, i, filehdr_size = 0;
|
||||
int img_hdrs_size = (num_of_images * sizeof(struct image_hdr));
|
||||
const u8 *p = fw->data;
|
||||
const struct flash_comp *pflashcomp;
|
||||
int num_comp, redboot;
|
||||
struct device *dev = &adapter->pdev->dev;
|
||||
struct flash_section_info *fsec = NULL;
|
||||
int status, i, filehdr_size, num_comp;
|
||||
const struct flash_comp *pflashcomp;
|
||||
bool crc_match;
|
||||
const u8 *p;
|
||||
|
||||
struct flash_comp gen3_flash_types[] = {
|
||||
{ FLASH_iSCSI_PRIMARY_IMAGE_START_g3, OPTYPE_ISCSI_ACTIVE,
|
||||
|
@ -3812,8 +3806,7 @@ static int be_flash_BEx(struct be_adapter *adapter,
|
|||
/* Get flash section info*/
|
||||
fsec = get_fsec_info(adapter, filehdr_size + img_hdrs_size, fw);
|
||||
if (!fsec) {
|
||||
dev_err(&adapter->pdev->dev,
|
||||
"Invalid Cookie. UFI corrupted ?\n");
|
||||
dev_err(dev, "Invalid Cookie. FW image may be corrupted\n");
|
||||
return -1;
|
||||
}
|
||||
for (i = 0; i < num_comp; i++) {
|
||||
|
@ -3829,25 +3822,32 @@ static int be_flash_BEx(struct be_adapter *adapter,
|
|||
continue;
|
||||
|
||||
if (pflashcomp[i].optype == OPTYPE_REDBOOT) {
|
||||
redboot = be_flash_redboot(adapter, fw->data,
|
||||
pflashcomp[i].offset,
|
||||
pflashcomp[i].size,
|
||||
filehdr_size +
|
||||
img_hdrs_size);
|
||||
if (!redboot)
|
||||
status = be_check_flash_crc(adapter, fw->data,
|
||||
pflashcomp[i].offset,
|
||||
pflashcomp[i].size,
|
||||
filehdr_size +
|
||||
img_hdrs_size,
|
||||
OPTYPE_REDBOOT, &crc_match);
|
||||
if (status) {
|
||||
dev_err(dev,
|
||||
"Could not get CRC for 0x%x region\n",
|
||||
pflashcomp[i].optype);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (crc_match)
|
||||
continue;
|
||||
}
|
||||
|
||||
p = fw->data;
|
||||
p += filehdr_size + pflashcomp[i].offset + img_hdrs_size;
|
||||
p = fw->data + filehdr_size + pflashcomp[i].offset +
|
||||
img_hdrs_size;
|
||||
if (p + pflashcomp[i].size > fw->data + fw->size)
|
||||
return -1;
|
||||
|
||||
status = be_flash(adapter, p, flash_cmd, pflashcomp[i].optype,
|
||||
pflashcomp[i].size);
|
||||
if (status) {
|
||||
dev_err(&adapter->pdev->dev,
|
||||
"Flashing section type %d failed.\n",
|
||||
dev_err(dev, "Flashing section type 0x%x failed\n",
|
||||
pflashcomp[i].img_type);
|
||||
return status;
|
||||
}
|
||||
|
@ -3855,74 +3855,134 @@ static int be_flash_BEx(struct be_adapter *adapter,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static u16 be_get_img_optype(struct flash_section_entry fsec_entry)
|
||||
{
|
||||
u32 img_type = le32_to_cpu(fsec_entry.type);
|
||||
u16 img_optype = le16_to_cpu(fsec_entry.optype);
|
||||
|
||||
if (img_optype != 0xFFFF)
|
||||
return img_optype;
|
||||
|
||||
switch (img_type) {
|
||||
case IMAGE_FIRMWARE_iSCSI:
|
||||
img_optype = OPTYPE_ISCSI_ACTIVE;
|
||||
break;
|
||||
case IMAGE_BOOT_CODE:
|
||||
img_optype = OPTYPE_REDBOOT;
|
||||
break;
|
||||
case IMAGE_OPTION_ROM_ISCSI:
|
||||
img_optype = OPTYPE_BIOS;
|
||||
break;
|
||||
case IMAGE_OPTION_ROM_PXE:
|
||||
img_optype = OPTYPE_PXE_BIOS;
|
||||
break;
|
||||
case IMAGE_OPTION_ROM_FCoE:
|
||||
img_optype = OPTYPE_FCOE_BIOS;
|
||||
break;
|
||||
case IMAGE_FIRMWARE_BACKUP_iSCSI:
|
||||
img_optype = OPTYPE_ISCSI_BACKUP;
|
||||
break;
|
||||
case IMAGE_NCSI:
|
||||
img_optype = OPTYPE_NCSI_FW;
|
||||
break;
|
||||
case IMAGE_FLASHISM_JUMPVECTOR:
|
||||
img_optype = OPTYPE_FLASHISM_JUMPVECTOR;
|
||||
break;
|
||||
case IMAGE_FIRMWARE_PHY:
|
||||
img_optype = OPTYPE_SH_PHY_FW;
|
||||
break;
|
||||
case IMAGE_REDBOOT_DIR:
|
||||
img_optype = OPTYPE_REDBOOT_DIR;
|
||||
break;
|
||||
case IMAGE_REDBOOT_CONFIG:
|
||||
img_optype = OPTYPE_REDBOOT_CONFIG;
|
||||
break;
|
||||
case IMAGE_UFI_DIR:
|
||||
img_optype = OPTYPE_UFI_DIR;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return img_optype;
|
||||
}
|
||||
|
||||
static int be_flash_skyhawk(struct be_adapter *adapter,
|
||||
const struct firmware *fw,
|
||||
struct be_dma_mem *flash_cmd, int num_of_images)
|
||||
{
|
||||
int status = 0, i, filehdr_size = 0;
|
||||
int img_offset, img_size, img_optype, redboot;
|
||||
int img_hdrs_size = num_of_images * sizeof(struct image_hdr);
|
||||
const u8 *p = fw->data;
|
||||
struct device *dev = &adapter->pdev->dev;
|
||||
struct flash_section_info *fsec = NULL;
|
||||
u32 img_offset, img_size, img_type;
|
||||
int status, i, filehdr_size;
|
||||
bool crc_match, old_fw_img;
|
||||
u16 img_optype;
|
||||
const u8 *p;
|
||||
|
||||
filehdr_size = sizeof(struct flash_file_hdr_g3);
|
||||
fsec = get_fsec_info(adapter, filehdr_size + img_hdrs_size, fw);
|
||||
if (!fsec) {
|
||||
dev_err(&adapter->pdev->dev,
|
||||
"Invalid Cookie. UFI corrupted ?\n");
|
||||
dev_err(dev, "Invalid Cookie. FW image may be corrupted\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < le32_to_cpu(fsec->fsec_hdr.num_images); i++) {
|
||||
img_offset = le32_to_cpu(fsec->fsec_entry[i].offset);
|
||||
img_size = le32_to_cpu(fsec->fsec_entry[i].pad_size);
|
||||
img_type = le32_to_cpu(fsec->fsec_entry[i].type);
|
||||
img_optype = be_get_img_optype(fsec->fsec_entry[i]);
|
||||
old_fw_img = fsec->fsec_entry[i].optype == 0xFFFF;
|
||||
|
||||
switch (le32_to_cpu(fsec->fsec_entry[i].type)) {
|
||||
case IMAGE_FIRMWARE_iSCSI:
|
||||
img_optype = OPTYPE_ISCSI_ACTIVE;
|
||||
break;
|
||||
case IMAGE_BOOT_CODE:
|
||||
img_optype = OPTYPE_REDBOOT;
|
||||
break;
|
||||
case IMAGE_OPTION_ROM_ISCSI:
|
||||
img_optype = OPTYPE_BIOS;
|
||||
break;
|
||||
case IMAGE_OPTION_ROM_PXE:
|
||||
img_optype = OPTYPE_PXE_BIOS;
|
||||
break;
|
||||
case IMAGE_OPTION_ROM_FCoE:
|
||||
img_optype = OPTYPE_FCOE_BIOS;
|
||||
break;
|
||||
case IMAGE_FIRMWARE_BACKUP_iSCSI:
|
||||
img_optype = OPTYPE_ISCSI_BACKUP;
|
||||
break;
|
||||
case IMAGE_NCSI:
|
||||
img_optype = OPTYPE_NCSI_FW;
|
||||
break;
|
||||
default:
|
||||
if (img_optype == 0xFFFF)
|
||||
continue;
|
||||
/* Don't bother verifying CRC if an old FW image is being
|
||||
* flashed
|
||||
*/
|
||||
if (old_fw_img)
|
||||
goto flash;
|
||||
|
||||
status = be_check_flash_crc(adapter, fw->data, img_offset,
|
||||
img_size, filehdr_size +
|
||||
img_hdrs_size, img_optype,
|
||||
&crc_match);
|
||||
/* The current FW image on the card does not recognize the new
|
||||
* FLASH op_type. The FW download is partially complete.
|
||||
* Reboot the server now to enable FW image to recognize the
|
||||
* new FLASH op_type. To complete the remaining process,
|
||||
* download the same FW again after the reboot.
|
||||
*/
|
||||
if (status == MCC_STATUS_ILLEGAL_REQUEST ||
|
||||
status == MCC_STATUS_ILLEGAL_FIELD) {
|
||||
dev_err(dev, "Flash incomplete. Reset the server\n");
|
||||
dev_err(dev, "Download FW image again after reset\n");
|
||||
return -EAGAIN;
|
||||
} else if (status) {
|
||||
dev_err(dev, "Could not get CRC for 0x%x region\n",
|
||||
img_optype);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (img_optype == OPTYPE_REDBOOT) {
|
||||
redboot = be_flash_redboot(adapter, fw->data,
|
||||
img_offset, img_size,
|
||||
filehdr_size +
|
||||
img_hdrs_size);
|
||||
if (!redboot)
|
||||
continue;
|
||||
}
|
||||
if (crc_match)
|
||||
continue;
|
||||
|
||||
p = fw->data;
|
||||
p += filehdr_size + img_offset + img_hdrs_size;
|
||||
flash:
|
||||
p = fw->data + filehdr_size + img_offset + img_hdrs_size;
|
||||
if (p + img_size > fw->data + fw->size)
|
||||
return -1;
|
||||
|
||||
status = be_flash(adapter, p, flash_cmd, img_optype, img_size);
|
||||
if (status) {
|
||||
dev_err(&adapter->pdev->dev,
|
||||
"Flashing section type %d failed.\n",
|
||||
fsec->fsec_entry[i].type);
|
||||
return status;
|
||||
/* For old FW images ignore ILLEGAL_FIELD error or errors on
|
||||
* UFI_DIR region
|
||||
*/
|
||||
if (old_fw_img && (status == MCC_STATUS_ILLEGAL_FIELD ||
|
||||
(img_optype == OPTYPE_UFI_DIR &&
|
||||
status == MCC_STATUS_FAILED))) {
|
||||
continue;
|
||||
} else if (status) {
|
||||
dev_err(dev, "Flashing section type 0x%x failed\n",
|
||||
img_type);
|
||||
return -EFAULT;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
|
Loading…
Reference in New Issue