Skip to content

Commit b3fc08a

Browse files
kuba-mooPaolo Abeni
authored andcommitted
net: prevent deadlocks when enabling NAPIs with mixed kthread config
The following order of calls currently deadlocks if: - device has threaded=1; and - NAPI has persistent config with threaded=0. netif_napi_add_weight_config() dev->threaded == 1 napi_kthread_create() napi_enable() napi_restore_config() napi_set_threaded(0) napi_stop_kthread() while (NAPIF_STATE_SCHED) msleep(20) We deadlock because disabled NAPI has STATE_SCHED set. Creating a thread in netif_napi_add() just to destroy it in napi_disable() is fairly ugly in the first place. Let's read both the device config and the NAPI config in netif_napi_add(). Fixes: e6d7626 ("net: Update threaded state in napi config in netif_set_threaded") Signed-off-by: Jakub Kicinski <[email protected]> Reviewed-by: Joe Damato <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Paolo Abeni <[email protected]>
1 parent ccba9f6 commit b3fc08a

File tree

2 files changed

+11
-2
lines changed

2 files changed

+11
-2
lines changed

net/core/dev.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7357,8 +7357,9 @@ void netif_napi_add_weight_locked(struct net_device *dev,
73577357
* Clear dev->threaded if kthread creation failed so that
73587358
* threaded mode will not be enabled in napi_enable().
73597359
*/
7360-
if (dev->threaded && napi_kthread_create(napi))
7361-
dev->threaded = NETDEV_NAPI_THREADED_DISABLED;
7360+
if (napi_get_threaded_config(dev, napi))
7361+
if (napi_kthread_create(napi))
7362+
dev->threaded = NETDEV_NAPI_THREADED_DISABLED;
73627363
netif_napi_set_irq_locked(napi, -1);
73637364
}
73647365
EXPORT_SYMBOL(netif_napi_add_weight_locked);

net/core/dev.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,14 @@ static inline enum netdev_napi_threaded napi_get_threaded(struct napi_struct *n)
323323
return NETDEV_NAPI_THREADED_DISABLED;
324324
}
325325

326+
static inline enum netdev_napi_threaded
327+
napi_get_threaded_config(struct net_device *dev, struct napi_struct *n)
328+
{
329+
if (n->config)
330+
return n->config->threaded;
331+
return dev->threaded;
332+
}
333+
326334
int napi_set_threaded(struct napi_struct *n,
327335
enum netdev_napi_threaded threaded);
328336

0 commit comments

Comments
 (0)