Commit da1aa63e authored by Anton Vorontsov's avatar Anton Vorontsov Committed by David S. Miller

ucc_geth: Pass proper device to DMA routines, otherwise oops happens

The driver should pass a device that actually specifies internal DMA
ops, but currently it passes netdev's device, which is wrong and that
causes following oops:

Kernel BUG at c01c4df8 [verbose debug info unavailable]
Oops: Exception in kernel mode, sig: 5 [#1]
[...]
NIP [c01c4df8] get_new_skb+0x7c/0xf8
LR [c01c4da4] get_new_skb+0x28/0xf8
Call Trace:
[ef82be00] [c01c4da4] get_new_skb+0x28/0xf8 (unreliable)
[ef82be20] [c01c4eb8] rx_bd_buffer_set+0x44/0x98
[ef82be40] [c01c62bc] ucc_geth_startup+0x11b0/0x147c
[ef82be80] [c01c6674] ucc_geth_open+0xec/0x2a4
[ef82bea0] [c02288a4] dev_open+0xc0/0x11c
[...]

Fix this by passing of_device's device that specifies DMA ops in its
archdata.
Signed-off-by: default avatarAnton Vorontsov <avorontsov@ru.mvista.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 050cc1f5
...@@ -222,10 +222,10 @@ static struct sk_buff *get_new_skb(struct ucc_geth_private *ugeth, ...@@ -222,10 +222,10 @@ static struct sk_buff *get_new_skb(struct ucc_geth_private *ugeth,
(((unsigned)skb->data) & (UCC_GETH_RX_DATA_BUF_ALIGNMENT - (((unsigned)skb->data) & (UCC_GETH_RX_DATA_BUF_ALIGNMENT -
1))); 1)));
skb->dev = ugeth->dev; skb->dev = ugeth->ndev;
out_be32(&((struct qe_bd __iomem *)bd)->buf, out_be32(&((struct qe_bd __iomem *)bd)->buf,
dma_map_single(&ugeth->dev->dev, dma_map_single(ugeth->dev,
skb->data, skb->data,
ugeth->ug_info->uf_info.max_rx_buf_length + ugeth->ug_info->uf_info.max_rx_buf_length +
UCC_GETH_RX_DATA_BUF_ALIGNMENT, UCC_GETH_RX_DATA_BUF_ALIGNMENT,
...@@ -1871,7 +1871,7 @@ static void ucc_geth_memclean(struct ucc_geth_private *ugeth) ...@@ -1871,7 +1871,7 @@ static void ucc_geth_memclean(struct ucc_geth_private *ugeth)
continue; continue;
for (j = 0; j < ugeth->ug_info->bdRingLenTx[i]; j++) { for (j = 0; j < ugeth->ug_info->bdRingLenTx[i]; j++) {
if (ugeth->tx_skbuff[i][j]) { if (ugeth->tx_skbuff[i][j]) {
dma_unmap_single(&ugeth->dev->dev, dma_unmap_single(ugeth->dev,
in_be32(&((struct qe_bd __iomem *)bd)->buf), in_be32(&((struct qe_bd __iomem *)bd)->buf),
(in_be32((u32 __iomem *)bd) & (in_be32((u32 __iomem *)bd) &
BD_LENGTH_MASK), BD_LENGTH_MASK),
...@@ -1899,7 +1899,7 @@ static void ucc_geth_memclean(struct ucc_geth_private *ugeth) ...@@ -1899,7 +1899,7 @@ static void ucc_geth_memclean(struct ucc_geth_private *ugeth)
bd = ugeth->p_rx_bd_ring[i]; bd = ugeth->p_rx_bd_ring[i];
for (j = 0; j < ugeth->ug_info->bdRingLenRx[i]; j++) { for (j = 0; j < ugeth->ug_info->bdRingLenRx[i]; j++) {
if (ugeth->rx_skbuff[i][j]) { if (ugeth->rx_skbuff[i][j]) {
dma_unmap_single(&ugeth->dev->dev, dma_unmap_single(ugeth->dev,
in_be32(&((struct qe_bd __iomem *)bd)->buf), in_be32(&((struct qe_bd __iomem *)bd)->buf),
ugeth->ug_info-> ugeth->ug_info->
uf_info.max_rx_buf_length + uf_info.max_rx_buf_length +
...@@ -3070,7 +3070,7 @@ static int ucc_geth_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -3070,7 +3070,7 @@ static int ucc_geth_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* set up the buffer descriptor */ /* set up the buffer descriptor */
out_be32(&((struct qe_bd __iomem *)bd)->buf, out_be32(&((struct qe_bd __iomem *)bd)->buf,
dma_map_single(&ugeth->dev->dev, skb->data, dma_map_single(ugeth->dev, skb->data,
skb->len, DMA_TO_DEVICE)); skb->len, DMA_TO_DEVICE));
/* printk(KERN_DEBUG"skb->data is 0x%x\n",skb->data); */ /* printk(KERN_DEBUG"skb->data is 0x%x\n",skb->data); */
...@@ -3126,7 +3126,7 @@ static int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit ...@@ -3126,7 +3126,7 @@ static int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit
ugeth_vdbg("%s: IN", __func__); ugeth_vdbg("%s: IN", __func__);
dev = ugeth->dev; dev = ugeth->ndev;
/* collect received buffers */ /* collect received buffers */
bd = ugeth->rxBd[rxQ]; bd = ugeth->rxBd[rxQ];
...@@ -3160,7 +3160,7 @@ static int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit ...@@ -3160,7 +3160,7 @@ static int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit
skb_put(skb, length); skb_put(skb, length);
/* Tell the skb what kind of packet this is */ /* Tell the skb what kind of packet this is */
skb->protocol = eth_type_trans(skb, ugeth->dev); skb->protocol = eth_type_trans(skb, ugeth->ndev);
dev->stats.rx_bytes += length; dev->stats.rx_bytes += length;
/* Send the packet up the stack */ /* Send the packet up the stack */
...@@ -3431,7 +3431,7 @@ static int ucc_geth_close(struct net_device *dev) ...@@ -3431,7 +3431,7 @@ static int ucc_geth_close(struct net_device *dev)
ucc_geth_stop(ugeth); ucc_geth_stop(ugeth);
free_irq(ugeth->ug_info->uf_info.irq, ugeth->dev); free_irq(ugeth->ug_info->uf_info.irq, ugeth->ndev);
netif_stop_queue(dev); netif_stop_queue(dev);
...@@ -3445,7 +3445,7 @@ static void ucc_geth_timeout_work(struct work_struct *work) ...@@ -3445,7 +3445,7 @@ static void ucc_geth_timeout_work(struct work_struct *work)
struct net_device *dev; struct net_device *dev;
ugeth = container_of(work, struct ucc_geth_private, timeout_work); ugeth = container_of(work, struct ucc_geth_private, timeout_work);
dev = ugeth->dev; dev = ugeth->ndev;
ugeth_vdbg("%s: IN", __func__); ugeth_vdbg("%s: IN", __func__);
...@@ -3755,7 +3755,8 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma ...@@ -3755,7 +3755,8 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
memcpy(dev->dev_addr, mac_addr, 6); memcpy(dev->dev_addr, mac_addr, 6);
ugeth->ug_info = ug_info; ugeth->ug_info = ug_info;
ugeth->dev = dev; ugeth->dev = device;
ugeth->ndev = dev;
ugeth->node = np; ugeth->node = np;
return 0; return 0;
......
...@@ -1128,7 +1128,8 @@ struct ucc_geth_info { ...@@ -1128,7 +1128,8 @@ struct ucc_geth_info {
struct ucc_geth_private { struct ucc_geth_private {
struct ucc_geth_info *ug_info; struct ucc_geth_info *ug_info;
struct ucc_fast_private *uccf; struct ucc_fast_private *uccf;
struct net_device *dev; struct device *dev;
struct net_device *ndev;
struct napi_struct napi; struct napi_struct napi;
struct work_struct timeout_work; struct work_struct timeout_work;
struct ucc_geth __iomem *ug_regs; struct ucc_geth __iomem *ug_regs;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment