aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ethernet/socionext/netsec.c56
1 files changed, 45 insertions, 11 deletions
diff --git a/drivers/net/ethernet/socionext/netsec.c b/drivers/net/ethernet/socionext/netsec.c
index bba9733b5119..584a6b3f6542 100644
--- a/drivers/net/ethernet/socionext/netsec.c
+++ b/drivers/net/ethernet/socionext/netsec.c
@@ -656,8 +656,13 @@ static int netsec_process_tx(struct netsec_priv *priv, int budget)
656 budget -= new; 656 budget -= new;
657 } while (new); 657 } while (new);
658 658
659 if (done && netif_queue_stopped(ndev)) 659 if (done && netif_queue_stopped(ndev)) {
660 /* Make sure we update the value, anyone stopping the queue
661 * after this will read the proper consumer idx
662 */
663 smp_wmb();
660 netif_wake_queue(ndev); 664 netif_wake_queue(ndev);
665 }
661 666
662 return done; 667 return done;
663} 668}
@@ -877,6 +882,41 @@ static void netsec_set_tx_de(struct netsec_priv *priv,
877 dring->head = (dring->head + 1) % DESC_NUM; 882 dring->head = (dring->head + 1) % DESC_NUM;
878} 883}
879 884
885static int netsec_desc_used(struct netsec_desc_ring *dring)
886{
887 int used;
888
889 if (dring->head >= dring->tail)
890 used = dring->head - dring->tail;
891 else
892 used = dring->head + DESC_NUM - dring->tail;
893
894 return used;
895}
896
897static int netsec_check_stop_tx(struct netsec_priv *priv, int used)
898{
899 struct netsec_desc_ring *dring = &priv->desc_ring[NETSEC_RING_TX];
900
901 /* keep tail from touching the queue */
902 if (DESC_NUM - used < 2) {
903 netif_stop_queue(priv->ndev);
904
905 /* Make sure we read the updated value in case
906 * descriptors got freed
907 */
908 smp_rmb();
909
910 used = netsec_desc_used(dring);
911 if (DESC_NUM - used < 2)
912 return NETDEV_TX_BUSY;
913
914 netif_wake_queue(priv->ndev);
915 }
916
917 return 0;
918}
919
880static netdev_tx_t netsec_netdev_start_xmit(struct sk_buff *skb, 920static netdev_tx_t netsec_netdev_start_xmit(struct sk_buff *skb,
881 struct net_device *ndev) 921 struct net_device *ndev)
882{ 922{
@@ -887,16 +927,10 @@ static netdev_tx_t netsec_netdev_start_xmit(struct sk_buff *skb,
887 u16 tso_seg_len = 0; 927 u16 tso_seg_len = 0;
888 int filled; 928 int filled;
889 929
890 /* differentiate between full/emtpy ring */ 930 filled = netsec_desc_used(dring);
891 if (dring->head >= dring->tail) 931 if (netsec_check_stop_tx(priv, filled)) {
892 filled = dring->head - dring->tail; 932 net_warn_ratelimited("%s %s Tx queue full\n",
893 else 933 dev_name(priv->dev), ndev->name);
894 filled = dring->head + DESC_NUM - dring->tail;
895
896 if (DESC_NUM - filled < 2) { /* if less than 2 available */
897 netif_err(priv, drv, priv->ndev, "%s: TxQFull!\n", __func__);
898 netif_stop_queue(priv->ndev);
899 dma_wmb();
900 return NETDEV_TX_BUSY; 934 return NETDEV_TX_BUSY;
901 } 935 }
902 936