2015-02-02 12:48:14

by Sujith Manoharan

[permalink] [raw]
Subject: [PATCH 0/6] ath9k patches

From: Sujith Manoharan <[email protected]>

ath9k patches for -next.

Sujith Manoharan (6):
ath9k: Add support for more WOW patterns
ath9k: Register correct WOW details with mac80211
ath9k: Fix issues with WoW enable
ath9k: Program AR_WA correctly
ath9k: Clear TSF2 properly
ath9k: Choose correct rate for 2GHz channel

drivers/net/wireless/ath/ath9k/ar9003_wow.c | 281 ++++++++++++++--------------
drivers/net/wireless/ath/ath9k/hw.h | 3 +-
drivers/net/wireless/ath/ath9k/reg.h | 2 +
drivers/net/wireless/ath/ath9k/reg_wow.h | 39 +++-
drivers/net/wireless/ath/ath9k/wow.c | 16 +-
5 files changed, 200 insertions(+), 141 deletions(-)

--
2.2.2



2015-02-02 12:48:22

by Sujith Manoharan

[permalink] [raw]
Subject: [PATCH 5/6] ath9k: Clear TSF2 properly

From: Sujith Manoharan <[email protected]>

Chips in the AR9003 family have a second TSF, which
needs to be cleared when putting the card to
sleep.

Signed-off-by: Sujith Manoharan <[email protected]>
---
drivers/net/wireless/ath/ath9k/ar9003_wow.c | 9 +++++++++
drivers/net/wireless/ath/ath9k/reg.h | 2 ++
2 files changed, 11 insertions(+)

diff --git a/drivers/net/wireless/ath/ath9k/ar9003_wow.c b/drivers/net/wireless/ath/ath9k/ar9003_wow.c
index cf45b91..2dc50a0 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_wow.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_wow.c
@@ -35,6 +35,15 @@ static void ath9k_hw_set_powermode_wow_sleep(struct ath_hw *ah)
return;
}

+ if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) {
+ if (!REG_READ(ah, AR_MAC_PCU_GEN_TIMER_TSF_SEL))
+ REG_CLR_BIT(ah, AR_DIRECT_CONNECT, AR_DC_TSF2_ENABLE);
+ } else if (AR_SREV_9485(ah)){
+ if (!(REG_READ(ah, AR_NDP2_TIMER_MODE) &
+ AR_GEN_TIMERS2_MODE_ENABLE_MASK))
+ REG_CLR_BIT(ah, AR_DIRECT_CONNECT, AR_DC_TSF2_ENABLE);
+ }
+
REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_ON_INT);
}

diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h
index b1b803d..9587ec6 100644
--- a/drivers/net/wireless/ath/ath9k/reg.h
+++ b/drivers/net/wireless/ath/ath9k/reg.h
@@ -1883,6 +1883,7 @@ enum {
#define AR_FIRST_NDP_TIMER 7
#define AR_NDP2_PERIOD 0x81a0
#define AR_NDP2_TIMER_MODE 0x81c0
+#define AR_GEN_TIMERS2_MODE_ENABLE_MASK 0x000000FF

#define AR_GEN_TIMERS(_i) (0x8200 + ((_i) << 2))
#define AR_NEXT_TBTT_TIMER AR_GEN_TIMERS(0)
@@ -1978,6 +1979,7 @@ enum {

#define AR_DIRECT_CONNECT 0x83a0
#define AR_DC_AP_STA_EN 0x00000001
+#define AR_DC_TSF2_ENABLE 0x00000001

#define AR_AES_MUTE_MASK0 0x805c
#define AR_AES_MUTE_MASK0_FC 0x0000FFFF
--
2.2.2


2015-02-02 12:48:18

by Sujith Manoharan

[permalink] [raw]
Subject: [PATCH 3/6] ath9k: Fix issues with WoW enable

From: Sujith Manoharan <[email protected]>

This patch addresses several issues with the
ath9k_hw_wow_enable() routine:

* The usage of set/clr variables is removed. Writing
the required values to registers is cleaner.

* The shift value of 28 for the contention window field
in AR_WOW_PATTERN is incorrect, change it to 27.

* Disabling Keep Alive needs to be done based on the
LINK_CHANGE option. This is done unconditionally now,
fix this.

* The workaround for the D1/D3 issue is required only
for AR9462.

* The bitfield for enabling pattern matching for packets
less than 256 bytes has expanded for new chips, handle
this accordingly.

* General cleanup.

Signed-off-by: Sujith Manoharan <[email protected]>
---
drivers/net/wireless/ath/ath9k/ar9003_wow.c | 181 ++++++++++++++--------------
drivers/net/wireless/ath/ath9k/hw.h | 2 +-
drivers/net/wireless/ath/ath9k/reg_wow.h | 5 +-
3 files changed, 93 insertions(+), 95 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/ar9003_wow.c b/drivers/net/wireless/ath/ath9k/ar9003_wow.c
index 4b53d0b..6ffa0e0 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_wow.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_wow.c
@@ -222,14 +222,9 @@ EXPORT_SYMBOL(ath9k_hw_wow_wakeup);
void ath9k_hw_wow_enable(struct ath_hw *ah, u32 pattern_enable)
{
u32 wow_event_mask;
+ u32 keep_alive, magic_pattern, host_pm_ctrl;
u32 set, clr;

- /*
- * wow_event_mask is a mask to the AR_WOW_PATTERN register to
- * indicate which WoW events we have enabled. The WoW events
- * are from the 'pattern_enable' in this function and
- * 'pattern_count' of ath9k_hw_wow_apply_pattern()
- */
wow_event_mask = ah->wow.wow_event_mask;

/*
@@ -249,152 +244,154 @@ void ath9k_hw_wow_enable(struct ath_hw *ah, u32 pattern_enable)
}

/*
- * set the power states appropriately and enable PME
+ * AR_PMCTRL_HOST_PME_EN - Override PME enable in configuration
+ * space and allow MAC to generate WoW anyway.
+ *
+ * AR_PMCTRL_PWR_PM_CTRL_ENA - ???
+ *
+ * AR_PMCTRL_AUX_PWR_DET - PCI core SYS_AUX_PWR_DET signal,
+ * needs to be set for WoW in PCI mode.
+ *
+ * AR_PMCTRL_WOW_PME_CLR - WoW Clear Signal going to the MAC.
+ *
+ * Set the power states appropriately and enable PME.
+ *
+ * Set and clear WOW_PME_CLEAR for the chip
+ * to generate next wow signal.
*/
- set = AR_PMCTRL_HOST_PME_EN | AR_PMCTRL_PWR_PM_CTRL_ENA |
- AR_PMCTRL_AUX_PWR_DET | AR_PMCTRL_WOW_PME_CLR;
+ REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PMCTRL_HOST_PME_EN |
+ AR_PMCTRL_PWR_PM_CTRL_ENA |
+ AR_PMCTRL_AUX_PWR_DET |
+ AR_PMCTRL_WOW_PME_CLR);
+ REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, AR_PMCTRL_WOW_PME_CLR);

/*
- * set and clear WOW_PME_CLEAR registers for the chip
- * to generate next wow signal.
+ * Random Backoff.
+ *
+ * 31:28 in AR_WOW_PATTERN : Indicates the number of bits used in the
+ * contention window. For value N,
+ * the random backoff will be selected between
+ * 0 and (2 ^ N) - 1.
*/
- REG_SET_BIT(ah, AR_PCIE_PM_CTRL, set);
- clr = AR_PMCTRL_WOW_PME_CLR;
- REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, clr);
+ REG_SET_BIT(ah, AR_WOW_PATTERN,
+ AR_WOW_BACK_OFF_SHIFT(AR_WOW_PAT_BACKOFF));

/*
- * Setup for:
- * - beacon misses
- * - magic pattern
- * - keep alive timeout
- * - pattern matching
+ * AIFS time, Slot time, Keep Alive count.
*/
-
+ REG_SET_BIT(ah, AR_WOW_COUNT, AR_WOW_AIFS_CNT(AR_WOW_CNT_AIFS_CNT) |
+ AR_WOW_SLOT_CNT(AR_WOW_CNT_SLOT_CNT) |
+ AR_WOW_KEEP_ALIVE_CNT(AR_WOW_CNT_KA_CNT));
/*
- * Program default values for pattern backoff, aifs/slot/KAL count,
- * beacon miss timeout, KAL timeout, etc.
+ * Beacon timeout.
*/
- set = AR_WOW_BACK_OFF_SHIFT(AR_WOW_PAT_BACKOFF);
- REG_SET_BIT(ah, AR_WOW_PATTERN, set);
-
- set = AR_WOW_AIFS_CNT(AR_WOW_CNT_AIFS_CNT) |
- AR_WOW_SLOT_CNT(AR_WOW_CNT_SLOT_CNT) |
- AR_WOW_KEEP_ALIVE_CNT(AR_WOW_CNT_KA_CNT);
- REG_SET_BIT(ah, AR_WOW_COUNT, set);
-
if (pattern_enable & AH_WOW_BEACON_MISS)
- set = AR_WOW_BEACON_TIMO;
- /* We are not using beacon miss, program a large value */
+ REG_WRITE(ah, AR_WOW_BCN_TIMO, AR_WOW_BEACON_TIMO);
else
- set = AR_WOW_BEACON_TIMO_MAX;
-
- REG_WRITE(ah, AR_WOW_BCN_TIMO, set);
+ REG_WRITE(ah, AR_WOW_BCN_TIMO, AR_WOW_BEACON_TIMO_MAX);

/*
- * Keep alive timo in ms except AR9280
+ * Keep alive timeout in ms.
*/
if (!pattern_enable)
- set = AR_WOW_KEEP_ALIVE_NEVER;
+ REG_WRITE(ah, AR_WOW_KEEP_ALIVE_TIMO, AR_WOW_KEEP_ALIVE_NEVER);
else
- set = KAL_TIMEOUT * 32;
-
- REG_WRITE(ah, AR_WOW_KEEP_ALIVE_TIMO, set);
+ REG_WRITE(ah, AR_WOW_KEEP_ALIVE_TIMO, KAL_TIMEOUT * 32);

/*
- * Keep alive delay in us. based on 'power on clock',
- * therefore in usec
+ * Keep alive delay in us.
*/
- set = KAL_DELAY * 1000;
- REG_WRITE(ah, AR_WOW_KEEP_ALIVE_DELAY, set);
+ REG_WRITE(ah, AR_WOW_KEEP_ALIVE_DELAY, KAL_DELAY * 1000);

/*
- * Create keep alive pattern to respond to beacons
+ * Create keep alive pattern to respond to beacons.
*/
ath9k_wow_create_keep_alive_pattern(ah);

/*
- * Configure MAC WoW Registers
+ * Configure keep alive register.
*/
- set = 0;
+ keep_alive = REG_READ(ah, AR_WOW_KEEP_ALIVE);
+
/* Send keep alive timeouts anyway */
- clr = AR_WOW_KEEP_ALIVE_AUTO_DIS;
+ keep_alive &= ~AR_WOW_KEEP_ALIVE_AUTO_DIS;

- if (pattern_enable & AH_WOW_LINK_CHANGE)
+ if (pattern_enable & AH_WOW_LINK_CHANGE) {
+ keep_alive &= ~AR_WOW_KEEP_ALIVE_FAIL_DIS;
wow_event_mask |= AR_WOW_KEEP_ALIVE_FAIL;
- else
- set = AR_WOW_KEEP_ALIVE_FAIL_DIS;
+ } else {
+ keep_alive |= AR_WOW_KEEP_ALIVE_FAIL_DIS;
+ }

- set = AR_WOW_KEEP_ALIVE_FAIL_DIS;
- REG_RMW(ah, AR_WOW_KEEP_ALIVE, set, clr);
+ REG_WRITE(ah, AR_WOW_KEEP_ALIVE, keep_alive);

/*
- * we are relying on a bmiss failure. ensure we have
- * enough threshold to prevent false positives
+ * We are relying on a bmiss failure, ensure we have
+ * enough threshold to prevent false positives.
*/
REG_RMW_FIELD(ah, AR_RSSI_THR, AR_RSSI_THR_BM_THR,
AR_WOW_BMISSTHRESHOLD);

- set = 0;
- clr = 0;
-
if (pattern_enable & AH_WOW_BEACON_MISS) {
- set = AR_WOW_BEACON_FAIL_EN;
wow_event_mask |= AR_WOW_BEACON_FAIL;
+ REG_SET_BIT(ah, AR_WOW_BCN_EN, AR_WOW_BEACON_FAIL_EN);
} else {
- clr = AR_WOW_BEACON_FAIL_EN;
+ REG_CLR_BIT(ah, AR_WOW_BCN_EN, AR_WOW_BEACON_FAIL_EN);
}

