From 30054d0855290af28bebec6016691704c52c5ba7 Mon Sep 17 00:00:00 2001 From: Mads Meisner-Jensen Date: Sat, 15 May 2021 15:02:02 +0200 Subject: [PATCH] rpi-4: move/pin eth0 IRQs to CPU2 Move all eth0 IRQ processing to CPU2 instead of CPU1 which is the default. CPU1 will continue handling all the USB interrupts which also include USB-Ethernet adapter interrupts. This significantly lowers the softirq load on CPU1 (from 99% to less than 10%) irqbalance could do the same and you can still run irqbalance because the /etc/init.d/irq-eth-pin script will add the eth0 to the ban list of irqbalance See interrupt load with while true; do clear; cat /proc/interrupts; sleep 1; done --- configs/rpi-4-files/etc/init.d/irq-eth-pin | 36 +++++++++++++++++++++ configs/rpi-4-files/etc/rc.d/S85irq-eth-pin | 1 + 2 files changed, 37 insertions(+) create mode 100755 configs/rpi-4-files/etc/init.d/irq-eth-pin create mode 120000 configs/rpi-4-files/etc/rc.d/S85irq-eth-pin diff --git a/configs/rpi-4-files/etc/init.d/irq-eth-pin b/configs/rpi-4-files/etc/init.d/irq-eth-pin new file mode 100755 index 0000000..8bbb143 --- /dev/null +++ b/configs/rpi-4-files/etc/init.d/irq-eth-pin @@ -0,0 +1,36 @@ +#!/bin/sh /etc/rc.common + +uci_banirq=irqbalance.irqbalance.banirq +cpu_irq_eth=2 + +# Move eth0 IRQs to CPU1 (numbered 1-4 when writing) +# And ban irqbalance from messing with it +# The USB3 Ethernet IRQs cannot be moved and must stay on CPU0 +irqs_eth0=$(sed -rn "s/^\s*([0-9]+):.*eth0$/\1/p" /proc/interrupts) + +for n in ${irqs_eth0}; do + echo ${cpu_irq_eth} > /proc/irq/${n}/smp_affinity + if ! uci get ${uci_banirq} | grep -q ${n}; then + uci add_list ${uci_banirq}=${n} + fi +done +uci commit + +logger -t "irq_eth_pin" "Moved eth0 IRQs ${irqs_eth0} to cpu${cpu_irq_eth}" + +softirqs_move() { + # Move softirqs for network traffic to CPU2 and CPU3 + # Maybe not a brilliant idea because the softirqs are probably better off + # being processed on the CPU that got the original IRQ + # (and that is exactly the default when the value is 0) + # NOTE: it appears that the openwrt 20.02-rc1 kernel has a bug that + # returns "No such file or directory" for /sys/class/net/eth1/queues/xps_cpus + for ifname in eth0; do # eth1 + for f in $(find /sys/class/net/${ifname}/queues -name xps_cpus -o -name rps_cpus); do + if [ -f ${f} ]; then + echo "${f} = $(cat ${f})" + echo c >${f} + fi + done + done +} diff --git a/configs/rpi-4-files/etc/rc.d/S85irq-eth-pin b/configs/rpi-4-files/etc/rc.d/S85irq-eth-pin new file mode 120000 index 0000000..d5fb68a --- /dev/null +++ b/configs/rpi-4-files/etc/rc.d/S85irq-eth-pin @@ -0,0 +1 @@ +../init.d/irq-eth-pin \ No newline at end of file