summaryrefslogtreecommitdiffstats
path: root/drivers/net/netxen/netxen_nic_hw.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/netxen/netxen_nic_hw.c')
-rw-r--r--drivers/net/netxen/netxen_nic_hw.c916
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