From 073ac8fd4a3e9a9265e8a59e0a79bc4b0b3822c3 Mon Sep 17 00:00:00 2001
From: Russell King <rmk@dyn-67.arm.linux.org.uk>
Date: Sat, 1 Sep 2007 21:27:18 +0100
Subject: [NET] smc91x: fix PXA DMA support code

The PXA DMA support code for smc91x doesn't pass a struct device to
the dma_*map_single() functions, which leads to an oops in the dma
bounce code.  We have a struct device which was used to probe the
SMC chip.  Use it.

(This patch is slightly larger because it requires struct smc_local
to move into the header file.)

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/net/smc91x.c | 55 ++++++--------------------------------------
 drivers/net/smc91x.h | 64 +++++++++++++++++++++++++++++++++++++++++++++-------
 2 files changed, 63 insertions(+), 56 deletions(-)

diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c
index 24e610e..7da7589 100644
--- a/drivers/net/smc91x.c
+++ b/drivers/net/smc91x.c
@@ -173,49 +173,6 @@ MODULE_LICENSE("GPL");
  */
 #define MII_DELAY		1
 
-/* store this information for the driver.. */
-struct smc_local {
-	/*
-	 * If I have to wait until memory is available to send a
-	 * packet, I will store the skbuff here, until I get the
-	 * desired memory.  Then, I'll send it out and free it.
-	 */
-	struct sk_buff *pending_tx_skb;
-	struct tasklet_struct tx_task;
-
-	/* version/revision of the SMC91x chip */
-	int	version;
-
-	/* Contains the current active transmission mode */
-	int	tcr_cur_mode;
-
-	/* Contains the current active receive mode */
-	int	rcr_cur_mode;
-
-	/* Contains the current active receive/phy mode */
-	int	rpc_cur_mode;
-	int	ctl_rfduplx;
-	int	ctl_rspeed;
-
-	u32	msg_enable;
-	u32	phy_type;
-	struct mii_if_info mii;
-
-	/* work queue */
-	struct work_struct phy_configure;
-	struct net_device *dev;
-	int	work_pending;
-
-	spinlock_t lock;
-
-#ifdef SMC_USE_PXA_DMA
-	/* DMA needs the physical address of the chip */
-	u_long physaddr;
-#endif
-	void __iomem *base;
-	void __iomem *datacs;
-};
-
 #if SMC_DEBUG > 0
 #define DBG(n, args...)					\
 	do {						\
@@ -2215,17 +2172,19 @@ static int smc_drv_probe(struct platform_device *pdev)
 		goto out_release_attrib;
 	}
 
-	platform_set_drvdata(pdev, ndev);
-	ret = smc_probe(ndev, addr);
-	if (ret != 0)
-		goto out_iounmap;
 #ifdef SMC_USE_PXA_DMA
