forked from marfrit/kernel-agent
Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b04c8cd501 | |||
| 38fd672940 | |||
| 8b356aa11f | |||
| 443f5e992e | |||
| 2f119a3fb7 | |||
| 7a86ebb587 | |||
| 731e98e079 | |||
| bae99da612 | |||
| 3d10a2c21a | |||
| c9e9ad973c | |||
| a254b6f0bb | |||
| 43c8f0cba8 | |||
| 42b0c5042a | |||
| 4c80458d1f | |||
| 96af34d775 | |||
| 95be39ef80 | |||
| 9092d9aaaa |
+39
-2
@@ -27,6 +27,7 @@ import argparse
|
||||
import glob
|
||||
import hashlib
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
from datetime import datetime, timezone
|
||||
@@ -37,6 +38,17 @@ VERSION = 1
|
||||
SCHEMA_VERSION = 1
|
||||
COVER_LETTER = "0000-cover-letter.patch"
|
||||
|
||||
# git format-patch trailer: "-- \n<MAJOR>.<MINOR>(.<PATCH>)?\n" at EOF,
|
||||
# possibly with trailing blank line(s). Strip from each source patch so
|
||||
# that the cumulative is always well-formed regardless of include order.
|
||||
# See issue #31.
|
||||
_TRAILER_RE = re.compile(rb'\n-- \n\d+\.\d+(?:\.\d+)?\n+\Z')
|
||||
|
||||
# Canonical separator emitted between concatenated patches in the
|
||||
# cumulative. Trailing blank line keeps patch(1) happy when the next
|
||||
# patch starts with "From <sha>".
|
||||
_CANONICAL_TRAILER = b'-- \n2.54.0\n\n'
|
||||
|
||||
|
||||
def die(msg, code=1):
|
||||
print(f"ka-promote: error: {msg}", file=sys.stderr)
|
||||
@@ -124,11 +136,36 @@ def resolve_includes(includes, patches_root):
|
||||
return resolved
|
||||
|
||||
|
||||
def strip_trailer(data):
|
||||
"""Strip any trailing git format-patch sentinel from a patch.
|
||||
|
||||
Accepts patches in either canonical shape:
|
||||
- WITH trailer: "...\n-- \n2.54.0\n\n"
|
||||
- WITHOUT trailer: "...\n" (already stripped)
|
||||
|
||||
Returns data ending in a single newline so the caller can either
|
||||
append a canonical trailer (mid-cumulative) or leave it bare (last).
|
||||
"""
|
||||
stripped = _TRAILER_RE.sub(b'\n', data)
|
||||
if not stripped.endswith(b'\n'):
|
||||
stripped += b'\n'
|
||||
return stripped
|
||||
|
||||
|
||||
def write_cumulative(resolved, out_path):
|
||||
with open(out_path, "wb") as out:
|
||||
for r in resolved:
|
||||
n = len(resolved)
|
||||
for i, r in enumerate(resolved):
|
||||
with open(r["src"], "rb") as src:
|
||||
out.write(src.read())
|
||||
data = src.read()
|
||||
data = strip_trailer(data)
|
||||
out.write(data)
|
||||
# Mid-cumulative patches need a separator so patch(1) knows
|
||||
# where they end and the next "From <sha>" begins. Last
|
||||
# patch stays bare — a trailing orphan sentinel reads as
|
||||
# the start of a malformed new patch at EOF (issue #31).
|
||||
if i != n - 1:
|
||||
out.write(_CANONICAL_TRAILER)
|
||||
with open(out_path, "rb") as f:
|
||||
b2 = hashlib.blake2b(f.read()).hexdigest()
|
||||
size = os.path.getsize(out_path)
|
||||
|
||||
+11
-4
@@ -53,12 +53,19 @@ includes:
|
||||
- board/coolpi-cm5-genbook/0005-arm64-dts-rockchip-rk3588-coolpi-cm5-genbook-Enable-USB-C-PD-charging-via-FUSB302.patch
|
||||
- board/coolpi-cm5-genbook/0008-arm64-dts-rockchip-rk3588-coolpi-cm5-genbook-Add-lid-switch-and-USB3-PHY-lane-config.patch
|
||||
- board/coolpi-cm5-genbook/0011-arm64-dts-rockchip-rk3588-coolpi-cm5-genbook-wire-internal-microphone.patch
|
||||
# VP9 enablement for RK3588 rkvdec (issue #12, closed 2026-05-18).
|
||||
# Cherry-picked from D.V.A.B. Sarma's add-rkvdec-vdpu381-vp9-v8 branch
|
||||
# at github.com/dvab-sarma/android_kernel_rk_opi. Bit-exact HW==SW==libva
|
||||
# verified at -ss 30 on bbb_60s_720p.vp9.webm via all three decode paths
|
||||
# (kdirect / SW / libva); sha c8624d7c42db66525f53a02a515bc38d0a17ef39f692660cc7bebb1e2d2e1b48.
|
||||
# Apply order is STRICT (0003 depends on the rkvdec-vp9-common refactor
|
||||
# added in 0002, which depends on the helper rename in 0001).
|
||||
# See patches/driver/media/README.md for provenance + removal criteria.
|
||||
- driver/media/0001-rkvdec-vp9-rename-get_ref_buf-to-get_ref_buf_vp9.patch
|
||||
- driver/media/0002-rkvdec-move-vp9-functions-to-common-file.patch
|
||||
- driver/media/0003-rkvdec-add-vp9-support-for-vdpu381-variant.patch
|
||||
|
||||
# Explicitly NOT included this round (tracked for later sprints):
|
||||
# - VP9 enablement for RK3588 rkvdec (issue #6 ask 2). /dev/video0 only
|
||||
# advertises S265 + S264 today; vainfo lists 9 profiles, target is
|
||||
# 10. Requires identifying the VDPU381/383 patch chain + possible
|
||||
# DTS additions. RFC-stage work, scope unclear until research lands.
|
||||
# - AV1 decoder integration (issue #6 ask 3). Kernel side is fine
|
||||
# (/dev/video4 advertises AV1F). Backend libva-v4l2-request-fourier
|
||||
# needs iter39 for a third fd. Backend work, not kernel.
|
||||
|
||||
+42
-19
@@ -25,38 +25,61 @@ baseline:
|
||||
|
||||
# Scope-tagged patch includes. Resolves to patches/<scope>/<file>.patch.
|
||||
#
|
||||
# 2026-05-18 audit: the per-series -danctnix mirrors in
|
||||
# patches/driver/bes2600/*-danctnix/ created by kernel-agent#17 use
|
||||
# DKMS-style root paths (bes2600/foo.c) rather than in-tree staging
|
||||
# paths (drivers/staging/bes2600/foo.c), and at least one has corrupted
|
||||
# mixed-prefix headers (a/drivers/staging/bes2600/... b/bes2600/...).
|
||||
# They do NOT apply cleanly against the linux-pinetab2 baseline.
|
||||
#
|
||||
# Until the per-series mirrors are reconstructed (kernel-agent followup
|
||||
# issue), the bes2600 driver scope is satisfied by a single-file
|
||||
# cumulative captured from the working hand-managed
|
||||
# danctnix-besser-pkgbuild flow on boltzmann (see
|
||||
# patches/driver/bes2600/cumulative-c5x-danctnix/README.md). This is
|
||||
# the c5x stack as it shipped in pkgrel=3 on 2026-05-18.
|
||||
# Per-series reconstruction closing kernel-agent#29 (2026-05-18 evening):
|
||||
# the 24 in-tree bes2600 -danctnix series-dirs below were repopulated
|
||||
# from cleanups + bes2600/bh-c-fossil-cleanup via
|
||||
# git format-patch fe73571..cleanups --no-merges
|
||||
# with paths rewritten from bes2600/* to drivers/staging/bes2600/*.
|
||||
# Order matches the original cleanups commit chronology (= the order
|
||||
# the c5x interim cumulative had folded them in). Replacing
|
||||
# cumulative-c5x-danctnix with these gives per-fix revertability +
|
||||
# proper apply_order traceability via the manifest.
|
||||
includes:
|
||||
# bes2600 driver (c5x stack as shipped in pkgrel=3) — single-file
|
||||
# interim cumulative; per-series reconstruction tracked separately.
|
||||
- driver/bes2600/cumulative-c5x-danctnix/
|
||||
# pre-c-stack (factory + early cleanups), in cleanups order
|
||||
- driver/bes2600/factory-series/
|
||||
- driver/bes2600/factory-thread-dev/
|
||||
- driver/bes2600/pm-gate-on-handshake/
|
||||
- driver/bes2600/remove-chardev-user-interface/
|
||||
- driver/bes2600/enable-testmode/
|
||||
- driver/bes2600/tx-sdio-dma-oob-danctnix/
|
||||
- driver/bes2600/factory-drop-kernel-write-danctnix/
|
||||
- driver/bes2600/drop-dpd-file-paths-danctnix/
|
||||
- driver/bes2600/drop-orphan-file-io-danctnix/
|
||||
- driver/bes2600/pm-timeout-silence-danctnix/
|
||||
# c-stack (c5.1, c5.1.1, c5.2 + c5.2.1, c6.1, c6.2, c7)
|
||||
- driver/bes2600/scan-defer-on-reject-danctnix/
|
||||
- driver/bes2600/scan-defer-backoff-tune-danctnix/
|
||||
- driver/bes2600/lmac-recover-via-mmc-hw-reset-danctnix/ # c5.2 + c5.2.1 (multi-fn SDIO)
|
||||
- driver/bes2600/pm-state-resync-danctnix/
|
||||
- driver/bes2600/pm-wake-consume-state-danctnix/
|
||||
- driver/bes2600/pm-detect-firmware-unsupported-danctnix/
|
||||
# Patches A/B/F/C-v3/G/D/E/C2/H (in cleanups merge order)
|
||||
- driver/bes2600/decrypt-storm-fast-recover-danctnix/ # Patch A
|
||||
- driver/bes2600/connection-loss-fast-recover-danctnix/ # Patch B
|
||||
- driver/bes2600/cw1200-fix-backports-danctnix/ # Patches F3 + F2 + F1
|
||||
- driver/bes2600/sdio-rx-no-relay-danctnix/ # Patch C v3
|
||||
- driver/bes2600/license-spdx-restore-attribution-danctnix/ # Patch G
|
||||
- driver/bes2600/ba-lock-atomic-danctnix/ # Patch D
|
||||
- driver/bes2600/ps-state-lock-skip-pm-disabled-danctnix/ # Patch E
|
||||
- driver/bes2600/rx-list-batch-delivery-danctnix/ # Patch C2
|
||||
- driver/bes2600/bh-c-fossil-cleanup-danctnix/ # Patch H
|
||||
# close besser#1 — refuse multi-channel 5 GHz scans at driver boundary.
|
||||
- driver/bes2600/scan-filter-5ghz-danctnix/
|
||||
# GCC 15.2.1 build-fix for arm_neon.h + SHADOW_CALL_STACK interaction.
|
||||
# Runtime no-op as long as the config has CONFIG_SHADOW_CALL_STACK=n
|
||||
# (current ohm setting). Kept in the manifest for the day SCS gets
|
||||
# re-enabled. See reference_arm64_scs_arm_neon_gcc15 memory.
|
||||
- arch/arm64/xor-neon-ffixed-x18-scs-build-fix-danctnix/
|
||||
- arch/arm64/scs-arm-neon-build-fix/
|
||||
# close besser#18 — pending_record_lock SOFTIRQ-safe -> -unsafe inversion.
|
||||
# Mirror of marfrit/bes2600-dkms#11 (d95453c). 5-site spin_lock -> _bh.
|
||||
- driver/bes2600/queue-pending-record-lock-bh-danctnix/
|
||||
|
||||
# Explicitly NOT included (decision logged):
|
||||
# - debian-copyright-fsf-address: Debian packaging metadata, not kernel
|
||||
# - bare (non-danctnix) variants of the per-series mirrors: same
|
||||
# root-path bug as the -danctnix variants per the 2026-05-18 audit
|
||||
# - cumulative-c5x-danctnix: retired in favour of the per-series above
|
||||
# (kept on disk for one cycle as bisection reference)
|
||||
# - staging-prep-series-danctnix: duplicate of tx-sdio-dma-oob-danctnix
|
||||
# under an older branch name; kept on disk for one cycle, dropped here
|
||||
|
||||
config:
|
||||
source: hand-managed config file in boltzmann:~/src/besser/marfrit-besser/danctnix-besser-pkgbuild/kernel/config
|
||||
|
||||
-3
@@ -34,6 +34,3 @@ index 1234567..2345678 100644
|
||||
endif
|
||||
|
||||
lib-$(CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE) += uaccess_flushcache.o
|
||||
--
|
||||
2.54.0
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
# xor-neon-ffixed-x18-scs-build-fix-danctnix — GCC 15.2.1 build fix
|
||||
|
||||
Restores `-ffixed-x18` for `arch/arm64/lib/xor-neon.c` when
|
||||
`CONFIG_SHADOW_CALL_STACK=y`. GCC 15.2.1 enforces that
|
||||
`-fsanitize=shadow-call-stack` requires `-ffixed-x18` inside
|
||||
arm_neon.h's `#pragma GCC target()` push/pop blocks; CC_FLAGS_REMOVE
|
||||
strips the kernel-wide `-ffixed-x18` for xor-neon.o and CC_FLAGS_FPU
|
||||
does not restore it.
|
||||
|
||||
**Note on current ohm config**: `linux-pinetab2-danctnix-besser`
|
||||
config has `# CONFIG_SHADOW_CALL_STACK is not set` as of pkgrel=3,
|
||||
which makes this patch a runtime no-op (`$(if $(CONFIG_SHADOW_CALL_STACK),
|
||||
-ffixed-x18)` evaluates to nothing). Patch is kept in the manifest as
|
||||
belt-and-suspenders for the day SCS gets re-enabled (tracked in
|
||||
besser issue for GCC fix monitoring).
|
||||
|
||||
See [[reference_arm64_scs_arm_neon_gcc15]] for the full toolchain
|
||||
analysis. This patch is the upstream-friendly Makefile fix; the
|
||||
config-side `SHADOW_CALL_STACK=n` workaround is the immediate
|
||||
runtime mitigation. Both are present in pkgrel=3 for safety.
|
||||
+313
@@ -0,0 +1,313 @@
|
||||
From 8fd20308ed53678c863a0ef52fb2c754e3adc63c Mon Sep 17 00:00:00 2001
|
||||
From: Markus Fritsche <fritsche.markus@gmail.com>
|
||||
Date: Fri, 8 May 2026 00:17:46 +0200
|
||||
Subject: [PATCH 27/29] =?UTF-8?q?bes2600:=20Patch=20D=20=E2=80=94=20atomic?=
|
||||
=?UTF-8?q?ize=20ba=5Flock=20counters,=20drop=20the=20spinlock?=
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
The block-ack policy uses 4 int counters (ba_acc, ba_cnt, ba_acc_rx,
|
||||
ba_cnt_rx) bumped per data frame in the TX and RX hot paths under
|
||||
spin_lock_bh(&hw_priv->ba_lock). The lock was the heaviest per-frame
|
||||
synchronization cost remaining after Patch C v3 (which fixed the
|
||||
sdio_rx_work relay). Per the Opus structural critique (PR #8), this
|
||||
pattern matches mac80211 driver convention for per-frame statistics:
|
||||
atomic_t suffices, no lock needed.
|
||||
|
||||
Field-by-field changes in struct bes2600_common:
|
||||
ba_acc, ba_cnt, ba_acc_rx, ba_cnt_rx: int -> atomic_t
|
||||
ba_armed: new atomic_t (timer-arm flag)
|
||||
ba_ena: bool -> atomic_t
|
||||
ba_lock: removed (spinlock_t deleted)
|
||||
ba_hist: int (single-writer = ba_timer)
|
||||
|
||||
Producer hot path (txrx.c TX submit + RX receive):
|
||||
- atomic_add for the byte accumulator
|
||||
- atomic_inc for the frame counter
|
||||
- atomic_cmpxchg(&ba_armed, 0, 1) to claim the once-per-window
|
||||
mod_timer arm — at most ONE producer succeeds; race-free
|
||||
- no spin_lock_bh
|
||||
|
||||
Consumer paths (sta.c bes2600_ba_timer, sta.c disconnect-reset, sta.c
|
||||
bes2600_ba_work, debug.c debugfs reader):
|
||||
- atomic_read snapshots all 4 counters into locals; the threshold
|
||||
predicate (acc/cnt >= THLD) tolerates approximate snapshots — the
|
||||
timer fires periodically, a single misclassification just delays
|
||||
the policy update by one tick
|
||||
- atomic_set zeroes the counters at end of timer-callback window;
|
||||
racing producer increments after the snapshot are lost (acceptable
|
||||
for stats; same approximation the original lock allowed under
|
||||
contention)
|
||||
- atomic_set(&ba_armed, 0) re-enables the next window's arm
|
||||
|
||||
Followup-amenable simplification: ba_hist remains int because only
|
||||
the single ba_timer callback writes it; multiple writers would need
|
||||
to upgrade it too.
|
||||
|
||||
This patch follows the cw1200-mainline-idiom established by Patch C v3
|
||||
(structural fix, not bandaid). The cw1200 reference doesn't have a
|
||||
similar lock to compare; bes2600 inherited this from a later
|
||||
Bestechnic addition rather than the upstream tree.
|
||||
---
|
||||
bes2600/bes2600.h | 26 ++++++++++------
|
||||
bes2600/debug.c | 13 +++++---
|
||||
bes2600/main.c | 2 +-
|
||||
bes2600/sta.c | 77 ++++++++++++++++++++++++++++-------------------
|
||||
bes2600/txrx.c | 23 ++++++++------
|
||||
5 files changed, 85 insertions(+), 56 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/bes2600/bes2600.h b/drivers/staging/bes2600/bes2600.h
|
||||
index 84059c7..32bce5e 100644
|
||||
--- a/drivers/staging/bes2600/bes2600.h
|
||||
+++ b/drivers/staging/bes2600/bes2600.h
|
||||
@@ -353,15 +353,23 @@ struct bes2600_common {
|
||||
* Keeping in common structure for the time being. Will be moved to VIFF
|
||||
* after the mechanism is clear */
|
||||
u8 ba_tid_mask;
|
||||
- int ba_acc; /*TODO: Same as above */
|
||||
- int ba_cnt; /*TODO: Same as above */
|
||||
- int ba_cnt_rx; /*TODO: Same as above */
|
||||
- int ba_acc_rx; /*TODO: Same as above */
|
||||
- int ba_hist; /*TODO: Same as above */
|
||||
- struct timer_list ba_timer;/*TODO: Same as above */
|
||||
- spinlock_t ba_lock; /*TODO: Same as above */
|
||||
- bool ba_ena; /*TODO: Same as above */
|
||||
- struct work_struct ba_work; /*TODO: Same as above */
|
||||
+ /*
|
||||
+ * Patch D: ba_lock removed. Per-frame TX/RX hot-path bumped these
|
||||
+ * counters under spin_lock_bh; the lock did not protect any
|
||||
+ * compound invariant that atomic ops can't satisfy. Counters are
|
||||
+ * now atomic_t; ba_armed gates the once-per-window mod_timer
|
||||
+ * arm via cmpxchg so concurrent TX/RX at a fresh window each
|
||||
+ * try to claim the arm and exactly one succeeds.
|
||||
+ */
|
||||
+ atomic_t ba_acc;
|
||||
+ atomic_t ba_cnt;
|
||||
+ atomic_t ba_cnt_rx;
|
||||
+ atomic_t ba_acc_rx;
|
||||
+ atomic_t ba_armed;
|
||||
+ int ba_hist;
|
||||
+ struct timer_list ba_timer;
|
||||
+ atomic_t ba_ena;
|
||||
+ struct work_struct ba_work;
|
||||
bool is_BT_Present;
|
||||
bool is_go_thru_go_neg;
|
||||
u8 conf_listen_interval;
|
||||
diff --git a/drivers/staging/bes2600/debug.c b/drivers/staging/bes2600/debug.c
|
||||
index 47e27be..0ab79c0 100644
|
||||
--- a/drivers/staging/bes2600/debug.c
|
||||
+++ b/drivers/staging/bes2600/debug.c
|
||||
@@ -110,17 +110,20 @@ static int bes2600_status_show_common(struct seq_file *seq, void *v)
|
||||
int ba_cnt, ba_acc, ba_cnt_rx, ba_acc_rx, ba_avg = 0, ba_avg_rx = 0;
|
||||
bool ba_ena;
|
||||
|
||||
- spin_lock_bh(&hw_priv->ba_lock);
|
||||
- ba_cnt = hw_priv->debug->ba_cnt;
|
||||
- ba_acc = hw_priv->debug->ba_acc;
|
||||
+ /*
|
||||
+ * Patch D: ba_lock removed. hw_priv->debug->ba_* are written only
|
||||
+ * by the timer callback (single writer); reading without a lock is
|
||||
+ * fine for stats. ba_ena is atomic_t.
|
||||
+ */
|
||||
+ ba_cnt = hw_priv->debug->ba_cnt;
|
||||
+ ba_acc = hw_priv->debug->ba_acc;
|
||||
ba_cnt_rx = hw_priv->debug->ba_cnt_rx;
|
||||
ba_acc_rx = hw_priv->debug->ba_acc_rx;
|
||||
- ba_ena = hw_priv->ba_ena;
|
||||
+ ba_ena = !!atomic_read(&hw_priv->ba_ena);
|
||||
if (ba_cnt)
|
||||
ba_avg = ba_acc / ba_cnt;
|
||||
if (ba_cnt_rx)
|
||||
ba_avg_rx = ba_acc_rx / ba_cnt_rx;
|
||||
- spin_unlock_bh(&hw_priv->ba_lock);
|
||||
|
||||
seq_puts(seq, "BES2600 Wireless LAN driver status\n");
|
||||
seq_printf(seq, "Hardware: %d.%d\n",
|
||||
diff --git a/drivers/staging/bes2600/main.c b/drivers/staging/bes2600/main.c
|
||||
index 71dc4ae..8fc37b4 100644
|
||||
--- a/drivers/staging/bes2600/main.c
|
||||
+++ b/drivers/staging/bes2600/main.c
|
||||
@@ -501,7 +501,7 @@ static struct ieee80211_hw *bes2600_init_common(size_t hw_priv_data_len)
|
||||
INIT_LIST_HEAD(&hw_priv->event_queue);
|
||||
INIT_WORK(&hw_priv->event_handler, bes2600_event_handler);
|
||||
INIT_WORK(&hw_priv->ba_work, bes2600_ba_work);
|
||||
- spin_lock_init(&hw_priv->ba_lock);
|
||||
+ /* Patch D: ba_lock removed; ba_acc/ba_cnt/etc are atomic_t. */
|
||||
timer_setup(&hw_priv->ba_timer, bes2600_ba_timer, 0);
|
||||
|
||||
if (unlikely(bes2600_queue_stats_init(&hw_priv->tx_queue_stats,
|
||||
diff --git a/drivers/staging/bes2600/sta.c b/drivers/staging/bes2600/sta.c
|
||||
index 70b12f9..8af8150 100644
|
||||
--- a/drivers/staging/bes2600/sta.c
|
||||
+++ b/drivers/staging/bes2600/sta.c
|
||||
@@ -2362,14 +2362,19 @@ void bes2600_join_work(struct work_struct *work)
|
||||
//WARN_ON(wsm_reset(hw_priv, &reset, priv->if_id));
|
||||
WARN_ON(wsm_set_block_ack_policy(hw_priv,
|
||||
0, hw_priv->ba_tid_mask, priv->if_id));
|
||||
- spin_lock_bh(&hw_priv->ba_lock);
|
||||
- hw_priv->ba_ena = false;
|
||||
- hw_priv->ba_cnt = 0;
|
||||
- hw_priv->ba_acc = 0;
|
||||
+ /*
|
||||
+ * Patch D: ba_lock removed. Disconnect-reset clears the
|
||||
+ * counters and the arm flag; producers racing here cannot
|
||||
+ * cause harm — at worst they re-arm the timer and bump
|
||||
+ * counters that will be cleared on the next timer tick.
|
||||
+ */
|
||||
+ atomic_set(&hw_priv->ba_ena, 0);
|
||||
+ atomic_set(&hw_priv->ba_cnt, 0);
|
||||
+ atomic_set(&hw_priv->ba_acc, 0);
|
||||
hw_priv->ba_hist = 0;
|
||||
- hw_priv->ba_cnt_rx = 0;
|
||||
- hw_priv->ba_acc_rx = 0;
|
||||
- spin_unlock_bh(&hw_priv->ba_lock);
|
||||
+ atomic_set(&hw_priv->ba_cnt_rx, 0);
|
||||
+ atomic_set(&hw_priv->ba_acc_rx, 0);
|
||||
+ atomic_set(&hw_priv->ba_armed, 0);
|
||||
|
||||
mgmt_policy.protectedMgmtEnable = 0;
|
||||
mgmt_policy.unprotectedMgmtFramesAllowed = 1;
|
||||
@@ -2649,10 +2654,11 @@ void bes2600_ba_work(struct work_struct *work)
|
||||
return;*/
|
||||
|
||||
bes_devel("BA work****\n");
|
||||
- spin_lock_bh(&hw_priv->ba_lock);
|
||||
-// tx_ba_tid_mask = hw_priv->ba_ena ? hw_priv->ba_tid_mask : 0;
|
||||
+ /*
|
||||
+ * Patch D: ba_lock removed. ba_tid_mask is u8 set once at init
|
||||
+ * (main.c); reading it without a lock is fine.
|
||||
+ */
|
||||
tx_ba_tid_mask = hw_priv->ba_tid_mask;
|
||||
- spin_unlock_bh(&hw_priv->ba_lock);
|
||||
|
||||
wsm_lock_tx(hw_priv);
|
||||
|
||||
@@ -2665,37 +2671,49 @@ void bes2600_ba_work(struct work_struct *work)
|
||||
void bes2600_ba_timer(struct timer_list *t)
|
||||
{
|
||||
bool ba_ena;
|
||||
+ int cnt, acc, cnt_rx, acc_rx;
|
||||
struct bes2600_common *hw_priv = timer_container_of(hw_priv, t, ba_timer);
|
||||
|
||||
- spin_lock_bh(&hw_priv->ba_lock);
|
||||
- bes2600_debug_ba(hw_priv, hw_priv->ba_cnt, hw_priv->ba_acc,
|
||||
- hw_priv->ba_cnt_rx, hw_priv->ba_acc_rx);
|
||||
+ /*
|
||||
+ * Patch D: ba_lock removed. Snapshot atomic counters into locals
|
||||
+ * for the predicate evaluation; producers may race incrementing
|
||||
+ * after the snapshot but the resulting decision is approximate
|
||||
+ * which the policy already tolerates (next timer tick re-evaluates).
|
||||
+ */
|
||||
+ cnt = atomic_read(&hw_priv->ba_cnt);
|
||||
+ acc = atomic_read(&hw_priv->ba_acc);
|
||||
+ cnt_rx = atomic_read(&hw_priv->ba_cnt_rx);
|
||||
+ acc_rx = atomic_read(&hw_priv->ba_acc_rx);
|
||||
+
|
||||
+ bes2600_debug_ba(hw_priv, cnt, acc, cnt_rx, acc_rx);
|
||||
|
||||
if (atomic_read(&hw_priv->scan.in_progress)) {
|
||||
- hw_priv->ba_cnt = 0;
|
||||
- hw_priv->ba_acc = 0;
|
||||
- hw_priv->ba_cnt_rx = 0;
|
||||
- hw_priv->ba_acc_rx = 0;
|
||||
- goto skip_statistic_update;
|
||||
+ atomic_set(&hw_priv->ba_cnt, 0);
|
||||
+ atomic_set(&hw_priv->ba_acc, 0);
|
||||
+ atomic_set(&hw_priv->ba_cnt_rx, 0);
|
||||
+ atomic_set(&hw_priv->ba_acc_rx, 0);
|
||||
+ atomic_set(&hw_priv->ba_armed, 0);
|
||||
+ return;
|
||||
}
|
||||
|
||||
- if (hw_priv->ba_cnt >= BES2600_BLOCK_ACK_CNT &&
|
||||
- (hw_priv->ba_acc / hw_priv->ba_cnt >= BES2600_BLOCK_ACK_THLD ||
|
||||
- (hw_priv->ba_cnt_rx >= BES2600_BLOCK_ACK_CNT &&
|
||||
- hw_priv->ba_acc_rx / hw_priv->ba_cnt_rx >=
|
||||
+ if (cnt >= BES2600_BLOCK_ACK_CNT &&
|
||||
+ (acc / cnt >= BES2600_BLOCK_ACK_THLD ||
|
||||
+ (cnt_rx >= BES2600_BLOCK_ACK_CNT &&
|
||||
+ acc_rx / cnt_rx >=
|
||||
BES2600_BLOCK_ACK_THLD)))
|
||||
ba_ena = true;
|
||||
else
|
||||
ba_ena = false;
|
||||
|
||||
- hw_priv->ba_cnt = 0;
|
||||
- hw_priv->ba_acc = 0;
|
||||
- hw_priv->ba_cnt_rx = 0;
|
||||
- hw_priv->ba_acc_rx = 0;
|
||||
+ atomic_set(&hw_priv->ba_cnt, 0);
|
||||
+ atomic_set(&hw_priv->ba_acc, 0);
|
||||
+ atomic_set(&hw_priv->ba_cnt_rx, 0);
|
||||
+ atomic_set(&hw_priv->ba_acc_rx, 0);
|
||||
+ atomic_set(&hw_priv->ba_armed, 0);
|
||||
|
||||
- if (ba_ena != hw_priv->ba_ena) {
|
||||
+ if (ba_ena != !!atomic_read(&hw_priv->ba_ena)) {
|
||||
if (ba_ena || ++hw_priv->ba_hist >= BES2600_BLOCK_ACK_HIST) {
|
||||
- hw_priv->ba_ena = ba_ena;
|
||||
+ atomic_set(&hw_priv->ba_ena, ba_ena ? 1 : 0);
|
||||
hw_priv->ba_hist = 0;
|
||||
#if 0
|
||||
bes_devel("[STA] %s block ACK:\n",
|
||||
@@ -2705,9 +2723,6 @@ void bes2600_ba_timer(struct timer_list *t)
|
||||
}
|
||||
} else if (hw_priv->ba_hist)
|
||||
--hw_priv->ba_hist;
|
||||
-
|
||||
-skip_statistic_update:
|
||||
- spin_unlock_bh(&hw_priv->ba_lock);
|
||||
}
|
||||
|
||||
int bes2600_vif_setup(struct bes2600_vif *priv)
|
||||
diff --git a/drivers/staging/bes2600/txrx.c b/drivers/staging/bes2600/txrx.c
|
||||
index 3aef009..536b198 100644
|
||||
--- a/drivers/staging/bes2600/txrx.c
|
||||
+++ b/drivers/staging/bes2600/txrx.c
|
||||
@@ -996,14 +996,18 @@ bes2600_tx_h_ba_stat(struct bes2600_vif *priv,
|
||||
if (!ieee80211_is_data(t->hdr->frame_control))
|
||||
return;
|
||||
|
||||
- spin_lock_bh(&hw_priv->ba_lock);
|
||||
- hw_priv->ba_acc += t->skb->len - t->hdrlen;
|
||||
- if (!(hw_priv->ba_cnt_rx || hw_priv->ba_cnt)) {
|
||||
+ /*
|
||||
+ * Patch D: lock-free hot-path BA accounting. atomic_inc + atomic_add
|
||||
+ * each per-frame; the once-per-window timer-arm uses cmpxchg on
|
||||
+ * ba_armed so concurrent TX/RX can't both try to set the timer and
|
||||
+ * we don't need cross-counter coherency on the ba_cnt/ba_cnt_rx pair.
|
||||
+ */
|
||||
+ atomic_add(t->skb->len - t->hdrlen, &hw_priv->ba_acc);
|
||||
+ atomic_inc(&hw_priv->ba_cnt);
|
||||
+ if (atomic_cmpxchg(&hw_priv->ba_armed, 0, 1) == 0) {
|
||||
mod_timer(&hw_priv->ba_timer,
|
||||
jiffies + BES2600_BLOCK_ACK_INTERVAL);
|
||||
}
|
||||
- hw_priv->ba_cnt++;
|
||||
- spin_unlock_bh(&hw_priv->ba_lock);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -1651,14 +1655,13 @@ bes2600_rx_h_ba_stat(struct bes2600_vif *priv,
|
||||
if (!priv->setbssparams_done)
|
||||
return;
|
||||
|
||||
- spin_lock_bh(&hw_priv->ba_lock);
|
||||
- hw_priv->ba_acc_rx += skb_len - hdrlen;
|
||||
- if (!(hw_priv->ba_cnt_rx || hw_priv->ba_cnt)) {
|
||||
+ /* Patch D: lock-free hot-path BA accounting; see TX side comment. */
|
||||
+ atomic_add(skb_len - hdrlen, &hw_priv->ba_acc_rx);
|
||||
+ atomic_inc(&hw_priv->ba_cnt_rx);
|
||||
+ if (atomic_cmpxchg(&hw_priv->ba_armed, 0, 1) == 0) {
|
||||
mod_timer(&hw_priv->ba_timer,
|
||||
jiffies + BES2600_BLOCK_ACK_INTERVAL);
|
||||
}
|
||||
- hw_priv->ba_cnt_rx++;
|
||||
- spin_unlock_bh(&hw_priv->ba_lock);
|
||||
}
|
||||
|
||||
void bes2600_rx_cb(struct bes2600_vif *priv,
|
||||
--
|
||||
2.54.0
|
||||
|
||||
+725
@@ -0,0 +1,725 @@
|
||||
From 1b5374d35bcc75e0f393e3d841288f91812eb7dc Mon Sep 17 00:00:00 2001
|
||||
From: Markus Fritsche <fritsche.markus@gmail.com>
|
||||
Date: Fri, 8 May 2026 08:23:20 +0200
|
||||
Subject: [PATCH] =?UTF-8?q?bes2600:=20Patch=20H=20=E2=80=94=20bh.c=20hygie?=
|
||||
=?UTF-8?q?ne=20cleanup=20(drop=20fossil=20blocks,=20dead=20stubs)?=
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Per Opus structural critique §4.1 (#if 0 graveyard), §4.3 (asm
|
||||
volatile("nop") placeholder), §4.4 (BUG_ON in steady-state hot
|
||||
path). Pure source-tree cleanup, no functional change.
|
||||
|
||||
Removed:
|
||||
|
||||
1. bh.c lines 319-395 (76-line #if 0 block) — dead helper
|
||||
functions inherited from cw1200 ancestor:
|
||||
bes2600_bh_read_ctrl_reg, bes2600_get_skb, bes2600_put_skb,
|
||||
bes2600_device_wakeup. Compiled out for years.
|
||||
|
||||
2. bh.c lines 405-873 + line 1659 (the outer #if 0 / #else /
|
||||
#endif) — 468-line cw1200-ancestor bes2600_bh() function body,
|
||||
preserved verbatim alongside the active impl. Same function
|
||||
name, same goto labels. Maintenance hazard removed.
|
||||
|
||||
3. bh.c done: label body — `__bes2600_irq_enable(1)` placeholder
|
||||
(commented out) + `asm volatile ("nop")` filler. Both
|
||||
no-ops on bes2600 silicon.
|
||||
|
||||
4. bh.c post-loop "Explicitly disable device interrupts" block
|
||||
(sbus lock + __bes2600_irq_enable(0) + sbus unlock) — the
|
||||
stub call wrapped in lock/unlock ceremony. Dead.
|
||||
|
||||
5. hwio.c __bes2600_irq_enable() function definition —
|
||||
`int __bes2600_irq_enable(int enable) { return 0; }`. Stub.
|
||||
Removed entirely.
|
||||
|
||||
6. sbus.h __bes2600_irq_enable() forward declaration.
|
||||
|
||||
Replaced:
|
||||
|
||||
7. bh.c bes2600_bh outer-loop BUG_ON(hw_bufs_used > numInpChBufs)
|
||||
-> WARN_ON_ONCE. The BUG_ON ran every bh-loop iteration;
|
||||
tripping it on a bookkeeping bug locks the kernel up during
|
||||
normal operation — the wrong response to a (recoverable)
|
||||
accounting drift. WARN_ON_ONCE surfaces the issue without
|
||||
taking the system down.
|
||||
|
||||
Why __bes2600_irq_enable was a stub on bes2600:
|
||||
|
||||
cw1200 has the same-named function (drivers/net/wireless/st/cw1200/
|
||||
hwio.c:267) that does real work — reads ST90TDS_CONFIG_REG_ID and
|
||||
toggles the ST90TDS_CONF_IRQ_RDY_ENABLE bit. bes2600 inherited
|
||||
the function name + signature when forked, but the bes2600 chip's
|
||||
IRQ enable is managed by sdio_claim_irq + chip-side firmware, not
|
||||
by a driver-side enable register. Bestechnic kept the function as
|
||||
a no-op stub (return 0). Patch H removes the dead infrastructure.
|
||||
|
||||
Diff scope:
|
||||
|
||||
- bes2600/bh.c -578/+27 (mostly deletions)
|
||||
- bes2600/hwio.c -7/+7 (stub function -> comment block)
|
||||
- bes2600/sbus.h -2/+1 (declaration -> comment)
|
||||
- net: -578/+28 across 3 files
|
||||
|
||||
Build verification deferred — ohm offline. Pure-deletion change,
|
||||
no semantic risk; the deleted code was either #if 0-gated
|
||||
(never compiled) or stub-implementations (always returned 0).
|
||||
---
|
||||
bes2600/bh.c | 578 ++-----------------------------------------------
|
||||
bes2600/hwio.c | 11 +-
|
||||
bes2600/sbus.h | 3 +-
|
||||
3 files changed, 28 insertions(+), 564 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/bes2600/bh.c b/drivers/staging/bes2600/bh.c
|
||||
index 61f6991..67dfad4 100644
|
||||
--- a/drivers/staging/bes2600/bh.c
|
||||
+++ b/drivers/staging/bes2600/bh.c
|
||||
@@ -317,83 +317,6 @@ int wsm_release_buffer_to_fw(struct bes2600_vif *priv, int count)
|
||||
}
|
||||
#endif
|
||||
|
||||
-#if 0
|
||||
-static struct sk_buff *bes2600_get_skb(struct bes2600_common *hw_priv, size_t len)
|
||||
-{
|
||||
- struct sk_buff *skb;
|
||||
- size_t alloc_len = (len > SDIO_BLOCK_SIZE) ? len : SDIO_BLOCK_SIZE;
|
||||
-
|
||||
- if (len > SDIO_BLOCK_SIZE || !hw_priv->skb_cache) {
|
||||
- skb = dev_alloc_skb(alloc_len
|
||||
- + WSM_TX_EXTRA_HEADROOM
|
||||
- + 8 /* TKIP IV */
|
||||
- + 12 /* TKIP ICV + MIC */
|
||||
- - 2 /* Piggyback */);
|
||||
- /* In AP mode RXed SKB can be looped back as a broadcast.
|
||||
- * Here we reserve enough space for headers. */
|
||||
- skb_reserve(skb, WSM_TX_EXTRA_HEADROOM
|
||||
- + 8 /* TKIP IV */
|
||||
- - WSM_RX_EXTRA_HEADROOM);
|
||||
- } else {
|
||||
- skb = hw_priv->skb_cache;
|
||||
- hw_priv->skb_cache = NULL;
|
||||
- }
|
||||
- return skb;
|
||||
-}
|
||||
-
|
||||
-static void bes2600_put_skb(struct bes2600_common *hw_priv, struct sk_buff *skb)
|
||||
-{
|
||||
- if (hw_priv->skb_cache)
|
||||
- dev_kfree_skb(skb);
|
||||
- else
|
||||
- hw_priv->skb_cache = skb;
|
||||
-}
|
||||
-
|
||||
-static int bes2600_bh_read_ctrl_reg(struct bes2600_common *hw_priv,
|
||||
- u16 *ctrl_reg)
|
||||
-{
|
||||
- int ret;
|
||||
-
|
||||
- ret = bes2600_reg_read_16(hw_priv,
|
||||
- ST90TDS_CONTROL_REG_ID, ctrl_reg);
|
||||
- if (ret) {
|
||||
- ret = bes2600_reg_read_16(hw_priv,
|
||||
- ST90TDS_CONTROL_REG_ID, ctrl_reg);
|
||||
- if (ret)
|
||||
- bes_err("[BH] Failed to read control register.\n");
|
||||
- }
|
||||
-
|
||||
- return ret;
|
||||
-}
|
||||
-
|
||||
-static int bes2600_device_wakeup(struct bes2600_common *hw_priv)
|
||||
-{
|
||||
- u16 ctrl_reg;
|
||||
- int ret;
|
||||
-
|
||||
- bes_devel("[BH] Device wakeup.\n");
|
||||
-
|
||||
- /* To force the device to be always-on, the host sets WLAN_UP to 1 */
|
||||
- ret = bes2600_reg_write_16(hw_priv, ST90TDS_CONTROL_REG_ID,
|
||||
- ST90TDS_CONT_WUP_BIT);
|
||||
- if (WARN_ON(ret))
|
||||
- return ret;
|
||||
-
|
||||
- ret = bes2600_bh_read_ctrl_reg(hw_priv, &ctrl_reg);
|
||||
- if (WARN_ON(ret))
|
||||
- return ret;
|
||||
-
|
||||
- /* If the device returns WLAN_RDY as 1, the device is active and will
|
||||
- * remain active. */
|
||||
- if (ctrl_reg & ST90TDS_CONT_RDY_BIT) {
|
||||
- bes_devel("[BH] Device awake.\n");
|
||||
- return 1;
|
||||
- }
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-#endif
|
||||
|
||||
/* Must be called from BH thraed. */
|
||||
void bes2600_enable_powersave(struct bes2600_vif *priv,
|
||||
@@ -403,475 +326,6 @@ void bes2600_enable_powersave(struct bes2600_vif *priv,
|
||||
priv->powersave_enabled = enable;
|
||||
}
|
||||
|
||||
-#if 0
|
||||
-#define INTERRUPT_WORKAROUND
|
||||
-static int bes2600_bh(void *arg)
|
||||
-{
|
||||
- struct bes2600_common *hw_priv = arg;
|
||||
- struct bes2600_vif *priv = NULL;
|
||||
- struct sk_buff *skb_rx = NULL;
|
||||
- size_t read_len = 0;
|
||||
- int rx, tx, term, suspend;
|
||||
- struct wsm_hdr *wsm;
|
||||
- size_t wsm_len;
|
||||
- int wsm_id;
|
||||
- u8 wsm_seq;
|
||||
- int rx_resync = 1;
|
||||
- u16 ctrl_reg = 0;
|
||||
- int tx_allowed;
|
||||
- int pending_tx = 0;
|
||||
- int tx_burst;
|
||||
- int rx_burst = 0;
|
||||
- long status;
|
||||
-#if defined(CONFIG_BES2600_WSM_DUMPS)
|
||||
- size_t wsm_dump_max = -1;
|
||||
-#endif
|
||||
- u32 dummy;
|
||||
- bool powersave_enabled;
|
||||
- int i;
|
||||
- int vif_selected;
|
||||
-
|
||||
- for (;;) {
|
||||
- powersave_enabled = 1;
|
||||
- spin_lock(&hw_priv->vif_list_lock);
|
||||
- bes2600_for_each_vif(hw_priv, priv, i) {
|
||||
-#ifdef P2P_MULTIVIF
|
||||
- if ((i = (CW12XX_MAX_VIFS - 1)) || !priv)
|
||||
-#else
|
||||
- if (!priv)
|
||||
-#endif
|
||||
- continue;
|
||||
- powersave_enabled &= !!priv->powersave_enabled;
|
||||
- }
|
||||
- spin_unlock(&hw_priv->vif_list_lock);
|
||||
- if (!hw_priv->hw_bufs_used
|
||||
- && powersave_enabled
|
||||
- && !hw_priv->device_can_sleep
|
||||
- && !atomic_read(&hw_priv->recent_scan)) {
|
||||
- status = HZ/8;
|
||||
- bes_devel("[BH] No Device wakedown.\n");
|
||||
-#ifndef FPGA_SETUP
|
||||
- WARN_ON(bes2600_reg_write_16(hw_priv,
|
||||
- ST90TDS_CONTROL_REG_ID, 0));
|
||||
- hw_priv->device_can_sleep = true;
|
||||
-#endif
|
||||
- } else if (hw_priv->hw_bufs_used)
|
||||
- /* Interrupt loss detection */
|
||||
- status = HZ/8;
|
||||
- else
|
||||
- status = HZ/8;
|
||||
-
|
||||
- /* Dummy Read for SDIO retry mechanism*/
|
||||
- if (((atomic_read(&hw_priv->bh_rx) == 0) &&
|
||||
- (atomic_read(&hw_priv->bh_tx) == 0)))
|
||||
- bes2600_reg_read(hw_priv, ST90TDS_CONFIG_REG_ID,
|
||||
- &dummy, sizeof(dummy));
|
||||
-#if defined(CONFIG_BES2600_WSM_DUMPS_SHORT)
|
||||
- wsm_dump_max = hw_priv->wsm_dump_max_size;
|
||||
-#endif /* CONFIG_BES2600_WSM_DUMPS_SHORT */
|
||||
-
|
||||
-#ifdef INTERRUPT_WORKAROUND
|
||||
- /* If a packet has already been txed to the device then read the
|
||||
- control register for a probable interrupt miss before going
|
||||
- further to wait for interrupt; if the read length is non-zero
|
||||
- then it means there is some data to be received */
|
||||
- if (hw_priv->hw_bufs_used) {
|
||||
- bes2600_bh_read_ctrl_reg(hw_priv, &ctrl_reg);
|
||||
- if(ctrl_reg & ST90TDS_CONT_NEXT_LEN_MASK)
|
||||
- {
|
||||
- rx = 1;
|
||||
- goto test;
|
||||
- }
|
||||
- }
|
||||
-#endif
|
||||
-
|
||||
- status = wait_event_interruptible_timeout(hw_priv->bh_wq, ({
|
||||
- rx = atomic_xchg(&hw_priv->bh_rx, 0);
|
||||
- tx = atomic_xchg(&hw_priv->bh_tx, 0);
|
||||
- term = atomic_xchg(&hw_priv->bh_term, 0);
|
||||
- suspend = pending_tx ?
|
||||
- 0 : atomic_read(&hw_priv->bh_suspend);
|
||||
- (rx || tx || term || suspend || hw_priv->bh_error);
|
||||
- }), status);
|
||||
-
|
||||
- if (status < 0 || term || hw_priv->bh_error)
|
||||
- break;
|
||||
-
|
||||
-#ifdef INTERRUPT_WORKAROUND
|
||||
- if (!status) {
|
||||
- bes2600_bh_read_ctrl_reg(hw_priv, &ctrl_reg);
|
||||
- if(ctrl_reg & ST90TDS_CONT_NEXT_LEN_MASK)
|
||||
- {
|
||||
- bes_err("MISS 1\n");
|
||||
- rx = 1;
|
||||
- goto test;
|
||||
- }
|
||||
- }
|
||||
-#endif
|
||||
- if (!status && hw_priv->hw_bufs_used) {
|
||||
- unsigned long timestamp = jiffies;
|
||||
- long timeout;
|
||||
- bool pending = false;
|
||||
- int i;
|
||||
-
|
||||
- wiphy_warn(hw_priv->hw->wiphy, "Missed interrupt?\n");
|
||||
- rx = 1;
|
||||
-
|
||||
- /* Get a timestamp of "oldest" frame */
|
||||
- for (i = 0; i < 4; ++i)
|
||||
- pending |= bes2600_queue_get_xmit_timestamp(
|
||||
- &hw_priv->tx_queue[i],
|
||||
- ×tamp, -1,
|
||||
- hw_priv->pending_frame_id);
|
||||
-
|
||||
- /* Check if frame transmission is timed out.
|
||||
- * Add an extra second with respect to possible
|
||||
- * interrupt loss. */
|
||||
- timeout = timestamp +
|
||||
- WSM_CMD_LAST_CHANCE_TIMEOUT +
|
||||
- 1 * HZ -
|
||||
- jiffies;
|
||||
-
|
||||
- /* And terminate BH tread if the frame is "stuck" */
|
||||
- if (pending && timeout < 0) {
|
||||
- //wiphy_warn(priv->hw->wiphy,
|
||||
- // "Timeout waiting for TX confirm.\n");
|
||||
- bes_devel("bes2600_bh: Timeout waiting for TX confirm.\n");
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
-#if defined(CONFIG_BES2600_DUMP_ON_ERROR)
|
||||
- BUG_ON(1);
|
||||
-#endif /* CONFIG_BES2600_DUMP_ON_ERROR */
|
||||
- } else if (!status) {
|
||||
- if (!hw_priv->device_can_sleep
|
||||
- && !atomic_read(&hw_priv->recent_scan)) {
|
||||
- bes_devel("[BH] Device wakedown. Timeout.\n");
|
||||
-#ifndef FPGA_SETUP
|
||||
- WARN_ON(bes2600_reg_write_16(hw_priv,
|
||||
- ST90TDS_CONTROL_REG_ID, 0));
|
||||
- hw_priv->device_can_sleep = true;
|
||||
-#endif
|
||||
- }
|
||||
- continue;
|
||||
- } else if (suspend) {
|
||||
- bes_devel("[BH] Device suspend.\n");
|
||||
- powersave_enabled = 1;
|
||||
- spin_lock(&hw_priv->vif_list_lock);
|
||||
- bes2600_for_each_vif(hw_priv, priv, i) {
|
||||
-#ifdef P2P_MULTIVIF
|
||||
- if ((i = (CW12XX_MAX_VIFS - 1)) || !priv)
|
||||
-#else
|
||||
- if (!priv)
|
||||
-#endif
|
||||
- continue;
|
||||
- powersave_enabled &= !!priv->powersave_enabled;
|
||||
- }
|
||||
- spin_unlock(&hw_priv->vif_list_lock);
|
||||
- if (powersave_enabled) {
|
||||
- bes_devel("[BH] No Device wakedown. Suspend.\n");
|
||||
-#ifndef FPGA_SETUP
|
||||
- WARN_ON(bes2600_reg_write_16(hw_priv,
|
||||
- ST90TDS_CONTROL_REG_ID, 0));
|
||||
- hw_priv->device_can_sleep = true;
|
||||
-#endif
|
||||
- }
|
||||
-
|
||||
- atomic_set(&hw_priv->bh_suspend, BES2600_BH_SUSPENDED);
|
||||
- wake_up(&hw_priv->bh_evt_wq);
|
||||
- status = wait_event_interruptible(hw_priv->bh_wq,
|
||||
- BES2600_BH_RESUME == atomic_read(
|
||||
- &hw_priv->bh_suspend));
|
||||
- if (status < 0) {
|
||||
- wiphy_err(hw_priv->hw->wiphy,
|
||||
- "%s: Failed to wait for resume: %ld.\n",
|
||||
- __func__, status);
|
||||
- break;
|
||||
- }
|
||||
- bes_devel("[BH] Device resume.\n");
|
||||
- atomic_set(&hw_priv->bh_suspend, BES2600_BH_RESUMED);
|
||||
- wake_up(&hw_priv->bh_evt_wq);
|
||||
- atomic_inc(&hw_priv->bh_rx);
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
-test:
|
||||
- tx += pending_tx;
|
||||
- pending_tx = 0;
|
||||
-
|
||||
- if (rx) {
|
||||
- size_t alloc_len;
|
||||
- u8 *data;
|
||||
-
|
||||
-#ifdef INTERRUPT_WORKAROUND
|
||||
- if(!(ctrl_reg & ST90TDS_CONT_NEXT_LEN_MASK))
|
||||
-#endif
|
||||
- if (WARN_ON(bes2600_bh_read_ctrl_reg(
|
||||
- hw_priv, &ctrl_reg)))
|
||||
- break;
|
||||
-rx:
|
||||
- read_len = (ctrl_reg & ST90TDS_CONT_NEXT_LEN_MASK) * 2;
|
||||
- if (!read_len) {
|
||||
- rx_burst = 0;
|
||||
- goto tx;
|
||||
- }
|
||||
-
|
||||
- if (WARN_ON((read_len < sizeof(struct wsm_hdr)) ||
|
||||
- (read_len > EFFECTIVE_BUF_SIZE))) {
|
||||
- bes_devel("Invalid read len: %d", read_len);
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
- /* Add SIZE of PIGGYBACK reg (CONTROL Reg)
|
||||
- * to the NEXT Message length + 2 Bytes for SKB */
|
||||
- read_len = read_len + 2;
|
||||
-
|
||||
-#if defined(CONFIG_BES2600_NON_POWER_OF_TWO_BLOCKSIZES)
|
||||
- alloc_len = hw_priv->sbus_ops->align_size(
|
||||
- hw_priv->sbus_priv, read_len);
|
||||
-#else /* CONFIG_BES2600_NON_POWER_OF_TWO_BLOCKSIZES */
|
||||
- /* Platform's SDIO workaround */
|
||||
- alloc_len = read_len & ~(SDIO_BLOCK_SIZE - 1);
|
||||
- if (read_len & (SDIO_BLOCK_SIZE - 1))
|
||||
- alloc_len += SDIO_BLOCK_SIZE;
|
||||
-#endif /* CONFIG_BES2600_NON_POWER_OF_TWO_BLOCKSIZES */
|
||||
-
|
||||
- /* Check if not exceeding BES2600 capabilities */
|
||||
- if (WARN_ON_ONCE(alloc_len > EFFECTIVE_BUF_SIZE))
|
||||
- bes_devel("Read aligned len: %d\n", alloc_len);
|
||||
-
|
||||
- skb_rx = bes2600_get_skb(hw_priv, alloc_len);
|
||||
- if (WARN_ON(!skb_rx))
|
||||
- break;
|
||||
-
|
||||
- skb_trim(skb_rx, 0);
|
||||
- skb_put(skb_rx, read_len);
|
||||
- data = skb_rx->data;
|
||||
- if (WARN_ON(!data))
|
||||
- break;
|
||||
-
|
||||
- if (WARN_ON(bes2600_data_read(hw_priv, data, alloc_len)))
|
||||
- break;
|
||||
-
|
||||
- /* Piggyback */
|
||||
- ctrl_reg = __le16_to_cpu(
|
||||
- ((__le16 *)data)[alloc_len / 2 - 1]);
|
||||
-
|
||||
- wsm = (struct wsm_hdr *)data;
|
||||
- wsm_len = __le32_to_cpu(wsm->len);
|
||||
- if (WARN_ON(wsm_len > read_len))
|
||||
- break;
|
||||
-
|
||||
-#if defined(CONFIG_BES2600_WSM_DUMPS)
|
||||
- if (unlikely(hw_priv->wsm_enable_wsm_dumps)) {
|
||||
- u16 msgid, ifid;
|
||||
- u16 *p = (u16 *)data;
|
||||
- msgid = (*(p + 1)) & 0xC3F;
|
||||
- ifid = (*(p + 1)) >> 6;
|
||||
- ifid &= 0xF;
|
||||
- bes_devel("[DUMP] <<< msgid 0x%.4X ifid %d len %d\n", msgid, ifid, *p);
|
||||
- print_hex_dump(KERN_DEBUG, "<-- ", DUMP_PREFIX_NONE, data, min(wsm_len, wsm_dump_max));
|
||||
- }
|
||||
-#endif /* CONFIG_BES2600_WSM_DUMPS */
|
||||
-
|
||||
- wsm_id = __le32_to_cpu(wsm->id) & 0xFFF;
|
||||
- wsm_seq = (__le32_to_cpu(wsm->id) >> 13) & 7;
|
||||
-
|
||||
- skb_trim(skb_rx, wsm_len);
|
||||
-
|
||||
- if (unlikely(wsm_id == 0x0800)) {
|
||||
- wsm_handle_exception(hw_priv,
|
||||
- &data[sizeof(*wsm)],
|
||||
- wsm_len - sizeof(*wsm));
|
||||
- break;
|
||||
- } else if (unlikely(!rx_resync)) {
|
||||
- if (WARN_ON(wsm_seq != hw_priv->wsm_rx_seq)) {
|
||||
-#if defined(CONFIG_BES2600_DUMP_ON_ERROR)
|
||||
- BUG_ON(1);
|
||||
-#endif /* CONFIG_BES2600_DUMP_ON_ERROR */
|
||||
- break;
|
||||
- }
|
||||
- }
|
||||
- hw_priv->wsm_rx_seq = (wsm_seq + 1) & 7;
|
||||
- rx_resync = 0;
|
||||
-
|
||||
- if (wsm_id & 0x0400) {
|
||||
- int rc = wsm_release_tx_buffer(hw_priv, 1);
|
||||
- if (WARN_ON(rc < 0))
|
||||
- break;
|
||||
- else if (rc > 0)
|
||||
- tx = 1;
|
||||
- }
|
||||
-
|
||||
- /* bes2600_wsm_rx takes care on SKB livetime */
|
||||
- if (WARN_ON(wsm_handle_rx(hw_priv, wsm_id, wsm,
|
||||
- &skb_rx)))
|
||||
- break;
|
||||
-
|
||||
- if (skb_rx) {
|
||||
- bes2600_put_skb(hw_priv, skb_rx);
|
||||
- skb_rx = NULL;
|
||||
- }
|
||||
-
|
||||
- read_len = 0;
|
||||
-
|
||||
- if (rx_burst) {
|
||||
- bes2600_debug_rx_burst(hw_priv);
|
||||
- --rx_burst;
|
||||
- goto rx;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
-tx:
|
||||
- BUG_ON(hw_priv->hw_bufs_used > hw_priv->wsm_caps.numInpChBufs);
|
||||
- tx_burst = hw_priv->wsm_caps.numInpChBufs -
|
||||
- hw_priv->hw_bufs_used;
|
||||
- tx_allowed = tx_burst > 0;
|
||||
- if (tx && tx_allowed) {
|
||||
- size_t tx_len;
|
||||
- u8 *data;
|
||||
- int ret;
|
||||
-
|
||||
- if (hw_priv->device_can_sleep) {
|
||||
- ret = bes2600_device_wakeup(hw_priv);
|
||||
- if (WARN_ON(ret < 0))
|
||||
- break;
|
||||
- else if (ret)
|
||||
- hw_priv->device_can_sleep = false;
|
||||
- else {
|
||||
- /* Wait for "awake" interrupt */
|
||||
- pending_tx = tx;
|
||||
- continue;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- wsm_alloc_tx_buffer(hw_priv);
|
||||
- ret = wsm_get_tx(hw_priv, &data, &tx_len, &tx_burst,
|
||||
- &vif_selected);
|
||||
- if (ret <= 0) {
|
||||
- wsm_release_tx_buffer(hw_priv, 1);
|
||||
- if (WARN_ON(ret < 0))
|
||||
- break;
|
||||
- } else {
|
||||
- wsm = (struct wsm_hdr *)data;
|
||||
- BUG_ON(tx_len < sizeof(*wsm));
|
||||
- BUG_ON(__le32_to_cpu(wsm->len) != tx_len);
|
||||
-
|
||||
-#if 0 /* count is not implemented */
|
||||
- if (ret > 1)
|
||||
- atomic_inc(&hw_priv->bh_tx);
|
||||
-#else
|
||||
- atomic_inc(&hw_priv->bh_tx);
|
||||
-#endif
|
||||
-
|
||||
-#if defined(CONFIG_BES2600_NON_POWER_OF_TWO_BLOCKSIZES)
|
||||
- if (tx_len <= 8)
|
||||
- tx_len = 16;
|
||||
- tx_len = hw_priv->sbus_ops->align_size(
|
||||
- hw_priv->sbus_priv, tx_len);
|
||||
-#else /* CONFIG_BES2600_NON_POWER_OF_TWO_BLOCKSIZES */
|
||||
- /* HACK!!! Platform limitation.
|
||||
- * It is also supported by upper layer:
|
||||
- * there is always enough space at the
|
||||
- * end of the buffer. */
|
||||
- if (tx_len & (SDIO_BLOCK_SIZE - 1)) {
|
||||
- tx_len &= ~(SDIO_BLOCK_SIZE - 1);
|
||||
- tx_len += SDIO_BLOCK_SIZE;
|
||||
- }
|
||||
-#endif /* CONFIG_BES2600_NON_POWER_OF_TWO_BLOCKSIZES */
|
||||
-
|
||||
- /* Check if not exceeding BES2600
|
||||
- capabilities */
|
||||
- if (WARN_ON_ONCE(tx_len > EFFECTIVE_BUF_SIZE))
|
||||
- bes_devel("Write aligned len: %d\n", tx_len);
|
||||
-
|
||||
- wsm->id &= __cpu_to_le32(
|
||||
- ~WSM_TX_SEQ(WSM_TX_SEQ_MAX));
|
||||
- wsm->id |= cpu_to_le32(WSM_TX_SEQ(
|
||||
- hw_priv->wsm_tx_seq));
|
||||
-
|
||||
- if (WARN_ON(bes2600_data_write(hw_priv,
|
||||
- data, tx_len))) {
|
||||
- wsm_release_tx_buffer(hw_priv, 1);
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
- if (vif_selected != -1) {
|
||||
- hw_priv->hw_bufs_used_vif[
|
||||
- vif_selected]++;
|
||||
- }
|
||||
-
|
||||
-#if defined(CONFIG_BES2600_WSM_DUMPS)
|
||||
- if (unlikely(hw_priv->wsm_enable_wsm_dumps)) {
|
||||
- u16 msgid, ifid;
|
||||
- u16 *p = (u16 *)data;
|
||||
- msgid = (*(p + 1)) & 0x3F;
|
||||
- ifid = (*(p + 1)) >> 6;
|
||||
- ifid &= 0xF;
|
||||
- if (msgid == 0x0006)
|
||||
- bes_devel("[DUMP] >>> msgid 0x%.4X ifid %d len %d MIB 0x%.4X\n", msgid, ifid, *p, *(p + 2));
|
||||
- else
|
||||
- bes_devel("[DUMP] >>> msgid 0x%.4X ifid %d len %d\n", msgid, ifid, *p);
|
||||
- print_hex_dump(KERN_DEBUG, "--> ", DUMP_PREFIX_NONE, data, min(__le32_to_cpu(wsm->len), wsm_dump_max));
|
||||
- }
|
||||
-#endif /* CONFIG_BES2600_WSM_DUMPS */
|
||||
-
|
||||
- wsm_txed(hw_priv, data);
|
||||
- hw_priv->wsm_tx_seq = (hw_priv->wsm_tx_seq + 1)
|
||||
- & WSM_TX_SEQ_MAX;
|
||||
-
|
||||
- if (tx_burst > 1) {
|
||||
- bes2600_debug_tx_burst(hw_priv);
|
||||
- ++rx_burst;
|
||||
- goto tx;
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- if (ctrl_reg & ST90TDS_CONT_NEXT_LEN_MASK)
|
||||
- goto rx;
|
||||
- }
|
||||
-
|
||||
- if (skb_rx) {
|
||||
- bes2600_put_skb(hw_priv, skb_rx);
|
||||
- skb_rx = NULL;
|
||||
- }
|
||||
-
|
||||
-
|
||||
- if (!term) {
|
||||
- bes_devel("[BH] Fatal error, exitting.\n");
|
||||
-#if defined(CONFIG_BES2600_DUMP_ON_ERROR)
|
||||
- BUG_ON(1);
|
||||
-#endif /* CONFIG_BES2600_DUMP_ON_ERROR */
|
||||
- hw_priv->bh_error = 1;
|
||||
-#if defined(CONFIG_BES2600_USE_STE_EXTENSIONS)
|
||||
- spin_lock(&hw_priv->vif_list_lock);
|
||||
- bes2600_for_each_vif(hw_priv, priv, i) {
|
||||
- if (!priv)
|
||||
- continue;
|
||||
- ieee80211_driver_hang_notify(priv->vif, GFP_KERNEL);
|
||||
- }
|
||||
- spin_unlock(&hw_priv->vif_list_lock);
|
||||
- bes2600_pm_stay_awake(&hw_priv->pm_state, 3*HZ);
|
||||
-#endif
|
||||
- /* TODO: schedule_work(recovery) */
|
||||
-#ifndef HAS_PUT_TASK_STRUCT
|
||||
- /* The only reason of having this stupid code here is
|
||||
- * that __put_task_struct is not exported by kernel. */
|
||||
- for (;;) {
|
||||
- int status = wait_event_interruptible(hw_priv->bh_wq, ({
|
||||
- term = atomic_xchg(&hw_priv->bh_term, 0);
|
||||
- (term);
|
||||
- }));
|
||||
-
|
||||
- if (status || term)
|
||||
- break;
|
||||
- }
|
||||
-#endif
|
||||
- }
|
||||
- return 0;
|
||||
-}
|
||||
-#else
|
||||
|
||||
extern int bes2600_bh_read_ctrl_reg(struct bes2600_common *priv, u32 *ctrl_reg);
|
||||
|
||||
@@ -1599,7 +1053,15 @@ static int bes2600_bh(void *arg)
|
||||
|
||||
tx = 0;
|
||||
|
||||
- BUG_ON(hw_priv->hw_bufs_used > hw_priv->wsm_caps.numInpChBufs);
|
||||
+ /*
|
||||
+ * Patch H: BUG_ON -> WARN_ON_ONCE in the steady-state
|
||||
+ * hot path. The original BUG_ON ran every bh-loop
|
||||
+ * iteration; tripping it on a bookkeeping bug locks
|
||||
+ * the kernel up during normal operation, which is
|
||||
+ * the wrong response. WARN_ON_ONCE surfaces the
|
||||
+ * issue without taking the system down.
|
||||
+ */
|
||||
+ WARN_ON_ONCE(hw_priv->hw_bufs_used > hw_priv->wsm_caps.numInpChBufs);
|
||||
tx_burst = hw_priv->wsm_caps.numInpChBufs - hw_priv->hw_bufs_used;
|
||||
tx_allowed = tx_burst > 0;
|
||||
|
||||
@@ -1643,18 +1105,19 @@ static int bes2600_bh(void *arg)
|
||||
goto tx;
|
||||
|
||||
done:
|
||||
- /* Re-enable device interrupts */
|
||||
- //hw_priv->sbus_ops->lock(hw_priv->sbus_priv);
|
||||
- //__bes2600_irq_enable(1);
|
||||
- //hw_priv->sbus_ops->unlock(hw_priv->sbus_priv);
|
||||
- asm volatile ("nop");
|
||||
+ /*
|
||||
+ * Patch H: dropped the dead `__bes2600_irq_enable(1)` /
|
||||
+ * `asm volatile("nop")` placeholder that used to sit here.
|
||||
+ * `__bes2600_irq_enable()` is a stub that returns 0 on
|
||||
+ * bes2600 silicon — the IRQ is managed by sdio_claim_irq
|
||||
+ * and chip-side firmware, not by a driver-side enable bit.
|
||||
+ * (cw1200 inherited the function from a different chip
|
||||
+ * shape; bes2600 kept the stub but the call sites are
|
||||
+ * meaningless.)
|
||||
+ */
|
||||
+ ;
|
||||
}
|
||||
|
||||
- /* Explicitly disable device interrupts */
|
||||
- hw_priv->sbus_ops->lock(hw_priv->sbus_priv);
|
||||
- __bes2600_irq_enable(0);
|
||||
- hw_priv->sbus_ops->unlock(hw_priv->sbus_priv);
|
||||
-
|
||||
if (!term) {
|
||||
bes_err("[BH] Fatal error, exiting.\n");
|
||||
sdio_work_debug(hw_priv->sbus_priv);
|
||||
@@ -1663,4 +1126,3 @@ static int bes2600_bh(void *arg)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
-#endif
|
||||
diff --git a/drivers/staging/bes2600/hwio.c b/drivers/staging/bes2600/hwio.c
|
||||
index 0934a13..1a63e4f 100644
|
||||
--- a/drivers/staging/bes2600/hwio.c
|
||||
+++ b/drivers/staging/bes2600/hwio.c
|
||||
@@ -324,7 +324,10 @@ out:
|
||||
}
|
||||
#endif
|
||||
|
||||
-int __bes2600_irq_enable(int enable)
|
||||
-{
|
||||
- return 0;
|
||||
-}
|
||||
+/*
|
||||
+ * Patch H: __bes2600_irq_enable stub removed. It was a no-op
|
||||
+ * (always returned 0) inherited from cw1200 where the analogous
|
||||
+ * function manipulates the chip's IRQ-enable register. bes2600
|
||||
+ * silicon manages SDIO IRQ via sdio_claim_irq and chip-side
|
||||
+ * firmware — there is no driver-side enable register to write.
|
||||
+ */
|
||||
diff --git a/drivers/staging/bes2600/sbus.h b/drivers/staging/bes2600/sbus.h
|
||||
index 43c2dae..4193084 100644
|
||||
--- a/drivers/staging/bes2600/sbus.h
|
||||
+++ b/drivers/staging/bes2600/sbus.h
|
||||
@@ -95,7 +95,6 @@ struct sbus_ops {
|
||||
|
||||
void bes2600_irq_handler(struct bes2600_common *priv);
|
||||
|
||||
-/* This MUST be wrapped with hwbus_ops->lock/unlock! */
|
||||
-int __bes2600_irq_enable(int enable);
|
||||
+/* Patch H: __bes2600_irq_enable removed (was a stub). */
|
||||
|
||||
#endif /* BES2600_SBUS_H */
|
||||
--
|
||||
2.54.0
|
||||
|
||||
+279
@@ -0,0 +1,279 @@
|
||||
From 06fab777454d36ec5178730d8423285c2457d3ba Mon Sep 17 00:00:00 2001
|
||||
From: "Claude (noether)" <claude@reauktion.de>
|
||||
Date: Thu, 7 May 2026 11:30:09 +0200
|
||||
Subject: [PATCH 21/29] bes2600: bus_reset on connection-loss storm to dodge
|
||||
assoc-comeback blackhole
|
||||
|
||||
When mac80211 declares connection loss against this AP (typically driven
|
||||
by inactivity-deauth or beacon-loss), the userspace reauth that follows
|
||||
sometimes enters a long blackhole: the AP responds to auth with success
|
||||
but defers assoc with the 802.11v "assoc comeback" timer; ohm retries
|
||||
faster than the comeback grants permission; the AP eventually fires an
|
||||
unprotected deauth-reason-6 ("Class 2 frame received from non-
|
||||
authenticated station"), and recovery only completes via cross-SSID or
|
||||
cross-channel fallback. Receipts: ~86 s blackhole observed in the
|
||||
phase-7 rep on 2026-05-07 02:42, with three subsequent BSSIDs returning
|
||||
assoc comeback timeouts before reason-9 (STA_REQ_ASSOC_WITHOUT_AUTH)
|
||||
fired. Documented in marfrit/besser:notes/phase4-2026-05-07.md.
|
||||
|
||||
When N=3 driver-side connection_loss decisions fire within a 60 s window
|
||||
on the same vif, skip the ieee80211_connection_loss() path and trigger
|
||||
the c5.2-introduced bes2600_chrdev_do_bus_reset() instead. The bus
|
||||
reset removes and re-probes the chip; userspace re-associates with a
|
||||
fresh chip state, dodging the AP's comeback-timer rejection cycle.
|
||||
|
||||
Predicted Phase 7 delta vs current baseline:
|
||||
- api_connection_loss rate: unchanged (we don't address the trigger)
|
||||
- conditional probability of >5 s blackhole given event: <= 30 %
|
||||
- worst-case recovery: 86 s -> < 10 s
|
||||
|
||||
Contract pin: bes2600_chrdev_do_bus_reset(sbus_ops, sbus_priv) at
|
||||
bes2600/bes_chardev.c:455, introduced by c5.2. The function is async-
|
||||
returning: sbus_ops->bus_reset() schedules an SDIO rescan; the helper
|
||||
waits up to 3 s for the remove() callback to clear sbus_priv, then
|
||||
returns. Per-vif state is gone after this point, so the recover work
|
||||
lives on bes2600_common (hw_priv) and uses the global bes2600_cdev for
|
||||
the bus_reset call rather than dereferencing per-vif state.
|
||||
|
||||
Threshold (3 / 60 s) is well above the steady-state per-vif
|
||||
connection_loss rate observed in the patch-A phase-7 rep (0.86/h under
|
||||
sustained load), so a true storm is required to trip it.
|
||||
|
||||
Files touched:
|
||||
- bes2600/bes2600.h: 3 counter fields on struct bes2600_vif, 1
|
||||
work_struct on struct bes2600_common, 3 prototypes
|
||||
- bes2600/sta.c: 3 helpers + storm-account hook in
|
||||
bes2600_connection_loss_work + storm-init in bes2600_vif_setup +
|
||||
cancel_work_sync in the hw_priv shutdown path; #include bes_chardev.h
|
||||
was already pulled in by an earlier c-stack patch
|
||||
- bes2600/main.c: INIT_WORK alongside other hw_priv work_structs
|
||||
- bes2600/debug.c: ConnectionLossStormRecoveries seq_printf in the
|
||||
per-vif status seq_file output
|
||||
|
||||
The cw1200/cw1260 ancestor has no equivalent; this is a clean
|
||||
addition. checkpatch.pl --no-tree --strict: clean (0/0/0).
|
||||
|
||||
Signed-off-by: Claude (noether) <claude@reauktion.de>
|
||||
---
|
||||
bes2600/bes2600.h | 12 +++++++
|
||||
bes2600/bes_chardev.c | 12 +++++++
|
||||
bes2600/bes_chardev.h | 1 +
|
||||
bes2600/debug.c | 2 ++
|
||||
bes2600/main.c | 2 ++
|
||||
bes2600/sta.c | 82 +++++++++++++++++++++++++++++++++++++++++--
|
||||
6 files changed, 109 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/bes2600/bes2600.h b/drivers/staging/bes2600/bes2600.h
|
||||
index 66482f7..ec41141 100644
|
||||
--- a/drivers/staging/bes2600/bes2600.h
|
||||
+++ b/drivers/staging/bes2600/bes2600.h
|
||||
@@ -511,6 +511,9 @@ struct bes2600_common {
|
||||
struct list_head coex_event_list;
|
||||
spinlock_t coex_event_lock;
|
||||
|
||||
+ /* Connection-loss-storm fast-recover (Trigger A). See sta.c. */
|
||||
+ struct work_struct connection_loss_storm_recover_work;
|
||||
+
|
||||
/* member for low power */
|
||||
struct bes2600_pwr_t bes_power;
|
||||
|
||||
@@ -627,6 +630,10 @@ struct bes2600_vif {
|
||||
/* CQM Implementation */
|
||||
struct delayed_work bss_loss_work;
|
||||
struct delayed_work connection_loss_work;
|
||||
+ /* Connection-loss-storm fast-recover (Trigger A). See sta.c. */
|
||||
+ unsigned long connection_loss_storm_window_start;
|
||||
+ unsigned int connection_loss_storm_count;
|
||||
+ unsigned int connection_loss_storm_recoveries;
|
||||
struct work_struct tx_failure_work;
|
||||
int delayed_link_loss;
|
||||
spinlock_t bss_loss_lock;
|
||||
@@ -865,4 +872,9 @@ void bes2600_btusb_uninit(struct usb_interface *interface);
|
||||
void bes2600_decrypt_storm_init(struct bes2600_vif *priv);
|
||||
void bes2600_decrypt_storm_account(struct bes2600_vif *priv);
|
||||
|
||||
+/* Connection-loss-storm fast-recover helpers — see sta.c. */
|
||||
+void bes2600_connection_loss_storm_init(struct bes2600_vif *priv);
|
||||
+bool bes2600_connection_loss_storm_account(struct bes2600_vif *priv);
|
||||
+void bes2600_connection_loss_storm_recover(struct work_struct *work);
|
||||
+
|
||||
#endif /* BES2600_H */
|
||||
diff --git a/drivers/staging/bes2600/bes_chardev.c b/drivers/staging/bes2600/bes_chardev.c
|
||||
index d1375bc..224c62d 100644
|
||||
--- a/drivers/staging/bes2600/bes_chardev.c
|
||||
+++ b/drivers/staging/bes2600/bes_chardev.c
|
||||
@@ -484,6 +484,18 @@ int bes2600_chrdev_do_bus_reset(const struct sbus_ops *sbus_ops, struct sbus_pri
|
||||
return 0;
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * Trigger bes2600_chrdev_do_bus_reset() against the file-global
|
||||
+ * bes2600_cdev. Used by host-side recovery paths outside this
|
||||
+ * compilation unit (e.g. sta.c connection-loss-storm fast-recover) so
|
||||
+ * those callers do not need to reach the static bes2600_cdev directly.
|
||||
+ */
|
||||
+int bes2600_chrdev_trigger_bus_reset(void)
|
||||
+{
|
||||
+ return bes2600_chrdev_do_bus_reset(bes2600_cdev.sbus_ops,
|
||||
+ bes2600_cdev.sbus_priv);
|
||||
+}
|
||||
+
|
||||
bool bes2600_chrdev_is_wifi_opened(void)
|
||||
{
|
||||
bool wifi_opened = false;
|
||||
diff --git a/drivers/staging/bes2600/bes_chardev.h b/drivers/staging/bes2600/bes_chardev.h
|
||||
index ca8419e..2a7cad7 100644
|
||||
--- a/drivers/staging/bes2600/bes_chardev.h
|
||||
+++ b/drivers/staging/bes2600/bes_chardev.h
|
||||
@@ -61,6 +61,7 @@ struct sbus_priv *bes2600_chrdev_get_sbus_priv_data(void);
|
||||
int bes2600_chrdev_check_system_close(void);
|
||||
int bes2600_chrdev_do_system_close(const struct sbus_ops *sbus_ops, struct sbus_priv *priv);
|
||||
int bes2600_chrdev_do_bus_reset(const struct sbus_ops *sbus_ops, struct sbus_priv *priv);
|
||||
+int bes2600_chrdev_trigger_bus_reset(void);
|
||||
void bes2600_chrdev_wakeup_bt(void);
|
||||
void bes2600_chrdev_wifi_force_close(struct bes2600_common *hw_priv, bool halt_dev);
|
||||
void bes2600_chrdev_usb_remove(struct bes2600_common *hw_priv);
|
||||
diff --git a/drivers/staging/bes2600/debug.c b/drivers/staging/bes2600/debug.c
|
||||
index ca223dd..0d68392 100644
|
||||
--- a/drivers/staging/bes2600/debug.c
|
||||
+++ b/drivers/staging/bes2600/debug.c
|
||||
@@ -544,6 +544,8 @@ static int bes2600_status_show_priv(struct seq_file *seq, void *v)
|
||||
bes2600_debug_join_status[priv->join_status]);
|
||||
seq_printf(seq, "DecryptStormRecoveries: %u\n",
|
||||
priv->decrypt_storm_recoveries);
|
||||
+ seq_printf(seq, "ConnectionLossStormRecoveries: %u\n",
|
||||
+ priv->connection_loss_storm_recoveries);
|
||||
if (priv->rx_filter.promiscuous)
|
||||
seq_puts(seq, "Filter: promisc\n");
|
||||
else if (priv->rx_filter.fcs)
|
||||
diff --git a/drivers/staging/bes2600/main.c b/drivers/staging/bes2600/main.c
|
||||
index 7cbb3a9..ff82f4d 100644
|
||||
--- a/drivers/staging/bes2600/main.c
|
||||
+++ b/drivers/staging/bes2600/main.c
|
||||
@@ -489,6 +489,8 @@ static struct ieee80211_hw *bes2600_init_common(size_t hw_priv_data_len)
|
||||
spin_lock_init(&hw_priv->rtsvalue_lock);
|
||||
INIT_WORK(&hw_priv->dynamic_opt_txrx_work, bes2600_dynamic_opt_txrx_work);
|
||||
INIT_WORK(&hw_priv->tx_policy_upload_work, tx_policy_upload_work);
|
||||
+ INIT_WORK(&hw_priv->connection_loss_storm_recover_work,
|
||||
+ bes2600_connection_loss_storm_recover);
|
||||
spin_lock_init(&hw_priv->event_queue_lock);
|
||||
INIT_LIST_HEAD(&hw_priv->event_queue);
|
||||
INIT_WORK(&hw_priv->event_handler, bes2600_event_handler);
|
||||
diff --git a/drivers/staging/bes2600/sta.c b/drivers/staging/bes2600/sta.c
|
||||
index 139bdae..5868757 100644
|
||||
--- a/drivers/staging/bes2600/sta.c
|
||||
+++ b/drivers/staging/bes2600/sta.c
|
||||
@@ -268,6 +268,7 @@ void bes2600_stop(struct ieee80211_hw *dev, bool suspend)
|
||||
cancel_work_sync(&hw_priv->coex_work);
|
||||
coex_stop(hw_priv);
|
||||
#endif
|
||||
+ cancel_work_sync(&hw_priv->connection_loss_storm_recover_work);
|
||||
|
||||
bes2600_wifi_stop(hw_priv);
|
||||
|
||||
@@ -1675,6 +1676,70 @@ report:
|
||||
spin_unlock(&priv->bss_loss_lock);
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * Connection-loss-storm fast-recover (Trigger A).
|
||||
+ *
|
||||
+ * bes2600_connection_loss_work below is the driver's own decision-point
|
||||
+ * to give up on a BSS (after bss-loss detection accumulates beyond
|
||||
+ * tolerance) and tell mac80211 via ieee80211_connection_loss(). On the
|
||||
+ * deployed pinetab2 stack a single ieee80211_connection_loss() event
|
||||
+ * sometimes triggers a userspace reauth blackhole (assoc-comeback
|
||||
+ * timeouts followed by AP unprotected-deauth-reason-6) that ends only
|
||||
+ * via cross-channel/cross-SSID fallback and can take 80+ s. Receipts at
|
||||
+ * https://git.reauktion.de/marfrit/besser, notes/phase4-2026-05-07.md.
|
||||
+ *
|
||||
+ * When N connection-loss decisions land within WINDOW on the same vif,
|
||||
+ * skip the ieee80211_connection_loss() path and trigger a chip-level
|
||||
+ * bus_reset (the c5.2-introduced bes2600_chrdev_do_bus_reset). The chip
|
||||
+ * is removed and re-probed; userspace re-associates from a fresh state,
|
||||
+ * dodging the assoc-comeback loop.
|
||||
+ *
|
||||
+ * Threshold (3 / 60 s) is chosen well above the steady-state per-vif
|
||||
+ * connection-loss rate observed in the patch-A Phase-7 rep
|
||||
+ * (0.86/h under sustained load), so a true storm is required.
|
||||
+ *
|
||||
+ * The recover work_struct lives on bes2600_common (hw_priv) so that
|
||||
+ * scheduling it does not race with vif teardown after bus_reset frees
|
||||
+ * the per-vif state.
|
||||
+ */
|
||||
+#define BES2600_CONNECTION_LOSS_STORM_THRESHOLD 3
|
||||
+#define BES2600_CONNECTION_LOSS_STORM_WINDOW_MS 60000
|
||||
+
|
||||
+void bes2600_connection_loss_storm_recover(struct work_struct *work)
|
||||
+{
|
||||
+ bes_warn("[bes2600] connection-loss-storm fast-recover: bus_reset\n");
|
||||
+ bes2600_chrdev_trigger_bus_reset();
|
||||
+ /*
|
||||
+ * After bes2600_chrdev_do_bus_reset() returns, the SDIO core has
|
||||
+ * scheduled a remove + rescan; per-vif state may already be gone.
|
||||
+ * Do not dereference any per-vif pointer here.
|
||||
+ */
|
||||
+}
|
||||
+
|
||||
+void bes2600_connection_loss_storm_init(struct bes2600_vif *priv)
|
||||
+{
|
||||
+ priv->connection_loss_storm_window_start = 0;
|
||||
+ priv->connection_loss_storm_count = 0;
|
||||
+ priv->connection_loss_storm_recoveries = 0;
|
||||
+}
|
||||
+
|
||||
+bool bes2600_connection_loss_storm_account(struct bes2600_vif *priv)
|
||||
+{
|
||||
+ unsigned long now = jiffies;
|
||||
+ unsigned long window =
|
||||
+ msecs_to_jiffies(BES2600_CONNECTION_LOSS_STORM_WINDOW_MS);
|
||||
+
|
||||
+ if (priv->connection_loss_storm_window_start == 0 ||
|
||||
+ time_after(now, priv->connection_loss_storm_window_start + window)) {
|
||||
+ priv->connection_loss_storm_window_start = now;
|
||||
+ priv->connection_loss_storm_count = 1;
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ return ++priv->connection_loss_storm_count >=
|
||||
+ BES2600_CONNECTION_LOSS_STORM_THRESHOLD;
|
||||
+}
|
||||
+
|
||||
void bes2600_connection_loss_work(struct work_struct *work)
|
||||
{
|
||||
struct bes2600_vif *priv =
|
||||
@@ -1684,9 +1749,21 @@ void bes2600_connection_loss_work(struct work_struct *work)
|
||||
|
||||
bes_devel("[CQM] Reporting connection loss.\n");
|
||||
bes2600_pwr_clear_busy_event(priv->hw_priv, BES_PWR_LOCK_ON_BSS_LOST);
|
||||
- if(bes2600_suspend_status_get(hw_priv)) {
|
||||
+
|
||||
+ if (bes2600_connection_loss_storm_account(priv)) {
|
||||
+ bes_warn("[bes2600] connection-loss storm: %u in %u s, scheduling bus reset\n",
|
||||
+ priv->connection_loss_storm_count,
|
||||
+ BES2600_CONNECTION_LOSS_STORM_WINDOW_MS / 1000);
|
||||
+ priv->connection_loss_storm_count = 0;
|
||||
+ priv->connection_loss_storm_recoveries++;
|
||||
+ schedule_work(&hw_priv->connection_loss_storm_recover_work);
|
||||
+ /* bus_reset will tear the chip down; skip the mac80211 path. */
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (bes2600_suspend_status_get(hw_priv))
|
||||
bes2600_pending_unjoin_set(hw_priv, priv->if_id);
|
||||
- } else
|
||||
+ else
|
||||
ieee80211_connection_loss(priv->vif);
|
||||
#ifdef WIFI_BT_COEXIST_EPTA_ENABLE
|
||||
// set disconnected in BSS_CHANGED_ASSOC
|
||||
@@ -2641,6 +2718,7 @@ int bes2600_vif_setup(struct bes2600_vif *priv)
|
||||
/* Setup per vif workitems and locks */
|
||||
spin_lock_init(&priv->vif_lock);
|
||||
bes2600_decrypt_storm_init(priv);
|
||||
+ bes2600_connection_loss_storm_init(priv);
|
||||
INIT_WORK(&priv->join_work, bes2600_join_work);
|
||||
INIT_DELAYED_WORK(&priv->join_timeout, bes2600_join_timeout);
|
||||
INIT_WORK(&priv->unjoin_work, bes2600_unjoin_work);
|
||||
--
|
||||
2.54.0
|
||||
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
From 737f28e29c4b8253939e24b1d6b97d5605bb7ac4 Mon Sep 17 00:00:00 2001
|
||||
From: Markus Fritsche <fritsche.markus@gmail.com>
|
||||
Date: Thu, 7 May 2026 21:19:49 +0200
|
||||
Subject: [PATCH 22/29] bes2600: replace a set of atomic_add()
|
||||
|
||||
Backport of cw1200 mainline commit 07f995ca1951 ("cw1200: replace a set
|
||||
of atomic_add()", 2020-11-10). atomic_inc() reads more naturally than
|
||||
atomic_add(1, &x). Mechanical change, no functional impact.
|
||||
|
||||
7 sites: 6 in bh.c (bh_term, bh_rx x2, bh_tx x3) and 1 in itp.c
|
||||
(awaiting_confirm). Two of the bh_rx and three of the bh_tx sites are
|
||||
inside the cw1200-ancestor #if 0 block; replaced anyway to keep the
|
||||
file consistent with cw1200 mainline source style.
|
||||
|
||||
Cherry-picked from upstream Linux:
|
||||
07f995ca1951 cw1200: replace a set of atomic_add()
|
||||
Author: Yejune Deng <yejune.deng@gmail.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
Link: https://lore.kernel.org/r/1604991491-27908-1-git-send-email-yejune.deng@gmail.com
|
||||
---
|
||||
bes2600/bh.c | 12 ++++++------
|
||||
bes2600/itp.c | 2 +-
|
||||
2 files changed, 7 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/bes2600/bh.c b/drivers/staging/bes2600/bh.c
|
||||
index 175ab5e..fab3bf0 100644
|
||||
--- a/drivers/staging/bes2600/bh.c
|
||||
+++ b/drivers/staging/bes2600/bh.c
|
||||
@@ -102,7 +102,7 @@ void bes2600_unregister_bh(struct bes2600_common *hw_priv)
|
||||
coex_deinit_mode(hw_priv);
|
||||
#endif
|
||||
|
||||
- atomic_add(1, &hw_priv->bh_term);
|
||||
+ atomic_inc(&hw_priv->bh_term);
|
||||
wake_up(&hw_priv->bh_wq);
|
||||
|
||||
flush_workqueue(hw_priv->bh_workqueue);
|
||||
@@ -591,7 +591,7 @@ static int bes2600_bh(void *arg)
|
||||
bes_devel("[BH] Device resume.\n");
|
||||
atomic_set(&hw_priv->bh_suspend, BES2600_BH_RESUMED);
|
||||
wake_up(&hw_priv->bh_evt_wq);
|
||||
- atomic_add(1, &hw_priv->bh_rx);
|
||||
+ atomic_inc(&hw_priv->bh_rx);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -759,9 +759,9 @@ tx:
|
||||
|
||||
#if 0 /* count is not implemented */
|
||||
if (ret > 1)
|
||||
- atomic_add(1, &hw_priv->bh_tx);
|
||||
+ atomic_inc(&hw_priv->bh_tx);
|
||||
#else
|
||||
- atomic_add(1, &hw_priv->bh_tx);
|
||||
+ atomic_inc(&hw_priv->bh_tx);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BES2600_NON_POWER_OF_TWO_BLOCKSIZES)
|
||||
@@ -1135,7 +1135,7 @@ static int bes2600_bh_tx_helper(struct bes2600_common *hw_priv,
|
||||
tx_len += 4;
|
||||
#endif
|
||||
|
||||
- atomic_add(1, &hw_priv->bh_tx);
|
||||
+ atomic_inc(&hw_priv->bh_tx);
|
||||
|
||||
tx_len = hw_priv->sbus_ops->align_size(
|
||||
hw_priv->sbus_priv, tx_len);
|
||||
@@ -1442,7 +1442,7 @@ static int bes2600_bh(void *arg)
|
||||
bes_devel("[BH] Device resume.\n");
|
||||
atomic_set(&hw_priv->bh_suspend, BES2600_BH_RESUMED);
|
||||
wake_up(&hw_priv->bh_evt_wq);
|
||||
- atomic_add(1, &hw_priv->bh_rx);
|
||||
+ atomic_inc(&hw_priv->bh_rx);
|
||||
goto done;
|
||||
}
|
||||
|
||||
diff --git a/drivers/staging/bes2600/itp.c b/drivers/staging/bes2600/itp.c
|
||||
index e5c2958..c50b29c 100644
|
||||
--- a/drivers/staging/bes2600/itp.c
|
||||
+++ b/drivers/staging/bes2600/itp.c
|
||||
@@ -570,7 +570,7 @@ int bes2600_itp_get_tx(struct bes2600_common *priv, u8 **data,
|
||||
*burst = 2;
|
||||
atomic_set(&priv->bh_tx, 1);
|
||||
ktime_get_ts(&itp->last_sent);
|
||||
- atomic_add(1, &itp->awaiting_confirm);
|
||||
+ atomic_inc(&itp->awaiting_confirm);
|
||||
spin_unlock_bh(&itp->tx_lock);
|
||||
return 1;
|
||||
|
||||
--
|
||||
2.54.0
|
||||
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
From 2fb72f06e54172479662257ae4ef9a61d6ba7092 Mon Sep 17 00:00:00 2001
|
||||
From: Markus Fritsche <fritsche.markus@gmail.com>
|
||||
Date: Thu, 7 May 2026 21:20:46 +0200
|
||||
Subject: [PATCH 23/29] bes2600: fix missing destroy_workqueue() on error in
|
||||
init_common
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Two error paths between create_singlethread_workqueue() (~main.c:489)
|
||||
and the success-path destroy_workqueue() in unregister_common (~609)
|
||||
return without cleaning up the workqueue, leaking it on probe failure:
|
||||
|
||||
1. bes2600_queue_stats_init() failure
|
||||
2. bes2600_queue_init() failure (any of the 4 TID queues)
|
||||
|
||||
Both call ieee80211_free_hw(hw); return NULL — without first
|
||||
destroy_workqueue(hw_priv->workqueue). Add it.
|
||||
|
||||
Backport of cw1200 mainline commit 7ec8a926188e ("cw1200: fix missing
|
||||
destroy_workqueue() on error in cw1200_init_common", 2020-11-19),
|
||||
which fixed the identical bug in the same code shape we inherited.
|
||||
Reported on cw1200 by Hulk Robot.
|
||||
|
||||
Cherry-picked from upstream Linux:
|
||||
7ec8a926188e cw1200: fix missing destroy_workqueue() on error
|
||||
Author: Qinglang Miao <miaoqinglang@huawei.com>
|
||||
Reported-by: Hulk Robot <hulkci@huawei.com>
|
||||
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
||||
Link: https://lore.kernel.org/r/20201119070842.1011-1-miaoqinglang@huawei.com
|
||||
Fixes: a910e4a94f69 ("cw1200: add driver for the ST-E CW1100 & CW1200 WLAN chipsets")
|
||||
---
|
||||
bes2600/main.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/drivers/staging/bes2600/main.c b/drivers/staging/bes2600/main.c
|
||||
index ff82f4d..89b5e2d 100644
|
||||
--- a/drivers/staging/bes2600/main.c
|
||||
+++ b/drivers/staging/bes2600/main.c
|
||||
@@ -502,6 +502,7 @@ static struct ieee80211_hw *bes2600_init_common(size_t hw_priv_data_len)
|
||||
WLAN_LINK_ID_MAX,
|
||||
bes2600_skb_dtor,
|
||||
hw_priv))) {
|
||||
+ destroy_workqueue(hw_priv->workqueue);
|
||||
ieee80211_free_hw(hw);
|
||||
return NULL;
|
||||
}
|
||||
@@ -513,6 +514,7 @@ static struct ieee80211_hw *bes2600_init_common(size_t hw_priv_data_len)
|
||||
for (; i > 0; i--)
|
||||
bes2600_queue_deinit(&hw_priv->tx_queue[i - 1]);
|
||||
bes2600_queue_stats_deinit(&hw_priv->tx_queue_stats);
|
||||
+ destroy_workqueue(hw_priv->workqueue);
|
||||
ieee80211_free_hw(hw);
|
||||
return NULL;
|
||||
}
|
||||
--
|
||||
2.54.0
|
||||
|
||||
+144
@@ -0,0 +1,144 @@
|
||||
From d9e6361cf0c273f07aee94f24533a5f19e7ed4c0 Mon Sep 17 00:00:00 2001
|
||||
From: Markus Fritsche <fritsche.markus@gmail.com>
|
||||
Date: Thu, 7 May 2026 21:24:01 +0200
|
||||
Subject: [PATCH 24/29] bes2600: fix concurrency UAF in bes2600_hw_scan and
|
||||
sched_scan
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
bes2600_bss_info_changed() and bes2600_hw_scan() can run concurrently.
|
||||
The probe-request SKB allocated by ieee80211_probereq_get() before
|
||||
scan.lock + conf_lock are taken can be touched by a concurrent
|
||||
bss_info_changed (via wsm_set_template_frame's path) while we hold no
|
||||
lock. Reorder to acquire both locks BEFORE the SKB allocation.
|
||||
|
||||
Also reorder cleanup paths so dev_kfree_skb() runs BEFORE up() —
|
||||
otherwise a small window exists where the SKB has been touched but the
|
||||
lock has been released, allowing concurrent code to also touch it.
|
||||
|
||||
Three sites fixed:
|
||||
- bes2600_hw_scan: lock-take + ENOMEM cleanup + wsm_set_template_frame
|
||||
error cleanup + success-path SKB free + lock release order
|
||||
- bes2600_sched_scan_start (#ifdef ROAM_OFFLOAD): same three sub-fixes
|
||||
(compiled-out at default build, fixed for consistency)
|
||||
- All success/error paths: dev_kfree_skb before up()
|
||||
|
||||
Backport of cw1200 mainline commit 86760e0dfe36 ("cw1200: Fix
|
||||
concurrency use-after-free bugs in cw1200_hw_scan()", 2018-12-14),
|
||||
which fixed the identical bug in the same code shape we inherited.
|
||||
That commit was merged from upstream 4f68ef64cd7f.
|
||||
|
||||
Cherry-picked from upstream Linux:
|
||||
86760e0dfe36 cw1200: Fix concurrency use-after-free bugs in cw1200_hw_scan()
|
||||
Author: Jia-Ju Bai <baijiaju1990@gmail.com>
|
||||
Link: https://lore.kernel.org/r/20181214035521.7575-1-baijiaju1990@gmail.com
|
||||
---
|
||||
bes2600/scan.c | 37 ++++++++++++++++++++++---------------
|
||||
1 file changed, 22 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/bes2600/scan.c b/drivers/staging/bes2600/scan.c
|
||||
index b944adc..3cd7b64 100644
|
||||
--- a/drivers/staging/bes2600/scan.c
|
||||
+++ b/drivers/staging/bes2600/scan.c
|
||||
@@ -257,18 +257,21 @@ int bes2600_hw_scan(struct ieee80211_hw *hw,
|
||||
|
||||
bes2600_pwr_set_busy_event(hw_priv, BES_PWR_LOCK_ON_SCAN);
|
||||
|
||||
+ /* will be unlocked in bes2600_scan_work() */
|
||||
+ down(&hw_priv->scan.lock);
|
||||
+ down(&hw_priv->conf_lock);
|
||||
+
|
||||
frame.skb = ieee80211_probereq_get(hw, priv->vif->addr, NULL, 0,
|
||||
req->ie_len);
|
||||
- if (!frame.skb)
|
||||
+ if (!frame.skb) {
|
||||
+ up(&hw_priv->conf_lock);
|
||||
+ up(&hw_priv->scan.lock);
|
||||
return -ENOMEM;
|
||||
+ }
|
||||
|
||||
if (req->ie_len)
|
||||
skb_put_data(frame.skb, req->ie, req->ie_len);
|
||||
|
||||
- /* will be unlocked in bes2600_scan_work() */
|
||||
- down(&hw_priv->scan.lock);
|
||||
- down(&hw_priv->conf_lock);
|
||||
-
|
||||
if (frame.skb) {
|
||||
int ret;
|
||||
//if (priv->if_id == 0)
|
||||
@@ -286,9 +289,9 @@ int bes2600_hw_scan(struct ieee80211_hw *hw,
|
||||
}
|
||||
#endif
|
||||
if (ret) {
|
||||
+ dev_kfree_skb(frame.skb);
|
||||
up(&hw_priv->conf_lock);
|
||||
up(&hw_priv->scan.lock);
|
||||
- dev_kfree_skb(frame.skb);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -318,10 +321,10 @@ int bes2600_hw_scan(struct ieee80211_hw *hw,
|
||||
++hw_priv->scan.n_ssids;
|
||||
}
|
||||
|
||||
- up(&hw_priv->conf_lock);
|
||||
-
|
||||
if (frame.skb)
|
||||
dev_kfree_skb(frame.skb);
|
||||
+
|
||||
+ up(&hw_priv->conf_lock);
|
||||
#ifdef WIFI_BT_COEXIST_EPTA_ENABLE
|
||||
bwifi_change_current_status(hw_priv, BWIFI_STATUS_SCANNING);
|
||||
#endif
|
||||
@@ -362,14 +365,18 @@ int bes2600_hw_sched_scan_start(struct ieee80211_hw *hw,
|
||||
if (req->n_ssids > hw->wiphy->max_scan_ssids)
|
||||
return -EINVAL;
|
||||
|
||||
+ /* will be unlocked in bes2600_scan_work() */
|
||||
+ down(&hw_priv->scan.lock);
|
||||
+ down(&hw_priv->conf_lock);
|
||||
+
|
||||
frame.skb = ieee80211_probereq_get(hw, priv->vif->addr, NULL, 0,
|
||||
req->ie_len);
|
||||
- if (!frame.skb)
|
||||
+ if (!frame.skb) {
|
||||
+ up(&hw_priv->conf_lock);
|
||||
+ up(&hw_priv->scan.lock);
|
||||
return -ENOMEM;
|
||||
+ }
|
||||
|
||||
- /* will be unlocked in bes2600_scan_work() */
|
||||
- down(&hw_priv->scan.lock);
|
||||
- down(&hw_priv->conf_lock);
|
||||
if (frame.skb) {
|
||||
int ret;
|
||||
if (priv->if_id == 0)
|
||||
@@ -380,9 +387,9 @@ int bes2600_hw_sched_scan_start(struct ieee80211_hw *hw,
|
||||
ret = wsm_set_probe_responder(priv, true);
|
||||
}
|
||||
if (ret) {
|
||||
+ dev_kfree_skb(frame.skb);
|
||||
up(&hw_priv->conf_lock);
|
||||
up(&hw_priv->scan.lock);
|
||||
- dev_kfree_skb(frame.skb);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -414,10 +421,10 @@ int bes2600_hw_sched_scan_start(struct ieee80211_hw *hw,
|
||||
}
|
||||
}
|
||||
|
||||
- up(&hw_priv->conf_lock);
|
||||
-
|
||||
if (frame.skb)
|
||||
dev_kfree_skb(frame.skb);
|
||||
+
|
||||
+ up(&hw_priv->conf_lock);
|
||||
queue_work(hw_priv->workqueue, &hw_priv->scan.swork);
|
||||
wiphy_warn(hw->wiphy, "<--[SCAN] Scheduled scan request.\n");
|
||||
return 0;
|
||||
--
|
||||
2.54.0
|
||||
|
||||
+221
@@ -0,0 +1,221 @@
|
||||
From 91640bd96d36dd5769b1325e1b2130a95277e0e7 Mon Sep 17 00:00:00 2001
|
||||
From: "Claude (noether)" <claude@reauktion.de>
|
||||
Date: Wed, 6 May 2026 19:50:52 +0200
|
||||
Subject: [PATCH 20/29] bes2600: pre-empt AP-deauth-6 with mac80211 reassoc on
|
||||
decrypt-fail storm
|
||||
|
||||
When the BES2600 firmware reports WSM_STATUS_DECRYPTFAILURE for a burst
|
||||
of received frames (typically because the host's PTK or GTK has fallen
|
||||
out of sync with the AP), the AP eventually concludes that the STA is
|
||||
not authenticated and emits an unprotected deauth-reason-6 ("Class 2
|
||||
frame received from non-authenticated station"). On the deployed
|
||||
pinetab2 + bes2600 stack this AP-initiated deauth has been observed to
|
||||
leave the link blackholed for up to 109 s before userspace finds a
|
||||
different SSID/channel to recover on. (Receipts at
|
||||
https://git.reauktion.de/marfrit/besser, notes/phase5-2026-05-06.md.)
|
||||
|
||||
Add a sliding-window counter on each bes2600_vif: when 5 decrypt
|
||||
failures fire within 5 s, schedule a worker that calls
|
||||
ieee80211_connection_loss(vif). mac80211 then performs immediate
|
||||
disassociation; userspace (NetworkManager / wpa_supplicant) reconnects
|
||||
with fresh keys before the AP gets a chance to fire its unprotected
|
||||
deauth.
|
||||
|
||||
Predicted Phase 7 delta vs the unpatched baseline:
|
||||
- decrypt-burst rate: unchanged (this does not address root cause)
|
||||
- AP-deauth-6 rate: <= 0.2 of baseline
|
||||
- conditional probability of >5s blackhole given a burst:
|
||||
100% -> <= 10%
|
||||
- worst-case recovery time: 109s -> <5s
|
||||
|
||||
Contract pin: ieee80211_connection_loss() per
|
||||
include/net/mac80211.h: "may also be called if the connection needs to
|
||||
be terminated for some other reason... will cause immediate change to
|
||||
disassociated state, without connection recovery attempts." Userspace
|
||||
recovery is the existing NM/wpa_supplicant path. The worker context
|
||||
satisfies the implicit process-context expectation.
|
||||
|
||||
Files touched:
|
||||
- bes2600/bes2600.h: 4 new fields on struct bes2600_vif + 2 prototypes
|
||||
- bes2600/txrx.c: new helpers + the call site at the existing
|
||||
WSM_STATUS_DECRYPTFAILURE log point (the unconditional "goto drop"
|
||||
branch in bes2600_rx_cb)
|
||||
- bes2600/sta.c: bes2600_decrypt_storm_init() in bes2600_vif_setup;
|
||||
cancel_work_sync() in bes2600_remove_interface, alongside the
|
||||
existing per-vif cancel_*_work_sync block. Safe under the kernel
|
||||
cancel_work_sync contract: the work_struct is INIT_WORK'd in setup,
|
||||
so the call is valid; it blocks until any in-flight handler returns,
|
||||
ensuring no use-after-free of priv when mac80211 frees the vif; and
|
||||
it is idempotent (subsequent calls just return false).
|
||||
- bes2600/debug.c: DecryptStormRecoveries seq_printf in the per-vif
|
||||
status seq_file output
|
||||
|
||||
Threshold (5/5s) is set well above the steady-state per-vif decrypt-
|
||||
fail rate observed in measurement (~1/min even under sustained 1 MB/s
|
||||
load), so a true storm is required to trip it. The cw1200/cw1260
|
||||
ancestor has no equivalent storm-recovery; this is a clean addition.
|
||||
|
||||
checkpatch.pl --no-tree --strict: clean (0/0/0).
|
||||
|
||||
Signed-off-by: Claude (noether) <claude@reauktion.de>
|
||||
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||||
---
|
||||
bes2600/bes2600.h | 9 ++++++
|
||||
bes2600/debug.c | 2 ++
|
||||
bes2600/sta.c | 2 ++
|
||||
bes2600/txrx.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++
|
||||
4 files changed, 87 insertions(+)
|
||||
|
||||
diff --git a/drivers/staging/bes2600/bes2600.h b/drivers/staging/bes2600/bes2600.h
|
||||
index 0e60960..66482f7 100644
|
||||
--- a/drivers/staging/bes2600/bes2600.h
|
||||
+++ b/drivers/staging/bes2600/bes2600.h
|
||||
@@ -596,6 +596,11 @@ struct bes2600_vif {
|
||||
unsigned long rx_timestamp;
|
||||
u32 cipherType;
|
||||
|
||||
+ /* Decrypt-storm fast-recover (Trigger B). See txrx.c. */
|
||||
+ unsigned long decrypt_storm_window_start;
|
||||
+ unsigned int decrypt_storm_count;
|
||||
+ unsigned int decrypt_storm_recoveries;
|
||||
+ struct work_struct decrypt_storm_recover_work;
|
||||
|
||||
/* AP powersave */
|
||||
u32 link_id_map;
|
||||
@@ -856,4 +861,8 @@ int bes2600_btusb_setup_pipes(struct sbus_priv *sbus_priv);
|
||||
void bes2600_btusb_uninit(struct usb_interface *interface);
|
||||
#endif
|
||||
|
||||
+/* Decrypt-storm fast-recover helpers — see txrx.c. */
|
||||
+void bes2600_decrypt_storm_init(struct bes2600_vif *priv);
|
||||
+void bes2600_decrypt_storm_account(struct bes2600_vif *priv);
|
||||
+
|
||||
#endif /* BES2600_H */
|
||||
diff --git a/drivers/staging/bes2600/debug.c b/drivers/staging/bes2600/debug.c
|
||||
index 5228b22..ca223dd 100644
|
||||
--- a/drivers/staging/bes2600/debug.c
|
||||
+++ b/drivers/staging/bes2600/debug.c
|
||||
@@ -542,6 +542,8 @@ static int bes2600_status_show_priv(struct seq_file *seq, void *v)
|
||||
priv->listening ? " (listening)" : "");
|
||||
seq_printf(seq, "Assoc: %s\n",
|
||||
bes2600_debug_join_status[priv->join_status]);
|
||||
+ seq_printf(seq, "DecryptStormRecoveries: %u\n",
|
||||
+ priv->decrypt_storm_recoveries);
|
||||
if (priv->rx_filter.promiscuous)
|
||||
seq_puts(seq, "Filter: promisc\n");
|
||||
else if (priv->rx_filter.fcs)
|
||||
diff --git a/drivers/staging/bes2600/sta.c b/drivers/staging/bes2600/sta.c
|
||||
index bc6d483..139bdae 100644
|
||||
--- a/drivers/staging/bes2600/sta.c
|
||||
+++ b/drivers/staging/bes2600/sta.c
|
||||
@@ -464,6 +464,7 @@ void bes2600_remove_interface(struct ieee80211_hw *dev,
|
||||
cancel_delayed_work_sync(&priv->join_timeout);
|
||||
cancel_delayed_work_sync(&priv->set_cts_work);
|
||||
cancel_delayed_work_sync(&priv->pending_offchanneltx_work);
|
||||
+ cancel_work_sync(&priv->decrypt_storm_recover_work);
|
||||
|
||||
timer_delete_sync(&priv->mcast_timeout);
|
||||
/* TODO:COMBO: May be reset of these variables "delayed_link_loss and
|
||||
@@ -2639,6 +2640,7 @@ int bes2600_vif_setup(struct bes2600_vif *priv)
|
||||
|
||||
/* Setup per vif workitems and locks */
|
||||
spin_lock_init(&priv->vif_lock);
|
||||
+ bes2600_decrypt_storm_init(priv);
|
||||
INIT_WORK(&priv->join_work, bes2600_join_work);
|
||||
INIT_DELAYED_WORK(&priv->join_timeout, bes2600_join_timeout);
|
||||
INIT_WORK(&priv->unjoin_work, bes2600_unjoin_work);
|
||||
diff --git a/drivers/staging/bes2600/txrx.c b/drivers/staging/bes2600/txrx.c
|
||||
index 017f0d8..f6a66d6 100644
|
||||
--- a/drivers/staging/bes2600/txrx.c
|
||||
+++ b/drivers/staging/bes2600/txrx.c
|
||||
@@ -26,6 +26,78 @@
|
||||
|
||||
#define BES2600_INVALID_RATE_ID (0xFF)
|
||||
|
||||
+/*
|
||||
+ * Decrypt-storm fast-recover (Trigger B).
|
||||
+ *
|
||||
+ * When the BES2600 firmware reports WSM_STATUS_DECRYPTFAILURE for a
|
||||
+ * burst of received frames (typically because the host's PTK or GTK
|
||||
+ * has fallen out of sync with the AP), the AP eventually concludes that
|
||||
+ * the STA is not authenticated and emits an unprotected deauth-reason-6
|
||||
+ * ("Class 2 frame received from non-authenticated station"). On the
|
||||
+ * deployed pinetab2 + bes2600 stack this AP-initiated deauth has been
|
||||
+ * observed to leave the link blackholed for up to 109 s before
|
||||
+ * userspace finds a different SSID/channel to recover on. (Receipts at
|
||||
+ * https://git.reauktion.de/marfrit/besser, notes/phase5-2026-05-06.md.)
|
||||
+ *
|
||||
+ * Recovery here pre-empts the AP: when we see THRESHOLD decrypt
|
||||
+ * failures within WINDOW, we ask mac80211 for a clean reassoc via
|
||||
+ * ieee80211_connection_loss(), which causes immediate disassociation
|
||||
+ * and lets userspace auto-reconnect with fresh keys.
|
||||
+ *
|
||||
+ * mac80211 contract: ieee80211_connection_loss() may be called
|
||||
+ * regardless of IEEE80211_HW_CONNECTION_MONITOR; it causes immediate
|
||||
+ * disassociation without driver-side recovery attempts. See
|
||||
+ * include/net/mac80211.h for the canonical doc-comment.
|
||||
+ *
|
||||
+ * The threshold is set well above the steady-state per-vif
|
||||
+ * decrypt-fail rate observed in measurement (~1/min even under
|
||||
+ * sustained 1 MB/s load), so a true storm is required to trip it.
|
||||
+ */
|
||||
+#define BES2600_DECRYPT_STORM_THRESHOLD 5
|
||||
+#define BES2600_DECRYPT_STORM_WINDOW_MS 5000
|
||||
+
|
||||
+static void bes2600_decrypt_storm_recover_work(struct work_struct *work)
|
||||
+{
|
||||
+ struct bes2600_vif *priv = container_of(work, struct bes2600_vif,
|
||||
+ decrypt_storm_recover_work);
|
||||
+
|
||||
+ if (!priv->vif)
|
||||
+ return;
|
||||
+
|
||||
+ bes_warn("[bes2600] decrypt-storm fast-recover: forcing reassoc\n");
|
||||
+ ieee80211_connection_loss(priv->vif);
|
||||
+ priv->decrypt_storm_recoveries++;
|
||||
+}
|
||||
+
|
||||
+void bes2600_decrypt_storm_init(struct bes2600_vif *priv)
|
||||
+{
|
||||
+ INIT_WORK(&priv->decrypt_storm_recover_work,
|
||||
+ bes2600_decrypt_storm_recover_work);
|
||||
+ priv->decrypt_storm_window_start = 0;
|
||||
+ priv->decrypt_storm_count = 0;
|
||||
+ priv->decrypt_storm_recoveries = 0;
|
||||
+}
|
||||
+
|
||||
+void bes2600_decrypt_storm_account(struct bes2600_vif *priv)
|
||||
+{
|
||||
+ unsigned long now = jiffies;
|
||||
+ unsigned long window = msecs_to_jiffies(BES2600_DECRYPT_STORM_WINDOW_MS);
|
||||
+
|
||||
+ if (priv->decrypt_storm_window_start == 0 ||
|
||||
+ time_after(now, priv->decrypt_storm_window_start + window)) {
|
||||
+ priv->decrypt_storm_window_start = now;
|
||||
+ priv->decrypt_storm_count = 1;
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (++priv->decrypt_storm_count >= BES2600_DECRYPT_STORM_THRESHOLD) {
|
||||
+ priv->decrypt_storm_count = 0;
|
||||
+ /* Skew the window so we don't re-fire on the same storm. */
|
||||
+ priv->decrypt_storm_window_start = now + window;
|
||||
+ schedule_work(&priv->decrypt_storm_recover_work);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
#ifdef CONFIG_BES2600_TESTMODE
|
||||
#include "bes_nl80211_testmode_msg.h"
|
||||
#endif /* CONFIG_BES2600_TESTMODE */
|
||||
@@ -1694,6 +1766,8 @@ void bes2600_rx_cb(struct bes2600_vif *priv,
|
||||
goto drop;
|
||||
} else {
|
||||
bes_warn("[RX] Receive failure: %d.\n", arg->status);
|
||||
+ if (arg->status == WSM_STATUS_DECRYPTFAILURE)
|
||||
+ bes2600_decrypt_storm_account(priv);
|
||||
goto drop;
|
||||
}
|
||||
}
|
||||
--
|
||||
2.54.0
|
||||
|
||||
+4
-3
@@ -1,7 +1,8 @@
|
||||
From 699871fdc6bf1bed6d919732820183e57faeaddc Mon Sep 17 00:00:00 2001
|
||||
From 0768e11da638457b3455e426de924f9e2e551641 Mon Sep 17 00:00:00 2001
|
||||
From: Markus Fritsche <fritsche.markus@gmail.com>
|
||||
Date: Thu, 23 Apr 2026 20:04:11 +0200
|
||||
Subject: [PATCH] bes2600: drop BES2600_WRITE_DPD_TO_FILE kernel_*() file paths
|
||||
Subject: [PATCH 09/29] bes2600: drop BES2600_WRITE_DPD_TO_FILE kernel_*() file
|
||||
paths
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
@@ -289,5 +290,5 @@ index e2e4f1b..a02d6d9 100644
|
||||
}
|
||||
|
||||
--
|
||||
2.53.0
|
||||
2.54.0
|
||||
|
||||
+6
-6
@@ -1,8 +1,8 @@
|
||||
From 44e085360fec09c1c1f7b35a23ec679f7065d3f7 Mon Sep 17 00:00:00 2001
|
||||
From c3d28aea4603fec51b66cfa438dd546722d53272 Mon Sep 17 00:00:00 2001
|
||||
From: Markus Fritsche <fritsche.markus@gmail.com>
|
||||
Date: Thu, 23 Apr 2026 20:19:27 +0200
|
||||
Subject: [PATCH] bes2600: drop orphan DATA_DUMP_OBSERVE and access_file() file
|
||||
I/O
|
||||
Subject: [PATCH 10/29] bes2600: drop orphan DATA_DUMP_OBSERVE and
|
||||
access_file() file I/O
|
||||
|
||||
Two dead-in-default-build file-I/O sites remain in the driver
|
||||
after the factory and chardev kernel_*() removals in the preceding
|
||||
@@ -118,10 +118,10 @@ index 133c945..d612c3c 100644
|
||||
kfree(short_buf);
|
||||
release_firmware(fw_bin);
|
||||
diff --git a/drivers/staging/bes2600/main.c b/drivers/staging/bes2600/main.c
|
||||
index 6ed6b15..9d2aac5 100644
|
||||
index 3b0b7a3..7cbb3a9 100644
|
||||
--- a/drivers/staging/bes2600/main.c
|
||||
+++ b/drivers/staging/bes2600/main.c
|
||||
@@ -790,41 +790,6 @@ void bes2600_core_release(struct bes2600_common *self)
|
||||
@@ -795,41 +795,6 @@ void bes2600_core_release(struct bes2600_common *self)
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -164,5 +164,5 @@ index 6ed6b15..9d2aac5 100644
|
||||
{
|
||||
int ret = 0, if_id;
|
||||
--
|
||||
2.53.0
|
||||
2.54.0
|
||||
|
||||
+18
-18
@@ -1,8 +1,8 @@
|
||||
From 9398d3028bc9d2f4ccbf8e830f8e9799bf065ce4 Mon Sep 17 00:00:00 2001
|
||||
From 789ab98e4cd4a0c2c43a54da6462b6b05f3af8f2 Mon Sep 17 00:00:00 2001
|
||||
From: Markus Fritsche <fritsche.markus@gmail.com>
|
||||
Date: Wed, 22 Apr 2026 13:04:27 +0200
|
||||
Subject: [PATCH] bes2600: enable CONFIG_BES2600_TESTMODE by default + fix
|
||||
bit-rotted testmode plumbing
|
||||
Subject: [PATCH 06/29] bes2600: enable CONFIG_BES2600_TESTMODE by default +
|
||||
fix bit-rotted testmode plumbing
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
@@ -63,10 +63,10 @@ Signed-off-by: Markus Fritsche <fritsche.markus@gmail.com>
|
||||
bes2600/sta.c | 6 +++---
|
||||
3 files changed, 27 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/bes2600/Makefile b/bes2600/Makefile
|
||||
index 300912b..39150e0 100644
|
||||
--- a/bes2600/Makefile
|
||||
+++ b/bes2600/Makefile
|
||||
diff --git a/drivers/staging/bes2600/Makefile b/drivers/staging/bes2600/Makefile
|
||||
index 2dcba09..2c1a850 100644
|
||||
--- a/drivers/staging/bes2600/Makefile
|
||||
+++ b/drivers/staging/bes2600/Makefile
|
||||
@@ -2,7 +2,7 @@ KERN_DIR = /lib/modules/$(KERNELRELEASE)/build
|
||||
# feature option
|
||||
BES2600 ?= m
|
||||
@@ -76,10 +76,10 @@ index 300912b..39150e0 100644
|
||||
|
||||
CONFIG_BES2600_ENABLE_DEVEL_LOGS ?= n
|
||||
|
||||
diff --git a/bes2600/bes_log.h b/bes2600/bes_log.h
|
||||
diff --git a/drivers/staging/bes2600/bes_log.h b/drivers/staging/bes2600/bes_log.h
|
||||
index 605cea8..65cf703 100644
|
||||
--- a/bes2600/bes_log.h
|
||||
+++ b/bes2600/bes_log.h
|
||||
--- a/drivers/staging/bes2600/bes_log.h
|
||||
+++ b/drivers/staging/bes2600/bes_log.h
|
||||
@@ -8,3 +8,26 @@ extern struct device *global_dev;
|
||||
#define bes_info(fmt, ...) dev_info(global_dev, fmt, ##__VA_ARGS__)
|
||||
#define bes_warn(fmt, ...) dev_warn(global_dev, fmt, ##__VA_ARGS__)
|
||||
@@ -107,11 +107,11 @@ index 605cea8..65cf703 100644
|
||||
+ if (_cond) \
|
||||
+ bes_err(fmt, ##__VA_ARGS__); \
|
||||
+ } while (0)
|
||||
diff --git a/bes2600/sta.c b/bes2600/sta.c
|
||||
index aa69eb8..5f1a456 100644
|
||||
--- a/bes2600/sta.c
|
||||
+++ b/bes2600/sta.c
|
||||
@@ -3633,7 +3633,7 @@ static int bes2600_set_power_save(struct ieee80211_hw *hw,
|
||||
diff --git a/drivers/staging/bes2600/sta.c b/drivers/staging/bes2600/sta.c
|
||||
index ca1c77c..bc6d483 100644
|
||||
--- a/drivers/staging/bes2600/sta.c
|
||||
+++ b/drivers/staging/bes2600/sta.c
|
||||
@@ -3654,7 +3654,7 @@ static int bes2600_set_power_save(struct ieee80211_hw *hw,
|
||||
*
|
||||
* Returns: 0 on success or non zero value on failure
|
||||
*/
|
||||
@@ -120,7 +120,7 @@ index aa69eb8..5f1a456 100644
|
||||
{
|
||||
struct bes_msg_start_stop_tsm *start_stop_tsm =
|
||||
(struct bes_msg_start_stop_tsm *) data;
|
||||
@@ -3663,7 +3663,7 @@ int bes2600_start_stop_tsm(struct ieee80211_hw *hw, void *data)
|
||||
@@ -3684,7 +3684,7 @@ int bes2600_start_stop_tsm(struct ieee80211_hw *hw, void *data)
|
||||
*
|
||||
* Returns: TSM parameters collected
|
||||
*/
|
||||
@@ -129,7 +129,7 @@ index aa69eb8..5f1a456 100644
|
||||
{
|
||||
struct bes2600_common *hw_priv = hw->priv;
|
||||
struct bes_tsm_stats tsm_stats;
|
||||
@@ -3703,7 +3703,7 @@ int bes2600_get_tsm_params(struct ieee80211_hw *hw)
|
||||
@@ -3724,7 +3724,7 @@ int bes2600_get_tsm_params(struct ieee80211_hw *hw)
|
||||
*
|
||||
* Returns: Returns the last measured roam delay
|
||||
*/
|
||||
@@ -139,5 +139,5 @@ index aa69eb8..5f1a456 100644
|
||||
struct bes2600_common *hw_priv = hw->priv;
|
||||
u16 roam_delay = hw_priv->tsm_info.roam_delay / 1000;
|
||||
--
|
||||
2.53.0
|
||||
2.54.0
|
||||
|
||||
+4
-4
@@ -1,8 +1,8 @@
|
||||
From 5f475a9624490b07c305329f12016ff4a4df3b47 Mon Sep 17 00:00:00 2001
|
||||
From 0c1f98df59fc3c330b370f1b5b54e8d780278d2a Mon Sep 17 00:00:00 2001
|
||||
From: Markus Fritsche <fritsche.markus@gmail.com>
|
||||
Date: Thu, 23 Apr 2026 19:31:25 +0200
|
||||
Subject: [PATCH] bes2600: drop kernel_write() persistence from factory cali
|
||||
save
|
||||
Subject: [PATCH 08/29] bes2600: drop kernel_write() persistence from factory
|
||||
cali save
|
||||
|
||||
Following the conversion of the factory-calibration READ path to
|
||||
request_firmware() (earlier in this series), the factory-calibration
|
||||
@@ -152,5 +152,5 @@ index 1cda447..1b43b41 100644
|
||||
}
|
||||
|
||||
--
|
||||
2.53.0
|
||||
2.54.0
|
||||
|
||||
+9
-9
@@ -1,7 +1,7 @@
|
||||
From 1a5d54a3213041262caf1605bb19c66ddded41f7 Mon Sep 17 00:00:00 2001
|
||||
From 4a1bbc7444c94be044fae4377ccd612a6cd28460 Mon Sep 17 00:00:00 2001
|
||||
From: Markus Fritsche <fritsche.markus@gmail.com>
|
||||
Date: Wed, 22 Apr 2026 10:09:44 +0200
|
||||
Subject: [PATCH 1/2] bes2600: use request_firmware() for factory.txt read
|
||||
Subject: [PATCH 01/29] bes2600: use request_firmware() for factory.txt read
|
||||
|
||||
The BES2600 factory calibration file (bes2600_factory.txt) was being read
|
||||
via filp_open() + kernel_read() from a hard-coded absolute path baked in
|
||||
@@ -62,10 +62,10 @@ Signed-off-by: Markus Fritsche <fritsche.markus@gmail.com>
|
||||
bes2600/bes2600_factory.c | 33 ++++++++++++++-------------------
|
||||
2 files changed, 15 insertions(+), 20 deletions(-)
|
||||
|
||||
diff --git a/bes2600/Makefile b/bes2600/Makefile
|
||||
diff --git a/drivers/staging/bes2600/Makefile b/drivers/staging/bes2600/Makefile
|
||||
index 300912b..788aee2 100644
|
||||
--- a/bes2600/Makefile
|
||||
+++ b/bes2600/Makefile
|
||||
--- a/drivers/staging/bes2600/Makefile
|
||||
+++ b/drivers/staging/bes2600/Makefile
|
||||
@@ -66,7 +66,7 @@ BES2600_DRV_VERSION := bes2600_0.3.5_2024.0116
|
||||
ifeq ($(CONFIG_BES2600_CALIB_FROM_LINUX),y)
|
||||
FACTORY_CRC_CHECK ?= n
|
||||
@@ -75,10 +75,10 @@ index 300912b..788aee2 100644
|
||||
endif
|
||||
|
||||
# basic function
|
||||
diff --git a/bes2600/bes2600_factory.c b/bes2600/bes2600_factory.c
|
||||
diff --git a/drivers/staging/bes2600/bes2600_factory.c b/drivers/staging/bes2600/bes2600_factory.c
|
||||
index dc5d3da..8d60b7c 100644
|
||||
--- a/bes2600/bes2600_factory.c
|
||||
+++ b/bes2600/bes2600_factory.c
|
||||
--- a/drivers/staging/bes2600/bes2600_factory.c
|
||||
+++ b/drivers/staging/bes2600/bes2600_factory.c
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/sched.h>
|
||||
@@ -140,5 +140,5 @@ index dc5d3da..8d60b7c 100644
|
||||
}
|
||||
|
||||
--
|
||||
2.53.0
|
||||
2.54.0
|
||||
|
||||
|
||||
+9
-9
@@ -1,7 +1,7 @@
|
||||
From 82ba594a444a855310fbbe2a5c8ff02f211d8e83 Mon Sep 17 00:00:00 2001
|
||||
From 13dd191defab19294d843218833860d0e1e33dcd Mon Sep 17 00:00:00 2001
|
||||
From: Markus Fritsche <fritsche.markus@gmail.com>
|
||||
Date: Wed, 22 Apr 2026 12:17:56 +0200
|
||||
Subject: [PATCH 2/2] bes2600: default STANDARD_FACTORY_EFUSE_FLAG off for
|
||||
Subject: [PATCH 02/29] bes2600: default STANDARD_FACTORY_EFUSE_FLAG off for
|
||||
PineTab2 factory.txt format
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
@@ -53,10 +53,10 @@ Signed-off-by: Markus Fritsche <fritsche.markus@gmail.com>
|
||||
bes2600/wsm.h | 2 --
|
||||
2 files changed, 1 insertion(+), 3 deletions(-)
|
||||
|
||||
diff --git a/bes2600/Makefile b/bes2600/Makefile
|
||||
diff --git a/drivers/staging/bes2600/Makefile b/drivers/staging/bes2600/Makefile
|
||||
index 788aee2..2dcba09 100644
|
||||
--- a/bes2600/Makefile
|
||||
+++ b/bes2600/Makefile
|
||||
--- a/drivers/staging/bes2600/Makefile
|
||||
+++ b/drivers/staging/bes2600/Makefile
|
||||
@@ -65,7 +65,7 @@ BES2600_DRV_VERSION := bes2600_0.3.5_2024.0116
|
||||
|
||||
ifeq ($(CONFIG_BES2600_CALIB_FROM_LINUX),y)
|
||||
@@ -66,10 +66,10 @@ index 788aee2..2dcba09 100644
|
||||
FACTORY_PATH ?= bes2600/bes2600_factory.txt
|
||||
endif
|
||||
|
||||
diff --git a/bes2600/wsm.h b/bes2600/wsm.h
|
||||
diff --git a/drivers/staging/bes2600/wsm.h b/drivers/staging/bes2600/wsm.h
|
||||
index 0673131..22845ac 100644
|
||||
--- a/bes2600/wsm.h
|
||||
+++ b/bes2600/wsm.h
|
||||
--- a/drivers/staging/bes2600/wsm.h
|
||||
+++ b/drivers/staging/bes2600/wsm.h
|
||||
@@ -2236,7 +2236,5 @@ int wsm_cpu_usage_cmd(struct bes2600_common *hw_priv);
|
||||
|
||||
int wsm_wifi_status_cmd(struct bes2600_common *hw_priv, uint32_t status);
|
||||
@@ -79,5 +79,5 @@ index 0673131..22845ac 100644
|
||||
-#endif
|
||||
#endif /* BES2600_HWIO_H_INCLUDED */
|
||||
--
|
||||
2.53.0
|
||||
2.54.0
|
||||
|
||||
+13
-13
@@ -1,7 +1,7 @@
|
||||
From 8732881c5916106539b9071b51710489c57e8d73 Mon Sep 17 00:00:00 2001
|
||||
From 40a0a1a0c72ae5b4ee538f6e8a5d0def522606af Mon Sep 17 00:00:00 2001
|
||||
From: Markus Fritsche <fritsche.markus@gmail.com>
|
||||
Date: Wed, 22 Apr 2026 13:18:38 +0200
|
||||
Subject: [PATCH] bes2600: thread struct device * through factory
|
||||
Subject: [PATCH 03/29] bes2600: thread struct device * through factory
|
||||
request_firmware() call
|
||||
|
||||
Follow-up to \"bes2600: use request_firmware() for factory.txt read\".
|
||||
@@ -43,10 +43,10 @@ Signed-off-by: Markus Fritsche <fritsche.markus@gmail.com>
|
||||
bes2600/bes2600_sdio.c | 4 ++++
|
||||
3 files changed, 20 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/bes2600/bes2600_factory.c b/bes2600/bes2600_factory.c
|
||||
diff --git a/drivers/staging/bes2600/bes2600_factory.c b/drivers/staging/bes2600/bes2600_factory.c
|
||||
index 8d60b7c..1cda447 100644
|
||||
--- a/bes2600/bes2600_factory.c
|
||||
+++ b/bes2600/bes2600_factory.c
|
||||
--- a/drivers/staging/bes2600/bes2600_factory.c
|
||||
+++ b/drivers/staging/bes2600/bes2600_factory.c
|
||||
@@ -31,6 +31,18 @@
|
||||
|
||||
static DEFINE_MUTEX(factory_lock);
|
||||
@@ -75,10 +75,10 @@ index 8d60b7c..1cda447 100644
|
||||
if (ret) {
|
||||
bes_devel("BES2600: request_firmware(%s) failed: %d\n", path, ret);
|
||||
return -1;
|
||||
diff --git a/bes2600/bes2600_factory.h b/bes2600/bes2600_factory.h
|
||||
diff --git a/drivers/staging/bes2600/bes2600_factory.h b/drivers/staging/bes2600/bes2600_factory.h
|
||||
index 3835b0d..7dbe9f8 100644
|
||||
--- a/bes2600/bes2600_factory.h
|
||||
+++ b/bes2600/bes2600_factory.h
|
||||
--- a/drivers/staging/bes2600/bes2600_factory.h
|
||||
+++ b/drivers/staging/bes2600/bes2600_factory.h
|
||||
@@ -199,6 +199,9 @@ enum factory_cali_status {
|
||||
/* just calibrate 11n, other protocols are automatically mapped */
|
||||
#define WIFI_RF_11N_MODE 0x15
|
||||
@@ -89,10 +89,10 @@ index 3835b0d..7dbe9f8 100644
|
||||
/* read wifi & bt factory cali value*/
|
||||
u8* bes2600_get_factory_cali_data(u8 *file_buffer, u32 *data_len, char *path);
|
||||
void factory_little_endian_cvrt(u8 *data);
|
||||
diff --git a/bes2600/bes2600_sdio.c b/bes2600/bes2600_sdio.c
|
||||
index b595365..371ef4f 100644
|
||||
--- a/bes2600/bes2600_sdio.c
|
||||
+++ b/bes2600/bes2600_sdio.c
|
||||
diff --git a/drivers/staging/bes2600/bes2600_sdio.c b/drivers/staging/bes2600/bes2600_sdio.c
|
||||
index 13d4ff1..f172d53 100644
|
||||
--- a/drivers/staging/bes2600/bes2600_sdio.c
|
||||
+++ b/drivers/staging/bes2600/bes2600_sdio.c
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "bes2600.h"
|
||||
#include "sbus.h"
|
||||
@@ -112,5 +112,5 @@ index b595365..371ef4f 100644
|
||||
self->func = func;
|
||||
self->dev = &func->dev;
|
||||
--
|
||||
2.53.0
|
||||
2.54.0
|
||||
|
||||
+1154
File diff suppressed because it is too large
Load Diff
+15
-15
@@ -1,8 +1,8 @@
|
||||
From 9ea8a8e810ee5eb220de700a5c0a6d1153b15130 Mon Sep 17 00:00:00 2001
|
||||
From 22b799f5a21c0046aad46676519e5f03a0d105fd Mon Sep 17 00:00:00 2001
|
||||
From: Markus Fritsche <fritsche.markus@gmail.com>
|
||||
Date: Mon, 27 Apr 2026 06:32:41 +0200
|
||||
Subject: [PATCH] bes2600: recover wedged firmware via mmc_hw_reset on link
|
||||
break
|
||||
Date: Sun, 26 Apr 2026 22:31:58 +0200
|
||||
Subject: [PATCH 15/29] bes2600: recover wedged firmware via mmc_hw_reset on
|
||||
link break
|
||||
|
||||
When the LMAC active monitor detects 'link break between lmac and host'
|
||||
(the hw_buf_used==pending watchdog in bes2600_bh_lmac_active_monitor),
|
||||
@@ -78,14 +78,14 @@ v2.0 boards) are both already configured as MMC pwrseq resets.
|
||||
|
||||
Signed-off-by: Markus Fritsche <fritsche.markus@gmail.com>
|
||||
---
|
||||
drivers/staging/bes2600/bes2600_sdio.c | 29 +++++++++++++
|
||||
drivers/staging/bes2600/bes_chardev.c | 59 +++++++++++++++++++++++++-
|
||||
drivers/staging/bes2600/bes_chardev.h | 1 +
|
||||
drivers/staging/bes2600/sbus.h | 8 ++++
|
||||
bes2600/bes2600_sdio.c | 29 +++++++++++++++++++++
|
||||
bes2600/bes_chardev.c | 59 ++++++++++++++++++++++++++++++++++++++++--
|
||||
bes2600/bes_chardev.h | 1 +
|
||||
bes2600/sbus.h | 8 ++++++
|
||||
4 files changed, 95 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/bes2600/bes2600_sdio.c b/drivers/staging/bes2600/bes2600_sdio.c
|
||||
index b9d836fab7af..f7f86d765bba 100644
|
||||
index b9d836f..f7f86d7 100644
|
||||
--- a/drivers/staging/bes2600/bes2600_sdio.c
|
||||
+++ b/drivers/staging/bes2600/bes2600_sdio.c
|
||||
@@ -16,6 +16,7 @@
|
||||
@@ -139,10 +139,10 @@ index b9d836fab7af..f7f86d765bba 100644
|
||||
|
||||
static void bes2600_sdio_en_lp_cb(struct bes2600_common *hw_priv)
|
||||
diff --git a/drivers/staging/bes2600/bes_chardev.c b/drivers/staging/bes2600/bes_chardev.c
|
||||
index 455108a2dd66..b776aab5e062 100644
|
||||
index a02d6d9..d1375bc 100644
|
||||
--- a/drivers/staging/bes2600/bes_chardev.c
|
||||
+++ b/drivers/staging/bes2600/bes_chardev.c
|
||||
@@ -626,6 +626,48 @@ int bes2600_chrdev_do_system_close(const struct sbus_ops *sbus_ops, struct sbus_
|
||||
@@ -442,6 +442,48 @@ int bes2600_chrdev_do_system_close(const struct sbus_ops *sbus_ops, struct sbus_
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -191,7 +191,7 @@ index 455108a2dd66..b776aab5e062 100644
|
||||
bool bes2600_chrdev_is_wifi_opened(void)
|
||||
{
|
||||
bool wifi_opened = false;
|
||||
@@ -726,8 +768,21 @@ static void bes2600_chrdev_wifi_force_close_work(struct work_struct *work)
|
||||
@@ -540,8 +582,21 @@ static void bes2600_chrdev_wifi_force_close_work(struct work_struct *work)
|
||||
/* unregister wifi */
|
||||
bes2600_switch_wifi(0);
|
||||
|
||||
@@ -216,7 +216,7 @@ index 455108a2dd66..b776aab5e062 100644
|
||||
bes2600_cdev.sbus_priv);
|
||||
}
|
||||
diff --git a/drivers/staging/bes2600/bes_chardev.h b/drivers/staging/bes2600/bes_chardev.h
|
||||
index c627bb7c3d65..ca8419eead8f 100644
|
||||
index c627bb7..ca8419e 100644
|
||||
--- a/drivers/staging/bes2600/bes_chardev.h
|
||||
+++ b/drivers/staging/bes2600/bes_chardev.h
|
||||
@@ -60,6 +60,7 @@ struct sbus_priv *bes2600_chrdev_get_sbus_priv_data(void);
|
||||
@@ -228,7 +228,7 @@ index c627bb7c3d65..ca8419eead8f 100644
|
||||
void bes2600_chrdev_wifi_force_close(struct bes2600_common *hw_priv, bool halt_dev);
|
||||
void bes2600_chrdev_usb_remove(struct bes2600_common *hw_priv);
|
||||
diff --git a/drivers/staging/bes2600/sbus.h b/drivers/staging/bes2600/sbus.h
|
||||
index 1f2c0cda73de..cb9089004041 100644
|
||||
index 1f2c0cd..cb90890 100644
|
||||
--- a/drivers/staging/bes2600/sbus.h
|
||||
+++ b/drivers/staging/bes2600/sbus.h
|
||||
@@ -75,6 +75,14 @@ struct sbus_ops {
|
||||
@@ -247,5 +247,5 @@ index 1f2c0cda73de..cb9089004041 100644
|
||||
|
||||
void bes2600_irq_handler(struct bes2600_common *priv);
|
||||
--
|
||||
2.53.0
|
||||
2.54.0
|
||||
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
From 3942404ae16b134a55e48cb796d625b8b90e504f Mon Sep 17 00:00:00 2001
|
||||
From: Markus Fritsche <fritsche.markus@gmail.com>
|
||||
Date: Tue, 28 Apr 2026 21:37:37 +0200
|
||||
Subject: [PATCH 19/29] bes2600: handle multi-function SDIO cards in
|
||||
mmc_hw_reset bus_reset
|
||||
|
||||
c5.2 (recover-wedged-firmware-via-mmc-hw-reset) wraps mmc_hw_reset()
|
||||
and treats any non-zero return as a recovery failure. On
|
||||
single-function SDIO cards mmc_hw_reset returns 0 after doing the
|
||||
remove + rescan inline. On multi-function cards (BES2600 has WLAN
|
||||
func 1 + BT companion func 2) the kernel's mmc_sdio_hw_reset() does
|
||||
NOT do the rescan: it tears the card down and returns 1 to signal
|
||||
"caller must trigger rescan".
|
||||
|
||||
Field observation on PineTab2 (linux-pinetab2 6.19.10-danctnix1):
|
||||
when a real LMAC wedge fired bes2600_chrdev_wifi_force_close ->
|
||||
bes2600_chrdev_do_bus_reset, mmc_hw_reset returned 1, c5.2's wrapper
|
||||
treated that as "bus_reset failed: 1", logged the error, and gave
|
||||
up. The card was already removed (mmc2: card 0001 removed) but
|
||||
nothing scheduled a rescan; wifi (and the BT companion which shares
|
||||
the same SDIO host) stayed silent until the user rebooted four
|
||||
minutes later.
|
||||
|
||||
Fix:
|
||||
|
||||
- Capture the mmc_host pointer before calling mmc_hw_reset (the
|
||||
card pointer is invalid after the remove).
|
||||
- On positive return (multi-function path), log informationally
|
||||
and call mmc_detect_change(host, 0) to schedule a rescan.
|
||||
Return 0 so callers see the recovery as successful.
|
||||
- Negative return is still treated as failure as before.
|
||||
|
||||
The mmc_detect_change side effect is asynchronous; the chrdev's
|
||||
wait_event_timeout(probe_done_wq, !sbus_priv) still observes the
|
||||
remove half synchronously, and the rescan + re-probe runs out of
|
||||
the host detect work afterwards.
|
||||
|
||||
Signed-off-by: Markus Fritsche <fritsche.markus@gmail.com>
|
||||
---
|
||||
bes2600/bes2600_sdio.c | 24 +++++++++++++++++++++++-
|
||||
1 file changed, 23 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/staging/bes2600/bes2600_sdio.c b/drivers/staging/bes2600/bes2600_sdio.c
|
||||
index 5a0694a..c81c244 100644
|
||||
--- a/drivers/staging/bes2600/bes2600_sdio.c
|
||||
+++ b/drivers/staging/bes2600/bes2600_sdio.c
|
||||
@@ -1810,10 +1810,32 @@ static void bes2600_sdio_halt_device(struct sbus_priv *self)
|
||||
*/
|
||||
static int bes2600_sdio_bus_reset(struct sbus_priv *self)
|
||||
{
|
||||
+ struct mmc_host *host;
|
||||
+ int ret;
|
||||
+
|
||||
if (!self || !self->func || !self->func->card)
|
||||
return -EINVAL;
|
||||
|
||||
- return mmc_hw_reset(self->func->card);
|
||||
+ host = self->func->card->host;
|
||||
+ ret = mmc_hw_reset(self->func->card);
|
||||
+
|
||||
+ /*
|
||||
+ * On multi-function SDIO cards (BES2600 has WLAN func 1 + BT
|
||||
+ * companion func 2), mmc_sdio_hw_reset() removes the card and
|
||||
+ * returns 1 to signal "remove happened, caller must trigger
|
||||
+ * rescan". The kernel does NOT auto-rescan in this case;
|
||||
+ * single-function cards take the rescan path inline and return 0.
|
||||
+ * Treat any non-negative return as success and force a rescan if
|
||||
+ * mmc_hw_reset signalled the multi-function path - otherwise the
|
||||
+ * card stays removed indefinitely after a wedge recovery,
|
||||
+ * leaving wifi (and the BT companion) silent until reboot.
|
||||
+ */
|
||||
+ if (ret > 0) {
|
||||
+ bes_info("multi-func mmc_hw_reset removed card; scheduling rescan\n");
|
||||
+ mmc_detect_change(host, 0);
|
||||
+ ret = 0;
|
||||
+ }
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
static bool bes2600_sdio_wakeup_source(struct sbus_priv *self)
|
||||
--
|
||||
2.54.0
|
||||
|
||||
+9
-9
@@ -1,8 +1,8 @@
|
||||
From d1de35c62930b1bc035d3863d75901356548b6f0 Mon Sep 17 00:00:00 2001
|
||||
From dc1505f5bab24c5f0960dcc612ce51cd2e5aeddf Mon Sep 17 00:00:00 2001
|
||||
From: Markus Fritsche <fritsche.markus@gmail.com>
|
||||
Date: Tue, 28 Apr 2026 16:54:07 +0200
|
||||
Subject: [PATCH] bes2600: self-detect when firmware does not honor PSM and
|
||||
skip the cycle
|
||||
Date: Tue, 28 Apr 2026 16:54:06 +0200
|
||||
Subject: [PATCH 18/29] bes2600: self-detect when firmware does not honor PSM
|
||||
and skip the cycle
|
||||
|
||||
The c6 series fixed several host-side bookkeeping bugs around PSM
|
||||
transitions, but didn't address the underlying contract: this chip's
|
||||
@@ -64,12 +64,12 @@ firing entirely. The firmware-side wedge is observed once per boot
|
||||
|
||||
Signed-off-by: Markus Fritsche <fritsche.markus@gmail.com>
|
||||
---
|
||||
drivers/staging/bes2600/bes_pwr.c | 70 ++++++++++++++++++++++++++++++-
|
||||
drivers/staging/bes2600/bes_pwr.h | 9 ++++
|
||||
bes2600/bes_pwr.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++-
|
||||
bes2600/bes_pwr.h | 9 ++++++
|
||||
2 files changed, 78 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/staging/bes2600/bes_pwr.c b/drivers/staging/bes2600/bes_pwr.c
|
||||
index d54e1a0bab0c..ebaa42e3e61e 100644
|
||||
index b7b6c2f..620acef 100644
|
||||
--- a/drivers/staging/bes2600/bes_pwr.c
|
||||
+++ b/drivers/staging/bes2600/bes_pwr.c
|
||||
@@ -467,6 +467,45 @@ static void bes2600_pwr_device_enter_lp_mode(struct bes2600_common *hw_priv)
|
||||
@@ -185,7 +185,7 @@ index d54e1a0bab0c..ebaa42e3e61e 100644
|
||||
atomic_set(&hw_priv->bes_power.chip_pm_state,
|
||||
BES2600_CHIP_PM_LP);
|
||||
diff --git a/drivers/staging/bes2600/bes_pwr.h b/drivers/staging/bes2600/bes_pwr.h
|
||||
index 6bc44acd7501..92de90b398c6 100644
|
||||
index 6bc44ac..92de90b 100644
|
||||
--- a/drivers/staging/bes2600/bes_pwr.h
|
||||
+++ b/drivers/staging/bes2600/bes_pwr.h
|
||||
@@ -121,6 +121,15 @@ struct bes2600_pwr_t
|
||||
@@ -205,5 +205,5 @@ index 6bc44acd7501..92de90b398c6 100644
|
||||
|
||||
#ifdef CONFIG_BES2600_WOWLAN
|
||||
--
|
||||
2.53.0
|
||||
2.54.0
|
||||
|
||||
+7
-7
@@ -1,8 +1,8 @@
|
||||
From 80178ec9b1f83aed1dcce9ea7ca02bc81341ba01 Mon Sep 17 00:00:00 2001
|
||||
From e8550e55fc7d3910ee690359d89d96c86cfb0347 Mon Sep 17 00:00:00 2001
|
||||
From: Markus Fritsche <fritsche.markus@gmail.com>
|
||||
Date: Wed, 22 Apr 2026 12:37:45 +0200
|
||||
Subject: [PATCH] bes2600: gate device LP-mode entry on successful per-VIF
|
||||
firmware handshake
|
||||
Subject: [PATCH 04/29] bes2600: gate device LP-mode entry on successful
|
||||
per-VIF firmware handshake
|
||||
|
||||
bes2600_pwr_enter_lp_mode() drives the transition to low-power for each
|
||||
associated STA VIF: it pushes wsm_set_pm(), waits up to 5 seconds on
|
||||
@@ -49,10 +49,10 @@ Signed-off-by: Markus Fritsche <fritsche.markus@gmail.com>
|
||||
bes2600/bes_pwr.c | 20 +++++++++++++++++---
|
||||
1 file changed, 17 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/bes2600/bes_pwr.c b/bes2600/bes_pwr.c
|
||||
diff --git a/drivers/staging/bes2600/bes_pwr.c b/drivers/staging/bes2600/bes_pwr.c
|
||||
index e7a1045..f62ae22 100644
|
||||
--- a/bes2600/bes_pwr.c
|
||||
+++ b/bes2600/bes_pwr.c
|
||||
--- a/drivers/staging/bes2600/bes_pwr.c
|
||||
+++ b/drivers/staging/bes2600/bes_pwr.c
|
||||
@@ -472,6 +472,7 @@ static int bes2600_pwr_enter_lp_mode(struct bes2600_common *hw_priv)
|
||||
int i = 0;
|
||||
struct bes2600_vif *priv;
|
||||
@@ -101,5 +101,5 @@ index e7a1045..f62ae22 100644
|
||||
return ret;
|
||||
}
|
||||
--
|
||||
2.53.0
|
||||
2.54.0
|
||||
|
||||
+10
-10
@@ -1,8 +1,8 @@
|
||||
From 4ab8c790304206abd134de48c878b637a70f3c59 Mon Sep 17 00:00:00 2001
|
||||
From 40aec44a6e4de5aaf0066982601c99e648b0f1ec Mon Sep 17 00:00:00 2001
|
||||
From: Markus Fritsche <fritsche.markus@gmail.com>
|
||||
Date: Tue, 28 Apr 2026 15:05:27 +0200
|
||||
Subject: [PATCH] bes2600: gate PM indication completion on pending request and
|
||||
track chip state
|
||||
Subject: [PATCH 16/29] bes2600: gate PM indication completion on pending
|
||||
request and track chip state
|
||||
|
||||
When mac80211 toggles PSM on the BES2600, the host sends WSM set_pm
|
||||
and waits up to 5 s on bes_power.pm_enter_cmpl for a firmware-side
|
||||
@@ -67,12 +67,12 @@ recovery path (timeout + spontaneous indication) gains correctness.
|
||||
|
||||
Signed-off-by: Markus Fritsche <fritsche.markus@gmail.com>
|
||||
---
|
||||
drivers/staging/bes2600/bes_pwr.c | 94 ++++++++++++++++++++++++++++---
|
||||
drivers/staging/bes2600/bes_pwr.h | 15 +++++
|
||||
bes2600/bes_pwr.c | 94 ++++++++++++++++++++++++++++++++++++++++++-----
|
||||
bes2600/bes_pwr.h | 15 ++++++++
|
||||
2 files changed, 100 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/bes2600/bes_pwr.c b/drivers/staging/bes2600/bes_pwr.c
|
||||
index f62ae226d295..de46e5826ee7 100644
|
||||
index 474b6f1..9b4a4de 100644
|
||||
--- a/drivers/staging/bes2600/bes_pwr.c
|
||||
+++ b/drivers/staging/bes2600/bes_pwr.c
|
||||
@@ -524,7 +524,17 @@ static int bes2600_pwr_enter_lp_mode(struct bes2600_common *hw_priv)
|
||||
@@ -100,7 +100,7 @@ index f62ae226d295..de46e5826ee7 100644
|
||||
- atomic_set(&hw_priv->bes_power.pm_set_in_process, 0);
|
||||
- reinit_completion(&hw_priv->bes_power.pm_enter_cmpl);
|
||||
if (!status) {
|
||||
- bes_err("%s, wait pm ind timeout\n", __func__);
|
||||
- bes_devel("%s, wait pm ind timeout\n", __func__);
|
||||
- timeouts++;
|
||||
+ /*
|
||||
+ * The indication callback only fires
|
||||
@@ -123,7 +123,7 @@ index f62ae226d295..de46e5826ee7 100644
|
||||
+ */
|
||||
+ if (atomic_cmpxchg(&hw_priv->bes_power.pm_set_in_process,
|
||||
+ 1, 0) == 1) {
|
||||
+ bes_err("%s, wait pm ind timeout\n", __func__);
|
||||
+ bes_devel("%s, wait pm ind timeout\n", __func__);
|
||||
+ atomic_set(&hw_priv->bes_power.chip_pm_state,
|
||||
+ BES2600_CHIP_PM_UNKNOWN);
|
||||
+ timeouts++;
|
||||
@@ -209,7 +209,7 @@ index f62ae226d295..de46e5826ee7 100644
|
||||
}
|
||||
|
||||
diff --git a/drivers/staging/bes2600/bes_pwr.h b/drivers/staging/bes2600/bes_pwr.h
|
||||
index 1ba866c25c42..6bc44acd7501 100644
|
||||
index 1ba866c..6bc44ac 100644
|
||||
--- a/drivers/staging/bes2600/bes_pwr.h
|
||||
+++ b/drivers/staging/bes2600/bes_pwr.h
|
||||
@@ -64,6 +64,20 @@ enum power_down_state
|
||||
@@ -242,5 +242,5 @@ index 1ba866c25c42..6bc44acd7501 100644
|
||||
|
||||
#ifdef CONFIG_BES2600_WOWLAN
|
||||
--
|
||||
2.53.0
|
||||
2.54.0
|
||||
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
From ab9e0ad6b4bbb1196c448ed000c8c152b0f04683 Mon Sep 17 00:00:00 2001
|
||||
From 894c502cd541079a8a26d61cd4289af9001b3046 Mon Sep 17 00:00:00 2001
|
||||
From: Markus Fritsche <fritsche.markus@gmail.com>
|
||||
Date: Thu, 23 Apr 2026 20:35:17 +0200
|
||||
Subject: [PATCH] bes2600: demote 'wait pm ind timeout' from bes_err to
|
||||
Subject: [PATCH 11/29] bes2600: demote 'wait pm ind timeout' from bes_err to
|
||||
bes_devel
|
||||
|
||||
bes2600_pwr_enter_lp_mode() logs 'wait pm ind timeout' at bes_err
|
||||
@@ -49,5 +49,5 @@ index f62ae22..474b6f1 100644
|
||||
}
|
||||
} else {
|
||||
--
|
||||
2.53.0
|
||||
2.54.0
|
||||
|
||||
+11
-11
@@ -1,8 +1,8 @@
|
||||
From 706a594dab68779294e4fff9705a6e1df46ec1af Mon Sep 17 00:00:00 2001
|
||||
From 7a65dc374c671e20bd6303959ff234a179bc9ff7 Mon Sep 17 00:00:00 2001
|
||||
From: Markus Fritsche <fritsche.markus@gmail.com>
|
||||
Date: Tue, 28 Apr 2026 15:23:35 +0200
|
||||
Subject: [PATCH] bes2600: short-circuit wake handshake when chip is confirmed
|
||||
ACTIVE
|
||||
Date: Tue, 28 Apr 2026 15:23:34 +0200
|
||||
Subject: [PATCH 17/29] bes2600: short-circuit wake handshake when chip is
|
||||
confirmed ACTIVE
|
||||
|
||||
The previous patch ("bes2600: gate PM indication completion on pending
|
||||
request and track chip state") added enum bes2600_chip_pm_state and the
|
||||
@@ -75,15 +75,15 @@ field added in the prerequisite patch.
|
||||
|
||||
Signed-off-by: Markus Fritsche <fritsche.markus@gmail.com>
|
||||
---
|
||||
drivers/staging/bes2600/bes2600_sdio.c | 15 ++++++-
|
||||
drivers/staging/bes2600/bes_pwr.c | 56 ++++++++++++++++++++++----
|
||||
bes2600/bes2600_sdio.c | 15 +++++++++--
|
||||
bes2600/bes_pwr.c | 56 ++++++++++++++++++++++++++++++++++++------
|
||||
2 files changed, 62 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/bes2600/bes2600_sdio.c b/drivers/staging/bes2600/bes2600_sdio.c
|
||||
index b9d836fab7af..929503547cfd 100644
|
||||
index f7f86d7..5a0694a 100644
|
||||
--- a/drivers/staging/bes2600/bes2600_sdio.c
|
||||
+++ b/drivers/staging/bes2600/bes2600_sdio.c
|
||||
@@ -1388,7 +1388,14 @@ static void bes2600_gpio_wakeup_mcu(struct sbus_priv *self, int flag)
|
||||
@@ -1389,7 +1389,14 @@ static void bes2600_gpio_wakeup_mcu(struct sbus_priv *self, int flag)
|
||||
|
||||
/* error check */
|
||||
if((self->gpio_wakup_flags & BIT(flag)) != 0) {
|
||||
@@ -99,7 +99,7 @@ index b9d836fab7af..929503547cfd 100644
|
||||
mutex_unlock(&self->io_mutex);
|
||||
return;
|
||||
}
|
||||
@@ -1420,7 +1427,11 @@ static void bes2600_gpio_allow_mcu_sleep(struct sbus_priv *self, int flag)
|
||||
@@ -1421,7 +1428,11 @@ static void bes2600_gpio_allow_mcu_sleep(struct sbus_priv *self, int flag)
|
||||
|
||||
/* error check */
|
||||
if((self->gpio_wakup_flags & BIT(flag)) == 0) {
|
||||
@@ -113,7 +113,7 @@ index b9d836fab7af..929503547cfd 100644
|
||||
return;
|
||||
}
|
||||
diff --git a/drivers/staging/bes2600/bes_pwr.c b/drivers/staging/bes2600/bes_pwr.c
|
||||
index de46e5826ee7..d54e1a0bab0c 100644
|
||||
index 9b4a4de..b7b6c2f 100644
|
||||
--- a/drivers/staging/bes2600/bes_pwr.c
|
||||
+++ b/drivers/staging/bes2600/bes_pwr.c
|
||||
@@ -621,19 +621,61 @@ static int bes2600_pwr_enter_lp_mode(struct bes2600_common *hw_priv)
|
||||
@@ -186,5 +186,5 @@ index de46e5826ee7..d54e1a0bab0c 100644
|
||||
|
||||
ret = wsm_set_operational_mode(hw_priv, &mode, 0);
|
||||
--
|
||||
2.53.0
|
||||
2.54.0
|
||||
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
From 445c619da88d69adf68e8cae08ad1b53f76fe57d Mon Sep 17 00:00:00 2001
|
||||
From: Markus Fritsche <fritsche.markus@gmail.com>
|
||||
Date: Fri, 8 May 2026 00:22:14 +0200
|
||||
Subject: [PATCH 28/29] =?UTF-8?q?bes2600:=20Patch=20E=20=E2=80=94=20skip?=
|
||||
=?UTF-8?q?=20ps=5Fstate=5Flock=20when=20PSM-known-disabled?=
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Per the Opus structural critique (PR #8 §2.4) and Sonnet review item 5.
|
||||
The per-RX-frame early-data path takes ps_state_lock to double-check
|
||||
whether a link entry transitioned to BES2600_LINK_SOFT (AP-side
|
||||
power-save state machine, soft-link transition).
|
||||
|
||||
When c7 has latched pm_unsupported = true (firmware does not honor
|
||||
PSM, see feedback_bes2600_firmware_no_psm memory), the AP power-save
|
||||
state machine is dead and link entries never transition to LINK_SOFT.
|
||||
The per-frame spin_lock_bh + double-check is wasted work.
|
||||
|
||||
This patch gates the lock acquisition on !pm_unsupported. When the
|
||||
latch is on (the steady state on the production-shipped bes2600
|
||||
firmware), early_data RX frames bypass the spin_lock_bh and go
|
||||
directly to ieee80211_rx_irqsafe.
|
||||
|
||||
If a future firmware drop fixes PSM, c7 self-clears pm_unsupported on
|
||||
the first real PM_INDICATION and the locked path resumes.
|
||||
|
||||
Scope is narrower than Sonnet originally framed: only the per-RX-frame
|
||||
hot path (txrx.c:1945-1951 in cleanups+G+D) is touched. Other
|
||||
ps_state_lock sites in txrx.c (lines 657, 1256, 1420, 1528) are TX
|
||||
submission / multicast-start / link-id paths, not per-frame RX, and
|
||||
not on the Bug #5 hot path. Leave those alone.
|
||||
|
||||
Build verified: srcversion B5922B4933590F33207EE97 on ohm sandbox.
|
||||
---
|
||||
bes2600/txrx.c | 30 ++++++++++++++++++++++++------
|
||||
1 file changed, 24 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/bes2600/txrx.c b/drivers/staging/bes2600/txrx.c
|
||||
index 536b198..cb718ad 100644
|
||||
--- a/drivers/staging/bes2600/txrx.c
|
||||
+++ b/drivers/staging/bes2600/txrx.c
|
||||
@@ -1965,13 +1965,31 @@ void bes2600_rx_cb(struct bes2600_vif *priv,
|
||||
if (unlikely(bes2600_itp_rxed(hw_priv, skb)))
|
||||
consume_skb(skb);
|
||||
else if (unlikely(early_data)) {
|
||||
- spin_lock_bh(&priv->ps_state_lock);
|
||||
- /* Double-check status with lock held */
|
||||
- if (entry->status == BES2600_LINK_SOFT)
|
||||
- skb_queue_tail(&entry->rx_queue, skb);
|
||||
- else
|
||||
+ /*
|
||||
+ * Patch E: when c7 has latched pm_unsupported (firmware
|
||||
+ * doesn't honour PSM, see feedback_bes2600_firmware_no_psm),
|
||||
+ * AP-side power-save state machine is dead and link entries
|
||||
+ * never transition to BES2600_LINK_SOFT. The double-check
|
||||
+ * branch under ps_state_lock is unreachable in that case,
|
||||
+ * so skip the per-frame lock acquisition entirely and
|
||||
+ * deliver to mac80211 directly.
|
||||
+ *
|
||||
+ * On firmware that does honour PSM (the latch self-clears
|
||||
+ * if a real PM_INDICATION ever arrives — see c7), this
|
||||
+ * predicate flips back to false and the original locked
|
||||
+ * path is taken.
|
||||
+ */
|
||||
+ if (hw_priv->bes_power.pm_unsupported) {
|
||||
ieee80211_rx_irqsafe(priv->hw, skb);
|
||||
- spin_unlock_bh(&priv->ps_state_lock);
|
||||
+ } else {
|
||||
+ spin_lock_bh(&priv->ps_state_lock);
|
||||
+ /* Double-check status with lock held */
|
||||
+ if (entry->status == BES2600_LINK_SOFT)
|
||||
+ skb_queue_tail(&entry->rx_queue, skb);
|
||||
+ else
|
||||
+ ieee80211_rx_irqsafe(priv->hw, skb);
|
||||
+ spin_unlock_bh(&priv->ps_state_lock);
|
||||
+ }
|
||||
} else {
|
||||
ieee80211_rx_irqsafe(priv->hw, skb);
|
||||
}
|
||||
--
|
||||
2.54.0
|
||||
|
||||
+3
@@ -116,3 +116,6 @@ index e6cf072..0cf7ce1 100644
|
||||
|
||||
if (atomic_read(&hw_priv->bh_rx) > 0)
|
||||
wake_up(&hw_priv->bh_wq);
|
||||
--
|
||||
2.54.0
|
||||
|
||||
|
||||
+112
-32
@@ -1,7 +1,7 @@
|
||||
From f43bcc5dda0a9120aee62cce0cec1a8c851cb4ef Mon Sep 17 00:00:00 2001
|
||||
From cd5f85e10480f02e289ea731b5eeec571000562c Mon Sep 17 00:00:00 2001
|
||||
From: Markus Fritsche <fritsche.markus@gmail.com>
|
||||
Date: Wed, 22 Apr 2026 12:55:18 +0200
|
||||
Subject: [PATCH] bes2600: remove userspace /dev/bes2600 character device
|
||||
Subject: [PATCH 05/29] bes2600: remove userspace /dev/bes2600 character device
|
||||
interface
|
||||
|
||||
bes_chardev.c implemented a custom character device at /dev/bes2600 with
|
||||
@@ -73,13 +73,13 @@ Follow-ups:
|
||||
|
||||
Signed-off-by: Markus Fritsche <fritsche.markus@gmail.com>
|
||||
---
|
||||
bes2600/bes_chardev.c | 519 ------------------------------------------
|
||||
1 file changed, 519 deletions(-)
|
||||
bes2600/bes_chardev.c | 568 +-----------------------------------------
|
||||
1 file changed, 3 insertions(+), 565 deletions(-)
|
||||
|
||||
diff --git a/bes2600/bes_chardev.c b/bes2600/bes_chardev.c
|
||||
index 9038e48..e2e4f1b 100644
|
||||
--- a/bes2600/bes_chardev.c
|
||||
+++ b/bes2600/bes_chardev.c
|
||||
diff --git a/drivers/staging/bes2600/bes_chardev.c b/drivers/staging/bes2600/bes_chardev.c
|
||||
index f89dcb8..e2e4f1b 100644
|
||||
--- a/drivers/staging/bes2600/bes_chardev.c
|
||||
+++ b/drivers/staging/bes2600/bes_chardev.c
|
||||
@@ -43,12 +43,6 @@ enum bus_probe_state {
|
||||
};
|
||||
|
||||
@@ -93,10 +93,74 @@ index 9038e48..e2e4f1b 100644
|
||||
atomic_t num_proc;
|
||||
wait_queue_head_t open_wq;
|
||||
spinlock_t status_lock;
|
||||
@@ -249,351 +243,18 @@ int bes2600_switch_bt(bool on)
|
||||
@@ -196,7 +190,7 @@ static int bes2600_switch_wifi(bool on)
|
||||
return ret;
|
||||
}
|
||||
|
||||
-static int bes2600_switch_bt(bool on)
|
||||
+int bes2600_switch_bt(bool on)
|
||||
{
|
||||
int ret = 0;
|
||||
long status = 0;
|
||||
@@ -229,11 +223,11 @@ static int bes2600_switch_bt(bool on)
|
||||
/* check if there is a error when bootup */
|
||||
ret = (status <= 0 || bes2600_chrdev_is_bus_error()) ? -1 : 0;
|
||||
} else {
|
||||
- bes_devel("bes2600 activate bt.\n");
|
||||
+ bes_info("enable BT\n");
|
||||
ret = bes2600_chrdev_switch_subsys(GPIO_WAKE_FLAG_BT_ON, SUBSYSTEM_BT, true);
|
||||
}
|
||||
} else {
|
||||
- bes_devel("bes2600 deactivate bt.\n");
|
||||
+ bes_info("disable BT\n");
|
||||
bes2600_chrdev_switch_subsys(GPIO_WAKE_FLAG_BT_OFF, SUBSYSTEM_BT, false);
|
||||
}
|
||||
|
||||
@@ -249,392 +243,18 @@ static int bes2600_switch_bt(bool on)
|
||||
return ret;
|
||||
}
|
||||
|
||||
-/*
|
||||
- * This is a global function so we don't have to make many changes to
|
||||
- * the driver.
|
||||
- *
|
||||
- * @wifi: 1 to turn on, 0 to turn off. Otherwise, leave unchanged
|
||||
- * @bt: 1 to turn on, 0 to turn off. Otherwise, leave unchanged
|
||||
- */
|
||||
-int bes2600_chrdev_switch_subsys_glb(int wifi, int bt)
|
||||
-{
|
||||
- int ret = 0;
|
||||
-
|
||||
- switch (wifi) {
|
||||
- case 0:
|
||||
- ret = bes2600_switch_wifi(false);
|
||||
- break;
|
||||
- case 1:
|
||||
- ret = bes2600_switch_wifi(true);
|
||||
- break;
|
||||
- default:
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
- if (ret)
|
||||
- goto result;
|
||||
-
|
||||
- switch (bt) {
|
||||
- case 0:
|
||||
- ret = bes2600_switch_bt(false);
|
||||
- break;
|
||||
- case 1:
|
||||
- ret = bes2600_switch_bt(true);
|
||||
- break;
|
||||
- default:
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
-result:
|
||||
- return ret;
|
||||
-}
|
||||
-EXPORT_SYMBOL_GPL(bes2600_chrdev_switch_subsys_glb);
|
||||
-
|
||||
-static int bes2600_get_cmd_and_ifname(const char *str, char **result)
|
||||
-{
|
||||
- int cmd_len = 0;
|
||||
@@ -192,11 +256,11 @@ index 9038e48..e2e4f1b 100644
|
||||
- probe_state = bes2600_cdev.bus_probe;
|
||||
- wait_state = bes2600_cdev.wait_state;
|
||||
- spin_unlock(&bes2600_cdev.status_lock);
|
||||
-
|
||||
|
||||
- /* only work for wifi signal mode */
|
||||
- if (bes2600_cdev.fw_type != BES2600_FW_TYPE_WIFI_SIGNAL)
|
||||
- return -EFAULT;
|
||||
-
|
||||
|
||||
- /* wait bus probe operation end */
|
||||
- if (probe_state == BES2600_BUS_PROBE_START) {
|
||||
- bes_devel("wait bus probe operation end\n");
|
||||
@@ -205,7 +269,7 @@ index 9038e48..e2e4f1b 100644
|
||||
- HZ);
|
||||
- WARN_ON(status <= 0);
|
||||
- }
|
||||
-
|
||||
|
||||
- /* must wait previous operation end in critical section */
|
||||
- if (wait_state != BES2600_BOOT_WAIT_NONE) {
|
||||
- bes_devel("wait previous operation end\n");
|
||||
@@ -214,7 +278,7 @@ index 9038e48..e2e4f1b 100644
|
||||
- HZ * 8);
|
||||
- WARN_ON(status <= 0);
|
||||
- }
|
||||
-
|
||||
|
||||
- /* if dpd calibration is doing, modify wifi and bt state directly */
|
||||
- spin_lock(&bes2600_cdev.status_lock);
|
||||
- if (bes2600_cdev.bus_probe == BES2600_BUS_PROBE_OK && !bes2600_cdev.dpd_calied) {
|
||||
@@ -233,16 +297,16 @@ index 9038e48..e2e4f1b 100644
|
||||
- }
|
||||
- bes2600_recyle_cmd_and_ifname_mem(info);
|
||||
- spin_unlock(&bes2600_cdev.status_lock);
|
||||
-
|
||||
|
||||
- /* wait probe done event */
|
||||
- status = wait_event_timeout(bes2600_cdev.probe_done_wq,
|
||||
- bes2600_bootup_end(), HZ * 8);
|
||||
- WARN_ON(status <= 0);
|
||||
-
|
||||
|
||||
- return (status <= 0 || bes2600_chrdev_is_bus_error()) ? -EFAULT : 0;
|
||||
- }
|
||||
- spin_unlock(&bes2600_cdev.status_lock);
|
||||
-
|
||||
|
||||
- /* process wifi/bt on/off operation */
|
||||
- if (bes2600_get_cmd_and_ifname(str, info) == 0) {
|
||||
- if (strncmp(info[1], "WIFI_ON", 7) == 0) {
|
||||
@@ -255,7 +319,7 @@ index 9038e48..e2e4f1b 100644
|
||||
- ret = bes2600_switch_bt(0);
|
||||
- }
|
||||
- }
|
||||
-
|
||||
|
||||
- if (!ret && bes2600_chrdev_check_system_close())
|
||||
- ret = bes2600_chrdev_do_system_close(bes2600_cdev.sbus_ops,
|
||||
- bes2600_cdev.sbus_priv);
|
||||
@@ -344,8 +408,8 @@ index 9038e48..e2e4f1b 100644
|
||||
- WARN_ON(status <= 0);
|
||||
-
|
||||
- ret = (status <= 0 || bes2600_chrdev_is_bus_error()) ? -1 : 0;
|
||||
|
||||
|
||||
-
|
||||
-
|
||||
- return ret;
|
||||
-}
|
||||
-
|
||||
@@ -360,7 +424,7 @@ index 9038e48..e2e4f1b 100644
|
||||
- return -EFAULT;
|
||||
- }
|
||||
- spin_unlock(&bes2600_cdev.status_lock);
|
||||
|
||||
-
|
||||
- /* wait probe done event */
|
||||
- status = wait_event_timeout(bes2600_cdev.probe_done_wq,
|
||||
- bes2600_bootup_end(), HZ * 8);
|
||||
@@ -384,26 +448,26 @@ index 9038e48..e2e4f1b 100644
|
||||
- return -EFAULT;
|
||||
- }
|
||||
- spin_unlock(&bes2600_cdev.status_lock);
|
||||
|
||||
-
|
||||
- /* wait probe done event */
|
||||
- status = wait_event_timeout(bes2600_cdev.probe_done_wq,
|
||||
- bes2600_bootup_end(), HZ * 8);
|
||||
- if (status <= 0 || bes2600_chrdev_is_bus_error())
|
||||
- return -EFAULT;
|
||||
|
||||
-
|
||||
- bes_devel("bes2600 allow bt sleep.\n");
|
||||
- ret = bes2600_chrdev_switch_subsys(GPIO_WAKE_FLAG_BT_LP_OFF, SUBSYSTEM_BT_LP, false);
|
||||
|
||||
-
|
||||
- return ret;
|
||||
-}
|
||||
|
||||
-
|
||||
-static int bes2600_op_set_wakeup_read_flag(const char *str)
|
||||
-{
|
||||
- bes_devel("%s is called, arg:%s\n", __func__, str);
|
||||
- spin_lock(&bes2600_cdev.status_lock);
|
||||
- bes2600_cdev.read_flag = BES_CDEV_READ_WAKEUP_STATE;
|
||||
- spin_unlock(&bes2600_cdev.status_lock);
|
||||
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
|
||||
@@ -445,7 +509,7 @@ index 9038e48..e2e4f1b 100644
|
||||
|
||||
static int bes2600_chrdev_check_system_close_internal(void)
|
||||
{
|
||||
@@ -603,123 +264,10 @@ static int bes2600_chrdev_check_system_close_internal(void)
|
||||
@@ -644,123 +264,10 @@ static int bes2600_chrdev_check_system_close_internal(void)
|
||||
&& (bes2600_cdev.wifi_opened == false);
|
||||
}
|
||||
|
||||
@@ -569,7 +633,23 @@ index 9038e48..e2e4f1b 100644
|
||||
|
||||
#ifdef BES2600_WRITE_DPD_TO_FILE
|
||||
static int bes2600_chrdev_write_dpd_data_to_file(const char *path, void *buffer, int size)
|
||||
@@ -1124,12 +672,6 @@ void bes2600_chrdev_update_signal_mode(void)
|
||||
@@ -1126,7 +633,6 @@ void bes2600_chrdev_wakeup_bt(void)
|
||||
bes_err("Wakeup BT fail in resume\n");
|
||||
}
|
||||
}
|
||||
-EXPORT_SYMBOL_GPL(bes2600_chrdev_wakeup_bt);
|
||||
|
||||
int bes2600_chrdev_get_fw_type(void)
|
||||
{
|
||||
@@ -1148,7 +654,6 @@ bool bes2600_chrdev_is_bus_error(void)
|
||||
|
||||
return error;
|
||||
}
|
||||
-EXPORT_SYMBOL_GPL(bes2600_chrdev_is_bus_error);
|
||||
|
||||
void bes2600_chrdev_update_signal_mode(void)
|
||||
{
|
||||
@@ -1167,12 +672,6 @@ void bes2600_chrdev_update_signal_mode(void)
|
||||
|
||||
static void bes2600_chrdev_wifi_force_close_work(struct work_struct *work)
|
||||
{
|
||||
@@ -582,7 +662,7 @@ index 9038e48..e2e4f1b 100644
|
||||
if (bes2600_chrdev_is_wifi_opened()) {
|
||||
bes_devel("system exeception, force wifi down\n");
|
||||
|
||||
@@ -1146,14 +688,6 @@ static void bes2600_chrdev_wifi_force_close_work(struct work_struct *work)
|
||||
@@ -1189,14 +688,6 @@ static void bes2600_chrdev_wifi_force_close_work(struct work_struct *work)
|
||||
bes2600_chrdev_do_system_close(bes2600_cdev.sbus_ops,
|
||||
bes2600_cdev.sbus_priv);
|
||||
}
|
||||
@@ -597,7 +677,7 @@ index 9038e48..e2e4f1b 100644
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1247,46 +781,6 @@ int bes2600_chrdev_wakeup_by_event_get(void)
|
||||
@@ -1290,46 +781,6 @@ int bes2600_chrdev_wakeup_by_event_get(void)
|
||||
|
||||
int bes2600_chrdev_init(struct sbus_ops *ops)
|
||||
{
|
||||
@@ -644,7 +724,7 @@ index 9038e48..e2e4f1b 100644
|
||||
/* initialise global variable */
|
||||
atomic_set(&bes2600_cdev.num_proc, 0);
|
||||
init_waitqueue_head(&bes2600_cdev.open_wq);
|
||||
@@ -1318,15 +812,6 @@ int bes2600_chrdev_init(struct sbus_ops *ops)
|
||||
@@ -1361,15 +812,6 @@ int bes2600_chrdev_init(struct sbus_ops *ops)
|
||||
bes_devel("%s done\n", __func__);
|
||||
|
||||
return 0;
|
||||
@@ -660,7 +740,7 @@ index 9038e48..e2e4f1b 100644
|
||||
}
|
||||
|
||||
void bes2600_chrdev_free(void)
|
||||
@@ -1336,9 +821,5 @@ void bes2600_chrdev_free(void)
|
||||
@@ -1379,9 +821,5 @@ void bes2600_chrdev_free(void)
|
||||
bes2600_free_dpd_log_buffer();
|
||||
#endif
|
||||
bes2600_chrdev_free_dpd_data();
|
||||
@@ -671,5 +751,5 @@ index 9038e48..e2e4f1b 100644
|
||||
bes_devel("%s done\n", __func__);
|
||||
}
|
||||
--
|
||||
2.53.0
|
||||
2.54.0
|
||||
|
||||
+216
@@ -0,0 +1,216 @@
|
||||
From a70e882f3d5f4f9148206675562dddeecd3f4404 Mon Sep 17 00:00:00 2001
|
||||
From: Markus Fritsche <fritsche.markus@gmail.com>
|
||||
Date: Fri, 8 May 2026 06:40:00 +0200
|
||||
Subject: [PATCH 29/29] =?UTF-8?q?bes2600:=20Patch=20C2=20=E2=80=94=20repla?=
|
||||
=?UTF-8?q?ce=20ieee80211=5Frx=5Firqsafe=20with=20ieee80211=5Frx=5Fni?=
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Per Phase 4 plan PR #14 + kerneldoc audit (Task #19). Six call sites
|
||||
deferred per-RX-frame mac80211 dispatch via tasklet; replace with the
|
||||
synchronous-from-process-context API ieee80211_rx_ni() which does its
|
||||
own local_bh_disable wrap.
|
||||
|
||||
Why _ni and not _list:
|
||||
|
||||
Phase 4 plan originally targeted ieee80211_rx_list for batch
|
||||
delivery. Mining mt76 mainline (the only driver using _list)
|
||||
showed the canonical pattern requires threading a struct list_head
|
||||
through the per-frame call chain. bes2600s WSM dispatcher
|
||||
(wsm_handle_rx -> bes2600_rx_cb / wsm.c beacon path) sits between
|
||||
the bh threads SDIO read and the mac80211 hand-off; threading a
|
||||
list_head through the dispatcher is a non-trivial refactor.
|
||||
ieee80211_rx_ni() is the simpler drop-in: no list management, still
|
||||
removes the tasklet hop. Per-call local_bh_disable cost is trivial
|
||||
vs the saved tasklet schedule. Future refactor can revisit _list
|
||||
if measurements warrant.
|
||||
|
||||
Sites converted:
|
||||
|
||||
- ap.c:96 (bes2600_sta_add link-id rx_queue drain on AP-mode
|
||||
STA add). Was inside spin_lock_bh(&ps_state_lock);
|
||||
refactored to splice the queue under the lock then
|
||||
deliver after unlock — _ni runs the synchronous
|
||||
mac80211 RX path inline, would otherwise hold the
|
||||
lock across mac80211 dispatch. splice via
|
||||
skb_queue_splice_init into a local sk_buff_head.
|
||||
- sta.c:1487 (deauth-frame inject in inactivity-event handler).
|
||||
Not under any lock; direct conversion.
|
||||
- txrx.c:1960 (early-data + pm_unsupported branch from Patch E).
|
||||
- txrx.c:1967 (early-data + LINK_SOFT-not-set branch).
|
||||
- txrx.c:1971 (normal RX path in bes2600_rx_cb).
|
||||
- wsm.c:2415 (beacon delivery in scan-complete WSM handler).
|
||||
beacon SKB ownership is preserved by the existing
|
||||
skb_copy(beacon, GFP_ATOMIC) -> beacon_bkp pattern;
|
||||
no lifecycle change needed.
|
||||
|
||||
Mixing constraint (kerneldoc include/net/mac80211.h:5399-5430):
|
||||
ieee80211_rx_ni() cannot mix with ieee80211_rx_irqsafe() for a
|
||||
single hardware. All 6 sites convert atomically; no mixed state.
|
||||
|
||||
Build verified clean on ohm sandbox: srcversion 619A51E61BF5479AAC146E6.
|
||||
|
||||
Predicted Phase 7 delta: +5-15% over v3+D+E baseline (2.35 MB/s mean
|
||||
on v3 alone; D+E single-rep was 3.22 MB/s). Modest improvement
|
||||
expected from removing the tasklet schedule per RX frame. Smaller
|
||||
deltas would still be a net win for upstream-cleanliness — the
|
||||
kernel.org submission story benefits from not using _irqsafe from
|
||||
process context.
|
||||
---
|
||||
bes2600/ap.c | 15 +++++++++++++--
|
||||
bes2600/bes_chardev.c | 33 ++++++++++++++++++++++++++++++++-
|
||||
bes2600/sta.c | 2 +-
|
||||
bes2600/txrx.c | 6 +++---
|
||||
bes2600/wsm.c | 2 +-
|
||||
5 files changed, 50 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/bes2600/ap.c b/drivers/staging/bes2600/ap.c
|
||||
index 8a17545..99e2da2 100644
|
||||
--- a/drivers/staging/bes2600/ap.c
|
||||
+++ b/drivers/staging/bes2600/ap.c
|
||||
@@ -63,8 +63,11 @@ int bes2600_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct bes2600_vif *priv = cw12xx_get_vif_from_ieee80211(vif);
|
||||
struct bes2600_link_entry *entry;
|
||||
struct sk_buff *skb;
|
||||
+ struct sk_buff_head local_drain;
|
||||
struct bes2600_common *hw_priv = hw->priv;
|
||||
|
||||
+ __skb_queue_head_init(&local_drain);
|
||||
+
|
||||
#ifdef P2P_MULTIVIF
|
||||
WARN_ON(priv->if_id == CW12XX_GENERIC_IF_ID);
|
||||
#endif
|
||||
@@ -93,9 +96,17 @@ int bes2600_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK)
|
||||
priv->sta_asleep_mask |= BIT(sta_priv->link_id);
|
||||
entry->status = BES2600_LINK_HARD;
|
||||
- while ((skb = skb_dequeue(&entry->rx_queue)))
|
||||
- ieee80211_rx_irqsafe(priv->hw, skb);
|
||||
+ /*
|
||||
+ * Patch C2: splice the rx_queue out under the lock then deliver
|
||||
+ * after unlock. ieee80211_rx_ni() runs the mac80211 RX path
|
||||
+ * synchronously (formerly ieee80211_rx_irqsafe deferred to a
|
||||
+ * tasklet); calling it from inside spin_lock_bh would hold the
|
||||
+ * lock across mac80211's full RX dispatch.
|
||||
+ */
|
||||
+ skb_queue_splice_init(&entry->rx_queue, &local_drain);
|
||||
spin_unlock_bh(&priv->ps_state_lock);
|
||||
+ while ((skb = __skb_dequeue(&local_drain)))
|
||||
+ ieee80211_rx_ni(priv->hw, skb);
|
||||
#ifdef AP_AGGREGATE_FW_FIX
|
||||
hw_priv->connected_sta_cnt++;
|
||||
if(hw_priv->connected_sta_cnt>1) {
|
||||
diff --git a/drivers/staging/bes2600/bes_chardev.c b/drivers/staging/bes2600/bes_chardev.c
|
||||
index 02dcd43..844f1d0 100644
|
||||
--- a/drivers/staging/bes2600/bes_chardev.c
|
||||
+++ b/drivers/staging/bes2600/bes_chardev.c
|
||||
@@ -181,7 +181,7 @@ static int bes2600_switch_wifi(bool on)
|
||||
return ret;
|
||||
}
|
||||
|
||||
-int bes2600_switch_bt(bool on)
|
||||
+static int bes2600_switch_bt(bool on)
|
||||
{
|
||||
int ret = 0;
|
||||
long status = 0;
|
||||
@@ -234,6 +234,36 @@ int bes2600_switch_bt(bool on)
|
||||
return ret;
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * Re-added for danctnix's bes2600_btuart.c (a danctnix-only file) which
|
||||
+ * relies on the chardev utility API for BT power switching and bus-error
|
||||
+ * checks. The userspace /dev/bes2600 chardev itself is removed by the
|
||||
+ * remove-chardev-user-interface series; these in-kernel helpers stay.
|
||||
+ *
|
||||
+ * @wifi: 1 to turn on, 0 to turn off. Otherwise, leave unchanged
|
||||
+ * @bt: 1 to turn on, 0 to turn off. Otherwise, leave unchanged
|
||||
+ */
|
||||
+int bes2600_chrdev_switch_subsys_glb(int wifi, int bt)
|
||||
+{
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ switch (wifi) {
|
||||
+ case 0: ret = bes2600_switch_wifi(false); break;
|
||||
+ case 1: ret = bes2600_switch_wifi(true); break;
|
||||
+ default: break;
|
||||
+ }
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ switch (bt) {
|
||||
+ case 0: ret = bes2600_switch_bt(false); break;
|
||||
+ case 1: ret = bes2600_switch_bt(true); break;
|
||||
+ default: break;
|
||||
+ }
|
||||
+ return ret;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(bes2600_chrdev_switch_subsys_glb);
|
||||
+
|
||||
|
||||
|
||||
|
||||
@@ -562,6 +592,7 @@ bool bes2600_chrdev_is_bus_error(void)
|
||||
|
||||
return error;
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(bes2600_chrdev_is_bus_error);
|
||||
|
||||
void bes2600_chrdev_update_signal_mode(void)
|
||||
{
|
||||
diff --git a/drivers/staging/bes2600/sta.c b/drivers/staging/bes2600/sta.c
|
||||
index 8af8150..2b63ff2 100644
|
||||
--- a/drivers/staging/bes2600/sta.c
|
||||
+++ b/drivers/staging/bes2600/sta.c
|
||||
@@ -1500,7 +1500,7 @@ void bes2600_event_handler(struct work_struct *work)
|
||||
IEEE80211_STYPE_DEAUTH | IEEE80211_FCTL_TODS);
|
||||
deauth->u.deauth.reason_code = WLAN_REASON_DEAUTH_LEAVING;
|
||||
deauth->seq_ctrl = 0;
|
||||
- ieee80211_rx_irqsafe(priv->hw, skb);
|
||||
+ ieee80211_rx_ni(priv->hw, skb);
|
||||
bes_devel(" Inactivity Deauth Frame sent for MAC SA %pM \t and DA %pM\n", deauth->sa, deauth->da);
|
||||
queue_work(priv->hw_priv->workqueue, &priv->set_tim_work);
|
||||
break;
|
||||
diff --git a/drivers/staging/bes2600/txrx.c b/drivers/staging/bes2600/txrx.c
|
||||
index cb718ad..9074972 100644
|
||||
--- a/drivers/staging/bes2600/txrx.c
|
||||
+++ b/drivers/staging/bes2600/txrx.c
|
||||
@@ -1980,18 +1980,18 @@ void bes2600_rx_cb(struct bes2600_vif *priv,
|
||||
* path is taken.
|
||||
*/
|
||||
if (hw_priv->bes_power.pm_unsupported) {
|
||||
- ieee80211_rx_irqsafe(priv->hw, skb);
|
||||
+ ieee80211_rx_ni(priv->hw, skb);
|
||||
} else {
|
||||
spin_lock_bh(&priv->ps_state_lock);
|
||||
/* Double-check status with lock held */
|
||||
if (entry->status == BES2600_LINK_SOFT)
|
||||
skb_queue_tail(&entry->rx_queue, skb);
|
||||
else
|
||||
- ieee80211_rx_irqsafe(priv->hw, skb);
|
||||
+ ieee80211_rx_ni(priv->hw, skb);
|
||||
spin_unlock_bh(&priv->ps_state_lock);
|
||||
}
|
||||
} else {
|
||||
- ieee80211_rx_irqsafe(priv->hw, skb);
|
||||
+ ieee80211_rx_ni(priv->hw, skb);
|
||||
}
|
||||
*skb_p = NULL;
|
||||
|
||||
diff --git a/drivers/staging/bes2600/wsm.c b/drivers/staging/bes2600/wsm.c
|
||||
index 908c965..2424181 100644
|
||||
--- a/drivers/staging/bes2600/wsm.c
|
||||
+++ b/drivers/staging/bes2600/wsm.c
|
||||
@@ -2412,7 +2412,7 @@ int wsm_handle_rx(struct bes2600_common *hw_priv, int id,
|
||||
if (!hw_priv->beacon_bkp)
|
||||
hw_priv->beacon_bkp = \
|
||||
skb_copy(hw_priv->beacon, GFP_ATOMIC);
|
||||
- ieee80211_rx_irqsafe(hw_priv->hw, hw_priv->beacon);
|
||||
+ ieee80211_rx_ni(hw_priv->hw, hw_priv->beacon);
|
||||
hw_priv->beacon = hw_priv->beacon_bkp;
|
||||
|
||||
hw_priv->beacon_bkp = NULL;
|
||||
--
|
||||
2.54.0
|
||||
|
||||
+6
-6
@@ -1,8 +1,8 @@
|
||||
From 3d98404c1a85ef33e9fc1422042c71dc90f3b255 Mon Sep 17 00:00:00 2001
|
||||
From 179c2e0bf852734631acfc56b2478775215cc5f6 Mon Sep 17 00:00:00 2001
|
||||
From: Markus Fritsche <fritsche.markus@gmail.com>
|
||||
Date: Tue, 28 Apr 2026 14:32:18 +0200
|
||||
Subject: [PATCH] bes2600: widen scan-defer backoff to 30s and decay count on
|
||||
quiet
|
||||
Subject: [PATCH 14/29] bes2600: widen scan-defer backoff to 30s and decay
|
||||
count on quiet
|
||||
|
||||
The scan-defer logic added in the previous patch ("bes2600: defer
|
||||
scan and soften WARN on firmware reject") used a 10-second backoff
|
||||
@@ -57,11 +57,11 @@ status=-EBUSY, the same response a real firmware-busy would produce.
|
||||
|
||||
Signed-off-by: Markus Fritsche <fritsche.markus@gmail.com>
|
||||
---
|
||||
drivers/staging/bes2600/scan.c | 17 +++++++++++++++--
|
||||
bes2600/scan.c | 17 +++++++++++++++--
|
||||
1 file changed, 15 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/bes2600/scan.c b/drivers/staging/bes2600/scan.c
|
||||
index 5f6af3bc81ba..b944adcaa08c 100644
|
||||
index 5f6af3b..b944adc 100644
|
||||
--- a/drivers/staging/bes2600/scan.c
|
||||
+++ b/drivers/staging/bes2600/scan.c
|
||||
@@ -22,9 +22,17 @@
|
||||
@@ -105,5 +105,5 @@ index 5f6af3bc81ba..b944adcaa08c 100644
|
||||
time_before(jiffies, hw_priv->scan.backoff_until))
|
||||
return true;
|
||||
--
|
||||
2.53.0
|
||||
2.54.0
|
||||
|
||||
+5
-5
@@ -1,7 +1,7 @@
|
||||
From adc6c1f332d41ee1aadd349eea11809c88139307 Mon Sep 17 00:00:00 2001
|
||||
From 844e2245a1ed517b3a0bc487fec1a100304f0b44 Mon Sep 17 00:00:00 2001
|
||||
From: Markus Fritsche <fritsche.markus@gmail.com>
|
||||
Date: Fri, 24 Apr 2026 21:31:45 +0200
|
||||
Subject: [PATCH] bes2600: defer scan and soften WARN on firmware reject
|
||||
Subject: [PATCH 13/29] bes2600: defer scan and soften WARN on firmware reject
|
||||
|
||||
On a BES2600-based PineTab2, mac80211's background-scan cadence
|
||||
(about every 30 s when associated) triggers a two-step WARN splat
|
||||
@@ -88,7 +88,7 @@ Signed-off-by: Markus Fritsche <fritsche.markus@gmail.com>
|
||||
3 files changed, 83 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/bes2600/scan.c b/drivers/staging/bes2600/scan.c
|
||||
index b2c22e7..faa1c90 100644
|
||||
index 3bfa535..5f6af3b 100644
|
||||
--- a/drivers/staging/bes2600/scan.c
|
||||
+++ b/drivers/staging/bes2600/scan.c
|
||||
@@ -14,11 +14,50 @@
|
||||
@@ -142,7 +142,7 @@ index b2c22e7..faa1c90 100644
|
||||
#ifdef CONFIG_BES2600_TESTMODE
|
||||
static int bes2600_advance_scan_start(struct bes2600_common *hw_priv)
|
||||
{
|
||||
@@ -702,10 +741,29 @@ void bes2600_scan_work(struct work_struct *work)
|
||||
@@ -703,10 +742,29 @@ void bes2600_scan_work(struct work_struct *work)
|
||||
wsm_unlock_tx(hw_priv);
|
||||
} else
|
||||
#endif
|
||||
@@ -222,5 +222,5 @@ index d40df30..55a4e2b 100644
|
||||
|
||||
underflow:
|
||||
--
|
||||
2.53.0
|
||||
2.54.0
|
||||
|
||||
+168
@@ -0,0 +1,168 @@
|
||||
From 093a5038b8b68f316d976b7cb69609ca7f24f322 Mon Sep 17 00:00:00 2001
|
||||
From: Markus Fritsche <fritsche.markus@gmail.com>
|
||||
Date: Mon, 18 May 2026 11:27:40 +0200
|
||||
Subject: [PATCH 1/2] bes2600: filter 5 GHz scans at the driver boundary
|
||||
(besser#1)
|
||||
|
||||
The BES2600 firmware refuses WSM start-scan for 5 GHz with status 2
|
||||
("rejected by policy"). This shows up in dmesg as the recurring
|
||||
|
||||
wsm_generic_confirm failed for request 0x0007.
|
||||
[SCAN] Scan failed (-22).
|
||||
|
||||
pattern (besser issue #1, ~14-16/h on ohm/PineTab2 baseline).
|
||||
|
||||
Trace shows every reject is the second of a back-to-back pair: mac80211
|
||||
splits multi-band hw_scan requests per band when the driver does not
|
||||
set IEEE80211_HW_SINGLE_SCAN_ON_ALL_BANDS (we don't), then re-invokes
|
||||
drv_hw_scan from __ieee80211_scan_completed for each subsequent band.
|
||||
The 2.4 GHz iteration succeeds; the 5 GHz iteration is what the
|
||||
firmware rejects. See ieee80211_prep_hw_scan in net/mac80211/scan.c
|
||||
for the loop, and the existing memory reference_bes2600_5ghz_scan_reject
|
||||
for the firmware behaviour.
|
||||
|
||||
The 056a71a defer-on-reject patch already in this tree handles the
|
||||
BT-A2DP-coex branch and the consecutive-reject backoff, but it cannot
|
||||
prevent the per-band-loop reject: by the time defer_should_scan is
|
||||
consulted, the per-band call is already in flight, and the reject_count
|
||||
gets reset on every successful 2.4 GHz scan in between (which is
|
||||
~36% of attempts), so the threshold never trips.
|
||||
|
||||
The fix: refuse the 5 GHz iteration upfront in bes2600_hw_scan. The
|
||||
2.4 GHz scan still runs normally. The 5 GHz portion is reported as
|
||||
aborted to userspace -- same outcome as today, minus the dmesg storm
|
||||
and the wsm_generic_confirm WARN cascade.
|
||||
|
||||
5 GHz band registration is intentionally left in place: direct-BSSID
|
||||
association to a known 5 GHz AP still works (no scan is needed for
|
||||
that path), and a future firmware update that fixes the scan behaviour
|
||||
should not be foreclosed by changing band advertisement.
|
||||
|
||||
Contract: per include/net/mac80211.h ieee80211_ops.hw_scan, a negative
|
||||
return aborts the scan without requiring ieee80211_scan_completed().
|
||||
-EOPNOTSUPP is the semantically accurate code (operation is legal,
|
||||
driver can't service it on this band today).
|
||||
|
||||
Phase 3 evidence:
|
||||
- baseline N=3: rate ~14.3-23.6/h converged at 14.3/h (matches OP)
|
||||
- back-to-back scan gap: 6/6 rejected pairs <200us, 1/1 successful
|
||||
pair was 114ms (single-band-only, no 5 GHz leg)
|
||||
- defer log fires: 0/9 in 30-min window (056a71a structurally bypassed)
|
||||
|
||||
Predicted Phase 7 delta: Pattern A 14/h -> 0/h.
|
||||
---
|
||||
bes2600/scan.c | 22 ++++++++++++++++++++++
|
||||
1 file changed, 22 insertions(+)
|
||||
|
||||
diff --git a/drivers/staging/bes2600/scan.c b/drivers/staging/bes2600/scan.c
|
||||
index fb1d298..a81afb6 100644
|
||||
--- a/drivers/staging/bes2600/scan.c
|
||||
+++ b/drivers/staging/bes2600/scan.c
|
||||
@@ -238,6 +238,28 @@ int bes2600_hw_scan(struct ieee80211_hw *hw,
|
||||
/* Scan when P2P_GO corrupt firmware MiniAP mode */
|
||||
if (priv->join_status == BES2600_JOIN_STATUS_AP)
|
||||
return -EOPNOTSUPP;
|
||||
+
|
||||
+ /*
|
||||
+ * Firmware refuses WSM start-scan for 5 GHz with status 2 ("rejected
|
||||
+ * by policy"); see besser issue #1. mac80211 splits multi-band
|
||||
+ * hw_scan requests per-band when the driver does not set
|
||||
+ * IEEE80211_HW_SINGLE_SCAN_ON_ALL_BANDS (we don't -- see
|
||||
+ * ieee80211_hw_set() calls in bes2600_main.c), so each per-band call
|
||||
+ * has req->channels[] from one band only (see ieee80211_prep_hw_scan
|
||||
+ * in net/mac80211/scan.c). Refuse the 5 GHz iteration at the driver
|
||||
+ * boundary so userspace gets a clean aborted-scan for that portion
|
||||
+ * rather than waiting for the firmware reject to cascade up. 5 GHz
|
||||
+ * band registration stays intact so direct-BSSID association to a
|
||||
+ * known 5 GHz AP still works (no scan needed for that path).
|
||||
+ *
|
||||
+ * Contract: per include/net/mac80211.h struct ieee80211_ops.hw_scan
|
||||
+ * documentation, a negative return aborts the scan without requiring
|
||||
+ * ieee80211_scan_completed().
|
||||
+ */
|
||||
+ if (req->n_channels > 0 &&
|
||||
+ req->channels[0]->band == NL80211_BAND_5GHZ)
|
||||
+ return -EOPNOTSUPP;
|
||||
+
|
||||
#if 0
|
||||
if (work_pending(&priv->offchannel_work) ||
|
||||
(hw_priv->roc_if_id != -1)) {
|
||||
--
|
||||
2.54.0
|
||||
|
||||
|
||||
From 8cd10f487c8144d462a510812ba0fa717b3e24df Mon Sep 17 00:00:00 2001
|
||||
From: Markus Fritsche <fritsche.markus@gmail.com>
|
||||
Date: Mon, 18 May 2026 15:56:34 +0200
|
||||
Subject: [PATCH 2/2] bes2600: scan-filter-5ghz: allow targeted single-channel
|
||||
scans (besser#1 follow-up)
|
||||
|
||||
The original Patch I refused EVERY 5 GHz scan request unconditionally
|
||||
(req->n_channels > 0 && band == NL80211_BAND_5GHZ). This eliminated
|
||||
the Pattern A storm but also broke 5 GHz association entirely:
|
||||
NM / wpa_supplicant iterates a freq_list when a connection profile
|
||||
specifies 802-11-wireless.band=a, issuing per-frequency single-channel
|
||||
scans to find the BSS before associating. Those single-channel scans
|
||||
were also refused by our guard, so the BSS was never seen and
|
||||
'Wi-Fi network could not be found' was the only outcome.
|
||||
|
||||
Tighten the guard: refuse only multi-channel 5 GHz scans (n_channels
|
||||
> 1), which is the per-band-sweep pattern mac80211 issues internally
|
||||
and the only one that triggers the firmware storm at the per-band
|
||||
loop boundary. Single-channel 5 GHz scans pass through to firmware,
|
||||
which generally accepts them -- and when they happen to be rejected,
|
||||
the failure is isolated and doesn't cascade.
|
||||
|
||||
Verified on ohm with pkgrel=3 (srcversion BEB625FA7443171EA8D55F7):
|
||||
- Pattern A count since boot: 0 (Phase 7 prediction still holds)
|
||||
- iw dev wlan0 scan freq 5180 -> allowed
|
||||
- iw dev wlan0 scan freq 5180 5200 ... -> refused -EOPNOTSUPP
|
||||
- NM 'nmcli connection up' with band=a -> associated to BSSID
|
||||
c0:25:06:e6:5b:33 on 5240 MHz / ch.48 in ~1 second
|
||||
- TX bitrate 150 Mbit/s MCS 7 40MHz short-GI (vs 72.2 Mbit/s
|
||||
HT20 on 2.4 GHz) -- ~2x throughput recovered
|
||||
|
||||
The change is a single byte (> 0 -> > 1) plus comment update; the
|
||||
test confirmation above is what motivates it.
|
||||
|
||||
Refs: besser#1 (closed but tracked for follow-up like this), original
|
||||
Patch I sha 093a503.
|
||||
---
|
||||
bes2600/scan.c | 16 ++++++++++++----
|
||||
1 file changed, 12 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/bes2600/scan.c b/drivers/staging/bes2600/scan.c
|
||||
index a81afb6..497523b 100644
|
||||
--- a/drivers/staging/bes2600/scan.c
|
||||
+++ b/drivers/staging/bes2600/scan.c
|
||||
@@ -248,15 +248,23 @@ int bes2600_hw_scan(struct ieee80211_hw *hw,
|
||||
* has req->channels[] from one band only (see ieee80211_prep_hw_scan
|
||||
* in net/mac80211/scan.c). Refuse the 5 GHz iteration at the driver
|
||||
* boundary so userspace gets a clean aborted-scan for that portion
|
||||
- * rather than waiting for the firmware reject to cascade up. 5 GHz
|
||||
- * band registration stays intact so direct-BSSID association to a
|
||||
- * known 5 GHz AP still works (no scan needed for that path).
|
||||
+ * rather than waiting for the firmware reject to cascade up.
|
||||
+ *
|
||||
+ * Only the multi-channel case is refused (n_channels > 1): that's
|
||||
+ * the per-band-sweep pattern mac80211 issues internally and the
|
||||
+ * one that triggers the firmware storm at the per-band loop
|
||||
+ * boundary. Single-channel 5 GHz scans (BSS verification, NM's
|
||||
+ * per-freq iteration when 802-11-wireless.band=a is set) pass
|
||||
+ * through to firmware, which generally accepts them since the
|
||||
+ * storm is the back-to-back per-band issue, not a blanket 5 GHz
|
||||
+ * reject. This preserves 5 GHz association via the
|
||||
+ * "wpa_supplicant iterates freq_list per channel" path.
|
||||
*
|
||||
* Contract: per include/net/mac80211.h struct ieee80211_ops.hw_scan
|
||||
* documentation, a negative return aborts the scan without requiring
|
||||
* ieee80211_scan_completed().
|
||||
*/
|
||||
- if (req->n_channels > 0 &&
|
||||
+ if (req->n_channels > 1 &&
|
||||
req->channels[0]->band == NL80211_BAND_5GHZ)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
--
|
||||
2.54.0
|
||||
|
||||
+540
@@ -0,0 +1,540 @@
|
||||
From 0f185172b020818faec9572fd800867db623a40e Mon Sep 17 00:00:00 2001
|
||||
From: Markus Fritsche <fritsche.markus@gmail.com>
|
||||
Date: Thu, 7 May 2026 22:34:11 +0200
|
||||
Subject: [PATCH 25/29] =?UTF-8?q?bes2600:=20drop=20sdio=5Frx=5Fwork=20rela?=
|
||||
=?UTF-8?q?y,=20IRQ=E2=86=92bh-direct=20(no-relay=20architecture)?=
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Patch C v3 — match cw1200 mainline architecture
|
||||
(drivers/net/wireless/st/cw1200/). Eliminates the
|
||||
sdio_rx_work workqueue relay that introduced a thread-safety
|
||||
race on hw_priv->hw_bufs_used in v1 (PR #3 closed) and that
|
||||
v2's atomic_t prep was a workaround for (PR #10 superseded by
|
||||
v3 plan PR #11).
|
||||
|
||||
Architectural changes:
|
||||
|
||||
- bes2600_gpio_irq_handler: now calls self->irq_handler()
|
||||
directly instead of queue_work(self->sdio_wq, &self->rx_work).
|
||||
Bumps bh_rx atomic + wakes bh_wq.
|
||||
- bes2600_bh_rx_helper (BES_SDIO_RX_MULTIPLE_ENABLE branch):
|
||||
now calls priv->sbus_ops->bus_rx_batch() to do the SDIO read
|
||||
inline. No pipe_read, no skb_dequeue.
|
||||
- bes2600_sdio_read_rx_batch (new): the SDIO read sequence
|
||||
extracted from sdio_rx_work, registered as
|
||||
sbus_ops->bus_rx_batch. Runs in bh thread context.
|
||||
- bes2600_sdio_extract_packets: calls
|
||||
bes2600_bh_handle_rx_skb() directly per parsed SKB. No
|
||||
skb_queue_tail, no rx_queue.
|
||||
- bes2600_bh_handle_rx_skb (new in bh.c): the per-SKB
|
||||
bookkeeping that bh_rx_helper used to do post-pipe_read
|
||||
(seq# check, exception, confirm-condition, wsm_handle_rx).
|
||||
Wakes bh thread for tx-burst via atomic_inc(&priv->bh_tx)
|
||||
instead of bes2600_bh_wakeup() — we ARE the bh thread.
|
||||
- Post-tx queue_work(rx_work) site: replaced with
|
||||
self->irq_handler() to wake bh for piggyback RX check.
|
||||
|
||||
Deleted infrastructure:
|
||||
|
||||
- struct sbus_priv: rx_queue, rx_queue_lock, rx_work fields
|
||||
- bes2600_sdio_pipe_read: function deleted (unused)
|
||||
- sdio_rx_work: function deleted (unused)
|
||||
- sbus_ops->pipe_read assignment: removed for SDIO bus
|
||||
- skb_queue_head_init(&self->rx_queue), spin_lock_init(...),
|
||||
INIT_WORK(rx_work): probe-time setup removed
|
||||
- cancel_work_sync(rx_work) + drain loop in empty_work: removed
|
||||
- flush_work(rx_work) in drain helper: replaced with msleep(2)
|
||||
- work_pending(rx_work) check in suspend predicate: removed
|
||||
|
||||
Concurrency invariant restored:
|
||||
|
||||
- hw_priv->hw_bufs_used: single-writer (bh thread only)
|
||||
by construction. No atomic_t needed.
|
||||
- hw_priv->hw_bufs_used_vif[]: ditto.
|
||||
- hw_priv->wsm_tx_pending[]: ditto.
|
||||
- All other shared state: unchanged or already protected.
|
||||
|
||||
Phase 7 partial verification (rep 1, 2026-05-07):
|
||||
|
||||
- Module loads clean, srcversion 371C6606B73AF19299228CA
|
||||
- Link associates, no WARN/BUG/oops
|
||||
- sdio_rx_work dispatches: 0 (function deleted)
|
||||
- bes2600_bh_work redispatches: 0 (single long-lived
|
||||
invariant preserved)
|
||||
- Chip handled stress traffic without wedge
|
||||
|
||||
Phase 7 full N=3 stress ramp deferred to follow-up rep series
|
||||
(rep 2 had a TCP-level nc race; not a bes2600 issue but
|
||||
invalidated rep 2's throughput number).
|
||||
---
|
||||
bes2600/bes2600_sdio.c | 144 ++++++++++++++++++++++++-----------------
|
||||
bes2600/bh.c | 129 ++++++++++++++++++++++++++++++++++--
|
||||
bes2600/bh.h | 9 +++
|
||||
bes2600/sbus.h | 8 +++
|
||||
4 files changed, 226 insertions(+), 64 deletions(-)
|
||||
|
||||
diff --git a/drivers/staging/bes2600/bes2600_sdio.c b/drivers/staging/bes2600/bes2600_sdio.c
|
||||
index c81c244..3834032 100644
|
||||
--- a/drivers/staging/bes2600/bes2600_sdio.c
|
||||
+++ b/drivers/staging/bes2600/bes2600_sdio.c
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <linux/of_gpio.h>
|
||||
|
||||
#include "bes2600.h"
|
||||
+#include "bh.h"
|
||||
#include "sbus.h"
|
||||
#include "bes2600_plat.h"
|
||||
#include "bes2600_factory.h"
|
||||
@@ -72,10 +73,12 @@ struct sbus_priv {
|
||||
int rx_data_toggle;
|
||||
#endif
|
||||
#ifdef BES_SDIO_RX_MULTIPLE_ENABLE
|
||||
- spinlock_t rx_queue_lock;
|
||||
- struct sk_buff_head rx_queue;
|
||||
+ /*
|
||||
+ * Patch C v3: rx_queue, rx_queue_lock, rx_work removed (no relay).
|
||||
+ * The bh thread now reads RX inline; the rx_buffer scratch area
|
||||
+ * stays. Counters/timestamps stay for debugfs visibility.
|
||||
+ */
|
||||
u8 *rx_buffer;
|
||||
- struct work_struct rx_work;
|
||||
u32 rx_last_ctrl;
|
||||
u32 rx_valid_ctrl;
|
||||
u32 rx_total_ctrl_cnt;
|
||||
@@ -412,10 +415,19 @@ static void bes2600_sdio_irq_handler(struct sdio_func *func)
|
||||
|
||||
bes_devel("%s called, fw_started:%d \n",
|
||||
__func__, self->fw_started);
|
||||
- if (likely(self->fw_started && self->core)) {
|
||||
- queue_work(self->sdio_wq, &self->rx_work);
|
||||
+ /*
|
||||
+ * Patch C v3: no more sdio_rx_work relay. Wake the bh thread
|
||||
+ * directly via self->irq_handler (bes2600_irq_handler in bh.c
|
||||
+ * which bumps bh_rx atomic + wakes bh_wq). The bh thread will
|
||||
+ * then call sbus_ops->bus_rx_batch() to do the SDIO read inline.
|
||||
+ * Matches cw1200 mainline IRQ → bh-direct architecture.
|
||||
+ */
|
||||
+ if (likely(self->fw_started && self->core && self->irq_handler)) {
|
||||
+ spin_lock_irqsave(&self->lock, flags);
|
||||
+ self->irq_handler(self->irq_priv);
|
||||
+ spin_unlock_irqrestore(&self->lock, flags);
|
||||
self->last_irq_timestamp = jiffies;
|
||||
- } else if(self->irq_handler) {
|
||||
+ } else if (self->irq_handler) {
|
||||
spin_lock_irqsave(&self->lock, flags);
|
||||
self->irq_handler(self->irq_priv);
|
||||
spin_unlock_irqrestore(&self->lock, flags);
|
||||
@@ -812,10 +824,15 @@ static int bes2600_sdio_extract_packets(struct sbus_priv *self, u32 ctrl_reg, u8
|
||||
skb_put(skb, packet_len);
|
||||
memcpy(skb->data, &data[pos], packet_len);
|
||||
bes_devel("%s, %d,%d\n", __func__, packet_len, pos);
|
||||
- spin_lock(&self->rx_queue_lock);
|
||||
- skb_queue_tail(&self->rx_queue, skb);
|
||||
self->rx_data_cnt++;
|
||||
- spin_unlock(&self->rx_queue_lock);
|
||||
+ /*
|
||||
+ * Patch C v3: deliver the SKB directly into the WSM/mac80211
|
||||
+ * stack from the bh thread. No rx_queue, no inter-thread
|
||||
+ * handoff, no atomic_t needed on the counters that
|
||||
+ * wsm_release_tx_buffer touches — single-writer-from-bh is
|
||||
+ * preserved by construction. See bh.c for the contract block.
|
||||
+ */
|
||||
+ bes2600_bh_handle_rx_skb(self->core, skb);
|
||||
packet_len = (packet_len + 3) & (~0x3);
|
||||
pos += packet_len;
|
||||
#ifdef BES_SDIO_OPTIMIZED_LEN
|
||||
@@ -826,17 +843,31 @@ static int bes2600_sdio_extract_packets(struct sbus_priv *self, u32 ctrl_reg, u8
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static void sdio_rx_work(struct work_struct *work)
|
||||
+/*
|
||||
+ * Patch C v3: bh thread calls this directly via sbus_ops->bus_rx_batch.
|
||||
+ * No more sdio_rx_work workqueue. SDIO read sequence (lock →
|
||||
+ * read_ctrl → memcpy_fromio → packets_check → extract_packets) runs
|
||||
+ * inline in bh-thread context. Each parsed SKB is delivered via
|
||||
+ * bes2600_bh_handle_rx_skb() from extract_packets — no rx_queue, no
|
||||
+ * second worker, no inter-thread handoff.
|
||||
+ *
|
||||
+ * Architecture matches cw1200 mainline. Single-writer-from-bh
|
||||
+ * invariant on hw_bufs_used preserved by construction.
|
||||
+ *
|
||||
+ * Returns 0 on success (caller's bh outer loop decides whether to
|
||||
+ * continue), negative on bus read error. On error: triggers
|
||||
+ * wifi_force_close (same as the old sdio_rx_work).
|
||||
+ */
|
||||
+static int bes2600_sdio_read_rx_batch(struct sbus_priv *self)
|
||||
{
|
||||
- int ret, again = 0, retry = 0, crc_retry = 0;
|
||||
+ int ret = 0, again = 0, retry = 0, crc_retry = 0;
|
||||
u32 ctrl_reg = 0;
|
||||
int total_len;
|
||||
- struct sbus_priv *self = container_of(work, struct sbus_priv, rx_work);
|
||||
u8 *buf = self->rx_buffer;
|
||||
|
||||
/* don't read/write sdio when sdio error */
|
||||
if (bes2600_chrdev_is_bus_error())
|
||||
- return;
|
||||
+ return 0;
|
||||
|
||||
bes2600_gpio_wakeup_mcu(self, GPIO_WAKE_FLAG_SDIO_RX);
|
||||
|
||||
@@ -891,6 +922,10 @@ static void sdio_rx_work(struct work_struct *work)
|
||||
goto failed;
|
||||
}
|
||||
|
||||
+ /*
|
||||
+ * extract_packets parses the multi-RX buffer and calls
|
||||
+ * bes2600_bh_handle_rx_skb() per SKB. No queueing.
|
||||
+ */
|
||||
if ((ret = bes2600_sdio_extract_packets(self, ctrl_reg, buf))) {
|
||||
bes_err("%s,%d error=%d\n", __func__, __LINE__, ret);
|
||||
goto failed;
|
||||
@@ -898,22 +933,16 @@ static void sdio_rx_work(struct work_struct *work)
|
||||
|
||||
ctrl_reg = 0;
|
||||
|
||||
- if (likely(self->irq_handler)) {
|
||||
- self->irq_handler(self->irq_priv);
|
||||
- } else {
|
||||
- bes_err("%s,%d\n", __func__, __LINE__);
|
||||
- goto failed;
|
||||
- }
|
||||
-
|
||||
} while (again);
|
||||
|
||||
bes2600_gpio_allow_mcu_sleep(self, GPIO_WAKE_FLAG_SDIO_RX);
|
||||
- return;
|
||||
+ return 0;
|
||||
|
||||
failed:
|
||||
bes2600_gpio_allow_mcu_sleep(self, GPIO_WAKE_FLAG_SDIO_RX);
|
||||
bes2600_chrdev_wifi_force_close(self->core, false);
|
||||
WARN_ON(1);
|
||||
+ return -1;
|
||||
}
|
||||
|
||||
static void sdio_scan_work(struct work_struct *work)
|
||||
@@ -921,26 +950,11 @@ static void sdio_scan_work(struct work_struct *work)
|
||||
bes_warn("%s: this function does nothing\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
-static void *bes2600_sdio_pipe_read(struct sbus_priv *self)
|
||||
-{
|
||||
- struct sk_buff *skb;
|
||||
-
|
||||
- if (bes2600_chrdev_is_bus_error()) {
|
||||
- return bes2600_tx_loop_read(self->core);
|
||||
- }
|
||||
-
|
||||
- spin_lock(&self->rx_queue_lock);
|
||||
- skb = skb_dequeue(&self->rx_queue);
|
||||
- if (skb)
|
||||
- self->rx_proc_cnt++;
|
||||
- spin_unlock(&self->rx_queue_lock);
|
||||
- if (likely(self->fw_started == true &&
|
||||
- !bes2600_pwr_device_is_idle(self->core) &&
|
||||
- self->core->hw_bufs_used > 0))
|
||||
- if (!skb)
|
||||
- queue_work(self->sdio_wq, &self->rx_work);
|
||||
- return skb;
|
||||
-}
|
||||
+/* Patch C v3: bes2600_sdio_pipe_read deleted. bh thread reads the
|
||||
+ * SDIO bus inline via bes2600_sdio_read_rx_batch (sbus_ops->bus_rx_batch).
|
||||
+ * No rx_queue, no skb_dequeue, no relay. bes2600_tx_loop_read remains
|
||||
+ * for the test bus error-fallback path but is now invoked at higher
|
||||
+ * level. */
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1196,7 +1210,14 @@ flush_previous:
|
||||
}
|
||||
} while (crc_retry <= 10);
|
||||
sdio_release_host(self->func);
|
||||
- queue_work(self->sdio_wq, &self->rx_work);
|
||||
+ /*
|
||||
+ * Patch C v3: wake the bh thread to check for any RX
|
||||
+ * that piggybacked on this TX window. Bumps bh_rx
|
||||
+ * atomic; bh's wait_event will pick it up and call
|
||||
+ * sbus_ops->bus_rx_batch().
|
||||
+ */
|
||||
+ if (likely(self->irq_handler))
|
||||
+ self->irq_handler(self->irq_priv);
|
||||
if (ret) {
|
||||
bes_err("%s,%d err=%d,%d,%d\n", __func__, __LINE__, ret, scatters, cur_blk);
|
||||
sdio_work_debug(self);
|
||||
@@ -1247,12 +1268,11 @@ static int bes2600_sdio_misc_init(struct sbus_priv *self, struct bes2600_common
|
||||
self->next_toggle = 0;
|
||||
#endif
|
||||
#ifdef BES_SDIO_RX_MULTIPLE_ENABLE
|
||||
- spin_lock_init(&self->rx_queue_lock);
|
||||
- skb_queue_head_init(&self->rx_queue);
|
||||
+ /* Patch C v3: rx_queue / rx_queue_lock removed (no relay). */
|
||||
self->rx_buffer = (u8 *)__get_dma_pages(GFP_KERNEL, get_order(1632 * BES_SDIO_RX_MULTIPLE_NUM));
|
||||
if (!self->rx_buffer)
|
||||
return -ENOMEM;
|
||||
- INIT_WORK(&self->rx_work, sdio_rx_work);
|
||||
+ /* Patch C v3: sdio_rx_work removed; bh thread does the read. */
|
||||
#endif
|
||||
#ifdef BES_SDIO_TX_MULTIPLE_ENABLE
|
||||
INIT_LIST_HEAD(&self->tx_bufferlist);
|
||||
@@ -1581,22 +1601,15 @@ err:
|
||||
|
||||
static void bes2600_sdio_empty_work(struct sbus_priv *self)
|
||||
{
|
||||
-#ifdef BES_SDIO_RX_MULTIPLE_ENABLE
|
||||
- struct sk_buff *skb;
|
||||
-#endif
|
||||
#ifdef BES_SDIO_TX_MULTIPLE_ENABLE
|
||||
struct bes_sdio_tx_list_t *tx_buffer, *temp;
|
||||
#endif
|
||||
|
||||
#ifdef BES_SDIO_RX_MULTIPLE_ENABLE
|
||||
- cancel_work_sync(&self->rx_work);
|
||||
- while (1) {
|
||||
- skb = skb_dequeue(&self->rx_queue);
|
||||
- if (skb)
|
||||
- dev_kfree_skb(skb);
|
||||
- else
|
||||
- break;
|
||||
- }
|
||||
+ /*
|
||||
+ * Patch C v3: rx_work and rx_queue removed. Counters still
|
||||
+ * reset for the next attach cycle.
|
||||
+ */
|
||||
self->rx_last_ctrl = 0;
|
||||
self->rx_total_ctrl_cnt = 0;
|
||||
self->rx_continuous_ctrl_cnt = 0;
|
||||
@@ -1864,7 +1877,8 @@ static struct sbus_ops bes2600_sdio_sbus_ops = {
|
||||
.sbus_reg_write = bes2600_sdio_reg_write,
|
||||
.init = bes2600_sdio_misc_init,
|
||||
#ifdef BES_SDIO_RX_MULTIPLE_ENABLE
|
||||
- .pipe_read = bes2600_sdio_pipe_read,
|
||||
+ /* Patch C v3: .pipe_read removed; bus_rx_batch replaces it. */
|
||||
+ .bus_rx_batch = bes2600_sdio_read_rx_batch,
|
||||
#endif
|
||||
#ifdef BES_SDIO_TX_MULTIPLE_ENABLE
|
||||
.pipe_send = bes2600_sdio_pipe_send,
|
||||
@@ -1884,9 +1898,15 @@ static void bes2600_sdio_en_lp_cb(struct bes2600_common *hw_priv)
|
||||
long unsigned int old_ts, new_ts;
|
||||
struct sbus_priv *self = hw_priv->sbus_priv;
|
||||
|
||||
+ /*
|
||||
+ * Patch C v3: rx_work removed. Wait for IRQ-timestamp activity
|
||||
+ * to settle by polling self->last_irq_timestamp via msleep
|
||||
+ * (best-effort). The caller already knows the bh thread will
|
||||
+ * process pending bh_rx during its next wait_event round.
|
||||
+ */
|
||||
do {
|
||||
old_ts = self->last_irq_timestamp;
|
||||
- flush_work(&self->rx_work);
|
||||
+ msleep(2);
|
||||
new_ts = self->last_irq_timestamp;
|
||||
} while(old_ts != new_ts);
|
||||
}
|
||||
@@ -2243,8 +2263,12 @@ static int bes2600_sdio_suspend_noirq(struct device *dev)
|
||||
if (func->num > 1)
|
||||
return 0;
|
||||
|
||||
- if(self->core &&
|
||||
- (work_pending(&self->rx_work) || atomic_read(&self->core->bh_rx))) {
|
||||
+ /*
|
||||
+ * Patch C v3: work_pending(&self->rx_work) check dropped (no
|
||||
+ * relay). bh_rx atomic alone tells us whether the bh thread
|
||||
+ * has un-processed RX events queued.
|
||||
+ */
|
||||
+ if (self->core && atomic_read(&self->core->bh_rx)) {
|
||||
bes_devel("%s: Suspend interrupted.\n", __func__);
|
||||
return -EAGAIN;
|
||||
}
|
||||
diff --git a/drivers/staging/bes2600/bh.c b/drivers/staging/bes2600/bh.c
|
||||
index fab3bf0..febcaf4 100644
|
||||
--- a/drivers/staging/bes2600/bh.c
|
||||
+++ b/drivers/staging/bes2600/bh.c
|
||||
@@ -959,6 +959,119 @@ static void bes2600_bh_parse_wakeup_event(struct bes2600_common *hw_priv, struct
|
||||
}
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * Direct-deliver an RX SKB into the WSM/mac80211 stack.
|
||||
+ *
|
||||
+ * Patch C v3 (no-relay architecture, matches cw1200): the bh thread
|
||||
+ * calls bes2600_sdio_read_rx_batch which calls
|
||||
+ * bes2600_sdio_extract_packets which calls THIS function per parsed
|
||||
+ * SKB. No rx_queue, no sdio_rx_work, no inter-thread handoff.
|
||||
+ *
|
||||
+ * Single-writer-from-bh invariant on hw_priv->hw_bufs_used,
|
||||
+ * hw_priv->hw_bufs_used_vif[] and hw_priv->wsm_tx_pending[] is
|
||||
+ * preserved BY CONSTRUCTION — there is now only one writer (the bh
|
||||
+ * thread itself), same as cw1200's design. No atomic_t conversion
|
||||
+ * needed.
|
||||
+ *
|
||||
+ * Contract:
|
||||
+ * - process context, sleepable. wsm_handle_rx (wsm.c, EXPORT_SYMBOL)
|
||||
+ * acquires wsm_cmd.lock and may sleep on wait_event_timeout.
|
||||
+ * - caller holds no bes2600 spinlock. bes2600_sdio_unlock(self) is
|
||||
+ * called inside read_rx_batch before extract_packets is invoked.
|
||||
+ * - SKB ownership: function frees on every path (success + error).
|
||||
+ * - No need to wake the bh thread on TX-confirm — we ARE the bh
|
||||
+ * thread; tx_burst is signalled by returning *tx_out = 1 to the
|
||||
+ * caller (bh_rx_helper), which propagates it to bh's outer loop.
|
||||
+ */
|
||||
+int bes2600_bh_handle_rx_skb(struct bes2600_common *priv, struct sk_buff *skb)
|
||||
+{
|
||||
+ struct wsm_hdr *wsm;
|
||||
+ size_t wsm_len;
|
||||
+ u16 wsm_id;
|
||||
+ u8 wsm_seq;
|
||||
+ int tx = 0;
|
||||
+ u32 confirm_label = 0x0;
|
||||
+
|
||||
+ if (!skb)
|
||||
+ return 0;
|
||||
+
|
||||
+ wsm = (struct wsm_hdr *)skb->data;
|
||||
+ wsm_len = __le16_to_cpu(wsm->len);
|
||||
+ if (WARN_ON(wsm_len > skb->len)) {
|
||||
+ bes_err("wsm_len err %d %d\n", (int)wsm_len, (int)skb->len);
|
||||
+ dev_kfree_skb(skb);
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ if (priv->wsm_enable_wsm_dumps)
|
||||
+ print_hex_dump(KERN_DEBUG, "<-- ", DUMP_PREFIX_NONE, 16, 1,
|
||||
+ skb->data, wsm_len, false);
|
||||
+
|
||||
+ wsm_id = __le16_to_cpu(wsm->id) & 0xFFF;
|
||||
+ wsm_seq = (__le16_to_cpu(wsm->id) >> 13) & 7;
|
||||
+ bes_devel("bes2600_bh_handle_rx_skb wsm_id:0x%04x seq:%d\n",
|
||||
+ wsm_id, wsm_seq);
|
||||
+
|
||||
+ skb_trim(skb, wsm_len);
|
||||
+
|
||||
+ if (wsm_id == 0x0800) {
|
||||
+ wsm_handle_exception(priv,
|
||||
+ &skb->data[sizeof(*wsm)],
|
||||
+ wsm_len - sizeof(*wsm));
|
||||
+ bes_err("wsm exception\n");
|
||||
+ dev_kfree_skb(skb);
|
||||
+ return -1;
|
||||
+ } else if ((wsm_seq != priv->wsm_rx_seq[WSM_TXRX_SEQ_IDX(wsm_id)])) {
|
||||
+ bes_err("seq error! %u. %u. 0x%x.", wsm_seq,
|
||||
+ priv->wsm_rx_seq[WSM_TXRX_SEQ_IDX(wsm_id)], wsm_id);
|
||||
+ dev_kfree_skb(skb);
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ bes2600_bh_parse_wakeup_event(priv, skb);
|
||||
+
|
||||
+ priv->wsm_rx_seq[WSM_TXRX_SEQ_IDX(wsm_id)] = (wsm_seq + 1) & 7;
|
||||
+
|
||||
+ if (IS_DRIVER_TO_MCU_CMD(wsm_id))
|
||||
+ confirm_label = __le32_to_cpu(((struct wsm_mcu_hdr *)wsm)->handle_label);
|
||||
+
|
||||
+ if (WSM_CONFIRM_CONDITION(wsm_id, confirm_label)) {
|
||||
+ int rc = wsm_release_tx_buffer(priv, 1);
|
||||
+ bes2600_bh_dec_pending_count(priv, WSM_TXRX_SEQ_IDX(wsm->id));
|
||||
+
|
||||
+ if (rc < 0) {
|
||||
+ bes_err("wsm_release_tx_buffer failed: %d\n", rc);
|
||||
+ dev_kfree_skb(skb);
|
||||
+ return rc;
|
||||
+ } else if (rc > 0) {
|
||||
+ tx = 1;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* wsm_handle_rx takes care of SKB lifetime: zeroes *skb_p if consumed. */
|
||||
+ if (wsm_handle_rx(priv, wsm_id, wsm, &skb)) {
|
||||
+ bes_err("wsm_handle_rx failed (id=0x%04x)\n", wsm_id);
|
||||
+ if (skb)
|
||||
+ dev_kfree_skb(skb);
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ if (skb)
|
||||
+ dev_kfree_skb(skb);
|
||||
+
|
||||
+ /*
|
||||
+ * Signal "tx side has new headroom" via atomic so the bh outer
|
||||
+ * loop's wait_event predicate notices on its next wait. No
|
||||
+ * cross-thread wake needed because we are the bh thread; the
|
||||
+ * outer loop will pick this up after read_rx_batch returns.
|
||||
+ */
|
||||
+ if (tx)
|
||||
+ atomic_inc(&priv->bh_tx);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+EXPORT_SYMBOL(bes2600_bh_handle_rx_skb);
|
||||
+
|
||||
static int bes2600_bh_rx_helper(struct bes2600_common *priv, int *tx)
|
||||
{
|
||||
struct sk_buff *skb = NULL;
|
||||
@@ -970,10 +1083,18 @@ static int bes2600_bh_rx_helper(struct bes2600_common *priv, int *tx)
|
||||
u32 confirm_label = 0x0; /* wsm to mcu cmd cnfirm label */
|
||||
|
||||
#if defined(BES_SDIO_RX_MULTIPLE_ENABLE)
|
||||
- skb = (struct sk_buff *)priv->sbus_ops->pipe_read(priv->sbus_priv);
|
||||
- if (!skb)
|
||||
- return 0;
|
||||
- rx = 1; // always consider rx pipe not empty
|
||||
+ /*
|
||||
+ * Patch C v3: the bh thread does the SDIO read inline via
|
||||
+ * sbus_ops->bus_rx_batch. bes2600_sdio_read_rx_batch reads the
|
||||
+ * multi-RX coalesced frames out of the chip and delivers each
|
||||
+ * one inline via bes2600_bh_handle_rx_skb (no rx_queue, no
|
||||
+ * pipe_read, no inter-thread handoff). Return value: 0 on
|
||||
+ * success (bh outer loop will check whether to continue),
|
||||
+ * negative on read error.
|
||||
+ */
|
||||
+ if (priv->sbus_ops->bus_rx_batch)
|
||||
+ return priv->sbus_ops->bus_rx_batch(priv->sbus_priv);
|
||||
+ return 0;
|
||||
#else
|
||||
u32 ctrl_reg = 0;
|
||||
size_t read_len = 0;
|
||||
diff --git a/drivers/staging/bes2600/bh.h b/drivers/staging/bes2600/bh.h
|
||||
index 7be82dc..9ed08b1 100644
|
||||
--- a/drivers/staging/bes2600/bh.h
|
||||
+++ b/drivers/staging/bes2600/bh.h
|
||||
@@ -39,6 +39,15 @@ int wsm_release_vif_tx_buffer(struct bes2600_common *hw_priv, int if_id,
|
||||
int bes2600_bh_sw_process(struct bes2600_common *hw_priv,
|
||||
struct wsm_tx_confirm *tx_confirm);
|
||||
|
||||
+/*
|
||||
+ * Direct-deliver an RX SKB into the WSM/mac80211 stack from the bh thread.
|
||||
+ * Called by bes2600_sdio_extract_packets per RX frame, no queueing.
|
||||
+ * Process context, sleepable, caller holds no bes2600 spinlock.
|
||||
+ * Function frees skb on every path. See bh.c for full contract.
|
||||
+ */
|
||||
+int bes2600_bh_handle_rx_skb(struct bes2600_common *hw_priv,
|
||||
+ struct sk_buff *skb);
|
||||
+
|
||||
void bes2600_bh_inc_pending_count(struct bes2600_common *hw_priv, int idx);
|
||||
void bes2600_bh_dec_pending_count(struct bes2600_common *hw_priv, int idx);
|
||||
|
||||
diff --git a/drivers/staging/bes2600/sbus.h b/drivers/staging/bes2600/sbus.h
|
||||
index cb90890..96b1d4c 100644
|
||||
--- a/drivers/staging/bes2600/sbus.h
|
||||
+++ b/drivers/staging/bes2600/sbus.h
|
||||
@@ -83,6 +83,14 @@ struct sbus_ops {
|
||||
* Returns 0 on success or a negative errno.
|
||||
*/
|
||||
int (*bus_reset)(struct sbus_priv *self);
|
||||
+ /*
|
||||
+ * Read a batch of RX frames inline from the bus and deliver each
|
||||
+ * one via bes2600_bh_handle_rx_skb(). Called from the bh thread
|
||||
+ * (process context, sleepable). Replaces the
|
||||
+ * sdio_rx_work + rx_queue + pipe_read relay (Patch C v3, 2026).
|
||||
+ * Returns 0 on success, negative on read error.
|
||||
+ */
|
||||
+ int (*bus_rx_batch)(struct sbus_priv *self);
|
||||
};
|
||||
|
||||
void bes2600_irq_handler(struct bes2600_common *priv);
|
||||
--
|
||||
2.54.0
|
||||
|
||||
+10
-10
@@ -1,7 +1,7 @@
|
||||
From 4ec7d25817af09654fb9439e472890f69281840c Mon Sep 17 00:00:00 2001
|
||||
From 2f9b4c719faf9563895c064439a7da25f35c8fc7 Mon Sep 17 00:00:00 2001
|
||||
From: Markus Fritsche <fritsche.markus@gmail.com>
|
||||
Date: Thu, 23 Apr 2026 11:58:31 +0200
|
||||
Subject: [PATCH] bes2600: bounce SDIO TX buffers to avoid DMA OOB read
|
||||
Subject: [PATCH 07/29] bes2600: bounce SDIO TX buffers to avoid DMA OOB read
|
||||
|
||||
The SDIO TX path rounds the DMA transfer length up to the host's
|
||||
current block size and hands that length to dma_map_sg() via
|
||||
@@ -44,14 +44,14 @@ claiming the bus.
|
||||
|
||||
Signed-off-by: Markus Fritsche <fritsche.markus@gmail.com>
|
||||
---
|
||||
drivers/staging/bes2600/bes2600_sdio.c | 39 ++++++++++++++++++++++++++++++++++++++-
|
||||
bes2600/bes2600_sdio.c | 39 ++++++++++++++++++++++++++++++++++++++-
|
||||
1 file changed, 38 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/staging/bes2600/bes2600_sdio.c b/bes2600/bes2600_sdio.c
|
||||
index b595365..7bc922c 100644
|
||||
diff --git a/drivers/staging/bes2600/bes2600_sdio.c b/drivers/staging/bes2600/bes2600_sdio.c
|
||||
index f172d53..b9d836f 100644
|
||||
--- a/drivers/staging/bes2600/bes2600_sdio.c
|
||||
+++ b/drivers/staging/bes2600/bes2600_sdio.c
|
||||
@@ -94,6 +94,7 @@ struct sbus_priv {
|
||||
@@ -95,6 +95,7 @@ struct sbus_priv {
|
||||
struct work_struct tx_work;
|
||||
struct scatterlist tx_sg[BES_SDIO_TX_MULTIPLE_NUM + 1];
|
||||
struct scatterlist tx_sg_nosignal[BES_SDIO_TX_MULTIPLE_NUM_NOSIGNAL + 1];
|
||||
@@ -59,7 +59,7 @@ index b595365..7bc922c 100644
|
||||
u32 tx_data_cnt;
|
||||
u32 tx_xfer_cnt;
|
||||
u32 tx_proc_cnt;
|
||||
@@ -1135,7 +1136,26 @@ static void sdio_tx_work(struct work_struct *work)
|
||||
@@ -1136,7 +1137,26 @@ static void sdio_tx_work(struct work_struct *work)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ index b595365..7bc922c 100644
|
||||
total_len += align;
|
||||
++scatters;
|
||||
/*del_node:*/
|
||||
@@ -1853,6 +1873,17 @@ static int bes2600_sdio_probe(struct sdio_func *func,
|
||||
@@ -1857,6 +1877,17 @@ static int bes2600_sdio_probe(struct sdio_func *func,
|
||||
if (!self->single_gathered_buffer)
|
||||
return -ENOMEM;
|
||||
#endif
|
||||
@@ -105,7 +105,7 @@ index b595365..7bc922c 100644
|
||||
#ifdef BES_SDIO_RXTX_TOGGLE
|
||||
self->fw_started = false;
|
||||
#endif
|
||||
@@ -1981,6 +2012,12 @@ static void bes2600_sdio_remove(struct sdio_func *func)
|
||||
@@ -1984,6 +2015,12 @@ static void bes2600_sdio_remove(struct sdio_func *func)
|
||||
if (self->single_gathered_buffer) {
|
||||
free_pages((unsigned long)self->single_gathered_buffer, get_order(MAX_SDIO_TRANSFER_LEN));
|
||||
}
|
||||
@@ -119,5 +119,5 @@ index b595365..7bc922c 100644
|
||||
kfree(self);
|
||||
}
|
||||
--
|
||||
2.53.0
|
||||
2.54.0
|
||||
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
From 9ddcae54a171f2fc7742e92e03b1478d87ae4bbb Mon Sep 17 00:00:00 2001
|
||||
From: Venkata Atchuta Bheemeswara Sarma Darbha <vdarbha0473@gmail.com>
|
||||
Date: Sat, 17 Jan 2026 14:27:22 -0600
|
||||
Subject: [PATCH 1/3] media: rkvdec: vp9: Changing get_ref_buf function name to
|
||||
get_ref_buf_vp9
|
||||
|
||||
This change is in preparation for the upcoming commits and to denote that this function is not to be confused with the similar function found in rkvdec's hevc.
|
||||
|
||||
Change-Id: I934684778c375c6960a19989a702be44655c55d6
|
||||
Signed-off-by: Venkata Atchuta Bheemeswara Sarma Darbha <vdarbha0473@gmail.com>
|
||||
(cherry picked from commit f60174f07d9c56e7499ca3111d0999e26444cdfd)
|
||||
---
|
||||
drivers/media/platform/rockchip/rkvdec/rkvdec-vp9.c | 10 +++++-----
|
||||
1 file changed, 5 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-vp9.c b/drivers/media/platform/rockchip/rkvdec/rkvdec-vp9.c
|
||||
index e4cdd2122873..bab2e9c83d06 100644
|
||||
--- a/drivers/media/platform/rockchip/rkvdec/rkvdec-vp9.c
|
||||
+++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-vp9.c
|
||||
@@ -349,7 +349,7 @@ static void init_probs(struct rkvdec_ctx *ctx,
|
||||
}
|
||||
|
||||
static struct rkvdec_decoded_buffer *
|
||||
-get_ref_buf(struct rkvdec_ctx *ctx, struct vb2_v4l2_buffer *dst, u64 timestamp)
|
||||
+get_ref_buf_vp9(struct rkvdec_ctx *ctx, struct vb2_v4l2_buffer *dst, u64 timestamp)
|
||||
{
|
||||
struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx;
|
||||
struct vb2_queue *cap_q = &m2m_ctx->cap_q_ctx.q;
|
||||
@@ -489,12 +489,12 @@ static void config_registers(struct rkvdec_ctx *ctx,
|
||||
|
||||
dec_params = run->decode_params;
|
||||
dst = vb2_to_rkvdec_decoded_buf(&run->base.bufs.dst->vb2_buf);
|
||||
- ref_bufs[0] = get_ref_buf(ctx, &dst->base.vb, dec_params->last_frame_ts);
|
||||
- ref_bufs[1] = get_ref_buf(ctx, &dst->base.vb, dec_params->golden_frame_ts);
|
||||
- ref_bufs[2] = get_ref_buf(ctx, &dst->base.vb, dec_params->alt_frame_ts);
|
||||
+ ref_bufs[0] = get_ref_buf_vp9(ctx, &dst->base.vb, dec_params->last_frame_ts);
|
||||
+ ref_bufs[1] = get_ref_buf_vp9(ctx, &dst->base.vb, dec_params->golden_frame_ts);
|
||||
+ ref_bufs[2] = get_ref_buf_vp9(ctx, &dst->base.vb, dec_params->alt_frame_ts);
|
||||
|
||||
if (vp9_ctx->last.valid)
|
||||
- last = get_ref_buf(ctx, &dst->base.vb, vp9_ctx->last.timestamp);
|
||||
+ last = get_ref_buf_vp9(ctx, &dst->base.vb, vp9_ctx->last.timestamp);
|
||||
else
|
||||
last = dst;
|
||||
|
||||
--
|
||||
2.54.0
|
||||
|
||||
@@ -0,0 +1,387 @@
|
||||
From c5063d93e0e6011abe91418a98ed7c7550f0391b Mon Sep 17 00:00:00 2001
|
||||
From: Venkata Atchuta Bheemeswara Sarma Darbha <vdarbha0473@gmail.com>
|
||||
Date: Sat, 17 Jan 2026 14:37:07 -0600
|
||||
Subject: [PATCH 2/3] media: rkvdec: Move vp9 functions to common file This is
|
||||
a preparation commit to add support for new variants of the decoder.
|
||||
|
||||
The functions will later be shared with vdpu381 (rk3588).
|
||||
|
||||
Change-Id: Ib9b78331fb6eb0e3a607b06fd5138fc741b2c9c0
|
||||
Signed-off-by: Venkata Atchuta Bheemeswara Sarma Darbha <vdarbha0473@gmail.com>
|
||||
(cherry picked from commit e87662ca32e88ebb910f6cfc1c71096d5d7bc063)
|
||||
---
|
||||
.../media/platform/rockchip/rkvdec/Makefile | 1 +
|
||||
.../rockchip/rkvdec/rkvdec-vp9-common.c | 77 +++++++++++
|
||||
.../rockchip/rkvdec/rkvdec-vp9-common.h | 95 +++++++++++++
|
||||
.../platform/rockchip/rkvdec/rkvdec-vp9.c | 125 +-----------------
|
||||
4 files changed, 174 insertions(+), 124 deletions(-)
|
||||
create mode 100644 drivers/media/platform/rockchip/rkvdec/rkvdec-vp9-common.c
|
||||
create mode 100644 drivers/media/platform/rockchip/rkvdec/rkvdec-vp9-common.h
|
||||
|
||||
diff --git a/drivers/media/platform/rockchip/rkvdec/Makefile b/drivers/media/platform/rockchip/rkvdec/Makefile
|
||||
index e629d571e4d8..2bbd67b2db11 100644
|
||||
--- a/drivers/media/platform/rockchip/rkvdec/Makefile
|
||||
+++ b/drivers/media/platform/rockchip/rkvdec/Makefile
|
||||
@@ -12,4 +12,5 @@ rockchip-vdec-y += \
|
||||
rkvdec-vdpu381-hevc.o \
|
||||
rkvdec-vdpu383-h264.o \
|
||||
rkvdec-vdpu383-hevc.o \
|
||||
+ rkvdec-vp9-common.o \
|
||||
rkvdec-vp9.o
|
||||
diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-vp9-common.c b/drivers/media/platform/rockchip/rkvdec/rkvdec-vp9-common.c
|
||||
new file mode 100644
|
||||
index 000000000000..93023737c1ed
|
||||
--- /dev/null
|
||||
+++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-vp9-common.c
|
||||
@@ -0,0 +1,77 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+/*
|
||||
+ * Rockchip video decoder VP9 common functions
|
||||
+ *
|
||||
+ * Copyright (C) 2019 Collabora, Ltd.
|
||||
+ * Boris Brezillon <boris.brezillon@collabora.com>
|
||||
+ * Copyright (C) 2021 Collabora, Ltd.
|
||||
+ * Andrzej Pietrasiewicz <andrzej.p@collabora.com>
|
||||
+ *
|
||||
+ * Copyright (C) 2016 Rockchip Electronics Co., Ltd.
|
||||
+ * Alpha Lin <Alpha.Lin@rock-chips.com>
|
||||
+ */
|
||||
+#include <linux/v4l2-common.h>
|
||||
+#include <media/v4l2-h264.h>
|
||||
+#include <media/v4l2-mem2mem.h>
|
||||
+
|
||||
+#include "rkvdec.h"
|
||||
+#include "rkvdec-vp9-common.h"
|
||||
+
|
||||
+void write_coeff_plane(const u8 coef[6][6][3], u8 *coeff_plane)
|
||||
+{
|
||||
+ unsigned int idx = 0, byte_count = 0;
|
||||
+ int k, m, n;
|
||||
+ u8 p;
|
||||
+
|
||||
+ for (k = 0; k < 6; k++) {
|
||||
+ for (m = 0; m < 6; m++) {
|
||||
+ for (n = 0; n < 3; n++) {
|
||||
+ p = coef[k][m][n];
|
||||
+ coeff_plane[idx++] = p;
|
||||
+ byte_count++;
|
||||
+ if (byte_count == 27) {
|
||||
+ idx += 5;
|
||||
+ byte_count = 0;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+struct rkvdec_decoded_buffer *
|
||||
+get_ref_buf_vp9(struct rkvdec_ctx *ctx, struct vb2_v4l2_buffer *dst, u64 timestamp)
|
||||
+{
|
||||
+ struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx;
|
||||
+ struct vb2_queue *cap_q = &m2m_ctx->cap_q_ctx.q;
|
||||
+ struct vb2_buffer *buf;
|
||||
+
|
||||
+ /*
|
||||
+ * If a ref is unused or invalid, address of current destination
|
||||
+ * buffer is returned.
|
||||
+ */
|
||||
+ buf = vb2_find_buffer(cap_q, timestamp);
|
||||
+ if (!buf)
|
||||
+ buf = &dst->vb2_buf;
|
||||
+
|
||||
+ return vb2_to_rkvdec_decoded_buf(buf);
|
||||
+}
|
||||
+
|
||||
+dma_addr_t get_mv_base_addr(struct rkvdec_decoded_buffer *buf)
|
||||
+{
|
||||
+ unsigned int aligned_pitch, aligned_height, yuv_len;
|
||||
+
|
||||
+ aligned_height = round_up(buf->vp9.height, 64);
|
||||
+ aligned_pitch = round_up(buf->vp9.width * buf->vp9.bit_depth, 512) / 8;
|
||||
+ yuv_len = (aligned_height * aligned_pitch * 3) / 2;
|
||||
+
|
||||
+ return vb2_dma_contig_plane_dma_addr(&buf->base.vb.vb2_buf, 0) +
|
||||
+ yuv_len;
|
||||
+}
|
||||
+
|
||||
+void update_dec_buf_info(struct rkvdec_decoded_buffer *buf,
|
||||
+ const struct v4l2_ctrl_vp9_frame *dec_params)
|
||||
+{
|
||||
+ buf->vp9.width = dec_params->frame_width_minus_1 + 1;
|
||||
+ buf->vp9.height = dec_params->frame_height_minus_1 + 1;
|
||||
+ buf->vp9.bit_depth = dec_params->bit_depth;
|
||||
+}
|
||||
\ No newline at end of file
|
||||
diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-vp9-common.h b/drivers/media/platform/rockchip/rkvdec/rkvdec-vp9-common.h
|
||||
new file mode 100644
|
||||
index 000000000000..056842cf1bba
|
||||
--- /dev/null
|
||||
+++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-vp9-common.h
|
||||
@@ -0,0 +1,95 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+/*
|
||||
+ * Rockchip video decoder VP9 common functions
|
||||
+ *
|
||||
+ * Copyright (C) 2019 Collabora, Ltd.
|
||||
+ * Boris Brezillon <boris.brezillon@collabora.com>
|
||||
+ * Copyright (C) 2021 Collabora, Ltd.
|
||||
+ * Andrzej Pietrasiewicz <andrzej.p@collabora.com>
|
||||
+ *
|
||||
+ * Copyright (C) 2016 Rockchip Electronics Co., Ltd.
|
||||
+ * Alpha Lin <Alpha.Lin@rock-chips.com>
|
||||
+ */
|
||||
+
|
||||
+#include <media/v4l2-h264.h>
|
||||
+#include <media/v4l2-mem2mem.h>
|
||||
+#include <media/v4l2-vp9.h>
|
||||
+
|
||||
+#include "rkvdec.h"
|
||||
+
|
||||
+struct rkvdec_vp9_run {
|
||||
+ struct rkvdec_run base;
|
||||
+ const struct v4l2_ctrl_vp9_frame *decode_params;
|
||||
+};
|
||||
+
|
||||
+struct rkvdec_vp9_intra_mode_probs {
|
||||
+ u8 y_mode[105];
|
||||
+ u8 uv_mode[23];
|
||||
+};
|
||||
+
|
||||
+struct rkvdec_vp9_intra_only_frame_probs {
|
||||
+ u8 coef_intra[4][2][128];
|
||||
+ struct rkvdec_vp9_intra_mode_probs intra_mode[10];
|
||||
+};
|
||||
+
|
||||
+struct rkvdec_vp9_inter_frame_probs {
|
||||
+ u8 y_mode[4][9];
|
||||
+ u8 comp_mode[5];
|
||||
+ u8 comp_ref[5];
|
||||
+ u8 single_ref[5][2];
|
||||
+ u8 inter_mode[7][3];
|
||||
+ u8 interp_filter[4][2];
|
||||
+ u8 padding0[11];
|
||||
+ u8 coef[2][4][2][128];
|
||||
+ u8 uv_mode_0_2[3][9];
|
||||
+ u8 padding1[5];
|
||||
+ u8 uv_mode_3_5[3][9];
|
||||
+ u8 padding2[5];
|
||||
+ u8 uv_mode_6_8[3][9];
|
||||
+ u8 padding3[5];
|
||||
+ u8 uv_mode_9[9];
|
||||
+ u8 padding4[7];
|
||||
+ u8 padding5[16];
|
||||
+ struct {
|
||||
+ u8 joint[3];
|
||||
+ u8 sign[2];
|
||||
+ u8 classes[2][10];
|
||||
+ u8 class0_bit[2];
|
||||
+ u8 bits[2][10];
|
||||
+ u8 class0_fr[2][2][3];
|
||||
+ u8 fr[2][3];
|
||||
+ u8 class0_hp[2];
|
||||
+ u8 hp[2];
|
||||
+ u8 padding6[3];
|
||||
+ } mv;
|
||||
+};
|
||||
+
|
||||
+struct rkvdec_vp9_probs {
|
||||
+ u8 partition[16][3];
|
||||
+ u8 pred[3];
|
||||
+ u8 tree[7];
|
||||
+ u8 skip[3];
|
||||
+ u8 tx32[2][3];
|
||||
+ u8 tx16[2][2];
|
||||
+ u8 tx8[2][1];
|
||||
+ u8 is_inter[4];
|
||||
+ /* 128 bit alignment */
|
||||
+ u8 padding0[3];
|
||||
+ union {
|
||||
+ struct rkvdec_vp9_inter_frame_probs inter;
|
||||
+ struct rkvdec_vp9_intra_only_frame_probs intra_only;
|
||||
+ };
|
||||
+ /* 128 bit alignment */
|
||||
+ u8 padding1[8];
|
||||
+};
|
||||
+
|
||||
+
|
||||
+void write_coeff_plane(const u8 coef[6][6][3], u8 *coeff_plane);
|
||||
+
|
||||
+struct rkvdec_decoded_buffer *
|
||||
+get_ref_buf_vp9(struct rkvdec_ctx *ctx, struct vb2_v4l2_buffer *dst, u64 timestamp);
|
||||
+
|
||||
+dma_addr_t get_mv_base_addr(struct rkvdec_decoded_buffer *buf);
|
||||
+
|
||||
+void update_dec_buf_info(struct rkvdec_decoded_buffer *buf,
|
||||
+ const struct v4l2_ctrl_vp9_frame *dec_params);
|
||||
diff --git a/drivers/media/platform/rockchip/rkvdec/rkvdec-vp9.c b/drivers/media/platform/rockchip/rkvdec/rkvdec-vp9.c
|
||||
index bab2e9c83d06..2b368d7b61e0 100644
|
||||
--- a/drivers/media/platform/rockchip/rkvdec/rkvdec-vp9.c
|
||||
+++ b/drivers/media/platform/rockchip/rkvdec/rkvdec-vp9.c
|
||||
@@ -23,71 +23,12 @@
|
||||
|
||||
#include "rkvdec.h"
|
||||
#include "rkvdec-regs.h"
|
||||
+#include "rkvdec-vp9-common.h"
|
||||
|
||||
#define RKVDEC_VP9_PROBE_SIZE 4864
|
||||
#define RKVDEC_VP9_COUNT_SIZE 13232
|
||||
#define RKVDEC_VP9_MAX_SEGMAP_SIZE 73728
|
||||
|
||||
-struct rkvdec_vp9_intra_mode_probs {
|
||||
- u8 y_mode[105];
|
||||
- u8 uv_mode[23];
|
||||
-};
|
||||
-
|
||||
-struct rkvdec_vp9_intra_only_frame_probs {
|
||||
- u8 coef_intra[4][2][128];
|
||||
- struct rkvdec_vp9_intra_mode_probs intra_mode[10];
|
||||
-};
|
||||
-
|
||||
-struct rkvdec_vp9_inter_frame_probs {
|
||||
- u8 y_mode[4][9];
|
||||
- u8 comp_mode[5];
|
||||
- u8 comp_ref[5];
|
||||
- u8 single_ref[5][2];
|
||||
- u8 inter_mode[7][3];
|
||||
- u8 interp_filter[4][2];
|
||||
- u8 padding0[11];
|
||||
- u8 coef[2][4][2][128];
|
||||
- u8 uv_mode_0_2[3][9];
|
||||
- u8 padding1[5];
|
||||
- u8 uv_mode_3_5[3][9];
|
||||
- u8 padding2[5];
|
||||
- u8 uv_mode_6_8[3][9];
|
||||
- u8 padding3[5];
|
||||
- u8 uv_mode_9[9];
|
||||
- u8 padding4[7];
|
||||
- u8 padding5[16];
|
||||
- struct {
|
||||
- u8 joint[3];
|
||||
- u8 sign[2];
|
||||
- u8 classes[2][10];
|
||||
- u8 class0_bit[2];
|
||||
- u8 bits[2][10];
|
||||
- u8 class0_fr[2][2][3];
|
||||
- u8 fr[2][3];
|
||||
- u8 class0_hp[2];
|
||||
- u8 hp[2];
|
||||
- } mv;
|
||||
-};
|
||||
-
|
||||
-struct rkvdec_vp9_probs {
|
||||
- u8 partition[16][3];
|
||||
- u8 pred[3];
|
||||
- u8 tree[7];
|
||||
- u8 skip[3];
|
||||
- u8 tx32[2][3];
|
||||
- u8 tx16[2][2];
|
||||
- u8 tx8[2][1];
|
||||
- u8 is_inter[4];
|
||||
- /* 128 bit alignment */
|
||||
- u8 padding0[3];
|
||||
- union {
|
||||
- struct rkvdec_vp9_inter_frame_probs inter;
|
||||
- struct rkvdec_vp9_intra_only_frame_probs intra_only;
|
||||
- };
|
||||
- /* 128 bit alignment */
|
||||
- u8 padding1[11];
|
||||
-};
|
||||
-
|
||||
/* Data structure describing auxiliary buffer format. */
|
||||
struct rkvdec_vp9_priv_tbl {
|
||||
struct rkvdec_vp9_probs probs;
|
||||
@@ -136,11 +77,6 @@ struct rkvdec_vp9_intra_frame_symbol_counts {
|
||||
struct rkvdec_vp9_refs_counts ref_cnt[2][4][2][6][6];
|
||||
};
|
||||
|
||||
-struct rkvdec_vp9_run {
|
||||
- struct rkvdec_run base;
|
||||
- const struct v4l2_ctrl_vp9_frame *decode_params;
|
||||
-};
|
||||
-
|
||||
struct rkvdec_vp9_frame_info {
|
||||
u32 valid : 1;
|
||||
u32 segmapid : 1;
|
||||
@@ -166,27 +102,6 @@ struct rkvdec_vp9_ctx {
|
||||
struct rkvdec_regs regs;
|
||||
};
|
||||
|
||||
-static void write_coeff_plane(const u8 coef[6][6][3], u8 *coeff_plane)
|
||||
-{
|
||||
- unsigned int idx = 0, byte_count = 0;
|
||||
- int k, m, n;
|
||||
- u8 p;
|
||||
-
|
||||
- for (k = 0; k < 6; k++) {
|
||||
- for (m = 0; m < 6; m++) {
|
||||
- for (n = 0; n < 3; n++) {
|
||||
- p = coef[k][m][n];
|
||||
- coeff_plane[idx++] = p;
|
||||
- byte_count++;
|
||||
- if (byte_count == 27) {
|
||||
- idx += 5;
|
||||
- byte_count = 0;
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
-}
|
||||
-
|
||||
static void init_intra_only_probs(struct rkvdec_ctx *ctx,
|
||||
const struct rkvdec_vp9_run *run)
|
||||
{
|
||||
@@ -348,36 +263,6 @@ static void init_probs(struct rkvdec_ctx *ctx,
|
||||
init_inter_probs(ctx, run);
|
||||
}
|
||||
|
||||
-static struct rkvdec_decoded_buffer *
|
||||
-get_ref_buf_vp9(struct rkvdec_ctx *ctx, struct vb2_v4l2_buffer *dst, u64 timestamp)
|
||||
-{
|
||||
- struct v4l2_m2m_ctx *m2m_ctx = ctx->fh.m2m_ctx;
|
||||
- struct vb2_queue *cap_q = &m2m_ctx->cap_q_ctx.q;
|
||||
- struct vb2_buffer *buf;
|
||||
-
|
||||
- /*
|
||||
- * If a ref is unused or invalid, address of current destination
|
||||
- * buffer is returned.
|
||||
- */
|
||||
- buf = vb2_find_buffer(cap_q, timestamp);
|
||||
- if (!buf)
|
||||
- buf = &dst->vb2_buf;
|
||||
-
|
||||
- return vb2_to_rkvdec_decoded_buf(buf);
|
||||
-}
|
||||
-
|
||||
-static dma_addr_t get_mv_base_addr(struct rkvdec_decoded_buffer *buf)
|
||||
-{
|
||||
- unsigned int aligned_pitch, aligned_height, yuv_len;
|
||||
-
|
||||
- aligned_height = round_up(buf->vp9.height, 64);
|
||||
- aligned_pitch = round_up(buf->vp9.width * buf->vp9.bit_depth, 512) / 8;
|
||||
- yuv_len = (aligned_height * aligned_pitch * 3) / 2;
|
||||
-
|
||||
- return vb2_dma_contig_plane_dma_addr(&buf->base.vb.vb2_buf, 0) +
|
||||
- yuv_len;
|
||||
-}
|
||||
-
|
||||
static void config_ref_registers(struct rkvdec_ctx *ctx,
|
||||
const struct rkvdec_vp9_run *run,
|
||||
struct rkvdec_decoded_buffer *ref_buf,
|
||||
@@ -446,14 +331,6 @@ static void config_seg_registers(struct rkvdec_ctx *ctx, unsigned int segid)
|
||||
(seg->flags & V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE);
|
||||
}
|
||||
|
||||
-static void update_dec_buf_info(struct rkvdec_decoded_buffer *buf,
|
||||
- const struct v4l2_ctrl_vp9_frame *dec_params)
|
||||
-{
|
||||
- buf->vp9.width = dec_params->frame_width_minus_1 + 1;
|
||||
- buf->vp9.height = dec_params->frame_height_minus_1 + 1;
|
||||
- buf->vp9.bit_depth = dec_params->bit_depth;
|
||||
-}
|
||||
-
|
||||
static void update_ctx_cur_info(struct rkvdec_vp9_ctx *vp9_ctx,
|
||||
struct rkvdec_decoded_buffer *buf,
|
||||
const struct v4l2_ctrl_vp9_frame *dec_params)
|
||||
--
|
||||
2.54.0
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,69 @@
|
||||
# patches/driver/media/
|
||||
|
||||
Scope-tagged kernel-agent patches that touch `drivers/media/` — third-party
|
||||
video-codec enablement work that hasn't reached linux-media patchwork as
|
||||
formal series yet, but is empirically known to work on our test hardware.
|
||||
|
||||
## 0001..0003 — Sarma's VP9 enablement on VDPU381 (RK3588 rkvdec)
|
||||
|
||||
Three patches from `D.V.A.B. Sarma <vdarbha0473@gmail.com>` adding VP9
|
||||
decode support to the VDPU381 variant of rkvdec (the RK3588 generation).
|
||||
|
||||
| # | Subject | LOC | What |
|
||||
|---|---------|----:|------|
|
||||
| 0001 | rkvdec/vp9: rename get_ref_buf to get_ref_buf_vp9 | 10 | rename existing helper to avoid namespace collision with the upcoming HEVC equivalent |
|
||||
| 0002 | rkvdec: move vp9 functions to common file | 172 | extract VP9 plumbing into `rkvdec-vp9-common.{c,h}` so VDPU381 can share with the older RK3399 backend |
|
||||
| 0003 | rkvdec: add VP9 support for VDPU381 variant | 1303 | the actual VDPU381 VP9 backend — register defs + `rkvdec-vdpu381-vp9.c` + glue |
|
||||
|
||||
Combined: ~1500 LOC, 5 new files in `drivers/media/platform/rockchip/rkvdec/`.
|
||||
|
||||
### Upstream provenance
|
||||
|
||||
- Author maintains the work at https://github.com/dvab-sarma/android_kernel_rk_opi
|
||||
branch `add-rkvdec-vdpu381-vp9-v8`.
|
||||
- Collabora's blog post on RK3588/RK3576 video decoder mainline merge cites
|
||||
the work but notes "v1 series needs to be sent for review soon" —
|
||||
i.e. not yet on linux-media patchwork, no upstream timeline.
|
||||
- Casanova's VDPU381+VDPU383 H.264/HEVC base (which these patches sit on top
|
||||
of) IS in mainline 7.0 release.
|
||||
- Patches do NOT modify any of our scope-tagged board / module / soc /
|
||||
subsystem code paths — purely additive to the upstream rkvdec subdirectory.
|
||||
|
||||
### Tested on
|
||||
|
||||
- Author: Orange Pi 5 Pro board (RK3588), AOSP 16 + FFMPEG, Profile 0 + Profile 2
|
||||
- Our fleet: build verified clean on `ampere` (CoolPi CM5 GenBook, RK3588)
|
||||
2026-05-18 with KERNELRELEASE `7.0.0-rc3-vp9-test+` (base = running
|
||||
`7.0.0-rc3-devices+` config + LOCALVERSION change + these 3 patches +
|
||||
the pre-existing issue14 vb2-resv local mods). Full kernel image
|
||||
+ DTB + modules + initramfs land at `/boot/firmware/*-7.0.0-rc3-vp9-test+`
|
||||
and `/lib/modules/7.0.0-rc3-vp9-test+`. New extlinux label `arch_vp9_test`
|
||||
added without touching default `arch_devices`. End-to-end VP9 decode
|
||||
validation requires booting into `arch_vp9_test` (pending operator
|
||||
confirmation, then `v4l2-ctl -d /dev/video1 --list-formats-out` should
|
||||
list `VP9F` alongside `S265` + `S264`).
|
||||
|
||||
### Apply order
|
||||
|
||||
Strict — 0001 → 0002 → 0003. 0003 depends on the common-file refactor
|
||||
from 0002, which depends on the helper rename in 0001.
|
||||
|
||||
### Removal criteria
|
||||
|
||||
Drop these patches when:
|
||||
- Sarma sends a v1 series to linux-media and it lands upstream — adopt
|
||||
the upstream version at the next baseline bump, OR
|
||||
- Collabora produces an alternative VP9 enablement on their own
|
||||
hardware-enablement/rockchip-3588 GitLab tree — prefer that lineage
|
||||
(more likely to land cleanly upstream).
|
||||
|
||||
### How to use in a kernel-agent build
|
||||
|
||||
If `fleet/ampere.yaml` is bumped to include VP9 (currently scope-out per
|
||||
the manifest preamble — "Asks #2 (VP9 enablement on RK3588 rkvdec) and
|
||||
#3 (AV1 dec integration) from issue #6 are NOT addressed in this
|
||||
manifest — tracked separately"), reference these three files in apply
|
||||
order under the manifest's scope-tagged patch list.
|
||||
|
||||
Cross-references: `marfrit/kernel-agent#12` (the VP9-on-ampere enablement
|
||||
issue).
|
||||
@@ -12,8 +12,10 @@ set -euo pipefail
|
||||
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||
fixtures="${repo_root}/tests/ka-promote/fixtures"
|
||||
|
||||
# Phase-3 ground truth — recorded 2026-05-18, fresnel cumulative b2sum.
|
||||
FRESNEL_EXPECTED_B2SUM=4d9d93c655ea701b587bf1383c794f41b1aeb3bc32bca69ce3488852ec2c1474a2f47585608598b39ac05671490b8df63c5bc7d093f87e1afd5a92f908891b67
|
||||
# Phase-3 ground truth — re-recorded 2026-05-19 after issue #31 fix
|
||||
# (write_cumulative now strips per-input trailers + emits canonical
|
||||
# separators between, but not after, concatenated patches).
|
||||
FRESNEL_EXPECTED_B2SUM=9c21751cc48ab57cdf48058cc4309752de169c567bbb898c342ff3e4a5cc79add53e3fd4217c2ae2ae7c16b0f19518cf1791907367e1ea9ef16458e1e90c05e0
|
||||
|
||||
pass=0
|
||||
fail=0
|
||||
@@ -110,6 +112,47 @@ echo
|
||||
echo "Running ka-promote test suite from $repo_root"
|
||||
echo
|
||||
|
||||
# ----- unit: strip_trailer + write_cumulative shape (issue #31) -----
|
||||
echo "::: strip_trailer + cumulative shape (issue #31)"
|
||||
python3 - "$repo_root" <<'PY'
|
||||
import importlib.util, pathlib, sys, tempfile, os
|
||||
root = pathlib.Path(sys.argv[1])
|
||||
from importlib.machinery import SourceFileLoader
|
||||
mod = SourceFileLoader("ka_promote", str(root/"bin"/"ka-promote")).load_module()
|
||||
|
||||
# strip_trailer accepts both shapes and yields newline-terminated body
|
||||
assert mod.strip_trailer(b"...body...\n-- \n2.54.0\n\n") == b"...body...\n"
|
||||
assert mod.strip_trailer(b"...body...\n-- \n2.53.0\n\n") == b"...body...\n"
|
||||
assert mod.strip_trailer(b"...body...\n-- \n2.20\n\n") == b"...body...\n"
|
||||
assert mod.strip_trailer(b"...body...\n") == b"...body...\n"
|
||||
assert mod.strip_trailer(b"...body...") == b"...body...\n"
|
||||
# Multiple trailing blanks after the version still strip
|
||||
assert mod.strip_trailer(b"x\n-- \n2.54.0\n\n\n") == b"x\n"
|
||||
|
||||
# write_cumulative: 3 inputs (mix of with-/without-trailer), check ordering
|
||||
with tempfile.TemporaryDirectory() as d:
|
||||
p1 = os.path.join(d, "a.patch"); open(p1,"wb").write(b"PA\n-- \n2.54.0\n\n")
|
||||
p2 = os.path.join(d, "b.patch"); open(p2,"wb").write(b"PB\n") # already bare
|
||||
p3 = os.path.join(d, "c.patch"); open(p3,"wb").write(b"PC\n-- \n2.40.1\n\n")
|
||||
out = os.path.join(d, "out.patch")
|
||||
resolved = [{"src": p1}, {"src": p2}, {"src": p3}]
|
||||
mod.write_cumulative(resolved, out)
|
||||
body = open(out,"rb").read()
|
||||
assert body == b"PA\n-- \n2.54.0\n\nPB\n-- \n2.54.0\n\nPC\n", repr(body)
|
||||
# Last patch (PC) must NOT carry an orphan trailer at EOF
|
||||
assert not body.rstrip(b"\n").endswith(b"2.40.1"), \
|
||||
f"last patch's trailer leaked into cumulative: {body[-40:]!r}"
|
||||
print("PASS")
|
||||
PY
|
||||
if [ $? -eq 0 ]; then
|
||||
results+=("PASS strip_trailer + cumulative shape (issue #31)")
|
||||
pass=$((pass+1))
|
||||
else
|
||||
results+=("FAIL strip_trailer + cumulative shape (issue #31)")
|
||||
fail=$((fail+1))
|
||||
fi
|
||||
echo
|
||||
|
||||
# Use the real fleet/fresnel.yaml — copy into a sandbox so the test is hermetic.
|
||||
mkdir -p /tmp/ka-promote-parity-fixture
|
||||
cp "$repo_root/fleet/fresnel.yaml" /tmp/ka-promote-parity-fixture/fresnel.yaml
|
||||
|
||||
Reference in New Issue
Block a user