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