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,
116ab7e11d9d0293ef1802d6ae8aab39ce58472b167Ian Campbell			       skb_frag_address(&skb_shinfo(skb)->frags[i]),
117ab7e11d9d0293ef1802d6ae8aab39ce58472b167Ian Campbell			       skb_shinfo(skb)->frags[i].size, true);
118d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
119d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
120d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
121d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic inline void greth_enable_tx(struct greth_private *greth)
122d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
123d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	wmb();
124d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	GRETH_REGORIN(greth->regs->control, GRETH_TXEN);
125d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
126d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
127d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic inline void greth_disable_tx(struct greth_private *greth)
128d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
129d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	GRETH_REGANDIN(greth->regs->control, ~GRETH_TXEN);
130d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
131d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
132d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic inline void greth_enable_rx(struct greth_private *greth)
133d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
134d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	wmb();
135d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	GRETH_REGORIN(greth->regs->control, GRETH_RXEN);
136d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
137d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
138d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic inline void greth_disable_rx(struct greth_private *greth)
139d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
140d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	GRETH_REGANDIN(greth->regs->control, ~GRETH_RXEN);
141d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
142d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
143d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic inline void greth_enable_irqs(struct greth_private *greth)
144d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
145d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	GRETH_REGORIN(greth->regs->control, GRETH_RXI | GRETH_TXI);
146d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
147d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
148d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic inline void greth_disable_irqs(struct greth_private *greth)
149d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
150d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	GRETH_REGANDIN(greth->regs->control, ~(GRETH_RXI|GRETH_TXI));
151d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
152d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
153d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic inline void greth_write_bd(u32 *bd, u32 val)
154d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
155d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	__raw_writel(cpu_to_be32(val), bd);
156d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
157d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
158d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic inline u32 greth_read_bd(u32 *bd)
159d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
160d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return be32_to_cpu(__raw_readl(bd));
161d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
162d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
163d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic void greth_clean_rings(struct greth_private *greth)
164d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
165d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	int i;
166d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_bd *rx_bdp = greth->rx_bd_base;
167d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_bd *tx_bdp = greth->tx_bd_base;
168d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
169d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (greth->gbit_mac) {
170d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
171d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		/* Free and unmap RX buffers */
172d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		for (i = 0; i < GRETH_RXBD_NUM; i++, rx_bdp++) {
173d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			if (greth->rx_skbuff[i] != NULL) {
174d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				dev_kfree_skb(greth->rx_skbuff[i]);
175d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				dma_unmap_single(greth->dev,
176d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo						 greth_read_bd(&rx_bdp->addr),
177d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo						 MAX_FRAME_SIZE+NET_IP_ALIGN,
178d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo						 DMA_FROM_DEVICE);
179d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			}
180d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		}
181d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
182d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		/* TX buffers */
183d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		while (greth->tx_free < GRETH_TXBD_NUM) {
184d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
185d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			struct sk_buff *skb = greth->tx_skbuff[greth->tx_last];
186d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			int nr_frags = skb_shinfo(skb)->nr_frags;
187d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			tx_bdp = greth->tx_bd_base + greth->tx_last;
188d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			greth->tx_last = NEXT_TX(greth->tx_last);
189d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
190d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			dma_unmap_single(greth->dev,
191d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo					 greth_read_bd(&tx_bdp->addr),
192d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo					 skb_headlen(skb),
193d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo					 DMA_TO_DEVICE);
194d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
195d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			for (i = 0; i < nr_frags; i++) {
196d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
197d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				tx_bdp = greth->tx_bd_base + greth->tx_last;
198d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
199d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				dma_unmap_page(greth->dev,
200d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo					       greth_read_bd(&tx_bdp->addr),
2019e903e085262ffbf1fc44a17ac06058aca03524aEric Dumazet					       skb_frag_size(frag),
202d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo					       DMA_TO_DEVICE);
203d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
204d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				greth->tx_last = NEXT_TX(greth->tx_last);
205d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			}
206d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			greth->tx_free += nr_frags+1;
207d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			dev_kfree_skb(skb);
208d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		}
209d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
210d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
211d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	} else { /* 10/100 Mbps MAC */
212d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
213d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		for (i = 0; i < GRETH_RXBD_NUM; i++, rx_bdp++) {
214d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			kfree(greth->rx_bufs[i]);
215d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			dma_unmap_single(greth->dev,
216d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo					 greth_read_bd(&rx_bdp->addr),
217d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo					 MAX_FRAME_SIZE,
218d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo					 DMA_FROM_DEVICE);
219d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		}
220d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		for (i = 0; i < GRETH_TXBD_NUM; i++, tx_bdp++) {
221d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			kfree(greth->tx_bufs[i]);
222d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			dma_unmap_single(greth->dev,
223d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo					 greth_read_bd(&tx_bdp->addr),
224d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo					 MAX_FRAME_SIZE,
225d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo					 DMA_TO_DEVICE);
226d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		}
227d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
228d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
229d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
230d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic int greth_init_rings(struct greth_private *greth)
231d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
232d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct sk_buff *skb;
233d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_bd *rx_bd, *tx_bd;
234d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	u32 dma_addr;
235d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	int i;
236d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
237d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	rx_bd = greth->rx_bd_base;
238d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	tx_bd = greth->tx_bd_base;
239d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
240d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	/* Initialize descriptor rings and buffers */
241d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (greth->gbit_mac) {
242d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
243d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		for (i = 0; i < GRETH_RXBD_NUM; i++) {
244d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			skb = netdev_alloc_skb(greth->netdev, MAX_FRAME_SIZE+NET_IP_ALIGN);
245d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			if (skb == NULL) {
246d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				if (netif_msg_ifup(greth))
247d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo					dev_err(greth->dev, "Error allocating DMA ring.\n");
248d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				goto cleanup;
249d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			}
250d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			skb_reserve(skb, NET_IP_ALIGN);
251d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			dma_addr = dma_map_single(greth->dev,
252d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo						  skb->data,
253d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo						  MAX_FRAME_SIZE+NET_IP_ALIGN,
254d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo						  DMA_FROM_DEVICE);
255d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
256d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			if (dma_mapping_error(greth->dev, dma_addr)) {
257d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				if (netif_msg_ifup(greth))
258d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo					dev_err(greth->dev, "Could not create initial DMA mapping\n");
259d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				goto cleanup;
260d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			}
261d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			greth->rx_skbuff[i] = skb;
262d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			greth_write_bd(&rx_bd[i].addr, dma_addr);
263d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			greth_write_bd(&rx_bd[i].stat, GRETH_BD_EN | GRETH_BD_IE);
264d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		}
265d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
266d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	} else {
267d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
268d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		/* 10/100 MAC uses a fixed set of buffers and copy to/from SKBs */
269d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		for (i = 0; i < GRETH_RXBD_NUM; i++) {
270d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
271d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			greth->rx_bufs[i] = kmalloc(MAX_FRAME_SIZE, GFP_KERNEL);
272d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
273d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			if (greth->rx_bufs[i] == NULL) {
274d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				if (netif_msg_ifup(greth))
275d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo					dev_err(greth->dev, "Error allocating DMA ring.\n");
276d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				goto cleanup;
277d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			}
278d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
279d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			dma_addr = dma_map_single(greth->dev,
280d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo						  greth->rx_bufs[i],
281d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo						  MAX_FRAME_SIZE,
282d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo						  DMA_FROM_DEVICE);
283d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
284d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			if (dma_mapping_error(greth->dev, dma_addr)) {
285d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				if (netif_msg_ifup(greth))
286d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo					dev_err(greth->dev, "Could not create initial DMA mapping\n");
287d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				goto cleanup;
288d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			}
289d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			greth_write_bd(&rx_bd[i].addr, dma_addr);
290d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			greth_write_bd(&rx_bd[i].stat, GRETH_BD_EN | GRETH_BD_IE);
291d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		}
292d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		for (i = 0; i < GRETH_TXBD_NUM; i++) {
293d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
294d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			greth->tx_bufs[i] = kmalloc(MAX_FRAME_SIZE, GFP_KERNEL);
295d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
296d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			if (greth->tx_bufs[i] == NULL) {
297d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				if (netif_msg_ifup(greth))
298d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo					dev_err(greth->dev, "Error allocating DMA ring.\n");
299d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				goto cleanup;
300d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			}
301d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
302d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			dma_addr = dma_map_single(greth->dev,
303d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo						  greth->tx_bufs[i],
304d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo						  MAX_FRAME_SIZE,
305d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo						  DMA_TO_DEVICE);
306d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
307d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			if (dma_mapping_error(greth->dev, dma_addr)) {
308d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				if (netif_msg_ifup(greth))
309d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo					dev_err(greth->dev, "Could not create initial DMA mapping\n");
310d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				goto cleanup;
311d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			}
312d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			greth_write_bd(&tx_bd[i].addr, dma_addr);
313d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			greth_write_bd(&tx_bd[i].stat, 0);
314d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		}
315d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
316d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth_write_bd(&rx_bd[GRETH_RXBD_NUM - 1].stat,
317d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		       greth_read_bd(&rx_bd[GRETH_RXBD_NUM - 1].stat) | GRETH_BD_WR);
318d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
319d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	/* Initialize pointers. */
320d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->rx_cur = 0;
321d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->tx_next = 0;
322d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->tx_last = 0;
323d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->tx_free = GRETH_TXBD_NUM;
324d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
325d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	/* Initialize descriptor base address */
326d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	GRETH_REGSAVE(greth->regs->tx_desc_p, greth->tx_bd_base_phys);
327d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	GRETH_REGSAVE(greth->regs->rx_desc_p, greth->rx_bd_base_phys);
328d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
329d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return 0;
330d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
331d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembocleanup:
332d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth_clean_rings(greth);
333d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return -ENOMEM;
334d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
335d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
336d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic int greth_open(struct net_device *dev)
337d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
338d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_private *greth = netdev_priv(dev);
339d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	int err;
340d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
341d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	err = greth_init_rings(greth);
342d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (err) {
343d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (netif_msg_ifup(greth))
344d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			dev_err(&dev->dev, "Could not allocate memory for DMA rings\n");
345d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		return err;
346d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
347d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
348d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	err = request_irq(greth->irq, greth_interrupt, 0, "eth", (void *) dev);
349d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (err) {
350d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (netif_msg_ifup(greth))
351d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			dev_err(&dev->dev, "Could not allocate interrupt %d\n", dev->irq);
352d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		greth_clean_rings(greth);
353d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		return err;
354d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
355d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
356d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (netif_msg_ifup(greth))
357d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		dev_dbg(&dev->dev, " starting queue\n");
358d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	netif_start_queue(dev);
359d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
360bbe9e637330abe55442aebe799425e224086959fDaniel Hellstrom	GRETH_REGSAVE(greth->regs->status, 0xFF);
361bbe9e637330abe55442aebe799425e224086959fDaniel Hellstrom
362d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	napi_enable(&greth->napi);
363d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
364d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth_enable_irqs(greth);
365d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth_enable_tx(greth);
366d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth_enable_rx(greth);
367d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return 0;
368d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
369d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
370d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
371d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic int greth_close(struct net_device *dev)
372d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
373d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_private *greth = netdev_priv(dev);
374d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
375d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	napi_disable(&greth->napi);
376d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
377bbe9e637330abe55442aebe799425e224086959fDaniel Hellstrom	greth_disable_irqs(greth);
378d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth_disable_tx(greth);
379bbe9e637330abe55442aebe799425e224086959fDaniel Hellstrom	greth_disable_rx(greth);
380d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
381d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	netif_stop_queue(dev);
382d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
383d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	free_irq(greth->irq, (void *) dev);
384d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
385d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth_clean_rings(greth);
386d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
387d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return 0;
388d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
389d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
39041a655ba5654e47847505c164f77f8190ca9ed27kirjanov@gmail.comstatic netdev_tx_t
39141a655ba5654e47847505c164f77f8190ca9ed27kirjanov@gmail.comgreth_start_xmit(struct sk_buff *skb, struct net_device *dev)
392d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
393d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_private *greth = netdev_priv(dev);
394d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_bd *bdp;
395d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	int err = NETDEV_TX_OK;
3960f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom	u32 status, dma_addr, ctrl;
3970f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom	unsigned long flags;
398d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
3990f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom	/* Clean TX Ring */
4000f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom	greth_clean_tx(greth->netdev);
401d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
402d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (unlikely(greth->tx_free <= 0)) {
4030f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		spin_lock_irqsave(&greth->devlock, flags);/*save from poll/irq*/
4040f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		ctrl = GRETH_REGLOAD(greth->regs->control);
4050f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		/* Enable TX IRQ only if not already in poll() routine */
4060f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		if (ctrl & GRETH_RXI)
4070f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom			GRETH_REGSAVE(greth->regs->control, ctrl | GRETH_TXI);
408d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		netif_stop_queue(dev);
4090f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		spin_unlock_irqrestore(&greth->devlock, flags);
410d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		return NETDEV_TX_BUSY;
411d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
412d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
413d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (netif_msg_pktdata(greth))
414d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		greth_print_tx_packet(skb);
415d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
416d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
417d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (unlikely(skb->len > MAX_FRAME_SIZE)) {
418d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		dev->stats.tx_errors++;
419d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		goto out;
420d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
421d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
4220f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom	bdp = greth->tx_bd_base + greth->tx_next;
423d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	dma_addr = greth_read_bd(&bdp->addr);
424d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
425d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	memcpy((unsigned char *) phys_to_virt(dma_addr), skb->data, skb->len);
426d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
427d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	dma_sync_single_for_device(greth->dev, dma_addr, skb->len, DMA_TO_DEVICE);
428d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
4290f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom	status = GRETH_BD_EN | GRETH_BD_IE | (skb->len & GRETH_BD_LEN);
4306af29a963cecf426966d56935d60a984bd5594eaDaniel Hellstrom	greth->tx_bufs_length[greth->tx_next] = 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
493d706f00f65146822c0097b796b3557ea8980c305Daniel Hellstrom	if (skb->ip_summed == CHECKSUM_PARTIAL)
494d706f00f65146822c0097b796b3557ea8980c305Daniel Hellstrom		status |= GRETH_TXBD_CSALL;
495d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	status |= skb_headlen(skb) & GRETH_BD_LEN;
496d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (greth->tx_next == GRETH_TXBD_NUM_MASK)
497d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		status |= GRETH_BD_WR;
498d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
499d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
500d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	bdp = greth->tx_bd_base + greth->tx_next;
501d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth_write_bd(&bdp->stat, status);
502d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	dma_addr = dma_map_single(greth->dev, skb->data, skb_headlen(skb), DMA_TO_DEVICE);
503d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
504d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (unlikely(dma_mapping_error(greth->dev, dma_addr)))
505d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		goto map_error;
506d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
507d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth_write_bd(&bdp->addr, dma_addr);
508d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
509d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	curr_tx = NEXT_TX(greth->tx_next);
510d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
511d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	/* Frags */
512d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	for (i = 0; i < nr_frags; i++) {
513d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
514d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		greth->tx_skbuff[curr_tx] = NULL;
515d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		bdp = greth->tx_bd_base + curr_tx;
516d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
517d706f00f65146822c0097b796b3557ea8980c305Daniel Hellstrom		status = GRETH_BD_EN;
518d706f00f65146822c0097b796b3557ea8980c305Daniel Hellstrom		if (skb->ip_summed == CHECKSUM_PARTIAL)
519d706f00f65146822c0097b796b3557ea8980c305Daniel Hellstrom			status |= GRETH_TXBD_CSALL;
5209e903e085262ffbf1fc44a17ac06058aca03524aEric Dumazet		status |= skb_frag_size(frag) & GRETH_BD_LEN;
521d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
522d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		/* Wrap around descriptor ring */
523d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (curr_tx == GRETH_TXBD_NUM_MASK)
524d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			status |= GRETH_BD_WR;
525d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
526d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		/* More fragments left */
527d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (i < nr_frags - 1)
528d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			status |= GRETH_TXBD_MORE;
5290f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		else
5300f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom			status |= GRETH_BD_IE; /* enable IRQ on last fragment */
531d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
532d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		greth_write_bd(&bdp->stat, status);
533d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
5349e903e085262ffbf1fc44a17ac06058aca03524aEric Dumazet		dma_addr = skb_frag_dma_map(greth->dev, frag, 0, skb_frag_size(frag),
535ab7e11d9d0293ef1802d6ae8aab39ce58472b167Ian Campbell					    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++;
6446af29a963cecf426966d56935d60a984bd5594eaDaniel Hellstrom		dev->stats.tx_bytes += greth->tx_bufs_length[greth->tx_last];
645d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		greth->tx_last = NEXT_TX(greth->tx_last);
646d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		greth->tx_free++;
647d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
648d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
649d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (greth->tx_free > 0) {
650d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		netif_wake_queue(dev);
651d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
652d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
653d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
654d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
655d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic inline void greth_update_tx_stats(struct net_device *dev, u32 stat)
656d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
657d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	/* Check status for errors */
658d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (unlikely(stat & GRETH_TXBD_STATUS)) {
659d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		dev->stats.tx_errors++;
660d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (stat & GRETH_TXBD_ERR_AL)
661d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			dev->stats.tx_aborted_errors++;
662d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (stat & GRETH_TXBD_ERR_UE)
663d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			dev->stats.tx_fifo_errors++;
664d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (stat & GRETH_TXBD_ERR_LC)
665d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			dev->stats.tx_aborted_errors++;
666d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
667d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	dev->stats.tx_packets++;
668d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
669d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
670d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic void greth_clean_tx_gbit(struct net_device *dev)
671d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
672d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_private *greth;
673d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_bd *bdp, *bdp_last_frag;
674d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct sk_buff *skb;
675d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	u32 stat;
676d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	int nr_frags, i;
677d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
678d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth = netdev_priv(dev);
679d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
680d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	while (greth->tx_free < GRETH_TXBD_NUM) {
681d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
682d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		skb = greth->tx_skbuff[greth->tx_last];
683d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
684d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		nr_frags = skb_shinfo(skb)->nr_frags;
685d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
686d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		/* We only clean fully completed SKBs */
687d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		bdp_last_frag = greth->tx_bd_base + SKIP_TX(greth->tx_last, nr_frags);
6880f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom
6890f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		GRETH_REGSAVE(greth->regs->status, GRETH_INT_TE | GRETH_INT_TX);
6900f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		mb();
6910f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		stat = greth_read_bd(&bdp_last_frag->stat);
692d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
693d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (stat & GRETH_BD_EN)
694d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			break;
695d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
696d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		greth->tx_skbuff[greth->tx_last] = NULL;
697d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
698d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		greth_update_tx_stats(dev, stat);
6996af29a963cecf426966d56935d60a984bd5594eaDaniel Hellstrom		dev->stats.tx_bytes += skb->len;
700d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
701d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		bdp = greth->tx_bd_base + greth->tx_last;
702d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
703d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		greth->tx_last = NEXT_TX(greth->tx_last);
704d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
705d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		dma_unmap_single(greth->dev,
706d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				 greth_read_bd(&bdp->addr),
707d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				 skb_headlen(skb),
708d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				 DMA_TO_DEVICE);
709d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
710d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		for (i = 0; i < nr_frags; i++) {
711d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
712d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			bdp = greth->tx_bd_base + greth->tx_last;
713d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
714d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			dma_unmap_page(greth->dev,
715d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				       greth_read_bd(&bdp->addr),
7169e903e085262ffbf1fc44a17ac06058aca03524aEric Dumazet				       skb_frag_size(frag),
717d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				       DMA_TO_DEVICE);
718d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
719d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			greth->tx_last = NEXT_TX(greth->tx_last);
720d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		}
721d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		greth->tx_free += nr_frags+1;
722d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		dev_kfree_skb(skb);
723d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
724d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
7250f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom	if (netif_queue_stopped(dev) && (greth->tx_free > (MAX_SKB_FRAGS+1)))
7260f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		netif_wake_queue(dev);
727d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
728d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
729d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic int greth_rx(struct net_device *dev, int limit)
730d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
731d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_private *greth;
732d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_bd *bdp;
733d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct sk_buff *skb;
734d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	int pkt_len;
735d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	int bad, count;
736d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	u32 status, dma_addr;
7370f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom	unsigned long flags;
738d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
739d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth = netdev_priv(dev);
740d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
741d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	for (count = 0; count < limit; ++count) {
742d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
743d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		bdp = greth->rx_bd_base + greth->rx_cur;
7440f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		GRETH_REGSAVE(greth->regs->status, GRETH_INT_RE | GRETH_INT_RX);
7450f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		mb();
746d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		status = greth_read_bd(&bdp->stat);
747d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
748d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (unlikely(status & GRETH_BD_EN)) {
749d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			break;
750d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		}
751d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
7520f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		dma_addr = greth_read_bd(&bdp->addr);
7530f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		bad = 0;
7540f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom
755d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		/* Check status for errors. */
756d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (unlikely(status & GRETH_RXBD_STATUS)) {
757d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			if (status & GRETH_RXBD_ERR_FT) {
758d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				dev->stats.rx_length_errors++;
759d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				bad = 1;
760d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			}
761d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			if (status & (GRETH_RXBD_ERR_AE | GRETH_RXBD_ERR_OE)) {
762d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				dev->stats.rx_frame_errors++;
763d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				bad = 1;
764d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			}
765d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			if (status & GRETH_RXBD_ERR_CRC) {
766d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				dev->stats.rx_crc_errors++;
767d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				bad = 1;
768d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			}
769d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		}
770d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (unlikely(bad)) {
771d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			dev->stats.rx_errors++;
772d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
773d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		} else {
774d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
775d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			pkt_len = status & GRETH_BD_LEN;
776d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
777d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			skb = netdev_alloc_skb(dev, pkt_len + NET_IP_ALIGN);
778d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
779d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			if (unlikely(skb == NULL)) {
780d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
781d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				if (net_ratelimit())
782d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo					dev_warn(&dev->dev, "low on memory - " "packet dropped\n");
783d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
784d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				dev->stats.rx_dropped++;
785d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
786d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			} else {
787d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				skb_reserve(skb, NET_IP_ALIGN);
788d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
789d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				dma_sync_single_for_cpu(greth->dev,
790d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo							dma_addr,
791d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo							pkt_len,
792d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo							DMA_FROM_DEVICE);
793d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
794d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				if (netif_msg_pktdata(greth))
795d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo					greth_print_rx_packet(phys_to_virt(dma_addr), pkt_len);
796d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
797d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				memcpy(skb_put(skb, pkt_len), phys_to_virt(dma_addr), pkt_len);
798d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
799d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				skb->protocol = eth_type_trans(skb, dev);
8006af29a963cecf426966d56935d60a984bd5594eaDaniel Hellstrom				dev->stats.rx_bytes += pkt_len;
801d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				dev->stats.rx_packets++;
802d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				netif_receive_skb(skb);
803d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			}
804d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		}
805d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
806d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		status = GRETH_BD_EN | GRETH_BD_IE;
807d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (greth->rx_cur == GRETH_RXBD_NUM_MASK) {
808d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			status |= GRETH_BD_WR;
809d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		}
810d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
811d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		wmb();
812d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		greth_write_bd(&bdp->stat, status);
813d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
814d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		dma_sync_single_for_device(greth->dev, dma_addr, MAX_FRAME_SIZE, DMA_FROM_DEVICE);
815d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
8160f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		spin_lock_irqsave(&greth->devlock, flags); /* save from XMIT */
817d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		greth_enable_rx(greth);
8180f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		spin_unlock_irqrestore(&greth->devlock, flags);
819d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
820d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		greth->rx_cur = NEXT_RX(greth->rx_cur);
821d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
822d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
823d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return count;
824d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
825d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
826d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic inline int hw_checksummed(u32 status)
827d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
828d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
829d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (status & GRETH_RXBD_IP_FRAG)
830d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		return 0;
831d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
832d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (status & GRETH_RXBD_IP && status & GRETH_RXBD_IP_CSERR)
833d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		return 0;
834d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
835d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (status & GRETH_RXBD_UDP && status & GRETH_RXBD_UDP_CSERR)
836d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		return 0;
837d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
838d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (status & GRETH_RXBD_TCP && status & GRETH_RXBD_TCP_CSERR)
839d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		return 0;
840d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
841d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return 1;
842d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
843d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
844d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic int greth_rx_gbit(struct net_device *dev, int limit)
845d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
846d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_private *greth;
847d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_bd *bdp;
848d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct sk_buff *skb, *newskb;
849d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	int pkt_len;
850d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	int bad, count = 0;
851d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	u32 status, dma_addr;
8520f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom	unsigned long flags;
853d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
854d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth = netdev_priv(dev);
855d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
856d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	for (count = 0; count < limit; ++count) {
857d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
858d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		bdp = greth->rx_bd_base + greth->rx_cur;
859d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		skb = greth->rx_skbuff[greth->rx_cur];
8600f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		GRETH_REGSAVE(greth->regs->status, GRETH_INT_RE | GRETH_INT_RX);
8610f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		mb();
862d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		status = greth_read_bd(&bdp->stat);
863d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		bad = 0;
864d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
865d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (status & GRETH_BD_EN)
866d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			break;
867d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
868d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		/* Check status for errors. */
869d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (unlikely(status & GRETH_RXBD_STATUS)) {
870d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
871d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			if (status & GRETH_RXBD_ERR_FT) {
872d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				dev->stats.rx_length_errors++;
873d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				bad = 1;
874d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			} else if (status &
875d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				   (GRETH_RXBD_ERR_AE | GRETH_RXBD_ERR_OE | GRETH_RXBD_ERR_LE)) {
876d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				dev->stats.rx_frame_errors++;
877d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				bad = 1;
878d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			} else if (status & GRETH_RXBD_ERR_CRC) {
879d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				dev->stats.rx_crc_errors++;
880d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				bad = 1;
881d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			}
882d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		}
883d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
884b669e7f0580f3c0058f1b32c276ef6da8f05c138Daniel Hellstrom		/* Allocate new skb to replace current, not needed if the
885b669e7f0580f3c0058f1b32c276ef6da8f05c138Daniel Hellstrom		 * current skb can be reused */
886b669e7f0580f3c0058f1b32c276ef6da8f05c138Daniel Hellstrom		if (!bad && (newskb=netdev_alloc_skb(dev, MAX_FRAME_SIZE + NET_IP_ALIGN))) {
887d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			skb_reserve(newskb, NET_IP_ALIGN);
888d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
889d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			dma_addr = dma_map_single(greth->dev,
890d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo						      newskb->data,
891d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo						      MAX_FRAME_SIZE + NET_IP_ALIGN,
892d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo						      DMA_FROM_DEVICE);
893d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
894d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			if (!dma_mapping_error(greth->dev, dma_addr)) {
895d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				/* Process the incoming frame. */
896d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				pkt_len = status & GRETH_BD_LEN;
897d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
898d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				dma_unmap_single(greth->dev,
899d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo						 greth_read_bd(&bdp->addr),
900d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo						 MAX_FRAME_SIZE + NET_IP_ALIGN,
901d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo						 DMA_FROM_DEVICE);
902d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
903d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				if (netif_msg_pktdata(greth))
904d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo					greth_print_rx_packet(phys_to_virt(greth_read_bd(&bdp->addr)), pkt_len);
905d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
906d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				skb_put(skb, pkt_len);
907d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
908131ae329702755d897c6072c7839086b0702fb10Michał Mirosław				if (dev->features & NETIF_F_RXCSUM && hw_checksummed(status))
909d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo					skb->ip_summed = CHECKSUM_UNNECESSARY;
910d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				else
911bc8acf2c8c3e43fcc192762a9f964b3e9a17748bEric Dumazet					skb_checksum_none_assert(skb);
912d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
913d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				skb->protocol = eth_type_trans(skb, dev);
914d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				dev->stats.rx_packets++;
9156af29a963cecf426966d56935d60a984bd5594eaDaniel Hellstrom				dev->stats.rx_bytes += pkt_len;
916d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				netif_receive_skb(skb);
917d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
918d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				greth->rx_skbuff[greth->rx_cur] = newskb;
919d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				greth_write_bd(&bdp->addr, dma_addr);
920d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			} else {
921d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				if (net_ratelimit())
922d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo					dev_warn(greth->dev, "Could not create DMA mapping, dropping packet\n");
923d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				dev_kfree_skb(newskb);
924b669e7f0580f3c0058f1b32c276ef6da8f05c138Daniel Hellstrom				/* reusing current skb, so it is a drop */
925d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				dev->stats.rx_dropped++;
926d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			}
927b669e7f0580f3c0058f1b32c276ef6da8f05c138Daniel Hellstrom		} else if (bad) {
928b669e7f0580f3c0058f1b32c276ef6da8f05c138Daniel Hellstrom			/* Bad Frame transfer, the skb is reused */
929b669e7f0580f3c0058f1b32c276ef6da8f05c138Daniel Hellstrom			dev->stats.rx_dropped++;
930d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		} else {
931b669e7f0580f3c0058f1b32c276ef6da8f05c138Daniel Hellstrom			/* Failed Allocating a new skb. This is rather stupid
932b669e7f0580f3c0058f1b32c276ef6da8f05c138Daniel Hellstrom			 * but the current "filled" skb is reused, as if
933b669e7f0580f3c0058f1b32c276ef6da8f05c138Daniel Hellstrom			 * transfer failure. One could argue that RX descriptor
934b669e7f0580f3c0058f1b32c276ef6da8f05c138Daniel Hellstrom			 * table handling should be divided into cleaning and
935b669e7f0580f3c0058f1b32c276ef6da8f05c138Daniel Hellstrom			 * filling as the TX part of the driver
936b669e7f0580f3c0058f1b32c276ef6da8f05c138Daniel Hellstrom			 */
937d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			if (net_ratelimit())
938d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				dev_warn(greth->dev, "Could not allocate SKB, dropping packet\n");
939b669e7f0580f3c0058f1b32c276ef6da8f05c138Daniel Hellstrom			/* reusing current skb, so it is a drop */
940d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			dev->stats.rx_dropped++;
941d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		}
942d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
943d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		status = GRETH_BD_EN | GRETH_BD_IE;
944d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (greth->rx_cur == GRETH_RXBD_NUM_MASK) {
945d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			status |= GRETH_BD_WR;
946d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		}
947d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
948d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		wmb();
949d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		greth_write_bd(&bdp->stat, status);
9500f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		spin_lock_irqsave(&greth->devlock, flags);
951d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		greth_enable_rx(greth);
9520f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		spin_unlock_irqrestore(&greth->devlock, flags);
953d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		greth->rx_cur = NEXT_RX(greth->rx_cur);
954d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
955d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
956d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return count;
957d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
958d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
959d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
960d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic int greth_poll(struct napi_struct *napi, int budget)
961d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
962d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_private *greth;
963d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	int work_done = 0;
9640f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom	unsigned long flags;
9650f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom	u32 mask, ctrl;
966d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth = container_of(napi, struct greth_private, napi);
967d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
9680f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstromrestart_txrx_poll:
9690f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom	if (netif_queue_stopped(greth->netdev)) {
9700f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		if (greth->gbit_mac)
9710f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom			greth_clean_tx_gbit(greth->netdev);
9720f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		else
9730f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom			greth_clean_tx(greth->netdev);
974d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
975d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
976d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (greth->gbit_mac) {
977d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		work_done += greth_rx_gbit(greth->netdev, budget - work_done);
978d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	} else {
979d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		work_done += greth_rx(greth->netdev, budget - work_done);
980d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
981d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
982d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (work_done < budget) {
983d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
9840f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		spin_lock_irqsave(&greth->devlock, flags);
985d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
9860f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		ctrl = GRETH_REGLOAD(greth->regs->control);
9870f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		if (netif_queue_stopped(greth->netdev)) {
9880f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom			GRETH_REGSAVE(greth->regs->control,
9890f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom					ctrl | GRETH_TXI | GRETH_RXI);
9900f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom			mask = GRETH_INT_RX | GRETH_INT_RE |
9910f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom			       GRETH_INT_TX | GRETH_INT_TE;
9920f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		} else {
9930f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom			GRETH_REGSAVE(greth->regs->control, ctrl | GRETH_RXI);
9940f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom			mask = GRETH_INT_RX | GRETH_INT_RE;
9950f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		}
9960f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom
9970f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		if (GRETH_REGLOAD(greth->regs->status) & mask) {
9980f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom			GRETH_REGSAVE(greth->regs->control, ctrl);
9990f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom			spin_unlock_irqrestore(&greth->devlock, flags);
10000f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom			goto restart_txrx_poll;
10010f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom		} else {
10020f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom			__napi_complete(napi);
10030f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom			spin_unlock_irqrestore(&greth->devlock, flags);
1004d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		}
1005d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
1006d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1007d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return work_done;
1008d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
1009d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1010d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic int greth_set_mac_add(struct net_device *dev, void *p)
1011d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
1012d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct sockaddr *addr = p;
1013d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_private *greth;
1014d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_regs *regs;
1015d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
10166e03718c852a7b2ce756e37ae340f4ebfec2f6f3kirjanov@gmail.com	greth = netdev_priv(dev);
1017d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	regs = (struct greth_regs *) greth->regs;
1018d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1019d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (!is_valid_ether_addr(addr->sa_data))
1020504f9b5a6bb5336ad434438d0cdd61a16db80129Danny Kukawka		return -EADDRNOTAVAIL;
1021d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1022d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
10239b9cfe7cf663c16c0d93349cc0094bb28ae7135aKristoffer Glembo	GRETH_REGSAVE(regs->esa_msb, dev->dev_addr[0] << 8 | dev->dev_addr[1]);
10249b9cfe7cf663c16c0d93349cc0094bb28ae7135aKristoffer Glembo	GRETH_REGSAVE(regs->esa_lsb, dev->dev_addr[2] << 24 | dev->dev_addr[3] << 16 |
10259b9cfe7cf663c16c0d93349cc0094bb28ae7135aKristoffer Glembo		      dev->dev_addr[4] << 8 | dev->dev_addr[5]);
1026d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1027d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return 0;
1028d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
1029d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1030d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic u32 greth_hash_get_index(__u8 *addr)
1031d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
1032d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return (ether_crc(6, addr)) & 0x3F;
1033d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
1034d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1035d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic void greth_set_hash_filter(struct net_device *dev)
1036d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
103722bedad3ce112d5ca1eaf043d4990fa2ed698c87Jiri Pirko	struct netdev_hw_addr *ha;
10386e03718c852a7b2ce756e37ae340f4ebfec2f6f3kirjanov@gmail.com	struct greth_private *greth = netdev_priv(dev);
1039d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_regs *regs = (struct greth_regs *) greth->regs;
1040d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	u32 mc_filter[2];
10416e03718c852a7b2ce756e37ae340f4ebfec2f6f3kirjanov@gmail.com	unsigned int bitnr;
1042d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1043d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	mc_filter[0] = mc_filter[1] = 0;
1044d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
104522bedad3ce112d5ca1eaf043d4990fa2ed698c87Jiri Pirko	netdev_for_each_mc_addr(ha, dev) {
104622bedad3ce112d5ca1eaf043d4990fa2ed698c87Jiri Pirko		bitnr = greth_hash_get_index(ha->addr);
1047d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		mc_filter[bitnr >> 5] |= 1 << (bitnr & 31);
1048d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
1049d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1050d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	GRETH_REGSAVE(regs->hash_msb, mc_filter[1]);
1051d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	GRETH_REGSAVE(regs->hash_lsb, mc_filter[0]);
1052d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
1053d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1054d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic void greth_set_multicast_list(struct net_device *dev)
1055d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
1056d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	int cfg;
1057d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_private *greth = netdev_priv(dev);
1058d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_regs *regs = (struct greth_regs *) greth->regs;
1059d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1060d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	cfg = GRETH_REGLOAD(regs->control);
1061d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (dev->flags & IFF_PROMISC)
1062d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		cfg |= GRETH_CTRL_PR;
1063d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	else
1064d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		cfg &= ~GRETH_CTRL_PR;
1065d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1066d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (greth->multicast) {
1067d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (dev->flags & IFF_ALLMULTI) {
1068d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			GRETH_REGSAVE(regs->hash_msb, -1);
1069d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			GRETH_REGSAVE(regs->hash_lsb, -1);
1070d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			cfg |= GRETH_CTRL_MCEN;
1071d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			GRETH_REGSAVE(regs->control, cfg);
1072d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			return;
1073d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		}
1074d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
10756e03718c852a7b2ce756e37ae340f4ebfec2f6f3kirjanov@gmail.com		if (netdev_mc_empty(dev)) {
1076d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			cfg &= ~GRETH_CTRL_MCEN;
1077d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			GRETH_REGSAVE(regs->control, cfg);
1078d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			return;
1079d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		}
1080d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1081d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		/* Setup multicast filter */
1082d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		greth_set_hash_filter(dev);
1083d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		cfg |= GRETH_CTRL_MCEN;
1084d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
1085d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	GRETH_REGSAVE(regs->control, cfg);
1086d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
1087d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1088d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic u32 greth_get_msglevel(struct net_device *dev)
1089d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
1090d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_private *greth = netdev_priv(dev);
1091d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return greth->msg_enable;
1092d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
1093d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1094d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic void greth_set_msglevel(struct net_device *dev, u32 value)
1095d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
1096d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_private *greth = netdev_priv(dev);
1097d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->msg_enable = value;
1098d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
1099d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic int greth_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
1100d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
1101d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_private *greth = netdev_priv(dev);
1102d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct phy_device *phy = greth->phy;
1103d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1104d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (!phy)
1105d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		return -ENODEV;
1106d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1107d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return phy_ethtool_gset(phy, cmd);
1108d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
1109d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1110d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic int greth_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
1111d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
1112d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_private *greth = netdev_priv(dev);
1113d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct phy_device *phy = greth->phy;
1114d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1115d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (!phy)
1116d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		return -ENODEV;
1117d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1118d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return phy_ethtool_sset(phy, cmd);
1119d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
1120d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1121d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic int greth_get_regs_len(struct net_device *dev)
1122d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
1123d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return sizeof(struct greth_regs);
1124d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
1125d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1126d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic void greth_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
1127d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
1128d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_private *greth = netdev_priv(dev);
1129d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1130d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	strncpy(info->driver, dev_driver_string(greth->dev), 32);
1131d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	strncpy(info->version, "revision: 1.0", 32);
1132d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	strncpy(info->bus_info, greth->dev->bus->name, 32);
1133d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	strncpy(info->fw_version, "N/A", 32);
1134d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	info->eedump_len = 0;
1135d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	info->regdump_len = sizeof(struct greth_regs);
1136d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
1137d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1138d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic void greth_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
1139d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
1140d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	int i;
1141d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_private *greth = netdev_priv(dev);
1142d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	u32 __iomem *greth_regs = (u32 __iomem *) greth->regs;
1143d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	u32 *buff = p;
1144d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1145d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	for (i = 0; i < sizeof(struct greth_regs) / sizeof(u32); i++)
1146d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		buff[i] = greth_read_bd(&greth_regs[i]);
1147d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
1148d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1149d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic const struct ethtool_ops greth_ethtool_ops = {
1150d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	.get_msglevel		= greth_get_msglevel,
1151d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	.set_msglevel		= greth_set_msglevel,
1152d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	.get_settings		= greth_get_settings,
1153d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	.set_settings		= greth_set_settings,
1154d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	.get_drvinfo		= greth_get_drvinfo,
1155d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	.get_regs_len           = greth_get_regs_len,
1156d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	.get_regs               = greth_get_regs,
1157d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	.get_link		= ethtool_op_get_link,
1158d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo};
1159d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1160d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic struct net_device_ops greth_netdev_ops = {
11610f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom	.ndo_open		= greth_open,
11620f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom	.ndo_stop		= greth_close,
11630f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom	.ndo_start_xmit		= greth_start_xmit,
11640f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom	.ndo_set_mac_address	= greth_set_mac_add,
11650f73f2c5a3ebb957ee66718c903c17ed71a4fc2eDaniel Hellstrom	.ndo_validate_addr	= eth_validate_addr,
1166d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo};
1167d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1168d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic inline int wait_for_mdio(struct greth_private *greth)
1169d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
1170d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	unsigned long timeout = jiffies + 4*HZ/100;
1171d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	while (GRETH_REGLOAD(greth->regs->mdio) & GRETH_MII_BUSY) {
1172d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (time_after(jiffies, timeout))
1173d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			return 0;
1174d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
1175d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return 1;
1176d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
1177d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1178d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic int greth_mdio_read(struct mii_bus *bus, int phy, int reg)
1179d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
1180d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_private *greth = bus->priv;
1181d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	int data;
1182d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1183d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (!wait_for_mdio(greth))
1184d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		return -EBUSY;
1185d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1186d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	GRETH_REGSAVE(greth->regs->mdio, ((phy & 0x1F) << 11) | ((reg & 0x1F) << 6) | 2);
1187d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1188d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (!wait_for_mdio(greth))
1189d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		return -EBUSY;
1190d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1191d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (!(GRETH_REGLOAD(greth->regs->mdio) & GRETH_MII_NVALID)) {
1192d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		data = (GRETH_REGLOAD(greth->regs->mdio) >> 16) & 0xFFFF;
1193d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		return data;
1194d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1195d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	} else {
1196d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		return -1;
1197d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
1198d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
1199d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1200d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic int greth_mdio_write(struct mii_bus *bus, int phy, int reg, u16 val)
1201d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
1202d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_private *greth = bus->priv;
1203d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1204d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (!wait_for_mdio(greth))
1205d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		return -EBUSY;
1206d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1207d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	GRETH_REGSAVE(greth->regs->mdio,
1208d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		      ((val & 0xFFFF) << 16) | ((phy & 0x1F) << 11) | ((reg & 0x1F) << 6) | 1);
1209d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1210d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (!wait_for_mdio(greth))
1211d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		return -EBUSY;
1212d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1213d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return 0;
1214d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
1215d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1216d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic int greth_mdio_reset(struct mii_bus *bus)
1217d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
1218d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return 0;
1219d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
1220d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1221d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic void greth_link_change(struct net_device *dev)
1222d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
1223d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_private *greth = netdev_priv(dev);
1224d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct phy_device *phydev = greth->phy;
1225d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	unsigned long flags;
1226d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	int status_change = 0;
12272436af8ca7a6c4679cf7da7e3867f1d5cd8528b7Daniel Hellstrom	u32 ctrl;
1228d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1229d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	spin_lock_irqsave(&greth->devlock, flags);
1230d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1231d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (phydev->link) {
1232d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1233d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if ((greth->speed != phydev->speed) || (greth->duplex != phydev->duplex)) {
12342436af8ca7a6c4679cf7da7e3867f1d5cd8528b7Daniel Hellstrom			ctrl = GRETH_REGLOAD(greth->regs->control) &
12352436af8ca7a6c4679cf7da7e3867f1d5cd8528b7Daniel Hellstrom			       ~(GRETH_CTRL_FD | GRETH_CTRL_SP | GRETH_CTRL_GB);
1236d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1237d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			if (phydev->duplex)
12382436af8ca7a6c4679cf7da7e3867f1d5cd8528b7Daniel Hellstrom				ctrl |= GRETH_CTRL_FD;
1239d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
12402436af8ca7a6c4679cf7da7e3867f1d5cd8528b7Daniel Hellstrom			if (phydev->speed == SPEED_100)
12412436af8ca7a6c4679cf7da7e3867f1d5cd8528b7Daniel Hellstrom				ctrl |= GRETH_CTRL_SP;
1242d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			else if (phydev->speed == SPEED_1000)
12432436af8ca7a6c4679cf7da7e3867f1d5cd8528b7Daniel Hellstrom				ctrl |= GRETH_CTRL_GB;
1244d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
12452436af8ca7a6c4679cf7da7e3867f1d5cd8528b7Daniel Hellstrom			GRETH_REGSAVE(greth->regs->control, ctrl);
1246d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			greth->speed = phydev->speed;
1247d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			greth->duplex = phydev->duplex;
1248d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			status_change = 1;
1249d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		}
1250d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
1251d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1252d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (phydev->link != greth->link) {
1253d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (!phydev->link) {
1254d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			greth->speed = 0;
1255d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			greth->duplex = -1;
1256d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		}
1257d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		greth->link = phydev->link;
1258d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1259d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		status_change = 1;
1260d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
1261d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1262d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	spin_unlock_irqrestore(&greth->devlock, flags);
1263d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1264d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (status_change) {
1265d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (phydev->link)
1266d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			pr_debug("%s: link up (%d/%s)\n",
1267d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				dev->name, phydev->speed,
1268d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				DUPLEX_FULL == phydev->duplex ? "Full" : "Half");
1269d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		else
1270d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			pr_debug("%s: link down\n", dev->name);
1271d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
1272d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
1273d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1274d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic int greth_mdio_probe(struct net_device *dev)
1275d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
1276d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_private *greth = netdev_priv(dev);
1277d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct phy_device *phy = NULL;
12786e03718c852a7b2ce756e37ae340f4ebfec2f6f3kirjanov@gmail.com	int ret;
1279d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1280d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	/* Find the first PHY */
12816e03718c852a7b2ce756e37ae340f4ebfec2f6f3kirjanov@gmail.com	phy = phy_find_first(greth->mdio);
12826e03718c852a7b2ce756e37ae340f4ebfec2f6f3kirjanov@gmail.com
1283d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (!phy) {
1284d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (netif_msg_probe(greth))
1285d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			dev_err(&dev->dev, "no PHY found\n");
1286d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		return -ENXIO;
1287d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
1288d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
12896e03718c852a7b2ce756e37ae340f4ebfec2f6f3kirjanov@gmail.com	ret = phy_connect_direct(dev, phy, &greth_link_change,
12906e03718c852a7b2ce756e37ae340f4ebfec2f6f3kirjanov@gmail.com			0, greth->gbit_mac ?
12916e03718c852a7b2ce756e37ae340f4ebfec2f6f3kirjanov@gmail.com			PHY_INTERFACE_MODE_GMII :
12926e03718c852a7b2ce756e37ae340f4ebfec2f6f3kirjanov@gmail.com			PHY_INTERFACE_MODE_MII);
12936e03718c852a7b2ce756e37ae340f4ebfec2f6f3kirjanov@gmail.com	if (ret) {
12946e03718c852a7b2ce756e37ae340f4ebfec2f6f3kirjanov@gmail.com		if (netif_msg_ifup(greth))
12956e03718c852a7b2ce756e37ae340f4ebfec2f6f3kirjanov@gmail.com			dev_err(&dev->dev, "could not attach to PHY\n");
12966e03718c852a7b2ce756e37ae340f4ebfec2f6f3kirjanov@gmail.com		return ret;
12976e03718c852a7b2ce756e37ae340f4ebfec2f6f3kirjanov@gmail.com	}
1298d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1299d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (greth->gbit_mac)
1300d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		phy->supported &= PHY_GBIT_FEATURES;
1301d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	else
1302d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		phy->supported &= PHY_BASIC_FEATURES;
1303d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1304d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	phy->advertising = phy->supported;
1305d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1306d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->link = 0;
1307d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->speed = 0;
1308d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->duplex = -1;
1309d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->phy = phy;
1310d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1311d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return 0;
1312d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
1313d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1314d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic inline int phy_aneg_done(struct phy_device *phydev)
1315d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
1316d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	int retval;
1317d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1318d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	retval = phy_read(phydev, MII_BMSR);
1319d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1320d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return (retval < 0) ? retval : (retval & BMSR_ANEGCOMPLETE);
1321d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
1322d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1323d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic int greth_mdio_init(struct greth_private *greth)
1324d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
1325d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	int ret, phy;
1326d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	unsigned long timeout;
1327d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1328d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->mdio = mdiobus_alloc();
1329d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (!greth->mdio) {
1330d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		return -ENOMEM;
1331d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
1332d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1333d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->mdio->name = "greth-mdio";
1334d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	snprintf(greth->mdio->id, MII_BUS_ID_SIZE, "%s-%d", greth->mdio->name, greth->irq);
1335d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->mdio->read = greth_mdio_read;
1336d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->mdio->write = greth_mdio_write;
1337d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->mdio->reset = greth_mdio_reset;
1338d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->mdio->priv = greth;
1339d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1340d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->mdio->irq = greth->mdio_irqs;
1341d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1342d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	for (phy = 0; phy < PHY_MAX_ADDR; phy++)
1343d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		greth->mdio->irq[phy] = PHY_POLL;
1344d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1345d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	ret = mdiobus_register(greth->mdio);
1346d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (ret) {
1347d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		goto error;
1348d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
1349d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1350d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	ret = greth_mdio_probe(greth->netdev);
1351d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (ret) {
1352d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (netif_msg_probe(greth))
1353d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			dev_err(&greth->netdev->dev, "failed to probe MDIO bus\n");
1354d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		goto unreg_mdio;
1355d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
1356d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1357d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	phy_start(greth->phy);
1358d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1359d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	/* If Ethernet debug link is used make autoneg happen right away */
1360d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (greth->edcl && greth_edcl == 1) {
1361d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		phy_start_aneg(greth->phy);
1362d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		timeout = jiffies + 6*HZ;
1363d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		while (!phy_aneg_done(greth->phy) && time_before(jiffies, timeout)) {
1364d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		}
1365d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		genphy_read_status(greth->phy);
1366d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		greth_link_change(greth->netdev);
1367d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
1368d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1369d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return 0;
1370d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1371d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembounreg_mdio:
1372d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	mdiobus_unregister(greth->mdio);
1373d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glemboerror:
1374d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	mdiobus_free(greth->mdio);
1375d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return ret;
1376d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
1377d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1378d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo/* Initialize the GRETH MAC */
137974888760d40b3ac9054f9c5fa07b566c0676ba2dGrant Likelystatic int __devinit greth_of_probe(struct platform_device *ofdev)
1380d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
1381d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct net_device *dev;
1382d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_private *greth;
1383d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_regs *regs;
1384d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1385d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	int i;
1386d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	int err;
1387d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	int tmp;
1388d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	unsigned long timeout;
1389d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1390d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	dev = alloc_etherdev(sizeof(struct greth_private));
1391d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1392d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (dev == NULL)
1393d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		return -ENOMEM;
1394d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1395d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth = netdev_priv(dev);
1396d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->netdev = dev;
1397d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->dev = &ofdev->dev;
1398d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1399d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (greth_debug > 0)
1400d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		greth->msg_enable = greth_debug;
1401d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	else
1402d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		greth->msg_enable = GRETH_DEF_MSG_ENABLE;
1403d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1404d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	spin_lock_init(&greth->devlock);
1405d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1406d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->regs = of_ioremap(&ofdev->resource[0], 0,
1407d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				 resource_size(&ofdev->resource[0]),
1408d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				 "grlib-greth regs");
1409d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1410d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (greth->regs == NULL) {
1411d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (netif_msg_probe(greth))
1412d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			dev_err(greth->dev, "ioremap failure.\n");
1413d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		err = -EIO;
1414d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		goto error1;
1415d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
1416d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1417d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	regs = (struct greth_regs *) greth->regs;
141819e4875fb21a69fbf620e84769a74d189c69c58dGrant Likely	greth->irq = ofdev->archdata.irqs[0];
1419d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1420d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	dev_set_drvdata(greth->dev, dev);
1421d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	SET_NETDEV_DEV(dev, greth->dev);
1422d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1423d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (netif_msg_probe(greth))
142472e60278d7e4a600fd6e067b42a5822e72946d6eMasanari Iida		dev_dbg(greth->dev, "resetting controller.\n");
1425d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1426d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	/* Reset the controller. */
1427d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	GRETH_REGSAVE(regs->control, GRETH_RESET);
1428d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1429d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	/* Wait for MAC to reset itself */
1430d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	timeout = jiffies + HZ/100;
1431d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	while (GRETH_REGLOAD(regs->control) & GRETH_RESET) {
1432d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (time_after(jiffies, timeout)) {
1433d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			err = -EIO;
1434d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			if (netif_msg_probe(greth))
1435d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				dev_err(greth->dev, "timeout when waiting for reset.\n");
1436d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			goto error2;
1437d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		}
1438d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
1439d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1440d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	/* Get default PHY address  */
1441d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->phyaddr = (GRETH_REGLOAD(regs->mdio) >> 11) & 0x1F;
1442d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1443d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	/* Check if we have GBIT capable MAC */
1444d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	tmp = GRETH_REGLOAD(regs->control);
1445d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->gbit_mac = (tmp >> 27) & 1;
1446d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1447d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	/* Check for multicast capability */
1448d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->multicast = (tmp >> 25) & 1;
1449d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1450d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->edcl = (tmp >> 31) & 1;
1451d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1452d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	/* If we have EDCL we disable the EDCL speed-duplex FSM so
1453d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	 * it doesn't interfere with the software */
1454d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (greth->edcl != 0)
1455d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		GRETH_REGORIN(regs->control, GRETH_CTRL_DISDUPLEX);
1456d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1457d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	/* Check if MAC can handle MDIO interrupts */
1458d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->mdio_int_en = (tmp >> 26) & 1;
1459d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1460d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	err = greth_mdio_init(greth);
1461d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (err) {
1462d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (netif_msg_probe(greth))
1463d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			dev_err(greth->dev, "failed to register MDIO bus\n");
1464d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		goto error2;
1465d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
1466d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1467d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	/* Allocate TX descriptor ring in coherent memory */
1468d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->tx_bd_base = (struct greth_bd *) dma_alloc_coherent(greth->dev,
1469d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo								   1024,
1470d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo								   &greth->tx_bd_base_phys,
1471d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo								   GFP_KERNEL);
1472d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1473d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (!greth->tx_bd_base) {
1474d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (netif_msg_probe(greth))
1475d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			dev_err(&dev->dev, "could not allocate descriptor memory.\n");
1476d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		err = -ENOMEM;
1477d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		goto error3;
1478d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
1479d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1480d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	memset(greth->tx_bd_base, 0, 1024);
1481d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1482d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	/* Allocate RX descriptor ring in coherent memory */
1483d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	greth->rx_bd_base = (struct greth_bd *) dma_alloc_coherent(greth->dev,
1484d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo								   1024,
1485d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo								   &greth->rx_bd_base_phys,
1486d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo								   GFP_KERNEL);
1487d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1488d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (!greth->rx_bd_base) {
1489d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (netif_msg_probe(greth))
1490d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			dev_err(greth->dev, "could not allocate descriptor memory.\n");
1491d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		err = -ENOMEM;
1492d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		goto error4;
1493d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
1494d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1495d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	memset(greth->rx_bd_base, 0, 1024);
1496d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1497d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	/* Get MAC address from: module param, OF property or ID prom */
1498d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	for (i = 0; i < 6; i++) {
1499d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (macaddr[i] != 0)
1500d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			break;
1501d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
1502d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (i == 6) {
1503d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		const unsigned char *addr;
1504d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		int len;
150561c7a080a5a061c976988fd4b844dfb468dda255Grant Likely		addr = of_get_property(ofdev->dev.of_node, "local-mac-address",
150661c7a080a5a061c976988fd4b844dfb468dda255Grant Likely					&len);
1507d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (addr != NULL && len == 6) {
1508d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			for (i = 0; i < 6; i++)
1509d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				macaddr[i] = (unsigned int) addr[i];
1510d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		} else {
1511d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo#ifdef CONFIG_SPARC
1512d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			for (i = 0; i < 6; i++)
1513d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo				macaddr[i] = (unsigned int) idprom->id_ethaddr[i];
1514d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo#endif
1515d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		}
1516d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
1517d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1518d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	for (i = 0; i < 6; i++)
1519d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		dev->dev_addr[i] = macaddr[i];
1520d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1521d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	macaddr[5]++;
1522d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1523d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (!is_valid_ether_addr(&dev->dev_addr[0])) {
1524d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (netif_msg_probe(greth))
1525d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			dev_err(greth->dev, "no valid ethernet address, aborting.\n");
1526d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		err = -EINVAL;
1527d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		goto error5;
1528d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
1529d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1530d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	GRETH_REGSAVE(regs->esa_msb, dev->dev_addr[0] << 8 | dev->dev_addr[1]);
1531d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	GRETH_REGSAVE(regs->esa_lsb, dev->dev_addr[2] << 24 | dev->dev_addr[3] << 16 |
1532d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		      dev->dev_addr[4] << 8 | dev->dev_addr[5]);
1533d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1534d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	/* Clear all pending interrupts except PHY irq */
1535d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	GRETH_REGSAVE(regs->status, 0xFF);
1536d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1537d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (greth->gbit_mac) {
1538131ae329702755d897c6072c7839086b0702fb10Michał Mirosław		dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM |
1539131ae329702755d897c6072c7839086b0702fb10Michał Mirosław			NETIF_F_RXCSUM;
1540131ae329702755d897c6072c7839086b0702fb10Michał Mirosław		dev->features = dev->hw_features | NETIF_F_HIGHDMA;
1541d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		greth_netdev_ops.ndo_start_xmit = greth_start_xmit_gbit;
1542d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
1543d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1544d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (greth->multicast) {
1545afc4b13df143122f99a0eb10bfefb216c2806de0Jiri Pirko		greth_netdev_ops.ndo_set_rx_mode = greth_set_multicast_list;
1546d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		dev->flags |= IFF_MULTICAST;
1547d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	} else {
1548d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		dev->flags &= ~IFF_MULTICAST;
1549d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
1550d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1551d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	dev->netdev_ops = &greth_netdev_ops;
1552d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	dev->ethtool_ops = &greth_ethtool_ops;
1553d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1554cb5d991a99104565f7b622b1b97587f4b1effa82Tobias Klauser	err = register_netdev(dev);
1555cb5d991a99104565f7b622b1b97587f4b1effa82Tobias Klauser	if (err) {
1556d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		if (netif_msg_probe(greth))
1557d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo			dev_err(greth->dev, "netdevice registration failed.\n");
1558d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		goto error5;
1559d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	}
1560d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1561d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	/* setup NAPI */
1562d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	netif_napi_add(dev, &greth->napi, greth_poll, 64);
1563d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1564d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return 0;
1565d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1566d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glemboerror5:
1567d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	dma_free_coherent(greth->dev, 1024, greth->rx_bd_base, greth->rx_bd_base_phys);
1568d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glemboerror4:
1569d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	dma_free_coherent(greth->dev, 1024, greth->tx_bd_base, greth->tx_bd_base_phys);
1570d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glemboerror3:
1571d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	mdiobus_unregister(greth->mdio);
1572d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glemboerror2:
1573d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	of_iounmap(&ofdev->resource[0], greth->regs, resource_size(&ofdev->resource[0]));
1574d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glemboerror1:
1575d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	free_netdev(dev);
1576d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return err;
1577d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
1578d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
15792dc11581376829303b98eadb2de253bee065a56aGrant Likelystatic int __devexit greth_of_remove(struct platform_device *of_dev)
1580d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo{
1581d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct net_device *ndev = dev_get_drvdata(&of_dev->dev);
1582d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	struct greth_private *greth = netdev_priv(ndev);
1583d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1584d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	/* Free descriptor areas */
1585d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	dma_free_coherent(&of_dev->dev, 1024, greth->rx_bd_base, greth->rx_bd_base_phys);
1586d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1587d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	dma_free_coherent(&of_dev->dev, 1024, greth->tx_bd_base, greth->tx_bd_base_phys);
1588d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1589d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	dev_set_drvdata(&of_dev->dev, NULL);
1590d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1591d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	if (greth->phy)
1592d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo		phy_stop(greth->phy);
1593d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	mdiobus_unregister(greth->mdio);
1594d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1595d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	unregister_netdev(ndev);
1596d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	free_netdev(ndev);
1597d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1598d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	of_iounmap(&of_dev->resource[0], greth->regs, resource_size(&of_dev->resource[0]));
1599d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1600d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	return 0;
1601d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo}
1602d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1603d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembostatic struct of_device_id greth_of_match[] = {
1604d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	{
1605d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	 .name = "GAISLER_ETHMAC",
1606d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	 },
1607ad4650a89ac47bd153cbb76c3fd6eb1fa6f315b7Daniel Hellstrom	{
1608ad4650a89ac47bd153cbb76c3fd6eb1fa6f315b7Daniel Hellstrom	 .name = "01_01d",
1609ad4650a89ac47bd153cbb76c3fd6eb1fa6f315b7Daniel Hellstrom	 },
1610d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	{},
1611d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo};
1612d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1613d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer GlemboMODULE_DEVICE_TABLE(of, greth_of_match);
1614d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
161574888760d40b3ac9054f9c5fa07b566c0676ba2dGrant Likelystatic struct platform_driver greth_of_driver = {
1616bc284f94f84c3d76e49c6f3df9028c503f9589d9David S. Miller	.driver = {
1617bc284f94f84c3d76e49c6f3df9028c503f9589d9David S. Miller		.name = "grlib-greth",
1618bc284f94f84c3d76e49c6f3df9028c503f9589d9David S. Miller		.owner = THIS_MODULE,
1619bc284f94f84c3d76e49c6f3df9028c503f9589d9David S. Miller		.of_match_table = greth_of_match,
1620bc284f94f84c3d76e49c6f3df9028c503f9589d9David S. Miller	},
1621d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	.probe = greth_of_probe,
1622d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo	.remove = __devexit_p(greth_of_remove),
1623d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo};
1624d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1625db62f684deeb291ab2533b99843d5df9a36b1f19Axel Linmodule_platform_driver(greth_of_driver);
1626d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer Glembo
1627d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer GlemboMODULE_AUTHOR("Aeroflex Gaisler AB.");
1628d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer GlemboMODULE_DESCRIPTION("Aeroflex Gaisler Ethernet MAC driver");
1629d4c41139df6e74c6fff0cbac43e51cab782133beKristoffer GlemboMODULE_LICENSE("GPL");
1630