net: Add napi_struct parameter irq_suspend_timeout

Add a per-NAPI IRQ suspension parameter, which can be get/set with
netdev-genl.

This patch doesn't change any behavior but prepares the code for other
changes in the following commits which use irq_suspend_timeout as a
timeout for IRQ suspension.

Signed-off-by: Martin Karsten <mkarsten@uwaterloo.ca>
Co-developed-by: Joe Damato <jdamato@fastly.com>
Signed-off-by: Joe Damato <jdamato@fastly.com>
Tested-by: Joe Damato <jdamato@fastly.com>
Tested-by: Martin Karsten <mkarsten@uwaterloo.ca>
Acked-by: Stanislav Fomichev <sdf@fomichev.me>
Reviewed-by: Sridhar Samudrala <sridhar.samudrala@intel.com>
Link: https://patch.msgid.link/20241109050245.191288-2-jdamato@fastly.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Martin Karsten 2024-11-09 05:02:31 +00:00 committed by Jakub Kicinski
parent f0fe51a043
commit 5dc51ec86d
8 changed files with 53 additions and 2 deletions

View File

@ -263,6 +263,11 @@ attribute-sets:
the end of a NAPI cycle. This may add receive latency in exchange the end of a NAPI cycle. This may add receive latency in exchange
for reducing the number of frames processed by the network stack. for reducing the number of frames processed by the network stack.
type: uint type: uint
-
name: irq-suspend-timeout
doc: The timeout, in nanoseconds, of how long to suspend irq
processing, if event polling finds events
type: uint
- -
name: queue name: queue
attributes: attributes:
@ -653,6 +658,7 @@ operations:
- pid - pid
- defer-hard-irqs - defer-hard-irqs
- gro-flush-timeout - gro-flush-timeout
- irq-suspend-timeout
dump: dump:
request: request:
attributes: attributes:
@ -704,6 +710,7 @@ operations:
- id - id
- defer-hard-irqs - defer-hard-irqs
- gro-flush-timeout - gro-flush-timeout
- irq-suspend-timeout
kernel-family: kernel-family:
headers: [ "linux/list.h"] headers: [ "linux/list.h"]

View File

