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

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'use-enum-to-represent-the-napi-threaded-state'

Samiullah Khawaja says:

====================
Use enum to represent the NAPI threaded state

Instead of using 0/1 to represent the NAPI threaded states use enum
(disabled/enabled) to represent the NAPI threaded states.

This patch series is a subset of patches from the following patch series:
https://lore.kernel.org/20250718232052.1266188-1-skhawaja@google.com

The first 3 patches are being sent separately as per the feedback to
replace the usage of 0/1 as NAPI threaded states with enum. See:
https://lore.kernel.org/20250721164856.1d2208e4@kernel.org
====================

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

+95 -54
+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
+1 -1
drivers/net/ethernet/atheros/atl1c/atl1c_main.c
··· 2688 2688 adapter->mii.mdio_write = atl1c_mdio_write; 2689 2689 adapter->mii.phy_id_mask = 0x1f; 2690 2690 adapter->mii.reg_num_mask = MDIO_CTRL_REG_MASK; 2691 - netif_set_threaded(netdev, true); 2691 + netif_threaded_enable(netdev); 2692 2692 for (i = 0; i < adapter->rx_queue_count; ++i) 2693 2693 netif_napi_add(netdev, &adapter->rrd_ring[i].napi, 2694 2694 atl1c_clean_rx);
+1 -1
drivers/net/ethernet/mellanox/mlxsw/pci.c
··· 156 156 } 157 157 strscpy(mlxsw_pci->napi_dev_rx->name, "mlxsw_rx", 158 158 sizeof(mlxsw_pci->napi_dev_rx->name)); 159 - netif_set_threaded(mlxsw_pci->napi_dev_rx, true); 159 + netif_threaded_enable(mlxsw_pci->napi_dev_rx); 160 160 161 161 return 0; 162 162
+1 -1
drivers/net/ethernet/renesas/ravb_main.c
··· 3075 3075 if (info->coalesce_irqs) { 3076 3076 netdev_sw_irq_coalesce_default_on(ndev); 3077 3077 if (num_present_cpus() == 1) 3078 - netif_set_threaded(ndev, true); 3078 + netif_threaded_enable(ndev); 3079 3079 } 3080 3080 3081 3081 /* Network device register */
+1 -1
drivers/net/wireguard/device.c
··· 366 366 if (ret < 0) 367 367 goto err_free_handshake_queue; 368 368 369 - netif_set_threaded(dev, true); 369 + netif_threaded_enable(dev); 370 370 ret = register_netdevice(dev); 371 371 if (ret < 0) 372 372 goto err_uninit_ratelimiter;
+1 -1
drivers/net/wireless/ath/ath10k/snoc.c
··· 936 936 937 937 bitmap_clear(ar_snoc->pending_ce_irqs, 0, CE_COUNT_MAX); 938 938 939 - netif_set_threaded(ar->napi_dev, true); 939 + netif_threaded_enable(ar->napi_dev); 940 940 ath10k_core_napi_enable(ar); 941 941 /* IRQs are left enabled when we restart due to a firmware crash */ 942 942 if (!test_bit(ATH10K_SNOC_FLAG_RECOVERY, &ar_snoc->flags))
+6 -6
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 ··· 589 589 return napi_complete_done(n, 0); 590 590 } 591 591 592 - int netif_set_threaded(struct net_device *dev, bool threaded); 593 - int dev_set_threaded(struct net_device *dev, bool threaded); 592 + void netif_threaded_enable(struct net_device *dev); 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
+6
include/net/gro.h
··· 534 534 gro->rx_count = 0; 535 535 } 536 536 537 + static inline void gro_flush_normal(struct gro_node *gro, bool flush_old) 538 + { 539 + gro_flush(gro, flush_old); 540 + gro_normal_list(gro); 541 + } 542 + 537 543 /* Queue one GRO_NORMAL SKB up for list processing. If batch size exceeded, 538 544 * pass the whole batch up to the stack. 539 545 */
+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,
+1 -2
kernel/bpf/cpumap.c
··· 282 282 * This is equivalent to how NAPI decides whether to perform a full 283 283 * flush. 284 284 */ 285 - gro_flush(&rcpu->gro, !empty && HZ >= 1000); 286 - gro_normal_list(&rcpu->gro); 285 + gro_flush_normal(&rcpu->gro, !empty && HZ >= 1000); 287 286 } 288 287 289 288 static int cpu_map_kthread_run(void *data)
+26 -11
net/core/dev.c
··· 6578 6578 * it, we need to bound somehow the time packets are kept in 6579 6579 * the GRO layer. 6580 6580 */ 6581 - gro_flush(&n->gro, !!timeout); 6582 - gro_normal_list(&n->gro); 6581 + gro_flush_normal(&n->gro, !!timeout); 6583 6582 6584 6583 if (unlikely(!list_empty(&n->poll_list))) { 6585 6584 /* If n->poll_list is not empty, we need to mask irqs */ ··· 6648 6649 } 6649 6650 6650 6651 /* Flush too old packets. If HZ < 1000, flush all packets */ 6651 - gro_flush(&napi->gro, HZ >= 1000); 6652 - gro_normal_list(&napi->gro); 6652 + gro_flush_normal(&napi->gro, HZ >= 1000); 6653 6653 6654 6654 clear_bit(NAPI_STATE_SCHED, &napi->state); 6655 6655 } ··· 6963 6965 napi->thread = NULL; 6964 6966 } 6965 6967 6966 - int napi_set_threaded(struct napi_struct *napi, bool threaded) 6968 + int napi_set_threaded(struct napi_struct *napi, 6969 + enum netdev_napi_threaded threaded) 6967 6970 { 6968 6971 if (threaded) { 6969 6972 if (!napi->thread) { ··· 6989 6990 return 0; 6990 6991 } 6991 6992 6992 - int netif_set_threaded(struct net_device *dev, bool threaded) 6993 + int netif_set_threaded(struct net_device *dev, 6994 + enum netdev_napi_threaded threaded) 6993 6995 { 6994 6996 struct napi_struct *napi; 6995 6997 int err = 0; ··· 7002 7002 if (!napi->thread) { 7003 7003 err = napi_kthread_create(napi); 7004 7004 if (err) { 7005 - threaded = false; 7005 + threaded = NETDEV_NAPI_THREADED_DISABLED; 7006 7006 break; 7007 7007 } 7008 7008 } ··· 7031 7031 7032 7032 return err; 7033 7033 } 7034 - EXPORT_SYMBOL(netif_set_threaded); 7034 + 7035 + /** 7036 + * netif_threaded_enable() - enable threaded NAPIs 7037 + * @dev: net_device instance 7038 + * 7039 + * Enable threaded mode for the NAPI instances of the device. This may be useful 7040 + * for devices where multiple NAPI instances get scheduled by a single 7041 + * interrupt. Threaded NAPI allows moving the NAPI processing to cores other 7042 + * than the core where IRQ is mapped. 7043 + * 7044 + * This function should be called before @dev is registered. 7045 + */ 7046 + void netif_threaded_enable(struct net_device *dev) 7047 + { 7048 + WARN_ON_ONCE(netif_set_threaded(dev, NETDEV_NAPI_THREADED_ENABLED)); 7049 + } 7050 + EXPORT_SYMBOL(netif_threaded_enable); 7035 7051 7036 7052 /** 7037 7053 * netif_queue_set_napi - Associate queue with the napi ··· 7362 7346 * threaded mode will not be enabled in napi_enable(). 7363 7347 */ 7364 7348 if (dev->threaded && napi_kthread_create(napi)) 7365 - dev->threaded = false; 7349 + dev->threaded = NETDEV_NAPI_THREADED_DISABLED; 7366 7350 netif_napi_set_irq_locked(napi, -1); 7367 7351 } 7368 7352 EXPORT_SYMBOL(netif_napi_add_weight_locked); ··· 7531 7515 } 7532 7516 7533 7517 /* Flush too old packets. If HZ < 1000, flush all packets */ 7534 - gro_flush(&n->gro, HZ >= 1000); 7535 - gro_normal_list(&n->gro); 7518 + gro_flush_normal(&n->gro, HZ >= 1000); 7536 7519 7537 7520 /* Some drivers may have called napi_schedule 7538 7521 * prior to exhausting their budget.
+10 -3
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); 328 + 329 + int netif_set_threaded(struct net_device *dev, 330 + enum netdev_napi_threaded threaded); 324 331 325 332 int rps_cpumask_housekeeping(struct cpumask *mask); 326 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: