diff mbox

[07/17] ath9k: Check WOW triggers properly

Message ID 1422624937-4810-8-git-send-email-sujith@msujith.org (mailing list archive)
State Accepted
Delegated to: Kalle Valo
Headers show

Commit Message

Sujith Manoharan Jan. 30, 2015, 1:35 p.m. UTC
From: Sujith Manoharan <c_manoha@qca.qualcomm.com>

This patch makes sure that valid WOW triggers
are present before trying to suspend the device.
Also, introduce and use ATH_OP_WOW_ENABLED to
bypass PCI suspend and clear it in resume().

Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath.h       |  1 +
 drivers/net/wireless/ath/ath9k/pci.c |  5 +++-
 drivers/net/wireless/ath/ath9k/wow.c | 53 ++++++++++++++++--------------------
 3 files changed, 29 insertions(+), 30 deletions(-)
diff mbox

Patch

diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h
index ccba4fe..1eebe2e 100644
--- a/drivers/net/wireless/ath/ath.h
+++ b/drivers/net/wireless/ath/ath.h
@@ -64,6 +64,7 @@  enum ath_op_flags {
 	ATH_OP_HW_RESET,
 	ATH_OP_SCANNING,
 	ATH_OP_MULTI_CHANNEL,
+	ATH_OP_WOW_ENABLED,
 };
 
 enum ath_bus_type {
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c
index cc5c681..e6fef1b 100644
--- a/drivers/net/wireless/ath/ath9k/pci.c
+++ b/drivers/net/wireless/ath/ath9k/pci.c
@@ -998,9 +998,12 @@  static int ath_pci_suspend(struct device *device)
 	struct pci_dev *pdev = to_pci_dev(device);
 	struct ieee80211_hw *hw = pci_get_drvdata(pdev);
 	struct ath_softc *sc = hw->priv;
+	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 
-	if (sc->wow_enabled)
+	if (test_bit(ATH_OP_WOW_ENABLED, &common->op_flags)) {
+		dev_info(&pdev->dev, "WOW is enabled, bypassing PCI suspend\n");
 		return 0;
+	}
 
 	/* The device has to be moved to FULLSLEEP forcibly.
 	 * Otherwise the chip never moved to full sleep,
diff --git a/drivers/net/wireless/ath/ath9k/wow.c b/drivers/net/wireless/ath/ath9k/wow.c
index 8bcbaa9..c0c564d 100644
--- a/drivers/net/wireless/ath/ath9k/wow.c
+++ b/drivers/net/wireless/ath/ath9k/wow.c
@@ -23,21 +23,21 @@  static const struct wiphy_wowlan_support ath9k_wowlan_support = {
 	.pattern_max_len = MAX_PATTERN_SIZE,
 };
 
-static void ath9k_wow_map_triggers(struct ath_softc *sc,
-				   struct cfg80211_wowlan *wowlan,
-				   u32 *wow_triggers)
+static u8 ath9k_wow_map_triggers(struct ath_softc *sc,
+				 struct cfg80211_wowlan *wowlan)
 {
+	u8 wow_triggers = 0;
+
 	if (wowlan->disconnect)
-		*wow_triggers |= AH_WOW_LINK_CHANGE |
-				 AH_WOW_BEACON_MISS;
+		wow_triggers |= AH_WOW_LINK_CHANGE |
+				AH_WOW_BEACON_MISS;
 	if (wowlan->magic_pkt)
-		*wow_triggers |= AH_WOW_MAGIC_PATTERN_EN;
+		wow_triggers |= AH_WOW_MAGIC_PATTERN_EN;
 
 	if (wowlan->n_patterns)
-		*wow_triggers |= AH_WOW_USER_PATTERN_EN;
-
-	sc->wow_enabled = *wow_triggers;
+		wow_triggers |= AH_WOW_USER_PATTERN_EN;
 
+	return wow_triggers;
 }
 
 static void ath9k_wow_add_disassoc_deauth_pattern(struct ath_softc *sc)
@@ -45,7 +45,7 @@  static void ath9k_wow_add_disassoc_deauth_pattern(struct ath_softc *sc)
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_common *common = ath9k_hw_common(ah);
 	int pattern_count = 0;
-	int i, byte_cnt;
+	int i, byte_cnt = 0;
 	u8 dis_deauth_pattern[MAX_PATTERN_SIZE];
 	u8 dis_deauth_mask[MAX_PATTERN_SIZE];
 
@@ -80,12 +80,7 @@  static void ath9k_wow_add_disassoc_deauth_pattern(struct ath_softc *sc)
 	 *			    | x:x:x:x:x:x  -- 22 bytes
 	 */
 
-	/* Create Disassociate Pattern first */
-
-	byte_cnt = 0;
-
 	/* Fill out the mask with all FF's */
-
 	for (i = 0; i < MAX_PATTERN_MASK_SIZE; i++)
 		dis_deauth_mask[i] = 0xff;
 
@@ -108,17 +103,13 @@  static void ath9k_wow_add_disassoc_deauth_pattern(struct ath_softc *sc)
 	byte_cnt += 6;
 
 	/* copy the bssid, its same as the source mac address */
-
 	memcpy((dis_deauth_pattern + byte_cnt), common->curbssid, ETH_ALEN);
 
 	/* Create Disassociate pattern mask */
-
 	dis_deauth_mask[0] = 0xfe;
 	dis_deauth_mask[1] = 0x03;
 	dis_deauth_mask[2] = 0xc0;
 
-	ath_dbg(common, WOW, "Adding disassoc/deauth patterns for WoW\n");
-
 	ath9k_hw_wow_apply_pattern(ah, dis_deauth_pattern, dis_deauth_mask,
 				   pattern_count, byte_cnt);
 
@@ -131,7 +122,6 @@  static void ath9k_wow_add_disassoc_deauth_pattern(struct ath_softc *sc)
 
 	ath9k_hw_wow_apply_pattern(ah, dis_deauth_pattern, dis_deauth_mask,
 				   pattern_count, byte_cnt);
-
 }
 
 static void ath9k_wow_add_pattern(struct ath_softc *sc,
@@ -190,7 +180,7 @@  int ath9k_suspend(struct ieee80211_hw *hw,
 	struct ath_softc *sc = hw->priv;
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_common *common = ath9k_hw_common(ah);
-	u32 wow_triggers_enabled = 0;
+	u8 triggers;
 	int ret = 0;
 
 	ath9k_deinit_channel_context(sc);
@@ -230,14 +220,16 @@  int ath9k_suspend(struct ieee80211_hw *hw,
 		goto fail_wow;
 	}
 
+	triggers = ath9k_wow_map_triggers(sc, wowlan);
+	if (!triggers) {
+		ath_dbg(common, WOW, "No valid WoW triggers\n");
+		ret = 1;
+		goto fail_wow;
+	}
+
 	ath_cancel_work(sc);
 	ath_stop_ani(sc);
 
-	ath9k_wow_map_triggers(sc, wowlan, &wow_triggers_enabled);
-
-	ath_dbg(common, WOW, "WoW triggers enabled 0x%x\n",
-		wow_triggers_enabled);
-
 	ath9k_ps_wakeup(sc);
 
 	ath9k_stop_btcoex(sc);
@@ -248,7 +240,7 @@  int ath9k_suspend(struct ieee80211_hw *hw,
 	 */
 	ath9k_wow_add_disassoc_deauth_pattern(sc);
 
-	if (wow_triggers_enabled & AH_WOW_USER_PATTERN_EN)
+	if (triggers & AH_WOW_USER_PATTERN_EN)
 		ath9k_wow_add_pattern(sc, wowlan);
 
 	spin_lock_bh(&sc->sc_pcu_lock);
@@ -273,12 +265,13 @@  int ath9k_suspend(struct ieee80211_hw *hw,
 	synchronize_irq(sc->irq);
 	tasklet_kill(&sc->intr_tq);
 
-	ath9k_hw_wow_enable(ah, wow_triggers_enabled);
+	ath9k_hw_wow_enable(ah, triggers);
 
 	ath9k_ps_restore(sc);
-	ath_dbg(common, ANY, "WoW enabled in ath9k\n");
+	ath_dbg(common, WOW, "Suspend with WoW triggers: 0x%x\n", triggers);
 	atomic_inc(&sc->wow_sleep_proc_intr);
 
+	set_bit(ATH_OP_WOW_ENABLED, &common->op_flags);
 fail_wow:
 	mutex_unlock(&sc->mutex);
 	return ret;
@@ -327,6 +320,8 @@  int ath9k_resume(struct ieee80211_hw *hw)
 	ath_restart_work(sc);
 	ath9k_start_btcoex(sc);
 
+	clear_bit(ATH_OP_WOW_ENABLED, &common->op_flags);
+
 	ath9k_ps_restore(sc);
 	mutex_unlock(&sc->mutex);