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 | |
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>
-rw-r--r-- | Documentation/networking/gianfar.txt | 72 | ||||
-rw-r--r-- | drivers/net/Makefile | 5 | ||||
-rw-r--r-- | drivers/net/gianfar.c | 231 | ||||
-rw-r--r-- | drivers/net/gianfar.h | 69 | ||||
-rw-r--r-- | drivers/net/gianfar_ethtool.c | 2 | ||||
-rw-r--r-- | drivers/net/gianfar_mii.h | 1 | ||||
-rw-r--r-- | drivers/net/gianfar_sysfs.c | 311 |
7 files changed, 579 insertions, 112 deletions
diff --git a/Documentation/networking/gianfar.txt b/Documentation/networking/gianfar.txt new file mode 100644 index 000000000000..ad474ea07d07 --- /dev/null +++ b/Documentation/networking/gianfar.txt | |||
@@ -0,0 +1,72 @@ | |||
1 | The Gianfar Ethernet Driver | ||
2 | Sysfs File description | ||
3 | |||
4 | Author: Andy Fleming <afleming@freescale.com> | ||
5 | Updated: 2005-07-28 | ||
6 | |||
7 | SYSFS | ||
8 | |||
9 | Several of the features of the gianfar driver are controlled | ||
10 | through sysfs files. These are: | ||
11 | |||
12 | bd_stash: | ||
13 | To stash RX Buffer Descriptors in the L2, echo 'on' or '1' to | ||
14 | bd_stash, echo 'off' or '0' to disable | ||
15 | |||
16 | rx_stash_len: | ||
17 | To stash the first n bytes of the packet in L2, echo the number | ||
18 | of bytes to buf_stash_len. echo 0 to disable. | ||
19 | |||
20 | WARNING: You could really screw these up if you set them too low or high! | ||
21 | fifo_threshold: | ||
22 | To change the number of bytes the controller needs in the | ||
23 | fifo before it starts transmission, echo the number of bytes to | ||
24 | fifo_thresh. Range should be 0-511. | ||
25 | |||
26 | fifo_starve: | ||
27 | When the FIFO has less than this many bytes during a transmit, it | ||
28 | enters starve mode, and increases the priority of TX memory | ||
29 | transactions. To change, echo the number of bytes to | ||
30 | fifo_starve. Range should be 0-511. | ||
31 | |||
32 | fifo_starve_off: | ||
33 | Once in starve mode, the FIFO remains there until it has this | ||
34 | many bytes. To change, echo the number of bytes to | ||
35 | fifo_starve_off. Range should be 0-511. | ||
36 | |||
37 | CHECKSUM OFFLOADING | ||
38 | |||
39 | The eTSEC controller (first included in parts from late 2005 like | ||
40 | the 8548) has the ability to perform TCP, UDP, and IP checksums | ||
41 | in hardware. The Linux kernel only offloads the TCP and UDP | ||
42 | checksums (and always performs the pseudo header checksums), so | ||
43 | the driver only supports checksumming for TCP/IP and UDP/IP | ||
44 | packets. Use ethtool to enable or disable this feature for RX | ||
45 | and TX. | ||
46 | |||
47 | VLAN | ||
48 | |||
49 | In order to use VLAN, please consult Linux documentation on | ||
50 | configuring VLANs. The gianfar driver supports hardware insertion and | ||
51 | extraction of VLAN headers, but not filtering. Filtering will be | ||
52 | done by the kernel. | ||
53 | |||
54 | MULTICASTING | ||
55 | |||
56 | The gianfar driver supports using the group hash table on the | ||
57 | TSEC (and the extended hash table on the eTSEC) for multicast | ||
58 | filtering. On the eTSEC, the exact-match MAC registers are used | ||
59 | before the hash tables. See Linux documentation on how to join | ||
60 | multicast groups. | ||
61 | |||
62 | PADDING | ||
63 | |||
64 | The gianfar driver supports padding received frames with 2 bytes | ||
65 | to align the IP header to a 16-byte boundary, when supported by | ||
66 | hardware. | ||
67 | |||
68 | ETHTOOL | ||
69 | |||
70 | The gianfar driver supports the use of ethtool for many | ||
71 | configuration options. You must run ethtool only on currently | ||
72 | open interfaces. See ethtool documentation for details. | ||
diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 27822a2f0683..505681406314 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile | |||
@@ -13,7 +13,10 @@ obj-$(CONFIG_CHELSIO_T1) += chelsio/ | |||
13 | obj-$(CONFIG_BONDING) += bonding/ | 13 | obj-$(CONFIG_BONDING) += bonding/ |
14 | obj-$(CONFIG_GIANFAR) += gianfar_driver.o | 14 | obj-$(CONFIG_GIANFAR) += gianfar_driver.o |
15 | 15 | ||
16 | gianfar_driver-objs := gianfar.o gianfar_ethtool.o gianfar_mii.o | 16 | gianfar_driver-objs := gianfar.o \ |
17 | gianfar_ethtool.o \ | ||
18 | gianfar_mii.o \ | ||
19 | gianfar_sysfs.o | ||
17 | 20 | ||
18 | # | 21 | # |
19 | # link order important here | 22 | # link order important here |
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 | { |
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index 5065ba82cb76..94a91da84fbb 100644 --- a/drivers/net/gianfar.h +++ b/drivers/net/gianfar.h | |||
@@ -90,12 +90,26 @@ extern const char gfar_driver_version[]; | |||
90 | #define GFAR_RX_MAX_RING_SIZE 256 | 90 | #define GFAR_RX_MAX_RING_SIZE 256 |
91 | #define GFAR_TX_MAX_RING_SIZE 256 | 91 | #define GFAR_TX_MAX_RING_SIZE 256 |
92 | 92 | ||
93 | #define GFAR_MAX_FIFO_THRESHOLD 511 | ||
94 | #define GFAR_MAX_FIFO_STARVE 511 | ||
95 | #define GFAR_MAX_FIFO_STARVE_OFF 511 | ||
96 | |||
93 | #define DEFAULT_RX_BUFFER_SIZE 1536 | 97 | #define DEFAULT_RX_BUFFER_SIZE 1536 |
94 | #define TX_RING_MOD_MASK(size) (size-1) | 98 | #define TX_RING_MOD_MASK(size) (size-1) |
95 | #define RX_RING_MOD_MASK(size) (size-1) | 99 | #define RX_RING_MOD_MASK(size) (size-1) |
96 | #define JUMBO_BUFFER_SIZE 9728 | 100 | #define JUMBO_BUFFER_SIZE 9728 |
97 | #define JUMBO_FRAME_SIZE 9600 | 101 | #define JUMBO_FRAME_SIZE 9600 |
98 | 102 | ||
103 | #define DEFAULT_FIFO_TX_THR 0x100 | ||
104 | #define DEFAULT_FIFO_TX_STARVE 0x40 | ||
105 | #define DEFAULT_FIFO_TX_STARVE_OFF 0x80 | ||
106 | #define DEFAULT_BD_STASH 1 | ||
107 | #define DEFAULT_STASH_LENGTH 64 | ||
108 | #define DEFAULT_STASH_INDEX 0 | ||
109 | |||
110 | /* The number of Exact Match registers */ | ||
111 | #define GFAR_EM_NUM 15 | ||
112 | |||
99 | /* Latency of interface clock in nanoseconds */ | 113 | /* Latency of interface clock in nanoseconds */ |
100 | /* Interface clock latency , in this case, means the | 114 | /* Interface clock latency , in this case, means the |
101 | * time described by a value of 1 in the interrupt | 115 | * time described by a value of 1 in the interrupt |
@@ -112,11 +126,11 @@ extern const char gfar_driver_version[]; | |||
112 | 126 | ||
113 | #define DEFAULT_TX_COALESCE 1 | 127 | #define DEFAULT_TX_COALESCE 1 |
114 | #define DEFAULT_TXCOUNT 16 | 128 | #define DEFAULT_TXCOUNT 16 |
115 | #define DEFAULT_TXTIME 400 | 129 | #define DEFAULT_TXTIME 4 |
116 | 130 | ||
117 | #define DEFAULT_RX_COALESCE 1 | 131 | #define DEFAULT_RX_COALESCE 1 |
118 | #define DEFAULT_RXCOUNT 16 | 132 | #define DEFAULT_RXCOUNT 16 |
119 | #define DEFAULT_RXTIME 400 | 133 | #define DEFAULT_RXTIME 4 |
120 | 134 | ||
121 | #define TBIPA_VALUE 0x1f | 135 | #define TBIPA_VALUE 0x1f |
122 | #define MIIMCFG_INIT_VALUE 0x00000007 | 136 | #define MIIMCFG_INIT_VALUE 0x00000007 |
@@ -147,6 +161,7 @@ extern const char gfar_driver_version[]; | |||
147 | 161 | ||
148 | #define ECNTRL_INIT_SETTINGS 0x00001000 | 162 | #define ECNTRL_INIT_SETTINGS 0x00001000 |
149 | #define ECNTRL_TBI_MODE 0x00000020 | 163 | #define ECNTRL_TBI_MODE 0x00000020 |
164 | #define ECNTRL_R100 0x00000008 | ||
150 | 165 | ||
151 | #define MRBLR_INIT_SETTINGS DEFAULT_RX_BUFFER_SIZE | 166 | #define MRBLR_INIT_SETTINGS DEFAULT_RX_BUFFER_SIZE |
152 | 167 | ||
@@ -181,10 +196,12 @@ extern const char gfar_driver_version[]; | |||
181 | #define RCTRL_PRSDEP_MASK 0x000000c0 | 196 | #define RCTRL_PRSDEP_MASK 0x000000c0 |
182 | #define RCTRL_PRSDEP_INIT 0x000000c0 | 197 | #define RCTRL_PRSDEP_INIT 0x000000c0 |
183 | #define RCTRL_PROM 0x00000008 | 198 | #define RCTRL_PROM 0x00000008 |
199 | #define RCTRL_EMEN 0x00000002 | ||
184 | #define RCTRL_CHECKSUMMING (RCTRL_IPCSEN \ | 200 | #define RCTRL_CHECKSUMMING (RCTRL_IPCSEN \ |
185 | | RCTRL_TUCSEN | RCTRL_PRSDEP_INIT) | 201 | | RCTRL_TUCSEN | RCTRL_PRSDEP_INIT) |
186 | #define RCTRL_EXTHASH (RCTRL_GHTX) | 202 | #define RCTRL_EXTHASH (RCTRL_GHTX) |
187 | #define RCTRL_VLAN (RCTRL_PRSDEP_INIT) | 203 | #define RCTRL_VLAN (RCTRL_PRSDEP_INIT) |
204 | #define RCTRL_PADDING(x) ((x << 16) & RCTRL_PAL_MASK) | ||
188 | 205 | ||
189 | 206 | ||
190 | #define RSTAT_CLEAR_RHALT 0x00800000 | 207 | #define RSTAT_CLEAR_RHALT 0x00800000 |
@@ -251,28 +268,26 @@ extern const char gfar_driver_version[]; | |||
251 | IMASK_XFUN | IMASK_RXC | IMASK_BABT | IMASK_DPE \ | 268 | IMASK_XFUN | IMASK_RXC | IMASK_BABT | IMASK_DPE \ |
252 | | IMASK_PERR) | 269 | | IMASK_PERR) |
253 | 270 | ||
271 | /* Fifo management */ | ||
272 | #define FIFO_TX_THR_MASK 0x01ff | ||
273 | #define FIFO_TX_STARVE_MASK 0x01ff | ||
274 | #define FIFO_TX_STARVE_OFF_MASK 0x01ff | ||
254 | 275 | ||
255 | /* Attribute fields */ | 276 | /* Attribute fields */ |
256 | 277 | ||
257 | /* This enables rx snooping for buffers and descriptors */ | 278 | /* This enables rx snooping for buffers and descriptors */ |
258 | #ifdef CONFIG_GFAR_BDSTASH | ||
259 | #define ATTR_BDSTASH 0x00000800 | 279 | #define ATTR_BDSTASH 0x00000800 |
260 | #else | ||
261 | #define ATTR_BDSTASH 0x00000000 | ||
262 | #endif | ||
263 | 280 | ||
264 | #ifdef CONFIG_GFAR_BUFSTASH | ||
265 | #define ATTR_BUFSTASH 0x00004000 | 281 | #define ATTR_BUFSTASH 0x00004000 |
266 | #define STASH_LENGTH 64 | ||
267 | #else | ||
268 | #define ATTR_BUFSTASH 0x00000000 | ||
269 | #endif | ||
270 | 282 | ||
271 | #define ATTR_SNOOPING 0x000000c0 | 283 | #define ATTR_SNOOPING 0x000000c0 |
272 | #define ATTR_INIT_SETTINGS (ATTR_SNOOPING \ | 284 | #define ATTR_INIT_SETTINGS ATTR_SNOOPING |
273 | | ATTR_BDSTASH | ATTR_BUFSTASH) | ||
274 | 285 | ||
275 | #define ATTRELI_INIT_SETTINGS 0x0 | 286 | #define ATTRELI_INIT_SETTINGS 0x0 |
287 | #define ATTRELI_EL_MASK 0x3fff0000 | ||
288 | #define ATTRELI_EL(x) (x << 16) | ||
289 | #define ATTRELI_EI_MASK 0x00003fff | ||
290 | #define ATTRELI_EI(x) (x) | ||
276 | 291 | ||
277 | 292 | ||
278 | /* TxBD status field bits */ | 293 | /* TxBD status field bits */ |
@@ -328,6 +343,7 @@ extern const char gfar_driver_version[]; | |||
328 | #define RXFCB_CTU 0x0400 | 343 | #define RXFCB_CTU 0x0400 |
329 | #define RXFCB_EIP 0x0200 | 344 | #define RXFCB_EIP 0x0200 |
330 | #define RXFCB_ETU 0x0100 | 345 | #define RXFCB_ETU 0x0100 |
346 | #define RXFCB_CSUM_MASK 0x0f00 | ||
331 | #define RXFCB_PERR_MASK 0x000c | 347 | #define RXFCB_PERR_MASK 0x000c |
332 | #define RXFCB_PERR_BADL3 0x0008 | 348 | #define RXFCB_PERR_BADL3 0x0008 |
333 | 349 | ||
@@ -339,14 +355,7 @@ struct txbd8 | |||
339 | }; | 355 | }; |
340 | 356 | ||
341 | struct txfcb { | 357 | struct txfcb { |
342 | u8 vln:1, | 358 | u8 flags; |
343 | ip:1, | ||
344 | ip6:1, | ||
345 | tup:1, | ||
346 | udp:1, | ||
347 | cip:1, | ||
348 | ctu:1, | ||
349 | nph:1; | ||
350 | u8 reserved; | 359 | u8 reserved; |
351 | u8 l4os; /* Level 4 Header Offset */ | 360 | u8 l4os; /* Level 4 Header Offset */ |
352 | u8 l3os; /* Level 3 Header Offset */ | 361 | u8 l3os; /* Level 3 Header Offset */ |
@@ -362,14 +371,7 @@ struct rxbd8 | |||
362 | }; | 371 | }; |
363 | 372 | ||
364 | struct rxfcb { | 373 | struct rxfcb { |
365 | u16 vln:1, | 374 | u16 flags; |
366 | ip:1, | ||
367 | ip6:1, | ||
368 | tup:1, | ||
369 | cip:1, | ||
370 | ctu:1, | ||
371 | eip:1, | ||
372 | etu:1; | ||
373 | u8 rq; /* Receive Queue index */ | 375 | u8 rq; /* Receive Queue index */ |
374 | u8 pro; /* Layer 4 Protocol */ | 376 | u8 pro; /* Layer 4 Protocol */ |
375 | u16 reserved; | 377 | u16 reserved; |
@@ -688,12 +690,17 @@ struct gfar_private { | |||
688 | spinlock_t lock; | 690 | spinlock_t lock; |
689 | unsigned int rx_buffer_size; | 691 | unsigned int rx_buffer_size; |
690 | unsigned int rx_stash_size; | 692 | unsigned int rx_stash_size; |
693 | unsigned int rx_stash_index; | ||
691 | unsigned int tx_ring_size; | 694 | unsigned int tx_ring_size; |
692 | unsigned int rx_ring_size; | 695 | unsigned int rx_ring_size; |
696 | unsigned int fifo_threshold; | ||
697 | unsigned int fifo_starve; | ||
698 | unsigned int fifo_starve_off; | ||
693 | 699 | ||
694 | unsigned char vlan_enable:1, | 700 | unsigned char vlan_enable:1, |
695 | rx_csum_enable:1, | 701 | rx_csum_enable:1, |
696 | extended_hash:1; | 702 | extended_hash:1, |
703 | bd_stash_en:1; | ||
697 | unsigned short padding; | 704 | unsigned short padding; |
698 | struct vlan_group *vlgrp; | 705 | struct vlan_group *vlgrp; |
699 | /* Info structure initialized by board setup code */ | 706 | /* Info structure initialized by board setup code */ |
@@ -731,6 +738,6 @@ extern void stop_gfar(struct net_device *dev); | |||
731 | extern void gfar_halt(struct net_device *dev); | 738 | extern void gfar_halt(struct net_device *dev); |
732 | extern void gfar_phy_test(struct mii_bus *bus, struct phy_device *phydev, | 739 | extern void gfar_phy_test(struct mii_bus *bus, struct phy_device *phydev, |
733 | int enable, u32 regnum, u32 read); | 740 | int enable, u32 regnum, u32 read); |
734 | void gfar_setup_stashing(struct net_device *dev); | 741 | void gfar_init_sysfs(struct net_device *dev); |
735 | 742 | ||
736 | #endif /* __GIANFAR_H */ | 743 | #endif /* __GIANFAR_H */ |
diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c index cfa3cd7c91a0..765e810620fe 100644 --- a/drivers/net/gianfar_ethtool.c +++ b/drivers/net/gianfar_ethtool.c | |||
@@ -125,7 +125,7 @@ static char stat_gstrings[][ETH_GSTRING_LEN] = { | |||
125 | static void gfar_gstrings(struct net_device *dev, u32 stringset, u8 * buf) | 125 | static void gfar_gstrings(struct net_device *dev, u32 stringset, u8 * buf) |
126 | { | 126 | { |
127 | struct gfar_private *priv = netdev_priv(dev); | 127 | struct gfar_private *priv = netdev_priv(dev); |
128 | 128 | ||
129 | if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON) | 129 | if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON) |
130 | memcpy(buf, stat_gstrings, GFAR_STATS_LEN * ETH_GSTRING_LEN); | 130 | memcpy(buf, stat_gstrings, GFAR_STATS_LEN * ETH_GSTRING_LEN); |
131 | else | 131 | else |
diff --git a/drivers/net/gianfar_mii.h b/drivers/net/gianfar_mii.h index e85eb216fb5b..d527cf2f9c1d 100644 --- a/drivers/net/gianfar_mii.h +++ b/drivers/net/gianfar_mii.h | |||
@@ -24,6 +24,7 @@ | |||
24 | #define MII_READ_COMMAND 0x00000001 | 24 | #define MII_READ_COMMAND 0x00000001 |
25 | 25 | ||
26 | #define GFAR_SUPPORTED (SUPPORTED_10baseT_Half \ | 26 | #define GFAR_SUPPORTED (SUPPORTED_10baseT_Half \ |
27 | | SUPPORTED_10baseT_Full \ | ||
27 | | SUPPORTED_100baseT_Half \ | 28 | | SUPPORTED_100baseT_Half \ |
28 | | SUPPORTED_100baseT_Full \ | 29 | | SUPPORTED_100baseT_Full \ |
29 | | SUPPORTED_Autoneg \ | 30 | | SUPPORTED_Autoneg \ |
diff --git a/drivers/net/gianfar_sysfs.c b/drivers/net/gianfar_sysfs.c new file mode 100644 index 000000000000..10d34cb19192 --- /dev/null +++ b/drivers/net/gianfar_sysfs.c | |||
@@ -0,0 +1,311 @@ | |||
1 | /* | ||
2 | * drivers/net/gianfar_sysfs.c | ||
3 | * | ||
4 | * Gianfar Ethernet Driver | ||
5 | * This driver is designed for the non-CPM ethernet controllers | ||
6 | * on the 85xx and 83xx family of integrated processors | ||
7 | * Based on 8260_io/fcc_enet.c | ||
8 | * | ||
9 | * Author: Andy Fleming | ||
10 | * Maintainer: Kumar Gala (kumar.gala@freescale.com) | ||
11 | * | ||
12 | * Copyright (c) 2002-2005 Freescale Semiconductor, Inc. | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify it | ||
15 | * under the terms of the GNU General Public License as published by the | ||
16 | * Free Software Foundation; either version 2 of the License, or (at your | ||
17 | * option) any later version. | ||
18 | * | ||
19 | * Sysfs file creation and management | ||
20 | */ | ||
21 | |||
22 | #include <linux/config.h> | ||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/sched.h> | ||
25 | #include <linux/string.h> | ||
26 | #include <linux/errno.h> | ||
27 | #include <linux/unistd.h> | ||
28 | #include <linux/slab.h> | ||
29 | #include <linux/init.h> | ||
30 | #include <linux/delay.h> | ||
31 | #include <linux/etherdevice.h> | ||
32 | #include <linux/spinlock.h> | ||
33 | #include <linux/mm.h> | ||
34 | #include <linux/device.h> | ||
35 | |||
36 | #include <asm/uaccess.h> | ||
37 | #include <linux/module.h> | ||
38 | #include <linux/version.h> | ||
39 | |||
40 | #include "gianfar.h" | ||
41 | |||
42 | #define GFAR_ATTR(_name) \ | ||
43 | static ssize_t gfar_show_##_name(struct class_device *cdev, char *buf); \ | ||
44 | static ssize_t gfar_set_##_name(struct class_device *cdev, \ | ||
45 | const char *buf, size_t count); \ | ||
46 | static CLASS_DEVICE_ATTR(_name, 0644, gfar_show_##_name, gfar_set_##_name) | ||
47 | |||
48 | #define GFAR_CREATE_FILE(_dev, _name) \ | ||
49 | class_device_create_file(&_dev->class_dev, &class_device_attr_##_name) | ||
50 | |||
51 | GFAR_ATTR(bd_stash); | ||
52 | GFAR_ATTR(rx_stash_size); | ||
53 | GFAR_ATTR(rx_stash_index); | ||
54 | GFAR_ATTR(fifo_threshold); | ||
55 | GFAR_ATTR(fifo_starve); | ||
56 | GFAR_ATTR(fifo_starve_off); | ||
57 | |||
58 | #define to_net_dev(cd) container_of(cd, struct net_device, class_dev) | ||
59 | |||
60 | static ssize_t gfar_show_bd_stash(struct class_device *cdev, char *buf) | ||
61 | { | ||
62 | struct net_device *dev = to_net_dev(cdev); | ||
63 | struct gfar_private *priv = netdev_priv(dev); | ||
64 | |||
65 | return sprintf(buf, "%s\n", priv->bd_stash_en? "on" : "off"); | ||
66 | } | ||
67 | |||
68 | static ssize_t gfar_set_bd_stash(struct class_device *cdev, | ||
69 | const char *buf, size_t count) | ||
70 | { | ||
71 | struct net_device *dev = to_net_dev(cdev); | ||
72 | struct gfar_private *priv = netdev_priv(dev); | ||
73 | int new_setting = 0; | ||
74 | u32 temp; | ||
75 | unsigned long flags; | ||
76 | |||
77 | /* Find out the new setting */ | ||
78 | if (!strncmp("on", buf, count-1) || !strncmp("1", buf, count-1)) | ||
79 | new_setting = 1; | ||
80 | else if (!strncmp("off", buf, count-1) || !strncmp("0", buf, count-1)) | ||
81 | new_setting = 0; | ||
82 | else | ||
83 | return count; | ||
84 | |||
85 | spin_lock_irqsave(&priv->lock, flags); | ||
86 | |||
87 | /* Set the new stashing value */ | ||
88 | priv->bd_stash_en = new_setting; | ||
89 | |||
90 | temp = gfar_read(&priv->regs->attr); | ||
91 | |||
92 | if (new_setting) | ||
93 | temp |= ATTR_BDSTASH; | ||
94 | else | ||
95 | temp &= ~(ATTR_BDSTASH); | ||
96 | |||
97 | gfar_write(&priv->regs->attr, temp); | ||
98 | |||
99 | spin_unlock_irqrestore(&priv->lock, flags); | ||
100 | |||
101 | return count; | ||
102 | } | ||
103 | |||
104 | static ssize_t gfar_show_rx_stash_size(struct class_device *cdev, char *buf) | ||
105 | { | ||
106 | struct net_device *dev = to_net_dev(cdev); | ||
107 | struct gfar_private *priv = netdev_priv(dev); | ||
108 | |||
109 | return sprintf(buf, "%d\n", priv->rx_stash_size); | ||
110 | } | ||
111 | |||
112 | static ssize_t gfar_set_rx_stash_size(struct class_device *cdev, | ||
113 | const char *buf, size_t count) | ||
114 | { | ||
115 | struct net_device *dev = to_net_dev(cdev); | ||
116 | struct gfar_private *priv = netdev_priv(dev); | ||
117 | unsigned int length = simple_strtoul(buf, NULL, 0); | ||
118 | u32 temp; | ||
119 | unsigned long flags; | ||
120 | |||
121 | spin_lock_irqsave(&priv->lock, flags); | ||
122 | if (length > priv->rx_buffer_size) | ||
123 | return count; | ||
124 | |||
125 | if (length == priv->rx_stash_size) | ||
126 | return count; | ||
127 | |||
128 | priv->rx_stash_size = length; | ||
129 | |||
130 | temp = gfar_read(&priv->regs->attreli); | ||
131 | temp &= ~ATTRELI_EL_MASK; | ||
132 | temp |= ATTRELI_EL(length); | ||
133 | gfar_write(&priv->regs->attreli, temp); | ||
134 | |||
135 | /* Turn stashing on/off as appropriate */ | ||
136 | temp = gfar_read(&priv->regs->attr); | ||
137 | |||
138 | if (length) | ||
139 | temp |= ATTR_BUFSTASH; | ||
140 | else | ||
141 | temp &= ~(ATTR_BUFSTASH); | ||
142 | |||
143 | gfar_write(&priv->regs->attr, temp); | ||
144 | |||
145 | spin_unlock_irqrestore(&priv->lock, flags); | ||
146 | |||
147 | return count; | ||
148 | } | ||
149 | |||
150 | |||
151 | /* Stashing will only be enabled when rx_stash_size != 0 */ | ||
152 | static ssize_t gfar_show_rx_stash_index(struct class_device *cdev, char *buf) | ||
153 | { | ||
154 | struct net_device *dev = to_net_dev(cdev); | ||
155 | struct gfar_private *priv = netdev_priv(dev); | ||
156 | |||
157 | return sprintf(buf, "%d\n", priv->rx_stash_index); | ||
158 | } | ||
159 | |||
160 | static ssize_t gfar_set_rx_stash_index(struct class_device *cdev, | ||
161 | const char *buf, size_t count) | ||
162 | { | ||
163 | struct net_device *dev = to_net_dev(cdev); | ||
164 | struct gfar_private *priv = netdev_priv(dev); | ||
165 | unsigned short index = simple_strtoul(buf, NULL, 0); | ||
166 | u32 temp; | ||
167 | unsigned long flags; | ||
168 | |||
169 | spin_lock_irqsave(&priv->lock, flags); | ||
170 | if (index > priv->rx_stash_size) | ||
171 | return count; | ||
172 | |||
173 | if (index == priv->rx_stash_index) | ||
174 | return count; | ||
175 | |||
176 | priv->rx_stash_index = index; | ||
177 | |||
178 | temp = gfar_read(&priv->regs->attreli); | ||
179 | temp &= ~ATTRELI_EI_MASK; | ||
180 | temp |= ATTRELI_EI(index); | ||
181 | gfar_write(&priv->regs->attreli, flags); | ||
182 | |||
183 | spin_unlock_irqrestore(&priv->lock, flags); | ||
184 | |||
185 | return count; | ||
186 | } | ||
187 | |||
188 | static ssize_t gfar_show_fifo_threshold(struct class_device *cdev, char *buf) | ||
189 | { | ||
190 | struct net_device *dev = to_net_dev(cdev); | ||
191 | struct gfar_private *priv = netdev_priv(dev); | ||
192 | |||
193 | return sprintf(buf, "%d\n", priv->fifo_threshold); | ||
194 | } | ||
195 | |||
196 | static ssize_t gfar_set_fifo_threshold(struct class_device *cdev, | ||
197 | const char *buf, size_t count) | ||
198 | { | ||
199 | struct net_device *dev = to_net_dev(cdev); | ||
200 | struct gfar_private *priv = netdev_priv(dev); | ||
201 | unsigned int length = simple_strtoul(buf, NULL, 0); | ||
202 | u32 temp; | ||
203 | unsigned long flags; | ||
204 | |||
205 | if (length > GFAR_MAX_FIFO_THRESHOLD) | ||
206 | return count; | ||
207 | |||
208 | spin_lock_irqsave(&priv->lock, flags); | ||
209 | |||
210 | priv->fifo_threshold = length; | ||
211 | |||
212 | temp = gfar_read(&priv->regs->fifo_tx_thr); | ||
213 | temp &= ~FIFO_TX_THR_MASK; | ||
214 | temp |= length; | ||
215 | gfar_write(&priv->regs->fifo_tx_thr, temp); | ||
216 | |||
217 | spin_unlock_irqrestore(&priv->lock, flags); | ||
218 | |||
219 | return count; | ||
220 | } | ||
221 | |||
222 | static ssize_t gfar_show_fifo_starve(struct class_device *cdev, char *buf) | ||
223 | { | ||
224 | struct net_device *dev = to_net_dev(cdev); | ||
225 | struct gfar_private *priv = netdev_priv(dev); | ||
226 | |||
227 | return sprintf(buf, "%d\n", priv->fifo_starve); | ||
228 | } | ||
229 | |||
230 | |||
231 | static ssize_t gfar_set_fifo_starve(struct class_device *cdev, | ||
232 | const char *buf, size_t count) | ||
233 | { | ||
234 | struct net_device *dev = to_net_dev(cdev); | ||
235 | struct gfar_private *priv = netdev_priv(dev); | ||
236 | unsigned int num = simple_strtoul(buf, NULL, 0); | ||
237 | u32 temp; | ||
238 | unsigned long flags; | ||
239 | |||
240 | if (num > GFAR_MAX_FIFO_STARVE) | ||
241 | return count; | ||
242 | |||
243 | spin_lock_irqsave(&priv->lock, flags); | ||
244 | |||
245 | priv->fifo_starve = num; | ||
246 | |||
247 | temp = gfar_read(&priv->regs->fifo_tx_starve); | ||
248 | temp &= ~FIFO_TX_STARVE_MASK; | ||
249 | temp |= num; | ||
250 | gfar_write(&priv->regs->fifo_tx_starve, temp); | ||
251 | |||
252 | spin_unlock_irqrestore(&priv->lock, flags); | ||
253 | |||
254 | return count; | ||
255 | } | ||
256 | |||
257 | static ssize_t gfar_show_fifo_starve_off(struct class_device *cdev, char *buf) | ||
258 | { | ||
259 | struct net_device *dev = to_net_dev(cdev); | ||
260 | struct gfar_private *priv = netdev_priv(dev); | ||
261 | |||
262 | return sprintf(buf, "%d\n", priv->fifo_starve_off); | ||
263 | } | ||
264 | |||
265 | static ssize_t gfar_set_fifo_starve_off(struct class_device *cdev, | ||
266 | const char *buf, size_t count) | ||
267 | { | ||
268 | struct net_device *dev = to_net_dev(cdev); | ||
269 | struct gfar_private *priv = netdev_priv(dev); | ||
270 | unsigned int num = simple_strtoul(buf, NULL, 0); | ||
271 | u32 temp; | ||
272 | unsigned long flags; | ||
273 | |||
274 | if (num > GFAR_MAX_FIFO_STARVE_OFF) | ||
275 | return count; | ||
276 | |||
277 | spin_lock_irqsave(&priv->lock, flags); | ||
278 | |||
279 | priv->fifo_starve_off = num; | ||
280 | |||
281 | temp = gfar_read(&priv->regs->fifo_tx_starve_shutoff); | ||
282 | temp &= ~FIFO_TX_STARVE_OFF_MASK; | ||
283 | temp |= num; | ||
284 | gfar_write(&priv->regs->fifo_tx_starve_shutoff, temp); | ||
285 | |||
286 | spin_unlock_irqrestore(&priv->lock, flags); | ||
287 | |||
288 | return count; | ||
289 | } | ||
290 | |||
291 | void gfar_init_sysfs(struct net_device *dev) | ||
292 | { | ||
293 | struct gfar_private *priv = netdev_priv(dev); | ||
294 | |||
295 | /* Initialize the default values */ | ||
296 | priv->rx_stash_size = DEFAULT_STASH_LENGTH; | ||
297 | priv->rx_stash_index = DEFAULT_STASH_INDEX; | ||
298 | priv->fifo_threshold = DEFAULT_FIFO_TX_THR; | ||
299 | priv->fifo_starve = DEFAULT_FIFO_TX_STARVE; | ||
300 | priv->fifo_starve_off = DEFAULT_FIFO_TX_STARVE_OFF; | ||
301 | priv->bd_stash_en = DEFAULT_BD_STASH; | ||
302 | |||
303 | /* Create our sysfs files */ | ||
304 | GFAR_CREATE_FILE(dev, bd_stash); | ||
305 | GFAR_CREATE_FILE(dev, rx_stash_size); | ||
306 | GFAR_CREATE_FILE(dev, rx_stash_index); | ||
307 | GFAR_CREATE_FILE(dev, fifo_threshold); | ||
308 | GFAR_CREATE_FILE(dev, fifo_starve); | ||
309 | GFAR_CREATE_FILE(dev, fifo_starve_off); | ||
310 | |||
311 | } | ||