aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAnton Vorontsov <avorontsov@ru.mvista.com>2009-04-02 04:26:07 -0400
committerDavid S. Miller <davem@davemloft.net>2009-04-02 04:26:07 -0400
commitda1aa63ec3b4e9b4c5680f06288f57f44caa61b8 (patch)
tree972f649dc0c35b5347c28bfba06463a3e3fb4d0f /drivers
parent050cc1f568e896a615110109999ed60ef75edf93 (diff)
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: Anton Vorontsov <avorontsov@ru.mvista.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/ucc_geth.c21
-rw-r--r--drivers/net/ucc_geth.h3
2 files changed, 13 insertions, 11 deletions
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index a124615421bf..d3f39e86eb95 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -222,10 +222,10 @@ static struct sk_buff *get_new_skb(struct ucc_geth_private *ugeth,
222 (((unsigned)skb->data) & (UCC_GETH_RX_DATA_BUF_ALIGNMENT - 222 (((unsigned)skb->data) & (UCC_GETH_RX_DATA_BUF_ALIGNMENT -
223 1))); 223 1)));
224 224
225 skb->dev = ugeth->dev; 225 skb->dev = ugeth->ndev;
226 226
227 out_be32(&((struct qe_bd __iomem *)bd)->buf, 227 out_be32(&((struct qe_bd __iomem *)bd)->buf,
228 dma_map_single(&ugeth->dev->dev, 228 dma_map_single(ugeth->dev,
229 skb->data, 229 skb->data,
230 ugeth->ug_info->uf_info.max_rx_buf_length + 230 ugeth->ug_info->uf_info.max_rx_buf_length +
231 UCC_GETH_RX_DATA_BUF_ALIGNMENT, 231 UCC_GETH_RX_DATA_BUF_ALIGNMENT,
@@ -1871,7 +1871,7 @@ static void ucc_geth_memclean(struct ucc_geth_private *ugeth)
1871 continue; 1871 continue;
1872 for (j = 0; j < ugeth->ug_info->bdRingLenTx[i]; j++) { 1872 for (j = 0; j < ugeth->ug_info->bdRingLenTx[i]; j++) {
1873 if (ugeth->tx_skbuff[i][j]) { 1873 if (ugeth->tx_skbuff[i][j]) {
1874 dma_unmap_single(&ugeth->dev->dev, 1874 dma_unmap_single(ugeth->dev,
1875 in_be32(&((struct qe_bd __iomem *)bd)->buf), 1875 in_be32(&((struct qe_bd __iomem *)bd)->buf),
1876 (in_be32((u32 __iomem *)bd) & 1876 (in_be32((u32 __iomem *)bd) &
1877 BD_LENGTH_MASK), 1877 BD_LENGTH_MASK),
@@ -1899,7 +1899,7 @@ static void ucc_geth_memclean(struct ucc_geth_private *ugeth)
1899 bd = ugeth->p_rx_bd_ring[i]; 1899 bd = ugeth->p_rx_bd_ring[i];
1900 for (j = 0; j < ugeth->ug_info->bdRingLenRx[i]; j++) { 1900 for (j = 0; j < ugeth->ug_info->bdRingLenRx[i]; j++) {
1901 if (ugeth->rx_skbuff[i][j]) { 1901 if (ugeth->rx_skbuff[i][j]) {
1902 dma_unmap_single(&ugeth->dev->dev, 1902 dma_unmap_single(ugeth->dev,
1903 in_be32(&((struct qe_bd __iomem *)bd)->buf), 1903 in_be32(&((struct qe_bd __iomem *)bd)->buf),
1904 ugeth->ug_info-> 1904 ugeth->ug_info->
1905 uf_info.max_rx_buf_length + 1905 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 3070
3071 /* set up the buffer descriptor */ 3071 /* set up the buffer descriptor */
3072 out_be32(&((struct qe_bd __iomem *)bd)->buf, 3072 out_be32(&((struct qe_bd __iomem *)bd)->buf,
3073 dma_map_single(&ugeth->dev->dev, skb->data, 3073 dma_map_single(ugeth->dev, skb->data,
3074 skb->len, DMA_TO_DEVICE)); 3074 skb->len, DMA_TO_DEVICE));
3075 3075
3076 /* printk(KERN_DEBUG"skb->data is 0x%x\n",skb->data); */ 3076 /* 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 3126
3127 ugeth_vdbg("%s: IN", __func__); 3127 ugeth_vdbg("%s: IN", __func__);
3128 3128
3129 dev = ugeth->dev; 3129 dev = ugeth->ndev;
3130 3130
3131 /* collect received buffers */ 3131 /* collect received buffers */
3132 bd = ugeth->rxBd[rxQ]; 3132 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 skb_put(skb, length); 3160 skb_put(skb, length);
3161 3161
3162 /* Tell the skb what kind of packet this is */ 3162 /* Tell the skb what kind of packet this is */
3163 skb->protocol = eth_type_trans(skb, ugeth->dev); 3163 skb->protocol = eth_type_trans(skb, ugeth->ndev);
3164 3164
3165 dev->stats.rx_bytes += length; 3165 dev->stats.rx_bytes += length;
3166 /* Send the packet up the stack */ 3166 /* Send the packet up the stack */
@@ -3431,7 +3431,7 @@ static int ucc_geth_close(struct net_device *dev)
3431 3431
3432 ucc_geth_stop(ugeth); 3432 ucc_geth_stop(ugeth);
3433 3433
3434 free_irq(ugeth->ug_info->uf_info.irq, ugeth->dev); 3434 free_irq(ugeth->ug_info->uf_info.irq, ugeth->ndev);
3435 3435
3436 netif_stop_queue(dev); 3436 netif_stop_queue(dev);
3437 3437
@@ -3445,7 +3445,7 @@ static void ucc_geth_timeout_work(struct work_struct *work)
3445 struct net_device *dev; 3445 struct net_device *dev;
3446 3446
3447 ugeth = container_of(work, struct ucc_geth_private, timeout_work); 3447 ugeth = container_of(work, struct ucc_geth_private, timeout_work);
3448 dev = ugeth->dev; 3448 dev = ugeth->ndev;
3449 3449
3450 ugeth_vdbg("%s: IN", __func__); 3450 ugeth_vdbg("%s: IN", __func__);
3451 3451
@@ -3755,7 +3755,8 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
3755 memcpy(dev->dev_addr, mac_addr, 6); 3755 memcpy(dev->dev_addr, mac_addr, 6);
3756 3756
3757 ugeth->ug_info = ug_info; 3757 ugeth->ug_info = ug_info;
3758 ugeth->dev = dev; 3758 ugeth->dev = device;
3759 ugeth->ndev = dev;
3759 ugeth->node = np; 3760 ugeth->node = np;
3760 3761
3761 return 0; 3762 return 0;
diff --git a/drivers/net/ucc_geth.h b/drivers/net/ucc_geth.h
index 48fde5ad6a34..2f8ee7c87efe 100644
--- a/drivers/net/ucc_geth.h
+++ b/drivers/net/ucc_geth.h
@@ -1128,7 +1128,8 @@ struct ucc_geth_info {
1128struct ucc_geth_private { 1128struct ucc_geth_private {
1129 struct ucc_geth_info *ug_info; 1129 struct ucc_geth_info *ug_info;
1130 struct ucc_fast_private *uccf; 1130 struct ucc_fast_private *uccf;
1131 struct net_device *dev; 1131 struct device *dev;
1132 struct net_device *ndev;
1132 struct napi_struct napi; 1133 struct napi_struct napi;
1133 struct work_struct timeout_work; 1134 struct work_struct timeout_work;
1134 struct ucc_geth __iomem *ug_regs; 1135 struct ucc_geth __iomem *ug_regs;