From 2a78eed8852cd840468a131c0e10b0cee379df91 Mon Sep 17 00:00:00 2001 From: CN_SZTL Date: Tue, 28 Jul 2020 15:10:55 +0800 Subject: [PATCH] rockchip: distribute net interrupts This adds a hotplug script for distributing interrupts of eth0 and eth1 across different cores. Otherwise the forwarding performance between eth0 and eth1 is severely affected. The existing SMP distribution mechanic in OpenWrt can't be used here, as the actual device IRQ has to be moved to dedicated cores. In case of eth1, this is in fact the USB3 controller. Signed-off-by: David Bauer --- .../etc/hotplug.d/net/40-net-smp-affinity | 30 +++ .../base-files/etc/init.d/adjust_network | 209 ------------------ 2 files changed, 30 insertions(+), 209 deletions(-) create mode 100644 target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity delete mode 100755 target/linux/rockchip/armv8/base-files/etc/init.d/adjust_network diff --git a/target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity b/target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity new file mode 100644 index 0000000000..ab3f954654 --- /dev/null +++ b/target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity @@ -0,0 +1,30 @@ +#!/bin/sh + +[ "$ACTION" = add ] || exit + +get_device_irq() { + local device="$1" + + local line=$(grep -m 1 "${device}\$" /proc/interrupts) + echo $(echo ${line} | sed 's/:.*//') +} + +set_interface_core() { + local core_mask="$1" + local interface="$2" + local device="$3" + + [ -z "${device}" ] && device="$interface" + + local irq=$(get_device_irq "$device") + + echo "${core_mask}" > /proc/irq/${irq}/smp_affinity +} + +case "$(board_name)" in +friendlyarm,nanopi-r2s) + set_interface_core 2 "eth0" + set_interface_core 4 "eth1" "xhci-hcd:usb3" + ;; +esac + diff --git a/target/linux/rockchip/armv8/base-files/etc/init.d/adjust_network b/target/linux/rockchip/armv8/base-files/etc/init.d/adjust_network deleted file mode 100755 index ac8050b59f..0000000000 --- a/target/linux/rockchip/armv8/base-files/etc/init.d/adjust_network +++ /dev/null @@ -1,209 +0,0 @@ -#!/bin/sh /etc/rc.common -# Copyright (C) 2006-2011 OpenWrt.org - -START=99 -STOP=98 - -rps_flow_cnt=4096 -core_count=$(grep -c processor /proc/cpuinfo) -rps_sock_flow_ent=`expr $core_count \* $rps_flow_cnt` -queue_cores="0 2" -i2c_core="2" -eth0_cores="1" -wifi_core="0" -usb_core="3" -dma_core="0" - -############### util functions ############### - -to_hex_list() { - local cores=$1 - local converted="" - for core in $(echo $cores | awk '{print}') - do - local hex="$(gen_hex_mask "$core")" - converted="$converted $hex" - done - echo `echo $converted | sed 's/^ *//'` -} - -gen_hex_mask() { - local cores=$1 - local mask=0 - for core in $(echo $cores | awk '{print}') - do - local bit="$((1 << $core))" - let "mask = mask + bit" - done - local hex="$(printf %x "$mask")" - echo "$hex" -} - -val_at_index() { - local values=$1 - local idx=$2 - echo `echo $values | awk -v i=$idx '{print $i}'` -} - -size_of_list() { - local list=$1 - local spaces=`echo $list | grep -o ' ' | wc -l` - echo `expr $spaces + 1` -} - -set_core_mask() { - local file=$1 - local cores=$2 - local mask="$(gen_hex_mask "$cores")" - echo $mask > $file -} - -set_core_mask_round() { - local files=$1 - local cores=$2 - local step_size=$3 - [ ! -n "$3" ] && step_size=1 - - local core_count="$(size_of_list "$cores")" - local counter=0 - local idx=1 - local roof=`expr $core_count \* $step_size` - for file in $(echo $files | awk '{print}') - do - let "idx = counter / step_size + 1" - local core="$(val_at_index "$cores" $idx)" - set_core_mask $file $core - let "counter = counter + 1" - [ $counter -ge $roof ] && counter=0 - done -} - -############### assign network queues ############### - -set_interface_round() { - local interface=$1 - local cores=$2 - local step_size=$3 - [ ! -n "$3" ] && step_size=1 - - echo "using round mask for interface: $interface, step size: $step_size" - set_core_mask_round "$(ls /sys/class/net/$interface/queues/tx-*/xps_cpus)" "$cores" $step_size - set_core_mask_round "$(ls /sys/class/net/$interface/queues/rx-*/rps_cpus)" "$cores" $step_size - - for file in /sys/class/net/$interface/queues/rx-[0-9]*/rps_flow_cnt - do - echo $rps_flow_cnt > $file - done -} - -set_interface() { - local interface=$1 - local cores=$2 - - echo "using cores: $cores for interface: $interface" - - for file in /sys/class/net/$interface/queues/rx-[0-9]*/rps_cpus - do - set_core_mask $file "$cores" - echo $rps_flow_cnt > `dirname $file`/rps_flow_cnt - done - - for file in /sys/class/net/$interface/queues/tx-[0-9]*/xps_cpus - do - set_core_mask $file "$cores" - done -} - -set_interface_queues() { - echo "using cpu: $queue_cores for network queues" - for dev in /sys/class/net/eth* - do - [ -d "$dev" ] || continue - - local interface=`basename $dev` - - set_interface $interface "$queue_cores" - done - - for dev in /sys/class/net/wlan* - do - [ -d "$dev" ] || continue - - local interface=`basename $dev` - - set_interface $interface "$queue_cores" - done - - for dev in /sys/class/net/eth* - do - local eth=`basename $dev` - echo "enabling offload on $eth" - ethtool -K $eth rx-checksum on >/dev/null 2>&1 - ethtool -K $eth tx-checksum-ip-generic on >/dev/null 2>&1 || ( - ethtool -K $eth tx-checksum-ipv4 on >/dev/null 2>&1 - ethtool -K $eth tx-checksum-ipv6 on >/dev/null 2>&1) - ethtool -K $eth tx-scatter-gather on >/dev/null 2>&1 - ethtool -K $eth gso on >/dev/null 2>&1 - ethtool -K $eth gro on >/dev/null 2>&1 - ethtool -K $eth lro on >/dev/null 2>&1 - ethtool -K $eth tso on >/dev/null 2>&1 - ethtool -K $eth ufo on >/dev/null 2>&1 - done - - echo $rps_sock_flow_ent > /proc/sys/net/core/rps_sock_flow_entries - sysctl -w net.core.rps_sock_flow_entries=$rps_sock_flow_ent -} - -############### assign interrupts ############### -set_irq_cores() { - local mask="$(gen_hex_mask "$2")" - echo "set mask $mask for irq: $1" - echo $mask > "/proc/irq/$1/smp_affinity" -} - -set_irq_pattern() { - local name_pattern="$1" - local cores="$2" - - for irq in `grep "$name_pattern" /proc/interrupts | cut -d: -f1 | sed 's, *,,'` - do - set_irq_cores $irq "$cores" - done -} - -set_irq_interleave() { - local name_pattern=$1 - local cores=$2 - local step_size=$3 - - local files="" - for irq in `grep "$name_pattern" /proc/interrupts | cut -d: -f1 | sed 's, *,,'` - do - files="$files\ - /proc/irq/$irq/smp_affinity" - done - - set_core_mask_round "$files" "$cores" "$step_size" -} - -set_irqs() { - #dma - set_irq_pattern dma "$dma_core" - - #eth0 - set_irq_pattern eth0 "$eth0_cores" - - #pcie - set_irq_pattern pcie "$wifi_core" - - #usb(eth1) - set_irq_pattern usb "$usb_core" - - #i2c - set_irq_pattern i2c "$i2c_core" -} - -start() { - set_interface_queues - set_irqs -}