aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ethernet/broadcom/bgmac.c80
-rw-r--r--drivers/net/ethernet/broadcom/bgmac.h7
2 files changed, 62 insertions, 25 deletions
diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c
index efda7cf82394..c7da37aef035 100644
--- a/drivers/net/ethernet/broadcom/bgmac.c
+++ b/drivers/net/ethernet/broadcom/bgmac.c
@@ -276,31 +276,31 @@ static int bgmac_dma_rx_skb_for_slot(struct bgmac *bgmac,
276 struct bgmac_slot_info *slot) 276 struct bgmac_slot_info *slot)
277{ 277{
278 struct device *dma_dev = bgmac->core->dma_dev; 278 struct device *dma_dev = bgmac->core->dma_dev;
279 struct sk_buff *skb;
280 dma_addr_t dma_addr; 279 dma_addr_t dma_addr;
281 struct bgmac_rx_header *rx; 280 struct bgmac_rx_header *rx;
281 void *buf;
282 282
283 /* Alloc skb */ 283 /* Alloc skb */
284 skb = netdev_alloc_skb(bgmac->net_dev, BGMAC_RX_BUF_SIZE); 284 buf = netdev_alloc_frag(BGMAC_RX_ALLOC_SIZE);
285 if (!skb) 285 if (!buf)
286 return -ENOMEM; 286 return -ENOMEM;
287 287
288 /* Poison - if everything goes fine, hardware will overwrite it */ 288 /* Poison - if everything goes fine, hardware will overwrite it */
289 rx = (struct bgmac_rx_header *)skb->data; 289 rx = buf;
290 rx->len = cpu_to_le16(0xdead); 290 rx->len = cpu_to_le16(0xdead);
291 rx->flags = cpu_to_le16(0xbeef); 291 rx->flags = cpu_to_le16(0xbeef);
292 292
293 /* Map skb for the DMA */ 293 /* Map skb for the DMA */
294 dma_addr = dma_map_single(dma_dev, skb->data, 294 dma_addr = dma_map_single(dma_dev, buf, BGMAC_RX_BUF_SIZE,
295 BGMAC_RX_BUF_SIZE, DMA_FROM_DEVICE); 295 DMA_FROM_DEVICE);
296 if (dma_mapping_error(dma_dev, dma_addr)) { 296 if (dma_mapping_error(dma_dev, dma_addr)) {
297 bgmac_err(bgmac, "DMA mapping error\n"); 297 bgmac_err(bgmac, "DMA mapping error\n");
298 dev_kfree_skb(skb); 298 put_page(virt_to_head_page(buf));
299 return -ENOMEM; 299 return -ENOMEM;
300 } 300 }
301 301
302 /* Update the slot */ 302 /* Update the slot */
303 slot->skb = skb; 303 slot->buf = buf;
304 slot->dma_addr = dma_addr; 304 slot->dma_addr = dma_addr;
305 305
306 return 0; 306 return 0;
@@ -343,8 +343,9 @@ static int bgmac_dma_rx_read(struct bgmac *bgmac, struct bgmac_dma_ring *ring,
343 while (ring->start != ring->end) { 343 while (ring->start != ring->end) {
344 struct device *dma_dev = bgmac->core->dma_dev; 344 struct device *dma_dev = bgmac->core->dma_dev;
345 struct bgmac_slot_info *slot = &ring->slots[ring->start]; 345 struct bgmac_slot_info *slot = &ring->slots[ring->start];
346 struct sk_buff *skb = slot->skb; 346 struct bgmac_rx_header *rx = slot->buf;
347 struct bgmac_rx_header *rx; 347 struct sk_buff *skb;
348 void *buf = slot->buf;
348 u16 len, flags; 349 u16 len, flags;
349 350
350 /* Unmap buffer to make it accessible to the CPU */ 351 /* Unmap buffer to make it accessible to the CPU */
@@ -352,7 +353,6 @@ static int bgmac_dma_rx_read(struct bgmac *bgmac, struct bgmac_dma_ring *ring,
352 BGMAC_RX_BUF_SIZE, DMA_FROM_DEVICE); 353 BGMAC_RX_BUF_SIZE, DMA_FROM_DEVICE);
353 354
354 /* Get info from the header */ 355 /* Get info from the header */
355 rx = (struct bgmac_rx_header *)skb->data;
356 len = le16_to_cpu(rx->len); 356 len = le16_to_cpu(rx->len);
357 flags = le16_to_cpu(rx->flags); 357 flags = le16_to_cpu(rx->flags);
358 358
@@ -393,12 +393,13 @@ static int bgmac_dma_rx_read(struct bgmac *bgmac, struct bgmac_dma_ring *ring,
393 dma_unmap_single(dma_dev, old_dma_addr, 393 dma_unmap_single(dma_dev, old_dma_addr,
394 BGMAC_RX_BUF_SIZE, DMA_FROM_DEVICE); 394 BGMAC_RX_BUF_SIZE, DMA_FROM_DEVICE);
395 395
396 skb = build_skb(buf, BGMAC_RX_ALLOC_SIZE);
396 skb_put(skb, BGMAC_RX_FRAME_OFFSET + len); 397 skb_put(skb, BGMAC_RX_FRAME_OFFSET + len);
397 skb_pull(skb, BGMAC_RX_FRAME_OFFSET); 398 skb_pull(skb, BGMAC_RX_FRAME_OFFSET);
398 399
399 skb_checksum_none_assert(skb); 400 skb_checksum_none_assert(skb);
400 skb->protocol = eth_type_trans(skb, bgmac->net_dev); 401 skb->protocol = eth_type_trans(skb, bgmac->net_dev);
401 netif_receive_skb(skb); 402 napi_gro_receive(&bgmac->napi, skb);
402 handled++; 403 handled++;
403 } while (0); 404 } while (0);
404 405
@@ -434,12 +435,11 @@ static bool bgmac_dma_unaligned(struct bgmac *bgmac,
434 return false; 435 return false;
435} 436}
436 437
437static void bgmac_dma_ring_free(struct bgmac *bgmac, 438static void bgmac_dma_tx_ring_free(struct bgmac *bgmac,
438 struct bgmac_dma_ring *ring) 439 struct bgmac_dma_ring *ring)
439{ 440{
440 struct device *dma_dev = bgmac->core->dma_dev; 441 struct device *dma_dev = bgmac->core->dma_dev;
441 struct bgmac_slot_info *slot; 442 struct bgmac_slot_info *slot;
442 int size;
443 int i; 443 int i;
444 444
445 for (i = 0; i < ring->num_slots; i++) { 445 for (i = 0; i < ring->num_slots; i++) {
@@ -451,23 +451,55 @@ static void bgmac_dma_ring_free(struct bgmac *bgmac,
451 dev_kfree_skb(slot->skb); 451 dev_kfree_skb(slot->skb);
452 } 452 }
453 } 453 }
454}
454 455
455 if (ring->cpu_base) { 456static void bgmac_dma_rx_ring_free(struct bgmac *bgmac,
456 /* Free ring of descriptors */ 457 struct bgmac_dma_ring *ring)
457 size = ring->num_slots * sizeof(struct bgmac_dma_desc); 458{
458 dma_free_coherent(dma_dev, size, ring->cpu_base, 459 struct device *dma_dev = bgmac->core->dma_dev;
459 ring->dma_base); 460 struct bgmac_slot_info *slot;
461 int i;
462
463 for (i = 0; i < ring->num_slots; i++) {
464 slot = &ring->slots[i];
465 if (!slot->buf)
466 continue;
467
468 if (slot->dma_addr)
469 dma_unmap_single(dma_dev, slot->dma_addr,
470 BGMAC_RX_BUF_SIZE,
471 DMA_FROM_DEVICE);
472 put_page(virt_to_head_page(slot->buf));
460 } 473 }
461} 474}
462 475
476static void bgmac_dma_ring_desc_free(struct bgmac *bgmac,
477 struct bgmac_dma_ring *ring)
478{
479 struct device *dma_dev = bgmac->core->dma_dev;
480 int size;
481
482 if (!ring->cpu_base)
483 return;
484
485 /* Free ring of descriptors */
486 size = ring->num_slots * sizeof(struct bgmac_dma_desc);
487 dma_free_coherent(dma_dev, size, ring->cpu_base,
488 ring->dma_base);
489}
490
463static void bgmac_dma_free(struct bgmac *bgmac) 491static void bgmac_dma_free(struct bgmac *bgmac)
464{ 492{
465 int i; 493 int i;
466 494
467 for (i = 0; i < BGMAC_MAX_TX_RINGS; i++) 495 for (i = 0; i < BGMAC_MAX_TX_RINGS; i++) {
468 bgmac_dma_ring_free(bgmac, &bgmac->tx_ring[i]); 496 bgmac_dma_tx_ring_free(bgmac, &bgmac->tx_ring[i]);
469 for (i = 0; i < BGMAC_MAX_RX_RINGS; i++) 497 bgmac_dma_ring_desc_free(bgmac, &bgmac->tx_ring[i]);
470 bgmac_dma_ring_free(bgmac, &bgmac->rx_ring[i]); 498 }
499 for (i = 0; i < BGMAC_MAX_RX_RINGS; i++) {
500 bgmac_dma_rx_ring_free(bgmac, &bgmac->rx_ring[i]);
501 bgmac_dma_ring_desc_free(bgmac, &bgmac->rx_ring[i]);
502 }
471} 503}
472 504
473static int bgmac_dma_alloc(struct bgmac *bgmac) 505static int bgmac_dma_alloc(struct bgmac *bgmac)
diff --git a/drivers/net/ethernet/broadcom/bgmac.h b/drivers/net/ethernet/broadcom/bgmac.h
index 1f9f36f2b658..3ad965fe7fcc 100644
--- a/drivers/net/ethernet/broadcom/bgmac.h
+++ b/drivers/net/ethernet/broadcom/bgmac.h
@@ -362,6 +362,8 @@
362#define BGMAC_RX_FRAME_OFFSET 30 /* There are 2 unused bytes between header and real data */ 362#define BGMAC_RX_FRAME_OFFSET 30 /* There are 2 unused bytes between header and real data */
363#define BGMAC_RX_MAX_FRAME_SIZE 1536 /* Copied from b44/tg3 */ 363#define BGMAC_RX_MAX_FRAME_SIZE 1536 /* Copied from b44/tg3 */
364#define BGMAC_RX_BUF_SIZE (BGMAC_RX_FRAME_OFFSET + BGMAC_RX_MAX_FRAME_SIZE) 364#define BGMAC_RX_BUF_SIZE (BGMAC_RX_FRAME_OFFSET + BGMAC_RX_MAX_FRAME_SIZE)
365#define BGMAC_RX_ALLOC_SIZE (SKB_DATA_ALIGN(BGMAC_RX_BUF_SIZE) + \
366 SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))
365 367
366#define BGMAC_BFL_ENETROBO 0x0010 /* has ephy roboswitch spi */ 368#define BGMAC_BFL_ENETROBO 0x0010 /* has ephy roboswitch spi */
367#define BGMAC_BFL_ENETADM 0x0080 /* has ADMtek switch */ 369#define BGMAC_BFL_ENETADM 0x0080 /* has ADMtek switch */
@@ -383,7 +385,10 @@
383#define ETHER_MAX_LEN 1518 385#define ETHER_MAX_LEN 1518
384 386
385struct bgmac_slot_info { 387struct bgmac_slot_info {
386 struct sk_buff *skb; 388 union {
389 struct sk_buff *skb;
390 void *buf;
391 };
387 dma_addr_t dma_addr; 392 dma_addr_t dma_addr;
388}; 393};
389 394