-	else {
+	{
 		struct smc_local *lp = netdev_priv(ndev);
+		lp->device = &pdev->dev;
 		lp->physaddr = res->start;
 	}
 #endif
 
+	platform_set_drvdata(pdev, ndev);
+	ret = smc_probe(ndev, addr);
+	if (ret != 0)
+		goto out_iounmap;
+
 	smc_request_datacs(pdev, ndev);
 
 	return 0;
diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h
index af9e6bf..729fd28 100644
--- a/drivers/net/smc91x.h
+++ b/drivers/net/smc91x.h
@@ -462,6 +462,52 @@ static inline void LPD7_SMC_outsw (unsigned char* a, int r,
 
 #endif
 
+
+/* store this information for the driver.. */
+struct smc_local {
+	/*
+	 * If I have to wait until memory is available to send a
+	 * packet, I will store the skbuff here, until I get the
+	 * desired memory.  Then, I'll send it out and free it.
+	 */
+	struct sk_buff *pending_tx_skb;
+	struct tasklet_struct tx_task;
+
+	/* version/revision of the SMC91x chip */
+	int	version;
+
+	/* Contains the current active transmission mode */
+	int	tcr_cur_mode;
+
+	/* Contains the current active receive mode */
+	int	rcr_cur_mode;
+
+	/* Contains the current active receive/phy mode */
+	int	rpc_cur_mode;
+	int	ctl_rfduplx;
+	int	ctl_rspeed;
+
+	u32	msg_enable;
+	u32	phy_type;
+	struct mii_if_info mii;
+
+	/* work queue */
+	struct work_struct phy_configure;
+	struct net_device *dev;
+	int	work_pending;
+
+	spinlock_t lock;
+
+#ifdef SMC_USE_PXA_DMA
+	/* DMA needs the physical address of the chip */
+	u_long physaddr;
+	struct device *device;
+#endif
+	void __iomem *base;
+	void __iomem *datacs;
+};
+
+
 #ifdef SMC_USE_PXA_DMA
 /*
  * Let's use the DMA engine on the XScale PXA2xx for RX packets. This is
@@ -476,11 +522,12 @@ static inline void LPD7_SMC_outsw (unsigned char* a, int r,
 #ifdef SMC_insl
 #undef SMC_insl
 #define SMC_insl(a, r, p, l) \
-	smc_pxa_dma_insl(a, lp->physaddr, r, dev->dma, p, l)
+	smc_pxa_dma_insl(a, lp, r, dev->dma, p, l)
 static inline void
-smc_pxa_dma_insl(void __iomem *ioaddr, u_long physaddr, int reg, int dma,
+smc_pxa_dma_insl(void __iomem *ioaddr, struct smc_local *lp, int reg, int dma,
 		 u_char *buf, int len)
 {
+	u_long physaddr = lp->physaddr;
 	dma_addr_t dmabuf;
 
 	/* fallback if no DMA available */
@@ -497,7 +544,7 @@ smc_pxa_dma_insl(void __iomem *ioaddr, u_long physaddr, int reg, int dma,
 	}
 
 	len *= 4;
-	dmabuf = dma_map_single(NULL, buf, len, DMA_FROM_DEVICE);
+	dmabuf = dma_map_single(lp->device, buf, len, DMA_FROM_DEVICE);
 	DCSR(dma) = DCSR_NODESC;
 	DTADR(dma) = dmabuf;
 	DSADR(dma) = physaddr + reg;
@@ -507,18 +554,19 @@ smc_pxa_dma_insl(void __iomem *ioaddr, u_long physaddr, int reg, int dma,
 	while (!(DCSR(dma) & DCSR_STOPSTATE))
 		cpu_relax();
 	DCSR(dma) = 0;
-	dma_unmap_single(NULL, dmabuf, len, DMA_FROM_DEVICE);
+	dma_unmap_single(lp->device, dmabuf, len, DMA_FROM_DEVICE);
 }
 #endif
 
 #ifdef SMC_insw
 #undef SMC_insw
 #define SMC_insw(a, r, p, l) \
-	smc_pxa_dma_insw(a, lp->physaddr, r, dev->dma, p, l)
+	smc_pxa_dma_insw(a, lp, r, dev->dma, p, l)
 static inline void
-smc_pxa_dma_insw(void __iomem *ioaddr, u_long physaddr, int reg, int dma,
+smc_pxa_dma_insw(void __iomem *ioaddr, struct smc_local *lp, int reg, int dma,
 		 u_char *buf, int len)
 {
+	u_long physaddr = lp->physaddr;
 	dma_addr_t dmabuf;
 
 	/* fallback if no DMA available */
@@ -535,7 +583,7 @@ smc_pxa_dma_insw(void __iomem *ioaddr, u_long physaddr, int reg, int dma,
 	}
 
 	len *= 2;
-	dmabuf = dma_map_single(NULL, buf, len, DMA_FROM_DEVICE);
+	dmabuf = dma_map_single(lp->device, buf, len, DMA_FROM_DEVICE);
 	DCSR(dma) = DCSR_NODESC;
 	DTADR(dma) = dmabuf;
 	DSADR(dma) = physaddr + reg;
@@ -545,7 +593,7 @@ smc_pxa_dma_insw(void __iomem *ioaddr, u_long physaddr, int reg, int dma,
 	while (!(DCSR(dma) & DCSR_STOPSTATE))
 		cpu_relax();
 	DCSR(dma) = 0;
-	dma_unmap_single(NULL, dmabuf, len, DMA_FROM_DEVICE);
+	dma_unmap_single(lp->device, dmabuf, len, DMA_FROM_DEVICE);
 }
 #endif
 
-- 
cgit v1.1