Commit 5198d545 authored by Jakub Kicinski's avatar Jakub Kicinski Committed by David S. Miller
Browse files

net: remove napi_hash_del() from driver-facing API



We allow drivers to call napi_hash_del() before calling
netif_napi_del() to batch RCU grace periods. This makes
the API asymmetric and leaks internal implementation details.
Soon we will want the grace period to protect more than just
the NAPI hash table.

Restructure the API and have drivers call a new function -
__netif_napi_del() if they want to take care of RCU waits.

Note that only core was checking the return status from
napi_hash_del() so the new helper does not report if the
NAPI was actually deleted.

Some notes on driver oddness:
 - veth observed the grace period before calling netif_napi_del()
   but that should not matter
 - myri10ge observed normal RCU flavor
 - bnx2x and enic did not actually observe the grace period
   (unless they did so implicitly)
 - virtio_net and enic only unhashed Rx NAPIs

The last two points seem to indicate that the calls to
napi_hash_del() were a left over rather than an optimization.
Regardless, it's easy enough to correct them.

This patch may introduce extra synchronize_net() calls for
interfaces which set NAPI_STATE_NO_BUSY_POLL and depend on
free_netdev() to call netif_napi_del(). This seems inevitable
since we want to use RCU for netpoll dev->napi_list traversal,
and almost no drivers set IFF_DISABLE_NETPOLL.

Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8b40f21b
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