diff options
Diffstat (limited to 'drivers/net/netxen')
-rw-r--r-- | drivers/net/netxen/netxen_nic.h | 6 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_ethtool.c | 9 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_hdr.h | 8 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_hw.c | 131 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_init.c | 169 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_main.c | 74 |
6 files changed, 276 insertions, 121 deletions
diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index 0f703838e21a..ffa1b9ce1cc5 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -95,6 +95,9 @@ #define ADDR_IN_WINDOW1(off) \ ((off > NETXEN_CRB_PCIX_HOST2) && (off < NETXEN_CRB_MAX)) ? 1 : 0 +#define ADDR_IN_RANGE(addr, low, high) \ + (((addr) < (high)) && ((addr) >= (low))) + /* * normalize a 64MB crb address to 32MB PCI window * To use NETXEN_CRB_NORMALIZE, window _must_ be set to 1 @@ -420,7 +423,6 @@ struct status_desc { } __attribute__ ((aligned(16))); /* UNIFIED ROMIMAGE *************************/ -#define NX_UNI_FW_MIN_SIZE 0xc8000 #define NX_UNI_DIR_SECT_PRODUCT_TBL 0x0 #define NX_UNI_DIR_SECT_BOOTLD 0x6 #define NX_UNI_DIR_SECT_FW 0x7 @@ -1353,6 +1355,8 @@ int netxen_config_rss(struct netxen_adapter *adapter, int enable); int netxen_config_ipaddr(struct netxen_adapter *adapter, u32 ip, int cmd); int netxen_linkevent_request(struct netxen_adapter *adapter, int enable); void netxen_advert_link_change(struct netxen_adapter *adapter, int linkup); +void netxen_pci_camqm_read_2M(struct netxen_adapter *, u64, u64 *); +void netxen_pci_camqm_write_2M(struct netxen_adapter *, u64, u64); int nx_fw_cmd_set_mtu(struct netxen_adapter *adapter, int mtu); int netxen_nic_change_mtu(struct net_device *netdev, int new_mtu); diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c index f8499e56cbee..20f7c58bd092 100644 --- a/drivers/net/netxen/netxen_nic_ethtool.c +++ b/drivers/net/netxen/netxen_nic_ethtool.c @@ -632,6 +632,9 @@ static int netxen_nic_reg_test(struct net_device *dev) if ((data_read & 0xffff) != adapter->pdev->vendor) return 1; + if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) + return 0; + data_written = (u32)0xa5a5a5a5; NXWR32(adapter, CRB_SCRATCHPAD_TEST, data_written); @@ -703,6 +706,11 @@ netxen_nic_get_ethtool_stats(struct net_device *dev, } } +static u32 netxen_nic_get_tx_csum(struct net_device *dev) +{ + return dev->features & NETIF_F_IP_CSUM; +} + static u32 netxen_nic_get_rx_csum(struct net_device *dev) { struct netxen_adapter *adapter = netdev_priv(dev); @@ -909,6 +917,7 @@ const struct ethtool_ops netxen_nic_ethtool_ops = { .set_ringparam = netxen_nic_set_ringparam, .get_pauseparam = netxen_nic_get_pauseparam, .set_pauseparam = netxen_nic_set_pauseparam, + .get_tx_csum = netxen_nic_get_tx_csum, .set_tx_csum = ethtool_op_set_tx_csum, .set_sg = ethtool_op_set_sg, .get_tso = netxen_nic_get_tso, diff --git a/drivers/net/netxen/netxen_nic_hdr.h b/drivers/net/netxen/netxen_nic_hdr.h index 622e4c8be937..d8bd73d7e296 100644 --- a/drivers/net/netxen/netxen_nic_hdr.h +++ b/drivers/net/netxen/netxen_nic_hdr.h @@ -681,14 +681,8 @@ enum { #define MIU_TEST_AGT_ADDR_HI (0x08) #define MIU_TEST_AGT_WRDATA_LO (0x10) #define MIU_TEST_AGT_WRDATA_HI (0x14) -#define MIU_TEST_AGT_WRDATA_UPPER_LO (0x20) -#define MIU_TEST_AGT_WRDATA_UPPER_HI (0x24) -#define MIU_TEST_AGT_WRDATA(i) (0x10+(0x10*((i)>>1))+(4*((i)&1))) #define MIU_TEST_AGT_RDDATA_LO (0x18) #define MIU_TEST_AGT_RDDATA_HI (0x1c) -#define MIU_TEST_AGT_RDDATA_UPPER_LO (0x28) -#define MIU_TEST_AGT_RDDATA_UPPER_HI (0x2c) -#define MIU_TEST_AGT_RDDATA(i) (0x18+(0x10*((i)>>1))+(4*((i)&1))) #define MIU_TEST_AGT_ADDR_MASK 0xfffffff8 #define MIU_TEST_AGT_UPPER_ADDR(off) (0) @@ -789,9 +783,7 @@ enum { * for backward compability */ #define CRB_NIC_CAPABILITIES_HOST NETXEN_NIC_REG(0x1a8) -#define CRB_NIC_CAPABILITIES_FW NETXEN_NIC_REG(0x1dc) #define CRB_NIC_MSI_MODE_HOST NETXEN_NIC_REG(0x270) -#define CRB_NIC_MSI_MODE_FW NETXEN_NIC_REG(0x274) #define INTR_SCHEME_PERPORT 0x1 #define MSI_MODE_MULTIFUNC 0x1 diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index b1cf46a0c48c..5c496f8d7c49 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -32,7 +32,6 @@ #define MASK(n) ((1ULL<<(n))-1) #define MN_WIN(addr) (((addr & 0x1fc0000) >> 1) | ((addr >> 25) & 0x3ff)) #define OCM_WIN(addr) (((addr & 0x1ff0000) >> 1) | ((addr >> 25) & 0x3ff)) -#define OCM_WIN_P3P(addr) (addr & 0xffc0000) #define MS_WIN(addr) (addr & 0x0ffc0000) #define GET_MEM_OFFS_2M(addr) (addr & MASK(18)) @@ -63,9 +62,6 @@ static inline void writeq(u64 val, void __iomem *addr) } #endif -#define ADDR_IN_RANGE(addr, low, high) \ - (((addr) < (high)) && ((addr) >= (low))) - #define PCI_OFFSET_FIRST_RANGE(adapter, off) \ ((adapter)->ahw.pci_base0 + (off)) #define PCI_OFFSET_SECOND_RANGE(adapter, off) \ @@ -538,7 +534,7 @@ netxen_nic_set_mcast_addr(struct netxen_adapter *adapter, void netxen_p2_nic_set_multi(struct net_device *netdev) { struct netxen_adapter *adapter = netdev_priv(netdev); - struct dev_mc_list *mc_ptr; + struct netdev_hw_addr *ha; u8 null_addr[6]; int i; @@ -572,8 +568,8 @@ void netxen_p2_nic_set_multi(struct net_device *netdev) netxen_nic_enable_mcast_filter(adapter); i = 0; - netdev_for_each_mc_addr(mc_ptr, netdev) - netxen_nic_set_mcast_addr(adapter, i++, mc_ptr->dmi_addr); + netdev_for_each_mc_addr(ha, netdev) + netxen_nic_set_mcast_addr(adapter, i++, ha->addr); /* Clear out remaining addresses */ while (i < adapter->max_mc_count) @@ -681,7 +677,7 @@ static int nx_p3_nic_add_mac(struct netxen_adapter *adapter, void netxen_p3_nic_set_multi(struct net_device *netdev) { struct netxen_adapter *adapter = netdev_priv(netdev); - struct dev_mc_list *mc_ptr; + struct netdev_hw_addr *ha; u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; u32 mode = VPORT_MISS_MODE_DROP; LIST_HEAD(del_list); @@ -708,8 +704,8 @@ void netxen_p3_nic_set_multi(struct net_device *netdev) } if (!netdev_mc_empty(netdev)) { - netdev_for_each_mc_addr(mc_ptr, netdev) - nx_p3_nic_add_mac(adapter, mc_ptr->dmi_addr, &del_list); + netdev_for_each_mc_addr(ha, netdev) + nx_p3_nic_add_mac(adapter, ha->addr, &del_list); } send_fw_cmd: @@ -1391,18 +1387,8 @@ netxen_nic_pci_set_window_2M(struct netxen_adapter *adapter, u64 addr, u32 *start) { u32 window; - struct pci_dev *pdev = adapter->pdev; - if ((addr & 0x00ff800) == 0xff800) { - if (printk_ratelimit()) - dev_warn(&pdev->dev, "QM access not handled\n"); - return -EIO; - } - - if (NX_IS_REVISION_P3P(adapter->ahw.revision_id)) - window = OCM_WIN_P3P(addr); - else - window = OCM_WIN(addr); + window = OCM_WIN(addr); writel(window, adapter->ahw.ocm_win_crb); /* read back to flush */ @@ -1419,7 +1405,7 @@ netxen_nic_pci_mem_access_direct(struct netxen_adapter *adapter, u64 off, { void __iomem *addr, *mem_ptr = NULL; resource_size_t mem_base; - int ret = -EIO; + int ret; u32 start; spin_lock(&adapter->ahw.mem_lock); @@ -1428,20 +1414,23 @@ netxen_nic_pci_mem_access_direct(struct netxen_adapter *adapter, u64 off, if (ret != 0) goto unlock; - addr = pci_base_offset(adapter, start); - if (addr) - goto noremap; - - mem_base = pci_resource_start(adapter->pdev, 0) + (start & PAGE_MASK); + if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { + addr = adapter->ahw.pci_base0 + start; + } else { + addr = pci_base_offset(adapter, start); + if (addr) + goto noremap; + + mem_base = pci_resource_start(adapter->pdev, 0) + + (start & PAGE_MASK); + mem_ptr = ioremap(mem_base, PAGE_SIZE); + if (mem_ptr == NULL) { + ret = -EIO; + goto unlock; + } - mem_ptr = ioremap(mem_base, PAGE_SIZE); - if (mem_ptr == NULL) { - ret = -EIO; - goto unlock; + addr = mem_ptr + (start & (PAGE_SIZE-1)); } - - addr = mem_ptr + (start & (PAGE_SIZE - 1)); - noremap: if (op == 0) /* read */ *data = readq(addr); @@ -1456,6 +1445,28 @@ unlock: return ret; } +void +netxen_pci_camqm_read_2M(struct netxen_adapter *adapter, u64 off, u64 *data) +{ + void __iomem *addr = adapter->ahw.pci_base0 + + NETXEN_PCI_CAMQM_2M_BASE + (off - NETXEN_PCI_CAMQM); + + spin_lock(&adapter->ahw.mem_lock); + *data = readq(addr); + spin_unlock(&adapter->ahw.mem_lock); +} + +void +netxen_pci_camqm_write_2M(struct netxen_adapter *adapter, u64 off, u64 data) +{ + void __iomem *addr = adapter->ahw.pci_base0 + + NETXEN_PCI_CAMQM_2M_BASE + (off - NETXEN_PCI_CAMQM); + + spin_lock(&adapter->ahw.mem_lock); + writeq(data, addr); + spin_unlock(&adapter->ahw.mem_lock); +} + #define MAX_CTL_CHECK 1000 static int @@ -1621,9 +1632,8 @@ static int netxen_nic_pci_mem_write_2M(struct netxen_adapter *adapter, u64 off, u64 data) { - int i, j, ret; + int j, ret; u32 temp, off8; - u64 stride; void __iomem *mem_crb; /* Only 64-bit aligned access */ @@ -1650,44 +1660,17 @@ netxen_nic_pci_mem_write_2M(struct netxen_adapter *adapter, return -EIO; correct: - stride = NX_IS_REVISION_P3P(adapter->ahw.revision_id) ? 16 : 8; - - off8 = off & ~(stride-1); + off8 = off & 0xfffffff8; spin_lock(&adapter->ahw.mem_lock); writel(off8, (mem_crb + MIU_TEST_AGT_ADDR_LO)); writel(0, (mem_crb + MIU_TEST_AGT_ADDR_HI)); - i = 0; - if (stride == 16) { - writel(TA_CTL_ENABLE, (mem_crb + TEST_AGT_CTRL)); - writel((TA_CTL_START | TA_CTL_ENABLE), - (mem_crb + TEST_AGT_CTRL)); - - for (j = 0; j < MAX_CTL_CHECK; j++) { - temp = readl(mem_crb + TEST_AGT_CTRL); - if ((temp & TA_CTL_BUSY) == 0) - break; - } - - if (j >= MAX_CTL_CHECK) { - ret = -EIO; - goto done; - } - - i = (off & 0xf) ? 0 : 2; - writel(readl(mem_crb + MIU_TEST_AGT_RDDATA(i)), - mem_crb + MIU_TEST_AGT_WRDATA(i)); - writel(readl(mem_crb + MIU_TEST_AGT_RDDATA(i+1)), - mem_crb + MIU_TEST_AGT_WRDATA(i+1)); - i = (off & 0xf) ? 2 : 0; - } - writel(data & 0xffffffff, - mem_crb + MIU_TEST_AGT_WRDATA(i)); + mem_crb + MIU_TEST_AGT_WRDATA_LO); writel((data >> 32) & 0xffffffff, - mem_crb + MIU_TEST_AGT_WRDATA(i+1)); + mem_crb + MIU_TEST_AGT_WRDATA_HI); writel((TA_CTL_ENABLE | TA_CTL_WRITE), (mem_crb + TEST_AGT_CTRL)); writel((TA_CTL_START | TA_CTL_ENABLE | TA_CTL_WRITE), @@ -1707,7 +1690,6 @@ correct: } else ret = 0; -done: spin_unlock(&adapter->ahw.mem_lock); return ret; @@ -1719,7 +1701,7 @@ netxen_nic_pci_mem_read_2M(struct netxen_adapter *adapter, { int j, ret; u32 temp, off8; - u64 val, stride; + u64 val; void __iomem *mem_crb; /* Only 64-bit aligned access */ @@ -1748,9 +1730,7 @@ netxen_nic_pci_mem_read_2M(struct netxen_adapter *adapter, return -EIO; correct: - stride = NX_IS_REVISION_P3P(adapter->ahw.revision_id) ? 16 : 8; - - off8 = off & ~(stride-1); + off8 = off & 0xfffffff8; spin_lock(&adapter->ahw.mem_lock); @@ -1771,13 +1751,8 @@ correct: "failed to read through agent\n"); ret = -EIO; } else { - off8 = MIU_TEST_AGT_RDDATA_LO; - if ((stride == 16) && (off & 0xf)) - off8 = MIU_TEST_AGT_RDDATA_UPPER_LO; - - temp = readl(mem_crb + off8 + 4); - val = (u64)temp << 32; - val |= readl(mem_crb + off8); + val = (u64)(readl(mem_crb + MIU_TEST_AGT_RDDATA_HI)) << 32; + val |= readl(mem_crb + MIU_TEST_AGT_RDDATA_LO); *data = val; ret = 0; } diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index 02876f59cbb2..045a7c8f5bdf 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -614,22 +614,123 @@ static struct uni_table_desc *nx_get_table_desc(const u8 *unirom, int section) return NULL; } +#define QLCNIC_FILEHEADER_SIZE (14 * 4) + static int -nx_set_product_offs(struct netxen_adapter *adapter) -{ - struct uni_table_desc *ptab_descr; +netxen_nic_validate_header(struct netxen_adapter *adapter) + { const u8 *unirom = adapter->fw->data; - uint32_t i; + struct uni_table_desc *directory = (struct uni_table_desc *) &unirom[0]; + u32 fw_file_size = adapter->fw->size; + u32 tab_size; __le32 entries; + __le32 entry_size; + + if (fw_file_size < QLCNIC_FILEHEADER_SIZE) + return -EINVAL; + + entries = cpu_to_le32(directory->num_entries); + entry_size = cpu_to_le32(directory->entry_size); + tab_size = cpu_to_le32(directory->findex) + (entries * entry_size); + + if (fw_file_size < tab_size) + return -EINVAL; + + return 0; +} + +static int +netxen_nic_validate_bootld(struct netxen_adapter *adapter) +{ + struct uni_table_desc *tab_desc; + struct uni_data_desc *descr; + const u8 *unirom = adapter->fw->data; + __le32 idx = cpu_to_le32(*((int *)&unirom[adapter->file_prd_off] + + NX_UNI_BOOTLD_IDX_OFF)); + u32 offs; + u32 tab_size; + u32 data_size; + + tab_desc = nx_get_table_desc(unirom, NX_UNI_DIR_SECT_BOOTLD); + + if (!tab_desc) + return -EINVAL; + + tab_size = cpu_to_le32(tab_desc->findex) + + (cpu_to_le32(tab_desc->entry_size) * (idx + 1)); + + if (adapter->fw->size < tab_size) + return -EINVAL; + + offs = cpu_to_le32(tab_desc->findex) + + (cpu_to_le32(tab_desc->entry_size) * (idx)); + descr = (struct uni_data_desc *)&unirom[offs]; + + data_size = cpu_to_le32(descr->findex) + cpu_to_le32(descr->size); + + if (adapter->fw->size < data_size) + return -EINVAL; + + return 0; +} + +static int +netxen_nic_validate_fw(struct netxen_adapter *adapter) +{ + struct uni_table_desc *tab_desc; + struct uni_data_desc *descr; + const u8 *unirom = adapter->fw->data; + __le32 idx = cpu_to_le32(*((int *)&unirom[adapter->file_prd_off] + + NX_UNI_FIRMWARE_IDX_OFF)); + u32 offs; + u32 tab_size; + u32 data_size; + + tab_desc = nx_get_table_desc(unirom, NX_UNI_DIR_SECT_FW); + + if (!tab_desc) + return -EINVAL; + + tab_size = cpu_to_le32(tab_desc->findex) + + (cpu_to_le32(tab_desc->entry_size) * (idx + 1)); + + if (adapter->fw->size < tab_size) + return -EINVAL; + + offs = cpu_to_le32(tab_desc->findex) + + (cpu_to_le32(tab_desc->entry_size) * (idx)); + descr = (struct uni_data_desc *)&unirom[offs]; + data_size = cpu_to_le32(descr->findex) + cpu_to_le32(descr->size); + + if (adapter->fw->size < data_size) + return -EINVAL; + return 0; +} + + +static int +netxen_nic_validate_product_offs(struct netxen_adapter *adapter) +{ + struct uni_table_desc *ptab_descr; + const u8 *unirom = adapter->fw->data; int mn_present = (NX_IS_REVISION_P2(adapter->ahw.revision_id)) ? 1 : netxen_p3_has_mn(adapter); + __le32 entries; + __le32 entry_size; + u32 tab_size; + u32 i; ptab_descr = nx_get_table_desc(unirom, NX_UNI_DIR_SECT_PRODUCT_TBL); if (ptab_descr == NULL) - return -1; + return -EINVAL; entries = cpu_to_le32(ptab_descr->num_entries); + entry_size = cpu_to_le32(ptab_descr->entry_size); + tab_size = cpu_to_le32(ptab_descr->findex) + (entries * entry_size); + + if (adapter->fw->size < tab_size) + return -EINVAL; nomn: for (i = 0; i < entries; i++) { @@ -658,9 +759,38 @@ nomn: goto nomn; } - return -1; + return -EINVAL; } +static int +netxen_nic_validate_unified_romimage(struct netxen_adapter *adapter) +{ + if (netxen_nic_validate_header(adapter)) { + dev_err(&adapter->pdev->dev, + "unified image: header validation failed\n"); + return -EINVAL; + } + + if (netxen_nic_validate_product_offs(adapter)) { + dev_err(&adapter->pdev->dev, + "unified image: product validation failed\n"); + return -EINVAL; + } + + if (netxen_nic_validate_bootld(adapter)) { + dev_err(&adapter->pdev->dev, + "unified image: bootld validation failed\n"); + return -EINVAL; + } + + if (netxen_nic_validate_fw(adapter)) { + dev_err(&adapter->pdev->dev, + "unified image: firmware validation failed\n"); + return -EINVAL; + } + + return 0; +} static struct uni_data_desc *nx_get_data_desc(struct netxen_adapter *adapter, u32 section, u32 idx_offset) @@ -890,6 +1020,16 @@ netxen_load_firmware(struct netxen_adapter *adapter) flashaddr += 8; } + + size = (__force u32)nx_get_fw_size(adapter) % 8; + if (size) { + data = cpu_to_le64(ptr64[i]); + + if (adapter->pci_mem_write(adapter, + flashaddr, data)) + return -EIO; + } + } else { u64 data; u32 hi, lo; @@ -934,27 +1074,23 @@ static int netxen_validate_firmware(struct netxen_adapter *adapter) { __le32 val; - u32 ver, min_ver, bios, min_size; + u32 ver, min_ver, bios; struct pci_dev *pdev = adapter->pdev; const struct firmware *fw = adapter->fw; u8 fw_type = adapter->fw_type; if (fw_type == NX_UNIFIED_ROMIMAGE) { - if (nx_set_product_offs(adapter)) + if (netxen_nic_validate_unified_romimage(adapter)) return -EINVAL; - - min_size = NX_UNI_FW_MIN_SIZE; } else { val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_MAGIC_OFFSET]); if ((__force u32)val != NETXEN_BDINFO_MAGIC) return -EINVAL; - min_size = NX_FW_MIN_SIZE; + if (fw->size < NX_FW_MIN_SIZE) + return -EINVAL; } - if (fw->size < min_size) - return -EINVAL; - val = nx_get_fw_version(adapter); if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) @@ -1225,10 +1361,12 @@ int netxen_init_firmware(struct netxen_adapter *adapter) return err; NXWR32(adapter, CRB_NIC_CAPABILITIES_HOST, INTR_SCHEME_PERPORT); - NXWR32(adapter, CRB_NIC_MSI_MODE_HOST, MSI_MODE_MULTIFUNC); NXWR32(adapter, CRB_MPORT_MODE, MPORT_MULTI_FUNCTION_MODE); NXWR32(adapter, CRB_CMDPEG_STATE, PHAN_INITIALIZE_ACK); + if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) + NXWR32(adapter, CRB_NIC_MSI_MODE_HOST, MSI_MODE_MULTIFUNC); + return err; } @@ -1763,6 +1901,5 @@ netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter, void netxen_nic_clear_stats(struct netxen_adapter *adapter) { memset(&adapter->stats, 0, sizeof(adapter->stats)); - return; } diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index ce838f7c8b0f..c61a61f177b7 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -782,15 +782,22 @@ netxen_check_options(struct netxen_adapter *adapter) if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { adapter->msix_supported = !!use_msi_x; adapter->rss_supported = !!use_msi_x; - } else if (adapter->fw_version >= NETXEN_VERSION_CODE(3, 4, 336)) { - switch (adapter->ahw.board_type) { - case NETXEN_BRDTYPE_P2_SB31_10G: - case NETXEN_BRDTYPE_P2_SB31_10G_CX4: - adapter->msix_supported = !!use_msi_x; - adapter->rss_supported = !!use_msi_x; - break; - default: - break; + } else { + u32 flashed_ver = 0; + netxen_rom_fast_read(adapter, + NX_FW_VERSION_OFFSET, (int *)&flashed_ver); + flashed_ver = NETXEN_DECODE_VERSION(flashed_ver); + + if (flashed_ver >= NETXEN_VERSION_CODE(3, 4, 336)) { + switch (adapter->ahw.board_type) { + case NETXEN_BRDTYPE_P2_SB31_10G: + case NETXEN_BRDTYPE_P2_SB31_10G_CX4: + adapter->msix_supported = !!use_msi_x; + adapter->rss_supported = !!use_msi_x; + break; + default: + break; + } } } @@ -2304,6 +2311,7 @@ netxen_fwinit_work(struct work_struct *work) } break; + case NX_DEV_NEED_RESET: case NX_DEV_INITALIZING: if (++adapter->fw_wait_cnt < FW_POLL_THRESH) { netxen_schedule_work(adapter, @@ -2347,6 +2355,9 @@ netxen_detach_work(struct work_struct *work) ref_cnt = nx_decr_dev_ref_cnt(adapter); + if (ref_cnt == -EIO) + goto err_ret; + delay = (ref_cnt == 0) ? 0 : (2 * FW_POLL_DELAY); adapter->fw_wait_cnt = 0; @@ -2526,14 +2537,24 @@ static int netxen_sysfs_validate_crb(struct netxen_adapter *adapter, loff_t offset, size_t size) { + size_t crb_size = 4; + if (!(adapter->flags & NETXEN_NIC_DIAG_ENABLED)) return -EIO; - if ((size != 4) || (offset & 0x3)) - return -EINVAL; + if (offset < NETXEN_PCI_CRBSPACE) { + if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) + return -EINVAL; - if (offset < NETXEN_PCI_CRBSPACE) - return -EINVAL; + if (ADDR_IN_RANGE(offset, NETXEN_PCI_CAMQM, + NETXEN_PCI_CAMQM_2M_END)) + crb_size = 8; + else + return -EINVAL; + } + + if ((size != crb_size) || (offset & (crb_size-1))) + return -EINVAL; return 0; } @@ -2545,14 +2566,23 @@ netxen_sysfs_read_crb(struct kobject *kobj, struct bin_attribute *attr, struct device *dev = container_of(kobj, struct device, kobj); struct netxen_adapter *adapter = dev_get_drvdata(dev); u32 data; + u64 qmdata; int ret; ret = netxen_sysfs_validate_crb(adapter, offset, size); if (ret != 0) return ret; - data = NXRD32(adapter, offset); - memcpy(buf, &data, size); + if (NX_IS_REVISION_P3(adapter->ahw.revision_id) && + ADDR_IN_RANGE(offset, NETXEN_PCI_CAMQM, + NETXEN_PCI_CAMQM_2M_END)) { + netxen_pci_camqm_read_2M(adapter, offset, &qmdata); + memcpy(buf, &qmdata, size); + } else { + data = NXRD32(adapter, offset); + memcpy(buf, &data, size); + } + return size; } @@ -2563,14 +2593,23 @@ netxen_sysfs_write_crb(struct kobject *kobj, struct bin_attribute *attr, struct device *dev = container_of(kobj, struct device, kobj); struct netxen_adapter *adapter = dev_get_drvdata(dev); u32 data; + u64 qmdata; int ret; ret = netxen_sysfs_validate_crb(adapter, offset, size); if (ret != 0) return ret; - memcpy(&data, buf, size); - NXWR32(adapter, offset, data); + if (NX_IS_REVISION_P3(adapter->ahw.revision_id) && + ADDR_IN_RANGE(offset, NETXEN_PCI_CAMQM, + NETXEN_PCI_CAMQM_2M_END)) { + memcpy(&qmdata, buf, size); + netxen_pci_camqm_write_2M(adapter, offset, qmdata); + } else { + memcpy(&data, buf, size); + NXWR32(adapter, offset, data); + } + return size; } @@ -2742,7 +2781,6 @@ netxen_config_indev_addr(struct net_device *dev, unsigned long event) } endfor_ifa(indev); in_dev_put(indev); - return; } static int netxen_netdev_event(struct notifier_block *this, |