fs_enet-main.c 25.7 KB
Newer Older
1 2 3
/*
 * Combined Ethernet driver for Motorola MPC8xx and MPC82xx.
 *
Vitaly Bordug's avatar
Vitaly Bordug committed
4
 * Copyright (c) 2003 Intracom S.A.
5
 *  by Pantelis Antoniou <panto@intracom.gr>
Vitaly Bordug's avatar
Vitaly Bordug committed
6 7
 *
 * 2005 (c) MontaVista Software, Inc.
8 9 10 11 12
 * Vitaly Bordug <vbordug@ru.mvista.com>
 *
 * Heavily based on original FEC driver by Dan Malek <dan@embeddededge.com>
 * and modifications by Joakim Tjernlund <joakim.tjernlund@lumentis.se>
 *
Vitaly Bordug's avatar
Vitaly Bordug committed
13 14
 * This file is licensed under the terms of the GNU General Public License
 * version 2. This program is licensed "as is" without any warranty of any
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
 * kind, whether express or implied.
 */

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/string.h>
#include <linux/ptrace.h>
#include <linux/errno.h>
#include <linux/ioport.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/spinlock.h>
#include <linux/mii.h>
#include <linux/ethtool.h>
#include <linux/bitops.h>
#include <linux/fs.h>
Marcelo Tosatti's avatar
Marcelo Tosatti committed
36
#include <linux/platform_device.h>
37
#include <linux/phy.h>
38 39
#include <linux/of.h>
#include <linux/of_mdio.h>
40
#include <linux/of_platform.h>
41
#include <linux/of_gpio.h>
42
#include <linux/of_net.h>
43
#include <linux/pgtable.h>
44 45 46

#include <linux/vmalloc.h>
#include <asm/irq.h>
47
#include <linux/uaccess.h>
48 49 50 51 52 53 54 55 56

#include "fs_enet.h"

/*************************************************/

MODULE_AUTHOR("Pantelis Antoniou <panto@intracom.gr>");
MODULE_DESCRIPTION("Freescale Ethernet Driver");
MODULE_LICENSE("GPL");

Scott Wood's avatar
Scott Wood committed
57
static int fs_enet_debug = -1; /* -1 == use FS_ENET_DEF_MSG_ENABLE as value */
Rusty Russell's avatar
Rusty Russell committed
58
module_param(fs_enet_debug, int, 0);
59 60 61
MODULE_PARM_DESC(fs_enet_debug,
		 "Freescale bitmapped debugging message enable value");

62 63 64
#define RX_RING_SIZE	32
#define TX_RING_SIZE	64

Vitaly Bordug's avatar
Vitaly Bordug committed
65 66 67
#ifdef CONFIG_NET_POLL_CONTROLLER
static void fs_enet_netpoll(struct net_device *dev);
#endif
68 69 70 71 72 73 74 75

static void fs_set_multicast_list(struct net_device *dev)
{
	struct fs_enet_private *fep = netdev_priv(dev);

	(*fep->ops->set_multicast_list)(dev);
}

Scott Wood's avatar
Scott Wood committed
76 77 78 79 80 81 82 83
static void skb_align(struct sk_buff *skb, int align)
{
	int off = ((unsigned long)skb->data) & (align - 1);

	if (off)
		skb_reserve(skb, align - off);
}

84 85
/* NAPI function */
static int fs_enet_napi(struct napi_struct *napi, int budget)
86
{
87
	struct fs_enet_private *fep = container_of(napi, struct fs_enet_private, napi);
Scott Wood's avatar
Scott Wood committed
88
	struct net_device *dev = fep->ndev;
89
	const struct fs_platform_info *fpi = fep->fpi;
Scott Wood's avatar
Scott Wood committed
90
	cbd_t __iomem *bdp;
91
	struct sk_buff *skb, *skbn;
92 93 94
	int received = 0;
	u16 pkt_len, sc;
	int curidx;
95 96
	int dirtyidx, do_wake, do_restart;
	int tx_left = TX_RING_SIZE;
97

98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
	spin_lock(&fep->tx_lock);
	bdp = fep->dirty_tx;

	/* clear status bits for napi*/
	(*fep->ops->napi_clear_event)(dev);

	do_wake = do_restart = 0;
	while (((sc = CBDR_SC(bdp)) & BD_ENET_TX_READY) == 0 && tx_left) {
		dirtyidx = bdp - fep->tx_bd_base;

		if (fep->tx_free == fep->tx_ring)
			break;

		skb = fep->tx_skbuff[dirtyidx];

		/*
		 * Check for errors.
		 */
		if (sc & (BD_ENET_TX_HB | BD_ENET_TX_LC |
			  BD_ENET_TX_RL | BD_ENET_TX_UN | BD_ENET_TX_CSL)) {

			if (sc & BD_ENET_TX_HB)	/* No heartbeat */
120
				dev->stats.tx_heartbeat_errors++;
121
			if (sc & BD_ENET_TX_LC)	/* Late collision */
122
				dev->stats.tx_window_errors++;
123
			if (sc & BD_ENET_TX_RL)	/* Retrans limit */
124
				dev->stats.tx_aborted_errors++;
125
			if (sc & BD_ENET_TX_UN)	/* Underrun */
126
				dev->stats.tx_fifo_errors++;
127
			if (sc & BD_ENET_TX_CSL)	/* Carrier lost */
128
				dev->stats.tx_carrier_errors++;
129 130

			if (sc & (BD_ENET_TX_LC | BD_ENET_TX_RL | BD_ENET_TX_UN)) {
131
				dev->stats.tx_errors++;
132 133 134
				do_restart = 1;
			}
		} else
135
			dev->stats.tx_packets++;
136 137 138 139 140 141 142 143 144 145 146

		if (sc & BD_ENET_TX_READY) {
			dev_warn(fep->dev,
				 "HEY! Enet xmit interrupt and TX_READY.\n");
		}

		/*
		 * Deferred means some collisions occurred during transmit,
		 * but we eventually sent the packet OK.
		 */
		if (sc & BD_ENET_TX_DEF)
147
			dev->stats.collisions++;
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190

		/* unmap */
		if (fep->mapped_as_page[dirtyidx])
			dma_unmap_page(fep->dev, CBDR_BUFADDR(bdp),
				       CBDR_DATLEN(bdp), DMA_TO_DEVICE);
		else
			dma_unmap_single(fep->dev, CBDR_BUFADDR(bdp),
					 CBDR_DATLEN(bdp), DMA_TO_DEVICE);

		/*
		 * Free the sk buffer associated with this last transmit.
		 */
		if (skb) {
			dev_kfree_skb(skb);
			fep->tx_skbuff[dirtyidx] = NULL;
		}

		/*
		 * Update pointer to next buffer descriptor to be transmitted.
		 */
		if ((sc & BD_ENET_TX_WRAP) == 0)
			bdp++;
		else
			bdp = fep->tx_bd_base;

		/*
		 * Since we have freed up a buffer, the ring is no longer
		 * full.
		 */
		if (++fep->tx_free == MAX_SKB_FRAGS)
			do_wake = 1;
		tx_left--;
	}

	fep->dirty_tx = bdp;

	if (do_restart)
		(*fep->ops->tx_restart)(dev);

	spin_unlock(&fep->tx_lock);

	if (do_wake)
		netif_wake_queue(dev);
191

192 193 194 195 196 197
	/*
	 * First, grab all of the stats for the incoming packet.
	 * These get messed up if we get called due to a busy condition.
	 */
	bdp = fep->cur_rx;

198 199
	while (((sc = CBDR_SC(bdp)) & BD_ENET_RX_EMPTY) == 0 &&
	       received < budget) {
200 201 202 203 204 205 206
		curidx = bdp - fep->rx_bd_base;

		/*
		 * Since we have allocated space to hold a complete frame,
		 * the last indicator should be set.
		 */
		if ((sc & BD_ENET_RX_LAST) == 0)
207
			dev_warn(fep->dev, "rcv is not +last\n");
208 209

		/*
Vitaly Bordug's avatar
Vitaly Bordug committed
210
		 * Check for errors.
211 212 213
		 */
		if (sc & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_CL |
			  BD_ENET_RX_NO | BD_ENET_RX_CR | BD_ENET_RX_OV)) {
214
			dev->stats.rx_errors++;
215 216
			/* Frame too long or too short. */
			if (sc & (BD_ENET_RX_LG | BD_ENET_RX_SH))
217
				dev->stats.rx_length_errors++;
218 219
			/* Frame alignment */
			if (sc & (BD_ENET_RX_NO | BD_ENET_RX_CL))
220
				dev->stats.rx_frame_errors++;
221 222
			/* CRC Error */
			if (sc & BD_ENET_RX_CR)
223
				dev->stats.rx_crc_errors++;
224 225
			/* FIFO overrun */
			if (sc & BD_ENET_RX_OV)
226
				dev->stats.rx_crc_errors++;
227

228
			skbn = fep->rx_skbuff[curidx];
229 230 231 232 233 234
		} else {
			skb = fep->rx_skbuff[curidx];

			/*
			 * Process the incoming frame.
			 */
235
			dev->stats.rx_packets++;
236
			pkt_len = CBDR_DATLEN(bdp) - 4;	/* remove CRC */
237
			dev->stats.rx_bytes += pkt_len + 4;
238 239 240

			if (pkt_len <= fpi->rx_copybreak) {
				/* +2 to make IP header L1 cache aligned */
241
				skbn = netdev_alloc_skb(dev, pkt_len + 2);
242 243
				if (skbn != NULL) {
					skb_reserve(skbn, 2);	/* align IP header */
244 245
					skb_copy_from_linear_data(skb,
						      skbn->data, pkt_len);
246
					swap(skb, skbn);
247 248 249 250
					dma_sync_single_for_cpu(fep->dev,
						CBDR_BUFADDR(bdp),
						L1_CACHE_ALIGN(pkt_len),
						DMA_FROM_DEVICE);
251
				}
Scott Wood's avatar
Scott Wood committed
252
			} else {
253
				skbn = netdev_alloc_skb(dev, ENET_RX_FRSIZE);
254

255 256 257
				if (skbn) {
					dma_addr_t dma;

Scott Wood's avatar
Scott Wood committed
258
					skb_align(skbn, ENET_RX_ALIGN);
259 260 261 262 263 264 265 266 267 268 269 270

					dma_unmap_single(fep->dev,
						CBDR_BUFADDR(bdp),
						L1_CACHE_ALIGN(PKT_MAXBUF_SIZE),
						DMA_FROM_DEVICE);

					dma = dma_map_single(fep->dev,
						skbn->data,
						L1_CACHE_ALIGN(PKT_MAXBUF_SIZE),
						DMA_FROM_DEVICE);
					CBDW_BUFADDR(bdp, dma);
				}
Scott Wood's avatar
Scott Wood committed
271 272
			}

273 274 275 276 277 278
			if (skbn != NULL) {
				skb_put(skb, pkt_len);	/* Make room */
				skb->protocol = eth_type_trans(skb, dev);
				received++;
				netif_receive_skb(skb);
			} else {
279
				dev->stats.rx_dropped++;
280 281 282 283 284 285 286 287 288
				skbn = skb;
			}
		}

		fep->rx_skbuff[curidx] = skbn;
		CBDW_DATLEN(bdp, 0);
		CBDW_SC(bdp, (sc & ~BD_ENET_RX_STATS) | BD_ENET_RX_EMPTY);

		/*
Vitaly Bordug's avatar
Vitaly Bordug committed
289
		 * Update BD pointer to next entry.
290 291 292 293 294 295 296 297 298 299 300
		 */
		if ((sc & BD_ENET_RX_WRAP) == 0)
			bdp++;
		else
			bdp = fep->rx_bd_base;

		(*fep->ops->rx_bd_done)(dev);
	}

	fep->cur_rx = bdp;

