nss-packages-breeze303/qca-nss-drv/files/qca-nss-drv.init
Sean Khan 07cee3d981 qca-nss-drv: Rework smp_affinity logic
Reworked flawed smp_affinity logic. It was assumed that all 'nss_*' IRQs
needed to be equally balanced across all CPUs. However, what ends up
happening most of the time is messing with scheduling, thrashing, missed
cache and high context switching.

For each core:
  1. nss_empty_buf_sos
  2. nss_empty_buf_queue
  3. nss_queue0

The IRQs should be kept on the same CPU. Doing so allows NSS cores to
properly feed and empty the queues.

Signed-off-by: Sean Khan <datapronix@protonmail.com>
2024-07-02 20:44:35 -04:00

136 lines
3.7 KiB
Bash

#!/bin/sh /etc/rc.common
# vim: set syn=bash
# shellcheck disable=2155,3010,3019,3043,3057,3060
START=94
PROG="qca-nss-drv"
log_msg() {
local irq_name="$1" affinity="$2" occurrence="$3" irq="$4"
msg="$(printf "Pinning IRQ($irq) %-24s to CPU ${affinity}\n" "$irq_name")"
[[ $irq_name =~ "nss" ]] && msg="$msg (NSS Core $((occurrence - 1)))"
logger -t "$PROG" "$msg"
}
######################################################################
### Takes a comma, space separated, or range list of CPU numbers and
## returns a bitmask of CPUs.
## cpus_to_bitmask "0,1,2,3" -> f
## cpus_to_bitmask "0 1 2 3" -> f
## cpus_to_bitmask "0-3" -> f
## cpus_to_bitmask "3" -> 8
#######################################################################
cpus_to_bitmask() {
local bitmask=0
# shellcheck disable=2048
for range in ${*//,/ }; do
start="${range%-*}"
end="${range#*-}"
if [ -z "$end" ]; then
bitmask="$((bitmask | 1 << start))"
else
bitmask="$((bitmask | (2 ** (end - start + 1) - 1) << start))"
fi
done
printf '%x' $bitmask
}
######################################################################
### Takes a bitmask of CPUs and returns a space separated list of
## CPU numbers.
## bitmask_to_cpus f -> 0 1 2 3
######################################################################
bitmask_to_cpus() {
[ "${1:0:2}" != "0x" ] && set -- "0x$1"
local bitmask="$(printf '%d' "$1")"
local cpus=""
for i in $(seq 0 63); do
if [ $((bitmask & 1)) -ne 0 ]; then
cpus="$cpus $i"
fi
bitmask=$((bitmask >> 1))
done
echo "${cpus# }"
}
######################################################################
### Sets the affinity of the IRQs with the given name to the given CPU.
## first argument: IRQ name ("nss_queue0")
## second argument: CPU number
## third argument: occurrence of the IRQ name
## since NSS core 0/1 share the same IRQ names
## set_affinity "nss_queue0" 1 1
set_affinity() {
local irq_name="$1" affinity="$2" occurrence="${3:-1}" bitmask
awk -v irq_name="$irq_name" -v occurrence="$occurrence" '
BEGIN{count=0}
$NF==irq_name {
if(++count==occurrence){
sub(/:$/,"",$1)
print $1
}
}' /proc/interrupts | while read -r irq; do
$enable_log && {
log_msg "$irq_name" "$affinity" "$occurrence" "$irq"
}
bitmask=$(cpus_to_bitmask "$affinity") && echo "$bitmask" > /proc/irq/"$irq"/smp_affinity
done
}
enable_rps() {
# NSS Core 0 : 4 nss queues to each core
set_affinity "nss_queue0" 0-3 1
set_affinity "nss_queue1" 1 1
set_affinity "nss_queue2" 2 1
set_affinity "nss_queue3" 3 1
# NSS Core 1 : 1 nss queue to 3rd core
set_affinity "nss_queue0" 3 2
# NSS Core 0 : 2 nss sos/queues to last core
set_affinity "nss_empty_buf_sos" 0-3 1
set_affinity "nss_empty_buf_queue" 0-3 1
# NSS Core 1 : 1 nss sos to last core
set_affinity "nss_empty_buf_sos" 3 2
# USB 3.0 : pin to 3rd core
set_affinity "xhci-hcd:usb1" 1,3 1
# TCL Completion, REO Dest, ERR, Exception and h2rxdma
# are offloaded, so balance remaining IRQs accordingly.
# PPDU IRQ : pin to 2nd and 3rd core
set_affinity 'ppdu-end-interrupts-mac1' 1 1
set_affinity 'ppdu-end-interrupts-mac3' 2 1
set_affinity 'ath10k_pci' 0-3 1
# Enable NSS RPS
sysctl -w dev.nss.rps.enable=1 >/dev/null 2>&1
}
start() {
local enable_rps
config_load nss
config_get enable_rps "general" enable_rps 1
config_get_bool enable_log "general" enable_log 1
[ "$enable_log" -eq 1 ] && enable_log=true || enable_log=false
[ "$enable_rps" -eq 1 ] && enable_rps
}