net/ixgbe: Fix concurrency issues between config flow and XSK
[ Upstream commit c0fdccfd226a1424683d3000d9e08384391210a2 ] Use synchronize_rcu to wait until the XSK wakeup function finishes before destroying the resources it uses: 1. ixgbe_down already calls synchronize_rcu after setting __IXGBE_DOWN. 2. After switching the XDP program, call synchronize_rcu to let ixgbe_xsk_wakeup exit before the XDP program is freed. 3. Changing the number of channels brings the interface down. 4. Disabling UMEM sets __IXGBE_TX_DISABLED before closing hardware resources and resetting xsk_umem. Check that bit in ixgbe_xsk_wakeup to avoid using the XDP ring when it's already destroyed. synchronize_rcu is called from ixgbe_txrx_ring_disable. Signed-off-by: Maxim Mikityanskiy <maximmi@mellanox.com> Signed-off-by: Björn Töpel <bjorn.topel@intel.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Link: https://lore.kernel.org/bpf/20191217162023.16011-5-maximmi@mellanox.com Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
4f5954a925
commit
47b957faa9
@ -10248,7 +10248,12 @@ static int ixgbe_xdp_setup(struct net_device *dev, struct bpf_prog *prog)
|
||||
|
||||
/* If transitioning XDP modes reconfigure rings */
|
||||
if (need_reset) {
|
||||
int err = ixgbe_setup_tc(dev, adapter->hw_tcs);
|
||||
int err;
|
||||
|
||||
if (!prog)
|
||||
/* Wait until ndo_xsk_wakeup completes. */
|
||||
synchronize_rcu();
|
||||
err = ixgbe_setup_tc(dev, adapter->hw_tcs);
|
||||
|
||||
if (err) {
|
||||
rcu_assign_pointer(adapter->xdp_prog, old_prog);
|
||||
|
@ -709,10 +709,14 @@ int ixgbe_xsk_wakeup(struct net_device *dev, u32 qid, u32 flags)
|
||||
if (qid >= adapter->num_xdp_queues)
|
||||
return -ENXIO;
|
||||
|
||||
if (!adapter->xdp_ring[qid]->xsk_umem)
|
||||
ring = adapter->xdp_ring[qid];
|
||||
|
||||
if (test_bit(__IXGBE_TX_DISABLED, &ring->state))
|
||||
return -ENETDOWN;
|
||||
|
||||
if (!ring->xsk_umem)
|
||||
return -ENXIO;
|
||||
|
||||
ring = adapter->xdp_ring[qid];
|
||||
if (!napi_if_scheduled_mark_missed(&ring->q_vector->napi)) {
|
||||
u64 eics = BIT_ULL(ring->q_vector->v_idx);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user