diff options
Diffstat (limited to 'drivers/net/netxen')
-rw-r--r-- | drivers/net/netxen/netxen_nic.h | 36 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_ethtool.c | 2 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_hdr.h | 76 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_hw.c | 857 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_init.c | 66 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_main.c | 277 |
6 files changed, 716 insertions, 598 deletions
diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index 7384f59df61..e98cfa6baa8 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -53,8 +53,8 @@ #define _NETXEN_NIC_LINUX_MAJOR 4 #define _NETXEN_NIC_LINUX_MINOR 0 -#define _NETXEN_NIC_LINUX_SUBVERSION 50 -#define NETXEN_NIC_LINUX_VERSIONID "4.0.50" +#define _NETXEN_NIC_LINUX_SUBVERSION 62 +#define NETXEN_NIC_LINUX_VERSIONID "4.0.62" #define NETXEN_VERSION_CODE(a, b, c) (((a) << 24) + ((b) << 16) + (c)) #define _major(v) (((v) >> 24) & 0xff) @@ -117,9 +117,11 @@ #define NX_P3_B0 0x40 #define NX_P3_B1 0x41 #define NX_P3_B2 0x42 +#define NX_P3P_A0 0x50 #define NX_IS_REVISION_P2(REVISION) (REVISION <= NX_P2_C1) #define NX_IS_REVISION_P3(REVISION) (REVISION >= NX_P3_A0) +#define NX_IS_REVISION_P3P(REVISION) (REVISION >= NX_P3P_A0) #define FIRST_PAGE_GROUP_START 0 #define FIRST_PAGE_GROUP_END 0x100000 @@ -543,13 +545,16 @@ struct netxen_hardware_context { void __iomem *pci_base1; void __iomem *pci_base2; void __iomem *db_base; + void __iomem *ocm_win_crb; + unsigned long db_len; unsigned long pci_len0; - int qdr_sn_window; - int ddr_mn_window; - u32 mn_win_crb; - u32 ms_win_crb; + u32 ocm_win; + u32 crb_win; + + rwlock_t crb_lock; + spinlock_t mem_lock; u8 cut_through; u8 revision_id; @@ -1039,6 +1044,9 @@ typedef struct { #define LINKEVENT_LINKSPEED_MBPS 0 #define LINKEVENT_LINKSPEED_ENCODED 1 +#define AUTO_FW_RESET_ENABLED 0xEF10AF12 +#define AUTO_FW_RESET_DISABLED 0xDCBAAF12 + /* firmware response header: * 63:58 - message type * 57:56 - owner @@ -1086,6 +1094,7 @@ typedef struct { #define NETXEN_NIC_MSIX_ENABLED 0x04 #define NETXEN_NIC_LRO_ENABLED 0x08 #define NETXEN_NIC_BRIDGE_ENABLED 0X10 +#define NETXEN_NIC_DIAG_ENABLED 0x20 #define NETXEN_IS_MSI_FAMILY(adapter) \ ((adapter)->flags & (NETXEN_NIC_MSI_ENABLED | NETXEN_NIC_MSIX_ENABLED)) @@ -1115,10 +1124,6 @@ struct netxen_adapter { struct pci_dev *pdev; struct list_head mac_list; - u32 curr_window; - u32 crb_win; - rwlock_t adapter_lock; - spinlock_t tx_clean_lock; u16 num_txd; @@ -1180,11 +1185,10 @@ struct netxen_adapter { u32 (*crb_read)(struct netxen_adapter *, ulong); int (*crb_write)(struct netxen_adapter *, ulong, u32); - int (*pci_mem_read)(struct netxen_adapter *, u64, void *, int); - int (*pci_mem_write)(struct netxen_adapter *, u64, void *, int); + int (*pci_mem_read)(struct netxen_adapter *, u64, u64 *); + int (*pci_mem_write)(struct netxen_adapter *, u64, u64); - unsigned long (*pci_set_window)(struct netxen_adapter *, - unsigned long long); + int (*pci_set_window)(struct netxen_adapter *, u64, u32 *); u32 (*io_read)(struct netxen_adapter *, void __iomem *); void (*io_write)(struct netxen_adapter *, void __iomem *, u32); @@ -1203,8 +1207,6 @@ struct netxen_adapter { struct work_struct tx_timeout_task; - struct net_device_stats net_stats; - nx_nic_intr_coalesce_t coal; unsigned long state; @@ -1271,7 +1273,7 @@ int netxen_load_firmware(struct netxen_adapter *adapter); int netxen_need_fw_reset(struct netxen_adapter *adapter); void netxen_request_firmware(struct netxen_adapter *adapter); void netxen_release_firmware(struct netxen_adapter *adapter); -int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose); +int netxen_pinit_from_rom(struct netxen_adapter *adapter); int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp); int netxen_rom_fast_read_words(struct netxen_adapter *adapter, int addr, diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c index 714f38791a9..a3b18e0c967 100644 --- a/drivers/net/netxen/netxen_nic_ethtool.c +++ b/drivers/net/netxen/netxen_nic_ethtool.c @@ -85,11 +85,9 @@ netxen_nic_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo) strncpy(drvinfo->driver, netxen_nic_driver_name, 32); strncpy(drvinfo->version, NETXEN_NIC_LINUX_VERSIONID, 32); - read_lock(&adapter->adapter_lock); fw_major = NXRD32(adapter, NETXEN_FW_VERSION_MAJOR); fw_minor = NXRD32(adapter, NETXEN_FW_VERSION_MINOR); fw_build = NXRD32(adapter, NETXEN_FW_VERSION_SUB); - read_unlock(&adapter->adapter_lock); sprintf(drvinfo->fw_version, "%d.%d.%d", fw_major, fw_minor, fw_build); strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32); diff --git a/drivers/net/netxen/netxen_nic_hdr.h b/drivers/net/netxen/netxen_nic_hdr.h index 1c46da63212..a39155d61ba 100644 --- a/drivers/net/netxen/netxen_nic_hdr.h +++ b/drivers/net/netxen/netxen_nic_hdr.h @@ -662,40 +662,51 @@ enum { #define NETXEN_NIU_AP_STATION_ADDR_0(I) (NETXEN_CRB_NIU+0xa0040+(I)*0x10000) #define NETXEN_NIU_AP_STATION_ADDR_1(I) (NETXEN_CRB_NIU+0xa0044+(I)*0x10000) + +#define TEST_AGT_CTRL (0x00) + +#define TA_CTL_START 1 +#define TA_CTL_ENABLE 2 +#define TA_CTL_WRITE 4 +#define TA_CTL_BUSY 8 + /* * Register offsets for MN */ -#define MIU_CONTROL (0x000) -#define MIU_TEST_AGT_CTRL (0x090) -#define MIU_TEST_AGT_ADDR_LO (0x094) -#define MIU_TEST_AGT_ADDR_HI (0x098) -#define MIU_TEST_AGT_WRDATA_LO (0x0a0) -#define MIU_TEST_AGT_WRDATA_HI (0x0a4) -#define MIU_TEST_AGT_WRDATA(i) (0x0a0+(4*(i))) -#define MIU_TEST_AGT_RDDATA_LO (0x0a8) -#define MIU_TEST_AGT_RDDATA_HI (0x0ac) -#define MIU_TEST_AGT_RDDATA(i) (0x0a8+(4*(i))) -#define MIU_TEST_AGT_ADDR_MASK 0xfffffff8 -#define MIU_TEST_AGT_UPPER_ADDR(off) (0) - -/* MIU_TEST_AGT_CTRL flags. work for SIU as well */ -#define MIU_TA_CTL_START 1 -#define MIU_TA_CTL_ENABLE 2 -#define MIU_TA_CTL_WRITE 4 -#define MIU_TA_CTL_BUSY 8 - -#define SIU_TEST_AGT_CTRL (0x060) -#define SIU_TEST_AGT_ADDR_LO (0x064) -#define SIU_TEST_AGT_ADDR_HI (0x078) -#define SIU_TEST_AGT_WRDATA_LO (0x068) -#define SIU_TEST_AGT_WRDATA_HI (0x06c) -#define SIU_TEST_AGT_WRDATA(i) (0x068+(4*(i))) -#define SIU_TEST_AGT_RDDATA_LO (0x070) -#define SIU_TEST_AGT_RDDATA_HI (0x074) -#define SIU_TEST_AGT_RDDATA(i) (0x070+(4*(i))) - -#define SIU_TEST_AGT_ADDR_MASK 0x3ffff8 -#define SIU_TEST_AGT_UPPER_ADDR(off) ((off)>>22) +#define MIU_TEST_AGT_BASE (0x90) + +#define MIU_TEST_AGT_ADDR_LO (0x04) +#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) + +/* + * Register offsets for MS + */ +#define SIU_TEST_AGT_BASE (0x60) + +#define SIU_TEST_AGT_ADDR_LO (0x04) +#define SIU_TEST_AGT_ADDR_HI (0x18) +#define SIU_TEST_AGT_WRDATA_LO (0x08) +#define SIU_TEST_AGT_WRDATA_HI (0x0c) +#define SIU_TEST_AGT_WRDATA(i) (0x08+(4*(i))) +#define SIU_TEST_AGT_RDDATA_LO (0x10) +#define SIU_TEST_AGT_RDDATA_HI (0x14) +#define SIU_TEST_AGT_RDDATA(i) (0x10+(4*(i))) + +#define SIU_TEST_AGT_ADDR_MASK 0x3ffff8 +#define SIU_TEST_AGT_UPPER_ADDR(off) ((off)>>22) /* XG Link status */ #define XG_LINK_UP 0x10 @@ -857,6 +868,9 @@ enum { (PCIX_SN_WINDOW_F0 + (0x20 * (func))) :\ (PCIX_SN_WINDOW_F4 + (0x10 * ((func)-4)))) +#define PCIX_OCM_WINDOW (0x10800) +#define PCIX_OCM_WINDOW_REG(func) (PCIX_OCM_WINDOW + 0x20 * (func)) + #define PCIX_TARGET_STATUS (0x10118) #define PCIX_TARGET_STATUS_F1 (0x10160) #define PCIX_TARGET_STATUS_F2 (0x10164) diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index 3185a98b091..69205ace16e 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -31,6 +31,7 @@ #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)) @@ -41,6 +42,11 @@ #define CRB_HI(off) ((crb_hub_agt[CRB_BLK(off)] << 20) | ((off) & 0xf0000)) #define CRB_INDIRECT_2M (0x1e0000UL) +static void netxen_nic_io_write_128M(struct netxen_adapter *adapter, + void __iomem *addr, u32 data); +static u32 netxen_nic_io_read_128M(struct netxen_adapter *adapter, + void __iomem *addr); + #ifndef readq static inline u64 readq(void __iomem *addr) { @@ -326,7 +332,7 @@ netxen_pcie_sem_lock(struct netxen_adapter *adapter, int sem, u32 id_reg) if (done == 1) break; if (++timeout >= NETXEN_PCIE_SEM_TIMEOUT) - return -1; + return -EIO; msleep(1); } @@ -1046,50 +1052,38 @@ int netxen_p3_get_mac_addr(struct netxen_adapter *adapter, __le64 *mac) * Changes the CRB window to the specified window. */ static void -netxen_nic_pci_change_crbwindow_128M(struct netxen_adapter *adapter, u32 wndw) +netxen_nic_pci_set_crbwindow_128M(struct netxen_adapter *adapter, + u32 window) { void __iomem *offset; - u32 tmp; - int count = 0; - uint8_t func = adapter->ahw.pci_func; + int count = 10; + u8 func = adapter->ahw.pci_func; - if (adapter->curr_window == wndw) + if (adapter->ahw.crb_win == window) return; - /* - * Move the CRB window. - * We need to write to the "direct access" region of PCI - * to avoid a race condition where the window register has - * not been successfully written across CRB before the target - * register address is received by PCI. The direct region bypasses - * the CRB bus. - */ + offset = PCI_OFFSET_SECOND_RANGE(adapter, NETXEN_PCIX_PH_REG(PCIE_CRB_WINDOW_REG(func))); - if (wndw & 0x1) - wndw = NETXEN_WINDOW_ONE; + writel(window, offset); + do { + if (window == readl(offset)) + break; - writel(wndw, offset); + if (printk_ratelimit()) + dev_warn(&adapter->pdev->dev, + "failed to set CRB window to %d\n", + (window == NETXEN_WINDOW_ONE)); + udelay(1); - /* MUST make sure window is set before we forge on... */ - while ((tmp = readl(offset)) != wndw) { - printk(KERN_WARNING "%s: %s WARNING: CRB window value not " - "registered properly: 0x%08x.\n", - netxen_nic_driver_name, __func__, tmp); - mdelay(1); - if (count >= 10) - break; - count++; - } + } while (--count > 0); - if (wndw == NETXEN_WINDOW_ONE) - adapter->curr_window = 1; - else - adapter->curr_window = 0; + if (count > 0) + adapter->ahw.crb_win = window; } /* - * Return -1 if off is not valid, + * Returns < 0 if off is not valid, * 1 if window access is needed. 'off' is set to offset from * CRB space in 128M pci map * 0 if no window access is needed. 'off' is set to 2M addr @@ -1102,7 +1096,7 @@ netxen_nic_pci_get_crb_addr_2M(struct netxen_adapter *adapter, ulong *off) if (*off >= NETXEN_CRB_MAX) - return -1; + return -EINVAL; if (*off >= NETXEN_PCI_CAMQM && (*off < NETXEN_PCI_CAMQM_2M_END)) { *off = (*off - NETXEN_PCI_CAMQM) + NETXEN_PCI_CAMQM_2M_BASE + @@ -1111,7 +1105,7 @@ netxen_nic_pci_get_crb_addr_2M(struct netxen_adapter *adapter, ulong *off) } if (*off < NETXEN_PCI_CRBSPACE) - return -1; + return -EINVAL; *off -= NETXEN_PCI_CRBSPACE; @@ -1140,20 +1134,24 @@ netxen_nic_pci_get_crb_addr_2M(struct netxen_adapter *adapter, ulong *off) static void netxen_nic_pci_set_crbwindow_2M(struct netxen_adapter *adapter, ulong *off) { - u32 win_read; + u32 window; + void __iomem *addr = adapter->ahw.pci_base0 + CRB_WINDOW_2M; - adapter->crb_win = CRB_HI(*off); - writel(adapter->crb_win, (adapter->ahw.pci_base0 + CRB_WINDOW_2M)); - /* - * Read back value to make sure write has gone through before trying - * to use it. - */ - win_read = readl(adapter->ahw.pci_base0 + CRB_WINDOW_2M); - if (win_read != adapter->crb_win) { - printk(KERN_ERR "%s: Written crbwin (0x%x) != " - "Read crbwin (0x%x), off=0x%lx\n", - __func__, adapter->crb_win, win_read, *off); + window = CRB_HI(*off); + + if (adapter->ahw.crb_win == window) + goto done; + + writel(window, addr); + if (readl(addr) != window) { + if (printk_ratelimit()) + dev_warn(&adapter->pdev->dev, + "failed to set CRB window to %d off 0x%lx\n", + window, *off); } + adapter->ahw.crb_win = window; + +done: *off = (*off & MASK(16)) + CRB_INDIRECT_2M + (ulong)adapter->ahw.pci_base0; } @@ -1172,16 +1170,15 @@ netxen_nic_hw_write_wx_128M(struct netxen_adapter *adapter, ulong off, u32 data) BUG_ON(!addr); if (ADDR_IN_WINDOW1(off)) { /* Window 1 */ - read_lock(&adapter->adapter_lock); - writel(data, addr); - read_unlock(&adapter->adapter_lock); + netxen_nic_io_write_128M(adapter, addr, data); } else { /* Window 0 */ - write_lock_irqsave(&adapter->adapter_lock, flags); + write_lock_irqsave(&adapter->ahw.crb_lock, flags); addr = pci_base_offset(adapter, off); - netxen_nic_pci_change_crbwindow_128M(adapter, 0); + netxen_nic_pci_set_crbwindow_128M(adapter, 0); writel(data, addr); - netxen_nic_pci_change_crbwindow_128M(adapter, 1); - write_unlock_irqrestore(&adapter->adapter_lock, flags); + netxen_nic_pci_set_crbwindow_128M(adapter, + NETXEN_WINDOW_ONE); + write_unlock_irqrestore(&adapter->ahw.crb_lock, flags); } return 0; @@ -1202,15 +1199,14 @@ netxen_nic_hw_read_wx_128M(struct netxen_adapter *adapter, ulong off) BUG_ON(!addr); if (ADDR_IN_WINDOW1(off)) { /* Window 1 */ - read_lock(&adapter->adapter_lock); - data = readl(addr); - read_unlock(&adapter->adapter_lock); + data = netxen_nic_io_read_128M(adapter, addr); } else { /* Window 0 */ - write_lock_irqsave(&adapter->adapter_lock, flags); - netxen_nic_pci_change_crbwindow_128M(adapter, 0); + write_lock_irqsave(&adapter->ahw.crb_lock, flags); + netxen_nic_pci_set_crbwindow_128M(adapter, 0); data = readl(addr); - netxen_nic_pci_change_crbwindow_128M(adapter, 1); - write_unlock_irqrestore(&adapter->adapter_lock, flags); + netxen_nic_pci_set_crbwindow_128M(adapter, + NETXEN_WINDOW_ONE); + write_unlock_irqrestore(&adapter->ahw.crb_lock, flags); } return data; @@ -1224,25 +1220,26 @@ netxen_nic_hw_write_wx_2M(struct netxen_adapter *adapter, ulong off, u32 data) rv = netxen_nic_pci_get_crb_addr_2M(adapter, &off); - if (rv == -1) { - printk(KERN_ERR "%s: invalid offset: 0x%016lx\n", - __func__, off); - dump_stack(); - return -1; + if (rv == 0) { + writel(data, (void __iomem *)off); + return 0; } - if (rv == 1) { - write_lock_irqsave(&adapter->adapter_lock, flags); + if (rv > 0) { + /* indirect access */ + write_lock_irqsave(&adapter->ahw.crb_lock, flags); crb_win_lock(adapter); netxen_nic_pci_set_crbwindow_2M(adapter, &off); writel(data, (void __iomem *)off); crb_win_unlock(adapter); - write_unlock_irqrestore(&adapter->adapter_lock, flags); - } else - writel(data, (void __iomem *)off); - + write_unlock_irqrestore(&adapter->ahw.crb_lock, flags); + return 0; + } - return 0; + dev_err(&adapter->pdev->dev, + "%s: invalid offset: 0x%016lx\n", __func__, off); + dump_stack(); + return -EIO; } static u32 @@ -1254,99 +1251,33 @@ netxen_nic_hw_read_wx_2M(struct netxen_adapter *adapter, ulong off) rv = netxen_nic_pci_get_crb_addr_2M(adapter, &off); - if (rv == -1) { - printk(KERN_ERR "%s: invalid offset: 0x%016lx\n", - __func__, off); - dump_stack(); - return -1; - } + if (rv == 0) + return readl((void __iomem *)off); - if (rv == 1) { - write_lock_irqsave(&adapter->adapter_lock, flags); + if (rv > 0) { + /* indirect access */ + write_lock_irqsave(&adapter->ahw.crb_lock, flags); crb_win_lock(adapter); netxen_nic_pci_set_crbwindow_2M(adapter, &off); data = readl((void __iomem *)off); crb_win_unlock(adapter); - write_unlock_irqrestore(&adapter->adapter_lock, flags); - } else - data = readl((void __iomem *)off); - - return data; -} - -static int netxen_pci_set_window_warning_count; - -static unsigned long -netxen_nic_pci_set_window_128M(struct netxen_adapter *adapter, - unsigned long long addr) -{ - void __iomem *offset; - int window; - unsigned long long qdr_max; - uint8_t func = adapter->ahw.pci_func; - - if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { - qdr_max = NETXEN_ADDR_QDR_NET_MAX_P2; - } else { - qdr_max = NETXEN_ADDR_QDR_NET_MAX_P3; + write_unlock_irqrestore(&adapter->ahw.crb_lock, flags); + return data; } - if (ADDR_IN_RANGE(addr, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) { - /* DDR network side */ - addr -= NETXEN_ADDR_DDR_NET; - window = (addr >> 25) & 0x3ff; - if (adapter->ahw.ddr_mn_window != window) { - adapter->ahw.ddr_mn_window = window; - offset = PCI_OFFSET_SECOND_RANGE(adapter, - NETXEN_PCIX_PH_REG(PCIE_MN_WINDOW_REG(func))); - writel(window, offset); - /* MUST make sure window is set before we forge on... */ - readl(offset); - } - addr -= (window * NETXEN_WINDOW_ONE); - addr += NETXEN_PCI_DDR_NET; - } else if (ADDR_IN_RANGE(addr, NETXEN_ADDR_OCM0, NETXEN_ADDR_OCM0_MAX)) { - addr -= NETXEN_ADDR_OCM0; - addr += NETXEN_PCI_OCM0; - } else if (ADDR_IN_RANGE(addr, NETXEN_ADDR_OCM1, NETXEN_ADDR_OCM1_MAX)) { - addr -= NETXEN_ADDR_OCM1; - addr += NETXEN_PCI_OCM1; - } else if (ADDR_IN_RANGE(addr, NETXEN_ADDR_QDR_NET, qdr_max)) { - /* QDR network side */ - addr -= NETXEN_ADDR_QDR_NET; - window = (addr >> 22) & 0x3f; - if (adapter->ahw.qdr_sn_window != window) { - adapter->ahw.qdr_sn_window = window; - offset = PCI_OFFSET_SECOND_RANGE(adapter, - NETXEN_PCIX_PH_REG(PCIE_SN_WINDOW_REG(func))); - writel((window << 22), offset); - /* MUST make sure window is set before we forge on... */ - readl(offset); - } - addr -= (window * 0x400000); - addr += NETXEN_PCI_QDR_NET; - } else { - /* - * peg gdb frequently accesses memory that doesn't exist, - * this limits the chit chat so debugging isn't slowed down. - */ - if ((netxen_pci_set_window_warning_count++ < 8) - || (netxen_pci_set_window_warning_count % 64 == 0)) - printk("%s: Warning:netxen_nic_pci_set_window()" - " Unknown address range!\n", - netxen_nic_driver_name); - addr = -1UL; - } - return addr; + dev_err(&adapter->pdev->dev, + "%s: invalid offset: 0x%016lx\n", __func__, off); + dump_stack(); + return -1; } /* window 1 registers only */ static void netxen_nic_io_write_128M(struct netxen_adapter *adapter, void __iomem *addr, u32 data) { - read_lock(&adapter->adapter_lock); + read_lock(&adapter->ahw.crb_lock); writel(data, addr); - read_unlock(&adapter->adapter_lock); + read_unlock(&adapter->ahw.crb_lock); } static u32 netxen_nic_io_read_128M(struct netxen_adapter *adapter, @@ -1354,9 +1285,9 @@ static u32 netxen_nic_io_read_128M(struct netxen_adapter *adapter, { u32 val; - read_lock(&adapter->adapter_lock); + read_lock(&adapter->ahw.crb_lock); val = readl(addr); - read_unlock(&adapter->adapter_lock); + read_unlock(&adapter->ahw.crb_lock); return val; } @@ -1389,475 +1320,421 @@ netxen_get_ioaddr(struct netxen_adapter *adapter, u32 offset) return (void __iomem *)off; } -static unsigned long -netxen_nic_pci_set_window_2M(struct netxen_adapter *adapter, - unsigned long long addr) +static int +netxen_nic_pci_set_window_128M(struct netxen_adapter *adapter, + u64 addr, u32 *start) { - int window; - u32 win_read; - - if (ADDR_IN_RANGE(addr, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) { - /* DDR network side */ - window = MN_WIN(addr); - adapter->ahw.ddr_mn_window = window; - NXWR32(adapter, adapter->ahw.mn_win_crb, window); - win_read = NXRD32(adapter, adapter->ahw.mn_win_crb); - if ((win_read << 17) != window) { - printk(KERN_INFO "Written MNwin (0x%x) != " - "Read MNwin (0x%x)\n", window, win_read); - } - addr = GET_MEM_OFFS_2M(addr) + NETXEN_PCI_DDR_NET; + if (ADDR_IN_RANGE(addr, NETXEN_ADDR_OCM0, NETXEN_ADDR_OCM0_MAX)) { + *start = (addr - NETXEN_ADDR_OCM0 + NETXEN_PCI_OCM0); + return 0; } else if (ADDR_IN_RANGE(addr, - NETXEN_ADDR_OCM0, NETXEN_ADDR_OCM0_MAX)) { - if ((addr & 0x00ff800) == 0xff800) { - printk("%s: QM access not handled.\n", __func__); - addr = -1UL; - } + NETXEN_ADDR_OCM1, NETXEN_ADDR_OCM1_MAX)) { + *start = (addr - NETXEN_ADDR_OCM1 + NETXEN_PCI_OCM1); + return 0; + } + return -EIO; +} + +static int +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); - adapter->ahw.ddr_mn_window = window; - NXWR32(adapter, adapter->ahw.mn_win_crb, window); - win_read = NXRD32(adapter, adapter->ahw.mn_win_crb); - if ((win_read >> 7) != window) { - printk(KERN_INFO "%s: Written OCMwin (0x%x) != " - "Read OCMwin (0x%x)\n", - __func__, window, win_read); - } - addr = GET_MEM_OFFS_2M(addr) + NETXEN_PCI_OCM0_2M; - } else if (ADDR_IN_RANGE(addr, - NETXEN_ADDR_QDR_NET, NETXEN_ADDR_QDR_NET_MAX_P3)) { - /* QDR network side */ - window = MS_WIN(addr); - adapter->ahw.qdr_sn_window = window; - NXWR32(adapter, adapter->ahw.ms_win_crb, window); - win_read = NXRD32(adapter, adapter->ahw.ms_win_crb); - if (win_read != window) { - printk(KERN_INFO "%s: Written MSwin (0x%x) != " - "Read MSwin (0x%x)\n", - __func__, window, win_read); - } - addr = GET_MEM_OFFS_2M(addr) + NETXEN_PCI_QDR_NET; + writel(window, adapter->ahw.ocm_win_crb); + /* read back to flush */ + readl(adapter->ahw.ocm_win_crb); - } else { - /* - * peg gdb frequently accesses memory that doesn't exist, - * this limits the chit chat so debugging isn't slowed down. - */ - if ((netxen_pci_set_window_warning_count++ < 8) - || (netxen_pci_set_window_warning_count%64 == 0)) { - printk("%s: Warning:%s Unknown address range!\n", - __func__, netxen_nic_driver_name); + adapter->ahw.ocm_win = window; + *start = NETXEN_PCI_OCM0_2M + GET_MEM_OFFS_2M(addr); + return 0; } - addr = -1UL; + +static int +netxen_nic_pci_mem_access_direct(struct netxen_adapter *adapter, u64 off, + u64 *data, int op) +{ + void __iomem *addr, *mem_ptr = NULL; + resource_size_t mem_base; + int ret = -EIO; + u32 start; + + spin_lock(&adapter->ahw.mem_lock); + + ret = adapter->pci_set_window(adapter, off, &start); + 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); + + mem_ptr = ioremap(mem_base, PAGE_SIZE); + if (mem_ptr == NULL) { + ret = -EIO; + goto unlock; } - return addr; + + addr = mem_ptr + (start & (PAGE_SIZE - 1)); + +noremap: + if (op == 0) /* read */ + *data = readq(addr); + else /* write */ + writeq(*data, addr); + +unlock: + spin_unlock(&adapter->ahw.mem_lock); + + if (mem_ptr) + iounmap(mem_ptr); + return ret; } #define MAX_CTL_CHECK 1000 static int netxen_nic_pci_mem_write_128M(struct netxen_adapter *adapter, - u64 off, void *data, int size) + u64 off, u64 data) { - unsigned long flags; - int i, j, ret = 0, loop, sz[2], off0; - uint32_t temp; - uint64_t off8, tmpw, word[2] = {0, 0}; + int j, ret; + u32 temp, off_lo, off_hi, addr_hi, data_hi, data_lo; void __iomem *mem_crb; - if (size != 8) + /* Only 64-bit aligned access */ + if (off & 7) return -EIO; + /* P2 has different SIU and MIU test agent base addr */ if (ADDR_IN_RANGE(off, NETXEN_ADDR_QDR_NET, NETXEN_ADDR_QDR_NET_MAX_P2)) { - mem_crb = pci_base_offset(adapter, NETXEN_CRB_QDR_NET); + mem_crb = pci_base_offset(adapter, + NETXEN_CRB_QDR_NET+SIU_TEST_AGT_BASE); + addr_hi = SIU_TEST_AGT_ADDR_HI; + data_lo = SIU_TEST_AGT_WRDATA_LO; + data_hi = SIU_TEST_AGT_WRDATA_HI; + off_lo = off & SIU_TEST_AGT_ADDR_MASK; + off_hi = SIU_TEST_AGT_UPPER_ADDR(off); goto correct; } if (ADDR_IN_RANGE(off, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) { - mem_crb = pci_base_offset(adapter, NETXEN_CRB_DDR_NET); + mem_crb = pci_base_offset(adapter, + NETXEN_CRB_DDR_NET+MIU_TEST_AGT_BASE); + addr_hi = MIU_TEST_AGT_ADDR_HI; + data_lo = MIU_TEST_AGT_WRDATA_LO; + data_hi = MIU_TEST_AGT_WRDATA_HI; + off_lo = off & MIU_TEST_AGT_ADDR_MASK; + off_hi = 0; goto correct; } - return -EIO; - -correct: - off8 = off & 0xfffffff8; - off0 = off & 0x7; - sz[0] = (size < (8 - off0)) ? size : (8 - off0); - sz[1] = size - sz[0]; - loop = ((off0 + size - 1) >> 3) + 1; - - if ((size != 8) || (off0 != 0)) { - for (i = 0; i < loop; i++) { - if (adapter->pci_mem_read(adapter, - off8 + (i << 3), &word[i], 8)) - return -1; + if (ADDR_IN_RANGE(off, NETXEN_ADDR_OCM0, NETXEN_ADDR_OCM0_MAX) || + ADDR_IN_RANGE(off, NETXEN_ADDR_OCM1, NETXEN_ADDR_OCM1_MAX)) { + if (adapter->ahw.pci_len0 != 0) { + return netxen_nic_pci_mem_access_direct(adapter, + off, &data, 1); } } - switch (size) { - case 1: - tmpw = *((uint8_t *)data); - break; - case 2: - tmpw = *((uint16_t *)data); - break; - case 4: - tmpw = *((uint32_t *)data); - break; - case 8: - default: - tmpw = *((uint64_t *)data); - break; - } - word[0] &= ~((~(~0ULL << (sz[0] * 8))) << (off0 * 8)); - word[0] |= tmpw << (off0 * 8); + return -EIO; - if (loop == 2) { - word[1] &= ~(~0ULL << (sz[1] * 8)); - word[1] |= tmpw >> (sz[0] * 8); +correct: + spin_lock(&adapter->ahw.mem_lock); + netxen_nic_pci_set_crbwindow_128M(adapter, 0); + + writel(off_lo, (mem_crb + MIU_TEST_AGT_ADDR_LO)); + writel(off_hi, (mem_crb + addr_hi)); + writel(data & 0xffffffff, (mem_crb + data_lo)); + writel((data >> 32) & 0xffffffff, (mem_crb + data_hi)); + writel((TA_CTL_ENABLE | TA_CTL_WRITE), (mem_crb + TEST_AGT_CTRL)); + writel((TA_CTL_START | TA_CTL_ENABLE | TA_CTL_WRITE), + (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; } - write_lock_irqsave(&adapter->adapter_lock, flags); - netxen_nic_pci_change_crbwindow_128M(adapter, 0); - - for (i = 0; i < loop; i++) { - writel((uint32_t)(off8 + (i << 3)), - (mem_crb+MIU_TEST_AGT_ADDR_LO)); - writel(0, - (mem_crb+MIU_TEST_AGT_ADDR_HI)); - writel(word[i] & 0xffffffff, - (mem_crb+MIU_TEST_AGT_WRDATA_LO)); - writel((word[i] >> 32) & 0xffffffff, - (mem_crb+MIU_TEST_AGT_WRDATA_HI)); - writel(MIU_TA_CTL_ENABLE|MIU_TA_CTL_WRITE, - (mem_crb+MIU_TEST_AGT_CTRL)); - writel(MIU_TA_CTL_START|MIU_TA_CTL_ENABLE|MIU_TA_CTL_WRITE, - (mem_crb+MIU_TEST_AGT_CTRL)); - - for (j = 0; j < MAX_CTL_CHECK; j++) { - temp = readl( - (mem_crb+MIU_TEST_AGT_CTRL)); - if ((temp & MIU_TA_CTL_BUSY) == 0) - break; - } - - if (j >= MAX_CTL_CHECK) { - if (printk_ratelimit()) - dev_err(&adapter->pdev->dev, + if (j >= MAX_CTL_CHECK) { + if (printk_ratelimit()) + dev_err(&adapter->pdev->dev, "failed to write through agent\n"); - ret = -1; - break; - } - } + ret = -EIO; + } else + ret = 0; - netxen_nic_pci_change_crbwindow_128M(adapter, 1); - write_unlock_irqrestore(&adapter->adapter_lock, flags); + netxen_nic_pci_set_crbwindow_128M(adapter, NETXEN_WINDOW_ONE); + spin_unlock(&adapter->ahw.mem_lock); return ret; } static int netxen_nic_pci_mem_read_128M(struct netxen_adapter *adapter, - u64 off, void *data, int size) + u64 off, u64 *data) { - unsigned long flags; - int i, j = 0, k, start, end, loop, sz[2], off0[2]; - uint32_t temp; - uint64_t off8, val, word[2] = {0, 0}; + int j, ret; + u32 temp, off_lo, off_hi, addr_hi, data_hi, data_lo; + u64 val; void __iomem *mem_crb; - if (size != 8) + /* Only 64-bit aligned access */ + if (off & 7) return -EIO; + /* P2 has different SIU and MIU test agent base addr */ if (ADDR_IN_RANGE(off, NETXEN_ADDR_QDR_NET, NETXEN_ADDR_QDR_NET_MAX_P2)) { - mem_crb = pci_base_offset(adapter, NETXEN_CRB_QDR_NET); + mem_crb = pci_base_offset(adapter, + NETXEN_CRB_QDR_NET+SIU_TEST_AGT_BASE); + addr_hi = SIU_TEST_AGT_ADDR_HI; + data_lo = SIU_TEST_AGT_RDDATA_LO; + data_hi = SIU_TEST_AGT_RDDATA_HI; + off_lo = off & SIU_TEST_AGT_ADDR_MASK; + off_hi = SIU_TEST_AGT_UPPER_ADDR(off); goto correct; } if (ADDR_IN_RANGE(off, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) { - mem_crb = pci_base_offset(adapter, NETXEN_CRB_DDR_NET); + mem_crb = pci_base_offset(adapter, + NETXEN_CRB_DDR_NET+MIU_TEST_AGT_BASE); + addr_hi = MIU_TEST_AGT_ADDR_HI; + data_lo = MIU_TEST_AGT_RDDATA_LO; + data_hi = MIU_TEST_AGT_RDDATA_HI; + off_lo = off & MIU_TEST_AGT_ADDR_MASK; + off_hi = 0; goto correct; } + if (ADDR_IN_RANGE(off, NETXEN_ADDR_OCM0, NETXEN_ADDR_OCM0_MAX) || + ADDR_IN_RANGE(off, NETXEN_ADDR_OCM1, NETXEN_ADDR_OCM1_MAX)) { + if (adapter->ahw.pci_len0 != 0) { + return netxen_nic_pci_mem_access_direct(adapter, + off, data, 0); + } + } + return -EIO; correct: - off8 = off & 0xfffffff8; - off0[0] = off & 0x7; - off0[1] = 0; - sz[0] = (size < (8 - off0[0])) ? size : (8 - off0[0]); - sz[1] = size - sz[0]; - loop = ((off0[0] + size - 1) >> 3) + 1; - - write_lock_irqsave(&adapter->adapter_lock, flags); - netxen_nic_pci_change_crbwindow_128M(adapter, 0); - - for (i = 0; i < loop; i++) { - writel((uint32_t)(off8 + (i << 3)), - (mem_crb+MIU_TEST_AGT_ADDR_LO)); - writel(0, - (mem_crb+MIU_TEST_AGT_ADDR_HI)); - writel(MIU_TA_CTL_ENABLE, - (mem_crb+MIU_TEST_AGT_CTRL)); - writel(MIU_TA_CTL_START|MIU_TA_CTL_ENABLE, - (mem_crb+MIU_TEST_AGT_CTRL)); + spin_lock(&adapter->ahw.mem_lock); + netxen_nic_pci_set_crbwindow_128M(adapter, 0); - for (j = 0; j < MAX_CTL_CHECK; j++) { - temp = readl( - (mem_crb+MIU_TEST_AGT_CTRL)); - if ((temp & MIU_TA_CTL_BUSY) == 0) - break; - } + writel(off_lo, (mem_crb + MIU_TEST_AGT_ADDR_LO)); + writel(off_hi, (mem_crb + addr_hi)); + writel(TA_CTL_ENABLE, (mem_crb + TEST_AGT_CTRL)); + writel((TA_CTL_START|TA_CTL_ENABLE), (mem_crb + TEST_AGT_CTRL)); - if (j >= MAX_CTL_CHECK) { - if (printk_ratelimit()) - dev_err(&adapter->pdev->dev, - "failed to read through agent\n"); + for (j = 0; j < MAX_CTL_CHECK; j++) { + temp = readl(mem_crb + TEST_AGT_CTRL); + if ((temp & TA_CTL_BUSY) == 0) break; - } - - start = off0[i] >> 2; - end = (off0[i] + sz[i] - 1) >> 2; - for (k = start; k <= end; k++) { - word[i] |= ((uint64_t) readl( - (mem_crb + - MIU_TEST_AGT_RDDATA(k))) << (32*k)); - } } - netxen_nic_pci_change_crbwindow_128M(adapter, 1); - write_unlock_irqrestore(&adapter->adapter_lock, flags); - - if (j >= MAX_CTL_CHECK) - return -1; - - if (sz[0] == 8) { - val = word[0]; + if (j >= MAX_CTL_CHECK) { + if (printk_ratelimit()) + dev_err(&adapter->pdev->dev, + "failed to read through agent\n"); + ret = -EIO; } else { - val = ((word[0] >> (off0[0] * 8)) & (~(~0ULL << (sz[0] * 8)))) | - ((word[1] & (~(~0ULL << (sz[1] * 8)))) << (sz[0] * 8)); - } - switch (size) { - case 1: - *(uint8_t *)data = val; - break; - case 2: - *(uint16_t *)data = val; - break; - case 4: - *(uint32_t *)data = val; - break; - case 8: - *(uint64_t *)data = val; - break; + temp = readl(mem_crb + data_hi); + val = ((u64)temp << 32); + val |= readl(mem_crb + data_lo); + *data = val; + ret = 0; } - return 0; + + netxen_nic_pci_set_crbwindow_128M(adapter, NETXEN_WINDOW_ONE); + spin_unlock(&adapter->ahw.mem_lock); + + return ret; } static int netxen_nic_pci_mem_write_2M(struct netxen_adapter *adapter, - u64 off, void *data, int size) + u64 off, u64 data) { - int i, j, ret = 0, loop, sz[2], off0; - uint32_t temp; - uint64_t off8, tmpw, word[2] = {0, 0}; + int i, j, ret; + u32 temp, off8; + u64 stride; void __iomem *mem_crb; - if (size != 8) + /* Only 64-bit aligned access */ + if (off & 7) return -EIO; + /* P3 onward, test agent base for MIU and SIU is same */ if (ADDR_IN_RANGE(off, NETXEN_ADDR_QDR_NET, NETXEN_ADDR_QDR_NET_MAX_P3)) { |