blob: a15345ba1e5947b83b850d7340d8cfc1815b92c4 [file] [log] [blame]
Pantelis Antoniou48257c42005-10-28 16:25:58 -04001/*
2 * Combined Ethernet driver for Motorola MPC8xx and MPC82xx.
3 *
Vitaly Bordug9b8ee8e2007-09-18 20:05:35 +04004 * Copyright (c) 2003 Intracom S.A.
Pantelis Antoniou48257c42005-10-28 16:25:58 -04005 * by Pantelis Antoniou <panto@intracom.gr>
Vitaly Bordug9b8ee8e2007-09-18 20:05:35 +04006 *
7 * 2005 (c) MontaVista Software, Inc.
Pantelis Antoniou48257c42005-10-28 16:25:58 -04008 * Vitaly Bordug <vbordug@ru.mvista.com>
9 *
10 * Heavily based on original FEC driver by Dan Malek <dan@embeddededge.com>
11 * and modifications by Joakim Tjernlund <joakim.tjernlund@lumentis.se>
12 *
Vitaly Bordug9b8ee8e2007-09-18 20:05:35 +040013 * This file is licensed under the terms of the GNU General Public License
14 * version 2. This program is licensed "as is" without any warranty of any
Pantelis Antoniou48257c42005-10-28 16:25:58 -040015 * kind, whether express or implied.
16 */
17
Pantelis Antoniou48257c42005-10-28 16:25:58 -040018#include <linux/module.h>
19#include <linux/kernel.h>
20#include <linux/types.h>
Pantelis Antoniou48257c42005-10-28 16:25:58 -040021#include <linux/string.h>
22#include <linux/ptrace.h>
23#include <linux/errno.h>
24#include <linux/ioport.h>
25#include <linux/slab.h>
26#include <linux/interrupt.h>
Pantelis Antoniou48257c42005-10-28 16:25:58 -040027#include <linux/init.h>
28#include <linux/delay.h>
29#include <linux/netdevice.h>
30#include <linux/etherdevice.h>
31#include <linux/skbuff.h>
32#include <linux/spinlock.h>
33#include <linux/mii.h>
34#include <linux/ethtool.h>
35#include <linux/bitops.h>
36#include <linux/fs.h>
Marcelo Tosattif7b99962005-11-09 11:00:16 -020037#include <linux/platform_device.h>
Vitaly Bordug5b4b8452006-08-14 23:00:30 -070038#include <linux/phy.h>
Pantelis Antoniou48257c42005-10-28 16:25:58 -040039
40#include <linux/vmalloc.h>
41#include <asm/pgtable.h>
Pantelis Antoniou48257c42005-10-28 16:25:58 -040042#include <asm/irq.h>
43#include <asm/uaccess.h>
44
45#include "fs_enet.h"
46
47/*************************************************/
48
49static char version[] __devinitdata =
50 DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")" "\n";
51
52MODULE_AUTHOR("Pantelis Antoniou <panto@intracom.gr>");
53MODULE_DESCRIPTION("Freescale Ethernet Driver");
54MODULE_LICENSE("GPL");
55MODULE_VERSION(DRV_MODULE_VERSION);
56
Rusty Russell8d3b33f2006-03-25 03:07:05 -080057int fs_enet_debug = -1; /* -1 == use FS_ENET_DEF_MSG_ENABLE as value */
58module_param(fs_enet_debug, int, 0);
Pantelis Antoniou48257c42005-10-28 16:25:58 -040059MODULE_PARM_DESC(fs_enet_debug,
60 "Freescale bitmapped debugging message enable value");
61
Vitaly Bordug9b8ee8e2007-09-18 20:05:35 +040062#ifdef CONFIG_NET_POLL_CONTROLLER
63static void fs_enet_netpoll(struct net_device *dev);
64#endif
Pantelis Antoniou48257c42005-10-28 16:25:58 -040065
66static void fs_set_multicast_list(struct net_device *dev)
67{
68 struct fs_enet_private *fep = netdev_priv(dev);
69
70 (*fep->ops->set_multicast_list)(dev);
71}
72
73/* NAPI receive function */
Stephen Hemmingerbea33482007-10-03 16:41:36 -070074static int fs_enet_rx_napi(struct napi_struct *napi, int budget)
Pantelis Antoniou48257c42005-10-28 16:25:58 -040075{
Stephen Hemmingerbea33482007-10-03 16:41:36 -070076 struct fs_enet_private *fep = container_of(napi, struct fs_enet_private, napi);
77 struct net_device *dev = to_net_dev(fep->dev);
Pantelis Antoniou48257c42005-10-28 16:25:58 -040078 const struct fs_platform_info *fpi = fep->fpi;
79 cbd_t *bdp;
80 struct sk_buff *skb, *skbn, *skbt;
81 int received = 0;
82 u16 pkt_len, sc;
83 int curidx;
Pantelis Antoniou48257c42005-10-28 16:25:58 -040084
85 if (!netif_running(dev))
86 return 0;
87
88 /*
89 * First, grab all of the stats for the incoming packet.
90 * These get messed up if we get called due to a busy condition.
91 */
92 bdp = fep->cur_rx;
93
94 /* clear RX status bits for napi*/
95 (*fep->ops->napi_clear_rx_event)(dev);
96
97 while (((sc = CBDR_SC(bdp)) & BD_ENET_RX_EMPTY) == 0) {
Pantelis Antoniou48257c42005-10-28 16:25:58 -040098 curidx = bdp - fep->rx_bd_base;
99
100 /*
101 * Since we have allocated space to hold a complete frame,
102 * the last indicator should be set.
103 */
104 if ((sc & BD_ENET_RX_LAST) == 0)
105 printk(KERN_WARNING DRV_MODULE_NAME
106 ": %s rcv is not +last\n",
107 dev->name);
108
109 /*
Vitaly Bordug9b8ee8e2007-09-18 20:05:35 +0400110 * Check for errors.
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400111 */
112 if (sc & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_CL |
113 BD_ENET_RX_NO | BD_ENET_RX_CR | BD_ENET_RX_OV)) {
114 fep->stats.rx_errors++;
115 /* Frame too long or too short. */
116 if (sc & (BD_ENET_RX_LG | BD_ENET_RX_SH))
117 fep->stats.rx_length_errors++;
118 /* Frame alignment */
119 if (sc & (BD_ENET_RX_NO | BD_ENET_RX_CL))
120 fep->stats.rx_frame_errors++;
121 /* CRC Error */
122 if (sc & BD_ENET_RX_CR)
123 fep->stats.rx_crc_errors++;
124 /* FIFO overrun */
125 if (sc & BD_ENET_RX_OV)
126 fep->stats.rx_crc_errors++;
127
128 skb = fep->rx_skbuff[curidx];
129
Pantelis Antoniou34e30d62005-10-30 01:22:40 +0300130 dma_unmap_single(fep->dev, CBDR_BUFADDR(bdp),
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400131 L1_CACHE_ALIGN(PKT_MAXBUF_SIZE),
132 DMA_FROM_DEVICE);
133
134 skbn = skb;
135
136 } else {
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400137 skb = fep->rx_skbuff[curidx];
138
Pantelis Antoniou34e30d62005-10-30 01:22:40 +0300139 dma_unmap_single(fep->dev, CBDR_BUFADDR(bdp),
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400140 L1_CACHE_ALIGN(PKT_MAXBUF_SIZE),
141 DMA_FROM_DEVICE);
142
143 /*
144 * Process the incoming frame.
145 */
146 fep->stats.rx_packets++;
147 pkt_len = CBDR_DATLEN(bdp) - 4; /* remove CRC */
148 fep->stats.rx_bytes += pkt_len + 4;
149
150 if (pkt_len <= fpi->rx_copybreak) {
151 /* +2 to make IP header L1 cache aligned */
152 skbn = dev_alloc_skb(pkt_len + 2);
153 if (skbn != NULL) {
154 skb_reserve(skbn, 2); /* align IP header */
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -0300155 skb_copy_from_linear_data(skb,
156 skbn->data, pkt_len);
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400157 /* swap */
158 skbt = skb;
159 skb = skbn;
160 skbn = skbt;
161 }
162 } else
163 skbn = dev_alloc_skb(ENET_RX_FRSIZE);
164
165 if (skbn != NULL) {
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400166 skb_put(skb, pkt_len); /* Make room */
167 skb->protocol = eth_type_trans(skb, dev);
168 received++;
169 netif_receive_skb(skb);
170 } else {
171 printk(KERN_WARNING DRV_MODULE_NAME
172 ": %s Memory squeeze, dropping packet.\n",
173 dev->name);
174 fep->stats.rx_dropped++;
175 skbn = skb;
176 }
177 }
178
179 fep->rx_skbuff[curidx] = skbn;
180 CBDW_BUFADDR(bdp, dma_map_single(fep->dev, skbn->data,
181 L1_CACHE_ALIGN(PKT_MAXBUF_SIZE),
182 DMA_FROM_DEVICE));
183 CBDW_DATLEN(bdp, 0);
184 CBDW_SC(bdp, (sc & ~BD_ENET_RX_STATS) | BD_ENET_RX_EMPTY);
185
186 /*
Vitaly Bordug9b8ee8e2007-09-18 20:05:35 +0400187 * Update BD pointer to next entry.
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400188 */
189 if ((sc & BD_ENET_RX_WRAP) == 0)
190 bdp++;
191 else
192 bdp = fep->rx_bd_base;
193
194 (*fep->ops->rx_bd_done)(dev);
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700195
196 if (received >= budget)
197 break;
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400198 }
199
200 fep->cur_rx = bdp;
201
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700202 if (received >= budget) {
203 /* done */
204 netif_rx_complete(dev, napi);
205 (*fep->ops->napi_enable_rx)(dev);
206 }
207 return received;
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400208}
209
210/* non NAPI receive function */
211static int fs_enet_rx_non_napi(struct net_device *dev)
212{
213 struct fs_enet_private *fep = netdev_priv(dev);
214 const struct fs_platform_info *fpi = fep->fpi;
215 cbd_t *bdp;
216 struct sk_buff *skb, *skbn, *skbt;
217 int received = 0;
218 u16 pkt_len, sc;
219 int curidx;
220 /*
221 * First, grab all of the stats for the incoming packet.
222 * These get messed up if we get called due to a busy condition.
223 */
224 bdp = fep->cur_rx;
225
226 while (((sc = CBDR_SC(bdp)) & BD_ENET_RX_EMPTY) == 0) {
227
228 curidx = bdp - fep->rx_bd_base;
229
230 /*
231 * Since we have allocated space to hold a complete frame,
232 * the last indicator should be set.
233 */
234 if ((sc & BD_ENET_RX_LAST) == 0)
235 printk(KERN_WARNING DRV_MODULE_NAME
236 ": %s rcv is not +last\n",
237 dev->name);
238
239 /*
Vitaly Bordug9b8ee8e2007-09-18 20:05:35 +0400240 * Check for errors.
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400241 */
242 if (sc & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_CL |
243 BD_ENET_RX_NO | BD_ENET_RX_CR | BD_ENET_RX_OV)) {
244 fep->stats.rx_errors++;
245 /* Frame too long or too short. */
246 if (sc & (BD_ENET_RX_LG | BD_ENET_RX_SH))
247 fep->stats.rx_length_errors++;
248 /* Frame alignment */
249 if (sc & (BD_ENET_RX_NO | BD_ENET_RX_CL))
250 fep->stats.rx_frame_errors++;
251 /* CRC Error */
252 if (sc & BD_ENET_RX_CR)
253 fep->stats.rx_crc_errors++;
254 /* FIFO overrun */
255 if (sc & BD_ENET_RX_OV)
256 fep->stats.rx_crc_errors++;
257
258 skb = fep->rx_skbuff[curidx];
259
Pantelis Antoniou34e30d62005-10-30 01:22:40 +0300260 dma_unmap_single(fep->dev, CBDR_BUFADDR(bdp),
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400261 L1_CACHE_ALIGN(PKT_MAXBUF_SIZE),
262 DMA_FROM_DEVICE);
263
264 skbn = skb;
265
266 } else {
267
268 skb = fep->rx_skbuff[curidx];
269
Pantelis Antoniou34e30d62005-10-30 01:22:40 +0300270 dma_unmap_single(fep->dev, CBDR_BUFADDR(bdp),
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400271 L1_CACHE_ALIGN(PKT_MAXBUF_SIZE),
272 DMA_FROM_DEVICE);
273
274 /*
275 * Process the incoming frame.
276 */
277 fep->stats.rx_packets++;
278 pkt_len = CBDR_DATLEN(bdp) - 4; /* remove CRC */
279 fep->stats.rx_bytes += pkt_len + 4;
280
281 if (pkt_len <= fpi->rx_copybreak) {
282 /* +2 to make IP header L1 cache aligned */
283 skbn = dev_alloc_skb(pkt_len + 2);
284 if (skbn != NULL) {
285 skb_reserve(skbn, 2); /* align IP header */
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -0300286 skb_copy_from_linear_data(skb,
287 skbn->data, pkt_len);
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400288 /* swap */
289 skbt = skb;
290 skb = skbn;
291 skbn = skbt;
292 }
293 } else
294 skbn = dev_alloc_skb(ENET_RX_FRSIZE);
295
296 if (skbn != NULL) {
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400297 skb_put(skb, pkt_len); /* Make room */
298 skb->protocol = eth_type_trans(skb, dev);
299 received++;
300 netif_rx(skb);
301 } else {
302 printk(KERN_WARNING DRV_MODULE_NAME
303 ": %s Memory squeeze, dropping packet.\n",
304 dev->name);
305 fep->stats.rx_dropped++;
306 skbn = skb;
307 }
308 }
309
310 fep->rx_skbuff[curidx] = skbn;
311 CBDW_BUFADDR(bdp, dma_map_single(fep->dev, skbn->data,
312 L1_CACHE_ALIGN(PKT_MAXBUF_SIZE),
313 DMA_FROM_DEVICE));
314 CBDW_DATLEN(bdp, 0);
315 CBDW_SC(bdp, (sc & ~BD_ENET_RX_STATS) | BD_ENET_RX_EMPTY);
316
317 /*
Vitaly Bordug9b8ee8e2007-09-18 20:05:35 +0400318 * Update BD pointer to next entry.
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400319 */
320 if ((sc & BD_ENET_RX_WRAP) == 0)
321 bdp++;
322 else
323 bdp = fep->rx_bd_base;
324
325 (*fep->ops->rx_bd_done)(dev);
326 }
327
328 fep->cur_rx = bdp;
329
330 return 0;
331}
332
333static void fs_enet_tx(struct net_device *dev)
334{
335 struct fs_enet_private *fep = netdev_priv(dev);
336 cbd_t *bdp;
337 struct sk_buff *skb;
338 int dirtyidx, do_wake, do_restart;
339 u16 sc;
340
Vitaly Bordugaa90f502007-09-18 20:05:27 +0400341 spin_lock(&fep->tx_lock);
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400342 bdp = fep->dirty_tx;
343
344 do_wake = do_restart = 0;
345 while (((sc = CBDR_SC(bdp)) & BD_ENET_TX_READY) == 0) {
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400346 dirtyidx = bdp - fep->tx_bd_base;
347
348 if (fep->tx_free == fep->tx_ring)
349 break;
350
351 skb = fep->tx_skbuff[dirtyidx];
352
353 /*
Vitaly Bordug9b8ee8e2007-09-18 20:05:35 +0400354 * Check for errors.
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400355 */
356 if (sc & (BD_ENET_TX_HB | BD_ENET_TX_LC |
357 BD_ENET_TX_RL | BD_ENET_TX_UN | BD_ENET_TX_CSL)) {
358
359 if (sc & BD_ENET_TX_HB) /* No heartbeat */
360 fep->stats.tx_heartbeat_errors++;
361 if (sc & BD_ENET_TX_LC) /* Late collision */
362 fep->stats.tx_window_errors++;
363 if (sc & BD_ENET_TX_RL) /* Retrans limit */
364 fep->stats.tx_aborted_errors++;
365 if (sc & BD_ENET_TX_UN) /* Underrun */
366 fep->stats.tx_fifo_errors++;
367 if (sc & BD_ENET_TX_CSL) /* Carrier lost */
368 fep->stats.tx_carrier_errors++;
369
370 if (sc & (BD_ENET_TX_LC | BD_ENET_TX_RL | BD_ENET_TX_UN)) {
371 fep->stats.tx_errors++;
372 do_restart = 1;
373 }
374 } else
375 fep->stats.tx_packets++;
376
377 if (sc & BD_ENET_TX_READY)
378 printk(KERN_WARNING DRV_MODULE_NAME
379 ": %s HEY! Enet xmit interrupt and TX_READY.\n",
380 dev->name);
381
382 /*
383 * Deferred means some collisions occurred during transmit,
384 * but we eventually sent the packet OK.
385 */
386 if (sc & BD_ENET_TX_DEF)
387 fep->stats.collisions++;
388
389 /* unmap */
Pantelis Antoniou34e30d62005-10-30 01:22:40 +0300390 dma_unmap_single(fep->dev, CBDR_BUFADDR(bdp),
391 skb->len, DMA_TO_DEVICE);
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400392
393 /*
Vitaly Bordug9b8ee8e2007-09-18 20:05:35 +0400394 * Free the sk buffer associated with this last transmit.
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400395 */
396 dev_kfree_skb_irq(skb);
397 fep->tx_skbuff[dirtyidx] = NULL;
398
399 /*
Vitaly Bordug9b8ee8e2007-09-18 20:05:35 +0400400 * Update pointer to next buffer descriptor to be transmitted.
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400401 */
402 if ((sc & BD_ENET_TX_WRAP) == 0)
403 bdp++;
404 else
405 bdp = fep->tx_bd_base;
406
407 /*
408 * Since we have freed up a buffer, the ring is no longer
409 * full.
410 */
411 if (!fep->tx_free++)
412 do_wake = 1;
413 }
414
415 fep->dirty_tx = bdp;
416
417 if (do_restart)
418 (*fep->ops->tx_restart)(dev);
419
Vitaly Bordugaa90f502007-09-18 20:05:27 +0400420 spin_unlock(&fep->tx_lock);
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400421
422 if (do_wake)
423 netif_wake_queue(dev);
424}
425
426/*
427 * The interrupt handler.
428 * This is called from the MPC core interrupt.
429 */
430static irqreturn_t
David Howells7d12e782006-10-05 14:55:46 +0100431fs_enet_interrupt(int irq, void *dev_id)
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400432{
433 struct net_device *dev = dev_id;
434 struct fs_enet_private *fep;
435 const struct fs_platform_info *fpi;
436 u32 int_events;
437 u32 int_clr_events;
438 int nr, napi_ok;
439 int handled;
440
441 fep = netdev_priv(dev);
442 fpi = fep->fpi;
443
444 nr = 0;
445 while ((int_events = (*fep->ops->get_int_events)(dev)) != 0) {
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400446 nr++;
447
448 int_clr_events = int_events;
449 if (fpi->use_napi)
450 int_clr_events &= ~fep->ev_napi_rx;
451
452 (*fep->ops->clear_int_events)(dev, int_clr_events);
453
454 if (int_events & fep->ev_err)
455 (*fep->ops->ev_error)(dev, int_events);
456
457 if (int_events & fep->ev_rx) {
458 if (!fpi->use_napi)
459 fs_enet_rx_non_napi(dev);
460 else {
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700461 napi_ok = napi_schedule_prep(&fep->napi);
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400462
463 (*fep->ops->napi_disable_rx)(dev);
464 (*fep->ops->clear_int_events)(dev, fep->ev_napi_rx);
465
466 /* NOTE: it is possible for FCCs in NAPI mode */
467 /* to submit a spurious interrupt while in poll */
468 if (napi_ok)
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700469 __netif_rx_schedule(dev, &fep->napi);
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400470 }
471 }
472
473 if (int_events & fep->ev_tx)
474 fs_enet_tx(dev);
475 }
476
477 handled = nr > 0;
478 return IRQ_RETVAL(handled);
479}
480
481void fs_init_bds(struct net_device *dev)
482{
483 struct fs_enet_private *fep = netdev_priv(dev);
484 cbd_t *bdp;
485 struct sk_buff *skb;
486 int i;
487
488 fs_cleanup_bds(dev);
489
490 fep->dirty_tx = fep->cur_tx = fep->tx_bd_base;
491 fep->tx_free = fep->tx_ring;
492 fep->cur_rx = fep->rx_bd_base;
493
494 /*
Vitaly Bordug9b8ee8e2007-09-18 20:05:35 +0400495 * Initialize the receive buffer descriptors.
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400496 */
497 for (i = 0, bdp = fep->rx_bd_base; i < fep->rx_ring; i++, bdp++) {
498 skb = dev_alloc_skb(ENET_RX_FRSIZE);
499 if (skb == NULL) {
500 printk(KERN_WARNING DRV_MODULE_NAME
501 ": %s Memory squeeze, unable to allocate skb\n",
502 dev->name);
503 break;
504 }
505 fep->rx_skbuff[i] = skb;
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400506 CBDW_BUFADDR(bdp,
507 dma_map_single(fep->dev, skb->data,
508 L1_CACHE_ALIGN(PKT_MAXBUF_SIZE),
509 DMA_FROM_DEVICE));
510 CBDW_DATLEN(bdp, 0); /* zero */
511 CBDW_SC(bdp, BD_ENET_RX_EMPTY |
512 ((i < fep->rx_ring - 1) ? 0 : BD_SC_WRAP));
513 }
514 /*
Vitaly Bordug9b8ee8e2007-09-18 20:05:35 +0400515 * if we failed, fillup remainder
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400516 */
517 for (; i < fep->rx_ring; i++, bdp++) {
518 fep->rx_skbuff[i] = NULL;
519 CBDW_SC(bdp, (i < fep->rx_ring - 1) ? 0 : BD_SC_WRAP);
520 }
521
522 /*
Vitaly Bordug9b8ee8e2007-09-18 20:05:35 +0400523 * ...and the same for transmit.
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400524 */
525 for (i = 0, bdp = fep->tx_bd_base; i < fep->tx_ring; i++, bdp++) {
526 fep->tx_skbuff[i] = NULL;
527 CBDW_BUFADDR(bdp, 0);
528 CBDW_DATLEN(bdp, 0);
529 CBDW_SC(bdp, (i < fep->tx_ring - 1) ? 0 : BD_SC_WRAP);
530 }
531}
532
533void fs_cleanup_bds(struct net_device *dev)
534{
535 struct fs_enet_private *fep = netdev_priv(dev);
536 struct sk_buff *skb;
Pantelis Antoniou34e30d62005-10-30 01:22:40 +0300537 cbd_t *bdp;
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400538 int i;
539
540 /*
Vitaly Bordug9b8ee8e2007-09-18 20:05:35 +0400541 * Reset SKB transmit buffers.
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400542 */
Pantelis Antoniou34e30d62005-10-30 01:22:40 +0300543 for (i = 0, bdp = fep->tx_bd_base; i < fep->tx_ring; i++, bdp++) {
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400544 if ((skb = fep->tx_skbuff[i]) == NULL)
545 continue;
546
547 /* unmap */
Pantelis Antoniou34e30d62005-10-30 01:22:40 +0300548 dma_unmap_single(fep->dev, CBDR_BUFADDR(bdp),
549 skb->len, DMA_TO_DEVICE);
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400550
551 fep->tx_skbuff[i] = NULL;
552 dev_kfree_skb(skb);
553 }
554
555 /*
Vitaly Bordug9b8ee8e2007-09-18 20:05:35 +0400556 * Reset SKB receive buffers
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400557 */
Pantelis Antoniou34e30d62005-10-30 01:22:40 +0300558 for (i = 0, bdp = fep->rx_bd_base; i < fep->rx_ring; i++, bdp++) {
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400559 if ((skb = fep->rx_skbuff[i]) == NULL)
560 continue;
561
562 /* unmap */
Pantelis Antoniou34e30d62005-10-30 01:22:40 +0300563 dma_unmap_single(fep->dev, CBDR_BUFADDR(bdp),
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400564 L1_CACHE_ALIGN(PKT_MAXBUF_SIZE),
565 DMA_FROM_DEVICE);
566
567 fep->rx_skbuff[i] = NULL;
568
569 dev_kfree_skb(skb);
570 }
571}
572
573/**********************************************************************************/
574
575static int fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
576{
577 struct fs_enet_private *fep = netdev_priv(dev);
578 cbd_t *bdp;
579 int curidx;
580 u16 sc;
581 unsigned long flags;
582
583 spin_lock_irqsave(&fep->tx_lock, flags);
584
585 /*
Vitaly Bordug9b8ee8e2007-09-18 20:05:35 +0400586 * Fill in a Tx ring entry
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400587 */
588 bdp = fep->cur_tx;
589
590 if (!fep->tx_free || (CBDR_SC(bdp) & BD_ENET_TX_READY)) {
591 netif_stop_queue(dev);
592 spin_unlock_irqrestore(&fep->tx_lock, flags);
593
594 /*
595 * Ooops. All transmit buffers are full. Bail out.
596 * This should not happen, since the tx queue should be stopped.
597 */
598 printk(KERN_WARNING DRV_MODULE_NAME
599 ": %s tx queue full!.\n", dev->name);
600 return NETDEV_TX_BUSY;
601 }
602
603 curidx = bdp - fep->tx_bd_base;
604 /*
Vitaly Bordug9b8ee8e2007-09-18 20:05:35 +0400605 * Clear all of the status flags.
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400606 */
607 CBDC_SC(bdp, BD_ENET_TX_STATS);
608
609 /*
Vitaly Bordug9b8ee8e2007-09-18 20:05:35 +0400610 * Save skb pointer.
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400611 */
612 fep->tx_skbuff[curidx] = skb;
613
614 fep->stats.tx_bytes += skb->len;
615
616 /*
Vitaly Bordug9b8ee8e2007-09-18 20:05:35 +0400617 * Push the data cache so the CPM does not get stale memory data.
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400618 */
619 CBDW_BUFADDR(bdp, dma_map_single(fep->dev,
620 skb->data, skb->len, DMA_TO_DEVICE));
621 CBDW_DATLEN(bdp, skb->len);
622
623 dev->trans_start = jiffies;
624
625 /*
Vitaly Bordug9b8ee8e2007-09-18 20:05:35 +0400626 * If this was the last BD in the ring, start at the beginning again.
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400627 */
628 if ((CBDR_SC(bdp) & BD_ENET_TX_WRAP) == 0)
629 fep->cur_tx++;
630 else
631 fep->cur_tx = fep->tx_bd_base;
632
633 if (!--fep->tx_free)
634 netif_stop_queue(dev);
635
636 /* Trigger transmission start */
637 sc = BD_ENET_TX_READY | BD_ENET_TX_INTR |
638 BD_ENET_TX_LAST | BD_ENET_TX_TC;
639
640 /* note that while FEC does not have this bit
641 * it marks it as available for software use
642 * yay for hw reuse :) */
643 if (skb->len <= 60)
644 sc |= BD_ENET_TX_PAD;
645 CBDS_SC(bdp, sc);
646
647 (*fep->ops->tx_kickstart)(dev);
648
649 spin_unlock_irqrestore(&fep->tx_lock, flags);
650
651 return NETDEV_TX_OK;
652}
653
654static int fs_request_irq(struct net_device *dev, int irq, const char *name,
David Howells7d12e782006-10-05 14:55:46 +0100655 irq_handler_t irqf)
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400656{
657 struct fs_enet_private *fep = netdev_priv(dev);
658
659 (*fep->ops->pre_request_irq)(dev, irq);
Thomas Gleixner1fb9df52006-07-01 19:29:39 -0700660 return request_irq(irq, irqf, IRQF_SHARED, name, dev);
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400661}
662
663static void fs_free_irq(struct net_device *dev, int irq)
664{
665 struct fs_enet_private *fep = netdev_priv(dev);
666
667 free_irq(irq, dev);
668 (*fep->ops->post_free_irq)(dev, irq);
669}
670
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400671static void fs_timeout(struct net_device *dev)
672{
673 struct fs_enet_private *fep = netdev_priv(dev);
674 unsigned long flags;
675 int wake = 0;
676
677 fep->stats.tx_errors++;
678
679 spin_lock_irqsave(&fep->lock, flags);
680
681 if (dev->flags & IFF_UP) {
Vitaly Bordug5b4b8452006-08-14 23:00:30 -0700682 phy_stop(fep->phydev);
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400683 (*fep->ops->stop)(dev);
684 (*fep->ops->restart)(dev);
Vitaly Bordug5b4b8452006-08-14 23:00:30 -0700685 phy_start(fep->phydev);
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400686 }
687
Vitaly Bordug5b4b8452006-08-14 23:00:30 -0700688 phy_start(fep->phydev);
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400689 wake = fep->tx_free && !(CBDR_SC(fep->cur_tx) & BD_ENET_TX_READY);
690 spin_unlock_irqrestore(&fep->lock, flags);
691
692 if (wake)
693 netif_wake_queue(dev);
694}
695
Vitaly Bordug5b4b8452006-08-14 23:00:30 -0700696/*-----------------------------------------------------------------------------
697 * generic link-change handler - should be sufficient for most cases
698 *-----------------------------------------------------------------------------*/
699static void generic_adjust_link(struct net_device *dev)
700{
Scott Wood0fb300f2007-10-01 14:20:17 -0500701 struct fs_enet_private *fep = netdev_priv(dev);
702 struct phy_device *phydev = fep->phydev;
703 int new_state = 0;
Vitaly Bordug5b4b8452006-08-14 23:00:30 -0700704
Scott Wood0fb300f2007-10-01 14:20:17 -0500705 if (phydev->link) {
706 /* adjust to duplex mode */
707 if (phydev->duplex != fep->oldduplex) {
708 new_state = 1;
709 fep->oldduplex = phydev->duplex;
710 }
Vitaly Bordug5b4b8452006-08-14 23:00:30 -0700711
Scott Wood0fb300f2007-10-01 14:20:17 -0500712 if (phydev->speed != fep->oldspeed) {
713 new_state = 1;
714 fep->oldspeed = phydev->speed;
715 }
Vitaly Bordug5b4b8452006-08-14 23:00:30 -0700716
Scott Wood0fb300f2007-10-01 14:20:17 -0500717 if (!fep->oldlink) {
718 new_state = 1;
719 fep->oldlink = 1;
720 netif_schedule(dev);
721 netif_carrier_on(dev);
722 netif_start_queue(dev);
723 }
Vitaly Bordug5b4b8452006-08-14 23:00:30 -0700724
Scott Wood0fb300f2007-10-01 14:20:17 -0500725 if (new_state)
726 fep->ops->restart(dev);
727 } else if (fep->oldlink) {
728 new_state = 1;
729 fep->oldlink = 0;
730 fep->oldspeed = 0;
731 fep->oldduplex = -1;
732 netif_carrier_off(dev);
733 netif_stop_queue(dev);
734 }
Vitaly Bordug5b4b8452006-08-14 23:00:30 -0700735
Scott Wood0fb300f2007-10-01 14:20:17 -0500736 if (new_state && netif_msg_link(fep))
737 phy_print_status(phydev);
Vitaly Bordug5b4b8452006-08-14 23:00:30 -0700738}
739
740
741static void fs_adjust_link(struct net_device *dev)
742{
743 struct fs_enet_private *fep = netdev_priv(dev);
744 unsigned long flags;
745
746 spin_lock_irqsave(&fep->lock, flags);
747
748 if(fep->ops->adjust_link)
749 fep->ops->adjust_link(dev);
750 else
751 generic_adjust_link(dev);
752
753 spin_unlock_irqrestore(&fep->lock, flags);
754}
755
756static int fs_init_phy(struct net_device *dev)
757{
758 struct fs_enet_private *fep = netdev_priv(dev);
759 struct phy_device *phydev;
760
761 fep->oldlink = 0;
762 fep->oldspeed = 0;
763 fep->oldduplex = -1;
764 if(fep->fpi->bus_id)
Andy Fleminge8a2b6a2006-12-01 12:01:06 -0600765 phydev = phy_connect(dev, fep->fpi->bus_id, &fs_adjust_link, 0,
766 PHY_INTERFACE_MODE_MII);
Vitaly Bordug5b4b8452006-08-14 23:00:30 -0700767 else {
768 printk("No phy bus ID specified in BSP code\n");
769 return -EINVAL;
770 }
771 if (IS_ERR(phydev)) {
772 printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
773 return PTR_ERR(phydev);
774 }
775
776 fep->phydev = phydev;
777
778 return 0;
779}
780
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400781static int fs_enet_open(struct net_device *dev)
782{
783 struct fs_enet_private *fep = netdev_priv(dev);
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400784 int r;
Vitaly Bordug5b4b8452006-08-14 23:00:30 -0700785 int err;
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400786
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700787 napi_enable(&fep->napi);
788
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400789 /* Install our interrupt handler. */
790 r = fs_request_irq(dev, fep->interrupt, "fs_enet-mac", fs_enet_interrupt);
791 if (r != 0) {
792 printk(KERN_ERR DRV_MODULE_NAME
Vitaly Bordug5b4b8452006-08-14 23:00:30 -0700793 ": %s Could not allocate FS_ENET IRQ!", dev->name);
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700794 napi_disable(&fep->napi);
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400795 return -EINVAL;
796 }
797
Vitaly Bordug5b4b8452006-08-14 23:00:30 -0700798 err = fs_init_phy(dev);
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700799 if(err) {
800 napi_disable(&fep->napi);
Vitaly Bordug5b4b8452006-08-14 23:00:30 -0700801 return err;
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700802 }
Vitaly Bordug5b4b8452006-08-14 23:00:30 -0700803 phy_start(fep->phydev);
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400804
805 return 0;
806}
807
808static int fs_enet_close(struct net_device *dev)
809{
810 struct fs_enet_private *fep = netdev_priv(dev);
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400811 unsigned long flags;
812
813 netif_stop_queue(dev);
814 netif_carrier_off(dev);
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700815 napi_disable(&fep->napi);
Vitaly Bordug5b4b8452006-08-14 23:00:30 -0700816 phy_stop(fep->phydev);
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400817
818 spin_lock_irqsave(&fep->lock, flags);
Vitaly Bordugaa90f502007-09-18 20:05:27 +0400819 spin_lock(&fep->tx_lock);
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400820 (*fep->ops->stop)(dev);
Vitaly Bordugaa90f502007-09-18 20:05:27 +0400821 spin_unlock(&fep->tx_lock);
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400822 spin_unlock_irqrestore(&fep->lock, flags);
823
824 /* release any irqs */
Vitaly Bordug5b4b8452006-08-14 23:00:30 -0700825 phy_disconnect(fep->phydev);
826 fep->phydev = NULL;
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400827 fs_free_irq(dev, fep->interrupt);
828
829 return 0;
830}
831
832static struct net_device_stats *fs_enet_get_stats(struct net_device *dev)
833{
834 struct fs_enet_private *fep = netdev_priv(dev);
835 return &fep->stats;
836}
837
838/*************************************************************************/
839
840static void fs_get_drvinfo(struct net_device *dev,
841 struct ethtool_drvinfo *info)
842{
843 strcpy(info->driver, DRV_MODULE_NAME);
844 strcpy(info->version, DRV_MODULE_VERSION);
845}
846
847static int fs_get_regs_len(struct net_device *dev)
848{
849 struct fs_enet_private *fep = netdev_priv(dev);
850
851 return (*fep->ops->get_regs_len)(dev);
852}
853
854static void fs_get_regs(struct net_device *dev, struct ethtool_regs *regs,
855 void *p)
856{
857 struct fs_enet_private *fep = netdev_priv(dev);
858 unsigned long flags;
859 int r, len;
860
861 len = regs->len;
862
863 spin_lock_irqsave(&fep->lock, flags);
864 r = (*fep->ops->get_regs)(dev, p, &len);
865 spin_unlock_irqrestore(&fep->lock, flags);
866
867 if (r == 0)
868 regs->version = 0;
869}
870
871static int fs_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
872{
873 struct fs_enet_private *fep = netdev_priv(dev);
Vitaly Bordug5b4b8452006-08-14 23:00:30 -0700874 return phy_ethtool_gset(fep->phydev, cmd);
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400875}
876
877static int fs_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
878{
879 struct fs_enet_private *fep = netdev_priv(dev);
Vitaly Bordug5b4b8452006-08-14 23:00:30 -0700880 phy_ethtool_sset(fep->phydev, cmd);
881 return 0;
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400882}
883
884static int fs_nway_reset(struct net_device *dev)
885{
Vitaly Bordug5b4b8452006-08-14 23:00:30 -0700886 return 0;
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400887}
888
889static u32 fs_get_msglevel(struct net_device *dev)
890{
891 struct fs_enet_private *fep = netdev_priv(dev);
892 return fep->msg_enable;
893}
894
895static void fs_set_msglevel(struct net_device *dev, u32 value)
896{
897 struct fs_enet_private *fep = netdev_priv(dev);
898 fep->msg_enable = value;
899}
900
Jeff Garzik7282d492006-09-13 14:30:00 -0400901static const struct ethtool_ops fs_ethtool_ops = {
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400902 .get_drvinfo = fs_get_drvinfo,
903 .get_regs_len = fs_get_regs_len,
904 .get_settings = fs_get_settings,
905 .set_settings = fs_set_settings,
906 .nway_reset = fs_nway_reset,
907 .get_link = ethtool_op_get_link,
908 .get_msglevel = fs_get_msglevel,
909 .set_msglevel = fs_set_msglevel,
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400910 .set_tx_csum = ethtool_op_set_tx_csum, /* local! */
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400911 .set_sg = ethtool_op_set_sg,
912 .get_regs = fs_get_regs,
913};
914
915static int fs_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
916{
917 struct fs_enet_private *fep = netdev_priv(dev);
918 struct mii_ioctl_data *mii = (struct mii_ioctl_data *)&rq->ifr_data;
919 unsigned long flags;
920 int rc;
921
922 if (!netif_running(dev))
923 return -EINVAL;
924
925 spin_lock_irqsave(&fep->lock, flags);
Vitaly Bordug5b4b8452006-08-14 23:00:30 -0700926 rc = phy_mii_ioctl(fep->phydev, mii, cmd);
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400927 spin_unlock_irqrestore(&fep->lock, flags);
928 return rc;
929}
930
931extern int fs_mii_connect(struct net_device *dev);
932extern void fs_mii_disconnect(struct net_device *dev);
933
934static struct net_device *fs_init_instance(struct device *dev,
Vitaly Bordug611a15a2006-09-21 22:38:05 +0400935 struct fs_platform_info *fpi)
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400936{
937 struct net_device *ndev = NULL;
938 struct fs_enet_private *fep = NULL;
939 int privsize, i, r, err = 0, registered = 0;
940
Vitaly Bordug611a15a2006-09-21 22:38:05 +0400941 fpi->fs_no = fs_get_id(fpi);
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400942 /* guard */
943 if ((unsigned int)fpi->fs_no >= FS_MAX_INDEX)
944 return ERR_PTR(-EINVAL);
945
946 privsize = sizeof(*fep) + (sizeof(struct sk_buff **) *
947 (fpi->rx_ring + fpi->tx_ring));
948
949 ndev = alloc_etherdev(privsize);
950 if (!ndev) {
951 err = -ENOMEM;
952 goto err;
953 }
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400954
955 fep = netdev_priv(ndev);
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400956
957 fep->dev = dev;
958 dev_set_drvdata(dev, ndev);
959 fep->fpi = fpi;
960 if (fpi->init_ioports)
Vitaly Bordugd3465c92006-09-21 22:38:05 +0400961 fpi->init_ioports((struct fs_platform_info *)fpi);
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400962
963#ifdef CONFIG_FS_ENET_HAS_FEC
964 if (fs_get_fec_index(fpi->fs_no) >= 0)
965 fep->ops = &fs_fec_ops;
966#endif
967
968#ifdef CONFIG_FS_ENET_HAS_SCC
Scott Wood0fb300f2007-10-01 14:20:17 -0500969 if (fs_get_scc_index(fpi->fs_no) >=0)
Pantelis Antoniou48257c42005-10-28 16:25:58 -0400970 fep->ops = &fs_scc_ops;
971#endif
972
973#ifdef CONFIG_FS_ENET_HAS_FCC
974 if (fs_get_fcc_index(fpi->fs_no) >= 0)
975 fep->ops = &fs_fcc_ops;
976#endif
977
978 if (fep->ops == NULL) {
979 printk(KERN_ERR DRV_MODULE_NAME
980 ": %s No matching ops found (%d).\n",
981 ndev->name, fpi->fs_no);
982 err = -EINVAL;
983 goto err;
984 }
985
986 r = (*fep->ops->setup_data)(ndev);
987 if (r != 0) {
988 printk(KERN_ERR DRV_MODULE_NAME
989 ": %s setup_data failed\n",
990 ndev->name);
991 err = r;
992 goto err;
993 }
994
995 /* point rx_skbuff, tx_skbuff */
996 fep->rx_skbuff = (struct sk_buff **)&fep[1];
997 fep->tx_skbuff = fep->rx_skbuff + fpi->rx_ring;
998
999 /* init locks */
1000 spin_lock_init(&fep->lock);
1001 spin_lock_init(&fep->tx_lock);
1002
1003 /*
Vitaly Bordug9b8ee8e2007-09-18 20:05:35 +04001004 * Set the Ethernet address.
Pantelis Antoniou48257c42005-10-28 16:25:58 -04001005 */
1006 for (i = 0; i < 6; i++)
1007 ndev->dev_addr[i] = fpi->macaddr[i];
Vitaly Bordug9b8ee8e2007-09-18 20:05:35 +04001008
Pantelis Antoniou48257c42005-10-28 16:25:58 -04001009 r = (*fep->ops->allocate_bd)(ndev);
Vitaly Bordug9b8ee8e2007-09-18 20:05:35 +04001010
Pantelis Antoniou48257c42005-10-28 16:25:58 -04001011 if (fep->ring_base == NULL) {
1012 printk(KERN_ERR DRV_MODULE_NAME
1013 ": %s buffer descriptor alloc failed (%d).\n", ndev->name, r);
1014 err = r;
1015 goto err;
1016 }
1017
1018 /*
1019 * Set receive and transmit descriptor base.
1020 */
1021 fep->rx_bd_base = fep->ring_base;
1022 fep->tx_bd_base = fep->rx_bd_base + fpi->rx_ring;
1023
1024 /* initialize ring size variables */
1025 fep->tx_ring = fpi->tx_ring;
1026 fep->rx_ring = fpi->rx_ring;
1027
1028 /*
Vitaly Bordug9b8ee8e2007-09-18 20:05:35 +04001029 * The FEC Ethernet specific entries in the device structure.
Pantelis Antoniou48257c42005-10-28 16:25:58 -04001030 */
1031 ndev->open = fs_enet_open;
1032 ndev->hard_start_xmit = fs_enet_start_xmit;
1033 ndev->tx_timeout = fs_timeout;
1034 ndev->watchdog_timeo = 2 * HZ;
1035 ndev->stop = fs_enet_close;
1036 ndev->get_stats = fs_enet_get_stats;
1037 ndev->set_multicast_list = fs_set_multicast_list;
Vitaly Bordug9b8ee8e2007-09-18 20:05:35 +04001038
1039#ifdef CONFIG_NET_POLL_CONTROLLER
1040 ndev->poll_controller = fs_enet_netpoll;
1041#endif
1042
Stephen Hemmingerbea33482007-10-03 16:41:36 -07001043 netif_napi_add(ndev, &fep->napi,
1044 fs_enet_rx_napi, fpi->napi_weight);
1045
Pantelis Antoniou48257c42005-10-28 16:25:58 -04001046 ndev->ethtool_ops = &fs_ethtool_ops;
1047 ndev->do_ioctl = fs_ioctl;
1048
1049 init_timer(&fep->phy_timer_list);
1050
1051 netif_carrier_off(ndev);
1052
1053 err = register_netdev(ndev);
1054 if (err != 0) {
1055 printk(KERN_ERR DRV_MODULE_NAME
1056 ": %s register_netdev failed.\n", ndev->name);
1057 goto err;
1058 }
1059 registered = 1;
1060
Pantelis Antoniou48257c42005-10-28 16:25:58 -04001061
1062 return ndev;
1063
Scott Wood0fb300f2007-10-01 14:20:17 -05001064err:
Pantelis Antoniou48257c42005-10-28 16:25:58 -04001065 if (ndev != NULL) {
Pantelis Antoniou48257c42005-10-28 16:25:58 -04001066 if (registered)
1067 unregister_netdev(ndev);
1068
1069 if (fep != NULL) {
1070 (*fep->ops->free_bd)(ndev);
1071 (*fep->ops->cleanup_data)(ndev);
1072 }
1073
1074 free_netdev(ndev);
1075 }
1076
1077 dev_set_drvdata(dev, NULL);
1078
1079 return ERR_PTR(err);
1080}
1081
1082static int fs_cleanup_instance(struct net_device *ndev)
1083{
1084 struct fs_enet_private *fep;
1085 const struct fs_platform_info *fpi;
1086 struct device *dev;
1087
1088 if (ndev == NULL)
1089 return -EINVAL;
1090
1091 fep = netdev_priv(ndev);
1092 if (fep == NULL)
1093 return -EINVAL;
1094
1095 fpi = fep->fpi;
1096
Pantelis Antoniou48257c42005-10-28 16:25:58 -04001097 unregister_netdev(ndev);
1098
1099 dma_free_coherent(fep->dev, (fpi->tx_ring + fpi->rx_ring) * sizeof(cbd_t),
1100 fep->ring_base, fep->ring_mem_addr);
1101
1102 /* reset it */
1103 (*fep->ops->cleanup_data)(ndev);
1104
1105 dev = fep->dev;
1106 if (dev != NULL) {
1107 dev_set_drvdata(dev, NULL);
1108 fep->dev = NULL;
1109 }
1110
1111 free_netdev(ndev);
1112
1113 return 0;
1114}
1115
1116/**************************************************************************************/
1117
1118/* handy pointer to the immap */
1119void *fs_enet_immap = NULL;
1120
1121static int setup_immap(void)
1122{
1123 phys_addr_t paddr = 0;
1124 unsigned long size = 0;
1125
1126#ifdef CONFIG_CPM1
1127 paddr = IMAP_ADDR;
1128 size = 0x10000; /* map 64K */
1129#endif
1130
1131#ifdef CONFIG_CPM2
1132 paddr = CPM_MAP_ADDR;
1133 size = 0x40000; /* map 256 K */
1134#endif
1135 fs_enet_immap = ioremap(paddr, size);
1136 if (fs_enet_immap == NULL)
1137 return -EBADF; /* XXX ahem; maybe just BUG_ON? */
1138
1139 return 0;
1140}
1141
1142static void cleanup_immap(void)
1143{
1144 if (fs_enet_immap != NULL) {
1145 iounmap(fs_enet_immap);
1146 fs_enet_immap = NULL;
1147 }
1148}
1149
1150/**************************************************************************************/
1151
1152static int __devinit fs_enet_probe(struct device *dev)
1153{
1154 struct net_device *ndev;
1155
1156 /* no fixup - no device */
1157 if (dev->platform_data == NULL) {
1158 printk(KERN_INFO "fs_enet: "
1159 "probe called with no platform data; "
1160 "remove unused devices\n");
1161 return -ENODEV;
1162 }
1163
1164 ndev = fs_init_instance(dev, dev->platform_data);
1165 if (IS_ERR(ndev))
1166 return PTR_ERR(ndev);
1167 return 0;
1168}
1169
1170static int fs_enet_remove(struct device *dev)
1171{
1172 return fs_cleanup_instance(dev_get_drvdata(dev));
1173}
1174
1175static struct device_driver fs_enet_fec_driver = {
1176 .name = "fsl-cpm-fec",
1177 .bus = &platform_bus_type,
1178 .probe = fs_enet_probe,
1179 .remove = fs_enet_remove,
1180#ifdef CONFIG_PM
1181/* .suspend = fs_enet_suspend, TODO */
1182/* .resume = fs_enet_resume, TODO */
1183#endif
1184};
1185
1186static struct device_driver fs_enet_scc_driver = {
1187 .name = "fsl-cpm-scc",
1188 .bus = &platform_bus_type,
1189 .probe = fs_enet_probe,
1190 .remove = fs_enet_remove,
1191#ifdef CONFIG_PM
1192/* .suspend = fs_enet_suspend, TODO */
1193/* .resume = fs_enet_resume, TODO */
1194#endif
1195};
1196
1197static struct device_driver fs_enet_fcc_driver = {
1198 .name = "fsl-cpm-fcc",
1199 .bus = &platform_bus_type,
1200 .probe = fs_enet_probe,
1201 .remove = fs_enet_remove,
1202#ifdef CONFIG_PM
1203/* .suspend = fs_enet_suspend, TODO */
1204/* .resume = fs_enet_resume, TODO */
1205#endif
1206};
1207
1208static int __init fs_init(void)
1209{
1210 int r;
1211
1212 printk(KERN_INFO
1213 "%s", version);
1214
1215 r = setup_immap();
1216 if (r != 0)
1217 return r;
Pantelis Antoniou48257c42005-10-28 16:25:58 -04001218
Vitaly Bordug5b4b8452006-08-14 23:00:30 -07001219#ifdef CONFIG_FS_ENET_HAS_FCC
1220 /* let's insert mii stuff */
1221 r = fs_enet_mdio_bb_init();
1222
1223 if (r != 0) {
1224 printk(KERN_ERR DRV_MODULE_NAME
1225 "BB PHY init failed.\n");
1226 return r;
1227 }
Pantelis Antoniou48257c42005-10-28 16:25:58 -04001228 r = driver_register(&fs_enet_fcc_driver);
1229 if (r != 0)
1230 goto err;
Vitaly Bordug5b4b8452006-08-14 23:00:30 -07001231#endif
Pantelis Antoniou48257c42005-10-28 16:25:58 -04001232
Vitaly Bordug5b4b8452006-08-14 23:00:30 -07001233#ifdef CONFIG_FS_ENET_HAS_FEC
1234 r = fs_enet_mdio_fec_init();
1235 if (r != 0) {
1236 printk(KERN_ERR DRV_MODULE_NAME
1237 "FEC PHY init failed.\n");
1238 return r;
1239 }
1240
1241 r = driver_register(&fs_enet_fec_driver);
1242 if (r != 0)
1243 goto err;
1244#endif
1245
1246#ifdef CONFIG_FS_ENET_HAS_SCC
Pantelis Antoniou48257c42005-10-28 16:25:58 -04001247 r = driver_register(&fs_enet_scc_driver);
1248 if (r != 0)
1249 goto err;
Vitaly Bordug5b4b8452006-08-14 23:00:30 -07001250#endif
Pantelis Antoniou48257c42005-10-28 16:25:58 -04001251
1252 return 0;
1253err:
1254 cleanup_immap();
1255 return r;
Pantelis Antoniou48257c42005-10-28 16:25:58 -04001256}
1257
1258static void __exit fs_cleanup(void)
1259{
1260 driver_unregister(&fs_enet_fec_driver);
1261 driver_unregister(&fs_enet_fcc_driver);
1262 driver_unregister(&fs_enet_scc_driver);
1263 cleanup_immap();
1264}
1265
Vitaly Bordug9b8ee8e2007-09-18 20:05:35 +04001266#ifdef CONFIG_NET_POLL_CONTROLLER
1267static void fs_enet_netpoll(struct net_device *dev)
1268{
1269 disable_irq(dev->irq);
1270 fs_enet_interrupt(dev->irq, dev, NULL);
1271 enable_irq(dev->irq);
1272}
1273#endif
1274
Pantelis Antoniou48257c42005-10-28 16:25:58 -04001275/**************************************************************************************/
1276
1277module_init(fs_init);
1278module_exit(fs_cleanup);