- REG_RMW(ah, AR_WOW_BCN_EN, set, clr);
-
- set = 0;
- clr = 0;
/*
- * Enable the magic packet registers
+ * Enable the magic packet registers.
*/
+ magic_pattern = REG_READ(ah, AR_WOW_PATTERN);
+ magic_pattern |= AR_WOW_MAC_INTR_EN;
+
if (pattern_enable & AH_WOW_MAGIC_PATTERN_EN) {
- set = AR_WOW_MAGIC_EN;
+ magic_pattern |= AR_WOW_MAGIC_EN;
wow_event_mask |= AR_WOW_MAGIC_PAT_FOUND;
} else {
- clr = AR_WOW_MAGIC_EN;
+ magic_pattern &= ~AR_WOW_MAGIC_EN;
}
- set |= AR_WOW_MAC_INTR_EN;
- REG_RMW(ah, AR_WOW_PATTERN, set, clr);

+ REG_WRITE(ah, AR_WOW_PATTERN, magic_pattern);
+
+ /*
+ * Enable pattern matching for packets which are less
+ * than 256 bytes.
+ */
REG_WRITE(ah, AR_WOW_PATTERN_MATCH_LT_256B,
AR_WOW_PATTERN_SUPPORTED);

/*
- * Set the power states appropriately and enable PME
+ * Set the power states appropriately and enable PME.
*/
- clr = 0;
- set = AR_PMCTRL_PWR_STATE_D1D3 | AR_PMCTRL_HOST_PME_EN |
- AR_PMCTRL_PWR_PM_CTRL_ENA;
+ host_pm_ctrl = REG_READ(ah, AR_PCIE_PM_CTRL);
+ host_pm_ctrl |= AR_PMCTRL_PWR_STATE_D1D3 |
+ AR_PMCTRL_HOST_PME_EN |
+ AR_PMCTRL_PWR_PM_CTRL_ENA;
+ host_pm_ctrl &= ~AR_PCIE_PM_CTRL_ENA;

- clr = AR_PCIE_PM_CTRL_ENA;
- REG_RMW(ah, AR_PCIE_PM_CTRL, set, clr);
+ if (AR_SREV_9462(ah)) {
+ /*
+ * This is needed to prevent the chip waking up
+ * the host within 3-4 seconds with certain
+ * platform/BIOS.
+ */
+ host_pm_ctrl &= ~AR_PMCTRL_PWR_STATE_D1D3;
+ host_pm_ctrl |= AR_PMCTRL_PWR_STATE_D1D3_REAL;
+ }
+
+ REG_WRITE(ah, AR_PCIE_PM_CTRL, host_pm_ctrl);

/*
- * this is needed to prevent the chip waking up
- * the host within 3-4 seconds with certain
- * platform/BIOS. The fix is to enable
- * D1 & D3 to match original definition and
- * also match the OTP value. Anyway this
- * is more related to SW WOW.
+ * Enable sequence number generation when asleep.
*/
- clr = AR_PMCTRL_PWR_STATE_D1D3;
- REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, clr);
-
- set = AR_PMCTRL_PWR_STATE_D1D3_REAL;
- REG_SET_BIT(ah, AR_PCIE_PM_CTRL, set);
-
REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PRESERVE_SEQNUM);

- /* to bring down WOW power low margin */
- set = BIT(13);
- REG_SET_BIT(ah, AR_PCIE_PHY_REG3, set);
+ /* To bring down WOW power low margin */
+ REG_SET_BIT(ah, AR_PCIE_PHY_REG3, BIT(13));
+
/* HW WoW */
- clr = BIT(5);
- REG_CLR_BIT(ah, AR_PCU_MISC_MODE3, clr);
+ REG_CLR_BIT(ah, AR_PCU_MISC_MODE3, BIT(5));

ath9k_hw_set_powermode_wow_sleep(ah);
ah->wow.wow_event_mask = wow_event_mask;
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index c8b3d8f..e82e570 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -199,7 +199,7 @@
#define KAL_NUM_DESC_WORDS 12
#define KAL_ANTENNA_MODE 1
#define KAL_TO_DS 1
-#define KAL_DELAY 4 /*delay of 4ms between 2 KAL frames */
+#define KAL_DELAY 4 /* delay of 4ms between 2 KAL frames */
#define KAL_TIMEOUT 900