@ -348,6 +348,7 @@ struct gro_list {
*/ */
struct napi_config { struct napi_config {
u64 gro_flush_timeout; u64 gro_flush_timeout;
u64 irq_suspend_timeout;
u32 defer_hard_irqs; u32 defer_hard_irqs;
unsigned int napi_id; unsigned int napi_id;
}; };
@ -384,6 +385,7 @@ struct napi_struct {
struct hrtimer timer; struct hrtimer timer;
struct task_struct *thread; struct task_struct *thread;
unsigned long gro_flush_timeout; unsigned long gro_flush_timeout;
unsigned long irq_suspend_timeout;
u32 defer_hard_irqs; u32 defer_hard_irqs;
/* control-path-only fields follow */ /* control-path-only fields follow */
struct list_head dev_list; struct list_head dev_list;

View File

@ -124,6 +124,7 @@ enum {
NETDEV_A_NAPI_PID, NETDEV_A_NAPI_PID,
NETDEV_A_NAPI_DEFER_HARD_IRQS, NETDEV_A_NAPI_DEFER_HARD_IRQS,
NETDEV_A_NAPI_GRO_FLUSH_TIMEOUT, NETDEV_A_NAPI_GRO_FLUSH_TIMEOUT,
NETDEV_A_NAPI_IRQ_SUSPEND_TIMEOUT,
__NETDEV_A_NAPI_MAX, __NETDEV_A_NAPI_MAX,
NETDEV_A_NAPI_MAX = (__NETDEV_A_NAPI_MAX - 1) NETDEV_A_NAPI_MAX = (__NETDEV_A_NAPI_MAX - 1)

View File

@ -6666,6 +6666,7 @@ static void napi_restore_config(struct napi_struct *n)
{ {
n->defer_hard_irqs = n->config->defer_hard_irqs; n->defer_hard_irqs = n->config->defer_hard_irqs;
n->gro_flush_timeout = n->config->gro_flush_timeout; n->gro_flush_timeout = n->config->gro_flush_timeout;
n->irq_suspend_timeout = n->config->irq_suspend_timeout;
/* a NAPI ID might be stored in the config, if so use it. if not, use /* a NAPI ID might be stored in the config, if so use it. if not, use
* napi_hash_add to generate one for us. It will be saved to the config * napi_hash_add to generate one for us. It will be saved to the config
* in napi_disable. * in napi_disable.
@ -6680,6 +6681,7 @@ static void napi_save_config(struct napi_struct *n)
{ {
n->config->defer_hard_irqs = n->defer_hard_irqs; n->config->defer_hard_irqs = n->defer_hard_irqs;
n->config->gro_flush_timeout = n->gro_flush_timeout; n->config->gro_flush_timeout = n->gro_flush_timeout;
n->config->irq_suspend_timeout = n->irq_suspend_timeout;
n->config->napi_id = n->napi_id; n->config->napi_id = n->napi_id;
napi_hash_del(n); napi_hash_del(n);
} }

View File

@ -236,6 +236,31 @@ static inline void netdev_set_gro_flush_timeout(struct net_device *netdev,
netdev->napi_config[i].gro_flush_timeout = timeout; netdev->napi_config[i].gro_flush_timeout = timeout;
} }
/**
* napi_get_irq_suspend_timeout - get the irq_suspend_timeout
* @n: napi struct to get the irq_suspend_timeout from
*
* Return: the per-NAPI value of the irq_suspend_timeout field.
*/
static inline unsigned long
napi_get_irq_suspend_timeout(const struct napi_struct *n)
{
return READ_ONCE(n->irq_suspend_timeout);
}
/**
* napi_set_irq_suspend_timeout - set the irq_suspend_timeout for a napi
* @n: napi struct to set the irq_suspend_timeout
* @timeout: timeout value to set
*
* napi_set_irq_suspend_timeout sets the per-NAPI irq_suspend_timeout
*/
static inline void napi_set_irq_suspend_timeout(struct napi_struct *n,
unsigned long timeout)
{
WRITE_ONCE(n->irq_suspend_timeout, timeout);
}
int rps_cpumask_housekeeping(struct cpumask *mask); int rps_cpumask_housekeeping(struct cpumask *mask);
#if defined(CONFIG_DEBUG_NET) && defined(CONFIG_BPF_SYSCALL) #if defined(CONFIG_DEBUG_NET) && defined(CONFIG_BPF_SYSCALL)

View File

@ -92,10 +92,11 @@ static const struct nla_policy netdev_bind_rx_nl_policy[NETDEV_A_DMABUF_FD + 1]
}; };
/* NETDEV_CMD_NAPI_SET - do */ /* NETDEV_CMD_NAPI_SET - do */
static const struct nla_policy netdev_napi_set_nl_policy[NETDEV_A_NAPI_GRO_FLUSH_TIMEOUT + 1] = { static const struct nla_policy netdev_napi_set_nl_policy[NETDEV_A_NAPI_IRQ_SUSPEND_TIMEOUT + 1] = {
[NETDEV_A_NAPI_ID] = { .type = NLA_U32, }, [NETDEV_A_NAPI_ID] = { .type = NLA_U32, },
[NETDEV_A_NAPI_DEFER_HARD_IRQS] = NLA_POLICY_FULL_RANGE(NLA_U32, &netdev_a_napi_defer_hard_irqs_range), [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_GRO_FLUSH_TIMEOUT] = { .type = NLA_UINT, },
[NETDEV_A_NAPI_IRQ_SUSPEND_TIMEOUT] = { .type = NLA_UINT, },
}; };
/* Ops table for netdev */ /* Ops table for netdev */
@ -186,7 +187,7 @@ static const struct genl_split_ops netdev_nl_ops[] = {
.cmd = NETDEV_CMD_NAPI_SET, .cmd = NETDEV_CMD_NAPI_SET,
.doit = netdev_nl_napi_set_doit, .doit = netdev_nl_napi_set_doit,
.policy = netdev_napi_set_nl_policy, .policy = netdev_napi_set_nl_policy,
.maxattr = NETDEV_A_NAPI_GRO_FLUSH_TIMEOUT, .maxattr = NETDEV_A_NAPI_IRQ_SUSPEND_TIMEOUT,
.flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
}, },
}; };

