diff options
Diffstat (limited to 'drivers/net/netxen/netxen_nic_hw.c')
-rw-r--r-- | drivers/net/netxen/netxen_nic_hw.c | 916 |
1 files changed, 395 insertions, 521 deletions
diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index 3185a98b091..b3054c6cc60 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,89 +1052,71 @@ 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 * In: 'off' is offset from base in 128M pci map */ static int -netxen_nic_pci_get_crb_addr_2M(struct netxen_adapter *adapter, ulong *off) +netxen_nic_pci_get_crb_addr_2M(struct netxen_adapter *adapter, + ulong off, void __iomem **addr) { crb_128M_2M_sub_block_map_t *m; - if (*off >= NETXEN_CRB_MAX) - return -1; - - if (*off >= NETXEN_PCI_CAMQM && (*off < NETXEN_PCI_CAMQM_2M_END)) { - *off = (*off - NETXEN_PCI_CAMQM) + NETXEN_PCI_CAMQM_2M_BASE + - (ulong)adapter->ahw.pci_base0; - return 0; - } - - if (*off < NETXEN_PCI_CRBSPACE) - return -1; + if ((off >= NETXEN_CRB_MAX) || (off < NETXEN_PCI_CRBSPACE)) + return -EINVAL; - *off -= NETXEN_PCI_CRBSPACE; + off -= NETXEN_PCI_CRBSPACE; /* * Try direct map */ - m = &crb_128M_2M_map[CRB_BLK(*off)].sub_block[CRB_SUBBLK(*off)]; + m = &crb_128M_2M_map[CRB_BLK(off)].sub_block[CRB_SUBBLK(off)]; - if (m->valid && (m->start_128M <= *off) && (m->end_128M > *off)) { - *off = *off + m->start_2M - m->start_128M + - (ulong)adapter->ahw.pci_base0; + if (m->valid && (m->start_128M <= off) && (m->end_128M > off)) { + *addr = adapter->ahw.pci_base0 + m->start_2M + + (off - m->start_128M); return 0; } /* * Not in direct map, use crb window */ + *addr = adapter->ahw.pci_base0 + CRB_INDIRECT_2M + + (off & MASK(16)); return 1; } @@ -1138,24 +1126,26 @@ netxen_nic_pci_get_crb_addr_2M(struct netxen_adapter *adapter, ulong *off) * side effect: lock crb window */ static void -netxen_nic_pci_set_crbwindow_2M(struct netxen_adapter *adapter, ulong *off) +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); + off -= NETXEN_PCI_CRBSPACE; + + window = CRB_HI(off); + + if (adapter->ahw.crb_win == window) + return; + + 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); } - *off = (*off & MASK(16)) + CRB_INDIRECT_2M + - (ulong)adapter->ahw.pci_base0; + adapter->ahw.crb_win = window; } static int @@ -1172,16 +1162,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 +1191,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; @@ -1221,28 +1209,30 @@ netxen_nic_hw_write_wx_2M(struct netxen_adapter *adapter, ulong off, u32 data) { unsigned long flags; int rv; + void __iomem *addr = NULL; - rv = netxen_nic_pci_get_crb_addr_2M(adapter, &off); + rv = netxen_nic_pci_get_crb_addr_2M(adapter, off, &addr); - if (rv == -1) { - printk(KERN_ERR "%s: invalid offset: 0x%016lx\n", - __func__, off); - dump_stack(); - return -1; + if (rv == 0) { + writel(data, addr); + 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); + netxen_nic_pci_set_crbwindow_2M(adapter, off); + writel(data, addr); 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 @@ -1251,102 +1241,37 @@ netxen_nic_hw_read_wx_2M(struct netxen_adapter *adapter, ulong off) unsigned long flags; int rv; u32 data; + void __iomem *addr = NULL; - rv = netxen_nic_pci_get_crb_addr_2M(adapter, &off); + rv = netxen_nic_pci_get_crb_addr_2M(adapter, off, &addr); - if (rv == -1) { - printk(KERN_ERR "%s: invalid offset: 0x%016lx\n", - __func__, off); - dump_stack(); - return -1; - } + if (rv == 0) + return readl(addr); - 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); + netxen_nic_pci_set_crbwindow_2M(adapter, off); + data = readl(addr); 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 +1279,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; } @@ -1376,488 +1301,437 @@ static u32 netxen_nic_io_read_2M(struct netxen_adapter *adapter, void __iomem * netxen_get_ioaddr(struct netxen_adapter *adapter, u32 offset) { - ulong off = offset; + void __iomem *addr = NULL; if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { - if (offset < NETXEN_CRB_PCIX_HOST2 && - offset > NETXEN_CRB_PCIX_HOST) - return PCI_OFFSET_SECOND_RANGE(adapter, offset); - return NETXEN_CRB_NORMALIZE(adapter, offset); + if ((offset < NETXEN_CRB_PCIX_HOST2) && + (offset > NETXEN_CRB_PCIX_HOST)) + addr = PCI_OFFSET_SECOND_RANGE(adapter, offset); + else + addr = NETXEN_CRB_NORMALIZE(adapter, offset); + } else { + WARN_ON(netxen_nic_pci_get_crb_addr_2M(adapter, + offset, &addr)); } - BUG_ON(netxen_nic_pci_get_crb_addr_2M(adapter, &off)); - return (void __iomem *)off; + return addr; } -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)) { - mem_crb = netxen_get_ioaddr(adapter, NETXEN_CRB_QDR_NET); + mem_crb = netxen_get_ioaddr(adapter, + NETXEN_CRB_QDR_NET+MIU_TEST_AGT_BASE); goto correct; } if (ADDR_IN_RANGE(off, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) { - mem_crb = netxen_get_ioaddr(adapter, NETXEN_CRB_DDR_NET); + mem_crb = netxen_get_ioaddr(adapter, + NETXEN_CRB_DDR_NET+MIU_TEST_AGT_BASE); goto correct; } + if (ADDR_IN_RANGE(off, NETXEN_ADDR_OCM0, NETXEN_ADDR_OCM0_MAX)) + return netxen_nic_pci_mem_access_direct(adapter, off, &data, 1); + 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; - } - } + stride = NX_IS_REVISION_P3P(adapter->ahw.revision_id) ? 16 : 8; - 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; - } + off8 = off & ~(stride-1); - word[0] &= ~((~(~0ULL << (sz[0] * 8))) << (off0 * 8)); - word[0] |= tmpw << (off0 * 8); + spin_lock(&adapter->ahw.mem_lock); - if (loop == 2) { - word[1] &= ~(~0ULL << (sz[1] * 8)); - word[1] |= tmpw >> (sz[0] * 8); - } - - /* - * don't lock here - write_wx gets the lock if each time - * write_lock_irqsave(&adapter->adapter_lock, flags); - * netxen_nic_pci_change_crbwindow_128M(adapter, 0); - */ + writel(off8, (mem_crb + MIU_TEST_AGT_ADDR_LO)); + writel(0, (mem_crb + MIU_TEST_AGT_ADDR_HI)); - for (i = 0; i < loop; i++) { - writel(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); + 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 + MIU_TEST_AGT_CTRL); - if ((temp & MIU_TA_CTL_BUSY) == 0) + temp = readl(mem_crb + TEST_AGT_CTRL); + if ((temp & TA_CTL_BUSY) == 0) break; } if (j >= MAX_CTL_CHECK) { - if (printk_ratelimit()) - dev_err(&adapter->pdev->dev, - "failed to write through agent\n"); - ret = -1; - break; + 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; } - /* - * netxen_nic_pci_change_crbwindow_128M(adapter, 1); - * write_unlock_irqrestore(&adapter->adapter_lock, flags); - */ + writel(data & 0xffffffff, + mem_crb + MIU_TEST_AGT_WRDATA(i)); + writel((data >> 32) & 0xffffffff, + mem_crb + MIU_TEST_AGT_WRDATA(i+1)); + + 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; + } + + if (j >= MAX_CTL_CHECK) { + if (printk_ratelimit()) + dev_err(&adapter->pdev->dev, + "failed to write through agent\n"); + ret = -EIO; + } else + ret = 0; + +done: + spin_unlock(&adapter->ahw.mem_lock); + return ret; } static int netxen_nic_pci_mem_read_2M(struct netxen_adapter *adapter, - u64 off, void *data, int size) + u64 off, u64 *data) { - 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, off8; + u64 val, 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)) { - mem_crb = netxen_get_ioaddr(adapter, NETXEN_CRB_QDR_NET); + mem_crb = netxen_get_ioaddr(adapter, + NETXEN_CRB_QDR_NET+MIU_TEST_AGT_BASE); goto correct; } if (ADDR_IN_RANGE(off, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) { - mem_crb = netxen_get_ioaddr(adapter, NETXEN_CRB_DDR_NET); + mem_crb = netxen_get_ioaddr(adapter, + NETXEN_CRB_DDR_NET+MIU_TEST_AGT_BASE); goto correct; } + if (ADDR_IN_RANGE(off, NETXEN_ADDR_OCM0, NETXEN_ADDR_OCM0_MAX)) { + 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; + stride = NX_IS_REVISION_P3P(adapter->ahw.revision_id) ? 16 : 8; - /* - * don't lock here - write_wx gets the lock if each time - * write_lock_irqsave(&adapter->adapter_lock, flags); - * netxen_nic_pci_change_crbwindow_128M(adapter, 0); - */ + off8 = off & ~(stride-1); - for (i = 0; i < loop; i++) { - writel(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); - 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(off8, (mem_crb + MIU_TEST_AGT_ADDR_LO)); + writel(0, (mem_crb + MIU_TEST_AGT_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++) { - temp = readl(mem_crb + MIU_TEST_AGT_RDDATA(k)); - word[i] |= ((uint64_t)temp << (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)); - } + off8 = MIU_TEST_AGT_RDDATA_LO; + if ((stride == 16) && (off & 0xf)) + off8 = MIU_TEST_AGT_RDDATA_UPPER_LO; - 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 + off8 + 4); + val = (u64)temp << 32; + val |= readl(mem_crb + off8); + *data = val; + ret = 0; } - return 0; + + spin_unlock(&adapter->ahw.mem_lock); + + return ret; } void |