#define MAX_PATTERN_SIZE 256
diff --git a/drivers/net/wireless/ath/ath9k/reg_wow.h b/drivers/net/wireless/ath/ath9k/reg_wow.h
index 83f27f9..3abfca5 100644
--- a/drivers/net/wireless/ath/ath9k/reg_wow.h
+++ b/drivers/net/wireless/ath/ath9k/reg_wow.h
@@ -68,7 +68,7 @@
#define AR_CLR_MAC_INTERRUPT 0x20
#define AR_CLR_KA_INTERRUPT 0x40

-#define AR_WOW_BACK_OFF_SHIFT(x) ((x & 0xf) << 28) /* in usecs */
+#define AR_WOW_BACK_OFF_SHIFT(x) ((x & 0xf) << 27) /* in usecs */
#define AR_WOW_MAC_INTR_EN 0x00040000
#define AR_WOW_MAGIC_EN 0x00010000
#define AR_WOW_PATTERN_EN(x) (x & 0xff)
@@ -113,7 +113,8 @@
#define AR_WOW_KA_DESC_WORD2 0xe000
#define AR_WOW_TB_PATTERN(i) (0xe100 + (i << 8))
#define AR_WOW_TB_MASK(i) (0xec00 + (i << 5))
-#define AR_WOW_PATTERN_SUPPORTED 0xff
+#define AR_WOW_PATTERN_SUPPORTED_LEGACY 0xff
+#define AR_WOW_PATTERN_SUPPORTED 0xffff
#define AR_WOW_LENGTH_MAX 0xff
#define AR_WOW_LEN1_SHIFT(_i) ((0x3 - ((_i) & 0x3)) << 0x3)
#define AR_WOW_LENGTH1_MASK(_i) (AR_WOW_LENGTH_MAX << AR_WOW_LEN1_SHIFT(_i))
--
2.2.2


2015-02-02 12:48:15

by Sujith Manoharan

[permalink] [raw]
Subject: [PATCH 1/6] ath9k: Add support for more WOW patterns

From: Sujith Manoharan <[email protected]>

Newer chips like WB222, WB335 support more than
8 user-configurable patterns. This patch adds
support for it by setting up the correct HW
registers.

