From c9057cac2c6db50490b12533b7df995cac8d1425 Mon Sep 17 00:00:00 2001 From: Markus Fritsche Date: Tue, 28 Apr 2026 15:51:58 +0200 Subject: [PATCH] patches: refresh c6.1 + c6.2 (init UNKNOWN; always run wsm_set_operational_mode) --- ...indication-completion-on-pending-req.patch | 6 +- ...indication-completion-on-pending-req.patch | 6 +- ...rcuit-wake-handshake-when-chip-is-co.patch | 93 +++++++++++-------- ...rcuit-wake-handshake-when-chip-is-co.patch | 93 +++++++++++-------- 4 files changed, 116 insertions(+), 82 deletions(-) diff --git a/patches/pm-state-resync-danctnix/0001-bes2600-gate-PM-indication-completion-on-pending-req.patch b/patches/pm-state-resync-danctnix/0001-bes2600-gate-PM-indication-completion-on-pending-req.patch index 31f67dc92..7496fb665 100644 --- a/patches/pm-state-resync-danctnix/0001-bes2600-gate-PM-indication-completion-on-pending-req.patch +++ b/patches/pm-state-resync-danctnix/0001-bes2600-gate-PM-indication-completion-on-pending-req.patch @@ -1,4 +1,4 @@ -From 699e4b59a90c396dc95df8cf8a233824f9c0fedf Mon Sep 17 00:00:00 2001 +From bc6236ce926a8da6f568a86fb65541034b1e074b Mon Sep 17 00:00:00 2001 From: Markus Fritsche Date: Tue, 28 Apr 2026 15:05:27 +0200 Subject: [PATCH] bes2600: gate PM indication completion on pending request and @@ -72,7 +72,7 @@ Signed-off-by: Markus Fritsche 2 files changed, 74 insertions(+), 7 deletions(-) diff --git a/drivers/staging/bes2600/bes_pwr.c b/drivers/staging/bes2600/bes_pwr.c -index f62ae226d295..0da1be272392 100644 +index f62ae226d295..ec0e0cc14ea4 100644 --- a/drivers/staging/bes2600/bes_pwr.c +++ b/drivers/staging/bes2600/bes_pwr.c @@ -524,7 +524,17 @@ static int bes2600_pwr_enter_lp_mode(struct bes2600_common *hw_priv) @@ -135,7 +135,7 @@ index f62ae226d295..0da1be272392 100644 hw_priv->bes_power.power_up_task = NULL; mutex_init(&hw_priv->bes_power.pwr_mutex); atomic_set(&hw_priv->bes_power.dev_state, 0); -+ atomic_set(&hw_priv->bes_power.chip_pm_state, BES2600_CHIP_PM_ACTIVE); ++ atomic_set(&hw_priv->bes_power.chip_pm_state, BES2600_CHIP_PM_UNKNOWN); init_completion(&hw_priv->bes_power.pm_enter_cmpl); sema_init(&hw_priv->bes_power.sync_lock, 1); device_set_wakeup_capable(hw_priv->pdev, true); diff --git a/patches/pm-state-resync/0001-bes2600-gate-PM-indication-completion-on-pending-req.patch b/patches/pm-state-resync/0001-bes2600-gate-PM-indication-completion-on-pending-req.patch index 8cb12ca46..87364e66e 100644 --- a/patches/pm-state-resync/0001-bes2600-gate-PM-indication-completion-on-pending-req.patch +++ b/patches/pm-state-resync/0001-bes2600-gate-PM-indication-completion-on-pending-req.patch @@ -1,4 +1,4 @@ -From 3853aadb48ae5f328d583a0ff2349c20589dd80b Mon Sep 17 00:00:00 2001 +From 44c520fdc0c196f44d7825ef60fa7932d2a60882 Mon Sep 17 00:00:00 2001 From: Markus Fritsche Date: Tue, 28 Apr 2026 15:05:27 +0200 Subject: [PATCH] bes2600: gate PM indication completion on pending request and @@ -72,7 +72,7 @@ Signed-off-by: Markus Fritsche 2 files changed, 74 insertions(+), 7 deletions(-) diff --git a/bes2600/bes_pwr.c b/bes2600/bes_pwr.c -index 474b6f1..cd1b8cd 100644 +index 474b6f1..820449c 100644 --- a/bes2600/bes_pwr.c +++ b/bes2600/bes_pwr.c @@ -524,7 +524,17 @@ static int bes2600_pwr_enter_lp_mode(struct bes2600_common *hw_priv) @@ -135,7 +135,7 @@ index 474b6f1..cd1b8cd 100644 hw_priv->bes_power.power_up_task = NULL; mutex_init(&hw_priv->bes_power.pwr_mutex); atomic_set(&hw_priv->bes_power.dev_state, 0); -+ atomic_set(&hw_priv->bes_power.chip_pm_state, BES2600_CHIP_PM_ACTIVE); ++ atomic_set(&hw_priv->bes_power.chip_pm_state, BES2600_CHIP_PM_UNKNOWN); init_completion(&hw_priv->bes_power.pm_enter_cmpl); sema_init(&hw_priv->bes_power.sync_lock, 1); device_set_wakeup_capable(hw_priv->pdev, true); diff --git a/patches/pm-wake-consume-state-danctnix/0001-bes2600-short-circuit-wake-handshake-when-chip-is-co.patch b/patches/pm-wake-consume-state-danctnix/0001-bes2600-short-circuit-wake-handshake-when-chip-is-co.patch index 06da38647..0688bb8c5 100644 --- a/patches/pm-wake-consume-state-danctnix/0001-bes2600-short-circuit-wake-handshake-when-chip-is-co.patch +++ b/patches/pm-wake-consume-state-danctnix/0001-bes2600-short-circuit-wake-handshake-when-chip-is-co.patch @@ -1,4 +1,4 @@ -From 1c5a06832f1cf7605aaf6a45cd029d1dad40b055 Mon Sep 17 00:00:00 2001 +From aea2b411713a192db26c3144abcda21914520705 Mon Sep 17 00:00:00 2001 From: Markus Fritsche Date: Tue, 28 Apr 2026 15:23:35 +0200 Subject: [PATCH] bes2600: short-circuit wake handshake when chip is confirmed @@ -75,9 +75,9 @@ field added in the prerequisite patch. Signed-off-by: Markus Fritsche --- - drivers/staging/bes2600/bes2600_sdio.c | 15 ++++++++++-- - drivers/staging/bes2600/bes_pwr.c | 34 +++++++++++++++++++++++++- - 2 files changed, 46 insertions(+), 3 deletions(-) + drivers/staging/bes2600/bes2600_sdio.c | 15 ++++++- + drivers/staging/bes2600/bes_pwr.c | 58 ++++++++++++++++++++++---- + 2 files changed, 63 insertions(+), 10 deletions(-) diff --git a/drivers/staging/bes2600/bes2600_sdio.c b/drivers/staging/bes2600/bes2600_sdio.c index b9d836fab7af..929503547cfd 100644 @@ -113,10 +113,10 @@ index b9d836fab7af..929503547cfd 100644 return; } diff --git a/drivers/staging/bes2600/bes_pwr.c b/drivers/staging/bes2600/bes_pwr.c -index 0da1be272392..e5e4d4d8944c 100644 +index ec0e0cc14ea4..43087ca3b0ed 100644 --- a/drivers/staging/bes2600/bes_pwr.c +++ b/drivers/staging/bes2600/bes_pwr.c -@@ -597,19 +597,51 @@ static int bes2600_pwr_enter_lp_mode(struct bes2600_common *hw_priv) +@@ -597,19 +597,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; @@ -126,45 +126,62 @@ index 0da1be272392..e5e4d4d8944c 100644 .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); +- +- 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__); + /* + * Consult chip_pm_state set by bes2600_pwr_notify_ps_changed(). -+ * If we last saw the firmware confirm ACTIVE, skip the wake-up -+ * handshake entirely - the GPIO is already asserted, the SDIO -+ * MCU subsystem is already running, and another sbus_active() -+ * round-trip just hits its 200x2ms timeout because the firmware -+ * has nothing to do. This is the deterministic source of the -+ * "active mcu fail" cycle in dmesg when an enter_lp_mode timeout -+ * left bookkeeping desynced. ++ * 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"); -+ return; -+ } ++ } 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); + - 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) -+ if (ret) { -+ /* -+ * The firmware did not raise MCU_WAKEUP_READY within -+ * the SDIO handshake window. Mark chip state UNKNOWN -+ * and bail out before issuing wsm_set_operational_mode -+ * over a wedged bus - that would just compound the -+ * failure. The next exit_lp_mode call will see UNKNOWN -+ * and try the wake again from scratch; if it stays -+ * UNKNOWN across multiple cycles, the LMAC active- -+ * monitor will 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); -+ return; ++ 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); ++ } + } } diff --git a/patches/pm-wake-consume-state/0001-bes2600-short-circuit-wake-handshake-when-chip-is-co.patch b/patches/pm-wake-consume-state/0001-bes2600-short-circuit-wake-handshake-when-chip-is-co.patch index c67549e37..6de5128cb 100644 --- a/patches/pm-wake-consume-state/0001-bes2600-short-circuit-wake-handshake-when-chip-is-co.patch +++ b/patches/pm-wake-consume-state/0001-bes2600-short-circuit-wake-handshake-when-chip-is-co.patch @@ -1,4 +1,4 @@ -From b6608f14fe81f38f53b5c3e7e6a739cdf20237f8 Mon Sep 17 00:00:00 2001 +From 1e6ccf95bba799e8599ae37c936aab76b9fc9018 Mon Sep 17 00:00:00 2001 From: Markus Fritsche Date: Tue, 28 Apr 2026 15:23:34 +0200 Subject: [PATCH] bes2600: short-circuit wake handshake when chip is confirmed @@ -75,9 +75,9 @@ field added in the prerequisite patch. Signed-off-by: Markus Fritsche --- - bes2600/bes2600_sdio.c | 15 +++++++++++++-- - bes2600/bes_pwr.c | 34 +++++++++++++++++++++++++++++++++- - 2 files changed, 46 insertions(+), 3 deletions(-) + bes2600/bes2600_sdio.c | 15 +++++++++-- + bes2600/bes_pwr.c | 58 ++++++++++++++++++++++++++++++++++++------ + 2 files changed, 63 insertions(+), 10 deletions(-) diff --git a/bes2600/bes2600_sdio.c b/bes2600/bes2600_sdio.c index 3e04e8c..acc0f19 100644 @@ -113,10 +113,10 @@ index 3e04e8c..acc0f19 100644 return; } diff --git a/bes2600/bes_pwr.c b/bes2600/bes_pwr.c -index cd1b8cd..22074db 100644 +index 820449c..2839ce7 100644 --- a/bes2600/bes_pwr.c +++ b/bes2600/bes_pwr.c -@@ -597,19 +597,51 @@ static int bes2600_pwr_enter_lp_mode(struct bes2600_common *hw_priv) +@@ -597,19 +597,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; @@ -126,45 +126,62 @@ index cd1b8cd..22074db 100644 .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); +- +- 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__); + /* + * Consult chip_pm_state set by bes2600_pwr_notify_ps_changed(). -+ * If we last saw the firmware confirm ACTIVE, skip the wake-up -+ * handshake entirely - the GPIO is already asserted, the SDIO -+ * MCU subsystem is already running, and another sbus_active() -+ * round-trip just hits its 200x2ms timeout because the firmware -+ * has nothing to do. This is the deterministic source of the -+ * "active mcu fail" cycle in dmesg when an enter_lp_mode timeout -+ * left bookkeeping desynced. ++ * 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"); -+ return; -+ } ++ } 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); + - 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) -+ if (ret) { -+ /* -+ * The firmware did not raise MCU_WAKEUP_READY within -+ * the SDIO handshake window. Mark chip state UNKNOWN -+ * and bail out before issuing wsm_set_operational_mode -+ * over a wedged bus - that would just compound the -+ * failure. The next exit_lp_mode call will see UNKNOWN -+ * and try the wake again from scratch; if it stays -+ * UNKNOWN across multiple cycles, the LMAC active- -+ * monitor will 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); -+ return; ++ 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); ++ } + } }