301
	if (received < budget && tx_left) {
302
		/* done */
303
		napi_complete_done(napi, received);
304
		(*fep->ops->napi_enable)(dev);
305

306
		return received;
LEROY Christophe's avatar
LEROY Christophe committed
307 308
	}

309
	return budget;
310 311 312 313 314 315 316
}

/*
 * The interrupt handler.
 * This is called from the MPC core interrupt.
 */
static irqreturn_t
317
fs_enet_interrupt(int irq, void *dev_id)
318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334
{
	struct net_device *dev = dev_id;
	struct fs_enet_private *fep;
	const struct fs_platform_info *fpi;
	u32 int_events;
	u32 int_clr_events;
	int nr, napi_ok;
	int handled;

	fep = netdev_priv(dev);
	fpi = fep->fpi;

	nr = 0;
	while ((int_events = (*fep->ops->get_int_events)(dev)) != 0) {
		nr++;

		int_clr_events = int_events;
335
		int_clr_events &= ~fep->ev_napi;
336 337 338 339 340 341

		(*fep->ops->clear_int_events)(dev, int_clr_events);

		if (int_events & fep->ev_err)
			(*fep->ops->ev_error)(dev, int_events);

342
		if (int_events & fep->ev) {
343 344
			napi_ok = napi_schedule_prep(&fep->napi);

345 346
			(*fep->ops->napi_disable)(dev);
			(*fep->ops->clear_int_events)(dev, fep->ev_napi);
347 348 349 350 351

			/* NOTE: it is possible for FCCs in NAPI mode    */
			/* to submit a spurious interrupt while in poll  */
			if (napi_ok)
				__napi_schedule(&fep->napi);
352 353 354 355 356 357 358 359 360 361 362
		}

	}

	handled = nr > 0;
	return IRQ_RETVAL(handled);
}

void fs_init_bds(struct net_device *dev)
{
	struct fs_enet_private *fep = netdev_priv(dev);
Scott Wood's avatar
Scott Wood committed
363
	cbd_t __iomem *bdp;
364 365 366 367 368 369 370 371 372 373
	struct sk_buff *skb;
	int i;

	fs_cleanup_bds(dev);

	fep->dirty_tx = fep->cur_tx = fep->tx_bd_base;
	fep->tx_free = fep->tx_ring;
	fep->cur_rx = fep->rx_bd_base;

	/*
Vitaly Bordug's avatar
Vitaly Bordug committed
374
	 * Initialize the receive buffer descriptors.
375 376
	 */
	for (i = 0, bdp = fep->rx_bd_base; i < fep->rx_ring; i++, bdp++) {
377
		skb = netdev_alloc_skb(dev, ENET_RX_FRSIZE);
378
		if (skb == NULL)
379
			break;
380

Scott Wood's avatar
Scott Wood committed
381
		skb_align(skb, ENET_RX_ALIGN);
382 383 384 385 386 387 388 389 390 391
		fep->rx_skbuff[i] = skb;
		CBDW_BUFADDR(bdp,
			dma_map_single(fep->dev, skb->data,
				L1_CACHE_ALIGN(PKT_MAXBUF_SIZE),
				DMA_FROM_DEVICE));
		CBDW_DATLEN(bdp, 0);	/* zero */
		CBDW_SC(bdp, BD_ENET_RX_EMPTY |
			((i < fep->rx_ring - 1) ? 0 : BD_SC_WRAP));
	}
	/*
Vitaly Bordug's avatar
Vitaly Bordug committed
392
	 * if we failed, fillup remainder
393 394 395 396 397 398 399
	 */
	for (; i < fep->rx_ring; i++, bdp++) {
		fep->rx_skbuff[i] = NULL;
		CBDW_SC(bdp, (i < fep->rx_ring - 1) ? 0 : BD_SC_WRAP);
	}

	/*
Vitaly Bordug's avatar
Vitaly Bordug committed
400
	 * ...and the same for transmit.
401 402 403 404 405 406 407 408 409 410 411 412 413
	 */
	for (i = 0, bdp = fep->tx_bd_base; i < fep->tx_ring; i++, bdp++) {
		fep->tx_skbuff[i] = NULL;
		CBDW_BUFADDR(bdp, 0);
		CBDW_DATLEN(bdp, 0);
		CBDW_SC(bdp, (i < fep->tx_ring - 1) ? 0 : BD_SC_WRAP);
	}
}

void fs_cleanup_bds(struct net_device *dev)
{
	struct fs_enet_private *fep = netdev_priv(dev);
	struct sk_buff *skb;
Scott Wood's avatar
Scott Wood committed
414
	cbd_t __iomem *bdp;
415 416 417
	int i;

	/*
Vitaly Bordug's avatar
Vitaly Bordug committed
418
	 * Reset SKB transmit buffers.
419
	 */
420
	for (i = 0, bdp = fep->tx_bd_base; i < fep->tx_ring; i++, bdp++) {
421 422 423 424
		if ((skb = fep->tx_skbuff[i]) == NULL)
			continue;

		/* unmap */
425 426
		dma_unmap_single(fep->dev, CBDR_BUFADDR(bdp),
				skb->len, DMA_TO_DEVICE);
427 428 429 430 431 432

		fep->tx_skbuff[i] = NULL;
		dev_kfree_skb(skb);
	}

	/*
Vitaly Bordug's avatar
Vitaly Bordug committed
433
	 * Reset SKB receive buffers
434
	 */
435
	for (i = 0, bdp = fep->rx_bd_base; i < fep->rx_ring; i++, bdp++) {
436 437 438 439
		if ((skb = fep->rx_skbuff[i]) == NULL)
			continue;

		/* unmap */
440
		dma_unmap_single(fep->dev, CBDR_BUFADDR(bdp),
441 442 443 444 445 446 447 448 449 450 451
			L1_CACHE_ALIGN(PKT_MAXBUF_SIZE),
			DMA_FROM_DEVICE);

		fep->rx_skbuff[i] = NULL;

		dev_kfree_skb(skb);
	}
}

/**********************************************************************************/

452 453 454 455 456 457 458 459 460
#ifdef CONFIG_FS_ENET_MPC5121_FEC
/*
 * MPC5121 FEC requeries 4-byte alignment for TX data buffer!
 */
static struct sk_buff *tx_skb_align_workaround(struct net_device *dev,
					       struct sk_buff *skb)
{
	struct sk_buff *new_skb;

461 462 463
	if (skb_linearize(skb))
		return NULL;

464
	/* Alloc new skb */
465
	new_skb = netdev_alloc_skb(dev, skb->len + 4);
466
	if (!new_skb)
467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482
		return NULL;

	/* Make sure new skb is properly aligned */
	skb_align(new_skb, 4);

	/* Copy data to new skb ... */
	skb_copy_from_linear_data(skb, new_skb->data, skb->len);
	skb_put(new_skb, skb->len);

	/* ... and free an old one */
	dev_kfree_skb_any(skb);

	return new_skb;
}
#endif

483 484
static netdev_tx_t
fs_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
485 486
{
	struct fs_enet_private *fep = netdev_priv(dev);
Scott Wood's avatar
Scott Wood committed
487
	cbd_t __iomem *bdp;
488 489
	int curidx;
	u16 sc;
490
	int nr_frags;
491 492
	skb_frag_t *frag;
	int len;
493
#ifdef CONFIG_FS_ENET_MPC5121_FEC
494 495 496 497 498 499 500 501 502
	int is_aligned = 1;
	int i;

	if (!IS_ALIGNED((unsigned long)skb->data, 4)) {
		is_aligned = 0;
	} else {
		nr_frags = skb_shinfo(skb)->nr_frags;
		frag = skb_shinfo(skb)->frags;
		for (i = 0; i < nr_frags; i++, frag++) {
503
			if (!IS_ALIGNED(skb_frag_off(frag), 4)) {
504 505 506 507 508 509 510
				is_aligned = 0;
				break;
			}
		}
	}

	if (!is_aligned) {
511 512 513 514 515 516 517 518 519 520 521
		skb = tx_skb_align_workaround(dev, skb);
		if (!skb) {
			/*
			 * We have lost packet due to memory allocation error
			 * in tx_skb_align_workaround(). Hopefully original
			 * skb is still valid, so try transmit it later.
			 */
			return NETDEV_TX_BUSY;
		}
	}
#endif
522

LEROY Christophe's avatar
LEROY Christophe committed
523
	spin_lock(&fep->tx_lock);
524 525

	/*
Vitaly Bordug's avatar
Vitaly Bordug committed
526
	 * Fill in a Tx ring entry
527 528 529
	 */
	bdp = fep->cur_tx;

530
	nr_frags = skb_shinfo(skb)->nr_frags;
531
	if (fep->tx_free <= nr_frags || (CBDR_SC(bdp) & BD_ENET_TX_READY)) {
532
		netif_stop_queue(dev);
LEROY Christophe's avatar
LEROY Christophe committed
533
		spin_unlock(&fep->tx_lock);
534 535 536 537 538

		/*
		 * Ooops.  All transmit buffers are full.  Bail out.
		 * This should not happen, since the tx queue should be stopped.
		 */
539
		dev_warn(fep->dev, "tx queue full!.\n");
540 541 542 543 544
		return NETDEV_TX_BUSY;
	}

	curidx = bdp - fep->tx_bd_base;

545
	len = skb->len;
546
	dev->stats.tx_bytes += len;
547 548 549
	if (nr_frags)
		len -= skb->data_len;
	fep->tx_free -= nr_frags + 1;
550
	/*
Vitaly Bordug's avatar
Vitaly Bordug committed
551
	 * Push the data cache so the CPM does not get stale memory data.
552 553
	 */
	CBDW_BUFADDR(bdp, dma_map_single(fep->dev,
554 555 556 557 558 559 560
				skb->data, len, DMA_TO_DEVICE));
	CBDW_DATLEN(bdp, len);

	fep->mapped_as_page[curidx] = 0;
	frag = skb_shinfo(skb)->frags;
	while (nr_frags) {
		CBDC_SC(bdp,
561 562
			BD_ENET_TX_STATS | BD_ENET_TX_INTR | BD_ENET_TX_LAST |
			BD_ENET_TX_TC);
563 564
		CBDS_SC(bdp, BD_ENET_TX_READY);

565 566 567 568 569 570 571
		if ((CBDR_SC(bdp) & BD_ENET_TX_WRAP) == 0) {
			bdp++;
			curidx++;
		} else {
			bdp = fep->tx_bd_base;
			curidx = 0;
		}
572

573 574 575 576
		len = skb_frag_size(frag);
		CBDW_BUFADDR(bdp, skb_frag_dma_map(fep->dev, frag, 0, len,
						   DMA_TO_DEVICE));
		CBDW_DATLEN(bdp, len);
577

578 579 580 581 582 583
		fep->tx_skbuff[curidx] = NULL;
		fep->mapped_as_page[curidx] = 1;

		frag++;
		nr_frags--;
	}
584 585 586 587 588 589 590 591 592 593

	/* Trigger transmission start */
	sc = BD_ENET_TX_READY | BD_ENET_TX_INTR |
	     BD_ENET_TX_LAST | BD_ENET_TX_TC;

	/* note that while FEC does not have this bit
	 * it marks it as available for software use
	 * yay for hw reuse :) */
	if (skb->len <= 60)
		sc |= BD_ENET_TX_PAD;
594
	CBDC_SC(bdp, BD_ENET_TX_STATS);
595 596
	CBDS_SC(bdp, sc);

597 598 599 600 601 602 603 604 605 606 607 608 609
	/* Save skb pointer. */
	fep->tx_skbuff[curidx] = skb;

	/* If this was the last BD in the ring, start at the beginning again. */
	if ((CBDR_SC(bdp) & BD_ENET_TX_WRAP) == 0)
		bdp++;
	else
		bdp = fep->tx_bd_base;
	fep->cur_tx = bdp;

	if (fep->tx_free < MAX_SKB_FRAGS)
		netif_stop_queue(dev);

610 611
	skb_tx_timestamp(skb);

612 613
	(*fep->ops->tx_kickstart)(dev);

LEROY Christophe's avatar
LEROY Christophe committed
614
	spin_unlock(&fep->tx_lock);
615 616 617 618

	return NETDEV_TX_OK;
}

619
static void fs_timeout_work(struct work_struct *work)
620
{
621 622 623
	struct fs_enet_private *fep = container_of(work, struct fs_enet_private,
						   timeout_work);
	struct net_device *dev = fep->ndev;
624 625 626
	unsigned long flags;
	int wake = 0;

627
	dev->stats.tx_errors++;
628 629 630 631

	spin_lock_irqsave(&fep->lock, flags);

	if (dev->flags & IFF_UP) {
632
		phy_stop(dev->phydev);
633 634 635 636
		(*fep->ops->stop)(dev);
		(*fep->ops->restart)(dev);
	}

637
	phy_start(dev->phydev);
638 639
	wake = fep->tx_free >= MAX_SKB_FRAGS &&
	       !(CBDR_SC(fep->cur_tx) & BD_ENET_TX_READY);
640 641 642 643 644 645
	spin_unlock_irqrestore(&fep->lock, flags);

	if (wake)
		netif_wake_queue(dev);
}

646
static void fs_timeout(struct net_device *dev, unsigned int txqueue)
647 648 649 650 651 652
{
	struct fs_enet_private *fep = netdev_priv(dev);

	schedule_work(&fep->timeout_work);
}

653 654 655 656 657
/*-----------------------------------------------------------------------------
 *  generic link-change handler - should be sufficient for most cases
 *-----------------------------------------------------------------------------*/
static void generic_adjust_link(struct  net_device *dev)
{
Scott Wood's avatar
Scott Wood committed
658
	struct fs_enet_private *fep = netdev_priv(dev);
659
	struct phy_device *phydev = dev->phydev;
Scott Wood's avatar
Scott Wood committed
660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689
	int new_state = 0;

	if (phydev->link) {
		/* adjust to duplex mode */
		if (phydev->duplex != fep->oldduplex) {
			new_state = 1;
			fep->oldduplex = phydev->duplex;
		}

		if (phydev->speed != fep->oldspeed) {
			new_state = 1;
			fep->oldspeed = phydev->speed;
		}

		if (!fep->oldlink) {
			new_state = 1;
			fep->oldlink = 1;
		}

		if (new_state)
			fep->ops->restart(dev);
	} else if (fep->oldlink) {
		new_state = 1;
		fep->oldlink = 0;
		fep->oldspeed = 0;
		fep->oldduplex = -1;
	}

	if (new_state && netif_msg_link(fep))
		phy_print_status(phydev);
690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711
}


static void fs_adjust_link(struct net_device *dev)
{
	struct fs_enet_private *fep = netdev_priv(dev);
	unsigned long flags;

	spin_lock_irqsave(&fep->lock, flags);

	if(fep->ops->adjust_link)
		fep->ops->adjust_link(dev);
	else
		generic_adjust_link(dev);

	spin_unlock_irqrestore(&fep->lock, flags);
}

static int fs_init_phy(struct net_device *dev)
{
	struct fs_enet_private *fep = netdev_priv(dev);
	struct phy_device *phydev;
712
	phy_interface_t iface;
713 714 715 716

	fep->oldlink = 0;
	fep->oldspeed = 0;
	fep->oldduplex = -1;
717

718 719 720
	iface = fep->fpi->use_rmii ?
		PHY_INTERFACE_MODE_RMII : PHY_INTERFACE_MODE_MII;

721
	phydev = of_phy_connect(dev, fep->fpi->phy_node, &fs_adjust_link, 0,
722
				iface);
723 724 725
	if (!phydev) {
		dev_err(&dev->dev, "Could not attach to PHY\n");
		return -ENODEV;
726 727 728 729 730
	}

	return 0;
}

731 732 733 734
static int fs_enet_open(struct net_device *dev)
{
	struct fs_enet_private *fep = netdev_priv(dev);
	int r;
735
	int err;
736

737
	/* to initialize the fep->cur_rx,... */
738
	/* not doing this, will cause a crash in fs_enet_napi */
739 740
	fs_init_bds(fep->ndev);

741
	napi_enable(&fep->napi);
742

743
	/* Install our interrupt handler. */
744 745
	r = request_irq(fep->interrupt, fs_enet_interrupt, IRQF_SHARED,
			"fs_enet-mac", dev);
746
	if (r != 0) {
747
		dev_err(fep->dev, "Could not allocate FS_ENET IRQ!");
748
		napi_disable(&fep->napi);
749 750 751
		return -EINVAL;
	}

752
	err = fs_init_phy(dev);
Scott Wood's avatar
Scott Wood committed
753
	if (err) {
754
		free_irq(fep->interrupt, dev);
755
		napi_disable(&fep->napi);
756
		return err;
757
	}
758
	phy_start(dev->phydev);
759

760 761
	netif_start_queue(dev);

762 763 764 765 766 767 768 769 770 771
	return 0;
}

static int fs_enet_close(struct net_device *dev)
{
	struct fs_enet_private *fep = netdev_priv(dev);
	unsigned long flags;

	netif_stop_queue(dev);
	netif_carrier_off(dev);
772
	napi_disable(&fep->napi);
773
	cancel_work_sync(&fep->timeout_work);
774
	phy_stop(dev->phydev);
775 776

	spin_lock_irqsave(&fep->lock, flags);
777
	spin_lock(&fep->tx_lock);
778
	(*fep->ops->stop)(dev);
779
	spin_unlock(&fep->tx_lock);
780 781 782
	spin_unlock_irqrestore(&fep->lock, flags);

	/* release any irqs */
783
	phy_disconnect(dev->phydev);
784
	free_irq(fep->interrupt, dev);
785 786 787 788 789 790 791 792 793

	return 0;
}

/*************************************************************************/

static void fs_get_drvinfo(struct net_device *dev,
			    struct ethtool_drvinfo *info)
{
794
	strlcpy(info->driver, DRV_MODULE_NAME, sizeof(info->driver));
795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832
}

static int fs_get_regs_len(struct net_device *dev)
{
	struct fs_enet_private *fep = netdev_priv(dev);

	return (*fep->ops->get_regs_len)(dev);
}

static void fs_get_regs(struct net_device *dev, struct ethtool_regs *regs,
			 void *p)
{
	struct fs_enet_private *fep = netdev_priv(dev);
	unsigned long flags;
	int r, len;

	len = regs->len;

	spin_lock_irqsave(&fep->lock, flags);
	r = (*fep->ops->get_regs)(dev, p, &len);
	spin_unlock_irqrestore(&fep->lock, flags);

	if (r == 0)
		regs->version = 0;
}

static u32 fs_get_msglevel(struct net_device *dev)
{
	struct fs_enet_private *fep = netdev_priv(dev);
	return fep->msg_enable;
}

static void fs_set_msglevel(struct net_device *dev, u32 value)
{
	struct fs_enet_private *fep = netdev_priv(dev);
	fep->msg_enable = value;
}

833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870
static int fs_get_tunable(struct net_device *dev,
			  const struct ethtool_tunable *tuna, void *data)
{
	struct fs_enet_private *fep = netdev_priv(dev);
	struct fs_platform_info *fpi = fep->fpi;
	int ret = 0;

	switch (tuna->id) {
	case ETHTOOL_RX_COPYBREAK:
		*(u32 *)data = fpi->rx_copybreak;
		break;
	default:
		ret = -EINVAL;
		break;
	}

	return ret;
}

static int fs_set_tunable(struct net_device *dev,
			  const struct ethtool_tunable *tuna, const void *data)
{
	struct fs_enet_private *fep = netdev_priv(dev);
	struct fs_platform_info *fpi = fep->fpi;
	int ret = 0;

	switch (tuna->id) {
	case ETHTOOL_RX_COPYBREAK:
		fpi->rx_copybreak = *(u32 *)data;
		break;
	default:
		ret = -EINVAL;
		break;
	}

	return ret;
}

