diff options
-rw-r--r-- | drivers/net/ethernet/socionext/netsec.c | 56 |
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 | ||
885 | static 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 | |||
897 | static 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 | |||
880 | static netdev_tx_t netsec_netdev_start_xmit(struct sk_buff *skb, | 920 | static 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 | ||