be2net: use offset based FW flashing for Skyhawk chip
While sending FW update cmds to the FW, the driver specifies the "type" of each component that needs to be flashed. The FW then picks the offset in the flash area at which the componnet is to be flashed. This doesn't work when new components that the current FW doesn't recognize, need to be flashed. Recent FWs (10.2 and above) support a scheme of FW-update wherein the "offset" of the component in the flash area can be specified instead of the "type". This patch uses the "offset" based FW-update mechanism and only when it fails, it fallsback to the old "type" based update. 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
81a9e226ff
commit
70a7b52570
|
@ -2436,7 +2436,8 @@ err_unlock:
|
||||||
}
|
}
|
||||||
|
|
||||||
int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd,
|
int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd,
|
||||||
u32 flash_type, u32 flash_opcode, u32 buf_size)
|
u32 flash_type, u32 flash_opcode, u32 img_offset,
|
||||||
|
u32 buf_size)
|
||||||
{
|
{
|
||||||
struct be_mcc_wrb *wrb;
|
struct be_mcc_wrb *wrb;
|
||||||
struct be_cmd_write_flashrom *req;
|
struct be_cmd_write_flashrom *req;
|
||||||
|
@ -2457,6 +2458,9 @@ int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd,
|
||||||
cmd);
|
cmd);
|
||||||
|
|
||||||
req->params.op_type = cpu_to_le32(flash_type);
|
req->params.op_type = cpu_to_le32(flash_type);
|
||||||
|
if (flash_type == OPTYPE_OFFSET_SPECIFIED)
|
||||||
|
req->params.offset = cpu_to_le32(img_offset);
|
||||||
|
|
||||||
req->params.op_code = cpu_to_le32(flash_opcode);
|
req->params.op_code = cpu_to_le32(flash_opcode);
|
||||||
req->params.data_buf_size = cpu_to_le32(buf_size);
|
req->params.data_buf_size = cpu_to_le32(buf_size);
|
||||||
|
|
||||||
|
@ -2477,10 +2481,10 @@ err_unlock:
|
||||||
}
|
}
|
||||||
|
|
||||||
int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc,
|
int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc,
|
||||||
u16 optype, int offset)
|
u16 img_optype, u32 img_offset, u32 crc_offset)
|
||||||
{
|
{
|
||||||
struct be_mcc_wrb *wrb;
|
|
||||||
struct be_cmd_read_flash_crc *req;
|
struct be_cmd_read_flash_crc *req;
|
||||||
|
struct be_mcc_wrb *wrb;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
spin_lock_bh(&adapter->mcc_lock);
|
spin_lock_bh(&adapter->mcc_lock);
|
||||||
|
@ -2496,9 +2500,13 @@ int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc,
|
||||||
OPCODE_COMMON_READ_FLASHROM, sizeof(*req),
|
OPCODE_COMMON_READ_FLASHROM, sizeof(*req),
|
||||||
wrb, NULL);
|
wrb, NULL);
|
||||||
|
|
||||||
req->params.op_type = cpu_to_le32(optype);
|
req->params.op_type = cpu_to_le32(img_optype);
|
||||||
|
if (img_optype == OPTYPE_OFFSET_SPECIFIED)
|
||||||
|
req->params.offset = cpu_to_le32(img_offset + crc_offset);
|
||||||
|
else
|
||||||
|
req->params.offset = cpu_to_le32(crc_offset);
|
||||||
|
|
||||||
req->params.op_code = cpu_to_le32(FLASHROM_OPER_REPORT);
|
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);
|
req->params.data_buf_size = cpu_to_le32(0x4);
|
||||||
|
|
||||||
status = be_mcc_notify_wait(adapter);
|
status = be_mcc_notify_wait(adapter);
|
||||||
|
|
|
@ -1172,6 +1172,7 @@ struct be_cmd_resp_get_beacon_state {
|
||||||
#define OPTYPE_REDBOOT 1
|
#define OPTYPE_REDBOOT 1
|
||||||
#define OPTYPE_BIOS 2
|
#define OPTYPE_BIOS 2
|
||||||
#define OPTYPE_PXE_BIOS 3
|
#define OPTYPE_PXE_BIOS 3
|
||||||
|
#define OPTYPE_OFFSET_SPECIFIED 7
|
||||||
#define OPTYPE_FCOE_BIOS 8
|
#define OPTYPE_FCOE_BIOS 8
|
||||||
#define OPTYPE_ISCSI_BACKUP 9
|
#define OPTYPE_ISCSI_BACKUP 9
|
||||||
#define OPTYPE_FCOE_FW_ACTIVE 10
|
#define OPTYPE_FCOE_FW_ACTIVE 10
|
||||||
|
@ -2255,7 +2256,8 @@ int be_cmd_read_port_transceiver_data(struct be_adapter *adapter,
|
||||||
u8 page_num, u8 *data);
|
u8 page_num, u8 *data);
|
||||||
int be_cmd_query_cable_type(struct be_adapter *adapter);
|
int be_cmd_query_cable_type(struct be_adapter *adapter);
|
||||||
int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd,
|
int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd,
|
||||||
u32 flash_oper, u32 flash_opcode, u32 buf_size);
|
u32 flash_oper, u32 flash_opcode, u32 img_offset,
|
||||||
|
u32 buf_size);
|
||||||
int lancer_cmd_write_object(struct be_adapter *adapter, struct be_dma_mem *cmd,
|
int lancer_cmd_write_object(struct be_adapter *adapter, struct be_dma_mem *cmd,
|
||||||
u32 data_size, u32 data_offset,
|
u32 data_size, u32 data_offset,
|
||||||
const char *obj_name, u32 *data_written,
|
const char *obj_name, u32 *data_written,
|
||||||
|
@ -2265,7 +2267,7 @@ int lancer_cmd_read_object(struct be_adapter *adapter, struct be_dma_mem *cmd,
|
||||||
u32 *data_read, u32 *eof, u8 *addn_status);
|
u32 *data_read, u32 *eof, u8 *addn_status);
|
||||||
int lancer_cmd_delete_object(struct be_adapter *adapter, const char *obj_name);
|
int lancer_cmd_delete_object(struct be_adapter *adapter, const char *obj_name);
|
||||||
int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc,
|
int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc,
|
||||||
u16 optype, int offset);
|
u16 img_optype, u32 img_offset, u32 crc_offset);
|
||||||
int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac,
|
int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac,
|
||||||
struct be_dma_mem *nonemb_cmd);
|
struct be_dma_mem *nonemb_cmd);
|
||||||
int be_cmd_fw_init(struct be_adapter *adapter);
|
int be_cmd_fw_init(struct be_adapter *adapter);
|
||||||
|
|
|
@ -3942,7 +3942,8 @@ static int be_check_flash_crc(struct be_adapter *adapter, const u8 *p,
|
||||||
int status;
|
int status;
|
||||||
u8 crc[4];
|
u8 crc[4];
|
||||||
|
|
||||||
status = be_cmd_get_flash_crc(adapter, crc, img_optype, img_size - 4);
|
status = be_cmd_get_flash_crc(adapter, crc, img_optype, img_offset,
|
||||||
|
img_size - 4);
|
||||||
if (status)
|
if (status)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
|
@ -3958,13 +3959,13 @@ static int be_check_flash_crc(struct be_adapter *adapter, const u8 *p,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int be_flash(struct be_adapter *adapter, const u8 *img,
|
static int be_flash(struct be_adapter *adapter, const u8 *img,
|
||||||
struct be_dma_mem *flash_cmd, int optype, int img_size)
|
struct be_dma_mem *flash_cmd, int optype, int img_size,
|
||||||
|
u32 img_offset)
|
||||||
{
|
{
|
||||||
|
u32 flash_op, num_bytes, total_bytes = img_size, bytes_sent = 0;
|
||||||
struct be_cmd_write_flashrom *req = flash_cmd->va;
|
struct be_cmd_write_flashrom *req = flash_cmd->va;
|
||||||
u32 total_bytes, flash_op, num_bytes;
|
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
total_bytes = img_size;
|
|
||||||
while (total_bytes) {
|
while (total_bytes) {
|
||||||
num_bytes = min_t(u32, 32*1024, total_bytes);
|
num_bytes = min_t(u32, 32*1024, total_bytes);
|
||||||
|
|
||||||
|
@ -3985,12 +3986,15 @@ static int be_flash(struct be_adapter *adapter, const u8 *img,
|
||||||
memcpy(req->data_buf, img, num_bytes);
|
memcpy(req->data_buf, img, num_bytes);
|
||||||
img += num_bytes;
|
img += num_bytes;
|
||||||
status = be_cmd_write_flashrom(adapter, flash_cmd, optype,
|
status = be_cmd_write_flashrom(adapter, flash_cmd, optype,
|
||||||
flash_op, num_bytes);
|
flash_op, img_offset +
|
||||||
|
bytes_sent, num_bytes);
|
||||||
if (base_status(status) == MCC_STATUS_ILLEGAL_REQUEST &&
|
if (base_status(status) == MCC_STATUS_ILLEGAL_REQUEST &&
|
||||||
optype == OPTYPE_PHY_FW)
|
optype == OPTYPE_PHY_FW)
|
||||||
break;
|
break;
|
||||||
else if (status)
|
else if (status)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
|
bytes_sent += num_bytes;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -4103,7 +4107,7 @@ static int be_flash_BEx(struct be_adapter *adapter,
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
status = be_flash(adapter, p, flash_cmd, pflashcomp[i].optype,
|
status = be_flash(adapter, p, flash_cmd, pflashcomp[i].optype,
|
||||||
pflashcomp[i].size);
|
pflashcomp[i].size, 0);
|
||||||
if (status) {
|
if (status) {
|
||||||
dev_err(dev, "Flashing section type 0x%x failed\n",
|
dev_err(dev, "Flashing section type 0x%x failed\n",
|
||||||
pflashcomp[i].img_type);
|
pflashcomp[i].img_type);
|
||||||
|
@ -4170,12 +4174,12 @@ static int be_flash_skyhawk(struct be_adapter *adapter,
|
||||||
struct be_dma_mem *flash_cmd, int num_of_images)
|
struct be_dma_mem *flash_cmd, int num_of_images)
|
||||||
{
|
{
|
||||||
int img_hdrs_size = num_of_images * sizeof(struct image_hdr);
|
int img_hdrs_size = num_of_images * sizeof(struct image_hdr);
|
||||||
|
bool crc_match, old_fw_img, flash_offset_support = true;
|
||||||
struct device *dev = &adapter->pdev->dev;
|
struct device *dev = &adapter->pdev->dev;
|
||||||
struct flash_section_info *fsec = NULL;
|
struct flash_section_info *fsec = NULL;
|
||||||
u32 img_offset, img_size, img_type;
|
u32 img_offset, img_size, img_type;
|
||||||
|
u16 img_optype, flash_optype;
|
||||||
int status, i, filehdr_size;
|
int status, i, filehdr_size;
|
||||||
bool crc_match, old_fw_img;
|
|
||||||
u16 img_optype;
|
|
||||||
const u8 *p;
|
const u8 *p;
|
||||||
|
|
||||||
filehdr_size = sizeof(struct flash_file_hdr_g3);
|
filehdr_size = sizeof(struct flash_file_hdr_g3);
|
||||||
|
@ -4185,6 +4189,7 @@ static int be_flash_skyhawk(struct be_adapter *adapter,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
retry_flash:
|
||||||
for (i = 0; i < le32_to_cpu(fsec->fsec_hdr.num_images); i++) {
|
for (i = 0; i < le32_to_cpu(fsec->fsec_hdr.num_images); i++) {
|
||||||
img_offset = le32_to_cpu(fsec->fsec_entry[i].offset);
|
img_offset = le32_to_cpu(fsec->fsec_entry[i].offset);
|
||||||
img_size = le32_to_cpu(fsec->fsec_entry[i].pad_size);
|
img_size = le32_to_cpu(fsec->fsec_entry[i].pad_size);
|
||||||
|
@ -4194,6 +4199,12 @@ static int be_flash_skyhawk(struct be_adapter *adapter,
|
||||||
|
|
||||||
if (img_optype == 0xFFFF)
|
if (img_optype == 0xFFFF)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (flash_offset_support)
|
||||||
|
flash_optype = OPTYPE_OFFSET_SPECIFIED;
|
||||||
|
else
|
||||||
|
flash_optype = img_optype;
|
||||||
|
|
||||||
/* Don't bother verifying CRC if an old FW image is being
|
/* Don't bother verifying CRC if an old FW image is being
|
||||||
* flashed
|
* flashed
|
||||||
*/
|
*/
|
||||||
|
@ -4202,16 +4213,26 @@ static int be_flash_skyhawk(struct be_adapter *adapter,
|
||||||
|
|
||||||
status = be_check_flash_crc(adapter, fw->data, img_offset,
|
status = be_check_flash_crc(adapter, fw->data, img_offset,
|
||||||
img_size, filehdr_size +
|
img_size, filehdr_size +
|
||||||
img_hdrs_size, img_optype,
|
img_hdrs_size, flash_optype,
|
||||||
&crc_match);
|
&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 (base_status(status) == MCC_STATUS_ILLEGAL_REQUEST ||
|
if (base_status(status) == MCC_STATUS_ILLEGAL_REQUEST ||
|
||||||
base_status(status) == MCC_STATUS_ILLEGAL_FIELD) {
|
base_status(status) == MCC_STATUS_ILLEGAL_FIELD) {
|
||||||
|
/* The current FW image on the card does not support
|
||||||
|
* OFFSET based flashing. Retry using older mechanism
|
||||||
|
* of OPTYPE based flashing
|
||||||
|
*/
|
||||||
|
if (flash_optype == OPTYPE_OFFSET_SPECIFIED) {
|
||||||
|
flash_offset_support = false;
|
||||||
|
goto retry_flash;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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.
|
||||||
|
*/
|
||||||
dev_err(dev, "Flash incomplete. Reset the server\n");
|
dev_err(dev, "Flash incomplete. Reset the server\n");
|
||||||
dev_err(dev, "Download FW image again after reset\n");
|
dev_err(dev, "Download FW image again after reset\n");
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
|
@ -4229,7 +4250,19 @@ flash:
|
||||||
if (p + img_size > fw->data + fw->size)
|
if (p + img_size > fw->data + fw->size)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
status = be_flash(adapter, p, flash_cmd, img_optype, img_size);
|
status = be_flash(adapter, p, flash_cmd, flash_optype, img_size,
|
||||||
|
img_offset);
|
||||||
|
|
||||||
|
/* The current FW image on the card does not support OFFSET
|
||||||
|
* based flashing. Retry using older mechanism of OPTYPE based
|
||||||
|
* flashing
|
||||||
|
*/
|
||||||
|
if (base_status(status) == MCC_STATUS_ILLEGAL_FIELD &&
|
||||||
|
flash_optype == OPTYPE_OFFSET_SPECIFIED) {
|
||||||
|
flash_offset_support = false;
|
||||||
|
goto retry_flash;
|
||||||
|
}
|
||||||
|
|
||||||
/* For old FW images ignore ILLEGAL_FIELD error or errors on
|
/* For old FW images ignore ILLEGAL_FIELD error or errors on
|
||||||
* UFI_DIR region
|
* UFI_DIR region
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue