mirror of
https://github.com/Dasharo/linux.git
synced 2026-03-06 15:25:10 -08:00
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: Sony Chacko <sony.chacko@qlogic.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
629263acae
commit
81d0aeb0a4
@@ -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 *);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user