diff options
Diffstat (limited to 'drivers/net/bfin_mac.c')
-rw-r--r-- | drivers/net/bfin_mac.c | 111 |
1 files changed, 81 insertions, 30 deletions
diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c index a8ec60e1ed7..3db7db1828e 100644 --- a/drivers/net/bfin_mac.c +++ b/drivers/net/bfin_mac.c | |||
@@ -605,36 +605,87 @@ adjust_head: | |||
605 | static int bfin_mac_hard_start_xmit(struct sk_buff *skb, | 605 | static int bfin_mac_hard_start_xmit(struct sk_buff *skb, |
606 | struct net_device *dev) | 606 | struct net_device *dev) |
607 | { | 607 | { |
608 | unsigned int data; | 608 | u16 *data; |
609 | 609 | ||
610 | current_tx_ptr->skb = skb; | 610 | current_tx_ptr->skb = skb; |
611 | 611 | ||
612 | /* | 612 | if (ANOMALY_05000285) { |
613 | * Is skb->data always 16-bit aligned? | 613 | /* |
614 | * Do we need to memcpy((char *)(tail->packet + 2), skb->data, len)? | 614 | * TXDWA feature is not avaible to older revision < 0.3 silicon |
615 | */ | 615 | * of BF537 |
616 | if ((((unsigned int)(skb->data)) & 0x02) == 2) { | 616 | * |
617 | /* move skb->data to current_tx_ptr payload */ | 617 | * Only if data buffer is ODD WORD alignment, we do not |
618 | data = (unsigned int)(skb->data) - 2; | 618 | * need to memcpy |
619 | *((unsigned short *)data) = (unsigned short)(skb->len); | 619 | */ |
620 | current_tx_ptr->desc_a.start_addr = (unsigned long)data; | 620 | u32 data_align = (u32)(skb->data) & 0x3; |
621 | /* this is important! */ | 621 | if (data_align == 0x2) { |
622 | blackfin_dcache_flush_range(data, (data + (skb->len)) + 2); | 622 | /* move skb->data to current_tx_ptr payload */ |
623 | 623 | data = (u16 *)(skb->data) - 1; | |
624 | *data = (u16)(skb->len); | ||
625 | current_tx_ptr->desc_a.start_addr = (u32)data; | ||
626 | /* this is important! */ | ||
627 | blackfin_dcache_flush_range((u32)data, | ||
628 | (u32)((u8 *)data + skb->len + 4)); | ||
629 | } else { | ||
630 | *((u16 *)(current_tx_ptr->packet)) = (u16)(skb->len); | ||
631 | memcpy((u8 *)(current_tx_ptr->packet + 2), skb->data, | ||
632 | skb->len); | ||
633 | current_tx_ptr->desc_a.start_addr = | ||
634 | (u32)current_tx_ptr->packet; | ||
635 | if (current_tx_ptr->status.status_word != 0) | ||
636 | current_tx_ptr->status.status_word = 0; | ||
637 | blackfin_dcache_flush_range( | ||
638 | (u32)current_tx_ptr->packet, | ||
639 | (u32)(current_tx_ptr->packet + skb->len + 2)); | ||
640 | } | ||
624 | } else { | 641 | } else { |
625 | *((unsigned short *)(current_tx_ptr->packet)) = | 642 | /* |
626 | (unsigned short)(skb->len); | 643 | * TXDWA feature is avaible to revision < 0.3 silicon of |
627 | memcpy((char *)(current_tx_ptr->packet + 2), skb->data, | 644 | * BF537 and always avaible to BF52x |
628 | (skb->len)); | 645 | */ |
629 | current_tx_ptr->desc_a.start_addr = | 646 | u32 data_align = (u32)(skb->data) & 0x3; |
630 | (unsigned long)current_tx_ptr->packet; | 647 | if (data_align == 0x0) { |
631 | if (current_tx_ptr->status.status_word != 0) | 648 | u16 sysctl = bfin_read_EMAC_SYSCTL(); |
632 | current_tx_ptr->status.status_word = 0; | 649 | sysctl |= TXDWA; |
633 | blackfin_dcache_flush_range((unsigned int)current_tx_ptr-> | 650 | bfin_write_EMAC_SYSCTL(sysctl); |
634 | packet, | 651 | |
635 | (unsigned int)(current_tx_ptr-> | 652 | /* move skb->data to current_tx_ptr payload */ |
636 | packet + skb->len) + | 653 | data = (u16 *)(skb->data) - 2; |
637 | 2); | 654 | *data = (u16)(skb->len); |
655 | current_tx_ptr->desc_a.start_addr = (u32)data; | ||
656 | /* this is important! */ | ||
657 | blackfin_dcache_flush_range( | ||
658 | (u32)data, | ||
659 | (u32)((u8 *)data + skb->len + 4)); | ||
660 | } else if (data_align == 0x2) { | ||
661 | u16 sysctl = bfin_read_EMAC_SYSCTL(); | ||
662 | sysctl &= ~TXDWA; | ||
663 | bfin_write_EMAC_SYSCTL(sysctl); | ||
664 | |||
665 | /* move skb->data to current_tx_ptr payload */ | ||
666 | data = (u16 *)(skb->data) - 1; | ||
667 | *data = (u16)(skb->len); | ||
668 | current_tx_ptr->desc_a.start_addr = (u32)data; | ||
669 | /* this is important! */ | ||
670 | blackfin_dcache_flush_range( | ||
671 | (u32)data, | ||
672 | (u32)((u8 *)data + skb->len + 4)); | ||
673 | } else { | ||
674 | u16 sysctl = bfin_read_EMAC_SYSCTL(); | ||
675 | sysctl &= ~TXDWA; | ||
676 | bfin_write_EMAC_SYSCTL(sysctl); | ||
677 | |||
678 | *((u16 *)(current_tx_ptr->packet)) = (u16)(skb->len); | ||
679 | memcpy((u8 *)(current_tx_ptr->packet + 2), skb->data, | ||
680 | skb->len); | ||
681 | current_tx_ptr->desc_a.start_addr = | ||
682 | (u32)current_tx_ptr->packet; | ||
683 | if (current_tx_ptr->status.status_word != 0) | ||
684 | current_tx_ptr->status.status_word = 0; | ||
685 | blackfin_dcache_flush_range( | ||
686 | (u32)current_tx_ptr->packet, | ||
687 | (u32)(current_tx_ptr->packet + skb->len + 2)); | ||
688 | } | ||
638 | } | 689 | } |
639 | 690 | ||
640 | /* enable this packet's dma */ | 691 | /* enable this packet's dma */ |
@@ -691,7 +742,6 @@ static void bfin_mac_rx(struct net_device *dev) | |||
691 | (unsigned long)skb->tail); | 742 | (unsigned long)skb->tail); |
692 | 743 | ||
693 | dev->last_rx = jiffies; | 744 | dev->last_rx = jiffies; |
694 | skb->dev = dev; | ||
695 | skb->protocol = eth_type_trans(skb, dev); | 745 | skb->protocol = eth_type_trans(skb, dev); |
696 | #if defined(BFIN_MAC_CSUM_OFFLOAD) | 746 | #if defined(BFIN_MAC_CSUM_OFFLOAD) |
697 | skb->csum = current_rx_ptr->status.ip_payload_csum; | 747 | skb->csum = current_rx_ptr->status.ip_payload_csum; |
@@ -920,6 +970,7 @@ static int bfin_mac_open(struct net_device *dev) | |||
920 | phy_start(lp->phydev); | 970 | phy_start(lp->phydev); |
921 | phy_write(lp->phydev, MII_BMCR, BMCR_RESET); | 971 | phy_write(lp->phydev, MII_BMCR, BMCR_RESET); |
922 | setup_system_regs(dev); | 972 | setup_system_regs(dev); |
973 | setup_mac_addr(dev->dev_addr); | ||
923 | bfin_mac_disable(); | 974 | bfin_mac_disable(); |
924 | bfin_mac_enable(); | 975 | bfin_mac_enable(); |
925 | pr_debug("hardware init finished\n"); | 976 | pr_debug("hardware init finished\n"); |
@@ -955,7 +1006,7 @@ static int bfin_mac_close(struct net_device *dev) | |||
955 | return 0; | 1006 | return 0; |
956 | } | 1007 | } |
957 | 1008 | ||
958 | static int __init bfin_mac_probe(struct platform_device *pdev) | 1009 | static int __devinit bfin_mac_probe(struct platform_device *pdev) |
959 | { | 1010 | { |
960 | struct net_device *ndev; | 1011 | struct net_device *ndev; |
961 | struct bfin_mac_local *lp; | 1012 | struct bfin_mac_local *lp; |
@@ -1081,7 +1132,7 @@ out_err_probe_mac: | |||
1081 | return rc; | 1132 | return rc; |
1082 | } | 1133 | } |
1083 | 1134 | ||
1084 | static int bfin_mac_remove(struct platform_device *pdev) | 1135 | static int __devexit bfin_mac_remove(struct platform_device *pdev) |
1085 | { | 1136 | { |
1086 | struct net_device *ndev = platform_get_drvdata(pdev); | 1137 | struct net_device *ndev = platform_get_drvdata(pdev); |
1087 | struct bfin_mac_local *lp = netdev_priv(ndev); | 1138 | struct bfin_mac_local *lp = netdev_priv(ndev); |
@@ -1128,7 +1179,7 @@ static int bfin_mac_resume(struct platform_device *pdev) | |||
1128 | 1179 | ||
1129 | static struct platform_driver bfin_mac_driver = { | 1180 | static struct platform_driver bfin_mac_driver = { |
1130 | .probe = bfin_mac_probe, | 1181 | .probe = bfin_mac_probe, |
1131 | .remove = bfin_mac_remove, | 1182 | .remove = __devexit_p(bfin_mac_remove), |
1132 | .resume = bfin_mac_resume, | 1183 | .resume = bfin_mac_resume, |
1133 | .suspend = bfin_mac_suspend, | 1184 | .suspend = bfin_mac_suspend, |
1134 | .driver = { | 1185 | .driver = { |