View File

@ -161,6 +161,7 @@ static int
netdev_nl_napi_fill_one(struct sk_buff *rsp, struct napi_struct *napi, netdev_nl_napi_fill_one(struct sk_buff *rsp, struct napi_struct *napi,
const struct genl_info *info) const struct genl_info *info)
{ {
unsigned long irq_suspend_timeout;
unsigned long gro_flush_timeout; unsigned long gro_flush_timeout;
u32 napi_defer_hard_irqs; u32 napi_defer_hard_irqs;
void *hdr; void *hdr;
@ -196,6 +197,11 @@ netdev_nl_napi_fill_one(struct sk_buff *rsp, struct napi_struct *napi,
napi_defer_hard_irqs)) napi_defer_hard_irqs))
goto nla_put_failure; goto nla_put_failure;
irq_suspend_timeout = napi_get_irq_suspend_timeout(napi);
if (nla_put_uint(rsp, NETDEV_A_NAPI_IRQ_SUSPEND_TIMEOUT,
irq_suspend_timeout))
goto nla_put_failure;
gro_flush_timeout = napi_get_gro_flush_timeout(napi); gro_flush_timeout = napi_get_gro_flush_timeout(napi);
if (nla_put_uint(rsp, NETDEV_A_NAPI_GRO_FLUSH_TIMEOUT, if (nla_put_uint(rsp, NETDEV_A_NAPI_GRO_FLUSH_TIMEOUT,
gro_flush_timeout)) gro_flush_timeout))
@ -306,6 +312,7 @@ int netdev_nl_napi_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
static int static int
netdev_nl_napi_set_config(struct napi_struct *napi, struct genl_info *info) netdev_nl_napi_set_config(struct napi_struct *napi, struct genl_info *info)
{ {
u64 irq_suspend_timeout = 0;
u64 gro_flush_timeout = 0; u64 gro_flush_timeout = 0;
u32 defer = 0; u32 defer = 0;
@ -314,6 +321,11 @@ netdev_nl_napi_set_config(struct napi_struct *napi, struct genl_info *info)
napi_set_defer_hard_irqs(napi, defer); napi_set_defer_hard_irqs(napi, defer);
} }
if (info->attrs[NETDEV_A_NAPI_IRQ_SUSPEND_TIMEOUT]) {
irq_suspend_timeout = nla_get_uint(info->attrs[NETDEV_A_NAPI_IRQ_SUSPEND_TIMEOUT]);
napi_set_irq_suspend_timeout(napi, irq_suspend_timeout);
}
if (info->attrs[NETDEV_A_NAPI_GRO_FLUSH_TIMEOUT]) { if (info->attrs[NETDEV_A_NAPI_GRO_FLUSH_TIMEOUT]) {
gro_flush_timeout = nla_get_uint(info->attrs[NETDEV_A_NAPI_GRO_FLUSH_TIMEOUT]); gro_flush_timeout = nla_get_uint(info->attrs[NETDEV_A_NAPI_GRO_FLUSH_TIMEOUT]);
napi_set_gro_flush_timeout(napi, gro_flush_timeout); napi_set_gro_flush_timeout(napi, gro_flush_timeout);

View File

@ -124,6 +124,7 @@ enum {
NETDEV_A_NAPI_PID, NETDEV_A_NAPI_PID,
NETDEV_A_NAPI_DEFER_HARD_IRQS, NETDEV_A_NAPI_DEFER_HARD_IRQS,
NETDEV_A_NAPI_GRO_FLUSH_TIMEOUT, NETDEV_A_NAPI_GRO_FLUSH_TIMEOUT,
NETDEV_A_NAPI_IRQ_SUSPEND_TIMEOUT,
__NETDEV_A_NAPI_MAX, __NETDEV_A_NAPI_MAX,
NETDEV_A_NAPI_MAX = (__NETDEV_A_NAPI_MAX - 1) NETDEV_A_NAPI_MAX = (__NETDEV_A_NAPI_MAX - 1)