greth.c revision afc4b13df143122f99a0eb10bfefb216c2806de0
1d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo/*
2d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo * Aeroflex Gaisler GRETH 10/100/1G Ethernet MAC.
3d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo *
40f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom * 2005-2010 (c) Aeroflex Gaisler AB
5d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo *
6d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo * This driver supports GRETH 10/100 and GRETH 10/100/1G Ethernet MACs
7d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo * available in the GRLIB VHDL IP core library.
8d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo *
9d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo * Full documentation of both cores can be found here:
10d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo * http://www.gaisler.com/products/grlib/grip.pdf
11d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo *
12d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo * The Gigabit version supports scatter/gather DMA, any alignment of
13d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo * buffers and checksum offloading.
14d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo *
15d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo * This program is free software; you can redistribute it and/or modify it
16d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo * under the terms of the GNU General Public License as published by the
17d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo * Free Software Foundation; either version 2 of the License, or (at your
18d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo * option) any later version.
19d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo *
20d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo * Contributors: Kristoffer Glembo
21d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo *               Daniel Hellstrom
22d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo *               Marko Isomaki
23d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo */
24d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
25b7f080cfe223b3b7424872639d153695615a9255Alexey Dobriyan#include <linux/dma-mapping.h>
26d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo#include <linux/module.h>
27d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo#include <linux/uaccess.h>
28d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo#include <linux/init.h>
29a6b7a407865aab9f849dd99a71072b7cd1175116Alexey Dobriyan#include <linux/interrupt.h>
30d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo#include <linux/netdevice.h>
31d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo#include <linux/etherdevice.h>
32d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo#include <linux/ethtool.h>
33d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo#include <linux/skbuff.h>
34d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo#include <linux/io.h>
35d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo#include <linux/crc32.h>
36d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo#include <linux/mii.h>
37d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo#include <linux/of_device.h>
38d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo#include <linux/of_platform.h>
395a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
40d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo#include <asm/cacheflush.h>
41d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo#include <asm/byteorder.h>
42d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
43d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo#ifdef CONFIG_SPARC
44d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo#include <asm/idprom.h>
45d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo#endif
46d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
47d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo#include "greth.h"
48d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
49d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo#define GRETH_DEF_MSG_ENABLE	  \
50d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	(NETIF_MSG_DRV		| \
51d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	 NETIF_MSG_PROBE	| \
52d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	 NETIF_MSG_LINK		| \
53d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	 NETIF_MSG_IFDOWN	| \
54d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	 NETIF_MSG_IFUP		| \
55d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	 NETIF_MSG_RX_ERR	| \
56d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	 NETIF_MSG_TX_ERR)
57d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
58d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic int greth_debug = -1;	/* -1 == use GRETH_DEF_MSG_ENABLE as value */
59d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembomodule_param(greth_debug, int, 0);
60d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer GlemboMODULE_PARM_DESC(greth_debug, "GRETH bitmapped debugging message enable value");
61d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
62d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo/* Accept MAC address of the form macaddr=0x08,0x00,0x20,0x30,0x40,0x50 */
63d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic int macaddr[6];
64d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembomodule_param_array(macaddr, int, NULL, 0);
65d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer GlemboMODULE_PARM_DESC(macaddr, "GRETH Ethernet MAC address");
66d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
67d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic int greth_edcl = 1;
68d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembomodule_param(greth_edcl, int, 0);
69d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer GlemboMODULE_PARM_DESC(greth_edcl, "GRETH EDCL usage indicator. Set to 1 if EDCL is used.");
70d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
71d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic int greth_open(struct net_device *dev);
7241a655ba5654e47847505c164f77f8190ca9ed27kirjanov@gmail.comstatic netdev_tx_t greth_start_xmit(struct sk_buff *skb,
7341a655ba5654e47847505c164f77f8190ca9ed27kirjanov@gmail.com	   struct net_device *dev);
7441a655ba5654e47847505c164f77f8190ca9ed27kirjanov@gmail.comstatic netdev_tx_t greth_start_xmit_gbit(struct sk_buff *skb,
7541a655ba5654e47847505c164f77f8190ca9ed27kirjanov@gmail.com	   struct net_device *dev);
76d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic int greth_rx(struct net_device *dev, int limit);
77d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic int greth_rx_gbit(struct net_device *dev, int limit);
78d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic void greth_clean_tx(struct net_device *dev);
79d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic void greth_clean_tx_gbit(struct net_device *dev);
80d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic irqreturn_t greth_interrupt(int irq, void *dev_id);
81d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic int greth_close(struct net_device *dev);
82d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic int greth_set_mac_add(struct net_device *dev, void *p);
83d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic void greth_set_multicast_list(struct net_device *dev);
84d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
85d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo#define GRETH_REGLOAD(a)	    (be32_to_cpu(__raw_readl(&(a))))
86d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo#define GRETH_REGSAVE(a, v)         (__raw_writel(cpu_to_be32(v), &(a)))
87d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo#define GRETH_REGORIN(a, v)         (GRETH_REGSAVE(a, (GRETH_REGLOAD(a) | (v))))
88d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo#define GRETH_REGANDIN(a, v)        (GRETH_REGSAVE(a, (GRETH_REGLOAD(a) & (v))))
89d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
90d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo#define NEXT_TX(N)      (((N) + 1) & GRETH_TXBD_NUM_MASK)
91d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo#define SKIP_TX(N, C)   (((N) + C) & GRETH_TXBD_NUM_MASK)
92d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo#define NEXT_RX(N)      (((N) + 1) & GRETH_RXBD_NUM_MASK)
93d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
94d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic void greth_print_rx_packet(void *addr, int len)
95d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
96d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	print_hex_dump(KERN_DEBUG, "RX: ", DUMP_PREFIX_OFFSET, 16, 1,
97d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			addr, len, true);
98d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
99d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
100d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic void greth_print_tx_packet(struct sk_buff *skb)
101d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
102d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	int i;
103d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	int length;
104d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
105d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (skb_shinfo(skb)->nr_frags == 0)
106d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		length = skb->len;
107d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	else
108d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		length = skb_headlen(skb);
109d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
110d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	print_hex_dump(KERN_DEBUG, "TX: ", DUMP_PREFIX_OFFSET, 16, 1,
111d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			skb->data, length, true);
112d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
113d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
114d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
115d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		print_hex_dump(KERN_DEBUG, "TX: ", DUMP_PREFIX_OFFSET, 16, 1,
116d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			       phys_to_virt(page_to_phys(skb_shinfo(skb)->frags[i].page)) +
117d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			       skb_shinfo(skb)->frags[i].page_offset,
118d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			       length, true);
119d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
120d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
121d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
122d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic inline void greth_enable_tx(struct greth_private *greth)
123d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
124d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	wmb();
125d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	GRETH_REGORIN(greth->regs->control, GRETH_TXEN);
126d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
127d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
128d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic inline void greth_disable_tx(struct greth_private *greth)
129d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
130d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	GRETH_REGANDIN(greth->regs->control, ~GRETH_TXEN);
131d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
132d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
133d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic inline void greth_enable_rx(struct greth_private *greth)
134d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
135d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	wmb();
136d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	GRETH_REGORIN(greth->regs->control, GRETH_RXEN);
137d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
138d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
139d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic inline void greth_disable_rx(struct greth_private *greth)
140d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
141d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	GRETH_REGANDIN(greth->regs->control, ~GRETH_RXEN);
142d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
143d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
144d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic inline void greth_enable_irqs(struct greth_private *greth)
145d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
146d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	GRETH_REGORIN(greth->regs->control, GRETH_RXI | GRETH_TXI);
147d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
148d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
149d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic inline void greth_disable_irqs(struct greth_private *greth)
150d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
151d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	GRETH_REGANDIN(greth->regs->control, ~(GRETH_RXI|GRETH_TXI));
152d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
153d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
154d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic inline void greth_write_bd(u32 *bd, u32 val)
155d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
156d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	__raw_writel(cpu_to_be32(val), bd);
157d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
158d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
159d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic inline u32 greth_read_bd(u32 *bd)
160d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
161d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return be32_to_cpu(__raw_readl(bd));
162d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
163d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
164d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic void greth_clean_rings(struct greth_private *greth)
165d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
166d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	int i;
167d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_bd *rx_bdp = greth->rx_bd_base;
168d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_bd *tx_bdp = greth->tx_bd_base;
169d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
170d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (greth->gbit_mac) {
171d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
172d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		/* Free and unmap RX buffers */
173d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		for (i = 0; i < GRETH_RXBD_NUM; i++, rx_bdp++) {
174d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			if (greth->rx_skbuff[i] != NULL) {
175d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				dev_kfree_skb(greth->rx_skbuff[i]);
176d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				dma_unmap_single(greth->dev,
177d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo						 greth_read_bd(&rx_bdp->addr),
178d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo						 MAX_FRAME_SIZE+NET_IP_ALIGN,
179d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo						 DMA_FROM_DEVICE);
180d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			}
181d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		}
182d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
183d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		/* TX buffers */
184d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		while (greth->tx_free < GRETH_TXBD_NUM) {
185d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
186d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			struct sk_buff *skb = greth->tx_skbuff[greth->tx_last];
187d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			int nr_frags = skb_shinfo(skb)->nr_frags;
188d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			tx_bdp = greth->tx_bd_base + greth->tx_last;
189d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			greth->tx_last = NEXT_TX(greth->tx_last);
190d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
191d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			dma_unmap_single(greth->dev,
192d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo					 greth_read_bd(&tx_bdp->addr),
193d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo					 skb_headlen(skb),
194d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo					 DMA_TO_DEVICE);
195d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
196d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			for (i = 0; i < nr_frags; i++) {
197d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
198d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				tx_bdp = greth->tx_bd_base + greth->tx_last;
199d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
200d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				dma_unmap_page(greth->dev,
201d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo					       greth_read_bd(&tx_bdp->addr),
202d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo					       frag->size,
203d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo					       DMA_TO_DEVICE);
204d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
205d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				greth->tx_last = NEXT_TX(greth->tx_last);
206d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			}
207d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			greth->tx_free += nr_frags+1;
208d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			dev_kfree_skb(skb);
209d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		}
210d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
211d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
212d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	} else { /* 10/100 Mbps MAC */
213d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
214d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		for (i = 0; i < GRETH_RXBD_NUM; i++, rx_bdp++) {
215d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			kfree(greth->rx_bufs[i]);
216d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			dma_unmap_single(greth->dev,
217d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo					 greth_read_bd(&rx_bdp->addr),
218d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo					 MAX_FRAME_SIZE,
219d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo					 DMA_FROM_DEVICE);
220d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		}
221d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		for (i = 0; i < GRETH_TXBD_NUM; i++, tx_bdp++) {
222d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			kfree(greth->tx_bufs[i]);
223d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			dma_unmap_single(greth->dev,
224d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo					 greth_read_bd(&tx_bdp->addr),
225d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo					 MAX_FRAME_SIZE,
226d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo					 DMA_TO_DEVICE);
227d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		}
228d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
229d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
230d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
231d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic int greth_init_rings(struct greth_private *greth)
232d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
233d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct sk_buff *skb;
234d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_bd *rx_bd, *tx_bd;
235d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	u32 dma_addr;
236d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	int i;
237d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
238d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	rx_bd = greth->rx_bd_base;
239d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	tx_bd = greth->tx_bd_base;
240d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
241d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	/* Initialize descriptor rings and buffers */
242d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (greth->gbit_mac) {
243d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
244d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		for (i = 0; i < GRETH_RXBD_NUM; i++) {
245d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			skb = netdev_alloc_skb(greth->netdev, MAX_FRAME_SIZE+NET_IP_ALIGN);
246d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			if (skb == NULL) {
247d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				if (netif_msg_ifup(greth))
248d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo					dev_err(greth->dev, "Error allocating DMA ring.\n");
249d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				goto cleanup;
250d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			}
251d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			skb_reserve(skb, NET_IP_ALIGN);
252d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			dma_addr = dma_map_single(greth->dev,
253d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo						  skb->data,
254d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo						  MAX_FRAME_SIZE+NET_IP_ALIGN,
255d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo						  DMA_FROM_DEVICE);
256d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
257d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			if (dma_mapping_error(greth->dev, dma_addr)) {
258d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				if (netif_msg_ifup(greth))
259d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo					dev_err(greth->dev, "Could not create initial DMA mapping\n");
260d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				goto cleanup;
261d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			}
262d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			greth->rx_skbuff[i] = skb;
263d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			greth_write_bd(&rx_bd[i].addr, dma_addr);
264d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			greth_write_bd(&rx_bd[i].stat, GRETH_BD_EN | GRETH_BD_IE);
265d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		}
266d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
267d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	} else {
268d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
269d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		/* 10/100 MAC uses a fixed set of buffers and copy to/from SKBs */
270d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		for (i = 0; i < GRETH_RXBD_NUM; i++) {
271d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
272d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			greth->rx_bufs[i] = kmalloc(MAX_FRAME_SIZE, GFP_KERNEL);
273d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
274d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			if (greth->rx_bufs[i] == NULL) {
275d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				if (netif_msg_ifup(greth))
276d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo					dev_err(greth->dev, "Error allocating DMA ring.\n");
277d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				goto cleanup;
278d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			}
279d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
280d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			dma_addr = dma_map_single(greth->dev,
281d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo						  greth->rx_bufs[i],
282d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo						  MAX_FRAME_SIZE,
283d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo						  DMA_FROM_DEVICE);
284d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
285d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			if (dma_mapping_error(greth->dev, dma_addr)) {
286d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				if (netif_msg_ifup(greth))
287d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo					dev_err(greth->dev, "Could not create initial DMA mapping\n");
288d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				goto cleanup;
289d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			}
290d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			greth_write_bd(&rx_bd[i].addr, dma_addr);
291d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			greth_write_bd(&rx_bd[i].stat, GRETH_BD_EN | GRETH_BD_IE);
292d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		}
293d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		for (i = 0; i < GRETH_TXBD_NUM; i++) {
294d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
295d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			greth->tx_bufs[i] = kmalloc(MAX_FRAME_SIZE, GFP_KERNEL);
296d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
297d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			if (greth->tx_bufs[i] == NULL) {
298d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				if (netif_msg_ifup(greth))
299d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo					dev_err(greth->dev, "Error allocating DMA ring.\n");
300d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				goto cleanup;
301d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			}
302d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
303d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			dma_addr = dma_map_single(greth->dev,
304d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo						  greth->tx_bufs[i],
305d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo						  MAX_FRAME_SIZE,
306d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo						  DMA_TO_DEVICE);
307d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
308d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			if (dma_mapping_error(greth->dev, dma_addr)) {
309d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				if (netif_msg_ifup(greth))
310d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo					dev_err(greth->dev, "Could not create initial DMA mapping\n");
311d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				goto cleanup;
312d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			}
313d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			greth_write_bd(&tx_bd[i].addr, dma_addr);
314d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			greth_write_bd(&tx_bd[i].stat, 0);
315d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		}
316d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
317d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth_write_bd(&rx_bd[GRETH_RXBD_NUM - 1].stat,
318d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		       greth_read_bd(&rx_bd[GRETH_RXBD_NUM - 1].stat) | GRETH_BD_WR);
319d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
320d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	/* Initialize pointers. */
321d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->rx_cur = 0;
322d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->tx_next = 0;
323d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->tx_last = 0;
324d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->tx_free = GRETH_TXBD_NUM;
325d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
326d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	/* Initialize descriptor base address */
327d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	GRETH_REGSAVE(greth->regs->tx_desc_p, greth->tx_bd_base_phys);
328d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	GRETH_REGSAVE(greth->regs->rx_desc_p, greth->rx_bd_base_phys);
329d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
330d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return 0;
331d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
332d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembocleanup:
333d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth_clean_rings(greth);
334d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return -ENOMEM;
335d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
336d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
337d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic int greth_open(struct net_device *dev)
338d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
339d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_private *greth = netdev_priv(dev);
340d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	int err;
341d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
342d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	err = greth_init_rings(greth);
343d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (err) {
344d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (netif_msg_ifup(greth))
345d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			dev_err(&dev->dev, "Could not allocate memory for DMA rings\n");
346d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		return err;
347d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
348d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
349d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	err = request_irq(greth->irq, greth_interrupt, 0, "eth", (void *) dev);
350d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (err) {
351d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (netif_msg_ifup(greth))
352d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			dev_err(&dev->dev, "Could not allocate interrupt %d\n", dev->irq);
353d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		greth_clean_rings(greth);
354d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		return err;
355d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
356d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
357d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (netif_msg_ifup(greth))
358d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		dev_dbg(&dev->dev, " starting queue\n");
359d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	netif_start_queue(dev);
360d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
361bbe9e637330abe55442aebe799425e224086959fDaniel Hellstrom	GRETH_REGSAVE(greth->regs->status, 0xFF);
362bbe9e637330abe55442aebe799425e224086959fDaniel Hellstrom
363d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	napi_enable(&greth->napi);
364d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
365d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth_enable_irqs(greth);
366d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth_enable_tx(greth);
367d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth_enable_rx(greth);
368d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return 0;
369d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
370d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
371d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
372d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic int greth_close(struct net_device *dev)
373d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
374d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_private *greth = netdev_priv(dev);
375d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
376d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	napi_disable(&greth->napi);
377d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
378bbe9e637330abe55442aebe799425e224086959fDaniel Hellstrom	greth_disable_irqs(greth);
379d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth_disable_tx(greth);
380bbe9e637330abe55442aebe799425e224086959fDaniel Hellstrom	greth_disable_rx(greth);
381d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
382d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	netif_stop_queue(dev);
383d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
384d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	free_irq(greth->irq, (void *) dev);
385d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
386d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth_clean_rings(greth);
387d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
388d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return 0;
389d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
390d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
39141a655ba5654e47847505c164f77f8190ca9ed27kirjanov@gmail.comstatic netdev_tx_t
39241a655ba5654e47847505c164f77f8190ca9ed27kirjanov@gmail.comgreth_start_xmit(struct sk_buff *skb, struct net_device *dev)
393d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
394d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_private *greth = netdev_priv(dev);
395d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_bd *bdp;
396d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	int err = NETDEV_TX_OK;
3970f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom	u32 status, dma_addr, ctrl;
3980f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom	unsigned long flags;
399d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
4000f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom	/* Clean TX Ring */
4010f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom	greth_clean_tx(greth->netdev);
402d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
403d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (unlikely(greth->tx_free <= 0)) {
4040f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		spin_lock_irqsave(&greth->devlock, flags);/*save from poll/irq*/
4050f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		ctrl = GRETH_REGLOAD(greth->regs->control);
4060f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		/* Enable TX IRQ only if not already in poll() routine */
4070f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		if (ctrl & GRETH_RXI)
4080f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom			GRETH_REGSAVE(greth->regs->control, ctrl | GRETH_TXI);
409d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		netif_stop_queue(dev);
4100f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		spin_unlock_irqrestore(&greth->devlock, flags);
411d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		return NETDEV_TX_BUSY;
412d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
413d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
414d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (netif_msg_pktdata(greth))
415d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		greth_print_tx_packet(skb);
416d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
417d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
418d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (unlikely(skb->len > MAX_FRAME_SIZE)) {
419d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		dev->stats.tx_errors++;
420d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		goto out;
421d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
422d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
4230f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom	bdp = greth->tx_bd_base + greth->tx_next;
424d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	dma_addr = greth_read_bd(&bdp->addr);
425d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
426d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	memcpy((unsigned char *) phys_to_virt(dma_addr), skb->data, skb->len);
427d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
428d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	dma_sync_single_for_device(greth->dev, dma_addr, skb->len, DMA_TO_DEVICE);
429d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
4300f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom	status = GRETH_BD_EN | GRETH_BD_IE | (skb->len & GRETH_BD_LEN);
431d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
432d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	/* Wrap around descriptor ring */
433d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (greth->tx_next == GRETH_TXBD_NUM_MASK) {
434d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		status |= GRETH_BD_WR;
435d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
436d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
437d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->tx_next = NEXT_TX(greth->tx_next);
438d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->tx_free--;
439d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
440d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	/* Write descriptor control word and enable transmission */
441d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth_write_bd(&bdp->stat, status);
4420f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom	spin_lock_irqsave(&greth->devlock, flags); /*save from poll/irq*/
443d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth_enable_tx(greth);
4440f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom	spin_unlock_irqrestore(&greth->devlock, flags);
445d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
446d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glemboout:
447d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	dev_kfree_skb(skb);
448d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return err;
449d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
450d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
451d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
45241a655ba5654e47847505c164f77f8190ca9ed27kirjanov@gmail.comstatic netdev_tx_t
45341a655ba5654e47847505c164f77f8190ca9ed27kirjanov@gmail.comgreth_start_xmit_gbit(struct sk_buff *skb, struct net_device *dev)
454d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
455d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_private *greth = netdev_priv(dev);
456d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_bd *bdp;
4570f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom	u32 status = 0, dma_addr, ctrl;
458d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	int curr_tx, nr_frags, i, err = NETDEV_TX_OK;
4590f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom	unsigned long flags;
460d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
461d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	nr_frags = skb_shinfo(skb)->nr_frags;
462d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
4630f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom	/* Clean TX Ring */
4640f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom	greth_clean_tx_gbit(dev);
4650f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom
466d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (greth->tx_free < nr_frags + 1) {
4670f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		spin_lock_irqsave(&greth->devlock, flags);/*save from poll/irq*/
4680f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		ctrl = GRETH_REGLOAD(greth->regs->control);
4690f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		/* Enable TX IRQ only if not already in poll() routine */
4700f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		if (ctrl & GRETH_RXI)
4710f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom			GRETH_REGSAVE(greth->regs->control, ctrl | GRETH_TXI);
472d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		netif_stop_queue(dev);
4730f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		spin_unlock_irqrestore(&greth->devlock, flags);
474d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		err = NETDEV_TX_BUSY;
475d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		goto out;
476d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
477d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
478d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (netif_msg_pktdata(greth))
479d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		greth_print_tx_packet(skb);
480d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
481d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (unlikely(skb->len > MAX_FRAME_SIZE)) {
482d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		dev->stats.tx_errors++;
483d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		goto out;
484d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
485d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
486d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	/* Save skb pointer. */
487d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->tx_skbuff[greth->tx_next] = skb;
488d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
489d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	/* Linear buf */
490d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (nr_frags != 0)
491d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		status = GRETH_TXBD_MORE;
492d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
493d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	status |= GRETH_TXBD_CSALL;
494d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	status |= skb_headlen(skb) & GRETH_BD_LEN;
495d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (greth->tx_next == GRETH_TXBD_NUM_MASK)
496d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		status |= GRETH_BD_WR;
497d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
498d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
499d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	bdp = greth->tx_bd_base + greth->tx_next;
500d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth_write_bd(&bdp->stat, status);
501d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	dma_addr = dma_map_single(greth->dev, skb->data, skb_headlen(skb), DMA_TO_DEVICE);
502d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
503d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (unlikely(dma_mapping_error(greth->dev, dma_addr)))
504d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		goto map_error;
505d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
506d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth_write_bd(&bdp->addr, dma_addr);
507d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
508d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	curr_tx = NEXT_TX(greth->tx_next);
509d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
510d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	/* Frags */
511d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	for (i = 0; i < nr_frags; i++) {
512d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
513d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		greth->tx_skbuff[curr_tx] = NULL;
514d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		bdp = greth->tx_bd_base + curr_tx;
515d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
5162a2bc012b98729ce9a39386faed28d11ee021683Daniel Hellstrom		status = GRETH_TXBD_CSALL | GRETH_BD_EN;
517d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		status |= frag->size & GRETH_BD_LEN;
518d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
519d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		/* Wrap around descriptor ring */
520d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (curr_tx == GRETH_TXBD_NUM_MASK)
521d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			status |= GRETH_BD_WR;
522d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
523d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		/* More fragments left */
524d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (i < nr_frags - 1)
525d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			status |= GRETH_TXBD_MORE;
5260f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		else
5270f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom			status |= GRETH_BD_IE; /* enable IRQ on last fragment */
528d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
529d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		greth_write_bd(&bdp->stat, status);
530d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
531d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		dma_addr = dma_map_page(greth->dev,
532d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo					frag->page,
533d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo					frag->page_offset,
534d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo					frag->size,
535d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo					DMA_TO_DEVICE);
536d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
537d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (unlikely(dma_mapping_error(greth->dev, dma_addr)))
538d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			goto frag_map_error;
539d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
540d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		greth_write_bd(&bdp->addr, dma_addr);
541d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
542d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		curr_tx = NEXT_TX(curr_tx);
543d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
544d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
545d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	wmb();
546d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
5472a2bc012b98729ce9a39386faed28d11ee021683Daniel Hellstrom	/* Enable the descriptor chain by enabling the first descriptor */
5482a2bc012b98729ce9a39386faed28d11ee021683Daniel Hellstrom	bdp = greth->tx_bd_base + greth->tx_next;
5492a2bc012b98729ce9a39386faed28d11ee021683Daniel Hellstrom	greth_write_bd(&bdp->stat, greth_read_bd(&bdp->stat) | GRETH_BD_EN);
5502a2bc012b98729ce9a39386faed28d11ee021683Daniel Hellstrom	greth->tx_next = curr_tx;
5512a2bc012b98729ce9a39386faed28d11ee021683Daniel Hellstrom	greth->tx_free -= nr_frags + 1;
5522a2bc012b98729ce9a39386faed28d11ee021683Daniel Hellstrom
5532a2bc012b98729ce9a39386faed28d11ee021683Daniel Hellstrom	wmb();
554d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
5550f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom	spin_lock_irqsave(&greth->devlock, flags); /*save from poll/irq*/
556d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth_enable_tx(greth);
5570f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom	spin_unlock_irqrestore(&greth->devlock, flags);
558d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
559d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return NETDEV_TX_OK;
560d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
561d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembofrag_map_error:
5622a2bc012b98729ce9a39386faed28d11ee021683Daniel Hellstrom	/* Unmap SKB mappings that succeeded and disable descriptor */
563d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	for (i = 0; greth->tx_next + i != curr_tx; i++) {
564d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		bdp = greth->tx_bd_base + greth->tx_next + i;
565d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		dma_unmap_single(greth->dev,
566d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				 greth_read_bd(&bdp->addr),
567d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				 greth_read_bd(&bdp->stat) & GRETH_BD_LEN,
568d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				 DMA_TO_DEVICE);
5692a2bc012b98729ce9a39386faed28d11ee021683Daniel Hellstrom		greth_write_bd(&bdp->stat, 0);
570d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
571d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembomap_error:
572d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (net_ratelimit())
573d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		dev_warn(greth->dev, "Could not create TX DMA mapping\n");
574d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	dev_kfree_skb(skb);
575d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glemboout:
576d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return err;
577d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
578d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
579d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic irqreturn_t greth_interrupt(int irq, void *dev_id)
580d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
581d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct net_device *dev = dev_id;
582d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_private *greth;
5830f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom	u32 status, ctrl;
584d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	irqreturn_t retval = IRQ_NONE;
585d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
586d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth = netdev_priv(dev);
587d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
588d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	spin_lock(&greth->devlock);
589d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
590d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	/* Get the interrupt events that caused us to be here. */
591d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	status = GRETH_REGLOAD(greth->regs->status);
592d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
5930f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom	/* Must see if interrupts are enabled also, INT_TX|INT_RX flags may be
5940f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom	 * set regardless of whether IRQ is enabled or not. Especially
5950f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom	 * important when shared IRQ.
5960f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom	 */
5970f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom	ctrl = GRETH_REGLOAD(greth->regs->control);
598d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
5990f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom	/* Handle rx and tx interrupts through poll */
6000f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom	if (((status & (GRETH_INT_RE | GRETH_INT_RX)) && (ctrl & GRETH_RXI)) ||
6010f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom	    ((status & (GRETH_INT_TE | GRETH_INT_TX)) && (ctrl & GRETH_TXI))) {
602d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		retval = IRQ_HANDLED;
603d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
604d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		/* Disable interrupts and schedule poll() */
605d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		greth_disable_irqs(greth);
606d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		napi_schedule(&greth->napi);
607d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
608d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
609d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	mmiowb();
610d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	spin_unlock(&greth->devlock);
611d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
612d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return retval;
613d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
614d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
615d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic void greth_clean_tx(struct net_device *dev)
616d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
617d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_private *greth;
618d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_bd *bdp;
619d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	u32 stat;
620d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
621d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth = netdev_priv(dev);
622d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
623d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	while (1) {
624d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		bdp = greth->tx_bd_base + greth->tx_last;
6250f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		GRETH_REGSAVE(greth->regs->status, GRETH_INT_TE | GRETH_INT_TX);
6260f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		mb();
627d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		stat = greth_read_bd(&bdp->stat);
628d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
629d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (unlikely(stat & GRETH_BD_EN))
630d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			break;
631d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
632d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (greth->tx_free == GRETH_TXBD_NUM)
633d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			break;
634d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
635d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		/* Check status for errors */
636d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (unlikely(stat & GRETH_TXBD_STATUS)) {
637d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			dev->stats.tx_errors++;
638d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			if (stat & GRETH_TXBD_ERR_AL)
639d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				dev->stats.tx_aborted_errors++;
640d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			if (stat & GRETH_TXBD_ERR_UE)
641d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				dev->stats.tx_fifo_errors++;
642d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		}
643d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		dev->stats.tx_packets++;
644d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		greth->tx_last = NEXT_TX(greth->tx_last);
645d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		greth->tx_free++;
646d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
647d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
648d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (greth->tx_free > 0) {
649d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		netif_wake_queue(dev);
650d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
651d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
652d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
653d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
654d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic inline void greth_update_tx_stats(struct net_device *dev, u32 stat)
655d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
656d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	/* Check status for errors */
657d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (unlikely(stat & GRETH_TXBD_STATUS)) {
658d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		dev->stats.tx_errors++;
659d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (stat & GRETH_TXBD_ERR_AL)
660d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			dev->stats.tx_aborted_errors++;
661d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (stat & GRETH_TXBD_ERR_UE)
662d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			dev->stats.tx_fifo_errors++;
663d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (stat & GRETH_TXBD_ERR_LC)
664d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			dev->stats.tx_aborted_errors++;
665d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
666d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	dev->stats.tx_packets++;
667d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
668d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
669d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic void greth_clean_tx_gbit(struct net_device *dev)
670d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
671d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_private *greth;
672d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_bd *bdp, *bdp_last_frag;
673d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct sk_buff *skb;
674d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	u32 stat;
675d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	int nr_frags, i;
676d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
677d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth = netdev_priv(dev);
678d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
679d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	while (greth->tx_free < GRETH_TXBD_NUM) {
680d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
681d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		skb = greth->tx_skbuff[greth->tx_last];
682d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
683d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		nr_frags = skb_shinfo(skb)->nr_frags;
684d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
685d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		/* We only clean fully completed SKBs */
686d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		bdp_last_frag = greth->tx_bd_base + SKIP_TX(greth->tx_last, nr_frags);
6870f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom
6880f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		GRETH_REGSAVE(greth->regs->status, GRETH_INT_TE | GRETH_INT_TX);
6890f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		mb();
6900f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		stat = greth_read_bd(&bdp_last_frag->stat);
691d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
692d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (stat & GRETH_BD_EN)
693d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			break;
694d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
695d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		greth->tx_skbuff[greth->tx_last] = NULL;
696d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
697d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		greth_update_tx_stats(dev, stat);
698d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
699d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		bdp = greth->tx_bd_base + greth->tx_last;
700d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
701d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		greth->tx_last = NEXT_TX(greth->tx_last);
702d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
703d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		dma_unmap_single(greth->dev,
704d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				 greth_read_bd(&bdp->addr),
705d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				 skb_headlen(skb),
706d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				 DMA_TO_DEVICE);
707d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
708d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		for (i = 0; i < nr_frags; i++) {
709d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
710d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			bdp = greth->tx_bd_base + greth->tx_last;
711d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
712d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			dma_unmap_page(greth->dev,
713d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				       greth_read_bd(&bdp->addr),
714d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				       frag->size,
715d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				       DMA_TO_DEVICE);
716d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
717d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			greth->tx_last = NEXT_TX(greth->tx_last);
718d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		}
719d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		greth->tx_free += nr_frags+1;
720d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		dev_kfree_skb(skb);
721d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
722d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
7230f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom	if (netif_queue_stopped(dev) && (greth->tx_free > (MAX_SKB_FRAGS+1)))
7240f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		netif_wake_queue(dev);
725d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
726d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
727d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic int greth_rx(struct net_device *dev, int limit)
728d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
729d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_private *greth;
730d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_bd *bdp;
731d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct sk_buff *skb;
732d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	int pkt_len;
733d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	int bad, count;
734d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	u32 status, dma_addr;
7350f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom	unsigned long flags;
736d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
737d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth = netdev_priv(dev);
738d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
739d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	for (count = 0; count < limit; ++count) {
740d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
741d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		bdp = greth->rx_bd_base + greth->rx_cur;
7420f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		GRETH_REGSAVE(greth->regs->status, GRETH_INT_RE | GRETH_INT_RX);
7430f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		mb();
744d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		status = greth_read_bd(&bdp->stat);
745d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
746d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (unlikely(status & GRETH_BD_EN)) {
747d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			break;
748d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		}
749d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
7500f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		dma_addr = greth_read_bd(&bdp->addr);
7510f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		bad = 0;
7520f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom
753d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		/* Check status for errors. */
754d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (unlikely(status & GRETH_RXBD_STATUS)) {
755d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			if (status & GRETH_RXBD_ERR_FT) {
756d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				dev->stats.rx_length_errors++;
757d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				bad = 1;
758d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			}
759d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			if (status & (GRETH_RXBD_ERR_AE | GRETH_RXBD_ERR_OE)) {
760d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				dev->stats.rx_frame_errors++;
761d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				bad = 1;
762d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			}
763d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			if (status & GRETH_RXBD_ERR_CRC) {
764d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				dev->stats.rx_crc_errors++;
765d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				bad = 1;
766d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			}
767d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		}
768d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (unlikely(bad)) {
769d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			dev->stats.rx_errors++;
770d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
771d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		} else {
772d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
773d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			pkt_len = status & GRETH_BD_LEN;
774d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
775d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			skb = netdev_alloc_skb(dev, pkt_len + NET_IP_ALIGN);
776d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
777d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			if (unlikely(skb == NULL)) {
778d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
779d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				if (net_ratelimit())
780d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo					dev_warn(&dev->dev, "low on memory - " "packet dropped\n");
781d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
782d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				dev->stats.rx_dropped++;
783d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
784d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			} else {
785d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				skb_reserve(skb, NET_IP_ALIGN);
786d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				skb->dev = dev;
787d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
788d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				dma_sync_single_for_cpu(greth->dev,
789d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo							dma_addr,
790d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo							pkt_len,
791d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo							DMA_FROM_DEVICE);
792d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
793d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				if (netif_msg_pktdata(greth))
794d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo					greth_print_rx_packet(phys_to_virt(dma_addr), pkt_len);
795d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
796d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				memcpy(skb_put(skb, pkt_len), phys_to_virt(dma_addr), pkt_len);
797d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
798d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				skb->protocol = eth_type_trans(skb, dev);
799d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				dev->stats.rx_packets++;
800d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				netif_receive_skb(skb);
801d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			}
802d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		}
803d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
804d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		status = GRETH_BD_EN | GRETH_BD_IE;
805d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (greth->rx_cur == GRETH_RXBD_NUM_MASK) {
806d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			status |= GRETH_BD_WR;
807d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		}
808d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
809d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		wmb();
810d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		greth_write_bd(&bdp->stat, status);
811d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
812d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		dma_sync_single_for_device(greth->dev, dma_addr, MAX_FRAME_SIZE, DMA_FROM_DEVICE);
813d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
8140f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		spin_lock_irqsave(&greth->devlock, flags); /* save from XMIT */
815d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		greth_enable_rx(greth);
8160f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		spin_unlock_irqrestore(&greth->devlock, flags);
817d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
818d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		greth->rx_cur = NEXT_RX(greth->rx_cur);
819d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
820d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
821d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return count;
822d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
823d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
824d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic inline int hw_checksummed(u32 status)
825d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
826d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
827d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (status & GRETH_RXBD_IP_FRAG)
828d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		return 0;
829d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
830d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (status & GRETH_RXBD_IP && status & GRETH_RXBD_IP_CSERR)
831d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		return 0;
832d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
833d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (status & GRETH_RXBD_UDP && status & GRETH_RXBD_UDP_CSERR)
834d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		return 0;
835d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
836d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (status & GRETH_RXBD_TCP && status & GRETH_RXBD_TCP_CSERR)
837d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		return 0;
838d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
839d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return 1;
840d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
841d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
842d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic int greth_rx_gbit(struct net_device *dev, int limit)
843d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
844d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_private *greth;
845d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_bd *bdp;
846d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct sk_buff *skb, *newskb;
847d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	int pkt_len;
848d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	int bad, count = 0;
849d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	u32 status, dma_addr;
8500f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom	unsigned long flags;
851d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
852d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth = netdev_priv(dev);
853d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
854d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	for (count = 0; count < limit; ++count) {
855d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
856d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		bdp = greth->rx_bd_base + greth->rx_cur;
857d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		skb = greth->rx_skbuff[greth->rx_cur];
8580f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		GRETH_REGSAVE(greth->regs->status, GRETH_INT_RE | GRETH_INT_RX);
8590f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		mb();
860d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		status = greth_read_bd(&bdp->stat);
861d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		bad = 0;
862d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
863d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (status & GRETH_BD_EN)
864d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			break;
865d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
866d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		/* Check status for errors. */
867d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (unlikely(status & GRETH_RXBD_STATUS)) {
868d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
869d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			if (status & GRETH_RXBD_ERR_FT) {
870d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				dev->stats.rx_length_errors++;
871d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				bad = 1;
872d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			} else if (status &
873d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				   (GRETH_RXBD_ERR_AE | GRETH_RXBD_ERR_OE | GRETH_RXBD_ERR_LE)) {
874d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				dev->stats.rx_frame_errors++;
875d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				bad = 1;
876d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			} else if (status & GRETH_RXBD_ERR_CRC) {
877d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				dev->stats.rx_crc_errors++;
878d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				bad = 1;
879d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			}
880d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		}
881d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
882b669e7f0580f3c0058f1b32c276ef6da8f05c138Daniel Hellstrom		/* Allocate new skb to replace current, not needed if the
883b669e7f0580f3c0058f1b32c276ef6da8f05c138Daniel Hellstrom		 * current skb can be reused */
884b669e7f0580f3c0058f1b32c276ef6da8f05c138Daniel Hellstrom		if (!bad && (newskb=netdev_alloc_skb(dev, MAX_FRAME_SIZE + NET_IP_ALIGN))) {
885d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			skb_reserve(newskb, NET_IP_ALIGN);
886d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
887d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			dma_addr = dma_map_single(greth->dev,
888d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo						      newskb->data,
889d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo						      MAX_FRAME_SIZE + NET_IP_ALIGN,
890d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo						      DMA_FROM_DEVICE);
891d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
892d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			if (!dma_mapping_error(greth->dev, dma_addr)) {
893d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				/* Process the incoming frame. */
894d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				pkt_len = status & GRETH_BD_LEN;
895d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
896d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				dma_unmap_single(greth->dev,
897d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo						 greth_read_bd(&bdp->addr),
898d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo						 MAX_FRAME_SIZE + NET_IP_ALIGN,
899d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo						 DMA_FROM_DEVICE);
900d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
901d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				if (netif_msg_pktdata(greth))
902d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo					greth_print_rx_packet(phys_to_virt(greth_read_bd(&bdp->addr)), pkt_len);
903d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
904d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				skb_put(skb, pkt_len);
905d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
906131ae329702755d897c6072c7839086b0702fb10Michał Mirosław				if (dev->features & NETIF_F_RXCSUM && hw_checksummed(status))
907d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo					skb->ip_summed = CHECKSUM_UNNECESSARY;
908d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				else
909bc8acf2c8c3e43fcc192762a9f964b3e9a17748bEric Dumazet					skb_checksum_none_assert(skb);
910d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
911d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				skb->protocol = eth_type_trans(skb, dev);
912d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				dev->stats.rx_packets++;
913d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				netif_receive_skb(skb);
914d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
915d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				greth->rx_skbuff[greth->rx_cur] = newskb;
916d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				greth_write_bd(&bdp->addr, dma_addr);
917d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			} else {
918d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				if (net_ratelimit())
919d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo					dev_warn(greth->dev, "Could not create DMA mapping, dropping packet\n");
920d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				dev_kfree_skb(newskb);
921b669e7f0580f3c0058f1b32c276ef6da8f05c138Daniel Hellstrom				/* reusing current skb, so it is a drop */
922d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				dev->stats.rx_dropped++;
923d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			}
924b669e7f0580f3c0058f1b32c276ef6da8f05c138Daniel Hellstrom		} else if (bad) {
925b669e7f0580f3c0058f1b32c276ef6da8f05c138Daniel Hellstrom			/* Bad Frame transfer, the skb is reused */
926b669e7f0580f3c0058f1b32c276ef6da8f05c138Daniel Hellstrom			dev->stats.rx_dropped++;
927d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		} else {
928b669e7f0580f3c0058f1b32c276ef6da8f05c138Daniel Hellstrom			/* Failed Allocating a new skb. This is rather stupid
929b669e7f0580f3c0058f1b32c276ef6da8f05c138Daniel Hellstrom			 * but the current "filled" skb is reused, as if
930b669e7f0580f3c0058f1b32c276ef6da8f05c138Daniel Hellstrom			 * transfer failure. One could argue that RX descriptor
931b669e7f0580f3c0058f1b32c276ef6da8f05c138Daniel Hellstrom			 * table handling should be divided into cleaning and
932b669e7f0580f3c0058f1b32c276ef6da8f05c138Daniel Hellstrom			 * filling as the TX part of the driver
933b669e7f0580f3c0058f1b32c276ef6da8f05c138Daniel Hellstrom			 */
934d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			if (net_ratelimit())
935d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				dev_warn(greth->dev, "Could not allocate SKB, dropping packet\n");
936b669e7f0580f3c0058f1b32c276ef6da8f05c138Daniel Hellstrom			/* reusing current skb, so it is a drop */
937d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			dev->stats.rx_dropped++;
938d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		}
939d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
940d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		status = GRETH_BD_EN | GRETH_BD_IE;
941d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (greth->rx_cur == GRETH_RXBD_NUM_MASK) {
942d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			status |= GRETH_BD_WR;
943d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		}
944d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
945d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		wmb();
946d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		greth_write_bd(&bdp->stat, status);
9470f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		spin_lock_irqsave(&greth->devlock, flags);
948d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		greth_enable_rx(greth);
9490f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		spin_unlock_irqrestore(&greth->devlock, flags);
950d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		greth->rx_cur = NEXT_RX(greth->rx_cur);
951d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
952d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
953d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return count;
954d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
955d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
956d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
957d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic int greth_poll(struct napi_struct *napi, int budget)
958d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
959d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_private *greth;
960d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	int work_done = 0;
9610f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom	unsigned long flags;
9620f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom	u32 mask, ctrl;
963d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth = container_of(napi, struct greth_private, napi);
964d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
9650f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstromrestart_txrx_poll:
9660f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom	if (netif_queue_stopped(greth->netdev)) {
9670f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		if (greth->gbit_mac)
9680f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom			greth_clean_tx_gbit(greth->netdev);
9690f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		else
9700f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom			greth_clean_tx(greth->netdev);
971d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
972d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
973d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (greth->gbit_mac) {
974d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		work_done += greth_rx_gbit(greth->netdev, budget - work_done);
975d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	} else {
976d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		work_done += greth_rx(greth->netdev, budget - work_done);
977d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
978d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
979d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (work_done < budget) {
980d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
9810f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		spin_lock_irqsave(&greth->devlock, flags);
982d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
9830f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		ctrl = GRETH_REGLOAD(greth->regs->control);
9840f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		if (netif_queue_stopped(greth->netdev)) {
9850f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom			GRETH_REGSAVE(greth->regs->control,
9860f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom					ctrl | GRETH_TXI | GRETH_RXI);
9870f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom			mask = GRETH_INT_RX | GRETH_INT_RE |
9880f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom			       GRETH_INT_TX | GRETH_INT_TE;
9890f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		} else {
9900f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom			GRETH_REGSAVE(greth->regs->control, ctrl | GRETH_RXI);
9910f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom			mask = GRETH_INT_RX | GRETH_INT_RE;
9920f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		}
9930f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom
9940f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		if (GRETH_REGLOAD(greth->regs->status) & mask) {
9950f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom			GRETH_REGSAVE(greth->regs->control, ctrl);
9960f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom			spin_unlock_irqrestore(&greth->devlock, flags);
9970f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom			goto restart_txrx_poll;
9980f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		} else {
9990f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom			__napi_complete(napi);
10000f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom			spin_unlock_irqrestore(&greth->devlock, flags);
1001d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		}
1002d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
1003d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1004d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return work_done;
1005d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
1006d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1007d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic int greth_set_mac_add(struct net_device *dev, void *p)
1008d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
1009d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct sockaddr *addr = p;
1010d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_private *greth;
1011d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_regs *regs;
1012d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
10136e03718c852a7b2ce756e37ae340f4ebfec2f6f3kirjanov@gmail.com	greth = netdev_priv(dev);
1014d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	regs = (struct greth_regs *) greth->regs;
1015d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1016d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (!is_valid_ether_addr(addr->sa_data))
1017d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		return -EINVAL;
1018d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1019d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
10209b9cfe7cf663c16c0d93349cc0094bb28ae7135aKristoffer Glembo	GRETH_REGSAVE(regs->esa_msb, dev->dev_addr[0] << 8 | dev->dev_addr[1]);
10219b9cfe7cf663c16c0d93349cc0094bb28ae7135aKristoffer Glembo	GRETH_REGSAVE(regs->esa_lsb, dev->dev_addr[2] << 24 | dev->dev_addr[3] << 16 |
10229b9cfe7cf663c16c0d93349cc0094bb28ae7135aKristoffer Glembo		      dev->dev_addr[4] << 8 | dev->dev_addr[5]);
1023d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1024d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return 0;
1025d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
1026d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1027d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic u32 greth_hash_get_index(__u8 *addr)
1028d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
1029d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return (ether_crc(6, addr)) & 0x3F;
1030d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
1031d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1032d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic void greth_set_hash_filter(struct net_device *dev)
1033d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
103422bedad3ce112d5ca1eaf043d4990fa2ed698c87Jiri Pirko	struct netdev_hw_addr *ha;
10356e03718c852a7b2ce756e37ae340f4ebfec2f6f3kirjanov@gmail.com	struct greth_private *greth = netdev_priv(dev);
1036d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_regs *regs = (struct greth_regs *) greth->regs;
1037d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	u32 mc_filter[2];
10386e03718c852a7b2ce756e37ae340f4ebfec2f6f3kirjanov@gmail.com	unsigned int bitnr;
1039d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1040d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	mc_filter[0] = mc_filter[1] = 0;
1041d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
104222bedad3ce112d5ca1eaf043d4990fa2ed698c87Jiri Pirko	netdev_for_each_mc_addr(ha, dev) {
104322bedad3ce112d5ca1eaf043d4990fa2ed698c87Jiri Pirko		bitnr = greth_hash_get_index(ha->addr);
1044d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		mc_filter[bitnr >> 5] |= 1 << (bitnr & 31);
1045d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
1046d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1047d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	GRETH_REGSAVE(regs->hash_msb, mc_filter[1]);
1048d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	GRETH_REGSAVE(regs->hash_lsb, mc_filter[0]);
1049d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
1050d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1051d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic void greth_set_multicast_list(struct net_device *dev)
1052d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
1053d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	int cfg;
1054d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_private *greth = netdev_priv(dev);
1055d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_regs *regs = (struct greth_regs *) greth->regs;
1056d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1057d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	cfg = GRETH_REGLOAD(regs->control);
1058d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (dev->flags & IFF_PROMISC)
1059d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		cfg |= GRETH_CTRL_PR;
1060d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	else
1061d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		cfg &= ~GRETH_CTRL_PR;
1062d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1063d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (greth->multicast) {
1064d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (dev->flags & IFF_ALLMULTI) {
1065d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			GRETH_REGSAVE(regs->hash_msb, -1);
1066d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			GRETH_REGSAVE(regs->hash_lsb, -1);
1067d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			cfg |= GRETH_CTRL_MCEN;
1068d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			GRETH_REGSAVE(regs->control, cfg);
1069d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			return;
1070d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		}
1071d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
10726e03718c852a7b2ce756e37ae340f4ebfec2f6f3kirjanov@gmail.com		if (netdev_mc_empty(dev)) {
1073d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			cfg &= ~GRETH_CTRL_MCEN;
1074d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			GRETH_REGSAVE(regs->control, cfg);
1075d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			return;
1076d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		}
1077d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1078d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		/* Setup multicast filter */
1079d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		greth_set_hash_filter(dev);
1080d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		cfg |= GRETH_CTRL_MCEN;
1081d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
1082d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	GRETH_REGSAVE(regs->control, cfg);
1083d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
1084d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1085d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic u32 greth_get_msglevel(struct net_device *dev)
1086d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
1087d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_private *greth = netdev_priv(dev);
1088d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return greth->msg_enable;
1089d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
1090d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1091d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic void greth_set_msglevel(struct net_device *dev, u32 value)
1092d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
1093d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_private *greth = netdev_priv(dev);
1094d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->msg_enable = value;
1095d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
1096d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic int greth_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
1097d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
1098d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_private *greth = netdev_priv(dev);
1099d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct phy_device *phy = greth->phy;
1100d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1101d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (!phy)
1102d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		return -ENODEV;
1103d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1104d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return phy_ethtool_gset(phy, cmd);
1105d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
1106d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1107d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic int greth_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
1108d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
1109d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_private *greth = netdev_priv(dev);
1110d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct phy_device *phy = greth->phy;
1111d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1112d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (!phy)
1113d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		return -ENODEV;
1114d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1115d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return phy_ethtool_sset(phy, cmd);
1116d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
1117d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1118d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic int greth_get_regs_len(struct net_device *dev)
1119d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
1120d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return sizeof(struct greth_regs);
1121d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
1122d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1123d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic void greth_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
1124d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
1125d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_private *greth = netdev_priv(dev);
1126d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1127d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	strncpy(info->driver, dev_driver_string(greth->dev), 32);
1128d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	strncpy(info->version, "revision: 1.0", 32);
1129d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	strncpy(info->bus_info, greth->dev->bus->name, 32);
1130d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	strncpy(info->fw_version, "N/A", 32);
1131d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	info->eedump_len = 0;
1132d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	info->regdump_len = sizeof(struct greth_regs);
1133d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
1134d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1135d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic void greth_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
1136d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
1137d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	int i;
1138d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_private *greth = netdev_priv(dev);
1139d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	u32 __iomem *greth_regs = (u32 __iomem *) greth->regs;
1140d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	u32 *buff = p;
1141d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1142d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	for (i = 0; i < sizeof(struct greth_regs) / sizeof(u32); i++)
1143d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		buff[i] = greth_read_bd(&greth_regs[i]);
1144d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
1145d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1146d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic const struct ethtool_ops greth_ethtool_ops = {
1147d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	.get_msglevel		= greth_get_msglevel,
1148d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	.set_msglevel		= greth_set_msglevel,
1149d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	.get_settings		= greth_get_settings,
1150d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	.set_settings		= greth_set_settings,
1151d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	.get_drvinfo		= greth_get_drvinfo,
1152d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	.get_regs_len           = greth_get_regs_len,
1153d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	.get_regs               = greth_get_regs,
1154d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	.get_link		= ethtool_op_get_link,
1155d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo};
1156d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1157d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic struct net_device_ops greth_netdev_ops = {
11580f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom	.ndo_open		= greth_open,
11590f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom	.ndo_stop		= greth_close,
11600f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom	.ndo_start_xmit		= greth_start_xmit,
11610f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom	.ndo_set_mac_address	= greth_set_mac_add,
11620f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom	.ndo_validate_addr	= eth_validate_addr,
1163d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo};
1164d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1165d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic inline int wait_for_mdio(struct greth_private *greth)
1166d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
1167d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	unsigned long timeout = jiffies + 4*HZ/100;
1168d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	while (GRETH_REGLOAD(greth->regs->mdio) & GRETH_MII_BUSY) {
1169d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (time_after(jiffies, timeout))
1170d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			return 0;
1171d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
1172d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return 1;
1173d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
1174d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1175d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic int greth_mdio_read(struct mii_bus *bus, int phy, int reg)
1176d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
1177d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_private *greth = bus->priv;
1178d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	int data;
1179d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1180d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (!wait_for_mdio(greth))
1181d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		return -EBUSY;
1182d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1183d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	GRETH_REGSAVE(greth->regs->mdio, ((phy & 0x1F) << 11) | ((reg & 0x1F) << 6) | 2);
1184d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1185d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (!wait_for_mdio(greth))
1186d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		return -EBUSY;
1187d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1188d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (!(GRETH_REGLOAD(greth->regs->mdio) & GRETH_MII_NVALID)) {
1189d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		data = (GRETH_REGLOAD(greth->regs->mdio) >> 16) & 0xFFFF;
1190d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		return data;
1191d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1192d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	} else {
1193d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		return -1;
1194d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
1195d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
1196d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1197d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic int greth_mdio_write(struct mii_bus *bus, int phy, int reg, u16 val)
1198d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
1199d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_private *greth = bus->priv;
1200d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1201d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (!wait_for_mdio(greth))
1202d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		return -EBUSY;
1203d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1204d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	GRETH_REGSAVE(greth->regs->mdio,
1205d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		      ((val & 0xFFFF) << 16) | ((phy & 0x1F) << 11) | ((reg & 0x1F) << 6) | 1);
1206d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1207d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (!wait_for_mdio(greth))
1208d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		return -EBUSY;
1209d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1210d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return 0;
1211d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
1212d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1213d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic int greth_mdio_reset(struct mii_bus *bus)
1214d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
1215d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return 0;
1216d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
1217d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1218d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic void greth_link_change(struct net_device *dev)
1219d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
1220d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_private *greth = netdev_priv(dev);
1221d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct phy_device *phydev = greth->phy;
1222d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	unsigned long flags;
1223d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	int status_change = 0;
12242436af8ca7a6c4679cf7da7e3867f1d5cd8528b7Daniel Hellstrom	u32 ctrl;
1225d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1226d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	spin_lock_irqsave(&greth->devlock, flags);
1227d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1228d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (phydev->link) {
1229d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1230d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if ((greth->speed != phydev->speed) || (greth->duplex != phydev->duplex)) {
12312436af8ca7a6c4679cf7da7e3867f1d5cd8528b7Daniel Hellstrom			ctrl = GRETH_REGLOAD(greth->regs->control) &
12322436af8ca7a6c4679cf7da7e3867f1d5cd8528b7Daniel Hellstrom			       ~(GRETH_CTRL_FD | GRETH_CTRL_SP | GRETH_CTRL_GB);
1233d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1234d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			if (phydev->duplex)
12352436af8ca7a6c4679cf7da7e3867f1d5cd8528b7Daniel Hellstrom				ctrl |= GRETH_CTRL_FD;
1236d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
12372436af8ca7a6c4679cf7da7e3867f1d5cd8528b7Daniel Hellstrom			if (phydev->speed == SPEED_100)
12382436af8ca7a6c4679cf7da7e3867f1d5cd8528b7Daniel Hellstrom				ctrl |= GRETH_CTRL_SP;
1239d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			else if (phydev->speed == SPEED_1000)
12402436af8ca7a6c4679cf7da7e3867f1d5cd8528b7Daniel Hellstrom				ctrl |= GRETH_CTRL_GB;
1241d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
12422436af8ca7a6c4679cf7da7e3867f1d5cd8528b7Daniel Hellstrom			GRETH_REGSAVE(greth->regs->control, ctrl);
1243d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			greth->speed = phydev->speed;
1244d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			greth->duplex = phydev->duplex;
1245d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			status_change = 1;
1246d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		}
1247d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
1248d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1249d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (phydev->link != greth->link) {
1250d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (!phydev->link) {
1251d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			greth->speed = 0;
1252d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			greth->duplex = -1;
1253d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		}
1254d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		greth->link = phydev->link;
1255d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1256d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		status_change = 1;
1257d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
1258d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1259d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	spin_unlock_irqrestore(&greth->devlock, flags);
1260d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1261d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (status_change) {
1262d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (phydev->link)
1263d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			pr_debug("%s: link up (%d/%s)\n",
1264d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				dev->name, phydev->speed,
1265d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				DUPLEX_FULL == phydev->duplex ? "Full" : "Half");
1266d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		else
1267d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			pr_debug("%s: link down\n", dev->name);
1268d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
1269d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
1270d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1271d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic int greth_mdio_probe(struct net_device *dev)
1272d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
1273d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_private *greth = netdev_priv(dev);
1274d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct phy_device *phy = NULL;
12756e03718c852a7b2ce756e37ae340f4ebfec2f6f3kirjanov@gmail.com	int ret;
1276d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1277d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	/* Find the first PHY */
12786e03718c852a7b2ce756e37ae340f4ebfec2f6f3kirjanov@gmail.com	phy = phy_find_first(greth->mdio);
12796e03718c852a7b2ce756e37ae340f4ebfec2f6f3kirjanov@gmail.com
1280d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (!phy) {
1281d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (netif_msg_probe(greth))
1282d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			dev_err(&dev->dev, "no PHY found\n");
1283d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		return -ENXIO;
1284d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
1285d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
12866e03718c852a7b2ce756e37ae340f4ebfec2f6f3kirjanov@gmail.com	ret = phy_connect_direct(dev, phy, &greth_link_change,
12876e03718c852a7b2ce756e37ae340f4ebfec2f6f3kirjanov@gmail.com			0, greth->gbit_mac ?
12886e03718c852a7b2ce756e37ae340f4ebfec2f6f3kirjanov@gmail.com			PHY_INTERFACE_MODE_GMII :
12896e03718c852a7b2ce756e37ae340f4ebfec2f6f3kirjanov@gmail.com			PHY_INTERFACE_MODE_MII);
12906e03718c852a7b2ce756e37ae340f4ebfec2f6f3kirjanov@gmail.com	if (ret) {
12916e03718c852a7b2ce756e37ae340f4ebfec2f6f3kirjanov@gmail.com		if (netif_msg_ifup(greth))
12926e03718c852a7b2ce756e37ae340f4ebfec2f6f3kirjanov@gmail.com			dev_err(&dev->dev, "could not attach to PHY\n");
12936e03718c852a7b2ce756e37ae340f4ebfec2f6f3kirjanov@gmail.com		return ret;
12946e03718c852a7b2ce756e37ae340f4ebfec2f6f3kirjanov@gmail.com	}
1295d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1296d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (greth->gbit_mac)
1297d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		phy->supported &= PHY_GBIT_FEATURES;
1298d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	else
1299d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		phy->supported &= PHY_BASIC_FEATURES;
1300d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1301d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	phy->advertising = phy->supported;
1302d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1303d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->link = 0;
1304d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->speed = 0;
1305d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->duplex = -1;
1306d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->phy = phy;
1307d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1308d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return 0;
1309d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
1310d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1311d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic inline int phy_aneg_done(struct phy_device *phydev)
1312d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
1313d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	int retval;
1314d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1315d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	retval = phy_read(phydev, MII_BMSR);
1316d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1317d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return (retval < 0) ? retval : (retval & BMSR_ANEGCOMPLETE);
1318d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
1319d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1320d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic int greth_mdio_init(struct greth_private *greth)
1321d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
1322d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	int ret, phy;
1323d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	unsigned long timeout;
1324d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1325d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->mdio = mdiobus_alloc();
1326d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (!greth->mdio) {
1327d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		return -ENOMEM;
1328d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
1329d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1330d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->mdio->name = "greth-mdio";
1331d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	snprintf(greth->mdio->id, MII_BUS_ID_SIZE, "%s-%d", greth->mdio->name, greth->irq);
1332d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->mdio->read = greth_mdio_read;
1333d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->mdio->write = greth_mdio_write;
1334d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->mdio->reset = greth_mdio_reset;
1335d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->mdio->priv = greth;
1336d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1337d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->mdio->irq = greth->mdio_irqs;
1338d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1339d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	for (phy = 0; phy < PHY_MAX_ADDR; phy++)
1340d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		greth->mdio->irq[phy] = PHY_POLL;
1341d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1342d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	ret = mdiobus_register(greth->mdio);
1343d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (ret) {
1344d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		goto error;
1345d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
1346d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1347d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	ret = greth_mdio_probe(greth->netdev);
1348d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (ret) {
1349d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (netif_msg_probe(greth))
1350d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			dev_err(&greth->netdev->dev, "failed to probe MDIO bus\n");
1351d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		goto unreg_mdio;
1352d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
1353d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1354d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	phy_start(greth->phy);
1355d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1356d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	/* If Ethernet debug link is used make autoneg happen right away */
1357d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (greth->edcl && greth_edcl == 1) {
1358d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		phy_start_aneg(greth->phy);
1359d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		timeout = jiffies + 6*HZ;
1360d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		while (!phy_aneg_done(greth->phy) && time_before(jiffies, timeout)) {
1361d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		}
1362d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		genphy_read_status(greth->phy);
1363d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		greth_link_change(greth->netdev);
1364d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
1365d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1366d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return 0;
1367d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1368d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembounreg_mdio:
1369d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	mdiobus_unregister(greth->mdio);
1370d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glemboerror:
1371d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	mdiobus_free(greth->mdio);
1372d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return ret;
1373d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
1374d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1375d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo/* Initialize the GRETH MAC */
137674888760d40b3ac9054f9c5fa07b566c0676ba2dGrant Likelystatic int __devinit greth_of_probe(struct platform_device *ofdev)
1377d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
1378d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct net_device *dev;
1379d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_private *greth;
1380d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_regs *regs;
1381d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1382d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	int i;
1383d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	int err;
1384d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	int tmp;
1385d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	unsigned long timeout;
1386d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1387d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	dev = alloc_etherdev(sizeof(struct greth_private));
1388d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1389d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (dev == NULL)
1390d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		return -ENOMEM;
1391d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1392d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth = netdev_priv(dev);
1393d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->netdev = dev;
1394d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->dev = &ofdev->dev;
1395d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1396d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (greth_debug > 0)
1397d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		greth->msg_enable = greth_debug;
1398d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	else
1399d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		greth->msg_enable = GRETH_DEF_MSG_ENABLE;
1400d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1401d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	spin_lock_init(&greth->devlock);
1402d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1403d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->regs = of_ioremap(&ofdev->resource[0], 0,
1404d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				 resource_size(&ofdev->resource[0]),
1405d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				 "grlib-greth regs");
1406d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1407d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (greth->regs == NULL) {
1408d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (netif_msg_probe(greth))
1409d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			dev_err(greth->dev, "ioremap failure.\n");
1410d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		err = -EIO;
1411d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		goto error1;
1412d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
1413d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1414d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	regs = (struct greth_regs *) greth->regs;
141519e4875fb21a69fbf620e84769a74d189c69c58dGrant Likely	greth->irq = ofdev->archdata.irqs[0];
1416d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1417d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	dev_set_drvdata(greth->dev, dev);
1418d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	SET_NETDEV_DEV(dev, greth->dev);
1419d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1420d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (netif_msg_probe(greth))
1421d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		dev_dbg(greth->dev, "reseting controller.\n");
1422d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1423d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	/* Reset the controller. */
1424d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	GRETH_REGSAVE(regs->control, GRETH_RESET);
1425d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1426d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	/* Wait for MAC to reset itself */
1427d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	timeout = jiffies + HZ/100;
1428d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	while (GRETH_REGLOAD(regs->control) & GRETH_RESET) {
1429d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (time_after(jiffies, timeout)) {
1430d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			err = -EIO;
1431d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			if (netif_msg_probe(greth))
1432d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				dev_err(greth->dev, "timeout when waiting for reset.\n");
1433d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			goto error2;
1434d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		}
1435d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
1436d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1437d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	/* Get default PHY address  */
1438d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->phyaddr = (GRETH_REGLOAD(regs->mdio) >> 11) & 0x1F;
1439d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1440d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	/* Check if we have GBIT capable MAC */
1441d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	tmp = GRETH_REGLOAD(regs->control);
1442d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->gbit_mac = (tmp >> 27) & 1;
1443d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1444d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	/* Check for multicast capability */
1445d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->multicast = (tmp >> 25) & 1;
1446d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1447d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->edcl = (tmp >> 31) & 1;
1448d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1449d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	/* If we have EDCL we disable the EDCL speed-duplex FSM so
1450d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	 * it doesn't interfere with the software */
1451d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (greth->edcl != 0)
1452d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		GRETH_REGORIN(regs->control, GRETH_CTRL_DISDUPLEX);
1453d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1454d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	/* Check if MAC can handle MDIO interrupts */
1455d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->mdio_int_en = (tmp >> 26) & 1;
1456d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1457d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	err = greth_mdio_init(greth);
1458d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (err) {
1459d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (netif_msg_probe(greth))
1460d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			dev_err(greth->dev, "failed to register MDIO bus\n");
1461d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		goto error2;
1462d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
1463d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1464d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	/* Allocate TX descriptor ring in coherent memory */
1465d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->tx_bd_base = (struct greth_bd *) dma_alloc_coherent(greth->dev,
1466d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo								   1024,
1467d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo								   &greth->tx_bd_base_phys,
1468d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo								   GFP_KERNEL);
1469d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1470d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (!greth->tx_bd_base) {
1471d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (netif_msg_probe(greth))
1472d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			dev_err(&dev->dev, "could not allocate descriptor memory.\n");
1473d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		err = -ENOMEM;
1474d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		goto error3;
1475d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
1476d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1477d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	memset(greth->tx_bd_base, 0, 1024);
1478d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1479d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	/* Allocate RX descriptor ring in coherent memory */
1480d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->rx_bd_base = (struct greth_bd *) dma_alloc_coherent(greth->dev,
1481d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo								   1024,
1482d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo								   &greth->rx_bd_base_phys,
1483d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo								   GFP_KERNEL);
1484d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1485d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (!greth->rx_bd_base) {
1486d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (netif_msg_probe(greth))
1487d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			dev_err(greth->dev, "could not allocate descriptor memory.\n");
1488d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		err = -ENOMEM;
1489d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		goto error4;
1490d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
1491d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1492d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	memset(greth->rx_bd_base, 0, 1024);
1493d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1494d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	/* Get MAC address from: module param, OF property or ID prom */
1495d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	for (i = 0; i < 6; i++) {
1496d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (macaddr[i] != 0)
1497d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			break;
1498d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
1499d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (i == 6) {
1500d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		const unsigned char *addr;
1501d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		int len;
150261c7a080a5a061c976988fd4b844dfb468dda255Grant Likely		addr = of_get_property(ofdev->dev.of_node, "local-mac-address",
150361c7a080a5a061c976988fd4b844dfb468dda255Grant Likely					&len);
1504d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (addr != NULL && len == 6) {
1505d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			for (i = 0; i < 6; i++)
1506d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				macaddr[i] = (unsigned int) addr[i];
1507d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		} else {
1508d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo#ifdef CONFIG_SPARC
1509d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			for (i = 0; i < 6; i++)
1510d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				macaddr[i] = (unsigned int) idprom->id_ethaddr[i];
1511d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo#endif
1512d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		}
1513d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
1514d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1515d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	for (i = 0; i < 6; i++)
1516d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		dev->dev_addr[i] = macaddr[i];
1517d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1518d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	macaddr[5]++;
1519d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1520d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (!is_valid_ether_addr(&dev->dev_addr[0])) {
1521d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (netif_msg_probe(greth))
1522d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			dev_err(greth->dev, "no valid ethernet address, aborting.\n");
1523d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		err = -EINVAL;
1524d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		goto error5;
1525d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
1526d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1527d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	GRETH_REGSAVE(regs->esa_msb, dev->dev_addr[0] << 8 | dev->dev_addr[1]);
1528d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	GRETH_REGSAVE(regs->esa_lsb, dev->dev_addr[2] << 24 | dev->dev_addr[3] << 16 |
1529d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		      dev->dev_addr[4] << 8 | dev->dev_addr[5]);
1530d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1531d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	/* Clear all pending interrupts except PHY irq */
1532d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	GRETH_REGSAVE(regs->status, 0xFF);
1533d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1534d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (greth->gbit_mac) {
1535131ae329702755d897c6072c7839086b0702fb10Michał Mirosław		dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM |
1536131ae329702755d897c6072c7839086b0702fb10Michał Mirosław			NETIF_F_RXCSUM;
1537131ae329702755d897c6072c7839086b0702fb10Michał Mirosław		dev->features = dev->hw_features | NETIF_F_HIGHDMA;
1538d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		greth_netdev_ops.ndo_start_xmit = greth_start_xmit_gbit;
1539d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
1540d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1541d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (greth->multicast) {
1542afc4b13df143122f99a0eb10bfefb216c2806de0Jiri Pirko		greth_netdev_ops.ndo_set_rx_mode = greth_set_multicast_list;
1543d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		dev->flags |= IFF_MULTICAST;
1544d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	} else {
1545d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		dev->flags &= ~IFF_MULTICAST;
1546d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
1547d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1548d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	dev->netdev_ops = &greth_netdev_ops;
1549d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	dev->ethtool_ops = &greth_ethtool_ops;
1550d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1551cb5d991a99104565f7b622b1b97587f4b1effa82Tobias Klauser	err = register_netdev(dev);
1552cb5d991a99104565f7b622b1b97587f4b1effa82Tobias Klauser	if (err) {
1553d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (netif_msg_probe(greth))
1554d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			dev_err(greth->dev, "netdevice registration failed.\n");
1555d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		goto error5;
1556d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
1557d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1558d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	/* setup NAPI */
1559d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	netif_napi_add(dev, &greth->napi, greth_poll, 64);
1560d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1561d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return 0;
1562d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1563d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glemboerror5:
1564d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	dma_free_coherent(greth->dev, 1024, greth->rx_bd_base, greth->rx_bd_base_phys);
1565d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glemboerror4:
1566d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	dma_free_coherent(greth->dev, 1024, greth->tx_bd_base, greth->tx_bd_base_phys);
1567d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glemboerror3:
1568d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	mdiobus_unregister(greth->mdio);
1569d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glemboerror2:
1570d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	of_iounmap(&ofdev->resource[0], greth->regs, resource_size(&ofdev->resource[0]));
1571d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glemboerror1:
1572d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	free_netdev(dev);
1573d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return err;
1574d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
1575d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
15762dc11581376829303b98eadb2de253bee065a56aGrant Likelystatic int __devexit greth_of_remove(struct platform_device *of_dev)
1577d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
1578d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct net_device *ndev = dev_get_drvdata(&of_dev->dev);
1579d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_private *greth = netdev_priv(ndev);
1580d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1581d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	/* Free descriptor areas */
1582d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	dma_free_coherent(&of_dev->dev, 1024, greth->rx_bd_base, greth->rx_bd_base_phys);
1583d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1584d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	dma_free_coherent(&of_dev->dev, 1024, greth->tx_bd_base, greth->tx_bd_base_phys);
1585d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1586d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	dev_set_drvdata(&of_dev->dev, NULL);
1587d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1588d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (greth->phy)
1589d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		phy_stop(greth->phy);
1590d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	mdiobus_unregister(greth->mdio);
1591d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1592d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	unregister_netdev(ndev);
1593d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	free_netdev(ndev);
1594d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1595d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	of_iounmap(&of_dev->resource[0], greth->regs, resource_size(&of_dev->resource[0]));
1596d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1597d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return 0;
1598d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
1599d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1600d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic struct of_device_id greth_of_match[] = {
1601d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	{
1602d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	 .name = "GAISLER_ETHMAC",
1603d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	 },
1604ad4650a89ac47bd153cbb76c3fd6eb1fa6f315b7Daniel Hellstrom	{
1605ad4650a89ac47bd153cbb76c3fd6eb1fa6f315b7Daniel Hellstrom	 .name = "01_01d",
1606ad4650a89ac47bd153cbb76c3fd6eb1fa6f315b7Daniel Hellstrom	 },
1607d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	{},
1608d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo};
1609d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1610d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer GlemboMODULE_DEVICE_TABLE(of, greth_of_match);
1611d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
161274888760d40b3ac9054f9c5fa07b566c0676ba2dGrant Likelystatic struct platform_driver greth_of_driver = {
1613bc284f94f84c3d76e49c6f3df9028c503f9589d9David S. Miller	.driver = {
1614bc284f94f84c3d76e49c6f3df9028c503f9589d9David S. Miller		.name = "grlib-greth",
1615bc284f94f84c3d76e49c6f3df9028c503f9589d9David S. Miller		.owner = THIS_MODULE,
1616bc284f94f84c3d76e49c6f3df9028c503f9589d9David S. Miller		.of_match_table = greth_of_match,
1617bc284f94f84c3d76e49c6f3df9028c503f9589d9David S. Miller	},
1618d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	.probe = greth_of_probe,
1619d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	.remove = __devexit_p(greth_of_remove),
1620d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo};
1621d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1622d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic int __init greth_init(void)
1623d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
162474888760d40b3ac9054f9c5fa07b566c0676ba2dGrant Likely	return platform_driver_register(&greth_of_driver);
1625d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
1626d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1627d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic void __exit greth_cleanup(void)
1628d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
162974888760d40b3ac9054f9c5fa07b566c0676ba2dGrant Likely	platform_driver_unregister(&greth_of_driver);
1630d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
1631d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1632d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembomodule_init(greth_init);
1633d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembomodule_exit(greth_cleanup);
1634d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1635d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer GlemboMODULE_AUTHOR("Aeroflex Gaisler AB.");
1636d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer GlemboMODULE_DESCRIPTION("Aeroflex Gaisler Ethernet MAC driver");
1637d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer GlemboMODULE_LICENSE("GPL");
1638