diff options
-rw-r--r-- | drivers/net/ethernet/broadcom/bgmac.c | 80 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/bgmac.h | 7 |
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 | ||
437 | static void bgmac_dma_ring_free(struct bgmac *bgmac, | 438 | static 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) { | 456 | static 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 | ||
476 | static 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 | |||
463 | static void bgmac_dma_free(struct bgmac *bgmac) | 491 | static 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 | ||
473 | static int bgmac_dma_alloc(struct bgmac *bgmac) | 505 | static 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 | ||
385 | struct bgmac_slot_info { | 387 | struct 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 | ||