fec_main.c 95 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1 2 3 4
/*
 * Fast Ethernet Controller (FEC) driver for Motorola MPC8xx.
 * Copyright (c) 1997 Dan Malek (dmalek@jlc.net)
 *
5
 * Right now, I am very wasteful with the buffers.  I allocate memory
Linus Torvalds's avatar
Linus Torvalds committed
6 7 8 9 10 11 12 13 14
 * pages and then divide them into 2K frame buffers.  This way I know I
 * have buffers large enough to hold one frame within one buffer descriptor.
 * Once I get this working, I will use 64 or 128 byte CPM buffers, which
 * will be much more memory efficient and will easily handle lots of
 * small packets.
 *
 * Much better multiple PHY support by Magnus Damm.
 * Copyright (c) 2000 Ericsson Radio Systems AB.
 *
15 16
 * Support for FEC controller of ColdFire processors.
 * Copyright (c) 2001-2005 Greg Ungerer (gerg@snapgear.com)
17 18
 *
 * Bug fixes and cleanup by Philippe De Muyter (phdm@macqel.be)
19
 * Copyright (c) 2004-2006 Macq Electronique SA.
20
 *
Shawn Guo's avatar
Shawn Guo committed
21
 * Copyright (C) 2010-2011 Freescale Semiconductor, Inc.
Linus Torvalds's avatar
Linus Torvalds committed
22 23 24 25 26
 */

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/string.h>
27
#include <linux/pm_runtime.h>
Linus Torvalds's avatar
Linus Torvalds committed
28 29 30 31 32 33 34 35 36
#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>
37 38 39
#include <linux/in.h>
#include <linux/ip.h>
#include <net/ip.h>
40
#include <net/tso.h>
41 42 43
#include <linux/tcp.h>
#include <linux/udp.h>
#include <linux/icmp.h>
Linus Torvalds's avatar
Linus Torvalds committed
44 45 46
#include <linux/spinlock.h>
#include <linux/workqueue.h>
#include <linux/bitops.h>
47 48
#include <linux/io.h>
#include <linux/irq.h>
49
#include <linux/clk.h>
50
#include <linux/platform_device.h>
51
#include <linux/mdio.h>
52
#include <linux/phy.h>
53
#include <linux/fec.h>
54 55 56
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
57
#include <linux/of_mdio.h>
58
#include <linux/of_net.h>
59
#include <linux/regulator/consumer.h>
60
#include <linux/if_vlan.h>
61
#include <linux/pinctrl/consumer.h>
62
#include <linux/prefetch.h>
63
#include <soc/imx/cpuidle.h>
Linus Torvalds's avatar
Linus Torvalds committed
64

65
#include <asm/cacheflush.h>
66

Linus Torvalds's avatar
Linus Torvalds committed
67 68
#include "fec.h"

69
static void set_multicast_list(struct net_device *ndev);
70
static void fec_enet_itr_coal_init(struct net_device *ndev);
71

72 73
#define DRIVER_NAME	"fec"

74 75
#define FEC_ENET_GET_QUQUE(_x) ((_x == 0) ? 1 : ((_x == 1) ? 2 : 0))

76 77 78 79 80 81 82
/* Pause frame feild and FIFO threshold */
#define FEC_ENET_FCE	(1 << 5)
#define FEC_ENET_RSEM_V	0x84
#define FEC_ENET_RSFL_V	16
#define FEC_ENET_RAEM_V	0x8
#define FEC_ENET_RAFL_V	0x8
#define FEC_ENET_OPD_V	0xFFF0
83
#define FEC_MDIO_PM_TIMEOUT  100 /* ms */
84

85 86
static struct platform_device_id fec_devtype[] = {
	{
87
		/* keep it for coldfire */
88 89
		.name = DRIVER_NAME,
		.driver_data = 0,
90 91
	}, {
		.name = "imx25-fec",
92
		.driver_data = FEC_QUIRK_USE_GASKET | FEC_QUIRK_MIB_CLEAR,
93 94
	}, {
		.name = "imx27-fec",
95
		.driver_data = FEC_QUIRK_MIB_CLEAR,
96 97
	}, {
		.name = "imx28-fec",
98
		.driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_SWAP_FRAME |
99
				FEC_QUIRK_SINGLE_MDIO | FEC_QUIRK_HAS_RACC,
Shawn Guo's avatar
Shawn Guo committed
100 101
	}, {
		.name = "imx6q-fec",
102
		.driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT |
103
				FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM |
104 105
				FEC_QUIRK_HAS_VLAN | FEC_QUIRK_ERR006358 |
				FEC_QUIRK_HAS_RACC,
106
	}, {
107
		.name = "mvf600-fec",
108
		.driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_RACC,
109 110 111 112
	}, {
		.name = "imx6sx-fec",
		.driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT |
				FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM |
113
				FEC_QUIRK_HAS_VLAN | FEC_QUIRK_HAS_AVB |
114
				FEC_QUIRK_ERR007885 | FEC_QUIRK_BUG_CAPTURE |
115
				FEC_QUIRK_HAS_RACC | FEC_QUIRK_HAS_COALESCE,
116 117 118 119
	}, {
		.name = "imx6ul-fec",
		.driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT |
				FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM |
120 121 122
				FEC_QUIRK_HAS_VLAN | FEC_QUIRK_ERR007885 |
				FEC_QUIRK_BUG_CAPTURE | FEC_QUIRK_HAS_RACC |
				FEC_QUIRK_HAS_COALESCE,
123 124 125
	}, {
		/* sentinel */
	}
126
};
127
MODULE_DEVICE_TABLE(platform, fec_devtype);
128

129
enum imx_fec_type {
Lothar Waßmann's avatar
Lothar Waßmann committed
130
	IMX25_FEC = 1,	/* runs on i.mx25/50/53 */
131 132
	IMX27_FEC,	/* runs on i.mx27/35/51 */
	IMX28_FEC,
Shawn Guo's avatar
Shawn Guo committed
133
	IMX6Q_FEC,
134
	MVF600_FEC,
135
	IMX6SX_FEC,
136
	IMX6UL_FEC,
137 138 139 140 141 142
};

static const struct of_device_id fec_dt_ids[] = {
	{ .compatible = "fsl,imx25-fec", .data = &fec_devtype[IMX25_FEC], },
	{ .compatible = "fsl,imx27-fec", .data = &fec_devtype[IMX27_FEC], },
	{ .compatible = "fsl,imx28-fec", .data = &fec_devtype[IMX28_FEC], },
Shawn Guo's avatar
Shawn Guo committed
143
	{ .compatible = "fsl,imx6q-fec", .data = &fec_devtype[IMX6Q_FEC], },
144
	{ .compatible = "fsl,mvf600-fec", .data = &fec_devtype[MVF600_FEC], },
145
	{ .compatible = "fsl,imx6sx-fec", .data = &fec_devtype[IMX6SX_FEC], },
146
	{ .compatible = "fsl,imx6ul-fec", .data = &fec_devtype[IMX6UL_FEC], },
147 148 149 150
	{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, fec_dt_ids);

151 152 153
static unsigned char macaddr[ETH_ALEN];
module_param_array(macaddr, byte, NULL, 0);
MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address");
Linus Torvalds's avatar
Linus Torvalds committed
154

155
#if defined(CONFIG_M5272)
Linus Torvalds's avatar
Linus Torvalds committed
156 157 158 159 160 161 162 163 164 165
/*
 * Some hardware gets it MAC address out of local flash memory.
 * if this is non-zero then assume it is the address to get MAC from.
 */
#if defined(CONFIG_NETtel)
#define	FEC_FLASHMAC	0xf0006006
#elif defined(CONFIG_GILBARCONAP) || defined(CONFIG_SCALES)
#define	FEC_FLASHMAC	0xf0006000
#elif defined(CONFIG_CANCam)
#define	FEC_FLASHMAC	0xf0020000
166 167 168
#elif defined (CONFIG_M5272C3)
#define	FEC_FLASHMAC	(0xffe04000 + 4)
#elif defined(CONFIG_MOD5272)
Lothar Waßmann's avatar
Lothar Waßmann committed
169
#define FEC_FLASHMAC	0xffc0406b
Linus Torvalds's avatar
Linus Torvalds committed
170 171 172
#else
#define	FEC_FLASHMAC	0
#endif
173
#endif /* CONFIG_M5272 */
174

175
/* The FEC stores dest/src/type/vlan, data, and checksum for receive packets.
176 177 178
 *
 * 2048 byte skbufs are allocated. However, alignment requirements
 * varies between FEC variants. Worst case is 64, so round down by 64.
Linus Torvalds's avatar
Linus Torvalds committed
179
 */
180
#define PKT_MAXBUF_SIZE		(round_down(2048 - 64, 64))
Linus Torvalds's avatar
Linus Torvalds committed
181 182
#define PKT_MINBUF_SIZE		64

183 184 185
/* FEC receive acceleration */
#define FEC_RACC_IPDIS		(1 << 1)
#define FEC_RACC_PRODIS		(1 << 2)
186
#define FEC_RACC_SHIFT16	BIT(7)
187 188
#define FEC_RACC_OPTIONS	(FEC_RACC_IPDIS | FEC_RACC_PRODIS)

189 190 191
/* MIB Control Register */
#define FEC_MIB_CTRLSTAT_DISABLE	BIT(31)

Linus Torvalds's avatar
Linus Torvalds committed
192
/*
193
 * The 5270/5271/5280/5282/532x RX control register also contains maximum frame
Linus Torvalds's avatar
Linus Torvalds committed
194 195 196
 * size bits. Other FEC hardware does not, so we need to take that into
 * account when setting it.
 */
197
#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
198
    defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARM)
Linus Torvalds's avatar
Linus Torvalds committed
199 200 201 202 203
#define	OPT_FRAME_SIZE	(PKT_MAXBUF_SIZE << 16)
#else
#define	OPT_FRAME_SIZE	0
#endif

204 205 206 207 208 209 210 211
/* FEC MII MMFR bits definition */
#define FEC_MMFR_ST		(1 << 30)
#define FEC_MMFR_OP_READ	(2 << 28)
#define FEC_MMFR_OP_WRITE	(1 << 28)
#define FEC_MMFR_PA(v)		((v & 0x1f) << 23)
#define FEC_MMFR_RA(v)		((v & 0x1f) << 18)
#define FEC_MMFR_TA		(2 << 16)
#define FEC_MMFR_DATA(v)	(v & 0xffff)
212 213 214
/* FEC ECR bits definition */
#define FEC_ECR_MAGICEN		(1 << 2)
#define FEC_ECR_SLEEP		(1 << 3)
Linus Torvalds's avatar
Linus Torvalds committed
215

216
#define FEC_MII_TIMEOUT		30000 /* us */
Linus Torvalds's avatar
Linus Torvalds committed
217

Sascha Hauer's avatar
Sascha Hauer committed
218 219
/* Transmitter timeout */
#define TX_TIMEOUT (2 * HZ)
Linus Torvalds's avatar
Linus Torvalds committed
220

221 222
#define FEC_PAUSE_FLAG_AUTONEG	0x1
#define FEC_PAUSE_FLAG_ENABLE	0x2
223 224 225
#define FEC_WOL_HAS_MAGIC_PACKET	(0x1 << 0)
#define FEC_WOL_FLAG_ENABLE		(0x1 << 1)
#define FEC_WOL_FLAG_SLEEP_ON		(0x1 << 2)
226

227 228
#define COPYBREAK_DEFAULT	256

229 230 231 232 233 234
/* Max number of allowed TCP segments for software TSO */
#define FEC_MAX_TSO_SEGS	100
#define FEC_MAX_SKB_DESCS	(FEC_MAX_TSO_SEGS * 2 + MAX_SKB_FRAGS)

#define IS_TSO_HEADER(txq, addr) \
	((addr >= txq->tso_hdrs_dma) && \
Troy Kisky's avatar
Troy Kisky committed
235
	(addr < txq->tso_hdrs_dma + txq->bd.ring_size * TSO_HEADER_SIZE))
236

237 238
static int mii_cnt;

Troy Kisky's avatar
Troy Kisky committed
239 240 241 242
static struct bufdesc *fec_enet_get_nextdesc(struct bufdesc *bdp,
					     struct bufdesc_prop *bd)
{
	return (bdp >= bd->last) ? bd->base
243
			: (struct bufdesc *)(((void *)bdp) + bd->dsize);
Troy Kisky's avatar
Troy Kisky committed
244
}
245

Troy Kisky's avatar
Troy Kisky committed
246 247 248 249
static struct bufdesc *fec_enet_get_prevdesc(struct bufdesc *bdp,
					     struct bufdesc_prop *bd)
{
	return (bdp <= bd->base) ? bd->last
250
			: (struct bufdesc *)(((void *)bdp) - bd->dsize);
251 252
}

Troy Kisky's avatar
Troy Kisky committed
253 254
static int fec_enet_get_bd_index(struct bufdesc *bdp,
				 struct bufdesc_prop *bd)
255
{
Troy Kisky's avatar
Troy Kisky committed
256
	return ((const char *)bdp - (const char *)bd->base) >> bd->dsize_log2;
257 258
}

Troy Kisky's avatar
Troy Kisky committed
259
static int fec_enet_get_free_txdesc_num(struct fec_enet_priv_tx_q *txq)
260 261 262
{
	int entries;

Troy Kisky's avatar
Troy Kisky committed
263 264
	entries = (((const char *)txq->dirty_tx -
			(const char *)txq->bd.cur) >> txq->bd.dsize_log2) - 1;
265

Troy Kisky's avatar
Troy Kisky committed
266
	return entries >= 0 ? entries : entries + txq->bd.ring_size;
267 268
}

269
static void swap_buffer(void *bufaddr, int len)
270 271 272 273
{
	int i;
	unsigned int *buf = bufaddr;

274
	for (i = 0; i < len; i += 4, buf++)
275
		swab32s(buf);
276 277
}

278 279 280 281 282 283 284 285 286 287
static void swap_buffer2(void *dst_buf, void *src_buf, int len)
{
	int i;
	unsigned int *src = src_buf;
	unsigned int *dst = dst_buf;

	for (i = 0; i < len; i += 4, src++, dst++)
		*dst = swab32p(src);
}

288 289 290
static void fec_dump(struct net_device *ndev)
{
	struct fec_enet_private *fep = netdev_priv(ndev);
291 292 293
	struct bufdesc *bdp;
	struct fec_enet_priv_tx_q *txq;
	int index = 0;
294 295 296 297

	netdev_info(ndev, "TX ring dump\n");
	pr_info("Nr     SC     addr       len  SKB\n");

298
	txq = fep->tx_queue[0];
Troy Kisky's avatar
Troy Kisky committed
299
	bdp = txq->bd.base;
300

301
	do {
302
		pr_info("%3u %c%c 0x%04x 0x%08x %4u %p\n",
303
			index,
Troy Kisky's avatar
Troy Kisky committed
304
			bdp == txq->bd.cur ? 'S' : ' ',
305
			bdp == txq->dirty_tx ? 'H' : ' ',
306 307 308
			fec16_to_cpu(bdp->cbd_sc),
			fec32_to_cpu(bdp->cbd_bufaddr),
			fec16_to_cpu(bdp->cbd_datlen),
309
			txq->tx_skbuff[index]);
Troy Kisky's avatar
Troy Kisky committed
310
		bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
311
		index++;
Troy Kisky's avatar
Troy Kisky committed
312
	} while (bdp != txq->bd.base);
313 314
}

315 316 317 318 319
static inline bool is_ipv4_pkt(struct sk_buff *skb)
{
	return skb->protocol == htons(ETH_P_IP) && ip_hdr(skb)->version == 4;
}

320 321 322 323 324 325 326 327 328 329
static int
fec_enet_clear_csum(struct sk_buff *skb, struct net_device *ndev)
{
	/* Only run for packets requiring a checksum. */
	if (skb->ip_summed != CHECKSUM_PARTIAL)
		return 0;

	if (unlikely(skb_cow_head(skb, 0)))
		return -1;

330 331
	if (is_ipv4_pkt(skb))
		ip_hdr(skb)->check = 0;
332 333 334 335 336
	*(__sum16 *)(skb->head + skb->csum_start + skb->csum_offset) = 0;

	return 0;
}

337
static struct bufdesc *
338 339 340
fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq,
			     struct sk_buff *skb,
			     struct net_device *ndev)
Linus Torvalds's avatar
Linus Torvalds committed
341
{
342
	struct fec_enet_private *fep = netdev_priv(ndev);
Troy Kisky's avatar
Troy Kisky committed
343
	struct bufdesc *bdp = txq->bd.cur;
344 345 346 347 348 349
	struct bufdesc_ex *ebdp;
	int nr_frags = skb_shinfo(skb)->nr_frags;
	int frag, frag_len;
	unsigned short status;
	unsigned int estatus = 0;
	skb_frag_t *this_frag;
350
	unsigned int index;
351
	void *bufaddr;
352
	dma_addr_t addr;
353
	int i;
Linus Torvalds's avatar
Linus Torvalds committed
354

355 356
	for (frag = 0; frag < nr_frags; frag++) {
		this_frag = &skb_shinfo(skb)->frags[frag];
Troy Kisky's avatar
Troy Kisky committed
357
		bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
358 359
		ebdp = (struct bufdesc_ex *)bdp;

360
		status = fec16_to_cpu(bdp->cbd_sc);
361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376
		status &= ~BD_ENET_TX_STATS;
		status |= (BD_ENET_TX_TC | BD_ENET_TX_READY);
		frag_len = skb_shinfo(skb)->frags[frag].size;

		/* Handle the last BD specially */
		if (frag == nr_frags - 1) {
			status |= (BD_ENET_TX_INTR | BD_ENET_TX_LAST);
			if (fep->bufdesc_ex) {
				estatus |= BD_ENET_TX_INT;
				if (unlikely(skb_shinfo(skb)->tx_flags &
					SKBTX_HW_TSTAMP && fep->hwts_tx_en))
					estatus |= BD_ENET_TX_TS;
			}
		}

		if (fep->bufdesc_ex) {
377
			if (fep->quirks & FEC_QUIRK_HAS_AVB)
378
				estatus |= FEC_TX_BD_FTYPE(txq->bd.qid);
379 380 381
			if (skb->ip_summed == CHECKSUM_PARTIAL)
				estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS;
			ebdp->cbd_bdu = 0;
382
			ebdp->cbd_esc = cpu_to_fec32(estatus);
383 384 385 386
		}

		bufaddr = page_address(this_frag->page.p) + this_frag->page_offset;

Troy Kisky's avatar
Troy Kisky committed
387
		index = fec_enet_get_bd_index(bdp, &txq->bd);
388
		if (((unsigned long) bufaddr) & fep->tx_align ||
389
			fep->quirks & FEC_QUIRK_SWAP_FRAME) {
390 391
			memcpy(txq->tx_bounce[index], bufaddr, frag_len);
			bufaddr = txq->tx_bounce[index];
392

393
			if (fep->quirks & FEC_QUIRK_SWAP_FRAME)
394 395 396
				swap_buffer(bufaddr, frag_len);
		}

397 398 399
		addr = dma_map_single(&fep->pdev->dev, bufaddr, frag_len,
				      DMA_TO_DEVICE);
		if (dma_mapping_error(&fep->pdev->dev, addr)) {
400 401 402 403 404
			if (net_ratelimit())
				netdev_err(ndev, "Tx DMA memory map failed\n");
			goto dma_mapping_error;
		}

405 406
		bdp->cbd_bufaddr = cpu_to_fec32(addr);
		bdp->cbd_datlen = cpu_to_fec16(frag_len);
407 408 409 410
		/* Make sure the updates to rest of the descriptor are
		 * performed before transferring ownership.
		 */
		wmb();
411
		bdp->cbd_sc = cpu_to_fec16(status);
412 413
	}

414
	return bdp;
415
dma_mapping_error:
Troy Kisky's avatar
Troy Kisky committed
416
	bdp = txq->bd.cur;
417
	for (i = 0; i < frag; i++) {
Troy Kisky's avatar
Troy Kisky committed
418
		bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
419 420
		dma_unmap_single(&fep->pdev->dev, fec32_to_cpu(bdp->cbd_bufaddr),
				 fec16_to_cpu(bdp->cbd_datlen), DMA_TO_DEVICE);
421
	}
422
	return ERR_PTR(-ENOMEM);
423
}
Linus Torvalds's avatar
Linus Torvalds committed
424

425 426
static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
				   struct sk_buff *skb, struct net_device *ndev)
427 428 429 430 431
{
	struct fec_enet_private *fep = netdev_priv(ndev);
	int nr_frags = skb_shinfo(skb)->nr_frags;
	struct bufdesc *bdp, *last_bdp;
	void *bufaddr;
432
	dma_addr_t addr;
433 434 435 436
	unsigned short status;
	unsigned short buflen;
	unsigned int estatus = 0;
	unsigned int index;
437
	int entries_free;
Sascha Hauer's avatar
Sascha Hauer committed
438

Troy Kisky's avatar
Troy Kisky committed
439
	entries_free = fec_enet_get_free_txdesc_num(txq);
440 441 442 443 444 445 446
	if (entries_free < MAX_SKB_FRAGS + 1) {
		dev_kfree_skb_any(skb);
		if (net_ratelimit())
			netdev_err(ndev, "NOT enough BD for SG!\n");
		return NETDEV_TX_OK;
	}

447 448
	/* Protocol checksum off-load for TCP and UDP. */
	if (fec_enet_clear_csum(skb, ndev)) {
449
		dev_kfree_skb_any(skb);
450 451 452
		return NETDEV_TX_OK;
	}

453
	/* Fill in a Tx ring entry */
Troy Kisky's avatar
Troy Kisky committed
454
	bdp = txq->bd.cur;
455
	last_bdp = bdp;
456
	status = fec16_to_cpu(bdp->cbd_sc);
457
	status &= ~BD_ENET_TX_STATS;
Linus Torvalds's avatar
Linus Torvalds committed
458

Sascha Hauer's avatar
Sascha Hauer committed
459
	/* Set buffer length and buffer pointer */
460
	bufaddr = skb->data;
461
	buflen = skb_headlen(skb);
Linus Torvalds's avatar
Linus Torvalds committed
462

Troy Kisky's avatar
Troy Kisky committed
463
	index = fec_enet_get_bd_index(bdp, &txq->bd);
464
	if (((unsigned long) bufaddr) & fep->tx_align ||
465
		fep->quirks & FEC_QUIRK_SWAP_FRAME) {
466 467
		memcpy(txq->tx_bounce[index], skb->data, buflen);
		bufaddr = txq->tx_bounce[index];
Linus Torvalds's avatar
Linus Torvalds committed
468

469
		if (fep->quirks & FEC_QUIRK_SWAP_FRAME)
470 471
			swap_buffer(bufaddr, buflen);
	}
472

473 474 475
	/* Push the data cache so the CPM does not get stale memory data. */
	addr = dma_map_single(&fep->pdev->dev, bufaddr, buflen, DMA_TO_DEVICE);
	if (dma_mapping_error(&fep->pdev->dev, addr)) {
476 477 478 479 480
		dev_kfree_skb_any(skb);
		if (net_ratelimit())
			netdev_err(ndev, "Tx DMA memory map failed\n");
		return NETDEV_TX_OK;
	}
Linus Torvalds's avatar
Linus Torvalds committed
481

482
	if (nr_frags) {
483
		last_bdp = fec_enet_txq_submit_frag_skb(txq, skb, ndev);
Troy Kisky's avatar
Troy Kisky committed
484 485 486 487
		if (IS_ERR(last_bdp)) {
			dma_unmap_single(&fep->pdev->dev, addr,
					 buflen, DMA_TO_DEVICE);
			dev_kfree_skb_any(skb);
488
			return NETDEV_TX_OK;
Troy Kisky's avatar
Troy Kisky committed
489
		}
490 491 492 493 494 495 496 497 498
	} else {
		status |= (BD_ENET_TX_INTR | BD_ENET_TX_LAST);
		if (fep->bufdesc_ex) {
			estatus = BD_ENET_TX_INT;
			if (unlikely(skb_shinfo(skb)->tx_flags &
				SKBTX_HW_TSTAMP && fep->hwts_tx_en))
				estatus |= BD_ENET_TX_TS;
		}
	}
Troy Kisky's avatar
Troy Kisky committed
499 500
	bdp->cbd_bufaddr = cpu_to_fec32(addr);
	bdp->cbd_datlen = cpu_to_fec16(buflen);
501

502 503 504
	if (fep->bufdesc_ex) {

		struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp;
505

506
		if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP &&
507
			fep->hwts_tx_en))
508
			skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
509

510
		if (fep->quirks & FEC_QUIRK_HAS_AVB)
511
			estatus |= FEC_TX_BD_FTYPE(txq->bd.qid);
512

513 514 515 516
		if (skb->ip_summed == CHECKSUM_PARTIAL)
			estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS;

		ebdp->cbd_bdu = 0;
517
		ebdp->cbd_esc = cpu_to_fec32(estatus);
518
	}
519

Troy Kisky's avatar
Troy Kisky committed
520
	index = fec_enet_get_bd_index(last_bdp, &txq->bd);
521
	/* Save skb pointer */
522
	txq->tx_skbuff[index] = skb;
523

524 525 526 527
	/* Make sure the updates to rest of the descriptor are performed before
	 * transferring ownership.
	 */
	wmb();
528

529 530 531
	/* Send it on its way.  Tell FEC it's ready, interrupt when done,
	 * it's the last BD of the frame, and to put the CRC on the end.
	 */
532
	status |= (BD_ENET_TX_READY | BD_ENET_TX_TC);
533
	bdp->cbd_sc = cpu_to_fec16(status);
534

Sascha Hauer's avatar
Sascha Hauer committed
535
	/* If this was the last BD in the ring, start at the beginning again. */
Troy Kisky's avatar
Troy Kisky committed
536
	bdp = fec_enet_get_nextdesc(last_bdp, &txq->bd);
Linus Torvalds's avatar
Linus Torvalds committed
537

538 539
	skb_tx_timestamp(skb);

540
	/* Make sure the update to bdp and tx_skbuff are performed before
Troy Kisky's avatar
Troy Kisky committed
541
	 * txq->bd.cur.
542 543
	 */
	wmb();
Troy Kisky's avatar
Troy Kisky committed
544
	txq->bd.cur = bdp;
545 546

	/* Trigger transmission start */
547
	writel(0, txq->bd.reg_desc_active);
Linus Torvalds's avatar
Linus Torvalds committed
548

549
	return 0;
Linus Torvalds's avatar
Linus Torvalds committed
550 551
}

552
static int
553 554 555 556
fec_enet_txq_put_data_tso(struct fec_enet_priv_tx_q *txq, struct sk_buff *skb,
			  struct net_device *ndev,
			  struct bufdesc *bdp, int index, char *data,
			  int size, bool last_tcp, bool is_last)
557 558
{
	struct fec_enet_private *fep = netdev_priv(ndev);
559
	struct bufdesc_ex *ebdp = container_of(bdp, struct bufdesc_ex, desc);
560 561
	unsigned short status;
	unsigned int estatus = 0;
562
	dma_addr_t addr;
563

564
	status = fec16_to_cpu(bdp->cbd_sc);
565
	status &= ~BD_ENET_TX_STATS;
566

567 568
	status |= (BD_ENET_TX_TC | BD_ENET_TX_READY);

569
	if (((unsigned long) data) & fep->tx_align ||
570
		fep->quirks & FEC_QUIRK_SWAP_FRAME) {
571 572
		memcpy(txq->tx_bounce[index], data, size);
		data = txq->tx_bounce[index];
573

574
		if (fep->quirks & FEC_QUIRK_SWAP_FRAME)
575 576 577
			swap_buffer(data, size);
	}

578 579
	addr = dma_map_single(&fep->pdev->dev, data, size, DMA_TO_DEVICE);
	if (dma_mapping_error(&fep->pdev->dev, addr)) {
580
		dev_kfree_skb_any(skb);
581
		if (net_ratelimit())
582
			netdev_err(ndev, "Tx DMA memory map failed\n");
583 584 585
		return NETDEV_TX_BUSY;
	}

586 587
	bdp->cbd_datlen = cpu_to_fec16(size);
	bdp->cbd_bufaddr = cpu_to_fec32(addr);
588

589
	if (fep->bufdesc_ex) {
590
		if (fep->quirks & FEC_QUIRK_HAS_AVB)
591
			estatus |= FEC_TX_BD_FTYPE(txq->bd.qid);
592 593 594
		if (skb->ip_summed == CHECKSUM_PARTIAL)
			estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS;
		ebdp->cbd_bdu = 0;
595
		ebdp->cbd_esc = cpu_to_fec32(estatus);
596 597 598 599 600 601 602 603
	}

	/* Handle the last BD specially */
	if (last_tcp)
		status |= (BD_ENET_TX_LAST | BD_ENET_TX_TC);
	if (is_last) {
		status |= BD_ENET_TX_INTR;
		if (fep->bufdesc_ex)
604
			ebdp->cbd_esc |= cpu_to_fec32(BD_ENET_TX_INT);
605 606
	}

607
	bdp->cbd_sc = cpu_to_fec16(status);
608 609 610 611 612

	return 0;
}

static int
613 614 615
fec_enet_txq_put_hdr_tso(struct fec_enet_priv_tx_q *txq,
			 struct sk_buff *skb, struct net_device *ndev,
			 struct bufdesc *bdp, int index)
616 617 618
{
	struct fec_enet_private *fep = netdev_priv(ndev);
	int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
619
	struct bufdesc_ex *ebdp = container_of(bdp, struct bufdesc_ex, desc);
620 621 622 623 624
	void *bufaddr;
	unsigned long dmabuf;
	unsigned short status;
	unsigned int estatus = 0;

625
	status = fec16_to_cpu(bdp->cbd_sc);
626 627 628
	status &= ~BD_ENET_TX_STATS;
	status |= (BD_ENET_TX_TC | BD_ENET_TX_READY);

629 630
	bufaddr = txq->tso_hdrs + index * TSO_HEADER_SIZE;
	dmabuf = txq->tso_hdrs_dma + index * TSO_HEADER_SIZE;
631
	if (((unsigned long)bufaddr) & fep->tx_align ||
632
		fep->quirks & FEC_QUIRK_SWAP_FRAME) {
633 634
		memcpy(txq->tx_bounce[index], skb->data, hdr_len);
		bufaddr = txq->tx_bounce[index];
635

636
		if (fep->quirks & FEC_QUIRK_SWAP_FRAME)
637 638 639 640 641 642 643 644 645 646 647 648
			swap_buffer(bufaddr, hdr_len);

		dmabuf = dma_map_single(&fep->pdev->dev, bufaddr,
					hdr_len, DMA_TO_DEVICE);
		if (dma_mapping_error(&fep->pdev->dev, dmabuf)) {
			dev_kfree_skb_any(skb);
			if (net_ratelimit())
				netdev_err(ndev, "Tx DMA memory map failed\n");
			return NETDEV_TX_BUSY;
		}
	}

649 650
	bdp->cbd_bufaddr = cpu_to_fec32(dmabuf);
	bdp->cbd_datlen = cpu_to_fec16(hdr_len);
651 652

	if (fep->bufdesc_ex) {
653
		if (fep->quirks & FEC_QUIRK_HAS_AVB)
654
			estatus |= FEC_TX_BD_FTYPE(txq->bd.qid);
655 656 657
		if (skb->ip_summed == CHECKSUM_PARTIAL)
			estatus |= BD_ENET_TX_PINS | BD_ENET_TX_IINS;
		ebdp->cbd_bdu = 0;
658
		ebdp->cbd_esc = cpu_to_fec32(estatus);
659 660
	}

661
	bdp->cbd_sc = cpu_to_fec16(status);
662 663 664 665

	return 0;
}

