mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-13 08:07:32 -04:00
qcacld-3.0: Fix dp_rx_thread hang issue
Issue happens as below scenaio: 1 suspend happens, but dp_rx_thread didn't finish in time, so timeout happens for suspend_event, here suspend will return success to kernel. 2 resume happens before dp_rx_thread to reset resume_event, and resume finished. 3 if dp_rx_thread finished and blocking with resume_event, and in following test, suspend didn't come(longer then hang detect time). 4 hang detect will alarm. Fix is to return failure if dp_rx_thread can't be suspend in time. Suspend can triger again later. Change-Id: Ifbfdef5bb1c8d6e00b8fa5cc5e6dc74d3495c9ea CRs-Fixed: 2626468
This commit is contained in:
parent
7439bf85b9
commit
9a4d95c3fd
3 changed files with 30 additions and 12 deletions
|
|
@ -407,7 +407,6 @@ static int dp_rx_thread_sub_loop(struct dp_rx_thread *rx_thread, bool *shutdown)
|
|||
dp_debug("received suspend ind (%s) id %d pid %d",
|
||||
qdf_get_current_comm(), rx_thread->id,
|
||||
qdf_get_current_pid());
|
||||
qdf_event_reset(&rx_thread->resume_event);
|
||||
qdf_event_set(&rx_thread->suspend_event);
|
||||
dp_debug("waiting for resume (%s) id %d pid %d",
|
||||
qdf_get_current_comm(), rx_thread->id,
|
||||
|
|
@ -648,7 +647,7 @@ ret:
|
|||
* @rx_tm_hdl: dp_rx_tm_handle containing the overall thread
|
||||
* infrastructure
|
||||
*
|
||||
* Return: QDF_STATUS_SUCCESS
|
||||
* Return: Success/Failure
|
||||
*/
|
||||
QDF_STATUS dp_rx_tm_suspend(struct dp_rx_tm_handle *rx_tm_hdl)
|
||||
{
|
||||
|
|
@ -661,9 +660,12 @@ QDF_STATUS dp_rx_tm_suspend(struct dp_rx_tm_handle *rx_tm_hdl)
|
|||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
rx_tm_hdl->state = DP_RX_THREADS_SUSPENDING;
|
||||
|
||||
for (i = 0; i < rx_tm_hdl->num_dp_rx_threads; i++) {
|
||||
if (!rx_tm_hdl->rx_thread[i])
|
||||
continue;
|
||||
qdf_event_reset(&rx_tm_hdl->rx_thread[i]->resume_event);
|
||||
qdf_event_reset(&rx_tm_hdl->rx_thread[i]->suspend_event);
|
||||
qdf_set_bit(RX_SUSPEND_EVENT,
|
||||
&rx_tm_hdl->rx_thread[i]->event_flag);
|
||||
|
|
@ -679,16 +681,22 @@ QDF_STATUS dp_rx_tm_suspend(struct dp_rx_tm_handle *rx_tm_hdl)
|
|||
DP_RX_THREAD_WAIT_TIMEOUT);
|
||||
if (QDF_IS_STATUS_SUCCESS(qdf_status))
|
||||
dp_debug("thread:%d suspended", rx_thread->id);
|
||||
else if (qdf_status == QDF_STATUS_E_TIMEOUT)
|
||||
dp_err("thread:%d timed out waiting for suspend",
|
||||
rx_thread->id);
|
||||
else
|
||||
dp_err("thread:%d failed while waiting for suspend",
|
||||
rx_thread->id);
|
||||
goto suspend_fail;
|
||||
}
|
||||
rx_tm_hdl->state = DP_RX_THREADS_SUSPENDED;
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
|
||||
suspend_fail:
|
||||
dp_err("thread:%d %s(%d) while waiting for suspend",
|
||||
rx_thread->id,
|
||||
qdf_status == QDF_STATUS_E_TIMEOUT ? "timeout out" : "failed",
|
||||
qdf_status);
|
||||
|
||||
dp_rx_tm_resume(rx_tm_hdl);
|
||||
|
||||
return qdf_status;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -781,7 +789,8 @@ QDF_STATUS dp_rx_tm_resume(struct dp_rx_tm_handle *rx_tm_hdl)
|
|||
{
|
||||
int i;
|
||||
|
||||
if (rx_tm_hdl->state != DP_RX_THREADS_SUSPENDED) {
|
||||
if (rx_tm_hdl->state != DP_RX_THREADS_SUSPENDED &&
|
||||
rx_tm_hdl->state != DP_RX_THREADS_SUSPENDING) {
|
||||
dp_info("resume callback received w/o suspend! Ignoring.");
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
|
@ -790,6 +799,12 @@ QDF_STATUS dp_rx_tm_resume(struct dp_rx_tm_handle *rx_tm_hdl)
|
|||
if (!rx_tm_hdl->rx_thread[i])
|
||||
continue;
|
||||
dp_debug("calling thread %d to resume", i);
|
||||
|
||||
/* postively reset event_flag for DP_RX_THREADS_SUSPENDING
|
||||
* state
|
||||
*/
|
||||
qdf_clear_bit(RX_SUSPEND_EVENT,
|
||||
&rx_tm_hdl->rx_thread[i]->event_flag);
|
||||
qdf_event_set(&rx_tm_hdl->rx_thread[i]->resume_event);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -110,11 +110,13 @@ struct dp_rx_thread {
|
|||
* @DP_RX_THREADS_INVALID: initial invalid state
|
||||
* @DP_RX_THREADS_RUNNING: rx threads functional(NOT suspended, processing
|
||||
* packets or waiting on a wait_queue)
|
||||
* @DP_RX_THREADS_SUSPENDING: rx thread is suspending
|
||||
* @DP_RX_THREADS_SUSPENDED: rx_threads suspended from cfg8011 suspend
|
||||
*/
|
||||
enum dp_rx_thread_state {
|
||||
DP_RX_THREADS_INVALID,
|
||||
DP_RX_THREADS_RUNNING,
|
||||
DP_RX_THREADS_SUSPENDING,
|
||||
DP_RX_THREADS_SUSPENDED
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1958,14 +1958,16 @@ static int __wlan_hdd_cfg80211_suspend_wlan(struct wiphy *wiphy,
|
|||
goto resume_ol_rx;
|
||||
}
|
||||
|
||||
if (hdd_ctx->enable_dp_rx_threads)
|
||||
dp_txrx_suspend(cds_get_context(QDF_MODULE_ID_SOC));
|
||||
if (hdd_ctx->enable_dp_rx_threads) {
|
||||
if (dp_txrx_suspend(cds_get_context(QDF_MODULE_ID_SOC)))
|
||||
goto resume_ol_rx;
|
||||
}
|
||||
|
||||
if (ucfg_pkt_capture_get_mode(hdd_ctx->psoc)) {
|
||||
adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
|
||||
if (adapter)
|
||||
if (ucfg_pkt_capture_suspend_mon_thread(adapter->vdev))
|
||||
goto resume_pkt_capture_mon_thread;
|
||||
goto resume_dp_thread;
|
||||
}
|
||||
|
||||
qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
|
||||
|
|
@ -1988,7 +1990,6 @@ resume_dp_thread:
|
|||
if (hdd_ctx->enable_dp_rx_threads)
|
||||
dp_txrx_resume(cds_get_context(QDF_MODULE_ID_SOC));
|
||||
|
||||
resume_pkt_capture_mon_thread:
|
||||
/* Resume packet capture MON thread */
|
||||
if (ucfg_pkt_capture_get_mode(hdd_ctx->psoc)) {
|
||||
adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
|
||||
|
|
|
|||
Loading…
Reference in a new issue