bgmac.c 41.0 KB
Newer Older
1 2 3 4 5 6 7 8 9
/*
 * Driver for (BCM4706)? GBit MAC core on BCMA bus.
 *
 * Copyright (C) 2012 Rafał Miłecki <zajec5@gmail.com>
 *
 * Licensed under the GNU/GPL. See COPYING for details.
 */


10 11 12
#define pr_fmt(fmt)		KBUILD_MODNAME ": " fmt

#include <linux/bcma/bcma.h>
13
#include <linux/etherdevice.h>
14
#include <linux/bcm47xx_nvram.h>
15 16
#include <linux/phy.h>
#include <linux/phy_fixed.h>
17
#include "bgmac.h"
18

19
static bool bgmac_wait_value(struct bgmac *bgmac, u16 reg, u32 mask,
20 21 22 23 24 25
			     u32 value, int timeout)
{
	u32 val;
	int i;

	for (i = 0; i < timeout / 10; i++) {
26
		val = bgmac_read(bgmac, reg);
27 28 29 30
		if ((val & mask) == value)
			return true;
		udelay(10);
	}
31
	dev_err(bgmac->dev, "Timeout waiting for reg 0x%X\n", reg);
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
	return false;
}

/**************************************************
 * DMA
 **************************************************/

static void bgmac_dma_tx_reset(struct bgmac *bgmac, struct bgmac_dma_ring *ring)
{
	u32 val;
	int i;

	if (!ring->mmio_base)
		return;

	/* Suspend DMA TX ring first.
	 * bgmac_wait_value doesn't support waiting for any of few values, so
	 * implement whole loop here.
	 */
	bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_TX_CTL,
		    BGMAC_DMA_TX_SUSPEND);
	for (i = 0; i < 10000 / 10; i++) {
		val = bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_TX_STATUS);
		val &= BGMAC_DMA_TX_STAT;
		if (val == BGMAC_DMA_TX_STAT_DISABLED ||
		    val == BGMAC_DMA_TX_STAT_IDLEWAIT ||
		    val == BGMAC_DMA_TX_STAT_STOPPED) {
			i = 0;
			break;
		}
		udelay(10);
	}
	if (i)
65 66
		dev_err(bgmac->dev, "Timeout suspending DMA TX ring 0x%X (BGMAC_DMA_TX_STAT: 0x%08X)\n",
			ring->mmio_base, val);
67 68 69

	/* Remove SUSPEND bit */
	bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_TX_CTL, 0);
70
	if (!bgmac_wait_value(bgmac,
71 72 73
			      ring->mmio_base + BGMAC_DMA_TX_STATUS,
			      BGMAC_DMA_TX_STAT, BGMAC_DMA_TX_STAT_DISABLED,
			      10000)) {
74 75
		dev_warn(bgmac->dev, "DMA TX ring 0x%X wasn't disabled on time, waiting additional 300us\n",
			 ring->mmio_base);
76 77 78
		udelay(300);
		val = bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_TX_STATUS);
		if ((val & BGMAC_DMA_TX_STAT) != BGMAC_DMA_TX_STAT_DISABLED)
79 80
			dev_err(bgmac->dev, "Reset of DMA TX ring 0x%X failed\n",
				ring->mmio_base);
81 82 83 84 85 86 87 88 89
	}
}

static void bgmac_dma_tx_enable(struct bgmac *bgmac,
				struct bgmac_dma_ring *ring)
{
	u32 ctl;

	ctl = bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_TX_CTL);
90
	if (bgmac->feature_flags & BGMAC_FEAT_TX_MASK_SETUP) {
91 92 93 94 95 96 97 98 99 100 101 102
		ctl &= ~BGMAC_DMA_TX_BL_MASK;
		ctl |= BGMAC_DMA_TX_BL_128 << BGMAC_DMA_TX_BL_SHIFT;

		ctl &= ~BGMAC_DMA_TX_MR_MASK;
		ctl |= BGMAC_DMA_TX_MR_2 << BGMAC_DMA_TX_MR_SHIFT;

		ctl &= ~BGMAC_DMA_TX_PC_MASK;
		ctl |= BGMAC_DMA_TX_PC_16 << BGMAC_DMA_TX_PC_SHIFT;

		ctl &= ~BGMAC_DMA_TX_PT_MASK;
		ctl |= BGMAC_DMA_TX_PT_8 << BGMAC_DMA_TX_PT_SHIFT;
	}
103 104 105 106 107
	ctl |= BGMAC_DMA_TX_ENABLE;
	ctl |= BGMAC_DMA_TX_PARITY_DISABLE;
	bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_TX_CTL, ctl);
}

108 109 110 111 112 113 114 115
static void
bgmac_dma_tx_add_buf(struct bgmac *bgmac, struct bgmac_dma_ring *ring,
		     int i, int len, u32 ctl0)
{
	struct bgmac_slot_info *slot;
	struct bgmac_dma_desc *dma_desc;
	u32 ctl1;

F
Felix Fietkau 已提交
116
	if (i == BGMAC_TX_RING_SLOTS - 1)
117 118 119 120 121 122 123 124 125 126 127 128
		ctl0 |= BGMAC_DESC_CTL0_EOT;

	ctl1 = len & BGMAC_DESC_CTL1_LEN;

	slot = &ring->slots[i];
	dma_desc = &ring->cpu_base[i];
	dma_desc->addr_low = cpu_to_le32(lower_32_bits(slot->dma_addr));
	dma_desc->addr_high = cpu_to_le32(upper_32_bits(slot->dma_addr));
	dma_desc->ctl0 = cpu_to_le32(ctl0);
	dma_desc->ctl1 = cpu_to_le32(ctl1);
}

129 130 131 132
static netdev_tx_t bgmac_dma_tx_add(struct bgmac *bgmac,
				    struct bgmac_dma_ring *ring,
				    struct sk_buff *skb)
{
133
	struct device *dma_dev = bgmac->dma_dev;
134
	struct net_device *net_dev = bgmac->net_dev;
135 136
	int index = ring->end % BGMAC_TX_RING_SLOTS;
	struct bgmac_slot_info *slot = &ring->slots[index];
137 138 139
	int nr_frags;
	u32 flags;
	int i;
140 141

	if (skb->len > BGMAC_DESC_CTL1_LEN) {
142
		netdev_err(bgmac->net_dev, "Too long skb (%d)\n", skb->len);
143
		goto err_drop;
144 145
	}

146 147 148 149 150
	if (skb->ip_summed == CHECKSUM_PARTIAL)
		skb_checksum_help(skb);

	nr_frags = skb_shinfo(skb)->nr_frags;

151 152 153 154
	/* ring->end - ring->start will return the number of valid slots,
	 * even when ring->end overflows
	 */
	if (ring->end - ring->start + nr_frags + 1 >= BGMAC_TX_RING_SLOTS) {
155
		netdev_err(bgmac->net_dev, "TX ring is full, queue should be stopped!\n");
156 157 158 159
		netif_stop_queue(net_dev);
		return NETDEV_TX_BUSY;
	}

160
	slot->dma_addr = dma_map_single(dma_dev, skb->data, skb_headlen(skb),
161
					DMA_TO_DEVICE);
162 163
	if (unlikely(dma_mapping_error(dma_dev, slot->dma_addr)))
		goto err_dma_head;
164

165 166 167
	flags = BGMAC_DESC_CTL0_SOF;
	if (!nr_frags)
		flags |= BGMAC_DESC_CTL0_EOF | BGMAC_DESC_CTL0_IOC;
168

169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
	bgmac_dma_tx_add_buf(bgmac, ring, index, skb_headlen(skb), flags);
	flags = 0;

	for (i = 0; i < nr_frags; i++) {
		struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i];
		int len = skb_frag_size(frag);

		index = (index + 1) % BGMAC_TX_RING_SLOTS;
		slot = &ring->slots[index];
		slot->dma_addr = skb_frag_dma_map(dma_dev, frag, 0,
						  len, DMA_TO_DEVICE);
		if (unlikely(dma_mapping_error(dma_dev, slot->dma_addr)))
			goto err_dma;

		if (i == nr_frags - 1)
			flags |= BGMAC_DESC_CTL0_EOF | BGMAC_DESC_CTL0_IOC;

		bgmac_dma_tx_add_buf(bgmac, ring, index, len, flags);
	}

	slot->skb = skb;
190
	ring->end += nr_frags + 1;
191 192
	netdev_sent_queue(net_dev, skb->len);

193 194 195 196 197 198
	wmb();

	/* Increase ring->end to point empty slot. We tell hardware the first
	 * slot it should *not* read.
	 */
	bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_TX_INDEX,
199
		    ring->index_base +
200 201
		    (ring->end % BGMAC_TX_RING_SLOTS) *
		    sizeof(struct bgmac_dma_desc));
202

203
	if (ring->end - ring->start >= BGMAC_TX_RING_SLOTS - 8)
204 205 206 207
		netif_stop_queue(net_dev);

	return NETDEV_TX_OK;

208 209 210 211
err_dma:
	dma_unmap_single(dma_dev, slot->dma_addr, skb_headlen(skb),
			 DMA_TO_DEVICE);

212
	while (i-- > 0) {
213 214 215 216 217 218 219 220 221
		int index = (ring->end + i) % BGMAC_TX_RING_SLOTS;
		struct bgmac_slot_info *slot = &ring->slots[index];
		u32 ctl1 = le32_to_cpu(ring->cpu_base[index].ctl1);
		int len = ctl1 & BGMAC_DESC_CTL1_LEN;

		dma_unmap_page(dma_dev, slot->dma_addr, len, DMA_TO_DEVICE);
	}

err_dma_head:
222 223
	netdev_err(bgmac->net_dev, "Mapping error of skb on ring 0x%X\n",
		   ring->mmio_base);
224 225

err_drop:
226
	dev_kfree_skb(skb);
227 228
	net_dev->stats.tx_dropped++;
	net_dev->stats.tx_errors++;
229 230 231 232 233 234
	return NETDEV_TX_OK;
}

/* Free transmitted packets */
static void bgmac_dma_tx_free(struct bgmac *bgmac, struct bgmac_dma_ring *ring)
{
235
	struct device *dma_dev = bgmac->dma_dev;
236 237
	int empty_slot;
	bool freed = false;
238
	unsigned bytes_compl = 0, pkts_compl = 0;
239 240 241 242

	/* The last slot that hardware didn't consume yet */
	empty_slot = bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_TX_STATUS);
	empty_slot &= BGMAC_DMA_TX_STATDPTR;
243 244
	empty_slot -= ring->index_base;
	empty_slot &= BGMAC_DMA_TX_STATDPTR;
245 246
	empty_slot /= sizeof(struct bgmac_dma_desc);

247 248 249
	while (ring->start != ring->end) {
		int slot_idx = ring->start % BGMAC_TX_RING_SLOTS;
		struct bgmac_slot_info *slot = &ring->slots[slot_idx];
250
		u32 ctl0, ctl1;
251
		int len;
252

253 254
		if (slot_idx == empty_slot)
			break;
255

256
		ctl0 = le32_to_cpu(ring->cpu_base[slot_idx].ctl0);
257 258
		ctl1 = le32_to_cpu(ring->cpu_base[slot_idx].ctl1);
		len = ctl1 & BGMAC_DESC_CTL1_LEN;
259
		if (ctl0 & BGMAC_DESC_CTL0_SOF)
260
			/* Unmap no longer used buffer */
261 262 263 264 265
			dma_unmap_single(dma_dev, slot->dma_addr, len,
					 DMA_TO_DEVICE);
		else
			dma_unmap_page(dma_dev, slot->dma_addr, len,
				       DMA_TO_DEVICE);
266

267
		if (slot->skb) {
268 269
			bgmac->net_dev->stats.tx_bytes += slot->skb->len;
			bgmac->net_dev->stats.tx_packets++;
270 271 272
			bytes_compl += slot->skb->len;
			pkts_compl++;

273 274 275 276 277
			/* Free memory! :) */
			dev_kfree_skb(slot->skb);
			slot->skb = NULL;
		}

278
		slot->dma_addr = 0;
279
		ring->start++;
280 281 282
		freed = true;
	}

283 284 285
	if (!pkts_compl)
		return;

286 287
	netdev_completed_queue(bgmac->net_dev, pkts_compl, bytes_compl);

288
	if (netif_queue_stopped(bgmac->net_dev))
289 290 291 292 293 294 295 296 297
		netif_wake_queue(bgmac->net_dev);
}

static void bgmac_dma_rx_reset(struct bgmac *bgmac, struct bgmac_dma_ring *ring)
{
	if (!ring->mmio_base)
		return;

	bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_RX_CTL, 0);
298
	if (!bgmac_wait_value(bgmac,
299 300 301
			      ring->mmio_base + BGMAC_DMA_RX_STATUS,
			      BGMAC_DMA_RX_STAT, BGMAC_DMA_RX_STAT_DISABLED,
			      10000))
302 303
		dev_err(bgmac->dev, "Reset of ring 0x%X RX failed\n",
			ring->mmio_base);
304 305 306 307 308 309 310 311
}

static void bgmac_dma_rx_enable(struct bgmac *bgmac,
				struct bgmac_dma_ring *ring)
{
	u32 ctl;

	ctl = bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_RX_CTL);
312 313 314 315

	/* preserve ONLY bits 16-17 from current hardware value */
	ctl &= BGMAC_DMA_RX_ADDREXT_MASK;

316
	if (bgmac->feature_flags & BGMAC_FEAT_RX_MASK_SETUP) {
317 318 319 320 321 322 323 324 325
		ctl &= ~BGMAC_DMA_RX_BL_MASK;
		ctl |= BGMAC_DMA_RX_BL_128 << BGMAC_DMA_RX_BL_SHIFT;

		ctl &= ~BGMAC_DMA_RX_PC_MASK;
		ctl |= BGMAC_DMA_RX_PC_8 << BGMAC_DMA_RX_PC_SHIFT;

		ctl &= ~BGMAC_DMA_RX_PT_MASK;
		ctl |= BGMAC_DMA_RX_PT_1 << BGMAC_DMA_RX_PT_SHIFT;
	}
326 327 328 329 330 331 332 333 334 335
	ctl |= BGMAC_DMA_RX_ENABLE;
	ctl |= BGMAC_DMA_RX_PARITY_DISABLE;
	ctl |= BGMAC_DMA_RX_OVERFLOW_CONT;
	ctl |= BGMAC_RX_FRAME_OFFSET << BGMAC_DMA_RX_FRAME_OFFSET_SHIFT;
	bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_RX_CTL, ctl);
}

static int bgmac_dma_rx_skb_for_slot(struct bgmac *bgmac,
				     struct bgmac_slot_info *slot)
{
336
	struct device *dma_dev = bgmac->dma_dev;
337
	dma_addr_t dma_addr;
338
	struct bgmac_rx_header *rx;
339
	void *buf;
340 341

	/* Alloc skb */
342 343
	buf = netdev_alloc_frag(BGMAC_RX_ALLOC_SIZE);
	if (!buf)
344 345 346
		return -ENOMEM;

	/* Poison - if everything goes fine, hardware will overwrite it */
347
	rx = buf + BGMAC_RX_BUF_OFFSET;
348 349 350 351
	rx->len = cpu_to_le16(0xdead);
	rx->flags = cpu_to_le16(0xbeef);

	/* Map skb for the DMA */
352 353
	dma_addr = dma_map_single(dma_dev, buf + BGMAC_RX_BUF_OFFSET,
				  BGMAC_RX_BUF_SIZE, DMA_FROM_DEVICE);
354
	if (dma_mapping_error(dma_dev, dma_addr)) {
355
		netdev_err(bgmac->net_dev, "DMA mapping error\n");
356
		put_page(virt_to_head_page(buf));
357 358
		return -ENOMEM;
	}
359 360

	/* Update the slot */
361
	slot->buf = buf;
362 363
	slot->dma_addr = dma_addr;

364 365 366
	return 0;
}

F
Felix Fietkau 已提交
367 368 369 370 371 372 373 374 375 376
static void bgmac_dma_rx_update_index(struct bgmac *bgmac,
				      struct bgmac_dma_ring *ring)
{
	dma_wmb();

	bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_RX_INDEX,
		    ring->index_base +
		    ring->end * sizeof(struct bgmac_dma_desc));
}

377 378 379 380 381 382
static void bgmac_dma_rx_setup_desc(struct bgmac *bgmac,
				    struct bgmac_dma_ring *ring, int desc_idx)
{
	struct bgmac_dma_desc *dma_desc = ring->cpu_base + desc_idx;
	u32 ctl0 = 0, ctl1 = 0;

F
Felix Fietkau 已提交
383
	if (desc_idx == BGMAC_RX_RING_SLOTS - 1)
384 385 386 387 388 389 390 391 392 393 394
		ctl0 |= BGMAC_DESC_CTL0_EOT;
	ctl1 |= BGMAC_RX_BUF_SIZE & BGMAC_DESC_CTL1_LEN;
	/* Is there any BGMAC device that requires extension? */
	/* ctl1 |= (addrext << B43_DMA64_DCTL1_ADDREXT_SHIFT) &
	 * B43_DMA64_DCTL1_ADDREXT_MASK;
	 */

	dma_desc->addr_low = cpu_to_le32(lower_32_bits(ring->slots[desc_idx].dma_addr));
	dma_desc->addr_high = cpu_to_le32(upper_32_bits(ring->slots[desc_idx].dma_addr));
	dma_desc->ctl0 = cpu_to_le32(ctl0);
	dma_desc->ctl1 = cpu_to_le32(ctl1);
F
Felix Fietkau 已提交
395 396

	ring->end = desc_idx;
397 398
}

399 400 401 402 403 404 405 406 407 408 409 410 411
static void bgmac_dma_rx_poison_buf(struct device *dma_dev,
				    struct bgmac_slot_info *slot)
{
	struct bgmac_rx_header *rx = slot->buf + BGMAC_RX_BUF_OFFSET;

	dma_sync_single_for_cpu(dma_dev, slot->dma_addr, BGMAC_RX_BUF_SIZE,
				DMA_FROM_DEVICE);
	rx->len = cpu_to_le16(0xdead);
	rx->flags = cpu_to_le16(0xbeef);
	dma_sync_single_for_device(dma_dev, slot->dma_addr, BGMAC_RX_BUF_SIZE,
				   DMA_FROM_DEVICE);
}

412 413 414 415 416 417 418 419
static int bgmac_dma_rx_read(struct bgmac *bgmac, struct bgmac_dma_ring *ring,
			     int weight)
{
	u32 end_slot;
	int handled = 0;

	end_slot = bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_RX_STATUS);
	end_slot &= BGMAC_DMA_RX_STATDPTR;
420 421
	end_slot -= ring->index_base;
	end_slot &= BGMAC_DMA_RX_STATDPTR;
422 423
	end_slot /= sizeof(struct bgmac_dma_desc);

F
Felix Fietkau 已提交
424
	while (ring->start != end_slot) {
425
		struct device *dma_dev = bgmac->dma_dev;
426
		struct bgmac_slot_info *slot = &ring->slots[ring->start];
427
		struct bgmac_rx_header *rx = slot->buf + BGMAC_RX_BUF_OFFSET;
428 429
		struct sk_buff *skb;
		void *buf = slot->buf;
430
		dma_addr_t dma_addr = slot->dma_addr;
431 432
		u16 len, flags;

433 434 435 436 437 438
		do {
			/* Prepare new skb as replacement */
			if (bgmac_dma_rx_skb_for_slot(bgmac, slot)) {
				bgmac_dma_rx_poison_buf(dma_dev, slot);
				break;
			}
439

440 441 442
			/* Unmap buffer to make it accessible to the CPU */
			dma_unmap_single(dma_dev, dma_addr,
					 BGMAC_RX_BUF_SIZE, DMA_FROM_DEVICE);
443

444 445 446
			/* Get info from the header */
			len = le16_to_cpu(rx->len);
			flags = le16_to_cpu(rx->flags);
447 448 449

			/* Check for poison and drop or pass the packet */
			if (len == 0xdead && flags == 0xbeef) {
450 451
				netdev_err(bgmac->net_dev, "Found poisoned packet at slot %d, DMA issue!\n",
					   ring->start);
452
				put_page(virt_to_head_page(buf));
453
				bgmac->net_dev->stats.rx_errors++;
454 455 456
				break;
			}

457
			if (len > BGMAC_RX_ALLOC_SIZE) {
458 459
				netdev_err(bgmac->net_dev, "Found oversized packet at slot %d, DMA issue!\n",
					   ring->start);
460
				put_page(virt_to_head_page(buf));
461 462
				bgmac->net_dev->stats.rx_length_errors++;
				bgmac->net_dev->stats.rx_errors++;
463 464 465
				break;
			}

H
Hauke Mehrtens 已提交
466 467 468
			/* Omit CRC. */
			len -= ETH_FCS_LEN;

469
			skb = build_skb(buf, BGMAC_RX_ALLOC_SIZE);
470
			if (unlikely(!skb)) {
471
				netdev_err(bgmac->net_dev, "build_skb failed\n");
472
				put_page(virt_to_head_page(buf));
473
				bgmac->net_dev->stats.rx_errors++;
474 475
				break;
			}
476 477 478 479
			skb_put(skb, BGMAC_RX_FRAME_OFFSET +
				BGMAC_RX_BUF_OFFSET + len);
			skb_pull(skb, BGMAC_RX_FRAME_OFFSET +
				 BGMAC_RX_BUF_OFFSET);
480

481 482
			skb_checksum_none_assert(skb);
			skb->protocol = eth_type_trans(skb, bgmac->net_dev);
483 484
			bgmac->net_dev->stats.rx_bytes += len;
			bgmac->net_dev->stats.rx_packets++;
485
			napi_gro_receive(&bgmac->napi, skb);
486 487
			handled++;
		} while (0);
488

489 490
		bgmac_dma_rx_setup_desc(bgmac, ring, ring->start);

491 492 493 494 495 496 497
		if (++ring->start >= BGMAC_RX_RING_SLOTS)
			ring->start = 0;

		if (handled >= weight) /* Should never be greater */
			break;
	}

F
Felix Fietkau 已提交
498 499
	bgmac_dma_rx_update_index(bgmac, ring);

500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524
	return handled;
}

/* Does ring support unaligned addressing? */
static bool bgmac_dma_unaligned(struct bgmac *bgmac,
				struct bgmac_dma_ring *ring,
				enum bgmac_dma_ring_type ring_type)
{
	switch (ring_type) {
	case BGMAC_DMA_RING_TX:
		bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_TX_RINGLO,
			    0xff0);
		if (bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_TX_RINGLO))
			return true;
		break;
	case BGMAC_DMA_RING_RX:
		bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_RX_RINGLO,
			    0xff0);
		if (bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_RX_RINGLO))
			return true;
		break;
	}
	return false;
}

525 526
static void bgmac_dma_tx_ring_free(struct bgmac *bgmac,
				   struct bgmac_dma_ring *ring)
527
{
528
	struct device *dma_dev = bgmac->dma_dev;
529
	struct bgmac_dma_desc *dma_desc = ring->cpu_base;
530 531 532
	struct bgmac_slot_info *slot;
	int i;

F
Felix Fietkau 已提交
533
	for (i = 0; i < BGMAC_TX_RING_SLOTS; i++) {
534 535
		int len = dma_desc[i].ctl1 & BGMAC_DESC_CTL1_LEN;

536
		slot = &ring->slots[i];
537 538 539 540 541 542 543 544 545 546 547
		dev_kfree_skb(slot->skb);

		if (!slot->dma_addr)
			continue;

		if (slot->skb)
			dma_unmap_single(dma_dev, slot->dma_addr,
					 len, DMA_TO_DEVICE);
		else
			dma_unmap_page(dma_dev, slot->dma_addr,
				       len, DMA_TO_DEVICE);
548
	}
549 550 551 552 553
}

static void bgmac_dma_rx_ring_free(struct bgmac *bgmac,
				   struct bgmac_dma_ring *ring)
{
554
	struct device *dma_dev = bgmac->dma_dev;
555 556 557
	struct bgmac_slot_info *slot;
	int i;

F
Felix Fietkau 已提交
558
	for (i = 0; i < BGMAC_RX_RING_SLOTS; i++) {
559
		slot = &ring->slots[i];
560
		if (!slot->dma_addr)
561
			continue;
562

563 564 565
		dma_unmap_single(dma_dev, slot->dma_addr,
				 BGMAC_RX_BUF_SIZE,
				 DMA_FROM_DEVICE);
566
		put_page(virt_to_head_page(slot->buf));
567
		slot->dma_addr = 0;
568 569 570
	}
}

571
static void bgmac_dma_ring_desc_free(struct bgmac *bgmac,
F
Felix Fietkau 已提交
572 573
				     struct bgmac_dma_ring *ring,
				     int num_slots)
574
{
575
	struct device *dma_dev = bgmac->dma_dev;
576 577 578 579 580 581
	int size;

	if (!ring->cpu_base)
	    return;

	/* Free ring of descriptors */
F
Felix Fietkau 已提交
582
	size = num_slots * sizeof(struct bgmac_dma_desc);
583 584 585 586
	dma_free_coherent(dma_dev, size, ring->cpu_base,
			  ring->dma_base);
}

F
Felix Fietkau 已提交
587
static void bgmac_dma_cleanup(struct bgmac *bgmac)
588 589 590
{
	int i;

F
Felix Fietkau 已提交
591
	for (i = 0; i < BGMAC_MAX_TX_RINGS; i++)
592
		bgmac_dma_tx_ring_free(bgmac, &bgmac->tx_ring[i]);
F
Felix Fietkau 已提交
593 594

	for (i = 0; i < BGMAC_MAX_RX_RINGS; i++)
595
		bgmac_dma_rx_ring_free(bgmac, &bgmac->rx_ring[i]);
F
Felix Fietkau 已提交
596 597 598 599 600 601 602
}

static void bgmac_dma_free(struct bgmac *bgmac)
{
	int i;

	for (i = 0; i < BGMAC_MAX_TX_RINGS; i++)
F
Felix Fietkau 已提交
603 604
		bgmac_dma_ring_desc_free(bgmac, &bgmac->tx_ring[i],
					 BGMAC_TX_RING_SLOTS);
F
Felix Fietkau 已提交
605 606

	for (i = 0; i < BGMAC_MAX_RX_RINGS; i++)
F
Felix Fietkau 已提交
607 608
		bgmac_dma_ring_desc_free(bgmac, &bgmac->rx_ring[i],
					 BGMAC_RX_RING_SLOTS);
609 610 611 612
}

static int bgmac_dma_alloc(struct bgmac *bgmac)
{
613
	struct device *dma_dev = bgmac->dma_dev;
614 615 616 617 618 619 620 621 622 623
	struct bgmac_dma_ring *ring;
	static const u16 ring_base[] = { BGMAC_DMA_BASE0, BGMAC_DMA_BASE1,
					 BGMAC_DMA_BASE2, BGMAC_DMA_BASE3, };
	int size; /* ring size: different for Tx and Rx */
	int err;
	int i;

	BUILD_BUG_ON(BGMAC_MAX_TX_RINGS > ARRAY_SIZE(ring_base));
	BUILD_BUG_ON(BGMAC_MAX_RX_RINGS > ARRAY_SIZE(ring_base));

624
	if (!(bgmac_idm_read(bgmac, BCMA_IOST) & BCMA_IOST_DMA64)) {
625
		dev_err(bgmac->dev, "Core does not report 64-bit DMA\n");
626 627 628 629 630 631 632 633
		return -ENOTSUPP;
	}

	for (i = 0; i < BGMAC_MAX_TX_RINGS; i++) {
		ring = &bgmac->tx_ring[i];
		ring->mmio_base = ring_base[i];

		/* Alloc ring of descriptors */
F
Felix Fietkau 已提交
634
		size = BGMAC_TX_RING_SLOTS * sizeof(struct bgmac_dma_desc);
635 636 637 638
		ring->cpu_base = dma_zalloc_coherent(dma_dev, size,
						     &ring->dma_base,
						     GFP_KERNEL);
		if (!ring->cpu_base) {
639 640
			dev_err(bgmac->dev, "Allocation of TX ring 0x%X failed\n",
				ring->mmio_base);
641 642 643
			goto err_dma_free;
		}

644 645 646 647 648 649 650
		ring->unaligned = bgmac_dma_unaligned(bgmac, ring,
						      BGMAC_DMA_RING_TX);
		if (ring->unaligned)
			ring->index_base = lower_32_bits(ring->dma_base);
		else
			ring->index_base = 0;

651 652 653 654 655 656 657 658
		/* No need to alloc TX slots yet */
	}

	for (i = 0; i < BGMAC_MAX_RX_RINGS; i++) {
		ring = &bgmac->rx_ring[i];
		ring->mmio_base = ring_base[i];

		/* Alloc ring of descriptors */
F
Felix Fietkau 已提交
659
		size = BGMAC_RX_RING_SLOTS * sizeof(struct bgmac_dma_desc);
660 661 662 663
		ring->cpu_base = dma_zalloc_coherent(dma_dev, size,
						     &ring->dma_base,
						     GFP_KERNEL);
		if (!ring->cpu_base) {
664 665
			dev_err(bgmac->dev, "Allocation of RX ring 0x%X failed\n",
				ring->mmio_base);
666 667 668 669
			err = -ENOMEM;
			goto err_dma_free;
		}

670 671 672 673 674 675
		ring->unaligned = bgmac_dma_unaligned(bgmac, ring,
						      BGMAC_DMA_RING_RX);
		if (ring->unaligned)
			ring->index_base = lower_32_bits(ring->dma_base);
		else
			ring->index_base = 0;
676 677 678 679 680 681 682 683 684
	}

	return 0;

err_dma_free:
	bgmac_dma_free(bgmac);
	return -ENOMEM;
}

F
Felix Fietkau 已提交
685
static int bgmac_dma_init(struct bgmac *bgmac)
686 687
{
	struct bgmac_dma_ring *ring;
F
Felix Fietkau 已提交
688
	int i, err;
689 690 691 692

	for (i = 0; i < BGMAC_MAX_TX_RINGS; i++) {
		ring = &bgmac->tx_ring[i];

693 694
		if (!ring->unaligned)
			bgmac_dma_tx_enable(bgmac, ring);
695 696 697 698
		bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_TX_RINGLO,
			    lower_32_bits(ring->dma_base));
		bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_TX_RINGHI,
			    upper_32_bits(ring->dma_base));
699 700
		if (ring->unaligned)
			bgmac_dma_tx_enable(bgmac, ring);
701 702 703 704 705 706

		ring->start = 0;
		ring->end = 0;	/* Points the slot that should *not* be read */
	}

	for (i = 0; i < BGMAC_MAX_RX_RINGS; i++) {
707 708
		int j;

709 710
		ring = &bgmac->rx_ring[i];

711 712
		if (!ring->unaligned)
			bgmac_dma_rx_enable(bgmac, ring);
713 714 715 716
		bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_RX_RINGLO,
			    lower_32_bits(ring->dma_base));
		bgmac_write(bgmac, ring->mmio_base + BGMAC_DMA_RX_RINGHI,
			    upper_32_bits(ring->dma_base));
717 718
		if (ring->unaligned)
			bgmac_dma_rx_enable(bgmac, ring);
719

F
Felix Fietkau 已提交
720 721
		ring->start = 0;
		ring->end = 0;
F
Felix Fietkau 已提交
722
		for (j = 0; j < BGMAC_RX_RING_SLOTS; j++) {
F
Felix Fietkau 已提交
723 724 725 726
			err = bgmac_dma_rx_skb_for_slot(bgmac, &ring->slots[j]);
			if (err)
				goto error;

727
			bgmac_dma_rx_setup_desc(bgmac, ring, j);
F
Felix Fietkau 已提交
728
		}
729

F
Felix Fietkau 已提交
730
		bgmac_dma_rx_update_index(bgmac, ring);
731
	}
F
Felix Fietkau 已提交
732 733 734 735 736 737

	return 0;

error:
	bgmac_dma_cleanup(bgmac);
	return err;
738 739 740 741 742 743 744 745 746 747 748 749 750 751 752
}


/**************************************************
 * Chip ops
 **************************************************/

/* TODO: can we just drop @force? Can we don't reset MAC at all if there is
 * nothing to change? Try if after stabilizng driver.
 */
static void bgmac_cmdcfg_maskset(struct bgmac *bgmac, u32 mask, u32 set,
				 bool force)
{
	u32 cmdcfg = bgmac_read(bgmac, BGMAC_CMDCFG);
	u32 new_val = (cmdcfg & mask) | set;
753
	u32 cmdcfg_sr;
754

755 756 757 758 759 760
	if (bgmac->feature_flags & BGMAC_FEAT_CMDCFG_SR_REV4)
		cmdcfg_sr = BGMAC_CMDCFG_SR_REV4;
	else
		cmdcfg_sr = BGMAC_CMDCFG_SR_REV0;

	bgmac_set(bgmac, BGMAC_CMDCFG, cmdcfg_sr);
761 762 763 764 765
	udelay(2);

	if (new_val != cmdcfg || force)
		bgmac_write(bgmac, BGMAC_CMDCFG, new_val);

766
	bgmac_mask(bgmac, BGMAC_CMDCFG, ~cmdcfg_sr);
767 768 769
	udelay(2);
}

770 771 772 773 774 775 776 777 778 779
static void bgmac_write_mac_address(struct bgmac *bgmac, u8 *addr)
{
	u32 tmp;

	tmp = (addr[0] << 24) | (addr[1] << 16) | (addr[2] << 8) | addr[3];
	bgmac_write(bgmac, BGMAC_MACADDR_HIGH, tmp);
	tmp = (addr[4] << 8) | addr[5];
	bgmac_write(bgmac, BGMAC_MACADDR_LOW, tmp);
}

780 781 782 783 784
static void bgmac_set_rx_mode(struct net_device *net_dev)
{
	struct bgmac *bgmac = netdev_priv(net_dev);

	if (net_dev->flags & IFF_PROMISC)
785
		bgmac_cmdcfg_maskset(bgmac, ~0, BGMAC_CMDCFG_PROM, true);
786
	else
787
		bgmac_cmdcfg_maskset(bgmac, ~BGMAC_CMDCFG_PROM, 0, true);
788 789
}

790 791 792 793 794
#if 0 /* We don't use that regs yet */
static void bgmac_chip_stats_update(struct bgmac *bgmac)
{
	int i;

795
	if (!(bgmac->feature_flags & BGMAC_FEAT_NO_CLR_MIB)) {
796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813
		for (i = 0; i < BGMAC_NUM_MIB_TX_REGS; i++)
			bgmac->mib_tx_regs[i] =
				bgmac_read(bgmac,
					   BGMAC_TX_GOOD_OCTETS + (i * 4));
		for (i = 0; i < BGMAC_NUM_MIB_RX_REGS; i++)
			bgmac->mib_rx_regs[i] =
				bgmac_read(bgmac,
					   BGMAC_RX_GOOD_OCTETS + (i * 4));
	}

	/* TODO: what else? how to handle BCM4706? Specs are needed */
}
#endif

static void bgmac_clear_mib(struct bgmac *bgmac)
{
	int i;

814
	if (bgmac->feature_flags & BGMAC_FEAT_NO_CLR_MIB)
815 816 817 818 819 820 821 822 823 824
		return;

	bgmac_set(bgmac, BGMAC_DEV_CTL, BGMAC_DC_MROR);
	for (i = 0; i < BGMAC_NUM_MIB_TX_REGS; i++)
		bgmac_read(bgmac, BGMAC_TX_GOOD_OCTETS + (i * 4));
	for (i = 0; i < BGMAC_NUM_MIB_RX_REGS; i++)
		bgmac_read(bgmac, BGMAC_RX_GOOD_OCTETS + (i * 4));
}

/* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/gmac_speed */
825
static void bgmac_mac_speed(struct bgmac *bgmac)
826 827 828 829
{
	u32 mask = ~(BGMAC_CMDCFG_ES_MASK | BGMAC_CMDCFG_HD);
	u32 set = 0;

830 831
	switch (bgmac->mac_speed) {
	case SPEED_10:
832
		set |= BGMAC_CMDCFG_ES_10;
833 834
		break;
	case SPEED_100:
835
		set |= BGMAC_CMDCFG_ES_100;
836 837
		break;
	case SPEED_1000:
838
		set |= BGMAC_CMDCFG_ES_1000;
839
		break;
840 841 842
	case SPEED_2500:
		set |= BGMAC_CMDCFG_ES_2500;
		break;
843
	default:
844 845
		dev_err(bgmac->dev, "Unsupported speed: %d\n",
			bgmac->mac_speed);
846 847 848
	}

	if (bgmac->mac_duplex == DUPLEX_HALF)
849
		set |= BGMAC_CMDCFG_HD;
850

851 852 853 854 855
	bgmac_cmdcfg_maskset(bgmac, mask, set, true);
}

static void bgmac_miiconfig(struct bgmac *bgmac)
{
856
	if (bgmac->feature_flags & BGMAC_FEAT_FORCE_SPEED_2500) {
857 858 859
		bgmac_idm_write(bgmac, BCMA_IOCTL,
				bgmac_idm_read(bgmac, BCMA_IOCTL) | 0x40 |
				BGMAC_BCMA_IOCTL_SW_CLKEN);
860
		bgmac->mac_speed = SPEED_2500;
861 862
		bgmac->mac_duplex = DUPLEX_FULL;
		bgmac_mac_speed(bgmac);
863
	} else {
864 865
		u8 imode;

866 867 868 869 870 871 872
		imode = (bgmac_read(bgmac, BGMAC_DEV_STATUS) &
			BGMAC_DS_MM_MASK) >> BGMAC_DS_MM_SHIFT;
		if (imode == 0 || imode == 1) {
			bgmac->mac_speed = SPEED_100;
			bgmac->mac_duplex = DUPLEX_FULL;
			bgmac_mac_speed(bgmac);
		}
873 874 875 876 877 878
	}
}

/* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipreset */
static void bgmac_chip_reset(struct bgmac *bgmac)
{
879
	u32 cmdcfg_sr;
880 881 882
	u32 iost;
	int i;

883
	if (bgmac_clk_enabled(bgmac)) {
884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900
		if (!bgmac->stats_grabbed) {
			/* bgmac_chip_stats_update(bgmac); */
			bgmac->stats_grabbed = true;
		}

		for (i = 0; i < BGMAC_MAX_TX_RINGS; i++)
			bgmac_dma_tx_reset(bgmac, &bgmac->tx_ring[i]);

		bgmac_cmdcfg_maskset(bgmac, ~0, BGMAC_CMDCFG_ML, false);
		udelay(1);

		for (i = 0; i < BGMAC_MAX_RX_RINGS; i++)
			bgmac_dma_rx_reset(bgmac, &bgmac->rx_ring[i]);

		/* TODO: Clear software multicast filter list */
	}

901
	iost = bgmac_idm_read(bgmac, BCMA_IOST);
902
	if (bgmac->feature_flags & BGMAC_FEAT_IOST_ATTACHED)
903 904
		iost &= ~BGMAC_BCMA_IOST_ATTACHED;

905
	/* 3GMAC: for BCM4707 & BCM47094, only do core reset at bgmac_probe() */
906 907
	if (!(bgmac->feature_flags & BGMAC_FEAT_NO_RESET)) {
		u32 flags = 0;
908 909 910 911 912
		if (iost & BGMAC_BCMA_IOST_ATTACHED) {
			flags = BGMAC_BCMA_IOCTL_SW_CLKEN;
			if (!bgmac->has_robosw)
				flags |= BGMAC_BCMA_IOCTL_SW_RESET;
		}
913
		bgmac_clk_enable(bgmac, flags);
914 915
	}

916
	/* Request Misc PLL for corerev > 2 */
917
	if (bgmac->feature_flags & BGMAC_FEAT_MISC_PLL_REQ) {
918 919
		bgmac_set(bgmac, BCMA_CLKCTLST,
			  BGMAC_BCMA_CLKCTLST_MISC_PLL_REQ);
920
		bgmac_wait_value(bgmac, BCMA_CLKCTLST,
921 922
				 BGMAC_BCMA_CLKCTLST_MISC_PLL_ST,
				 BGMAC_BCMA_CLKCTLST_MISC_PLL_ST,
923 924 925
				 1000);
	}

926
	if (bgmac->feature_flags & BGMAC_FEAT_SW_TYPE_PHY) {
927 928
		u8 et_swtype = 0;
		u8 sw_type = BGMAC_CHIPCTL_1_SW_TYPE_EPHY |
929
			     BGMAC_CHIPCTL_1_IF_TYPE_MII;
930
		char buf[4];
931

932
		if (bcm47xx_nvram_getenv("et_swtype", buf, sizeof(buf)) > 0) {
933
			if (kstrtou8(buf, 0, &et_swtype))
934 935
				dev_err(bgmac->dev, "Failed to parse et_swtype (%s)\n",
					buf);
936 937 938
			et_swtype &= 0x0f;
			et_swtype <<= 4;
			sw_type = et_swtype;
939
		} else if (bgmac->feature_flags & BGMAC_FEAT_SW_TYPE_EPHYRMII) {
940 941
			sw_type = BGMAC_CHIPCTL_1_IF_TYPE_RMII |
				  BGMAC_CHIPCTL_1_SW_TYPE_EPHYRMII;
942
		} else if (bgmac->feature_flags & BGMAC_FEAT_SW_TYPE_RGMII) {
943 944
			sw_type = BGMAC_CHIPCTL_1_IF_TYPE_RGMII |
				  BGMAC_CHIPCTL_1_SW_TYPE_RGMII;
945
		}
946 947 948
		bgmac_cco_ctl_maskset(bgmac, 1, ~(BGMAC_CHIPCTL_1_IF_TYPE_MASK |
						  BGMAC_CHIPCTL_1_SW_TYPE_MASK),
				      sw_type);
949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969
	} else if (bgmac->feature_flags & BGMAC_FEAT_CC4_IF_SW_TYPE) {
		u32 sw_type = BGMAC_CHIPCTL_4_IF_TYPE_MII |
			      BGMAC_CHIPCTL_4_SW_TYPE_EPHY;
		u8 et_swtype = 0;
		char buf[4];

		if (bcm47xx_nvram_getenv("et_swtype", buf, sizeof(buf)) > 0) {
			if (kstrtou8(buf, 0, &et_swtype))
				dev_err(bgmac->dev, "Failed to parse et_swtype (%s)\n",
					buf);
			sw_type = (et_swtype & 0x0f) << 12;
		} else if (bgmac->feature_flags & BGMAC_FEAT_CC4_IF_SW_TYPE_RGMII) {
			sw_type = BGMAC_CHIPCTL_4_IF_TYPE_RGMII |
				  BGMAC_CHIPCTL_4_SW_TYPE_RGMII;
		}
		bgmac_cco_ctl_maskset(bgmac, 4, ~(BGMAC_CHIPCTL_4_IF_TYPE_MASK |
						  BGMAC_CHIPCTL_4_SW_TYPE_MASK),
				      sw_type);
	} else if (bgmac->feature_flags & BGMAC_FEAT_CC7_IF_TYPE_RGMII) {
		bgmac_cco_ctl_maskset(bgmac, 7, ~BGMAC_CHIPCTL_7_IF_TYPE_MASK,
				      BGMAC_CHIPCTL_7_IF_TYPE_RGMII);
970 971 972
	}

	if (iost & BGMAC_BCMA_IOST_ATTACHED && !bgmac->has_robosw)
973 974 975
		bgmac_idm_write(bgmac, BCMA_IOCTL,
				bgmac_idm_read(bgmac, BCMA_IOCTL) &
				~BGMAC_BCMA_IOCTL_SW_RESET);
976 977 978 979 980 981

	/* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/gmac_reset
	 * Specs don't say about using BGMAC_CMDCFG_SR, but in this routine
	 * BGMAC_CMDCFG is read _after_ putting chip in a reset. So it has to
	 * be keps until taking MAC out of the reset.
	 */
982 983 984 985 986
	if (bgmac->feature_flags & BGMAC_FEAT_CMDCFG_SR_REV4)
		cmdcfg_sr = BGMAC_CMDCFG_SR_REV4;
	else
		cmdcfg_sr = BGMAC_CMDCFG_SR_REV0;

987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003
	bgmac_cmdcfg_maskset(bgmac,
			     ~(BGMAC_CMDCFG_TE |
			       BGMAC_CMDCFG_RE |
			       BGMAC_CMDCFG_RPI |
			       BGMAC_CMDCFG_TAI |
			       BGMAC_CMDCFG_HD |
			       BGMAC_CMDCFG_ML |
			       BGMAC_CMDCFG_CFE |
			       BGMAC_CMDCFG_RL |
			       BGMAC_CMDCFG_RED |
			       BGMAC_CMDCFG_PE |
			       BGMAC_CMDCFG_TPI |
			       BGMAC_CMDCFG_PAD_EN |
			       BGMAC_CMDCFG_PF),
			     BGMAC_CMDCFG_PROM |
			     BGMAC_CMDCFG_NLC |
			     BGMAC_CMDCFG_CFE |
1004
			     cmdcfg_sr,
1005
			     false);
1006 1007
	bgmac->mac_speed = SPEED_UNKNOWN;
	bgmac->mac_duplex = DUPLEX_UNKNOWN;
1008 1009

	bgmac_clear_mib(bgmac);
1010
	if (bgmac->feature_flags & BGMAC_FEAT_CMN_PHY_CTL)
1011 1012
		bgmac_cmn_maskset32(bgmac, BCMA_GMAC_CMN_PHY_CTL, ~0,
				    BCMA_GMAC_CMN_PC_MTE);
1013 1014 1015
	else
		bgmac_set(bgmac, BGMAC_PHY_CNTL, BGMAC_PC_MTE);
	bgmac_miiconfig(bgmac);
1016 1017
	if (bgmac->mii_bus)
		bgmac->mii_bus->reset(bgmac->mii_bus);
1018

1019
	netdev_reset_queue(bgmac->net_dev);
1020 1021 1022 1023 1024 1025 1026 1027 1028 1029
}

static void bgmac_chip_intrs_on(struct bgmac *bgmac)
{
	bgmac_write(bgmac, BGMAC_INT_MASK, bgmac->int_mask);
}

static void bgmac_chip_intrs_off(struct bgmac *bgmac)
{
	bgmac_write(bgmac, BGMAC_INT_MASK, 0);
1030
	bgmac_read(bgmac, BGMAC_INT_MASK);
1031 1032 1033 1034 1035
}

/* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/gmac_enable */
static void bgmac_enable(struct bgmac *bgmac)
{
1036
	u32 cmdcfg_sr;
1037 1038
	u32 cmdcfg;
	u32 mode;
1039 1040 1041 1042 1043

	if (bgmac->feature_flags & BGMAC_FEAT_CMDCFG_SR_REV4)
		cmdcfg_sr = BGMAC_CMDCFG_SR_REV4;
	else
		cmdcfg_sr = BGMAC_CMDCFG_SR_REV0;
1044 1045 1046

	cmdcfg = bgmac_read(bgmac, BGMAC_CMDCFG);
	bgmac_cmdcfg_maskset(bgmac, ~(BGMAC_CMDCFG_TE | BGMAC_CMDCFG_RE),
1047
			     cmdcfg_sr, true);
1048 1049 1050 1051 1052 1053
	udelay(2);
	cmdcfg |= BGMAC_CMDCFG_TE | BGMAC_CMDCFG_RE;
	bgmac_write(bgmac, BGMAC_CMDCFG, cmdcfg);

	mode = (bgmac_read(bgmac, BGMAC_DEV_STATUS) & BGMAC_DS_MM_MASK) >>
		BGMAC_DS_MM_SHIFT;
1054
	if (bgmac->feature_flags & BGMAC_FEAT_CLKCTLST || mode != 0)
1055
		bgmac_set(bgmac, BCMA_CLKCTLST, BCMA_CLKCTLST_FORCEHT);
1056
	if (!(bgmac->feature_flags & BGMAC_FEAT_CLKCTLST) && mode == 2)
1057 1058
		bgmac_cco_ctl_maskset(bgmac, 1, ~0,
				      BGMAC_CHIPCTL_1_RXC_DLL_BYPASS);
1059

1060 1061 1062 1063 1064
	if (bgmac->feature_flags & (BGMAC_FEAT_FLW_CTRL1 |
				    BGMAC_FEAT_FLW_CTRL2)) {
		u32 fl_ctl;

		if (bgmac->feature_flags & BGMAC_FEAT_FLW_CTRL1)
1065
			fl_ctl = 0x2300e1;
1066 1067 1068
		else
			fl_ctl = 0x03cb04cb;

1069 1070 1071 1072
		bgmac_write(bgmac, BGMAC_FLOW_CTL_THRESH, fl_ctl);
		bgmac_write(bgmac, BGMAC_PAUSE_CTL, 0x27fff);
	}

1073 1074 1075 1076 1077
	if (bgmac->feature_flags & BGMAC_FEAT_SET_RXQ_CLK) {
		u32 rxq_ctl;
		u16 bp_clk;
		u8 mdp;

1078 1079
		rxq_ctl = bgmac_read(bgmac, BGMAC_RXQ_CTL);
		rxq_ctl &= ~BGMAC_RXQ_CTL_MDP_MASK;
1080
		bp_clk = bgmac_get_bus_clock(bgmac) / 1000000;
1081 1082 1083 1084
		mdp = (bp_clk * 128 / 1000) - 3;
		rxq_ctl |= (mdp << BGMAC_RXQ_CTL_MDP_SHIFT);
		bgmac_write(bgmac, BGMAC_RXQ_CTL, rxq_ctl);
	}
1085 1086 1087
}

/* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipinit */
F
Felix Fietkau 已提交
1088
static void bgmac_chip_init(struct bgmac *bgmac)
1089
{
J
Jon Mason 已提交
1090 1091 1092
	/* Clear any erroneously pending interrupts */
	bgmac_write(bgmac, BGMAC_INT_STATUS, ~0);

1093 1094 1095 1096 1097 1098
	/* 1 interrupt per received frame */
	bgmac_write(bgmac, BGMAC_INT_RECV_LAZY, 1 << BGMAC_IRL_FC_SHIFT);

	/* Enable 802.3x tx flow control (honor received PAUSE frames) */
	bgmac_cmdcfg_maskset(bgmac, ~BGMAC_CMDCFG_RPI, 0, true);

1099
	bgmac_set_rx_mode(bgmac->net_dev);
1100

1101
	bgmac_write_mac_address(bgmac, bgmac->net_dev->dev_addr);
1102 1103

	if (bgmac->loopback)
1104
		bgmac_cmdcfg_maskset(bgmac, ~0, BGMAC_CMDCFG_ML, false);
1105
	else
1106
		bgmac_cmdcfg_maskset(bgmac, ~BGMAC_CMDCFG_ML, 0, false);
1107 1108 1109

	bgmac_write(bgmac, BGMAC_RXMAX_LENGTH, 32 + ETHER_MAX_LEN);

F
Felix Fietkau 已提交
1110
	bgmac_chip_intrs_on(bgmac);
1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124

	bgmac_enable(bgmac);
}

static irqreturn_t bgmac_interrupt(int irq, void *dev_id)
{
	struct bgmac *bgmac = netdev_priv(dev_id);

	u32 int_status = bgmac_read(bgmac, BGMAC_INT_STATUS);
	int_status &= bgmac->int_mask;

	if (!int_status)
		return IRQ_NONE;

1125 1126
	int_status &= ~(BGMAC_IS_TX0 | BGMAC_IS_RX);
	if (int_status)
1127
		dev_err(bgmac->dev, "Unknown IRQs: 0x%08X\n", int_status);
1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141

	/* Disable new interrupts until handling existing ones */
	bgmac_chip_intrs_off(bgmac);

	napi_schedule(&bgmac->napi);

	return IRQ_HANDLED;
}

static int bgmac_poll(struct napi_struct *napi, int weight)
{
	struct bgmac *bgmac = container_of(napi, struct bgmac, napi);
	int handled = 0;

1142 1143
	/* Ack */
	bgmac_write(bgmac, BGMAC_INT_STATUS, ~0);
1144

1145 1146
	bgmac_dma_tx_free(bgmac, &bgmac->tx_ring[0]);
	handled += bgmac_dma_rx_read(bgmac, &bgmac->rx_ring[0], weight);
1147

1148 1149
	/* Poll again if more events arrived in the meantime */
	if (bgmac_read(bgmac, BGMAC_INT_STATUS) & (BGMAC_IS_TX0 | BGMAC_IS_RX))
1150
		return weight;
1151

1152
	if (handled < weight) {
1153
		napi_complete_done(napi, handled);
1154 1155
		bgmac_chip_intrs_on(bgmac);
	}
1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169

	return handled;
}

/**************************************************
 * net_device_ops
 **************************************************/

static int bgmac_open(struct net_device *net_dev)
{
	struct bgmac *bgmac = netdev_priv(net_dev);
	int err = 0;

	bgmac_chip_reset(bgmac);
F
Felix Fietkau 已提交
1170 1171 1172 1173 1174

	err = bgmac_dma_init(bgmac);
	if (err)
		return err;

1175
	/* Specs say about reclaiming rings here, but we do that in DMA init */
F
Felix Fietkau 已提交
1176
	bgmac_chip_init(bgmac);
1177

1178
	err = request_irq(bgmac->irq, bgmac_interrupt, IRQF_SHARED,
1179 1180
			  KBUILD_MODNAME, net_dev);
	if (err < 0) {
1181
		dev_err(bgmac->dev, "IRQ request error: %d!\n", err);
F
Felix Fietkau 已提交
1182 1183
		bgmac_dma_cleanup(bgmac);
		return err;
1184 1185 1186
	}
	napi_enable(&bgmac->napi);

1187
	phy_start(net_dev->phydev);
1188

1189 1190
	netif_start_queue(net_dev);

F
Felix Fietkau 已提交
1191
	return 0;
1192 1193 1194 1195 1196 1197 1198 1199
}

static int bgmac_stop(struct net_device *net_dev)
{
	struct bgmac *bgmac = netdev_priv(net_dev);

	netif_carrier_off(net_dev);

1200
	phy_stop(net_dev->phydev);
1201

1202 1203
	napi_disable(&bgmac->napi);
	bgmac_chip_intrs_off(bgmac);
1204
	free_irq(bgmac->irq, net_dev);
1205 1206

	bgmac_chip_reset(bgmac);
F
Felix Fietkau 已提交
1207
	bgmac_dma_cleanup(bgmac);
1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222

	return 0;
}

static netdev_tx_t bgmac_start_xmit(struct sk_buff *skb,
				    struct net_device *net_dev)
{
	struct bgmac *bgmac = netdev_priv(net_dev);
	struct bgmac_dma_ring *ring;

	/* No QOS support yet */
	ring = &bgmac->tx_ring[0];
	return bgmac_dma_tx_add(bgmac, ring, skb);
}

1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235
static int bgmac_set_mac_address(struct net_device *net_dev, void *addr)
{
	struct bgmac *bgmac = netdev_priv(net_dev);
	int ret;

	ret = eth_prepare_mac_addr_change(net_dev, addr);
	if (ret < 0)
		return ret;
	bgmac_write_mac_address(bgmac, (u8 *)addr);
	eth_commit_mac_addr_change(net_dev, addr);
	return 0;
}

1236 1237
static int bgmac_ioctl(struct net_device *net_dev, struct ifreq *ifr, int cmd)
{
1238 1239 1240
	if (!netif_running(net_dev))
		return -EINVAL;

1241
	return phy_mii_ioctl(net_dev->phydev, ifr, cmd);
1242 1243 1244 1245 1246 1247
}

static const struct net_device_ops bgmac_netdev_ops = {
	.ndo_open		= bgmac_open,
	.ndo_stop		= bgmac_stop,
	.ndo_start_xmit		= bgmac_start_xmit,
1248
	.ndo_set_rx_mode	= bgmac_set_rx_mode,
1249
	.ndo_set_mac_address	= bgmac_set_mac_address,
1250
	.ndo_validate_addr	= eth_validate_addr,
1251 1252 1253 1254 1255 1256 1257
	.ndo_do_ioctl           = bgmac_ioctl,
};

/**************************************************
 * ethtool_ops
 **************************************************/

1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378
struct bgmac_stat {
	u8 size;
	u32 offset;
	const char *name;
};

static struct bgmac_stat bgmac_get_strings_stats[] = {
	{ 8, BGMAC_TX_GOOD_OCTETS, "tx_good_octets" },
	{ 4, BGMAC_TX_GOOD_PKTS, "tx_good" },
	{ 8, BGMAC_TX_OCTETS, "tx_octets" },
	{ 4, BGMAC_TX_PKTS, "tx_pkts" },
	{ 4, BGMAC_TX_BROADCAST_PKTS, "tx_broadcast" },
	{ 4, BGMAC_TX_MULTICAST_PKTS, "tx_multicast" },
	{ 4, BGMAC_TX_LEN_64, "tx_64" },
	{ 4, BGMAC_TX_LEN_65_TO_127, "tx_65_127" },
	{ 4, BGMAC_TX_LEN_128_TO_255, "tx_128_255" },
	{ 4, BGMAC_TX_LEN_256_TO_511, "tx_256_511" },
	{ 4, BGMAC_TX_LEN_512_TO_1023, "tx_512_1023" },
	{ 4, BGMAC_TX_LEN_1024_TO_1522, "tx_1024_1522" },
	{ 4, BGMAC_TX_LEN_1523_TO_2047, "tx_1523_2047" },
	{ 4, BGMAC_TX_LEN_2048_TO_4095, "tx_2048_4095" },
	{ 4, BGMAC_TX_LEN_4096_TO_8191, "tx_4096_8191" },
	{ 4, BGMAC_TX_LEN_8192_TO_MAX, "tx_8192_max" },
	{ 4, BGMAC_TX_JABBER_PKTS, "tx_jabber" },
	{ 4, BGMAC_TX_OVERSIZE_PKTS, "tx_oversize" },
	{ 4, BGMAC_TX_FRAGMENT_PKTS, "tx_fragment" },
	{ 4, BGMAC_TX_UNDERRUNS, "tx_underruns" },
	{ 4, BGMAC_TX_TOTAL_COLS, "tx_total_cols" },
	{ 4, BGMAC_TX_SINGLE_COLS, "tx_single_cols" },
	{ 4, BGMAC_TX_MULTIPLE_COLS, "tx_multiple_cols" },
	{ 4, BGMAC_TX_EXCESSIVE_COLS, "tx_excessive_cols" },
	{ 4, BGMAC_TX_LATE_COLS, "tx_late_cols" },
	{ 4, BGMAC_TX_DEFERED, "tx_defered" },
	{ 4, BGMAC_TX_CARRIER_LOST, "tx_carrier_lost" },
	{ 4, BGMAC_TX_PAUSE_PKTS, "tx_pause" },
	{ 4, BGMAC_TX_UNI_PKTS, "tx_unicast" },
	{ 4, BGMAC_TX_Q0_PKTS, "tx_q0" },
	{ 8, BGMAC_TX_Q0_OCTETS, "tx_q0_octets" },
	{ 4, BGMAC_TX_Q1_PKTS, "tx_q1" },
	{ 8, BGMAC_TX_Q1_OCTETS, "tx_q1_octets" },
	{ 4, BGMAC_TX_Q2_PKTS, "tx_q2" },
	{ 8, BGMAC_TX_Q2_OCTETS, "tx_q2_octets" },
	{ 4, BGMAC_TX_Q3_PKTS, "tx_q3" },
	{ 8, BGMAC_TX_Q3_OCTETS, "tx_q3_octets" },
	{ 8, BGMAC_RX_GOOD_OCTETS, "rx_good_octets" },
	{ 4, BGMAC_RX_GOOD_PKTS, "rx_good" },
	{ 8, BGMAC_RX_OCTETS, "rx_octets" },
	{ 4, BGMAC_RX_PKTS, "rx_pkts" },
	{ 4, BGMAC_RX_BROADCAST_PKTS, "rx_broadcast" },
	{ 4, BGMAC_RX_MULTICAST_PKTS, "rx_multicast" },
	{ 4, BGMAC_RX_LEN_64, "rx_64" },
	{ 4, BGMAC_RX_LEN_65_TO_127, "rx_65_127" },
	{ 4, BGMAC_RX_LEN_128_TO_255, "rx_128_255" },
	{ 4, BGMAC_RX_LEN_256_TO_511, "rx_256_511" },
	{ 4, BGMAC_RX_LEN_512_TO_1023, "rx_512_1023" },
	{ 4, BGMAC_RX_LEN_1024_TO_1522, "rx_1024_1522" },
	{ 4, BGMAC_RX_LEN_1523_TO_2047, "rx_1523_2047" },
	{ 4, BGMAC_RX_LEN_2048_TO_4095, "rx_2048_4095" },
	{ 4, BGMAC_RX_LEN_4096_TO_8191, "rx_4096_8191" },
	{ 4, BGMAC_RX_LEN_8192_TO_MAX, "rx_8192_max" },
	{ 4, BGMAC_RX_JABBER_PKTS, "rx_jabber" },
	{ 4, BGMAC_RX_OVERSIZE_PKTS, "rx_oversize" },
	{ 4, BGMAC_RX_FRAGMENT_PKTS, "rx_fragment" },
	{ 4, BGMAC_RX_MISSED_PKTS, "rx_missed" },
	{ 4, BGMAC_RX_CRC_ALIGN_ERRS, "rx_crc_align" },
	{ 4, BGMAC_RX_UNDERSIZE, "rx_undersize" },
	{ 4, BGMAC_RX_CRC_ERRS, "rx_crc" },
	{ 4, BGMAC_RX_ALIGN_ERRS, "rx_align" },
	{ 4, BGMAC_RX_SYMBOL_ERRS, "rx_symbol" },
	{ 4, BGMAC_RX_PAUSE_PKTS, "rx_pause" },
	{ 4, BGMAC_RX_NONPAUSE_PKTS, "rx_nonpause" },
	{ 4, BGMAC_RX_SACHANGES, "rx_sa_changes" },
	{ 4, BGMAC_RX_UNI_PKTS, "rx_unicast" },
};

#define BGMAC_STATS_LEN	ARRAY_SIZE(bgmac_get_strings_stats)

static int bgmac_get_sset_count(struct net_device *dev, int string_set)
{
	switch (string_set) {
	case ETH_SS_STATS:
		return BGMAC_STATS_LEN;
	}

	return -EOPNOTSUPP;
}

static void bgmac_get_strings(struct net_device *dev, u32 stringset,
			      u8 *data)
{
	int i;

	if (stringset != ETH_SS_STATS)
		return;

	for (i = 0; i < BGMAC_STATS_LEN; i++)
		strlcpy(data + i * ETH_GSTRING_LEN,
			bgmac_get_strings_stats[i].name, ETH_GSTRING_LEN);
}

static void bgmac_get_ethtool_stats(struct net_device *dev,
				    struct ethtool_stats *ss, uint64_t *data)
{
	struct bgmac *bgmac = netdev_priv(dev);
	const struct bgmac_stat *s;
	unsigned int i;
	u64 val;

	if (!netif_running(dev))
		return;

	for (i = 0; i < BGMAC_STATS_LEN; i++) {
		s = &bgmac_get_strings_stats[i];
		val = 0;
		if (s->size == 8)
			val = (u64)bgmac_read(bgmac, s->offset + 4) << 32;
		val |= bgmac_read(bgmac, s->offset);
		data[i] = val;
	}
}

1379 1380 1381 1382
static void bgmac_get_drvinfo(struct net_device *net_dev,
			      struct ethtool_drvinfo *info)
{
	strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
1383
	strlcpy(info->bus_info, "AXI", sizeof(info->bus_info));
1384 1385 1386
}

static const struct ethtool_ops bgmac_ethtool_ops = {
1387 1388 1389
	.get_strings		= bgmac_get_strings,
	.get_sset_count		= bgmac_get_sset_count,
	.get_ethtool_stats	= bgmac_get_ethtool_stats,
1390
	.get_drvinfo		= bgmac_get_drvinfo,
1391 1392
	.get_link_ksettings     = phy_ethtool_get_link_ksettings,
	.set_link_ksettings     = phy_ethtool_set_link_ksettings,
1393 1394
};

R
Rafał Miłecki 已提交
1395 1396 1397 1398
/**************************************************
 * MII
 **************************************************/

1399
void bgmac_adjust_link(struct net_device *net_dev)
1400 1401
{
	struct bgmac *bgmac = netdev_priv(net_dev);
1402
	struct phy_device *phy_dev = net_dev->phydev;
1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421
	bool update = false;

	if (phy_dev->link) {
		if (phy_dev->speed != bgmac->mac_speed) {
			bgmac->mac_speed = phy_dev->speed;
			update = true;
		}

		if (phy_dev->duplex != bgmac->mac_duplex) {
			bgmac->mac_duplex = phy_dev->duplex;
			update = true;
		}
	}

	if (update) {
		bgmac_mac_speed(bgmac);
		phy_print_status(phy_dev);
	}
}
1422
EXPORT_SYMBOL_GPL(bgmac_adjust_link);
1423

1424
int bgmac_phy_connect_direct(struct bgmac *bgmac)
1425 1426 1427 1428 1429 1430 1431 1432 1433
{
	struct fixed_phy_status fphy_status = {
		.link = 1,
		.speed = SPEED_1000,
		.duplex = DUPLEX_FULL,
	};
	struct phy_device *phy_dev;
	int err;

1434
	phy_dev = fixed_phy_register(PHY_POLL, &fphy_status, -1, NULL);
1435
	if (!phy_dev || IS_ERR(phy_dev)) {
1436
		dev_err(bgmac->dev, "Failed to register fixed PHY device\n");
1437 1438 1439 1440 1441 1442
		return -ENODEV;
	}

	err = phy_connect_direct(bgmac->net_dev, phy_dev, bgmac_adjust_link,
				 PHY_INTERFACE_MODE_MII);
	if (err) {
1443
		dev_err(bgmac->dev, "Connecting PHY failed\n");
1444 1445 1446 1447 1448
		return err;
	}

	return err;
}
1449
EXPORT_SYMBOL_GPL(bgmac_phy_connect_direct);
R
Rafał Miłecki 已提交
1450

1451
struct bgmac *bgmac_alloc(struct device *dev)
1452 1453 1454 1455 1456
{
	struct net_device *net_dev;
	struct bgmac *bgmac;

	/* Allocation and references */
1457
	net_dev = devm_alloc_etherdev(dev, sizeof(*bgmac));
1458
	if (!net_dev)
1459
		return NULL;
1460

1461
	net_dev->netdev_ops = &bgmac_netdev_ops;
1462
	net_dev->ethtool_ops = &bgmac_ethtool_ops;
1463

1464
	bgmac = netdev_priv(net_dev);
1465
	bgmac->dev = dev;
1466
	bgmac->net_dev = net_dev;
1467 1468 1469 1470 1471 1472 1473 1474 1475 1476

	return bgmac;
}
EXPORT_SYMBOL_GPL(bgmac_alloc);

int bgmac_enet_probe(struct bgmac *bgmac)
{
	struct net_device *net_dev = bgmac->net_dev;
	int err;

1477 1478 1479
	net_dev->irq = bgmac->irq;
	SET_NETDEV_DEV(net_dev, bgmac->dev);

1480
	if (!is_valid_ether_addr(net_dev->dev_addr)) {
1481
		dev_err(bgmac->dev, "Invalid MAC addr: %pM\n",
1482 1483
			net_dev->dev_addr);
		eth_hw_addr_random(net_dev);
1484
		dev_warn(bgmac->dev, "Using random MAC: %pM\n",
1485
			 net_dev->dev_addr);
1486 1487
	}

1488 1489 1490 1491
	/* This (reset &) enable is not preset in specs or reference driver but
	 * Broadcom does it in arch PCI code when enabling fake PCI device.
	 */
	bgmac_clk_enable(bgmac, 0);
1492

1493 1494 1495 1496
	/* This seems to be fixing IRQ by assigning OOB #6 to the core */
	if (bgmac->feature_flags & BGMAC_FEAT_IRQ_ID_OOB_6)
		bgmac_idm_write(bgmac, BCMA_OOB_SEL_OUT_A30, 0x86);

1497 1498 1499 1500
	bgmac_chip_reset(bgmac);

	err = bgmac_dma_alloc(bgmac);
	if (err) {
1501
		dev_err(bgmac->dev, "Unable to alloc memory for DMA\n");
1502
		goto err_out;
1503 1504 1505
	}

	bgmac->int_mask = BGMAC_IS_ERRMASK | BGMAC_IS_RX | BGMAC_IS_TX_MASK;
R
Ralf Baechle 已提交
1506
	if (bcm47xx_nvram_getenv("et0_no_txint", NULL, 0) == 0)
1507 1508
		bgmac->int_mask &= ~BGMAC_IS_TX_MASK;

1509 1510
	netif_napi_add(net_dev, &bgmac->napi, bgmac_poll, BGMAC_WEIGHT);

1511
	err = bgmac_phy_connect(bgmac);
R
Rafał Miłecki 已提交
1512
	if (err) {
1513
		dev_err(bgmac->dev, "Cannot connect to phy\n");
1514
		goto err_dma_free;
R
Rafał Miłecki 已提交
1515 1516
	}

1517 1518 1519 1520
	net_dev->features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
	net_dev->hw_features = net_dev->features;
	net_dev->vlan_features = net_dev->features;

1521 1522
	err = register_netdev(bgmac->net_dev);
	if (err) {
1523
		dev_err(bgmac->dev, "Cannot register net device\n");
1524
		goto err_phy_disconnect;
1525 1526 1527 1528 1529 1530
	}

	netif_carrier_off(net_dev);

	return 0;

1531 1532
err_phy_disconnect:
	phy_disconnect(net_dev->phydev);
1533 1534
err_dma_free:
	bgmac_dma_free(bgmac);
1535
err_out:
1536 1537 1538

	return err;
}
1539
EXPORT_SYMBOL_GPL(bgmac_enet_probe);
1540

1541
void bgmac_enet_remove(struct bgmac *bgmac)
1542 1543
{
	unregister_netdev(bgmac->net_dev);
1544
	phy_disconnect(bgmac->net_dev->phydev);
1545
	netif_napi_del(&bgmac->napi);
1546 1547 1548
	bgmac_dma_free(bgmac);
	free_netdev(bgmac->net_dev);
}
1549
EXPORT_SYMBOL_GPL(bgmac_enet_remove);
1550 1551 1552

MODULE_AUTHOR("Rafał Miłecki");
MODULE_LICENSE("GPL");