From 86177c2c77718fac559ef7e3362123a3f194a327 Mon Sep 17 00:00:00 2001 From: Rajeev Kumar Date: Thu, 16 Mar 2017 19:44:39 -0700 Subject: [PATCH] qcacld-3.0: Fix race condition between external threads and module stop External threads and interface change timer are racing against each other leading to various side effects. Fix the race condition between external threads and interface change timer by leveraging existing ssr/driver unload protection mechanism for module stop. Change-Id: Ic3d6d516161afee1dd65abb8f1eafe160bea54ff CRs-Fixed: 2021483 --- core/cds/inc/cds_sched.h | 7 +++++++ core/cds/src/cds_sched.c | 5 +++++ core/hdd/src/wlan_hdd_main.c | 10 ++++++++++ 3 files changed, 22 insertions(+) diff --git a/core/cds/inc/cds_sched.h b/core/cds/inc/cds_sched.h index fa54829895..5623ec671a 100644 --- a/core/cds/inc/cds_sched.h +++ b/core/cds/inc/cds_sched.h @@ -467,6 +467,13 @@ void cds_ssr_unprotect(const char *caller_func); bool cds_wait_for_external_threads_completion(const char *caller_func); int cds_get_gfp_flags(void); +/** + * cds_return_external_threads_count() - return active external thread calls + * + * Return: total number of active extrenal threads in driver + */ +int cds_return_external_threads_count(void); + /** * cds_shutdown_notifier_register() - Register for shutdown notification * @cb : Call back to be called diff --git a/core/cds/src/cds_sched.c b/core/cds/src/cds_sched.c index a0327422b4..4c5cb2dae1 100644 --- a/core/cds/src/cds_sched.c +++ b/core/cds/src/cds_sched.c @@ -1179,6 +1179,11 @@ bool cds_wait_for_external_threads_completion(const char *caller_func) return true; } +int cds_return_external_threads_count(void) +{ + return atomic_read(&ssr_protect_entry_count); +} + /** * cds_get_gfp_flags(): get GFP flags * diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 2dd6edb9be..6a4fc8d899 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -8735,6 +8735,16 @@ int hdd_wlan_stop_modules(hdd_context_t *hdd_ctx) mutex_lock(&hdd_ctx->iface_change_lock); hdd_ctx->stop_modules_in_progress = true; + if (cds_return_external_threads_count() || hdd_ctx->isWiphySuspended) { + mutex_unlock(&hdd_ctx->iface_change_lock); + hdd_warn("External threads %d wiphy suspend %d", + cds_return_external_threads_count(), + hdd_ctx->isWiphySuspended); + qdf_mc_timer_start(&hdd_ctx->iface_change_timer, + hdd_ctx->config->iface_change_wait_time); + return 0; + } + hdd_info("Present Driver Status: %d", hdd_ctx->driver_status); switch (hdd_ctx->driver_status) {