]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
fm10k: prevent multiple threads updating statistics
authorJacob Keller <jacob.e.keller@intel.com>
Tue, 7 Jun 2016 23:08:45 +0000 (16:08 -0700)
committerChuck Anderson <chuck.anderson@oracle.com>
Sun, 26 Feb 2017 06:04:17 +0000 (22:04 -0800)
Also prevent updating stats while the interface is down. If we're
already updating stats, just return doing nothing. When we take the
device down, block stat updates until we come back up. This ensures that
we avoid tearing down rings when we're updating statistics, and prevents
updating statistics until we're up.

We can't re-use the __FM10K_DOWN for this because it wouldn't prevent
multiple threads from accessing statistics. Neither does it prevent the
case where we start updating stats and then start going down in another
thread.

The fm10k_get_stats64 is except from this, because it has a completely
different flow which does not suffer from the same issues as
fm10k_update_stats might.

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 9d73edee5900baff47887b36e9b97f45a7d13b6d)
Signed-off-by: Jack Vogel <jack.vogel@oracle.com>
drivers/net/ethernet/intel/fm10k/fm10k.h
drivers/net/ethernet/intel/fm10k/fm10k_pci.c

index 8f4d5172640bfea98de56b7d3b4f9cbb15cc550c..58393b23f92426af1627d48bfa8e769706658f05 100644 (file)
@@ -379,6 +379,7 @@ enum fm10k_state_t {
        __FM10K_SERVICE_DISABLE,
        __FM10K_MBX_LOCK,
        __FM10K_LINK_DOWN,
+       __FM10K_UPDATING_STATS,
 };
 
 static inline void fm10k_mbx_lock(struct fm10k_intfc *interface)
index 7eb41417ec225224df1ed85b35eb3e11aa381737..818f2be39b474e8bb08ec9134382fda6c4b0234a 100644 (file)
@@ -375,6 +375,10 @@ void fm10k_update_stats(struct fm10k_intfc *interface)
        u64 bytes, pkts;
        int i;
 
+       /* ensure only one thread updates stats at a time */
+       if (test_and_set_bit(__FM10K_UPDATING_STATS, &interface->state))
+               return;
+
        /* do not allow stats update via service task for next second */
        interface->next_stats_update = jiffies + HZ;
 
@@ -452,6 +456,8 @@ void fm10k_update_stats(struct fm10k_intfc *interface)
        /* Fill out the OS statistics structure */
        net_stats->rx_errors = rx_errors;
        net_stats->rx_dropped = interface->stats.nodesc_drop.count;
+
+       clear_bit(__FM10K_UPDATING_STATS, &interface->state);
 }
 
 /**
@@ -1659,6 +1665,9 @@ void fm10k_up(struct fm10k_intfc *interface)
        /* configure interrupts */
        hw->mac.ops.update_int_moderator(hw);
 
+       /* enable statistics capture again */
+       clear_bit(__FM10K_UPDATING_STATS, &interface->state);
+
        /* clear down bit to indicate we are ready to go */
        clear_bit(__FM10K_DOWN, &interface->state);
 
@@ -1716,6 +1725,10 @@ void fm10k_down(struct fm10k_intfc *interface)
        /* capture stats one last time before stopping interface */
        fm10k_update_stats(interface);
 
+       /* prevent updating statistics while we're down */
+       while (test_and_set_bit(__FM10K_UPDATING_STATS, &interface->state))
+               usleep_range(1000, 2000);
+
        /* Disable DMA engine for Tx/Rx */
        err = hw->mac.ops.stop_hw(hw);
        if (err)
@@ -1853,6 +1866,7 @@ static int fm10k_sw_init(struct fm10k_intfc *interface,
 
        /* Start off interface as being down */
        set_bit(__FM10K_DOWN, &interface->state);
+       set_bit(__FM10K_UPDATING_STATS, &interface->state);
 
        return 0;
 }