qcacld-3.0: Fix pre cac work thread hung

wlan_hdd_sap_pre_cac_success run in the work thread
scheduled by sap_pre_cac_work.
But hdd_stop_adapter will call
cds_flush_work(&hdd_ctx->sap_pre_cac_work);
That means the work waits itself to finish.

The Fix is to add flag to hdd_stop_adapter
to identify the "stop" running in the work handler
and skip the "sync" cancel the work self.

Change-Id: I875c2f14ffd54272fc9ea0df1cecc6dd1171e310
CRs-Fixed: 2252085
This commit is contained in:
Liangwei Dong 2018-06-01 01:56:23 -04:00 • committed by nshrivas
commit ad89c765fd
3 changed files with 51 additions and 7 deletions

View file

@ -2057,6 +2057,15 @@ void hdd_deinit_adapter(struct hdd_context *hdd_ctx,
bool rtnl_held);
QDF_STATUS hdd_stop_adapter(struct hdd_context *hdd_ctx,
struct hdd_adapter *adapter);
enum hdd_adapter_stop_flag_t {
HDD_IN_CAC_WORK_TH_CONTEXT = 0x00000001,
};
QDF_STATUS hdd_stop_adapter_ext(struct hdd_context *hdd_ctx,
struct hdd_adapter *adapter,
enum hdd_adapter_stop_flag_t flag);
void hdd_set_station_ops(struct net_device *dev);
uint8_t *wlan_hdd_get_intf_addr(struct hdd_context *hdd_ctx);
void wlan_hdd_release_intf_addr(struct hdd_context *hdd_ctx,

View file

@ -1030,6 +1030,32 @@ static int wlan_hdd_set_pre_cac_complete_status(struct hdd_adapter *ap_adapter,
return 0;
}
/**
* hdd_check_adapter() - check adapter existing or not
* @adapter: adapter
*
* Check adapter in the hdd global list or not
*
* Return: true if adapter exists.
*/
static bool hdd_check_adapter(struct hdd_adapter *adapter)
{
struct hdd_adapter *temp;
struct hdd_context *hdd_ctx;
hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
if (!hdd_ctx) {
hdd_err("HDD context is null");
return false;
}
hdd_for_each_adapter(hdd_ctx, temp) {
if (temp == adapter)
return true;
}
return false;
}
/**
* __wlan_hdd_sap_pre_cac_failure() - Process the pre cac failure
* @data: AP adapter
@ -1046,7 +1072,7 @@ static void __wlan_hdd_sap_pre_cac_failure(void *data)
hdd_enter();
adapter = (struct hdd_adapter *) data;
if (!adapter ||
if (!adapter || !hdd_check_adapter(adapter) ||
adapter->magic != WLAN_HDD_ADAPTER_MAGIC) {
hdd_err("SAP Pre CAC adapter invalid");
return;
@ -1060,7 +1086,7 @@ static void __wlan_hdd_sap_pre_cac_failure(void *data)
wlan_hdd_release_intf_addr(hdd_ctx,
adapter->mac_addr.bytes);
hdd_stop_adapter(hdd_ctx, adapter);
hdd_stop_adapter_ext(hdd_ctx, adapter, HDD_IN_CAC_WORK_TH_CONTEXT);
hdd_close_adapter(hdd_ctx, adapter, false);
}
@ -1097,8 +1123,9 @@ static void wlan_hdd_sap_pre_cac_success(void *data)
hdd_enter();
adapter = (struct hdd_adapter *) data;
if (!adapter) {
hdd_err("AP adapter is NULL");
if (!adapter || !hdd_check_adapter(adapter) ||
adapter->magic != WLAN_HDD_ADAPTER_MAGIC) {
hdd_err("SAP Pre CAC adapter invalid");
return;
}
@ -1111,7 +1138,7 @@ static void wlan_hdd_sap_pre_cac_success(void *data)
cds_ssr_protect(__func__);
wlan_hdd_release_intf_addr(hdd_ctx,
adapter->mac_addr.bytes);
hdd_stop_adapter(hdd_ctx, adapter);
hdd_stop_adapter_ext(hdd_ctx, adapter, HDD_IN_CAC_WORK_TH_CONTEXT);
hdd_close_adapter(hdd_ctx, adapter, false);
cds_ssr_unprotect(__func__);

View file

@ -4831,8 +4831,8 @@ QDF_STATUS hdd_close_adapter(struct hdd_context *hdd_ctx, struct hdd_adapter *ad
/* cleanup adapter */
policy_mgr_clear_concurrency_mode(hdd_ctx->hdd_psoc,
adapter->device_mode);
hdd_cleanup_adapter(hdd_ctx, adapter, rtnl_held);
hdd_remove_adapter(hdd_ctx, adapter);
hdd_cleanup_adapter(hdd_ctx, adapter, rtnl_held);
/* conditionally restart the bw timer */
hdd_bus_bw_compute_timer_try_start(hdd_ctx);
@ -4927,6 +4927,13 @@ void wlan_hdd_reset_prob_rspies(struct hdd_adapter *adapter)
QDF_STATUS hdd_stop_adapter(struct hdd_context *hdd_ctx,
struct hdd_adapter *adapter)
{
return hdd_stop_adapter_ext(hdd_ctx, adapter, 0);
}
QDF_STATUS hdd_stop_adapter_ext(struct hdd_context *hdd_ctx,
struct hdd_adapter *adapter,
enum hdd_adapter_stop_flag_t flag)
{
QDF_STATUS qdf_ret_status = QDF_STATUS_SUCCESS;
struct csr_roam_profile *roam_profile;
@ -5058,7 +5065,8 @@ QDF_STATUS hdd_stop_adapter(struct hdd_context *hdd_ctx,
wlansap_reset_sap_config_add_ie(sap_config,
eUPDATE_IE_ALL);
ucfg_ipa_flush(hdd_ctx->hdd_pdev);
cds_flush_work(&hdd_ctx->sap_pre_cac_work);
if (!(flag & HDD_IN_CAC_WORK_TH_CONTEXT))
cds_flush_work(&hdd_ctx->sap_pre_cac_work);
/* fallthrough */
case QDF_P2P_GO_MODE: