mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-10 07:59:42 -04:00
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>
This commit is contained in:
@@ -85,6 +85,10 @@ definitions:
|
||||
name: qstats-scope
|
||||
type: flags
|
||||
entries: [queue]
|
||||
-
|
||||
name: napi-threaded
|
||||
type: enum
|
||||
entries: [disabled, enabled]
|
||||
|
||||
attribute-sets:
|
||||
-
|
||||
@@ -286,11 +290,10 @@ attribute-sets:
|
||||
-
|
||||
name: threaded
|
||||
doc: Whether the NAPI is configured to operate in threaded polling
|
||||
mode. If this is set to 1 then the NAPI context operates in
|
||||
threaded polling mode.
|
||||
type: uint
|
||||
checks:
|
||||
max: 1
|
||||
mode. If this is set to enabled then the NAPI context operates
|
||||
in threaded polling mode.
|
||||
type: u32
|
||||
enum: napi-threaded
|
||||
-
|
||||
name: xsk-info
|
||||
attributes: []
|
||||
|
||||
@@ -68,6 +68,7 @@ unsigned_char addr_assign_type
|
||||
unsigned_char addr_len
|
||||
unsigned_char upper_level
|
||||
unsigned_char lower_level
|
||||
u8 threaded napi_poll(napi_enable,netif_set_threaded)
|
||||
unsigned_short neigh_priv_len
|
||||
unsigned_short padded
|
||||
unsigned_short dev_id
|
||||
@@ -165,7 +166,6 @@ struct sfp_bus* sfp_bus
|
||||
struct lock_class_key* qdisc_tx_busylock
|
||||
bool proto_down
|
||||
unsigned:1 wol_enabled
|
||||
unsigned:1 threaded napi_poll(napi_enable,netif_set_threaded)
|
||||
unsigned_long:1 see_all_hwtstamp_requests
|
||||
unsigned_long:1 change_proto_down
|
||||
unsigned_long:1 netns_immutable
|
||||
|
||||
@@ -2688,7 +2688,7 @@ static int atl1c_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
adapter->mii.mdio_write = atl1c_mdio_write;
|
||||
adapter->mii.phy_id_mask = 0x1f;
|
||||
adapter->mii.reg_num_mask = MDIO_CTRL_REG_MASK;
|
||||
netif_set_threaded(netdev, true);
|
||||
netif_threaded_enable(netdev);
|
||||
for (i = 0; i < adapter->rx_queue_count; ++i)
|
||||
netif_napi_add(netdev, &adapter->rrd_ring[i].napi,
|
||||
atl1c_clean_rx);
|
||||
|
||||
@@ -156,7 +156,7 @@ static int mlxsw_pci_napi_devs_init(struct mlxsw_pci *mlxsw_pci)
|
||||
}
|
||||
strscpy(mlxsw_pci->napi_dev_rx->name, "mlxsw_rx",
|
||||
sizeof(mlxsw_pci->napi_dev_rx->name));
|
||||
netif_set_threaded(mlxsw_pci->napi_dev_rx, true);
|
||||
netif_threaded_enable(mlxsw_pci->napi_dev_rx);
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
@@ -3075,7 +3075,7 @@ static int ravb_probe(struct platform_device *pdev)
|
||||
if (info->coalesce_irqs) {
|
||||
netdev_sw_irq_coalesce_default_on(ndev);
|
||||
if (num_present_cpus() == 1)
|
||||
netif_set_threaded(ndev, true);
|
||||
netif_threaded_enable(ndev);
|
||||
}
|
||||
|
||||
/* Network device register */
|
||||
|
||||
@@ -366,7 +366,7 @@ static int wg_newlink(struct net_device *dev,
|
||||
if (ret < 0)
|
||||
goto err_free_handshake_queue;
|
||||
|
||||
netif_set_threaded(dev, true);
|
||||
netif_threaded_enable(dev);
|
||||
ret = register_netdevice(dev);
|
||||
if (ret < 0)
|
||||
goto err_uninit_ratelimiter;
|
||||
|
||||
@@ -936,7 +936,7 @@ static int ath10k_snoc_hif_start(struct ath10k *ar)
|
||||
|
||||
bitmap_clear(ar_snoc->pending_ce_irqs, 0, CE_COUNT_MAX);
|
||||
|
||||
netif_set_threaded(ar->napi_dev, true);
|
||||
netif_threaded_enable(ar->napi_dev);
|
||||
ath10k_core_napi_enable(ar);
|
||||
/* IRQs are left enabled when we restart due to a firmware crash */
|
||||
if (!test_bit(ATH10K_SNOC_FLAG_RECOVERY, &ar_snoc->flags))
|
||||
|
||||
@@ -369,7 +369,7 @@ struct napi_config {
|
||||
u64 irq_suspend_timeout;
|
||||
u32 defer_hard_irqs;
|
||||
cpumask_t affinity_mask;
|
||||
bool threaded;
|
||||
u8 threaded;
|
||||
unsigned int napi_id;
|
||||
};
|
||||
|
||||
@@ -589,8 +589,9 @@ static inline bool napi_complete(struct napi_struct *n)
|
||||
return napi_complete_done(n, 0);
|
||||
}
|
||||
|
||||
int netif_set_threaded(struct net_device *dev, bool threaded);
|
||||
int dev_set_threaded(struct net_device *dev, bool threaded);
|
||||
void netif_threaded_enable(struct net_device *dev);
|
||||
int dev_set_threaded(struct net_device *dev,
|
||||
enum netdev_napi_threaded threaded);
|
||||
|
||||
void napi_disable(struct napi_struct *n);
|
||||
void napi_disable_locked(struct napi_struct *n);
|
||||
@@ -1872,6 +1873,7 @@ enum netdev_reg_state {
|
||||
* @addr_len: Hardware address length
|
||||
* @upper_level: Maximum depth level of upper devices.
|
||||
* @lower_level: Maximum depth level of lower devices.
|
||||
* @threaded: napi threaded state.
|
||||
* @neigh_priv_len: Used in neigh_alloc()
|
||||
* @dev_id: Used to differentiate devices that share
|
||||
* the same link layer address
|
||||
@@ -2011,8 +2013,6 @@ enum netdev_reg_state {
|
||||
* switch driver and used to set the phys state of the
|
||||
* switch port.
|
||||
*
|
||||
* @threaded: napi threaded mode is enabled
|
||||
*
|
||||
* @irq_affinity_auto: driver wants the core to store and re-assign the IRQ
|
||||
* affinity. Set by netif_enable_irq_affinity(), then
|
||||
* the driver must create a persistent napi by
|
||||
@@ -2248,6 +2248,7 @@ struct net_device {
|
||||
unsigned char addr_len;
|
||||
unsigned char upper_level;
|
||||
unsigned char lower_level;
|
||||
u8 threaded;
|
||||
|
||||
unsigned short neigh_priv_len;
|
||||
unsigned short dev_id;
|
||||
@@ -2429,7 +2430,6 @@ struct net_device {
|
||||
struct sfp_bus *sfp_bus;
|
||||
struct lock_class_key *qdisc_tx_busylock;
|
||||
bool proto_down;
|
||||
bool threaded;
|
||||
bool irq_affinity_auto;
|
||||
bool rx_cpu_rmap_auto;
|
||||
|
||||
|
||||
@@ -534,6 +534,12 @@ static inline void gro_normal_list(struct gro_node *gro)
|
||||
gro->rx_count = 0;
|
||||
}
|
||||
|
||||
static inline void gro_flush_normal(struct gro_node *gro, bool flush_old)
|
||||
{
|
||||
gro_flush(gro, flush_old);
|
||||
gro_normal_list(gro);
|
||||
}
|
||||
|
||||
/* Queue one GRO_NORMAL SKB up for list processing. If batch size exceeded,
|
||||
* pass the whole batch up to the stack.
|
||||
*/
|
||||
|
||||
@@ -77,6 +77,11 @@ enum netdev_qstats_scope {
|
||||
NETDEV_QSTATS_SCOPE_QUEUE = 1,
|
||||
};
|
||||
|
||||
enum netdev_napi_threaded {
|
||||
NETDEV_NAPI_THREADED_DISABLED,
|
||||
NETDEV_NAPI_THREADED_ENABLED,
|
||||
};
|
||||
|
||||
enum {
|
||||
NETDEV_A_DEV_IFINDEX = 1,
|
||||
NETDEV_A_DEV_PAD,
|
||||
|
||||
@@ -282,8 +282,7 @@ static void cpu_map_gro_flush(struct bpf_cpu_map_entry *rcpu, bool empty)
|
||||
* This is equivalent to how NAPI decides whether to perform a full
|
||||
* flush.
|
||||
*/
|
||||
gro_flush(&rcpu->gro, !empty && HZ >= 1000);
|
||||
gro_normal_list(&rcpu->gro);
|
||||
gro_flush_normal(&rcpu->gro, !empty && HZ >= 1000);
|
||||
}
|
||||
|
||||
static int cpu_map_kthread_run(void *data)
|
||||
|
||||
@@ -6578,8 +6578,7 @@ bool napi_complete_done(struct napi_struct *n, int work_done)
|
||||
* it, we need to bound somehow the time packets are kept in
|
||||
* the GRO layer.
|
||||
*/
|
||||
gro_flush(&n->gro, !!timeout);
|
||||
gro_normal_list(&n->gro);
|
||||
gro_flush_normal(&n->gro, !!timeout);
|
||||
|
||||
if (unlikely(!list_empty(&n->poll_list))) {
|
||||
/* If n->poll_list is not empty, we need to mask irqs */
|
||||
@@ -6649,8 +6648,7 @@ static void __busy_poll_stop(struct napi_struct *napi, bool skip_schedule)
|
||||
}
|
||||
|
||||
/* Flush too old packets. If HZ < 1000, flush all packets */
|
||||
gro_flush(&napi->gro, HZ >= 1000);
|
||||
gro_normal_list(&napi->gro);
|
||||
gro_flush_normal(&napi->gro, HZ >= 1000);
|
||||
|
||||
clear_bit(NAPI_STATE_SCHED, &napi->state);
|
||||
}
|
||||
@@ -6965,7 +6963,8 @@ static void napi_stop_kthread(struct napi_struct *napi)
|
||||
napi->thread = NULL;
|
||||
}
|
||||
|
||||
int napi_set_threaded(struct napi_struct *napi, bool threaded)
|
||||
int napi_set_threaded(struct napi_struct *napi,
|
||||
enum netdev_napi_threaded threaded)
|
||||
{
|
||||
if (threaded) {
|
||||
if (!napi->thread) {
|
||||
@@ -6990,7 +6989,8 @@ int napi_set_threaded(struct napi_struct *napi, bool threaded)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int netif_set_threaded(struct net_device *dev, bool threaded)
|
||||
int netif_set_threaded(struct net_device *dev,
|
||||
enum netdev_napi_threaded threaded)
|
||||
{
|
||||
struct napi_struct *napi;
|
||||
int err = 0;
|
||||
@@ -7002,7 +7002,7 @@ int netif_set_threaded(struct net_device *dev, bool threaded)
|
||||
if (!napi->thread) {
|
||||
err = napi_kthread_create(napi);
|
||||
if (err) {
|
||||
threaded = false;
|
||||
threaded = NETDEV_NAPI_THREADED_DISABLED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -7031,7 +7031,23 @@ int netif_set_threaded(struct net_device *dev, bool threaded)
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(netif_set_threaded);
|
||||
|
||||
/**
|
||||
* netif_threaded_enable() - enable threaded NAPIs
|
||||
* @dev: net_device instance
|
||||
*
|
||||
* Enable threaded mode for the NAPI instances of the device. This may be useful
|
||||
* for devices where multiple NAPI instances get scheduled by a single
|
||||
* interrupt. Threaded NAPI allows moving the NAPI processing to cores other
|
||||
* than the core where IRQ is mapped.
|
||||
*
|
||||
* This function should be called before @dev is registered.
|
||||
*/
|
||||
void netif_threaded_enable(struct net_device *dev)
|
||||
{
|
||||
WARN_ON_ONCE(netif_set_threaded(dev, NETDEV_NAPI_THREADED_ENABLED));
|
||||
}
|
||||
EXPORT_SYMBOL(netif_threaded_enable);
|
||||
|
||||
/**
|
||||
* netif_queue_set_napi - Associate queue with the napi
|
||||
@@ -7346,7 +7362,7 @@ void netif_napi_add_weight_locked(struct net_device *dev,
|
||||
* threaded mode will not be enabled in napi_enable().
|
||||
*/
|
||||
if (dev->threaded && napi_kthread_create(napi))
|
||||
dev->threaded = false;
|
||||
dev->threaded = NETDEV_NAPI_THREADED_DISABLED;
|
||||
netif_napi_set_irq_locked(napi, -1);
|
||||
}
|
||||
EXPORT_SYMBOL(netif_napi_add_weight_locked);
|
||||
@@ -7515,8 +7531,7 @@ static int __napi_poll(struct napi_struct *n, bool *repoll)
|
||||
}
|
||||
|
||||
/* Flush too old packets. If HZ < 1000, flush all packets */
|
||||
gro_flush(&n->gro, HZ >= 1000);
|
||||
gro_normal_list(&n->gro);
|
||||
gro_flush_normal(&n->gro, HZ >= 1000);
|
||||
|
||||
/* Some drivers may have called napi_schedule
|
||||
* prior to exhausting their budget.
|
||||
|
||||
@@ -315,12 +315,19 @@ static inline void napi_set_irq_suspend_timeout(struct napi_struct *n,
|
||||
WRITE_ONCE(n->irq_suspend_timeout, timeout);
|
||||
}
|
||||
|
||||
static inline bool napi_get_threaded(struct napi_struct *n)
|
||||
static inline enum netdev_napi_threaded napi_get_threaded(struct napi_struct *n)
|
||||
{
|
||||
return test_bit(NAPI_STATE_THREADED, &n->state);
|
||||
if (test_bit(NAPI_STATE_THREADED, &n->state))
|
||||
return NETDEV_NAPI_THREADED_ENABLED;
|
||||
|
||||
return NETDEV_NAPI_THREADED_DISABLED;
|
||||
}
|
||||
|
||||
int napi_set_threaded(struct napi_struct *n, bool threaded);
|
||||
int napi_set_threaded(struct napi_struct *n,
|
||||
enum netdev_napi_threaded threaded);
|
||||
|
||||
int netif_set_threaded(struct net_device *dev,
|
||||
enum netdev_napi_threaded threaded);
|
||||
|
||||
int rps_cpumask_housekeeping(struct cpumask *mask);
|
||||
|
||||
|
||||
@@ -368,7 +368,8 @@ void netdev_state_change(struct net_device *dev)
|
||||
}
|
||||
EXPORT_SYMBOL(netdev_state_change);
|
||||
|
||||
int dev_set_threaded(struct net_device *dev, bool threaded)
|
||||
int dev_set_threaded(struct net_device *dev,
|
||||
enum netdev_napi_threaded threaded)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@ static const struct nla_policy netdev_napi_set_nl_policy[NETDEV_A_NAPI_THREADED
|
||||
[NETDEV_A_NAPI_DEFER_HARD_IRQS] = NLA_POLICY_FULL_RANGE(NLA_U32, &netdev_a_napi_defer_hard_irqs_range),
|
||||
[NETDEV_A_NAPI_GRO_FLUSH_TIMEOUT] = { .type = NLA_UINT, },
|
||||
[NETDEV_A_NAPI_IRQ_SUSPEND_TIMEOUT] = { .type = NLA_UINT, },
|
||||
[NETDEV_A_NAPI_THREADED] = NLA_POLICY_MAX(NLA_UINT, 1),
|
||||
[NETDEV_A_NAPI_THREADED] = NLA_POLICY_MAX(NLA_U32, 1),
|
||||
};
|
||||
|
||||
/* NETDEV_CMD_BIND_TX - do */
|
||||
|
||||
@@ -333,7 +333,7 @@ netdev_nl_napi_set_config(struct napi_struct *napi, struct genl_info *info)
|
||||
int ret;
|
||||
|
||||
threaded = nla_get_uint(info->attrs[NETDEV_A_NAPI_THREADED]);
|
||||
ret = napi_set_threaded(napi, !!threaded);
|
||||
ret = napi_set_threaded(napi, threaded);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -77,6 +77,11 @@ enum netdev_qstats_scope {
|
||||
NETDEV_QSTATS_SCOPE_QUEUE = 1,
|
||||
};
|
||||
|
||||
enum netdev_napi_threaded {
|
||||
NETDEV_NAPI_THREADED_DISABLED,
|
||||
NETDEV_NAPI_THREADED_ENABLED,
|
||||
};
|
||||
|
||||
enum {
|
||||
NETDEV_A_DEV_IFINDEX = 1,
|
||||
NETDEV_A_DEV_PAD,
|
||||
|
||||
@@ -52,14 +52,14 @@ def napi_set_threaded(nf) -> None:
|
||||
napi1_id = napis[1]['id']
|
||||
|
||||
# set napi threaded and verify
|
||||
nf.napi_set({'id': napi0_id, 'threaded': 1})
|
||||
nf.napi_set({'id': napi0_id, 'threaded': "enabled"})
|
||||
napi0 = nf.napi_get({'id': napi0_id})
|
||||
ksft_eq(napi0['threaded'], 1)
|
||||
ksft_eq(napi0['threaded'], "enabled")
|
||||
ksft_ne(napi0.get('pid'), None)
|
||||
|
||||
# check it is not set for napi1
|
||||
napi1 = nf.napi_get({'id': napi1_id})
|
||||
ksft_eq(napi1['threaded'], 0)
|
||||
ksft_eq(napi1['threaded'], "disabled")
|
||||
ksft_eq(napi1.get('pid'), None)
|
||||
|
||||
ip(f"link set dev {nsim.ifname} down")
|
||||
@@ -67,18 +67,18 @@ def napi_set_threaded(nf) -> None:
|
||||
|
||||
# verify if napi threaded is still set
|
||||
napi0 = nf.napi_get({'id': napi0_id})
|
||||
ksft_eq(napi0['threaded'], 1)
|
||||
ksft_eq(napi0['threaded'], "enabled")
|
||||
ksft_ne(napi0.get('pid'), None)
|
||||
|
||||
# check it is still not set for napi1
|
||||
napi1 = nf.napi_get({'id': napi1_id})
|
||||
ksft_eq(napi1['threaded'], 0)
|
||||
ksft_eq(napi1['threaded'], "disabled")
|
||||
ksft_eq(napi1.get('pid'), None)
|
||||
|
||||
# unset napi threaded and verify
|
||||
nf.napi_set({'id': napi0_id, 'threaded': 0})
|
||||
nf.napi_set({'id': napi0_id, 'threaded': "disabled"})
|
||||
napi0 = nf.napi_get({'id': napi0_id})
|
||||
ksft_eq(napi0['threaded'], 0)
|
||||
ksft_eq(napi0['threaded'], "disabled")
|
||||
ksft_eq(napi0.get('pid'), None)
|
||||
|
||||
# set threaded at device level
|
||||
@@ -86,10 +86,10 @@ def napi_set_threaded(nf) -> None:
|
||||
|
||||
# check napi threaded is set for both napis
|
||||
napi0 = nf.napi_get({'id': napi0_id})
|
||||
ksft_eq(napi0['threaded'], 1)
|
||||
ksft_eq(napi0['threaded'], "enabled")
|
||||
ksft_ne(napi0.get('pid'), None)
|
||||
napi1 = nf.napi_get({'id': napi1_id})
|
||||
ksft_eq(napi1['threaded'], 1)
|
||||
ksft_eq(napi1['threaded'], "enabled")
|
||||
ksft_ne(napi1.get('pid'), None)
|
||||
|
||||
# unset threaded at device level
|
||||
@@ -97,16 +97,16 @@ def napi_set_threaded(nf) -> None:
|
||||
|
||||
# check napi threaded is unset for both napis
|
||||
napi0 = nf.napi_get({'id': napi0_id})
|
||||
ksft_eq(napi0['threaded'], 0)
|
||||
ksft_eq(napi0['threaded'], "disabled")
|
||||
ksft_eq(napi0.get('pid'), None)
|
||||
napi1 = nf.napi_get({'id': napi1_id})
|
||||
ksft_eq(napi1['threaded'], 0)
|
||||
ksft_eq(napi1['threaded'], "disabled")
|
||||
ksft_eq(napi1.get('pid'), None)
|
||||
|
||||
# set napi threaded for napi0
|
||||
nf.napi_set({'id': napi0_id, 'threaded': 1})
|
||||
napi0 = nf.napi_get({'id': napi0_id})
|
||||
ksft_eq(napi0['threaded'], 1)
|
||||
ksft_eq(napi0['threaded'], "enabled")
|
||||
ksft_ne(napi0.get('pid'), None)
|
||||
|
||||
# unset threaded at device level
|
||||
@@ -114,10 +114,10 @@ def napi_set_threaded(nf) -> None:
|
||||
|
||||
# check napi threaded is unset for both napis
|
||||
napi0 = nf.napi_get({'id': napi0_id})
|
||||
ksft_eq(napi0['threaded'], 0)
|
||||
ksft_eq(napi0['threaded'], "disabled")
|
||||
ksft_eq(napi0.get('pid'), None)
|
||||
napi1 = nf.napi_get({'id': napi1_id})
|
||||
ksft_eq(napi1['threaded'], 0)
|
||||
ksft_eq(napi1['threaded'], "disabled")
|
||||
ksft_eq(napi1.get('pid'), None)
|
||||
|
||||
def dev_set_threaded(nf) -> None:
|
||||
@@ -141,10 +141,10 @@ def dev_set_threaded(nf) -> None:
|
||||
|
||||
# check napi threaded is set for both napis
|
||||
napi0 = nf.napi_get({'id': napi0_id})
|
||||
ksft_eq(napi0['threaded'], 1)
|
||||
ksft_eq(napi0['threaded'], "enabled")
|
||||
ksft_ne(napi0.get('pid'), None)
|
||||
napi1 = nf.napi_get({'id': napi1_id})
|
||||
ksft_eq(napi1['threaded'], 1)
|
||||
ksft_eq(napi1['threaded'], "enabled")
|
||||
ksft_ne(napi1.get('pid'), None)
|
||||
|
||||
# unset threaded
|
||||
@@ -152,10 +152,10 @@ def dev_set_threaded(nf) -> None:
|
||||
|
||||
# check napi threaded is unset for both napis
|
||||
napi0 = nf.napi_get({'id': napi0_id})
|
||||
ksft_eq(napi0['threaded'], 0)
|
||||
ksft_eq(napi0['threaded'], "disabled")
|
||||
ksft_eq(napi0.get('pid'), None)
|
||||
napi1 = nf.napi_get({'id': napi1_id})
|
||||
ksft_eq(napi1['threaded'], 0)
|
||||
ksft_eq(napi1['threaded'], "disabled")
|
||||
ksft_eq(napi1.get('pid'), None)
|
||||
|
||||
def nsim_rxq_reset_down(nf) -> None:
|
||||
|
||||
Reference in New Issue
Block a user