qcacmn: Fix long ping delay after enable RTPM
Issue1: Driver RTPM state is ON/NONE, Kernel state is RESUMING. cdp_runtime_resume is already complete, hif_pm_runtime_get return -E_INPROGRESS, dp_tx_hw_enqueue will set the flush event, but cdp_runtime_resume is already done, this flush event will be handled only on next pkt tx. Issue2: Driver RTPM state: Resuming hif_pm_runtime_get returns -EBUSY, dp_tx_hw_enqueue is interrupted by any IRQ, cdp_runtime_resume is completed, dp_tx_hw_enqueue will set the flush event, This flush event will be handled only on next pkt tx. Fix: Introduce a link_state_up atomic variable in hif to track the link state change by pld_cb. Set atomic variable link_state_up=1 in pmo_core_psoc_bus_runtime_resume just after pld_cb. pld_cb brings the PCIe bus out of suspend state. Set atomic variable link_state_up=0 in pmo_core_psoc_bus_runtime_suspend just before pld_cb. pld_cb puts the PCIe bus into suspend state. Introduce dp_runtime_get and dp_runtime_put. dp_runtime_get get refcount with increment of an atomic variable. dp_runtime_put return refcount with decrement of this atomic variable. If hif_pm_runtime_get returns -EBUSY or -EINPROGRESS, take the dp runtime refcount using dp_runtime_get, check if the link state is up, write TX ring HP, return the dp runtime refcount using dp_runtime_put. cdp_runtime_suspend should reject the suspend, if dp_runtime_get is non zero. cdp_runtime_resume should wait until dp_runtime_get becomes zero or time out, then flush pending tx for runtime suspend. Change-Id: I5b97d50cba710082f117f3845f7830712b86cda7 CRs-Fixed: 2844888
This commit is contained in:
@@ -1295,8 +1295,73 @@ dp_tx_ring_access_end(struct dp_soc *soc, hal_ring_handle_t hal_ring_hdl,
|
||||
{
|
||||
dp_tx_hal_ring_access_end(soc, hal_ring_hdl);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef FEATURE_RUNTIME_PM
|
||||
/**
|
||||
* dp_tx_ring_access_end_wrapper() - Wrapper for ring access end
|
||||
* @soc: Datapath soc handle
|
||||
* @hal_ring_hdl: HAL ring handle
|
||||
* @coalesce: Coalesce the current write or not
|
||||
*
|
||||
* Wrapper for HAL ring access end for data transmission for
|
||||
* FEATURE_RUNTIME_PM
|
||||
*
|
||||
* Returns: none
|
||||
*/
|
||||
static inline void
|
||||
dp_tx_ring_access_end_wrapper(struct dp_soc *soc,
|
||||
hal_ring_handle_t hal_ring_hdl,
|
||||
int coalesce)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = hif_pm_runtime_get(soc->hif_handle,
|
||||
RTPM_ID_DW_TX_HW_ENQUEUE, true);
|
||||
switch (ret) {
|
||||
case 0:
|
||||
dp_tx_ring_access_end(soc, hal_ring_hdl, coalesce);
|
||||
hif_pm_runtime_put(soc->hif_handle,
|
||||
RTPM_ID_DW_TX_HW_ENQUEUE);
|
||||
break;
|
||||
/*
|
||||
* If hif_pm_runtime_get returns -EBUSY or -EINPROGRESS,
|
||||
* take the dp runtime refcount using dp_runtime_get,
|
||||
* check link state,if up, write TX ring HP, else just set flush event.
|
||||
* In dp_runtime_resume, wait until dp runtime refcount becomes
|
||||
* zero or time out, then flush pending tx.
|
||||
*/
|
||||
case -EBUSY:
|
||||
case -EINPROGRESS:
|
||||
dp_runtime_get(soc);
|
||||
if (hif_pm_get_link_state(soc->hif_handle) ==
|
||||
HIF_PM_LINK_STATE_UP) {
|
||||
dp_tx_ring_access_end(soc, hal_ring_hdl, coalesce);
|
||||
} else {
|
||||
dp_tx_hal_ring_access_end_reap(soc, hal_ring_hdl);
|
||||
hal_srng_set_event(hal_ring_hdl, HAL_SRNG_FLUSH_EVENT);
|
||||
hal_srng_inc_flush_cnt(hal_ring_hdl);
|
||||
}
|
||||
dp_runtime_put(soc);
|
||||
break;
|
||||
default:
|
||||
dp_runtime_get(soc);
|
||||
dp_tx_hal_ring_access_end_reap(soc, hal_ring_hdl);
|
||||
hal_srng_set_event(hal_ring_hdl, HAL_SRNG_FLUSH_EVENT);
|
||||
hal_srng_inc_flush_cnt(hal_ring_hdl);
|
||||
dp_runtime_put(soc);
|
||||
}
|
||||
}
|
||||
#else
|
||||
static inline void
|
||||
dp_tx_ring_access_end_wrapper(struct dp_soc *soc,
|
||||
hal_ring_handle_t hal_ring_hdl,
|
||||
int coalesce)
|
||||
{
|
||||
dp_tx_ring_access_end(soc, hal_ring_hdl, coalesce);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* dp_tx_hw_enqueue() - Enqueue to TCL HW for transmit
|
||||
* @soc: DP Soc Handle
|
||||
@@ -1432,16 +1497,7 @@ dp_tx_hw_enqueue(struct dp_soc *soc, struct dp_vdev *vdev,
|
||||
status = QDF_STATUS_SUCCESS;
|
||||
|
||||
ring_access_fail:
|
||||
if (hif_pm_runtime_get(soc->hif_handle,
|
||||
RTPM_ID_DW_TX_HW_ENQUEUE, true) == 0) {
|
||||
dp_tx_ring_access_end(soc, hal_ring_hdl, coalesce);
|
||||
hif_pm_runtime_put(soc->hif_handle,
|
||||
RTPM_ID_DW_TX_HW_ENQUEUE);
|
||||
} else {
|
||||
dp_tx_hal_ring_access_end_reap(soc, hal_ring_hdl);
|
||||
hal_srng_set_event(hal_ring_hdl, HAL_SRNG_FLUSH_EVENT);
|
||||
hal_srng_inc_flush_cnt(hal_ring_hdl);
|
||||
}
|
||||
dp_tx_ring_access_end_wrapper(soc, hal_ring_hdl, coalesce);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
Reference in New Issue
Block a user