174ba9207SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2baf0fbfeSJeff Kirsher /*
3baf0fbfeSJeff Kirsher  * Faraday FTMAC100 10/100 Ethernet
4baf0fbfeSJeff Kirsher  *
5baf0fbfeSJeff Kirsher  * (C) Copyright 2009-2011 Faraday Technology
6baf0fbfeSJeff Kirsher  * Po-Yu Chuang <ratbert@faraday-tech.com>
7baf0fbfeSJeff Kirsher  */
8baf0fbfeSJeff Kirsher 
9baf0fbfeSJeff Kirsher #define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
10baf0fbfeSJeff Kirsher 
11baf0fbfeSJeff Kirsher #include <linux/dma-mapping.h>
12baf0fbfeSJeff Kirsher #include <linux/etherdevice.h>
13baf0fbfeSJeff Kirsher #include <linux/ethtool.h>
14*30f837b7SVladimir Oltean #include <linux/if_vlan.h>
15baf0fbfeSJeff Kirsher #include <linux/init.h>
1617f1bbcaSThomas Faber #include <linux/interrupt.h>
17baf0fbfeSJeff Kirsher #include <linux/io.h>
18baf0fbfeSJeff Kirsher #include <linux/mii.h>
19baf0fbfeSJeff Kirsher #include <linux/module.h>
20ac316725SRandy Dunlap #include <linux/mod_devicetable.h>
21baf0fbfeSJeff Kirsher #include <linux/netdevice.h>
22baf0fbfeSJeff Kirsher #include <linux/platform_device.h>
23baf0fbfeSJeff Kirsher 
24baf0fbfeSJeff Kirsher #include "ftmac100.h"
25baf0fbfeSJeff Kirsher 
26baf0fbfeSJeff Kirsher #define DRV_NAME	"ftmac100"
27baf0fbfeSJeff Kirsher 
28baf0fbfeSJeff Kirsher #define RX_QUEUE_ENTRIES	128	/* must be power of 2 */
29baf0fbfeSJeff Kirsher #define TX_QUEUE_ENTRIES	16	/* must be power of 2 */
30baf0fbfeSJeff Kirsher 
31baf0fbfeSJeff Kirsher #define MAX_PKT_SIZE		1518
32baf0fbfeSJeff Kirsher #define RX_BUF_SIZE		2044	/* must be smaller than 0x7ff */
33baf0fbfeSJeff Kirsher 
34baf0fbfeSJeff Kirsher #if MAX_PKT_SIZE > 0x7ff
35baf0fbfeSJeff Kirsher #error invalid MAX_PKT_SIZE
36baf0fbfeSJeff Kirsher #endif
37baf0fbfeSJeff Kirsher 
38baf0fbfeSJeff Kirsher #if RX_BUF_SIZE > 0x7ff || RX_BUF_SIZE > PAGE_SIZE
39baf0fbfeSJeff Kirsher #error invalid RX_BUF_SIZE
40baf0fbfeSJeff Kirsher #endif
41baf0fbfeSJeff Kirsher 
42baf0fbfeSJeff Kirsher /******************************************************************************
43baf0fbfeSJeff Kirsher  * private data
44baf0fbfeSJeff Kirsher  *****************************************************************************/
45baf0fbfeSJeff Kirsher struct ftmac100_descs {
46baf0fbfeSJeff Kirsher 	struct ftmac100_rxdes rxdes[RX_QUEUE_ENTRIES];
47baf0fbfeSJeff Kirsher 	struct ftmac100_txdes txdes[TX_QUEUE_ENTRIES];
48baf0fbfeSJeff Kirsher };
49baf0fbfeSJeff Kirsher 
50baf0fbfeSJeff Kirsher struct ftmac100 {
51baf0fbfeSJeff Kirsher 	struct resource *res;
52baf0fbfeSJeff Kirsher 	void __iomem *base;
53baf0fbfeSJeff Kirsher 	int irq;
54baf0fbfeSJeff Kirsher 
55baf0fbfeSJeff Kirsher 	struct ftmac100_descs *descs;
56baf0fbfeSJeff Kirsher 	dma_addr_t descs_dma_addr;
57baf0fbfeSJeff Kirsher 
58baf0fbfeSJeff Kirsher 	unsigned int rx_pointer;
59baf0fbfeSJeff Kirsher 	unsigned int tx_clean_pointer;
60baf0fbfeSJeff Kirsher 	unsigned int tx_pointer;
61baf0fbfeSJeff Kirsher 	unsigned int tx_pending;
62baf0fbfeSJeff Kirsher 
63baf0fbfeSJeff Kirsher 	spinlock_t tx_lock;
64baf0fbfeSJeff Kirsher 
65baf0fbfeSJeff Kirsher 	struct net_device *netdev;
66baf0fbfeSJeff Kirsher 	struct device *dev;
67baf0fbfeSJeff Kirsher 	struct napi_struct napi;
68baf0fbfeSJeff Kirsher 
69baf0fbfeSJeff Kirsher 	struct mii_if_info mii;
70baf0fbfeSJeff Kirsher };
71baf0fbfeSJeff Kirsher 
72baf0fbfeSJeff Kirsher static int ftmac100_alloc_rx_page(struct ftmac100 *priv,
73baf0fbfeSJeff Kirsher 				  struct ftmac100_rxdes *rxdes, gfp_t gfp);
74baf0fbfeSJeff Kirsher 
75baf0fbfeSJeff Kirsher /******************************************************************************
76baf0fbfeSJeff Kirsher  * internal functions (hardware register access)
77baf0fbfeSJeff Kirsher  *****************************************************************************/
78baf0fbfeSJeff Kirsher #define INT_MASK_ALL_ENABLED	(FTMAC100_INT_RPKT_FINISH	| \
79baf0fbfeSJeff Kirsher 				 FTMAC100_INT_NORXBUF		| \
80baf0fbfeSJeff Kirsher 				 FTMAC100_INT_XPKT_OK		| \
81baf0fbfeSJeff Kirsher 				 FTMAC100_INT_XPKT_LOST		| \
82baf0fbfeSJeff Kirsher 				 FTMAC100_INT_RPKT_LOST		| \
83baf0fbfeSJeff Kirsher 				 FTMAC100_INT_AHB_ERR		| \
84baf0fbfeSJeff Kirsher 				 FTMAC100_INT_PHYSTS_CHG)
85baf0fbfeSJeff Kirsher 
86baf0fbfeSJeff Kirsher #define INT_MASK_ALL_DISABLED	0
87baf0fbfeSJeff Kirsher 
88baf0fbfeSJeff Kirsher static void ftmac100_enable_all_int(struct ftmac100 *priv)
89baf0fbfeSJeff Kirsher {
90baf0fbfeSJeff Kirsher 	iowrite32(INT_MASK_ALL_ENABLED, priv->base + FTMAC100_OFFSET_IMR);
91baf0fbfeSJeff Kirsher }
92baf0fbfeSJeff Kirsher 
93baf0fbfeSJeff Kirsher static void ftmac100_disable_all_int(struct ftmac100 *priv)
94baf0fbfeSJeff Kirsher {
95baf0fbfeSJeff Kirsher 	iowrite32(INT_MASK_ALL_DISABLED, priv->base + FTMAC100_OFFSET_IMR);
96baf0fbfeSJeff Kirsher }
97baf0fbfeSJeff Kirsher 
98baf0fbfeSJeff Kirsher static void ftmac100_set_rx_ring_base(struct ftmac100 *priv, dma_addr_t addr)
99baf0fbfeSJeff Kirsher {
100baf0fbfeSJeff Kirsher 	iowrite32(addr, priv->base + FTMAC100_OFFSET_RXR_BADR);
101baf0fbfeSJeff Kirsher }
102baf0fbfeSJeff Kirsher 
103baf0fbfeSJeff Kirsher static void ftmac100_set_tx_ring_base(struct ftmac100 *priv, dma_addr_t addr)
104baf0fbfeSJeff Kirsher {
105baf0fbfeSJeff Kirsher 	iowrite32(addr, priv->base + FTMAC100_OFFSET_TXR_BADR);
106baf0fbfeSJeff Kirsher }
107baf0fbfeSJeff Kirsher 
108baf0fbfeSJeff Kirsher static void ftmac100_txdma_start_polling(struct ftmac100 *priv)
109baf0fbfeSJeff Kirsher {
110baf0fbfeSJeff Kirsher 	iowrite32(1, priv->base + FTMAC100_OFFSET_TXPD);
111baf0fbfeSJeff Kirsher }
112baf0fbfeSJeff Kirsher 
113baf0fbfeSJeff Kirsher static int ftmac100_reset(struct ftmac100 *priv)
114baf0fbfeSJeff Kirsher {
115baf0fbfeSJeff Kirsher 	struct net_device *netdev = priv->netdev;
116baf0fbfeSJeff Kirsher 	int i;
117baf0fbfeSJeff Kirsher 
118baf0fbfeSJeff Kirsher 	/* NOTE: reset clears all registers */
119baf0fbfeSJeff Kirsher 	iowrite32(FTMAC100_MACCR_SW_RST, priv->base + FTMAC100_OFFSET_MACCR);
120baf0fbfeSJeff Kirsher 
121baf0fbfeSJeff Kirsher 	for (i = 0; i < 5; i++) {
122baf0fbfeSJeff Kirsher 		unsigned int maccr;
123baf0fbfeSJeff Kirsher 
124baf0fbfeSJeff Kirsher 		maccr = ioread32(priv->base + FTMAC100_OFFSET_MACCR);
125baf0fbfeSJeff Kirsher 		if (!(maccr & FTMAC100_MACCR_SW_RST)) {
126baf0fbfeSJeff Kirsher 			/*
127baf0fbfeSJeff Kirsher 			 * FTMAC100_MACCR_SW_RST cleared does not indicate
128baf0fbfeSJeff Kirsher 			 * that hardware reset completed (what the f*ck).
129baf0fbfeSJeff Kirsher 			 * We still need to wait for a while.
130baf0fbfeSJeff Kirsher 			 */
131baf0fbfeSJeff Kirsher 			udelay(500);
132baf0fbfeSJeff Kirsher 			return 0;
133baf0fbfeSJeff Kirsher 		}
134baf0fbfeSJeff Kirsher 
135baf0fbfeSJeff Kirsher 		udelay(1000);
136baf0fbfeSJeff Kirsher 	}
137baf0fbfeSJeff Kirsher 
138baf0fbfeSJeff Kirsher 	netdev_err(netdev, "software reset failed\n");
139baf0fbfeSJeff Kirsher 	return -EIO;
140baf0fbfeSJeff Kirsher }
141baf0fbfeSJeff Kirsher 
142baf0fbfeSJeff Kirsher static void ftmac100_set_mac(struct ftmac100 *priv, const unsigned char *mac)
143baf0fbfeSJeff Kirsher {
144baf0fbfeSJeff Kirsher 	unsigned int maddr = mac[0] << 8 | mac[1];
145baf0fbfeSJeff Kirsher 	unsigned int laddr = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5];
146baf0fbfeSJeff Kirsher 
147baf0fbfeSJeff Kirsher 	iowrite32(maddr, priv->base + FTMAC100_OFFSET_MAC_MADR);
148baf0fbfeSJeff Kirsher 	iowrite32(laddr, priv->base + FTMAC100_OFFSET_MAC_LADR);
149baf0fbfeSJeff Kirsher }
150baf0fbfeSJeff Kirsher 
151baf0fbfeSJeff Kirsher #define MACCR_ENABLE_ALL	(FTMAC100_MACCR_XMT_EN	| \
152baf0fbfeSJeff Kirsher 				 FTMAC100_MACCR_RCV_EN	| \
153baf0fbfeSJeff Kirsher 				 FTMAC100_MACCR_XDMA_EN	| \
154baf0fbfeSJeff Kirsher 				 FTMAC100_MACCR_RDMA_EN	| \
155baf0fbfeSJeff Kirsher 				 FTMAC100_MACCR_CRC_APD	| \
156baf0fbfeSJeff Kirsher 				 FTMAC100_MACCR_FULLDUP	| \
157baf0fbfeSJeff Kirsher 				 FTMAC100_MACCR_RX_RUNT	| \
158baf0fbfeSJeff Kirsher 				 FTMAC100_MACCR_RX_BROADPKT)
159baf0fbfeSJeff Kirsher 
160baf0fbfeSJeff Kirsher static int ftmac100_start_hw(struct ftmac100 *priv)
161baf0fbfeSJeff Kirsher {
162baf0fbfeSJeff Kirsher 	struct net_device *netdev = priv->netdev;
163baf0fbfeSJeff Kirsher 
164baf0fbfeSJeff Kirsher 	if (ftmac100_reset(priv))
165baf0fbfeSJeff Kirsher 		return -EIO;
166baf0fbfeSJeff Kirsher 
167baf0fbfeSJeff Kirsher 	/* setup ring buffer base registers */
168baf0fbfeSJeff Kirsher 	ftmac100_set_rx_ring_base(priv,
169baf0fbfeSJeff Kirsher 				  priv->descs_dma_addr +
170baf0fbfeSJeff Kirsher 				  offsetof(struct ftmac100_descs, rxdes));
171baf0fbfeSJeff Kirsher 	ftmac100_set_tx_ring_base(priv,
172baf0fbfeSJeff Kirsher 				  priv->descs_dma_addr +
173baf0fbfeSJeff Kirsher 				  offsetof(struct ftmac100_descs, txdes));
174baf0fbfeSJeff Kirsher 
175baf0fbfeSJeff Kirsher 	iowrite32(FTMAC100_APTC_RXPOLL_CNT(1), priv->base + FTMAC100_OFFSET_APTC);
176baf0fbfeSJeff Kirsher 
177baf0fbfeSJeff Kirsher 	ftmac100_set_mac(priv, netdev->dev_addr);
178baf0fbfeSJeff Kirsher 
179baf0fbfeSJeff Kirsher 	iowrite32(MACCR_ENABLE_ALL, priv->base + FTMAC100_OFFSET_MACCR);
180baf0fbfeSJeff Kirsher 	return 0;
181baf0fbfeSJeff Kirsher }
182baf0fbfeSJeff Kirsher 
183baf0fbfeSJeff Kirsher static void ftmac100_stop_hw(struct ftmac100 *priv)
184baf0fbfeSJeff Kirsher {
185baf0fbfeSJeff Kirsher 	iowrite32(0, priv->base + FTMAC100_OFFSET_MACCR);
186baf0fbfeSJeff Kirsher }
187baf0fbfeSJeff Kirsher 
188baf0fbfeSJeff Kirsher /******************************************************************************
189baf0fbfeSJeff Kirsher  * internal functions (receive descriptor)
190baf0fbfeSJeff Kirsher  *****************************************************************************/
191baf0fbfeSJeff Kirsher static bool ftmac100_rxdes_first_segment(struct ftmac100_rxdes *rxdes)
192baf0fbfeSJeff Kirsher {
193baf0fbfeSJeff Kirsher 	return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_FRS);
194baf0fbfeSJeff Kirsher }
195baf0fbfeSJeff Kirsher 
196baf0fbfeSJeff Kirsher static bool ftmac100_rxdes_last_segment(struct ftmac100_rxdes *rxdes)
197baf0fbfeSJeff Kirsher {
198baf0fbfeSJeff Kirsher 	return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_LRS);
199baf0fbfeSJeff Kirsher }
200baf0fbfeSJeff Kirsher 
201baf0fbfeSJeff Kirsher static bool ftmac100_rxdes_owned_by_dma(struct ftmac100_rxdes *rxdes)
202baf0fbfeSJeff Kirsher {
203baf0fbfeSJeff Kirsher 	return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_RXDMA_OWN);
204baf0fbfeSJeff Kirsher }
205baf0fbfeSJeff Kirsher 
206baf0fbfeSJeff Kirsher static void ftmac100_rxdes_set_dma_own(struct ftmac100_rxdes *rxdes)
207baf0fbfeSJeff Kirsher {
208baf0fbfeSJeff Kirsher 	/* clear status bits */
209baf0fbfeSJeff Kirsher 	rxdes->rxdes0 = cpu_to_le32(FTMAC100_RXDES0_RXDMA_OWN);
210baf0fbfeSJeff Kirsher }
211baf0fbfeSJeff Kirsher 
212baf0fbfeSJeff Kirsher static bool ftmac100_rxdes_rx_error(struct ftmac100_rxdes *rxdes)
213baf0fbfeSJeff Kirsher {
214baf0fbfeSJeff Kirsher 	return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_RX_ERR);
215baf0fbfeSJeff Kirsher }
216baf0fbfeSJeff Kirsher 
217baf0fbfeSJeff Kirsher static bool ftmac100_rxdes_crc_error(struct ftmac100_rxdes *rxdes)
218baf0fbfeSJeff Kirsher {
219baf0fbfeSJeff Kirsher 	return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_CRC_ERR);
220baf0fbfeSJeff Kirsher }
221baf0fbfeSJeff Kirsher 
222baf0fbfeSJeff Kirsher static bool ftmac100_rxdes_runt(struct ftmac100_rxdes *rxdes)
223baf0fbfeSJeff Kirsher {
224baf0fbfeSJeff Kirsher 	return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_RUNT);
225baf0fbfeSJeff Kirsher }
226baf0fbfeSJeff Kirsher 
227baf0fbfeSJeff Kirsher static bool ftmac100_rxdes_odd_nibble(struct ftmac100_rxdes *rxdes)
228baf0fbfeSJeff Kirsher {
229baf0fbfeSJeff Kirsher 	return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_RX_ODD_NB);
230baf0fbfeSJeff Kirsher }
231baf0fbfeSJeff Kirsher 
232baf0fbfeSJeff Kirsher static unsigned int ftmac100_rxdes_frame_length(struct ftmac100_rxdes *rxdes)
233baf0fbfeSJeff Kirsher {
234baf0fbfeSJeff Kirsher 	return le32_to_cpu(rxdes->rxdes0) & FTMAC100_RXDES0_RFL;
235baf0fbfeSJeff Kirsher }
236baf0fbfeSJeff Kirsher 
237baf0fbfeSJeff Kirsher static bool ftmac100_rxdes_multicast(struct ftmac100_rxdes *rxdes)
238baf0fbfeSJeff Kirsher {
239baf0fbfeSJeff Kirsher 	return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_MULTICAST);
240baf0fbfeSJeff Kirsher }
241baf0fbfeSJeff Kirsher 
242baf0fbfeSJeff Kirsher static void ftmac100_rxdes_set_buffer_size(struct ftmac100_rxdes *rxdes,
243baf0fbfeSJeff Kirsher 					   unsigned int size)
244baf0fbfeSJeff Kirsher {
245baf0fbfeSJeff Kirsher 	rxdes->rxdes1 &= cpu_to_le32(FTMAC100_RXDES1_EDORR);
246baf0fbfeSJeff Kirsher 	rxdes->rxdes1 |= cpu_to_le32(FTMAC100_RXDES1_RXBUF_SIZE(size));
247baf0fbfeSJeff Kirsher }
248baf0fbfeSJeff Kirsher 
249baf0fbfeSJeff Kirsher static void ftmac100_rxdes_set_end_of_ring(struct ftmac100_rxdes *rxdes)
250baf0fbfeSJeff Kirsher {
251baf0fbfeSJeff Kirsher 	rxdes->rxdes1 |= cpu_to_le32(FTMAC100_RXDES1_EDORR);
252baf0fbfeSJeff Kirsher }
253baf0fbfeSJeff Kirsher 
254baf0fbfeSJeff Kirsher static void ftmac100_rxdes_set_dma_addr(struct ftmac100_rxdes *rxdes,
255baf0fbfeSJeff Kirsher 					dma_addr_t addr)
256baf0fbfeSJeff Kirsher {
257baf0fbfeSJeff Kirsher 	rxdes->rxdes2 = cpu_to_le32(addr);
258baf0fbfeSJeff Kirsher }
259baf0fbfeSJeff Kirsher 
260baf0fbfeSJeff Kirsher static dma_addr_t ftmac100_rxdes_get_dma_addr(struct ftmac100_rxdes *rxdes)
261baf0fbfeSJeff Kirsher {
262baf0fbfeSJeff Kirsher 	return le32_to_cpu(rxdes->rxdes2);
263baf0fbfeSJeff Kirsher }
264baf0fbfeSJeff Kirsher 
265baf0fbfeSJeff Kirsher /*
266baf0fbfeSJeff Kirsher  * rxdes3 is not used by hardware. We use it to keep track of page.
267baf0fbfeSJeff Kirsher  * Since hardware does not touch it, we can skip cpu_to_le32()/le32_to_cpu().
268baf0fbfeSJeff Kirsher  */
269baf0fbfeSJeff Kirsher static void ftmac100_rxdes_set_page(struct ftmac100_rxdes *rxdes, struct page *page)
270baf0fbfeSJeff Kirsher {
271baf0fbfeSJeff Kirsher 	rxdes->rxdes3 = (unsigned int)page;
272baf0fbfeSJeff Kirsher }
273baf0fbfeSJeff Kirsher 
274baf0fbfeSJeff Kirsher static struct page *ftmac100_rxdes_get_page(struct ftmac100_rxdes *rxdes)
275baf0fbfeSJeff Kirsher {
276baf0fbfeSJeff Kirsher 	return (struct page *)rxdes->rxdes3;
277baf0fbfeSJeff Kirsher }
278baf0fbfeSJeff Kirsher 
279baf0fbfeSJeff Kirsher /******************************************************************************
280baf0fbfeSJeff Kirsher  * internal functions (receive)
281baf0fbfeSJeff Kirsher  *****************************************************************************/
282baf0fbfeSJeff Kirsher static int ftmac100_next_rx_pointer(int pointer)
283baf0fbfeSJeff Kirsher {
284baf0fbfeSJeff Kirsher 	return (pointer + 1) & (RX_QUEUE_ENTRIES - 1);
285baf0fbfeSJeff Kirsher }
286baf0fbfeSJeff Kirsher 
287baf0fbfeSJeff Kirsher static void ftmac100_rx_pointer_advance(struct ftmac100 *priv)
288baf0fbfeSJeff Kirsher {
289baf0fbfeSJeff Kirsher 	priv->rx_pointer = ftmac100_next_rx_pointer(priv->rx_pointer);
290baf0fbfeSJeff Kirsher }
291baf0fbfeSJeff Kirsher 
292baf0fbfeSJeff Kirsher static struct ftmac100_rxdes *ftmac100_current_rxdes(struct ftmac100 *priv)
293baf0fbfeSJeff Kirsher {
294baf0fbfeSJeff Kirsher 	return &priv->descs->rxdes[priv->rx_pointer];
295baf0fbfeSJeff Kirsher }
296baf0fbfeSJeff Kirsher 
297baf0fbfeSJeff Kirsher static struct ftmac100_rxdes *
298baf0fbfeSJeff Kirsher ftmac100_rx_locate_first_segment(struct ftmac100 *priv)
299baf0fbfeSJeff Kirsher {
300baf0fbfeSJeff Kirsher 	struct ftmac100_rxdes *rxdes = ftmac100_current_rxdes(priv);
301baf0fbfeSJeff Kirsher 
302baf0fbfeSJeff Kirsher 	while (!ftmac100_rxdes_owned_by_dma(rxdes)) {
303baf0fbfeSJeff Kirsher 		if (ftmac100_rxdes_first_segment(rxdes))
304baf0fbfeSJeff Kirsher 			return rxdes;
305baf0fbfeSJeff Kirsher 
306baf0fbfeSJeff Kirsher 		ftmac100_rxdes_set_dma_own(rxdes);
307baf0fbfeSJeff Kirsher 		ftmac100_rx_pointer_advance(priv);
308baf0fbfeSJeff Kirsher 		rxdes = ftmac100_current_rxdes(priv);
309baf0fbfeSJeff Kirsher 	}
310baf0fbfeSJeff Kirsher 
311baf0fbfeSJeff Kirsher 	return NULL;
312baf0fbfeSJeff Kirsher }
313baf0fbfeSJeff Kirsher 
314baf0fbfeSJeff Kirsher static bool ftmac100_rx_packet_error(struct ftmac100 *priv,
315baf0fbfeSJeff Kirsher 				     struct ftmac100_rxdes *rxdes)
316baf0fbfeSJeff Kirsher {
317baf0fbfeSJeff Kirsher 	struct net_device *netdev = priv->netdev;
318baf0fbfeSJeff Kirsher 	bool error = false;
319baf0fbfeSJeff Kirsher 
320baf0fbfeSJeff Kirsher 	if (unlikely(ftmac100_rxdes_rx_error(rxdes))) {
321baf0fbfeSJeff Kirsher 		if (net_ratelimit())
322baf0fbfeSJeff Kirsher 			netdev_info(netdev, "rx err\n");
323baf0fbfeSJeff Kirsher 
324baf0fbfeSJeff Kirsher 		netdev->stats.rx_errors++;
325baf0fbfeSJeff Kirsher 		error = true;
326baf0fbfeSJeff Kirsher 	}
327baf0fbfeSJeff Kirsher 
328baf0fbfeSJeff Kirsher 	if (unlikely(ftmac100_rxdes_crc_error(rxdes))) {
329baf0fbfeSJeff Kirsher 		if (net_ratelimit())
330baf0fbfeSJeff Kirsher 			netdev_info(netdev, "rx crc err\n");
331baf0fbfeSJeff Kirsher 
332baf0fbfeSJeff Kirsher 		netdev->stats.rx_crc_errors++;
333baf0fbfeSJeff Kirsher 		error = true;
334baf0fbfeSJeff Kirsher 	}
335baf0fbfeSJeff Kirsher 
33655f6f3dbSVladimir Oltean 	if (unlikely(ftmac100_rxdes_runt(rxdes))) {
337baf0fbfeSJeff Kirsher 		if (net_ratelimit())
338baf0fbfeSJeff Kirsher 			netdev_info(netdev, "rx runt\n");
339baf0fbfeSJeff Kirsher 
340baf0fbfeSJeff Kirsher 		netdev->stats.rx_length_errors++;
341baf0fbfeSJeff Kirsher 		error = true;
342baf0fbfeSJeff Kirsher 	} else if (unlikely(ftmac100_rxdes_odd_nibble(rxdes))) {
343baf0fbfeSJeff Kirsher 		if (net_ratelimit())
344baf0fbfeSJeff Kirsher 			netdev_info(netdev, "rx odd nibble\n");
345baf0fbfeSJeff Kirsher 
346baf0fbfeSJeff Kirsher 		netdev->stats.rx_length_errors++;
347baf0fbfeSJeff Kirsher 		error = true;
348baf0fbfeSJeff Kirsher 	}
34955f6f3dbSVladimir Oltean 	/*
35055f6f3dbSVladimir Oltean 	 * FTMAC100_RXDES0_FTL is not an error, it just indicates that the
35155f6f3dbSVladimir Oltean 	 * frame is longer than 1518 octets. Receiving these is possible when
35255f6f3dbSVladimir Oltean 	 * we told the hardware not to drop them, via FTMAC100_MACCR_RX_FTL.
35355f6f3dbSVladimir Oltean 	 */
354baf0fbfeSJeff Kirsher 
355baf0fbfeSJeff Kirsher 	return error;
356baf0fbfeSJeff Kirsher }
357baf0fbfeSJeff Kirsher 
358baf0fbfeSJeff Kirsher static void ftmac100_rx_drop_packet(struct ftmac100 *priv)
359baf0fbfeSJeff Kirsher {
360baf0fbfeSJeff Kirsher 	struct net_device *netdev = priv->netdev;
361baf0fbfeSJeff Kirsher 	struct ftmac100_rxdes *rxdes = ftmac100_current_rxdes(priv);
362baf0fbfeSJeff Kirsher 	bool done = false;
363baf0fbfeSJeff Kirsher 
364baf0fbfeSJeff Kirsher 	if (net_ratelimit())
365baf0fbfeSJeff Kirsher 		netdev_dbg(netdev, "drop packet %p\n", rxdes);
366baf0fbfeSJeff Kirsher 
367baf0fbfeSJeff Kirsher 	do {
368baf0fbfeSJeff Kirsher 		if (ftmac100_rxdes_last_segment(rxdes))
369baf0fbfeSJeff Kirsher 			done = true;
370baf0fbfeSJeff Kirsher 
371baf0fbfeSJeff Kirsher 		ftmac100_rxdes_set_dma_own(rxdes);
372baf0fbfeSJeff Kirsher 		ftmac100_rx_pointer_advance(priv);
373baf0fbfeSJeff Kirsher 		rxdes = ftmac100_current_rxdes(priv);
374baf0fbfeSJeff Kirsher 	} while (!done && !ftmac100_rxdes_owned_by_dma(rxdes));
375baf0fbfeSJeff Kirsher 
376baf0fbfeSJeff Kirsher 	netdev->stats.rx_dropped++;
377baf0fbfeSJeff Kirsher }
378baf0fbfeSJeff Kirsher 
379baf0fbfeSJeff Kirsher static bool ftmac100_rx_packet(struct ftmac100 *priv, int *processed)
380baf0fbfeSJeff Kirsher {
381baf0fbfeSJeff Kirsher 	struct net_device *netdev = priv->netdev;
382baf0fbfeSJeff Kirsher 	struct ftmac100_rxdes *rxdes;
383baf0fbfeSJeff Kirsher 	struct sk_buff *skb;
384baf0fbfeSJeff Kirsher 	struct page *page;
385baf0fbfeSJeff Kirsher 	dma_addr_t map;
386baf0fbfeSJeff Kirsher 	int length;
3875bca178eSGustavo A. R. Silva 	bool ret;
388baf0fbfeSJeff Kirsher 
389baf0fbfeSJeff Kirsher 	rxdes = ftmac100_rx_locate_first_segment(priv);
390baf0fbfeSJeff Kirsher 	if (!rxdes)
391baf0fbfeSJeff Kirsher 		return false;
392baf0fbfeSJeff Kirsher 
393baf0fbfeSJeff Kirsher 	if (unlikely(ftmac100_rx_packet_error(priv, rxdes))) {
394baf0fbfeSJeff Kirsher 		ftmac100_rx_drop_packet(priv);
395baf0fbfeSJeff Kirsher 		return true;
396baf0fbfeSJeff Kirsher 	}
397baf0fbfeSJeff Kirsher 
39855f6f3dbSVladimir Oltean 	/* We don't support multi-segment packets for now, so drop them. */
3995bca178eSGustavo A. R. Silva 	ret = ftmac100_rxdes_last_segment(rxdes);
40055f6f3dbSVladimir Oltean 	if (unlikely(!ret)) {
40155f6f3dbSVladimir Oltean 		netdev->stats.rx_length_errors++;
40255f6f3dbSVladimir Oltean 		ftmac100_rx_drop_packet(priv);
40355f6f3dbSVladimir Oltean 		return true;
40455f6f3dbSVladimir Oltean 	}
405baf0fbfeSJeff Kirsher 
406baf0fbfeSJeff Kirsher 	/* start processing */
407baf0fbfeSJeff Kirsher 	skb = netdev_alloc_skb_ip_align(netdev, 128);
408baf0fbfeSJeff Kirsher 	if (unlikely(!skb)) {
409baf0fbfeSJeff Kirsher 		if (net_ratelimit())
410baf0fbfeSJeff Kirsher 			netdev_err(netdev, "rx skb alloc failed\n");
411baf0fbfeSJeff Kirsher 
412baf0fbfeSJeff Kirsher 		ftmac100_rx_drop_packet(priv);
413baf0fbfeSJeff Kirsher 		return true;
414baf0fbfeSJeff Kirsher 	}
415baf0fbfeSJeff Kirsher 
416baf0fbfeSJeff Kirsher 	if (unlikely(ftmac100_rxdes_multicast(rxdes)))
417baf0fbfeSJeff Kirsher 		netdev->stats.multicast++;
418baf0fbfeSJeff Kirsher 
419baf0fbfeSJeff Kirsher 	map = ftmac100_rxdes_get_dma_addr(rxdes);
420baf0fbfeSJeff Kirsher 	dma_unmap_page(priv->dev, map, RX_BUF_SIZE, DMA_FROM_DEVICE);
421baf0fbfeSJeff Kirsher 
422baf0fbfeSJeff Kirsher 	length = ftmac100_rxdes_frame_length(rxdes);
423baf0fbfeSJeff Kirsher 	page = ftmac100_rxdes_get_page(rxdes);
424baf0fbfeSJeff Kirsher 	skb_fill_page_desc(skb, 0, page, 0, length);
425baf0fbfeSJeff Kirsher 	skb->len += length;
426baf0fbfeSJeff Kirsher 	skb->data_len += length;
42796cd8951SEric Dumazet 
4286ecd09ddSEric Dumazet 	if (length > 128) {
42996cd8951SEric Dumazet 		skb->truesize += PAGE_SIZE;
4306ecd09ddSEric Dumazet 		/* We pull the minimum amount into linear part */
4316ecd09ddSEric Dumazet 		__pskb_pull_tail(skb, ETH_HLEN);
4326ecd09ddSEric Dumazet 	} else {
4336ecd09ddSEric Dumazet 		/* Small frames are copied into linear part to free one page */
4346ecd09ddSEric Dumazet 		__pskb_pull_tail(skb, length);
4356ecd09ddSEric Dumazet 	}
436baf0fbfeSJeff Kirsher 	ftmac100_alloc_rx_page(priv, rxdes, GFP_ATOMIC);
437baf0fbfeSJeff Kirsher 
438baf0fbfeSJeff Kirsher 	ftmac100_rx_pointer_advance(priv);
439baf0fbfeSJeff Kirsher 
440baf0fbfeSJeff Kirsher 	skb->protocol = eth_type_trans(skb, netdev);
441baf0fbfeSJeff Kirsher 
442baf0fbfeSJeff Kirsher 	netdev->stats.rx_packets++;
443baf0fbfeSJeff Kirsher 	netdev->stats.rx_bytes += skb->len;
444baf0fbfeSJeff Kirsher 
445baf0fbfeSJeff Kirsher 	/* push packet to protocol stack */
446baf0fbfeSJeff Kirsher 	netif_receive_skb(skb);
447baf0fbfeSJeff Kirsher 
448baf0fbfeSJeff Kirsher 	(*processed)++;
449baf0fbfeSJeff Kirsher 	return true;
450baf0fbfeSJeff Kirsher }
451baf0fbfeSJeff Kirsher 
452baf0fbfeSJeff Kirsher /******************************************************************************
453baf0fbfeSJeff Kirsher  * internal functions (transmit descriptor)
454baf0fbfeSJeff Kirsher  *****************************************************************************/
455baf0fbfeSJeff Kirsher static void ftmac100_txdes_reset(struct ftmac100_txdes *txdes)
456baf0fbfeSJeff Kirsher {
457baf0fbfeSJeff Kirsher 	/* clear all except end of ring bit */
458baf0fbfeSJeff Kirsher 	txdes->txdes0 = 0;
459baf0fbfeSJeff Kirsher 	txdes->txdes1 &= cpu_to_le32(FTMAC100_TXDES1_EDOTR);
460baf0fbfeSJeff Kirsher 	txdes->txdes2 = 0;
461baf0fbfeSJeff Kirsher 	txdes->txdes3 = 0;
462baf0fbfeSJeff Kirsher }
463baf0fbfeSJeff Kirsher 
464baf0fbfeSJeff Kirsher static bool ftmac100_txdes_owned_by_dma(struct ftmac100_txdes *txdes)
465baf0fbfeSJeff Kirsher {
466baf0fbfeSJeff Kirsher 	return txdes->txdes0 & cpu_to_le32(FTMAC100_TXDES0_TXDMA_OWN);
467baf0fbfeSJeff Kirsher }
468baf0fbfeSJeff Kirsher 
469baf0fbfeSJeff Kirsher static void ftmac100_txdes_set_dma_own(struct ftmac100_txdes *txdes)
470baf0fbfeSJeff Kirsher {
471baf0fbfeSJeff Kirsher 	/*
472baf0fbfeSJeff Kirsher 	 * Make sure dma own bit will not be set before any other
473baf0fbfeSJeff Kirsher 	 * descriptor fields.
474baf0fbfeSJeff Kirsher 	 */
475baf0fbfeSJeff Kirsher 	wmb();
476baf0fbfeSJeff Kirsher 	txdes->txdes0 |= cpu_to_le32(FTMAC100_TXDES0_TXDMA_OWN);
477baf0fbfeSJeff Kirsher }
478baf0fbfeSJeff Kirsher 
479baf0fbfeSJeff Kirsher static bool ftmac100_txdes_excessive_collision(struct ftmac100_txdes *txdes)
480baf0fbfeSJeff Kirsher {
481baf0fbfeSJeff Kirsher 	return txdes->txdes0 & cpu_to_le32(FTMAC100_TXDES0_TXPKT_EXSCOL);
482baf0fbfeSJeff Kirsher }
483baf0fbfeSJeff Kirsher 
484baf0fbfeSJeff Kirsher static bool ftmac100_txdes_late_collision(struct ftmac100_txdes *txdes)
485baf0fbfeSJeff Kirsher {
486baf0fbfeSJeff Kirsher 	return txdes->txdes0 & cpu_to_le32(FTMAC100_TXDES0_TXPKT_LATECOL);
487baf0fbfeSJeff Kirsher }
488baf0fbfeSJeff Kirsher 
489baf0fbfeSJeff Kirsher static void ftmac100_txdes_set_end_of_ring(struct ftmac100_txdes *txdes)
490baf0fbfeSJeff Kirsher {
491baf0fbfeSJeff Kirsher 	txdes->txdes1 |= cpu_to_le32(FTMAC100_TXDES1_EDOTR);
492baf0fbfeSJeff Kirsher }
493baf0fbfeSJeff Kirsher 
494baf0fbfeSJeff Kirsher static void ftmac100_txdes_set_first_segment(struct ftmac100_txdes *txdes)
495baf0fbfeSJeff Kirsher {
496baf0fbfeSJeff Kirsher 	txdes->txdes1 |= cpu_to_le32(FTMAC100_TXDES1_FTS);
497baf0fbfeSJeff Kirsher }
498baf0fbfeSJeff Kirsher 
499baf0fbfeSJeff Kirsher static void ftmac100_txdes_set_last_segment(struct ftmac100_txdes *txdes)
500baf0fbfeSJeff Kirsher {
501baf0fbfeSJeff Kirsher 	txdes->txdes1 |= cpu_to_le32(FTMAC100_TXDES1_LTS);
502baf0fbfeSJeff Kirsher }
503baf0fbfeSJeff Kirsher 
504baf0fbfeSJeff Kirsher static void ftmac100_txdes_set_txint(struct ftmac100_txdes *txdes)
505baf0fbfeSJeff Kirsher {
506baf0fbfeSJeff Kirsher 	txdes->txdes1 |= cpu_to_le32(FTMAC100_TXDES1_TXIC);
507baf0fbfeSJeff Kirsher }
508baf0fbfeSJeff Kirsher 
509baf0fbfeSJeff Kirsher static void ftmac100_txdes_set_buffer_size(struct ftmac100_txdes *txdes,
510baf0fbfeSJeff Kirsher 					   unsigned int len)
511baf0fbfeSJeff Kirsher {
512baf0fbfeSJeff Kirsher 	txdes->txdes1 |= cpu_to_le32(FTMAC100_TXDES1_TXBUF_SIZE(len));
513baf0fbfeSJeff Kirsher }
514baf0fbfeSJeff Kirsher 
515baf0fbfeSJeff Kirsher static void ftmac100_txdes_set_dma_addr(struct ftmac100_txdes *txdes,
516baf0fbfeSJeff Kirsher 					dma_addr_t addr)
517baf0fbfeSJeff Kirsher {
518baf0fbfeSJeff Kirsher 	txdes->txdes2 = cpu_to_le32(addr);
519baf0fbfeSJeff Kirsher }
520baf0fbfeSJeff Kirsher 
521baf0fbfeSJeff Kirsher static dma_addr_t ftmac100_txdes_get_dma_addr(struct ftmac100_txdes *txdes)
522baf0fbfeSJeff Kirsher {
523baf0fbfeSJeff Kirsher 	return le32_to_cpu(txdes->txdes2);
524baf0fbfeSJeff Kirsher }
525baf0fbfeSJeff Kirsher 
526baf0fbfeSJeff Kirsher /*
527baf0fbfeSJeff Kirsher  * txdes3 is not used by hardware. We use it to keep track of socket buffer.
528baf0fbfeSJeff Kirsher  * Since hardware does not touch it, we can skip cpu_to_le32()/le32_to_cpu().
529baf0fbfeSJeff Kirsher  */
530baf0fbfeSJeff Kirsher static void ftmac100_txdes_set_skb(struct ftmac100_txdes *txdes, struct sk_buff *skb)
531baf0fbfeSJeff Kirsher {
532baf0fbfeSJeff Kirsher 	txdes->txdes3 = (unsigned int)skb;
533baf0fbfeSJeff Kirsher }
534baf0fbfeSJeff Kirsher 
535baf0fbfeSJeff Kirsher static struct sk_buff *ftmac100_txdes_get_skb(struct ftmac100_txdes *txdes)
536baf0fbfeSJeff Kirsher {
537baf0fbfeSJeff Kirsher 	return (struct sk_buff *)txdes->txdes3;
538baf0fbfeSJeff Kirsher }
539baf0fbfeSJeff Kirsher 
540baf0fbfeSJeff Kirsher /******************************************************************************
541baf0fbfeSJeff Kirsher  * internal functions (transmit)
542baf0fbfeSJeff Kirsher  *****************************************************************************/
543baf0fbfeSJeff Kirsher static int ftmac100_next_tx_pointer(int pointer)
544baf0fbfeSJeff Kirsher {
545baf0fbfeSJeff Kirsher 	return (pointer + 1) & (TX_QUEUE_ENTRIES - 1);
546baf0fbfeSJeff Kirsher }
547baf0fbfeSJeff Kirsher 
548baf0fbfeSJeff Kirsher static void ftmac100_tx_pointer_advance(struct ftmac100 *priv)
549baf0fbfeSJeff Kirsher {
550baf0fbfeSJeff Kirsher 	priv->tx_pointer = ftmac100_next_tx_pointer(priv->tx_pointer);
551baf0fbfeSJeff Kirsher }
552baf0fbfeSJeff Kirsher 
553baf0fbfeSJeff Kirsher static void ftmac100_tx_clean_pointer_advance(struct ftmac100 *priv)
554baf0fbfeSJeff Kirsher {
555baf0fbfeSJeff Kirsher 	priv->tx_clean_pointer = ftmac100_next_tx_pointer(priv->tx_clean_pointer);
556baf0fbfeSJeff Kirsher }
557baf0fbfeSJeff Kirsher 
558baf0fbfeSJeff Kirsher static struct ftmac100_txdes *ftmac100_current_txdes(struct ftmac100 *priv)
559baf0fbfeSJeff Kirsher {
560baf0fbfeSJeff Kirsher 	return &priv->descs->txdes[priv->tx_pointer];
561baf0fbfeSJeff Kirsher }
562baf0fbfeSJeff Kirsher 
563baf0fbfeSJeff Kirsher static struct ftmac100_txdes *ftmac100_current_clean_txdes(struct ftmac100 *priv)
564baf0fbfeSJeff Kirsher {
565baf0fbfeSJeff Kirsher 	return &priv->descs->txdes[priv->tx_clean_pointer];
566baf0fbfeSJeff Kirsher }
567baf0fbfeSJeff Kirsher 
568baf0fbfeSJeff Kirsher static bool ftmac100_tx_complete_packet(struct ftmac100 *priv)
569baf0fbfeSJeff Kirsher {
570baf0fbfeSJeff Kirsher 	struct net_device *netdev = priv->netdev;
571baf0fbfeSJeff Kirsher 	struct ftmac100_txdes *txdes;
572baf0fbfeSJeff Kirsher 	struct sk_buff *skb;
573baf0fbfeSJeff Kirsher 	dma_addr_t map;
574baf0fbfeSJeff Kirsher 
575baf0fbfeSJeff Kirsher 	if (priv->tx_pending == 0)
576baf0fbfeSJeff Kirsher 		return false;
577baf0fbfeSJeff Kirsher 
578baf0fbfeSJeff Kirsher 	txdes = ftmac100_current_clean_txdes(priv);
579baf0fbfeSJeff Kirsher 
580baf0fbfeSJeff Kirsher 	if (ftmac100_txdes_owned_by_dma(txdes))
581baf0fbfeSJeff Kirsher 		return false;
582baf0fbfeSJeff Kirsher 
583baf0fbfeSJeff Kirsher 	skb = ftmac100_txdes_get_skb(txdes);
584baf0fbfeSJeff Kirsher 	map = ftmac100_txdes_get_dma_addr(txdes);
585baf0fbfeSJeff Kirsher 
586baf0fbfeSJeff Kirsher 	if (unlikely(ftmac100_txdes_excessive_collision(txdes) ||
587baf0fbfeSJeff Kirsher 		     ftmac100_txdes_late_collision(txdes))) {
588baf0fbfeSJeff Kirsher 		/*
589baf0fbfeSJeff Kirsher 		 * packet transmitted to ethernet lost due to late collision
590baf0fbfeSJeff Kirsher 		 * or excessive collision
591baf0fbfeSJeff Kirsher 		 */
592baf0fbfeSJeff Kirsher 		netdev->stats.tx_aborted_errors++;
593baf0fbfeSJeff Kirsher 	} else {
594baf0fbfeSJeff Kirsher 		netdev->stats.tx_packets++;
595baf0fbfeSJeff Kirsher 		netdev->stats.tx_bytes += skb->len;
596baf0fbfeSJeff Kirsher 	}
597baf0fbfeSJeff Kirsher 
598baf0fbfeSJeff Kirsher 	dma_unmap_single(priv->dev, map, skb_headlen(skb), DMA_TO_DEVICE);
599baf0fbfeSJeff Kirsher 	dev_kfree_skb(skb);
600baf0fbfeSJeff Kirsher 
601baf0fbfeSJeff Kirsher 	ftmac100_txdes_reset(txdes);
602baf0fbfeSJeff Kirsher 
603baf0fbfeSJeff Kirsher 	ftmac100_tx_clean_pointer_advance(priv);
604baf0fbfeSJeff Kirsher 
605baf0fbfeSJeff Kirsher 	spin_lock(&priv->tx_lock);
606baf0fbfeSJeff Kirsher 	priv->tx_pending--;
607baf0fbfeSJeff Kirsher 	spin_unlock(&priv->tx_lock);
608baf0fbfeSJeff Kirsher 	netif_wake_queue(netdev);
609baf0fbfeSJeff Kirsher 
610baf0fbfeSJeff Kirsher 	return true;
611baf0fbfeSJeff Kirsher }
612baf0fbfeSJeff Kirsher 
613baf0fbfeSJeff Kirsher static void ftmac100_tx_complete(struct ftmac100 *priv)
614baf0fbfeSJeff Kirsher {
615baf0fbfeSJeff Kirsher 	while (ftmac100_tx_complete_packet(priv))
616baf0fbfeSJeff Kirsher 		;
617baf0fbfeSJeff Kirsher }
618baf0fbfeSJeff Kirsher 
6190a715156SYueHaibing static netdev_tx_t ftmac100_xmit(struct ftmac100 *priv, struct sk_buff *skb,
620baf0fbfeSJeff Kirsher 				 dma_addr_t map)
621baf0fbfeSJeff Kirsher {
622baf0fbfeSJeff Kirsher 	struct net_device *netdev = priv->netdev;
623baf0fbfeSJeff Kirsher 	struct ftmac100_txdes *txdes;
624baf0fbfeSJeff Kirsher 	unsigned int len = (skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len;
625baf0fbfeSJeff Kirsher 
626baf0fbfeSJeff Kirsher 	txdes = ftmac100_current_txdes(priv);
627baf0fbfeSJeff Kirsher 	ftmac100_tx_pointer_advance(priv);
628baf0fbfeSJeff Kirsher 
629baf0fbfeSJeff Kirsher 	/* setup TX descriptor */
630baf0fbfeSJeff Kirsher 	ftmac100_txdes_set_skb(txdes, skb);
631baf0fbfeSJeff Kirsher 	ftmac100_txdes_set_dma_addr(txdes, map);
632baf0fbfeSJeff Kirsher 
633baf0fbfeSJeff Kirsher 	ftmac100_txdes_set_first_segment(txdes);
634baf0fbfeSJeff Kirsher 	ftmac100_txdes_set_last_segment(txdes);
635baf0fbfeSJeff Kirsher 	ftmac100_txdes_set_txint(txdes);
636baf0fbfeSJeff Kirsher 	ftmac100_txdes_set_buffer_size(txdes, len);
637baf0fbfeSJeff Kirsher 
638baf0fbfeSJeff Kirsher 	spin_lock(&priv->tx_lock);
639baf0fbfeSJeff Kirsher 	priv->tx_pending++;
640baf0fbfeSJeff Kirsher 	if (priv->tx_pending == TX_QUEUE_ENTRIES)
641baf0fbfeSJeff Kirsher 		netif_stop_queue(netdev);
642baf0fbfeSJeff Kirsher 
643baf0fbfeSJeff Kirsher 	/* start transmit */
644baf0fbfeSJeff Kirsher 	ftmac100_txdes_set_dma_own(txdes);
645baf0fbfeSJeff Kirsher 	spin_unlock(&priv->tx_lock);
646baf0fbfeSJeff Kirsher 
647baf0fbfeSJeff Kirsher 	ftmac100_txdma_start_polling(priv);
648baf0fbfeSJeff Kirsher 	return NETDEV_TX_OK;
649baf0fbfeSJeff Kirsher }
650baf0fbfeSJeff Kirsher 
651baf0fbfeSJeff Kirsher /******************************************************************************
652baf0fbfeSJeff Kirsher  * internal functions (buffer)
653baf0fbfeSJeff Kirsher  *****************************************************************************/
654baf0fbfeSJeff Kirsher static int ftmac100_alloc_rx_page(struct ftmac100 *priv,
655baf0fbfeSJeff Kirsher 				  struct ftmac100_rxdes *rxdes, gfp_t gfp)
656baf0fbfeSJeff Kirsher {
657baf0fbfeSJeff Kirsher 	struct net_device *netdev = priv->netdev;
658baf0fbfeSJeff Kirsher 	struct page *page;
659baf0fbfeSJeff Kirsher 	dma_addr_t map;
660baf0fbfeSJeff Kirsher 
661baf0fbfeSJeff Kirsher 	page = alloc_page(gfp);
662baf0fbfeSJeff Kirsher 	if (!page) {
663baf0fbfeSJeff Kirsher 		if (net_ratelimit())
664baf0fbfeSJeff Kirsher 			netdev_err(netdev, "failed to allocate rx page\n");
665baf0fbfeSJeff Kirsher 		return -ENOMEM;
666baf0fbfeSJeff Kirsher 	}
667baf0fbfeSJeff Kirsher 
668baf0fbfeSJeff Kirsher 	map = dma_map_page(priv->dev, page, 0, RX_BUF_SIZE, DMA_FROM_DEVICE);
669baf0fbfeSJeff Kirsher 	if (unlikely(dma_mapping_error(priv->dev, map))) {
670baf0fbfeSJeff Kirsher 		if (net_ratelimit())
671baf0fbfeSJeff Kirsher 			netdev_err(netdev, "failed to map rx page\n");
672baf0fbfeSJeff Kirsher 		__free_page(page);
673baf0fbfeSJeff Kirsher 		return -ENOMEM;
674baf0fbfeSJeff Kirsher 	}
675baf0fbfeSJeff Kirsher 
676baf0fbfeSJeff Kirsher 	ftmac100_rxdes_set_page(rxdes, page);
677baf0fbfeSJeff Kirsher 	ftmac100_rxdes_set_dma_addr(rxdes, map);
678baf0fbfeSJeff Kirsher 	ftmac100_rxdes_set_buffer_size(rxdes, RX_BUF_SIZE);
679baf0fbfeSJeff Kirsher 	ftmac100_rxdes_set_dma_own(rxdes);
680baf0fbfeSJeff Kirsher 	return 0;
681baf0fbfeSJeff Kirsher }
682baf0fbfeSJeff Kirsher 
683baf0fbfeSJeff Kirsher static void ftmac100_free_buffers(struct ftmac100 *priv)
684baf0fbfeSJeff Kirsher {
685baf0fbfeSJeff Kirsher 	int i;
686baf0fbfeSJeff Kirsher 
687baf0fbfeSJeff Kirsher 	for (i = 0; i < RX_QUEUE_ENTRIES; i++) {
688baf0fbfeSJeff Kirsher 		struct ftmac100_rxdes *rxdes = &priv->descs->rxdes[i];
689baf0fbfeSJeff Kirsher 		struct page *page = ftmac100_rxdes_get_page(rxdes);
690baf0fbfeSJeff Kirsher 		dma_addr_t map = ftmac100_rxdes_get_dma_addr(rxdes);
691baf0fbfeSJeff Kirsher 
692baf0fbfeSJeff Kirsher 		if (!page)
693baf0fbfeSJeff Kirsher 			continue;
694baf0fbfeSJeff Kirsher 
695baf0fbfeSJeff Kirsher 		dma_unmap_page(priv->dev, map, RX_BUF_SIZE, DMA_FROM_DEVICE);
696baf0fbfeSJeff Kirsher 		__free_page(page);
697baf0fbfeSJeff Kirsher 	}
698baf0fbfeSJeff Kirsher 
699baf0fbfeSJeff Kirsher 	for (i = 0; i < TX_QUEUE_ENTRIES; i++) {
700baf0fbfeSJeff Kirsher 		struct ftmac100_txdes *txdes = &priv->descs->txdes[i];
701baf0fbfeSJeff Kirsher 		struct sk_buff *skb = ftmac100_txdes_get_skb(txdes);
702baf0fbfeSJeff Kirsher 		dma_addr_t map = ftmac100_txdes_get_dma_addr(txdes);
703baf0fbfeSJeff Kirsher 
704baf0fbfeSJeff Kirsher 		if (!skb)
705baf0fbfeSJeff Kirsher 			continue;
706baf0fbfeSJeff Kirsher 
707baf0fbfeSJeff Kirsher 		dma_unmap_single(priv->dev, map, skb_headlen(skb), DMA_TO_DEVICE);
708baf0fbfeSJeff Kirsher 		dev_kfree_skb(skb);
709baf0fbfeSJeff Kirsher 	}
710baf0fbfeSJeff Kirsher 
711baf0fbfeSJeff Kirsher 	dma_free_coherent(priv->dev, sizeof(struct ftmac100_descs),
712baf0fbfeSJeff Kirsher 			  priv->descs, priv->descs_dma_addr);
713baf0fbfeSJeff Kirsher }
714baf0fbfeSJeff Kirsher 
715baf0fbfeSJeff Kirsher static int ftmac100_alloc_buffers(struct ftmac100 *priv)
716baf0fbfeSJeff Kirsher {
717baf0fbfeSJeff Kirsher 	int i;
718baf0fbfeSJeff Kirsher 
719750afb08SLuis Chamberlain 	priv->descs = dma_alloc_coherent(priv->dev,
7201f9061d2SJoe Perches 					 sizeof(struct ftmac100_descs),
721750afb08SLuis Chamberlain 					 &priv->descs_dma_addr, GFP_KERNEL);
722baf0fbfeSJeff Kirsher 	if (!priv->descs)
723baf0fbfeSJeff Kirsher 		return -ENOMEM;
724baf0fbfeSJeff Kirsher 
725baf0fbfeSJeff Kirsher 	/* initialize RX ring */
726baf0fbfeSJeff Kirsher 	ftmac100_rxdes_set_end_of_ring(&priv->descs->rxdes[RX_QUEUE_ENTRIES - 1]);
727baf0fbfeSJeff Kirsher 
728baf0fbfeSJeff Kirsher 	for (i = 0; i < RX_QUEUE_ENTRIES; i++) {
729baf0fbfeSJeff Kirsher 		struct ftmac100_rxdes *rxdes = &priv->descs->rxdes[i];
730baf0fbfeSJeff Kirsher 
731baf0fbfeSJeff Kirsher 		if (ftmac100_alloc_rx_page(priv, rxdes, GFP_KERNEL))
732baf0fbfeSJeff Kirsher 			goto err;
733baf0fbfeSJeff Kirsher 	}
734baf0fbfeSJeff Kirsher 
735baf0fbfeSJeff Kirsher 	/* initialize TX ring */
736baf0fbfeSJeff Kirsher 	ftmac100_txdes_set_end_of_ring(&priv->descs->txdes[TX_QUEUE_ENTRIES - 1]);
737baf0fbfeSJeff Kirsher 	return 0;
738baf0fbfeSJeff Kirsher 
739baf0fbfeSJeff Kirsher err:
740baf0fbfeSJeff Kirsher 	ftmac100_free_buffers(priv);
741baf0fbfeSJeff Kirsher 	return -ENOMEM;
742baf0fbfeSJeff Kirsher }
743baf0fbfeSJeff Kirsher 
744baf0fbfeSJeff Kirsher /******************************************************************************
745baf0fbfeSJeff Kirsher  * struct mii_if_info functions
746baf0fbfeSJeff Kirsher  *****************************************************************************/
747baf0fbfeSJeff Kirsher static int ftmac100_mdio_read(struct net_device *netdev, int phy_id, int reg)
748baf0fbfeSJeff Kirsher {
749baf0fbfeSJeff Kirsher 	struct ftmac100 *priv = netdev_priv(netdev);
750baf0fbfeSJeff Kirsher 	unsigned int phycr;
751baf0fbfeSJeff Kirsher 	int i;
752baf0fbfeSJeff Kirsher 
753baf0fbfeSJeff Kirsher 	phycr = FTMAC100_PHYCR_PHYAD(phy_id) |
754baf0fbfeSJeff Kirsher 		FTMAC100_PHYCR_REGAD(reg) |
755baf0fbfeSJeff Kirsher 		FTMAC100_PHYCR_MIIRD;
756baf0fbfeSJeff Kirsher 
757baf0fbfeSJeff Kirsher 	iowrite32(phycr, priv->base + FTMAC100_OFFSET_PHYCR);
758baf0fbfeSJeff Kirsher 
759baf0fbfeSJeff Kirsher 	for (i = 0; i < 10; i++) {
760baf0fbfeSJeff Kirsher 		phycr = ioread32(priv->base + FTMAC100_OFFSET_PHYCR);
761baf0fbfeSJeff Kirsher 
762baf0fbfeSJeff Kirsher 		if ((phycr & FTMAC100_PHYCR_MIIRD) == 0)
763baf0fbfeSJeff Kirsher 			return phycr & FTMAC100_PHYCR_MIIRDATA;
764baf0fbfeSJeff Kirsher 
765baf0fbfeSJeff Kirsher 		udelay(100);
766baf0fbfeSJeff Kirsher 	}
767baf0fbfeSJeff Kirsher 
768baf0fbfeSJeff Kirsher 	netdev_err(netdev, "mdio read timed out\n");
769baf0fbfeSJeff Kirsher 	return 0;
770baf0fbfeSJeff Kirsher }
771baf0fbfeSJeff Kirsher 
772baf0fbfeSJeff Kirsher static void ftmac100_mdio_write(struct net_device *netdev, int phy_id, int reg,
773baf0fbfeSJeff Kirsher 				int data)
774baf0fbfeSJeff Kirsher {
775baf0fbfeSJeff Kirsher 	struct ftmac100 *priv = netdev_priv(netdev);
776baf0fbfeSJeff Kirsher 	unsigned int phycr;
777baf0fbfeSJeff Kirsher 	int i;
778baf0fbfeSJeff Kirsher 
779baf0fbfeSJeff Kirsher 	phycr = FTMAC100_PHYCR_PHYAD(phy_id) |
780baf0fbfeSJeff Kirsher 		FTMAC100_PHYCR_REGAD(reg) |
781baf0fbfeSJeff Kirsher 		FTMAC100_PHYCR_MIIWR;
782baf0fbfeSJeff Kirsher 
783baf0fbfeSJeff Kirsher 	data = FTMAC100_PHYWDATA_MIIWDATA(data);
784baf0fbfeSJeff Kirsher 
785baf0fbfeSJeff Kirsher 	iowrite32(data, priv->base + FTMAC100_OFFSET_PHYWDATA);
786baf0fbfeSJeff Kirsher 	iowrite32(phycr, priv->base + FTMAC100_OFFSET_PHYCR);
787baf0fbfeSJeff Kirsher 
788baf0fbfeSJeff Kirsher 	for (i = 0; i < 10; i++) {
789baf0fbfeSJeff Kirsher 		phycr = ioread32(priv->base + FTMAC100_OFFSET_PHYCR);
790baf0fbfeSJeff Kirsher 
791baf0fbfeSJeff Kirsher 		if ((phycr & FTMAC100_PHYCR_MIIWR) == 0)
792baf0fbfeSJeff Kirsher 			return;
793baf0fbfeSJeff Kirsher 
794baf0fbfeSJeff Kirsher 		udelay(100);
795baf0fbfeSJeff Kirsher 	}
796baf0fbfeSJeff Kirsher 
797baf0fbfeSJeff Kirsher 	netdev_err(netdev, "mdio write timed out\n");
798baf0fbfeSJeff Kirsher }
799baf0fbfeSJeff Kirsher 
800baf0fbfeSJeff Kirsher /******************************************************************************
801baf0fbfeSJeff Kirsher  * struct ethtool_ops functions
802baf0fbfeSJeff Kirsher  *****************************************************************************/
803baf0fbfeSJeff Kirsher static void ftmac100_get_drvinfo(struct net_device *netdev,
804baf0fbfeSJeff Kirsher 				 struct ethtool_drvinfo *info)
805baf0fbfeSJeff Kirsher {
806f029c781SWolfram Sang 	strscpy(info->driver, DRV_NAME, sizeof(info->driver));
807f029c781SWolfram Sang 	strscpy(info->bus_info, dev_name(&netdev->dev), sizeof(info->bus_info));
808baf0fbfeSJeff Kirsher }
809baf0fbfeSJeff Kirsher 
8109da12b64SPhilippe Reynes static int ftmac100_get_link_ksettings(struct net_device *netdev,
8119da12b64SPhilippe Reynes 				       struct ethtool_link_ksettings *cmd)
812baf0fbfeSJeff Kirsher {
813baf0fbfeSJeff Kirsher 	struct ftmac100 *priv = netdev_priv(netdev);
81482c01a84Syuval.shaia@oracle.com 
81582c01a84Syuval.shaia@oracle.com 	mii_ethtool_get_link_ksettings(&priv->mii, cmd);
81682c01a84Syuval.shaia@oracle.com 
81782c01a84Syuval.shaia@oracle.com 	return 0;
818baf0fbfeSJeff Kirsher }
819baf0fbfeSJeff Kirsher 
8209da12b64SPhilippe Reynes static int ftmac100_set_link_ksettings(struct net_device *netdev,
8219da12b64SPhilippe Reynes 				       const struct ethtool_link_ksettings *cmd)
822baf0fbfeSJeff Kirsher {
823baf0fbfeSJeff Kirsher 	struct ftmac100 *priv = netdev_priv(netdev);
8249da12b64SPhilippe Reynes 	return mii_ethtool_set_link_ksettings(&priv->mii, cmd);
825baf0fbfeSJeff Kirsher }
826baf0fbfeSJeff Kirsher 
827baf0fbfeSJeff Kirsher static int ftmac100_nway_reset(struct net_device *netdev)
828baf0fbfeSJeff Kirsher {
829baf0fbfeSJeff Kirsher 	struct ftmac100 *priv = netdev_priv(netdev);
830baf0fbfeSJeff Kirsher 	return mii_nway_restart(&priv->mii);
831baf0fbfeSJeff Kirsher }
832baf0fbfeSJeff Kirsher 
833baf0fbfeSJeff Kirsher static u32 ftmac100_get_link(struct net_device *netdev)
834baf0fbfeSJeff Kirsher {
835baf0fbfeSJeff Kirsher 	struct ftmac100 *priv = netdev_priv(netdev);
836baf0fbfeSJeff Kirsher 	return mii_link_ok(&priv->mii);
837baf0fbfeSJeff Kirsher }
838baf0fbfeSJeff Kirsher 
839baf0fbfeSJeff Kirsher static const struct ethtool_ops ftmac100_ethtool_ops = {
840baf0fbfeSJeff Kirsher 	.get_drvinfo		= ftmac100_get_drvinfo,
841baf0fbfeSJeff Kirsher 	.nway_reset		= ftmac100_nway_reset,
842baf0fbfeSJeff Kirsher 	.get_link		= ftmac100_get_link,
8439da12b64SPhilippe Reynes 	.get_link_ksettings	= ftmac100_get_link_ksettings,
8449da12b64SPhilippe Reynes 	.set_link_ksettings	= ftmac100_set_link_ksettings,
845baf0fbfeSJeff Kirsher };
846baf0fbfeSJeff Kirsher 
847baf0fbfeSJeff Kirsher /******************************************************************************
848baf0fbfeSJeff Kirsher  * interrupt handler
849baf0fbfeSJeff Kirsher  *****************************************************************************/
850baf0fbfeSJeff Kirsher static irqreturn_t ftmac100_interrupt(int irq, void *dev_id)
851baf0fbfeSJeff Kirsher {
852baf0fbfeSJeff Kirsher 	struct net_device *netdev = dev_id;
853baf0fbfeSJeff Kirsher 	struct ftmac100 *priv = netdev_priv(netdev);
854baf0fbfeSJeff Kirsher 
855baf0fbfeSJeff Kirsher 	/* Disable interrupts for polling */
856baf0fbfeSJeff Kirsher 	ftmac100_disable_all_int(priv);
857426a593eSVincent Chen 	if (likely(netif_running(netdev)))
858baf0fbfeSJeff Kirsher 		napi_schedule(&priv->napi);
859baf0fbfeSJeff Kirsher 
860baf0fbfeSJeff Kirsher 	return IRQ_HANDLED;
861baf0fbfeSJeff Kirsher }
862baf0fbfeSJeff Kirsher 
863baf0fbfeSJeff Kirsher /******************************************************************************
864baf0fbfeSJeff Kirsher  * struct napi_struct functions
865baf0fbfeSJeff Kirsher  *****************************************************************************/
866baf0fbfeSJeff Kirsher static int ftmac100_poll(struct napi_struct *napi, int budget)
867baf0fbfeSJeff Kirsher {
868baf0fbfeSJeff Kirsher 	struct ftmac100 *priv = container_of(napi, struct ftmac100, napi);
869baf0fbfeSJeff Kirsher 	struct net_device *netdev = priv->netdev;
870baf0fbfeSJeff Kirsher 	unsigned int status;
871baf0fbfeSJeff Kirsher 	bool completed = true;
872baf0fbfeSJeff Kirsher 	int rx = 0;
873baf0fbfeSJeff Kirsher 
874baf0fbfeSJeff Kirsher 	status = ioread32(priv->base + FTMAC100_OFFSET_ISR);
875baf0fbfeSJeff Kirsher 
876baf0fbfeSJeff Kirsher 	if (status & (FTMAC100_INT_RPKT_FINISH | FTMAC100_INT_NORXBUF)) {
877baf0fbfeSJeff Kirsher 		/*
878baf0fbfeSJeff Kirsher 		 * FTMAC100_INT_RPKT_FINISH:
879baf0fbfeSJeff Kirsher 		 *	RX DMA has received packets into RX buffer successfully
880baf0fbfeSJeff Kirsher 		 *
881baf0fbfeSJeff Kirsher 		 * FTMAC100_INT_NORXBUF:
882baf0fbfeSJeff Kirsher 		 *	RX buffer unavailable
883baf0fbfeSJeff Kirsher 		 */
884baf0fbfeSJeff Kirsher 		bool retry;
885baf0fbfeSJeff Kirsher 
886baf0fbfeSJeff Kirsher 		do {
887baf0fbfeSJeff Kirsher 			retry = ftmac100_rx_packet(priv, &rx);
888baf0fbfeSJeff Kirsher 		} while (retry && rx < budget);
889baf0fbfeSJeff Kirsher 
890baf0fbfeSJeff Kirsher 		if (retry && rx == budget)
891baf0fbfeSJeff Kirsher 			completed = false;
892baf0fbfeSJeff Kirsher 	}
893baf0fbfeSJeff Kirsher 
894baf0fbfeSJeff Kirsher 	if (status & (FTMAC100_INT_XPKT_OK | FTMAC100_INT_XPKT_LOST)) {
895baf0fbfeSJeff Kirsher 		/*
896baf0fbfeSJeff Kirsher 		 * FTMAC100_INT_XPKT_OK:
897baf0fbfeSJeff Kirsher 		 *	packet transmitted to ethernet successfully
898baf0fbfeSJeff Kirsher 		 *
899baf0fbfeSJeff Kirsher 		 * FTMAC100_INT_XPKT_LOST:
900baf0fbfeSJeff Kirsher 		 *	packet transmitted to ethernet lost due to late
901baf0fbfeSJeff Kirsher 		 *	collision or excessive collision
902baf0fbfeSJeff Kirsher 		 */
903baf0fbfeSJeff Kirsher 		ftmac100_tx_complete(priv);
904baf0fbfeSJeff Kirsher 	}
905baf0fbfeSJeff Kirsher 
906baf0fbfeSJeff Kirsher 	if (status & (FTMAC100_INT_NORXBUF | FTMAC100_INT_RPKT_LOST |
907baf0fbfeSJeff Kirsher 		      FTMAC100_INT_AHB_ERR | FTMAC100_INT_PHYSTS_CHG)) {
908baf0fbfeSJeff Kirsher 		if (net_ratelimit())
909baf0fbfeSJeff Kirsher 			netdev_info(netdev, "[ISR] = 0x%x: %s%s%s%s\n", status,
910baf0fbfeSJeff Kirsher 				    status & FTMAC100_INT_NORXBUF ? "NORXBUF " : "",
911baf0fbfeSJeff Kirsher 				    status & FTMAC100_INT_RPKT_LOST ? "RPKT_LOST " : "",
912baf0fbfeSJeff Kirsher 				    status & FTMAC100_INT_AHB_ERR ? "AHB_ERR " : "",
913baf0fbfeSJeff Kirsher 				    status & FTMAC100_INT_PHYSTS_CHG ? "PHYSTS_CHG" : "");
914baf0fbfeSJeff Kirsher 
915baf0fbfeSJeff Kirsher 		if (status & FTMAC100_INT_NORXBUF) {
916baf0fbfeSJeff Kirsher 			/* RX buffer unavailable */
917baf0fbfeSJeff Kirsher 			netdev->stats.rx_over_errors++;
918baf0fbfeSJeff Kirsher 		}
919baf0fbfeSJeff Kirsher 
920baf0fbfeSJeff Kirsher 		if (status & FTMAC100_INT_RPKT_LOST) {
921baf0fbfeSJeff Kirsher 			/* received packet lost due to RX FIFO full */
922baf0fbfeSJeff Kirsher 			netdev->stats.rx_fifo_errors++;
923baf0fbfeSJeff Kirsher 		}
924baf0fbfeSJeff Kirsher 
925baf0fbfeSJeff Kirsher 		if (status & FTMAC100_INT_PHYSTS_CHG) {
926baf0fbfeSJeff Kirsher 			/* PHY link status change */
927baf0fbfeSJeff Kirsher 			mii_check_link(&priv->mii);
928baf0fbfeSJeff Kirsher 		}
929baf0fbfeSJeff Kirsher 	}
930baf0fbfeSJeff Kirsher 
931baf0fbfeSJeff Kirsher 	if (completed) {
932baf0fbfeSJeff Kirsher 		/* stop polling */
933baf0fbfeSJeff Kirsher 		napi_complete(napi);
934baf0fbfeSJeff Kirsher 		ftmac100_enable_all_int(priv);
935baf0fbfeSJeff Kirsher 	}
936baf0fbfeSJeff Kirsher 
937baf0fbfeSJeff Kirsher 	return rx;
938baf0fbfeSJeff Kirsher }
939baf0fbfeSJeff Kirsher 
940baf0fbfeSJeff Kirsher /******************************************************************************
941baf0fbfeSJeff Kirsher  * struct net_device_ops functions
942baf0fbfeSJeff Kirsher  *****************************************************************************/
943baf0fbfeSJeff Kirsher static int ftmac100_open(struct net_device *netdev)
944baf0fbfeSJeff Kirsher {
945baf0fbfeSJeff Kirsher 	struct ftmac100 *priv = netdev_priv(netdev);
946baf0fbfeSJeff Kirsher 	int err;
947baf0fbfeSJeff Kirsher 
948baf0fbfeSJeff Kirsher 	err = ftmac100_alloc_buffers(priv);
949baf0fbfeSJeff Kirsher 	if (err) {
950baf0fbfeSJeff Kirsher 		netdev_err(netdev, "failed to allocate buffers\n");
951baf0fbfeSJeff Kirsher 		goto err_alloc;
952baf0fbfeSJeff Kirsher 	}
953baf0fbfeSJeff Kirsher 
954baf0fbfeSJeff Kirsher 	err = request_irq(priv->irq, ftmac100_interrupt, 0, netdev->name, netdev);
955baf0fbfeSJeff Kirsher 	if (err) {
956baf0fbfeSJeff Kirsher 		netdev_err(netdev, "failed to request irq %d\n", priv->irq);
957baf0fbfeSJeff Kirsher 		goto err_irq;
958baf0fbfeSJeff Kirsher 	}
959baf0fbfeSJeff Kirsher 
960baf0fbfeSJeff Kirsher 	priv->rx_pointer = 0;
961baf0fbfeSJeff Kirsher 	priv->tx_clean_pointer = 0;
962baf0fbfeSJeff Kirsher 	priv->tx_pointer = 0;
963baf0fbfeSJeff Kirsher 	priv->tx_pending = 0;
964baf0fbfeSJeff Kirsher 
965baf0fbfeSJeff Kirsher 	err = ftmac100_start_hw(priv);
966baf0fbfeSJeff Kirsher 	if (err)
967baf0fbfeSJeff Kirsher 		goto err_hw;
968baf0fbfeSJeff Kirsher 
969baf0fbfeSJeff Kirsher 	napi_enable(&priv->napi);
970baf0fbfeSJeff Kirsher 	netif_start_queue(netdev);
971baf0fbfeSJeff Kirsher 
972baf0fbfeSJeff Kirsher 	ftmac100_enable_all_int(priv);
973baf0fbfeSJeff Kirsher 
974baf0fbfeSJeff Kirsher 	return 0;
975baf0fbfeSJeff Kirsher 
976baf0fbfeSJeff Kirsher err_hw:
977baf0fbfeSJeff Kirsher 	free_irq(priv->irq, netdev);
978baf0fbfeSJeff Kirsher err_irq:
979baf0fbfeSJeff Kirsher 	ftmac100_free_buffers(priv);
980baf0fbfeSJeff Kirsher err_alloc:
981baf0fbfeSJeff Kirsher 	return err;
982baf0fbfeSJeff Kirsher }
983baf0fbfeSJeff Kirsher 
984baf0fbfeSJeff Kirsher static int ftmac100_stop(struct net_device *netdev)
985baf0fbfeSJeff Kirsher {
986baf0fbfeSJeff Kirsher 	struct ftmac100 *priv = netdev_priv(netdev);
987baf0fbfeSJeff Kirsher 
988baf0fbfeSJeff Kirsher 	ftmac100_disable_all_int(priv);
989baf0fbfeSJeff Kirsher 	netif_stop_queue(netdev);
990baf0fbfeSJeff Kirsher 	napi_disable(&priv->napi);
991baf0fbfeSJeff Kirsher 	ftmac100_stop_hw(priv);
992baf0fbfeSJeff Kirsher 	free_irq(priv->irq, netdev);
993baf0fbfeSJeff Kirsher 	ftmac100_free_buffers(priv);
994baf0fbfeSJeff Kirsher 
995baf0fbfeSJeff Kirsher 	return 0;
996baf0fbfeSJeff Kirsher }
997baf0fbfeSJeff Kirsher 
9980a715156SYueHaibing static netdev_tx_t
9990a715156SYueHaibing ftmac100_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev)
1000baf0fbfeSJeff Kirsher {
1001baf0fbfeSJeff Kirsher 	struct ftmac100 *priv = netdev_priv(netdev);
1002baf0fbfeSJeff Kirsher 	dma_addr_t map;
1003baf0fbfeSJeff Kirsher 
1004baf0fbfeSJeff Kirsher 	if (unlikely(skb->len > MAX_PKT_SIZE)) {
1005baf0fbfeSJeff Kirsher 		if (net_ratelimit())
1006baf0fbfeSJeff Kirsher 			netdev_dbg(netdev, "tx packet too big\n");
1007baf0fbfeSJeff Kirsher 
1008baf0fbfeSJeff Kirsher 		netdev->stats.tx_dropped++;
1009baf0fbfeSJeff Kirsher 		dev_kfree_skb(skb);
1010baf0fbfeSJeff Kirsher 		return NETDEV_TX_OK;
1011baf0fbfeSJeff Kirsher 	}
1012baf0fbfeSJeff Kirsher 
1013baf0fbfeSJeff Kirsher 	map = dma_map_single(priv->dev, skb->data, skb_headlen(skb), DMA_TO_DEVICE);
1014baf0fbfeSJeff Kirsher 	if (unlikely(dma_mapping_error(priv->dev, map))) {
1015baf0fbfeSJeff Kirsher 		/* drop packet */
1016baf0fbfeSJeff Kirsher 		if (net_ratelimit())
1017baf0fbfeSJeff Kirsher 			netdev_err(netdev, "map socket buffer failed\n");
1018baf0fbfeSJeff Kirsher 
1019baf0fbfeSJeff Kirsher 		netdev->stats.tx_dropped++;
1020baf0fbfeSJeff Kirsher 		dev_kfree_skb(skb);
1021baf0fbfeSJeff Kirsher 		return NETDEV_TX_OK;
1022baf0fbfeSJeff Kirsher 	}
1023baf0fbfeSJeff Kirsher 
1024baf0fbfeSJeff Kirsher 	return ftmac100_xmit(priv, skb, map);
1025baf0fbfeSJeff Kirsher }
1026baf0fbfeSJeff Kirsher 
1027baf0fbfeSJeff Kirsher /* optional */
1028baf0fbfeSJeff Kirsher static int ftmac100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
1029baf0fbfeSJeff Kirsher {
1030baf0fbfeSJeff Kirsher 	struct ftmac100 *priv = netdev_priv(netdev);
1031baf0fbfeSJeff Kirsher 	struct mii_ioctl_data *data = if_mii(ifr);
1032baf0fbfeSJeff Kirsher 
1033baf0fbfeSJeff Kirsher 	return generic_mii_ioctl(&priv->mii, data, cmd, NULL);
1034baf0fbfeSJeff Kirsher }
1035baf0fbfeSJeff Kirsher 
1036baf0fbfeSJeff Kirsher static const struct net_device_ops ftmac100_netdev_ops = {
1037baf0fbfeSJeff Kirsher 	.ndo_open		= ftmac100_open,
1038baf0fbfeSJeff Kirsher 	.ndo_stop		= ftmac100_stop,
1039baf0fbfeSJeff Kirsher 	.ndo_start_xmit		= ftmac100_hard_start_xmit,
1040baf0fbfeSJeff Kirsher 	.ndo_set_mac_address	= eth_mac_addr,
1041baf0fbfeSJeff Kirsher 	.ndo_validate_addr	= eth_validate_addr,
1042a7605370SArnd Bergmann 	.ndo_eth_ioctl		= ftmac100_do_ioctl,
1043baf0fbfeSJeff Kirsher };
1044baf0fbfeSJeff Kirsher 
1045baf0fbfeSJeff Kirsher /******************************************************************************
1046baf0fbfeSJeff Kirsher  * struct platform_driver functions
1047baf0fbfeSJeff Kirsher  *****************************************************************************/
1048baf0fbfeSJeff Kirsher static int ftmac100_probe(struct platform_device *pdev)
1049baf0fbfeSJeff Kirsher {
1050baf0fbfeSJeff Kirsher 	struct resource *res;
1051baf0fbfeSJeff Kirsher 	int irq;
1052baf0fbfeSJeff Kirsher 	struct net_device *netdev;
1053baf0fbfeSJeff Kirsher 	struct ftmac100 *priv;
1054baf0fbfeSJeff Kirsher 	int err;
1055baf0fbfeSJeff Kirsher 
1056baf0fbfeSJeff Kirsher 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1057baf0fbfeSJeff Kirsher 	if (!res)
1058baf0fbfeSJeff Kirsher 		return -ENXIO;
1059baf0fbfeSJeff Kirsher 
1060baf0fbfeSJeff Kirsher 	irq = platform_get_irq(pdev, 0);
1061baf0fbfeSJeff Kirsher 	if (irq < 0)
1062baf0fbfeSJeff Kirsher 		return irq;
1063baf0fbfeSJeff Kirsher 
1064baf0fbfeSJeff Kirsher 	/* setup net_device */
1065baf0fbfeSJeff Kirsher 	netdev = alloc_etherdev(sizeof(*priv));
1066baf0fbfeSJeff Kirsher 	if (!netdev) {
1067baf0fbfeSJeff Kirsher 		err = -ENOMEM;
1068baf0fbfeSJeff Kirsher 		goto err_alloc_etherdev;
1069baf0fbfeSJeff Kirsher 	}
1070baf0fbfeSJeff Kirsher 
1071baf0fbfeSJeff Kirsher 	SET_NETDEV_DEV(netdev, &pdev->dev);
10727ad24ea4SWilfried Klaebe 	netdev->ethtool_ops = &ftmac100_ethtool_ops;
1073baf0fbfeSJeff Kirsher 	netdev->netdev_ops = &ftmac100_netdev_ops;
1074*30f837b7SVladimir Oltean 	netdev->max_mtu = MAX_PKT_SIZE - VLAN_ETH_HLEN;
1075baf0fbfeSJeff Kirsher 
1076f7650d82SSergei Antonov 	err = platform_get_ethdev_address(&pdev->dev, netdev);
1077f7650d82SSergei Antonov 	if (err == -EPROBE_DEFER)
1078f7650d82SSergei Antonov 		goto defer_get_mac;
1079f7650d82SSergei Antonov 
1080baf0fbfeSJeff Kirsher 	platform_set_drvdata(pdev, netdev);
1081baf0fbfeSJeff Kirsher 
1082baf0fbfeSJeff Kirsher 	/* setup private data */
1083baf0fbfeSJeff Kirsher 	priv = netdev_priv(netdev);
1084baf0fbfeSJeff Kirsher 	priv->netdev = netdev;
1085baf0fbfeSJeff Kirsher 	priv->dev = &pdev->dev;
1086baf0fbfeSJeff Kirsher 
1087baf0fbfeSJeff Kirsher 	spin_lock_init(&priv->tx_lock);
1088baf0fbfeSJeff Kirsher 
1089baf0fbfeSJeff Kirsher 	/* initialize NAPI */
1090b48b89f9SJakub Kicinski 	netif_napi_add(netdev, &priv->napi, ftmac100_poll);
1091baf0fbfeSJeff Kirsher 
1092baf0fbfeSJeff Kirsher 	/* map io memory */
1093baf0fbfeSJeff Kirsher 	priv->res = request_mem_region(res->start, resource_size(res),
1094baf0fbfeSJeff Kirsher 				       dev_name(&pdev->dev));
1095baf0fbfeSJeff Kirsher 	if (!priv->res) {
1096baf0fbfeSJeff Kirsher 		dev_err(&pdev->dev, "Could not reserve memory region\n");
1097baf0fbfeSJeff Kirsher 		err = -ENOMEM;
1098baf0fbfeSJeff Kirsher 		goto err_req_mem;
1099baf0fbfeSJeff Kirsher 	}
1100baf0fbfeSJeff Kirsher 
1101baf0fbfeSJeff Kirsher 	priv->base = ioremap(res->start, resource_size(res));
1102baf0fbfeSJeff Kirsher 	if (!priv->base) {
1103baf0fbfeSJeff Kirsher 		dev_err(&pdev->dev, "Failed to ioremap ethernet registers\n");
1104baf0fbfeSJeff Kirsher 		err = -EIO;
1105baf0fbfeSJeff Kirsher 		goto err_ioremap;
1106baf0fbfeSJeff Kirsher 	}
1107baf0fbfeSJeff Kirsher 
1108baf0fbfeSJeff Kirsher 	priv->irq = irq;
1109baf0fbfeSJeff Kirsher 
1110baf0fbfeSJeff Kirsher 	/* initialize struct mii_if_info */
1111baf0fbfeSJeff Kirsher 	priv->mii.phy_id	= 0;
1112baf0fbfeSJeff Kirsher 	priv->mii.phy_id_mask	= 0x1f;
1113baf0fbfeSJeff Kirsher 	priv->mii.reg_num_mask	= 0x1f;
1114baf0fbfeSJeff Kirsher 	priv->mii.dev		= netdev;
1115baf0fbfeSJeff Kirsher 	priv->mii.mdio_read	= ftmac100_mdio_read;
1116baf0fbfeSJeff Kirsher 	priv->mii.mdio_write	= ftmac100_mdio_write;
1117baf0fbfeSJeff Kirsher 
1118baf0fbfeSJeff Kirsher 	/* register network device */
1119baf0fbfeSJeff Kirsher 	err = register_netdev(netdev);
1120baf0fbfeSJeff Kirsher 	if (err) {
1121baf0fbfeSJeff Kirsher 		dev_err(&pdev->dev, "Failed to register netdev\n");
1122baf0fbfeSJeff Kirsher 		goto err_register_netdev;
1123baf0fbfeSJeff Kirsher 	}
1124baf0fbfeSJeff Kirsher 
1125baf0fbfeSJeff Kirsher 	netdev_info(netdev, "irq %d, mapped at %p\n", priv->irq, priv->base);
1126baf0fbfeSJeff Kirsher 
1127baf0fbfeSJeff Kirsher 	if (!is_valid_ether_addr(netdev->dev_addr)) {
1128f2cedb63SDanny Kukawka 		eth_hw_addr_random(netdev);
1129baf0fbfeSJeff Kirsher 		netdev_info(netdev, "generated random MAC address %pM\n",
1130baf0fbfeSJeff Kirsher 			    netdev->dev_addr);
1131baf0fbfeSJeff Kirsher 	}
1132baf0fbfeSJeff Kirsher 
1133baf0fbfeSJeff Kirsher 	return 0;
1134baf0fbfeSJeff Kirsher 
1135baf0fbfeSJeff Kirsher err_register_netdev:
1136baf0fbfeSJeff Kirsher 	iounmap(priv->base);
1137baf0fbfeSJeff Kirsher err_ioremap:
1138baf0fbfeSJeff Kirsher 	release_resource(priv->res);
1139baf0fbfeSJeff Kirsher err_req_mem:
1140baf0fbfeSJeff Kirsher 	netif_napi_del(&priv->napi);
1141f7650d82SSergei Antonov defer_get_mac:
1142baf0fbfeSJeff Kirsher 	free_netdev(netdev);
1143baf0fbfeSJeff Kirsher err_alloc_etherdev:
1144baf0fbfeSJeff Kirsher 	return err;
1145baf0fbfeSJeff Kirsher }
1146baf0fbfeSJeff Kirsher 
1147be12502eSDmitry Torokhov static int ftmac100_remove(struct platform_device *pdev)
1148baf0fbfeSJeff Kirsher {
1149baf0fbfeSJeff Kirsher 	struct net_device *netdev;
1150baf0fbfeSJeff Kirsher 	struct ftmac100 *priv;
1151baf0fbfeSJeff Kirsher 
1152baf0fbfeSJeff Kirsher 	netdev = platform_get_drvdata(pdev);
1153baf0fbfeSJeff Kirsher 	priv = netdev_priv(netdev);
1154baf0fbfeSJeff Kirsher 
1155baf0fbfeSJeff Kirsher 	unregister_netdev(netdev);
1156baf0fbfeSJeff Kirsher 
1157baf0fbfeSJeff Kirsher 	iounmap(priv->base);
1158baf0fbfeSJeff Kirsher 	release_resource(priv->res);
1159baf0fbfeSJeff Kirsher 
1160baf0fbfeSJeff Kirsher 	netif_napi_del(&priv->napi);
1161baf0fbfeSJeff Kirsher 	free_netdev(netdev);
1162baf0fbfeSJeff Kirsher 	return 0;
1163baf0fbfeSJeff Kirsher }
1164baf0fbfeSJeff Kirsher 
116547ab37a1SGreentime Hu static const struct of_device_id ftmac100_of_ids[] = {
116647ab37a1SGreentime Hu 	{ .compatible = "andestech,atmac100" },
116747ab37a1SGreentime Hu 	{ }
116847ab37a1SGreentime Hu };
116947ab37a1SGreentime Hu 
1170baf0fbfeSJeff Kirsher static struct platform_driver ftmac100_driver = {
1171baf0fbfeSJeff Kirsher 	.probe		= ftmac100_probe,
1172be12502eSDmitry Torokhov 	.remove		= ftmac100_remove,
1173baf0fbfeSJeff Kirsher 	.driver		= {
1174baf0fbfeSJeff Kirsher 		.name	= DRV_NAME,
117547ab37a1SGreentime Hu 		.of_match_table = ftmac100_of_ids
1176baf0fbfeSJeff Kirsher 	},
1177baf0fbfeSJeff Kirsher };
1178baf0fbfeSJeff Kirsher 
1179baf0fbfeSJeff Kirsher /******************************************************************************
1180baf0fbfeSJeff Kirsher  * initialization / finalization
1181baf0fbfeSJeff Kirsher  *****************************************************************************/
1182d280a2c2SZhichao Cai module_platform_driver(ftmac100_driver);
1183baf0fbfeSJeff Kirsher 
1184baf0fbfeSJeff Kirsher MODULE_AUTHOR("Po-Yu Chuang <ratbert@faraday-tech.com>");
1185baf0fbfeSJeff Kirsher MODULE_DESCRIPTION("FTMAC100 driver");
1186baf0fbfeSJeff Kirsher MODULE_LICENSE("GPL");
118747ab37a1SGreentime Hu MODULE_DEVICE_TABLE(of, ftmac100_of_ids);
1188