From: Martin Karsten <mkarsten@xxxxxxxxxxxx> 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@xxxxxxxxxxxx> Co-developed-by: Joe Damato <jdamato@xxxxxxxxxx> Signed-off-by: Joe Damato <jdamato@xxxxxxxxxx> Tested-by: Joe Damato <jdamato@xxxxxxxxxx> Tested-by: Martin Karsten <mkarsten@xxxxxxxxxxxx> --- Documentation/networking/napi.rst | 3 +++ include/linux/netdevice.h | 2 ++ net/core/dev.c | 3 ++- net/core/net-sysfs.c | 18 ++++++++++++++++++ 4 files changed, 25 insertions(+), 1 deletion(-) diff --git a/Documentation/networking/napi.rst b/Documentation/networking/napi.rst index 7bf7b95c4f7a..0a029dd6d77e 100644 --- a/Documentation/networking/napi.rst +++ b/Documentation/networking/napi.rst @@ -192,6 +192,9 @@ The ``gro_flush_timeout`` sysfs configuration of the netdevice is reused to control the delay of the timer, while ``napi_defer_hard_irqs`` controls the number of consecutive empty polls before NAPI gives up and goes back to using hardware IRQs. +``irq_suspend_timeout`` is used to determine how long an application can +completely suspend IRQs. It is used in combination with SO_PREFER_BUSY_POLL, +which can be set on a per-epoll context basis with EPIOCSPARAMS ioctl. .. _poll: diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 0ef3eaa23f4b..31867bb2ff65 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1857,6 +1857,7 @@ enum netdev_reg_state { * @gro_flush_timeout: timeout for GRO layer in NAPI * @napi_defer_hard_irqs: If not zero, provides a counter that would * allow to avoid NIC hard IRQ, on busy queues. + * @irq_suspend_timeout: IRQ suspension timeout * * @rx_handler: handler for received packets * @rx_handler_data: XXX: need comments on this one @@ -2060,6 +2061,7 @@ struct net_device { struct netdev_rx_queue *_rx; unsigned long gro_flush_timeout; int napi_defer_hard_irqs; + unsigned long irq_suspend_timeout; unsigned int gro_max_size; unsigned int gro_ipv4_max_size; rx_handler_func_t __rcu *rx_handler; diff --git a/net/core/dev.c b/net/core/dev.c index 751d9b70e6ad..bf45c90aebcd 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -11937,6 +11937,7 @@ static void __init net_dev_struct_check(void) CACHELINE_ASSERT_GROUP_MEMBER(struct net_device, net_device_read_rx, _rx); CACHELINE_ASSERT_GROUP_MEMBER(struct net_device, net_device_read_rx, gro_flush_timeout); CACHELINE_ASSERT_GROUP_MEMBER(struct net_device, net_device_read_rx, napi_defer_hard_irqs); + CACHELINE_ASSERT_GROUP_MEMBER(struct net_device, net_device_read_rx, irq_suspend_timeout); CACHELINE_ASSERT_GROUP_MEMBER(struct net_device, net_device_read_rx, gro_max_size); CACHELINE_ASSERT_GROUP_MEMBER(struct net_device, net_device_read_rx, gro_ipv4_max_size); CACHELINE_ASSERT_GROUP_MEMBER(struct net_device, net_device_read_rx, rx_handler); @@ -11948,7 +11949,7 @@ static void __init net_dev_struct_check(void) #ifdef CONFIG_NET_XGRESS CACHELINE_ASSERT_GROUP_MEMBER(struct net_device, net_device_read_rx, tcx_ingress); #endif - CACHELINE_ASSERT_GROUP_SIZE(struct net_device, net_device_read_rx, 104); + CACHELINE_ASSERT_GROUP_SIZE(struct net_device, net_device_read_rx, 112); } /* diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 0e2084ce7b75..fb6f3327310f 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -440,6 +440,23 @@ static ssize_t napi_defer_hard_irqs_store(struct device *dev, } NETDEVICE_SHOW_RW(napi_defer_hard_irqs, fmt_dec); +static int change_irq_suspend_timeout(struct net_device *dev, unsigned long val) +{ + WRITE_ONCE(dev->irq_suspend_timeout, val); + return 0; +} + +static ssize_t irq_suspend_timeout_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len) +{ + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + return netdev_store(dev, attr, buf, len, change_irq_suspend_timeout); +} +NETDEVICE_SHOW_RW(irq_suspend_timeout, fmt_ulong); + static ssize_t ifalias_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { @@ -664,6 +681,7 @@ static struct attribute *net_class_attrs[] __ro_after_init = { &dev_attr_tx_queue_len.attr, &dev_attr_gro_flush_timeout.attr, &dev_attr_napi_defer_hard_irqs.attr, + &dev_attr_irq_suspend_timeout.attr, &dev_attr_phys_port_id.attr, &dev_attr_phys_port_name.attr, &dev_attr_phys_switch_id.attr, -- 2.25.1