Commit 81d0aeb0 authored by Sony Chacko's avatar Sony Chacko Committed by David S. Miller

qlcnic: flash template based firmware reset recovery

Flash template provides instructions to stop, restart and initalize the
firmware. These instructions are abstracted as a series of read, write and
poll operations on hardware registers. Register information and operation
specifics are not exposed to the driver. Driver reads the template from
flash and executes the instructions located at pre-defined offsets.

Template based firmware reset recovery and initialization mechanism minimize
driver changes as firmware evolves.
Signed-off-by: default avatarSony Chacko <sony.chacko@qlogic.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 629263ac
......@@ -442,6 +442,7 @@ struct qlcnic_hardware_context {
struct qlcnic_nic_intr_coalesce coal;
struct qlcnic_fw_dump fw_dump;
struct qlcnic_fdt fdt;
struct qlc_83xx_reset reset;
struct qlc_83xx_idc idc;
struct qlc_83xx_fw_info fw_info;
struct qlcnic_intrpt_config *intr_tbl;
......
......@@ -2343,3 +2343,43 @@ int qlcnic_83xx_ms_mem_write128(struct qlcnic_adapter *adapter, u64 addr,
return ret;
}
int qlcnic_83xx_flash_read32(struct qlcnic_adapter *adapter, u32 flash_addr,
u8 *p_data, int count)
{
int i, ret;
u32 word, addr = flash_addr;
ulong indirect_addr;
if (qlcnic_83xx_lock_flash(adapter) != 0)
return -EIO;
if (addr & 0x3) {
dev_err(&adapter->pdev->dev, "Illegal addr = 0x%x\n", addr);
qlcnic_83xx_unlock_flash(adapter);
return -EIO;
}
for (i = 0; i < count; i++) {
if (qlcnic_83xx_wrt_reg_indirect(adapter,
QLC_83XX_FLASH_DIRECT_WINDOW,
(addr))) {
qlcnic_83xx_unlock_flash(adapter);
return -EIO;
}
indirect_addr = QLC_83XX_FLASH_DIRECT_DATA(addr);
ret = qlcnic_83xx_rd_reg_indirect(adapter,
indirect_addr);
if (ret == -EIO)
return -EIO;
word = ret;
*p_data = word;
p_data = p_data + 4;
addr = addr + 4;
}
qlcnic_83xx_unlock_flash(adapter);
return 0;
}
......@@ -77,6 +77,8 @@
#define QLC_83XX_BOOT_FROM_FLASH 0
#define QLC_83XX_BOOT_FROM_FILE 0x12345678
#define QLC_83XX_MAX_RESET_SEQ_ENTRIES 16
struct qlcnic_intrpt_config {
u8 type;
u8 enabled;
......@@ -98,6 +100,20 @@ struct qlc_83xx_fw_info {
u8 load_from_file;
};
struct qlc_83xx_reset {
struct qlc_83xx_reset_hdr *hdr;
int seq_index;
int seq_error;
int array_index;
u32 array[QLC_83XX_MAX_RESET_SEQ_ENTRIES];
u8 *buff;
u8 *stop_offset;
u8 *start_offset;
u8 *init_offset;
u8 seq_end;
u8 template_end;
};
#define QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY 0x1
#define QLC_83XX_IDC_GRACEFULL_RESET 0x2
#define QLC_83XX_IDC_TIMESTAMP 0
......@@ -377,6 +393,7 @@ int qlcnic_83xx_init(struct qlcnic_adapter *);
int qlcnic_83xx_idc_ready_state_entry(struct qlcnic_adapter *);
int qlcnic_83xx_check_hw_status(struct qlcnic_adapter *p_dev);
void qlcnic_83xx_idc_poll_dev_state(struct work_struct *);
int qlcnic_83xx_get_reset_instruction_template(struct qlcnic_adapter *);
void qlcnic_83xx_idc_exit(struct qlcnic_adapter *);
void qlcnic_83xx_idc_request_reset(struct qlcnic_adapter *, u32);
int qlcnic_83xx_lock_driver(struct qlcnic_adapter *);
......
......@@ -1473,6 +1473,7 @@ static void qlcnic_free_adapter_resources(struct qlcnic_adapter *adapter)
adapter->ahw->fw_dump.tmpl_hdr = NULL;
}
kfree(adapter->ahw->reset.buff);
adapter->ahw->fw_dump.tmpl_hdr = NULL;
}
......
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