Signed-off-by: Sujith Manoharan <[email protected]>
---
drivers/net/wireless/ath/ath9k/ar9003_wow.c | 48 +++++++++++++----------------
drivers/net/wireless/ath/ath9k/hw.h | 1 +
drivers/net/wireless/ath/ath9k/reg_wow.h | 34 ++++++++++++++++++++
3 files changed, 56 insertions(+), 27 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/ar9003_wow.c b/drivers/net/wireless/ath/ath9k/ar9003_wow.c
index d2a4f6f..4b53d0b 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_wow.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_wow.c
@@ -100,9 +100,11 @@ int ath9k_hw_wow_apply_pattern(struct ath_hw *ah, u8 *user_pattern,
if (pattern_count >= ah->wow.max_patterns)
return -ENOSPC;

- REG_SET_BIT(ah, AR_WOW_PATTERN, BIT(pattern_count));
+ if (pattern_count < MAX_NUM_PATTERN_LEGACY)
+ REG_SET_BIT(ah, AR_WOW_PATTERN, BIT(pattern_count));
+ else
+ REG_SET_BIT(ah, AR_MAC_PCU_WOW4, BIT(pattern_count - 8));

- /* set the registers for pattern */
for (i = 0; i < MAX_PATTERN_SIZE; i += 4) {
memcpy(&pattern_val, user_pattern, 4);
REG_WRITE(ah, (AR_WOW_TB_PATTERN(pattern_count) + i),
@@ -110,47 +112,39 @@ int ath9k_hw_wow_apply_pattern(struct ath_hw *ah, u8 *user_pattern,
user_pattern += 4;
}

- /* set the registers for mask */
for (i = 0; i < MAX_PATTERN_MASK_SIZE; i += 4) {
memcpy(&mask_val, user_mask, 4);
REG_WRITE(ah, (AR_WOW_TB_MASK(pattern_count) + i), mask_val);
user_mask += 4;
}

- /* set the pattern length to be matched
- *
- * AR_WOW_LENGTH1_REG1
- * bit 31:24 pattern 0 length
- * bit 23:16 pattern 1 length
- * bit 15:8 pattern 2 length
- * bit 7:0 pattern 3 length
- *
- * AR_WOW_LENGTH1_REG2
- * bit 31:24 pattern 4 length
- * bit 23:16 pattern 5 length
- * bit 15:8 pattern 6 length
- * bit 7:0 pattern 7 length
- *
- * the below logic writes out the new
- * pattern length for the corresponding
- * pattern_count, while masking out the
- * other fields
- */
-
- ah->wow.wow_event_mask |= BIT(pattern_count + AR_WOW_PAT_FOUND_SHIFT);
+ if (pattern_count < MAX_NUM_PATTERN_LEGACY)
+ ah->wow.wow_event_mask |=
+ BIT(pattern_count + AR_WOW_PAT_FOUND_SHIFT);
+ else
+ ah->wow.wow_event_mask2 |=
+ BIT((pattern_count - 8) + AR_WOW_PAT_FOUND_SHIFT);

if (pattern_count < 4) {
- /* Pattern 0-3 uses AR_WOW_LENGTH1 register */
set = (pattern_len & AR_WOW_LENGTH_MAX) <<
AR_WOW_LEN1_SHIFT(pattern_count);
clr = AR_WOW_LENGTH1_MASK(pattern_count);
REG_RMW(ah, AR_WOW_LENGTH1, set, clr);
- } else {
- /* Pattern 4-7 uses AR_WOW_LENGTH2 register */
+ } else if (pattern_count < 8) {
set = (pattern_len & AR_WOW_LENGTH_MAX) <<
AR_WOW_LEN2_SHIFT(pattern_count);
clr = AR_WOW_LENGTH2_MASK(pattern_count);
REG_RMW(ah, AR_WOW_LENGTH2, set, clr);
+ } else if (pattern_count < 12) {
+ set = (pattern_len & AR_WOW_LENGTH_MAX) <<
+ AR_WOW_LEN3_SHIFT(pattern_count);
+ clr = AR_WOW_LENGTH3_MASK(pattern_count);
+ REG_RMW(ah, AR_WOW_LENGTH3, set, clr);
+ } else if (pattern_count < MAX_NUM_PATTERN) {
+ set = (pattern_len & AR_WOW_LENGTH_MAX) <<
+ AR_WOW_LEN4_SHIFT(pattern_count);
+ clr = AR_WOW_LENGTH4_MASK(pattern_count);
+ REG_RMW(ah, AR_WOW_LENGTH4, set, clr);
}

return 0;
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index f51a28f..c8b3d8f 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -273,6 +273,7 @@ enum ath9k_hw_caps {

struct ath9k_hw_wow {
u32 wow_event_mask;
+ u32 wow_event_mask2;
u8 max_patterns;
};

diff --git a/drivers/net/wireless/ath/ath9k/reg_wow.h b/drivers/net/wireless/ath/ath9k/reg_wow.h
index e6de4a3..83f27f9 100644
--- a/drivers/net/wireless/ath/ath9k/reg_wow.h
+++ b/drivers/net/wireless/ath/ath9k/reg_wow.h
@@ -25,9 +25,39 @@
#define AR_WOW_KEEP_ALIVE 0x827c
#define AR_WOW_KEEP_ALIVE_DELAY 0x8288
#define AR_WOW_PATTERN_MATCH 0x828c
+
+/*
+ * AR_WOW_LENGTH1
+ * bit 31:24 pattern 0 length
+ * bit 23:16 pattern 1 length
+ * bit 15:8 pattern 2 length
+ * bit 7:0 pattern 3 length
+ *
+ * AR_WOW_LENGTH2
+ * bit 31:24 pattern 4 length
+ * bit 23:16 pattern 5 length
+ * bit 15:8 pattern 6 length
+ * bit 7:0 pattern 7 length
+ *
+ * AR_WOW_LENGTH3
+ * bit 31:24 pattern 8 length
+ * bit 23:16 pattern 9 length
+ * bit 15:8 pattern 10 length
+ * bit 7:0 pattern 11 length
+ *
+ * AR_WOW_LENGTH4
+ * bit 31:24 pattern 12 length
+ * bit 23:16 pattern 13 length
+ * bit 15:8 pattern 14 length
+ * bit 7:0 pattern 15 length
+ */
#define AR_WOW_LENGTH1 0x8360
#define AR_WOW_LENGTH2 0X8364
+#define AR_WOW_LENGTH3 0X8380
+#define AR_WOW_LENGTH4 0X8384
+
#define AR_WOW_PATTERN_MATCH_LT_256B 0x8368
+#define AR_MAC_PCU_WOW4 0x8370

#define AR_SW_WOW_CONTROL 0x20018
#define AR_SW_WOW_ENABLE 0x1
@@ -89,5 +119,9 @@
#define AR_WOW_LENGTH1_MASK(_i) (AR_WOW_LENGTH_MAX << AR_WOW_LEN1_SHIFT(_i))
#define AR_WOW_LEN2_SHIFT(_i) ((0x7 - ((_i) & 0x7)) << 0x3)
#define AR_WOW_LENGTH2_MASK(_i) (AR_WOW_LENGTH_MAX << AR_WOW_LEN2_SHIFT(_i))
+#define AR_WOW_LEN3_SHIFT(_i) ((0xb - ((_i) & 0xb)) << 0x3)
+#define AR_WOW_LENGTH3_MASK(_i) (AR_WOW_LENGTH_MAX << AR_WOW_LEN3_SHIFT(_i))
+#define AR_WOW_LEN4_SHIFT(_i) ((0xf - ((_i) & 0xf)) << 0x3)
+#define AR_WOW_LENGTH4_MASK(_i) (AR_WOW_LENGTH_MAX << AR_WOW_LEN4_SHIFT(_i))

#endif /* REG_WOW_H */
--
2.2.2


2015-02-02 12:48:17

by Sujith Manoharan

[permalink] [raw]
Subject: [PATCH 2/6] ath9k: Register correct WOW details with mac80211

From: Sujith Manoharan <[email protected]>

Since the number of user patterns is higher for
newer chips, make sure that this is registered
during initialization.

Signed-off-by: Sujith Manoharan <[email protected]>
---
drivers/net/wireless/ath/ath9k/wow.c | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/wow.c b/drivers/net/wireless/ath/ath9k/wow.c
index 5092939..8d0b173 100644
--- a/drivers/net/wireless/ath/ath9k/wow.c
+++ b/drivers/net/wireless/ath/ath9k/wow.c
@@ -16,13 +16,20 @@

#include "ath9k.h"

-static const struct wiphy_wowlan_support ath9k_wowlan_support = {
+static const struct wiphy_wowlan_support ath9k_wowlan_support_legacy = {
.flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT,
.n_patterns = MAX_NUM_USER_PATTERN,
.pattern_min_len = 1,
.pattern_max_len = MAX_PATTERN_SIZE,
};

+static const struct wiphy_wowlan_support ath9k_wowlan_support = {
+ .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT,
+ .n_patterns = MAX_NUM_PATTERN - 2,
+ .pattern_min_len = 1,
+ .pattern_max_len = MAX_PATTERN_SIZE,
+};
+
static u8 ath9k_wow_map_triggers(struct ath_softc *sc,
struct cfg80211_wowlan *wowlan)
{
@@ -320,9 +327,14 @@ void ath9k_set_wakeup(struct ieee80211_hw *hw, bool enabled)
void ath9k_init_wow(struct ieee80211_hw *hw)
{
struct ath_softc *sc = hw->priv;
+ struct ath_hw *ah = sc->sc_ah;

if ((sc->driver_data & ATH9K_PCI_WOW) || sc->force_wow) {
- hw->wiphy->wowlan = &ath9k_wowlan_support;
+ if (AR_SREV_9462_20_OR_LATER(ah) || AR_SREV_9565_11_OR_LATER(ah))
+ hw->wiphy->wowlan = &ath9k_wowlan_support;
+ else
+ hw->wiphy->wowlan = &ath9k_wowlan_support_legacy;
+
device_init_wakeup(sc->dev, 1);
}
}
--
2.2.2


2015-02-02 12:48:23

by Sujith Manoharan

[permalink] [raw]
Subject: [PATCH 6/6] ath9k: Choose correct rate for 2GHz channel

From: Sujith Manoharan <[email protected]>

Set the transmit rate for the keep-alive frames
as 1M/CCK when the current channel is in the
2GHz band.

Signed-off-by: Sujith Manoharan <[email protected]>
---
drivers/net/wireless/ath/ath9k/ar9003_wow.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath9k/ar9003_wow.c b/drivers/net/wireless/ath/ath9k/ar9003_wow.c
index 2dc50a0..86bfc96 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_wow.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_wow.c
@@ -62,11 +62,15 @@ static void ath9k_wow_create_keep_alive_pattern(struct ath_hw *ah)
/* set the transmit buffer */
ctl[0] = (KAL_FRAME_LEN | (MAX_RATE_POWER << 16));
ctl[1] = 0;
- ctl[3] = 0xb; /* OFDM_6M hardware value for this rate */
ctl[4] = 0;
ctl[7] = (ah->txchainmask) << 2;
ctl[2] = 0xf << 16; /* tx_tries 0 */

+ if (IS_CHAN_2GHZ(ah->curchan))
+ ctl[3] = 0x1b; /* CCK_1M */
+ else
+ ctl[3] = 0xb; /* OFDM_6M */
+
for (i = 0; i < KAL_NUM_DESC_WORDS; i++)
REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + i * 4), ctl[i]);

--
2.2.2


2015-02-02 12:48:20

by Sujith Manoharan

[permalink] [raw]
Subject: [PATCH 4/6] ath9k: Program AR_WA correctly

From: Sujith Manoharan <[email protected]>

Setting the required configuration in the PCIE
WorkAround register needs to be done after all the
WoW parameters have been set.

Signed-off-by: Sujith Manoharan <[email protected]>
---
drivers/net/wireless/ath/ath9k/ar9003_wow.c | 39 ++++++++++++++++-------------
1 file changed, 22 insertions(+), 17 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/ar9003_wow.c b/drivers/net/wireless/ath/ath9k/ar9003_wow.c
index 6ffa0e0..cf45b91 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_wow.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_wow.c
@@ -219,31 +219,34 @@ u32 ath9k_hw_wow_wakeup(struct ath_hw *ah)
}
EXPORT_SYMBOL(ath9k_hw_wow_wakeup);

+static void ath9k_hw_wow_set_arwr_reg(struct ath_hw *ah)
+{
+ u32 wa_reg;
+
+ if (!ah->is_pciexpress)
+ return;
+
+ /*
+ * We need to untie the internal POR (power-on-reset)
+ * to the external PCI-E reset. We also need to tie
+ * the PCI-E Phy reset to the PCI-E reset.
+ */
+ wa_reg = REG_READ(ah, AR_WA);
+ wa_reg &= ~AR_WA_UNTIE_RESET_EN;
+ wa_reg |= AR_WA_RESET_EN;
+ wa_reg |= AR_WA_POR_SHORT;
+
+ REG_WRITE(ah, AR_WA, wa_reg);
+}
+
void ath9k_hw_wow_enable(struct ath_hw *ah, u32 pattern_enable)
{
u32 wow_event_mask;
u32 keep_alive, magic_pattern, host_pm_ctrl;
- u32 set, clr;

wow_event_mask = ah->wow.wow_event_mask;

/*
- * Untie Power-on-Reset from the PCI-E-Reset. When we are in
- * WOW sleep, we do want the Reset from the PCI-E to disturb
- * our hw state
- */
- if (ah->is_pciexpress) {
- /*
- * we need to untie the internal POR (power-on-reset)
- * to the external PCI-E reset. We also need to tie
- * the PCI-E Phy reset to the PCI-E reset.
- */
- set = AR_WA_RESET_EN | AR_WA_POR_SHORT;
- clr = AR_WA_UNTIE_RESET_EN | AR_WA_D3_L1_DISABLE;
- REG_RMW(ah, AR_WA, set, clr);
- }
-
- /*
* AR_PMCTRL_HOST_PME_EN - Override PME enable in configuration
* space and allow MAC to generate WoW anyway.
*
@@ -390,6 +393,8 @@ void ath9k_hw_wow_enable(struct ath_hw *ah, u32 pattern_enable)
/* To bring down WOW power low margin */
REG_SET_BIT(ah, AR_PCIE_PHY_REG3, BIT(13));

+ ath9k_hw_wow_set_arwr_reg(ah);
+
/* HW WoW */
REG_CLR_BIT(ah, AR_PCU_MISC_MODE3, BIT(5));

--
2.2.2