Alternate ath9k and ath10k radio reset for deaf nodes (#857)

* A scan, especially if we have to do both active and passive, essentially mutes
the radio to AREDN traffic for 10-20 seconds, which isn't good. If the radio is completely
deaf then it doesn't matter, but particularly on the 9K radios we do this when
things are looking a bit dodgy, though not deaf. 
* Provide hook to reset ath9k from userspace.  This hook is attributed to:
Linus Lüssing <ll@simonwunderlich.de>
* User /sys reset hooks rather than iw scan
This commit is contained in:
Tim Wilkinson 2023-06-01 17:06:39 -07:00 committed by GitHub
parent 0890ab210f
commit a61dfcdafe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 133 additions and 29 deletions

View File

@ -33,10 +33,9 @@
--]]
local periodic_scan_time = 300 -- 5 minutes
local periodic_scan_tick = 5
local wifiiface
local last_scan_time = 0
function rssi_monitor_10k()
if not string.match(get_ifname("wifi"), "^wlan") then
@ -67,9 +66,13 @@ if not file_exists(logfile) then
io.open(logfile, "w+"):close()
end
local last_station_count = 0
local station_zero = 0
local log = aredn.log.open(logfile, 16000)
local function reset_network()
write_all("/sys/kernel/debug/ieee80211/" .. phy .. "/ath10k/simulate_fw_crash", "hw-restart")
end
function run_monitor_10k()
local station_count = 0
@ -79,15 +82,16 @@ function run_monitor_10k()
station_count = station_count + 1
end
if station_count == 0 and (last_station_count ~= 0 or nixio.sysinfo().uptime > periodic_scan_time + last_scan_time) then
-- reset
last_scan_time = nixio.sysinfo().uptime
os.execute("/usr/sbin/iw " .. wifiiface .. " scan > /dev/null 2>&1")
os.execute("/usr/sbin/iw " .. wifiiface .. " scan passive > /dev/null 2>&1")
log:write("No stations detected")
log:flush()
if station_count ~= 0 then
station_zero = periodic_scan_tick - 1
else
station_zero = station_zero + 1
if math.mod(station_zero, periodic_scan_tick) == 0 then
reset_network()
log:write("No stations detected")
log:flush()
end
end
last_station_count = station_count
end
return rssi_monitor_10k

View File

@ -75,9 +75,14 @@ if not file_exists(logfile) then
io.open(logfile, "w+"):close()
end
local last_station_count = 0
local station_zero = 0
local periodic_scan_tick = 5
local log = aredn.log.open(logfile, 16000)
local function reset_network()
write_all("/sys/kernel/debug/ieee80211/" .. phy .. "/ath9k/reset", "1")
end
function run_monitor_9k()
local now = nixio.sysinfo().uptime
@ -105,13 +110,6 @@ function run_monitor_9k()
end
end
local amac = nil
-- avoid node going deaf while trying to obtain 'normal' statistics of neighbor strength
-- in first few minutes after boot
if now > 119 and now < 750 then
os.execute("/usr/sbin/iw " .. wifiiface .. " scan > /dev/null 2>&1")
end
local station_count = 0
local rssi = get_rssi(wifiiface)
for mac, info in pairs(rssi)
@ -166,9 +164,7 @@ function run_monitor_9k()
end
if amac then
-- reset
os.execute("/usr/sbin/iw " .. wifiiface .. " scan > /dev/null 2>&1")
os.execute("/usr/sbin/iw " .. wifiiface .. " scan passive > /dev/null 2>&1")
reset_network()
wait_for_ticks(5)
-- update time
now = nixio.sysinfo().uptime
@ -202,13 +198,18 @@ function run_monitor_9k()
rssih.num = rssih.num + 1
end
end
elseif station_count == 0 and last_station_count ~= 0 then
-- reset
os.execute("/usr/sbin/iw " .. wifiiface .. " scan > /dev/null 2>&1")
wait_for_ticks(5)
log:write("No stations detected")
else
if station_count ~= 0 then
station_zero = periodic_scan_tick - 1
else
station_zero = station_zero + 1
if math.mod(station_zero, periodic_scan_tick) == 0 then
reset_network()
wait_for_ticks(5)
log:write("No stations detected")
end
end
end
last_station_count = station_count
local f = io.open(datfile, "w")
if f then

View File

@ -51,7 +51,6 @@ local log = aredn.log.open(logfile, 8000)
function rejoin_network()
os.execute(IW .. " " .. wifiiface .. " ibss leave")
nixio.nanosleep(1, 0)
os.execute(IW .. " " .. wifiiface .. " ibss join " .. ssid .. " " .. frequency .. " fixed-freq")
log:write("Rejoining network")
log:flush()

