8b356aa11f
Replaces the 13 broken DKMS-path -danctnix mirrors from PR #17 + adds 9 new series-dirs for the c-stack patches that were never split (Patches A/B/C-v3/F/D/E/C2/G/H) + retires the cumulative-c5x-danctnix single-file interim from fleet/ohm.yaml. Mechanism: cd marfrit/bes2600-dkms-mobian git format-patch fe73571..cleanups --no-merges -o /tmp/cleanups/ git format-patch cleanups..bes2600/bh-c-fossil-cleanup --no-merges -o /tmp/h/ for each commit: route to series-dir, sed-rewrite a/bes2600/foo.c -> a/drivers/staging/bes2600/foo.c The 29 cleanups commits + 1 Patch H commit map to 25 series-dirs (a few series-dirs get multiple commits: lmac-recover gets c5.2 + c5.2.1 as 0001+0002; cw1200-fix-backports gets F3+F2+F1 as 0001-0003; factory-series gets request_firmware + STANDARD_FACTORY_EFUSE_FLAG as 0001+0002). fleet/ohm.yaml apply order matches cleanups commit chronology, which is what produced the working c5x interim. cumulative.patch from ka-promote ohm now has 32 resolved patches (29 cleanups + 1 Patch H + scan-filter-5ghz + xor-neon SCS + besser#18-fix), 276 079 bytes, b2sum 7418db5ddf8fe938b130bc9d0e9f7dc9060f3a13703cd50757835ac43140a13... Apply order in cleanups + bh-c-fossil-cleanup: 1 factory-series (c1 + factory-no-efuse-flag) 3 factory-thread-dev 4 pm-gate-on-handshake 5 remove-chardev-user-interface 6 enable-testmode 7 tx-sdio-dma-oob-danctnix (was 'staging-prep-series') 8 factory-drop-kernel-write-danctnix 9 drop-dpd-file-paths-danctnix 10 drop-orphan-file-io-danctnix 11 pm-timeout-silence-danctnix 12 scan-defer-on-reject-danctnix (c5.1) 13 scan-defer-backoff-tune-danctnix (c5.1.1) 14 lmac-recover-via-mmc-hw-reset-danctnix (c5.2 + c5.2.1) 16 pm-state-resync-danctnix (c6.1) 17 pm-wake-consume-state-danctnix (c6.2) 18 pm-detect-firmware-unsupported-danctnix (c7) 19 decrypt-storm-fast-recover-danctnix (Patch A) 20 connection-loss-fast-recover-danctnix (Patch B) 21 cw1200-fix-backports-danctnix (Patches F3 + F2 + F1) 24 sdio-rx-no-relay-danctnix (Patch C v3) 25 license-spdx-restore-attribution-danctnix (Patch G) 26 ba-lock-atomic-danctnix (Patch D) 27 ps-state-lock-skip-pm-disabled-danctnix (Patch E) 28 rx-list-batch-delivery-danctnix (Patch C2) 29 bh-c-fossil-cleanup-danctnix (Patch H) 30 scan-filter-5ghz-danctnix (besser#1) 31 arch/arm64/xor-neon-... (GCC 15 SCS) 32 queue-pending-record-lock-bh-danctnix (besser#18) Verification: pkgrel=6 build from this manifest in progress; if srcversion == 26B0003FE9F2B05DCE838C4 (pkgrel=5's), source-tree is byte-equivalent to the c5x interim + scan-filter + besser#18 stack that's currently running on ohm. Refs: #17 (the broken mirror), #28 (the interim PR that landed cumulative-c5x), #31 (ka-promote trailer normalisation followup).
726 lines
21 KiB
Diff
726 lines
21 KiB
Diff
From f68fd5530f3bc3c2dc33cc5e3408047ff21a7676 Mon Sep 17 00:00:00 2001
|
|
From: Markus Fritsche <fritsche.markus@gmail.com>
|
|
Date: Fri, 8 May 2026 08:23:20 +0200
|
|
Subject: [PATCH] =?UTF-8?q?bes2600:=20Patch=20H=20=E2=80=94=20bh.c=20hygie?=
|
|
=?UTF-8?q?ne=20cleanup=20(drop=20fossil=20blocks,=20dead=20stubs)?=
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
Per Opus structural critique §4.1 (#if 0 graveyard), §4.3 (asm
|
|
volatile("nop") placeholder), §4.4 (BUG_ON in steady-state hot
|
|
path). Pure source-tree cleanup, no functional change.
|
|
|
|
Removed:
|
|
|
|
1. bh.c lines 319-395 (76-line #if 0 block) — dead helper
|
|
functions inherited from cw1200 ancestor:
|
|
bes2600_bh_read_ctrl_reg, bes2600_get_skb, bes2600_put_skb,
|
|
bes2600_device_wakeup. Compiled out for years.
|
|
|
|
2. bh.c lines 405-873 + line 1659 (the outer #if 0 / #else /
|
|
#endif) — 468-line cw1200-ancestor bes2600_bh() function body,
|
|
preserved verbatim alongside the active impl. Same function
|
|
name, same goto labels. Maintenance hazard removed.
|
|
|
|
3. bh.c done: label body — `__bes2600_irq_enable(1)` placeholder
|
|
(commented out) + `asm volatile ("nop")` filler. Both
|
|
no-ops on bes2600 silicon.
|
|
|
|
4. bh.c post-loop "Explicitly disable device interrupts" block
|
|
(sbus lock + __bes2600_irq_enable(0) + sbus unlock) — the
|
|
stub call wrapped in lock/unlock ceremony. Dead.
|
|
|
|
5. hwio.c __bes2600_irq_enable() function definition —
|
|
`int __bes2600_irq_enable(int enable) { return 0; }`. Stub.
|
|
Removed entirely.
|
|
|
|
6. sbus.h __bes2600_irq_enable() forward declaration.
|
|
|
|
Replaced:
|
|
|
|
7. bh.c bes2600_bh outer-loop BUG_ON(hw_bufs_used > numInpChBufs)
|
|
-> WARN_ON_ONCE. The BUG_ON ran every bh-loop iteration;
|
|
tripping it on a bookkeeping bug locks the kernel up during
|
|
normal operation — the wrong response to a (recoverable)
|
|
accounting drift. WARN_ON_ONCE surfaces the issue without
|
|
taking the system down.
|
|
|
|
Why __bes2600_irq_enable was a stub on bes2600:
|
|
|
|
cw1200 has the same-named function (drivers/net/wireless/st/cw1200/
|
|
hwio.c:267) that does real work — reads ST90TDS_CONFIG_REG_ID and
|
|
toggles the ST90TDS_CONF_IRQ_RDY_ENABLE bit. bes2600 inherited
|
|
the function name + signature when forked, but the bes2600 chip's
|
|
IRQ enable is managed by sdio_claim_irq + chip-side firmware, not
|
|
by a driver-side enable register. Bestechnic kept the function as
|
|
a no-op stub (return 0). Patch H removes the dead infrastructure.
|
|
|
|
Diff scope:
|
|
|
|
- bes2600/bh.c -578/+27 (mostly deletions)
|
|
- bes2600/hwio.c -7/+7 (stub function -> comment block)
|
|
- bes2600/sbus.h -2/+1 (declaration -> comment)
|
|
- net: -578/+28 across 3 files
|
|
|
|
Build verification deferred — ohm offline. Pure-deletion change,
|
|
no semantic risk; the deleted code was either #if 0-gated
|
|
(never compiled) or stub-implementations (always returned 0).
|
|
---
|
|
bes2600/bh.c | 578 ++-----------------------------------------------
|
|
bes2600/hwio.c | 11 +-
|
|
bes2600/sbus.h | 3 +-
|
|
3 files changed, 28 insertions(+), 564 deletions(-)
|
|
|
|
diff --git a/drivers/staging/bes2600/bh.c b/drivers/staging/bes2600/bh.c
|
|
index 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
|
|
|