aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/qlogic
diff options
context:
space:
mode:
authorShahed Shaikh <shahed.shaikh@qlogic.com>2014-02-21 13:20:10 -0500
committerDavid S. Miller <davem@davemloft.net>2014-02-24 18:43:19 -0500
commit225837a076b284ac408a3b0104584ae0ad117a0c (patch)
tree406d15ae01fd9e27f9d3d69c2663841a4ba344fd /drivers/net/ethernet/qlogic
parenta1991c749a7bfacb766a056aff11864216670dd6 (diff)
qlcnic: Re-factor firmware minidump template header handling
Treat firmware minidump template headers for 82xx and 83xx/84xx adapters separately, as it may change for 82xx and 83xx/84xx adapter type independently. Signed-off-by: Shahed Shaikh <shahed.shaikh@qlogic.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/qlogic')
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic.h73
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c7
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h8
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c17
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h8
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c7
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c233
7 files changed, 287 insertions, 66 deletions
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
index f19f81cde134..6ad1bcebc0fe 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
@@ -394,7 +394,7 @@ struct qlcnic_nic_intr_coalesce {
394 u32 timer_out; 394 u32 timer_out;
395}; 395};
396 396
397struct qlcnic_dump_template_hdr { 397struct qlcnic_83xx_dump_template_hdr {
398 u32 type; 398 u32 type;
399 u32 offset; 399 u32 offset;
400 u32 size; 400 u32 size;
@@ -411,15 +411,42 @@ struct qlcnic_dump_template_hdr {
411 u32 rsvd[0]; 411 u32 rsvd[0];
412}; 412};
413 413
414struct qlcnic_82xx_dump_template_hdr {
415 u32 type;
416 u32 offset;
417 u32 size;
418 u32 cap_mask;
419 u32 num_entries;
420 u32 version;
421 u32 timestamp;
422 u32 checksum;
423 u32 drv_cap_mask;
424 u32 sys_info[3];
425 u32 saved_state[16];
426 u32 cap_sizes[8];
427 u32 rsvd[7];
428 u32 capabilities;
429 u32 rsvd1[0];
430};
431
414struct qlcnic_fw_dump { 432struct qlcnic_fw_dump {
415 u8 clr; /* flag to indicate if dump is cleared */ 433 u8 clr; /* flag to indicate if dump is cleared */
416 bool enable; /* enable/disable dump */ 434 bool enable; /* enable/disable dump */
417 u32 size; /* total size of the dump */ 435 u32 size; /* total size of the dump */
436 u32 cap_mask; /* Current capture mask */
418 void *data; /* dump data area */ 437 void *data; /* dump data area */
419 struct qlcnic_dump_template_hdr *tmpl_hdr; 438 void *tmpl_hdr;
420 dma_addr_t phys_addr; 439 dma_addr_t phys_addr;
421 void *dma_buffer; 440 void *dma_buffer;
422 bool use_pex_dma; 441 bool use_pex_dma;
442 /* Read only elements which are common between 82xx and 83xx
443 * template header. Update these values immediately after we read
444 * template header from Firmware
445 */
446 u32 tmpl_hdr_size;
447 u32 version;
448 u32 num_entries;
449 u32 offset;
423}; 450};
424 451
425/* 452/*
@@ -1769,6 +1796,12 @@ struct qlcnic_hardware_ops {
1769 struct qlcnic_host_tx_ring *); 1796 struct qlcnic_host_tx_ring *);
1770 void (*disable_tx_intr) (struct qlcnic_adapter *, 1797 void (*disable_tx_intr) (struct qlcnic_adapter *,
1771 struct qlcnic_host_tx_ring *); 1798 struct qlcnic_host_tx_ring *);
1799 u32 (*get_saved_state)(void *, u32);
1800 void (*set_saved_state)(void *, u32, u32);
1801 void (*cache_tmpl_hdr_values)(struct qlcnic_fw_dump *);
1802 u32 (*get_cap_size)(void *, int);
1803 void (*set_sys_info)(void *, int, u32);
1804 void (*store_cap_mask)(void *, u32);
1772}; 1805};
1773 1806
1774extern struct qlcnic_nic_template qlcnic_vf_ops; 1807extern struct qlcnic_nic_template qlcnic_vf_ops;
@@ -2007,6 +2040,42 @@ static inline void qlcnic_read_phys_port_id(struct qlcnic_adapter *adapter)
2007 adapter->ahw->hw_ops->read_phys_port_id(adapter); 2040 adapter->ahw->hw_ops->read_phys_port_id(adapter);
2008} 2041}
2009 2042
2043static inline u32 qlcnic_get_saved_state(struct qlcnic_adapter *adapter,
2044 void *t_hdr, u32 index)
2045{
2046 return adapter->ahw->hw_ops->get_saved_state(t_hdr, index);
2047}
2048
2049static inline void qlcnic_set_saved_state(struct qlcnic_adapter *adapter,
2050 void *t_hdr, u32 index, u32 value)
2051{
2052 adapter->ahw->hw_ops->set_saved_state(t_hdr, index, value);
2053}
2054
2055static inline void qlcnic_cache_tmpl_hdr_values(struct qlcnic_adapter *adapter,
2056 struct qlcnic_fw_dump *fw_dump)
2057{
2058 adapter->ahw->hw_ops->cache_tmpl_hdr_values(fw_dump);
2059}
2060
2061static inline u32 qlcnic_get_cap_size(struct qlcnic_adapter *adapter,
2062 void *tmpl_hdr, int index)
2063{
2064 return adapter->ahw->hw_ops->get_cap_size(tmpl_hdr, index);
2065}
2066
2067static inline void qlcnic_set_sys_info(struct qlcnic_adapter *adapter,
2068 void *tmpl_hdr, int idx, u32 value)
2069{
2070 adapter->ahw->hw_ops->set_sys_info(tmpl_hdr, idx, value);
2071}
2072
2073static inline void qlcnic_store_cap_mask(struct qlcnic_adapter *adapter,
2074 void *tmpl_hdr, u32 mask)
2075{
2076 adapter->ahw->hw_ops->store_cap_mask(tmpl_hdr, mask);
2077}
2078
2010static inline void qlcnic_dev_request_reset(struct qlcnic_adapter *adapter, 2079static inline void qlcnic_dev_request_reset(struct qlcnic_adapter *adapter,
2011 u32 key) 2080 u32 key)
2012{ 2081{
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
index 4146664d4d6a..0f39778e0e5b 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
@@ -203,7 +203,12 @@ static struct qlcnic_hardware_ops qlcnic_83xx_hw_ops = {
203 .disable_sds_intr = qlcnic_83xx_disable_sds_intr, 203 .disable_sds_intr = qlcnic_83xx_disable_sds_intr,
204 .enable_tx_intr = qlcnic_83xx_enable_tx_intr, 204 .enable_tx_intr = qlcnic_83xx_enable_tx_intr,
205 .disable_tx_intr = qlcnic_83xx_disable_tx_intr, 205 .disable_tx_intr = qlcnic_83xx_disable_tx_intr,
206 206 .get_saved_state = qlcnic_83xx_get_saved_state,
207 .set_saved_state = qlcnic_83xx_set_saved_state,
208 .cache_tmpl_hdr_values = qlcnic_83xx_cache_tmpl_hdr_values,
209 .get_cap_size = qlcnic_83xx_get_cap_size,
210 .set_sys_info = qlcnic_83xx_set_sys_info,
211 .store_cap_mask = qlcnic_83xx_store_cap_mask,
207}; 212};
208 213
209static struct qlcnic_nic_template qlcnic_83xx_ops = { 214static struct qlcnic_nic_template qlcnic_83xx_ops = {
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
index f92485ca21d1..81c1889f6f3e 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
@@ -308,6 +308,8 @@ struct qlc_83xx_reset {
308#define QLC_83XX_IDC_FLASH_PARAM_ADDR 0x3e8020 308#define QLC_83XX_IDC_FLASH_PARAM_ADDR 0x3e8020
309 309
310struct qlcnic_adapter; 310struct qlcnic_adapter;
311struct qlcnic_fw_dump;
312
311struct qlc_83xx_idc { 313struct qlc_83xx_idc {
312 int (*state_entry) (struct qlcnic_adapter *); 314 int (*state_entry) (struct qlcnic_adapter *);
313 u64 sec_counter; 315 u64 sec_counter;
@@ -650,4 +652,10 @@ int qlcnic_83xx_check_vnic_state(struct qlcnic_adapter *);
650void qlcnic_83xx_aer_stop_poll_work(struct qlcnic_adapter *); 652void qlcnic_83xx_aer_stop_poll_work(struct qlcnic_adapter *);
651int qlcnic_83xx_aer_reset(struct qlcnic_adapter *); 653int qlcnic_83xx_aer_reset(struct qlcnic_adapter *);
652void qlcnic_83xx_aer_start_poll_work(struct qlcnic_adapter *); 654void qlcnic_83xx_aer_start_poll_work(struct qlcnic_adapter *);
655u32 qlcnic_83xx_get_saved_state(void *, u32);
656void qlcnic_83xx_set_saved_state(void *, u32, u32);
657void qlcnic_83xx_cache_tmpl_hdr_values(struct qlcnic_fw_dump *);
658u32 qlcnic_83xx_get_cap_size(void *, int);
659void qlcnic_83xx_set_sys_info(void *, int, u32);
660void qlcnic_83xx_store_cap_mask(void *, u32);
653#endif 661#endif
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
index acee1a5d80c6..1960609481ce 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
@@ -1639,14 +1639,14 @@ qlcnic_get_dump_flag(struct net_device *netdev, struct ethtool_dump *dump)
1639 } 1639 }
1640 1640
1641 if (fw_dump->clr) 1641 if (fw_dump->clr)
1642 dump->len = fw_dump->tmpl_hdr->size + fw_dump->size; 1642 dump->len = fw_dump->tmpl_hdr_size + fw_dump->size;
1643 else 1643 else
1644 dump->len = 0; 1644 dump->len = 0;
1645 1645
1646 if (!qlcnic_check_fw_dump_state(adapter)) 1646 if (!qlcnic_check_fw_dump_state(adapter))
1647 dump->flag = ETH_FW_DUMP_DISABLE; 1647 dump->flag = ETH_FW_DUMP_DISABLE;
1648 else 1648 else
1649 dump->flag = fw_dump->tmpl_hdr->drv_cap_mask; 1649 dump->flag = fw_dump->cap_mask;
1650 1650
1651 dump->version = adapter->fw_version; 1651 dump->version = adapter->fw_version;
1652 return 0; 1652 return 0;
@@ -1671,9 +1671,10 @@ qlcnic_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump,
1671 netdev_info(netdev, "Dump not available\n"); 1671 netdev_info(netdev, "Dump not available\n");
1672 return -EINVAL; 1672 return -EINVAL;
1673 } 1673 }
1674
1674 /* Copy template header first */ 1675 /* Copy template header first */
1675 copy_sz = fw_dump->tmpl_hdr->size; 1676 copy_sz = fw_dump->tmpl_hdr_size;
1676 hdr_ptr = (u32 *) fw_dump->tmpl_hdr; 1677 hdr_ptr = (u32 *)fw_dump->tmpl_hdr;
1677 data = buffer; 1678 data = buffer;
1678 for (i = 0; i < copy_sz/sizeof(u32); i++) 1679 for (i = 0; i < copy_sz/sizeof(u32); i++)
1679 *data++ = cpu_to_le32(*hdr_ptr++); 1680 *data++ = cpu_to_le32(*hdr_ptr++);
@@ -1681,7 +1682,7 @@ qlcnic_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump,
1681 /* Copy captured dump data */ 1682 /* Copy captured dump data */
1682 memcpy(buffer + copy_sz, fw_dump->data, fw_dump->size); 1683 memcpy(buffer + copy_sz, fw_dump->data, fw_dump->size);
1683 dump->len = copy_sz + fw_dump->size; 1684 dump->len = copy_sz + fw_dump->size;
1684 dump->flag = fw_dump->tmpl_hdr->drv_cap_mask; 1685 dump->flag = fw_dump->cap_mask;
1685 1686
1686 /* Free dump area once data has been captured */ 1687 /* Free dump area once data has been captured */
1687 vfree(fw_dump->data); 1688 vfree(fw_dump->data);
@@ -1703,7 +1704,11 @@ static int qlcnic_set_dump_mask(struct qlcnic_adapter *adapter, u32 mask)
1703 return -EOPNOTSUPP; 1704 return -EOPNOTSUPP;
1704 } 1705 }
1705 1706
1706 fw_dump->tmpl_hdr->drv_cap_mask = mask; 1707 fw_dump->cap_mask = mask;
1708
1709 /* Store new capture mask in template header as well*/
1710 qlcnic_store_cap_mask(adapter, fw_dump->tmpl_hdr, mask);
1711
1707 netdev_info(netdev, "Driver mask changed to: 0x%x\n", mask); 1712 netdev_info(netdev, "Driver mask changed to: 0x%x\n", mask);
1708 return 0; 1713 return 0;
1709} 1714}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h
index 63d75617d445..576b301b11ef 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h
@@ -161,6 +161,7 @@ struct qlcnic_host_sds_ring;
161struct qlcnic_host_tx_ring; 161struct qlcnic_host_tx_ring;
162struct qlcnic_hardware_context; 162struct qlcnic_hardware_context;
163struct qlcnic_adapter; 163struct qlcnic_adapter;
164struct qlcnic_fw_dump;
164 165
165int qlcnic_82xx_hw_read_wx_2M(struct qlcnic_adapter *adapter, ulong, int *); 166int qlcnic_82xx_hw_read_wx_2M(struct qlcnic_adapter *adapter, ulong, int *);
166int qlcnic_82xx_hw_write_wx_2M(struct qlcnic_adapter *, ulong, u32); 167int qlcnic_82xx_hw_write_wx_2M(struct qlcnic_adapter *, ulong, u32);
@@ -213,4 +214,11 @@ int qlcnic_82xx_shutdown(struct pci_dev *);
213int qlcnic_82xx_resume(struct qlcnic_adapter *); 214int qlcnic_82xx_resume(struct qlcnic_adapter *);
214void qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter, u8 failed); 215void qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter, u8 failed);
215void qlcnic_fw_poll_work(struct work_struct *work); 216void qlcnic_fw_poll_work(struct work_struct *work);
217
218u32 qlcnic_82xx_get_saved_state(void *, u32);
219void qlcnic_82xx_set_saved_state(void *, u32, u32);
220void qlcnic_82xx_cache_tmpl_hdr_values(struct qlcnic_fw_dump *);
221u32 qlcnic_82xx_get_cap_size(void *, int);
222void qlcnic_82xx_set_sys_info(void *, int, u32);
223void qlcnic_82xx_store_cap_mask(void *, u32);
216#endif /* __QLCNIC_HW_H_ */ 224#endif /* __QLCNIC_HW_H_ */
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index e07fd948d98b..964ba457a7c6 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -90,7 +90,6 @@ static void qlcnic_82xx_io_resume(struct pci_dev *);
90static void qlcnic_82xx_set_mac_filter_count(struct qlcnic_adapter *); 90static void qlcnic_82xx_set_mac_filter_count(struct qlcnic_adapter *);
91static pci_ers_result_t qlcnic_82xx_io_error_detected(struct pci_dev *, 91static pci_ers_result_t qlcnic_82xx_io_error_detected(struct pci_dev *,
92 pci_channel_state_t); 92 pci_channel_state_t);
93
94static u32 qlcnic_vlan_tx_check(struct qlcnic_adapter *adapter) 93static u32 qlcnic_vlan_tx_check(struct qlcnic_adapter *adapter)
95{ 94{
96 struct qlcnic_hardware_context *ahw = adapter->ahw; 95 struct qlcnic_hardware_context *ahw = adapter->ahw;
@@ -561,6 +560,12 @@ static struct qlcnic_hardware_ops qlcnic_hw_ops = {
561 .disable_sds_intr = qlcnic_82xx_disable_sds_intr, 560 .disable_sds_intr = qlcnic_82xx_disable_sds_intr,
562 .enable_tx_intr = qlcnic_82xx_enable_tx_intr, 561 .enable_tx_intr = qlcnic_82xx_enable_tx_intr,
563 .disable_tx_intr = qlcnic_82xx_disable_tx_intr, 562 .disable_tx_intr = qlcnic_82xx_disable_tx_intr,
563 .get_saved_state = qlcnic_82xx_get_saved_state,
564 .set_saved_state = qlcnic_82xx_set_saved_state,
565 .cache_tmpl_hdr_values = qlcnic_82xx_cache_tmpl_hdr_values,
566 .get_cap_size = qlcnic_82xx_get_cap_size,
567 .set_sys_info = qlcnic_82xx_set_sys_info,
568 .store_cap_mask = qlcnic_82xx_store_cap_mask,
564}; 569};
565 570
566static int qlcnic_check_multi_tx_capability(struct qlcnic_adapter *adapter) 571static int qlcnic_check_multi_tx_capability(struct qlcnic_adapter *adapter)
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c
index 7763962e2ec4..37b979b1266b 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c
@@ -211,6 +211,107 @@ enum qlcnic_minidump_opcode {
211 QLCNIC_DUMP_RDEND = 255 211 QLCNIC_DUMP_RDEND = 255
212}; 212};
213 213
214inline u32 qlcnic_82xx_get_saved_state(void *t_hdr, u32 index)
215{
216 struct qlcnic_82xx_dump_template_hdr *hdr = t_hdr;
217
218 return hdr->saved_state[index];
219}
220
221inline void qlcnic_82xx_set_saved_state(void *t_hdr, u32 index,
222 u32 value)
223{
224 struct qlcnic_82xx_dump_template_hdr *hdr = t_hdr;
225
226 hdr->saved_state[index] = value;
227}
228
229void qlcnic_82xx_cache_tmpl_hdr_values(struct qlcnic_fw_dump *fw_dump)
230{
231 struct qlcnic_82xx_dump_template_hdr *hdr;
232
233 hdr = fw_dump->tmpl_hdr;
234 fw_dump->tmpl_hdr_size = hdr->size;
235 fw_dump->version = hdr->version;
236 fw_dump->num_entries = hdr->num_entries;
237 fw_dump->offset = hdr->offset;
238
239 hdr->drv_cap_mask = hdr->cap_mask;
240 fw_dump->cap_mask = hdr->cap_mask;
241}
242
243inline u32 qlcnic_82xx_get_cap_size(void *t_hdr, int index)
244{
245 struct qlcnic_82xx_dump_template_hdr *hdr = t_hdr;
246
247 return hdr->cap_sizes[index];
248}
249
250void qlcnic_82xx_set_sys_info(void *t_hdr, int idx, u32 value)
251{
252 struct qlcnic_82xx_dump_template_hdr *hdr = t_hdr;
253
254 hdr->sys_info[idx] = value;
255}
256
257void qlcnic_82xx_store_cap_mask(void *tmpl_hdr, u32 mask)
258{
259 struct qlcnic_82xx_dump_template_hdr *hdr = tmpl_hdr;
260
261 hdr->drv_cap_mask = mask;
262}
263
264inline u32 qlcnic_83xx_get_saved_state(void *t_hdr, u32 index)
265{
266 struct qlcnic_83xx_dump_template_hdr *hdr = t_hdr;
267
268 return hdr->saved_state[index];
269}
270
271inline void qlcnic_83xx_set_saved_state(void *t_hdr, u32 index,
272 u32 value)
273{
274 struct qlcnic_83xx_dump_template_hdr *hdr = t_hdr;
275
276 hdr->saved_state[index] = value;
277}
278
279void qlcnic_83xx_cache_tmpl_hdr_values(struct qlcnic_fw_dump *fw_dump)
280{
281 struct qlcnic_83xx_dump_template_hdr *hdr;
282
283 hdr = fw_dump->tmpl_hdr;
284 fw_dump->tmpl_hdr_size = hdr->size;
285 fw_dump->version = hdr->version;
286 fw_dump->num_entries = hdr->num_entries;
287 fw_dump->offset = hdr->offset;
288
289 hdr->drv_cap_mask = hdr->cap_mask;
290 fw_dump->cap_mask = hdr->cap_mask;
291}
292
293inline u32 qlcnic_83xx_get_cap_size(void *t_hdr, int index)
294{
295 struct qlcnic_83xx_dump_template_hdr *hdr = t_hdr;
296
297 return hdr->cap_sizes[index];
298}
299
300void qlcnic_83xx_set_sys_info(void *t_hdr, int idx, u32 value)
301{
302 struct qlcnic_83xx_dump_template_hdr *hdr = t_hdr;
303
304 hdr->sys_info[idx] = value;
305}
306
307void qlcnic_83xx_store_cap_mask(void *tmpl_hdr, u32 mask)
308{
309 struct qlcnic_83xx_dump_template_hdr *hdr;
310
311 hdr = tmpl_hdr;
312 hdr->drv_cap_mask = mask;
313}
314
214struct qlcnic_dump_operations { 315struct qlcnic_dump_operations {
215 enum qlcnic_minidump_opcode opcode; 316 enum qlcnic_minidump_opcode opcode;
216 u32 (*handler)(struct qlcnic_adapter *, struct qlcnic_dump_entry *, 317 u32 (*handler)(struct qlcnic_adapter *, struct qlcnic_dump_entry *,
@@ -238,11 +339,11 @@ static u32 qlcnic_dump_crb(struct qlcnic_adapter *adapter,
238static u32 qlcnic_dump_ctrl(struct qlcnic_adapter *adapter, 339static u32 qlcnic_dump_ctrl(struct qlcnic_adapter *adapter,
239 struct qlcnic_dump_entry *entry, __le32 *buffer) 340 struct qlcnic_dump_entry *entry, __le32 *buffer)
240{ 341{
342 void *hdr = adapter->ahw->fw_dump.tmpl_hdr;
343 struct __ctrl *ctr = &entry->region.ctrl;
241 int i, k, timeout = 0; 344 int i, k, timeout = 0;
242 u32 addr, data; 345 u32 addr, data, temp;
243 u8 no_ops; 346 u8 no_ops;
244 struct __ctrl *ctr = &entry->region.ctrl;
245 struct qlcnic_dump_template_hdr *t_hdr = adapter->ahw->fw_dump.tmpl_hdr;
246 347
247 addr = ctr->addr; 348 addr = ctr->addr;
248 no_ops = ctr->no_ops; 349 no_ops = ctr->no_ops;
@@ -285,29 +386,42 @@ static u32 qlcnic_dump_ctrl(struct qlcnic_adapter *adapter,
285 } 386 }
286 break; 387 break;
287 case QLCNIC_DUMP_RD_SAVE: 388 case QLCNIC_DUMP_RD_SAVE:
288 if (ctr->index_a) 389 temp = ctr->index_a;
289 addr = t_hdr->saved_state[ctr->index_a]; 390 if (temp)
391 addr = qlcnic_get_saved_state(adapter,
392 hdr,
393 temp);
290 data = qlcnic_ind_rd(adapter, addr); 394 data = qlcnic_ind_rd(adapter, addr);
291 t_hdr->saved_state[ctr->index_v] = data; 395 qlcnic_set_saved_state(adapter, hdr,
396 ctr->index_v, data);
292 break; 397 break;
293 case QLCNIC_DUMP_WRT_SAVED: 398 case QLCNIC_DUMP_WRT_SAVED:
294 if (ctr->index_v) 399 temp = ctr->index_v;
295 data = t_hdr->saved_state[ctr->index_v]; 400 if (temp)
401 data = qlcnic_get_saved_state(adapter,
402 hdr,
403 temp);
296 else 404 else
297 data = ctr->val1; 405 data = ctr->val1;
298 if (ctr->index_a) 406
299 addr = t_hdr->saved_state[ctr->index_a]; 407 temp = ctr->index_a;
408 if (temp)
409 addr = qlcnic_get_saved_state(adapter,
410 hdr,
411 temp);
300 qlcnic_ind_wr(adapter, addr, data); 412 qlcnic_ind_wr(adapter, addr, data);
301 break; 413 break;
302 case QLCNIC_DUMP_MOD_SAVE_ST: 414 case QLCNIC_DUMP_MOD_SAVE_ST:
303 data = t_hdr->saved_state[ctr->index_v]; 415 data = qlcnic_get_saved_state(adapter, hdr,
416 ctr->index_v);
304 data <<= ctr->shl_val; 417 data <<= ctr->shl_val;
305 data >>= ctr->shr_val; 418 data >>= ctr->shr_val;
306 if (ctr->val2) 419 if (ctr->val2)
307 data &= ctr->val2; 420 data &= ctr->val2;
308 data |= ctr->val3; 421 data |= ctr->val3;
309 data += ctr->val1; 422 data += ctr->val1;
310 t_hdr->saved_state[ctr->index_v] = data; 423 qlcnic_set_saved_state(adapter, hdr,
424 ctr->index_v, data);
311 break; 425 break;
312 default: 426 default:
313 dev_info(&adapter->pdev->dev, 427 dev_info(&adapter->pdev->dev,
@@ -544,7 +658,7 @@ out:
544static int qlcnic_start_pex_dma(struct qlcnic_adapter *adapter, 658static int qlcnic_start_pex_dma(struct qlcnic_adapter *adapter,
545 struct __mem *mem) 659 struct __mem *mem)
546{ 660{
547 struct qlcnic_dump_template_hdr *tmpl_hdr; 661 struct qlcnic_83xx_dump_template_hdr *tmpl_hdr;
548 struct device *dev = &adapter->pdev->dev; 662 struct device *dev = &adapter->pdev->dev;
549 u32 dma_no, dma_base_addr, temp_addr; 663 u32 dma_no, dma_base_addr, temp_addr;
550 int i, ret, dma_sts; 664 int i, ret, dma_sts;
@@ -596,7 +710,7 @@ static u32 qlcnic_read_memory_pexdma(struct qlcnic_adapter *adapter,
596 struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump; 710 struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
597 u32 temp, dma_base_addr, size = 0, read_size = 0; 711 u32 temp, dma_base_addr, size = 0, read_size = 0;
598 struct qlcnic_pex_dma_descriptor *dma_descr; 712 struct qlcnic_pex_dma_descriptor *dma_descr;
599 struct qlcnic_dump_template_hdr *tmpl_hdr; 713 struct qlcnic_83xx_dump_template_hdr *tmpl_hdr;
600 struct device *dev = &adapter->pdev->dev; 714 struct device *dev = &adapter->pdev->dev;
601 dma_addr_t dma_phys_addr; 715 dma_addr_t dma_phys_addr;
602 void *dma_buffer; 716 void *dma_buffer;
@@ -938,8 +1052,8 @@ static int
938qlcnic_fw_flash_get_minidump_temp_size(struct qlcnic_adapter *adapter, 1052qlcnic_fw_flash_get_minidump_temp_size(struct qlcnic_adapter *adapter,
939 struct qlcnic_cmd_args *cmd) 1053 struct qlcnic_cmd_args *cmd)
940{ 1054{
941 struct qlcnic_dump_template_hdr tmp_hdr; 1055 struct qlcnic_83xx_dump_template_hdr tmp_hdr;
942 u32 size = sizeof(struct qlcnic_dump_template_hdr) / sizeof(u32); 1056 u32 size = sizeof(tmp_hdr) / sizeof(u32);
943 int ret = 0; 1057 int ret = 0;
944 1058
945 if (qlcnic_82xx_check(adapter)) 1059 if (qlcnic_82xx_check(adapter))
@@ -1027,17 +1141,19 @@ free_mem:
1027 return err; 1141 return err;
1028} 1142}
1029 1143
1144#define QLCNIC_TEMPLATE_VERSION (0x20001)
1145
1030int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter) 1146int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter)
1031{ 1147{
1032 int err;
1033 u32 temp_size = 0;
1034 u32 version, csum, *tmp_buf;
1035 struct qlcnic_hardware_context *ahw; 1148 struct qlcnic_hardware_context *ahw;
1036 struct qlcnic_dump_template_hdr *tmpl_hdr; 1149 struct qlcnic_fw_dump *fw_dump;
1150 u32 version, csum, *tmp_buf;
1037 u8 use_flash_temp = 0; 1151 u8 use_flash_temp = 0;
1152 u32 temp_size = 0;
1153 int err;
1038 1154
1039 ahw = adapter->ahw; 1155 ahw = adapter->ahw;
1040 1156 fw_dump = &ahw->fw_dump;
1041 err = qlcnic_fw_get_minidump_temp_size(adapter, &version, &temp_size, 1157 err = qlcnic_fw_get_minidump_temp_size(adapter, &version, &temp_size,
1042 &use_flash_temp); 1158 &use_flash_temp);
1043 if (err) { 1159 if (err) {
@@ -1046,11 +1162,11 @@ int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter)
1046 return -EIO; 1162 return -EIO;
1047 } 1163 }
1048 1164
1049 ahw->fw_dump.tmpl_hdr = vzalloc(temp_size); 1165 fw_dump->tmpl_hdr = vzalloc(temp_size);
1050 if (!ahw->fw_dump.tmpl_hdr) 1166 if (!fw_dump->tmpl_hdr)
1051 return -ENOMEM; 1167 return -ENOMEM;
1052 1168
1053 tmp_buf = (u32 *)ahw->fw_dump.tmpl_hdr; 1169 tmp_buf = (u32 *)fw_dump->tmpl_hdr;
1054 if (use_flash_temp) 1170 if (use_flash_temp)
1055 goto flash_temp; 1171 goto flash_temp;
1056 1172
@@ -1065,8 +1181,8 @@ flash_temp:
1065 dev_err(&adapter->pdev->dev, 1181 dev_err(&adapter->pdev->dev,
1066 "Failed to get minidump template header %d\n", 1182 "Failed to get minidump template header %d\n",
1067 err); 1183 err);
1068 vfree(ahw->fw_dump.tmpl_hdr); 1184 vfree(fw_dump->tmpl_hdr);
1069 ahw->fw_dump.tmpl_hdr = NULL; 1185 fw_dump->tmpl_hdr = NULL;
1070 return -EIO; 1186 return -EIO;
1071 } 1187 }
1072 } 1188 }
@@ -1076,21 +1192,22 @@ flash_temp:
1076 if (csum) { 1192 if (csum) {
1077 dev_err(&adapter->pdev->dev, 1193 dev_err(&adapter->pdev->dev,
1078 "Template header checksum validation failed\n"); 1194 "Template header checksum validation failed\n");
1079 vfree(ahw->fw_dump.tmpl_hdr); 1195 vfree(fw_dump->tmpl_hdr);
1080 ahw->fw_dump.tmpl_hdr = NULL; 1196 fw_dump->tmpl_hdr = NULL;
1081 return -EIO; 1197 return -EIO;
1082 } 1198 }
1083 1199
1084 tmpl_hdr = ahw->fw_dump.tmpl_hdr; 1200 qlcnic_cache_tmpl_hdr_values(adapter, fw_dump);
1085 tmpl_hdr->drv_cap_mask = tmpl_hdr->cap_mask; 1201
1086 dev_info(&adapter->pdev->dev, 1202 dev_info(&adapter->pdev->dev,
1087 "Default minidump capture mask 0x%x\n", 1203 "Default minidump capture mask 0x%x\n",
1088 tmpl_hdr->cap_mask); 1204 fw_dump->cap_mask);
1089 1205
1090 if ((tmpl_hdr->version & 0xfffff) >= 0x20001) 1206 if (qlcnic_83xx_check(adapter) &&
1091 ahw->fw_dump.use_pex_dma = true; 1207 (fw_dump->version & 0xfffff) >= QLCNIC_TEMPLATE_VERSION)
1208 fw_dump->use_pex_dma = true;
1092 else 1209 else
1093 ahw->fw_dump.use_pex_dma = false; 1210 fw_dump->use_pex_dma = false;
1094 1211
1095 qlcnic_enable_fw_dump_state(adapter); 1212 qlcnic_enable_fw_dump_state(adapter);
1096 1213
@@ -1099,21 +1216,22 @@ flash_temp:
1099 1216
1100int qlcnic_dump_fw(struct qlcnic_adapter *adapter) 1217int qlcnic_dump_fw(struct qlcnic_adapter *adapter)
1101{ 1218{
1102 __le32 *buffer;
1103 u32 ocm_window;
1104 char mesg[64];
1105 char *msg[] = {mesg, NULL};
1106 int i, k, ops_cnt, ops_index, dump_size = 0;
1107 u32 entry_offset, dump, no_entries, buf_offset = 0;
1108 struct qlcnic_dump_entry *entry;
1109 struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump; 1219 struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
1110 struct qlcnic_dump_template_hdr *tmpl_hdr = fw_dump->tmpl_hdr;
1111 static const struct qlcnic_dump_operations *fw_dump_ops; 1220 static const struct qlcnic_dump_operations *fw_dump_ops;
1221 struct qlcnic_83xx_dump_template_hdr *hdr_83xx;
1222 u32 entry_offset, dump, no_entries, buf_offset = 0;
1223 int i, k, ops_cnt, ops_index, dump_size = 0;
1112 struct device *dev = &adapter->pdev->dev; 1224 struct device *dev = &adapter->pdev->dev;
1113 struct qlcnic_hardware_context *ahw; 1225 struct qlcnic_hardware_context *ahw;
1114 void *temp_buffer; 1226 struct qlcnic_dump_entry *entry;
1227 void *temp_buffer, *tmpl_hdr;
1228 u32 ocm_window;
1229 __le32 *buffer;
1230 char mesg[64];
1231 char *msg[] = {mesg, NULL};
1115 1232
1116 ahw = adapter->ahw; 1233 ahw = adapter->ahw;
1234 tmpl_hdr = fw_dump->tmpl_hdr;
1117 1235
1118 /* Return if we don't have firmware dump template header */ 1236 /* Return if we don't have firmware dump template header */
1119 if (!tmpl_hdr) 1237 if (!tmpl_hdr)
@@ -1133,8 +1251,9 @@ int qlcnic_dump_fw(struct qlcnic_adapter *adapter)
1133 netif_info(adapter->ahw, drv, adapter->netdev, "Take FW dump\n"); 1251 netif_info(adapter->ahw, drv, adapter->netdev, "Take FW dump\n");
1134 /* Calculate the size for dump data area only */ 1252 /* Calculate the size for dump data area only */
1135 for (i = 2, k = 1; (i & QLCNIC_DUMP_MASK_MAX); i <<= 1, k++) 1253 for (i = 2, k = 1; (i & QLCNIC_DUMP_MASK_MAX); i <<= 1, k++)
1136 if (i & tmpl_hdr->drv_cap_mask) 1254 if (i & fw_dump->cap_mask)
1137 dump_size += tmpl_hdr->cap_sizes[k]; 1255 dump_size += qlcnic_get_cap_size(adapter, tmpl_hdr, k);
1256
1138 if (!dump_size) 1257 if (!dump_size)
1139 return -EIO; 1258 return -EIO;
1140 1259
@@ -1144,10 +1263,10 @@ int qlcnic_dump_fw(struct qlcnic_adapter *adapter)
1144 1263
1145 buffer = fw_dump->data; 1264 buffer = fw_dump->data;
1146 fw_dump->size = dump_size; 1265 fw_dump->size = dump_size;
1147 no_entries = tmpl_hdr->num_entries; 1266 no_entries = fw_dump->num_entries;
1148 entry_offset = tmpl_hdr->offset; 1267 entry_offset = fw_dump->offset;
1149 tmpl_hdr->sys_info[0] = QLCNIC_DRIVER_VERSION; 1268 qlcnic_set_sys_info(adapter, tmpl_hdr, 0, QLCNIC_DRIVER_VERSION);
1150 tmpl_hdr->sys_info[1] = adapter->fw_version; 1269 qlcnic_set_sys_info(adapter, tmpl_hdr, 1, adapter->fw_version);
1151 1270
1152 if (fw_dump->use_pex_dma) { 1271 if (fw_dump->use_pex_dma) {
1153 temp_buffer = dma_alloc_coherent(dev, QLC_PEX_DMA_READ_SIZE, 1272 temp_buffer = dma_alloc_coherent(dev, QLC_PEX_DMA_READ_SIZE,
@@ -1163,16 +1282,17 @@ int qlcnic_dump_fw(struct qlcnic_adapter *adapter)
1163 ops_cnt = ARRAY_SIZE(qlcnic_fw_dump_ops); 1282 ops_cnt = ARRAY_SIZE(qlcnic_fw_dump_ops);
1164 fw_dump_ops = qlcnic_fw_dump_ops; 1283 fw_dump_ops = qlcnic_fw_dump_ops;
1165 } else { 1284 } else {
1285 hdr_83xx = tmpl_hdr;
1166 ops_cnt = ARRAY_SIZE(qlcnic_83xx_fw_dump_ops); 1286 ops_cnt = ARRAY_SIZE(qlcnic_83xx_fw_dump_ops);
1167 fw_dump_ops = qlcnic_83xx_fw_dump_ops; 1287 fw_dump_ops = qlcnic_83xx_fw_dump_ops;
1168 ocm_window = tmpl_hdr->ocm_wnd_reg[adapter->ahw->pci_func]; 1288 ocm_window = hdr_83xx->ocm_wnd_reg[ahw->pci_func];
1169 tmpl_hdr->saved_state[QLC_83XX_OCM_INDEX] = ocm_window; 1289 hdr_83xx->saved_state[QLC_83XX_OCM_INDEX] = ocm_window;
1170 tmpl_hdr->saved_state[QLC_83XX_PCI_INDEX] = ahw->pci_func; 1290 hdr_83xx->saved_state[QLC_83XX_PCI_INDEX] = ahw->pci_func;
1171 } 1291 }
1172 1292
1173 for (i = 0; i < no_entries; i++) { 1293 for (i = 0; i < no_entries; i++) {
1174 entry = (void *)tmpl_hdr + entry_offset; 1294 entry = tmpl_hdr + entry_offset;
1175 if (!(entry->hdr.mask & tmpl_hdr->drv_cap_mask)) { 1295 if (!(entry->hdr.mask & fw_dump->cap_mask)) {
1176 entry->hdr.flags |= QLCNIC_DUMP_SKIP; 1296 entry->hdr.flags |= QLCNIC_DUMP_SKIP;
1177 entry_offset += entry->hdr.offset; 1297 entry_offset += entry->hdr.offset;
1178 continue; 1298 continue;
@@ -1209,8 +1329,9 @@ int qlcnic_dump_fw(struct qlcnic_adapter *adapter)
1209 1329
1210 fw_dump->clr = 1; 1330 fw_dump->clr = 1;
1211 snprintf(mesg, sizeof(mesg), "FW_DUMP=%s", adapter->netdev->name); 1331 snprintf(mesg, sizeof(mesg), "FW_DUMP=%s", adapter->netdev->name);
1212 dev_info(dev, "%s: Dump data %d bytes captured, template header size %d bytes\n", 1332 netdev_info(adapter->netdev,
1213 adapter->netdev->name, fw_dump->size, tmpl_hdr->size); 1333 "Dump data %d bytes captured, template header size %d bytes\n",
1334 fw_dump->size, fw_dump->tmpl_hdr_size);
1214 /* Send a udev event to notify availability of FW dump */ 1335 /* Send a udev event to notify availability of FW dump */
1215 kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, msg); 1336 kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, msg);
1216 1337