99
patches/701-ath9k-reset.patch Executable file
View File

@ -0,0 +1,99 @@
--- /dev/null
+++ b/package/kernel/mac80211/patches/ath/301-ath-reset.patch
@@ -0,0 +1,96 @@
+diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
+index 4c81b1d7f417..fb7a2952d0ce 100644
+--- a/drivers/net/wireless/ath/ath9k/debug.c
++++ b/drivers/net/wireless/ath/ath9k/debug.c
+@@ -749,9 +749,9 @@ static int read_file_misc(struct seq_file *file, void *data)
+
+ static int read_file_reset(struct seq_file *file, void *data)
+ {
+- struct ieee80211_hw *hw = dev_get_drvdata(file->private);
+- struct ath_softc *sc = hw->priv;
++ struct ath_softc *sc = file->private;
+ static const char * const reset_cause[__RESET_TYPE_MAX] = {
++ [RESET_TYPE_USER] = "User reset",
+ [RESET_TYPE_BB_HANG] = "Baseband Hang",
+ [RESET_TYPE_BB_WATCHDOG] = "Baseband Watchdog",
+ [RESET_TYPE_FATAL_INT] = "Fatal HW Error",
+@@ -779,6 +779,55 @@ static int read_file_reset(struct seq_file *file, void *data)
+ return 0;
+ }
+
++static int open_file_reset(struct inode *inode, struct file *f)
++{
++ return single_open(f, read_file_reset, inode->i_private);
++}
++
++static ssize_t write_file_reset(struct file *file,
++ const char __user *user_buf,
++ size_t count, loff_t *ppos)
++{
++ struct ath_softc *sc = file_inode(file)->i_private;
++ struct ath_hw *ah = sc->sc_ah;
++ struct ath_common *common = ath9k_hw_common(ah);
++ unsigned long val;
++ char buf[32];
++ ssize_t len;
++
++ len = min(count, sizeof(buf) - 1);
++ if (copy_from_user(buf, user_buf, len))
++ return -EFAULT;
++
++ buf[len] = '\0';
++ if (kstrtoul(buf, 0, &val))
++ return -EINVAL;
++
++ if (val != 1)
++ return -EINVAL;
++
++ /* avoid rearming hw_reset_work on shutdown */
++ mutex_lock(&sc->mutex);
++ if (test_bit(ATH_OP_INVALID, &common->op_flags)) {
++ mutex_unlock(&sc->mutex);
++ return -EBUSY;
++ }
++
++ ath9k_queue_reset(sc, RESET_TYPE_USER);
++ mutex_unlock(&sc->mutex);
++
++ return count;
++}
++
++static const struct file_operations fops_reset = {
++ .read = seq_read,
++ .write = write_file_reset,
++ .open = open_file_reset,
++ .owner = THIS_MODULE,
++ .llseek = seq_lseek,
++ .release = single_release,
++};
++
+ void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
+ struct ath_tx_status *ts, struct ath_txq *txq,
+ unsigned int flags)
+@@ -1393,8 +1442,8 @@ int ath9k_init_debug(struct ath_hw *ah)
+ read_file_queues);
+ debugfs_create_devm_seqfile(sc->dev, "misc", sc->debug.debugfs_phy,
+ read_file_misc);
+- debugfs_create_devm_seqfile(sc->dev, "reset", sc->debug.debugfs_phy,
+- read_file_reset);
++ debugfs_create_file("reset", 0600, sc->debug.debugfs_phy,
++ sc, &fops_reset);
+
+ ath9k_cmn_debug_recv(sc->debug.debugfs_phy, &sc->debug.stats.rxstats);
+ ath9k_cmn_debug_phy_err(sc->debug.debugfs_phy, &sc->debug.stats.rxstats);
+diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h
+index 33826aa13687..389459c04d14 100644
+--- a/drivers/net/wireless/ath/ath9k/debug.h
++++ b/drivers/net/wireless/ath/ath9k/debug.h
+@@ -39,6 +39,7 @@ struct fft_sample_tlv;
+ #endif
+
+ enum ath_reset_type {
++ RESET_TYPE_USER,
+ RESET_TYPE_BB_HANG,
+ RESET_TYPE_BB_WATCHDOG,
+ RESET_TYPE_FATAL_INT,
+

View File

@ -2,6 +2,7 @@
001-ath79-cpe220v3-sysupgrade-supported.patch
001-ath79-reverse-wpad-basic-wolfssl.patch
006-rocket-m-flash-fix.patch
701-ath9k-reset.patch
701-extended-spectrum.patch
702-enable-country-hx.patch
703-fix-dnsmasq.patch