Commit d5c8f0e4 authored by Erni Sri Satya Vennela's avatar Erni Sri Satya Vennela Committed by Paolo Abeni
Browse files

net: mana: Fix potential deadlocks in mana napi ops



When net_shaper_ops are enabled for MANA, netdev_ops_lock
becomes active.

MANA VF setup/teardown by netvsc follows this call chain:

netvsc_vf_setup()
        dev_change_flags()
		...
         __dev_open() OR __dev_close()

dev_change_flags() holds the netdev mutex via netdev_lock_ops.

Meanwhile, mana_create_txq() and mana_create_rxq() in mana_open()
path call NAPI APIs (netif_napi_add_tx(), netif_napi_add_weight(),
napi_enable()), which also try to acquire the same lock, risking
deadlock.

Similarly in the teardown path (mana_close()), netif_napi_disable()
and netif_napi_del(), contend for the same lock.

Switch to the _locked variants of these APIs to avoid deadlocks
when the netdev_ops_lock is held.

Fixes: d4c22ec6 ("net: hold netdev instance lock during ndo_open/ndo_stop")
Signed-off-by: default avatarErni Sri Satya Vennela <ernis@linux.microsoft.com>
Reviewed-by: default avatarHaiyang Zhang <haiyangz@microsoft.com>
Reviewed-by: default avatarShradha Gupta <shradhagupta@linux.microsoft.com>
Reviewed-by: default avatarSaurabh Singh Sengar <ssengar@linux.microsoft.com>
Reviewed-by: default avatarLong Li <longli@microsoft.com>
Link: https://patch.msgid.link/1750144656-2021-2-git-send-email-ernis@linux.microsoft.com


Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent d3623dd5
Loading
Loading
Loading
Loading
+19 −9
Original line number Diff line number Diff line
@@ -1912,8 +1912,10 @@ static void mana_destroy_txq(struct mana_port_context *apc)
		napi = &apc->tx_qp[i].tx_cq.napi;
		if (apc->tx_qp[i].txq.napi_initialized) {
			napi_synchronize(napi);
			napi_disable(napi);
			netif_napi_del(napi);
			netdev_lock_ops_to_full(napi->dev);
			napi_disable_locked(napi);
			netif_napi_del_locked(napi);
			netdev_unlock_full_to_ops(napi->dev);
			apc->tx_qp[i].txq.napi_initialized = false;
		}
		mana_destroy_wq_obj(apc, GDMA_SQ, apc->tx_qp[i].tx_object);
@@ -2065,8 +2067,11 @@ static int mana_create_txq(struct mana_port_context *apc,

		mana_create_txq_debugfs(apc, i);

		netif_napi_add_tx(net, &cq->napi, mana_poll);
		napi_enable(&cq->napi);
		set_bit(NAPI_STATE_NO_BUSY_POLL, &cq->napi.state);
		netdev_lock_ops_to_full(net);
		netif_napi_add_locked(net, &cq->napi, mana_poll);
		napi_enable_locked(&cq->napi);
		netdev_unlock_full_to_ops(net);
		txq->napi_initialized = true;

		mana_gd_ring_cq(cq->gdma_cq, SET_ARM_BIT);
@@ -2102,9 +2107,10 @@ static void mana_destroy_rxq(struct mana_port_context *apc,
	if (napi_initialized) {
		napi_synchronize(napi);

		napi_disable(napi);

		netif_napi_del(napi);
		netdev_lock_ops_to_full(napi->dev);
		napi_disable_locked(napi);
		netif_napi_del_locked(napi);
		netdev_unlock_full_to_ops(napi->dev);
	}
	xdp_rxq_info_unreg(&rxq->xdp_rxq);

@@ -2355,14 +2361,18 @@ static struct mana_rxq *mana_create_rxq(struct mana_port_context *apc,

	gc->cq_table[cq->gdma_id] = cq->gdma_cq;

	netif_napi_add_weight(ndev, &cq->napi, mana_poll, 1);
	netdev_lock_ops_to_full(ndev);
	netif_napi_add_weight_locked(ndev, &cq->napi, mana_poll, 1);
	netdev_unlock_full_to_ops(ndev);

	WARN_ON(xdp_rxq_info_reg(&rxq->xdp_rxq, ndev, rxq_idx,
				 cq->napi.napi_id));
	WARN_ON(xdp_rxq_info_reg_mem_model(&rxq->xdp_rxq, MEM_TYPE_PAGE_POOL,
					   rxq->page_pool));

	napi_enable(&cq->napi);
	netdev_lock_ops_to_full(ndev);
	napi_enable_locked(&cq->napi);
	netdev_unlock_full_to_ops(ndev);

	mana_gd_ring_cq(cq->gdma_cq, SET_ARM_BIT);
out: