]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
fm10k: use software values when checking for Tx hangs in hot path
authorJacob Keller <jacob.e.keller@intel.com>
Thu, 9 Jun 2016 21:56:05 +0000 (14:56 -0700)
committerChuck Anderson <chuck.anderson@oracle.com>
Sun, 26 Feb 2017 06:04:29 +0000 (22:04 -0800)
A previous patch added support to check for hardware Tx pending in the
fm10k_down routine. This support was intended to ensure that we
accurately check what the hardware state is. However, checking for Tx
hangs in this manor during the hotpath results in a large performance
hit. Avoid this by making the hotpath check use the SW counters instead.

Fixes: a0f53cf49cb0 ("fm10k: use actual hardware registers when checking for pending Tx", 2016-06-08)
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Krishneil Singh <Krishneil.k.singh@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Orabug: 25394529
(cherry picked from commit 5b9e4432db038eefcafe2be468e3adaf2edbbe91)
Signed-off-by: Jack Vogel <jack.vogel@oracle.com>
drivers/net/ethernet/intel/fm10k/fm10k.h
drivers/net/ethernet/intel/fm10k/fm10k_main.c
drivers/net/ethernet/intel/fm10k/fm10k_pci.c

index 8ec8bb88d934a093d20ff8fb82ce0e554c19dc5b..52955687a7bfcd68f7b6cdee575ef54f017fb987 100644 (file)
@@ -475,7 +475,7 @@ __be16 fm10k_tx_encap_offload(struct sk_buff *skb);
 netdev_tx_t fm10k_xmit_frame_ring(struct sk_buff *skb,
                                  struct fm10k_ring *tx_ring);
 void fm10k_tx_timeout_reset(struct fm10k_intfc *interface);
-u64 fm10k_get_tx_pending(struct fm10k_ring *ring);
+u64 fm10k_get_tx_pending(struct fm10k_ring *ring, bool in_sw);
 bool fm10k_check_tx_hang(struct fm10k_ring *tx_ring);
 void fm10k_alloc_rx_buffers(struct fm10k_ring *rx_ring, u16 cleaned_count);
 
index 1ffa6872cefe0c01e48351de09634b420f4bdb83..ff3511555256a7cf47068b04884460d6c2a42561 100644 (file)
@@ -1148,13 +1148,24 @@ static u64 fm10k_get_tx_completed(struct fm10k_ring *ring)
        return ring->stats.packets;
 }
 
-u64 fm10k_get_tx_pending(struct fm10k_ring *ring)
+/**
+ * fm10k_get_tx_pending - how many Tx descriptors not processed
+ * @ring: the ring structure
+ * @in_sw: is tx_pending being checked in SW or in HW?
+ */
+u64 fm10k_get_tx_pending(struct fm10k_ring *ring, bool in_sw)
 {
        struct fm10k_intfc *interface = ring->q_vector->interface;
        struct fm10k_hw *hw = &interface->hw;
+       u32 head, tail;
 
-       u32 head = fm10k_read_reg(hw, FM10K_TDH(ring->reg_idx));
-       u32 tail = fm10k_read_reg(hw, FM10K_TDT(ring->reg_idx));
+       if (likely(in_sw)) {
+               head = ring->next_to_clean;
+               tail = ring->next_to_use;
+       } else {
+               head = fm10k_read_reg(hw, FM10K_TDH(ring->reg_idx));
+               tail = fm10k_read_reg(hw, FM10K_TDT(ring->reg_idx));
+       }
 
        return ((head <= tail) ? tail : tail + ring->count) - head;
 }
@@ -1163,7 +1174,7 @@ bool fm10k_check_tx_hang(struct fm10k_ring *tx_ring)
 {
        u32 tx_done = fm10k_get_tx_completed(tx_ring);
        u32 tx_done_old = tx_ring->tx_stats.tx_done_old;
-       u32 tx_pending = fm10k_get_tx_pending(tx_ring);
+       u32 tx_pending = fm10k_get_tx_pending(tx_ring, true);
 
        clear_check_for_tx_hang(tx_ring);
 
index d2eb88a7df7ed613504dcc7b25a5bbd8828bb7a6..713a116314db53926282869e72f6a7afe377858b 100644 (file)
@@ -1786,7 +1786,7 @@ void fm10k_down(struct fm10k_intfc *interface)
 
                /* start checking at the last ring to have pending Tx */
                for (; i < interface->num_tx_queues; i++)
-                       if (fm10k_get_tx_pending(interface->tx_ring[i]))
+                       if (fm10k_get_tx_pending(interface->tx_ring[i], false))
                                break;
 
                /* if all the queues are drained, we can break now */