Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: define an enum for the napi threaded state

Instead of using '0' and '1' for napi threaded state use an enum with
'disabled' and 'enabled' states.

Tested:
./tools/testing/selftests/net/nl_netdev.py
TAP version 13
1..7
ok 1 nl_netdev.empty_check
ok 2 nl_netdev.lo_check
ok 3 nl_netdev.page_pool_check
ok 4 nl_netdev.napi_list_check
ok 5 nl_netdev.dev_set_threaded
ok 6 nl_netdev.napi_set_threaded
ok 7 nl_netdev.nsim_rxq_reset_down
# Totals: pass:7 fail:0 xfail:0 xpass:0 skip:0 error:0

Signed-off-by: Samiullah Khawaja <skhawaja@google.com>
Link: https://patch.msgid.link/20250723013031.2911384-4-skhawaja@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Samiullah Khawaja and committed by
Jakub Kicinski
8e7583a4 78afdada

+62 -41
+8 -5
Documentation/netlink/specs/netdev.yaml
··· 85 85 name: qstats-scope 86 86 type: flags 87 87 entries: [queue] 88 + - 89 + name: napi-threaded 90 + type: enum 91 + entries: [disabled, enabled] 88 92 89 93 attribute-sets: 90 94 - ··· 290 286 - 291 287 name: threaded 292 288 doc: Whether the NAPI is configured to operate in threaded polling 293 - mode. If this is set to 1 then the NAPI context operates in 294 - threaded polling mode. 295 - type: uint 296 - checks: 297 - max: 1 289 + mode. If this is set to enabled then the NAPI context operates 290 + in threaded polling mode. 291 + type: u32 292 + enum: napi-threaded 298 293 - 299 294 name: xsk-info 300 295 attributes: []
+1 -1
Documentation/networking/net_cachelines/net_device.rst
··· 68 68 unsigned_char addr_len 69 69 unsigned_char upper_level 70 70 unsigned_char lower_level 71 + u8 threaded napi_poll(napi_enable,netif_set_threaded) 71 72 unsigned_short neigh_priv_len 72 73 unsigned_short padded 73 74 unsigned_short dev_id ··· 166 165 struct lock_class_key* qdisc_tx_busylock 167 166 bool proto_down 168 167 unsigned:1 wol_enabled 169 - unsigned:1 threaded napi_poll(napi_enable,netif_set_threaded) 170 168 unsigned_long:1 see_all_hwtstamp_requests 171 169 unsigned_long:1 change_proto_down 172 170 unsigned_long:1 netns_immutable
+5 -5
include/linux/netdevice.h
··· 369 369 u64 irq_suspend_timeout; 370 370 u32 defer_hard_irqs; 371 371 cpumask_t affinity_mask; 372 - bool threaded; 372 + u8 threaded; 373 373 unsigned int napi_id; 374 374 }; 375 375 ··· 590 590 } 591 591 592 592 void netif_threaded_enable(struct net_device *dev); 593 - int dev_set_threaded(struct net_device *dev, bool threaded); 593 + int dev_set_threaded(struct net_device *dev, 594 + enum netdev_napi_threaded threaded); 594 595 595 596 void napi_disable(struct napi_struct *n); 596 597 void napi_disable_locked(struct napi_struct *n); ··· 1873 1872 * @addr_len: Hardware address length 1874 1873 * @upper_level: Maximum depth level of upper devices. 1875 1874 * @lower_level: Maximum depth level of lower devices. 1875 + * @threaded: napi threaded state. 1876 1876 * @neigh_priv_len: Used in neigh_alloc() 1877 1877 * @dev_id: Used to differentiate devices that share 1878 1878 * the same link layer address ··· 2012 2010 * @proto_down: protocol port state information can be sent to the 2013 2011 * switch driver and used to set the phys state of the 2014 2012 * switch port. 2015 - * 2016 - * @threaded: napi threaded mode is enabled 2017 2013 * 2018 2014 * @irq_affinity_auto: driver wants the core to store and re-assign the IRQ 2019 2015 * affinity. Set by netif_enable_irq_affinity(), then ··· 2248 2248 unsigned char addr_len; 2249 2249 unsigned char upper_level; 2250 2250 unsigned char lower_level; 2251 + u8 threaded; 2251 2252 2252 2253 unsigned short neigh_priv_len; 2253 2254 unsigned short dev_id; ··· 2430 2429 struct sfp_bus *sfp_bus; 2431 2430 struct lock_class_key *qdisc_tx_busylock; 2432 2431 bool proto_down; 2433 - bool threaded; 2434 2432 bool irq_affinity_auto; 2435 2433 bool rx_cpu_rmap_auto; 2436 2434
+5
include/uapi/linux/netdev.h
··· 77 77 NETDEV_QSTATS_SCOPE_QUEUE = 1, 78 78 }; 79 79 80 + enum netdev_napi_threaded { 81 + NETDEV_NAPI_THREADED_DISABLED, 82 + NETDEV_NAPI_THREADED_ENABLED, 83 + }; 84 + 80 85 enum { 81 86 NETDEV_A_DEV_IFINDEX = 1, 82 87 NETDEV_A_DEV_PAD,
+7 -5
net/core/dev.c
··· 6963 6963 napi->thread = NULL; 6964 6964 } 6965 6965 6966 - int napi_set_threaded(struct napi_struct *napi, bool threaded) 6966 + int napi_set_threaded(struct napi_struct *napi, 6967 + enum netdev_napi_threaded threaded) 6967 6968 { 6968 6969 if (threaded) { 6969 6970 if (!napi->thread) { ··· 6989 6988 return 0; 6990 6989 } 6991 6990 6992 - int netif_set_threaded(struct net_device *dev, bool threaded) 6991 + int netif_set_threaded(struct net_device *dev, 6992 + enum netdev_napi_threaded threaded) 6993 6993 { 6994 6994 struct napi_struct *napi; 6995 6995 int err = 0; ··· 7002 7000 if (!napi->thread) { 7003 7001 err = napi_kthread_create(napi); 7004 7002 if (err) { 7005 - threaded = false; 7003 + threaded = NETDEV_NAPI_THREADED_DISABLED; 7006 7004 break; 7007 7005 } 7008 7006 } ··· 7045 7043 */ 7046 7044 void netif_threaded_enable(struct net_device *dev) 7047 7045 { 7048 - WARN_ON_ONCE(netif_set_threaded(dev, true)); 7046 + WARN_ON_ONCE(netif_set_threaded(dev, NETDEV_NAPI_THREADED_ENABLED)); 7049 7047 } 7050 7048 EXPORT_SYMBOL(netif_threaded_enable); 7051 7049 ··· 7362 7360 * threaded mode will not be enabled in napi_enable(). 7363 7361 */ 7364 7362 if (dev->threaded && napi_kthread_create(napi)) 7365 - dev->threaded = false; 7363 + dev->threaded = NETDEV_NAPI_THREADED_DISABLED; 7366 7364 netif_napi_set_irq_locked(napi, -1); 7367 7365 } 7368 7366 EXPORT_SYMBOL(netif_napi_add_weight_locked);
+9 -4
net/core/dev.h
··· 315 315 WRITE_ONCE(n->irq_suspend_timeout, timeout); 316 316 } 317 317 318 - static inline bool napi_get_threaded(struct napi_struct *n) 318 + static inline enum netdev_napi_threaded napi_get_threaded(struct napi_struct *n) 319 319 { 320 - return test_bit(NAPI_STATE_THREADED, &n->state); 320 + if (test_bit(NAPI_STATE_THREADED, &n->state)) 321 + return NETDEV_NAPI_THREADED_ENABLED; 322 + 323 + return NETDEV_NAPI_THREADED_DISABLED; 321 324 } 322 325 323 - int napi_set_threaded(struct napi_struct *n, bool threaded); 326 + int napi_set_threaded(struct napi_struct *n, 327 + enum netdev_napi_threaded threaded); 324 328 325 - int netif_set_threaded(struct net_device *dev, bool threaded); 329 + int netif_set_threaded(struct net_device *dev, 330 + enum netdev_napi_threaded threaded); 326 331 327 332 int rps_cpumask_housekeeping(struct cpumask *mask); 328 333
+2 -1
net/core/dev_api.c
··· 368 368 } 369 369 EXPORT_SYMBOL(netdev_state_change); 370 370 371 - int dev_set_threaded(struct net_device *dev, bool threaded) 371 + int dev_set_threaded(struct net_device *dev, 372 + enum netdev_napi_threaded threaded) 372 373 { 373 374 int ret; 374 375
+1 -1
net/core/netdev-genl-gen.c
··· 97 97 [NETDEV_A_NAPI_DEFER_HARD_IRQS] = NLA_POLICY_FULL_RANGE(NLA_U32, &netdev_a_napi_defer_hard_irqs_range), 98 98 [NETDEV_A_NAPI_GRO_FLUSH_TIMEOUT] = { .type = NLA_UINT, }, 99 99 [NETDEV_A_NAPI_IRQ_SUSPEND_TIMEOUT] = { .type = NLA_UINT, }, 100 - [NETDEV_A_NAPI_THREADED] = NLA_POLICY_MAX(NLA_UINT, 1), 100 + [NETDEV_A_NAPI_THREADED] = NLA_POLICY_MAX(NLA_U32, 1), 101 101 }; 102 102 103 103 /* NETDEV_CMD_BIND_TX - do */
+1 -1
net/core/netdev-genl.c
··· 333 333 int ret; 334 334 335 335 threaded = nla_get_uint(info->attrs[NETDEV_A_NAPI_THREADED]); 336 - ret = napi_set_threaded(napi, !!threaded); 336 + ret = napi_set_threaded(napi, threaded); 337 337 if (ret) 338 338 return ret; 339 339 }
+5
tools/include/uapi/linux/netdev.h
··· 77 77 NETDEV_QSTATS_SCOPE_QUEUE = 1, 78 78 }; 79 79 80 + enum netdev_napi_threaded { 81 + NETDEV_NAPI_THREADED_DISABLED, 82 + NETDEV_NAPI_THREADED_ENABLED, 83 + }; 84 + 80 85 enum { 81 86 NETDEV_A_DEV_IFINDEX = 1, 82 87 NETDEV_A_DEV_PAD,
+18 -18
tools/testing/selftests/net/nl_netdev.py
··· 52 52 napi1_id = napis[1]['id'] 53 53 54 54 # set napi threaded and verify 55 - nf.napi_set({'id': napi0_id, 'threaded': 1}) 55 + nf.napi_set({'id': napi0_id, 'threaded': "enabled"}) 56 56 napi0 = nf.napi_get({'id': napi0_id}) 57 - ksft_eq(napi0['threaded'], 1) 57 + ksft_eq(napi0['threaded'], "enabled") 58 58 ksft_ne(napi0.get('pid'), None) 59 59 60 60 # check it is not set for napi1 61 61 napi1 = nf.napi_get({'id': napi1_id}) 62 - ksft_eq(napi1['threaded'], 0) 62 + ksft_eq(napi1['threaded'], "disabled") 63 63 ksft_eq(napi1.get('pid'), None) 64 64 65 65 ip(f"link set dev {nsim.ifname} down") ··· 67 67 68 68 # verify if napi threaded is still set 69 69 napi0 = nf.napi_get({'id': napi0_id}) 70 - ksft_eq(napi0['threaded'], 1) 70 + ksft_eq(napi0['threaded'], "enabled") 71 71 ksft_ne(napi0.get('pid'), None) 72 72 73 73 # check it is still not set for napi1 74 74 napi1 = nf.napi_get({'id': napi1_id}) 75 - ksft_eq(napi1['threaded'], 0) 75 + ksft_eq(napi1['threaded'], "disabled") 76 76 ksft_eq(napi1.get('pid'), None) 77 77 78 78 # unset napi threaded and verify 79 - nf.napi_set({'id': napi0_id, 'threaded': 0}) 79 + nf.napi_set({'id': napi0_id, 'threaded': "disabled"}) 80 80 napi0 = nf.napi_get({'id': napi0_id}) 81 - ksft_eq(napi0['threaded'], 0) 81 + ksft_eq(napi0['threaded'], "disabled") 82 82 ksft_eq(napi0.get('pid'), None) 83 83 84 84 # set threaded at device level ··· 86 86 87 87 # check napi threaded is set for both napis 88 88 napi0 = nf.napi_get({'id': napi0_id}) 89 - ksft_eq(napi0['threaded'], 1) 89 + ksft_eq(napi0['threaded'], "enabled") 90 90 ksft_ne(napi0.get('pid'), None) 91 91 napi1 = nf.napi_get({'id': napi1_id}) 92 - ksft_eq(napi1['threaded'], 1) 92 + ksft_eq(napi1['threaded'], "enabled") 93 93 ksft_ne(napi1.get('pid'), None) 94 94 95 95 # unset threaded at device level ··· 97 97 98 98 # check napi threaded is unset for both napis 99 99 napi0 = nf.napi_get({'id': napi0_id}) 100 - ksft_eq(napi0['threaded'], 0) 100 + ksft_eq(napi0['threaded'], "disabled") 101 101 ksft_eq(napi0.get('pid'), None) 102 102 napi1 = nf.napi_get({'id': napi1_id}) 103 - ksft_eq(napi1['threaded'], 0) 103 + ksft_eq(napi1['threaded'], "disabled") 104 104 ksft_eq(napi1.get('pid'), None) 105 105 106 106 # set napi threaded for napi0 107 107 nf.napi_set({'id': napi0_id, 'threaded': 1}) 108 108 napi0 = nf.napi_get({'id': napi0_id}) 109 - ksft_eq(napi0['threaded'], 1) 109 + ksft_eq(napi0['threaded'], "enabled") 110 110 ksft_ne(napi0.get('pid'), None) 111 111 112 112 # unset threaded at device level ··· 114 114 115 115 # check napi threaded is unset for both napis 116 116 napi0 = nf.napi_get({'id': napi0_id}) 117 - ksft_eq(napi0['threaded'], 0) 117 + ksft_eq(napi0['threaded'], "disabled") 118 118 ksft_eq(napi0.get('pid'), None) 119 119 napi1 = nf.napi_get({'id': napi1_id}) 120 - ksft_eq(napi1['threaded'], 0) 120 + ksft_eq(napi1['threaded'], "disabled") 121 121 ksft_eq(napi1.get('pid'), None) 122 122 123 123 def dev_set_threaded(nf) -> None: ··· 141 141 142 142 # check napi threaded is set for both napis 143 143 napi0 = nf.napi_get({'id': napi0_id}) 144 - ksft_eq(napi0['threaded'], 1) 144 + ksft_eq(napi0['threaded'], "enabled") 145 145 ksft_ne(napi0.get('pid'), None) 146 146 napi1 = nf.napi_get({'id': napi1_id}) 147 - ksft_eq(napi1['threaded'], 1) 147 + ksft_eq(napi1['threaded'], "enabled") 148 148 ksft_ne(napi1.get('pid'), None) 149 149 150 150 # unset threaded ··· 152 152 153 153 # check napi threaded is unset for both napis 154 154 napi0 = nf.napi_get({'id': napi0_id}) 155 - ksft_eq(napi0['threaded'], 0) 155 + ksft_eq(napi0['threaded'], "disabled") 156 156 ksft_eq(napi0.get('pid'), None) 157 157 napi1 = nf.napi_get({'id': napi1_id}) 158 - ksft_eq(napi1['threaded'], 0) 158 + ksft_eq(napi1['threaded'], "disabled") 159 159 ksft_eq(napi1.get('pid'), None) 160 160 161 161 def nsim_rxq_reset_down(nf) -> None: