* [PATCH v1] Bluetooth: btintel_pcie: fix PM flow for S0ix, S3 and S4
@ 2026-08-28 9:51 Ravindra
2026-08-28 11:51 ` [v1] " bluez.test.bot
0 siblings, 1 reply; 2+ messages in thread
From: Ravindra @ 2026-08-28 9:51 UTC (permalink / raw)
To: linux-bluetooth
Cc: ravishankar.srivatsa, chethan.tumkur.narayan, kiran.k, Ravindra
Use pm_suspend_target_state to differentiate S0ix from S3/S4. Set the
controller to D3_HOT for S0ix (PM_SUSPEND_TO_IDLE) and D3_COLD for S3/S4
to prevent post-resume instability.
Remove .freeze, .thaw, and .poweroff callbacks to avoid redundant D3
handshakes that time out and abort hibernation. Add .restore to force
FLR-based firmware recovery after S4 and S3 (PM_SUSPEND_MEM), as power
is lost. S0ix resumes via a normal D0 transition.
Fixes: e57362f4911b ("Bluetooth: btintel_pcie: Add support for _suspend() / _resume()")
Assisted-by: GitHub-Copilot:GPT5
Signed-off-by: Ravindra <ravindra@intel.com>
---
drivers/bluetooth/btintel_pcie.c | 63 ++++++++++++++++----------------
drivers/bluetooth/btintel_pcie.h | 2 -
2 files changed, 32 insertions(+), 33 deletions(-)
diff --git a/drivers/bluetooth/btintel_pcie.c b/drivers/bluetooth/btintel_pcie.c
index 005c77a4f5eb..ba5d16a3b3a5 100644
--- a/drivers/bluetooth/btintel_pcie.c
+++ b/drivers/bluetooth/btintel_pcie.c
@@ -16,6 +16,7 @@
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/acpi.h>
+#include <linux/suspend.h>
#include <linux/unaligned.h>
#include <linux/devcoredump.h>
@@ -3134,11 +3135,14 @@ static void btintel_pcie_coredump(struct device *dev)
static int btintel_pcie_set_dxstate(struct btintel_pcie_data *data, u32 dxstate)
{
- int retry = 0, status;
+ int retry = 0;
+ long status;
u32 dx_intr_timeout_ms = 200;
+ /* Set outside the loop to avoid discarding late interrupts on retry. */
+ data->gp0_received = false;
+
do {
- data->gp0_received = false;
btintel_pcie_wr_sleep_cntrl(data, dxstate);
@@ -3184,18 +3188,20 @@ static int btintel_pcie_suspend_late(struct device *dev, pm_message_t mesg)
data = pci_get_drvdata(pdev);
- dxstate = (mesg.event == PM_EVENT_SUSPEND ?
+ /* Set D3_HOT for S0ix (s2idle) and D3_COLD for S3 (suspend-to-RAM). */
+ dxstate = (pm_suspend_target_state == PM_SUSPEND_TO_IDLE ?
BTINTEL_PCIE_STATE_D3_HOT : BTINTEL_PCIE_STATE_D3_COLD);
- data->pm_sx_event = mesg.event;
-
start = ktime_get();
/* Refer: 6.4.11.7 -> Platform power management */
err = btintel_pcie_set_dxstate(data, dxstate);
- if (err)
+ if (err) {
+ bt_dev_err(data->hdev, "Failed to set dxstate:%u (%d)",
+ dxstate, err);
return err;
+ }
bt_dev_dbg(data->hdev,
"device entered into d3 state from d0 in %lld us",
@@ -3208,17 +3214,7 @@ static int btintel_pcie_suspend(struct device *dev)
return btintel_pcie_suspend_late(dev, PMSG_SUSPEND);
}
-static int btintel_pcie_hibernate(struct device *dev)
-{
- return btintel_pcie_suspend_late(dev, PMSG_HIBERNATE);
-}
-
-static int btintel_pcie_freeze(struct device *dev)
-{
- return btintel_pcie_suspend_late(dev, PMSG_FREEZE);
-}
-
-static int btintel_pcie_resume(struct device *dev)
+static int btintel_pcie_resume_event(struct device *dev, pm_message_t mesg)
{
struct pci_dev *pdev = to_pci_dev(dev);
struct btintel_pcie_data *data;
@@ -3226,19 +3222,15 @@ static int btintel_pcie_resume(struct device *dev)
int err;
data = pci_get_drvdata(pdev);
- data->gp0_received = false;
start = ktime_get();
- /* When the system enters S4 (hibernate) mode, bluetooth device loses
- * power, which results in the erasure of its loaded firmware.
- * Consequently, function level reset (flr) is required on system
- * resume to bring the controller back into an operational state by
- * initiating a new firmware download.
+ /* S3 and S4 may cut power, erasing the firmware. Force FLR to recover
+ * instead of a normal D0 transition.
*/
-
- if (data->pm_sx_event == PM_EVENT_FREEZE ||
- data->pm_sx_event == PM_EVENT_HIBERNATE) {
+ if (mesg.event == PM_EVENT_RESTORE ||
+ (mesg.event == PM_EVENT_RESUME &&
+ pm_suspend_target_state == PM_SUSPEND_MEM)) {
set_bit(BTINTEL_PCIE_CORE_HALTED, &data->flags);
btintel_pcie_request_reset(data, BTINTEL_PCIE_IOSF_PRR_FLR);
return 0;
@@ -3247,7 +3239,9 @@ static int btintel_pcie_resume(struct device *dev)
/* Refer: 6.4.11.7 -> Platform power management */
err = btintel_pcie_set_dxstate(data, BTINTEL_PCIE_STATE_D0);
- if (err == 0) {
+ if (err) {
+ bt_dev_err(data->hdev, "Failed to set D0 state (%d)", err);
+ } else {
bt_dev_dbg(data->hdev,
"device entered into d0 state from d3 in %lld us",
ktime_to_us(ktime_get() - start));
@@ -3272,13 +3266,20 @@ static int btintel_pcie_resume(struct device *dev)
return err;
}
+static int btintel_pcie_resume(struct device *dev)
+{
+ return btintel_pcie_resume_event(dev, PMSG_RESUME);
+}
+
+static int btintel_pcie_restore(struct device *dev)
+{
+ return btintel_pcie_resume_event(dev, PMSG_RESTORE);
+}
+
static const struct dev_pm_ops btintel_pcie_pm_ops = {
.suspend = btintel_pcie_suspend,
.resume = btintel_pcie_resume,
- .freeze = btintel_pcie_freeze,
- .thaw = btintel_pcie_resume,
- .poweroff = btintel_pcie_hibernate,
- .restore = btintel_pcie_resume,
+ .restore = btintel_pcie_restore,
};
static struct pci_driver btintel_pcie_driver = {
diff --git a/drivers/bluetooth/btintel_pcie.h b/drivers/bluetooth/btintel_pcie.h
index 749369b24031..980eb62fdf8b 100644
--- a/drivers/bluetooth/btintel_pcie.h
+++ b/drivers/bluetooth/btintel_pcie.h
@@ -479,7 +479,6 @@ struct btintel_pcie_dump_header {
* @txq: TX Queue struct
* @rxq: RX Queue struct
* @alive_intr_ctxt: Alive interrupt context
- * @pm_sx_event: PM event on which system got suspended
*/
struct btintel_pcie_data {
struct pci_dev *pdev;
@@ -536,7 +535,6 @@ struct btintel_pcie_data {
enum btintel_pcie_reset_type reset_type;
struct btintel_pcie_dbgc dbgc;
struct btintel_pcie_dump_header dmp_hdr;
- u8 pm_sx_event;
u32 debug_evt_addr;
u32 debug_evt_size;
};
--
2.43.0
^ permalink raw reply related [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-08-28 11:51 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-28 9:51 [PATCH v1] Bluetooth: btintel_pcie: fix PM flow for S0ix, S3 and S4 Ravindra
2026-08-28 11:51 ` [v1] " bluez.test.bot
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.