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 | ||
