Commit cf2c4189 authored by Yue Ma's avatar Yue Ma Committed by Madan Mohan Koyyalamudi
Browse files

qcacld: Add support to do FW initiated recovery

Host driver initiated recovery will cause issues if FW is still
trying to access host buffers. Hence add the support that recovery
can be initiated by FW to make sure FW activity has stopped.

Change-Id: I5f00fe9b969a7d2ce39e31df3dafa30d35078de5
CRs-fixed: 851449
parent 12309b6b
......@@ -1060,6 +1060,8 @@ void ol_ramdump_handler(struct ol_softc *scn)
void ol_target_failure(void *instance, A_STATUS status)
{
struct ol_softc *scn = (struct ol_softc *)instance;
void *vos_context = vos_get_global_context(VOS_MODULE_ID_WDA, NULL);
tp_wma_handle wma = vos_get_context(VOS_MODULE_ID_WDA, vos_context);
#ifndef CONFIG_CNSS
A_UINT32 reg_dump_area = 0;
A_UINT32 reg_dump_values[REGISTER_DUMP_LEN_MAX];
......@@ -1069,8 +1071,6 @@ void ol_target_failure(void *instance, A_STATUS status)
struct dbglog_hdr_host dbglog_hdr;
struct dbglog_buf_host dbglog_buf;
A_UINT8 *dbglog_data;
void *vos_context = vos_get_global_context(VOS_MODULE_ID_WDA, NULL);
tp_wma_handle wma = vos_get_context(VOS_MODULE_ID_WDA, vos_context);
#else
int ret;
#endif
......@@ -1084,6 +1084,8 @@ void ol_target_failure(void *instance, A_STATUS status)
}
#endif
vos_event_set(&wma->recovery_event);
if (OL_TRGET_STATUS_RESET == scn->target_status) {
printk("Target is already asserted, ignore!\n");
return;
......@@ -1091,6 +1093,11 @@ void ol_target_failure(void *instance, A_STATUS status)
scn->target_status = OL_TRGET_STATUS_RESET;
if (vos_is_logp_in_progress(VOS_MODULE_ID_VOSS, NULL)) {
pr_info("%s: LOGP is in progress, ignore!\n", __func__);
return;
}
if (vos_is_load_unload_in_progress(VOS_MODULE_ID_VOSS, NULL)) {
printk("%s: Loading/Unloading is in progress, ignore!\n",
__func__);
......
......@@ -4828,6 +4828,12 @@ VOS_STATUS WDA_open(v_VOID_t *vos_context, v_VOID_t *os_ctx,
goto err_event_init;
}
 
vos_status = vos_event_init(&wma_handle->recovery_event);
if (vos_status != VOS_STATUS_SUCCESS) {
WMA_LOGP("%s: recovery event initialization failed", __func__);
goto err_event_init;
}
INIT_LIST_HEAD(&wma_handle->vdev_resp_queue);
adf_os_spinlock_init(&wma_handle->vdev_respq_lock);
adf_os_spinlock_init(&wma_handle->vdev_detach_lock);
......@@ -10656,6 +10662,24 @@ static int wmi_crash_inject(wmi_unified_t wmi_handle, u_int32_t delay_time_ms)
return ret;
}
 
/**
* wma_crash_inject() - sends command to FW to simulate crash
* @wma_handle: pointer of WMA context
* @type: subtype of the command
* @delay_time_ms: time in milliseconds for FW to delay the crash
*
* This function will send a command to FW in order to simulate different
* kinds of FW crashes.
*
* Return: 0 for success or reasons for failure
*/
int wma_crash_inject(tp_wma_handle wma_handle, uint32_t type,
uint32_t delay_time_ms)
{
return wmi_crash_inject(wma_handle->wmi_handle, delay_time_ms);
}
static int32_t wmi_unified_set_sta_ps_param(wmi_unified_t wmi_handle,
u_int32_t vdev_id, u_int32_t param, u_int32_t value)
{
......@@ -24223,6 +24247,7 @@ VOS_STATUS wma_close(v_VOID_t *vos_ctx)
vos_event_destroy(&wma_handle->wma_ready_event);
vos_event_destroy(&wma_handle->target_suspend);
vos_event_destroy(&wma_handle->wma_resume_event);
vos_event_destroy(&wma_handle->recovery_event);
wma_cleanup_vdev_resp(wma_handle);
#ifdef QCA_WIFI_ISOC
vos_event_destroy(&wma_handle->cfg_nv_tx_complete);
......
......@@ -82,6 +82,8 @@
#define WMA_MAX_RESUME_RETRY 1000
#define WMA_RESUME_TIMEOUT 3000
#define MAX_MEM_CHUNKS 32
#define WMA_CRASH_INJECT_TIMEOUT 5000
/*
In prima 12 HW stations are supported including BCAST STA(staId 0)
and SELF STA(staId 1) so total ASSOC stations which can connect to Prima
......@@ -563,6 +565,8 @@ typedef struct {
vos_event_t wma_ready_event;
vos_event_t wma_resume_event;
vos_event_t target_suspend;
vos_event_t recovery_event;
t_cfg_nv_param cfg_nv;
v_U16_t max_station;
......@@ -1647,4 +1651,7 @@ A_UINT32 eCsrEncryptionType_to_rsn_cipherset (eCsrEncryptionType encr);
#define WMA_TX_Q_RECHECK_TIMER_WAIT 2 // 2 ms
#define WMA_TX_Q_RECHECK_TIMER_MAX_WAIT 20 // 20 ms
int wma_crash_inject(tp_wma_handle wma_handle, uint32_t type,
uint32_t delay_time_ms);
#endif
......@@ -99,7 +99,7 @@
#include "htc_api.h"
#endif /* #ifndef QCA_WIFI_ISOC */
#endif /* #ifdef QCA_WIFI_2_0 */
#include "wma.h"
/*---------------------------------------------------------------------------
* Preprocessor Definitions and Constants
......@@ -2643,21 +2643,47 @@ v_BOOL_t vos_is_packet_log_enabled(void)
return pHddCtx->cfg_ini->enablePacketLog;
}
#if defined(CONFIG_CNSS)
/* worker thread to recover when target does not respond over PCIe */
void self_recovery_work_handler(struct work_struct *recovery)
{
cnss_device_self_recovery();
}
static DECLARE_WORK(self_recovery_work, self_recovery_work_handler);
#endif
void vos_trigger_recovery(void)
{
pVosContextType vos_context;
tp_wma_handle wma_handle;
VOS_STATUS status = VOS_STATUS_SUCCESS;
vos_context = vos_get_global_context(VOS_MODULE_ID_VOSS, NULL);
if (!vos_context) {
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"VOS context is invald!");
return;
}
wma_handle = (tp_wma_handle)vos_get_context(VOS_MODULE_ID_WDA,
vos_context);
if (!wma_handle) {
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"WMA context is invald!");
return;
}
wma_crash_inject(wma_handle, RECOVERY_SIM_SELF_RECOVERY, 0);
status = vos_wait_single_event(&wma_handle->recovery_event,
WMA_CRASH_INJECT_TIMEOUT);
if (VOS_STATUS_SUCCESS != status) {
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"CRASH_INJECT command is timed out!");
#ifdef CONFIG_CNSS
schedule_work(&self_recovery_work);
if (vos_is_logp_in_progress(VOS_MODULE_ID_VOSS, NULL)) {
VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
"LOGP is in progress, ignore!");
return;
}
vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, TRUE);
cnss_schedule_recovery_work();
#endif
return;
}
}
v_U64_t vos_get_monotonic_boottime(void)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment