Commit 485bf569 authored by Shripad Nunjundarao's avatar Shripad Nunjundarao Committed by David S. Miller

be2net: FW download for Lancer

Added implementation of FW download feature for Lancer.
Signed-off-by: default avatarShripad Nunjundarao <shripad.nunjundarao@emulex.com>
Signed-off-by: default avatarSevin Xavier <selvin.xavier@emulex.com>
Signed-off-by: default avatarPadmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 005d5696
...@@ -71,7 +71,8 @@ static int be_mcc_compl_process(struct be_adapter *adapter, ...@@ -71,7 +71,8 @@ static int be_mcc_compl_process(struct be_adapter *adapter,
compl_status = (compl->status >> CQE_STATUS_COMPL_SHIFT) & compl_status = (compl->status >> CQE_STATUS_COMPL_SHIFT) &
CQE_STATUS_COMPL_MASK; CQE_STATUS_COMPL_MASK;
if ((compl->tag0 == OPCODE_COMMON_WRITE_FLASHROM) && if (((compl->tag0 == OPCODE_COMMON_WRITE_FLASHROM) ||
(compl->tag0 == OPCODE_COMMON_WRITE_OBJECT)) &&
(compl->tag1 == CMD_SUBSYSTEM_COMMON)) { (compl->tag1 == CMD_SUBSYSTEM_COMMON)) {
adapter->flash_status = compl_status; adapter->flash_status = compl_status;
complete(&adapter->flash_compl); complete(&adapter->flash_compl);
...@@ -1801,6 +1802,81 @@ int be_cmd_get_beacon_state(struct be_adapter *adapter, u8 port_num, u32 *state) ...@@ -1801,6 +1802,81 @@ int be_cmd_get_beacon_state(struct be_adapter *adapter, u8 port_num, u32 *state)
return status; return status;
} }
int lancer_cmd_write_object(struct be_adapter *adapter, struct be_dma_mem *cmd,
u32 data_size, u32 data_offset, const char *obj_name,
u32 *data_written, u8 *addn_status)
{
struct be_mcc_wrb *wrb;
struct lancer_cmd_req_write_object *req;
struct lancer_cmd_resp_write_object *resp;
void *ctxt = NULL;
int status;
spin_lock_bh(&adapter->mcc_lock);
adapter->flash_status = 0;
wrb = wrb_from_mccq(adapter);
if (!wrb) {
status = -EBUSY;
goto err_unlock;
}
req = embedded_payload(wrb);
be_wrb_hdr_prepare(wrb, sizeof(struct lancer_cmd_req_write_object),
true, 1, OPCODE_COMMON_WRITE_OBJECT);
wrb->tag1 = CMD_SUBSYSTEM_COMMON;
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
OPCODE_COMMON_WRITE_OBJECT,
sizeof(struct lancer_cmd_req_write_object));
ctxt = &req->context;
AMAP_SET_BITS(struct amap_lancer_write_obj_context,
write_length, ctxt, data_size);
if (data_size == 0)
AMAP_SET_BITS(struct amap_lancer_write_obj_context,
eof, ctxt, 1);
else
AMAP_SET_BITS(struct amap_lancer_write_obj_context,
eof, ctxt, 0);
be_dws_cpu_to_le(ctxt, sizeof(req->context));
req->write_offset = cpu_to_le32(data_offset);
strcpy(req->object_name, obj_name);
req->descriptor_count = cpu_to_le32(1);
req->buf_len = cpu_to_le32(data_size);
req->addr_low = cpu_to_le32((cmd->dma +
sizeof(struct lancer_cmd_req_write_object))
& 0xFFFFFFFF);
req->addr_high = cpu_to_le32(upper_32_bits(cmd->dma +
sizeof(struct lancer_cmd_req_write_object)));
be_mcc_notify(adapter);
spin_unlock_bh(&adapter->mcc_lock);
if (!wait_for_completion_timeout(&adapter->flash_compl,
msecs_to_jiffies(12000)))
status = -1;
else
status = adapter->flash_status;
resp = embedded_payload(wrb);
if (!status) {
*data_written = le32_to_cpu(resp->actual_write_len);
} else {
*addn_status = resp->additional_status;
status = resp->status;
}
return status;
err_unlock:
spin_unlock_bh(&adapter->mcc_lock);
return status;
}
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 buf_size)
{ {
......
...@@ -193,6 +193,7 @@ struct be_mcc_mailbox { ...@@ -193,6 +193,7 @@ struct be_mcc_mailbox {
#define OPCODE_COMMON_GET_PHY_DETAILS 102 #define OPCODE_COMMON_GET_PHY_DETAILS 102
#define OPCODE_COMMON_SET_DRIVER_FUNCTION_CAP 103 #define OPCODE_COMMON_SET_DRIVER_FUNCTION_CAP 103
#define OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES 121 #define OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES 121
#define OPCODE_COMMON_WRITE_OBJECT 172
#define OPCODE_ETH_RSS_CONFIG 1 #define OPCODE_ETH_RSS_CONFIG 1
#define OPCODE_ETH_ACPI_CONFIG 2 #define OPCODE_ETH_ACPI_CONFIG 2
...@@ -1131,6 +1132,36 @@ struct be_cmd_write_flashrom { ...@@ -1131,6 +1132,36 @@ struct be_cmd_write_flashrom {
struct flashrom_params params; struct flashrom_params params;
}; };
/**************** Lancer Firmware Flash ************/
struct amap_lancer_write_obj_context {
u8 write_length[24];
u8 reserved1[7];
u8 eof;
} __packed;
struct lancer_cmd_req_write_object {
struct be_cmd_req_hdr hdr;
u8 context[sizeof(struct amap_lancer_write_obj_context) / 8];
u32 write_offset;
u8 object_name[104];
u32 descriptor_count;
u32 buf_len;
u32 addr_low;
u32 addr_high;
};
struct lancer_cmd_resp_write_object {
u8 opcode;
u8 subsystem;
u8 rsvd1[2];
u8 status;
u8 additional_status;
u8 rsvd2[2];
u32 resp_len;
u32 actual_resp_len;
u32 actual_write_len;
};
/************************ WOL *******************************/ /************************ WOL *******************************/
struct be_cmd_req_acpi_wol_magic_config{ struct be_cmd_req_acpi_wol_magic_config{
struct be_cmd_req_hdr hdr; struct be_cmd_req_hdr hdr;
...@@ -1481,6 +1512,11 @@ extern int be_cmd_get_beacon_state(struct be_adapter *adapter, ...@@ -1481,6 +1512,11 @@ extern int be_cmd_get_beacon_state(struct be_adapter *adapter,
extern int be_cmd_write_flashrom(struct be_adapter *adapter, extern int be_cmd_write_flashrom(struct be_adapter *adapter,
struct be_dma_mem *cmd, u32 flash_oper, struct be_dma_mem *cmd, u32 flash_oper,
u32 flash_opcode, u32 buf_size); u32 flash_opcode, u32 buf_size);
extern int lancer_cmd_write_object(struct be_adapter *adapter,
struct be_dma_mem *cmd,
u32 data_size, u32 data_offset,
const char *obj_name,
u32 *data_written, u8 *addn_status);
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,
int offset); int offset);
extern int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac, extern int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac,
......
...@@ -2712,7 +2712,6 @@ static int be_flash_data(struct be_adapter *adapter, ...@@ -2712,7 +2712,6 @@ static int be_flash_data(struct be_adapter *adapter,
"cmd to write to flash rom failed.\n"); "cmd to write to flash rom failed.\n");
return -1; return -1;
} }
yield();
} }
} }
return 0; return 0;
...@@ -2730,32 +2729,98 @@ static int get_ufigen_type(struct flash_file_hdr_g2 *fhdr) ...@@ -2730,32 +2729,98 @@ static int get_ufigen_type(struct flash_file_hdr_g2 *fhdr)
return 0; return 0;
} }
int be_load_fw(struct be_adapter *adapter, u8 *func) static int lancer_fw_download(struct be_adapter *adapter,
const struct firmware *fw)
{ {
char fw_file[ETHTOOL_FLASH_MAX_FILENAME]; #define LANCER_FW_DOWNLOAD_CHUNK (32 * 1024)
const struct firmware *fw; #define LANCER_FW_DOWNLOAD_LOCATION "/prg"
struct flash_file_hdr_g2 *fhdr;
struct flash_file_hdr_g3 *fhdr3;
struct image_hdr *img_hdr_ptr = NULL;
struct be_dma_mem flash_cmd; struct be_dma_mem flash_cmd;
int status, i = 0, num_imgs = 0; struct lancer_cmd_req_write_object *req;
const u8 *p; const u8 *data_ptr = NULL;
u8 *dest_image_ptr = NULL;
size_t image_size = 0;
u32 chunk_size = 0;
u32 data_written = 0;
u32 offset = 0;
int status = 0;
u8 add_status = 0;
if (!netif_running(adapter->netdev)) { if (!IS_ALIGNED(fw->size, sizeof(u32))) {
dev_err(&adapter->pdev->dev, dev_err(&adapter->pdev->dev,
"Firmware load not allowed (interface is down)\n"); "FW Image not properly aligned. "
return -EPERM; "Length must be 4 byte aligned.\n");
status = -EINVAL;
goto lancer_fw_exit;
} }
strcpy(fw_file, func); flash_cmd.size = sizeof(struct lancer_cmd_req_write_object)
+ LANCER_FW_DOWNLOAD_CHUNK;
flash_cmd.va = dma_alloc_coherent(&adapter->pdev->dev, flash_cmd.size,
&flash_cmd.dma, GFP_KERNEL);
if (!flash_cmd.va) {
status = -ENOMEM;
dev_err(&adapter->pdev->dev,
"Memory allocation failure while flashing\n");
goto lancer_fw_exit;
}
req = flash_cmd.va;
dest_image_ptr = flash_cmd.va +
sizeof(struct lancer_cmd_req_write_object);
image_size = fw->size;
data_ptr = fw->data;
while (image_size) {
chunk_size = min_t(u32, image_size, LANCER_FW_DOWNLOAD_CHUNK);
/* Copy the image chunk content. */
memcpy(dest_image_ptr, data_ptr, chunk_size);
status = lancer_cmd_write_object(adapter, &flash_cmd,
chunk_size, offset, LANCER_FW_DOWNLOAD_LOCATION,
&data_written, &add_status);
status = request_firmware(&fw, fw_file, &adapter->pdev->dev);
if (status) if (status)
goto fw_exit; break;
offset += data_written;
data_ptr += data_written;
image_size -= data_written;
}
if (!status) {
/* Commit the FW written */
status = lancer_cmd_write_object(adapter, &flash_cmd,
0, offset, LANCER_FW_DOWNLOAD_LOCATION,
&data_written, &add_status);
}
dma_free_coherent(&adapter->pdev->dev, flash_cmd.size, flash_cmd.va,
flash_cmd.dma);
if (status) {
dev_err(&adapter->pdev->dev,
"Firmware load error. "
"Status code: 0x%x Additional Status: 0x%x\n",
status, add_status);
goto lancer_fw_exit;
}
dev_info(&adapter->pdev->dev, "Firmware flashed successfully\n");
lancer_fw_exit:
return status;
}
static int be_fw_download(struct be_adapter *adapter, const struct firmware* fw)
{
struct flash_file_hdr_g2 *fhdr;
struct flash_file_hdr_g3 *fhdr3;
struct image_hdr *img_hdr_ptr = NULL;
struct be_dma_mem flash_cmd;
const u8 *p;
int status = 0, i = 0, num_imgs = 0;
p = fw->data; p = fw->data;
fhdr = (struct flash_file_hdr_g2 *) p; fhdr = (struct flash_file_hdr_g2 *) p;
dev_info(&adapter->pdev->dev, "Flashing firmware file %s\n", fw_file);
flash_cmd.size = sizeof(struct be_cmd_write_flashrom) + 32*1024; flash_cmd.size = sizeof(struct be_cmd_write_flashrom) + 32*1024;
flash_cmd.va = dma_alloc_coherent(&adapter->pdev->dev, flash_cmd.size, flash_cmd.va = dma_alloc_coherent(&adapter->pdev->dev, flash_cmd.size,
...@@ -2764,7 +2829,7 @@ int be_load_fw(struct be_adapter *adapter, u8 *func) ...@@ -2764,7 +2829,7 @@ int be_load_fw(struct be_adapter *adapter, u8 *func)
status = -ENOMEM; status = -ENOMEM;
dev_err(&adapter->pdev->dev, dev_err(&adapter->pdev->dev,
"Memory allocation failure while flashing\n"); "Memory allocation failure while flashing\n");
goto fw_exit; goto be_fw_exit;
} }
if ((adapter->generation == BE_GEN3) && if ((adapter->generation == BE_GEN3) &&
...@@ -2792,11 +2857,37 @@ int be_load_fw(struct be_adapter *adapter, u8 *func) ...@@ -2792,11 +2857,37 @@ int be_load_fw(struct be_adapter *adapter, u8 *func)
flash_cmd.dma); flash_cmd.dma);
if (status) { if (status) {
dev_err(&adapter->pdev->dev, "Firmware load error\n"); dev_err(&adapter->pdev->dev, "Firmware load error\n");
goto fw_exit; goto be_fw_exit;
} }
dev_info(&adapter->pdev->dev, "Firmware flashed successfully\n"); dev_info(&adapter->pdev->dev, "Firmware flashed successfully\n");
be_fw_exit:
return status;
}
int be_load_fw(struct be_adapter *adapter, u8 *fw_file)
{
const struct firmware *fw;
int status;
if (!netif_running(adapter->netdev)) {
dev_err(&adapter->pdev->dev,
"Firmware load not allowed (interface is down)\n");
return -1;
}
status = request_firmware(&fw, fw_file, &adapter->pdev->dev);
if (status)
goto fw_exit;
dev_info(&adapter->pdev->dev, "Flashing firmware file %s\n", fw_file);
if (lancer_chip(adapter))
status = lancer_fw_download(adapter, fw);
else
status = be_fw_download(adapter, fw);
fw_exit: fw_exit:
release_firmware(fw); release_firmware(fw);
return status; return status;
......
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