From 225837a076b284ac408a3b0104584ae0ad117a0c Mon Sep 17 00:00:00 2001 From: Shahed Shaikh Date: Fri, 21 Feb 2014 13:20:10 -0500 Subject: [PATCH 1/7] 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 Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 73 +++++- .../ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | 7 +- .../ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h | 8 + .../ethernet/qlogic/qlcnic/qlcnic_ethtool.c | 17 +- .../net/ethernet/qlogic/qlcnic/qlcnic_hw.h | 8 + .../net/ethernet/qlogic/qlcnic/qlcnic_main.c | 7 +- .../ethernet/qlogic/qlcnic/qlcnic_minidump.c | 235 +++++++++++++----- 7 files changed, 288 insertions(+), 67 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 { u32 timer_out; }; -struct qlcnic_dump_template_hdr { +struct qlcnic_83xx_dump_template_hdr { u32 type; u32 offset; u32 size; @@ -411,15 +411,42 @@ struct qlcnic_dump_template_hdr { u32 rsvd[0]; }; +struct qlcnic_82xx_dump_template_hdr { + u32 type; + u32 offset; + u32 size; + u32 cap_mask; + u32 num_entries; + u32 version; + u32 timestamp; + u32 checksum; + u32 drv_cap_mask; + u32 sys_info[3]; + u32 saved_state[16]; + u32 cap_sizes[8]; + u32 rsvd[7]; + u32 capabilities; + u32 rsvd1[0]; +}; + struct qlcnic_fw_dump { u8 clr; /* flag to indicate if dump is cleared */ bool enable; /* enable/disable dump */ u32 size; /* total size of the dump */ + u32 cap_mask; /* Current capture mask */ void *data; /* dump data area */ - struct qlcnic_dump_template_hdr *tmpl_hdr; + void *tmpl_hdr; dma_addr_t phys_addr; void *dma_buffer; bool use_pex_dma; + /* Read only elements which are common between 82xx and 83xx + * template header. Update these values immediately after we read + * template header from Firmware + */ + u32 tmpl_hdr_size; + u32 version; + u32 num_entries; + u32 offset; }; /* @@ -1769,6 +1796,12 @@ struct qlcnic_hardware_ops { struct qlcnic_host_tx_ring *); void (*disable_tx_intr) (struct qlcnic_adapter *, struct qlcnic_host_tx_ring *); + u32 (*get_saved_state)(void *, u32); + void (*set_saved_state)(void *, u32, u32); + void (*cache_tmpl_hdr_values)(struct qlcnic_fw_dump *); + u32 (*get_cap_size)(void *, int); + void (*set_sys_info)(void *, int, u32); + void (*store_cap_mask)(void *, u32); }; extern struct qlcnic_nic_template qlcnic_vf_ops; @@ -2007,6 +2040,42 @@ static inline void qlcnic_read_phys_port_id(struct qlcnic_adapter *adapter) adapter->ahw->hw_ops->read_phys_port_id(adapter); } +static inline u32 qlcnic_get_saved_state(struct qlcnic_adapter *adapter, + void *t_hdr, u32 index) +{ + return adapter->ahw->hw_ops->get_saved_state(t_hdr, index); +} + +static inline void qlcnic_set_saved_state(struct qlcnic_adapter *adapter, + void *t_hdr, u32 index, u32 value) +{ + adapter->ahw->hw_ops->set_saved_state(t_hdr, index, value); +} + +static inline void qlcnic_cache_tmpl_hdr_values(struct qlcnic_adapter *adapter, + struct qlcnic_fw_dump *fw_dump) +{ + adapter->ahw->hw_ops->cache_tmpl_hdr_values(fw_dump); +} + +static inline u32 qlcnic_get_cap_size(struct qlcnic_adapter *adapter, + void *tmpl_hdr, int index) +{ + return adapter->ahw->hw_ops->get_cap_size(tmpl_hdr, index); +} + +static inline void qlcnic_set_sys_info(struct qlcnic_adapter *adapter, + void *tmpl_hdr, int idx, u32 value) +{ + adapter->ahw->hw_ops->set_sys_info(tmpl_hdr, idx, value); +} + +static inline void qlcnic_store_cap_mask(struct qlcnic_adapter *adapter, + void *tmpl_hdr, u32 mask) +{ + adapter->ahw->hw_ops->store_cap_mask(tmpl_hdr, mask); +} + static inline void qlcnic_dev_request_reset(struct qlcnic_adapter *adapter, u32 key) { 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 = { .disable_sds_intr = qlcnic_83xx_disable_sds_intr, .enable_tx_intr = qlcnic_83xx_enable_tx_intr, .disable_tx_intr = qlcnic_83xx_disable_tx_intr, - + .get_saved_state = qlcnic_83xx_get_saved_state, + .set_saved_state = qlcnic_83xx_set_saved_state, + .cache_tmpl_hdr_values = qlcnic_83xx_cache_tmpl_hdr_values, + .get_cap_size = qlcnic_83xx_get_cap_size, + .set_sys_info = qlcnic_83xx_set_sys_info, + .store_cap_mask = qlcnic_83xx_store_cap_mask, }; static 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 { #define QLC_83XX_IDC_FLASH_PARAM_ADDR 0x3e8020 struct qlcnic_adapter; +struct qlcnic_fw_dump; + struct qlc_83xx_idc { int (*state_entry) (struct qlcnic_adapter *); u64 sec_counter; @@ -650,4 +652,10 @@ int qlcnic_83xx_check_vnic_state(struct qlcnic_adapter *); void qlcnic_83xx_aer_stop_poll_work(struct qlcnic_adapter *); int qlcnic_83xx_aer_reset(struct qlcnic_adapter *); void qlcnic_83xx_aer_start_poll_work(struct qlcnic_adapter *); +u32 qlcnic_83xx_get_saved_state(void *, u32); +void qlcnic_83xx_set_saved_state(void *, u32, u32); +void qlcnic_83xx_cache_tmpl_hdr_values(struct qlcnic_fw_dump *); +u32 qlcnic_83xx_get_cap_size(void *, int); +void qlcnic_83xx_set_sys_info(void *, int, u32); +void qlcnic_83xx_store_cap_mask(void *, u32); #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) } if (fw_dump->clr) - dump->len = fw_dump->tmpl_hdr->size + fw_dump->size; + dump->len = fw_dump->tmpl_hdr_size + fw_dump->size; else dump->len = 0; if (!qlcnic_check_fw_dump_state(adapter)) dump->flag = ETH_FW_DUMP_DISABLE; else - dump->flag = fw_dump->tmpl_hdr->drv_cap_mask; + dump->flag = fw_dump->cap_mask; dump->version = adapter->fw_version; return 0; @@ -1671,9 +1671,10 @@ qlcnic_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump, netdev_info(netdev, "Dump not available\n"); return -EINVAL; } + /* Copy template header first */ - copy_sz = fw_dump->tmpl_hdr->size; - hdr_ptr = (u32 *) fw_dump->tmpl_hdr; + copy_sz = fw_dump->tmpl_hdr_size; + hdr_ptr = (u32 *)fw_dump->tmpl_hdr; data = buffer; for (i = 0; i < copy_sz/sizeof(u32); i++) *data++ = cpu_to_le32(*hdr_ptr++); @@ -1681,7 +1682,7 @@ qlcnic_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump, /* Copy captured dump data */ memcpy(buffer + copy_sz, fw_dump->data, fw_dump->size); dump->len = copy_sz + fw_dump->size; - dump->flag = fw_dump->tmpl_hdr->drv_cap_mask; + dump->flag = fw_dump->cap_mask; /* Free dump area once data has been captured */ vfree(fw_dump->data); @@ -1703,7 +1704,11 @@ static int qlcnic_set_dump_mask(struct qlcnic_adapter *adapter, u32 mask) return -EOPNOTSUPP; } - fw_dump->tmpl_hdr->drv_cap_mask = mask; + fw_dump->cap_mask = mask; + + /* Store new capture mask in template header as well*/ + qlcnic_store_cap_mask(adapter, fw_dump->tmpl_hdr, mask); + netdev_info(netdev, "Driver mask changed to: 0x%x\n", mask); return 0; } 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; struct qlcnic_host_tx_ring; struct qlcnic_hardware_context; struct qlcnic_adapter; +struct qlcnic_fw_dump; int qlcnic_82xx_hw_read_wx_2M(struct qlcnic_adapter *adapter, ulong, int *); int qlcnic_82xx_hw_write_wx_2M(struct qlcnic_adapter *, ulong, u32); @@ -213,4 +214,11 @@ int qlcnic_82xx_shutdown(struct pci_dev *); int qlcnic_82xx_resume(struct qlcnic_adapter *); void qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter, u8 failed); void qlcnic_fw_poll_work(struct work_struct *work); + +u32 qlcnic_82xx_get_saved_state(void *, u32); +void qlcnic_82xx_set_saved_state(void *, u32, u32); +void qlcnic_82xx_cache_tmpl_hdr_values(struct qlcnic_fw_dump *); +u32 qlcnic_82xx_get_cap_size(void *, int); +void qlcnic_82xx_set_sys_info(void *, int, u32); +void qlcnic_82xx_store_cap_mask(void *, u32); #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 *); static void qlcnic_82xx_set_mac_filter_count(struct qlcnic_adapter *); static pci_ers_result_t qlcnic_82xx_io_error_detected(struct pci_dev *, pci_channel_state_t); - static u32 qlcnic_vlan_tx_check(struct qlcnic_adapter *adapter) { struct qlcnic_hardware_context *ahw = adapter->ahw; @@ -561,6 +560,12 @@ static struct qlcnic_hardware_ops qlcnic_hw_ops = { .disable_sds_intr = qlcnic_82xx_disable_sds_intr, .enable_tx_intr = qlcnic_82xx_enable_tx_intr, .disable_tx_intr = qlcnic_82xx_disable_tx_intr, + .get_saved_state = qlcnic_82xx_get_saved_state, + .set_saved_state = qlcnic_82xx_set_saved_state, + .cache_tmpl_hdr_values = qlcnic_82xx_cache_tmpl_hdr_values, + .get_cap_size = qlcnic_82xx_get_cap_size, + .set_sys_info = qlcnic_82xx_set_sys_info, + .store_cap_mask = qlcnic_82xx_store_cap_mask, }; static 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 { QLCNIC_DUMP_RDEND = 255 }; +inline u32 qlcnic_82xx_get_saved_state(void *t_hdr, u32 index) +{ + struct qlcnic_82xx_dump_template_hdr *hdr = t_hdr; + + return hdr->saved_state[index]; +} + +inline void qlcnic_82xx_set_saved_state(void *t_hdr, u32 index, + u32 value) +{ + struct qlcnic_82xx_dump_template_hdr *hdr = t_hdr; + + hdr->saved_state[index] = value; +} + +void qlcnic_82xx_cache_tmpl_hdr_values(struct qlcnic_fw_dump *fw_dump) +{ + struct qlcnic_82xx_dump_template_hdr *hdr; + + hdr = fw_dump->tmpl_hdr; + fw_dump->tmpl_hdr_size = hdr->size; + fw_dump->version = hdr->version; + fw_dump->num_entries = hdr->num_entries; + fw_dump->offset = hdr->offset; + + hdr->drv_cap_mask = hdr->cap_mask; + fw_dump->cap_mask = hdr->cap_mask; +} + +inline u32 qlcnic_82xx_get_cap_size(void *t_hdr, int index) +{ + struct qlcnic_82xx_dump_template_hdr *hdr = t_hdr; + + return hdr->cap_sizes[index]; +} + +void qlcnic_82xx_set_sys_info(void *t_hdr, int idx, u32 value) +{ + struct qlcnic_82xx_dump_template_hdr *hdr = t_hdr; + + hdr->sys_info[idx] = value; +} + +void qlcnic_82xx_store_cap_mask(void *tmpl_hdr, u32 mask) +{ + struct qlcnic_82xx_dump_template_hdr *hdr = tmpl_hdr; + + hdr->drv_cap_mask = mask; +} + +inline u32 qlcnic_83xx_get_saved_state(void *t_hdr, u32 index) +{ + struct qlcnic_83xx_dump_template_hdr *hdr = t_hdr; + + return hdr->saved_state[index]; +} + +inline void qlcnic_83xx_set_saved_state(void *t_hdr, u32 index, + u32 value) +{ + struct qlcnic_83xx_dump_template_hdr *hdr = t_hdr; + + hdr->saved_state[index] = value; +} + +void qlcnic_83xx_cache_tmpl_hdr_values(struct qlcnic_fw_dump *fw_dump) +{ + struct qlcnic_83xx_dump_template_hdr *hdr; + + hdr = fw_dump->tmpl_hdr; + fw_dump->tmpl_hdr_size = hdr->size; + fw_dump->version = hdr->version; + fw_dump->num_entries = hdr->num_entries; + fw_dump->offset = hdr->offset; + + hdr->drv_cap_mask = hdr->cap_mask; + fw_dump->cap_mask = hdr->cap_mask; +} + +inline u32 qlcnic_83xx_get_cap_size(void *t_hdr, int index) +{ + struct qlcnic_83xx_dump_template_hdr *hdr = t_hdr; + + return hdr->cap_sizes[index]; +} + +void qlcnic_83xx_set_sys_info(void *t_hdr, int idx, u32 value) +{ + struct qlcnic_83xx_dump_template_hdr *hdr = t_hdr; + + hdr->sys_info[idx] = value; +} + +void qlcnic_83xx_store_cap_mask(void *tmpl_hdr, u32 mask) +{ + struct qlcnic_83xx_dump_template_hdr *hdr; + + hdr = tmpl_hdr; + hdr->drv_cap_mask = mask; +} + struct qlcnic_dump_operations { enum qlcnic_minidump_opcode opcode; u32 (*handler)(struct qlcnic_adapter *, struct qlcnic_dump_entry *, @@ -238,11 +339,11 @@ static u32 qlcnic_dump_crb(struct qlcnic_adapter *adapter, static u32 qlcnic_dump_ctrl(struct qlcnic_adapter *adapter, struct qlcnic_dump_entry *entry, __le32 *buffer) { - int i, k, timeout = 0; - u32 addr, data; - u8 no_ops; + void *hdr = adapter->ahw->fw_dump.tmpl_hdr; struct __ctrl *ctr = &entry->region.ctrl; - struct qlcnic_dump_template_hdr *t_hdr = adapter->ahw->fw_dump.tmpl_hdr; + int i, k, timeout = 0; + u32 addr, data, temp; + u8 no_ops; addr = ctr->addr; no_ops = ctr->no_ops; @@ -285,29 +386,42 @@ static u32 qlcnic_dump_ctrl(struct qlcnic_adapter *adapter, } break; case QLCNIC_DUMP_RD_SAVE: - if (ctr->index_a) - addr = t_hdr->saved_state[ctr->index_a]; + temp = ctr->index_a; + if (temp) + addr = qlcnic_get_saved_state(adapter, + hdr, + temp); data = qlcnic_ind_rd(adapter, addr); - t_hdr->saved_state[ctr->index_v] = data; + qlcnic_set_saved_state(adapter, hdr, + ctr->index_v, data); break; case QLCNIC_DUMP_WRT_SAVED: - if (ctr->index_v) - data = t_hdr->saved_state[ctr->index_v]; + temp = ctr->index_v; + if (temp) + data = qlcnic_get_saved_state(adapter, + hdr, + temp); else data = ctr->val1; - if (ctr->index_a) - addr = t_hdr->saved_state[ctr->index_a]; + + temp = ctr->index_a; + if (temp) + addr = qlcnic_get_saved_state(adapter, + hdr, + temp); qlcnic_ind_wr(adapter, addr, data); break; case QLCNIC_DUMP_MOD_SAVE_ST: - data = t_hdr->saved_state[ctr->index_v]; + data = qlcnic_get_saved_state(adapter, hdr, + ctr->index_v); data <<= ctr->shl_val; data >>= ctr->shr_val; if (ctr->val2) data &= ctr->val2; data |= ctr->val3; data += ctr->val1; - t_hdr->saved_state[ctr->index_v] = data; + qlcnic_set_saved_state(adapter, hdr, + ctr->index_v, data); break; default: dev_info(&adapter->pdev->dev, @@ -544,7 +658,7 @@ static u32 qlcnic_read_memory_test_agent(struct qlcnic_adapter *adapter, static int qlcnic_start_pex_dma(struct qlcnic_adapter *adapter, struct __mem *mem) { - struct qlcnic_dump_template_hdr *tmpl_hdr; + struct qlcnic_83xx_dump_template_hdr *tmpl_hdr; struct device *dev = &adapter->pdev->dev; u32 dma_no, dma_base_addr, temp_addr; int i, ret, dma_sts; @@ -596,7 +710,7 @@ static u32 qlcnic_read_memory_pexdma(struct qlcnic_adapter *adapter, struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump; u32 temp, dma_base_addr, size = 0, read_size = 0; struct qlcnic_pex_dma_descriptor *dma_descr; - struct qlcnic_dump_template_hdr *tmpl_hdr; + struct qlcnic_83xx_dump_template_hdr *tmpl_hdr; struct device *dev = &adapter->pdev->dev; dma_addr_t dma_phys_addr; void *dma_buffer; @@ -938,8 +1052,8 @@ static int qlcnic_fw_flash_get_minidump_temp_size(struct qlcnic_adapter *adapter, struct qlcnic_cmd_args *cmd) { - struct qlcnic_dump_template_hdr tmp_hdr; - u32 size = sizeof(struct qlcnic_dump_template_hdr) / sizeof(u32); + struct qlcnic_83xx_dump_template_hdr tmp_hdr; + u32 size = sizeof(tmp_hdr) / sizeof(u32); int ret = 0; if (qlcnic_82xx_check(adapter)) @@ -1027,17 +1141,19 @@ static int __qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter, return err; } +#define QLCNIC_TEMPLATE_VERSION (0x20001) + int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter) { - int err; - u32 temp_size = 0; - u32 version, csum, *tmp_buf; struct qlcnic_hardware_context *ahw; - struct qlcnic_dump_template_hdr *tmpl_hdr; + struct qlcnic_fw_dump *fw_dump; + u32 version, csum, *tmp_buf; u8 use_flash_temp = 0; + u32 temp_size = 0; + int err; ahw = adapter->ahw; - + fw_dump = &ahw->fw_dump; err = qlcnic_fw_get_minidump_temp_size(adapter, &version, &temp_size, &use_flash_temp); if (err) { @@ -1046,11 +1162,11 @@ int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter) return -EIO; } - ahw->fw_dump.tmpl_hdr = vzalloc(temp_size); - if (!ahw->fw_dump.tmpl_hdr) + fw_dump->tmpl_hdr = vzalloc(temp_size); + if (!fw_dump->tmpl_hdr) return -ENOMEM; - tmp_buf = (u32 *)ahw->fw_dump.tmpl_hdr; + tmp_buf = (u32 *)fw_dump->tmpl_hdr; if (use_flash_temp) goto flash_temp; @@ -1065,8 +1181,8 @@ int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter) dev_err(&adapter->pdev->dev, "Failed to get minidump template header %d\n", err); - vfree(ahw->fw_dump.tmpl_hdr); - ahw->fw_dump.tmpl_hdr = NULL; + vfree(fw_dump->tmpl_hdr); + fw_dump->tmpl_hdr = NULL; return -EIO; } } @@ -1076,21 +1192,22 @@ int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter) if (csum) { dev_err(&adapter->pdev->dev, "Template header checksum validation failed\n"); - vfree(ahw->fw_dump.tmpl_hdr); - ahw->fw_dump.tmpl_hdr = NULL; + vfree(fw_dump->tmpl_hdr); + fw_dump->tmpl_hdr = NULL; return -EIO; } - tmpl_hdr = ahw->fw_dump.tmpl_hdr; - tmpl_hdr->drv_cap_mask = tmpl_hdr->cap_mask; + qlcnic_cache_tmpl_hdr_values(adapter, fw_dump); + dev_info(&adapter->pdev->dev, "Default minidump capture mask 0x%x\n", - tmpl_hdr->cap_mask); + fw_dump->cap_mask); - if ((tmpl_hdr->version & 0xfffff) >= 0x20001) - ahw->fw_dump.use_pex_dma = true; + if (qlcnic_83xx_check(adapter) && + (fw_dump->version & 0xfffff) >= QLCNIC_TEMPLATE_VERSION) + fw_dump->use_pex_dma = true; else - ahw->fw_dump.use_pex_dma = false; + fw_dump->use_pex_dma = false; qlcnic_enable_fw_dump_state(adapter); @@ -1099,21 +1216,22 @@ int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter) int qlcnic_dump_fw(struct qlcnic_adapter *adapter) { - __le32 *buffer; - u32 ocm_window; - char mesg[64]; - char *msg[] = {mesg, NULL}; - int i, k, ops_cnt, ops_index, dump_size = 0; - u32 entry_offset, dump, no_entries, buf_offset = 0; - struct qlcnic_dump_entry *entry; struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump; - struct qlcnic_dump_template_hdr *tmpl_hdr = fw_dump->tmpl_hdr; static const struct qlcnic_dump_operations *fw_dump_ops; + struct qlcnic_83xx_dump_template_hdr *hdr_83xx; + u32 entry_offset, dump, no_entries, buf_offset = 0; + int i, k, ops_cnt, ops_index, dump_size = 0; struct device *dev = &adapter->pdev->dev; struct qlcnic_hardware_context *ahw; - void *temp_buffer; + struct qlcnic_dump_entry *entry; + void *temp_buffer, *tmpl_hdr; + u32 ocm_window; + __le32 *buffer; + char mesg[64]; + char *msg[] = {mesg, NULL}; ahw = adapter->ahw; + tmpl_hdr = fw_dump->tmpl_hdr; /* Return if we don't have firmware dump template header */ if (!tmpl_hdr) @@ -1133,8 +1251,9 @@ int qlcnic_dump_fw(struct qlcnic_adapter *adapter) netif_info(adapter->ahw, drv, adapter->netdev, "Take FW dump\n"); /* Calculate the size for dump data area only */ for (i = 2, k = 1; (i & QLCNIC_DUMP_MASK_MAX); i <<= 1, k++) - if (i & tmpl_hdr->drv_cap_mask) - dump_size += tmpl_hdr->cap_sizes[k]; + if (i & fw_dump->cap_mask) + dump_size += qlcnic_get_cap_size(adapter, tmpl_hdr, k); + if (!dump_size) return -EIO; @@ -1144,10 +1263,10 @@ int qlcnic_dump_fw(struct qlcnic_adapter *adapter) buffer = fw_dump->data; fw_dump->size = dump_size; - no_entries = tmpl_hdr->num_entries; - entry_offset = tmpl_hdr->offset; - tmpl_hdr->sys_info[0] = QLCNIC_DRIVER_VERSION; - tmpl_hdr->sys_info[1] = adapter->fw_version; + no_entries = fw_dump->num_entries; + entry_offset = fw_dump->offset; + qlcnic_set_sys_info(adapter, tmpl_hdr, 0, QLCNIC_DRIVER_VERSION); + qlcnic_set_sys_info(adapter, tmpl_hdr, 1, adapter->fw_version); if (fw_dump->use_pex_dma) { temp_buffer = dma_alloc_coherent(dev, QLC_PEX_DMA_READ_SIZE, @@ -1163,16 +1282,17 @@ int qlcnic_dump_fw(struct qlcnic_adapter *adapter) ops_cnt = ARRAY_SIZE(qlcnic_fw_dump_ops); fw_dump_ops = qlcnic_fw_dump_ops; } else { + hdr_83xx = tmpl_hdr; ops_cnt = ARRAY_SIZE(qlcnic_83xx_fw_dump_ops); fw_dump_ops = qlcnic_83xx_fw_dump_ops; - ocm_window = tmpl_hdr->ocm_wnd_reg[adapter->ahw->pci_func]; - tmpl_hdr->saved_state[QLC_83XX_OCM_INDEX] = ocm_window; - tmpl_hdr->saved_state[QLC_83XX_PCI_INDEX] = ahw->pci_func; + ocm_window = hdr_83xx->ocm_wnd_reg[ahw->pci_func]; + hdr_83xx->saved_state[QLC_83XX_OCM_INDEX] = ocm_window; + hdr_83xx->saved_state[QLC_83XX_PCI_INDEX] = ahw->pci_func; } for (i = 0; i < no_entries; i++) { - entry = (void *)tmpl_hdr + entry_offset; - if (!(entry->hdr.mask & tmpl_hdr->drv_cap_mask)) { + entry = tmpl_hdr + entry_offset; + if (!(entry->hdr.mask & fw_dump->cap_mask)) { entry->hdr.flags |= QLCNIC_DUMP_SKIP; entry_offset += entry->hdr.offset; continue; @@ -1209,8 +1329,9 @@ int qlcnic_dump_fw(struct qlcnic_adapter *adapter) fw_dump->clr = 1; snprintf(mesg, sizeof(mesg), "FW_DUMP=%s", adapter->netdev->name); - dev_info(dev, "%s: Dump data %d bytes captured, template header size %d bytes\n", - adapter->netdev->name, fw_dump->size, tmpl_hdr->size); + netdev_info(adapter->netdev, + "Dump data %d bytes captured, template header size %d bytes\n", + fw_dump->size, fw_dump->tmpl_hdr_size); /* Send a udev event to notify availability of FW dump */ kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, msg); From d91abf903b1d39f46251305328e245c76f14b349 Mon Sep 17 00:00:00 2001 From: Jitendra Kalsaria Date: Fri, 21 Feb 2014 13:20:11 -0500 Subject: [PATCH 2/7] qlcnic: Updates to QLogic application/driver interface for virtual NIC configuration Qlogic application interface in the driver which has larger than 8 vNIC configuration support has been updated to handle the following cases: o Only 8 or lower total vNICs were enabled within the vNIC 0-7 range o vNICs were enabled in the vNIC 0-15 range such that enabled vNICs were not contiguous and only 8 or lower number of total VNICs were enabled o Disconnect in the vNIC mapping between application and driver when the enabled VNICs were dis contiguous Signed-off-by: Jitendra Kalsaria Signed-off-by: David S. Miller --- .../net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c | 102 +++++++----------- 1 file changed, 37 insertions(+), 65 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c index 3d64113a35af..448d156c3d08 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c @@ -350,33 +350,15 @@ static ssize_t qlcnic_sysfs_write_mem(struct file *filp, struct kobject *kobj, return size; } -static u32 qlcnic_get_pci_func_count(struct qlcnic_adapter *adapter) -{ - struct qlcnic_hardware_context *ahw = adapter->ahw; - u32 count = 0; - - if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)) - return ahw->total_nic_func; - - if (ahw->total_pci_func <= QLC_DEFAULT_VNIC_COUNT) - count = QLC_DEFAULT_VNIC_COUNT; - else - count = ahw->max_vnic_func; - - return count; -} - int qlcnic_is_valid_nic_func(struct qlcnic_adapter *adapter, u8 pci_func) { - u32 pci_func_count = qlcnic_get_pci_func_count(adapter); int i; - for (i = 0; i < pci_func_count; i++) { + for (i = 0; i < adapter->ahw->max_vnic_func; i++) { if (adapter->npars[i].pci_func == pci_func) return i; } - - return -1; + return -EINVAL; } static int validate_pm_config(struct qlcnic_adapter *adapter, @@ -464,23 +446,21 @@ static ssize_t qlcnic_sysfs_read_pm_config(struct file *filp, { struct device *dev = container_of(kobj, struct device, kobj); struct qlcnic_adapter *adapter = dev_get_drvdata(dev); - u32 pci_func_count = qlcnic_get_pci_func_count(adapter); struct qlcnic_pm_func_cfg *pm_cfg; - int i, pm_cfg_size; u8 pci_func; + u32 count; + int i; - pm_cfg_size = pci_func_count * sizeof(*pm_cfg); - if (size != pm_cfg_size) - return QL_STATUS_INVALID_PARAM; - - memset(buf, 0, pm_cfg_size); + memset(buf, 0, size); pm_cfg = (struct qlcnic_pm_func_cfg *)buf; - - for (i = 0; i < pci_func_count; i++) { + count = size / sizeof(struct qlcnic_pm_func_cfg); + for (i = 0; i < adapter->ahw->total_nic_func; i++) { pci_func = adapter->npars[i].pci_func; - if (!adapter->npars[i].active) + if (pci_func >= count) { + dev_dbg(dev, "%s: Total nic functions[%d], App sent function count[%d]\n", + __func__, adapter->ahw->total_nic_func, count); continue; - + } if (!adapter->npars[i].eswitch_status) continue; @@ -494,7 +474,6 @@ static ssize_t qlcnic_sysfs_read_pm_config(struct file *filp, static int validate_esw_config(struct qlcnic_adapter *adapter, struct qlcnic_esw_func_cfg *esw_cfg, int count) { - u32 pci_func_count = qlcnic_get_pci_func_count(adapter); struct qlcnic_hardware_context *ahw = adapter->ahw; int i, ret; u32 op_mode; @@ -507,7 +486,7 @@ static int validate_esw_config(struct qlcnic_adapter *adapter, for (i = 0; i < count; i++) { pci_func = esw_cfg[i].pci_func; - if (pci_func >= pci_func_count) + if (pci_func >= ahw->max_vnic_func) return QL_STATUS_INVALID_PARAM; if (adapter->ahw->op_mode == QLCNIC_MGMT_FUNC) @@ -642,23 +621,21 @@ static ssize_t qlcnic_sysfs_read_esw_config(struct file *file, { struct device *dev = container_of(kobj, struct device, kobj); struct qlcnic_adapter *adapter = dev_get_drvdata(dev); - u32 pci_func_count = qlcnic_get_pci_func_count(adapter); struct qlcnic_esw_func_cfg *esw_cfg; - size_t esw_cfg_size; - u8 i, pci_func; + u8 pci_func; + u32 count; + int i; - esw_cfg_size = pci_func_count * sizeof(*esw_cfg); - if (size != esw_cfg_size) - return QL_STATUS_INVALID_PARAM; - - memset(buf, 0, esw_cfg_size); + memset(buf, 0, size); esw_cfg = (struct qlcnic_esw_func_cfg *)buf; - - for (i = 0; i < pci_func_count; i++) { + count = size / sizeof(struct qlcnic_esw_func_cfg); + for (i = 0; i < adapter->ahw->total_nic_func; i++) { pci_func = adapter->npars[i].pci_func; - if (!adapter->npars[i].active) + if (pci_func >= count) { + dev_dbg(dev, "%s: Total nic functions[%d], App sent function count[%d]\n", + __func__, adapter->ahw->total_nic_func, count); continue; - + } if (!adapter->npars[i].eswitch_status) continue; @@ -741,23 +718,24 @@ static ssize_t qlcnic_sysfs_read_npar_config(struct file *file, { struct device *dev = container_of(kobj, struct device, kobj); struct qlcnic_adapter *adapter = dev_get_drvdata(dev); - u32 pci_func_count = qlcnic_get_pci_func_count(adapter); struct qlcnic_npar_func_cfg *np_cfg; struct qlcnic_info nic_info; - size_t np_cfg_size; int i, ret; - - np_cfg_size = pci_func_count * sizeof(*np_cfg); - if (size != np_cfg_size) - return QL_STATUS_INVALID_PARAM; + u32 count; memset(&nic_info, 0, sizeof(struct qlcnic_info)); - memset(buf, 0, np_cfg_size); + memset(buf, 0, size); np_cfg = (struct qlcnic_npar_func_cfg *)buf; - for (i = 0; i < pci_func_count; i++) { + count = size / sizeof(struct qlcnic_npar_func_cfg); + for (i = 0; i < adapter->ahw->total_nic_func; i++) { if (qlcnic_is_valid_nic_func(adapter, i) < 0) continue; + if (adapter->npars[i].pci_func >= count) { + dev_dbg(dev, "%s: Total nic functions[%d], App sent function count[%d]\n", + __func__, adapter->ahw->total_nic_func, count); + continue; + } ret = qlcnic_get_nic_info(adapter, &nic_info, i); if (ret) return ret; @@ -783,7 +761,6 @@ static ssize_t qlcnic_sysfs_get_port_stats(struct file *file, { struct device *dev = container_of(kobj, struct device, kobj); struct qlcnic_adapter *adapter = dev_get_drvdata(dev); - u32 pci_func_count = qlcnic_get_pci_func_count(adapter); struct qlcnic_esw_statistics port_stats; int ret; @@ -793,7 +770,7 @@ static ssize_t qlcnic_sysfs_get_port_stats(struct file *file, if (size != sizeof(struct qlcnic_esw_statistics)) return QL_STATUS_INVALID_PARAM; - if (offset >= pci_func_count) + if (offset >= adapter->ahw->max_vnic_func) return QL_STATUS_INVALID_PARAM; memset(&port_stats, 0, size); @@ -884,13 +861,12 @@ static ssize_t qlcnic_sysfs_clear_port_stats(struct file *file, struct device *dev = container_of(kobj, struct device, kobj); struct qlcnic_adapter *adapter = dev_get_drvdata(dev); - u32 pci_func_count = qlcnic_get_pci_func_count(adapter); int ret; if (qlcnic_83xx_check(adapter)) return QLC_STATUS_UNSUPPORTED_CMD; - if (offset >= pci_func_count) + if (offset >= adapter->ahw->max_vnic_func) return QL_STATUS_INVALID_PARAM; ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_PORT, offset, @@ -914,17 +890,12 @@ static ssize_t qlcnic_sysfs_read_pci_config(struct file *file, { struct device *dev = container_of(kobj, struct device, kobj); struct qlcnic_adapter *adapter = dev_get_drvdata(dev); - u32 pci_func_count = qlcnic_get_pci_func_count(adapter); struct qlcnic_pci_func_cfg *pci_cfg; struct qlcnic_pci_info *pci_info; - size_t pci_cfg_sz; int i, ret; + u32 count; - pci_cfg_sz = pci_func_count * sizeof(*pci_cfg); - if (size != pci_cfg_sz) - return QL_STATUS_INVALID_PARAM; - - pci_info = kcalloc(pci_func_count, sizeof(*pci_info), GFP_KERNEL); + pci_info = kcalloc(size, sizeof(*pci_info), GFP_KERNEL); if (!pci_info) return -ENOMEM; @@ -935,7 +906,8 @@ static ssize_t qlcnic_sysfs_read_pci_config(struct file *file, } pci_cfg = (struct qlcnic_pci_func_cfg *)buf; - for (i = 0; i < pci_func_count; i++) { + count = size / sizeof(struct qlcnic_pci_func_cfg); + for (i = 0; i < count; i++) { pci_cfg[i].pci_func = pci_info[i].id; pci_cfg[i].func_type = pci_info[i].type; pci_cfg[i].func_state = 0; From 2a355aecd27f88d26ba8213b4e55123522ef5eae Mon Sep 17 00:00:00 2001 From: Sucheta Chakraborty Date: Fri, 21 Feb 2014 13:20:12 -0500 Subject: [PATCH 3/7] qlcnic: Enhance driver message in failed state. Signed-off-by: Sucheta Chakraborty Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index 964ba457a7c6..a33547292878 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c @@ -2450,8 +2450,8 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (err) { switch (err) { case -ENOTRECOVERABLE: - dev_err(&pdev->dev, "Adapter initialization failed due to a faulty hardware. Please reboot\n"); - dev_err(&pdev->dev, "If reboot doesn't help, please replace the adapter with new one and return the faulty adapter for repair\n"); + dev_err(&pdev->dev, "Adapter initialization failed due to a faulty hardware\n"); + dev_err(&pdev->dev, "Please replace the adapter with new one and return the faulty adapter for repair\n"); goto err_out_free_hw; case -ENOMEM: dev_err(&pdev->dev, "Adapter initialization failed. Please reboot\n"); From cecd59d84d8e401db7860fc5fae503c965e5c470 Mon Sep 17 00:00:00 2001 From: Rajesh Borundia Date: Fri, 21 Feb 2014 13:20:13 -0500 Subject: [PATCH 4/7] qlcnic: Allow vlan0 traffic o Adapter allows vlan0 traffic in case of SR-IOV after setting QLC_SRIOV_ALLOW_VLAN0 bit even though we do not add vlan0 filters. Signed-off-by: Rajesh Borundia Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c index 09acf15c3a56..a28460cf873d 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c @@ -17,6 +17,7 @@ #define QLC_MAC_STAR_DEL 7 #define QLC_VF_FLOOD_BIT BIT_16 #define QLC_FLOOD_MODE 0x5 +#define QLC_SRIOV_ALLOW_VLAN0 BIT_19 static int qlcnic_sriov_pf_get_vport_handle(struct qlcnic_adapter *, u8); @@ -337,8 +338,11 @@ static int qlcnic_sriov_pf_cfg_vlan_filtering(struct qlcnic_adapter *adapter, return err; cmd.req.arg[1] = 0x4; - if (enable) + if (enable) { cmd.req.arg[1] |= BIT_16; + if (qlcnic_84xx_check(adapter)) + cmd.req.arg[1] |= QLC_SRIOV_ALLOW_VLAN0; + } err = qlcnic_issue_cmd(adapter, &cmd); if (err) From 1a51042bb8fc6317270bb70daf5eb1c57002340a Mon Sep 17 00:00:00 2001 From: Harish Patil Date: Fri, 21 Feb 2014 13:20:14 -0500 Subject: [PATCH 5/7] qlcnic: Enhance semaphore lock access failure error message Signed-off-by: Harish Patil Signed-off-by: David S. Miller --- .../net/ethernet/qlogic/qlcnic/qlcnic_hw.c | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c index 03d18a0be6ce..9f3adf4e70b5 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c @@ -317,9 +317,7 @@ static void qlcnic_write_window_reg(u32 addr, void __iomem *bar0, u32 data) int qlcnic_pcie_sem_lock(struct qlcnic_adapter *adapter, int sem, u32 id_reg) { - int timeout = 0; - int err = 0; - u32 done = 0; + int timeout = 0, err = 0, done = 0; while (!done) { done = QLCRD32(adapter, QLCNIC_PCIE_REG(PCIE_SEM_LOCK(sem)), @@ -327,10 +325,20 @@ qlcnic_pcie_sem_lock(struct qlcnic_adapter *adapter, int sem, u32 id_reg) if (done == 1) break; if (++timeout >= QLCNIC_PCIE_SEM_TIMEOUT) { - dev_err(&adapter->pdev->dev, - "Failed to acquire sem=%d lock; holdby=%d\n", - sem, - id_reg ? QLCRD32(adapter, id_reg, &err) : -1); + if (id_reg) { + done = QLCRD32(adapter, id_reg, &err); + if (done != -1) + dev_err(&adapter->pdev->dev, + "Failed to acquire sem=%d lock held by=%d\n", + sem, done); + else + dev_err(&adapter->pdev->dev, + "Failed to acquire sem=%d lock", + sem); + } else { + dev_err(&adapter->pdev->dev, + "Failed to acquire sem=%d lock", sem); + } return -EIO; } msleep(1); From 3dd4705698f12a076204c6825c754297633a9a8d Mon Sep 17 00:00:00 2001 From: Shahed Shaikh Date: Fri, 21 Feb 2014 13:20:15 -0500 Subject: [PATCH 6/7] qlcnic: Update version to 5.3.56 Signed-off-by: Shahed Shaikh Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h index 6ad1bcebc0fe..df9daa335292 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h @@ -38,8 +38,8 @@ #define _QLCNIC_LINUX_MAJOR 5 #define _QLCNIC_LINUX_MINOR 3 -#define _QLCNIC_LINUX_SUBVERSION 55 -#define QLCNIC_LINUX_VERSIONID "5.3.55" +#define _QLCNIC_LINUX_SUBVERSION 56 +#define QLCNIC_LINUX_VERSIONID "5.3.56" #define QLCNIC_DRV_IDC_VER 0x01 #define QLCNIC_DRIVER_VERSION ((_QLCNIC_LINUX_MAJOR << 16) |\ (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION)) From e6b0b019795c50c9e6cef4e2b3ccabfc12d7ea18 Mon Sep 17 00:00:00 2001 From: Shahed Shaikh Date: Fri, 21 Feb 2014 13:20:16 -0500 Subject: [PATCH 7/7] Update MAINTAINERS for qlcnic driver Keep myself as only maintainer for qlcnic driver and update group email alias to Dept-HSGLinuxNICDev@qlogic.com Signed-off-by: Shahed Shaikh Signed-off-by: David S. Miller --- MAINTAINERS | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index b0196ab3e489..ebd298e00f44 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7038,13 +7038,8 @@ F: Documentation/networking/LICENSE.qla3xxx F: drivers/net/ethernet/qlogic/qla3xxx.* QLOGIC QLCNIC (1/10)Gb ETHERNET DRIVER -M: Himanshu Madhani -M: Rajesh Borundia M: Shahed Shaikh -M: Jitendra Kalsaria -M: Sony Chacko -M: Sucheta Chakraborty -M: linux-driver@qlogic.com +M: Dept-HSGLinuxNICDev@qlogic.com L: netdev@vger.kernel.org S: Supported F: drivers/net/ethernet/qlogic/qlcnic/