diff options
author | Greg Ungerer <gerg@snapgear.com> | 2009-08-06 13:58:18 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-08-10 00:45:33 -0400 |
commit | 9555b31e8c29d2000e1e1f569f6f242ebd596e47 (patch) | |
tree | f12a6e5ac329c6059539a39e0cc4fce38afef8a3 /drivers/net | |
parent | e84b90ae5eb3c112d1f208964df1d8156a538289 (diff) |
fec: fix FEC driver packet transmission breakage
Commit f0b3fbeae11a526c3d308b691684589ee37c359b ("FEC Buffer rework")
breaks transmission of packets where the skb data buffer is not memory
aligned according to FEC_ALIGNMENT. It incorrectly passes to
dma_sync_single() the buffer address directly from the skb, instead of
the address calculated for use (which may be the skb address or one of
the bounce buffers).
It seems there is no use converting the cpu address of the buffer to
a physical either, since dma_map_single() expects the cpu address and
will return the dma address to use in the descriptor. So remove the use
of __pa() on the buffer address as well.
This patch is against 2.6.30-rc5. This breakage is a regression over
2.6.30, which does not have this problem.
Signed-off-by: Greg Ungerer <gerg@uclinux.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/fec.c | 9 |
1 files changed, 5 insertions, 4 deletions
diff --git a/drivers/net/fec.c b/drivers/net/fec.c index d4b98074b1b7..c9fd82d3a80d 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c | |||
@@ -285,6 +285,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
285 | { | 285 | { |
286 | struct fec_enet_private *fep = netdev_priv(dev); | 286 | struct fec_enet_private *fep = netdev_priv(dev); |
287 | struct bufdesc *bdp; | 287 | struct bufdesc *bdp; |
288 | void *bufaddr; | ||
288 | unsigned short status; | 289 | unsigned short status; |
289 | unsigned long flags; | 290 | unsigned long flags; |
290 | 291 | ||
@@ -312,7 +313,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
312 | status &= ~BD_ENET_TX_STATS; | 313 | status &= ~BD_ENET_TX_STATS; |
313 | 314 | ||
314 | /* Set buffer length and buffer pointer */ | 315 | /* Set buffer length and buffer pointer */ |
315 | bdp->cbd_bufaddr = __pa(skb->data); | 316 | bufaddr = skb->data; |
316 | bdp->cbd_datlen = skb->len; | 317 | bdp->cbd_datlen = skb->len; |
317 | 318 | ||
318 | /* | 319 | /* |
@@ -320,11 +321,11 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
320 | * 4-byte boundaries. Use bounce buffers to copy data | 321 | * 4-byte boundaries. Use bounce buffers to copy data |
321 | * and get it aligned. Ugh. | 322 | * and get it aligned. Ugh. |
322 | */ | 323 | */ |
323 | if (bdp->cbd_bufaddr & FEC_ALIGNMENT) { | 324 | if (((unsigned long) bufaddr) & FEC_ALIGNMENT) { |
324 | unsigned int index; | 325 | unsigned int index; |
325 | index = bdp - fep->tx_bd_base; | 326 | index = bdp - fep->tx_bd_base; |
326 | memcpy(fep->tx_bounce[index], (void *)skb->data, skb->len); | 327 | memcpy(fep->tx_bounce[index], (void *)skb->data, skb->len); |
327 | bdp->cbd_bufaddr = __pa(fep->tx_bounce[index]); | 328 | bufaddr = fep->tx_bounce[index]; |
328 | } | 329 | } |
329 | 330 | ||
330 | /* Save skb pointer */ | 331 | /* Save skb pointer */ |
@@ -336,7 +337,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
336 | /* Push the data cache so the CPM does not get stale memory | 337 | /* Push the data cache so the CPM does not get stale memory |
337 | * data. | 338 | * data. |
338 | */ | 339 | */ |
339 | bdp->cbd_bufaddr = dma_map_single(&dev->dev, skb->data, | 340 | bdp->cbd_bufaddr = dma_map_single(&dev->dev, bufaddr, |
340 | FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE); | 341 | FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE); |
341 | 342 | ||
342 | /* Send it on its way. Tell FEC it's ready, interrupt when done, | 343 | /* Send it on its way. Tell FEC it's ready, interrupt when done, |