diff options
| author | Ciara Loftus <ciara.loftus@intel.com> | 2020-06-09 13:19:43 +0000 | 
|---|---|---|
| committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2020-06-18 22:30:04 -0700 | 
| commit | f140ad9fe2ae16f385f8fe4dc9cf67bb4c51d794 (patch) | |
| tree | f44c113db08ef954f7a0fa52b94a172fb9fbdf3c | |
| parent | 0ad6f6e767ec2f613418cbc7ebe5ec4c35af540c (diff) | |
ixgbe: protect ring accesses with READ- and WRITE_ONCE
READ_ONCE should be used when reading rings prior to accessing the
statistics pointer. Introduce this as well as the corresponding WRITE_ONCE
usage when allocating and freeing the rings, to ensure protected access.
Signed-off-by: Ciara Loftus <ciara.loftus@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
| -rw-r--r-- | drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c | 12 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 14 | 
2 files changed, 17 insertions, 9 deletions
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c index fd9f5d41b594..2e35c5706cf1 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c @@ -921,7 +921,7 @@ static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter,  		ring->queue_index = txr_idx;  		/* assign ring to adapter */ -		adapter->tx_ring[txr_idx] = ring; +		WRITE_ONCE(adapter->tx_ring[txr_idx], ring);  		/* update count and index */  		txr_count--; @@ -948,7 +948,7 @@ static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter,  		set_ring_xdp(ring);  		/* assign ring to adapter */ -		adapter->xdp_ring[xdp_idx] = ring; +		WRITE_ONCE(adapter->xdp_ring[xdp_idx], ring);  		/* update count and index */  		xdp_count--; @@ -991,7 +991,7 @@ static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter,  		ring->queue_index = rxr_idx;  		/* assign ring to adapter */ -		adapter->rx_ring[rxr_idx] = ring; +		WRITE_ONCE(adapter->rx_ring[rxr_idx], ring);  		/* update count and index */  		rxr_count--; @@ -1020,13 +1020,13 @@ static void ixgbe_free_q_vector(struct ixgbe_adapter *adapter, int v_idx)  	ixgbe_for_each_ring(ring, q_vector->tx) {  		if (ring_is_xdp(ring)) -			adapter->xdp_ring[ring->queue_index] = NULL; +			WRITE_ONCE(adapter->xdp_ring[ring->queue_index], NULL);  		else -			adapter->tx_ring[ring->queue_index] = NULL; +			WRITE_ONCE(adapter->tx_ring[ring->queue_index], NULL);  	}  	ixgbe_for_each_ring(ring, q_vector->rx) -		adapter->rx_ring[ring->queue_index] = NULL; +		WRITE_ONCE(adapter->rx_ring[ring->queue_index], NULL);  	adapter->q_vector[v_idx] = NULL;  	napi_hash_del(&q_vector->napi); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index f162b8b8f345..97a423ecf808 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -7051,7 +7051,10 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter)  	}  	for (i = 0; i < adapter->num_rx_queues; i++) { -		struct ixgbe_ring *rx_ring = adapter->rx_ring[i]; +		struct ixgbe_ring *rx_ring = READ_ONCE(adapter->rx_ring[i]); + +		if (!rx_ring) +			continue;  		non_eop_descs += rx_ring->rx_stats.non_eop_descs;  		alloc_rx_page += rx_ring->rx_stats.alloc_rx_page;  		alloc_rx_page_failed += rx_ring->rx_stats.alloc_rx_page_failed; @@ -7072,15 +7075,20 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter)  	packets = 0;  	/* gather some stats to the adapter struct that are per queue */  	for (i = 0; i < adapter->num_tx_queues; i++) { -		struct ixgbe_ring *tx_ring = adapter->tx_ring[i]; +		struct ixgbe_ring *tx_ring = READ_ONCE(adapter->tx_ring[i]); + +		if (!tx_ring) +			continue;  		restart_queue += tx_ring->tx_stats.restart_queue;  		tx_busy += tx_ring->tx_stats.tx_busy;  		bytes += tx_ring->stats.bytes;  		packets += tx_ring->stats.packets;  	}  	for (i = 0; i < adapter->num_xdp_queues; i++) { -		struct ixgbe_ring *xdp_ring = adapter->xdp_ring[i]; +		struct ixgbe_ring *xdp_ring = READ_ONCE(adapter->xdp_ring[i]); +		if (!xdp_ring) +			continue;  		restart_queue += xdp_ring->tx_stats.restart_queue;  		tx_busy += xdp_ring->tx_stats.tx_busy;  		bytes += xdp_ring->stats.bytes;  | 
