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

Commit f6a04016 authored by Sarada Prasanna Garnayak's avatar Sarada Prasanna Garnayak Committed by Gerrit - the friendly Code Review server
Browse files

ath10k: fix the race condition in wow suspend-resume cycle



During wow suspend enable the wow event wakeup source if
the STA is in connected state and during wow resume report
the wow wakeup reason to mac80211 and nl80211 layer.

This fix adds support to synchronize the wow suspend-resume cycle
and prevent the device to wakeup from wow suspend state by an invalid
wow event when the STA is in the disconnected state.

CRs-Fixed: 2175472
Change-Id: I093f3c5a80b4f67578dfb114b9cc9ea778f19168
Signed-off-by: default avatarSarada Prasanna Garnayak <sgarna@codeaurora.org>
parent 34594476
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -4215,6 +4215,7 @@ void ath10k_wmi_event_wow_wakeup_host(struct ath10k *ar, struct sk_buff *skb)
		return;
	}

	ar->wow.wakeup_reason = ev.wake_reason;
	ath10k_dbg(ar, ATH10K_DBG_WMI, "wow wakeup host reason %s\n",
		   wow_reason(ev.wake_reason));
}
+52 −11
Original line number Diff line number Diff line
@@ -84,6 +84,7 @@ static int ath10k_vif_wow_set_wakeups(struct ath10k_vif *arvif,
	int ret, i;
	unsigned long wow_mask = 0;
	struct ath10k *ar = arvif->ar;
	struct ieee80211_bss_conf *bss = &arvif->vif->bss_conf;
	const struct cfg80211_pkt_pattern *patterns = wowlan->patterns;
	int pattern_id = 0;

@@ -102,6 +103,7 @@ static int ath10k_vif_wow_set_wakeups(struct ath10k_vif *arvif,
		__set_bit(WOW_RA_MATCH_EVENT, &wow_mask);
		break;
	case WMI_VDEV_TYPE_STA:
		if (arvif->is_up && bss->assoc) {
			if (wowlan->disconnect) {
				__set_bit(WOW_DEAUTH_RECVD_EVENT, &wow_mask);
				__set_bit(WOW_DISASSOC_RECVD_EVENT, &wow_mask);
@@ -111,9 +113,9 @@ static int ath10k_vif_wow_set_wakeups(struct ath10k_vif *arvif,

			if (wowlan->magic_pkt)
				__set_bit(WOW_MAGIC_PKT_RECVD_EVENT, &wow_mask);

			if (wowlan->gtk_rekey_failure)
				__set_bit(WOW_GTK_ERR_EVENT, &wow_mask);
		}
		break;
	default:
		break;
@@ -464,6 +466,44 @@ void ath10k_wow_op_set_wakeup(struct ieee80211_hw *hw, bool enabled)
	mutex_unlock(&ar->conf_mutex);
}

static void ath10k_wow_op_report_wakeup_reason(struct ath10k *ar)
{
	struct cfg80211_wowlan_wakeup *wakeup = &ar->wow.wakeup;
	struct ath10k_vif *arvif;

	switch (ar->wow.wakeup_reason) {
	case WOW_REASON_UNSPECIFIED:
		wakeup = NULL;
		break;
	case WOW_REASON_RECV_MAGIC_PATTERN:
		wakeup->magic_pkt = true;
		break;
	case WOW_REASON_DEAUTH_RECVD:
	case WOW_REASON_DISASSOC_RECVD:
	case WOW_REASON_AP_ASSOC_LOST:
	case WOW_REASON_CSA_EVENT:
		wakeup->disconnect = true;
		break;
	case WOW_REASON_GTK_HS_ERR:
		wakeup->gtk_rekey_failure = true;
		break;
	}

	if (wakeup) {
		wakeup->pattern_idx = -1;
		list_for_each_entry(arvif, &ar->arvifs, list) {
			ieee80211_report_wowlan_wakeup(arvif->vif,
						       wakeup, GFP_KERNEL);
			if (wakeup->disconnect)
				ieee80211_resume_disconnect(arvif->vif);
		}
	} else {
		list_for_each_entry(arvif, &ar->arvifs, list)
			ieee80211_report_wowlan_wakeup(arvif->vif,
						       NULL, GFP_KERNEL);
	}
}

int ath10k_wow_op_resume(struct ieee80211_hw *hw)
{
	struct ath10k *ar = hw->priv;
@@ -518,6 +558,7 @@ exit:
		}
	}

	ath10k_wow_op_report_wakeup_reason(ar);
	mutex_unlock(&ar->conf_mutex);
	return ret;
}
+2 −0
Original line number Diff line number Diff line
@@ -17,8 +17,10 @@
#define _WOW_H_

struct ath10k_wow {
	u32 wakeup_reason;
	u32 max_num_patterns;
	struct completion wakeup_completed;
	struct cfg80211_wowlan_wakeup wakeup;
	struct wiphy_wowlan_support wowlan_support;
};