From b1c8990ec8f16f5bdc3fc362f6d0498f1e5dfd2f Mon Sep 17 00:00:00 2001 From: Dustin Brown Date: Wed, 30 May 2018 13:05:22 -0700 Subject: [PATCH] qcacld-3.0: Set unloading before grabbing lock In wlan_hdd_pld_remove(), a global mutext is grabbed before setting the global "unloading" flag. In the case of __hdd_open(), this flag is checked before also grabbing the same lock. Ultimately this can lead to deadlocks when other shared locks are involved. As a short-to-medium term work around, set the unloading flag before waiting for external threads to exit. After external threads have exited, then grab the lock to avoid deadlocking with external threads like those invoking __hdd_open(). Effectively, this does a stop-and-flush on external threads into the driver before unloading. Change-Id: Iaaf52d730807abd9a99950970988ec58a1abb87d CRs-Fixed: 2251271 --- core/hdd/src/wlan_hdd_driver_ops.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/hdd/src/wlan_hdd_driver_ops.c b/core/hdd/src/wlan_hdd_driver_ops.c index 450a6b3c8c60..79c2b3621f13 100644 --- a/core/hdd/src/wlan_hdd_driver_ops.c +++ b/core/hdd/src/wlan_hdd_driver_ops.c @@ -471,12 +471,16 @@ static void wlan_hdd_remove(struct device *dev) if (!cds_wait_for_external_threads_completion(__func__)) hdd_warn("External threads are still active attempting driver unload anyway"); + mutex_lock(&hdd_init_deinit_lock); + hdd_start_driver_ops_timer(eHDD_DRV_OP_REMOVE); if (QDF_IS_EPPING_ENABLED(cds_get_conparam())) { epping_disable(); epping_close(); } else { __hdd_wlan_exit(); } + hdd_stop_driver_ops_timer(); + mutex_unlock(&hdd_init_deinit_lock); cds_set_driver_in_bad_state(false); cds_set_unload_in_progress(false); @@ -1267,13 +1271,9 @@ static void wlan_hdd_pld_remove(struct device *dev, enum pld_bus_type bus_type) { hdd_enter(); - mutex_lock(&hdd_init_deinit_lock); - hdd_start_driver_ops_timer(eHDD_DRV_OP_REMOVE); wlan_hdd_remove(dev); - hdd_stop_driver_ops_timer(); - mutex_unlock(&hdd_init_deinit_lock); hdd_exit(); }