diff options
Diffstat (limited to 'drivers/net/gianfar.c')
| -rw-r--r-- | drivers/net/gianfar.c | 231 |
1 files changed, 152 insertions, 79 deletions
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 0f030b73cbb3..146f9513aea5 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c | |||
| @@ -2,7 +2,8 @@ | |||
| 2 | * drivers/net/gianfar.c | 2 | * drivers/net/gianfar.c |
| 3 | * | 3 | * |
| 4 | * Gianfar Ethernet Driver | 4 | * Gianfar Ethernet Driver |
| 5 | * Driver for FEC on MPC8540 and TSEC on MPC8540/MPC8560 | 5 | * This driver is designed for the non-CPM ethernet controllers |
| 6 | * on the 85xx and 83xx family of integrated processors | ||
| 6 | * Based on 8260_io/fcc_enet.c | 7 | * Based on 8260_io/fcc_enet.c |
| 7 | * | 8 | * |
| 8 | * Author: Andy Fleming | 9 | * Author: Andy Fleming |
| @@ -22,8 +23,6 @@ | |||
| 22 | * B-V +1.62 | 23 | * B-V +1.62 |
| 23 | * | 24 | * |
| 24 | * Theory of operation | 25 | * Theory of operation |
| 25 | * This driver is designed for the non-CPM ethernet controllers | ||
| 26 | * on the 85xx and 83xx family of integrated processors | ||
| 27 | * | 26 | * |
| 28 | * The driver is initialized through platform_device. Structures which | 27 | * The driver is initialized through platform_device. Structures which |
| 29 | * define the configuration needed by the board are defined in a | 28 | * define the configuration needed by the board are defined in a |
| @@ -110,7 +109,7 @@ | |||
| 110 | #endif | 109 | #endif |
| 111 | 110 | ||
| 112 | const char gfar_driver_name[] = "Gianfar Ethernet"; | 111 | const char gfar_driver_name[] = "Gianfar Ethernet"; |
| 113 | const char gfar_driver_version[] = "1.2"; | 112 | const char gfar_driver_version[] = "1.3"; |
| 114 | 113 | ||
| 115 | static int gfar_enet_open(struct net_device *dev); | 114 | static int gfar_enet_open(struct net_device *dev); |
| 116 | static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev); | 115 | static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev); |
| @@ -139,6 +138,10 @@ static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, int l | |||
| 139 | static void gfar_vlan_rx_register(struct net_device *netdev, | 138 | static void gfar_vlan_rx_register(struct net_device *netdev, |
| 140 | struct vlan_group *grp); | 139 | struct vlan_group *grp); |
| 141 | static void gfar_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid); | 140 | static void gfar_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid); |
| 141 | void gfar_halt(struct net_device *dev); | ||
| 142 | void gfar_start(struct net_device *dev); | ||
| 143 | static void gfar_clear_exact_match(struct net_device *dev); | ||
| 144 | static void gfar_set_mac_for_addr(struct net_device *dev, int num, u8 *addr); | ||
| 142 | 145 | ||
| 143 | extern struct ethtool_ops gfar_ethtool_ops; | 146 | extern struct ethtool_ops gfar_ethtool_ops; |
| 144 | 147 | ||
| @@ -146,12 +149,10 @@ MODULE_AUTHOR("Freescale Semiconductor, Inc"); | |||
| 146 | MODULE_DESCRIPTION("Gianfar Ethernet Driver"); | 149 | MODULE_DESCRIPTION("Gianfar Ethernet Driver"); |
| 147 | MODULE_LICENSE("GPL"); | 150 | MODULE_LICENSE("GPL"); |
| 148 | 151 | ||
| 149 | int gfar_uses_fcb(struct gfar_private *priv) | 152 | /* Returns 1 if incoming frames use an FCB */ |
| 153 | static inline int gfar_uses_fcb(struct gfar_private *priv) | ||
| 150 | { | 154 | { |
| 151 | if (priv->vlan_enable || priv->rx_csum_enable) | 155 | return (priv->vlan_enable || priv->rx_csum_enable); |
| 152 | return 1; | ||
| 153 | else | ||
| 154 | return 0; | ||
| 155 | } | 156 | } |
| 156 | 157 | ||
| 157 | /* Set up the ethernet device structure, private data, | 158 | /* Set up the ethernet device structure, private data, |
| @@ -320,15 +321,10 @@ static int gfar_probe(struct platform_device *pdev) | |||
| 320 | else | 321 | else |
| 321 | priv->padding = 0; | 322 | priv->padding = 0; |
| 322 | 323 | ||
| 323 | dev->hard_header_len += priv->padding; | ||
| 324 | |||
| 325 | if (dev->features & NETIF_F_IP_CSUM) | 324 | if (dev->features & NETIF_F_IP_CSUM) |
| 326 | dev->hard_header_len += GMAC_FCB_LEN; | 325 | dev->hard_header_len += GMAC_FCB_LEN; |
| 327 | 326 | ||
| 328 | priv->rx_buffer_size = DEFAULT_RX_BUFFER_SIZE; | 327 | priv->rx_buffer_size = DEFAULT_RX_BUFFER_SIZE; |
| 329 | #ifdef CONFIG_GFAR_BUFSTASH | ||
| 330 | priv->rx_stash_size = STASH_LENGTH; | ||
| 331 | #endif | ||
| 332 | priv->tx_ring_size = DEFAULT_TX_RING_SIZE; | 328 | priv->tx_ring_size = DEFAULT_TX_RING_SIZE; |
| 333 | priv->rx_ring_size = DEFAULT_RX_RING_SIZE; | 329 | priv->rx_ring_size = DEFAULT_RX_RING_SIZE; |
| 334 | 330 | ||
| @@ -350,6 +346,9 @@ static int gfar_probe(struct platform_device *pdev) | |||
| 350 | goto register_fail; | 346 | goto register_fail; |
| 351 | } | 347 | } |
| 352 | 348 | ||
| 349 | /* Create all the sysfs files */ | ||
| 350 | gfar_init_sysfs(dev); | ||
| 351 | |||
| 353 | /* Print out the device info */ | 352 | /* Print out the device info */ |
| 354 | printk(KERN_INFO DEVICE_NAME, dev->name); | 353 | printk(KERN_INFO DEVICE_NAME, dev->name); |
| 355 | for (idx = 0; idx < 6; idx++) | 354 | for (idx = 0; idx < 6; idx++) |
| @@ -357,8 +356,7 @@ static int gfar_probe(struct platform_device *pdev) | |||
| 357 | printk("\n"); | 356 | printk("\n"); |
| 358 | 357 | ||
| 359 | /* Even more device info helps when determining which kernel */ | 358 | /* Even more device info helps when determining which kernel */ |
| 360 | /* provided which set of benchmarks. Since this is global for all */ | 359 | /* provided which set of benchmarks. */ |
| 361 | /* devices, we only print it once */ | ||
| 362 | #ifdef CONFIG_GFAR_NAPI | 360 | #ifdef CONFIG_GFAR_NAPI |
| 363 | printk(KERN_INFO "%s: Running with NAPI enabled\n", dev->name); | 361 | printk(KERN_INFO "%s: Running with NAPI enabled\n", dev->name); |
| 364 | #else | 362 | #else |
| @@ -463,19 +461,9 @@ static void init_registers(struct net_device *dev) | |||
| 463 | /* Initialize the max receive buffer length */ | 461 | /* Initialize the max receive buffer length */ |
| 464 | gfar_write(&priv->regs->mrblr, priv->rx_buffer_size); | 462 | gfar_write(&priv->regs->mrblr, priv->rx_buffer_size); |
| 465 | 463 | ||
| 466 | #ifdef CONFIG_GFAR_BUFSTASH | ||
| 467 | /* If we are stashing buffers, we need to set the | ||
| 468 | * extraction length to the size of the buffer */ | ||
| 469 | gfar_write(&priv->regs->attreli, priv->rx_stash_size << 16); | ||
| 470 | #endif | ||
| 471 | |||
| 472 | /* Initialize the Minimum Frame Length Register */ | 464 | /* Initialize the Minimum Frame Length Register */ |
| 473 | gfar_write(&priv->regs->minflr, MINFLR_INIT_SETTINGS); | 465 | gfar_write(&priv->regs->minflr, MINFLR_INIT_SETTINGS); |
| 474 | 466 | ||
| 475 | /* Setup Attributes so that snooping is on for rx */ | ||
| 476 | gfar_write(&priv->regs->attr, ATTR_INIT_SETTINGS); | ||
| 477 | gfar_write(&priv->regs->attreli, ATTRELI_INIT_SETTINGS); | ||
| 478 | |||
| 479 | /* Assign the TBI an address which won't conflict with the PHYs */ | 467 | /* Assign the TBI an address which won't conflict with the PHYs */ |
| 480 | gfar_write(&priv->regs->tbipa, TBIPA_VALUE); | 468 | gfar_write(&priv->regs->tbipa, TBIPA_VALUE); |
| 481 | } | 469 | } |
| @@ -577,8 +565,7 @@ static void free_skb_resources(struct gfar_private *priv) | |||
| 577 | for (i = 0; i < priv->rx_ring_size; i++) { | 565 | for (i = 0; i < priv->rx_ring_size; i++) { |
| 578 | if (priv->rx_skbuff[i]) { | 566 | if (priv->rx_skbuff[i]) { |
| 579 | dma_unmap_single(NULL, rxbdp->bufPtr, | 567 | dma_unmap_single(NULL, rxbdp->bufPtr, |
| 580 | priv->rx_buffer_size | 568 | priv->rx_buffer_size, |
| 581 | + RXBUF_ALIGNMENT, | ||
| 582 | DMA_FROM_DEVICE); | 569 | DMA_FROM_DEVICE); |
| 583 | 570 | ||
| 584 | dev_kfree_skb_any(priv->rx_skbuff[i]); | 571 | dev_kfree_skb_any(priv->rx_skbuff[i]); |
| @@ -636,6 +623,7 @@ int startup_gfar(struct net_device *dev) | |||
| 636 | struct gfar *regs = priv->regs; | 623 | struct gfar *regs = priv->regs; |
| 637 | int err = 0; | 624 | int err = 0; |
| 638 | u32 rctrl = 0; | 625 | u32 rctrl = 0; |
| 626 | u32 attrs = 0; | ||
| 639 | 627 | ||
| 640 | gfar_write(®s->imask, IMASK_INIT_CLEAR); | 628 | gfar_write(®s->imask, IMASK_INIT_CLEAR); |
| 641 | 629 | ||
| @@ -795,18 +783,50 @@ int startup_gfar(struct net_device *dev) | |||
| 795 | if (priv->rx_csum_enable) | 783 | if (priv->rx_csum_enable) |
| 796 | rctrl |= RCTRL_CHECKSUMMING; | 784 | rctrl |= RCTRL_CHECKSUMMING; |
| 797 | 785 | ||
| 798 | if (priv->extended_hash) | 786 | if (priv->extended_hash) { |
| 799 | rctrl |= RCTRL_EXTHASH; | 787 | rctrl |= RCTRL_EXTHASH; |
| 800 | 788 | ||
| 789 | gfar_clear_exact_match(dev); | ||
| 790 | rctrl |= RCTRL_EMEN; | ||
| 791 | } | ||
| 792 | |||
| 801 | if (priv->vlan_enable) | 793 | if (priv->vlan_enable) |
| 802 | rctrl |= RCTRL_VLAN; | 794 | rctrl |= RCTRL_VLAN; |
| 803 | 795 | ||
| 796 | if (priv->padding) { | ||
| 797 | rctrl &= ~RCTRL_PAL_MASK; | ||
| 798 | rctrl |= RCTRL_PADDING(priv->padding); | ||
| 799 | } | ||
| 800 | |||
| 804 | /* Init rctrl based on our settings */ | 801 | /* Init rctrl based on our settings */ |
| 805 | gfar_write(&priv->regs->rctrl, rctrl); | 802 | gfar_write(&priv->regs->rctrl, rctrl); |
| 806 | 803 | ||
| 807 | if (dev->features & NETIF_F_IP_CSUM) | 804 | if (dev->features & NETIF_F_IP_CSUM) |
| 808 | gfar_write(&priv->regs->tctrl, TCTRL_INIT_CSUM); | 805 | gfar_write(&priv->regs->tctrl, TCTRL_INIT_CSUM); |
| 809 | 806 | ||
| 807 | /* Set the extraction length and index */ | ||
| 808 | attrs = ATTRELI_EL(priv->rx_stash_size) | | ||
| 809 | ATTRELI_EI(priv->rx_stash_index); | ||
| 810 | |||
| 811 | gfar_write(&priv->regs->attreli, attrs); | ||
| 812 | |||
| 813 | /* Start with defaults, and add stashing or locking | ||
| 814 | * depending on the approprate variables */ | ||
| 815 | attrs = ATTR_INIT_SETTINGS; | ||
| 816 | |||
| 817 | if (priv->bd_stash_en) | ||
| 818 | attrs |= ATTR_BDSTASH; | ||
| 819 | |||
| 820 | if (priv->rx_stash_size != 0) | ||
| 821 | attrs |= ATTR_BUFSTASH; | ||
| 822 | |||
| 823 | gfar_write(&priv->regs->attr, attrs); | ||
| 824 | |||
| 825 | gfar_write(&priv->regs->fifo_tx_thr, priv->fifo_threshold); | ||
| 826 | gfar_write(&priv->regs->fifo_tx_starve, priv->fifo_starve); | ||
| 827 | gfar_write(&priv->regs->fifo_tx_starve_shutoff, priv->fifo_starve_off); | ||
| 828 | |||
| 829 | /* Start the controller */ | ||
| 810 | gfar_start(dev); | 830 | gfar_start(dev); |
| 811 | 831 | ||
| 812 | return 0; | 832 | return 0; |
| @@ -851,34 +871,32 @@ static int gfar_enet_open(struct net_device *dev) | |||
| 851 | return err; | 871 | return err; |
| 852 | } | 872 | } |
| 853 | 873 | ||
| 854 | static struct txfcb *gfar_add_fcb(struct sk_buff *skb, struct txbd8 *bdp) | 874 | static inline struct txfcb *gfar_add_fcb(struct sk_buff *skb, struct txbd8 *bdp) |
| 855 | { | 875 | { |
| 856 | struct txfcb *fcb = (struct txfcb *)skb_push (skb, GMAC_FCB_LEN); | 876 | struct txfcb *fcb = (struct txfcb *)skb_push (skb, GMAC_FCB_LEN); |
| 857 | 877 | ||
| 858 | memset(fcb, 0, GMAC_FCB_LEN); | 878 | memset(fcb, 0, GMAC_FCB_LEN); |
| 859 | 879 | ||
| 860 | /* Flag the bd so the controller looks for the FCB */ | ||
| 861 | bdp->status |= TXBD_TOE; | ||
| 862 | |||
| 863 | return fcb; | 880 | return fcb; |
| 864 | } | 881 | } |
| 865 | 882 | ||
| 866 | static inline void gfar_tx_checksum(struct sk_buff *skb, struct txfcb *fcb) | 883 | static inline void gfar_tx_checksum(struct sk_buff *skb, struct txfcb *fcb) |
| 867 | { | 884 | { |
| 868 | int len; | 885 | u8 flags = 0; |
| 869 | 886 | ||
| 870 | /* If we're here, it's a IP packet with a TCP or UDP | 887 | /* If we're here, it's a IP packet with a TCP or UDP |
| 871 | * payload. We set it to checksum, using a pseudo-header | 888 | * payload. We set it to checksum, using a pseudo-header |
| 872 | * we provide | 889 | * we provide |
| 873 | */ | 890 | */ |
| 874 | fcb->ip = 1; | 891 | flags = TXFCB_DEFAULT; |
| 875 | fcb->tup = 1; | ||
| 876 | fcb->ctu = 1; | ||
| 877 | fcb->nph = 1; | ||
| 878 | 892 | ||
| 879 | /* Notify the controller what the protocol is */ | 893 | /* Tell the controller what the protocol is */ |
| 880 | if (skb->nh.iph->protocol == IPPROTO_UDP) | 894 | /* And provide the already calculated phcs */ |
| 881 | fcb->udp = 1; | 895 | if (skb->nh.iph->protocol == IPPROTO_UDP) { |
| 896 | flags |= TXFCB_UDP; | ||
| 897 | fcb->phcs = skb->h.uh->check; | ||
| 898 | } else | ||
| 899 | fcb->phcs = skb->h.th->check; | ||
| 882 | 900 | ||
| 883 | /* l3os is the distance between the start of the | 901 | /* l3os is the distance between the start of the |
| 884 | * frame (skb->data) and the start of the IP hdr. | 902 | * frame (skb->data) and the start of the IP hdr. |
| @@ -887,17 +905,12 @@ static inline void gfar_tx_checksum(struct sk_buff *skb, struct txfcb *fcb) | |||
| 887 | fcb->l3os = (u16)(skb->nh.raw - skb->data - GMAC_FCB_LEN); | 905 | fcb->l3os = (u16)(skb->nh.raw - skb->data - GMAC_FCB_LEN); |
| 888 | fcb->l4os = (u16)(skb->h.raw - skb->nh.raw); | 906 | fcb->l4os = (u16)(skb->h.raw - skb->nh.raw); |
| 889 | 907 | ||
| 890 | len = skb->nh.iph->tot_len - fcb->l4os; | 908 | fcb->flags = flags; |
| 891 | |||
| 892 | /* Provide the pseudoheader csum */ | ||
| 893 | fcb->phcs = ~csum_tcpudp_magic(skb->nh.iph->saddr, | ||
| 894 | skb->nh.iph->daddr, len, | ||
| 895 | skb->nh.iph->protocol, 0); | ||
| 896 | } | 909 | } |
| 897 | 910 | ||
| 898 | void gfar_tx_vlan(struct sk_buff *skb, struct txfcb *fcb) | 911 | void inline gfar_tx_vlan(struct sk_buff *skb, struct txfcb *fcb) |
| 899 | { | 912 | { |
| 900 | fcb->vln = 1; | 913 | fcb->flags |= TXFCB_VLN; |
| 901 | fcb->vlctl = vlan_tx_tag_get(skb); | 914 | fcb->vlctl = vlan_tx_tag_get(skb); |
| 902 | } | 915 | } |
| 903 | 916 | ||
| @@ -908,6 +921,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 908 | struct gfar_private *priv = netdev_priv(dev); | 921 | struct gfar_private *priv = netdev_priv(dev); |
| 909 | struct txfcb *fcb = NULL; | 922 | struct txfcb *fcb = NULL; |
| 910 | struct txbd8 *txbdp; | 923 | struct txbd8 *txbdp; |
| 924 | u16 status; | ||
| 911 | 925 | ||
| 912 | /* Update transmit stats */ | 926 | /* Update transmit stats */ |
| 913 | priv->stats.tx_bytes += skb->len; | 927 | priv->stats.tx_bytes += skb->len; |
| @@ -919,19 +933,22 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 919 | txbdp = priv->cur_tx; | 933 | txbdp = priv->cur_tx; |
| 920 | 934 | ||
| 921 | /* Clear all but the WRAP status flags */ | 935 | /* Clear all but the WRAP status flags */ |
| 922 | txbdp->status &= TXBD_WRAP; | 936 | status = txbdp->status & TXBD_WRAP; |
| 923 | 937 | ||
| 924 | /* Set up checksumming */ | 938 | /* Set up checksumming */ |
| 925 | if ((dev->features & NETIF_F_IP_CSUM) | 939 | if (likely((dev->features & NETIF_F_IP_CSUM) |
| 926 | && (CHECKSUM_HW == skb->ip_summed)) { | 940 | && (CHECKSUM_HW == skb->ip_summed))) { |
| 927 | fcb = gfar_add_fcb(skb, txbdp); | 941 | fcb = gfar_add_fcb(skb, txbdp); |
| 942 | status |= TXBD_TOE; | ||
| 928 | gfar_tx_checksum(skb, fcb); | 943 | gfar_tx_checksum(skb, fcb); |
| 929 | } | 944 | } |
| 930 | 945 | ||
| 931 | if (priv->vlan_enable && | 946 | if (priv->vlan_enable && |
| 932 | unlikely(priv->vlgrp && vlan_tx_tag_present(skb))) { | 947 | unlikely(priv->vlgrp && vlan_tx_tag_present(skb))) { |
| 933 | if (NULL == fcb) | 948 | if (unlikely(NULL == fcb)) { |
| 934 | fcb = gfar_add_fcb(skb, txbdp); | 949 | fcb = gfar_add_fcb(skb, txbdp); |
| 950 | status |= TXBD_TOE; | ||
| 951 | } | ||
| 935 | 952 | ||
| 936 | gfar_tx_vlan(skb, fcb); | 953 | gfar_tx_vlan(skb, fcb); |
| 937 | } | 954 | } |
| @@ -949,14 +966,16 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 949 | (priv->skb_curtx + 1) & TX_RING_MOD_MASK(priv->tx_ring_size); | 966 | (priv->skb_curtx + 1) & TX_RING_MOD_MASK(priv->tx_ring_size); |
| 950 | 967 | ||
| 951 | /* Flag the BD as interrupt-causing */ | 968 | /* Flag the BD as interrupt-causing */ |
| 952 | txbdp->status |= TXBD_INTERRUPT; | 969 | status |= TXBD_INTERRUPT; |
| 953 | 970 | ||
| 954 | /* Flag the BD as ready to go, last in frame, and */ | 971 | /* Flag the BD as ready to go, last in frame, and */ |
| 955 | /* in need of CRC */ | 972 | /* in need of CRC */ |
| 956 | txbdp->status |= (TXBD_READY | TXBD_LAST | TXBD_CRC); | 973 | status |= (TXBD_READY | TXBD_LAST | TXBD_CRC); |
| 957 | 974 | ||
| 958 | dev->trans_start = jiffies; | 975 | dev->trans_start = jiffies; |
| 959 | 976 | ||
| 977 | txbdp->status = status; | ||
| 978 | |||
| 960 | /* If this was the last BD in the ring, the next one */ | 979 | /* If this was the last BD in the ring, the next one */ |
| 961 | /* is at the beginning of the ring */ | 980 | /* is at the beginning of the ring */ |
| 962 | if (txbdp->status & TXBD_WRAP) | 981 | if (txbdp->status & TXBD_WRAP) |
| @@ -1010,21 +1029,7 @@ static struct net_device_stats * gfar_get_stats(struct net_device *dev) | |||
| 1010 | /* Changes the mac address if the controller is not running. */ | 1029 | /* Changes the mac address if the controller is not running. */ |
| 1011 | int gfar_set_mac_address(struct net_device *dev) | 1030 | int gfar_set_mac_address(struct net_device *dev) |
| 1012 | { | 1031 | { |
| 1013 | struct gfar_private *priv = netdev_priv(dev); | 1032 | gfar_set_mac_for_addr(dev, 0, dev->dev_addr); |
| 1014 | int i; | ||
| 1015 | char tmpbuf[MAC_ADDR_LEN]; | ||
| 1016 | u32 tempval; | ||
| 1017 | |||
| 1018 | /* Now copy it into the mac registers backwards, cuz */ | ||
| 1019 | /* little endian is silly */ | ||
| 1020 | for (i = 0; i < MAC_ADDR_LEN; i++) | ||
| 1021 | tmpbuf[MAC_ADDR_LEN - 1 - i] = dev->dev_addr[i]; | ||
| 1022 | |||
| 1023 | gfar_write(&priv->regs->macstnaddr1, *((u32 *) (tmpbuf))); | ||
| 1024 | |||
| 1025 | tempval = *((u32 *) (tmpbuf + 4)); | ||
| 1026 | |||
| 1027 | gfar_write(&priv->regs->macstnaddr2, tempval); | ||
| 1028 | 1033 | ||
| 1029 | return 0; | 1034 | return 0; |
| 1030 | } | 1035 | } |
| @@ -1110,7 +1115,7 @@ static int gfar_change_mtu(struct net_device *dev, int new_mtu) | |||
| 1110 | INCREMENTAL_BUFFER_SIZE; | 1115 | INCREMENTAL_BUFFER_SIZE; |
| 1111 | 1116 | ||
| 1112 | /* Only stop and start the controller if it isn't already | 1117 | /* Only stop and start the controller if it isn't already |
| 1113 | * stopped */ | 1118 | * stopped, and we changed something */ |
| 1114 | if ((oldsize != tempsize) && (dev->flags & IFF_UP)) | 1119 | if ((oldsize != tempsize) && (dev->flags & IFF_UP)) |
| 1115 | stop_gfar(dev); | 1120 | stop_gfar(dev); |
| 1116 | 1121 | ||
| @@ -1220,6 +1225,7 @@ static irqreturn_t gfar_transmit(int irq, void *dev_id, struct pt_regs *regs) | |||
| 1220 | 1225 | ||
| 1221 | struct sk_buff * gfar_new_skb(struct net_device *dev, struct rxbd8 *bdp) | 1226 | struct sk_buff * gfar_new_skb(struct net_device *dev, struct rxbd8 *bdp) |
| 1222 | { | 1227 | { |
| 1228 | unsigned int alignamount; | ||
| 1223 | struct gfar_private *priv = netdev_priv(dev); | 1229 | struct gfar_private *priv = netdev_priv(dev); |
| 1224 | struct sk_buff *skb = NULL; | 1230 | struct sk_buff *skb = NULL; |
| 1225 | unsigned int timeout = SKB_ALLOC_TIMEOUT; | 1231 | unsigned int timeout = SKB_ALLOC_TIMEOUT; |
| @@ -1231,18 +1237,18 @@ struct sk_buff * gfar_new_skb(struct net_device *dev, struct rxbd8 *bdp) | |||
| 1231 | if (NULL == skb) | 1237 | if (NULL == skb) |
| 1232 | return NULL; | 1238 | return NULL; |
| 1233 | 1239 | ||
| 1240 | alignamount = RXBUF_ALIGNMENT - | ||
| 1241 | (((unsigned) skb->data) & (RXBUF_ALIGNMENT - 1)); | ||
| 1242 | |||
| 1234 | /* We need the data buffer to be aligned properly. We will reserve | 1243 | /* We need the data buffer to be aligned properly. We will reserve |
| 1235 | * as many bytes as needed to align the data properly | 1244 | * as many bytes as needed to align the data properly |
| 1236 | */ | 1245 | */ |
| 1237 | skb_reserve(skb, | 1246 | skb_reserve(skb, alignamount); |
| 1238 | RXBUF_ALIGNMENT - | ||
| 1239 | (((unsigned) skb->data) & (RXBUF_ALIGNMENT - 1))); | ||
| 1240 | 1247 | ||
| 1241 | skb->dev = dev; | 1248 | skb->dev = dev; |
| 1242 | 1249 | ||
| 1243 | bdp->bufPtr = dma_map_single(NULL, skb->data, | 1250 | bdp->bufPtr = dma_map_single(NULL, skb->data, |
| 1244 | priv->rx_buffer_size + RXBUF_ALIGNMENT, | 1251 | priv->rx_buffer_size, DMA_FROM_DEVICE); |
| 1245 | DMA_FROM_DEVICE); | ||
| 1246 | 1252 | ||
| 1247 | bdp->length = 0; | 1253 | bdp->length = 0; |
| 1248 | 1254 | ||
| @@ -1350,7 +1356,7 @@ static inline void gfar_rx_checksum(struct sk_buff *skb, struct rxfcb *fcb) | |||
| 1350 | /* If valid headers were found, and valid sums | 1356 | /* If valid headers were found, and valid sums |
| 1351 | * were verified, then we tell the kernel that no | 1357 | * were verified, then we tell the kernel that no |
| 1352 | * checksumming is necessary. Otherwise, it is */ | 1358 | * checksumming is necessary. Otherwise, it is */ |
| 1353 | if (fcb->cip && !fcb->eip && fcb->ctu && !fcb->etu) | 1359 | if ((fcb->flags & RXFCB_CSUM_MASK) == (RXFCB_CIP | RXFCB_CTU)) |
| 1354 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 1360 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
| 1355 | else | 1361 | else |
| 1356 | skb->ip_summed = CHECKSUM_NONE; | 1362 | skb->ip_summed = CHECKSUM_NONE; |
| @@ -1401,7 +1407,7 @@ static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, | |||
| 1401 | skb->protocol = eth_type_trans(skb, dev); | 1407 | skb->protocol = eth_type_trans(skb, dev); |
| 1402 | 1408 | ||
| 1403 | /* Send the packet up the stack */ | 1409 | /* Send the packet up the stack */ |
| 1404 | if (unlikely(priv->vlgrp && fcb->vln)) | 1410 | if (unlikely(priv->vlgrp && (fcb->flags & RXFCB_VLN))) |
| 1405 | ret = gfar_rx_vlan(skb, priv->vlgrp, fcb->vlctl); | 1411 | ret = gfar_rx_vlan(skb, priv->vlgrp, fcb->vlctl); |
| 1406 | else | 1412 | else |
| 1407 | ret = RECEIVE(skb); | 1413 | ret = RECEIVE(skb); |
| @@ -1620,6 +1626,7 @@ static void adjust_link(struct net_device *dev) | |||
| 1620 | spin_lock_irqsave(&priv->lock, flags); | 1626 | spin_lock_irqsave(&priv->lock, flags); |
| 1621 | if (phydev->link) { | 1627 | if (phydev->link) { |
| 1622 | u32 tempval = gfar_read(®s->maccfg2); | 1628 | u32 tempval = gfar_read(®s->maccfg2); |
| 1629 | u32 ecntrl = gfar_read(®s->ecntrl); | ||
| 1623 | 1630 | ||
| 1624 | /* Now we make sure that we can be in full duplex mode. | 1631 | /* Now we make sure that we can be in full duplex mode. |
| 1625 | * If not, we operate in half-duplex mode. */ | 1632 | * If not, we operate in half-duplex mode. */ |
| @@ -1644,6 +1651,13 @@ static void adjust_link(struct net_device *dev) | |||
| 1644 | case 10: | 1651 | case 10: |
| 1645 | tempval = | 1652 | tempval = |
| 1646 | ((tempval & ~(MACCFG2_IF)) | MACCFG2_MII); | 1653 | ((tempval & ~(MACCFG2_IF)) | MACCFG2_MII); |
| 1654 | |||
| 1655 | /* Reduced mode distinguishes | ||
| 1656 | * between 10 and 100 */ | ||
| 1657 | if (phydev->speed == SPEED_100) | ||
| 1658 | ecntrl |= ECNTRL_R100; | ||
| 1659 | else | ||
| 1660 | ecntrl &= ~(ECNTRL_R100); | ||
| 1647 | break; | 1661 | break; |
| 1648 | default: | 1662 | default: |
| 1649 | if (netif_msg_link(priv)) | 1663 | if (netif_msg_link(priv)) |
| @@ -1657,6 +1671,7 @@ static void adjust_link(struct net_device *dev) | |||
| 1657 | } | 1671 | } |
| 1658 | 1672 | ||
| 1659 | gfar_write(®s->maccfg2, tempval); | 1673 | gfar_write(®s->maccfg2, tempval); |
| 1674 | gfar_write(®s->ecntrl, ecntrl); | ||
| 1660 | 1675 | ||
| 1661 | if (!priv->oldlink) { | 1676 | if (!priv->oldlink) { |
| 1662 | new_state = 1; | 1677 | new_state = 1; |
| @@ -1721,6 +1736,9 @@ static void gfar_set_multi(struct net_device *dev) | |||
| 1721 | gfar_write(®s->gaddr6, 0xffffffff); | 1736 | gfar_write(®s->gaddr6, 0xffffffff); |
| 1722 | gfar_write(®s->gaddr7, 0xffffffff); | 1737 | gfar_write(®s->gaddr7, 0xffffffff); |
| 1723 | } else { | 1738 | } else { |
| 1739 | int em_num; | ||
| 1740 | int idx; | ||
| 1741 | |||
| 1724 | /* zero out the hash */ | 1742 | /* zero out the hash */ |
| 1725 | gfar_write(®s->igaddr0, 0x0); | 1743 | gfar_write(®s->igaddr0, 0x0); |
| 1726 | gfar_write(®s->igaddr1, 0x0); | 1744 | gfar_write(®s->igaddr1, 0x0); |
| @@ -1739,18 +1757,47 @@ static void gfar_set_multi(struct net_device *dev) | |||
| 1739 | gfar_write(®s->gaddr6, 0x0); | 1757 | gfar_write(®s->gaddr6, 0x0); |
| 1740 | gfar_write(®s->gaddr7, 0x0); | 1758 | gfar_write(®s->gaddr7, 0x0); |
| 1741 | 1759 | ||
| 1760 | /* If we have extended hash tables, we need to | ||
| 1761 | * clear the exact match registers to prepare for | ||
| 1762 | * setting them */ | ||
| 1763 | if (priv->extended_hash) { | ||
| 1764 | em_num = GFAR_EM_NUM + 1; | ||
| 1765 | gfar_clear_exact_match(dev); | ||
| 1766 | idx = 1; | ||
| 1767 | } else { | ||
| 1768 | idx = 0; | ||
| 1769 | em_num = 0; | ||
| 1770 | } | ||
| 1771 | |||
| 1742 | if(dev->mc_count == 0) | 1772 | if(dev->mc_count == 0) |
| 1743 | return; | 1773 | return; |
| 1744 | 1774 | ||
| 1745 | /* Parse the list, and set the appropriate bits */ | 1775 | /* Parse the list, and set the appropriate bits */ |
| 1746 | for(mc_ptr = dev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) { | 1776 | for(mc_ptr = dev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) { |
| 1747 | gfar_set_hash_for_addr(dev, mc_ptr->dmi_addr); | 1777 | if (idx < em_num) { |
| 1778 | gfar_set_mac_for_addr(dev, idx, | ||
| 1779 | mc_ptr->dmi_addr); | ||
| 1780 | idx++; | ||
| 1781 | } else | ||
| 1782 | gfar_set_hash_for_addr(dev, mc_ptr->dmi_addr); | ||
| 1748 | } | 1783 | } |
| 1749 | } | 1784 | } |
| 1750 | 1785 | ||
| 1751 | return; | 1786 | return; |
| 1752 | } | 1787 | } |
| 1753 | 1788 | ||
| 1789 | |||
| 1790 | /* Clears each of the exact match registers to zero, so they | ||
| 1791 | * don't interfere with normal reception */ | ||
| 1792 | static void gfar_clear_exact_match(struct net_device *dev) | ||
| 1793 | { | ||
| 1794 | int idx; | ||
| 1795 | u8 zero_arr[MAC_ADDR_LEN] = {0,0,0,0,0,0}; | ||
| 1796 | |||
| 1797 | for(idx = 1;idx < GFAR_EM_NUM + 1;idx++) | ||
| 1798 | gfar_set_mac_for_addr(dev, idx, (u8 *)zero_arr); | ||
| 1799 | } | ||
| 1800 | |||
| 1754 | /* Set the appropriate hash bit for the given addr */ | 1801 | /* Set the appropriate hash bit for the given addr */ |
| 1755 | /* The algorithm works like so: | 1802 | /* The algorithm works like so: |
| 1756 | * 1) Take the Destination Address (ie the multicast address), and | 1803 | * 1) Take the Destination Address (ie the multicast address), and |
| @@ -1781,6 +1828,32 @@ static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr) | |||
| 1781 | return; | 1828 | return; |
| 1782 | } | 1829 | } |
| 1783 | 1830 | ||
| 1831 | |||
| 1832 | /* There are multiple MAC Address register pairs on some controllers | ||
| 1833 | * This function sets the numth pair to a given address | ||
| 1834 | */ | ||
| 1835 | static void gfar_set_mac_for_addr(struct net_device *dev, int num, u8 *addr) | ||
| 1836 | { | ||
| 1837 | struct gfar_private *priv = netdev_priv(dev); | ||
| 1838 | int idx; | ||
| 1839 | char tmpbuf[MAC_ADDR_LEN]; | ||
| 1840 | u32 tempval; | ||
| 1841 | u32 *macptr = &priv->regs->macstnaddr1; | ||
| 1842 | |||
| 1843 | macptr += num*2; | ||
| 1844 | |||
| 1845 | /* Now copy it into the mac registers backwards, cuz */ | ||
| 1846 | /* little endian is silly */ | ||
| 1847 | for (idx = 0; idx < MAC_ADDR_LEN; idx++) | ||
| 1848 | tmpbuf[MAC_ADDR_LEN - 1 - idx] = addr[idx]; | ||
| 1849 | |||
| 1850 | gfar_write(macptr, *((u32 *) (tmpbuf))); | ||
| 1851 | |||
| 1852 | tempval = *((u32 *) (tmpbuf + 4)); | ||
| 1853 | |||
| 1854 | gfar_write(macptr+1, tempval); | ||
| 1855 | } | ||
| 1856 | |||
| 1784 | /* GFAR error interrupt handler */ | 1857 | /* GFAR error interrupt handler */ |
| 1785 | static irqreturn_t gfar_error(int irq, void *dev_id, struct pt_regs *regs) | 1858 | static irqreturn_t gfar_error(int irq, void *dev_id, struct pt_regs *regs) |
| 1786 | { | 1859 | { |
