diff options
author | Florian Fainelli <f.fainelli@gmail.com> | 2017-01-12 15:09:09 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-02-04 03:47:09 -0500 |
commit | b66b1f5ac33d20d12fb56b30a1dac8d79c8a0038 (patch) | |
tree | 0d86b497f5276ac51f5d0cfe260cae6e81d3aa72 | |
parent | 958bb1bdc2c272fb63f31510d00579f59acb7a06 (diff) |
net: systemport: Decouple flow control from __bcm_sysport_tx_reclaim
[ Upstream commit 148d3d021cf9724fcf189ce4e525a094bbf5ce89 ]
The __bcm_sysport_tx_reclaim() function is used to reclaim transmit
resources in different places within the driver. Most of them should
not affect the state of the transit flow control.
Introduce bcm_sysport_tx_clean() which cleans the ring, but does not
re-enable flow control towards the networking stack, and make
bcm_sysport_tx_reclaim() do the actual transmit queue flow control.
Fixes: 80105befdb4b ("net: systemport: add Broadcom SYSTEMPORT Ethernet MAC driver")
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/net/ethernet/broadcom/bcmsysport.c | 25 |
1 files changed, 18 insertions, 7 deletions
diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c index 25d1eb4933d0..be7ec5a76a54 100644 --- a/drivers/net/ethernet/broadcom/bcmsysport.c +++ b/drivers/net/ethernet/broadcom/bcmsysport.c | |||
@@ -710,11 +710,8 @@ static unsigned int __bcm_sysport_tx_reclaim(struct bcm_sysport_priv *priv, | |||
710 | unsigned int c_index, last_c_index, last_tx_cn, num_tx_cbs; | 710 | unsigned int c_index, last_c_index, last_tx_cn, num_tx_cbs; |
711 | unsigned int pkts_compl = 0, bytes_compl = 0; | 711 | unsigned int pkts_compl = 0, bytes_compl = 0; |
712 | struct bcm_sysport_cb *cb; | 712 | struct bcm_sysport_cb *cb; |
713 | struct netdev_queue *txq; | ||
714 | u32 hw_ind; | 713 | u32 hw_ind; |
715 | 714 | ||
716 | txq = netdev_get_tx_queue(ndev, ring->index); | ||
717 | |||
718 | /* Compute how many descriptors have been processed since last call */ | 715 | /* Compute how many descriptors have been processed since last call */ |
719 | hw_ind = tdma_readl(priv, TDMA_DESC_RING_PROD_CONS_INDEX(ring->index)); | 716 | hw_ind = tdma_readl(priv, TDMA_DESC_RING_PROD_CONS_INDEX(ring->index)); |
720 | c_index = (hw_ind >> RING_CONS_INDEX_SHIFT) & RING_CONS_INDEX_MASK; | 717 | c_index = (hw_ind >> RING_CONS_INDEX_SHIFT) & RING_CONS_INDEX_MASK; |
@@ -745,9 +742,6 @@ static unsigned int __bcm_sysport_tx_reclaim(struct bcm_sysport_priv *priv, | |||
745 | 742 | ||
746 | ring->c_index = c_index; | 743 | ring->c_index = c_index; |
747 | 744 | ||
748 | if (netif_tx_queue_stopped(txq) && pkts_compl) | ||
749 | netif_tx_wake_queue(txq); | ||
750 | |||
751 | netif_dbg(priv, tx_done, ndev, | 745 | netif_dbg(priv, tx_done, ndev, |
752 | "ring=%d c_index=%d pkts_compl=%d, bytes_compl=%d\n", | 746 | "ring=%d c_index=%d pkts_compl=%d, bytes_compl=%d\n", |
753 | ring->index, ring->c_index, pkts_compl, bytes_compl); | 747 | ring->index, ring->c_index, pkts_compl, bytes_compl); |
@@ -759,16 +753,33 @@ static unsigned int __bcm_sysport_tx_reclaim(struct bcm_sysport_priv *priv, | |||
759 | static unsigned int bcm_sysport_tx_reclaim(struct bcm_sysport_priv *priv, | 753 | static unsigned int bcm_sysport_tx_reclaim(struct bcm_sysport_priv *priv, |
760 | struct bcm_sysport_tx_ring *ring) | 754 | struct bcm_sysport_tx_ring *ring) |
761 | { | 755 | { |
756 | struct netdev_queue *txq; | ||
762 | unsigned int released; | 757 | unsigned int released; |
763 | unsigned long flags; | 758 | unsigned long flags; |
764 | 759 | ||
760 | txq = netdev_get_tx_queue(priv->netdev, ring->index); | ||
761 | |||
765 | spin_lock_irqsave(&ring->lock, flags); | 762 | spin_lock_irqsave(&ring->lock, flags); |
766 | released = __bcm_sysport_tx_reclaim(priv, ring); | 763 | released = __bcm_sysport_tx_reclaim(priv, ring); |
764 | if (released) | ||
765 | netif_tx_wake_queue(txq); | ||
766 | |||
767 | spin_unlock_irqrestore(&ring->lock, flags); | 767 | spin_unlock_irqrestore(&ring->lock, flags); |
768 | 768 | ||
769 | return released; | 769 | return released; |
770 | } | 770 | } |
771 | 771 | ||
772 | /* Locked version of the per-ring TX reclaim, but does not wake the queue */ | ||
773 | static void bcm_sysport_tx_clean(struct bcm_sysport_priv *priv, | ||
774 | struct bcm_sysport_tx_ring *ring) | ||
775 | { | ||
776 | unsigned long flags; | ||
777 | |||
778 | spin_lock_irqsave(&ring->lock, flags); | ||
779 | __bcm_sysport_tx_reclaim(priv, ring); | ||
780 | spin_unlock_irqrestore(&ring->lock, flags); | ||
781 | } | ||
782 | |||
772 | static int bcm_sysport_tx_poll(struct napi_struct *napi, int budget) | 783 | static int bcm_sysport_tx_poll(struct napi_struct *napi, int budget) |
773 | { | 784 | { |
774 | struct bcm_sysport_tx_ring *ring = | 785 | struct bcm_sysport_tx_ring *ring = |
@@ -1253,7 +1264,7 @@ static void bcm_sysport_fini_tx_ring(struct bcm_sysport_priv *priv, | |||
1253 | napi_disable(&ring->napi); | 1264 | napi_disable(&ring->napi); |
1254 | netif_napi_del(&ring->napi); | 1265 | netif_napi_del(&ring->napi); |
1255 | 1266 | ||
1256 | bcm_sysport_tx_reclaim(priv, ring); | 1267 | bcm_sysport_tx_clean(priv, ring); |
1257 | 1268 | ||
1258 | kfree(ring->cbs); | 1269 | kfree(ring->cbs); |
1259 | ring->cbs = NULL; | 1270 | ring->cbs = NULL; |