Skip to content

Commit

Permalink
qlcnic: flash template based firmware reset recovery
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Sony Chacko authored and davem330 committed Jan 2, 2013
1 parent 629263a commit 81d0aeb
Show file tree
Hide file tree
Showing 5 changed files with 538 additions and 0 deletions.
1 change: 1 addition & 0 deletions drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
40 changes: 40 additions & 0 deletions drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
17 changes: 17 additions & 0 deletions drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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
Expand Down Expand Up @@ -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 *);
Expand Down

0 comments on commit 81d0aeb

Please sign in to comment.