qlcnic: FW dump support
Added code to take FW dump.
o Driver queries FW at the init time and gets the dump template
o It takes FW dump as per the dump template
o Level of FW dump (and its size) is configured via dump flag
Signed-off-by: Sritej Velaga <sritej.velaga@qlogic.com>
Signed-off-by: Anirban Chakraborty <anirban.chakraborty@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h
index f729363..689adea 100644
--- a/drivers/net/qlcnic/qlcnic.h
+++ b/drivers/net/qlcnic/qlcnic.h
@@ -411,6 +411,29 @@
u32 timer_out;
};
+struct qlcnic_dump_template_hdr {
+ __le32 type;
+ __le32 offset;
+ __le32 size;
+ __le32 cap_mask;
+ __le32 num_entries;
+ __le32 version;
+ __le32 timestamp;
+ __le32 checksum;
+ __le32 drv_cap_mask;
+ __le32 sys_info[3];
+ __le32 saved_state[16];
+ __le32 cap_sizes[8];
+ __le32 rsvd[0];
+};
+
+struct qlcnic_fw_dump {
+ u8 clr; /* flag to indicate if dump is cleared */
+ u32 size; /* total size of the dump */
+ void *data; /* dump data area */
+ struct qlcnic_dump_template_hdr *tmpl_hdr;
+};
+
/*
* One hardware_context{} per adapter
* contains interrupt info as well shared hardware info.
@@ -431,6 +454,7 @@
u16 board_type;
struct qlcnic_nic_intr_coalesce coal;
+ struct qlcnic_fw_dump fw_dump;
};
struct qlcnic_adapter_stats {
@@ -574,6 +598,8 @@
#define QLCNIC_CDRP_CMD_GET_ESWITCH_PORT_CONFIG 0x00000029
#define QLCNIC_CDRP_CMD_GET_ESWITCH_STATS 0x0000002a
#define QLCNIC_CDRP_CMD_CONFIG_PORT 0x0000002E
+#define QLCNIC_CDRP_CMD_TEMP_SIZE 0x0000002f
+#define QLCNIC_CDRP_CMD_GET_TEMP_HDR 0x00000030
#define QLCNIC_RCODE_SUCCESS 0
#define QLCNIC_RCODE_NOT_SUPPORTED 9
@@ -1157,6 +1183,152 @@
struct __qlcnic_esw_statistics tx;
};
+struct qlcnic_common_entry_hdr {
+ __le32 type;
+ __le32 offset;
+ __le32 cap_size;
+ u8 mask;
+ u8 rsvd[2];
+ u8 flags;
+} __packed;
+
+struct __crb {
+ __le32 addr;
+ u8 stride;
+ u8 rsvd1[3];
+ __le32 data_size;
+ __le32 no_ops;
+ __le32 rsvd2[4];
+} __packed;
+
+struct __ctrl {
+ __le32 addr;
+ u8 stride;
+ u8 index_a;
+ __le16 timeout;
+ __le32 data_size;
+ __le32 no_ops;
+ u8 opcode;
+ u8 index_v;
+ u8 shl_val;
+ u8 shr_val;
+ __le32 val1;
+ __le32 val2;
+ __le32 val3;
+} __packed;
+
+struct __cache {
+ __le32 addr;
+ u8 stride;
+ u8 rsvd;
+ __le16 init_tag_val;
+ __le32 size;
+ __le32 no_ops;
+ __le32 ctrl_addr;
+ __le32 ctrl_val;
+ __le32 read_addr;
+ u8 read_addr_stride;
+ u8 read_addr_num;
+ u8 rsvd1[2];
+} __packed;
+
+struct __ocm {
+ u8 rsvd[8];
+ __le32 size;
+ __le32 no_ops;
+ u8 rsvd1[8];
+ __le32 read_addr;
+ __le32 read_addr_stride;
+} __packed;
+
+struct __mem {
+ u8 rsvd[24];
+ __le32 addr;
+ __le32 size;
+} __packed;
+
+struct __mux {
+ __le32 addr;
+ u8 rsvd[4];
+ __le32 size;
+ __le32 no_ops;
+ __le32 val;
+ __le32 val_stride;
+ __le32 read_addr;
+ u8 rsvd2[4];
+} __packed;
+
+struct __queue {
+ __le32 sel_addr;
+ __le16 stride;
+ u8 rsvd[2];
+ __le32 size;
+ __le32 no_ops;
+ u8 rsvd2[8];
+ __le32 read_addr;
+ u8 read_addr_stride;
+ u8 read_addr_cnt;
+ u8 rsvd3[2];
+} __packed;
+
+struct qlcnic_dump_entry {
+ struct qlcnic_common_entry_hdr hdr;
+ union {
+ struct __crb crb;
+ struct __cache cache;
+ struct __ocm ocm;
+ struct __mem mem;
+ struct __mux mux;
+ struct __queue que;
+ struct __ctrl ctrl;
+ } region;
+} __packed;
+
+enum op_codes {
+ QLCNIC_DUMP_NOP = 0,
+ QLCNIC_DUMP_READ_CRB = 1,
+ QLCNIC_DUMP_READ_MUX = 2,
+ QLCNIC_DUMP_QUEUE = 3,
+ QLCNIC_DUMP_BRD_CONFIG = 4,
+ QLCNIC_DUMP_READ_OCM = 6,
+ QLCNIC_DUMP_PEG_REG = 7,
+ QLCNIC_DUMP_L1_DTAG = 8,
+ QLCNIC_DUMP_L1_ITAG = 9,
+ QLCNIC_DUMP_L1_DATA = 11,
+ QLCNIC_DUMP_L1_INST = 12,
+ QLCNIC_DUMP_L2_DTAG = 21,
+ QLCNIC_DUMP_L2_ITAG = 22,
+ QLCNIC_DUMP_L2_DATA = 23,
+ QLCNIC_DUMP_L2_INST = 24,
+ QLCNIC_DUMP_READ_ROM = 71,
+ QLCNIC_DUMP_READ_MEM = 72,
+ QLCNIC_DUMP_READ_CTRL = 98,
+ QLCNIC_DUMP_TLHDR = 99,
+ QLCNIC_DUMP_RDEND = 255
+};
+
+#define QLCNIC_DUMP_WCRB BIT_0
+#define QLCNIC_DUMP_RWCRB BIT_1
+#define QLCNIC_DUMP_ANDCRB BIT_2
+#define QLCNIC_DUMP_ORCRB BIT_3
+#define QLCNIC_DUMP_POLLCRB BIT_4
+#define QLCNIC_DUMP_RD_SAVE BIT_5
+#define QLCNIC_DUMP_WRT_SAVED BIT_6
+#define QLCNIC_DUMP_MOD_SAVE_ST BIT_7
+#define QLCNIC_DUMP_SKIP BIT_7
+
+#define QLCNIC_DUMP_MASK_MIN 3
+#define QLCNIC_DUMP_MASK_DEF 0x0f
+#define QLCNIC_DUMP_MASK_MAX 0xff
+#define QLCNIC_FORCE_FW_DUMP_KEY 0xdeadfeed
+
+struct qlcnic_dump_operations {
+ enum op_codes opcode;
+ u32 (*handler)(struct qlcnic_adapter *,
+ struct qlcnic_dump_entry *, u32 *);
+};
+
+int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter);
int qlcnic_fw_cmd_set_port(struct qlcnic_adapter *adapter, u32 config);
u32 qlcnic_hw_read_wx_2M(struct qlcnic_adapter *adapter, ulong off);
@@ -1203,6 +1375,7 @@
int qlcnic_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate);
void qlcnic_prune_lb_filters(struct qlcnic_adapter *adapter);
void qlcnic_delete_lb_filters(struct qlcnic_adapter *adapter);
+int qlcnic_dump_fw(struct qlcnic_adapter *);
/* Functions from qlcnic_init.c */
int qlcnic_load_firmware(struct qlcnic_adapter *adapter);
@@ -1213,7 +1386,7 @@
int qlcnic_setup_idc_param(struct qlcnic_adapter *adapter);
int qlcnic_check_flash_fw_ver(struct qlcnic_adapter *adapter);
-int qlcnic_rom_fast_read(struct qlcnic_adapter *adapter, int addr, int *valp);
+int qlcnic_rom_fast_read(struct qlcnic_adapter *adapter, u32 addr, u32 *valp);
int qlcnic_rom_fast_read_words(struct qlcnic_adapter *adapter, int addr,
u8 *bytes, size_t size);
int qlcnic_alloc_sw_resources(struct qlcnic_adapter *adapter);
@@ -1265,6 +1438,7 @@
netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
int qlcnic_validate_max_rss(struct net_device *netdev, u8 max_hw, u8 val);
int qlcnic_set_max_rss(struct qlcnic_adapter *adapter, u8 data);
+void qlcnic_dev_request_reset(struct qlcnic_adapter *);
/* Management functions */
int qlcnic_get_mac_address(struct qlcnic_adapter *, u8*);