diff --git a/target/linux/qualcommax/ipq60xx/base-files/etc/init.d/smp_affinity b/target/linux/qualcommax/ipq60xx/base-files/etc/init.d/smp_affinity new file mode 100755 index 00000000000..45868e9aad2 --- /dev/null +++ b/target/linux/qualcommax/ipq60xx/base-files/etc/init.d/smp_affinity @@ -0,0 +1,105 @@ +#!/bin/sh /etc/rc.common + +START=94 + +PROG=smp_affinity + +log_msg() { + local type="$1" id="$2" name="$3" affinity="$4" + + logger -t "$PROG" "Pinning $type($id) $name to CPU $affinity" +} + +get_irq() { + awk -v name="$1" '$NF == name { + sub(/:$/, "", $1) + print $1 + exit + }' /proc/interrupts +} + +get_napi_threads() { + local comm comm_path id pid + + TX_NAPI_ID= + TX_PID= + RX_NAPI_ID= + RX_PID= + + for comm_path in /proc/[0-9]*/comm; do + read -r comm < "$comm_path" + case "$comm" in + napi/eth0-[0-9]*) + id="${comm##*-}" + pid="${comm_path#/proc/}" + pid="${pid%/comm}" + + if [ -z "$TX_NAPI_ID" ] || [ "$id" -lt "$TX_NAPI_ID" ]; then + TX_NAPI_ID="$id" + TX_PID="$pid" + fi + + if [ -z "$RX_NAPI_ID" ] || [ "$id" -gt "$RX_NAPI_ID" ]; then + RX_NAPI_ID="$id" + RX_PID="$pid" + fi + ;; + esac + done +} + +pin_irq() { + local irq="$1" mask="$2" affinity="$3" name="$4" + + [ -n "$irq" ] || return + $enable_log && log_msg IRQ "$irq" "$name" "$affinity" + echo "$mask" > "/proc/irq/$irq/smp_affinity" +} + +pin_thread() { + local pid="$1" mask="$2" affinity="$3" name="$4" + + [ -n "$pid" ] || return + $enable_log && log_msg thread "$pid" "$name" "$affinity" + taskset -p "$mask" "$pid" >/dev/null +} + +enable_affinity_edma() { + local seconds=0 rx_irq tx_irq + + while [ "$seconds" -lt 60 ]; do + rx_irq="$(get_irq edma_rxdesc)" + tx_irq="$(get_irq edma_txcmpl)" + get_napi_threads + + [ -n "$rx_irq" ] && [ -n "$tx_irq" ] && + [ -n "$RX_PID" ] && [ -n "$TX_PID" ] && + [ "$RX_PID" != "$TX_PID" ] && break + + seconds=$((seconds + 1)) + sleep 1 + done + + [ -n "$rx_irq" ] && [ -n "$tx_irq" ] && + [ -n "$RX_PID" ] && [ -n "$TX_PID" ] && + [ "$RX_PID" != "$TX_PID" ] || return + + pin_irq "$rx_irq" 2 1 edma_rxdesc + pin_thread "$RX_PID" 2 1 "EDMA RX NAPI" + pin_irq "$tx_irq" 4 2 edma_txcmpl + pin_thread "$TX_PID" 4 2 "EDMA TX NAPI" +} + +boot() { + local enable + + config_load smp_affinity + + config_get_bool enable "general" enable 1 + config_get_bool enable_log "general" enable_log 1 + + [ "$enable" -eq 1 ] && enable=true || enable=false + [ "$enable_log" -eq 1 ] && enable_log=true || enable_log=false + + $enable && enable_affinity_edma & +} diff --git a/target/linux/qualcommax/ipq60xx/base-files/etc/uci-defaults/15_smp_affinity b/target/linux/qualcommax/ipq60xx/base-files/etc/uci-defaults/15_smp_affinity new file mode 100644 index 00000000000..3ec0adc44cd --- /dev/null +++ b/target/linux/qualcommax/ipq60xx/base-files/etc/uci-defaults/15_smp_affinity @@ -0,0 +1,11 @@ +#!/bin/sh + +uci -q get smp_affinity && exit 0 +touch /etc/config/smp_affinity + +uci -q batch << EOF + set smp_affinity.general=smp_affinity + set smp_affinity.general.enable='1' + set smp_affinity.general.enable_log='1' + commit smp_affinity +EOF diff --git a/target/linux/qualcommax/ipq807x/base-files/etc/init.d/smp_affinity b/target/linux/qualcommax/ipq807x/base-files/etc/init.d/smp_affinity index ecf88aea095..690a8cfa34f 100755 --- a/target/linux/qualcommax/ipq807x/base-files/etc/init.d/smp_affinity +++ b/target/linux/qualcommax/ipq807x/base-files/etc/init.d/smp_affinity @@ -81,6 +81,68 @@ set_affinity() { done } +get_napi_threads() { + + local comm comm_path id pid + + TX_NAPI_ID= + TX_PID= + RX_NAPI_ID= + RX_PID= + + for comm_path in /proc/[0-9]*/comm; do + read -r comm < "$comm_path" + case "$comm" in + napi/eth0-[0-9]*) + id="${comm##*-}" + pid="${comm_path#/proc/}" + pid="${pid%/comm}" + + if [ -z "$TX_NAPI_ID" ] || [ "$id" -lt "$TX_NAPI_ID" ]; then + TX_NAPI_ID="$id" + TX_PID="$pid" + fi + + if [ -z "$RX_NAPI_ID" ] || [ "$id" -gt "$RX_NAPI_ID" ]; then + RX_NAPI_ID="$id" + RX_PID="$pid" + fi + ;; + esac + done +} + +set_thread_affinity() { + + local pid="$1" affinity="$2" bitmask + + [ -n "$pid" ] || return + bitmask=$(cpus_to_bitmask "$affinity") && + taskset -p "$bitmask" "$pid" >/dev/null +} + +enable_affinity_edma() { + + local seconds=0 + + while [ "$seconds" -lt 60 ]; do + get_napi_threads + [ -n "$RX_PID" ] && [ -n "$TX_PID" ] && + [ "$RX_PID" != "$TX_PID" ] && break + + seconds=$((seconds + 1)) + sleep 1 + done + + [ -n "$RX_PID" ] && [ -n "$TX_PID" ] && + [ "$RX_PID" != "$TX_PID" ] || return + + set_affinity 'edma_rxdesc' 1 + set_thread_affinity "$RX_PID" 1 + set_affinity 'edma_txcmpl' 2 + set_thread_affinity "$TX_PID" 2 +} + enable_affinity_ipq807x() { # assign 4 rx interrupts to each core @@ -99,11 +161,6 @@ enable_affinity_ipq807x() { set_affinity 'ppdu-end-interrupts-mac2' 2 set_affinity 'ppdu-end-interrupts-mac3' 3 - # assign 4 lan/wan to core 4 - set_affinity 'edma_txcmpl' 3 - set_affinity 'edma_rxfill' 3 - set_affinity 'edma_rxdesc' 3 - set_affinity 'edma_misc' 3 } boot() { @@ -118,5 +175,8 @@ boot() { [ "$enable" -eq 1 ] && enable=true || enable=false [ "$enable_log" -eq 1 ] && enable_log=true || enable_log=false - $enable && enable_affinity_ipq807x + $enable && { + enable_affinity_ipq807x + enable_affinity_edma & + } }