aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorAnatolij Gustschin <agust@denx.de>2010-02-26 07:00:49 -0500
committerDavid S. Miller <davem@davemloft.net>2010-02-27 05:34:36 -0500
commitcb395eaf439625f26c8527bb05bb905774a54c36 (patch)
tree16a3f6c024230e65b37ddc8dae29b29d33820758 /drivers/net
parent60ab4361adc188fb47da1c4892cc7a2bb621efef (diff)
fs_enet: add FEC TX buffer alignment workaround for MPC5121
MPC5121 FEC requeries 4-byte alignmnent for TX data buffers. This patch is a work around that copies misaligned tx packets to an aligned skb before sending. Signed-off-by: John Rigby <jcrigby@gmail.com> Signed-off-by: Piotr Ziecik <kosmo@semihalf.com> Signed-off-by: Wolfgang Denk <wd@denx.de> Signed-off-by: Anatolij Gustschin <agust@denx.de> Acked-by: Grant Likely <grant.likely@secretlab.ca> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/fs_enet/fs_enet-main.c47
1 files changed, 47 insertions, 0 deletions
diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
index 4297021214d1..0770e2f6da6b 100644
--- a/drivers/net/fs_enet/fs_enet-main.c
+++ b/drivers/net/fs_enet/fs_enet-main.c
@@ -580,6 +580,40 @@ void fs_cleanup_bds(struct net_device *dev)
580 580
581/**********************************************************************************/ 581/**********************************************************************************/
582 582
583#ifdef CONFIG_FS_ENET_MPC5121_FEC
584/*
585 * MPC5121 FEC requeries 4-byte alignment for TX data buffer!
586 */
587static struct sk_buff *tx_skb_align_workaround(struct net_device *dev,
588 struct sk_buff *skb)
589{
590 struct sk_buff *new_skb;
591 struct fs_enet_private *fep = netdev_priv(dev);
592
593 /* Alloc new skb */
594 new_skb = dev_alloc_skb(skb->len + 4);
595 if (!new_skb) {
596 if (net_ratelimit()) {
597 dev_warn(fep->dev,
598 "Memory squeeze, dropping tx packet.\n");
599 }
600 return NULL;
601 }
602
603 /* Make sure new skb is properly aligned */
604 skb_align(new_skb, 4);
605
606 /* Copy data to new skb ... */
607 skb_copy_from_linear_data(skb, new_skb->data, skb->len);
608 skb_put(new_skb, skb->len);
609
610 /* ... and free an old one */
611 dev_kfree_skb_any(skb);
612
613 return new_skb;
614}
615#endif
616
583static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) 617static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
584{ 618{
585 struct fs_enet_private *fep = netdev_priv(dev); 619 struct fs_enet_private *fep = netdev_priv(dev);
@@ -588,6 +622,19 @@ static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
588 u16 sc; 622 u16 sc;
589 unsigned long flags; 623 unsigned long flags;
590 624
625#ifdef CONFIG_FS_ENET_MPC5121_FEC
626 if (((unsigned long)skb->data) & 0x3) {
627 skb = tx_skb_align_workaround(dev, skb);
628 if (!skb) {
629 /*
630 * We have lost packet due to memory allocation error
631 * in tx_skb_align_workaround(). Hopefully original
632 * skb is still valid, so try transmit it later.
633 */
634 return NETDEV_TX_BUSY;
635 }
636 }
637#endif
591 spin_lock_irqsave(&fep->tx_lock, flags); 638 spin_lock_irqsave(&fep->tx_lock, flags);
592 639
593 /* 640 /*