Skip to content

Commit 7407881

Browse files
author
Paolo Abeni
committed
Merge branch 'net-prevent-deadlocks-and-mis-configuration-with-per-napi-threaded-config'
Jakub Kicinski says: ==================== net: prevent deadlocks and mis-configuration with per-NAPI threaded config Running the test added with a recent fix on a driver with persistent NAPI config leads to a deadlock. The deadlock is fixed by patch 3, patch 2 is I think a more fundamental problem with the way we implemented the config. I hope the fix makes sense, my own thinking is definitely colored by my preference (IOW how the per-queue config RFC was implemented). v1: https://lore.kernel.org/[email protected] ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Paolo Abeni <[email protected]>
2 parents e93f7af + b3fc08a commit 7407881

File tree

4 files changed

+27
-8
lines changed

4 files changed

+27
-8
lines changed

include/linux/netdevice.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2071,6 +2071,8 @@ enum netdev_reg_state {
20712071
* @max_pacing_offload_horizon: max EDT offload horizon in nsec.
20722072
* @napi_config: An array of napi_config structures containing per-NAPI
20732073
* settings.
2074+
* @num_napi_configs: number of allocated NAPI config structs,
2075+
* always >= max(num_rx_queues, num_tx_queues).
20742076
* @gro_flush_timeout: timeout for GRO layer in NAPI
20752077
* @napi_defer_hard_irqs: If not zero, provides a counter that would
20762078
* allow to avoid NIC hard IRQ, on busy queues.
@@ -2482,8 +2484,9 @@ struct net_device {
24822484

24832485
u64 max_pacing_offload_horizon;
24842486
struct napi_config *napi_config;
2485-
unsigned long gro_flush_timeout;
2487+
u32 num_napi_configs;
24862488
u32 napi_defer_hard_irqs;
2489+
unsigned long gro_flush_timeout;
24872490

24882491
/**
24892492
* @up: copy of @state's IFF_UP, but safe to read with just @lock.

net/core/dev.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6999,7 +6999,7 @@ int netif_set_threaded(struct net_device *dev,
69996999
enum netdev_napi_threaded threaded)
70007000
{
70017001
struct napi_struct *napi;
7002-
int err = 0;
7002+
int i, err = 0;
70037003

70047004
netdev_assert_locked_or_invisible(dev);
70057005

@@ -7021,6 +7021,10 @@ int netif_set_threaded(struct net_device *dev,
70217021
list_for_each_entry(napi, &dev->napi_list, dev_list)
70227022
WARN_ON_ONCE(napi_set_threaded(napi, threaded));
70237023

7024+
/* Override the config for all NAPIs even if currently not listed */
7025+
for (i = 0; i < dev->num_napi_configs; i++)
7026+
dev->napi_config[i].threaded = threaded;
7027+
70247028
return err;
70257029
}
70267030

@@ -7353,8 +7357,9 @@ void netif_napi_add_weight_locked(struct net_device *dev,
73537357
* Clear dev->threaded if kthread creation failed so that
73547358
* threaded mode will not be enabled in napi_enable().
73557359
*/
7356-
if (dev->threaded && napi_kthread_create(napi))
7357-
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;
73587363
netif_napi_set_irq_locked(napi, -1);
73597364
}
73607365
EXPORT_SYMBOL(netif_napi_add_weight_locked);
@@ -11873,6 +11878,7 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
1187311878
goto free_all;
1187411879
dev->cfg_pending = dev->cfg;
1187511880

11881+
dev->num_napi_configs = maxqs;
1187611882
napi_config_sz = array_size(maxqs, sizeof(*dev->napi_config));
1187711883
dev->napi_config = kvzalloc(napi_config_sz, GFP_KERNEL_ACCOUNT);
1187811884
if (!dev->napi_config)

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

tools/testing/selftests/drivers/net/napi_threaded.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ def _setup_deferred_cleanup(cfg) -> None:
3535
threaded = cmd(f"cat /sys/class/net/{cfg.ifname}/threaded").stdout
3636
defer(_set_threaded_state, cfg, threaded)
3737

38+
return combined
39+
3840

3941
def enable_dev_threaded_disable_napi_threaded(cfg, nl) -> None:
4042
"""
@@ -49,7 +51,7 @@ def enable_dev_threaded_disable_napi_threaded(cfg, nl) -> None:
4951
napi0_id = napis[0]['id']
5052
napi1_id = napis[1]['id']
5153

52-
_setup_deferred_cleanup(cfg)
54+
qcnt = _setup_deferred_cleanup(cfg)
5355

5456
# set threaded
5557
_set_threaded_state(cfg, 1)
@@ -62,7 +64,7 @@ def enable_dev_threaded_disable_napi_threaded(cfg, nl) -> None:
6264
nl.napi_set({'id': napi1_id, 'threaded': 'disabled'})
6365

6466
cmd(f"ethtool -L {cfg.ifname} combined 1")
65-
cmd(f"ethtool -L {cfg.ifname} combined 2")
67+
cmd(f"ethtool -L {cfg.ifname} combined {qcnt}")
6668
_assert_napi_threaded_enabled(nl, napi0_id)
6769
_assert_napi_threaded_disabled(nl, napi1_id)
6870

@@ -80,7 +82,7 @@ def change_num_queues(cfg, nl) -> None:
8082
napi0_id = napis[0]['id']
8183
napi1_id = napis[1]['id']
8284

83-
_setup_deferred_cleanup(cfg)
85+
qcnt = _setup_deferred_cleanup(cfg)
8486

8587
# set threaded
8688
_set_threaded_state(cfg, 1)
@@ -90,7 +92,7 @@ def change_num_queues(cfg, nl) -> None:
9092
_assert_napi_threaded_enabled(nl, napi1_id)
9193

9294
cmd(f"ethtool -L {cfg.ifname} combined 1")
93-
cmd(f"ethtool -L {cfg.ifname} combined 2")
95+
cmd(f"ethtool -L {cfg.ifname} combined {qcnt}")
9496

9597
# check napi threaded is set for both napis
9698
_assert_napi_threaded_enabled(nl, napi0_id)

0 commit comments

Comments
 (0)