871
static const struct ethtool_ops fs_ethtool_ops = {
872 873
	.get_drvinfo = fs_get_drvinfo,
	.get_regs_len = fs_get_regs_len,
874
	.nway_reset = phy_ethtool_nway_reset,
875 876 877 878
	.get_link = ethtool_op_get_link,
	.get_msglevel = fs_get_msglevel,
	.set_msglevel = fs_set_msglevel,
	.get_regs = fs_get_regs,
879
	.get_ts_info = ethtool_op_get_ts_info,
880 881
	.get_link_ksettings = phy_ethtool_get_link_ksettings,
	.set_link_ksettings = phy_ethtool_set_link_ksettings,
882 883
	.get_tunable = fs_get_tunable,
	.set_tunable = fs_set_tunable,
884 885 886 887 888 889 890
};

extern int fs_mii_connect(struct net_device *dev);
extern void fs_mii_disconnect(struct net_device *dev);

/**************************************************************************************/

891 892 893 894 895 896
#ifdef CONFIG_FS_ENET_HAS_FEC
#define IS_FEC(match) ((match)->data == &fs_fec_ops)
#else
#define IS_FEC(match) 0
#endif

897 898 899 900 901
static const struct net_device_ops fs_enet_netdev_ops = {
	.ndo_open		= fs_enet_open,
	.ndo_stop		= fs_enet_close,
	.ndo_start_xmit		= fs_enet_start_xmit,
	.ndo_tx_timeout		= fs_timeout,
902
	.ndo_set_rx_mode	= fs_set_multicast_list,
903
	.ndo_do_ioctl		= phy_do_ioctl_running,
904 905 906 907 908 909 910
	.ndo_validate_addr	= eth_validate_addr,
	.ndo_set_mac_address	= eth_mac_addr,
#ifdef CONFIG_NET_POLL_CONTROLLER
	.ndo_poll_controller	= fs_enet_netpoll,
#endif
};

911
static const struct of_device_id fs_enet_match[];
912
static int fs_enet_probe(struct platform_device *ofdev)
913
{
914
	const struct of_device_id *match;
915 916 917 918
	struct net_device *ndev;
	struct fs_enet_private *fep;
	struct fs_platform_info *fpi;
	const u32 *data;
919 920
	struct clk *clk;
	int err;
921
	const u8 *mac_addr;
922
	const char *phy_connection_type;
923 924
	int privsize, len, ret = -ENODEV;

925 926
	match = of_match_device(fs_enet_match, &ofdev->dev);
	if (!match)
927 928
		return -EINVAL;

929 930 931 932
	fpi = kzalloc(sizeof(*fpi), GFP_KERNEL);
	if (!fpi)
		return -ENOMEM;

933
	if (!IS_FEC(match)) {
934
		data = of_get_property(ofdev->dev.of_node, "fsl,cpm-command", &len);
935 936 937 938 939 940
		if (!data || len != 4)
			goto out_free_fpi;

		fpi->cp_command = *data;
	}

941 942
	fpi->rx_ring = RX_RING_SIZE;
	fpi->tx_ring = TX_RING_SIZE;
943 944
	fpi->rx_copybreak = 240;
	fpi->napi_weight = 17;
945
	fpi->phy_node = of_parse_phandle(ofdev->dev.of_node, "phy-handle", 0);
946 947 948 949 950 951 952 953
	if (!fpi->phy_node && of_phy_is_fixed_link(ofdev->dev.of_node)) {
		err = of_phy_register_fixed_link(ofdev->dev.of_node);
		if (err)
			goto out_free_fpi;

		/* In the case of a fixed PHY, the DT node associated
		 * to the PHY is the Ethernet MAC DT node.
		 */
954
		fpi->phy_node = of_node_get(ofdev->dev.of_node);
955
	}
956

957 958 959 960 961 962 963
	if (of_device_is_compatible(ofdev->dev.of_node, "fsl,mpc5125-fec")) {
		phy_connection_type = of_get_property(ofdev->dev.of_node,
						"phy-connection-type", NULL);
		if (phy_connection_type && !strcmp("rmii", phy_connection_type))
			fpi->use_rmii = 1;
	}

964 965 966 967 968 969
	/* make clock lookup non-fatal (the driver is shared among platforms),
	 * but require enable to succeed when a clock was specified/found,
	 * keep a reference to the clock upon successful acquisition
	 */
	clk = devm_clk_get(&ofdev->dev, "per");
	if (!IS_ERR(clk)) {
970 971
		ret = clk_prepare_enable(clk);
		if (ret)
972
			goto out_deregister_fixed_link;
973

974 975 976
		fpi->clk_per = clk;
	}

977 978
	privsize = sizeof(*fep) +
	           sizeof(struct sk_buff **) *
979 980
		     (fpi->rx_ring + fpi->tx_ring) +
		   sizeof(char) * fpi->tx_ring;
981 982 983 984

	ndev = alloc_etherdev(privsize);
	if (!ndev) {
		ret = -ENOMEM;
985
		goto out_put;
986 987
	}

988
	SET_NETDEV_DEV(ndev, &ofdev->dev);
989
	platform_set_drvdata(ofdev, ndev);
990 991 992

	fep = netdev_priv(ndev);
	fep->dev = &ofdev->dev;
Scott Wood's avatar
Scott Wood committed
993
	fep->ndev = ndev;
994
	fep->fpi = fpi;
995
	fep->ops = match->data;
996 997 998 999 1000 1001 1002

	ret = fep->ops->setup_data(ndev);
	if (ret)
		goto out_free_dev;

	fep->rx_skbuff = (struct sk_buff **)&fep[1];
	fep->tx_skbuff = fep->rx_skbuff + fpi->rx_ring;
1003 1004
	fep->mapped_as_page = (char *)(fep->rx_skbuff + fpi->rx_ring +
				       fpi->tx_ring);
1005 1006 1007 1008

	spin_lock_init(&fep->lock);
	spin_lock_init(&fep->tx_lock);

1009
	mac_addr = of_get_mac_address(ofdev->dev.of_node);
1010
	if (!IS_ERR(mac_addr))
1011
		ether_addr_copy(ndev->dev_addr, mac_addr);
1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022

	ret = fep->ops->allocate_bd(ndev);
	if (ret)
		goto out_cleanup_data;

	fep->rx_bd_base = fep->ring_base;
	fep->tx_bd_base = fep->rx_bd_base + fpi->rx_ring;

	fep->tx_ring = fpi->tx_ring;
	fep->rx_ring = fpi->rx_ring;

1023
	ndev->netdev_ops = &fs_enet_netdev_ops;
1024
	ndev->watchdog_timeo = 2 * HZ;
1025
	INIT_WORK(&fep->timeout_work, fs_timeout_work);
1026
	netif_napi_add(ndev, &fep->napi, fs_enet_napi, fpi->napi_weight);
Scott Wood's avatar
Scott Wood committed
1027

1028 1029 1030 1031
	ndev->ethtool_ops = &fs_ethtool_ops;

	netif_carrier_off(ndev);

1032 1033
	ndev->features |= NETIF_F_SG;

1034 1035 1036 1037
	ret = register_netdev(ndev);
	if (ret)
		goto out_free_bd;

1038
	pr_info("%s: fs_enet: %pM\n", ndev->name, ndev->dev_addr);
1039 1040 1041 1042 1043 1044 1045 1046 1047

	return 0;

out_free_bd:
	fep->ops->free_bd(ndev);
out_cleanup_data:
	fep->ops->cleanup_data(ndev);
out_free_dev:
	free_netdev(ndev);
1048
out_put:
1049
	clk_disable_unprepare(fpi->clk_per);
1050
out_deregister_fixed_link:
1051
	of_node_put(fpi->phy_node);
1052 1053
	if (of_phy_is_fixed_link(ofdev->dev.of_node))
		of_phy_deregister_fixed_link(ofdev->dev.of_node);
1054 1055 1056 1057 1058
out_free_fpi:
	kfree(fpi);
	return ret;
}

