]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
Revert "ixgbe: get rid of custom busy polling code"
authorJack Vogel <jack.vogel@oracle.com>
Thu, 27 Jul 2017 18:42:28 +0000 (11:42 -0700)
committerJack Vogel <jack.vogel@oracle.com>
Wed, 2 Aug 2017 21:39:59 +0000 (14:39 -0700)
This reverts commit 9244251e4f45dc9a61dd094a5d7ba23bb0285a86. The core napi support is
not in place, we need to keep the driver support or performance suffers.

Orabug: 26494997
Signed-off-by: Jack Vogel <jack.vogel@oracle.com>
Reviewed-by: Shannon Nelson <shannon.nelson@oracle.com>
drivers/net/ethernet/intel/ixgbe/ixgbe.h
drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c

index a37ceaec53826d35b3f993c5713794d4b7f1d591..98cb26ebf6a97795eb4ada71ceb7f041e4a2c50d 100644 (file)
@@ -55,6 +55,9 @@
 
 #include <net/busy_poll.h>
 
+#ifdef CONFIG_NET_RX_BUSY_POLL
+#define BP_EXTENDED_STATS
+#endif
 /* common prefix used by pr_<> macros */
 #undef pr_fmt
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -206,6 +209,11 @@ struct ixgbe_rx_buffer {
 struct ixgbe_queue_stats {
        u64 packets;
        u64 bytes;
+#ifdef BP_EXTENDED_STATS
+       u64 yields;
+       u64 misses;
+       u64 cleaned;
+#endif  /* BP_EXTENDED_STATS */
 };
 
 struct ixgbe_tx_queue_stats {
@@ -405,10 +413,127 @@ struct ixgbe_q_vector {
        struct rcu_head rcu;    /* to avoid race with update stats on free */
        char name[IFNAMSIZ + 9];
 
+#ifdef CONFIG_NET_RX_BUSY_POLL
+       atomic_t state;
+#endif  /* CONFIG_NET_RX_BUSY_POLL */
+
        /* for dynamic allocation of rings associated with this q_vector */
        struct ixgbe_ring ring[0] ____cacheline_internodealigned_in_smp;
 };
 
+#ifdef CONFIG_NET_RX_BUSY_POLL
+enum ixgbe_qv_state_t {
+       IXGBE_QV_STATE_IDLE = 0,
+       IXGBE_QV_STATE_NAPI,
+       IXGBE_QV_STATE_POLL,
+       IXGBE_QV_STATE_DISABLE
+};
+
+static inline void ixgbe_qv_init_lock(struct ixgbe_q_vector *q_vector)
+{
+       /* reset state to idle */
+       atomic_set(&q_vector->state, IXGBE_QV_STATE_IDLE);
+}
+
+/* called from the device poll routine to get ownership of a q_vector */
+static inline bool ixgbe_qv_lock_napi(struct ixgbe_q_vector *q_vector)
+{
+       int rc = atomic_cmpxchg(&q_vector->state, IXGBE_QV_STATE_IDLE,
+                               IXGBE_QV_STATE_NAPI);
+#ifdef BP_EXTENDED_STATS
+       if (rc != IXGBE_QV_STATE_IDLE)
+               q_vector->tx.ring->stats.yields++;
+#endif
+
+       return rc == IXGBE_QV_STATE_IDLE;
+}
+
+/* returns true is someone tried to get the qv while napi had it */
+static inline void ixgbe_qv_unlock_napi(struct ixgbe_q_vector *q_vector)
+{
+       WARN_ON(atomic_read(&q_vector->state) != IXGBE_QV_STATE_NAPI);
+
+       /* flush any outstanding Rx frames */
+       if (q_vector->napi.gro_list)
+               napi_gro_flush(&q_vector->napi, false);
+
+       /* reset state to idle */
+       atomic_set(&q_vector->state, IXGBE_QV_STATE_IDLE);
+}
+
+/* called from ixgbe_low_latency_poll() */
+static inline bool ixgbe_qv_lock_poll(struct ixgbe_q_vector *q_vector)
+{
+       int rc = atomic_cmpxchg(&q_vector->state, IXGBE_QV_STATE_IDLE,
+                               IXGBE_QV_STATE_POLL);
+#ifdef BP_EXTENDED_STATS
+       if (rc != IXGBE_QV_STATE_IDLE)
+               q_vector->rx.ring->stats.yields++;
+#endif
+       return rc == IXGBE_QV_STATE_IDLE;
+}
+
+/* returns true if someone tried to get the qv while it was locked */
+static inline void ixgbe_qv_unlock_poll(struct ixgbe_q_vector *q_vector)
+{
+       WARN_ON(atomic_read(&q_vector->state) != IXGBE_QV_STATE_POLL);
+
+       /* reset state to idle */
+       atomic_set(&q_vector->state, IXGBE_QV_STATE_IDLE);
+}
+
+/* true if a socket is polling, even if it did not get the lock */
+static inline bool ixgbe_qv_busy_polling(struct ixgbe_q_vector *q_vector)
+{
+       return atomic_read(&q_vector->state) == IXGBE_QV_STATE_POLL;
+}
+
+/* false if QV is currently owned */
+static inline bool ixgbe_qv_disable(struct ixgbe_q_vector *q_vector)
+{
+       int rc = atomic_cmpxchg(&q_vector->state, IXGBE_QV_STATE_IDLE,
+                               IXGBE_QV_STATE_DISABLE);
+
+       return rc == IXGBE_QV_STATE_IDLE;
+}
+
+#else /* CONFIG_NET_RX_BUSY_POLL */
+static inline void ixgbe_qv_init_lock(struct ixgbe_q_vector *q_vector)
+{
+}
+
+static inline bool ixgbe_qv_lock_napi(struct ixgbe_q_vector *q_vector)
+{
+       return true;
+}
+
+static inline bool ixgbe_qv_unlock_napi(struct ixgbe_q_vector *q_vector)
+{
+       return false;
+}
+
+static inline bool ixgbe_qv_lock_poll(struct ixgbe_q_vector *q_vector)
+{
+       return false;
+}
+
+static inline bool ixgbe_qv_unlock_poll(struct ixgbe_q_vector *q_vector)
+{
+       return false;
+}
+
+static inline bool ixgbe_qv_busy_polling(struct ixgbe_q_vector *q_vector)
+{
+       return false;
+}
+
+static inline bool ixgbe_qv_disable(struct ixgbe_q_vector *q_vector)
+{
+       return true;
+}
+
+#endif /* CONFIG_NET_RX_BUSY_POLL */
+
 #ifdef CONFIG_IXGBE_HWMON
 
 #define IXGBE_HWMON_TYPE_LOC           0
index 6e14e197a50d208760a1ccd7f5d72df5f9d7803d..1b8cde0f3491c276f096419266d4d116b7c3fff3 100644 (file)
@@ -1195,6 +1195,12 @@ static void ixgbe_get_ethtool_stats(struct net_device *netdev,
                        data[i] = 0;
                        data[i+1] = 0;
                        i += 2;
+#ifdef BP_EXTENDED_STATS
+                       data[i] = 0;
+                       data[i+1] = 0;
+                       data[i+2] = 0;
+                       i += 3;
+#endif
                        continue;
                }
 
@@ -1204,6 +1210,12 @@ static void ixgbe_get_ethtool_stats(struct net_device *netdev,
                        data[i+1] = ring->stats.bytes;
                } while (u64_stats_fetch_retry_irq(&ring->syncp, start));
                i += 2;
+#ifdef BP_EXTENDED_STATS
+               data[i] = ring->stats.yields;
+               data[i+1] = ring->stats.misses;
+               data[i+2] = ring->stats.cleaned;
+               i += 3;
+#endif
        }
        for (j = 0; j < IXGBE_NUM_RX_QUEUES; j++) {
                ring = adapter->rx_ring[j];
@@ -1211,6 +1223,12 @@ static void ixgbe_get_ethtool_stats(struct net_device *netdev,
                        data[i] = 0;
                        data[i+1] = 0;
                        i += 2;
+#ifdef BP_EXTENDED_STATS
+                       data[i] = 0;
+                       data[i+1] = 0;
+                       data[i+2] = 0;
+                       i += 3;
+#endif
                        continue;
                }
 
@@ -1220,6 +1238,12 @@ static void ixgbe_get_ethtool_stats(struct net_device *netdev,
                        data[i+1] = ring->stats.bytes;
                } while (u64_stats_fetch_retry_irq(&ring->syncp, start));
                i += 2;
+#ifdef BP_EXTENDED_STATS
+               data[i] = ring->stats.yields;
+               data[i+1] = ring->stats.misses;
+               data[i+2] = ring->stats.cleaned;
+               i += 3;
+#endif
        }
 
        for (j = 0; j < IXGBE_MAX_PACKET_BUFFERS; j++) {
@@ -1256,12 +1280,28 @@ static void ixgbe_get_strings(struct net_device *netdev, u32 stringset,
                        p += ETH_GSTRING_LEN;
                        sprintf(p, "tx_queue_%u_bytes", i);
                        p += ETH_GSTRING_LEN;
+#ifdef BP_EXTENDED_STATS
+                       sprintf(p, "tx_queue_%u_bp_napi_yield", i);
+                       p += ETH_GSTRING_LEN;
+                       sprintf(p, "tx_queue_%u_bp_misses", i);
+                       p += ETH_GSTRING_LEN;
+                       sprintf(p, "tx_queue_%u_bp_cleaned", i);
+                       p += ETH_GSTRING_LEN;
+#endif /* BP_EXTENDED_STATS */
                }
                for (i = 0; i < IXGBE_NUM_RX_QUEUES; i++) {
                        sprintf(p, "rx_queue_%u_packets", i);
                        p += ETH_GSTRING_LEN;
                        sprintf(p, "rx_queue_%u_bytes", i);
                        p += ETH_GSTRING_LEN;
+#ifdef BP_EXTENDED_STATS
+                       sprintf(p, "rx_queue_%u_bp_poll_yield", i);
+                       p += ETH_GSTRING_LEN;
+                       sprintf(p, "rx_queue_%u_bp_misses", i);
+                       p += ETH_GSTRING_LEN;
+                       sprintf(p, "rx_queue_%u_bp_cleaned", i);
+                       p += ETH_GSTRING_LEN;
+#endif /* BP_EXTENDED_STATS */
                }
                for (i = 0; i < IXGBE_MAX_PACKET_BUFFERS; i++) {
                        sprintf(p, "tx_pb_%u_pxon", i);
index eccba1c05c431ed110adcc6dd2dc2c985ff004db..4ca2dc0749fb1ee648df9bb4854108017ec53cbb 100644 (file)
@@ -854,6 +854,11 @@ static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter,
                       ixgbe_poll, 64);
        napi_hash_add(&q_vector->napi);
 
+#ifdef CONFIG_NET_RX_BUSY_POLL
+       /* initialize busy poll */
+       atomic_set(&q_vector->state, IXGBE_QV_STATE_DISABLE);
+
+#endif
        /* tie q_vector and adapter together */
        adapter->q_vector[v_idx] = q_vector;
        q_vector->adapter = adapter;
index a245d3dbe6dcb1bdee9a189a805f3f09afc7efbb..14ba496f2b704ec2fb0418368480963c24e5d523 100644 (file)
@@ -1729,14 +1729,10 @@ static void ixgbe_process_skb_fields(struct ixgbe_ring *rx_ring,
 static void ixgbe_rx_skb(struct ixgbe_q_vector *q_vector,
                         struct sk_buff *skb)
 {
-#ifdef OLD_CODE
        if (ixgbe_qv_busy_polling(q_vector))
                netif_receive_skb(skb);
        else
                napi_gro_receive(&q_vector->napi, skb);
-#else
-       napi_gro_receive(&q_vector->napi, skb);
-#endif
 }
 
 /**
@@ -2214,6 +2210,40 @@ static int ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
        return total_rx_packets;
 }
 
+#ifdef CONFIG_NET_RX_BUSY_POLL
+/* must be called with local_bh_disable()d */
+static int ixgbe_low_latency_recv(struct napi_struct *napi)
+{
+       struct ixgbe_q_vector *q_vector =
+                       container_of(napi, struct ixgbe_q_vector, napi);
+       struct ixgbe_adapter *adapter = q_vector->adapter;
+       struct ixgbe_ring  *ring;
+       int found = 0;
+
+       if (test_bit(__IXGBE_DOWN, &adapter->state))
+               return LL_FLUSH_FAILED;
+
+       if (!ixgbe_qv_lock_poll(q_vector))
+               return LL_FLUSH_BUSY;
+
+       ixgbe_for_each_ring(ring, q_vector->rx) {
+               found = ixgbe_clean_rx_irq(q_vector, ring, 4);
+#ifdef BP_EXTENDED_STATS
+               if (found)
+                       ring->stats.cleaned += found;
+               else
+                       ring->stats.misses++;
+#endif
+               if (found)
+                       break;
+       }
+
+       ixgbe_qv_unlock_poll(q_vector);
+
+       return found;
+}
+#endif /* CONFIG_NET_RX_BUSY_POLL */
+
 /**
  * ixgbe_configure_msix - Configure MSI-X hardware
  * @adapter: board private structure
@@ -2854,8 +2884,8 @@ int ixgbe_poll(struct napi_struct *napi, int budget)
        ixgbe_for_each_ring(ring, q_vector->tx)
                clean_complete &= !!ixgbe_clean_tx_irq(q_vector, ring);
 
-       /* Exit if we are called by netpoll */
-       if (budget <= 0)
+       /* Exit if we are called by netpoll or busy polling is active */
+       if ((budget <= 0) || !ixgbe_qv_lock_napi(q_vector))
                return budget;
 
        /* attempt to distribute budget to each queue fairly, but don't allow
@@ -2873,6 +2903,7 @@ int ixgbe_poll(struct napi_struct *napi, int budget)
                clean_complete &= (cleaned < per_ring_budget);
        }
 
+       ixgbe_qv_unlock_napi(q_vector);
        /* If all work not completed, return budget and keep polling */
        if (!clean_complete)
                return budget;
@@ -4636,16 +4667,23 @@ static void ixgbe_napi_enable_all(struct ixgbe_adapter *adapter)
 {
        int q_idx;
 
-       for (q_idx = 0; q_idx < adapter->num_q_vectors; q_idx++)
+       for (q_idx = 0; q_idx < adapter->num_q_vectors; q_idx++) {
+               ixgbe_qv_init_lock(adapter->q_vector[q_idx]);
                napi_enable(&adapter->q_vector[q_idx]->napi);
+       }
 }
 
 static void ixgbe_napi_disable_all(struct ixgbe_adapter *adapter)
 {
        int q_idx;
 
-       for (q_idx = 0; q_idx < adapter->num_q_vectors; q_idx++)
+       for (q_idx = 0; q_idx < adapter->num_q_vectors; q_idx++) {
                napi_disable(&adapter->q_vector[q_idx]->napi);
+               while (!ixgbe_qv_disable(adapter->q_vector[q_idx])) {
+                       pr_info("QV %d locked\n", q_idx);
+                       usleep_range(1000, 20000);
+               }
+       }
 }
 
 static void ixgbe_clear_vxlan_port(struct ixgbe_adapter *adapter)
@@ -8936,6 +8974,9 @@ static const struct net_device_ops ixgbe_netdev_ops = {
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller    = ixgbe_netpoll,
 #endif
+#ifdef CONFIG_NET_RX_BUSY_POLL
+       .ndo_busy_poll          = ixgbe_low_latency_recv,
+#endif
 #ifdef IXGBE_FCOE
        .ndo_fcoe_ddp_setup = ixgbe_fcoe_ddp_get,
        .ndo_fcoe_ddp_target = ixgbe_fcoe_ddp_target,