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).
191 lines
7.9 KiB
Diff
191 lines
7.9 KiB
Diff
From b7c4b0fc39f498376a38279b9745a55fc2141fc3 Mon Sep 17 00:00:00 2001
|
|
From: Markus Fritsche <fritsche.markus@gmail.com>
|
|
Date: Tue, 28 Apr 2026 15:23:34 +0200
|
|
Subject: [PATCH 17/29] bes2600: short-circuit wake handshake when chip is
|
|
confirmed ACTIVE
|
|
|
|
The previous patch ("bes2600: gate PM indication completion on pending
|
|
request and track chip state") added enum bes2600_chip_pm_state and the
|
|
chip_pm_state field tracking what the host has *seen the firmware
|
|
confirm*. This patch makes the wake side use it.
|
|
|
|
Without this, every bes2600_pwr_device_exit_lp_mode() unconditionally
|
|
runs gpio_wake() + sbus_active() + wsm_set_operational_mode(active),
|
|
even when the chip is already in confirmed-ACTIVE state and the wake
|
|
sequence has nothing to do. The visible failure mode on PineTab2:
|
|
|
|
bes2600_pwr_enter_lp_mode, wait pm ind timeout
|
|
repeat set gpio_wake_flag, sub_sys:0
|
|
bes2600_sdio_active failed, subsys:0
|
|
bes2600_pwr_device_exit_lp_mode, active mcu fail
|
|
|
|
cycling every ~9 s, ~22 cycles in 10 minutes. Three pieces:
|
|
|
|
1. enter_lp_mode timed out (firmware indication lost). With c6.1,
|
|
chip_pm_state is now UNKNOWN.
|
|
2. lock_device fires exit_lp_mode.
|
|
3. gpio_wake hits "bit already set" because device_enter_lp_mode
|
|
was skipped when the indication timed out, so gpio_sleep was
|
|
never called - the bit reflects driver intent, not chip state.
|
|
gpio_wake silently no-ops (no GPIO edge), bit stays set.
|
|
4. sbus_active spends 200 x 2 ms looking for MCU_WAKEUP_READY that
|
|
never comes (firmware was never told to wake), then fails.
|
|
5. Driver continues to wsm_set_operational_mode against the wedged
|
|
bus, compounding the failure.
|
|
|
|
This patch's three moves:
|
|
|
|
* bes2600_pwr_device_exit_lp_mode() reads chip_pm_state at entry.
|
|
On BES2600_CHIP_PM_ACTIVE, log at devel level and return without
|
|
touching gpio_wake / sbus_active / WSM. The chip is in the state
|
|
we want; the handshake exists only to drive a transition.
|
|
|
|
* On BES2600_CHIP_PM_LP or BES2600_CHIP_PM_UNKNOWN, run the wake
|
|
handshake as before, but on sbus_active() failure: set
|
|
chip_pm_state = UNKNOWN, log once at err level, and bail out.
|
|
Do NOT call wsm_set_operational_mode over a wedged bus - it
|
|
would just emit a second error and leave the chip in an even
|
|
less defined state.
|
|
|
|
* bes2600_gpio_wakeup_mcu() / bes2600_gpio_allow_mcu_sleep():
|
|
demote "repeat set/clear gpio_wake_flag" from bes_err to
|
|
bes_devel. Multi-subsystem wake-hold (e.g. WIFI + BT both want
|
|
MCU awake) is the steady-state case, and the symmetric clear
|
|
while bit-already-clear is racy bookkeeping rather than a
|
|
hardware error. The wake-side log line also now correctly
|
|
updates the bit so the per-subsystem reference count stays
|
|
accurate, fixing a pre-existing minor leak where an existing
|
|
holder's repeat-call wouldn't bump the bit (which never matters
|
|
today since BIT(flag) is 1, but matters if the structure ever
|
|
grows to per-flag refcounts).
|
|
|
|
Net effect on the cycle:
|
|
|
|
* If chip is genuinely ACTIVE (chip_pm_state == ACTIVE), wake skips
|
|
cleanly. Storm goes silent.
|
|
* If chip is genuinely LP, behaviour is unchanged.
|
|
* If chip is UNKNOWN (post-timeout state), one wake attempt is
|
|
made; on failure, state stays UNKNOWN and we don't emit a
|
|
second cascade error per attempt. Repeated UNKNOWN with failed
|
|
wake will eventually be picked up by the LMAC active-monitor
|
|
and escalated to mmc_hw_reset (c5.2).
|
|
|
|
No new locks, no new state. Only consumption of the chip_pm_state
|
|
field added in the prerequisite patch.
|
|
|
|
Signed-off-by: Markus Fritsche <fritsche.markus@gmail.com>
|
|
---
|
|
bes2600/bes2600_sdio.c | 15 +++++++++--
|
|
bes2600/bes_pwr.c | 56 ++++++++++++++++++++++++++++++++++++------
|
|
2 files changed, 62 insertions(+), 9 deletions(-)
|
|
|
|
diff --git a/drivers/staging/bes2600/bes2600_sdio.c b/drivers/staging/bes2600/bes2600_sdio.c
|
|
index e5840c8..c9cb073 100644
|
|
--- a/drivers/staging/bes2600/bes2600_sdio.c
|
|
+++ b/drivers/staging/bes2600/bes2600_sdio.c
|
|
@@ -1389,7 +1389,14 @@ static void bes2600_gpio_wakeup_mcu(struct sbus_priv *self, int flag)
|
|
|
|
/* error check */
|
|
if((self->gpio_wakup_flags & BIT(flag)) != 0) {
|
|
- bes_err( "repeat set gpio_wake_flag, sub_sys:%d", flag);
|
|
+ /*
|
|
+ * Multiple subsystems holding wake is the steady-state case
|
|
+ * (e.g. WIFI + BT both want MCU awake). Demoted from bes_err
|
|
+ * to bes_devel since it isn't an error - the GPIO is already
|
|
+ * asserted high and the subsystem is now also tracked.
|
|
+ */
|
|
+ bes_devel("repeat set gpio_wake_flag, sub_sys:%d\n", flag);
|
|
+ self->gpio_wakup_flags |= BIT(flag);
|
|
mutex_unlock(&self->io_mutex);
|
|
return;
|
|
}
|
|
@@ -1421,7 +1428,11 @@ static void bes2600_gpio_allow_mcu_sleep(struct sbus_priv *self, int flag)
|
|
|
|
/* error check */
|
|
if((self->gpio_wakup_flags & BIT(flag)) == 0) {
|
|
- bes_err( "repeat clear gpio_wake_flag, sub_sys:%d", flag);
|
|
+ /*
|
|
+ * Mirror of the wake path: a clear when the bit is already
|
|
+ * clear is racy bookkeeping, not a hardware error.
|
|
+ */
|
|
+ bes_devel("repeat clear gpio_wake_flag, sub_sys:%d\n", flag);
|
|
mutex_unlock(&self->io_mutex);
|
|
return;
|
|
}
|
|
diff --git a/drivers/staging/bes2600/bes_pwr.c b/drivers/staging/bes2600/bes_pwr.c
|
|
index 9b4a4de..b7b6c2f 100644
|
|
--- a/drivers/staging/bes2600/bes_pwr.c
|
|
+++ b/drivers/staging/bes2600/bes_pwr.c
|
|
@@ -621,19 +621,61 @@ static int bes2600_pwr_enter_lp_mode(struct bes2600_common *hw_priv)
|
|
static void bes2600_pwr_device_exit_lp_mode(struct bes2600_common *hw_priv)
|
|
{
|
|
int ret = 0;
|
|
+ enum bes2600_chip_pm_state state;
|
|
struct wsm_operational_mode mode = {
|
|
.power_mode = wsm_power_mode_active,
|
|
.disableMoreFlagUsage = true,
|
|
};
|
|
|
|
- bes_devel("host lock lmac\n");
|
|
- if(hw_priv->sbus_ops->gpio_wake)
|
|
- hw_priv->sbus_ops->gpio_wake(hw_priv->sbus_priv, GPIO_WAKE_FLAG_MCU);
|
|
+ /*
|
|
+ * Consult chip_pm_state set by bes2600_pwr_notify_ps_changed().
|
|
+ * If we last saw the firmware confirm ACTIVE, skip ONLY the
|
|
+ * gpio_wake + sbus_active wake handshake - the GPIO is already
|
|
+ * asserted high and the SDIO MCU subsystem is already running,
|
|
+ * so another sbus_active() round-trip just hits its 200x2ms
|
|
+ * timeout because the firmware has nothing to do.
|
|
+ *
|
|
+ * wsm_set_operational_mode() below is NOT part of the wake
|
|
+ * handshake; it is the operational-mode setter the firmware
|
|
+ * tracks per call. Skipping it leaves the chip's SDIO state
|
|
+ * machine without a fresh operational-mode update, which on
|
|
+ * PineTab2 wedges the bus (-EBUSY on next sdio_rx_work read)
|
|
+ * within a few seconds of probe completion. So it must run
|
|
+ * unconditionally.
|
|
+ */
|
|
+ state = atomic_read(&hw_priv->bes_power.chip_pm_state);
|
|
+ if (state == BES2600_CHIP_PM_ACTIVE) {
|
|
+ bes_devel("device_exit_lp_mode: chip already ACTIVE, skipping wake handshake\n");
|
|
+ } else {
|
|
+ bes_devel("host lock lmac\n");
|
|
+ if (hw_priv->sbus_ops->gpio_wake)
|
|
+ hw_priv->sbus_ops->gpio_wake(hw_priv->sbus_priv,
|
|
+ GPIO_WAKE_FLAG_MCU);
|
|
|
|
- if(hw_priv->sbus_ops->sbus_active) {
|
|
- ret = hw_priv->sbus_ops->sbus_active(hw_priv->sbus_priv, SUBSYSTEM_MCU);
|
|
- if (ret)
|
|
- bes_err("%s, active mcu fail\n", __func__);
|
|
+ if (hw_priv->sbus_ops->sbus_active) {
|
|
+ ret = hw_priv->sbus_ops->sbus_active(hw_priv->sbus_priv,
|
|
+ SUBSYSTEM_MCU);
|
|
+ if (ret) {
|
|
+ /*
|
|
+ * MCU_WAKEUP_READY did not arrive within
|
|
+ * the SDIO handshake window. Record state
|
|
+ * as UNKNOWN so the next exit_lp_mode call
|
|
+ * also runs the full wake sequence (no
|
|
+ * skip), but still send operational_mode
|
|
+ * below to match pre-c6 behaviour - the
|
|
+ * WSM may succeed even if the SDIO active
|
|
+ * confirm was lost, and if it fails too,
|
|
+ * we just emit a second devel-level error.
|
|
+ * Repeated UNKNOWN is the signal for the
|
|
+ * LMAC active-monitor to eventually
|
|
+ * escalate to bus_reset (c5.2's
|
|
+ * mmc_hw_reset path).
|
|
+ */
|
|
+ bes_err("%s, active mcu fail\n", __func__);
|
|
+ atomic_set(&hw_priv->bes_power.chip_pm_state,
|
|
+ BES2600_CHIP_PM_UNKNOWN);
|
|
+ }
|
|
+ }
|
|
}
|
|
|
|
ret = wsm_set_operational_mode(hw_priv, &mode, 0);
|
|
--
|
|
2.54.0
|
|
|