From f58dbd7320e148b25cc0088ef37f524c99c6790f Mon Sep 17 00:00:00 2001
From: Narender Kumar <narender.kumar@qlogic.com>
Date: Wed, 2 Dec 2009 15:46:18 +0000
Subject: [PATCH] netxen : fix debug tools access for NX2031

Driver maps only some part of the MMIO bar 0 in case of
NX2031. This is sufficient for tx and rx by the driver.
When debug tools need to access resources in
unmapped regions, driver needs to map these on the fly
in order to complete read/write request.

Signed-off-by: Narender Kumar <narender.kumar@qlogic.com>
Signed-off-by: Dhananjay Phadke <dhananjay.phadke@qlogic.com>
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
 drivers/net/netxen/netxen_nic_hw.c | 63 +++++++++++++++++++++---------
 1 file changed, 44 insertions(+), 19 deletions(-)

diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c
index e71ca30433ef..89bd5194e37a 100644
--- a/drivers/net/netxen/netxen_nic_hw.c
+++ b/drivers/net/netxen/netxen_nic_hw.c
@@ -1175,24 +1175,46 @@ netxen_nic_pci_set_crbwindow_2M(struct netxen_adapter *adapter, ulong off)
 	adapter->ahw.crb_win = window;
 }
 
+static void __iomem *
+netxen_nic_map_indirect_address_128M(struct netxen_adapter *adapter,
+		ulong win_off, void __iomem **mem_ptr)
+{
+	ulong off = win_off;
+	void __iomem *addr;
+	resource_size_t mem_base;
+
+	if (ADDR_IN_WINDOW1(win_off))
+		off = NETXEN_CRB_NORMAL(win_off);
+
+	addr = pci_base_offset(adapter, off);
+	if (addr)
+		return addr;
+
+	if (adapter->ahw.pci_len0 == 0)
+		off -= NETXEN_PCI_CRBSPACE;
+
+	mem_base = pci_resource_start(adapter->pdev, 0);
+	*mem_ptr = ioremap(mem_base + (off & PAGE_MASK), PAGE_SIZE);
+	if (*mem_ptr)
+		addr = *mem_ptr + (off & (PAGE_SIZE - 1));
+
+	return addr;
+}
+
 static int
 netxen_nic_hw_write_wx_128M(struct netxen_adapter *adapter, ulong off, u32 data)
 {
 	unsigned long flags;
-	void __iomem *addr;
-
-	if (ADDR_IN_WINDOW1(off))
-		addr = NETXEN_CRB_NORMALIZE(adapter, off);
-	else
-		addr = pci_base_offset(adapter, off);
+	void __iomem *addr, *mem_ptr = NULL;
 
-	BUG_ON(!addr);
+	addr = netxen_nic_map_indirect_address_128M(adapter, off, &mem_ptr);
+	if (!addr)
+		return -EIO;
 
-	if (ADDR_IN_WINDOW1(off)) {	/* Window 1 */
+	if (ADDR_IN_WINDOW1(off)) { /* Window 1 */
 		netxen_nic_io_write_128M(adapter, addr, data);
-	} else {		/* Window 0 */
+	} else {        /* Window 0 */
 		write_lock_irqsave(&adapter->ahw.crb_lock, flags);
-		addr = pci_base_offset(adapter, off);
 		netxen_nic_pci_set_crbwindow_128M(adapter, 0);
 		writel(data, addr);
 		netxen_nic_pci_set_crbwindow_128M(adapter,
@@ -1200,6 +1222,9 @@ netxen_nic_hw_write_wx_128M(struct netxen_adapter *adapter, ulong off, u32 data)
 		write_unlock_irqrestore(&adapter->ahw.crb_lock, flags);
 	}
 
+	if (mem_ptr)
+		iounmap(mem_ptr);
+
 	return 0;
 }
 
@@ -1207,19 +1232,16 @@ static u32
 netxen_nic_hw_read_wx_128M(struct netxen_adapter *adapter, ulong off)
 {
 	unsigned long flags;
-	void __iomem *addr;
+	void __iomem *addr, *mem_ptr = NULL;
 	u32 data;
 
-	if (ADDR_IN_WINDOW1(off))
-		addr = NETXEN_CRB_NORMALIZE(adapter, off);
-	else
-		addr = pci_base_offset(adapter, off);
-
-	BUG_ON(!addr);
+	addr = netxen_nic_map_indirect_address_128M(adapter, off, &mem_ptr);
+	if (!addr)
+		return -EIO;
 
-	if (ADDR_IN_WINDOW1(off)) {	/* Window 1 */
+	if (ADDR_IN_WINDOW1(off)) { /* Window 1 */
 		data = netxen_nic_io_read_128M(adapter, addr);
-	} else {		/* Window 0 */
+	} else {        /* Window 0 */
 		write_lock_irqsave(&adapter->ahw.crb_lock, flags);
 		netxen_nic_pci_set_crbwindow_128M(adapter, 0);
 		data = readl(addr);
@@ -1228,6 +1250,9 @@ netxen_nic_hw_read_wx_128M(struct netxen_adapter *adapter, ulong off)
 		write_unlock_irqrestore(&adapter->ahw.crb_lock, flags);
 	}
 
+	if (mem_ptr)
+		iounmap(mem_ptr);
+
 	return data;
 }
 
-- 
GitLab