Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 073ac8fd authored by Russell King's avatar Russell King Committed by Russell King
Browse files

[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: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent 97d97224
Loading
Loading
Loading
Loading
+7 −48
Original line number Diff line number Diff line
@@ -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;
+56 −8
Original line number Diff line number Diff line
@@ -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