Commit 6198f446 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'netpoll-make-sure-napi_list-is-safe-for-RCU-traversal'



Jakub Kicinski says:

====================
netpoll: make sure napi_list is safe for RCU traversal

This series is a follow-up to the fix in commit 96e97bc0 ("net:
disable netpoll on fresh napis"). To avoid any latent race conditions
convert dev->napi_list to a proper RCU list. We need minor restructuring
because it looks like netif_napi_del() used to be idempotent, and
it may be quite hard to track down everyone who depends on that.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 8b40f21b 5251ef82
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -825,9 +825,9 @@ static inline void bnx2x_del_all_napi_cnic(struct bnx2x *bp)
	int i;

	for_each_rx_queue_cnic(bp, i) {
		napi_hash_del(&bnx2x_fp(bp, i, napi));
		netif_napi_del(&bnx2x_fp(bp, i, napi));
		__netif_napi_del(&bnx2x_fp(bp, i, napi));
	}
	synchronize_net();
}

static inline void bnx2x_del_all_napi(struct bnx2x *bp)
@@ -835,9 +835,9 @@ static inline void bnx2x_del_all_napi(struct bnx2x *bp)
	int i;

	for_each_eth_queue(bp, i) {
		napi_hash_del(&bnx2x_fp(bp, i, napi));
		netif_napi_del(&bnx2x_fp(bp, i, napi));
		__netif_napi_del(&bnx2x_fp(bp, i, napi));
	}
	synchronize_net();
}

int bnx2x_set_int_mode(struct bnx2x *bp);
+2 −3
Original line number Diff line number Diff line
@@ -8634,10 +8634,9 @@ static void bnxt_del_napi(struct bnxt *bp)
	for (i = 0; i < bp->cp_nr_rings; i++) {
		struct bnxt_napi *bnapi = bp->bnapi[i];

		napi_hash_del(&bnapi->napi);
		netif_napi_del(&bnapi->napi);
		__netif_napi_del(&bnapi->napi);
	}
	/* We called napi_hash_del() before netif_napi_del(), we need
	/* We called __netif_napi_del(), we need
	 * to respect an RCU grace period before freeing napi structures.
	 */
	synchronize_net();
+7 −5
Original line number Diff line number Diff line
@@ -2529,13 +2529,15 @@ static void enic_dev_deinit(struct enic *enic)
{
	unsigned int i;

	for (i = 0; i < enic->rq_count; i++) {
		napi_hash_del(&enic->napi[i]);
		netif_napi_del(&enic->napi[i]);
	}
	for (i = 0; i < enic->rq_count; i++)
		__netif_napi_del(&enic->napi[i]);

	if (vnic_dev_get_intr_mode(enic->vdev) == VNIC_DEV_INTR_MODE_MSIX)
		for (i = 0; i < enic->wq_count; i++)
			netif_napi_del(&enic->napi[enic_cq_wq(enic, i)]);
			__netif_napi_del(&enic->napi[enic_cq_wq(enic, i)]);

	/* observe RCU grace period after __netif_napi_del() calls */
	synchronize_net();

	enic_free_vnic_resources(enic);
	enic_clear_intr_mode(enic);
+2 −2
Original line number Diff line number Diff line
@@ -1029,10 +1029,10 @@ static void ixgbe_free_q_vector(struct ixgbe_adapter *adapter, int v_idx)
		WRITE_ONCE(adapter->rx_ring[ring->queue_index], NULL);

	adapter->q_vector[v_idx] = NULL;
	napi_hash_del(&q_vector->napi);
	netif_napi_del(&q_vector->napi);
	__netif_napi_del(&q_vector->napi);

	/*
	 * after a call to __netif_napi_del() napi may still be used and
	 * ixgbe_get_stats64() might access the rings on this vector,
	 * we must wait a grace period before freeing it.
	 */
+2 −3
Original line number Diff line number Diff line
@@ -3543,11 +3543,10 @@ static void myri10ge_free_slices(struct myri10ge_priv *mgp)
					  ss->fw_stats, ss->fw_stats_bus);
			ss->fw_stats = NULL;
		}
		napi_hash_del(&ss->napi);
		netif_napi_del(&ss->napi);
		__netif_napi_del(&ss->napi);
	}
	/* Wait till napi structs are no longer used, and then free ss. */
	synchronize_rcu();
	synchronize_net();
	kfree(mgp->ss);
	mgp->ss = NULL;
}
Loading