diff options
author | Andy Fleming <afleming@freescale.com> | 2005-11-11 13:38:59 -0500 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-11-18 13:31:26 -0500 |
commit | 7f7f53168dbee6d6a462acea666fddd18aad4f08 (patch) | |
tree | 9c59f9b4b7c06f70b48197408f37398e54b4771e /drivers/net/gianfar.c | |
parent | fed5eccdcf542742786701b2514b5cb7ab282b93 (diff) |
[PATCH] Gianfar update and sysfs support
This seems to have gotten lost, so I'll resend.
Signed-off-by: Andy Fleming <afleming@freescale.com>
* Added sysfs support to gianfar for modifying FIFO and stashing parameters
* Updated driver to support 10 Mbit, full duplex operation
* Improved comments throughout
* Cleaned up and optimized offloading code
* Fixed a bug where rx buffers were being improperly mapped and unmapped
* (only manifested if cache-coherency was off)
* Added support for using the eTSEC exact-match MAC registers
* Bumped the version to 1.3
* Added support for distinguishing between reduced 100 and 10 Mbit modes
* Modified default coalescing values to lower latency
* Added documentation
Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
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 | { |