Commit ca8d0fa7 authored by Daniel Borkmann's avatar Daniel Borkmann
Browse files

Merge branch 'bpf-fix-xsk-wakeup'



Maxim Mikityanskiy says:

====================
This series addresses the issue described in the commit message of the
first patch: lack of synchronization between XSK wakeup and destroying
the resources used by XSK wakeup. The idea is similar to napi_synchronize.
The series contains fixes for the drivers that implement XSK.

v2 incorporates changes suggested by Björn:

1. Call synchronize_rcu in Intel drivers only if the XDP program is
   being unloaded.
2. Don't forget rcu_read_lock when wakeup is called from xsk_poll.
3. Use xs->zc as the condition to call ndo_xsk_wakeup.
====================

Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
parents e4730423 c0fdccfd
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1152,7 +1152,7 @@ void i40e_set_fec_in_flags(u8 fec_cfg, u32 *flags);

static inline bool i40e_enabled_xdp_vsi(struct i40e_vsi *vsi)
{
	return !!vsi->xdp_prog;
	return !!READ_ONCE(vsi->xdp_prog);
}

int i40e_create_queue_channel(struct i40e_vsi *vsi, struct i40e_channel *ch);
+7 −3
Original line number Diff line number Diff line
@@ -6823,8 +6823,8 @@ void i40e_down(struct i40e_vsi *vsi)
	for (i = 0; i < vsi->num_queue_pairs; i++) {
		i40e_clean_tx_ring(vsi->tx_rings[i]);
		if (i40e_enabled_xdp_vsi(vsi)) {
			/* Make sure that in-progress ndo_xdp_xmit
			 * calls are completed.
			/* Make sure that in-progress ndo_xdp_xmit and
			 * ndo_xsk_wakeup calls are completed.
			 */
			synchronize_rcu();
			i40e_clean_tx_ring(vsi->xdp_rings[i]);
@@ -12546,8 +12546,12 @@ static int i40e_xdp_setup(struct i40e_vsi *vsi,

	old_prog = xchg(&vsi->xdp_prog, prog);

	if (need_reset)
	if (need_reset) {
		if (!prog)
			/* Wait until ndo_xsk_wakeup completes. */
			synchronize_rcu();
		i40e_reset_and_rebuild(pf, true, true);
	}

	for (i = 0; i < vsi->num_queue_pairs; i++)
		WRITE_ONCE(vsi->rx_rings[i]->xdp_prog, vsi->xdp_prog);
+4 −0
Original line number Diff line number Diff line
@@ -787,8 +787,12 @@ int i40e_xsk_wakeup(struct net_device *dev, u32 queue_id, u32 flags)
{
	struct i40e_netdev_priv *np = netdev_priv(dev);
	struct i40e_vsi *vsi = np->vsi;
	struct i40e_pf *pf = vsi->back;
	struct i40e_ring *ring;

	if (test_bit(__I40E_CONFIG_BUSY, pf->state))
		return -ENETDOWN;

	if (test_bit(__I40E_VSI_DOWN, vsi->state))
		return -ENETDOWN;

+6 −1
Original line number Diff line number Diff line
@@ -10261,7 +10261,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);
+6 −2
Original line number Diff line number Diff line
@@ -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