Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e421eb90 authored by Ciara Loftus's avatar Ciara Loftus Committed by Greg Kroah-Hartman
Browse files

ixgbe: protect ring accesses with READ- and WRITE_ONCE



[ Upstream commit f140ad9fe2ae16f385f8fe4dc9cf67bb4c51d794 ]

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: default avatarCiara Loftus <ciara.loftus@intel.com>
Tested-by: default avatarAndrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent ee4846b0
Loading
Loading
Loading
Loading
+6 −6
Original line number Original line Diff line number Diff line
@@ -923,7 +923,7 @@ static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter,
		ring->queue_index = txr_idx;
		ring->queue_index = txr_idx;


		/* assign ring to adapter */
		/* assign ring to adapter */
		adapter->tx_ring[txr_idx] = ring;
		WRITE_ONCE(adapter->tx_ring[txr_idx], ring);


		/* update count and index */
		/* update count and index */
		txr_count--;
		txr_count--;
@@ -950,7 +950,7 @@ static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter,
		set_ring_xdp(ring);
		set_ring_xdp(ring);


		/* assign ring to adapter */
		/* assign ring to adapter */
		adapter->xdp_ring[xdp_idx] = ring;
		WRITE_ONCE(adapter->xdp_ring[xdp_idx], ring);


		/* update count and index */
		/* update count and index */
		xdp_count--;
		xdp_count--;
@@ -993,7 +993,7 @@ static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter,
		ring->queue_index = rxr_idx;
		ring->queue_index = rxr_idx;


		/* assign ring to adapter */
		/* assign ring to adapter */
		adapter->rx_ring[rxr_idx] = ring;
		WRITE_ONCE(adapter->rx_ring[rxr_idx], ring);


		/* update count and index */
		/* update count and index */
		rxr_count--;
		rxr_count--;
@@ -1022,13 +1022,13 @@ static void ixgbe_free_q_vector(struct ixgbe_adapter *adapter, int v_idx)


	ixgbe_for_each_ring(ring, q_vector->tx) {
	ixgbe_for_each_ring(ring, q_vector->tx) {
		if (ring_is_xdp(ring))
		if (ring_is_xdp(ring))
			adapter->xdp_ring[ring->queue_index] = NULL;
			WRITE_ONCE(adapter->xdp_ring[ring->queue_index], NULL);
		else
		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)
	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;
	adapter->q_vector[v_idx] = NULL;
	napi_hash_del(&q_vector->napi);
	napi_hash_del(&q_vector->napi);
+11 −3
Original line number Original line Diff line number Diff line
@@ -7005,7 +7005,10 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter)
	}
	}


	for (i = 0; i < adapter->num_rx_queues; i++) {
	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;
		non_eop_descs += rx_ring->rx_stats.non_eop_descs;
		alloc_rx_page += rx_ring->rx_stats.alloc_rx_page;
		alloc_rx_page += rx_ring->rx_stats.alloc_rx_page;
		alloc_rx_page_failed += rx_ring->rx_stats.alloc_rx_page_failed;
		alloc_rx_page_failed += rx_ring->rx_stats.alloc_rx_page_failed;
@@ -7026,15 +7029,20 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter)
	packets = 0;
	packets = 0;
	/* gather some stats to the adapter struct that are per queue */
	/* gather some stats to the adapter struct that are per queue */
	for (i = 0; i < adapter->num_tx_queues; i++) {
	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;
		restart_queue += tx_ring->tx_stats.restart_queue;
		tx_busy += tx_ring->tx_stats.tx_busy;
		tx_busy += tx_ring->tx_stats.tx_busy;
		bytes += tx_ring->stats.bytes;
		bytes += tx_ring->stats.bytes;
		packets += tx_ring->stats.packets;
		packets += tx_ring->stats.packets;
	}
	}
	for (i = 0; i < adapter->num_xdp_queues; i++) {
	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;
		restart_queue += xdp_ring->tx_stats.restart_queue;
		tx_busy += xdp_ring->tx_stats.tx_busy;
		tx_busy += xdp_ring->tx_stats.tx_busy;
		bytes += xdp_ring->stats.bytes;
		bytes += xdp_ring->stats.bytes;