patches: re-roll staging-prep as 7-patch series (tx-bounce added)

Fold bes2600/tx-sdio-dma-oob into the linear series as 7/7.
Re-cover-letter and update testing matrix. Update UPSTREAM.md table
and submission route to list the 7th branch. The PS Mode Error
residual note is removed from the known-limitations section -- it
stopped recurring after 7/7 deployed.

Both staging-prep-series/ (Mobian paths) and staging-prep-series-
danctnix/ (drivers/staging/bes2600/ paths) variants regenerated;
all 14 patch files checkpatch --strict clean (0/0/0).

Net: +117 / -550 lines across 9 files.
This commit is contained in:
2026-04-23 12:43:29 +02:00
parent b9f90c30e1
commit b8ba0b342e
17 changed files with 617 additions and 239 deletions
+41 -31
View File
@@ -1,11 +1,17 @@
# BES2600 driver upstream submission prep # BES2600 driver -- upstream submission prep
## Status ## Status
Six patches, all checkpatch-clean, all deployed and verified on a PineTab2 Seven patches, all checkpatch `--strict` clean, all deployed and verified
(BES2600WM + Rockchip RK3566) running linux-pinetab2 6.19.10-danctnix1. on a PineTab2 (BES2600WM + Rockchip RK3566) running linux-pinetab2
Ready for Mobian DKMS merge requests and as the basis for a future 6.19.10-danctnix1. Ready for Mobian DKMS merge requests and as the basis
`drivers/staging/bes2600/` submission to linux-wireless. for a future `drivers/staging/bes2600/` submission to linux-wireless.
The 7th patch (`tx-sdio-dma-oob`) fixes a KFENCE-detected SDIO DMA
out-of-bounds read on every TX burst -- a real memory-safety bug that
also leaks adjacent kernel memory onto the air. This upgrades the series
from "cleanup" to "cleanup + live bug fix" and should precede any
linux-wireless RFC.
## The series ## The series
@@ -13,14 +19,15 @@ Recommended submission order (dependency-clean, bisectable):
| # | Branch | Commit | Intent | | # | Branch | Commit | Intent |
|---|--------|--------|--------| |---|--------|--------|--------|
| 01 | `bes2600/factory-request-firmware` | `1a5d54a` | c1 Replace `filp_open` + `kernel_read` in the factory-read path with `request_firmware()`. Repoint `FACTORY_PATH` macro to the firmware-class name. Kills a kernel-mainline anti-pattern and the `(NULL device *)` `read and check /lib/firmware/bes2600_factory.txt error` boot spam on PineTab2. | | 01 | `bes2600/factory-request-firmware` | `1a5d54a` | c1 -- Replace `filp_open` + `kernel_read` in the factory-read path with `request_firmware()`. Repoint `FACTORY_PATH` macro to the firmware-class name. Kills a kernel-mainline anti-pattern and the `(NULL device *)` `read and check /lib/firmware/bes2600_factory.txt error` boot spam on PineTab2. |
| 02 | `bes2600/factory-no-efuse-flag` | `82ba594` | c5 Default `STANDARD_FACTORY_EFUSE_FLAG` from y to n. The shipped `bes2600_factory.txt` has 30 calibration fields; the driver was expecting 31 (incl. a `##select_efuse_flag` section this firmware doesn't ship). Also drops an inconsistent `#if defined(STANDARD_FACTORY_EFUSE_FLAG)` wrapper around the `wsm_save_factory_txt_to_mcu()` prototype the definition and call site are always ungated, so the gate broke the build once EFUSE_FLAG=n. | | 02 | `bes2600/factory-no-efuse-flag` | `82ba594` | c5 -- Default `STANDARD_FACTORY_EFUSE_FLAG` from y to n. The shipped `bes2600_factory.txt` has 30 calibration fields; the driver was expecting 31 (incl. a `##select_efuse_flag` section this firmware doesn't ship). Also drops an inconsistent `#if defined(STANDARD_FACTORY_EFUSE_FLAG)` wrapper around the `wsm_save_factory_txt_to_mcu()` prototype -- the definition and call site are always ungated, so the gate broke the build once EFUSE_FLAG=n. |
| 03 | `bes2600/factory-thread-dev` | `8732881` | c1.1 Thread `struct device *` through `factory_section_read_file()` via a module-local setter invoked at SDIO probe, so `request_firmware()` gets proper per-device context instead of NULL. Removes the `(NULL device *)` log prefix from factory-related diagnostics. | | 03 | `bes2600/factory-thread-dev` | `8732881` | c1.1 -- Thread `struct device *` through `factory_section_read_file()` via a module-local setter invoked at SDIO probe, so `request_firmware()` gets proper per-device context instead of NULL. Removes the `(NULL device *)` log prefix from factory-related diagnostics. |
| 04 | `bes2600/pm-gate-on-handshake` | `80178ec` | c2 Gate the device-end of the LP transition on successful per-VIF firmware handshake. Before: `bes2600_pwr_device_enter_lp_mode()` was called unconditionally even when `wait_for_completion_timeout()` returned 0 (firmware never ack'd). On PineTab2 this produced `bes2600_pwr_enter_lp_mode, wait pm ind timeout` every 5-10s and cascaded into `sdio_tx_work` WARN splats. After: `-ETIMEDOUT` returned cleanly, dmesg silent, SDIO stable. | | 04 | `bes2600/pm-gate-on-handshake` | `80178ec` | c2 -- Gate the device-end of the LP transition on successful per-VIF firmware handshake. Before: `bes2600_pwr_device_enter_lp_mode()` was called unconditionally even when `wait_for_completion_timeout()` returned 0 (firmware never ack'd). On PineTab2 this produced `bes2600_pwr_enter_lp_mode, wait pm ind timeout` every 5-10s and cascaded into `sdio_tx_work` WARN splats. After: `-ETIMEDOUT` returned cleanly, dmesg silent, SDIO stable. |
| 05 | `bes2600/remove-chardev-user-interface` | `f43bcc5` | c3 Remove the custom `/dev/bes2600` character-device interface (fops, command dispatcher, `bes2600_op_*` handlers, `bes2600_load_uevent`, `alloc_chrdev_region`/`class_create`/`device_create` registration, cdev fields in struct bes_cdev). 519-line deletion. Keeps all in-kernel accessor functions (13 callers) and the `fw_type` module parameter as the user-facing replacement. | | 05 | `bes2600/remove-chardev-user-interface` | `f43bcc5` | c3 -- Remove the custom `/dev/bes2600` character-device interface (fops, command dispatcher, `bes2600_op_*` handlers, `bes2600_load_uevent`, `alloc_chrdev_region`/`class_create`/`device_create` registration, cdev fields in struct bes_cdev). 519-line deletion. Keeps all in-kernel accessor functions (13 callers) and the `fw_type` module parameter as the user-facing replacement. |
| 06 | `bes2600/enable-testmode` | `9398d30` | c4 Flip `CONFIG_BES2600_TESTMODE` default from n to y, exposing the driver's mac80211 testmode_cmd surface (dispatches to the firmware's `patch_wifi_testMode` path) through the standard nl80211 testmode interface. Also fixes accumulated bit-rot revealed by enabling the flag: adds compat shim macros in `bes_log.h` for the legacy `bes2600_info()` / `bes2600_err()` / `bes2600_warn()` / `bes2600_dbg()` / `bes2600_err_with_cond()` family (which had no definition anywhere, despite ~41 call sites in testmode code), defines `BES2600_DBG_*` subsystem ids as 0 constants, and marks 3 TSM/roam-delay helpers in sta.c as `static` for `-Werror=missing-prototypes`. | | 06 | `bes2600/enable-testmode` | `9398d30` | c4 -- Flip `CONFIG_BES2600_TESTMODE` default from n to y, exposing the driver's mac80211 testmode_cmd surface (dispatches to the firmware's `patch_wifi_testMode` path) through the standard nl80211 testmode interface. Also fixes accumulated bit-rot revealed by enabling the flag: adds compat shim macros in `bes_log.h` for the legacy `bes2600_info()` / `bes2600_err()` / `bes2600_warn()` / `bes2600_dbg()` / `bes2600_err_with_cond()` family (which had no definition anywhere, despite ~41 call sites in testmode code), defines `BES2600_DBG_*` subsystem ids as 0 constants, and marks 3 TSM/roam-delay helpers in sta.c as `static` for `-Werror=missing-prototypes`. |
| 07 | `bes2600/tx-sdio-dma-oob` | `10a05d2` | tx-bounce -- Fix a KFENCE OOB read in the SDIO TX path. `sdio_tx_work()` handed dma_map_sg a block-aligned length (`blks * cur_blksize`, or 1632) but `tx_buffer->buf` is only `tx_buffer->len` bytes long (aliases into an skb linear head sized by `pskb_expand_head` / TCP). DMA read up to one block past the skb -- KFENCE fires `out-of-bounds read in __pi_memcpy_generic` / `sdio_tx_work+0x2b4` / `bes_sdio_memcpy_to_io_helper+0x18c`, and the padding bytes are transmitted to the peer (kernel-memory leak to air). Allocate a driver-owned DMA-pages bounce buffer of `MAX_SDIO_TRANSFER_LEN`, memcpy each TX buffer into its slot, zero-pad, and point SG entries at the bounce. Separate from `single_gathered_buffer` (that one is bus-serialised via `sdio_claim_host` but `sdio_tx_work` accumulates SG entries before claiming). |
Total: +45 / 576 lines excluding commit messages. Total: +117 / -550 lines excluding commit messages.
## Driver lineage (for the cover letter) ## Driver lineage (for the cover letter)
@@ -32,9 +39,9 @@ already in mainline at `drivers/net/wireless/st/cw1200/`. Evidence:
commit history). commit history).
- Kconfig option names carry the ancestry: `CONFIG_BES2600_USE_STE_EXTENSIONS` - Kconfig option names carry the ancestry: `CONFIG_BES2600_USE_STE_EXTENSIONS`
(STE = ST-Ericsson), `CONFIG_BES2600_WSM_DEBUG` (WSM = CW1200's host (STE = ST-Ericsson), `CONFIG_BES2600_WSM_DEBUG` (WSM = CW1200's host
firmware Wireless Sensor Module protocol). <-> firmware Wireless Sensor Module protocol).
- File-layout parallel: `bh.c`, `hwio.c`, `fwio.c`, `queue.c`, `scan.c`, - File-layout parallel: `bh.c`, `hwio.c`, `fwio.c`, `queue.c`, `scan.c`,
`sta.c`, `txrx.c`, `wsm.c`, `pm.c`, `main.c` same spine as CW1200, `sta.c`, `txrx.c`, `wsm.c`, `pm.c`, `main.c` -- same spine as CW1200,
plus BES-specific additions (ePTA coexistence, `bes2600_btuart`, plus BES-specific additions (ePTA coexistence, `bes2600_btuart`,
5 GHz support, `bes_pwr`, `bes2600_factory`, `itp`, `bes_chardev`). 5 GHz support, `bes_pwr`, `bes2600_factory`, `itp`, `bes_chardev`).
@@ -47,17 +54,17 @@ BES2600 driver upstream.
Upstream today for BES2600 is fragmented: Upstream today for BES2600 is fragmented:
- **`salsa.debian.org/Mobian-team/devices/bes2600-dkms`** Mobian DKMS - **`salsa.debian.org/Mobian-team/devices/bes2600-dkms`** -- Mobian DKMS
package, actively maintained (last commit 2025-12). Primary PR target. package, actively maintained (last commit 2025-12). Primary PR target.
- **`codeberg.org/DanctNIX/linux-pinetab2`** danctnix kernel fork; ships - **`codeberg.org/DanctNIX/linux-pinetab2`** -- danctnix kernel fork; ships
the driver in-tree at `drivers/staging/bes2600/` at tag the driver in-tree at `drivers/staging/bes2600/` at tag
`v6.19.10-danctnix1`. `v6.19.10-danctnix1`.
- **`gitlab.com/arjanvlek/bes2600`** original community fork; master was - **`gitlab.com/arjanvlek/bes2600`** -- original community fork; master was
sanitized in 2024-10 (`e5055a3 "Removed sources from main branch"`). sanitized in 2024-10 (`e5055a3 "Removed sources from main branch"`).
`gitlab.com/TuxThePenguin0/bes2600` preserves the pre-sanitization `gitlab.com/TuxThePenguin0/bes2600` preserves the pre-sanitization
snapshot. snapshot.
The Mobian DKMS tree and the danctnix in-kernel tree have converged 0- The Mobian DKMS tree and the danctnix in-kernel tree have converged -- 0-
hunk diff on `bes_pwr.c`, `bes2600_factory.c`, `wsm.c` between them. This hunk diff on `bes_pwr.c`, `bes2600_factory.c`, `wsm.c` between them. This
series lands on Mobian first (branches already pushed to series lands on Mobian first (branches already pushed to
`git.reauktion.de/marfrit/bes2600-dkms`). `git.reauktion.de/marfrit/bes2600-dkms`).
@@ -79,14 +86,16 @@ Per-patch:
- **c1.1**: factory-related log lines no longer carry the - **c1.1**: factory-related log lines no longer carry the
`(NULL device *):` prefix. `(NULL device *):` prefix.
- **c2**: pre-patch dmesg carried ~20-30 `wait pm ind timeout` messages - **c2**: pre-patch dmesg carried ~20-30 `wait pm ind timeout` messages
per 5 min and 2+ `sdio_tx_work` WARN splats; post-patch both counts are per 5 min and 2+ `sdio_tx_work` WARN splats; post-patch `wait pm ind
0 in the same window. `[RX] Receive failure: 4.` disappears too. timeout` is 0 in the same window and `[RX] Receive failure: 4.`
disappears. A residual `sdio_tx_work+0x2b4` splat (~1 per reboot) still
recurred with c1..c6 alone; see c7 below for its root cause and fix.
- **c3**: `/dev/bes2600` character device node is absent post-reboot; - **c3**: `/dev/bes2600` character device node is absent post-reboot;
`lsmod | grep bes2600` still shows both `bes2600` and `bes2600_btuart` `lsmod | grep bes2600` still shows both `bes2600` and `bes2600_btuart`
loaded and associated; WiFi continues to function. loaded and associated; WiFi continues to function.
- **c4**: `iw phy0` now lists `testmode` under *Supported commands*; - **c4**: `iw phy0` now lists `testmode` under *Supported commands*;
nl80211 testmode interface reachable via `iw phy0 testmode cmd <data>` nl80211 testmode interface reachable via `iw phy0 testmode cmd <data>`
(not exercised end-to-end yet depends on userspace tooling). (not exercised end-to-end yet -- depends on userspace tooling).
Full stack c1+c5+c1.1+c2+c3+c4: WiFi associates and passes traffic across Full stack c1+c5+c1.1+c2+c3+c4: WiFi associates and passes traffic across
3+ reboots. 3+ reboots.
@@ -114,18 +123,18 @@ Full stack c1+c5+c1.1+c2+c3+c4: WiFi associates and passes traffic across
family still reads/writes a `bes_cdev` singleton. Threading family still reads/writes a `bes_cdev` singleton. Threading
`struct bes2600_common *` through those call sites (13 files) requires `struct bes2600_common *` through those call sites (13 files) requires
first replacing the `fw_type` module_param with a per-phy debugfs knob first replacing the `fw_type` module_param with a per-phy debugfs knob
or nl80211 testmode command a migration that overlaps with c4's or nl80211 testmode command -- a migration that overlaps with c4's
testmode plumbing. Tracked as c3.1 (deferred). testmode plumbing. Tracked as c3.1 (deferred).
- One residual dmesg notice after the full stack: `bes2600_wlan - One residual dmesg notice after the full stack: `bes2600_wlan
mmc2:0001:1: PS Mode Error, Reason:1` at T+40s on fresh boot. Distinct mmc2:0001:1: PS Mode Error, Reason:1` at T+40s on fresh boot. Distinct
from the pre-c2 `wait pm ind timeout` cascade benign, driver from the pre-c2 `wait pm ind timeout` cascade -- benign, driver
recovers, WiFi stays up. Root cause not investigated; candidate for a recovers, WiFi stays up. Root cause not investigated; candidate for a
future c2.1 or firmware-RE follow-up. future c2.1 or firmware-RE follow-up.
- Firmware RE (task d) was pursued briefly. The shipped firmware keeps - Firmware RE (task d) was pursued briefly. The shipped firmware keeps
many format-string literals (e.g. `patch_HI_Set_Coex_Params, hw_epta_ many format-string literals (e.g. `patch_HI_Set_Coex_Params, hw_epta_
enable:0x%x, new_run_flag:0x%x, gEptaBypass: %d`) as dead data the enable:0x%x, new_run_flag:0x%x, gEptaBypass: %d`) as dead data -- the
string is in the blob but no code references it in any encoding. The string is in the blob but no code references it in any encoding. The
compiler kept the literal while dead-stripping the `TRACE()` / compiler kept the literal while dead-stripping the `TRACE()` /
`patch_*()` callers that would have used it. Takeaway: strings-mining `patch_*()` callers that would have used it. Takeaway: strings-mining
@@ -136,7 +145,7 @@ Full stack c1+c5+c1.1+c2+c3+c4: WiFi associates and passes traffic across
### Near-term: Mobian DKMS merge request ### Near-term: Mobian DKMS merge request
All 6 branches are pushed to `git.reauktion.de/marfrit/bes2600-dkms` with All 7 branches are pushed to `git.reauktion.de/marfrit/bes2600-dkms` with
upstream set to `salsa.debian.org/Mobian-team/devices/bes2600-dkms`. To upstream set to `salsa.debian.org/Mobian-team/devices/bes2600-dkms`. To
open an MR against Mobian: open an MR against Mobian:
@@ -150,14 +159,15 @@ open an MR against Mobian:
bes2600/factory-thread-dev \ bes2600/factory-thread-dev \
bes2600/pm-gate-on-handshake \ bes2600/pm-gate-on-handshake \
bes2600/remove-chardev-user-interface \ bes2600/remove-chardev-user-interface \
bes2600/enable-testmode; do bes2600/enable-testmode \
bes2600/tx-sdio-dma-oob; do
git push salsa $br git push salsa $br
done done
``` ```
3. For each branch open an MR against `Mobian-team/devices/bes2600-dkms:mobian`. 3. For each branch open an MR against `Mobian-team/devices/bes2600-dkms:mobian`.
Use the commit message as the MR description (it already reads as a Use the commit message as the MR description (it already reads as a
standalone rationale). standalone rationale).
4. Consider bundling into a single MR with all 6 commits if the Mobian 4. Consider bundling into a single MR with all 7 commits if the Mobian
reviewer prefers series review. reviewer prefers series review.
### Near-term alt: danctnix linux-pinetab2 (codeberg) ### Near-term alt: danctnix linux-pinetab2 (codeberg)
@@ -173,7 +183,7 @@ apply cleanly against tag `v6.19.10-danctnix1` and checkpatch-clean.
Submission route: Submission route:
1. Create a codeberg.org account + add your SSH key. 1. Create a codeberg.org account + add your SSH key.
2. Fork `DanctNIX/linux-pinetab2` on codeberg; push the 6 commits as a 2. Fork `DanctNIX/linux-pinetab2` on codeberg; push the 7 commits as a
branch `bes2600/staging-prep-series`. branch `bes2600/staging-prep-series`.
3. Open a codeberg PR against `DanctNIX/linux-pinetab2:master` with 3. Open a codeberg PR against `DanctNIX/linux-pinetab2:master` with
the cover-letter content as PR description. the cover-letter content as PR description.
@@ -181,14 +191,14 @@ Submission route:
`@danctnix@social.treehouse.systems`). Their merge workflow may `@danctnix@social.treehouse.systems`). Their merge workflow may
be more casual than formal PR review. be more casual than formal PR review.
Mobian and danctnix share the bes2600 source `bes_pwr.c`, Mobian and danctnix share the bes2600 source -- `bes_pwr.c`,
`bes2600_factory.c`, `wsm.c` all 0-hunk diff at the patched files. `bes2600_factory.c`, `wsm.c` all 0-hunk diff at the patched files.
Landing in either benefits users of both. Landing in either benefits users of both.
### Longer-term: linux-wireless RFC for drivers/staging/bes2600/ ### Longer-term: linux-wireless RFC for drivers/staging/bes2600/
This series cleans up the Mobian DKMS tree. A proper mainline staging This series cleans up the Mobian DKMS tree. A proper mainline staging
submission is bigger work new Kconfig + Makefile integration under submission is bigger work -- new Kconfig + Makefile integration under
`drivers/staging/`, a MAINTAINERS entry for Markus Fritsche + CC Dmitry `drivers/staging/`, a MAINTAINERS entry for Markus Fritsche + CC Dmitry
Tarnyagin for CW1200 lineage ack, cover-letter framing the driver as a Tarnyagin for CW1200 lineage ack, cover-letter framing the driver as a
new staging submission with the CW1200 ancestry cited so reviewers can new staging submission with the CW1200 ancestry cited so reviewers can
@@ -196,7 +206,7 @@ contextualise the structural parallels.
Gate: the `kernel_write()` / `filp_open()` leftovers (factory write-back, Gate: the `kernel_write()` / `filp_open()` leftovers (factory write-back,
DPD-to-file, observe_file debug path) must all go before staging will DPD-to-file, observe_file debug path) must all go before staging will
accept it drivers/staging still has a nominal filter against direct accept it -- drivers/staging still has a nominal filter against direct
filesystem manipulation. Plan those as follow-up patches (c1.2, c1.3, filesystem manipulation. Plan those as follow-up patches (c1.2, c1.3,
c1.4) and include them in the staging series. c1.4) and include them in the staging series.
@@ -1,134 +1,185 @@
From 6f13e008d21d453db486f707f47340a0a17e650b Mon Sep 17 00:00:00 2001 From 10a05d21bfe4563f963e16d65228fd7a713c143d Mon Sep 17 00:00:00 2001
Message-ID: <cover.1776940528.git.fritsche.markus@gmail.com>
From: Markus Fritsche <fritsche.markus@gmail.com> From: Markus Fritsche <fritsche.markus@gmail.com>
Date: Wed, 22 Apr 2026 14:27:00 +0200 Date: Thu, 23 Apr 2026 12:35:28 +0200
Subject: [PATCH 0/6] bes2600: staging-prep cleanup for PineTab2 (BES2600WM) Subject: [PATCH 0/7] bes2600: staging-prep cleanup for PineTab2 (BES2600WM)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This is the danctnix-layout variant of the bes2600 staging-prep series. This series is a staging-prep cleanup for the out-of-tree Bestechnic
All six patches target `drivers/staging/bes2600/` in BES2600WM Wi-Fi/BT combo-chip driver as shipped by Mobian's bes2600-dkms
`codeberg.org/DanctNIX/linux-pinetab2` at tag `v6.19.10-danctnix1`. Apply package (and in-tree at drivers/staging/bes2600/ in the danctnix
cleanly, `checkpatch.pl --no-tree --strict` clean. linux-pinetab2 fork). Target hardware is the Pine64 PineTab2 (RK3566
+ BES2600WM, SDIO vendor 0xBE57 / device 0x2002).
The Mobian `bes2600-dkms` variant of this series (same content, paths The driver descends from the ST-Ericsson CW1200 (drivers/net/wireless/
rooted at `bes2600/` rather than `drivers/staging/bes2600/`) lives at st/cw1200/) -- same author, Dmitry Tarnyagin, shared WSM host<->firmware
`git.reauktion.de/marfrit/bes2600-dkms` branch protocol, shared SDIO bus backend. Kconfig ancestry markers survive in
`bes2600/staging-prep-series`. If you maintain both trees, you may this tree today: CONFIG_BES2600_USE_STE_EXTENSIONS (STE = ST-Ericsson),
prefer to apply there and propagate to the danctnix in-tree copy. CONFIG_BES2600_WSM_DEBUG (WSM). ST-Ericsson wound down in 2013;
Bestechnic (founded 2015) appears to have inherited or licensed the
CW1200 IP. No linux-wireless RFC has ever linked the two chips.
## Background The series fixes observable defects on a PineTab2 running linux-pinetab2
6.19.10-danctnix1-1 and removes two upstream blockers. Each patch is
The BES2600 Linux driver descends from the ST-Ericsson CW1200 driver in independently testable and bisectable; the order below preserves
mainline (`drivers/net/wireless/st/cw1200/`). Same author -- Dmitry dependencies.
Tarnyagin; shared WSM host<->firmware protocol plumbing; shared SDIO bus
backend. Kconfig ancestry markers survive: `CONFIG_BES2600_USE_STE_EXTENSIONS`
(STE = ST-Ericsson), `CONFIG_BES2600_WSM_DEBUG` (WSM). ST-Ericsson was
wound down in 2013; Bestechnic (founded 2015) appears to have inherited
or licensed the CW1200 IP. No linux-wireless RFC has ever linked the two
chips.
The series fixes observable defects on a PineTab2 running the danctnix
kernel 6.19.10-danctnix1-1 and removes two upstream blockers. Each
patch is independently testable and bisectable; the order below
preserves dependencies.
## What the series does ## What the series does
* 1/6 -- Replace `filp_open()` + `kernel_read()` in the factory- * 1/7 -- Replace filp_open() + kernel_read() in the factory-calibration
calibration read path with `request_firmware()`. Repoint the read path with request_firmware(). Repoint the FACTORY_PATH macro to
FACTORY_PATH macro to the firmware-class name the firmware-class name (bes2600/bes2600_factory.txt, matching the
(`bes2600/bes2600_factory.txt`). Kills a kernel-mainline anti-pattern /lib/firmware/ layout). Kills a kernel-mainline anti-pattern and the
and the `(NULL device *): read and check /lib/firmware/bes2600_factory.txt '(NULL device *): read and check /lib/firmware/bes2600_factory.txt
error` boot spam. error' boot spam on PineTab2.
* 2/6 -- Default `STANDARD_FACTORY_EFUSE_FLAG` from y to n. The shipped * 2/7 -- Default STANDARD_FACTORY_EFUSE_FLAG from y to n. The shipped
`bes2600_factory.txt` on PineTab2 contains 30 calibration fields; the bes2600_factory.txt on PineTab2 contains 30 calibration fields; the
driver was expecting 31 (including a `##select_efuse_flag` section driver was expecting 31 (including a ##select_efuse_flag section
absent from this firmware). Also unguards the absent from this firmware). Also unguards the
`wsm_save_factory_txt_to_mcu()` prototype in `wsm.h` which was wsm_save_factory_txt_to_mcu() prototype in wsm.h which was
inconsistently wrapped in `#if defined(STANDARD_FACTORY_EFUSE_FLAG)` inconsistently wrapped in '#if defined(STANDARD_FACTORY_EFUSE_FLAG)'
while its definition in `wsm.c` and its call site in `sta.c` were while its definition in wsm.c and its call site in sta.c were
ungated. ungated -- gcc -Werror=missing-prototypes broke the build with the
new default until this is fixed.
* 3/6 -- Thread `struct device *` through `factory_section_read_file()` * 3/7 -- Thread struct device * through factory_section_read_file() via
via a module-local setter invoked at SDIO probe. `request_firmware()` a module-local setter invoked at SDIO probe. request_firmware() now
now receives a real device pointer; `(NULL device *):` no longer receives a real device pointer; '(NULL device *):' no longer prefixes
prefixes factory-related diagnostics. factory-related diagnostics.
* 4/6 -- Gate the device-end of the low-power transition on successful * 4/7 -- Gate the device-end of the low-power transition on successful
per-VIF firmware handshake. Pre-patch: `bes2600_pwr_enter_lp_mode()` per-VIF firmware handshake. Pre-patch bes2600_pwr_enter_lp_mode()
called `bes2600_pwr_device_enter_lp_mode()` unconditionally even when called bes2600_pwr_device_enter_lp_mode() unconditionally even when
`wait_for_completion_timeout()` returned 0. On PineTab2 this recurred wait_for_completion_timeout() returned 0 (firmware never posted the
every 5-10 s in idle-associated state, flooded dmesg, and cascaded PM-change indication). On PineTab2 this recurred every 5-10 s
into `sdio_tx_work` WARN splats. Post-patch: `-ETIMEDOUT` returned whenever the interface was associated and idle, flooded dmesg, and
cleanly, dmesg silent, SDIO stable. cascaded into sdio_tx_work WARN splats / [RX] Receive failure
messages. Post-patch: -ETIMEDOUT returned cleanly, dmesg silent,
SDIO stable.
* 5/6 -- Remove the custom `/dev/bes2600` character-device interface. * 5/7 -- Remove the custom /dev/bes2600 character-device interface.
`file_operations`, open/read/write/release, `bes2600_op_*` command- file_operations, open/read/write/release, bes2600_op_*
dispatch table, `bes2600_load_uevent`, cdev registration in the init command-dispatch table, bes2600_load_uevent, alloc_chrdev_region /
path -- 519 lines deleted. In-kernel accessors (`is_signal_mode`, cdev_init / cdev_add / class_create / device_create in the init
`get_fw_type`, etc., 13 call sites) and the `fw_type` module path, and the matching teardown in bes2600_chrdev_free -- 519 lines
parameter are preserved. deleted. The in-kernel accessor functions (is_signal_mode,
get_fw_type, etc., 13 call sites) and the fw_type module parameter
are preserved; the userspace interface becomes rfkill + module_param
+ (with 6/7) nl80211 testmode.
* 6/6 -- Flip `CONFIG_BES2600_TESTMODE` default from n to y. Also fixes * 6/7 -- Flip CONFIG_BES2600_TESTMODE default from n to y. The driver
accumulated bit-rot revealed by enabling the flag: shim macros in already implements a mac80211 testmode_cmd dispatcher (routing to
`bes_log.h` for the legacy `bes2600_info/err/warn/dbg/err_with_cond` the firmware's patch_wifi_testMode path), already gated on the flag;
family, `BES2600_DBG_*` constants defined as 0, 3 TSM/roam-delay CONFIG_NL80211_TESTMODE=y is common on target kernels. Enabling the
helpers marked `static`. flag also exposes accumulated bit-rot -- ~41 calls to undefined
bes2600_info/err/warn/dbg/err_with_cond macros, and 3 TSM/roam-delay
helpers with external linkage but no prototype. Add shim macros to
bes_log.h rewiring the legacy calls onto the existing bes_info /
bes_err / bes_warn / bes_devel family, define BES2600_DBG_* subsystem
ids as 0 constants, and mark the 3 helpers static.
* 7/7 -- Bounce SDIO TX buffers to avoid DMA out-of-bounds reads.
sdio_tx_work() rounded the transfer length up to the SDIO block size
(align = blks * cur_blksize, or 1632) and handed that length to
dma_map_sg() via sg_set_buf(..., tx_buffer->buf, align); tx_buffer->buf
typically aliases into an skb linear head allocated to tx_buffer->len,
not the block-aligned length. The DMA engine therefore read up to one
block past the end of the skb -- KFENCE on PineTab2 fires as
'out-of-bounds read in __pi_memcpy_generic ... 704B right of
kfence-#...' with sdio_tx_work+0x2b4 / bes_sdio_memcpy_to_io_helper in
the stack and pskb_expand_head / validate_xmit_skb / tcp_write_xmit in
the allocator stack. Besides being undefined behavior, the padding
bytes are transmitted to the peer, leaking adjacent kernel memory on
the air. Allocate a driver-owned DMA-pages bounce buffer of
MAX_SDIO_TRANSFER_LEN, memcpy each TX buffer into its slot, zero the
padding tail, and point the SG entries at the bounce. Mirrors the
pattern already used for single_gathered_buffer; kept as a separate
allocation because sdio_tx_work accumulates SG entries before claiming
the bus.
## Testing ## Testing
Reference hardware: Pine64 PineTab2 (BES2600WM + Rockchip RK3566, Reference hardware: Pine64 PineTab2 (BES2600WM + Rockchip RK3566,
MAC `8a:2e:77:1f:ec:05`). Host kernel: linux-pinetab2 8a:2e:77:1f:ec:05, LAN AP newton @ 2.4 GHz ch11, tested also on
6.19.10-danctnix1-1 with `CONFIG_NL80211_TESTMODE=y`. Full stack TelekomHotspot@ERGO @ 5 GHz ch36).
applied, verified over 3+ reboots: WiFi associates and passes traffic
on both 2.4 GHz (newton / ch11) and 5 GHz (TelekomHotspot@ERGO / ch36).
Per-patch outcomes in post-reboot dmesg: Host kernel: linux-pinetab2 6.19.10-danctnix1-1-pinetab2 with
- 1/6: `read and check /lib/firmware/bes2600_factory.txt error` -- gone CONFIG_NL80211_TESTMODE=y and CONFIG_KFENCE=y (for 7/7 verification).
- 2/6: `bes2600_factory.txt parse fail` / `factory cali data get failed.` -- gone Driver installed via /lib/modules/<ver>/extra/ and verified loaded via
- 3/6: `(NULL device *):` prefix on factory lines -- gone modinfo srcversion.
- 4/6: `wait pm ind timeout` (pre-patch 20-30 msgs / 5 min) -- 0 per 5 min;
`sdio_tx_work` WARN splat (pre-patch 2+ / 5 min) -- 0 per 5 min; Per-patch outcomes in post-reboot dmesg (full-stack applied, 11+ min
`[RX] Receive failure: 4.` -- gone soak, 245k RX packets / 365 MB traffic):
- 5/6: `/dev/bes2600` -- absent; driver continues to associate
- 6/6: `iw phy0` lists `testmode` under *Supported commands* - 1/7: 'read and check /lib/firmware/bes2600_factory.txt error' -- gone
- 2/7: 'bes2600_factory.txt parse fail' / 'factory cali data get
failed.' -- gone
- 3/7: '(NULL device *):' prefix on factory lines -- gone
- 4/7: 'bes2600_pwr_enter_lp_mode, wait pm ind timeout' (pre-patch 20-30
msgs / 5 min window) -- 0 per 5 min; '[RX] Receive failure: 4.' --
gone
- 5/7: /dev/bes2600 -- absent; driver continues to associate
- 6/7: 'iw phy0' lists 'testmode' under Supported commands; module
builds cleanly
- 7/7: 'BUG: KFENCE: out-of-bounds read in __pi_memcpy_generic'
(pre-patch ~65 splats per 4 h of real traffic, always via
sdio_tx_work+0x2b4 / bes_sdio_memcpy_to_io_helper+0x18c) -- 0;
'sdio_tx_work+0x2b4' WARN splat residual from 4/7's cascade -- 0
(previously recurred ~1 per reboot even with 4/7 applied);
'PS Mode Error, Reason:1' benign handshake notice at T+40s --
also gone, apparently a downstream effect of no longer DMAing
uninitialised padding bytes into firmware
Full stack: wifi associates and passes traffic across 3+ reboots.
## Known limitations / out of scope ## Known limitations / out of scope
- `factory_section_write_file()` still uses `kernel_write()` + `filp_open()` - factory_section_write_file() in bes2600_factory.c still uses
for calibration persistence. Conversion to debugfs/nl80211 is a kernel_write() + filp_open(O_CREAT) to persist per-channel
calibration updates back to /lib/firmware/bes2600_factory.txt.
Converting the write-back path to debugfs or nl80211 testmode is a
follow-up. follow-up.
- `bes_chardev.c` still contains DPD-to-file read/write paths (gated by
`BES2600_WRITE_DPD_TO_FILE`, off by default -- dead code in default
builds). Same treatment needed.
- `bes_fw.c:587` unconditionally creates
`/lib/firmware/bes2002_fw_write.bin` via `filp_open()` for debug
observation. Must go before a future drivers/net/wireless/st/
promotion.
- `bes_cdev` singleton still holds `sig_mode`/`fw_type`. Migrating
fw_type from module_param to per-phy debugfs knob or nl80211 testmode
is the next architectural step.
- Residual benign dmesg: `bes2600_wlan mmc2:0001:1: PS Mode Error,
Reason:1` at T+40 s on fresh boot. Distinct from the pre-4/6 timeout
cascade; driver recovers, WiFi stays up.
Markus Fritsche (6): - bes_chardev.c still carries DPD file-read/write paths gated by
BES2600_WRITE_DPD_TO_FILE (off by default, so dead code in the
default build). Same treatment needed.
- bes_fw.c:587 unconditionally creates
/lib/firmware/bes2002_fw_write.bin via filp_open() for debug
observation. Needs to go before drivers/staging/ accepts the driver.
- bes_cdev global singleton still holds sig_mode and fw_type. Moving
those to per-hw_priv state is blocked by fw_type being a module
parameter (inherently singleton). Migrating fw_type to a per-phy
debugfs knob or nl80211 testmode command is the next step; overlaps
with 6/7's testmode plumbing.
Markus Fritsche (7):
bes2600: use request_firmware() for factory.txt read bes2600: use request_firmware() for factory.txt read
bes2600: default STANDARD_FACTORY_EFUSE_FLAG off for PineTab2 factory.txt format bes2600: default STANDARD_FACTORY_EFUSE_FLAG off for PineTab2
bes2600: thread struct device * through factory request_firmware() call factory.txt format
bes2600: gate device LP-mode entry on successful per-VIF firmware handshake bes2600: thread struct device * through factory request_firmware()
call
bes2600: gate device LP-mode entry on successful per-VIF firmware
handshake
bes2600: remove userspace /dev/bes2600 character device interface bes2600: remove userspace /dev/bes2600 character device interface
bes2600: enable CONFIG_BES2600_TESTMODE by default + fix bit-rotted testmode plumbing bes2600: enable CONFIG_BES2600_TESTMODE by default + fix bit-rotted
testmode plumbing
bes2600: bounce SDIO TX buffers to avoid DMA OOB read
drivers/staging/bes2600/Makefile | 6 +- drivers/staging/bes2600/Makefile | 6 +-
drivers/staging/bes2600/bes2600_factory.c | 45 +-- drivers/staging/bes2600/bes2600_factory.c | 45 ++--
drivers/staging/bes2600/bes2600_factory.h | 3 + drivers/staging/bes2600/bes2600_factory.h | 3 +
drivers/staging/bes2600/bes2600_sdio.c | 4 + drivers/staging/bes2600/bes2600_sdio.c | 43 +++-
drivers/staging/bes2600/bes_chardev.c | 519 -------------------------------- drivers/staging/bes2600/bes_chardev.c | 519 --------------------------------------
drivers/staging/bes2600/bes_log.h | 23 ++ drivers/staging/bes2600/bes_log.h | 23 ++
drivers/staging/bes2600/bes_pwr.c | 20 +- drivers/staging/bes2600/bes_pwr.c | 20 +-
drivers/staging/bes2600/sta.c | 6 +- drivers/staging/bes2600/sta.c | 6 +-
drivers/staging/bes2600/wsm.h | 2 - drivers/staging/bes2600/wsm.h | 2 -
9 files changed, 79 insertions(+), 549 deletions(-) 9 files changed, 117 insertions(+), 550 deletions(-)
-- --
2.53.0 2.53.0
@@ -1,7 +1,10 @@
From 30a51afef7db9c4ce964cfbb2ffd15ed9eeadab0 Mon Sep 17 00:00:00 2001 From d18aa6a9bc03a03e455434f83577892aa1a60ffe Mon Sep 17 00:00:00 2001
Message-ID: <d18aa6a9bc03a03e455434f83577892aa1a60ffe.1776940528.git.fritsche.markus@gmail.com>
In-Reply-To: <cover.1776940528.git.fritsche.markus@gmail.com>
References: <cover.1776940528.git.fritsche.markus@gmail.com>
From: Markus Fritsche <fritsche.markus@gmail.com> From: Markus Fritsche <fritsche.markus@gmail.com>
Date: Wed, 22 Apr 2026 10:09:44 +0200 Date: Wed, 22 Apr 2026 10:09:44 +0200
Subject: [PATCH 1/6] bes2600: use request_firmware() for factory.txt read Subject: [PATCH 1/7] bes2600: use request_firmware() for factory.txt read
The BES2600 factory calibration file (bes2600_factory.txt) was being 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 via filp_open() + kernel_read() from a hard-coded absolute path baked in
@@ -59,11 +62,11 @@ exposed and tracked separately).
Signed-off-by: Markus Fritsche <fritsche.markus@gmail.com> Signed-off-by: Markus Fritsche <fritsche.markus@gmail.com>
--- ---
drivers/staging/bes2600/Makefile | 2 +- drivers/staging/bes2600/Makefile | 2 +-
drivers/staging/bes2600/bes2600_factory.c | 33 ++++++++++------------- drivers/staging/bes2600/bes2600_factory.c | 33 ++++++++++++++-------------------
2 files changed, 15 insertions(+), 20 deletions(-) 2 files changed, 15 insertions(+), 20 deletions(-)
diff --git a/drivers/staging/bes2600/Makefile b/drivers/staging/bes2600/Makefile diff --git a/drivers/staging/bes2600/Makefile b/bes2600/Makefile
index df5e55d..95b07fa 100644 index 300912b..788aee2 100644
--- a/drivers/staging/bes2600/Makefile --- a/drivers/staging/bes2600/Makefile
+++ b/drivers/staging/bes2600/Makefile +++ b/drivers/staging/bes2600/Makefile
@@ -66,7 +66,7 @@ BES2600_DRV_VERSION := bes2600_0.3.5_2024.0116 @@ -66,7 +66,7 @@ BES2600_DRV_VERSION := bes2600_0.3.5_2024.0116
@@ -71,11 +74,11 @@ index df5e55d..95b07fa 100644
FACTORY_CRC_CHECK ?= n FACTORY_CRC_CHECK ?= n
STANDARD_FACTORY_EFUSE_FLAG ?= y STANDARD_FACTORY_EFUSE_FLAG ?= y
-FACTORY_PATH ?= /lib/firmware/bes2600_factory.txt -FACTORY_PATH ?= /lib/firmware/bes2600_factory.txt
+FACTORY_PATH ?= bes2600/bes2600_factory.txt +FACTORY_PATH ?= drivers/staging/bes2600/bes2600_factory.txt
endif endif
# basic function # basic function
diff --git a/drivers/staging/bes2600/bes2600_factory.c b/drivers/staging/bes2600/bes2600_factory.c diff --git a/drivers/staging/bes2600/bes2600_factory.c b/bes2600/bes2600_factory.c
index dc5d3da..8d60b7c 100644 index dc5d3da..8d60b7c 100644
--- a/drivers/staging/bes2600/bes2600_factory.c --- a/drivers/staging/bes2600/bes2600_factory.c
+++ b/drivers/staging/bes2600/bes2600_factory.c +++ b/drivers/staging/bes2600/bes2600_factory.c
@@ -1,7 +1,10 @@
From 6cc2efd4dfbb6358e2d458398afcebda4e05ffe6 Mon Sep 17 00:00:00 2001 From a826f4db7d97a3a872d92079db37dbdaf9a0cdec Mon Sep 17 00:00:00 2001
Message-ID: <a826f4db7d97a3a872d92079db37dbdaf9a0cdec.1776940528.git.fritsche.markus@gmail.com>
In-Reply-To: <cover.1776940528.git.fritsche.markus@gmail.com>
References: <cover.1776940528.git.fritsche.markus@gmail.com>
From: Markus Fritsche <fritsche.markus@gmail.com> From: Markus Fritsche <fritsche.markus@gmail.com>
Date: Wed, 22 Apr 2026 12:17:56 +0200 Date: Wed, 22 Apr 2026 12:17:56 +0200
Subject: [PATCH 2/6] bes2600: default STANDARD_FACTORY_EFUSE_FLAG off for Subject: [PATCH 2/7] bes2600: default STANDARD_FACTORY_EFUSE_FLAG off for
PineTab2 factory.txt format PineTab2 factory.txt format
MIME-Version: 1.0 MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8 Content-Type: text/plain; charset=UTF-8
@@ -23,7 +26,7 @@ The PineTab2 factory.txt has no select_efuse_flag section, so sscanf
stops after field 30 and factory_parse() returns -1 with: stops after field 30 and factory_parse() returns -1 with:
bes2600_factory.txt parse fail bes2600_factory.txt parse fail
read and check bes2600/bes2600_factory.txt error read and check drivers/staging/bes2600/bes2600_factory.txt error
factory cali data get failed. factory cali data get failed.
This was latent until the preceding patch (use request_firmware() for This was latent until the preceding patch (use request_firmware() for
@@ -53,8 +56,8 @@ Signed-off-by: Markus Fritsche <fritsche.markus@gmail.com>
drivers/staging/bes2600/wsm.h | 2 -- drivers/staging/bes2600/wsm.h | 2 --
2 files changed, 1 insertion(+), 3 deletions(-) 2 files changed, 1 insertion(+), 3 deletions(-)
diff --git a/drivers/staging/bes2600/Makefile b/drivers/staging/bes2600/Makefile diff --git a/drivers/staging/bes2600/Makefile b/bes2600/Makefile
index 95b07fa..4ea2424 100644 index 788aee2..2dcba09 100644
--- a/drivers/staging/bes2600/Makefile --- a/drivers/staging/bes2600/Makefile
+++ b/drivers/staging/bes2600/Makefile +++ b/drivers/staging/bes2600/Makefile
@@ -65,7 +65,7 @@ BES2600_DRV_VERSION := bes2600_0.3.5_2024.0116 @@ -65,7 +65,7 @@ BES2600_DRV_VERSION := bes2600_0.3.5_2024.0116
@@ -63,10 +66,10 @@ index 95b07fa..4ea2424 100644
FACTORY_CRC_CHECK ?= n FACTORY_CRC_CHECK ?= n
-STANDARD_FACTORY_EFUSE_FLAG ?= y -STANDARD_FACTORY_EFUSE_FLAG ?= y
+STANDARD_FACTORY_EFUSE_FLAG ?= n +STANDARD_FACTORY_EFUSE_FLAG ?= n
FACTORY_PATH ?= bes2600/bes2600_factory.txt FACTORY_PATH ?= drivers/staging/bes2600/bes2600_factory.txt
endif endif
diff --git a/drivers/staging/bes2600/wsm.h b/drivers/staging/bes2600/wsm.h diff --git a/drivers/staging/bes2600/wsm.h b/bes2600/wsm.h
index 0673131..22845ac 100644 index 0673131..22845ac 100644
--- a/drivers/staging/bes2600/wsm.h --- a/drivers/staging/bes2600/wsm.h
+++ b/drivers/staging/bes2600/wsm.h +++ b/drivers/staging/bes2600/wsm.h
@@ -1,7 +1,10 @@
From cfbbf5d5430925e2175f53f153c482cb17520d6d Mon Sep 17 00:00:00 2001 From c7ba2044b78cc3778763737daea60c9912b710c6 Mon Sep 17 00:00:00 2001
Message-ID: <c7ba2044b78cc3778763737daea60c9912b710c6.1776940528.git.fritsche.markus@gmail.com>
In-Reply-To: <cover.1776940528.git.fritsche.markus@gmail.com>
References: <cover.1776940528.git.fritsche.markus@gmail.com>
From: Markus Fritsche <fritsche.markus@gmail.com> From: Markus Fritsche <fritsche.markus@gmail.com>
Date: Wed, 22 Apr 2026 13:18:38 +0200 Date: Wed, 22 Apr 2026 13:18:38 +0200
Subject: [PATCH 3/6] bes2600: thread struct device * through factory Subject: [PATCH 3/7] bes2600: thread struct device * through factory
request_firmware() call request_firmware() call
Follow-up to \"bes2600: use request_firmware() for factory.txt read\". Follow-up to \"bes2600: use request_firmware() for factory.txt read\".
@@ -43,7 +46,7 @@ Signed-off-by: Markus Fritsche <fritsche.markus@gmail.com>
drivers/staging/bes2600/bes2600_sdio.c | 4 ++++ drivers/staging/bes2600/bes2600_sdio.c | 4 ++++
3 files changed, 20 insertions(+), 1 deletion(-) 3 files changed, 20 insertions(+), 1 deletion(-)
diff --git a/drivers/staging/bes2600/bes2600_factory.c b/drivers/staging/bes2600/bes2600_factory.c diff --git a/drivers/staging/bes2600/bes2600_factory.c b/bes2600/bes2600_factory.c
index 8d60b7c..1cda447 100644 index 8d60b7c..1cda447 100644
--- a/drivers/staging/bes2600/bes2600_factory.c --- a/drivers/staging/bes2600/bes2600_factory.c
+++ b/drivers/staging/bes2600/bes2600_factory.c +++ b/drivers/staging/bes2600/bes2600_factory.c
@@ -75,7 +78,7 @@ index 8d60b7c..1cda447 100644
if (ret) { if (ret) {
bes_devel("BES2600: request_firmware(%s) failed: %d\n", path, ret); bes_devel("BES2600: request_firmware(%s) failed: %d\n", path, ret);
return -1; return -1;
diff --git a/drivers/staging/bes2600/bes2600_factory.h b/drivers/staging/bes2600/bes2600_factory.h diff --git a/drivers/staging/bes2600/bes2600_factory.h b/bes2600/bes2600_factory.h
index 3835b0d..7dbe9f8 100644 index 3835b0d..7dbe9f8 100644
--- a/drivers/staging/bes2600/bes2600_factory.h --- a/drivers/staging/bes2600/bes2600_factory.h
+++ b/drivers/staging/bes2600/bes2600_factory.h +++ b/drivers/staging/bes2600/bes2600_factory.h
@@ -89,8 +92,8 @@ index 3835b0d..7dbe9f8 100644
/* read wifi & bt factory cali value*/ /* read wifi & bt factory cali value*/
u8* bes2600_get_factory_cali_data(u8 *file_buffer, u32 *data_len, char *path); u8* bes2600_get_factory_cali_data(u8 *file_buffer, u32 *data_len, char *path);
void factory_little_endian_cvrt(u8 *data); void factory_little_endian_cvrt(u8 *data);
diff --git a/drivers/staging/bes2600/bes2600_sdio.c b/drivers/staging/bes2600/bes2600_sdio.c diff --git a/drivers/staging/bes2600/bes2600_sdio.c b/bes2600/bes2600_sdio.c
index 13d4ff1..f172d53 100644 index b595365..371ef4f 100644
--- a/drivers/staging/bes2600/bes2600_sdio.c --- a/drivers/staging/bes2600/bes2600_sdio.c
+++ b/drivers/staging/bes2600/bes2600_sdio.c +++ b/drivers/staging/bes2600/bes2600_sdio.c
@@ -30,6 +30,7 @@ @@ -30,6 +30,7 @@
@@ -1,7 +1,10 @@
From 28a5de5303e72ff0670ee2e3509088c228270829 Mon Sep 17 00:00:00 2001 From 108d3967eac4ba3a6e0f508d865a5f221b49079d Mon Sep 17 00:00:00 2001
Message-ID: <108d3967eac4ba3a6e0f508d865a5f221b49079d.1776940528.git.fritsche.markus@gmail.com>
In-Reply-To: <cover.1776940528.git.fritsche.markus@gmail.com>
References: <cover.1776940528.git.fritsche.markus@gmail.com>
From: Markus Fritsche <fritsche.markus@gmail.com> From: Markus Fritsche <fritsche.markus@gmail.com>
Date: Wed, 22 Apr 2026 12:37:45 +0200 Date: Wed, 22 Apr 2026 12:37:45 +0200
Subject: [PATCH 4/6] bes2600: gate device LP-mode entry on successful per-VIF Subject: [PATCH 4/7] bes2600: gate device LP-mode entry on successful per-VIF
firmware handshake firmware handshake
bes2600_pwr_enter_lp_mode() drives the transition to low-power for each bes2600_pwr_enter_lp_mode() drives the transition to low-power for each
@@ -49,7 +52,7 @@ Signed-off-by: Markus Fritsche <fritsche.markus@gmail.com>
drivers/staging/bes2600/bes_pwr.c | 20 +++++++++++++++++--- drivers/staging/bes2600/bes_pwr.c | 20 +++++++++++++++++---
1 file changed, 17 insertions(+), 3 deletions(-) 1 file changed, 17 insertions(+), 3 deletions(-)
diff --git a/drivers/staging/bes2600/bes_pwr.c b/drivers/staging/bes2600/bes_pwr.c diff --git a/drivers/staging/bes2600/bes_pwr.c b/bes2600/bes_pwr.c
index e7a1045..f62ae22 100644 index e7a1045..f62ae22 100644
--- a/drivers/staging/bes2600/bes_pwr.c --- a/drivers/staging/bes2600/bes_pwr.c
+++ b/drivers/staging/bes2600/bes_pwr.c +++ b/drivers/staging/bes2600/bes_pwr.c
@@ -1,7 +1,10 @@
From adb2cb22a8189ee6d2de5521e65aed63aebf1d09 Mon Sep 17 00:00:00 2001 From 3304b13a2b2e7388ebf076c2bcb7f02cd0b6800f Mon Sep 17 00:00:00 2001
Message-ID: <3304b13a2b2e7388ebf076c2bcb7f02cd0b6800f.1776940528.git.fritsche.markus@gmail.com>
In-Reply-To: <cover.1776940528.git.fritsche.markus@gmail.com>
References: <cover.1776940528.git.fritsche.markus@gmail.com>
From: Markus Fritsche <fritsche.markus@gmail.com> From: Markus Fritsche <fritsche.markus@gmail.com>
Date: Wed, 22 Apr 2026 13:04:27 +0200 Date: Wed, 22 Apr 2026 12:55:18 +0200
Subject: [PATCH 5/6] bes2600: remove userspace /dev/bes2600 character device Subject: [PATCH 5/7] bes2600: remove userspace /dev/bes2600 character device
interface interface
bes_chardev.c implemented a custom character device at /dev/bes2600 with bes_chardev.c implemented a custom character device at /dev/bes2600 with
@@ -73,11 +76,11 @@ Follow-ups:
Signed-off-by: Markus Fritsche <fritsche.markus@gmail.com> Signed-off-by: Markus Fritsche <fritsche.markus@gmail.com>
--- ---
drivers/staging/bes2600/bes_chardev.c | 519 -------------------------- drivers/staging/bes2600/bes_chardev.c | 519 ------------------------------------------
1 file changed, 519 deletions(-) 1 file changed, 519 deletions(-)
diff --git a/drivers/staging/bes2600/bes_chardev.c b/drivers/staging/bes2600/bes_chardev.c diff --git a/drivers/staging/bes2600/bes_chardev.c b/bes2600/bes_chardev.c
index f89dcb8..455108a 100644 index 9038e48..e2e4f1b 100644
--- a/drivers/staging/bes2600/bes_chardev.c --- a/drivers/staging/bes2600/bes_chardev.c
+++ b/drivers/staging/bes2600/bes_chardev.c +++ b/drivers/staging/bes2600/bes_chardev.c
@@ -43,12 +43,6 @@ enum bus_probe_state { @@ -43,12 +43,6 @@ enum bus_probe_state {
@@ -93,9 +96,9 @@ index f89dcb8..455108a 100644
atomic_t num_proc; atomic_t num_proc;
wait_queue_head_t open_wq; wait_queue_head_t open_wq;
spinlock_t status_lock; spinlock_t status_lock;
@@ -290,351 +284,18 @@ int bes2600_chrdev_switch_subsys_glb(int wifi, int bt) @@ -249,351 +243,18 @@ int bes2600_switch_bt(bool on)
return ret;
} }
EXPORT_SYMBOL_GPL(bes2600_chrdev_switch_subsys_glb);
-static int bes2600_get_cmd_and_ifname(const char *str, char **result) -static int bes2600_get_cmd_and_ifname(const char *str, char **result)
-{ -{
@@ -119,7 +122,7 @@ index f89dcb8..455108a 100644
- if (!tmp_ptr) { - if (!tmp_ptr) {
- return -2; - return -2;
- } - }
-
- strncpy(tmp_ptr, str+7, ifname_len); - strncpy(tmp_ptr, str+7, ifname_len);
- tmp_ptr[ifname_len] = '\0'; - tmp_ptr[ifname_len] = '\0';
- result[0] = tmp_ptr; - result[0] = tmp_ptr;
@@ -150,33 +153,33 @@ index f89dcb8..455108a 100644
- -
- return 0; - return 0;
-} -}
-
-static void bes2600_recyle_cmd_and_ifname_mem(char **info) -static void bes2600_recyle_cmd_and_ifname_mem(char **info)
-{ -{
- if (info[0]) { - if (info[0]) {
- kfree(info[0]); - kfree(info[0]);
- info[0] = NULL; - info[0] = NULL;
- } - }
-
- if (info[1]) { - if (info[1]) {
- kfree(info[1]); - kfree(info[1]);
- info[1] = NULL; - info[1] = NULL;
- } - }
-
-} -}
-
-static int bes2600_op_default_handler(const char *str) -static int bes2600_op_default_handler(const char *str)
-{ -{
- char *info[2] = {0}; - char *info[2] = {0};
-
- if (bes2600_get_cmd_and_ifname(str, info) == 0) { - if (bes2600_get_cmd_and_ifname(str, info) == 0) {
- bes_devel("cmd(%s) on %s not handled\n", info[1], info[0]); - bes_devel("cmd(%s) on %s not handled\n", info[1], info[0]);
- } else { - } else {
- bes_err("%s get command fail, the origin string is %s\n", __func__, str); - bes_err("%s get command fail, the origin string is %s\n", __func__, str);
- } - }
-
- bes2600_recyle_cmd_and_ifname_mem(info); - bes2600_recyle_cmd_and_ifname_mem(info);
-
- return 0; - return 0;
-} -}
- -
@@ -344,8 +347,8 @@ index f89dcb8..455108a 100644
- WARN_ON(status <= 0); - WARN_ON(status <= 0);
- -
- ret = (status <= 0 || bes2600_chrdev_is_bus_error()) ? -1 : 0; - ret = (status <= 0 || bes2600_chrdev_is_bus_error()) ? -1 : 0;
-
-
- return ret; - return ret;
-} -}
- -
@@ -360,7 +363,7 @@ index f89dcb8..455108a 100644
- return -EFAULT; - return -EFAULT;
- } - }
- spin_unlock(&bes2600_cdev.status_lock); - spin_unlock(&bes2600_cdev.status_lock);
-
- /* wait probe done event */ - /* wait probe done event */
- status = wait_event_timeout(bes2600_cdev.probe_done_wq, - status = wait_event_timeout(bes2600_cdev.probe_done_wq,
- bes2600_bootup_end(), HZ * 8); - bes2600_bootup_end(), HZ * 8);
@@ -384,26 +387,26 @@ index f89dcb8..455108a 100644
- return -EFAULT; - return -EFAULT;
- } - }
- spin_unlock(&bes2600_cdev.status_lock); - spin_unlock(&bes2600_cdev.status_lock);
-
- /* wait probe done event */ - /* wait probe done event */
- status = wait_event_timeout(bes2600_cdev.probe_done_wq, - status = wait_event_timeout(bes2600_cdev.probe_done_wq,
- bes2600_bootup_end(), HZ * 8); - bes2600_bootup_end(), HZ * 8);
- if (status <= 0 || bes2600_chrdev_is_bus_error()) - if (status <= 0 || bes2600_chrdev_is_bus_error())
- return -EFAULT; - return -EFAULT;
-
- bes_devel("bes2600 allow bt sleep.\n"); - bes_devel("bes2600 allow bt sleep.\n");
- ret = bes2600_chrdev_switch_subsys(GPIO_WAKE_FLAG_BT_LP_OFF, SUBSYSTEM_BT_LP, false); - ret = bes2600_chrdev_switch_subsys(GPIO_WAKE_FLAG_BT_LP_OFF, SUBSYSTEM_BT_LP, false);
-
- return ret; - return ret;
-} -}
-
-static int bes2600_op_set_wakeup_read_flag(const char *str) -static int bes2600_op_set_wakeup_read_flag(const char *str)
-{ -{
- bes_devel("%s is called, arg:%s\n", __func__, str); - bes_devel("%s is called, arg:%s\n", __func__, str);
- spin_lock(&bes2600_cdev.status_lock); - spin_lock(&bes2600_cdev.status_lock);
- bes2600_cdev.read_flag = BES_CDEV_READ_WAKEUP_STATE; - bes2600_cdev.read_flag = BES_CDEV_READ_WAKEUP_STATE;
- spin_unlock(&bes2600_cdev.status_lock); - spin_unlock(&bes2600_cdev.status_lock);
-
- return 0; - return 0;
-} -}
@@ -445,7 +448,7 @@ index f89dcb8..455108a 100644
static int bes2600_chrdev_check_system_close_internal(void) static int bes2600_chrdev_check_system_close_internal(void)
{ {
@@ -644,123 +305,10 @@ static int bes2600_chrdev_check_system_close_internal(void) @@ -603,123 +264,10 @@ static int bes2600_chrdev_check_system_close_internal(void)
&& (bes2600_cdev.wifi_opened == false); && (bes2600_cdev.wifi_opened == false);
} }
@@ -456,20 +459,20 @@ index f89dcb8..455108a 100644
- (atomic_read(&bes2600_cdev.num_proc) == 0), - (atomic_read(&bes2600_cdev.num_proc) == 0),
- MAX_SCHEDULE_TIMEOUT); - MAX_SCHEDULE_TIMEOUT);
- } - }
-
- bes_devel("bes2600 char device is opened\n"); - bes_devel("bes2600 char device is opened\n");
- atomic_inc(&bes2600_cdev.num_proc); - atomic_inc(&bes2600_cdev.num_proc);
-
- return 0; - return 0;
-} -}
-
-static ssize_t bes2600_chrdev_read(struct file *file, char __user *user_buf, -static ssize_t bes2600_chrdev_read(struct file *file, char __user *user_buf,
- size_t count, loff_t *ppos) - size_t count, loff_t *ppos)
-{ -{
- char buf[64] = {0}; - char buf[64] = {0};
- unsigned int len; - unsigned int len;
- long status = 0; - long status = 0;
-
- switch (bes2600_cdev.read_flag) { - switch (bes2600_cdev.read_flag) {
- case BES_CDEV_READ_WAKEUP_STATE: - case BES_CDEV_READ_WAKEUP_STATE:
- if (bes2600_chrdev_wakeup_by_event_get() > WAKEUP_EVENT_NONE) { - if (bes2600_chrdev_wakeup_by_event_get() > WAKEUP_EVENT_NONE) {
@@ -546,18 +549,18 @@ index f89dcb8..455108a 100644
- -
- return (ret == 0) ? count : ret; - return (ret == 0) ? count : ret;
-} -}
-
-static int bes2600_chrdev_release (struct inode *inode, struct file *file) -static int bes2600_chrdev_release (struct inode *inode, struct file *file)
-{ -{
- if (atomic_dec_and_test(&bes2600_cdev.num_proc)) { - if (atomic_dec_and_test(&bes2600_cdev.num_proc)) {
- wake_up(&bes2600_cdev.open_wq); - wake_up(&bes2600_cdev.open_wq);
- } - }
-
- bes_devel("bes2600 char device is closed\n"); - bes_devel("bes2600 char device is closed\n");
-
- return 0; - return 0;
-} -}
-
-static struct file_operations bes2600_chardev_fops = -static struct file_operations bes2600_chardev_fops =
-{ -{
- .owner = THIS_MODULE, - .owner = THIS_MODULE,
@@ -569,7 +572,7 @@ index f89dcb8..455108a 100644
#ifdef BES2600_WRITE_DPD_TO_FILE #ifdef BES2600_WRITE_DPD_TO_FILE
static int bes2600_chrdev_write_dpd_data_to_file(const char *path, void *buffer, int size) static int bes2600_chrdev_write_dpd_data_to_file(const char *path, void *buffer, int size)
@@ -1167,12 +715,6 @@ void bes2600_chrdev_update_signal_mode(void) @@ -1124,12 +672,6 @@ void bes2600_chrdev_update_signal_mode(void)
static void bes2600_chrdev_wifi_force_close_work(struct work_struct *work) static void bes2600_chrdev_wifi_force_close_work(struct work_struct *work)
{ {
@@ -582,7 +585,7 @@ index f89dcb8..455108a 100644
if (bes2600_chrdev_is_wifi_opened()) { if (bes2600_chrdev_is_wifi_opened()) {
bes_devel("system exeception, force wifi down\n"); bes_devel("system exeception, force wifi down\n");
@@ -1189,14 +731,6 @@ static void bes2600_chrdev_wifi_force_close_work(struct work_struct *work) @@ -1146,14 +688,6 @@ static void bes2600_chrdev_wifi_force_close_work(struct work_struct *work)
bes2600_chrdev_do_system_close(bes2600_cdev.sbus_ops, bes2600_chrdev_do_system_close(bes2600_cdev.sbus_ops,
bes2600_cdev.sbus_priv); bes2600_cdev.sbus_priv);
} }
@@ -597,7 +600,7 @@ index f89dcb8..455108a 100644
} }
} }
@@ -1290,46 +824,6 @@ int bes2600_chrdev_wakeup_by_event_get(void) @@ -1247,46 +781,6 @@ int bes2600_chrdev_wakeup_by_event_get(void)
int bes2600_chrdev_init(struct sbus_ops *ops) int bes2600_chrdev_init(struct sbus_ops *ops)
{ {
@@ -644,7 +647,7 @@ index f89dcb8..455108a 100644
/* initialise global variable */ /* initialise global variable */
atomic_set(&bes2600_cdev.num_proc, 0); atomic_set(&bes2600_cdev.num_proc, 0);
init_waitqueue_head(&bes2600_cdev.open_wq); init_waitqueue_head(&bes2600_cdev.open_wq);
@@ -1361,15 +855,6 @@ int bes2600_chrdev_init(struct sbus_ops *ops) @@ -1318,15 +812,6 @@ int bes2600_chrdev_init(struct sbus_ops *ops)
bes_devel("%s done\n", __func__); bes_devel("%s done\n", __func__);
return 0; return 0;
@@ -660,7 +663,7 @@ index f89dcb8..455108a 100644
} }
void bes2600_chrdev_free(void) void bes2600_chrdev_free(void)
@@ -1379,9 +864,5 @@ void bes2600_chrdev_free(void) @@ -1336,9 +821,5 @@ void bes2600_chrdev_free(void)
bes2600_free_dpd_log_buffer(); bes2600_free_dpd_log_buffer();
#endif #endif
bes2600_chrdev_free_dpd_data(); bes2600_chrdev_free_dpd_data();
@@ -1,7 +1,10 @@
From f1d22ab91dbc0d12064f672300fec5ec0ff220e3 Mon Sep 17 00:00:00 2001 From 6f13e008d21d453db486f707f47340a0a17e650b Mon Sep 17 00:00:00 2001
Message-ID: <6f13e008d21d453db486f707f47340a0a17e650b.1776940528.git.fritsche.markus@gmail.com>
In-Reply-To: <cover.1776940528.git.fritsche.markus@gmail.com>
References: <cover.1776940528.git.fritsche.markus@gmail.com>
From: Markus Fritsche <fritsche.markus@gmail.com> From: Markus Fritsche <fritsche.markus@gmail.com>
Date: Wed, 22 Apr 2026 14:26:43 +0200 Date: Wed, 22 Apr 2026 13:04:27 +0200
Subject: [PATCH 6/6] bes2600: enable CONFIG_BES2600_TESTMODE by default + fix Subject: [PATCH 6/7] bes2600: enable CONFIG_BES2600_TESTMODE by default + fix
bit-rotted testmode plumbing bit-rotted testmode plumbing
MIME-Version: 1.0 MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8 Content-Type: text/plain; charset=UTF-8
@@ -63,11 +66,11 @@ Signed-off-by: Markus Fritsche <fritsche.markus@gmail.com>
drivers/staging/bes2600/sta.c | 6 +++--- drivers/staging/bes2600/sta.c | 6 +++---
3 files changed, 27 insertions(+), 4 deletions(-) 3 files changed, 27 insertions(+), 4 deletions(-)
diff --git a/drivers/staging/bes2600/Makefile b/drivers/staging/bes2600/Makefile diff --git a/drivers/staging/bes2600/Makefile b/bes2600/Makefile
index 4ea2424..aecb302 100644 index 2dcba09..2c1a850 100644
--- a/drivers/staging/bes2600/Makefile --- a/drivers/staging/bes2600/Makefile
+++ b/drivers/staging/bes2600/Makefile +++ b/drivers/staging/bes2600/Makefile
@@ -2,7 +2,7 @@ KERN_DIR = /lib/modules/$(shell uname -r)/build @@ -2,7 +2,7 @@ KERN_DIR = /lib/modules/$(KERNELRELEASE)/build
# feature option # feature option
BES2600 ?= m BES2600 ?= m
@@ -76,7 +79,7 @@ index 4ea2424..aecb302 100644
CONFIG_BES2600_ENABLE_DEVEL_LOGS ?= n CONFIG_BES2600_ENABLE_DEVEL_LOGS ?= n
diff --git a/drivers/staging/bes2600/bes_log.h b/drivers/staging/bes2600/bes_log.h diff --git a/drivers/staging/bes2600/bes_log.h b/bes2600/bes_log.h
index 605cea8..65cf703 100644 index 605cea8..65cf703 100644
--- a/drivers/staging/bes2600/bes_log.h --- a/drivers/staging/bes2600/bes_log.h
+++ b/drivers/staging/bes2600/bes_log.h +++ b/drivers/staging/bes2600/bes_log.h
@@ -107,11 +110,11 @@ index 605cea8..65cf703 100644
+ if (_cond) \ + if (_cond) \
+ bes_err(fmt, ##__VA_ARGS__); \ + bes_err(fmt, ##__VA_ARGS__); \
+ } while (0) + } while (0)
diff --git a/drivers/staging/bes2600/sta.c b/drivers/staging/bes2600/sta.c diff --git a/drivers/staging/bes2600/sta.c b/bes2600/sta.c
index ca1c77c..bc6d483 100644 index aa69eb8..5f1a456 100644
--- a/drivers/staging/bes2600/sta.c --- a/drivers/staging/bes2600/sta.c
+++ b/drivers/staging/bes2600/sta.c +++ b/drivers/staging/bes2600/sta.c
@@ -3654,7 +3654,7 @@ static int bes2600_set_power_save(struct ieee80211_hw *hw, @@ -3633,7 +3633,7 @@ static int bes2600_set_power_save(struct ieee80211_hw *hw,
* *
* Returns: 0 on success or non zero value on failure * Returns: 0 on success or non zero value on failure
*/ */
@@ -120,7 +123,7 @@ index ca1c77c..bc6d483 100644
{ {
struct bes_msg_start_stop_tsm *start_stop_tsm = struct bes_msg_start_stop_tsm *start_stop_tsm =
(struct bes_msg_start_stop_tsm *) data; (struct bes_msg_start_stop_tsm *) data;
@@ -3684,7 +3684,7 @@ int bes2600_start_stop_tsm(struct ieee80211_hw *hw, void *data) @@ -3663,7 +3663,7 @@ int bes2600_start_stop_tsm(struct ieee80211_hw *hw, void *data)
* *
* Returns: TSM parameters collected * Returns: TSM parameters collected
*/ */
@@ -129,7 +132,7 @@ index ca1c77c..bc6d483 100644
{ {
struct bes2600_common *hw_priv = hw->priv; struct bes2600_common *hw_priv = hw->priv;
struct bes_tsm_stats tsm_stats; struct bes_tsm_stats tsm_stats;
@@ -3724,7 +3724,7 @@ int bes2600_get_tsm_params(struct ieee80211_hw *hw) @@ -3703,7 +3703,7 @@ int bes2600_get_tsm_params(struct ieee80211_hw *hw)
* *
* Returns: Returns the last measured roam delay * Returns: Returns the last measured roam delay
*/ */
@@ -0,0 +1,126 @@
From 10a05d21bfe4563f963e16d65228fd7a713c143d Mon Sep 17 00:00:00 2001
Message-ID: <10a05d21bfe4563f963e16d65228fd7a713c143d.1776940528.git.fritsche.markus@gmail.com>
In-Reply-To: <cover.1776940528.git.fritsche.markus@gmail.com>
References: <cover.1776940528.git.fritsche.markus@gmail.com>
From: Markus Fritsche <fritsche.markus@gmail.com>
Date: Thu, 23 Apr 2026 11:58:31 +0200
Subject: [PATCH 7/7] 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
sg_set_buf(&sg[scatters], tx_buffer->buf, align) in sdio_tx_work().
tx_buffer->buf typically aliases into an skb linear head whose
allocated size matches tx_buffer->len, not the block-aligned
align. The DMA engine (swiotlb / dw_mci IDMAC) therefore reads up
to one block past the end of the skb. On a PineTab2 with KFENCE
enabled this fires as:
BUG: KFENCE: out-of-bounds read in __pi_memcpy_generic
Out-of-bounds read at ... (704B right of kfence-#...):
__pi_memcpy_generic
swiotlb_tbl_map_single
swiotlb_map
dma_direct_map_sg
__dma_map_sg_attrs
dma_map_sg_attrs
dw_mci_pre_dma_transfer
__dw_mci_start_request
...
bes_sdio_memcpy_to_io_helper+0x18c/0x288 [bes2600]
sdio_tx_work+0x2b4/0x4a0 [bes2600]
allocated by ... pskb_expand_head / validate_xmit_skb / tcp_*
In addition to being undefined behavior, the padding bytes (which
come from whatever memory follows the skb) are transmitted to the
peer, leaking kernel memory on the air.
Allocate a driver-owned DMA-page bounce buffer sized to
MAX_SDIO_TRANSFER_LEN and use it as the scatter-gather backing for
sdio_tx_work. Each TX buffer is copied into its bounce slot and the
tail (align - tx_buffer->len bytes) is zeroed. This mirrors the
existing bounce pattern already used by bes2600_sdio_memcpy_toio()
via single_gathered_buffer; a separate allocation is used for the
TX path because single_gathered_buffer is only serialised via
sdio_claim_host and sdio_tx_work accumulates scatter entries before
claiming the bus.
Signed-off-by: Markus Fritsche <fritsche.markus@gmail.com>
---
drivers/staging/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 371ef4f..3e04e8c 100644
--- a/drivers/staging/bes2600/bes2600_sdio.c
+++ b/drivers/staging/bes2600/bes2600_sdio.c
@@ -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];
+ u8 *tx_bounce;
u32 tx_data_cnt;
u32 tx_xfer_cnt;
u32 tx_proc_cnt;
@@ -1136,7 +1137,26 @@ static void sdio_tx_work(struct work_struct *work)
}
}
- sg_set_buf(&sg[scatters], tx_buffer->buf, align);
+ /*
+ * The transfer length is rounded up to the SDIO block
+ * size, but tx_buffer->buf is only tx_buffer->len bytes
+ * long (it usually aliases into an skb linear head).
+ * Copy into a driver-owned bounce buffer and zero-pad
+ * to the aligned size; otherwise DMA reads past the
+ * skb and leaks adjacent kernel memory on the wire --
+ * observed as KFENCE OOB reads from
+ * bes_sdio_memcpy_to_io_helper via dma_map_sg.
+ */
+ if (WARN_ON_ONCE(total_len + align > MAX_SDIO_TRANSFER_LEN))
+ goto flush_previous;
+ memcpy(self->tx_bounce + total_len,
+ tx_buffer->buf, tx_buffer->len);
+ if (align > tx_buffer->len)
+ memset(self->tx_bounce + total_len +
+ tx_buffer->len, 0,
+ align - tx_buffer->len);
+ sg_set_buf(&sg[scatters],
+ self->tx_bounce + total_len, align);
total_len += align;
++scatters;
/*del_node:*/
@@ -1857,6 +1877,17 @@ static int bes2600_sdio_probe(struct sdio_func *func,
if (!self->single_gathered_buffer)
return -ENOMEM;
#endif
+#ifdef BES_SDIO_TX_MULTIPLE_ENABLE
+ self->tx_bounce = (u8 *)__get_dma_pages(GFP_KERNEL,
+ get_order(MAX_SDIO_TRANSFER_LEN));
+ if (!self->tx_bounce) {
+#ifndef SDIO_HOST_ADMA_SUPPORT
+ free_pages((unsigned long)self->single_gathered_buffer,
+ get_order(MAX_SDIO_TRANSFER_LEN));
+#endif
+ return -ENOMEM;
+ }
+#endif
#ifdef BES_SDIO_RXTX_TOGGLE
self->fw_started = false;
#endif
@@ -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));
}
+#endif
+#ifdef BES_SDIO_TX_MULTIPLE_ENABLE
+ if (self->tx_bounce) {
+ free_pages((unsigned long)self->tx_bounce,
+ get_order(MAX_SDIO_TRANSFER_LEN));
+ }
#endif
kfree(self);
}
--
2.53.0
@@ -1,7 +1,11 @@
From 6f13e008d21d453db486f707f47340a0a17e650b Mon Sep 17 00:00:00 2001 From 10a05d21bfe4563f963e16d65228fd7a713c143d Mon Sep 17 00:00:00 2001
Message-ID: <cover.1776940528.git.fritsche.markus@gmail.com>
From: Markus Fritsche <fritsche.markus@gmail.com> From: Markus Fritsche <fritsche.markus@gmail.com>
Date: Wed, 22 Apr 2026 14:15:56 +0200 Date: Thu, 23 Apr 2026 12:35:28 +0200
Subject: [PATCH 0/6] bes2600: staging-prep cleanup for PineTab2 (BES2600WM) Subject: [PATCH 0/7] bes2600: staging-prep cleanup for PineTab2 (BES2600WM)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This series is a staging-prep cleanup for the out-of-tree Bestechnic This series is a staging-prep cleanup for the out-of-tree Bestechnic
BES2600WM Wi-Fi/BT combo-chip driver as shipped by Mobian's bes2600-dkms BES2600WM Wi-Fi/BT combo-chip driver as shipped by Mobian's bes2600-dkms
@@ -24,14 +28,14 @@ dependencies.
## What the series does ## What the series does
* 1/6 -- Replace filp_open() + kernel_read() in the factory-calibration * 1/7 -- Replace filp_open() + kernel_read() in the factory-calibration
read path with request_firmware(). Repoint the FACTORY_PATH macro to read path with request_firmware(). Repoint the FACTORY_PATH macro to
the firmware-class name (bes2600/bes2600_factory.txt, matching the the firmware-class name (bes2600/bes2600_factory.txt, matching the
/lib/firmware/ layout). Kills a kernel-mainline anti-pattern and the /lib/firmware/ layout). Kills a kernel-mainline anti-pattern and the
'(NULL device *): read and check /lib/firmware/bes2600_factory.txt '(NULL device *): read and check /lib/firmware/bes2600_factory.txt
error' boot spam on PineTab2. error' boot spam on PineTab2.
* 2/6 -- Default STANDARD_FACTORY_EFUSE_FLAG from y to n. The shipped * 2/7 -- Default STANDARD_FACTORY_EFUSE_FLAG from y to n. The shipped
bes2600_factory.txt on PineTab2 contains 30 calibration fields; the bes2600_factory.txt on PineTab2 contains 30 calibration fields; the
driver was expecting 31 (including a ##select_efuse_flag section driver was expecting 31 (including a ##select_efuse_flag section
absent from this firmware). Also unguards the absent from this firmware). Also unguards the
@@ -41,12 +45,12 @@ dependencies.
ungated -- gcc -Werror=missing-prototypes broke the build with the ungated -- gcc -Werror=missing-prototypes broke the build with the
new default until this is fixed. new default until this is fixed.
* 3/6 -- Thread struct device * through factory_section_read_file() via * 3/7 -- Thread struct device * through factory_section_read_file() via
a module-local setter invoked at SDIO probe. request_firmware() now a module-local setter invoked at SDIO probe. request_firmware() now
receives a real device pointer; '(NULL device *):' no longer prefixes receives a real device pointer; '(NULL device *):' no longer prefixes
factory-related diagnostics. factory-related diagnostics.
* 4/6 -- Gate the device-end of the low-power transition on successful * 4/7 -- Gate the device-end of the low-power transition on successful
per-VIF firmware handshake. Pre-patch bes2600_pwr_enter_lp_mode() per-VIF firmware handshake. Pre-patch bes2600_pwr_enter_lp_mode()
called bes2600_pwr_device_enter_lp_mode() unconditionally even when called bes2600_pwr_device_enter_lp_mode() unconditionally even when
wait_for_completion_timeout() returned 0 (firmware never posted the wait_for_completion_timeout() returned 0 (firmware never posted the
@@ -56,7 +60,7 @@ dependencies.
messages. Post-patch: -ETIMEDOUT returned cleanly, dmesg silent, messages. Post-patch: -ETIMEDOUT returned cleanly, dmesg silent,
SDIO stable. SDIO stable.
* 5/6 -- Remove the custom /dev/bes2600 character-device interface. * 5/7 -- Remove the custom /dev/bes2600 character-device interface.
file_operations, open/read/write/release, bes2600_op_* file_operations, open/read/write/release, bes2600_op_*
command-dispatch table, bes2600_load_uevent, alloc_chrdev_region / command-dispatch table, bes2600_load_uevent, alloc_chrdev_region /
cdev_init / cdev_add / class_create / device_create in the init cdev_init / cdev_add / class_create / device_create in the init
@@ -64,9 +68,9 @@ dependencies.
deleted. The in-kernel accessor functions (is_signal_mode, deleted. The in-kernel accessor functions (is_signal_mode,
get_fw_type, etc., 13 call sites) and the fw_type module parameter get_fw_type, etc., 13 call sites) and the fw_type module parameter
are preserved; the userspace interface becomes rfkill + module_param are preserved; the userspace interface becomes rfkill + module_param
+ (with 6/6) nl80211 testmode. + (with 6/7) nl80211 testmode.
* 6/6 -- Flip CONFIG_BES2600_TESTMODE default from n to y. The driver * 6/7 -- Flip CONFIG_BES2600_TESTMODE default from n to y. The driver
already implements a mac80211 testmode_cmd dispatcher (routing to already implements a mac80211 testmode_cmd dispatcher (routing to
the firmware's patch_wifi_testMode path), already gated on the flag; the firmware's patch_wifi_testMode path), already gated on the flag;
CONFIG_NL80211_TESTMODE=y is common on target kernels. Enabling the CONFIG_NL80211_TESTMODE=y is common on target kernels. Enabling the
@@ -77,6 +81,25 @@ dependencies.
bes_err / bes_warn / bes_devel family, define BES2600_DBG_* subsystem bes_err / bes_warn / bes_devel family, define BES2600_DBG_* subsystem
ids as 0 constants, and mark the 3 helpers static. ids as 0 constants, and mark the 3 helpers static.
* 7/7 -- Bounce SDIO TX buffers to avoid DMA out-of-bounds reads.
sdio_tx_work() rounded the transfer length up to the SDIO block size
(align = blks * cur_blksize, or 1632) and handed that length to
dma_map_sg() via sg_set_buf(..., tx_buffer->buf, align); tx_buffer->buf
typically aliases into an skb linear head allocated to tx_buffer->len,
not the block-aligned length. The DMA engine therefore read up to one
block past the end of the skb -- KFENCE on PineTab2 fires as
'out-of-bounds read in __pi_memcpy_generic ... 704B right of
kfence-#...' with sdio_tx_work+0x2b4 / bes_sdio_memcpy_to_io_helper in
the stack and pskb_expand_head / validate_xmit_skb / tcp_write_xmit in
the allocator stack. Besides being undefined behavior, the padding
bytes are transmitted to the peer, leaking adjacent kernel memory on
the air. Allocate a driver-owned DMA-pages bounce buffer of
MAX_SDIO_TRANSFER_LEN, memcpy each TX buffer into its slot, zero the
padding tail, and point the SG entries at the bounce. Mirrors the
pattern already used for single_gathered_buffer; kept as a separate
allocation because sdio_tx_work accumulates SG entries before claiming
the bus.
## Testing ## Testing
Reference hardware: Pine64 PineTab2 (BES2600WM + Rockchip RK3566, Reference hardware: Pine64 PineTab2 (BES2600WM + Rockchip RK3566,
@@ -84,21 +107,31 @@ Reference hardware: Pine64 PineTab2 (BES2600WM + Rockchip RK3566,
TelekomHotspot@ERGO @ 5 GHz ch36). TelekomHotspot@ERGO @ 5 GHz ch36).
Host kernel: linux-pinetab2 6.19.10-danctnix1-1-pinetab2 with Host kernel: linux-pinetab2 6.19.10-danctnix1-1-pinetab2 with
CONFIG_NL80211_TESTMODE=y. Driver installed via CONFIG_NL80211_TESTMODE=y and CONFIG_KFENCE=y (for 7/7 verification).
/lib/modules/<ver>/extra/ and verified loaded via modinfo srcversion. Driver installed via /lib/modules/<ver>/extra/ and verified loaded via
modinfo srcversion.
Per-patch outcomes in post-reboot dmesg (full-stack applied): Per-patch outcomes in post-reboot dmesg (full-stack applied, 11+ min
- 1/6: 'read and check /lib/firmware/bes2600_factory.txt error' -- gone soak, 245k RX packets / 365 MB traffic):
- 2/6: 'bes2600_factory.txt parse fail' / 'factory cali data get
- 1/7: 'read and check /lib/firmware/bes2600_factory.txt error' -- gone
- 2/7: 'bes2600_factory.txt parse fail' / 'factory cali data get
failed.' -- gone failed.' -- gone
- 3/6: '(NULL device *):' prefix on factory lines -- gone - 3/7: '(NULL device *):' prefix on factory lines -- gone
- 4/6: 'bes2600_pwr_enter_lp_mode, wait pm ind timeout' (pre-patch 20-30 - 4/7: 'bes2600_pwr_enter_lp_mode, wait pm ind timeout' (pre-patch 20-30
msgs / 5 min window) -- 0 per 5 min; 'sdio_tx_work' WARN splat msgs / 5 min window) -- 0 per 5 min; '[RX] Receive failure: 4.' --
(pre-patch 2+ / 5 min) -- 0 per 5 min; '[RX] Receive failure: 4.' --
gone gone
- 5/6: /dev/bes2600 -- absent; driver continues to associate - 5/7: /dev/bes2600 -- absent; driver continues to associate
- 6/6: 'iw phy0' lists 'testmode' under Supported commands; module - 6/7: 'iw phy0' lists 'testmode' under Supported commands; module
builds cleanly builds cleanly
- 7/7: 'BUG: KFENCE: out-of-bounds read in __pi_memcpy_generic'
(pre-patch ~65 splats per 4 h of real traffic, always via
sdio_tx_work+0x2b4 / bes_sdio_memcpy_to_io_helper+0x18c) -- 0;
'sdio_tx_work+0x2b4' WARN splat residual from 4/7's cascade -- 0
(previously recurred ~1 per reboot even with 4/7 applied);
'PS Mode Error, Reason:1' benign handshake notice at T+40s --
also gone, apparently a downstream effect of no longer DMAing
uninitialised padding bytes into firmware
Full stack: wifi associates and passes traffic across 3+ reboots. Full stack: wifi associates and passes traffic across 3+ reboots.
@@ -122,14 +155,9 @@ Full stack: wifi associates and passes traffic across 3+ reboots.
those to per-hw_priv state is blocked by fw_type being a module those to per-hw_priv state is blocked by fw_type being a module
parameter (inherently singleton). Migrating fw_type to a per-phy parameter (inherently singleton). Migrating fw_type to a per-phy
debugfs knob or nl80211 testmode command is the next step; overlaps debugfs knob or nl80211 testmode command is the next step; overlaps
with 6/6's testmode plumbing. with 6/7's testmode plumbing.
- One residual benign notice after the full stack: 'bes2600_wlan Markus Fritsche (7):
mmc2:0001:1: PS Mode Error, Reason:1' at T+40s on fresh boot.
Distinct from the pre-4/6 timeout cascade; driver recovers, WiFi
stays up. Root cause not investigated.
Markus Fritsche (6):
bes2600: use request_firmware() for factory.txt read bes2600: use request_firmware() for factory.txt read
bes2600: default STANDARD_FACTORY_EFUSE_FLAG off for PineTab2 bes2600: default STANDARD_FACTORY_EFUSE_FLAG off for PineTab2
factory.txt format factory.txt format
@@ -140,17 +168,18 @@ Markus Fritsche (6):
bes2600: remove userspace /dev/bes2600 character device interface bes2600: remove userspace /dev/bes2600 character device interface
bes2600: enable CONFIG_BES2600_TESTMODE by default + fix bit-rotted bes2600: enable CONFIG_BES2600_TESTMODE by default + fix bit-rotted
testmode plumbing testmode plumbing
bes2600: bounce SDIO TX buffers to avoid DMA OOB read
bes2600/Makefile | 6 +- bes2600/Makefile | 6 +-
bes2600/bes2600_factory.c | 45 ++-- bes2600/bes2600_factory.c | 45 ++--
bes2600/bes2600_factory.h | 3 + bes2600/bes2600_factory.h | 3 +
bes2600/bes2600_sdio.c | 4 + bes2600/bes2600_sdio.c | 43 +++-
bes2600/bes_chardev.c | 519 -------------------------------------- bes2600/bes_chardev.c | 519 --------------------------------------
bes2600/bes_log.h | 23 ++ bes2600/bes_log.h | 23 ++
bes2600/bes_pwr.c | 20 +- bes2600/bes_pwr.c | 20 +-
bes2600/sta.c | 6 +- bes2600/sta.c | 6 +-
bes2600/wsm.h | 2 - bes2600/wsm.h | 2 -
9 files changed, 79 insertions(+), 549 deletions(-) 9 files changed, 117 insertions(+), 550 deletions(-)
-- --
2.53.0 2.53.0
@@ -1,7 +1,10 @@
From d18aa6a9bc03a03e455434f83577892aa1a60ffe Mon Sep 17 00:00:00 2001 From d18aa6a9bc03a03e455434f83577892aa1a60ffe Mon Sep 17 00:00:00 2001
Message-ID: <d18aa6a9bc03a03e455434f83577892aa1a60ffe.1776940528.git.fritsche.markus@gmail.com>
In-Reply-To: <cover.1776940528.git.fritsche.markus@gmail.com>
References: <cover.1776940528.git.fritsche.markus@gmail.com>
From: Markus Fritsche <fritsche.markus@gmail.com> From: Markus Fritsche <fritsche.markus@gmail.com>
Date: Wed, 22 Apr 2026 10:09:44 +0200 Date: Wed, 22 Apr 2026 10:09:44 +0200
Subject: [PATCH 1/6] bes2600: use request_firmware() for factory.txt read Subject: [PATCH 1/7] bes2600: use request_firmware() for factory.txt read
The BES2600 factory calibration file (bes2600_factory.txt) was being 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 via filp_open() + kernel_read() from a hard-coded absolute path baked in
@@ -1,7 +1,10 @@
From a826f4db7d97a3a872d92079db37dbdaf9a0cdec Mon Sep 17 00:00:00 2001 From a826f4db7d97a3a872d92079db37dbdaf9a0cdec Mon Sep 17 00:00:00 2001
Message-ID: <a826f4db7d97a3a872d92079db37dbdaf9a0cdec.1776940528.git.fritsche.markus@gmail.com>
In-Reply-To: <cover.1776940528.git.fritsche.markus@gmail.com>
References: <cover.1776940528.git.fritsche.markus@gmail.com>
From: Markus Fritsche <fritsche.markus@gmail.com> From: Markus Fritsche <fritsche.markus@gmail.com>
Date: Wed, 22 Apr 2026 12:17:56 +0200 Date: Wed, 22 Apr 2026 12:17:56 +0200
Subject: [PATCH 2/6] bes2600: default STANDARD_FACTORY_EFUSE_FLAG off for Subject: [PATCH 2/7] bes2600: default STANDARD_FACTORY_EFUSE_FLAG off for
PineTab2 factory.txt format PineTab2 factory.txt format
MIME-Version: 1.0 MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8 Content-Type: text/plain; charset=UTF-8
@@ -1,7 +1,10 @@
From c7ba2044b78cc3778763737daea60c9912b710c6 Mon Sep 17 00:00:00 2001 From c7ba2044b78cc3778763737daea60c9912b710c6 Mon Sep 17 00:00:00 2001
Message-ID: <c7ba2044b78cc3778763737daea60c9912b710c6.1776940528.git.fritsche.markus@gmail.com>
In-Reply-To: <cover.1776940528.git.fritsche.markus@gmail.com>
References: <cover.1776940528.git.fritsche.markus@gmail.com>
From: Markus Fritsche <fritsche.markus@gmail.com> From: Markus Fritsche <fritsche.markus@gmail.com>
Date: Wed, 22 Apr 2026 13:18:38 +0200 Date: Wed, 22 Apr 2026 13:18:38 +0200
Subject: [PATCH 3/6] bes2600: thread struct device * through factory Subject: [PATCH 3/7] bes2600: thread struct device * through factory
request_firmware() call request_firmware() call
Follow-up to \"bes2600: use request_firmware() for factory.txt read\". Follow-up to \"bes2600: use request_firmware() for factory.txt read\".
@@ -1,7 +1,10 @@
From 108d3967eac4ba3a6e0f508d865a5f221b49079d Mon Sep 17 00:00:00 2001 From 108d3967eac4ba3a6e0f508d865a5f221b49079d Mon Sep 17 00:00:00 2001
Message-ID: <108d3967eac4ba3a6e0f508d865a5f221b49079d.1776940528.git.fritsche.markus@gmail.com>
In-Reply-To: <cover.1776940528.git.fritsche.markus@gmail.com>
References: <cover.1776940528.git.fritsche.markus@gmail.com>
From: Markus Fritsche <fritsche.markus@gmail.com> From: Markus Fritsche <fritsche.markus@gmail.com>
Date: Wed, 22 Apr 2026 12:37:45 +0200 Date: Wed, 22 Apr 2026 12:37:45 +0200
Subject: [PATCH 4/6] bes2600: gate device LP-mode entry on successful per-VIF Subject: [PATCH 4/7] bes2600: gate device LP-mode entry on successful per-VIF
firmware handshake firmware handshake
bes2600_pwr_enter_lp_mode() drives the transition to low-power for each bes2600_pwr_enter_lp_mode() drives the transition to low-power for each
@@ -1,7 +1,10 @@
From 3304b13a2b2e7388ebf076c2bcb7f02cd0b6800f Mon Sep 17 00:00:00 2001 From 3304b13a2b2e7388ebf076c2bcb7f02cd0b6800f Mon Sep 17 00:00:00 2001
Message-ID: <3304b13a2b2e7388ebf076c2bcb7f02cd0b6800f.1776940528.git.fritsche.markus@gmail.com>
In-Reply-To: <cover.1776940528.git.fritsche.markus@gmail.com>
References: <cover.1776940528.git.fritsche.markus@gmail.com>
From: Markus Fritsche <fritsche.markus@gmail.com> From: Markus Fritsche <fritsche.markus@gmail.com>
Date: Wed, 22 Apr 2026 12:55:18 +0200 Date: Wed, 22 Apr 2026 12:55:18 +0200
Subject: [PATCH 5/6] bes2600: remove userspace /dev/bes2600 character device Subject: [PATCH 5/7] bes2600: remove userspace /dev/bes2600 character device
interface interface
bes_chardev.c implemented a custom character device at /dev/bes2600 with bes_chardev.c implemented a custom character device at /dev/bes2600 with
@@ -1,7 +1,10 @@
From 6f13e008d21d453db486f707f47340a0a17e650b Mon Sep 17 00:00:00 2001 From 6f13e008d21d453db486f707f47340a0a17e650b Mon Sep 17 00:00:00 2001
Message-ID: <6f13e008d21d453db486f707f47340a0a17e650b.1776940528.git.fritsche.markus@gmail.com>
In-Reply-To: <cover.1776940528.git.fritsche.markus@gmail.com>
References: <cover.1776940528.git.fritsche.markus@gmail.com>
From: Markus Fritsche <fritsche.markus@gmail.com> From: Markus Fritsche <fritsche.markus@gmail.com>
Date: Wed, 22 Apr 2026 13:04:27 +0200 Date: Wed, 22 Apr 2026 13:04:27 +0200
Subject: [PATCH 6/6] bes2600: enable CONFIG_BES2600_TESTMODE by default + fix Subject: [PATCH 6/7] bes2600: enable CONFIG_BES2600_TESTMODE by default + fix
bit-rotted testmode plumbing bit-rotted testmode plumbing
MIME-Version: 1.0 MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8 Content-Type: text/plain; charset=UTF-8
@@ -0,0 +1,126 @@
From 10a05d21bfe4563f963e16d65228fd7a713c143d Mon Sep 17 00:00:00 2001
Message-ID: <10a05d21bfe4563f963e16d65228fd7a713c143d.1776940528.git.fritsche.markus@gmail.com>
In-Reply-To: <cover.1776940528.git.fritsche.markus@gmail.com>
References: <cover.1776940528.git.fritsche.markus@gmail.com>
From: Markus Fritsche <fritsche.markus@gmail.com>
Date: Thu, 23 Apr 2026 11:58:31 +0200
Subject: [PATCH 7/7] 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
sg_set_buf(&sg[scatters], tx_buffer->buf, align) in sdio_tx_work().
tx_buffer->buf typically aliases into an skb linear head whose
allocated size matches tx_buffer->len, not the block-aligned
align. The DMA engine (swiotlb / dw_mci IDMAC) therefore reads up
to one block past the end of the skb. On a PineTab2 with KFENCE
enabled this fires as:
BUG: KFENCE: out-of-bounds read in __pi_memcpy_generic
Out-of-bounds read at ... (704B right of kfence-#...):
__pi_memcpy_generic
swiotlb_tbl_map_single
swiotlb_map
dma_direct_map_sg
__dma_map_sg_attrs
dma_map_sg_attrs
dw_mci_pre_dma_transfer
__dw_mci_start_request
...
bes_sdio_memcpy_to_io_helper+0x18c/0x288 [bes2600]
sdio_tx_work+0x2b4/0x4a0 [bes2600]
allocated by ... pskb_expand_head / validate_xmit_skb / tcp_*
In addition to being undefined behavior, the padding bytes (which
come from whatever memory follows the skb) are transmitted to the
peer, leaking kernel memory on the air.
Allocate a driver-owned DMA-page bounce buffer sized to
MAX_SDIO_TRANSFER_LEN and use it as the scatter-gather backing for
sdio_tx_work. Each TX buffer is copied into its bounce slot and the
tail (align - tx_buffer->len bytes) is zeroed. This mirrors the
existing bounce pattern already used by bes2600_sdio_memcpy_toio()
via single_gathered_buffer; a separate allocation is used for the
TX path because single_gathered_buffer is only serialised via
sdio_claim_host and sdio_tx_work accumulates scatter entries before
claiming the bus.
Signed-off-by: Markus Fritsche <fritsche.markus@gmail.com>
---
bes2600/bes2600_sdio.c | 39 ++++++++++++++++++++++++++++++++++++++-
1 file changed, 38 insertions(+), 1 deletion(-)
diff --git a/bes2600/bes2600_sdio.c b/bes2600/bes2600_sdio.c
index 371ef4f..3e04e8c 100644
--- a/bes2600/bes2600_sdio.c
+++ b/bes2600/bes2600_sdio.c
@@ -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];
+ u8 *tx_bounce;
u32 tx_data_cnt;
u32 tx_xfer_cnt;
u32 tx_proc_cnt;
@@ -1136,7 +1137,26 @@ static void sdio_tx_work(struct work_struct *work)
}
}
- sg_set_buf(&sg[scatters], tx_buffer->buf, align);
+ /*
+ * The transfer length is rounded up to the SDIO block
+ * size, but tx_buffer->buf is only tx_buffer->len bytes
+ * long (it usually aliases into an skb linear head).
+ * Copy into a driver-owned bounce buffer and zero-pad
+ * to the aligned size; otherwise DMA reads past the
+ * skb and leaks adjacent kernel memory on the wire --
+ * observed as KFENCE OOB reads from
+ * bes_sdio_memcpy_to_io_helper via dma_map_sg.
+ */
+ if (WARN_ON_ONCE(total_len + align > MAX_SDIO_TRANSFER_LEN))
+ goto flush_previous;
+ memcpy(self->tx_bounce + total_len,
+ tx_buffer->buf, tx_buffer->len);
+ if (align > tx_buffer->len)
+ memset(self->tx_bounce + total_len +
+ tx_buffer->len, 0,
+ align - tx_buffer->len);
+ sg_set_buf(&sg[scatters],
+ self->tx_bounce + total_len, align);
total_len += align;
++scatters;
/*del_node:*/
@@ -1857,6 +1877,17 @@ static int bes2600_sdio_probe(struct sdio_func *func,
if (!self->single_gathered_buffer)
return -ENOMEM;
#endif
+#ifdef BES_SDIO_TX_MULTIPLE_ENABLE
+ self->tx_bounce = (u8 *)__get_dma_pages(GFP_KERNEL,
+ get_order(MAX_SDIO_TRANSFER_LEN));
+ if (!self->tx_bounce) {
+#ifndef SDIO_HOST_ADMA_SUPPORT
+ free_pages((unsigned long)self->single_gathered_buffer,
+ get_order(MAX_SDIO_TRANSFER_LEN));
+#endif
+ return -ENOMEM;
+ }
+#endif
#ifdef BES_SDIO_RXTX_TOGGLE
self->fw_started = false;
#endif
@@ -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));
}
+#endif
+#ifdef BES_SDIO_TX_MULTIPLE_ENABLE
+ if (self->tx_bounce) {
+ free_pages((unsigned long)self->tx_bounce,
+ get_order(MAX_SDIO_TRANSFER_LEN));
+ }
#endif
kfree(self);
}
--
2.53.0