lkml.org 
[lkml]   [2020]   [Jul]   [14]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.4 018/109] ixgbe: protect ring accesses with READ- and WRITE_ONCE
    Date
    From: Ciara Loftus <ciara.loftus@intel.com>

    [ 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: Ciara Loftus <ciara.loftus@intel.com>
    Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
    Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c | 12 ++++++------
    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 cc3196ae5aea8..636e6e840afa2 100644
    --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
    +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
    @@ -923,7 +923,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--;
    @@ -950,7 +950,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--;
    @@ -993,7 +993,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--;
    @@ -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) {
    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 edaa0bffa5c35..5336bfcd2d701 100644
    --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
    +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
    @@ -7064,7 +7064,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;
    @@ -7085,15 +7088,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;
    --
    2.25.1


    \
     
     \ /
      Last update: 2020-07-14 21:09    [W:9.572 / U:0.036 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site