mirror of
https://github.com/torvalds/linux.git
synced 2024-12-06 19:11:31 +00:00
be2net: FW download for Lancer
Added implementation of FW download feature for Lancer. Signed-off-by: Shripad Nunjundarao <shripad.nunjundarao@emulex.com> Signed-off-by: Sevin Xavier <selvin.xavier@emulex.com> Signed-off-by: Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
005d569600
commit
485bf569ba
@ -71,7 +71,8 @@ static int be_mcc_compl_process(struct be_adapter *adapter,
|
||||
compl_status = (compl->status >> CQE_STATUS_COMPL_SHIFT) &
|
||||
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)) {
|
||||
adapter->flash_status = compl_status;
|
||||
complete(&adapter->flash_compl);
|
||||
@ -1801,6 +1802,81 @@ err:
|
||||
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,
|
||||
u32 flash_type, u32 flash_opcode, u32 buf_size)
|
||||
{
|
||||
|
@ -193,6 +193,7 @@ struct be_mcc_mailbox {
|
||||
#define OPCODE_COMMON_GET_PHY_DETAILS 102
|
||||
#define OPCODE_COMMON_SET_DRIVER_FUNCTION_CAP 103
|
||||
#define OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES 121
|
||||
#define OPCODE_COMMON_WRITE_OBJECT 172
|
||||
|
||||
#define OPCODE_ETH_RSS_CONFIG 1
|
||||
#define OPCODE_ETH_ACPI_CONFIG 2
|
||||
@ -1131,6 +1132,36 @@ struct be_cmd_write_flashrom {
|
||||
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 *******************************/
|
||||
struct be_cmd_req_acpi_wol_magic_config{
|
||||
struct be_cmd_req_hdr hdr;
|
||||
@ -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,
|
||||
struct be_dma_mem *cmd, u32 flash_oper,
|
||||
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 offset);
|
||||
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,
|
||||
"cmd to write to flash rom failed.\n");
|
||||
return -1;
|
||||
}
|
||||
yield();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@ -2730,32 +2729,98 @@ static int get_ufigen_type(struct flash_file_hdr_g2 *fhdr)
|
||||
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)
|
||||
{
|
||||
#define LANCER_FW_DOWNLOAD_CHUNK (32 * 1024)
|
||||
#define LANCER_FW_DOWNLOAD_LOCATION "/prg"
|
||||
struct be_dma_mem flash_cmd;
|
||||
struct lancer_cmd_req_write_object *req;
|
||||
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 (!IS_ALIGNED(fw->size, sizeof(u32))) {
|
||||
dev_err(&adapter->pdev->dev,
|
||||
"FW Image not properly aligned. "
|
||||
"Length must be 4 byte aligned.\n");
|
||||
status = -EINVAL;
|
||||
goto lancer_fw_exit;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (status)
|
||||
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)
|
||||
{
|
||||
char fw_file[ETHTOOL_FLASH_MAX_FILENAME];
|
||||
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;
|
||||
int status, i = 0, num_imgs = 0;
|
||||
const u8 *p;
|
||||
|
||||
if (!netif_running(adapter->netdev)) {
|
||||
dev_err(&adapter->pdev->dev,
|
||||
"Firmware load not allowed (interface is down)\n");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
strcpy(fw_file, func);
|
||||
|
||||
status = request_firmware(&fw, fw_file, &adapter->pdev->dev);
|
||||
if (status)
|
||||
goto fw_exit;
|
||||
int status = 0, i = 0, num_imgs = 0;
|
||||
|
||||
p = fw->data;
|
||||
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.va = dma_alloc_coherent(&adapter->pdev->dev, flash_cmd.size,
|
||||
@ -2764,7 +2829,7 @@ int be_load_fw(struct be_adapter *adapter, u8 *func)
|
||||
status = -ENOMEM;
|
||||
dev_err(&adapter->pdev->dev,
|
||||
"Memory allocation failure while flashing\n");
|
||||
goto fw_exit;
|
||||
goto be_fw_exit;
|
||||
}
|
||||
|
||||
if ((adapter->generation == BE_GEN3) &&
|
||||
@ -2792,11 +2857,37 @@ int be_load_fw(struct be_adapter *adapter, u8 *func)
|
||||
flash_cmd.dma);
|
||||
if (status) {
|
||||
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");
|
||||
|
||||
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:
|
||||
release_firmware(fw);
|
||||
return status;
|
||||
|
Loading…
Reference in New Issue
Block a user