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

Commit 725b8277 authored by Arik Nemtsov's avatar Arik Nemtsov Committed by Luciano Coelho
Browse files

wlcore: prevent recovery in the middle of resume



Take the mutex early in the resume handler and use the locked version of
the IRQ routine. This ensures any recoveries queued will only take place
after resume has fully completed.

Signed-off-by: default avatarArik Nemtsov <arik@wizery.com>
Signed-off-by: default avatarLuciano Coelho <coelho@ti.com>
parent b5b45b3c
Loading
Loading
Loading
Loading
+8 −3
Original line number Original line Diff line number Diff line
@@ -1723,6 +1723,7 @@ static int wl1271_op_resume(struct ieee80211_hw *hw)
	struct wl12xx_vif *wlvif;
	struct wl12xx_vif *wlvif;
	unsigned long flags;
	unsigned long flags;
	bool run_irq_work = false, pending_recovery;
	bool run_irq_work = false, pending_recovery;
	int ret;


	wl1271_debug(DEBUG_MAC80211, "mac80211 resume wow=%d",
	wl1271_debug(DEBUG_MAC80211, "mac80211 resume wow=%d",
		     wl->wow_enabled);
		     wl->wow_enabled);
@@ -1738,6 +1739,8 @@ static int wl1271_op_resume(struct ieee80211_hw *hw)
		run_irq_work = true;
		run_irq_work = true;
	spin_unlock_irqrestore(&wl->wl_lock, flags);
	spin_unlock_irqrestore(&wl->wl_lock, flags);


	mutex_lock(&wl->mutex);

	/* test the recovery flag before calling any SDIO functions */
	/* test the recovery flag before calling any SDIO functions */
	pending_recovery = test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS,
	pending_recovery = test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS,
				    &wl->flags);
				    &wl->flags);
@@ -1747,13 +1750,15 @@ static int wl1271_op_resume(struct ieee80211_hw *hw)
			     "run postponed irq_work directly");
			     "run postponed irq_work directly");


		/* don't talk to the HW if recovery is pending */
		/* don't talk to the HW if recovery is pending */
		if (!pending_recovery)
		if (!pending_recovery) {
			wlcore_irq(0, wl);
			ret = wlcore_irq_locked(wl);
			if (ret)
				wl12xx_queue_recovery_work(wl);
		}


		wlcore_enable_interrupts(wl);
		wlcore_enable_interrupts(wl);
	}
	}


	mutex_lock(&wl->mutex);
	if (pending_recovery) {
	if (pending_recovery) {
		wl1271_warning("queuing forgotten recovery on resume");
		wl1271_warning("queuing forgotten recovery on resume");
		ieee80211_queue_work(wl->hw, &wl->recovery_work);
		ieee80211_queue_work(wl->hw, &wl->recovery_work);