ixgb: Maybe stop TX if not enough free descriptors
authorJesse Brandeburg <jesse.brandeburg@intel.com>
Sat, 6 Jan 2007 17:51:38 +0000 (09:51 -0800)
committerAuke Kok <juke-jan.h.kok@intel.com>
Sat, 6 Jan 2007 17:51:38 +0000 (09:51 -0800)
A similar patch to commit 65c7973fa5b46b024f38be208aa477e8daf9a603
but now for ixgb.

Cc: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Signed-off-by: Auke Kok <auke-jan.h.kok@intel.com>
drivers/net/ixgb/ixgb.h
drivers/net/ixgb/ixgb_ethtool.c
drivers/net/ixgb/ixgb_main.c

index 50ffe90..f4aba43 100644 (file)
@@ -171,6 +171,7 @@ struct ixgb_adapter {
 
        /* TX */
        struct ixgb_desc_ring tx_ring ____cacheline_aligned_in_smp;
+       unsigned int restart_queue;
        unsigned long timeo_start;
        uint32_t tx_cmd_type;
        uint64_t hw_csum_tx_good;
index cd22523..82c044d 100644 (file)
@@ -79,6 +79,7 @@ static struct ixgb_stats ixgb_gstrings_stats[] = {
        {"tx_window_errors", IXGB_STAT(net_stats.tx_window_errors)},
        {"tx_deferred_ok", IXGB_STAT(stats.dc)},
        {"tx_timeout_count", IXGB_STAT(tx_timeout_count) },
+       {"tx_restart_queue", IXGB_STAT(restart_queue) },
        {"rx_long_length_errors", IXGB_STAT(stats.roc)},
        {"rx_short_length_errors", IXGB_STAT(stats.ruc)},
 #ifdef NETIF_F_TSO
index 70ac9d4..16317b5 100644 (file)
@@ -1411,6 +1411,37 @@ ixgb_tx_queue(struct ixgb_adapter *adapter, int count, int vlan_id,int tx_flags)
        IXGB_WRITE_REG(&adapter->hw, TDT, i);
 }
 
+static int __ixgb_maybe_stop_tx(struct net_device *netdev, int size)
+{
+       struct ixgb_adapter *adapter = netdev_priv(netdev);
+       struct ixgb_desc_ring *tx_ring = &adapter->tx_ring;
+
+       netif_stop_queue(netdev);
+       /* Herbert's original patch had:
+        *  smp_mb__after_netif_stop_queue();
+        * but since that doesn't exist yet, just open code it. */
+       smp_mb();
+
+       /* We need to check again in a case another CPU has just
+        * made room available. */
+       if (likely(IXGB_DESC_UNUSED(tx_ring) < size))
+               return -EBUSY;
+
+       /* A reprieve! */
+       netif_start_queue(netdev);
+       ++adapter->restart_queue;
+       return 0;
+}
+
+static int ixgb_maybe_stop_tx(struct net_device *netdev,
+                              struct ixgb_desc_ring *tx_ring, int size)
+{
+       if (likely(IXGB_DESC_UNUSED(tx_ring) >= size))
+               return 0;
+       return __ixgb_maybe_stop_tx(netdev, size);
+}
+
+
 /* Tx Descriptors needed, worst case */
 #define TXD_USE_COUNT(S) (((S) >> IXGB_MAX_TXD_PWR) + \
                         (((S) & (IXGB_MAX_DATA_PER_TXD - 1)) ? 1 : 0))
@@ -1444,7 +1475,8 @@ ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        spin_lock_irqsave(&adapter->tx_lock, flags);
 #endif
 
-       if(unlikely(IXGB_DESC_UNUSED(&adapter->tx_ring) < DESC_NEEDED)) {
+       if (unlikely(ixgb_maybe_stop_tx(netdev, &adapter->tx_ring,
+                     DESC_NEEDED))) {
                netif_stop_queue(netdev);
                spin_unlock_irqrestore(&adapter->tx_lock, flags);
                return NETDEV_TX_BUSY;
@@ -1482,8 +1514,7 @@ ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 
 #ifdef NETIF_F_LLTX
        /* Make sure there is space in the ring for the next send. */
-       if(unlikely(IXGB_DESC_UNUSED(&adapter->tx_ring) < DESC_NEEDED))
-               netif_stop_queue(netdev);
+       ixgb_maybe_stop_tx(netdev, &adapter->tx_ring, DESC_NEEDED);
 
        spin_unlock_irqrestore(&adapter->tx_lock, flags);