Skip to content

Commit 88c6216

Browse files
ravindr1Vudentz
authored andcommitted
Bluetooth: btintel_pcie: Suspend/Resume: Controller doorbell interrupt handling
Due to a hardware bug during suspend/resume, the controller may miss a doorbell interrupt. To address this, a retry mechanism has been added to inform the controller before reporting a failure. Test case: - run suspend and resume cycles. Signed-off-by: Ravindra <[email protected]> Signed-off-by: Kiran K <[email protected]> Signed-off-by: Luiz Augusto von Dentz <[email protected]>
1 parent 1fb0d83 commit 88c6216

File tree

2 files changed

+73
-42
lines changed

2 files changed

+73
-42
lines changed

drivers/bluetooth/btintel_pcie.c

Lines changed: 71 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -2524,6 +2524,48 @@ static void btintel_pcie_coredump(struct device *dev)
25242524
}
25252525
#endif
25262526

2527+
static int btintel_pcie_set_dxstate(struct btintel_pcie_data *data, u32 dxstate)
2528+
{
2529+
int retry = 0, status;
2530+
u32 dx_intr_timeout_ms = 200;
2531+
2532+
do {
2533+
data->gp0_received = false;
2534+
2535+
btintel_pcie_wr_sleep_cntrl(data, dxstate);
2536+
2537+
status = wait_event_timeout(data->gp0_wait_q, data->gp0_received,
2538+
msecs_to_jiffies(dx_intr_timeout_ms));
2539+
2540+
if (status)
2541+
return 0;
2542+
2543+
bt_dev_warn(data->hdev,
2544+
"Timeout (%u ms) on alive interrupt for D%d entry, retry count %d",
2545+
dx_intr_timeout_ms, dxstate, retry);
2546+
2547+
/* clear gp0 cause */
2548+
btintel_pcie_clr_reg_bits(data,
2549+
BTINTEL_PCIE_CSR_MSIX_HW_INT_CAUSES,
2550+
BTINTEL_PCIE_MSIX_HW_INT_CAUSES_GP0);
2551+
2552+
/* A hardware bug may cause the alive interrupt to be missed.
2553+
* Check if the controller reached the expected state and retry
2554+
* the operation only if it hasn't.
2555+
*/
2556+
if (dxstate == BTINTEL_PCIE_STATE_D0) {
2557+
if (btintel_pcie_in_d0(data))
2558+
return 0;
2559+
} else {
2560+
if (btintel_pcie_in_d3(data))
2561+
return 0;
2562+
}
2563+
2564+
} while (++retry < BTINTEL_PCIE_DX_TRANSITION_MAX_RETRIES);
2565+
2566+
return -EBUSY;
2567+
}
2568+
25272569
static int btintel_pcie_suspend_late(struct device *dev, pm_message_t mesg)
25282570
{
25292571
struct pci_dev *pdev = to_pci_dev(dev);
@@ -2539,26 +2581,18 @@ static int btintel_pcie_suspend_late(struct device *dev, pm_message_t mesg)
25392581

25402582
data->pm_sx_event = mesg.event;
25412583

2542-
data->gp0_received = false;
2543-
25442584
start = ktime_get();
25452585

25462586
/* Refer: 6.4.11.7 -> Platform power management */
2547-
btintel_pcie_wr_sleep_cntrl(data, dxstate);
2548-
err = wait_event_timeout(data->gp0_wait_q, data->gp0_received,
2549-
msecs_to_jiffies(BTINTEL_DEFAULT_INTR_TIMEOUT_MS));
2550-
if (err == 0) {
2551-
bt_dev_err(data->hdev,
2552-
"Timeout (%u ms) on alive interrupt for D3 entry",
2553-
BTINTEL_DEFAULT_INTR_TIMEOUT_MS);
2554-
return -EBUSY;
2555-
}
2587+
err = btintel_pcie_set_dxstate(data, dxstate);
2588+
2589+
if (err)
2590+
return err;
25562591

25572592
bt_dev_dbg(data->hdev,
25582593
"device entered into d3 state from d0 in %lld us",
25592594
ktime_to_us(ktime_get() - start));
2560-
2561-
return 0;
2595+
return err;
25622596
}
25632597

25642598
static int btintel_pcie_suspend(struct device *dev)
@@ -2603,40 +2637,35 @@ static int btintel_pcie_resume(struct device *dev)
26032637
}
26042638

26052639
/* Refer: 6.4.11.7 -> Platform power management */
2606-
btintel_pcie_wr_sleep_cntrl(data, BTINTEL_PCIE_STATE_D0);
2607-
err = wait_event_timeout(data->gp0_wait_q, data->gp0_received,
2608-
msecs_to_jiffies(BTINTEL_DEFAULT_INTR_TIMEOUT_MS));
2640+
err = btintel_pcie_set_dxstate(data, BTINTEL_PCIE_STATE_D0);
2641+
26092642
if (err == 0) {
2610-
bt_dev_err(data->hdev,
2611-
"Timeout (%u ms) on alive interrupt for D0 entry",
2612-
BTINTEL_DEFAULT_INTR_TIMEOUT_MS);
2643+
bt_dev_dbg(data->hdev,
2644+
"device entered into d0 state from d3 in %lld us",
2645+
ktime_to_us(ktime_get() - start));
2646+
return err;
2647+
}
26132648

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-
*/
2649+
/* Trigger function level reset if the controller is in error
2650+
* state during resume() to bring back the controller to
2651+
* operational mode
2652+
*/
26182653

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);
2654+
data->boot_stage_cache = btintel_pcie_rd_reg32(data,
2655+
BTINTEL_PCIE_CSR_BOOT_STAGE_REG);
2656+
if (btintel_pcie_in_error(data) ||
2657+
btintel_pcie_in_device_halt(data)) {
2658+
bt_dev_err(data->hdev, "Controller in error state for D0 entry");
2659+
if (!test_and_set_bit(BTINTEL_PCIE_COREDUMP_INPROGRESS,
2660+
&data->flags)) {
2661+
data->dmp_hdr.trigger_reason =
2662+
BTINTEL_PCIE_TRIGGER_REASON_FW_ASSERT;
2663+
queue_work(data->workqueue, &data->rx_work);
26322664
}
2633-
return -EBUSY;
2665+
set_bit(BTINTEL_PCIE_CORE_HALTED, &data->flags);
2666+
btintel_pcie_reset(data->hdev);
26342667
}
2635-
2636-
bt_dev_dbg(data->hdev,
2637-
"device entered into d0 state from d3 in %lld us",
2638-
ktime_to_us(ktime_get() - start));
2639-
return 0;
2668+
return err;
26402669
}
26412670

26422671
static const struct dev_pm_ops btintel_pcie_pm_ops = {

drivers/bluetooth/btintel_pcie.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,8 @@ enum msix_mbox_int_causes {
158158
/* Default interrupt timeout in msec */
159159
#define BTINTEL_DEFAULT_INTR_TIMEOUT_MS 3000
160160

161+
#define BTINTEL_PCIE_DX_TRANSITION_MAX_RETRIES 3
162+
161163
/* The number of descriptors in TX queues */
162164
#define BTINTEL_PCIE_TX_DESCS_COUNT 32
163165

0 commit comments

Comments
 (0)