666 667 668
static int fec_enet_txq_submit_tso(struct fec_enet_priv_tx_q *txq,
				   struct sk_buff *skb,
				   struct net_device *ndev)
669 670 671 672
{
	struct fec_enet_private *fep = netdev_priv(ndev);
	int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
	int total_len, data_left;
Troy Kisky's avatar
Troy Kisky committed
673
	struct bufdesc *bdp = txq->bd.cur;
674 675 676 677
	struct tso_t tso;
	unsigned int index = 0;
	int ret;

Troy Kisky's avatar
Troy Kisky committed
678
	if (tso_count_descs(skb) >= fec_enet_get_free_txdesc_num(txq)) {
679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697
		dev_kfree_skb_any(skb);
		if (net_ratelimit())
			netdev_err(ndev, "NOT enough BD for TSO!\n");
		return NETDEV_TX_OK;
	}

	/* Protocol checksum off-load for TCP and UDP. */
	if (fec_enet_clear_csum(skb, ndev)) {
		dev_kfree_skb_any(skb);
		return NETDEV_TX_OK;
	}

	/* Initialize the TSO handler, and prepare the first payload */
	tso_start(skb, &tso);

	total_len = skb->len - hdr_len;
	while (total_len > 0) {
		char *hdr;

Troy Kisky's avatar
Troy Kisky committed
698
		index = fec_enet_get_bd_index(bdp, &txq->bd);
699 700 701 702
		data_left = min_t(int, skb_shinfo(skb)->gso_size, total_len);
		total_len -= data_left;

		/* prepare packet headers: MAC + IP + TCP */
703
		hdr = txq->tso_hdrs + index * TSO_HEADER_SIZE;
704
		tso_build_hdr(skb, hdr, &tso, data_left, total_len == 0);
705
		ret = fec_enet_txq_put_hdr_tso(txq, skb, ndev, bdp, index);
706 707 708 709 710 711 712
		if (ret)
			goto err_release;

		while (data_left > 0) {
			int size;

			size = min_t(int, tso.size, data_left);
Troy Kisky's avatar
Troy Kisky committed
713 714
			bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
			index = fec_enet_get_bd_index(bdp, &txq->bd);
715 716 717 718
			ret = fec_enet_txq_put_data_tso(txq, skb, ndev,
							bdp, index,
							tso.data, size,
							size == data_left,
719 720 721 722 723 724 725 726
							total_len == 0);
			if (ret)
				goto err_release;

			data_left -= size;
			tso_build_data(skb, &tso, size);
		}

Troy Kisky's avatar
Troy Kisky committed
727
		bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
728 729 730
	}

	/* Save skb pointer */
731
	txq->tx_skbuff[index] = skb;
732 733

	skb_tx_timestamp(skb);
Troy Kisky's avatar
Troy Kisky committed
734
	txq->bd.cur = bdp;
735 736

	/* Trigger transmission start */
737
	if (!(fep->quirks & FEC_QUIRK_ERR007885) ||
738 739 740 741 742
	    !readl(txq->bd.reg_desc_active) ||
	    !readl(txq->bd.reg_desc_active) ||
	    !readl(txq->bd.reg_desc_active) ||
	    !readl(txq->bd.reg_desc_active))
		writel(0, txq->bd.reg_desc_active);
743 744 745 746 747 748 749 750 751 752 753 754 755

	return 0;

err_release:
	/* TODO: Release all used data descriptors for TSO */
	return ret;
}

static netdev_tx_t
fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
{
	struct fec_enet_private *fep = netdev_priv(ndev);
	int entries_free;
756 757 758
	unsigned short queue;
	struct fec_enet_priv_tx_q *txq;
	struct netdev_queue *nq;
759 760
	int ret;

761 762 763 764
	queue = skb_get_queue_mapping(skb);
	txq = fep->tx_queue[queue];
	nq = netdev_get_tx_queue(ndev, queue);

765
	if (skb_is_gso(skb))
766
		ret = fec_enet_txq_submit_tso(txq, skb, ndev);
767
	else
768
		ret = fec_enet_txq_submit_skb(txq, skb, ndev);
769 770
	if (ret)
		return ret;
771

Troy Kisky's avatar
Troy Kisky committed
772
	entries_free = fec_enet_get_free_txdesc_num(txq);
773 774
	if (entries_free <= txq->tx_stop_threshold)
		netif_tx_stop_queue(nq);
775 776 777 778

	return NETDEV_TX_OK;
}

779 780 781 782 783
/* Init RX & TX buffer descriptors
 */
static void fec_enet_bd_init(struct net_device *dev)
{
	struct fec_enet_private *fep = netdev_priv(dev);
784 785
	struct fec_enet_priv_tx_q *txq;
	struct fec_enet_priv_rx_q *rxq;
786 787
	struct bufdesc *bdp;
	unsigned int i;
788
	unsigned int q;
789

790 791 792
	for (q = 0; q < fep->num_rx_queues; q++) {
		/* Initialize the receive buffer descriptors. */
		rxq = fep->rx_queue[q];
Troy Kisky's avatar
Troy Kisky committed
793
		bdp = rxq->bd.base;
794

Troy Kisky's avatar
Troy Kisky committed
795
		for (i = 0; i < rxq->bd.ring_size; i++) {
796

797 798
			/* Initialize the BD for every fragment in the page. */
			if (bdp->cbd_bufaddr)
799
				bdp->cbd_sc = cpu_to_fec16(BD_ENET_RX_EMPTY);
800
			else
801
				bdp->cbd_sc = cpu_to_fec16(0);
Troy Kisky's avatar
Troy Kisky committed
802
			bdp = fec_enet_get_nextdesc(bdp, &rxq->bd);
803 804 805
		}

		/* Set the last buffer to wrap */
Troy Kisky's avatar
Troy Kisky committed
806
		bdp = fec_enet_get_prevdesc(bdp, &rxq->bd);
807
		bdp->cbd_sc |= cpu_to_fec16(BD_SC_WRAP);
808

Troy Kisky's avatar
Troy Kisky committed
809
		rxq->bd.cur = rxq->bd.base;
810 811 812 813 814
	}

	for (q = 0; q < fep->num_tx_queues; q++) {
		/* ...and the same for transmit */
		txq = fep->tx_queue[q];
Troy Kisky's avatar
Troy Kisky committed
815 816
		bdp = txq->bd.base;
		txq->bd.cur = bdp;
817

Troy Kisky's avatar
Troy Kisky committed
818
		for (i = 0; i < txq->bd.ring_size; i++) {
819
			/* Initialize the BD for every fragment in the page. */
820
			bdp->cbd_sc = cpu_to_fec16(0);
821 822 823 824 825 826
			if (bdp->cbd_bufaddr &&
			    !IS_TSO_HEADER(txq, fec32_to_cpu(bdp->cbd_bufaddr)))
				dma_unmap_single(&fep->pdev->dev,
						 fec32_to_cpu(bdp->cbd_bufaddr),
						 fec16_to_cpu(bdp->cbd_datlen),
						 DMA_TO_DEVICE);
827 828 829 830
			if (txq->tx_skbuff[i]) {
				dev_kfree_skb_any(txq->tx_skbuff[i]);
				txq->tx_skbuff[i] = NULL;
			}
831
			bdp->cbd_bufaddr = cpu_to_fec32(0);
Troy Kisky's avatar
Troy Kisky committed
832
			bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
833 834 835
		}

		/* Set the last buffer to wrap */
Troy Kisky's avatar
Troy Kisky committed
836
		bdp = fec_enet_get_prevdesc(bdp, &txq->bd);
837
		bdp->cbd_sc |= cpu_to_fec16(BD_SC_WRAP);
838
		txq->dirty_tx = bdp;
839
	}
840
}
841

Frank Li's avatar
Frank Li committed
842 843 844 845 846 847
static void fec_enet_active_rxring(struct net_device *ndev)
{
	struct fec_enet_private *fep = netdev_priv(ndev);
	int i;

	for (i = 0; i < fep->num_rx_queues; i++)
848
		writel(0, fep->rx_queue[i]->bd.reg_desc_active);
Frank Li's avatar
Frank Li committed
849 850
}

851 852 853 854 855 856
static void fec_enet_enable_ring(struct net_device *ndev)
{
	struct fec_enet_private *fep = netdev_priv(ndev);
	struct fec_enet_priv_tx_q *txq;
	struct fec_enet_priv_rx_q *rxq;
	int i;
857

858 859
	for (i = 0; i < fep->num_rx_queues; i++) {
		rxq = fep->rx_queue[i];
Troy Kisky's avatar
Troy Kisky committed
860
		writel(rxq->bd.dma, fep->hwp + FEC_R_DES_START(i));
861
		writel(PKT_MAXBUF_SIZE, fep->hwp + FEC_R_BUFF_SIZE(i));
862

863 864 865 866 867
		/* enable DMA1/2 */
		if (i)
			writel(RCMR_MATCHEN | RCMR_CMP(i),
			       fep->hwp + FEC_RCMR(i));
	}
868

869 870
	for (i = 0; i < fep->num_tx_queues; i++) {
		txq = fep->tx_queue[i];
Troy Kisky's avatar
Troy Kisky committed
871
		writel(txq->bd.dma, fep->hwp + FEC_X_DES_START(i));
872 873 874 875 876

		/* enable DMA1/2 */
		if (i)
			writel(DMA_CLASS_EN | IDLE_SLOPE(i),
			       fep->hwp + FEC_DMA_CFG(i));
877
	}
878
}
879

880 881 882 883 884 885 886 887 888
static void fec_enet_reset_skb(struct net_device *ndev)
{
	struct fec_enet_private *fep = netdev_priv(ndev);
	struct fec_enet_priv_tx_q *txq;
	int i, j;

	for (i = 0; i < fep->num_tx_queues; i++) {
		txq = fep->tx_queue[i];

Troy Kisky's avatar
Troy Kisky committed
889
		for (j = 0; j < txq->bd.ring_size; j++) {
Frank Li's avatar