Skip to content

Commit 1fb0d83

Browse files
ravindr1Vudentz
authored andcommitted
Bluetooth: btintel_pcie: Support for S4 (Hibernate)
During S4 (hibernate), the Bluetooth device loses power. Upon resume, the driver performs the following actions: 1. Unregisters hdev 2. Calls function level reset 3. Registers hdev Test case: - run command sudo rtcwake -m disk -s 60 Signed-off-by: Ravindra <[email protected]> Signed-off-by: Kiran K <[email protected]> Signed-off-by: Luiz Augusto von Dentz <[email protected]>
1 parent 5a6700a commit 1fb0d83

File tree

2 files changed

+43
-0
lines changed

2 files changed

+43
-0
lines changed

drivers/bluetooth/btintel_pcie.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -825,6 +825,11 @@ static inline bool btintel_pcie_in_d0(struct btintel_pcie_data *data)
825825
return !(data->boot_stage_cache & BTINTEL_PCIE_CSR_BOOT_STAGE_D3_STATE_READY);
826826
}
827827

828+
static inline bool btintel_pcie_in_device_halt(struct btintel_pcie_data *data)
829+
{
830+
return data->boot_stage_cache & BTINTEL_PCIE_CSR_BOOT_STAGE_DEVICE_HALTED;
831+
}
832+
828833
static void btintel_pcie_wr_sleep_cntrl(struct btintel_pcie_data *data,
829834
u32 dxstate)
830835
{
@@ -2532,6 +2537,8 @@ static int btintel_pcie_suspend_late(struct device *dev, pm_message_t mesg)
25322537
dxstate = (mesg.event == PM_EVENT_SUSPEND ?
25332538
BTINTEL_PCIE_STATE_D3_HOT : BTINTEL_PCIE_STATE_D3_COLD);
25342539

2540+
data->pm_sx_event = mesg.event;
2541+
25352542
data->gp0_received = false;
25362543

25372544
start = ktime_get();
@@ -2581,6 +2588,20 @@ static int btintel_pcie_resume(struct device *dev)
25812588

25822589
start = ktime_get();
25832590

2591+
/* When the system enters S4 (hibernate) mode, bluetooth device loses
2592+
* power, which results in the erasure of its loaded firmware.
2593+
* Consequently, function level reset (flr) is required on system
2594+
* resume to bring the controller back into an operational state by
2595+
* initiating a new firmware download.
2596+
*/
2597+
2598+
if (data->pm_sx_event == PM_EVENT_FREEZE ||
2599+
data->pm_sx_event == PM_EVENT_HIBERNATE) {
2600+
set_bit(BTINTEL_PCIE_CORE_HALTED, &data->flags);
2601+
btintel_pcie_reset(data->hdev);
2602+
return 0;
2603+
}
2604+
25842605
/* Refer: 6.4.11.7 -> Platform power management */
25852606
btintel_pcie_wr_sleep_cntrl(data, BTINTEL_PCIE_STATE_D0);
25862607
err = wait_event_timeout(data->gp0_wait_q, data->gp0_received,
@@ -2589,6 +2610,26 @@ static int btintel_pcie_resume(struct device *dev)
25892610
bt_dev_err(data->hdev,
25902611
"Timeout (%u ms) on alive interrupt for D0 entry",
25912612
BTINTEL_DEFAULT_INTR_TIMEOUT_MS);
2613+
2614+
/* Trigger function level reset if the controller is in error
2615+
* state during resume() to bring back the controller to
2616+
* operational mode
2617+
*/
2618+
2619+
data->boot_stage_cache = btintel_pcie_rd_reg32(data,
2620+
BTINTEL_PCIE_CSR_BOOT_STAGE_REG);
2621+
if (btintel_pcie_in_error(data) ||
2622+
btintel_pcie_in_device_halt(data)) {
2623+
bt_dev_err(data->hdev, "Controller in error state for D0 entry");
2624+
if (!test_and_set_bit(BTINTEL_PCIE_COREDUMP_INPROGRESS,
2625+
&data->flags)) {
2626+
data->dmp_hdr.trigger_reason =
2627+
BTINTEL_PCIE_TRIGGER_REASON_FW_ASSERT;
2628+
queue_work(data->workqueue, &data->rx_work);
2629+
}
2630+
set_bit(BTINTEL_PCIE_CORE_HALTED, &data->flags);
2631+
btintel_pcie_reset(data->hdev);
2632+
}
25922633
return -EBUSY;
25932634
}
25942635

drivers/bluetooth/btintel_pcie.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,7 @@ struct btintel_pcie_dump_header {
464464
* @txq: TX Queue struct
465465
* @rxq: RX Queue struct
466466
* @alive_intr_ctxt: Alive interrupt context
467+
* @pm_sx_event: PM event on which system got suspended
467468
*/
468469
struct btintel_pcie_data {
469470
struct pci_dev *pdev;
@@ -513,6 +514,7 @@ struct btintel_pcie_data {
513514
u32 alive_intr_ctxt;
514515
struct btintel_pcie_dbgc dbgc;
515516
struct btintel_pcie_dump_header dmp_hdr;
517+
u8 pm_sx_event;
516518
};
517519

518520
static inline u32 btintel_pcie_rd_reg32(struct btintel_pcie_data *data,

0 commit comments

Comments
 (0)