From: Kalle Valo Date: Tue, 8 Oct 2013 18:45:25 +0000 (+0300) Subject: ath10k: fix ath10k_debug_start() locking X-Git-Url: http://git.maquefel.me/?a=commitdiff_plain;h=60631c5c10efbf24a77e1ca1ddecdb4e82ed2833;p=linux.git ath10k: fix ath10k_debug_start() locking ath10k_debug_start() was not called with conf_mutex, fix that. Also there was a deadlock in ath10k_debug_stop(), rename it to ath10k_debug_destroy() and call it only when the device is destroyed. Reported-by: Mohammed Shafi Shajakhan Signed-off-by: Kalle Valo --- diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 5acb4048b008a..e016f5141c663 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -737,6 +737,8 @@ EXPORT_SYMBOL(ath10k_core_create); void ath10k_core_destroy(struct ath10k *ar) { + ath10k_debug_destroy(ar); + flush_workqueue(ar->workqueue); destroy_workqueue(ar->workqueue); @@ -748,6 +750,8 @@ int ath10k_core_start(struct ath10k *ar) { int status; + lockdep_assert_held(&ar->conf_mutex); + ath10k_bmi_start(ar); if (ath10k_init_configure_target(ar)) { @@ -836,6 +840,8 @@ EXPORT_SYMBOL(ath10k_core_start); void ath10k_core_stop(struct ath10k *ar) { + lockdep_assert_held(&ar->conf_mutex); + ath10k_debug_stop(ar); ath10k_htc_stop(&ar->htc); ath10k_htt_detach(&ar->htt); @@ -883,15 +889,21 @@ static int ath10k_core_probe_fw(struct ath10k *ar) return ret; } + mutex_lock(&ar->conf_mutex); + ret = ath10k_core_start(ar); if (ret) { ath10k_err("could not init core (%d)\n", ret); ath10k_core_free_firmware_files(ar); ath10k_hif_power_down(ar); + mutex_unlock(&ar->conf_mutex); return ret; } ath10k_core_stop(ar); + + mutex_unlock(&ar->conf_mutex); + ath10k_hif_power_down(ar); return 0; } diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index 59615c7f217e4..760ff2289e3cf 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c @@ -618,6 +618,8 @@ int ath10k_debug_start(struct ath10k *ar) { int ret; + lockdep_assert_held(&ar->conf_mutex); + ret = ath10k_debug_htt_stats_req(ar); if (ret) /* continue normally anyway, this isn't serious */ @@ -628,7 +630,13 @@ int ath10k_debug_start(struct ath10k *ar) void ath10k_debug_stop(struct ath10k *ar) { - cancel_delayed_work_sync(&ar->debug.htt_stats_dwork); + lockdep_assert_held(&ar->conf_mutex); + + /* Must not use _sync to avoid deadlock, we do that in + * ath10k_debug_destroy(). The check for htt_stats_mask is to avoid + * warning from del_timer(). */ + if (ar->debug.htt_stats_mask != 0) + cancel_delayed_work(&ar->debug.htt_stats_dwork); } int ath10k_debug_create(struct ath10k *ar) @@ -662,6 +670,11 @@ int ath10k_debug_create(struct ath10k *ar) return 0; } +void ath10k_debug_destroy(struct ath10k *ar) +{ + cancel_delayed_work_sync(&ar->debug.htt_stats_dwork); +} + #endif /* CONFIG_ATH10K_DEBUGFS */ #ifdef CONFIG_ATH10K_DEBUG diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h index fa581486626f7..46e640a6968d0 100644 --- a/drivers/net/wireless/ath/ath10k/debug.h +++ b/drivers/net/wireless/ath/ath10k/debug.h @@ -46,6 +46,7 @@ extern __printf(1, 2) int ath10k_warn(const char *fmt, ...); int ath10k_debug_start(struct ath10k *ar); void ath10k_debug_stop(struct ath10k *ar); int ath10k_debug_create(struct ath10k *ar); +void ath10k_debug_destroy(struct ath10k *ar); void ath10k_debug_read_service_map(struct ath10k *ar, void *service_map, size_t map_size); @@ -67,6 +68,10 @@ static inline int ath10k_debug_create(struct ath10k *ar) return 0; } +static inline void ath10k_debug_destroy(struct ath10k *ar) +{ +} + static inline void ath10k_debug_read_service_map(struct ath10k *ar, void *service_map, size_t map_size)