qcacld-3.0: Avoid recovery trigger while recovering
Currently, cds_trigger_recovery is unconditional. Instead, avoid triggering recovery if recovery is already in progress. Change-Id: I5c77048701930591e0e520e07275e6f8631108a0 CRs-Fixed: 2070845
This commit is contained in:
committed by
Anjaneedevi Kapparapu
parent
f7ffe94567
commit
100201ecca
@@ -345,13 +345,7 @@ bool cds_is_packet_log_enabled(void);
|
||||
|
||||
uint64_t cds_get_monotonic_boottime(void);
|
||||
|
||||
/**
|
||||
* cds_trigger_recovery_wrapper() - a temp wrapper to trigger self recovery
|
||||
*
|
||||
* Return: none
|
||||
*/
|
||||
void cds_trigger_recovery_wrapper(void);
|
||||
void cds_trigger_recovery(bool);
|
||||
void cds_trigger_recovery(void);
|
||||
|
||||
void cds_set_wakelock_logging(bool value);
|
||||
bool cds_is_wakelock_enabled(void);
|
||||
|
||||
@@ -138,7 +138,7 @@ v_CONTEXT_t cds_init(void)
|
||||
qdf_lock_stats_init();
|
||||
qdf_mem_init();
|
||||
qdf_mc_timer_manager_init();
|
||||
qdf_register_self_recovery_callback(cds_trigger_recovery_wrapper);
|
||||
qdf_register_self_recovery_callback(cds_trigger_recovery);
|
||||
|
||||
gp_cds_context = &g_cds_context;
|
||||
|
||||
@@ -1713,97 +1713,134 @@ bool cds_is_packet_log_enabled(void)
|
||||
return pHddCtx->config->enablePacketLog;
|
||||
}
|
||||
|
||||
/**
|
||||
* cds_config_recovery_work() - configure self recovery
|
||||
* @qdf_ctx: pointer of qdf context
|
||||
*
|
||||
* Return: none
|
||||
*/
|
||||
|
||||
static void cds_config_recovery_work(qdf_device_t qdf_ctx)
|
||||
static int cds_force_assert_target_via_pld(qdf_device_t qdf)
|
||||
{
|
||||
if (cds_is_driver_recovering() || cds_is_driver_in_bad_state()) {
|
||||
QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
|
||||
"Recovery is in progress, ignore!");
|
||||
} else {
|
||||
cds_set_recovery_in_progress(true);
|
||||
QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
|
||||
"schedule recovery work!");
|
||||
pld_schedule_recovery_work(qdf_ctx->dev,
|
||||
PLD_REASON_DEFAULT);
|
||||
}
|
||||
int errno;
|
||||
|
||||
errno = pld_force_assert_target(qdf->dev);
|
||||
if (errno == -EOPNOTSUPP)
|
||||
cds_info("PLD does not support target force assert");
|
||||
else if (errno)
|
||||
cds_err("Failed PLD target force assert; errno %d", errno);
|
||||
else
|
||||
cds_info("Target force assert triggered via PLD");
|
||||
|
||||
return errno;
|
||||
}
|
||||
|
||||
void cds_trigger_recovery_wrapper(void)
|
||||
static QDF_STATUS cds_force_assert_target_via_wmi(qdf_device_t qdf)
|
||||
{
|
||||
cds_trigger_recovery(false);
|
||||
QDF_STATUS status;
|
||||
t_wma_handle *wma;
|
||||
|
||||
wma = cds_get_context(QDF_MODULE_ID_WMA);
|
||||
if (!wma) {
|
||||
cds_err("wma is null");
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
status = wma_crash_inject(wma, RECOVERY_SIM_SELF_RECOVERY, 0);
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
cds_err("Failed target force assert; status %d", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
status = qdf_wait_single_event(&wma->recovery_event,
|
||||
WMA_CRASH_INJECT_TIMEOUT);
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
cds_err("Failed target force assert wait; status %d", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* cds_force_assert_target() - Send assert command to firmware
|
||||
* @qdf: QDF device instance to assert
|
||||
*
|
||||
* An out-of-band recovery mechanism will cleanup and restart the entire wlan
|
||||
* subsystem in the event of a firmware crash. This API injects a firmware
|
||||
* crash to start this process when the wlan driver is known to be in a bad
|
||||
* state. If a firmware assert inject fails, the wlan driver will schedule
|
||||
* the driver recovery anyway, as a best effort attempt to return to a working
|
||||
* state.
|
||||
*
|
||||
* Return: QDF_STATUS
|
||||
*/
|
||||
static QDF_STATUS cds_force_assert_target(qdf_device_t qdf)
|
||||
{
|
||||
int errno;
|
||||
QDF_STATUS status;
|
||||
|
||||
/* first, try target assert inject via pld */
|
||||
errno = cds_force_assert_target_via_pld(qdf);
|
||||
if (!errno)
|
||||
return QDF_STATUS_SUCCESS;
|
||||
if (errno != -EOPNOTSUPP)
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
|
||||
/* pld assert is not supported, try target assert inject via wmi */
|
||||
status = cds_force_assert_target_via_wmi(qdf);
|
||||
if (QDF_IS_STATUS_SUCCESS(status))
|
||||
return QDF_STATUS_SUCCESS;
|
||||
|
||||
/* wmi assert failed, start recovery without the firmware assert */
|
||||
cds_err("Scheduling recovery work without firmware assert");
|
||||
cds_set_recovery_in_progress(true);
|
||||
pld_schedule_recovery_work(qdf->dev, PLD_REASON_DEFAULT);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* cds_trigger_recovery() - trigger self recovery
|
||||
* @skip_crash_inject: Boolean value to skip to send crash inject cmd
|
||||
*
|
||||
* Return: none
|
||||
*/
|
||||
void cds_trigger_recovery(bool skip_crash_inject)
|
||||
void cds_trigger_recovery(void)
|
||||
{
|
||||
tp_wma_handle wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
|
||||
QDF_STATUS status = QDF_STATUS_SUCCESS;
|
||||
qdf_runtime_lock_t recovery_lock;
|
||||
qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
|
||||
QDF_STATUS status;
|
||||
qdf_runtime_lock_t rtl;
|
||||
qdf_device_t qdf;
|
||||
|
||||
if (!wma_handle) {
|
||||
QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
|
||||
"WMA context is invalid!");
|
||||
return;
|
||||
}
|
||||
if (!qdf_ctx) {
|
||||
QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
|
||||
"QDF context is invalid!");
|
||||
if (!cds_is_self_recovery_enabled()) {
|
||||
cds_err("Recovery is not enabled");
|
||||
QDF_BUG(0);
|
||||
return;
|
||||
}
|
||||
|
||||
status = qdf_runtime_lock_init(&recovery_lock);
|
||||
if (QDF_STATUS_SUCCESS != status) {
|
||||
QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
|
||||
"Could not acquire runtime pm lock: %d!", status);
|
||||
if (cds_is_driver_recovering() || cds_is_driver_in_bad_state()) {
|
||||
cds_err("Recovery in progress; ignoring recovery trigger");
|
||||
return;
|
||||
}
|
||||
|
||||
qdf_runtime_pm_prevent_suspend(&recovery_lock);
|
||||
|
||||
/*
|
||||
* If force assert thru platform is available, trigger that interface.
|
||||
* That should generate recovery by going thru the normal FW
|
||||
* assert recovery model.
|
||||
*/
|
||||
if (!pld_force_assert_target(qdf_ctx->dev)) {
|
||||
QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO_HIGH,
|
||||
"Force assert triggered");
|
||||
goto out;
|
||||
qdf = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
|
||||
if (!qdf) {
|
||||
cds_err("Qdf context is null");
|
||||
return;
|
||||
}
|
||||
|
||||
QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO_HIGH,
|
||||
"Force assert not available at platform");
|
||||
|
||||
if (!skip_crash_inject) {
|
||||
|
||||
wma_crash_inject(wma_handle, RECOVERY_SIM_SELF_RECOVERY, 0);
|
||||
status = qdf_wait_single_event(&wma_handle->recovery_event,
|
||||
WMA_CRASH_INJECT_TIMEOUT);
|
||||
|
||||
if (QDF_STATUS_SUCCESS != status) {
|
||||
QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
|
||||
"CRASH_INJECT command is timed out!");
|
||||
cds_config_recovery_work(qdf_ctx);
|
||||
}
|
||||
} else {
|
||||
cds_config_recovery_work(qdf_ctx);
|
||||
status = qdf_runtime_lock_init(&rtl);
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
cds_err("Failed to initialize runtime pm lock");
|
||||
return;
|
||||
}
|
||||
|
||||
out:
|
||||
qdf_runtime_pm_allow_suspend(&recovery_lock);
|
||||
qdf_runtime_lock_deinit(&recovery_lock);
|
||||
status = qdf_runtime_pm_prevent_suspend(&rtl);
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
cds_err("Failed to acquire runtime pm lock");
|
||||
goto deinit_rtl;
|
||||
}
|
||||
|
||||
cds_force_assert_target(qdf);
|
||||
|
||||
status = qdf_runtime_pm_allow_suspend(&rtl);
|
||||
if (QDF_IS_STATUS_ERROR(status))
|
||||
cds_err("Failed to release runtime pm lock");
|
||||
|
||||
deinit_rtl:
|
||||
qdf_runtime_lock_deinit(&rtl);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2504,21 +2504,11 @@ ol_txrx_peer_attach(struct cdp_vdev *pvdev, uint8_t *peer_mac_addr)
|
||||
rc = qdf_wait_single_event(&vdev->wait_delete_comp,
|
||||
PEER_DELETION_TIMEOUT);
|
||||
if (QDF_STATUS_SUCCESS != rc) {
|
||||
ol_txrx_err(
|
||||
"error waiting for peer(%d) deletion, status %d\n",
|
||||
vdev->wait_on_peer_id, (int) rc);
|
||||
if (cds_is_self_recovery_enabled())
|
||||
cds_trigger_recovery(false);
|
||||
else
|
||||
|
||||
/*
|
||||
* Add equivalent of following line when it
|
||||
* becomes available.
|
||||
* wma_peer_debug_dump();
|
||||
*/
|
||||
QDF_ASSERT(0);
|
||||
|
||||
ol_txrx_err("error waiting for peer(%d) deletion, status %d\n",
|
||||
vdev->wait_on_peer_id, (int) rc);
|
||||
cds_trigger_recovery();
|
||||
vdev->wait_on_peer_id = OL_TXRX_INVALID_LOCAL_PEER_ID;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -3407,19 +3397,7 @@ static QDF_STATUS ol_txrx_clear_peer(struct cdp_pdev *ppdev, uint8_t sta_id)
|
||||
void peer_unmap_timer_work_function(void *param)
|
||||
{
|
||||
WMA_LOGE("Enter: %s", __func__);
|
||||
/*
|
||||
* wma_peer_debug_dump() will be replaced with a new routine.
|
||||
* Add the equivalent of wma_peer_debug_dump() when available.
|
||||
*/
|
||||
if (cds_is_self_recovery_enabled()) {
|
||||
if (!cds_is_driver_recovering())
|
||||
cds_trigger_recovery(false);
|
||||
else
|
||||
WMA_LOGE("%s: Recovery is in progress, ignore!",
|
||||
__func__);
|
||||
} else {
|
||||
QDF_BUG(0);
|
||||
}
|
||||
cds_trigger_recovery();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2645,7 +2645,7 @@ static int __iw_softap_set_two_ints_getnone(struct net_device *dev,
|
||||
hdd_err("WE_SET_FW_CRASH_INJECT: %d %d",
|
||||
value[1], value[2]);
|
||||
if (value[1] == 3) {
|
||||
cds_trigger_recovery(false);
|
||||
cds_trigger_recovery();
|
||||
return 0;
|
||||
}
|
||||
ret = wma_cli_set2_command(adapter->sessionId,
|
||||
|
||||
@@ -144,11 +144,8 @@ static void hdd_scan_inactivity_timer_handler(void *scan_req)
|
||||
else if (cds_is_driver_in_bad_state())
|
||||
hdd_err("%s: Module in bad state; Ignore hdd scan req timeout",
|
||||
__func__);
|
||||
else if (cds_is_self_recovery_enabled())
|
||||
cds_trigger_recovery(false);
|
||||
else
|
||||
QDF_BUG(0);
|
||||
|
||||
cds_trigger_recovery();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -919,13 +916,9 @@ static int __wlan_hdd_cfg80211_scan(struct wiphy *wiphy,
|
||||
WLAN_LOG_REASON_SCAN_NOT_ALLOWED,
|
||||
false,
|
||||
pHddCtx->config->enableSelfRecovery);
|
||||
} else if (pHddCtx->config->
|
||||
enableSelfRecovery) {
|
||||
hdd_err("Triggering SSR due to scan stuck");
|
||||
cds_trigger_recovery(false);
|
||||
} else {
|
||||
hdd_err("QDF_BUG due to scan stuck");
|
||||
QDF_BUG(0);
|
||||
hdd_err("Triggering SSR due to scan stuck");
|
||||
cds_trigger_recovery();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12821,7 +12821,7 @@ static int __iw_set_two_ints_getnone(struct net_device *dev,
|
||||
pr_err("SSR is triggered by iwpriv CRASH_INJECT: %d %d\n",
|
||||
value[1], value[2]);
|
||||
if (value[1] == 3) {
|
||||
cds_trigger_recovery(false);
|
||||
cds_trigger_recovery();
|
||||
return 0;
|
||||
}
|
||||
ret = wma_cli_set2_command(pAdapter->sessionId,
|
||||
|
||||
@@ -1538,25 +1538,19 @@ int pld_is_qmi_disable(struct device *dev)
|
||||
*/
|
||||
int pld_force_assert_target(struct device *dev)
|
||||
{
|
||||
int ret = 0;
|
||||
enum pld_bus_type type = pld_get_bus_type(dev);
|
||||
|
||||
switch (type) {
|
||||
case PLD_BUS_TYPE_SNOC:
|
||||
ret = pld_snoc_force_assert_target(dev);
|
||||
break;
|
||||
return pld_snoc_force_assert_target(dev);
|
||||
case PLD_BUS_TYPE_PCIE:
|
||||
ret = pld_pcie_force_assert_target(dev);
|
||||
break;
|
||||
return pld_pcie_force_assert_target(dev);
|
||||
case PLD_BUS_TYPE_SDIO:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
return -EINVAL;
|
||||
default:
|
||||
pr_err("Invalid device type %d\n", type);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
return -EINVAL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -507,10 +507,8 @@ tSmeCmd *sme_get_command_buffer(tpAniSirGlobal pMac)
|
||||
WLAN_LOG_REASON_SME_OUT_OF_CMD_BUF,
|
||||
false,
|
||||
pMac->sme.enableSelfRecovery ? true : false);
|
||||
else if (pMac->sme.enableSelfRecovery)
|
||||
cds_trigger_recovery(false);
|
||||
else
|
||||
QDF_BUG(0);
|
||||
cds_trigger_recovery();
|
||||
}
|
||||
|
||||
/* memset to zero */
|
||||
|
||||
@@ -3903,16 +3903,8 @@ static inline void wma_suspend_target_timeout(bool is_self_recovery_enabled)
|
||||
if (cds_is_load_or_unload_in_progress())
|
||||
WMA_LOGE("%s: Module (un)loading; Ignoring suspend timeout",
|
||||
__func__);
|
||||
else if (cds_is_driver_recovering())
|
||||
WMA_LOGE("%s: Module recovering; Ignoring suspend timeout",
|
||||
__func__);
|
||||
else if (cds_is_driver_in_bad_state())
|
||||
WMA_LOGE("%s: Module in bad state; Ignoring suspend timeout",
|
||||
__func__);
|
||||
else if (is_self_recovery_enabled)
|
||||
cds_trigger_recovery(false);
|
||||
else
|
||||
QDF_BUG(0);
|
||||
cds_trigger_recovery();
|
||||
}
|
||||
|
||||
#ifdef FEATURE_WLAN_TDLS
|
||||
|
||||
Reference in New Issue
Block a user