diff options
Diffstat (limited to 'drivers/net/ethernet/broadcom/genet/bcmgenet.c')
-rw-r--r-- | drivers/net/ethernet/broadcom/genet/bcmgenet.c | 122 |
1 files changed, 92 insertions, 30 deletions
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index 51300532ec26..84feb241d60b 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c | |||
@@ -487,6 +487,7 @@ enum bcmgenet_stat_type { | |||
487 | BCMGENET_STAT_MIB_TX, | 487 | BCMGENET_STAT_MIB_TX, |
488 | BCMGENET_STAT_RUNT, | 488 | BCMGENET_STAT_RUNT, |
489 | BCMGENET_STAT_MISC, | 489 | BCMGENET_STAT_MISC, |
490 | BCMGENET_STAT_SOFT, | ||
490 | }; | 491 | }; |
491 | 492 | ||
492 | struct bcmgenet_stats { | 493 | struct bcmgenet_stats { |
@@ -515,6 +516,7 @@ struct bcmgenet_stats { | |||
515 | #define STAT_GENET_MIB_RX(str, m) STAT_GENET_MIB(str, m, BCMGENET_STAT_MIB_RX) | 516 | #define STAT_GENET_MIB_RX(str, m) STAT_GENET_MIB(str, m, BCMGENET_STAT_MIB_RX) |
516 | #define STAT_GENET_MIB_TX(str, m) STAT_GENET_MIB(str, m, BCMGENET_STAT_MIB_TX) | 517 | #define STAT_GENET_MIB_TX(str, m) STAT_GENET_MIB(str, m, BCMGENET_STAT_MIB_TX) |
517 | #define STAT_GENET_RUNT(str, m) STAT_GENET_MIB(str, m, BCMGENET_STAT_RUNT) | 518 | #define STAT_GENET_RUNT(str, m) STAT_GENET_MIB(str, m, BCMGENET_STAT_RUNT) |
519 | #define STAT_GENET_SOFT_MIB(str, m) STAT_GENET_MIB(str, m, BCMGENET_STAT_SOFT) | ||
518 | 520 | ||
519 | #define STAT_GENET_MISC(str, m, offset) { \ | 521 | #define STAT_GENET_MISC(str, m, offset) { \ |
520 | .stat_string = str, \ | 522 | .stat_string = str, \ |
@@ -614,9 +616,9 @@ static const struct bcmgenet_stats bcmgenet_gstrings_stats[] = { | |||
614 | UMAC_RBUF_OVFL_CNT), | 616 | UMAC_RBUF_OVFL_CNT), |
615 | STAT_GENET_MISC("rbuf_err_cnt", mib.rbuf_err_cnt, UMAC_RBUF_ERR_CNT), | 617 | STAT_GENET_MISC("rbuf_err_cnt", mib.rbuf_err_cnt, UMAC_RBUF_ERR_CNT), |
616 | STAT_GENET_MISC("mdf_err_cnt", mib.mdf_err_cnt, UMAC_MDF_ERR_CNT), | 618 | STAT_GENET_MISC("mdf_err_cnt", mib.mdf_err_cnt, UMAC_MDF_ERR_CNT), |
617 | STAT_GENET_MIB_RX("alloc_rx_buff_failed", mib.alloc_rx_buff_failed), | 619 | STAT_GENET_SOFT_MIB("alloc_rx_buff_failed", mib.alloc_rx_buff_failed), |
618 | STAT_GENET_MIB_RX("rx_dma_failed", mib.rx_dma_failed), | 620 | STAT_GENET_SOFT_MIB("rx_dma_failed", mib.rx_dma_failed), |
619 | STAT_GENET_MIB_TX("tx_dma_failed", mib.tx_dma_failed), | 621 | STAT_GENET_SOFT_MIB("tx_dma_failed", mib.tx_dma_failed), |
620 | }; | 622 | }; |
621 | 623 | ||
622 | #define BCMGENET_STATS_LEN ARRAY_SIZE(bcmgenet_gstrings_stats) | 624 | #define BCMGENET_STATS_LEN ARRAY_SIZE(bcmgenet_gstrings_stats) |
@@ -668,6 +670,7 @@ static void bcmgenet_update_mib_counters(struct bcmgenet_priv *priv) | |||
668 | s = &bcmgenet_gstrings_stats[i]; | 670 | s = &bcmgenet_gstrings_stats[i]; |
669 | switch (s->type) { | 671 | switch (s->type) { |
670 | case BCMGENET_STAT_NETDEV: | 672 | case BCMGENET_STAT_NETDEV: |
673 | case BCMGENET_STAT_SOFT: | ||
671 | continue; | 674 | continue; |
672 | case BCMGENET_STAT_MIB_RX: | 675 | case BCMGENET_STAT_MIB_RX: |
673 | case BCMGENET_STAT_MIB_TX: | 676 | case BCMGENET_STAT_MIB_TX: |
@@ -971,13 +974,14 @@ static inline void bcmgenet_tx_ring_int_disable(struct bcmgenet_priv *priv, | |||
971 | } | 974 | } |
972 | 975 | ||
973 | /* Unlocked version of the reclaim routine */ | 976 | /* Unlocked version of the reclaim routine */ |
974 | static void __bcmgenet_tx_reclaim(struct net_device *dev, | 977 | static unsigned int __bcmgenet_tx_reclaim(struct net_device *dev, |
975 | struct bcmgenet_tx_ring *ring) | 978 | struct bcmgenet_tx_ring *ring) |
976 | { | 979 | { |
977 | struct bcmgenet_priv *priv = netdev_priv(dev); | 980 | struct bcmgenet_priv *priv = netdev_priv(dev); |
978 | int last_tx_cn, last_c_index, num_tx_bds; | 981 | int last_tx_cn, last_c_index, num_tx_bds; |
979 | struct enet_cb *tx_cb_ptr; | 982 | struct enet_cb *tx_cb_ptr; |
980 | struct netdev_queue *txq; | 983 | struct netdev_queue *txq; |
984 | unsigned int pkts_compl = 0; | ||
981 | unsigned int bds_compl; | 985 | unsigned int bds_compl; |
982 | unsigned int c_index; | 986 | unsigned int c_index; |
983 | 987 | ||
@@ -1005,6 +1009,7 @@ static void __bcmgenet_tx_reclaim(struct net_device *dev, | |||
1005 | tx_cb_ptr = ring->cbs + last_c_index; | 1009 | tx_cb_ptr = ring->cbs + last_c_index; |
1006 | bds_compl = 0; | 1010 | bds_compl = 0; |
1007 | if (tx_cb_ptr->skb) { | 1011 | if (tx_cb_ptr->skb) { |
1012 | pkts_compl++; | ||
1008 | bds_compl = skb_shinfo(tx_cb_ptr->skb)->nr_frags + 1; | 1013 | bds_compl = skb_shinfo(tx_cb_ptr->skb)->nr_frags + 1; |
1009 | dev->stats.tx_bytes += tx_cb_ptr->skb->len; | 1014 | dev->stats.tx_bytes += tx_cb_ptr->skb->len; |
1010 | dma_unmap_single(&dev->dev, | 1015 | dma_unmap_single(&dev->dev, |
@@ -1028,23 +1033,45 @@ static void __bcmgenet_tx_reclaim(struct net_device *dev, | |||
1028 | last_c_index &= (num_tx_bds - 1); | 1033 | last_c_index &= (num_tx_bds - 1); |
1029 | } | 1034 | } |
1030 | 1035 | ||
1031 | if (ring->free_bds > (MAX_SKB_FRAGS + 1)) | 1036 | if (ring->free_bds > (MAX_SKB_FRAGS + 1)) { |
1032 | ring->int_disable(priv, ring); | 1037 | if (netif_tx_queue_stopped(txq)) |
1033 | 1038 | netif_tx_wake_queue(txq); | |
1034 | if (netif_tx_queue_stopped(txq)) | 1039 | } |
1035 | netif_tx_wake_queue(txq); | ||
1036 | 1040 | ||
1037 | ring->c_index = c_index; | 1041 | ring->c_index = c_index; |
1042 | |||
1043 | return pkts_compl; | ||
1038 | } | 1044 | } |
1039 | 1045 | ||
1040 | static void bcmgenet_tx_reclaim(struct net_device *dev, | 1046 | static unsigned int bcmgenet_tx_reclaim(struct net_device *dev, |
1041 | struct bcmgenet_tx_ring *ring) | 1047 | struct bcmgenet_tx_ring *ring) |
1042 | { | 1048 | { |
1049 | unsigned int released; | ||
1043 | unsigned long flags; | 1050 | unsigned long flags; |
1044 | 1051 | ||
1045 | spin_lock_irqsave(&ring->lock, flags); | 1052 | spin_lock_irqsave(&ring->lock, flags); |
1046 | __bcmgenet_tx_reclaim(dev, ring); | 1053 | released = __bcmgenet_tx_reclaim(dev, ring); |
1047 | spin_unlock_irqrestore(&ring->lock, flags); | 1054 | spin_unlock_irqrestore(&ring->lock, flags); |
1055 | |||
1056 | return released; | ||
1057 | } | ||
1058 | |||
1059 | static int bcmgenet_tx_poll(struct napi_struct *napi, int budget) | ||
1060 | { | ||
1061 | struct bcmgenet_tx_ring *ring = | ||
1062 | container_of(napi, struct bcmgenet_tx_ring, napi); | ||
1063 | unsigned int work_done = 0; | ||
1064 | |||
1065 | work_done = bcmgenet_tx_reclaim(ring->priv->dev, ring); | ||
1066 | |||
1067 | if (work_done == 0) { | ||
1068 | napi_complete(napi); | ||
1069 | ring->int_enable(ring->priv, ring); | ||
1070 | |||
1071 | return 0; | ||
1072 | } | ||
1073 | |||
1074 | return budget; | ||
1048 | } | 1075 | } |
1049 | 1076 | ||
1050 | static void bcmgenet_tx_reclaim_all(struct net_device *dev) | 1077 | static void bcmgenet_tx_reclaim_all(struct net_device *dev) |
@@ -1302,10 +1329,8 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev) | |||
1302 | bcmgenet_tdma_ring_writel(priv, ring->index, | 1329 | bcmgenet_tdma_ring_writel(priv, ring->index, |
1303 | ring->prod_index, TDMA_PROD_INDEX); | 1330 | ring->prod_index, TDMA_PROD_INDEX); |
1304 | 1331 | ||
1305 | if (ring->free_bds <= (MAX_SKB_FRAGS + 1)) { | 1332 | if (ring->free_bds <= (MAX_SKB_FRAGS + 1)) |
1306 | netif_tx_stop_queue(txq); | 1333 | netif_tx_stop_queue(txq); |
1307 | ring->int_enable(priv, ring); | ||
1308 | } | ||
1309 | 1334 | ||
1310 | out: | 1335 | out: |
1311 | spin_unlock_irqrestore(&ring->lock, flags); | 1336 | spin_unlock_irqrestore(&ring->lock, flags); |
@@ -1621,6 +1646,7 @@ static int init_umac(struct bcmgenet_priv *priv) | |||
1621 | struct device *kdev = &priv->pdev->dev; | 1646 | struct device *kdev = &priv->pdev->dev; |
1622 | int ret; | 1647 | int ret; |
1623 | u32 reg, cpu_mask_clear; | 1648 | u32 reg, cpu_mask_clear; |
1649 | int index; | ||
1624 | 1650 | ||
1625 | dev_dbg(&priv->pdev->dev, "bcmgenet: init_umac\n"); | 1651 | dev_dbg(&priv->pdev->dev, "bcmgenet: init_umac\n"); |
1626 | 1652 | ||
@@ -1647,7 +1673,7 @@ static int init_umac(struct bcmgenet_priv *priv) | |||
1647 | 1673 | ||
1648 | bcmgenet_intr_disable(priv); | 1674 | bcmgenet_intr_disable(priv); |
1649 | 1675 | ||
1650 | cpu_mask_clear = UMAC_IRQ_RXDMA_BDONE; | 1676 | cpu_mask_clear = UMAC_IRQ_RXDMA_BDONE | UMAC_IRQ_TXDMA_BDONE; |
1651 | 1677 | ||
1652 | dev_dbg(kdev, "%s:Enabling RXDMA_BDONE interrupt\n", __func__); | 1678 | dev_dbg(kdev, "%s:Enabling RXDMA_BDONE interrupt\n", __func__); |
1653 | 1679 | ||
@@ -1674,6 +1700,10 @@ static int init_umac(struct bcmgenet_priv *priv) | |||
1674 | 1700 | ||
1675 | bcmgenet_intrl2_0_writel(priv, cpu_mask_clear, INTRL2_CPU_MASK_CLEAR); | 1701 | bcmgenet_intrl2_0_writel(priv, cpu_mask_clear, INTRL2_CPU_MASK_CLEAR); |
1676 | 1702 | ||
1703 | for (index = 0; index < priv->hw_params->tx_queues; index++) | ||
1704 | bcmgenet_intrl2_1_writel(priv, (1 << index), | ||
1705 | INTRL2_CPU_MASK_CLEAR); | ||
1706 | |||
1677 | /* Enable rx/tx engine.*/ | 1707 | /* Enable rx/tx engine.*/ |
1678 | dev_dbg(kdev, "done init umac\n"); | 1708 | dev_dbg(kdev, "done init umac\n"); |
1679 | 1709 | ||
@@ -1690,6 +1720,8 @@ static void bcmgenet_init_tx_ring(struct bcmgenet_priv *priv, | |||
1690 | u32 flow_period_val = 0; | 1720 | u32 flow_period_val = 0; |
1691 | 1721 | ||
1692 | spin_lock_init(&ring->lock); | 1722 | spin_lock_init(&ring->lock); |
1723 | ring->priv = priv; | ||
1724 | netif_napi_add(priv->dev, &ring->napi, bcmgenet_tx_poll, 64); | ||
1693 | ring->index = index; | 1725 | ring->index = index; |
1694 | if (index == DESC_INDEX) { | 1726 | if (index == DESC_INDEX) { |
1695 | ring->queue = 0; | 1727 | ring->queue = 0; |
@@ -1732,6 +1764,17 @@ static void bcmgenet_init_tx_ring(struct bcmgenet_priv *priv, | |||
1732 | TDMA_WRITE_PTR); | 1764 | TDMA_WRITE_PTR); |
1733 | bcmgenet_tdma_ring_writel(priv, index, end_ptr * words_per_bd - 1, | 1765 | bcmgenet_tdma_ring_writel(priv, index, end_ptr * words_per_bd - 1, |
1734 | DMA_END_ADDR); | 1766 | DMA_END_ADDR); |
1767 | |||
1768 | napi_enable(&ring->napi); | ||
1769 | } | ||
1770 | |||
1771 | static void bcmgenet_fini_tx_ring(struct bcmgenet_priv *priv, | ||
1772 | unsigned int index) | ||
1773 | { | ||
1774 | struct bcmgenet_tx_ring *ring = &priv->tx_rings[index]; | ||
1775 | |||
1776 | napi_disable(&ring->napi); | ||
1777 | netif_napi_del(&ring->napi); | ||
1735 | } | 1778 | } |
1736 | 1779 | ||
1737 | /* Initialize a RDMA ring */ | 1780 | /* Initialize a RDMA ring */ |
@@ -1896,7 +1939,7 @@ static int bcmgenet_dma_teardown(struct bcmgenet_priv *priv) | |||
1896 | return ret; | 1939 | return ret; |
1897 | } | 1940 | } |
1898 | 1941 | ||
1899 | static void bcmgenet_fini_dma(struct bcmgenet_priv *priv) | 1942 | static void __bcmgenet_fini_dma(struct bcmgenet_priv *priv) |
1900 | { | 1943 | { |
1901 | int i; | 1944 | int i; |
1902 | 1945 | ||
@@ -1915,6 +1958,18 @@ static void bcmgenet_fini_dma(struct bcmgenet_priv *priv) | |||
1915 | kfree(priv->tx_cbs); | 1958 | kfree(priv->tx_cbs); |
1916 | } | 1959 | } |
1917 | 1960 | ||
1961 | static void bcmgenet_fini_dma(struct bcmgenet_priv *priv) | ||
1962 | { | ||
1963 | int i; | ||
1964 | |||
1965 | bcmgenet_fini_tx_ring(priv, DESC_INDEX); | ||
1966 | |||
1967 | for (i = 0; i < priv->hw_params->tx_queues; i++) | ||
1968 | bcmgenet_fini_tx_ring(priv, i); | ||
1969 | |||
1970 | __bcmgenet_fini_dma(priv); | ||
1971 | } | ||
1972 | |||
1918 | /* init_edma: Initialize DMA control register */ | 1973 | /* init_edma: Initialize DMA control register */ |
1919 | static int bcmgenet_init_dma(struct bcmgenet_priv *priv) | 1974 | static int bcmgenet_init_dma(struct bcmgenet_priv *priv) |
1920 | { | 1975 | { |
@@ -1943,7 +1998,7 @@ static int bcmgenet_init_dma(struct bcmgenet_priv *priv) | |||
1943 | priv->tx_cbs = kcalloc(priv->num_tx_bds, sizeof(struct enet_cb), | 1998 | priv->tx_cbs = kcalloc(priv->num_tx_bds, sizeof(struct enet_cb), |
1944 | GFP_KERNEL); | 1999 | GFP_KERNEL); |
1945 | if (!priv->tx_cbs) { | 2000 | if (!priv->tx_cbs) { |
1946 | bcmgenet_fini_dma(priv); | 2001 | __bcmgenet_fini_dma(priv); |
1947 | return -ENOMEM; | 2002 | return -ENOMEM; |
1948 | } | 2003 | } |
1949 | 2004 | ||
@@ -1965,9 +2020,6 @@ static int bcmgenet_poll(struct napi_struct *napi, int budget) | |||
1965 | struct bcmgenet_priv, napi); | 2020 | struct bcmgenet_priv, napi); |
1966 | unsigned int work_done; | 2021 | unsigned int work_done; |
1967 | 2022 | ||
1968 | /* tx reclaim */ | ||
1969 | bcmgenet_tx_reclaim(priv->dev, &priv->tx_rings[DESC_INDEX]); | ||
1970 | |||
1971 | work_done = bcmgenet_desc_rx(priv, budget); | 2023 | work_done = bcmgenet_desc_rx(priv, budget); |
1972 | 2024 | ||
1973 | /* Advancing our consumer index*/ | 2025 | /* Advancing our consumer index*/ |
@@ -2012,28 +2064,34 @@ static void bcmgenet_irq_task(struct work_struct *work) | |||
2012 | static irqreturn_t bcmgenet_isr1(int irq, void *dev_id) | 2064 | static irqreturn_t bcmgenet_isr1(int irq, void *dev_id) |
2013 | { | 2065 | { |
2014 | struct bcmgenet_priv *priv = dev_id; | 2066 | struct bcmgenet_priv *priv = dev_id; |
2067 | struct bcmgenet_tx_ring *ring; | ||
2015 | unsigned int index; | 2068 | unsigned int index; |
2016 | 2069 | ||
2017 | /* Save irq status for bottom-half processing. */ | 2070 | /* Save irq status for bottom-half processing. */ |
2018 | priv->irq1_stat = | 2071 | priv->irq1_stat = |
2019 | bcmgenet_intrl2_1_readl(priv, INTRL2_CPU_STAT) & | 2072 | bcmgenet_intrl2_1_readl(priv, INTRL2_CPU_STAT) & |
2020 | ~priv->int1_mask; | 2073 | ~bcmgenet_intrl2_1_readl(priv, INTRL2_CPU_MASK_STATUS); |
2021 | /* clear interrupts */ | 2074 | /* clear interrupts */ |
2022 | bcmgenet_intrl2_1_writel(priv, priv->irq1_stat, INTRL2_CPU_CLEAR); | 2075 | bcmgenet_intrl2_1_writel(priv, priv->irq1_stat, INTRL2_CPU_CLEAR); |
2023 | 2076 | ||
2024 | netif_dbg(priv, intr, priv->dev, | 2077 | netif_dbg(priv, intr, priv->dev, |
2025 | "%s: IRQ=0x%x\n", __func__, priv->irq1_stat); | 2078 | "%s: IRQ=0x%x\n", __func__, priv->irq1_stat); |
2079 | |||
2026 | /* Check the MBDONE interrupts. | 2080 | /* Check the MBDONE interrupts. |
2027 | * packet is done, reclaim descriptors | 2081 | * packet is done, reclaim descriptors |
2028 | */ | 2082 | */ |
2029 | if (priv->irq1_stat & 0x0000ffff) { | 2083 | for (index = 0; index < priv->hw_params->tx_queues; index++) { |
2030 | index = 0; | 2084 | if (!(priv->irq1_stat & BIT(index))) |
2031 | for (index = 0; index < 16; index++) { | 2085 | continue; |
2032 | if (priv->irq1_stat & (1 << index)) | 2086 | |
2033 | bcmgenet_tx_reclaim(priv->dev, | 2087 | ring = &priv->tx_rings[index]; |
2034 | &priv->tx_rings[index]); | 2088 | |
2089 | if (likely(napi_schedule_prep(&ring->napi))) { | ||
2090 | ring->int_disable(priv, ring); | ||
2091 | __napi_schedule(&ring->napi); | ||
2035 | } | 2092 | } |
2036 | } | 2093 | } |
2094 | |||
2037 | return IRQ_HANDLED; | 2095 | return IRQ_HANDLED; |
2038 | } | 2096 | } |
2039 | 2097 | ||
@@ -2065,8 +2123,12 @@ static irqreturn_t bcmgenet_isr0(int irq, void *dev_id) | |||
2065 | } | 2123 | } |
2066 | if (priv->irq0_stat & | 2124 | if (priv->irq0_stat & |
2067 | (UMAC_IRQ_TXDMA_BDONE | UMAC_IRQ_TXDMA_PDONE)) { | 2125 | (UMAC_IRQ_TXDMA_BDONE | UMAC_IRQ_TXDMA_PDONE)) { |
2068 | /* Tx reclaim */ | 2126 | struct bcmgenet_tx_ring *ring = &priv->tx_rings[DESC_INDEX]; |
2069 | bcmgenet_tx_reclaim(priv->dev, &priv->tx_rings[DESC_INDEX]); | 2127 | |
2128 | if (likely(napi_schedule_prep(&ring->napi))) { | ||
2129 | ring->int_disable(priv, ring); | ||
2130 | __napi_schedule(&ring->napi); | ||
2131 | } | ||
2070 | } | 2132 | } |
2071 | if (priv->irq0_stat & (UMAC_IRQ_PHY_DET_R | | 2133 | if (priv->irq0_stat & (UMAC_IRQ_PHY_DET_R | |
2072 | UMAC_IRQ_PHY_DET_F | | 2134 | UMAC_IRQ_PHY_DET_F | |