diff options
author | David S. Miller <davem@davemloft.net> | 2015-05-31 02:51:37 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-05-31 02:51:37 -0400 |
commit | 5289e4a03fb9ba79f0ad065c26024afe379c3d35 (patch) | |
tree | 329f41c29ccf0528095ee270034511b114b01f21 | |
parent | 3d2f6d41d1588c975d16c5969726d018bba90794 (diff) | |
parent | 25977ac77d62b3de19908979ac84c8fd5809de6f (diff) |
Merge branch 'systemport-next'
Florian Fainelli says:
====================
net: systemport: misc improvements
These patches are highly inspired by changes from Petri on bcmgenet, last patch
is a misc fix that I had pending for a while, but is not a candidate for 'net'
at this point.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/broadcom/bcmsysport.c | 107 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/bcmsysport.h | 2 |
2 files changed, 58 insertions, 51 deletions
diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c index 084a50a555de..909ad7a0d480 100644 --- a/drivers/net/ethernet/broadcom/bcmsysport.c +++ b/drivers/net/ethernet/broadcom/bcmsysport.c | |||
@@ -524,67 +524,70 @@ static void bcm_sysport_free_cb(struct bcm_sysport_cb *cb) | |||
524 | dma_unmap_addr_set(cb, dma_addr, 0); | 524 | dma_unmap_addr_set(cb, dma_addr, 0); |
525 | } | 525 | } |
526 | 526 | ||
527 | static int bcm_sysport_rx_refill(struct bcm_sysport_priv *priv, | 527 | static struct sk_buff *bcm_sysport_rx_refill(struct bcm_sysport_priv *priv, |
528 | struct bcm_sysport_cb *cb) | 528 | struct bcm_sysport_cb *cb) |
529 | { | 529 | { |
530 | struct device *kdev = &priv->pdev->dev; | 530 | struct device *kdev = &priv->pdev->dev; |
531 | struct net_device *ndev = priv->netdev; | 531 | struct net_device *ndev = priv->netdev; |
532 | struct sk_buff *skb, *rx_skb; | ||
532 | dma_addr_t mapping; | 533 | dma_addr_t mapping; |
533 | int ret; | ||
534 | 534 | ||
535 | cb->skb = netdev_alloc_skb(priv->netdev, RX_BUF_LENGTH); | 535 | /* Allocate a new SKB for a new packet */ |
536 | if (!cb->skb) { | 536 | skb = netdev_alloc_skb(priv->netdev, RX_BUF_LENGTH); |
537 | if (!skb) { | ||
538 | priv->mib.alloc_rx_buff_failed++; | ||
537 | netif_err(priv, rx_err, ndev, "SKB alloc failed\n"); | 539 | netif_err(priv, rx_err, ndev, "SKB alloc failed\n"); |
538 | return -ENOMEM; | 540 | return NULL; |
539 | } | 541 | } |
540 | 542 | ||
541 | mapping = dma_map_single(kdev, cb->skb->data, | 543 | mapping = dma_map_single(kdev, skb->data, |
542 | RX_BUF_LENGTH, DMA_FROM_DEVICE); | 544 | RX_BUF_LENGTH, DMA_FROM_DEVICE); |
543 | ret = dma_mapping_error(kdev, mapping); | 545 | if (dma_mapping_error(kdev, mapping)) { |
544 | if (ret) { | ||
545 | priv->mib.rx_dma_failed++; | 546 | priv->mib.rx_dma_failed++; |
546 | bcm_sysport_free_cb(cb); | 547 | dev_kfree_skb_any(skb); |
547 | netif_err(priv, rx_err, ndev, "DMA mapping failure\n"); | 548 | netif_err(priv, rx_err, ndev, "DMA mapping failure\n"); |
548 | return ret; | 549 | return NULL; |
549 | } | 550 | } |
550 | 551 | ||
551 | dma_unmap_addr_set(cb, dma_addr, mapping); | 552 | /* Grab the current SKB on the ring */ |
552 | dma_desc_set_addr(priv, priv->rx_bd_assign_ptr, mapping); | 553 | rx_skb = cb->skb; |
554 | if (likely(rx_skb)) | ||
555 | dma_unmap_single(kdev, dma_unmap_addr(cb, dma_addr), | ||
556 | RX_BUF_LENGTH, DMA_FROM_DEVICE); | ||
553 | 557 | ||
554 | priv->rx_bd_assign_index++; | 558 | /* Put the new SKB on the ring */ |
555 | priv->rx_bd_assign_index &= (priv->num_rx_bds - 1); | 559 | cb->skb = skb; |
556 | priv->rx_bd_assign_ptr = priv->rx_bds + | 560 | dma_unmap_addr_set(cb, dma_addr, mapping); |
557 | (priv->rx_bd_assign_index * DESC_SIZE); | 561 | dma_desc_set_addr(priv, cb->bd_addr, mapping); |
558 | 562 | ||
559 | netif_dbg(priv, rx_status, ndev, "RX refill\n"); | 563 | netif_dbg(priv, rx_status, ndev, "RX refill\n"); |
560 | 564 | ||
561 | return 0; | 565 | /* Return the current SKB to the caller */ |
566 | return rx_skb; | ||
562 | } | 567 | } |
563 | 568 | ||
564 | static int bcm_sysport_alloc_rx_bufs(struct bcm_sysport_priv *priv) | 569 | static int bcm_sysport_alloc_rx_bufs(struct bcm_sysport_priv *priv) |
565 | { | 570 | { |
566 | struct bcm_sysport_cb *cb; | 571 | struct bcm_sysport_cb *cb; |
567 | int ret = 0; | 572 | struct sk_buff *skb; |
568 | unsigned int i; | 573 | unsigned int i; |
569 | 574 | ||
570 | for (i = 0; i < priv->num_rx_bds; i++) { | 575 | for (i = 0; i < priv->num_rx_bds; i++) { |
571 | cb = &priv->rx_cbs[priv->rx_bd_assign_index]; | 576 | cb = &priv->rx_cbs[i]; |
572 | if (cb->skb) | 577 | skb = bcm_sysport_rx_refill(priv, cb); |
573 | continue; | 578 | if (skb) |
574 | 579 | dev_kfree_skb(skb); | |
575 | ret = bcm_sysport_rx_refill(priv, cb); | 580 | if (!cb->skb) |
576 | if (ret) | 581 | return -ENOMEM; |
577 | break; | ||
578 | } | 582 | } |
579 | 583 | ||
580 | return ret; | 584 | return 0; |
581 | } | 585 | } |
582 | 586 | ||
583 | /* Poll the hardware for up to budget packets to process */ | 587 | /* Poll the hardware for up to budget packets to process */ |
584 | static unsigned int bcm_sysport_desc_rx(struct bcm_sysport_priv *priv, | 588 | static unsigned int bcm_sysport_desc_rx(struct bcm_sysport_priv *priv, |
585 | unsigned int budget) | 589 | unsigned int budget) |
586 | { | 590 | { |
587 | struct device *kdev = &priv->pdev->dev; | ||
588 | struct net_device *ndev = priv->netdev; | 591 | struct net_device *ndev = priv->netdev; |
589 | unsigned int processed = 0, to_process; | 592 | unsigned int processed = 0, to_process; |
590 | struct bcm_sysport_cb *cb; | 593 | struct bcm_sysport_cb *cb; |
@@ -592,7 +595,6 @@ static unsigned int bcm_sysport_desc_rx(struct bcm_sysport_priv *priv, | |||
592 | unsigned int p_index; | 595 | unsigned int p_index; |
593 | u16 len, status; | 596 | u16 len, status; |
594 | struct bcm_rsb *rsb; | 597 | struct bcm_rsb *rsb; |
595 | int ret; | ||
596 | 598 | ||
597 | /* Determine how much we should process since last call */ | 599 | /* Determine how much we should process since last call */ |
598 | p_index = rdma_readl(priv, RDMA_PROD_INDEX); | 600 | p_index = rdma_readl(priv, RDMA_PROD_INDEX); |
@@ -610,13 +612,8 @@ static unsigned int bcm_sysport_desc_rx(struct bcm_sysport_priv *priv, | |||
610 | 612 | ||
611 | while ((processed < to_process) && (processed < budget)) { | 613 | while ((processed < to_process) && (processed < budget)) { |
612 | cb = &priv->rx_cbs[priv->rx_read_ptr]; | 614 | cb = &priv->rx_cbs[priv->rx_read_ptr]; |
613 | skb = cb->skb; | 615 | skb = bcm_sysport_rx_refill(priv, cb); |
614 | 616 | ||
615 | processed++; | ||
616 | priv->rx_read_ptr++; | ||
617 | |||
618 | if (priv->rx_read_ptr == priv->num_rx_bds) | ||
619 | priv->rx_read_ptr = 0; | ||
620 | 617 | ||
621 | /* We do not have a backing SKB, so we do not a corresponding | 618 | /* We do not have a backing SKB, so we do not a corresponding |
622 | * DMA mapping for this incoming packet since | 619 | * DMA mapping for this incoming packet since |
@@ -627,12 +624,9 @@ static unsigned int bcm_sysport_desc_rx(struct bcm_sysport_priv *priv, | |||
627 | netif_err(priv, rx_err, ndev, "out of memory!\n"); | 624 | netif_err(priv, rx_err, ndev, "out of memory!\n"); |
628 | ndev->stats.rx_dropped++; | 625 | ndev->stats.rx_dropped++; |
629 | ndev->stats.rx_errors++; | 626 | ndev->stats.rx_errors++; |
630 | goto refill; | 627 | goto next; |
631 | } | 628 | } |
632 | 629 | ||
633 | dma_unmap_single(kdev, dma_unmap_addr(cb, dma_addr), | ||
634 | RX_BUF_LENGTH, DMA_FROM_DEVICE); | ||
635 | |||
636 | /* Extract the Receive Status Block prepended */ | 630 | /* Extract the Receive Status Block prepended */ |
637 | rsb = (struct bcm_rsb *)skb->data; | 631 | rsb = (struct bcm_rsb *)skb->data; |
638 | len = (rsb->rx_status_len >> DESC_LEN_SHIFT) & DESC_LEN_MASK; | 632 | len = (rsb->rx_status_len >> DESC_LEN_SHIFT) & DESC_LEN_MASK; |
@@ -644,12 +638,20 @@ static unsigned int bcm_sysport_desc_rx(struct bcm_sysport_priv *priv, | |||
644 | p_index, priv->rx_c_index, priv->rx_read_ptr, | 638 | p_index, priv->rx_c_index, priv->rx_read_ptr, |
645 | len, status); | 639 | len, status); |
646 | 640 | ||
641 | if (unlikely(len > RX_BUF_LENGTH)) { | ||
642 | netif_err(priv, rx_status, ndev, "oversized packet\n"); | ||
643 | ndev->stats.rx_length_errors++; | ||
644 | ndev->stats.rx_errors++; | ||
645 | dev_kfree_skb_any(skb); | ||
646 | goto next; | ||
647 | } | ||
648 | |||
647 | if (unlikely(!(status & DESC_EOP) || !(status & DESC_SOP))) { | 649 | if (unlikely(!(status & DESC_EOP) || !(status & DESC_SOP))) { |
648 | netif_err(priv, rx_status, ndev, "fragmented packet!\n"); | 650 | netif_err(priv, rx_status, ndev, "fragmented packet!\n"); |
649 | ndev->stats.rx_dropped++; | 651 | ndev->stats.rx_dropped++; |
650 | ndev->stats.rx_errors++; | 652 | ndev->stats.rx_errors++; |
651 | bcm_sysport_free_cb(cb); | 653 | dev_kfree_skb_any(skb); |
652 | goto refill; | 654 | goto next; |
653 | } | 655 | } |
654 | 656 | ||
655 | if (unlikely(status & (RX_STATUS_ERR | RX_STATUS_OVFLOW))) { | 657 | if (unlikely(status & (RX_STATUS_ERR | RX_STATUS_OVFLOW))) { |
@@ -658,8 +660,8 @@ static unsigned int bcm_sysport_desc_rx(struct bcm_sysport_priv *priv, | |||
658 | ndev->stats.rx_over_errors++; | 660 | ndev->stats.rx_over_errors++; |
659 | ndev->stats.rx_dropped++; | 661 | ndev->stats.rx_dropped++; |
660 | ndev->stats.rx_errors++; | 662 | ndev->stats.rx_errors++; |
661 | bcm_sysport_free_cb(cb); | 663 | dev_kfree_skb_any(skb); |
662 | goto refill; | 664 | goto next; |
663 | } | 665 | } |
664 | 666 | ||
665 | skb_put(skb, len); | 667 | skb_put(skb, len); |
@@ -686,10 +688,12 @@ static unsigned int bcm_sysport_desc_rx(struct bcm_sysport_priv *priv, | |||
686 | ndev->stats.rx_bytes += len; | 688 | ndev->stats.rx_bytes += len; |
687 | 689 | ||
688 | napi_gro_receive(&priv->napi, skb); | 690 | napi_gro_receive(&priv->napi, skb); |
689 | refill: | 691 | next: |
690 | ret = bcm_sysport_rx_refill(priv, cb); | 692 | processed++; |
691 | if (ret) | 693 | priv->rx_read_ptr++; |
692 | priv->mib.alloc_rx_buff_failed++; | 694 | |
695 | if (priv->rx_read_ptr == priv->num_rx_bds) | ||
696 | priv->rx_read_ptr = 0; | ||
693 | } | 697 | } |
694 | 698 | ||
695 | return processed; | 699 | return processed; |
@@ -1330,14 +1334,14 @@ static inline int tdma_enable_set(struct bcm_sysport_priv *priv, | |||
1330 | 1334 | ||
1331 | static int bcm_sysport_init_rx_ring(struct bcm_sysport_priv *priv) | 1335 | static int bcm_sysport_init_rx_ring(struct bcm_sysport_priv *priv) |
1332 | { | 1336 | { |
1337 | struct bcm_sysport_cb *cb; | ||
1333 | u32 reg; | 1338 | u32 reg; |
1334 | int ret; | 1339 | int ret; |
1340 | int i; | ||
1335 | 1341 | ||
1336 | /* Initialize SW view of the RX ring */ | 1342 | /* Initialize SW view of the RX ring */ |
1337 | priv->num_rx_bds = NUM_RX_DESC; | 1343 | priv->num_rx_bds = NUM_RX_DESC; |
1338 | priv->rx_bds = priv->base + SYS_PORT_RDMA_OFFSET; | 1344 | priv->rx_bds = priv->base + SYS_PORT_RDMA_OFFSET; |
1339 | priv->rx_bd_assign_ptr = priv->rx_bds; | ||
1340 | priv->rx_bd_assign_index = 0; | ||
1341 | priv->rx_c_index = 0; | 1345 | priv->rx_c_index = 0; |
1342 | priv->rx_read_ptr = 0; | 1346 | priv->rx_read_ptr = 0; |
1343 | priv->rx_cbs = kcalloc(priv->num_rx_bds, sizeof(struct bcm_sysport_cb), | 1347 | priv->rx_cbs = kcalloc(priv->num_rx_bds, sizeof(struct bcm_sysport_cb), |
@@ -1347,6 +1351,11 @@ static int bcm_sysport_init_rx_ring(struct bcm_sysport_priv *priv) | |||
1347 | return -ENOMEM; | 1351 | return -ENOMEM; |
1348 | } | 1352 | } |
1349 | 1353 | ||
1354 | for (i = 0; i < priv->num_rx_bds; i++) { | ||
1355 | cb = priv->rx_cbs + i; | ||
1356 | cb->bd_addr = priv->rx_bds + i * DESC_SIZE; | ||
1357 | } | ||
1358 | |||
1350 | ret = bcm_sysport_alloc_rx_bufs(priv); | 1359 | ret = bcm_sysport_alloc_rx_bufs(priv); |
1351 | if (ret) { | 1360 | if (ret) { |
1352 | netif_err(priv, hw, priv->netdev, "SKB allocation failed\n"); | 1361 | netif_err(priv, hw, priv->netdev, "SKB allocation failed\n"); |
diff --git a/drivers/net/ethernet/broadcom/bcmsysport.h b/drivers/net/ethernet/broadcom/bcmsysport.h index 42a4b4a0bc14..f28bf545d7f4 100644 --- a/drivers/net/ethernet/broadcom/bcmsysport.h +++ b/drivers/net/ethernet/broadcom/bcmsysport.h | |||
@@ -663,8 +663,6 @@ struct bcm_sysport_priv { | |||
663 | 663 | ||
664 | /* Receive queue */ | 664 | /* Receive queue */ |
665 | void __iomem *rx_bds; | 665 | void __iomem *rx_bds; |
666 | void __iomem *rx_bd_assign_ptr; | ||
667 | unsigned int rx_bd_assign_index; | ||
668 | struct bcm_sysport_cb *rx_cbs; | 666 | struct bcm_sysport_cb *rx_cbs; |
669 | unsigned int num_rx_bds; | 667 | unsigned int num_rx_bds; |
670 | unsigned int rx_read_ptr; | 668 | unsigned int rx_read_ptr; |