Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 60631c5c authored by Kalle Valo's avatar Kalle Valo
Browse files

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: default avatarMohammed Shafi Shajakhan <mohammed@qca.qualcomm.com>
Signed-off-by: default avatarKalle Valo <kvalo@qca.qualcomm.com>
parent a24b88b5
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -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;
}
+14 −1
Original line number Diff line number Diff line
@@ -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
+5 −0
Original line number Diff line number Diff line
@@ -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)