aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2015-05-31 02:51:37 -0400
committerDavid S. Miller <davem@davemloft.net>2015-05-31 02:51:37 -0400
commit5289e4a03fb9ba79f0ad065c26024afe379c3d35 (patch)
tree329f41c29ccf0528095ee270034511b114b01f21
parent3d2f6d41d1588c975d16c5969726d018bba90794 (diff)
parent25977ac77d62b3de19908979ac84c8fd5809de6f (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.c107
-rw-r--r--drivers/net/ethernet/broadcom/bcmsysport.h2
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
527static int bcm_sysport_rx_refill(struct bcm_sysport_priv *priv, 527static 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
564static int bcm_sysport_alloc_rx_bufs(struct bcm_sysport_priv *priv) 569static 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 */
584static unsigned int bcm_sysport_desc_rx(struct bcm_sysport_priv *priv, 588static 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);
689refill: 691next:
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
1331static int bcm_sysport_init_rx_ring(struct bcm_sysport_priv *priv) 1335static 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;