1059
static int fs_enet_remove(struct platform_device *ofdev)
1060
{
1061
	struct net_device *ndev = platform_get_drvdata(ofdev);
1062 1063 1064 1065 1066 1067 1068
	struct fs_enet_private *fep = netdev_priv(ndev);

	unregister_netdev(ndev);

	fep->ops->free_bd(ndev);
	fep->ops->cleanup_data(ndev);
	dev_set_drvdata(fep->dev, NULL);
1069
	of_node_put(fep->fpi->phy_node);
1070
	clk_disable_unprepare(fep->fpi->clk_per);
1071 1072
	if (of_phy_is_fixed_link(ofdev->dev.of_node))
		of_phy_deregister_fixed_link(ofdev->dev.of_node);
1073 1074 1075 1076
	free_netdev(ndev);
	return 0;
}

1077
static const struct of_device_id fs_enet_match[] = {
1078 1079 1080 1081 1082
#ifdef CONFIG_FS_ENET_HAS_SCC
	{
		.compatible = "fsl,cpm1-scc-enet",
		.data = (void *)&fs_scc_ops,
	},
1083 1084 1085 1086
	{
		.compatible = "fsl,cpm2-scc-enet",
		.data = (void *)&fs_scc_ops,
	},
1087 1088 1089 1090 1091 1092 1093 1094
#endif
#ifdef CONFIG_FS_ENET_HAS_FCC
	{
		.compatible = "fsl,cpm2-fcc-enet",
		.data = (void *)&fs_fcc_ops,
	},
#endif
#ifdef CONFIG_FS_ENET_HAS_FEC
1095 1096 1097 1098 1099
#ifdef CONFIG_FS_ENET_MPC5121_FEC
	{
		.compatible = "fsl,mpc5121-fec",
		.data = (void *)&fs_fec_ops,
	},
1100 1101 1102 1103
	{
		.compatible = "fsl,mpc5125-fec",
		.data = (void *)&fs_fec_ops,
	},
1104
#else
1105 1106 1107 1108
	{
		.compatible = "fsl,pq1-fec-enet",
		.data = (void *)&fs_fec_ops,
	},
1109
#endif
1110 1111 1112
#endif
	{}
};
1113
MODULE_DEVICE_TABLE(of, fs_enet_match);
1114

1115
static struct platform_driver fs_enet_driver = {
1116 1117 1118 1119
	.driver = {
		.name = "fs_enet",
		.of_match_table = fs_enet_match,
	},
1120 1121 1122 1123
	.probe = fs_enet_probe,
	.remove = fs_enet_remove,
};

Vitaly Bordug's avatar
Vitaly Bordug committed
1124 1125 1126 1127
#ifdef CONFIG_NET_POLL_CONTROLLER
static void fs_enet_netpoll(struct net_device *dev)
{
       disable_irq(dev->irq);
Alexey Dobriyan's avatar
Alexey Dobriyan committed
1128
       fs_enet_interrupt(dev->irq, dev);
Vitaly Bordug's avatar
Vitaly Bordug committed
1129 1130 1131 1132
       enable_irq(dev->irq);
}
#endif

1133
module_platform_driver(fs_enet_driver);