@@ -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+
25272569static 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
25642598static 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
26422671static const struct dev_pm_ops btintel_pcie_pm_ops = {
0 commit comments