s series makes the NAPI/queue/IRQ relationship visible to the network stack, backports the drivers and locking fixes it needs, and then builds net/dynthread on top of it: a loadable module that adapts the NAPI processing and the RX queue IRQ placement of a set of net devices to the scheduling behaviour of a target application at runtime. Motivation ---------- Interrupt and softirq processing of network RX competes with latency sensitive applications (e.g. mysqld) for CPU time. When such an application runs for a long time on a CPU without blocking, the softirq work of the NIC completion queues can preempt it on the same CPU and inflate its tail latency. The usual remedies are to steer the RX queue IRQs to other CPUs and/or to move NAPI processing into kernel threads bound to spare CPUs, but a static configuration cannot follow the application: once the target goes idle, is scheduled in short bursts, or is displaced, the reserved CPUs are simply wasted. To do this from a module, the queue a NAPI instance serves, the NAPI instance of a queue and the interrupt vector of that NAPI must be discoverable. Mainline added that association in v6.8/v6.9 (queue/NAPI pointer, netif_napi_set_irq(), mlx5e conversion) together with the RTNL fixes it requires. Patches 1-8 of this series backport that infrastructure, adapt it to the OLK KABI layout and fix the mlx5e lock ordering; patches 9-14 add the scheduler. Approach -------- The module periodically samples the scheduling statistics of all threads matching the appname module parameter and classifies them into one of five statuses (DATA_LOSS, NO_TASK, NOT_RUNNING, FRAGMENTATION, LONG_RUNNING_WITH_INTERRUPTS). Acting on that status it: - restores the RX queue IRQs to their original affinity when the target is gone or barely running; - spreads the IRQs over the NUMA node of their queues when processing in softirq context is acceptable again; - switches the NAPI processing of the configured net devices to kernel threads and binds the NAPI threads (and, optionally, the queue IRQs) to the CPUs of their NUMA node that the target tasks are not allowed to use; - scales the number of CPUs used by those threads with their measured load while the target stays in the long-running status. An unusable sample (counters moved backwards: DATA_LOSS) keeps the previous status, so a single bad sample cannot toggle the mode. Everything is controlled through module parameters, and the original IRQ affinity and NAPI mode are restored when the target disappears, the scheduler is disabled or the module is unloaded. The module is buildable only as a loadable module; the Kconfig entry currently allows ARM64 and it is enabled in the arm64 openeuler defconfig. Patch breakdown --------------- 1/14 net: Add queue and napi association Backport the queue <-> NAPI mapping: add enum netdev_queue_type, a napi pointer to struct netdev_queue and struct netdev_rx_queue, and netif_queue_set_napi() to set or clear it for RX and TX queues. The new netdev_queue field is put into reserve space so the layout of the structure is preserved. 2/14 net: fix KABI breakage for queue napi association Keep the struct layout stable across the backport: use the reserved domain segment of KABI 1 for netdev_queue and KABI 2 for netdev_rx_queue. 3/14 net: Add NAPI IRQ support Add napi->irq and netif_napi_set_irq(), so a driver can publish the interrupt vector that serves a NAPI instance. It is initialized to -1 by netif_napi_add_weight() and stays unknown for drivers that do not call the setter. The ice and netdev-genl/netlink parts of the upstream patch are not needed here and are dropped. 4/14 net: Fix napi irq KABI breakage Store napi->irq in the reserved domain segment of KABI 1 so that the napi_struct layout does not change. 5/14 net/mlx5e: link NAPI instances to queues and IRQs Make mlx5e call netif_napi_set_irq() when a channel is opened and register/clear the queue/NAPI association for its RX and TX queues (including the PTP queues) when they are activated/deactivated. This is also what users of the queue GET netlink API expect. 6/14 net/mlx5e: Acquire RTNL lock before RQs/SQs activation/deactivation netif_queue_set_napi() asserts RTNL for a registered netdev, so take the lock in the mlx5e TX reporter recovery paths that activate or deactivate queues without it. 7/14 net/mlx5e: Fix lock order in mlx5e_tx_reporter_ptpsq_unhealthy_recover The RTNL has to be acquired before priv->state_lock in the PTP SQ recovery. Move the lock acquisition up so the order matches the probe and channel switch paths. 8/14 net/mlx5e: Do not block on RTNL while recovering an SQ The recovery callbacks run synchronously from devlink_health_report() under the devlink lock, from SQ work items, while channel teardown holds the RTNL and waits for those work items with cancel_work_sync(). Replace the blocking rtnl_lock() with rtnl_trylock() and abandon the recovery when the SQ has been disabled by the teardown, following the existing mlx5e_tx_timeout_work() pattern. This avoids a deadlock that also stalled all devlink operations on the device. 9/14 net: dynthread: Add dynamic threaded NAPI scheduler framework Wire the new directory into net/Kconfig and net/Makefile, add the NET_DYNTHREAD Kconfig entry (ARM64, module only) and the module skeleton. On load the module takes a reference on each device given with the '#' separated ifname parameter, walks the IRQ descriptor table through the exported irq_get_irq_data(), snapshots desc->action and the effective affinity under desc->lock, and records the IRQ number and the original affinity CPU of every RX queue. IRQs are matched against the device name, its parent device name and the irqname pattern. Also count the NUMA nodes the recorded queues span, drop the device references on unload, and unwind a partially failed init. 10/14 net: dynthread: Monitor the load of the target tasks Add the sampling loop and the status judgement. Every dyn_threaded_interval ms, every monitored thread whose name matches appname contributes its runtime, voluntary/involuntary context switches and its allowed CPU mask; the masks are unioned to know where the target may run. The sample is compared with the previous one to derive the average runtime per switch, the nvcsw percentage and the CPU load, and to classify it as DATA_LOSS, NO_TASK, NOT_RUNNING, FRAGMENTATION or LONG_RUNNING_WITH_INTERRUPTS. Add the periodic hrtimer/work worker, the dynthreaded enable/disable parameter, a mutex serializing the worker control, a zeroed baseline on every enable, and the last_status tracking used to carry the transition sample. 11/14 net: dynthread: Steer the RX queue IRQs away from the target tasks Manage the affinity of the recorded RX queue IRQs. When the target tasks sit in a single NUMA node and enough CPUs of that node are free, move all queue IRQs there round-robin; when the target is gone or barely running, restore the affinity recorded at load time; when the target is fragmented, spread the IRQs over a subset of their own NUMA node sized from dyn_threaded_irq_cpucore_per. Track the "bound to one node" state so spreading is suppressed while it is active, and clear it on every recovery. All of this is skipped when dyn_threaded_bindirq is off, and the IRQ affinity is restored when the worker is stopped. 12/14 net: dynthread: Switch NAPI to threads on spare CPUs Enable threaded NAPI (dev_set_threaded) on the monitored devices in LONG_RUNNING_WITH_INTERRUPTS and bind each NAPI thread from the NUMA node of its queue IRQ: use the whole node if the target is not there, the target-free CPUs of the node if any, otherwise the first dyn_threaded_corenum CPUs of the node. Use napi->irq when the driver published it and fall back to the RX queue IRQ recorded by the module (e.g. hns3) otherwise. The NAPI list is built by head insertion, so it is walked in reverse to visit the NAPIs in registration (vector) order, matching the ascending order in which the RX queue IRQs are recorded. Optionally bind the queue IRQ to the same mask. Record the CPUs used by the NAPI threads in napi_cpumask for the load evaluation of the next patch. Switch the devices back to softirq mode in NO_TASK, NOT_RUNNING and FRAGMENTATION, when the scheduler is disabled and on module unload; the NAPI and IRQ operations run under the rtnetlink lock. 13/14 net: dynthread: Scale the number of NAPI thread CPUs Sample the kernel_cpustat of the CPUs used by the NAPI threads and compare consecutive periods. Grow dyn_threaded_corenum when the irq/softirq share or the total load of those CPUs is too high, and shrink it when the user share is high or the total load is low, within the lower/upper limit parameters. Damping and anti-fight rules avoid oscillating right after a change or undoing a change made for the opposite reason; the two total-load driven directions check each other, and the cpustat baseline is taken over the mask that was actually just bound. The default core count is computed at init from the busiest device's RX queue count divided by the online NUMA nodes. The lower/upper limit parameters reject zero and an inverted range, refuse a change that would move the computed default out of range, and clamp the current core count into the new range. Reset the damping state and the baseline when leaving the long-running status or when the scheduler is stopped, and serialize the core-count updates with the module parameter setter. 14/14 net: dynthread: Add debug switch and instrumentation Add the dyn_threaded_debug module parameter and instrument the periodic sampling, the status transitions, the IRQ affinity decisions, the NAPI thread masks and the CPU-count resizes. The messages are recorded with trace_printk() so they can be read from tracefs without flooding the console; without tracing support they fall back to dynamic debug. The switch is off by default. Amritha Nambiar (2): net: Add queue and napi association net: Add NAPI IRQ support Cai Xinchen (7): net/mlx5e: Do not block on RTNL while recovering an SQ net: dynthread: Add dynamic threaded NAPI scheduler framework net: dynthread: Monitor the load of the target tasks net: dynthread: Steer the RX queue IRQs away from the target tasks net: dynthread: Switch NAPI to threads on spare CPUs net: dynthread: Scale the number of NAPI thread CPUs net: dynthread: Add debug switch and instrumentation Carolina Jubran (1): net/mlx5e: Acquire RTNL lock before RQs/SQs activation/deactivation Cosmin Ratiu (1): net/mlx5e: Fix lock order in mlx5e_tx_reporter_ptpsq_unhealthy_recover JiangJieHua (2): net: fix KABI breakage for queue napi association net: Fix napi irq KABI breakage Joe Damato (1): net/mlx5e: link NAPI instances to queues and IRQs arch/arm64/configs/openeuler_defconfig | 1 + .../net/ethernet/mellanox/mlx5/core/en/ptp.c | 5 +- .../mellanox/mlx5/core/en/reporter_tx.c | 23 + .../net/ethernet/mellanox/mlx5/core/en_main.c | 7 + include/linux/netdevice.h | 21 +- include/net/netdev_rx_queue.h | 2 +- net/Kconfig | 1 + net/Makefile | 1 + net/core/dev.c | 38 + net/dynthread/Kconfig | 13 + net/dynthread/Makefile | 2 + net/dynthread/net_dynthread.c | 1494 +++++++++++++++++ 12 files changed, 1604 insertions(+), 4 deletions(-) create mode 100644 net/dynthread/Kconfig create mode 100644 net/dynthread/Makefile create mode 100644 net/dynthread/net_dynthread.c -- 2.18.0.huawei.25