diff options
-rw-r--r-- | drivers/net/ixgbe/ixgbe.h | 1 | ||||
-rw-r--r-- | drivers/net/ixgbe/ixgbe_main.c | 34 |
2 files changed, 25 insertions, 10 deletions
diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index ed8703cfffb7..018e143612b2 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h | |||
@@ -192,6 +192,7 @@ struct ixgbe_ring { | |||
192 | 192 | ||
193 | unsigned int size; /* length in bytes */ | 193 | unsigned int size; /* length in bytes */ |
194 | dma_addr_t dma; /* phys. address of descriptor ring */ | 194 | dma_addr_t dma; /* phys. address of descriptor ring */ |
195 | struct rcu_head rcu; | ||
195 | } ____cacheline_internodealigned_in_smp; | 196 | } ____cacheline_internodealigned_in_smp; |
196 | 197 | ||
197 | enum ixgbe_ring_f_enum { | 198 | enum ixgbe_ring_f_enum { |
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index fbad4d819608..a137f9dbaacd 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c | |||
@@ -4751,6 +4751,11 @@ err_set_interrupt: | |||
4751 | return err; | 4751 | return err; |
4752 | } | 4752 | } |
4753 | 4753 | ||
4754 | static void ring_free_rcu(struct rcu_head *head) | ||
4755 | { | ||
4756 | kfree(container_of(head, struct ixgbe_ring, rcu)); | ||
4757 | } | ||
4758 | |||
4754 | /** | 4759 | /** |
4755 | * ixgbe_clear_interrupt_scheme - Clear the current interrupt scheme settings | 4760 | * ixgbe_clear_interrupt_scheme - Clear the current interrupt scheme settings |
4756 | * @adapter: board private structure to clear interrupt scheme on | 4761 | * @adapter: board private structure to clear interrupt scheme on |
@@ -4767,7 +4772,12 @@ void ixgbe_clear_interrupt_scheme(struct ixgbe_adapter *adapter) | |||
4767 | adapter->tx_ring[i] = NULL; | 4772 | adapter->tx_ring[i] = NULL; |
4768 | } | 4773 | } |
4769 | for (i = 0; i < adapter->num_rx_queues; i++) { | 4774 | for (i = 0; i < adapter->num_rx_queues; i++) { |
4770 | kfree(adapter->rx_ring[i]); | 4775 | struct ixgbe_ring *ring = adapter->rx_ring[i]; |
4776 | |||
4777 | /* ixgbe_get_stats64() might access this ring, we must wait | ||
4778 | * a grace period before freeing it. | ||
4779 | */ | ||
4780 | call_rcu(&ring->rcu, ring_free_rcu); | ||
4771 | adapter->rx_ring[i] = NULL; | 4781 | adapter->rx_ring[i] = NULL; |
4772 | } | 4782 | } |
4773 | 4783 | ||
@@ -6563,20 +6573,23 @@ static struct rtnl_link_stats64 *ixgbe_get_stats64(struct net_device *netdev, | |||
6563 | 6573 | ||
6564 | /* accurate rx/tx bytes/packets stats */ | 6574 | /* accurate rx/tx bytes/packets stats */ |
6565 | dev_txq_stats_fold(netdev, stats); | 6575 | dev_txq_stats_fold(netdev, stats); |
6576 | rcu_read_lock(); | ||
6566 | for (i = 0; i < adapter->num_rx_queues; i++) { | 6577 | for (i = 0; i < adapter->num_rx_queues; i++) { |
6567 | struct ixgbe_ring *ring = adapter->rx_ring[i]; | 6578 | struct ixgbe_ring *ring = ACCESS_ONCE(adapter->rx_ring[i]); |
6568 | u64 bytes, packets; | 6579 | u64 bytes, packets; |
6569 | unsigned int start; | 6580 | unsigned int start; |
6570 | 6581 | ||
6571 | do { | 6582 | if (ring) { |
6572 | start = u64_stats_fetch_begin_bh(&ring->syncp); | 6583 | do { |
6573 | packets = ring->stats.packets; | 6584 | start = u64_stats_fetch_begin_bh(&ring->syncp); |
6574 | bytes = ring->stats.bytes; | 6585 | packets = ring->stats.packets; |
6575 | } while (u64_stats_fetch_retry_bh(&ring->syncp, start)); | 6586 | bytes = ring->stats.bytes; |
6576 | stats->rx_packets += packets; | 6587 | } while (u64_stats_fetch_retry_bh(&ring->syncp, start)); |
6577 | stats->rx_bytes += bytes; | 6588 | stats->rx_packets += packets; |
6589 | stats->rx_bytes += bytes; | ||
6590 | } | ||
6578 | } | 6591 | } |
6579 | 6592 | rcu_read_unlock(); | |
6580 | /* following stats updated by ixgbe_watchdog_task() */ | 6593 | /* following stats updated by ixgbe_watchdog_task() */ |
6581 | stats->multicast = netdev->stats.multicast; | 6594 | stats->multicast = netdev->stats.multicast; |
6582 | stats->rx_errors = netdev->stats.rx_errors; | 6595 | stats->rx_errors = netdev->stats.rx_errors; |
@@ -7282,6 +7295,7 @@ static void __exit ixgbe_exit_module(void) | |||
7282 | dca_unregister_notify(&dca_notifier); | 7295 | dca_unregister_notify(&dca_notifier); |
7283 | #endif | 7296 | #endif |
7284 | pci_unregister_driver(&ixgbe_driver); | 7297 | pci_unregister_driver(&ixgbe_driver); |
7298 | rcu_barrier(); /* Wait for completion of call_rcu()'s */ | ||
7285 | } | 7299 | } |
7286 | 7300 | ||
7287 | #ifdef CONFIG_IXGBE_DCA | 7301 | #ifdef CONFIG_IXGBE_DCA |