diff --git a/fleet/ohm.yaml b/fleet/ohm.yaml index 5456d01..e1a2bfd 100644 --- a/fleet/ohm.yaml +++ b/fleet/ohm.yaml @@ -25,23 +25,44 @@ baseline: # Scope-tagged patch includes. Resolves to patches//.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. @@ -55,8 +76,10 @@ includes: # 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 diff --git a/patches/driver/bes2600/ba-lock-atomic-danctnix/0001-bes2600-Patch-D-atomicize-ba_lock-counters-drop-the-spinlock.patch b/patches/driver/bes2600/ba-lock-atomic-danctnix/0001-bes2600-Patch-D-atomicize-ba_lock-counters-drop-the-spinlock.patch new file mode 100644 index 0000000..7947458 --- /dev/null +++ b/patches/driver/bes2600/ba-lock-atomic-danctnix/0001-bes2600-Patch-D-atomicize-ba_lock-counters-drop-the-spinlock.patch @@ -0,0 +1,313 @@ +From 44b296647be9246c6802a86c082c6507669810b0 Mon Sep 17 00:00:00 2001 +From: Markus Fritsche +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 ec41141..31a411b 100644 +--- a/drivers/staging/bes2600/bes2600.h ++++ b/drivers/staging/bes2600/bes2600.h +@@ -356,15 +356,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 0d68392..2d144ac 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 90a8ff8..be375f5 100644 +--- a/drivers/staging/bes2600/main.c ++++ b/drivers/staging/bes2600/main.c +@@ -490,7 +490,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 81f88ed..d94dd2e 100644 +--- a/drivers/staging/bes2600/sta.c ++++ b/drivers/staging/bes2600/sta.c +@@ -2342,14 +2342,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; +@@ -2629,10 +2634,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); + +@@ -2645,37 +2651,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 = from_timer(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", +@@ -2685,9 +2703,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 346312c..82ef6fa 100644 +--- a/drivers/staging/bes2600/txrx.c ++++ b/drivers/staging/bes2600/txrx.c +@@ -995,14 +995,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 +@@ -1629,14 +1633,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 + diff --git a/patches/driver/bes2600/bh-c-fossil-cleanup-danctnix/0001-bes2600-Patch-H-bh.c-hygiene-cleanup-drop-fossil-blocks-dead-stubs.patch b/patches/driver/bes2600/bh-c-fossil-cleanup-danctnix/0001-bes2600-Patch-H-bh.c-hygiene-cleanup-drop-fossil-blocks-dead-stubs.patch new file mode 100644 index 0000000..330c2d6 --- /dev/null +++ b/patches/driver/bes2600/bh-c-fossil-cleanup-danctnix/0001-bes2600-Patch-H-bh.c-hygiene-cleanup-drop-fossil-blocks-dead-stubs.patch @@ -0,0 +1,725 @@ +From f68fd5530f3bc3c2dc33cc5e3408047ff21a7676 Mon Sep 17 00:00:00 2001 +From: Markus Fritsche +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 0e0888e..e419e35 100644 +--- a/drivers/staging/bes2600/bh.c ++++ b/drivers/staging/bes2600/bh.c +@@ -316,83 +316,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, +@@ -402,475 +325,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); + +@@ -1592,7 +1046,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; + +@@ -1636,18 +1098,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); +@@ -1656,4 +1119,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 + diff --git a/patches/driver/bes2600/connection-loss-fast-recover-danctnix/0001-bes2600-bus_reset-on-connection-loss-storm-to-dodge-assoc-comeback-blackhole.patch b/patches/driver/bes2600/connection-loss-fast-recover-danctnix/0001-bes2600-bus_reset-on-connection-loss-storm-to-dodge-assoc-comeback-blackhole.patch new file mode 100644 index 0000000..b16d98e --- /dev/null +++ b/patches/driver/bes2600/connection-loss-fast-recover-danctnix/0001-bes2600-bus_reset-on-connection-loss-storm-to-dodge-assoc-comeback-blackhole.patch @@ -0,0 +1,279 @@ +From f2cf586f89d31e297228fabec92dcea5c3fb7165 Mon Sep 17 00:00:00 2001 +From: "Claude (noether)" +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) +--- + 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 3f0c59b..310ab81 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 9d2aac5..d6da84a 100644 +--- a/drivers/staging/bes2600/main.c ++++ b/drivers/staging/bes2600/main.c +@@ -484,6 +484,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 1b78051..81f88ed 100644 +--- a/drivers/staging/bes2600/sta.c ++++ b/drivers/staging/bes2600/sta.c +@@ -266,6 +266,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); + +@@ -1659,6 +1660,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 = +@@ -1668,9 +1733,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 +@@ -2621,6 +2698,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 + diff --git a/patches/driver/bes2600/cw1200-fix-backports-danctnix/0001-bes2600-replace-atomic_add-with-atomic_inc-cw1200-backport.patch b/patches/driver/bes2600/cw1200-fix-backports-danctnix/0001-bes2600-replace-atomic_add-with-atomic_inc-cw1200-backport.patch new file mode 100644 index 0000000..076eb44 --- /dev/null +++ b/patches/driver/bes2600/cw1200-fix-backports-danctnix/0001-bes2600-replace-atomic_add-with-atomic_inc-cw1200-backport.patch @@ -0,0 +1,92 @@ +From 4bc0a34c94094d9e896c5a2f45b54d8be6c0fca7 Mon Sep 17 00:00:00 2001 +From: Markus Fritsche +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 + Signed-off-by: Kalle Valo + 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 6385312..1d2773c 100644 +--- a/drivers/staging/bes2600/bh.c ++++ b/drivers/staging/bes2600/bh.c +@@ -101,7 +101,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); +@@ -590,7 +590,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; + } + +@@ -758,9 +758,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) +@@ -1134,7 +1134,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); +@@ -1435,7 +1435,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 + diff --git a/patches/driver/bes2600/cw1200-fix-backports-danctnix/0002-bes2600-fix-missing-destroy_workqueue-on-error-in-init_common.patch b/patches/driver/bes2600/cw1200-fix-backports-danctnix/0002-bes2600-fix-missing-destroy_workqueue-on-error-in-init_common.patch new file mode 100644 index 0000000..a8e53b6 --- /dev/null +++ b/patches/driver/bes2600/cw1200-fix-backports-danctnix/0002-bes2600-fix-missing-destroy_workqueue-on-error-in-init_common.patch @@ -0,0 +1,58 @@ +From 65a4c39914f07bcb0fc01ea78b974e6901d3377d Mon Sep 17 00:00:00 2001 +From: Markus Fritsche +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 + Reported-by: Hulk Robot + Signed-off-by: Kalle Valo + 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 d6da84a..90a8ff8 100644 +--- a/drivers/staging/bes2600/main.c ++++ b/drivers/staging/bes2600/main.c +@@ -497,6 +497,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; + } +@@ -508,6 +509,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 + diff --git a/patches/driver/bes2600/cw1200-fix-backports-danctnix/0003-bes2600-fix-concurrency-UAF-in-bes2600_hw_scan-and-sched_scan.patch b/patches/driver/bes2600/cw1200-fix-backports-danctnix/0003-bes2600-fix-concurrency-UAF-in-bes2600_hw_scan-and-sched_scan.patch new file mode 100644 index 0000000..b3d34d1 --- /dev/null +++ b/patches/driver/bes2600/cw1200-fix-backports-danctnix/0003-bes2600-fix-concurrency-UAF-in-bes2600_hw_scan-and-sched_scan.patch @@ -0,0 +1,144 @@ +From b717251598c95bb7ce7822ffa103216598f19b67 Mon Sep 17 00:00:00 2001 +From: Markus Fritsche +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 + 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 ad5033b..16b5d0f 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 + diff --git a/patches/driver/bes2600/decrypt-storm-fast-recover-danctnix/0001-bes2600-pre-empt-AP-deauth-6-mac80211-reassoc-on-decrypt-fail-storm.patch b/patches/driver/bes2600/decrypt-storm-fast-recover-danctnix/0001-bes2600-pre-empt-AP-deauth-6-mac80211-reassoc-on-decrypt-fail-storm.patch new file mode 100644 index 0000000..1195522 --- /dev/null +++ b/patches/driver/bes2600/decrypt-storm-fast-recover-danctnix/0001-bes2600-pre-empt-AP-deauth-6-mac80211-reassoc-on-decrypt-fail-storm.patch @@ -0,0 +1,221 @@ +From d0f14e3ba7408e81ed4c76941b8a4c7abda0c61b Mon Sep 17 00:00:00 2001 +From: "Claude (noether)" +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) +Co-Authored-By: Claude Opus 4.7 (1M context) +--- + 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 5f1a456..1b78051 100644 +--- a/drivers/staging/bes2600/sta.c ++++ b/drivers/staging/bes2600/sta.c +@@ -448,6 +448,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); + + del_timer_sync(&priv->mcast_timeout); + /* TODO:COMBO: May be reset of these variables "delayed_link_loss and +@@ -2619,6 +2620,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 dbd1b23..346312c 100644 +--- a/drivers/staging/bes2600/txrx.c ++++ b/drivers/staging/bes2600/txrx.c +@@ -25,6 +25,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 */ +@@ -1672,6 +1744,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 + diff --git a/patches/driver/bes2600/drop-dpd-file-paths-danctnix/0001-bes2600-drop-BES2600_WRITE_DPD_TO_FILE-kernel-file-p.patch b/patches/driver/bes2600/drop-dpd-file-paths-danctnix/0001-bes2600-drop-BES2600_WRITE_DPD_TO_FILE-kernel-file-paths.patch similarity index 98% rename from patches/driver/bes2600/drop-dpd-file-paths-danctnix/0001-bes2600-drop-BES2600_WRITE_DPD_TO_FILE-kernel-file-p.patch rename to patches/driver/bes2600/drop-dpd-file-paths-danctnix/0001-bes2600-drop-BES2600_WRITE_DPD_TO_FILE-kernel-file-paths.patch index 76f6100..b2cab67 100644 --- a/patches/driver/bes2600/drop-dpd-file-paths-danctnix/0001-bes2600-drop-BES2600_WRITE_DPD_TO_FILE-kernel-file-p.patch +++ b/patches/driver/bes2600/drop-dpd-file-paths-danctnix/0001-bes2600-drop-BES2600_WRITE_DPD_TO_FILE-kernel-file-paths.patch @@ -1,7 +1,8 @@ -From 699871fdc6bf1bed6d919732820183e57faeaddc Mon Sep 17 00:00:00 2001 +From ef24cdb8918b72006226ff18c4a8b9b504879510 Mon Sep 17 00:00:00 2001 From: Markus Fritsche 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 diff --git a/patches/driver/bes2600/drop-orphan-file-io-danctnix/0001-bes2600-drop-orphan-DATA_DUMP_OBSERVE-and-access_fil.patch b/patches/driver/bes2600/drop-orphan-file-io-danctnix/0001-bes2600-drop-orphan-DATA_DUMP_OBSERVE-and-access_file-IO.patch similarity index 96% rename from patches/driver/bes2600/drop-orphan-file-io-danctnix/0001-bes2600-drop-orphan-DATA_DUMP_OBSERVE-and-access_fil.patch rename to patches/driver/bes2600/drop-orphan-file-io-danctnix/0001-bes2600-drop-orphan-DATA_DUMP_OBSERVE-and-access_file-IO.patch index 38fef50..dec48e0 100644 --- a/patches/driver/bes2600/drop-orphan-file-io-danctnix/0001-bes2600-drop-orphan-DATA_DUMP_OBSERVE-and-access_fil.patch +++ b/patches/driver/bes2600/drop-orphan-file-io-danctnix/0001-bes2600-drop-orphan-DATA_DUMP_OBSERVE-and-access_file-IO.patch @@ -1,8 +1,8 @@ -From 44e085360fec09c1c1f7b35a23ec679f7065d3f7 Mon Sep 17 00:00:00 2001 +From ebb5c579889e8cf98bdfe0f1b317e89cbb692948 Mon Sep 17 00:00:00 2001 From: Markus Fritsche 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 @@ -164,5 +164,5 @@ index 6ed6b15..9d2aac5 100644 { int ret = 0, if_id; -- -2.53.0 +2.54.0 diff --git a/patches/driver/bes2600/enable-testmode/0001-bes2600-enable-CONFIG_BES2600_TESTMODE-by-default-fi.patch b/patches/driver/bes2600/enable-testmode/0001-bes2600-enable-CONFIG_BES2600_TESTMODE-by-default-fix-bitrot.patch similarity index 88% rename from patches/driver/bes2600/enable-testmode/0001-bes2600-enable-CONFIG_BES2600_TESTMODE-by-default-fi.patch rename to patches/driver/bes2600/enable-testmode/0001-bes2600-enable-CONFIG_BES2600_TESTMODE-by-default-fix-bitrot.patch index 276d176..5761984 100644 --- a/patches/driver/bes2600/enable-testmode/0001-bes2600-enable-CONFIG_BES2600_TESTMODE-by-default-fi.patch +++ b/patches/driver/bes2600/enable-testmode/0001-bes2600-enable-CONFIG_BES2600_TESTMODE-by-default-fix-bitrot.patch @@ -1,8 +1,8 @@ -From 9398d3028bc9d2f4ccbf8e830f8e9799bf065ce4 Mon Sep 17 00:00:00 2001 +From 9012b74eea8d540c8637d7645093204d1e94e99a Mon Sep 17 00:00:00 2001 From: Markus Fritsche 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 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,10 +107,10 @@ index 605cea8..65cf703 100644 + if (_cond) \ + bes_err(fmt, ##__VA_ARGS__); \ + } while (0) -diff --git a/bes2600/sta.c b/bes2600/sta.c +diff --git a/drivers/staging/bes2600/sta.c b/drivers/staging/bes2600/sta.c index aa69eb8..5f1a456 100644 ---- a/bes2600/sta.c -+++ b/bes2600/sta.c +--- a/drivers/staging/bes2600/sta.c ++++ b/drivers/staging/bes2600/sta.c @@ -3633,7 +3633,7 @@ static int bes2600_set_power_save(struct ieee80211_hw *hw, * * Returns: 0 on success or non zero value on failure @@ -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 diff --git a/patches/driver/bes2600/factory-drop-kernel-write-danctnix/0001-bes2600-drop-kernel_write-persistence-from-factory-c.patch b/patches/driver/bes2600/factory-drop-kernel-write-danctnix/0001-bes2600-drop-kernel_write-persistence-from-factory-cali-save.patch similarity index 97% rename from patches/driver/bes2600/factory-drop-kernel-write-danctnix/0001-bes2600-drop-kernel_write-persistence-from-factory-c.patch rename to patches/driver/bes2600/factory-drop-kernel-write-danctnix/0001-bes2600-drop-kernel_write-persistence-from-factory-cali-save.patch index e1555cb..85491fe 100644 --- a/patches/driver/bes2600/factory-drop-kernel-write-danctnix/0001-bes2600-drop-kernel_write-persistence-from-factory-c.patch +++ b/patches/driver/bes2600/factory-drop-kernel-write-danctnix/0001-bes2600-drop-kernel_write-persistence-from-factory-cali-save.patch @@ -1,8 +1,8 @@ -From 5f475a9624490b07c305329f12016ff4a4df3b47 Mon Sep 17 00:00:00 2001 +From 64eae76f4e237fa3149c858a7b1ac07b67559970 Mon Sep 17 00:00:00 2001 From: Markus Fritsche 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 diff --git a/patches/driver/bes2600/factory-series/0001-bes2600-use-request_firmware-for-factory.txt-read.patch b/patches/driver/bes2600/factory-series/0001-bes2600-use-request_firmware-for-factory.txt-read.patch index 7d2a684..b8d66fd 100644 --- a/patches/driver/bes2600/factory-series/0001-bes2600-use-request_firmware-for-factory.txt-read.patch +++ b/patches/driver/bes2600/factory-series/0001-bes2600-use-request_firmware-for-factory.txt-read.patch @@ -1,7 +1,7 @@ -From 1a5d54a3213041262caf1605bb19c66ddded41f7 Mon Sep 17 00:00:00 2001 +From b76c9904f88e3147644960925d8c9835341e99d7 Mon Sep 17 00:00:00 2001 From: Markus Fritsche 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 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 #include @@ -140,5 +140,5 @@ index dc5d3da..8d60b7c 100644 } -- -2.53.0 +2.54.0 diff --git a/patches/driver/bes2600/factory-series/0002-bes2600-default-STANDARD_FACTORY_EFUSE_FLAG-off-for-.patch b/patches/driver/bes2600/factory-series/0002-bes2600-default-STANDARD_FACTORY_EFUSE_FLAG-off-for-PineTab2.patch similarity index 87% rename from patches/driver/bes2600/factory-series/0002-bes2600-default-STANDARD_FACTORY_EFUSE_FLAG-off-for-.patch rename to patches/driver/bes2600/factory-series/0002-bes2600-default-STANDARD_FACTORY_EFUSE_FLAG-off-for-PineTab2.patch index c55db93..350ed82 100644 --- a/patches/driver/bes2600/factory-series/0002-bes2600-default-STANDARD_FACTORY_EFUSE_FLAG-off-for-.patch +++ b/patches/driver/bes2600/factory-series/0002-bes2600-default-STANDARD_FACTORY_EFUSE_FLAG-off-for-PineTab2.patch @@ -1,7 +1,7 @@ -From 82ba594a444a855310fbbe2a5c8ff02f211d8e83 Mon Sep 17 00:00:00 2001 +From 98c6e363f0522ded02b06802f003f3c2f168e564 Mon Sep 17 00:00:00 2001 From: Markus Fritsche 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 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 diff --git a/patches/driver/bes2600/factory-thread-dev/0001-bes2600-thread-struct-device-through-factory-request.patch b/patches/driver/bes2600/factory-thread-dev/0001-bes2600-thread-struct-device-through-factory-request_firmware.patch similarity index 83% rename from patches/driver/bes2600/factory-thread-dev/0001-bes2600-thread-struct-device-through-factory-request.patch rename to patches/driver/bes2600/factory-thread-dev/0001-bes2600-thread-struct-device-through-factory-request_firmware.patch index 4052ba9..a5595f6 100644 --- a/patches/driver/bes2600/factory-thread-dev/0001-bes2600-thread-struct-device-through-factory-request.patch +++ b/patches/driver/bes2600/factory-thread-dev/0001-bes2600-thread-struct-device-through-factory-request_firmware.patch @@ -1,7 +1,7 @@ -From 8732881c5916106539b9071b51710489c57e8d73 Mon Sep 17 00:00:00 2001 +From 20d349e2b5bffe25c17af2612d179b42e27c7414 Mon Sep 17 00:00:00 2001 From: Markus Fritsche 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 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 +diff --git a/drivers/staging/bes2600/bes2600_sdio.c b/drivers/staging/bes2600/bes2600_sdio.c index b595365..371ef4f 100644 ---- a/bes2600/bes2600_sdio.c -+++ b/bes2600/bes2600_sdio.c +--- 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 diff --git a/patches/driver/bes2600/license-spdx-restore-attribution-danctnix/0001-bes2600-Patch-G-restore-SPDX-identifiers-ST-Ericsson-attribution.patch b/patches/driver/bes2600/license-spdx-restore-attribution-danctnix/0001-bes2600-Patch-G-restore-SPDX-identifiers-ST-Ericsson-attribution.patch new file mode 100644 index 0000000..2f49393 --- /dev/null +++ b/patches/driver/bes2600/license-spdx-restore-attribution-danctnix/0001-bes2600-Patch-G-restore-SPDX-identifiers-ST-Ericsson-attribution.patch @@ -0,0 +1,1154 @@ +From 8dd79199f8a09ee3af6853e01a2ab3bab7684d81 Mon Sep 17 00:00:00 2001 +From: Markus Fritsche +Date: Fri, 8 May 2026 00:03:50 +0200 +Subject: [PATCH 26/29] =?UTF-8?q?bes2600:=20Patch=20G=20=E2=80=94=20restor?= + =?UTF-8?q?e=20SPDX=20identifiers=20+=20ST-Ericsson=20attribution?= +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The bes2600 driver is a fork of the upstream cw1200 driver +(drivers/net/wireless/st/cw1200/, ST-Ericsson, Dmitry Tarnyagin +2010-2011). The fork's file headers have three GPL-compliance issues: + + 1. NO SPDX-License-Identifier on any of 48 source files (cw1200 + mainline has them on all 25). kernel.org-mandated since 2017. + + 2. Original "Copyright (c) 2010, ST-Ericsson" lines stripped from + all files inherited from cw1200, replaced with + "Copyright (c) 2010, Bestechnic" — factually impossible + (Bestechnic did not author the 2010 work) and a GPL-2.0 §1 + attribution-preservation violation. + + 3. The "GPL version 2 as published by the Free Software Foundation" + boilerplate paragraph is redundant alongside SPDX and is the + legacy form modern kernel sources have replaced. + +This patch corrects all three for the 48 .c/.h files in bes2600/: + + - Adds `// SPDX-License-Identifier: GPL-2.0-only` (or `/* ... */` + for headers) as line 1 of every file. + - Restores `Copyright (c) 2010, ST-Ericsson` + `Author: Dmitry + Tarnyagin ` as the FIRST copyright + chain entry on all 22 files derived from cw1200 (bh.{c,h}, + debug.{c,h}, fwio.{c,h}, hwio.{c,h}, main.c, pm.{c,h}, + queue.{c,h}, scan.{c,h}, sta.{c,h}, txrx.{c,h}, wsm.{c,h}). + - Keeps `Copyright (c) 2022, Bestechnic (Beijing) Co., Ltd.` as + the SECOND chain entry where Bestechnic genuinely contributed. + - Notes "Derived from cw1200_sdio.c" + ST-Ericsson copyright on + bes2600_sdio.c (heavy derivation, not a literal rename). + - Notes "Replaces hwbus.h from cw1200/" + ST-Ericsson copyright + on sbus.h. + - Preserves the prism54/islsm authorship chain on main.c and + bes2600.h (Michael Wu 2006 + Jean-Baptiste Note 2004-2006). + - Drops the GPL-2.0 boilerplate paragraph in favour of SPDX. + +No code changes — only file-header comment blocks. Module build is +unaffected (verified by header-only diff scope). + +This is a prerequisite for any kernel.org submission attempt. The +existing MODULE_LICENSE("GPL") + MODULE_AUTHOR(Tarnyagin@stericsson.com) +declarations were already present and are unchanged here; the +mismatch between MODULE_AUTHOR and the (since-corrected) per-file +copyrights is now resolved. +--- + bes2600/ap.c | 9 +++------ + bes2600/ap.h | 9 +++------ + bes2600/bes2600.h | 11 ++++------- + bes2600/bes2600_factory.c | 9 +++------ + bes2600/bes2600_factory.h | 9 +++------ + bes2600/bes2600_plat.h | 9 +++------ + bes2600/bes2600_sdio.c | 13 +++++++------ + bes2600/bes_chardev.c | 9 +++------ + bes2600/bes_chardev.h | 9 +++------ + bes2600/bes_fw.c | 9 +++------ + bes2600/bes_fw_common.c | 9 +++------ + bes2600/bes_fw_common.h | 9 +++------ + bes2600/bes_log.h | 7 +++++++ + bes2600/bes_nl80211_testmode_msg.h | 9 +++------ + bes2600/bes_pwr.c | 9 +++------ + bes2600/bes_pwr.h | 9 +++------ + bes2600/bh.c | 12 ++++++------ + bes2600/bh.h | 12 ++++++------ + bes2600/debug.c | 12 ++++++------ + bes2600/debug.h | 12 ++++++------ + bes2600/epta_coex.c | 9 +++------ + bes2600/epta_coex.h | 9 +++------ + bes2600/epta_request.c | 9 +++------ + bes2600/epta_request.h | 9 +++------ + bes2600/fwio.c | 12 ++++++------ + bes2600/fwio.h | 12 ++++++------ + bes2600/ht.h | 9 +++------ + bes2600/hwio.c | 12 ++++++------ + bes2600/hwio.h | 15 +++++---------- + bes2600/itp.c | 10 +++------- + bes2600/itp.h | 9 +++------ + bes2600/main.c | 18 ++++++++++++------ + bes2600/pm.c | 12 ++++++------ + bes2600/pm.h | 12 ++++++------ + bes2600/queue.c | 12 ++++++------ + bes2600/queue.h | 12 ++++++------ + bes2600/sbus.h | 12 ++++++------ + bes2600/scan.c | 12 ++++++------ + bes2600/scan.h | 12 ++++++------ + bes2600/sta.c | 12 ++++++------ + bes2600/sta.h | 12 ++++++------ + bes2600/tx_loop.c | 9 +++------ + bes2600/tx_loop.h | 9 +++------ + bes2600/txrx.c | 12 ++++++------ + bes2600/txrx.h | 12 ++++++------ + bes2600/wifi_testmode_cmd.c | 9 +++------ + bes2600/wsm.c | 13 ++++++------- + bes2600/wsm.h | 14 +++++--------- + 48 files changed, 223 insertions(+), 292 deletions(-) + +diff --git a/drivers/staging/bes2600/ap.c b/drivers/staging/bes2600/ap.c +index 71660d4..0a23790 100644 +--- a/drivers/staging/bes2600/ap.c ++++ b/drivers/staging/bes2600/ap.c +@@ -1,12 +1,9 @@ ++// SPDX-License-Identifier: GPL-2.0-only + /* +- * mac80211 STA and AP API for mac80211 BES2600 drivers ++ * AP mode for BES2600 mac80211 driver + * +- * Copyright (c) 2022, Bestechnic +- * Author: ++ * Copyright (c) 2022, Bestechnic (Beijing) Co., Ltd. + * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. + */ + + #include "bes2600.h" +diff --git a/drivers/staging/bes2600/ap.h b/drivers/staging/bes2600/ap.h +index 6f27852..f6e88c6 100644 +--- a/drivers/staging/bes2600/ap.h ++++ b/drivers/staging/bes2600/ap.h +@@ -1,12 +1,9 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ + /* +- * mac80211 STA and AP API for mac80211 BES2600 drivers ++ * AP mode interface for BES2600 mac80211 driver + * +- * Copyright (c) 2010, Bestechnic +- * Author: ++ * Copyright (c) 2022, Bestechnic (Beijing) Co., Ltd. + * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. + */ + #include + #ifndef AP_H_INCLUDED +diff --git a/drivers/staging/bes2600/bes2600.h b/drivers/staging/bes2600/bes2600.h +index ec41141..84059c7 100644 +--- a/drivers/staging/bes2600/bes2600.h ++++ b/drivers/staging/bes2600/bes2600.h +@@ -1,18 +1,15 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ + /* +- * Common private data for BES2600 drivers ++ * Common private data for BES2600 mac80211 driver + * +- * Copyright (c) 2010, Bestechnic +- * Author: ++ * Copyright (c) 2022, Bestechnic (Beijing) Co., Ltd. + * + * Based on the mac80211 Prism54 code, which is + * Copyright (c) 2006, Michael Wu + * +- * Based on the islsm (softmac prism54) driver, which is: ++ * Based on the islsm (softmac prism54) driver, which is + * Copyright 2004-2006 Jean-Baptiste Note , et al. + * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. + */ + + #ifndef BES2600_H +diff --git a/drivers/staging/bes2600/bes2600_factory.c b/drivers/staging/bes2600/bes2600_factory.c +index 1b43b41..0d2bfa1 100644 +--- a/drivers/staging/bes2600/bes2600_factory.c ++++ b/drivers/staging/bes2600/bes2600_factory.c +@@ -1,12 +1,9 @@ ++// SPDX-License-Identifier: GPL-2.0-only + /* +- * Mac80211 driver for BES2600 device ++ * Factory calibration loader for BES2600 + * +- * Copyright (c) 2022, Bestechnic +- * Author: ++ * Copyright (c) 2022, Bestechnic (Beijing) Co., Ltd. + * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. + */ + + #include +diff --git a/drivers/staging/bes2600/bes2600_factory.h b/drivers/staging/bes2600/bes2600_factory.h +index 7dbe9f8..0b1a321 100644 +--- a/drivers/staging/bes2600/bes2600_factory.h ++++ b/drivers/staging/bes2600/bes2600_factory.h +@@ -1,12 +1,9 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ + /* +- * Mac80211 driver for BES2600 device ++ * Factory calibration loader interface + * +- * Copyright (c) 2022, Bestechnic +- * Author: ++ * Copyright (c) 2022, Bestechnic (Beijing) Co., Ltd. + * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. + */ + #ifndef __FACTORY_H__ + #define __FACTORY_H__ +diff --git a/drivers/staging/bes2600/bes2600_plat.h b/drivers/staging/bes2600/bes2600_plat.h +index 63c3275..ebec635 100644 +--- a/drivers/staging/bes2600/bes2600_plat.h ++++ b/drivers/staging/bes2600/bes2600_plat.h +@@ -1,12 +1,9 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ + /* +- * Mac80211 driver for BES2600 device ++ * Platform data for BES2600 SDIO bus + * +- * Copyright (c) 2010, Bestechnic +- * Author: ++ * Copyright (c) 2022, Bestechnic (Beijing) Co., Ltd. + * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. + */ + #ifndef BES2600_PLAT_H_INCLUDED + #define BES2600_PLAT_H_INCLUDED +diff --git a/drivers/staging/bes2600/bes2600_sdio.c b/drivers/staging/bes2600/bes2600_sdio.c +index b6b4e4e..3abda2a 100644 +--- a/drivers/staging/bes2600/bes2600_sdio.c ++++ b/drivers/staging/bes2600/bes2600_sdio.c +@@ -1,12 +1,13 @@ ++// SPDX-License-Identifier: GPL-2.0-only + /* +- * Mac80211 SDIO driver for BES2600 device ++ * SDIO bus glue for BES2600 mac80211 driver ++ * ++ * Copyright (c) 2022, Bestechnic (Beijing) Co., Ltd. ++ * Derived from drivers/net/wireless/st/cw1200/cw1200_sdio.c ++ * Copyright (c) 2010, ST-Ericsson ++ * Author: Dmitry Tarnyagin + * +- * Copyright (c) 2010, Bestechnic +- * Author: + * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. + */ + #define DEBUG 1 + #include +diff --git a/drivers/staging/bes2600/bes_chardev.c b/drivers/staging/bes2600/bes_chardev.c +index 224c62d..02dcd43 100644 +--- a/drivers/staging/bes2600/bes_chardev.c ++++ b/drivers/staging/bes2600/bes_chardev.c +@@ -1,12 +1,9 @@ ++// SPDX-License-Identifier: GPL-2.0-only + /* +- * Mac80211 driver for BES2600 device ++ * Character device for BES2600 mac80211 driver + * +- * Copyright (c) 2022, Bestechnic +- * Author: ++ * Copyright (c) 2022, Bestechnic (Beijing) Co., Ltd. + * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. + */ + #include + #include +diff --git a/drivers/staging/bes2600/bes_chardev.h b/drivers/staging/bes2600/bes_chardev.h +index 310ab81..3e4eee6 100644 +--- a/drivers/staging/bes2600/bes_chardev.h ++++ b/drivers/staging/bes2600/bes_chardev.h +@@ -1,12 +1,9 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ + /* +- * Mac80211 driver for BES2600 device ++ * Character device interface for BES2600 + * +- * Copyright (c) 2022, Bestechnic +- * Author: ++ * Copyright (c) 2022, Bestechnic (Beijing) Co., Ltd. + * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. + */ + #ifndef __BES_CHARDEV_H__ + #define __BES_CHARDEV_H__ +diff --git a/drivers/staging/bes2600/bes_fw.c b/drivers/staging/bes2600/bes_fw.c +index d612c3c..6c5598b 100644 +--- a/drivers/staging/bes2600/bes_fw.c ++++ b/drivers/staging/bes2600/bes_fw.c +@@ -1,12 +1,9 @@ ++// SPDX-License-Identifier: GPL-2.0-only + /* +- * Mac80211 driver for BES2600 device ++ * Firmware download for BES2600 + * +- * Copyright (c) 2022, Bestechnic +- * Author: ++ * Copyright (c) 2022, Bestechnic (Beijing) Co., Ltd. + * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. + */ + #include "bes_fw_common.h" + #include "bes2600.h" +diff --git a/drivers/staging/bes2600/bes_fw_common.c b/drivers/staging/bes2600/bes_fw_common.c +index 2e47455..a0c1f93 100644 +--- a/drivers/staging/bes2600/bes_fw_common.c ++++ b/drivers/staging/bes2600/bes_fw_common.c +@@ -1,12 +1,9 @@ ++// SPDX-License-Identifier: GPL-2.0-only + /* +- * Mac80211 driver for BES2600 device ++ * Firmware download common code for BES2600 + * +- * Copyright (c) 2022, Bestechnic +- * Author: ++ * Copyright (c) 2022, Bestechnic (Beijing) Co., Ltd. + * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. + */ + #include "bes_fw_common.h" + #include "bes_log.h" +diff --git a/drivers/staging/bes2600/bes_fw_common.h b/drivers/staging/bes2600/bes_fw_common.h +index 5c6561a..dcd5200 100644 +--- a/drivers/staging/bes2600/bes_fw_common.h ++++ b/drivers/staging/bes2600/bes_fw_common.h +@@ -1,12 +1,9 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ + /* +- * Mac80211 driver for BES2600 device ++ * Firmware download common interface + * +- * Copyright (c) 2022, Bestechnic +- * Author: ++ * Copyright (c) 2022, Bestechnic (Beijing) Co., Ltd. + * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. + */ + #ifndef __BES_FW_COMMON_H__ + #define __BES_FW_COMMON_H__ +diff --git a/drivers/staging/bes2600/bes_log.h b/drivers/staging/bes2600/bes_log.h +index 65cf703..7d3c4b8 100644 +--- a/drivers/staging/bes2600/bes_log.h ++++ b/drivers/staging/bes2600/bes_log.h +@@ -1,3 +1,10 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ ++/* ++ * printk wrappers for BES2600 ++ * ++ * Copyright (c) 2022, Bestechnic (Beijing) Co., Ltd. ++ * ++ */ + extern struct device *global_dev; + + #ifdef CONFIG_BES2600_ENABLE_DEVEL_LOGS +diff --git a/drivers/staging/bes2600/bes_nl80211_testmode_msg.h b/drivers/staging/bes2600/bes_nl80211_testmode_msg.h +index b70a0dd..c97c1ad 100644 +--- a/drivers/staging/bes2600/bes_nl80211_testmode_msg.h ++++ b/drivers/staging/bes2600/bes_nl80211_testmode_msg.h +@@ -1,12 +1,9 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ + /* +- * Mac80211 driver for BES2600 device ++ * Vendor testmode messages for BES2600 + * +- * Copyright (c) 2010, Bestechnic +- * Author: ++ * Copyright (c) 2022, Bestechnic (Beijing) Co., Ltd. + * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. + */ + + #ifndef BES_NL80211_TESTMODE_MSG_H +diff --git a/drivers/staging/bes2600/bes_pwr.c b/drivers/staging/bes2600/bes_pwr.c +index 620acef..a3f954b 100644 +--- a/drivers/staging/bes2600/bes_pwr.c ++++ b/drivers/staging/bes2600/bes_pwr.c +@@ -1,12 +1,9 @@ ++// SPDX-License-Identifier: GPL-2.0-only + /* +- * Mac80211 driver for BES2600 device ++ * Chip-side power state machine for BES2600 + * +- * Copyright (c) 2022, Bestechnic +- * Author: ++ * Copyright (c) 2022, Bestechnic (Beijing) Co., Ltd. + * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. + */ + #include + #include +diff --git a/drivers/staging/bes2600/bes_pwr.h b/drivers/staging/bes2600/bes_pwr.h +index 92de90b..49477b3 100644 +--- a/drivers/staging/bes2600/bes_pwr.h ++++ b/drivers/staging/bes2600/bes_pwr.h +@@ -1,12 +1,9 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ + /* +- * Mac80211 driver for BES2600 device ++ * Chip-side power state machine interface + * +- * Copyright (c) 2022, Bestechnic +- * Author: ++ * Copyright (c) 2022, Bestechnic (Beijing) Co., Ltd. + * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. + */ + #ifndef __BES_PWR_H__ + #define __BES_PWR_H__ +diff --git a/drivers/staging/bes2600/bh.c b/drivers/staging/bes2600/bh.c +index d5a8c77..0e0888e 100644 +--- a/drivers/staging/bes2600/bh.c ++++ b/drivers/staging/bes2600/bh.c +@@ -1,12 +1,12 @@ ++// SPDX-License-Identifier: GPL-2.0-only + /* +- * Mac80211 driver for BES2600 device ++ * Bottom-half thread for BES2600 mac80211 driver + * +- * Copyright (c) 2022, Bestechnic +- * Author: ++ * Copyright (c) 2010, ST-Ericsson ++ * Author: Dmitry Tarnyagin ++ * ++ * Copyright (c) 2022, Bestechnic (Beijing) Co., Ltd. + * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. + */ + #include + #include +diff --git a/drivers/staging/bes2600/bh.h b/drivers/staging/bes2600/bh.h +index 9ed08b1..700f2aa 100644 +--- a/drivers/staging/bes2600/bh.h ++++ b/drivers/staging/bes2600/bh.h +@@ -1,12 +1,12 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ + /* +- * Device handling thread interface for mac80211 BES2600 drivers ++ * Bottom-half thread interface for BES2600 mac80211 driver + * +- * Copyright (c) 2010, Bestechnic +- * Author: ++ * Copyright (c) 2010, ST-Ericsson ++ * Author: Dmitry Tarnyagin ++ * ++ * Copyright (c) 2022, Bestechnic (Beijing) Co., Ltd. + * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. + */ + + #ifndef BES2600_BH_H +diff --git a/drivers/staging/bes2600/debug.c b/drivers/staging/bes2600/debug.c +index 0d68392..47e27be 100644 +--- a/drivers/staging/bes2600/debug.c ++++ b/drivers/staging/bes2600/debug.c +@@ -1,12 +1,12 @@ ++// SPDX-License-Identifier: GPL-2.0-only + /* +- * Mac80211 driver for BES2600 device ++ * Debugging interface for BES2600 mac80211 driver + * +- * Copyright (c) 2022, Bestechnic +- * Author: ++ * Copyright (c) 2010, ST-Ericsson ++ * Author: Dmitry Tarnyagin ++ * ++ * Copyright (c) 2022, Bestechnic (Beijing) Co., Ltd. + * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. + */ + + #include +diff --git a/drivers/staging/bes2600/debug.h b/drivers/staging/bes2600/debug.h +index 3714577..5914ffc 100644 +--- a/drivers/staging/bes2600/debug.h ++++ b/drivers/staging/bes2600/debug.h +@@ -1,12 +1,12 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ + /* +- * DebugFS code for BES2600 mac80211 driver ++ * Debugging interface for BES2600 mac80211 driver + * +- * Copyright (c) 2011, Bestechnic +- * Author: ++ * Copyright (c) 2010, ST-Ericsson ++ * Author: Dmitry Tarnyagin ++ * ++ * Copyright (c) 2022, Bestechnic (Beijing) Co., Ltd. + * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. + */ + + #ifndef BES2600_DEBUG_H_INCLUDED +diff --git a/drivers/staging/bes2600/epta_coex.c b/drivers/staging/bes2600/epta_coex.c +index dfdf8e7..3ed76f1 100644 +--- a/drivers/staging/bes2600/epta_coex.c ++++ b/drivers/staging/bes2600/epta_coex.c +@@ -1,12 +1,9 @@ ++// SPDX-License-Identifier: GPL-2.0-only + /* +- * Mac80211 driver for BES2600 device ++ * BT/WiFi coexistence (ePTA) for BES2600 + * +- * Copyright (c) 2022, Bestechnic +- * Author: ++ * Copyright (c) 2022, Bestechnic (Beijing) Co., Ltd. + * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. + */ + #include + #include +diff --git a/drivers/staging/bes2600/epta_coex.h b/drivers/staging/bes2600/epta_coex.h +index bc9eed6..f8a5fea 100644 +--- a/drivers/staging/bes2600/epta_coex.h ++++ b/drivers/staging/bes2600/epta_coex.h +@@ -1,12 +1,9 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ + /* +- * Mac80211 driver for BES2600 device ++ * BT/WiFi coexistence interface for BES2600 + * +- * Copyright (c) 2022, Bestechnic +- * Author: ++ * Copyright (c) 2022, Bestechnic (Beijing) Co., Ltd. + * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. + */ + #ifndef __EPTA_COEX_H__ + #define __EPTA_COEX_H__ +diff --git a/drivers/staging/bes2600/epta_request.c b/drivers/staging/bes2600/epta_request.c +index 3b3e6af..486f02b 100644 +--- a/drivers/staging/bes2600/epta_request.c ++++ b/drivers/staging/bes2600/epta_request.c +@@ -1,12 +1,9 @@ ++// SPDX-License-Identifier: GPL-2.0-only + /* +- * Mac80211 driver for BES2600 device ++ * BT/WiFi coexistence request handling + * +- * Copyright (c) 2022, Bestechnic +- * Author: ++ * Copyright (c) 2022, Bestechnic (Beijing) Co., Ltd. + * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. + */ + #include + #include +diff --git a/drivers/staging/bes2600/epta_request.h b/drivers/staging/bes2600/epta_request.h +index f0217c2..b3d9228 100644 +--- a/drivers/staging/bes2600/epta_request.h ++++ b/drivers/staging/bes2600/epta_request.h +@@ -1,12 +1,9 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ + /* +- * Mac80211 driver for BES2600 device ++ * BT/WiFi coexistence request interface + * +- * Copyright (c) 2022, Bestechnic +- * Author: ++ * Copyright (c) 2022, Bestechnic (Beijing) Co., Ltd. + * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. + */ + #ifndef EPTA_REQUEST_H + #define EPTA_REQUEST_H +diff --git a/drivers/staging/bes2600/fwio.c b/drivers/staging/bes2600/fwio.c +index 5fe6b50..29aa2b3 100644 +--- a/drivers/staging/bes2600/fwio.c ++++ b/drivers/staging/bes2600/fwio.c +@@ -1,12 +1,12 @@ ++// SPDX-License-Identifier: GPL-2.0-only + /* +- * Mac80211 driver for BES2600 device ++ * Firmware I/O for BES2600 mac80211 driver + * +- * Copyright (c) 2022, Bestechnic +- * Author: ++ * Copyright (c) 2010, ST-Ericsson ++ * Author: Dmitry Tarnyagin ++ * ++ * Copyright (c) 2022, Bestechnic (Beijing) Co., Ltd. + * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. + */ + + #include +diff --git a/drivers/staging/bes2600/fwio.h b/drivers/staging/bes2600/fwio.h +index a4afb7a..adbd708 100644 +--- a/drivers/staging/bes2600/fwio.h ++++ b/drivers/staging/bes2600/fwio.h +@@ -1,12 +1,12 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ + /* +- * Mac80211 driver for BES2600 device ++ * Firmware I/O interface for BES2600 mac80211 driver + * +- * Copyright (c) 2022, Bestechnic +- * Author: ++ * Copyright (c) 2010, ST-Ericsson ++ * Author: Dmitry Tarnyagin ++ * ++ * Copyright (c) 2022, Bestechnic (Beijing) Co., Ltd. + * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. + */ + #ifndef FWIO_H_INCLUDED + #define FWIO_H_INCLUDED +diff --git a/drivers/staging/bes2600/ht.h b/drivers/staging/bes2600/ht.h +index b5caa29..5ac077b 100644 +--- a/drivers/staging/bes2600/ht.h ++++ b/drivers/staging/bes2600/ht.h +@@ -1,12 +1,9 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ + /* +- * HT-related code for BES2600 driver ++ * HT capability config for BES2600 + * +- * Copyright (c) 2010, Bestechnic +- * Author: ++ * Copyright (c) 2022, Bestechnic (Beijing) Co., Ltd. + * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. + */ + + #ifndef BES2600_HT_H_INCLUDED +diff --git a/drivers/staging/bes2600/hwio.c b/drivers/staging/bes2600/hwio.c +index ea88210..0934a13 100644 +--- a/drivers/staging/bes2600/hwio.c ++++ b/drivers/staging/bes2600/hwio.c +@@ -1,12 +1,12 @@ ++// SPDX-License-Identifier: GPL-2.0-only + /* +- * Low-level device IO routines for BES2600 drivers ++ * Low-level device I/O for BES2600 mac80211 driver + * +- * Copyright (c) 2022, Bestechnic +- * Author: ++ * Copyright (c) 2010, ST-Ericsson ++ * Author: Dmitry Tarnyagin ++ * ++ * Copyright (c) 2022, Bestechnic (Beijing) Co., Ltd. + * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. + */ + + #include +diff --git a/drivers/staging/bes2600/hwio.h b/drivers/staging/bes2600/hwio.h +index b9c1858..48e5215 100644 +--- a/drivers/staging/bes2600/hwio.h ++++ b/drivers/staging/bes2600/hwio.h +@@ -1,17 +1,12 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ + /* +- * Low-level API for mac80211 BES2600 drivers ++ * Low-level device I/O interface for BES2600 mac80211 driver + * +- * Copyright (c) 2010, Bestechnic +- * Author: ++ * Copyright (c) 2010, ST-Ericsson ++ * Author: Dmitry Tarnyagin + * +- * Based on: +- * UMAC BES2600 driver which is +- * Copyright (c) 2010, Bestechnic +- * Author: ++ * Copyright (c) 2022, Bestechnic (Beijing) Co., Ltd. + * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. + */ + + #ifndef BES2600_HWIO_H_INCLUDED +diff --git a/drivers/staging/bes2600/itp.c b/drivers/staging/bes2600/itp.c +index c50b29c..7cc237c 100644 +--- a/drivers/staging/bes2600/itp.c ++++ b/drivers/staging/bes2600/itp.c +@@ -1,13 +1,9 @@ ++// SPDX-License-Identifier: GPL-2.0-only + /* +- * mac80211 glue code for mac80211 BES2600 drivers +- * ITP code ++ * ITP (in-band test mode) for BES2600 + * +- * Copyright (c) 2010, Bestechnic +- * Author: ++ * Copyright (c) 2022, Bestechnic (Beijing) Co., Ltd. + * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. + */ + + #include +diff --git a/drivers/staging/bes2600/itp.h b/drivers/staging/bes2600/itp.h +index 5cfba46..bec3647 100644 +--- a/drivers/staging/bes2600/itp.h ++++ b/drivers/staging/bes2600/itp.h +@@ -1,12 +1,9 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ + /* +- * ITP code for BES2600 mac80211 driver ++ * ITP interface for BES2600 + * +- * Copyright (c) 2011, Bestechnic +- * Author: ++ * Copyright (c) 2022, Bestechnic (Beijing) Co., Ltd. + * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. + */ + + #ifndef BES2600_ITP_H_INCLUDED +diff --git a/drivers/staging/bes2600/main.c b/drivers/staging/bes2600/main.c +index 90a8ff8..19f196f 100644 +--- a/drivers/staging/bes2600/main.c ++++ b/drivers/staging/bes2600/main.c +@@ -1,12 +1,18 @@ ++// SPDX-License-Identifier: GPL-2.0-only + /* +- * Mac80211 driver for BES2600 device ++ * Main entry/init for BES2600 mac80211 driver + * +- * Copyright (c) 2022, Bestechnic +- * Author: ++ * Copyright (c) 2010, ST-Ericsson ++ * Author: Dmitry Tarnyagin ++ * ++ * Copyright (c) 2022, Bestechnic (Beijing) Co., Ltd. ++ * ++ * Based on the mac80211 Prism54 code, which is ++ * Copyright (c) 2006, Michael Wu ++ * ++ * Based on the islsm (softmac prism54) driver, which is ++ * Copyright 2004-2006 Jean-Baptiste Note , et al. + * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. + */ + + #include +diff --git a/drivers/staging/bes2600/pm.c b/drivers/staging/bes2600/pm.c +index c32c68e..0424aae 100644 +--- a/drivers/staging/bes2600/pm.c ++++ b/drivers/staging/bes2600/pm.c +@@ -1,12 +1,12 @@ ++// SPDX-License-Identifier: GPL-2.0-only + /* +- * Mac80211 power management API for BES2600 drivers ++ * Power management for BES2600 mac80211 driver + * +- * Copyright (c) 2011, Bestechnic +- * Author: ++ * Copyright (c) 2010, ST-Ericsson ++ * Author: Dmitry Tarnyagin ++ * ++ * Copyright (c) 2022, Bestechnic (Beijing) Co., Ltd. + * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. + */ + + #include +diff --git a/drivers/staging/bes2600/pm.h b/drivers/staging/bes2600/pm.h +index 0f6943e..ae70453 100644 +--- a/drivers/staging/bes2600/pm.h ++++ b/drivers/staging/bes2600/pm.h +@@ -1,12 +1,12 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ + /* +- * Mac80211 power management interface for BES2600 mac80211 drivers ++ * Power management interface for BES2600 mac80211 driver + * +- * Copyright (c) 2011, Bestechnic +- * Author: ++ * Copyright (c) 2010, ST-Ericsson ++ * Author: Dmitry Tarnyagin ++ * ++ * Copyright (c) 2022, Bestechnic (Beijing) Co., Ltd. + * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. + */ + + #ifndef PM_H_INCLUDED +diff --git a/drivers/staging/bes2600/queue.c b/drivers/staging/bes2600/queue.c +index f050df6..cc606c1 100644 +--- a/drivers/staging/bes2600/queue.c ++++ b/drivers/staging/bes2600/queue.c +@@ -1,12 +1,12 @@ ++// SPDX-License-Identifier: GPL-2.0-only + /* +- * O(1) TX queue with built-in allocator for BES2600 drivers ++ * O(1) TX queue for BES2600 mac80211 driver + * +- * Copyright (c) 2022, Bestechnic +- * Author: ++ * Copyright (c) 2010, ST-Ericsson ++ * Author: Dmitry Tarnyagin ++ * ++ * Copyright (c) 2022, Bestechnic (Beijing) Co., Ltd. + * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. + */ + + #include +diff --git a/drivers/staging/bes2600/queue.h b/drivers/staging/bes2600/queue.h +index a5395b6..94874dd 100644 +--- a/drivers/staging/bes2600/queue.h ++++ b/drivers/staging/bes2600/queue.h +@@ -1,12 +1,12 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ + /* +- * O(1) TX queue with built-in allocator for BES2600 drivers ++ * O(1) TX queue interface for BES2600 mac80211 driver + * +- * Copyright (c) 2010, Bestechnic +- * Author: ++ * Copyright (c) 2010, ST-Ericsson ++ * Author: Dmitry Tarnyagin ++ * ++ * Copyright (c) 2022, Bestechnic (Beijing) Co., Ltd. + * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. + */ + + #ifndef BES2600_QUEUE_H_INCLUDED +diff --git a/drivers/staging/bes2600/sbus.h b/drivers/staging/bes2600/sbus.h +index 96b1d4c..43c2dae 100644 +--- a/drivers/staging/bes2600/sbus.h ++++ b/drivers/staging/bes2600/sbus.h +@@ -1,12 +1,12 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ + /* +- * Common sbus abstraction layer interface for bes2600 wireless driver ++ * Bus abstraction interface for BES2600 ++ * ++ * Copyright (c) 2022, Bestechnic (Beijing) Co., Ltd. ++ * Replaces hwbus.h from drivers/net/wireless/st/cw1200/ ++ * Copyright (c) 2010, ST-Ericsson + * +- * Copyright (c) 2010, Bestechnic +- * Author: + * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. + */ + + #ifndef BES2600_SBUS_H +diff --git a/drivers/staging/bes2600/scan.c b/drivers/staging/bes2600/scan.c +index 16b5d0f..fb1d298 100644 +--- a/drivers/staging/bes2600/scan.c ++++ b/drivers/staging/bes2600/scan.c +@@ -1,12 +1,12 @@ ++// SPDX-License-Identifier: GPL-2.0-only + /* +- * Scan implementation for BES2600 mac80211 drivers ++ * Scan implementation for BES2600 mac80211 driver + * +- * Copyright (c) 2022, Bestechnic +- * Author: ++ * Copyright (c) 2010, ST-Ericsson ++ * Author: Dmitry Tarnyagin ++ * ++ * Copyright (c) 2022, Bestechnic (Beijing) Co., Ltd. + * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. + */ + + #include +diff --git a/drivers/staging/bes2600/scan.h b/drivers/staging/bes2600/scan.h +index 1f3adea..295be18 100644 +--- a/drivers/staging/bes2600/scan.h ++++ b/drivers/staging/bes2600/scan.h +@@ -1,12 +1,12 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ + /* +- * Scan interface for BES2600 mac80211 drivers ++ * Scan interface for BES2600 mac80211 driver + * +- * Copyright (c) 2010, Bestechnic +- * Author: ++ * Copyright (c) 2010, ST-Ericsson ++ * Author: Dmitry Tarnyagin ++ * ++ * Copyright (c) 2022, Bestechnic (Beijing) Co., Ltd. + * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. + */ + + #ifndef SCAN_H_INCLUDED +diff --git a/drivers/staging/bes2600/sta.c b/drivers/staging/bes2600/sta.c +index 81f88ed..bfd8ae9 100644 +--- a/drivers/staging/bes2600/sta.c ++++ b/drivers/staging/bes2600/sta.c +@@ -1,12 +1,12 @@ ++// SPDX-License-Identifier: GPL-2.0-only + /* +- * Mac80211 STA API for BES2600 drivers ++ * Mac80211 STA API for BES2600 mac80211 driver + * +- * Copyright (c) 2022, Bestechnic +- * Author: ++ * Copyright (c) 2010, ST-Ericsson ++ * Author: Dmitry Tarnyagin ++ * ++ * Copyright (c) 2022, Bestechnic (Beijing) Co., Ltd. + * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. + */ + + #include +diff --git a/drivers/staging/bes2600/sta.h b/drivers/staging/bes2600/sta.h +index e4e266c..6ea3b0f 100644 +--- a/drivers/staging/bes2600/sta.h ++++ b/drivers/staging/bes2600/sta.h +@@ -1,12 +1,12 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ + /* +- * Mac80211 STA interface for BES2600 mac80211 drivers ++ * Mac80211 STA API interface for BES2600 mac80211 driver + * +- * Copyright (c) 2010, Bestechnic +- * Author: ++ * Copyright (c) 2010, ST-Ericsson ++ * Author: Dmitry Tarnyagin ++ * ++ * Copyright (c) 2022, Bestechnic (Beijing) Co., Ltd. + * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. + */ + #include + #ifndef STA_H_INCLUDED +diff --git a/drivers/staging/bes2600/tx_loop.c b/drivers/staging/bes2600/tx_loop.c +index baab3f0..e6cf072 100644 +--- a/drivers/staging/bes2600/tx_loop.c ++++ b/drivers/staging/bes2600/tx_loop.c +@@ -1,12 +1,9 @@ ++// SPDX-License-Identifier: GPL-2.0-only + /* +- * Mac80211 driver for BES2600 device ++ * Test-mode TX loopback for BES2600 + * +- * Copyright (c) 2022, Bestechnic +- * Author: ++ * Copyright (c) 2022, Bestechnic (Beijing) Co., Ltd. + * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. + */ + #include "bes2600.h" + #include "wsm.h" +diff --git a/drivers/staging/bes2600/tx_loop.h b/drivers/staging/bes2600/tx_loop.h +index de82b30..7f42c04 100644 +--- a/drivers/staging/bes2600/tx_loop.h ++++ b/drivers/staging/bes2600/tx_loop.h +@@ -1,12 +1,9 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ + /* +- * Mac80211 driver for BES2600 device ++ * Test-mode TX loopback interface for BES2600 + * +- * Copyright (c) 2022, Bestechnic +- * Author: ++ * Copyright (c) 2022, Bestechnic (Beijing) Co., Ltd. + * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. + */ + #ifndef __TX_LOOP_H__ + #define __TX_LOOP_H__ +diff --git a/drivers/staging/bes2600/txrx.c b/drivers/staging/bes2600/txrx.c +index 346312c..7cdb7de 100644 +--- a/drivers/staging/bes2600/txrx.c ++++ b/drivers/staging/bes2600/txrx.c +@@ -1,12 +1,12 @@ ++// SPDX-License-Identifier: GPL-2.0-only + /* +- * Datapath implementation for BES2600 mac80211 drivers ++ * Datapath implementation for BES2600 mac80211 driver + * +- * Copyright (c) 2022, Bestechnic +- * Author: ++ * Copyright (c) 2010, ST-Ericsson ++ * Author: Dmitry Tarnyagin ++ * ++ * Copyright (c) 2022, Bestechnic (Beijing) Co., Ltd. + * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. + */ + + #include +diff --git a/drivers/staging/bes2600/txrx.h b/drivers/staging/bes2600/txrx.h +index cb7c192..6466c33 100644 +--- a/drivers/staging/bes2600/txrx.h ++++ b/drivers/staging/bes2600/txrx.h +@@ -1,12 +1,12 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ + /* +- * Datapath interface for BES2600 mac80211 drivers ++ * Datapath interface for BES2600 mac80211 driver + * +- * Copyright (c) 2010, Bestechnic +- * Author: ++ * Copyright (c) 2010, ST-Ericsson ++ * Author: Dmitry Tarnyagin ++ * ++ * Copyright (c) 2022, Bestechnic (Beijing) Co., Ltd. + * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. + */ + + #ifndef BES2600_TXRX_H +diff --git a/drivers/staging/bes2600/wifi_testmode_cmd.c b/drivers/staging/bes2600/wifi_testmode_cmd.c +index 2494cca..c010e8d 100644 +--- a/drivers/staging/bes2600/wifi_testmode_cmd.c ++++ b/drivers/staging/bes2600/wifi_testmode_cmd.c +@@ -1,12 +1,9 @@ ++// SPDX-License-Identifier: GPL-2.0-only + /* +- * Mac80211 driver for BES2600 device ++ * WiFi testmode commands for BES2600 + * +- * Copyright (c) 2022, Bestechnic +- * Author: ++ * Copyright (c) 2022, Bestechnic (Beijing) Co., Ltd. + * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. + */ + #ifdef CONFIG_BES2600_TESTMODE + #include +diff --git a/drivers/staging/bes2600/wsm.c b/drivers/staging/bes2600/wsm.c +index 55a4e2b..908c965 100644 +--- a/drivers/staging/bes2600/wsm.c ++++ b/drivers/staging/bes2600/wsm.c +@@ -1,13 +1,12 @@ ++// SPDX-License-Identifier: GPL-2.0-only + /* +- * WSM host interface (HI) implementation for +- * BES2600 mac80211 drivers. ++ * WSM host interface for BES2600 mac80211 driver + * +- * Copyright (c) 2022, Bestechnic +- * Author: ++ * Copyright (c) 2010, ST-Ericsson ++ * Author: Dmitry Tarnyagin ++ * ++ * Copyright (c) 2022, Bestechnic (Beijing) Co., Ltd. + * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. + */ + + #include +diff --git a/drivers/staging/bes2600/wsm.h b/drivers/staging/bes2600/wsm.h +index 22845ac..0d755a3 100644 +--- a/drivers/staging/bes2600/wsm.h ++++ b/drivers/staging/bes2600/wsm.h +@@ -1,16 +1,12 @@ ++/* SPDX-License-Identifier: GPL-2.0-only */ + /* +- * WSM host interface (HI) interface for BES2600 mac80211 drivers ++ * WSM host interface for BES2600 mac80211 driver + * +- * Copyright (c) 2022, Bestechnic +- * Author: ++ * Copyright (c) 2010, ST-Ericsson ++ * Author: Dmitry Tarnyagin + * +- * Based on BES2600 UMAC WSM API, which is +- * Copyright (C) SA 2010 +- * Author: Stewart Mathers ++ * Copyright (c) 2022, Bestechnic (Beijing) Co., Ltd. + * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. + */ + + #ifndef BES2600_WSM_H_INCLUDED +-- +2.54.0 + diff --git a/patches/driver/bes2600/lmac-recover-via-mmc-hw-reset-danctnix/0001-bes2600-recover-wedged-firmware-via-mmc_hw_reset-on-.patch b/patches/driver/bes2600/lmac-recover-via-mmc-hw-reset-danctnix/0001-bes2600-recover-wedged-firmware-via-mmc_hw_reset-on-link-break.patch similarity index 93% rename from patches/driver/bes2600/lmac-recover-via-mmc-hw-reset-danctnix/0001-bes2600-recover-wedged-firmware-via-mmc_hw_reset-on-.patch rename to patches/driver/bes2600/lmac-recover-via-mmc-hw-reset-danctnix/0001-bes2600-recover-wedged-firmware-via-mmc_hw_reset-on-link-break.patch index c6b3392..076c244 100644 --- a/patches/driver/bes2600/lmac-recover-via-mmc-hw-reset-danctnix/0001-bes2600-recover-wedged-firmware-via-mmc_hw_reset-on-.patch +++ b/patches/driver/bes2600/lmac-recover-via-mmc-hw-reset-danctnix/0001-bes2600-recover-wedged-firmware-via-mmc_hw_reset-on-link-break.patch @@ -1,8 +1,8 @@ -From 9ea8a8e810ee5eb220de700a5c0a6d1153b15130 Mon Sep 17 00:00:00 2001 +From 0dde479994a84f9e968b327d5409c3a926acb69c Mon Sep 17 00:00:00 2001 From: Markus Fritsche -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 --- - 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 3e04e8c..e5840c8 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 15602ba..3f0c59b 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 diff --git a/patches/driver/bes2600/lmac-recover-via-mmc-hw-reset-danctnix/0002-bes2600-handle-multi-function-SDIO-cards-in-mmc_hw_reset-bus_reset.patch b/patches/driver/bes2600/lmac-recover-via-mmc-hw-reset-danctnix/0002-bes2600-handle-multi-function-SDIO-cards-in-mmc_hw_reset-bus_reset.patch new file mode 100644 index 0000000..c4a387d --- /dev/null +++ b/patches/driver/bes2600/lmac-recover-via-mmc-hw-reset-danctnix/0002-bes2600-handle-multi-function-SDIO-cards-in-mmc_hw_reset-bus_reset.patch @@ -0,0 +1,83 @@ +From 80e5e68c223b676698288fde62e527b96e1ac8e2 Mon Sep 17 00:00:00 2001 +From: Markus Fritsche +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 +--- + 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 c9cb073..b998381 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 + diff --git a/patches/driver/bes2600/pm-detect-firmware-unsupported-danctnix/0001-bes2600-self-detect-when-firmware-does-not-honor-PSM.patch b/patches/driver/bes2600/pm-detect-firmware-unsupported-danctnix/0001-bes2600-self-detect-firmware-does-not-honor-PSM-skip-cycle.patch similarity index 95% rename from patches/driver/bes2600/pm-detect-firmware-unsupported-danctnix/0001-bes2600-self-detect-when-firmware-does-not-honor-PSM.patch rename to patches/driver/bes2600/pm-detect-firmware-unsupported-danctnix/0001-bes2600-self-detect-firmware-does-not-honor-PSM-skip-cycle.patch index e26b391..f662f60 100644 --- a/patches/driver/bes2600/pm-detect-firmware-unsupported-danctnix/0001-bes2600-self-detect-when-firmware-does-not-honor-PSM.patch +++ b/patches/driver/bes2600/pm-detect-firmware-unsupported-danctnix/0001-bes2600-self-detect-firmware-does-not-honor-PSM-skip-cycle.patch @@ -1,8 +1,8 @@ -From d1de35c62930b1bc035d3863d75901356548b6f0 Mon Sep 17 00:00:00 2001 +From 983bd62dd0ba9b25dfb986f39fc5a79145da6008 Mon Sep 17 00:00:00 2001 From: Markus Fritsche -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 --- - 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 diff --git a/patches/driver/bes2600/pm-gate-on-handshake/0001-bes2600-gate-device-LP-mode-entry-on-successful-per-.patch b/patches/driver/bes2600/pm-gate-on-handshake/0001-bes2600-gate-device-LP-mode-entry-on-successful-handshake.patch similarity index 91% rename from patches/driver/bes2600/pm-gate-on-handshake/0001-bes2600-gate-device-LP-mode-entry-on-successful-per-.patch rename to patches/driver/bes2600/pm-gate-on-handshake/0001-bes2600-gate-device-LP-mode-entry-on-successful-handshake.patch index a538337..49432f4 100644 --- a/patches/driver/bes2600/pm-gate-on-handshake/0001-bes2600-gate-device-LP-mode-entry-on-successful-per-.patch +++ b/patches/driver/bes2600/pm-gate-on-handshake/0001-bes2600-gate-device-LP-mode-entry-on-successful-handshake.patch @@ -1,8 +1,8 @@ -From 80178ec9b1f83aed1dcce9ea7ca02bc81341ba01 Mon Sep 17 00:00:00 2001 +From 19feb8181a75caa13442f5ac436b4014e68fe416 Mon Sep 17 00:00:00 2001 From: Markus Fritsche 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 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 diff --git a/patches/driver/bes2600/pm-state-resync-danctnix/0001-bes2600-gate-PM-indication-completion-on-pending-req.patch b/patches/driver/bes2600/pm-state-resync-danctnix/0001-bes2600-gate-PM-indication-completion-on-pending-request-and-track-state.patch similarity index 95% rename from patches/driver/bes2600/pm-state-resync-danctnix/0001-bes2600-gate-PM-indication-completion-on-pending-req.patch rename to patches/driver/bes2600/pm-state-resync-danctnix/0001-bes2600-gate-PM-indication-completion-on-pending-request-and-track-state.patch index 083ba8f..fcc8215 100644 --- a/patches/driver/bes2600/pm-state-resync-danctnix/0001-bes2600-gate-PM-indication-completion-on-pending-req.patch +++ b/patches/driver/bes2600/pm-state-resync-danctnix/0001-bes2600-gate-PM-indication-completion-on-pending-request-and-track-state.patch @@ -1,8 +1,8 @@ -From 4ab8c790304206abd134de48c878b637a70f3c59 Mon Sep 17 00:00:00 2001 +From 6168e9d34036bb6586be9ecb4f67f15401471aa0 Mon Sep 17 00:00:00 2001 From: Markus Fritsche 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 --- - 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 diff --git a/patches/driver/bes2600/pm-timeout-silence-danctnix/0001-bes2600-demote-wait-pm-ind-timeout-from-bes_err-to-b.patch b/patches/driver/bes2600/pm-timeout-silence-danctnix/0001-bes2600-demote-wait-pm-ind-timeout-from-bes_err-to-bes_devel.patch similarity index 93% rename from patches/driver/bes2600/pm-timeout-silence-danctnix/0001-bes2600-demote-wait-pm-ind-timeout-from-bes_err-to-b.patch rename to patches/driver/bes2600/pm-timeout-silence-danctnix/0001-bes2600-demote-wait-pm-ind-timeout-from-bes_err-to-bes_devel.patch index 77291f2..277a001 100644 --- a/patches/driver/bes2600/pm-timeout-silence-danctnix/0001-bes2600-demote-wait-pm-ind-timeout-from-bes_err-to-b.patch +++ b/patches/driver/bes2600/pm-timeout-silence-danctnix/0001-bes2600-demote-wait-pm-ind-timeout-from-bes_err-to-bes_devel.patch @@ -1,7 +1,7 @@ -From ab9e0ad6b4bbb1196c448ed000c8c152b0f04683 Mon Sep 17 00:00:00 2001 +From 88557185112dafbfba0053e9b5229125a97f5154 Mon Sep 17 00:00:00 2001 From: Markus Fritsche 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 diff --git a/patches/driver/bes2600/pm-wake-consume-state-danctnix/0001-bes2600-short-circuit-wake-handshake-when-chip-is-co.patch b/patches/driver/bes2600/pm-wake-consume-state-danctnix/0001-bes2600-short-circuit-wake-handshake-when-chip-confirmed-ACTIVE.patch similarity index 93% rename from patches/driver/bes2600/pm-wake-consume-state-danctnix/0001-bes2600-short-circuit-wake-handshake-when-chip-is-co.patch rename to patches/driver/bes2600/pm-wake-consume-state-danctnix/0001-bes2600-short-circuit-wake-handshake-when-chip-confirmed-ACTIVE.patch index 0655857..6c477d7 100644 --- a/patches/driver/bes2600/pm-wake-consume-state-danctnix/0001-bes2600-short-circuit-wake-handshake-when-chip-is-co.patch +++ b/patches/driver/bes2600/pm-wake-consume-state-danctnix/0001-bes2600-short-circuit-wake-handshake-when-chip-confirmed-ACTIVE.patch @@ -1,8 +1,8 @@ -From 706a594dab68779294e4fff9705a6e1df46ec1af Mon Sep 17 00:00:00 2001 +From b7c4b0fc39f498376a38279b9745a55fc2141fc3 Mon Sep 17 00:00:00 2001 From: Markus Fritsche -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 --- - 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 e5840c8..c9cb073 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 diff --git a/patches/driver/bes2600/ps-state-lock-skip-pm-disabled-danctnix/0001-bes2600-Patch-E-skip-ps_state_lock-when-PSM-known-disabled.patch b/patches/driver/bes2600/ps-state-lock-skip-pm-disabled-danctnix/0001-bes2600-Patch-E-skip-ps_state_lock-when-PSM-known-disabled.patch new file mode 100644 index 0000000..fe34fbc --- /dev/null +++ b/patches/driver/bes2600/ps-state-lock-skip-pm-disabled-danctnix/0001-bes2600-Patch-E-skip-ps_state_lock-when-PSM-known-disabled.patch @@ -0,0 +1,83 @@ +From 4be43770fd03391df66f9043280d55764e477221 Mon Sep 17 00:00:00 2001 +From: Markus Fritsche +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 84c34bc..bf17777 100644 +--- a/drivers/staging/bes2600/txrx.c ++++ b/drivers/staging/bes2600/txrx.c +@@ -1942,13 +1942,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 + diff --git a/patches/driver/bes2600/remove-chardev-user-interface/0001-bes2600-remove-userspace-dev-bes2600-character-devic.patch b/patches/driver/bes2600/remove-chardev-user-interface/0001-bes2600-remove-userspace-dev-bes2600-character-device-interface.patch similarity index 98% rename from patches/driver/bes2600/remove-chardev-user-interface/0001-bes2600-remove-userspace-dev-bes2600-character-devic.patch rename to patches/driver/bes2600/remove-chardev-user-interface/0001-bes2600-remove-userspace-dev-bes2600-character-device-interface.patch index af1d781..7c26b2c 100644 --- a/patches/driver/bes2600/remove-chardev-user-interface/0001-bes2600-remove-userspace-dev-bes2600-character-devic.patch +++ b/patches/driver/bes2600/remove-chardev-user-interface/0001-bes2600-remove-userspace-dev-bes2600-character-device-interface.patch @@ -1,7 +1,7 @@ -From f43bcc5dda0a9120aee62cce0cec1a8c851cb4ef Mon Sep 17 00:00:00 2001 +From 8539460bf141f9362daf30b927150fedd08e5717 Mon Sep 17 00:00:00 2001 From: Markus Fritsche 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 @@ -76,10 +76,10 @@ Signed-off-by: Markus Fritsche bes2600/bes_chardev.c | 519 ------------------------------------------ 1 file changed, 519 deletions(-) -diff --git 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 9038e48..e2e4f1b 100644 ---- a/bes2600/bes_chardev.c -+++ b/bes2600/bes_chardev.c +--- a/drivers/staging/bes2600/bes_chardev.c ++++ b/drivers/staging/bes2600/bes_chardev.c @@ -43,12 +43,6 @@ enum bus_probe_state { }; @@ -671,5 +671,5 @@ index 9038e48..e2e4f1b 100644 bes_devel("%s done\n", __func__); } -- -2.53.0 +2.54.0 diff --git a/patches/driver/bes2600/rx-list-batch-delivery-danctnix/0001-bes2600-Patch-C2-replace-ieee80211_rx_irqsafe-with-ieee80211_rx_ni.patch b/patches/driver/bes2600/rx-list-batch-delivery-danctnix/0001-bes2600-Patch-C2-replace-ieee80211_rx_irqsafe-with-ieee80211_rx_ni.patch new file mode 100644 index 0000000..1ce259b --- /dev/null +++ b/patches/driver/bes2600/rx-list-batch-delivery-danctnix/0001-bes2600-Patch-C2-replace-ieee80211_rx_irqsafe-with-ieee80211_rx_ni.patch @@ -0,0 +1,157 @@ +From 0ec58c0ad539e1e8d347b5527ce66cf847782338 Mon Sep 17 00:00:00 2001 +From: Markus Fritsche +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/sta.c | 2 +- + bes2600/txrx.c | 6 +++--- + bes2600/wsm.c | 2 +- + 4 files changed, 18 insertions(+), 7 deletions(-) + +diff --git a/drivers/staging/bes2600/ap.c b/drivers/staging/bes2600/ap.c +index 0a23790..6d4428c 100644 +--- a/drivers/staging/bes2600/ap.c ++++ b/drivers/staging/bes2600/ap.c +@@ -62,8 +62,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 +@@ -92,9 +95,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/sta.c b/drivers/staging/bes2600/sta.c +index 7caeb4b..e64841a 100644 +--- a/drivers/staging/bes2600/sta.c ++++ b/drivers/staging/bes2600/sta.c +@@ -1484,7 +1484,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 bf17777..de521a3 100644 +--- a/drivers/staging/bes2600/txrx.c ++++ b/drivers/staging/bes2600/txrx.c +@@ -1957,18 +1957,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 + diff --git a/patches/driver/bes2600/scan-defer-backoff-tune-danctnix/0001-bes2600-widen-scan-defer-backoff-to-30s-and-decay-co.patch b/patches/driver/bes2600/scan-defer-backoff-tune-danctnix/0001-bes2600-widen-scan-defer-backoff-30s-and-decay-on-quiet.patch similarity index 94% rename from patches/driver/bes2600/scan-defer-backoff-tune-danctnix/0001-bes2600-widen-scan-defer-backoff-to-30s-and-decay-co.patch rename to patches/driver/bes2600/scan-defer-backoff-tune-danctnix/0001-bes2600-widen-scan-defer-backoff-30s-and-decay-on-quiet.patch index 0d4c7d3..aa52c85 100644 --- a/patches/driver/bes2600/scan-defer-backoff-tune-danctnix/0001-bes2600-widen-scan-defer-backoff-to-30s-and-decay-co.patch +++ b/patches/driver/bes2600/scan-defer-backoff-tune-danctnix/0001-bes2600-widen-scan-defer-backoff-30s-and-decay-on-quiet.patch @@ -1,8 +1,8 @@ -From 3d98404c1a85ef33e9fc1422042c71dc90f3b255 Mon Sep 17 00:00:00 2001 +From 8fc1bacdeda64feb751433ee827dc9647e23bee4 Mon Sep 17 00:00:00 2001 From: Markus Fritsche 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 --- - 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 faa1c90..ad5033b 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 diff --git a/patches/driver/bes2600/scan-defer-on-reject-danctnix/0001-bes2600-defer-scan-and-soften-WARN-on-firmware-rejec.patch b/patches/driver/bes2600/scan-defer-on-reject-danctnix/0001-bes2600-defer-scan-and-soften-WARN-on-firmware-reject.patch similarity index 98% rename from patches/driver/bes2600/scan-defer-on-reject-danctnix/0001-bes2600-defer-scan-and-soften-WARN-on-firmware-rejec.patch rename to patches/driver/bes2600/scan-defer-on-reject-danctnix/0001-bes2600-defer-scan-and-soften-WARN-on-firmware-reject.patch index 20b93b0..d0c374f 100644 --- a/patches/driver/bes2600/scan-defer-on-reject-danctnix/0001-bes2600-defer-scan-and-soften-WARN-on-firmware-rejec.patch +++ b/patches/driver/bes2600/scan-defer-on-reject-danctnix/0001-bes2600-defer-scan-and-soften-WARN-on-firmware-reject.patch @@ -1,7 +1,7 @@ -From adc6c1f332d41ee1aadd349eea11809c88139307 Mon Sep 17 00:00:00 2001 +From aff632ea648092aabee6b735819152d4a09ec95e Mon Sep 17 00:00:00 2001 From: Markus Fritsche 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 @@ -222,5 +222,5 @@ index d40df30..55a4e2b 100644 underflow: -- -2.53.0 +2.54.0 diff --git a/patches/driver/bes2600/sdio-rx-no-relay-danctnix/0001-bes2600-drop-sdio_rx_work-relay-IRQ-bh-direct-no-relay-architecture.patch b/patches/driver/bes2600/sdio-rx-no-relay-danctnix/0001-bes2600-drop-sdio_rx_work-relay-IRQ-bh-direct-no-relay-architecture.patch new file mode 100644 index 0000000..67f7698 --- /dev/null +++ b/patches/driver/bes2600/sdio-rx-no-relay-danctnix/0001-bes2600-drop-sdio_rx_work-relay-IRQ-bh-direct-no-relay-architecture.patch @@ -0,0 +1,540 @@ +From 1e9eb4581f113aa6cca2d0de325f9b61b80ebbee Mon Sep 17 00:00:00 2001 +From: Markus Fritsche +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 b998381..b6b4e4e 100644 +--- a/drivers/staging/bes2600/bes2600_sdio.c ++++ b/drivers/staging/bes2600/bes2600_sdio.c +@@ -29,6 +29,7 @@ + #include + + #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); + } +@@ -2244,8 +2264,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 1d2773c..d5a8c77 100644 +--- a/drivers/staging/bes2600/bh.c ++++ b/drivers/staging/bes2600/bh.c +@@ -958,6 +958,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; +@@ -969,10 +1082,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 + diff --git a/patches/driver/bes2600/tx-sdio-dma-oob-danctnix/0001-bes2600-bounce-SDIO-TX-buffers-to-avoid-DMA-OOB-read.patch b/patches/driver/bes2600/tx-sdio-dma-oob-danctnix/0001-bes2600-bounce-SDIO-TX-buffers-to-avoid-DMA-OOB-read.patch index 0db0eed..0e5866d 100644 --- a/patches/driver/bes2600/tx-sdio-dma-oob-danctnix/0001-bes2600-bounce-SDIO-TX-buffers-to-avoid-DMA-OOB-read.patch +++ b/patches/driver/bes2600/tx-sdio-dma-oob-danctnix/0001-bes2600-bounce-SDIO-TX-buffers-to-avoid-DMA-OOB-read.patch @@ -1,7 +1,7 @@ -From 4ec7d25817af09654fb9439e472890f69281840c Mon Sep 17 00:00:00 2001 +From 315986ea27e7508275e71a070461d243ce1a1058 Mon Sep 17 00:00:00 2001 From: Markus Fritsche 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 --- - 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 371ef4f..3e04e8c 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) +@@ -1985,6 +2016,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