aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath9k
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath/ath9k')
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_calib.c61
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_wow.c315
-rw-r--r--drivers/net/wireless/ath/ath9k/ar953x_initvals.h4
-rw-r--r--drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h4
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h15
-rw-r--r--drivers/net/wireless/ath/ath9k/common-spectral.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.c68
-rw-r--r--drivers/net/wireless/ath/ath9k/gpio.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/htc.h2
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_gpio.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_init.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c10
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h37
-rw-r--r--drivers/net/wireless/ath/ath9k/init.c5
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c9
-rw-r--r--drivers/net/wireless/ath/ath9k/pci.c5
-rw-r--r--drivers/net/wireless/ath/ath9k/reg.h125
-rw-r--r--drivers/net/wireless/ath/ath9k/reg_wow.h128
-rw-r--r--drivers/net/wireless/ath/ath9k/wow.c228
19 files changed, 560 insertions, 466 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
index 06ab71db6e80..174442beb952 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
@@ -1203,24 +1203,41 @@ static void ar9003_hw_tx_iq_cal_reload(struct ath_hw *ah)
1203static void ar9003_hw_manual_peak_cal(struct ath_hw *ah, u8 chain, bool is_2g) 1203static void ar9003_hw_manual_peak_cal(struct ath_hw *ah, u8 chain, bool is_2g)
1204{ 1204{
1205 int offset[8] = {0}, total = 0, test; 1205 int offset[8] = {0}, total = 0, test;
1206 int agc_out, i; 1206 int agc_out, i, peak_detect_threshold;
1207 1207
1208 if (AR_SREV_9550(ah) || AR_SREV_9531(ah))
1209 peak_detect_threshold = 8;
1210 else
1211 peak_detect_threshold = 0;
1212
1213 /*
1214 * Turn off LNA/SW.
1215 */
1208 REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain), 1216 REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain),
1209 AR_PHY_65NM_RXRF_GAINSTAGES_RX_OVERRIDE, 0x1); 1217 AR_PHY_65NM_RXRF_GAINSTAGES_RX_OVERRIDE, 0x1);
1210 REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain), 1218 REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain),
1211 AR_PHY_65NM_RXRF_GAINSTAGES_LNAON_CALDC, 0x0); 1219 AR_PHY_65NM_RXRF_GAINSTAGES_LNAON_CALDC, 0x0);
1212 if (is_2g)
1213 REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain),
1214 AR_PHY_65NM_RXRF_GAINSTAGES_LNA2G_GAIN_OVR, 0x0);
1215 else
1216 REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain),
1217 AR_PHY_65NM_RXRF_GAINSTAGES_LNA5G_GAIN_OVR, 0x0);
1218 1220
1221 if (AR_SREV_9003_PCOEM(ah) || AR_SREV_9330_11(ah)) {
1222 if (is_2g)
1223 REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain),
1224 AR_PHY_65NM_RXRF_GAINSTAGES_LNA2G_GAIN_OVR, 0x0);
1225 else
1226 REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain),
1227 AR_PHY_65NM_RXRF_GAINSTAGES_LNA5G_GAIN_OVR, 0x0);
1228 }
1229
1230 /*
1231 * Turn off RXON.
1232 */
1219 REG_RMW_FIELD(ah, AR_PHY_65NM_RXTX2(chain), 1233 REG_RMW_FIELD(ah, AR_PHY_65NM_RXTX2(chain),
1220 AR_PHY_65NM_RXTX2_RXON_OVR, 0x1); 1234 AR_PHY_65NM_RXTX2_RXON_OVR, 0x1);
1221 REG_RMW_FIELD(ah, AR_PHY_65NM_RXTX2(chain), 1235 REG_RMW_FIELD(ah, AR_PHY_65NM_RXTX2(chain),
1222 AR_PHY_65NM_RXTX2_RXON, 0x0); 1236 AR_PHY_65NM_RXTX2_RXON, 0x0);
1223 1237
1238 /*
1239 * Turn on AGC for cal.
1240 */
1224 REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), 1241 REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
1225 AR_PHY_65NM_RXRF_AGC_AGC_OVERRIDE, 0x1); 1242 AR_PHY_65NM_RXRF_AGC_AGC_OVERRIDE, 0x1);
1226 REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), 1243 REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
@@ -1228,16 +1245,19 @@ static void ar9003_hw_manual_peak_cal(struct ath_hw *ah, u8 chain, bool is_2g)
1228 REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), 1245 REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
1229 AR_PHY_65NM_RXRF_AGC_AGC_CAL_OVR, 0x1); 1246 AR_PHY_65NM_RXRF_AGC_AGC_CAL_OVR, 0x1);
1230 1247
1231 if (AR_SREV_9330_11(ah)) { 1248 if (AR_SREV_9330_11(ah))
1232 REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), 1249 REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
1233 AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR, 0x0); 1250 AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR, 0x0);
1234 } else { 1251
1252 if (AR_SREV_9003_PCOEM(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah)) {
1235 if (is_2g) 1253 if (is_2g)
1236 REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), 1254 REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
1237 AR_PHY_65NM_RXRF_AGC_AGC2G_DBDAC_OVR, 0x0); 1255 AR_PHY_65NM_RXRF_AGC_AGC2G_DBDAC_OVR,
1256 peak_detect_threshold);
1238 else 1257 else
1239 REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), 1258 REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
1240 AR_PHY_65NM_RXRF_AGC_AGC5G_DBDAC_OVR, 0x0); 1259 AR_PHY_65NM_RXRF_AGC_AGC5G_DBDAC_OVR,
1260 peak_detect_threshold);
1241 } 1261 }
1242 1262
1243 for (i = 6; i > 0; i--) { 1263 for (i = 6; i > 0; i--) {
@@ -1266,10 +1286,19 @@ static void ar9003_hw_manual_peak_cal(struct ath_hw *ah, u8 chain, bool is_2g)
1266 REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), 1286 REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
1267 AR_PHY_65NM_RXRF_AGC_AGC5G_CALDAC_OVR, total); 1287 AR_PHY_65NM_RXRF_AGC_AGC5G_CALDAC_OVR, total);
1268 1288
1289 /*
1290 * Turn on LNA.
1291 */
1269 REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain), 1292 REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_GAINSTAGES(chain),
1270 AR_PHY_65NM_RXRF_GAINSTAGES_RX_OVERRIDE, 0); 1293 AR_PHY_65NM_RXRF_GAINSTAGES_RX_OVERRIDE, 0);
1294 /*
1295 * Turn off RXON.
1296 */
1271 REG_RMW_FIELD(ah, AR_PHY_65NM_RXTX2(chain), 1297 REG_RMW_FIELD(ah, AR_PHY_65NM_RXTX2(chain),
1272 AR_PHY_65NM_RXTX2_RXON_OVR, 0); 1298 AR_PHY_65NM_RXTX2_RXON_OVR, 0);
1299 /*
1300 * Turn off peak detect calibration.
1301 */
1273 REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), 1302 REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
1274 AR_PHY_65NM_RXRF_AGC_AGC_CAL_OVR, 0); 1303 AR_PHY_65NM_RXRF_AGC_AGC_CAL_OVR, 0);
1275} 1304}
@@ -1611,8 +1640,14 @@ static bool ar9003_hw_init_cal_soc(struct ath_hw *ah,
1611 1640
1612skip_tx_iqcal: 1641skip_tx_iqcal:
1613 if (run_agc_cal || !(ah->ah_flags & AH_FASTCC)) { 1642 if (run_agc_cal || !(ah->ah_flags & AH_FASTCC)) {
1614 if (AR_SREV_9330_11(ah)) 1643 if (AR_SREV_9330_11(ah) || AR_SREV_9531(ah) || AR_SREV_9550(ah)) {
1615 ar9003_hw_manual_peak_cal(ah, 0, IS_CHAN_2GHZ(chan)); 1644 for (i = 0; i < AR9300_MAX_CHAINS; i++) {
1645 if (!(ah->rxchainmask & (1 << i)))
1646 continue;
1647 ar9003_hw_manual_peak_cal(ah, i,
1648 IS_CHAN_2GHZ(chan));
1649 }
1650 }
1616 1651
1617 /* 1652 /*
1618 * For non-AR9550 chips, we just trigger AGC calibration 1653 * For non-AR9550 chips, we just trigger AGC calibration
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_wow.c b/drivers/net/wireless/ath/ath9k/ar9003_wow.c
index 81c88dd606dc..86bfc9604dca 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_wow.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_wow.c
@@ -17,23 +17,9 @@
17#include <linux/export.h> 17#include <linux/export.h>
18#include "ath9k.h" 18#include "ath9k.h"
19#include "reg.h" 19#include "reg.h"
20#include "reg_wow.h"
20#include "hw-ops.h" 21#include "hw-ops.h"
21 22
22const char *ath9k_hw_wow_event_to_string(u32 wow_event)
23{
24 if (wow_event & AH_WOW_MAGIC_PATTERN_EN)
25 return "Magic pattern";
26 if (wow_event & AH_WOW_USER_PATTERN_EN)
27 return "User pattern";
28 if (wow_event & AH_WOW_LINK_CHANGE)
29 return "Link change";
30 if (wow_event & AH_WOW_BEACON_MISS)
31 return "Beacon miss";
32
33 return "unknown reason";
34}
35EXPORT_SYMBOL(ath9k_hw_wow_event_to_string);
36
37static void ath9k_hw_set_powermode_wow_sleep(struct ath_hw *ah) 23static void ath9k_hw_set_powermode_wow_sleep(struct ath_hw *ah)
38{ 24{
39 struct ath_common *common = ath9k_hw_common(ah); 25 struct ath_common *common = ath9k_hw_common(ah);
@@ -49,6 +35,15 @@ static void ath9k_hw_set_powermode_wow_sleep(struct ath_hw *ah)
49 return; 35 return;
50 } 36 }
51 37
38 if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) {
39 if (!REG_READ(ah, AR_MAC_PCU_GEN_TIMER_TSF_SEL))
40 REG_CLR_BIT(ah, AR_DIRECT_CONNECT, AR_DC_TSF2_ENABLE);
41 } else if (AR_SREV_9485(ah)){
42 if (!(REG_READ(ah, AR_NDP2_TIMER_MODE) &
43 AR_GEN_TIMERS2_MODE_ENABLE_MASK))
44 REG_CLR_BIT(ah, AR_DIRECT_CONNECT, AR_DC_TSF2_ENABLE);
45 }
46
52 REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_ON_INT); 47 REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_ON_INT);
53} 48}
54 49
@@ -67,11 +62,15 @@ static void ath9k_wow_create_keep_alive_pattern(struct ath_hw *ah)
67 /* set the transmit buffer */ 62 /* set the transmit buffer */
68 ctl[0] = (KAL_FRAME_LEN | (MAX_RATE_POWER << 16)); 63 ctl[0] = (KAL_FRAME_LEN | (MAX_RATE_POWER << 16));
69 ctl[1] = 0; 64 ctl[1] = 0;
70 ctl[3] = 0xb; /* OFDM_6M hardware value for this rate */
71 ctl[4] = 0; 65 ctl[4] = 0;
72 ctl[7] = (ah->txchainmask) << 2; 66 ctl[7] = (ah->txchainmask) << 2;
73 ctl[2] = 0xf << 16; /* tx_tries 0 */ 67 ctl[2] = 0xf << 16; /* tx_tries 0 */
74 68
69 if (IS_CHAN_2GHZ(ah->curchan))
70 ctl[3] = 0x1b; /* CCK_1M */
71 else
72 ctl[3] = 0xb; /* OFDM_6M */
73
75 for (i = 0; i < KAL_NUM_DESC_WORDS; i++) 74 for (i = 0; i < KAL_NUM_DESC_WORDS; i++)
76 REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + i * 4), ctl[i]); 75 REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + i * 4), ctl[i]);
77 76
@@ -103,21 +102,22 @@ static void ath9k_wow_create_keep_alive_pattern(struct ath_hw *ah)
103 102
104} 103}
105 104
106void ath9k_hw_wow_apply_pattern(struct ath_hw *ah, u8 *user_pattern, 105int ath9k_hw_wow_apply_pattern(struct ath_hw *ah, u8 *user_pattern,
107 u8 *user_mask, int pattern_count, 106 u8 *user_mask, int pattern_count,
108 int pattern_len) 107 int pattern_len)
109{ 108{
110 int i; 109 int i;
111 u32 pattern_val, mask_val; 110 u32 pattern_val, mask_val;
112 u32 set, clr; 111 u32 set, clr;
113 112
114 /* FIXME: should check count by querying the hardware capability */ 113 if (pattern_count >= ah->wow.max_patterns)
115 if (pattern_count >= MAX_NUM_PATTERN) 114 return -ENOSPC;
116 return;
117 115
118 REG_SET_BIT(ah, AR_WOW_PATTERN, BIT(pattern_count)); 116 if (pattern_count < MAX_NUM_PATTERN_LEGACY)
117 REG_SET_BIT(ah, AR_WOW_PATTERN, BIT(pattern_count));
118 else
119 REG_SET_BIT(ah, AR_MAC_PCU_WOW4, BIT(pattern_count - 8));
119 120
120 /* set the registers for pattern */
121 for (i = 0; i < MAX_PATTERN_SIZE; i += 4) { 121 for (i = 0; i < MAX_PATTERN_SIZE; i += 4) {
122 memcpy(&pattern_val, user_pattern, 4); 122 memcpy(&pattern_val, user_pattern, 4);
123 REG_WRITE(ah, (AR_WOW_TB_PATTERN(pattern_count) + i), 123 REG_WRITE(ah, (AR_WOW_TB_PATTERN(pattern_count) + i),
@@ -125,49 +125,42 @@ void ath9k_hw_wow_apply_pattern(struct ath_hw *ah, u8 *user_pattern,
125 user_pattern += 4; 125 user_pattern += 4;
126 } 126 }
127 127
128 /* set the registers for mask */
129 for (i = 0; i < MAX_PATTERN_MASK_SIZE; i += 4) { 128 for (i = 0; i < MAX_PATTERN_MASK_SIZE; i += 4) {
130 memcpy(&mask_val, user_mask, 4); 129 memcpy(&mask_val, user_mask, 4);
131 REG_WRITE(ah, (AR_WOW_TB_MASK(pattern_count) + i), mask_val); 130 REG_WRITE(ah, (AR_WOW_TB_MASK(pattern_count) + i), mask_val);
132 user_mask += 4; 131 user_mask += 4;
133 } 132 }
134 133
135 /* set the pattern length to be matched 134 if (pattern_count < MAX_NUM_PATTERN_LEGACY)
136 * 135 ah->wow.wow_event_mask |=
137 * AR_WOW_LENGTH1_REG1 136 BIT(pattern_count + AR_WOW_PAT_FOUND_SHIFT);
138 * bit 31:24 pattern 0 length 137 else
139 * bit 23:16 pattern 1 length 138 ah->wow.wow_event_mask2 |=
140 * bit 15:8 pattern 2 length 139 BIT((pattern_count - 8) + AR_WOW_PAT_FOUND_SHIFT);
141 * bit 7:0 pattern 3 length
142 *
143 * AR_WOW_LENGTH1_REG2
144 * bit 31:24 pattern 4 length
145 * bit 23:16 pattern 5 length
146 * bit 15:8 pattern 6 length
147 * bit 7:0 pattern 7 length
148 *
149 * the below logic writes out the new
150 * pattern length for the corresponding
151 * pattern_count, while masking out the
152 * other fields
153 */
154
155 ah->wow_event_mask |= BIT(pattern_count + AR_WOW_PAT_FOUND_SHIFT);
156 140
157 if (pattern_count < 4) { 141 if (pattern_count < 4) {
158 /* Pattern 0-3 uses AR_WOW_LENGTH1 register */
159 set = (pattern_len & AR_WOW_LENGTH_MAX) << 142 set = (pattern_len & AR_WOW_LENGTH_MAX) <<
160 AR_WOW_LEN1_SHIFT(pattern_count); 143 AR_WOW_LEN1_SHIFT(pattern_count);
161 clr = AR_WOW_LENGTH1_MASK(pattern_count); 144 clr = AR_WOW_LENGTH1_MASK(pattern_count);
162 REG_RMW(ah, AR_WOW_LENGTH1, set, clr); 145 REG_RMW(ah, AR_WOW_LENGTH1, set, clr);
163 } else { 146 } else if (pattern_count < 8) {
164 /* Pattern 4-7 uses AR_WOW_LENGTH2 register */
165 set = (pattern_len & AR_WOW_LENGTH_MAX) << 147 set = (pattern_len & AR_WOW_LENGTH_MAX) <<
166 AR_WOW_LEN2_SHIFT(pattern_count); 148 AR_WOW_LEN2_SHIFT(pattern_count);
167 clr = AR_WOW_LENGTH2_MASK(pattern_count); 149 clr = AR_WOW_LENGTH2_MASK(pattern_count);
168 REG_RMW(ah, AR_WOW_LENGTH2, set, clr); 150 REG_RMW(ah, AR_WOW_LENGTH2, set, clr);
151 } else if (pattern_count < 12) {
152 set = (pattern_len & AR_WOW_LENGTH_MAX) <<
153 AR_WOW_LEN3_SHIFT(pattern_count);
154 clr = AR_WOW_LENGTH3_MASK(pattern_count);
155 REG_RMW(ah, AR_WOW_LENGTH3, set, clr);
156 } else if (pattern_count < MAX_NUM_PATTERN) {
157 set = (pattern_len & AR_WOW_LENGTH_MAX) <<
158 AR_WOW_LEN4_SHIFT(pattern_count);
159 clr = AR_WOW_LENGTH4_MASK(pattern_count);
160 REG_RMW(ah, AR_WOW_LENGTH4, set, clr);
169 } 161 }
170 162
163 return 0;
171} 164}
172EXPORT_SYMBOL(ath9k_hw_wow_apply_pattern); 165EXPORT_SYMBOL(ath9k_hw_wow_apply_pattern);
173 166
@@ -189,7 +182,7 @@ u32 ath9k_hw_wow_wakeup(struct ath_hw *ah)
189 * register. This mask will clean it up. 182 * register. This mask will clean it up.
190 */ 183 */
191 184
192 val &= ah->wow_event_mask; 185 val &= ah->wow.wow_event_mask;
193 186
194 if (val) { 187 if (val) {
195 if (val & AR_WOW_MAGIC_PAT_FOUND) 188 if (val & AR_WOW_MAGIC_PAT_FOUND)
@@ -233,190 +226,192 @@ u32 ath9k_hw_wow_wakeup(struct ath_hw *ah)
233 if (ah->is_pciexpress) 226 if (ah->is_pciexpress)
234 ath9k_hw_configpcipowersave(ah, false); 227 ath9k_hw_configpcipowersave(ah, false);
235 228
236 ah->wow_event_mask = 0; 229 ah->wow.wow_event_mask = 0;
237 230
238 return wow_status; 231 return wow_status;
239} 232}
240EXPORT_SYMBOL(ath9k_hw_wow_wakeup); 233EXPORT_SYMBOL(ath9k_hw_wow_wakeup);
241 234
242void ath9k_hw_wow_enable(struct ath_hw *ah, u32 pattern_enable) 235static void ath9k_hw_wow_set_arwr_reg(struct ath_hw *ah)
243{ 236{
244 u32 wow_event_mask; 237 u32 wa_reg;
245 u32 set, clr;
246 238
247 /* 239 if (!ah->is_pciexpress)
248 * wow_event_mask is a mask to the AR_WOW_PATTERN register to 240 return;
249 * indicate which WoW events we have enabled. The WoW events
250 * are from the 'pattern_enable' in this function and
251 * 'pattern_count' of ath9k_hw_wow_apply_pattern()
252 */
253 wow_event_mask = ah->wow_event_mask;
254 241
255 /* 242 /*
256 * Untie Power-on-Reset from the PCI-E-Reset. When we are in 243 * We need to untie the internal POR (power-on-reset)
257 * WOW sleep, we do want the Reset from the PCI-E to disturb 244 * to the external PCI-E reset. We also need to tie
258 * our hw state 245 * the PCI-E Phy reset to the PCI-E reset.
259 */ 246 */
260 if (ah->is_pciexpress) { 247 wa_reg = REG_READ(ah, AR_WA);
261 /* 248 wa_reg &= ~AR_WA_UNTIE_RESET_EN;
262 * we need to untie the internal POR (power-on-reset) 249 wa_reg |= AR_WA_RESET_EN;
263 * to the external PCI-E reset. We also need to tie 250 wa_reg |= AR_WA_POR_SHORT;
264 * the PCI-E Phy reset to the PCI-E reset.
265 */
266 set = AR_WA_RESET_EN | AR_WA_POR_SHORT;
267 clr = AR_WA_UNTIE_RESET_EN | AR_WA_D3_L1_DISABLE;
268 REG_RMW(ah, AR_WA, set, clr);
269 }
270 251
271 /* 252 REG_WRITE(ah, AR_WA, wa_reg);
272 * set the power states appropriately and enable PME 253}
273 */ 254
274 set = AR_PMCTRL_HOST_PME_EN | AR_PMCTRL_PWR_PM_CTRL_ENA | 255void ath9k_hw_wow_enable(struct ath_hw *ah, u32 pattern_enable)
275 AR_PMCTRL_AUX_PWR_DET | AR_PMCTRL_WOW_PME_CLR; 256{
257 u32 wow_event_mask;
258 u32 keep_alive, magic_pattern, host_pm_ctrl;
259
260 wow_event_mask = ah->wow.wow_event_mask;
276 261
277 /* 262 /*
278 * set and clear WOW_PME_CLEAR registers for the chip 263 * AR_PMCTRL_HOST_PME_EN - Override PME enable in configuration
264 * space and allow MAC to generate WoW anyway.
265 *
266 * AR_PMCTRL_PWR_PM_CTRL_ENA - ???
267 *
268 * AR_PMCTRL_AUX_PWR_DET - PCI core SYS_AUX_PWR_DET signal,
269 * needs to be set for WoW in PCI mode.
270 *
271 * AR_PMCTRL_WOW_PME_CLR - WoW Clear Signal going to the MAC.
272 *
273 * Set the power states appropriately and enable PME.
274 *
275 * Set and clear WOW_PME_CLEAR for the chip
279 * to generate next wow signal. 276 * to generate next wow signal.
280 */ 277 */
281 REG_SET_BIT(ah, AR_PCIE_PM_CTRL, set); 278 REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PMCTRL_HOST_PME_EN |
282 clr = AR_PMCTRL_WOW_PME_CLR; 279 AR_PMCTRL_PWR_PM_CTRL_ENA |
283 REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, clr); 280 AR_PMCTRL_AUX_PWR_DET |
281 AR_PMCTRL_WOW_PME_CLR);
282 REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, AR_PMCTRL_WOW_PME_CLR);
284 283
285 /* 284 /*
286 * Setup for: 285 * Random Backoff.
287 * - beacon misses 286 *
288 * - magic pattern 287 * 31:28 in AR_WOW_PATTERN : Indicates the number of bits used in the
289 * - keep alive timeout 288 * contention window. For value N,
290 * - pattern matching 289 * the random backoff will be selected between
290 * 0 and (2 ^ N) - 1.
291 */ 291 */
292 REG_SET_BIT(ah, AR_WOW_PATTERN,
293 AR_WOW_BACK_OFF_SHIFT(AR_WOW_PAT_BACKOFF));
292 294
293 /* 295 /*
294 * Program default values for pattern backoff, aifs/slot/KAL count, 296 * AIFS time, Slot time, Keep Alive count.
295 * beacon miss timeout, KAL timeout, etc. 297 */
298 REG_SET_BIT(ah, AR_WOW_COUNT, AR_WOW_AIFS_CNT(AR_WOW_CNT_AIFS_CNT) |
299 AR_WOW_SLOT_CNT(AR_WOW_CNT_SLOT_CNT) |
300 AR_WOW_KEEP_ALIVE_CNT(AR_WOW_CNT_KA_CNT));
301 /*
302 * Beacon timeout.
296 */ 303 */
297 set = AR_WOW_BACK_OFF_SHIFT(AR_WOW_PAT_BACKOFF);
298 REG_SET_BIT(ah, AR_WOW_PATTERN, set);
299
300 set = AR_WOW_AIFS_CNT(AR_WOW_CNT_AIFS_CNT) |
301 AR_WOW_SLOT_CNT(AR_WOW_CNT_SLOT_CNT) |
302 AR_WOW_KEEP_ALIVE_CNT(AR_WOW_CNT_KA_CNT);
303 REG_SET_BIT(ah, AR_WOW_COUNT, set);
304
305 if (pattern_enable & AH_WOW_BEACON_MISS) 304 if (pattern_enable & AH_WOW_BEACON_MISS)
306 set = AR_WOW_BEACON_TIMO; 305 REG_WRITE(ah, AR_WOW_BCN_TIMO, AR_WOW_BEACON_TIMO);
307 /* We are not using beacon miss, program a large value */
308 else 306 else
309 set = AR_WOW_BEACON_TIMO_MAX; 307 REG_WRITE(ah, AR_WOW_BCN_TIMO, AR_WOW_BEACON_TIMO_MAX);
310
311 REG_WRITE(ah, AR_WOW_BCN_TIMO, set);
312 308
313 /* 309 /*
314 * Keep alive timo in ms except AR9280 310 * Keep alive timeout in ms.
315 */ 311 */
316 if (!pattern_enable) 312 if (!pattern_enable)
317 set = AR_WOW_KEEP_ALIVE_NEVER; 313 REG_WRITE(ah, AR_WOW_KEEP_ALIVE_TIMO, AR_WOW_KEEP_ALIVE_NEVER);
318 else 314 else
319 set = KAL_TIMEOUT * 32; 315 REG_WRITE(ah, AR_WOW_KEEP_ALIVE_TIMO, KAL_TIMEOUT * 32);
320
321 REG_WRITE(ah, AR_WOW_KEEP_ALIVE_TIMO, set);
322 316
323 /* 317 /*
324 * Keep alive delay in us. based on 'power on clock', 318 * Keep alive delay in us.
325 * therefore in usec
326 */ 319 */
327 set = KAL_DELAY * 1000; 320 REG_WRITE(ah, AR_WOW_KEEP_ALIVE_DELAY, KAL_DELAY * 1000);
328 REG_WRITE(ah, AR_WOW_KEEP_ALIVE_DELAY, set);
329 321
330 /* 322 /*
331 * Create keep alive pattern to respond to beacons 323 * Create keep alive pattern to respond to beacons.
332 */ 324 */
333 ath9k_wow_create_keep_alive_pattern(ah); 325 ath9k_wow_create_keep_alive_pattern(ah);
334 326
335 /* 327 /*
336 * Configure MAC WoW Registers 328 * Configure keep alive register.
337 */ 329 */
338 set = 0; 330 keep_alive = REG_READ(ah, AR_WOW_KEEP_ALIVE);
331
339 /* Send keep alive timeouts anyway */ 332 /* Send keep alive timeouts anyway */
340 clr = AR_WOW_KEEP_ALIVE_AUTO_DIS; 333 keep_alive &= ~AR_WOW_KEEP_ALIVE_AUTO_DIS;
341 334
342 if (pattern_enable & AH_WOW_LINK_CHANGE) 335 if (pattern_enable & AH_WOW_LINK_CHANGE) {
336 keep_alive &= ~AR_WOW_KEEP_ALIVE_FAIL_DIS;
343 wow_event_mask |= AR_WOW_KEEP_ALIVE_FAIL; 337 wow_event_mask |= AR_WOW_KEEP_ALIVE_FAIL;
344 else 338 } else {
345 set = AR_WOW_KEEP_ALIVE_FAIL_DIS; 339 keep_alive |= AR_WOW_KEEP_ALIVE_FAIL_DIS;
340 }
346 341
347 set = AR_WOW_KEEP_ALIVE_FAIL_DIS; 342 REG_WRITE(ah, AR_WOW_KEEP_ALIVE, keep_alive);
348 REG_RMW(ah, AR_WOW_KEEP_ALIVE, set, clr);
349 343
350 /* 344 /*
351 * we are relying on a bmiss failure. ensure we have 345 * We are relying on a bmiss failure, ensure we have
352 * enough threshold to prevent false positives 346 * enough threshold to prevent false positives.
353 */ 347 */
354 REG_RMW_FIELD(ah, AR_RSSI_THR, AR_RSSI_THR_BM_THR, 348 REG_RMW_FIELD(ah, AR_RSSI_THR, AR_RSSI_THR_BM_THR,
355 AR_WOW_BMISSTHRESHOLD); 349 AR_WOW_BMISSTHRESHOLD);
356 350
357 set = 0;
358 clr = 0;
359
360 if (pattern_enable & AH_WOW_BEACON_MISS) { 351 if (pattern_enable & AH_WOW_BEACON_MISS) {
361 set = AR_WOW_BEACON_FAIL_EN;
362 wow_event_mask |= AR_WOW_BEACON_FAIL; 352 wow_event_mask |= AR_WOW_BEACON_FAIL;
353 REG_SET_BIT(ah, AR_WOW_BCN_EN, AR_WOW_BEACON_FAIL_EN);
363 } else { 354 } else {
364 clr = AR_WOW_BEACON_FAIL_EN; 355 REG_CLR_BIT(ah, AR_WOW_BCN_EN, AR_WOW_BEACON_FAIL_EN);
365 } 356 }
366 357
367 REG_RMW(ah, AR_WOW_BCN_EN, set, clr);
368
369 set = 0;
370 clr = 0;
371 /* 358 /*
372 * Enable the magic packet registers 359 * Enable the magic packet registers.
373 */ 360 */
361 magic_pattern = REG_READ(ah, AR_WOW_PATTERN);
362 magic_pattern |= AR_WOW_MAC_INTR_EN;
363
374 if (pattern_enable & AH_WOW_MAGIC_PATTERN_EN) { 364 if (pattern_enable & AH_WOW_MAGIC_PATTERN_EN) {
375 set = AR_WOW_MAGIC_EN; 365 magic_pattern |= AR_WOW_MAGIC_EN;
376 wow_event_mask |= AR_WOW_MAGIC_PAT_FOUND; 366 wow_event_mask |= AR_WOW_MAGIC_PAT_FOUND;
377 } else { 367 } else {
378 clr = AR_WOW_MAGIC_EN; 368 magic_pattern &= ~AR_WOW_MAGIC_EN;
379 } 369 }
380 set |= AR_WOW_MAC_INTR_EN;
381 REG_RMW(ah, AR_WOW_PATTERN, set, clr);
382 370
371 REG_WRITE(ah, AR_WOW_PATTERN, magic_pattern);
372
373 /*
374 * Enable pattern matching for packets which are less
375 * than 256 bytes.
376 */
383 REG_WRITE(ah, AR_WOW_PATTERN_MATCH_LT_256B, 377 REG_WRITE(ah, AR_WOW_PATTERN_MATCH_LT_256B,
384 AR_WOW_PATTERN_SUPPORTED); 378 AR_WOW_PATTERN_SUPPORTED);
385 379
386 /* 380 /*
387 * Set the power states appropriately and enable PME 381 * Set the power states appropriately and enable PME.
388 */ 382 */
389 clr = 0; 383 host_pm_ctrl = REG_READ(ah, AR_PCIE_PM_CTRL);
390 set = AR_PMCTRL_PWR_STATE_D1D3 | AR_PMCTRL_HOST_PME_EN | 384 host_pm_ctrl |= AR_PMCTRL_PWR_STATE_D1D3 |
391 AR_PMCTRL_PWR_PM_CTRL_ENA; 385 AR_PMCTRL_HOST_PME_EN |
386 AR_PMCTRL_PWR_PM_CTRL_ENA;
387 host_pm_ctrl &= ~AR_PCIE_PM_CTRL_ENA;
392 388
393 clr = AR_PCIE_PM_CTRL_ENA; 389 if (AR_SREV_9462(ah)) {
394 REG_RMW(ah, AR_PCIE_PM_CTRL, set, clr); 390 /*
391 * This is needed to prevent the chip waking up
392 * the host within 3-4 seconds with certain
393 * platform/BIOS.
394 */
395 host_pm_ctrl &= ~AR_PMCTRL_PWR_STATE_D1D3;
396 host_pm_ctrl |= AR_PMCTRL_PWR_STATE_D1D3_REAL;
397 }
398
399 REG_WRITE(ah, AR_PCIE_PM_CTRL, host_pm_ctrl);
395 400
396 /* 401 /*
397 * this is needed to prevent the chip waking up 402 * Enable sequence number generation when asleep.
398 * the host within 3-4 seconds with certain
399 * platform/BIOS. The fix is to enable
400 * D1 & D3 to match original definition and
401 * also match the OTP value. Anyway this
402 * is more related to SW WOW.
403 */ 403 */
404 clr = AR_PMCTRL_PWR_STATE_D1D3; 404 REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PRESERVE_SEQNUM);
405 REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, clr);
406 405
407 set = AR_PMCTRL_PWR_STATE_D1D3_REAL; 406 /* To bring down WOW power low margin */
408 REG_SET_BIT(ah, AR_PCIE_PM_CTRL, set); 407 REG_SET_BIT(ah, AR_PCIE_PHY_REG3, BIT(13));
409 408
410 REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PRESERVE_SEQNUM); 409 ath9k_hw_wow_set_arwr_reg(ah);
411 410
412 /* to bring down WOW power low margin */
413 set = BIT(13);
414 REG_SET_BIT(ah, AR_PCIE_PHY_REG3, set);
415 /* HW WoW */ 411 /* HW WoW */
416 clr = BIT(5); 412 REG_CLR_BIT(ah, AR_PCU_MISC_MODE3, BIT(5));
417 REG_CLR_BIT(ah, AR_PCU_MISC_MODE3, clr);
418 413
419 ath9k_hw_set_powermode_wow_sleep(ah); 414 ath9k_hw_set_powermode_wow_sleep(ah);
420 ah->wow_event_mask = wow_event_mask; 415 ah->wow.wow_event_mask = wow_event_mask;
421} 416}
422EXPORT_SYMBOL(ath9k_hw_wow_enable); 417EXPORT_SYMBOL(ath9k_hw_wow_enable);
diff --git a/drivers/net/wireless/ath/ath9k/ar953x_initvals.h b/drivers/net/wireless/ath/ath9k/ar953x_initvals.h
index 159cc6fd2362..6fc0d07e5ec6 100644
--- a/drivers/net/wireless/ath/ath9k/ar953x_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar953x_initvals.h
@@ -358,7 +358,7 @@ static const u32 qca953x_1p0_baseband_postamble[][5] = {
358 {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, 358 {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
359 {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, 359 {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
360 {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, 360 {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
361 {0x00009e3c, 0xcfa10820, 0xcfa10820, 0xcfa10822, 0xcfa10822}, 361 {0x00009e3c, 0xcfa10820, 0xcfa10820, 0xcfa10820, 0xcfa10820},
362 {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27}, 362 {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27},
363 {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, 363 {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
364 {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, 364 {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
@@ -378,7 +378,7 @@ static const u32 qca953x_1p0_baseband_postamble[][5] = {
378 {0x0000a284, 0x00000000, 0x00000000, 0x00000010, 0x00000010}, 378 {0x0000a284, 0x00000000, 0x00000000, 0x00000010, 0x00000010},
379 {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110}, 379 {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110},
380 {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222}, 380 {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222},
381 {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, 381 {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00058d18, 0x00058d18},
382 {0x0000a2cc, 0x18c50033, 0x18c43433, 0x18c41033, 0x18c44c33}, 382 {0x0000a2cc, 0x18c50033, 0x18c43433, 0x18c41033, 0x18c44c33},
383 {0x0000a2d0, 0x00041982, 0x00041982, 0x00041982, 0x00041982}, 383 {0x0000a2d0, 0x00041982, 0x00041982, 0x00041982, 0x00041982},
384 {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b}, 384 {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b},
diff --git a/drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h
index fd6a84ccd49e..148562addd38 100644
--- a/drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h
@@ -63,7 +63,7 @@ static const u32 ar955x_1p0_baseband_postamble[][5] = {
63 {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, 63 {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
64 {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, 64 {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
65 {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, 65 {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
66 {0x00009e3c, 0xcfa10820, 0xcfa10820, 0xcfa10822, 0xcfa10822}, 66 {0x00009e3c, 0xcfa10820, 0xcfa10820, 0xcfa10820, 0xcfa10820},
67 {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27}, 67 {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27},
68 {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, 68 {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
69 {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, 69 {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
@@ -83,7 +83,7 @@ static const u32 ar955x_1p0_baseband_postamble[][5] = {
83 {0x0000a284, 0x00000000, 0x00000000, 0x00000010, 0x00000010}, 83 {0x0000a284, 0x00000000, 0x00000000, 0x00000010, 0x00000010},
84 {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110}, 84 {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110},
85 {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222}, 85 {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222},
86 {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, 86 {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00058d18, 0x00058d18},
87 {0x0000a2cc, 0x18c50033, 0x18c43433, 0x18c41033, 0x18c44c33}, 87 {0x0000a2cc, 0x18c50033, 0x18c43433, 0x18c41033, 0x18c44c33},
88 {0x0000a2d0, 0x00041982, 0x00041982, 0x00041982, 0x00041982}, 88 {0x0000a2d0, 0x00041982, 0x00041982, 0x00041982, 0x00041982},
89 {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b}, 89 {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b},
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 1a9fe0983a6b..0f8e9464e4ab 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -34,7 +34,7 @@ struct ath_vif;
34 34
35extern struct ieee80211_ops ath9k_ops; 35extern struct ieee80211_ops ath9k_ops;
36extern int ath9k_modparam_nohwcrypt; 36extern int ath9k_modparam_nohwcrypt;
37extern int led_blink; 37extern int ath9k_led_blink;
38extern bool is_ath9k_unloaded; 38extern bool is_ath9k_unloaded;
39extern int ath9k_use_chanctx; 39extern int ath9k_use_chanctx;
40 40
@@ -830,14 +830,9 @@ static inline void ath_fill_led_pin(struct ath_softc *sc)
830/* Wake on Wireless LAN */ 830/* Wake on Wireless LAN */
831/************************/ 831/************************/
832 832
833struct ath9k_wow_pattern {
834 u8 pattern_bytes[MAX_PATTERN_SIZE];
835 u8 mask_bytes[MAX_PATTERN_SIZE];
836 u32 pattern_len;
837};
838
839#ifdef CONFIG_ATH9K_WOW 833#ifdef CONFIG_ATH9K_WOW
840void ath9k_init_wow(struct ieee80211_hw *hw); 834void ath9k_init_wow(struct ieee80211_hw *hw);
835void ath9k_deinit_wow(struct ieee80211_hw *hw);
841int ath9k_suspend(struct ieee80211_hw *hw, 836int ath9k_suspend(struct ieee80211_hw *hw,
842 struct cfg80211_wowlan *wowlan); 837 struct cfg80211_wowlan *wowlan);
843int ath9k_resume(struct ieee80211_hw *hw); 838int ath9k_resume(struct ieee80211_hw *hw);
@@ -846,6 +841,9 @@ void ath9k_set_wakeup(struct ieee80211_hw *hw, bool enabled);
846static inline void ath9k_init_wow(struct ieee80211_hw *hw) 841static inline void ath9k_init_wow(struct ieee80211_hw *hw)
847{ 842{
848} 843}
844static inline void ath9k_deinit_wow(struct ieee80211_hw *hw)
845{
846}
849static inline int ath9k_suspend(struct ieee80211_hw *hw, 847static inline int ath9k_suspend(struct ieee80211_hw *hw,
850 struct cfg80211_wowlan *wowlan) 848 struct cfg80211_wowlan *wowlan)
851{ 849{
@@ -1039,9 +1037,8 @@ struct ath_softc {
1039 s16 tx99_power; 1037 s16 tx99_power;
1040 1038
1041#ifdef CONFIG_ATH9K_WOW 1039#ifdef CONFIG_ATH9K_WOW
1042 atomic_t wow_got_bmiss_intr;
1043 atomic_t wow_sleep_proc_intr; /* in the middle of WoW sleep ? */
1044 u32 wow_intr_before_sleep; 1040 u32 wow_intr_before_sleep;
1041 bool force_wow;
1045#endif 1042#endif
1046}; 1043};
1047 1044
diff --git a/drivers/net/wireless/ath/ath9k/common-spectral.c b/drivers/net/wireless/ath/ath9k/common-spectral.c
index ec93ddf0863a..5cee231cca1f 100644
--- a/drivers/net/wireless/ath/ath9k/common-spectral.c
+++ b/drivers/net/wireless/ath/ath9k/common-spectral.c
@@ -582,7 +582,7 @@ static struct rchan_callbacks rfs_spec_scan_cb = {
582 582
583void ath9k_cmn_spectral_deinit_debug(struct ath_spec_scan_priv *spec_priv) 583void ath9k_cmn_spectral_deinit_debug(struct ath_spec_scan_priv *spec_priv)
584{ 584{
585 if (config_enabled(CONFIG_ATH9K_DEBUGFS) && spec_priv->rfs_chan_spec_scan) { 585 if (config_enabled(CONFIG_ATH9K_DEBUGFS)) {
586 relay_close(spec_priv->rfs_chan_spec_scan); 586 relay_close(spec_priv->rfs_chan_spec_scan);
587 spec_priv->rfs_chan_spec_scan = NULL; 587 spec_priv->rfs_chan_spec_scan = NULL;
588 } 588 }
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index dd5d3914799b..50a2e0ac3b8b 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -1043,6 +1043,69 @@ static const struct file_operations fops_ackto = {
1043}; 1043};
1044#endif 1044#endif
1045 1045
1046#ifdef CONFIG_ATH9K_WOW
1047
1048static ssize_t read_file_wow(struct file *file, char __user *user_buf,
1049 size_t count, loff_t *ppos)
1050{
1051 struct ath_softc *sc = file->private_data;
1052 unsigned int len = 0, size = 32;
1053 ssize_t retval;
1054 char *buf;
1055
1056 buf = kzalloc(size, GFP_KERNEL);
1057 if (!buf)
1058 return -ENOMEM;
1059
1060 len += scnprintf(buf + len, size - len, "WOW: %s\n",
1061 sc->force_wow ? "ENABLED" : "DISABLED");
1062
1063 if (len > size)
1064 len = size;
1065
1066 retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
1067 kfree(buf);
1068
1069 return retval;
1070}
1071
1072static ssize_t write_file_wow(struct file *file, const char __user *user_buf,
1073 size_t count, loff_t *ppos)
1074{
1075 struct ath_softc *sc = file->private_data;
1076 unsigned long val;
1077 char buf[32];
1078 ssize_t len;
1079
1080 len = min(count, sizeof(buf) - 1);
1081 if (copy_from_user(buf, user_buf, len))
1082 return -EFAULT;
1083
1084 buf[len] = '\0';
1085 if (kstrtoul(buf, 0, &val))
1086 return -EINVAL;
1087
1088 if (val != 1)
1089 return -EINVAL;
1090
1091 if (!sc->force_wow) {
1092 sc->force_wow = true;
1093 ath9k_init_wow(sc->hw);
1094 }
1095
1096 return count;
1097}
1098
1099static const struct file_operations fops_wow = {
1100 .read = read_file_wow,
1101 .write = write_file_wow,
1102 .open = simple_open,
1103 .owner = THIS_MODULE,
1104 .llseek = default_llseek,
1105};
1106
1107#endif
1108
1046static ssize_t read_file_tpc(struct file *file, char __user *user_buf, 1109static ssize_t read_file_tpc(struct file *file, char __user *user_buf,
1047 size_t count, loff_t *ppos) 1110 size_t count, loff_t *ppos)
1048{ 1111{
@@ -1313,6 +1376,11 @@ int ath9k_init_debug(struct ath_hw *ah)
1313 &fops_btcoex); 1376 &fops_btcoex);
1314#endif 1377#endif
1315 1378
1379#ifdef CONFIG_ATH9K_WOW
1380 debugfs_create_file("wow", S_IRUSR | S_IWUSR,
1381 sc->debug.debugfs_phy, sc, &fops_wow);
1382#endif
1383
1316#ifdef CONFIG_ATH9K_DYNACK 1384#ifdef CONFIG_ATH9K_DYNACK
1317 debugfs_create_file("ack_to", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, 1385 debugfs_create_file("ack_to", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
1318 sc, &fops_ackto); 1386 sc, &fops_ackto);
diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c
index 2fef7a480fec..da344b27326c 100644
--- a/drivers/net/wireless/ath/ath9k/gpio.c
+++ b/drivers/net/wireless/ath/ath9k/gpio.c
@@ -49,7 +49,7 @@ void ath_init_leds(struct ath_softc *sc)
49 if (AR_SREV_9100(sc->sc_ah)) 49 if (AR_SREV_9100(sc->sc_ah))
50 return; 50 return;
51 51
52 if (!led_blink) 52 if (!ath9k_led_blink)
53 sc->led_cdev.default_trigger = 53 sc->led_cdev.default_trigger =
54 ieee80211_get_radio_led_name(sc->hw); 54 ieee80211_get_radio_led_name(sc->hw);
55 55
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
index c43fec51b8ec..300d3671d0ef 100644
--- a/drivers/net/wireless/ath/ath9k/htc.h
+++ b/drivers/net/wireless/ath/ath9k/htc.h
@@ -45,7 +45,7 @@
45extern struct ieee80211_ops ath9k_htc_ops; 45extern struct ieee80211_ops ath9k_htc_ops;
46extern int htc_modparam_nohwcrypt; 46extern int htc_modparam_nohwcrypt;
47#ifdef CONFIG_MAC80211_LEDS 47#ifdef CONFIG_MAC80211_LEDS
48extern int led_blink; 48extern int ath9k_htc_led_blink;
49#endif 49#endif
50 50
51enum htc_phymode { 51enum htc_phymode {
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c
index 998b558d4126..2aabcbdaba4e 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c
@@ -279,7 +279,7 @@ void ath9k_init_leds(struct ath9k_htc_priv *priv)
279 else 279 else
280 priv->ah->led_pin = ATH_LED_PIN_DEF; 280 priv->ah->led_pin = ATH_LED_PIN_DEF;
281 281
282 if (!led_blink) 282 if (!ath9k_htc_led_blink)
283 priv->led_cdev.default_trigger = 283 priv->led_cdev.default_trigger =
284 ieee80211_get_radio_led_name(priv->hw); 284 ieee80211_get_radio_led_name(priv->hw);
285 285
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
index 947012757f81..fd229409f676 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
@@ -39,8 +39,8 @@ module_param_named(ps_enable, ath9k_ps_enable, int, 0444);
39MODULE_PARM_DESC(ps_enable, "Enable WLAN PowerSave"); 39MODULE_PARM_DESC(ps_enable, "Enable WLAN PowerSave");
40 40
41#ifdef CONFIG_MAC80211_LEDS 41#ifdef CONFIG_MAC80211_LEDS
42int led_blink = 1; 42int ath9k_htc_led_blink = 1;
43module_param_named(blink, led_blink, int, 0444); 43module_param_named(blink, ath9k_htc_led_blink, int, 0444);
44MODULE_PARM_DESC(blink, "Enable LED blink on activity"); 44MODULE_PARM_DESC(blink, "Enable LED blink on activity");
45 45
46static const struct ieee80211_tpt_blink ath9k_htc_tpt_blink[] = { 46static const struct ieee80211_tpt_blink ath9k_htc_tpt_blink[] = {
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 82d8f32a3461..60aa8d71e753 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -2544,13 +2544,17 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
2544 pCap->hw_caps |= ATH9K_HW_CAP_RTT; 2544 pCap->hw_caps |= ATH9K_HW_CAP_RTT;
2545 } 2545 }
2546 2546
2547 if (AR_SREV_9462(ah))
2548 pCap->hw_caps |= ATH9K_HW_WOW_DEVICE_CAPABLE;
2549
2550 if (AR_SREV_9300_20_OR_LATER(ah) && 2547 if (AR_SREV_9300_20_OR_LATER(ah) &&
2551 ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) 2548 ah->eep_ops->get_eeprom(ah, EEP_PAPRD))
2552 pCap->hw_caps |= ATH9K_HW_CAP_PAPRD; 2549 pCap->hw_caps |= ATH9K_HW_CAP_PAPRD;
2553 2550
2551#ifdef CONFIG_ATH9K_WOW
2552 if (AR_SREV_9462_20_OR_LATER(ah) || AR_SREV_9565_11_OR_LATER(ah))
2553 ah->wow.max_patterns = MAX_NUM_PATTERN;
2554 else
2555 ah->wow.max_patterns = MAX_NUM_PATTERN_LEGACY;
2556#endif
2557
2554 return 0; 2558 return 0;
2555} 2559}
2556 2560
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index 450704e49f03..e82e570de330 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -199,12 +199,13 @@
199#define KAL_NUM_DESC_WORDS 12 199#define KAL_NUM_DESC_WORDS 12
200#define KAL_ANTENNA_MODE 1 200#define KAL_ANTENNA_MODE 1
201#define KAL_TO_DS 1 201#define KAL_TO_DS 1
202#define KAL_DELAY 4 /*delay of 4ms between 2 KAL frames */ 202#define KAL_DELAY 4 /* delay of 4ms between 2 KAL frames */
203#define KAL_TIMEOUT 900 203#define KAL_TIMEOUT 900
204 204
205#define MAX_PATTERN_SIZE 256 205#define MAX_PATTERN_SIZE 256
206#define MAX_PATTERN_MASK_SIZE 32 206#define MAX_PATTERN_MASK_SIZE 32
207#define MAX_NUM_PATTERN 8 207#define MAX_NUM_PATTERN 16
208#define MAX_NUM_PATTERN_LEGACY 8
208#define MAX_NUM_USER_PATTERN 6 /* deducting the disassociate and 209#define MAX_NUM_USER_PATTERN 6 /* deducting the disassociate and
209 deauthenticate packets */ 210 deauthenticate packets */
210 211
@@ -248,12 +249,10 @@ enum ath9k_hw_caps {
248#ifdef CONFIG_ATH9K_PCOEM 249#ifdef CONFIG_ATH9K_PCOEM
249 ATH9K_HW_CAP_RTT = BIT(14), 250 ATH9K_HW_CAP_RTT = BIT(14),
250 ATH9K_HW_CAP_MCI = BIT(15), 251 ATH9K_HW_CAP_MCI = BIT(15),
251 ATH9K_HW_WOW_DEVICE_CAPABLE = BIT(16),
252 ATH9K_HW_CAP_BT_ANT_DIV = BIT(17), 252 ATH9K_HW_CAP_BT_ANT_DIV = BIT(17),
253#else 253#else
254 ATH9K_HW_CAP_RTT = 0, 254 ATH9K_HW_CAP_RTT = 0,
255 ATH9K_HW_CAP_MCI = 0, 255 ATH9K_HW_CAP_MCI = 0,
256 ATH9K_HW_WOW_DEVICE_CAPABLE = 0,
257 ATH9K_HW_CAP_BT_ANT_DIV = 0, 256 ATH9K_HW_CAP_BT_ANT_DIV = 0,
258#endif 257#endif
259 ATH9K_HW_CAP_DFS = BIT(18), 258 ATH9K_HW_CAP_DFS = BIT(18),
@@ -272,6 +271,12 @@ enum ath9k_hw_caps {
272 * of those types. 271 * of those types.
273 */ 272 */
274 273
274struct ath9k_hw_wow {
275 u32 wow_event_mask;
276 u32 wow_event_mask2;
277 u8 max_patterns;
278};
279
275struct ath9k_hw_capabilities { 280struct ath9k_hw_capabilities {
276 u32 hw_caps; /* ATH9K_HW_CAP_* from ath9k_hw_caps */ 281 u32 hw_caps; /* ATH9K_HW_CAP_* from ath9k_hw_caps */
277 u16 rts_aggr_limit; 282 u16 rts_aggr_limit;
@@ -930,7 +935,7 @@ struct ath_hw {
930 u32 ent_mode; 935 u32 ent_mode;
931 936
932#ifdef CONFIG_ATH9K_WOW 937#ifdef CONFIG_ATH9K_WOW
933 u32 wow_event_mask; 938 struct ath9k_hw_wow wow;
934#endif 939#endif
935 bool is_clk_25mhz; 940 bool is_clk_25mhz;
936 int (*get_mac_revision)(void); 941 int (*get_mac_revision)(void);
@@ -1148,23 +1153,19 @@ ath9k_hw_get_btcoex_scheme(struct ath_hw *ah)
1148 1153
1149 1154
1150#ifdef CONFIG_ATH9K_WOW 1155#ifdef CONFIG_ATH9K_WOW
1151const char *ath9k_hw_wow_event_to_string(u32 wow_event); 1156int ath9k_hw_wow_apply_pattern(struct ath_hw *ah, u8 *user_pattern,
1152void ath9k_hw_wow_apply_pattern(struct ath_hw *ah, u8 *user_pattern, 1157 u8 *user_mask, int pattern_count,
1153 u8 *user_mask, int pattern_count, 1158 int pattern_len);
1154 int pattern_len);
1155u32 ath9k_hw_wow_wakeup(struct ath_hw *ah); 1159u32 ath9k_hw_wow_wakeup(struct ath_hw *ah);
1156void ath9k_hw_wow_enable(struct ath_hw *ah, u32 pattern_enable); 1160void ath9k_hw_wow_enable(struct ath_hw *ah, u32 pattern_enable);
1157#else 1161#else
1158static inline const char *ath9k_hw_wow_event_to_string(u32 wow_event) 1162static inline int ath9k_hw_wow_apply_pattern(struct ath_hw *ah,
1159{ 1163 u8 *user_pattern,
1160 return NULL; 1164 u8 *user_mask,
1161} 1165 int pattern_count,
1162static inline void ath9k_hw_wow_apply_pattern(struct ath_hw *ah, 1166 int pattern_len)
1163 u8 *user_pattern,
1164 u8 *user_mask,
1165 int pattern_count,
1166 int pattern_len)
1167{ 1167{
1168 return 0;
1168} 1169}
1169static inline u32 ath9k_hw_wow_wakeup(struct ath_hw *ah) 1170static inline u32 ath9k_hw_wow_wakeup(struct ath_hw *ah)
1170{ 1171{
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index d1c39346b264..6c6e88495394 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -45,8 +45,8 @@ int ath9k_modparam_nohwcrypt;
45module_param_named(nohwcrypt, ath9k_modparam_nohwcrypt, int, 0444); 45module_param_named(nohwcrypt, ath9k_modparam_nohwcrypt, int, 0444);
46MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption"); 46MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption");
47 47
48int led_blink; 48int ath9k_led_blink;
49module_param_named(blink, led_blink, int, 0444); 49module_param_named(blink, ath9k_led_blink, int, 0444);
50MODULE_PARM_DESC(blink, "Enable LED blink on activity"); 50MODULE_PARM_DESC(blink, "Enable LED blink on activity");
51 51
52static int ath9k_btcoex_enable; 52static int ath9k_btcoex_enable;
@@ -996,6 +996,7 @@ void ath9k_deinit_device(struct ath_softc *sc)
996 ath9k_ps_restore(sc); 996 ath9k_ps_restore(sc);
997 997
998 ath9k_deinit_debug(sc); 998 ath9k_deinit_debug(sc);
999 ath9k_deinit_wow(hw);
999 ieee80211_unregister_hw(hw); 1000 ieee80211_unregister_hw(hw);
1000 ath_rx_cleanup(sc); 1001 ath_rx_cleanup(sc);
1001 ath9k_deinit_softc(sc); 1002 ath9k_deinit_softc(sc);
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 62b0bf4fdf6b..9ede991b8d76 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -555,15 +555,6 @@ irqreturn_t ath_isr(int irq, void *dev)
555 (status & ATH9K_INT_BB_WATCHDOG)) 555 (status & ATH9K_INT_BB_WATCHDOG))
556 goto chip_reset; 556 goto chip_reset;
557 557
558#ifdef CONFIG_ATH9K_WOW
559 if (status & ATH9K_INT_BMISS) {
560 if (atomic_read(&sc->wow_sleep_proc_intr) == 0) {
561 atomic_inc(&sc->wow_got_bmiss_intr);
562 atomic_dec(&sc->wow_sleep_proc_intr);
563 }
564 }
565#endif
566
567 if (status & ATH9K_INT_SWBA) 558 if (status & ATH9K_INT_SWBA)
568 tasklet_schedule(&sc->bcon_tasklet); 559 tasklet_schedule(&sc->bcon_tasklet);
569 560
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c
index cc5c6810f32e..e6fef1be9977 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)
998 struct pci_dev *pdev = to_pci_dev(device); 998 struct pci_dev *pdev = to_pci_dev(device);
999 struct ieee80211_hw *hw = pci_get_drvdata(pdev); 999 struct ieee80211_hw *hw = pci_get_drvdata(pdev);
1000 struct ath_softc *sc = hw->priv; 1000 struct ath_softc *sc = hw->priv;
1001 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
1001 1002
1002 if (sc->wow_enabled) 1003 if (test_bit(ATH_OP_WOW_ENABLED, &common->op_flags)) {
1004 dev_info(&pdev->dev, "WOW is enabled, bypassing PCI suspend\n");
1003 return 0; 1005 return 0;
1006 }
1004 1007
1005 /* The device has to be moved to FULLSLEEP forcibly. 1008 /* The device has to be moved to FULLSLEEP forcibly.
1006 * Otherwise the chip never moved to full sleep, 1009 * Otherwise the chip never moved to full sleep,
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h
index eb2bb0db297f..9587ec655680 100644
--- a/drivers/net/wireless/ath/ath9k/reg.h
+++ b/drivers/net/wireless/ath/ath9k/reg.h
@@ -900,10 +900,13 @@
900 (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9485)) 900 (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9485))
901#define AR_SREV_9565(_ah) \ 901#define AR_SREV_9565(_ah) \
902 (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565)) 902 (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565))
903#define AR_SREV_9003_PCOEM(_ah) \
904 (AR_SREV_9462(_ah) || AR_SREV_9485(_ah) || AR_SREV_9565(_ah))
903#else 905#else
904#define AR_SREV_9462(_ah) 0 906#define AR_SREV_9462(_ah) 0
905#define AR_SREV_9485(_ah) 0 907#define AR_SREV_9485(_ah) 0
906#define AR_SREV_9565(_ah) 0 908#define AR_SREV_9565(_ah) 0
909#define AR_SREV_9003_PCOEM(_ah) 0
907#endif 910#endif
908 911
909#define AR_SREV_9485_11_OR_LATER(_ah) \ 912#define AR_SREV_9485_11_OR_LATER(_ah) \
@@ -1880,6 +1883,7 @@ enum {
1880#define AR_FIRST_NDP_TIMER 7 1883#define AR_FIRST_NDP_TIMER 7
1881#define AR_NDP2_PERIOD 0x81a0 1884#define AR_NDP2_PERIOD 0x81a0
1882#define AR_NDP2_TIMER_MODE 0x81c0 1885#define AR_NDP2_TIMER_MODE 0x81c0
1886#define AR_GEN_TIMERS2_MODE_ENABLE_MASK 0x000000FF
1883 1887
1884#define AR_GEN_TIMERS(_i) (0x8200 + ((_i) << 2)) 1888#define AR_GEN_TIMERS(_i) (0x8200 + ((_i) << 2))
1885#define AR_NEXT_TBTT_TIMER AR_GEN_TIMERS(0) 1889#define AR_NEXT_TBTT_TIMER AR_GEN_TIMERS(0)
@@ -1975,6 +1979,7 @@ enum {
1975 1979
1976#define AR_DIRECT_CONNECT 0x83a0 1980#define AR_DIRECT_CONNECT 0x83a0
1977#define AR_DC_AP_STA_EN 0x00000001 1981#define AR_DC_AP_STA_EN 0x00000001
1982#define AR_DC_TSF2_ENABLE 0x00000001
1978 1983
1979#define AR_AES_MUTE_MASK0 0x805c 1984#define AR_AES_MUTE_MASK0 0x805c
1980#define AR_AES_MUTE_MASK0_FC 0x0000FFFF 1985#define AR_AES_MUTE_MASK0_FC 0x0000FFFF
@@ -2007,126 +2012,6 @@ enum {
2007 2012
2008#define AR_WOW_BEACON_TIMO_MAX 0xffffffff 2013#define AR_WOW_BEACON_TIMO_MAX 0xffffffff
2009 2014
2010/*
2011 * MAC WoW Registers
2012 */
2013
2014#define AR_WOW_PATTERN 0x825C
2015#define AR_WOW_COUNT 0x8260
2016#define AR_WOW_BCN_EN 0x8270
2017#define AR_WOW_BCN_TIMO 0x8274
2018#define AR_WOW_KEEP_ALIVE_TIMO 0x8278
2019#define AR_WOW_KEEP_ALIVE 0x827c
2020#define AR_WOW_US_SCALAR 0x8284
2021#define AR_WOW_KEEP_ALIVE_DELAY 0x8288
2022#define AR_WOW_PATTERN_MATCH 0x828c
2023#define AR_WOW_PATTERN_OFF1 0x8290 /* pattern bytes 0 -> 3 */
2024#define AR_WOW_PATTERN_OFF2 0x8294 /* pattern bytes 4 -> 7 */
2025
2026/* for AR9285 or later version of chips */
2027#define AR_WOW_EXACT 0x829c
2028#define AR_WOW_LENGTH1 0x8360
2029#define AR_WOW_LENGTH2 0X8364
2030/* register to enable match for less than 256 bytes packets */
2031#define AR_WOW_PATTERN_MATCH_LT_256B 0x8368
2032
2033#define AR_SW_WOW_CONTROL 0x20018
2034#define AR_SW_WOW_ENABLE 0x1
2035#define AR_SWITCH_TO_REFCLK 0x2
2036#define AR_RESET_CONTROL 0x4
2037#define AR_RESET_VALUE_MASK 0x8
2038#define AR_HW_WOW_DISABLE 0x10
2039#define AR_CLR_MAC_INTERRUPT 0x20
2040#define AR_CLR_KA_INTERRUPT 0x40
2041
2042/* AR_WOW_PATTERN register values */
2043#define AR_WOW_BACK_OFF_SHIFT(x) ((x & 0xf) << 28) /* in usecs */
2044#define AR_WOW_MAC_INTR_EN 0x00040000
2045#define AR_WOW_MAGIC_EN 0x00010000
2046#define AR_WOW_PATTERN_EN(x) (x & 0xff)
2047#define AR_WOW_PAT_FOUND_SHIFT 8
2048#define AR_WOW_PATTERN_FOUND(x) (x & (0xff << AR_WOW_PAT_FOUND_SHIFT))
2049#define AR_WOW_PATTERN_FOUND_MASK ((0xff) << AR_WOW_PAT_FOUND_SHIFT)
2050#define AR_WOW_MAGIC_PAT_FOUND 0x00020000
2051#define AR_WOW_MAC_INTR 0x00080000
2052#define AR_WOW_KEEP_ALIVE_FAIL 0x00100000
2053#define AR_WOW_BEACON_FAIL 0x00200000
2054
2055#define AR_WOW_STATUS(x) (x & (AR_WOW_PATTERN_FOUND_MASK | \
2056 AR_WOW_MAGIC_PAT_FOUND | \
2057 AR_WOW_KEEP_ALIVE_FAIL | \
2058 AR_WOW_BEACON_FAIL))
2059#define AR_WOW_CLEAR_EVENTS(x) (x & ~(AR_WOW_PATTERN_EN(0xff) | \
2060 AR_WOW_MAGIC_EN | \
2061 AR_WOW_MAC_INTR_EN | \
2062 AR_WOW_BEACON_FAIL | \
2063 AR_WOW_KEEP_ALIVE_FAIL))
2064
2065/* AR_WOW_COUNT register values */
2066#define AR_WOW_AIFS_CNT(x) (x & 0xff)
2067#define AR_WOW_SLOT_CNT(x) ((x & 0xff) << 8)
2068#define AR_WOW_KEEP_ALIVE_CNT(x) ((x & 0xff) << 16)
2069
2070/* AR_WOW_BCN_EN register */
2071#define AR_WOW_BEACON_FAIL_EN 0x00000001
2072
2073/* AR_WOW_BCN_TIMO rgister */
2074#define AR_WOW_BEACON_TIMO 0x40000000 /* valid if BCN_EN is set */
2075
2076/* AR_WOW_KEEP_ALIVE_TIMO register */
2077#define AR_WOW_KEEP_ALIVE_TIMO_VALUE
2078#define AR_WOW_KEEP_ALIVE_NEVER 0xffffffff
2079
2080/* AR_WOW_KEEP_ALIVE register */
2081#define AR_WOW_KEEP_ALIVE_AUTO_DIS 0x00000001
2082#define AR_WOW_KEEP_ALIVE_FAIL_DIS 0x00000002
2083
2084/* AR_WOW_KEEP_ALIVE_DELAY register */
2085#define AR_WOW_KEEP_ALIVE_DELAY_VALUE 0x000003e8 /* 1 msec */
2086
2087
2088/*
2089 * keep it long for beacon workaround - ensure no false alarm
2090 */
2091#define AR_WOW_BMISSTHRESHOLD 0x20
2092
2093/* AR_WOW_PATTERN_MATCH register */
2094#define AR_WOW_PAT_END_OF_PKT(x) (x & 0xf)
2095#define AR_WOW_PAT_OFF_MATCH(x) ((x & 0xf) << 8)
2096
2097/*
2098 * default values for Wow Configuration for backoff, aifs, slot, keep-alive
2099 * to be programmed into various registers.
2100 */
2101#define AR_WOW_PAT_BACKOFF 0x00000004 /* AR_WOW_PATTERN_REG */
2102#define AR_WOW_CNT_AIFS_CNT 0x00000022 /* AR_WOW_COUNT_REG */
2103#define AR_WOW_CNT_SLOT_CNT 0x00000009 /* AR_WOW_COUNT_REG */
2104/*
2105 * Keepalive count applicable for AR9280 2.0 and above.
2106 */
2107#define AR_WOW_CNT_KA_CNT 0x00000008 /* AR_WOW_COUNT register */
2108
2109/* WoW - Transmit buffer for keep alive frames */
2110#define AR_WOW_TRANSMIT_BUFFER 0xe000 /* E000 - EFFC */
2111
2112#define AR_WOW_TXBUF(i) (AR_WOW_TRANSMIT_BUFFER + ((i) << 2))
2113
2114#define AR_WOW_KA_DESC_WORD2 0xe000
2115
2116#define AR_WOW_KA_DATA_WORD0 0xe030
2117
2118/* WoW Transmit Buffer for patterns */
2119#define AR_WOW_TB_PATTERN(i) (0xe100 + (i << 8))
2120#define AR_WOW_TB_MASK(i) (0xec00 + (i << 5))
2121
2122/* Currently Pattern 0-7 are supported - so bit 0-7 are set */
2123#define AR_WOW_PATTERN_SUPPORTED 0xff
2124#define AR_WOW_LENGTH_MAX 0xff
2125#define AR_WOW_LEN1_SHIFT(_i) ((0x3 - ((_i) & 0x3)) << 0x3)
2126#define AR_WOW_LENGTH1_MASK(_i) (AR_WOW_LENGTH_MAX << AR_WOW_LEN1_SHIFT(_i))
2127#define AR_WOW_LEN2_SHIFT(_i) ((0x7 - ((_i) & 0x7)) << 0x3)
2128#define AR_WOW_LENGTH2_MASK(_i) (AR_WOW_LENGTH_MAX << AR_WOW_LEN2_SHIFT(_i))
2129
2130#define AR9271_CORE_CLOCK 117 /* clock to 117Mhz */ 2015#define AR9271_CORE_CLOCK 117 /* clock to 117Mhz */
2131#define AR9271_TARGET_BAUD_RATE 19200 /* 115200 */ 2016#define AR9271_TARGET_BAUD_RATE 19200 /* 115200 */
2132 2017
diff --git a/drivers/net/wireless/ath/ath9k/reg_wow.h b/drivers/net/wireless/ath/ath9k/reg_wow.h
new file mode 100644
index 000000000000..3abfca56ca58
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/reg_wow.h
@@ -0,0 +1,128 @@
1/*
2 * Copyright (c) 2015 Qualcomm Atheros Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#ifndef REG_WOW_H
18#define REG_WOW_H
19
20#define AR_WOW_PATTERN 0x825C
21#define AR_WOW_COUNT 0x8260
22#define AR_WOW_BCN_EN 0x8270
23#define AR_WOW_BCN_TIMO 0x8274
24#define AR_WOW_KEEP_ALIVE_TIMO 0x8278
25#define AR_WOW_KEEP_ALIVE 0x827c
26#define AR_WOW_KEEP_ALIVE_DELAY 0x8288
27#define AR_WOW_PATTERN_MATCH 0x828c
28
29/*
30 * AR_WOW_LENGTH1
31 * bit 31:24 pattern 0 length
32 * bit 23:16 pattern 1 length
33 * bit 15:8 pattern 2 length
34 * bit 7:0 pattern 3 length
35 *
36 * AR_WOW_LENGTH2
37 * bit 31:24 pattern 4 length
38 * bit 23:16 pattern 5 length
39 * bit 15:8 pattern 6 length
40 * bit 7:0 pattern 7 length
41 *
42 * AR_WOW_LENGTH3
43 * bit 31:24 pattern 8 length
44 * bit 23:16 pattern 9 length
45 * bit 15:8 pattern 10 length
46 * bit 7:0 pattern 11 length
47 *
48 * AR_WOW_LENGTH4
49 * bit 31:24 pattern 12 length
50 * bit 23:16 pattern 13 length
51 * bit 15:8 pattern 14 length
52 * bit 7:0 pattern 15 length
53 */
54#define AR_WOW_LENGTH1 0x8360
55#define AR_WOW_LENGTH2 0X8364
56#define AR_WOW_LENGTH3 0X8380
57#define AR_WOW_LENGTH4 0X8384
58
59#define AR_WOW_PATTERN_MATCH_LT_256B 0x8368
60#define AR_MAC_PCU_WOW4 0x8370
61
62#define AR_SW_WOW_CONTROL 0x20018
63#define AR_SW_WOW_ENABLE 0x1
64#define AR_SWITCH_TO_REFCLK 0x2
65#define AR_RESET_CONTROL 0x4
66#define AR_RESET_VALUE_MASK 0x8
67#define AR_HW_WOW_DISABLE 0x10
68#define AR_CLR_MAC_INTERRUPT 0x20
69#define AR_CLR_KA_INTERRUPT 0x40
70
71#define AR_WOW_BACK_OFF_SHIFT(x) ((x & 0xf) << 27) /* in usecs */
72#define AR_WOW_MAC_INTR_EN 0x00040000
73#define AR_WOW_MAGIC_EN 0x00010000
74#define AR_WOW_PATTERN_EN(x) (x & 0xff)
75#define AR_WOW_PAT_FOUND_SHIFT 8
76#define AR_WOW_PATTERN_FOUND(x) (x & (0xff << AR_WOW_PAT_FOUND_SHIFT))
77#define AR_WOW_PATTERN_FOUND_MASK ((0xff) << AR_WOW_PAT_FOUND_SHIFT)
78#define AR_WOW_MAGIC_PAT_FOUND 0x00020000
79#define AR_WOW_MAC_INTR 0x00080000
80#define AR_WOW_KEEP_ALIVE_FAIL 0x00100000
81#define AR_WOW_BEACON_FAIL 0x00200000
82
83#define AR_WOW_STATUS(x) (x & (AR_WOW_PATTERN_FOUND_MASK | \
84 AR_WOW_MAGIC_PAT_FOUND | \
85 AR_WOW_KEEP_ALIVE_FAIL | \
86 AR_WOW_BEACON_FAIL))
87#define AR_WOW_CLEAR_EVENTS(x) (x & ~(AR_WOW_PATTERN_EN(0xff) | \
88 AR_WOW_MAGIC_EN | \
89 AR_WOW_MAC_INTR_EN | \
90 AR_WOW_BEACON_FAIL | \
91 AR_WOW_KEEP_ALIVE_FAIL))
92
93#define AR_WOW_AIFS_CNT(x) (x & 0xff)
94#define AR_WOW_SLOT_CNT(x) ((x & 0xff) << 8)
95#define AR_WOW_KEEP_ALIVE_CNT(x) ((x & 0xff) << 16)
96
97#define AR_WOW_BEACON_FAIL_EN 0x00000001
98#define AR_WOW_BEACON_TIMO 0x40000000
99#define AR_WOW_KEEP_ALIVE_NEVER 0xffffffff
100#define AR_WOW_KEEP_ALIVE_AUTO_DIS 0x00000001
101#define AR_WOW_KEEP_ALIVE_FAIL_DIS 0x00000002
102#define AR_WOW_KEEP_ALIVE_DELAY_VALUE 0x000003e8 /* 1 msec */
103#define AR_WOW_BMISSTHRESHOLD 0x20
104#define AR_WOW_PAT_END_OF_PKT(x) (x & 0xf)
105#define AR_WOW_PAT_OFF_MATCH(x) ((x & 0xf) << 8)
106#define AR_WOW_PAT_BACKOFF 0x00000004
107#define AR_WOW_CNT_AIFS_CNT 0x00000022
108#define AR_WOW_CNT_SLOT_CNT 0x00000009
109#define AR_WOW_CNT_KA_CNT 0x00000008
110
111#define AR_WOW_TRANSMIT_BUFFER 0xe000
112#define AR_WOW_TXBUF(i) (AR_WOW_TRANSMIT_BUFFER + ((i) << 2))
113#define AR_WOW_KA_DESC_WORD2 0xe000
114#define AR_WOW_TB_PATTERN(i) (0xe100 + (i << 8))
115#define AR_WOW_TB_MASK(i) (0xec00 + (i << 5))
116#define AR_WOW_PATTERN_SUPPORTED_LEGACY 0xff
117#define AR_WOW_PATTERN_SUPPORTED 0xffff
118#define AR_WOW_LENGTH_MAX 0xff
119#define AR_WOW_LEN1_SHIFT(_i) ((0x3 - ((_i) & 0x3)) << 0x3)
120#define AR_WOW_LENGTH1_MASK(_i) (AR_WOW_LENGTH_MAX << AR_WOW_LEN1_SHIFT(_i))
121#define AR_WOW_LEN2_SHIFT(_i) ((0x7 - ((_i) & 0x7)) << 0x3)
122#define AR_WOW_LENGTH2_MASK(_i) (AR_WOW_LENGTH_MAX << AR_WOW_LEN2_SHIFT(_i))
123#define AR_WOW_LEN3_SHIFT(_i) ((0xb - ((_i) & 0xb)) << 0x3)
124#define AR_WOW_LENGTH3_MASK(_i) (AR_WOW_LENGTH_MAX << AR_WOW_LEN3_SHIFT(_i))
125#define AR_WOW_LEN4_SHIFT(_i) ((0xf - ((_i) & 0xf)) << 0x3)
126#define AR_WOW_LENGTH4_MASK(_i) (AR_WOW_LENGTH_MAX << AR_WOW_LEN4_SHIFT(_i))
127
128#endif /* REG_WOW_H */
diff --git a/drivers/net/wireless/ath/ath9k/wow.c b/drivers/net/wireless/ath/ath9k/wow.c
index 5f30e580d942..8d0b1730a9d5 100644
--- a/drivers/net/wireless/ath/ath9k/wow.c
+++ b/drivers/net/wireless/ath/ath9k/wow.c
@@ -16,36 +16,43 @@
16 16
17#include "ath9k.h" 17#include "ath9k.h"
18 18
19static const struct wiphy_wowlan_support ath9k_wowlan_support = { 19static const struct wiphy_wowlan_support ath9k_wowlan_support_legacy = {
20 .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT, 20 .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT,
21 .n_patterns = MAX_NUM_USER_PATTERN, 21 .n_patterns = MAX_NUM_USER_PATTERN,
22 .pattern_min_len = 1, 22 .pattern_min_len = 1,
23 .pattern_max_len = MAX_PATTERN_SIZE, 23 .pattern_max_len = MAX_PATTERN_SIZE,
24}; 24};
25 25
26static void ath9k_wow_map_triggers(struct ath_softc *sc, 26static const struct wiphy_wowlan_support ath9k_wowlan_support = {
27 struct cfg80211_wowlan *wowlan, 27 .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT,
28 u32 *wow_triggers) 28 .n_patterns = MAX_NUM_PATTERN - 2,
29 .pattern_min_len = 1,
30 .pattern_max_len = MAX_PATTERN_SIZE,
31};
32
33static u8 ath9k_wow_map_triggers(struct ath_softc *sc,
34 struct cfg80211_wowlan *wowlan)
29{ 35{
36 u8 wow_triggers = 0;
37
30 if (wowlan->disconnect) 38 if (wowlan->disconnect)
31 *wow_triggers |= AH_WOW_LINK_CHANGE | 39 wow_triggers |= AH_WOW_LINK_CHANGE |
32 AH_WOW_BEACON_MISS; 40 AH_WOW_BEACON_MISS;
33 if (wowlan->magic_pkt) 41 if (wowlan->magic_pkt)
34 *wow_triggers |= AH_WOW_MAGIC_PATTERN_EN; 42 wow_triggers |= AH_WOW_MAGIC_PATTERN_EN;
35 43
36 if (wowlan->n_patterns) 44 if (wowlan->n_patterns)
37 *wow_triggers |= AH_WOW_USER_PATTERN_EN; 45 wow_triggers |= AH_WOW_USER_PATTERN_EN;
38
39 sc->wow_enabled = *wow_triggers;
40 46
47 return wow_triggers;
41} 48}
42 49
43static void ath9k_wow_add_disassoc_deauth_pattern(struct ath_softc *sc) 50static int ath9k_wow_add_disassoc_deauth_pattern(struct ath_softc *sc)
44{ 51{
45 struct ath_hw *ah = sc->sc_ah; 52 struct ath_hw *ah = sc->sc_ah;
46 struct ath_common *common = ath9k_hw_common(ah); 53 struct ath_common *common = ath9k_hw_common(ah);
47 int pattern_count = 0; 54 int pattern_count = 0;
48 int i, byte_cnt; 55 int ret, i, byte_cnt = 0;
49 u8 dis_deauth_pattern[MAX_PATTERN_SIZE]; 56 u8 dis_deauth_pattern[MAX_PATTERN_SIZE];
50 u8 dis_deauth_mask[MAX_PATTERN_SIZE]; 57 u8 dis_deauth_mask[MAX_PATTERN_SIZE];
51 58
@@ -80,12 +87,7 @@ static void ath9k_wow_add_disassoc_deauth_pattern(struct ath_softc *sc)
80 * | x:x:x:x:x:x -- 22 bytes 87 * | x:x:x:x:x:x -- 22 bytes
81 */ 88 */
82 89
83 /* Create Disassociate Pattern first */
84
85 byte_cnt = 0;
86
87 /* Fill out the mask with all FF's */ 90 /* Fill out the mask with all FF's */
88
89 for (i = 0; i < MAX_PATTERN_MASK_SIZE; i++) 91 for (i = 0; i < MAX_PATTERN_MASK_SIZE; i++)
90 dis_deauth_mask[i] = 0xff; 92 dis_deauth_mask[i] = 0xff;
91 93
@@ -108,19 +110,17 @@ static void ath9k_wow_add_disassoc_deauth_pattern(struct ath_softc *sc)
108 byte_cnt += 6; 110 byte_cnt += 6;
109 111
110 /* copy the bssid, its same as the source mac address */ 112 /* copy the bssid, its same as the source mac address */
111
112 memcpy((dis_deauth_pattern + byte_cnt), common->curbssid, ETH_ALEN); 113 memcpy((dis_deauth_pattern + byte_cnt), common->curbssid, ETH_ALEN);
113 114
114 /* Create Disassociate pattern mask */ 115 /* Create Disassociate pattern mask */
115
116 dis_deauth_mask[0] = 0xfe; 116 dis_deauth_mask[0] = 0xfe;
117 dis_deauth_mask[1] = 0x03; 117 dis_deauth_mask[1] = 0x03;
118 dis_deauth_mask[2] = 0xc0; 118 dis_deauth_mask[2] = 0xc0;
119 119
120 ath_dbg(common, WOW, "Adding disassoc/deauth patterns for WoW\n"); 120 ret = ath9k_hw_wow_apply_pattern(ah, dis_deauth_pattern, dis_deauth_mask,
121 121 pattern_count, byte_cnt);
122 ath9k_hw_wow_apply_pattern(ah, dis_deauth_pattern, dis_deauth_mask, 122 if (ret)
123 pattern_count, byte_cnt); 123 goto exit;
124 124
125 pattern_count++; 125 pattern_count++;
126 /* 126 /*
@@ -129,59 +129,39 @@ static void ath9k_wow_add_disassoc_deauth_pattern(struct ath_softc *sc)
129 */ 129 */
130 dis_deauth_pattern[0] = 0xC0; 130 dis_deauth_pattern[0] = 0xC0;
131 131
132 ath9k_hw_wow_apply_pattern(ah, dis_deauth_pattern, dis_deauth_mask, 132 ret = ath9k_hw_wow_apply_pattern(ah, dis_deauth_pattern, dis_deauth_mask,
133 pattern_count, byte_cnt); 133 pattern_count, byte_cnt);
134 134exit:
135 return ret;
135} 136}
136 137
137static void ath9k_wow_add_pattern(struct ath_softc *sc, 138static int ath9k_wow_add_pattern(struct ath_softc *sc,
138 struct cfg80211_wowlan *wowlan) 139 struct cfg80211_wowlan *wowlan)
139{ 140{
140 struct ath_hw *ah = sc->sc_ah; 141 struct ath_hw *ah = sc->sc_ah;
141 struct ath9k_wow_pattern *wow_pattern = NULL;
142 struct cfg80211_pkt_pattern *patterns = wowlan->patterns; 142 struct cfg80211_pkt_pattern *patterns = wowlan->patterns;
143 int mask_len; 143 u8 wow_pattern[MAX_PATTERN_SIZE];
144 u8 wow_mask[MAX_PATTERN_SIZE];
145 int mask_len, ret = 0;
144 s8 i = 0; 146 s8 i = 0;
145 147
146 if (!wowlan->n_patterns)
147 return;
148
149 /*
150 * Add the new user configured patterns
151 */
152 for (i = 0; i < wowlan->n_patterns; i++) { 148 for (i = 0; i < wowlan->n_patterns; i++) {
153 149 mask_len = DIV_ROUND_UP(patterns[i].pattern_len, 8);
154 wow_pattern = kzalloc(sizeof(*wow_pattern), GFP_KERNEL); 150 memset(wow_pattern, 0, MAX_PATTERN_SIZE);
155 151 memset(wow_mask, 0, MAX_PATTERN_SIZE);
156 if (!wow_pattern) 152 memcpy(wow_pattern, patterns[i].pattern, patterns[i].pattern_len);
157 return; 153 memcpy(wow_mask, patterns[i].mask, mask_len);
158 154
159 /* 155 ret = ath9k_hw_wow_apply_pattern(ah,
160 * TODO: convert the generic user space pattern to 156 wow_pattern,
161 * appropriate chip specific/802.11 pattern. 157 wow_mask,
162 */ 158 i + 2,
163 159 patterns[i].pattern_len);
164 mask_len = DIV_ROUND_UP(wowlan->patterns[i].pattern_len, 8); 160 if (ret)
165 memset(wow_pattern->pattern_bytes, 0, MAX_PATTERN_SIZE); 161 break;
166 memset(wow_pattern->mask_bytes, 0, MAX_PATTERN_SIZE);
167 memcpy(wow_pattern->pattern_bytes, patterns[i].pattern,
168 patterns[i].pattern_len);
169 memcpy(wow_pattern->mask_bytes, patterns[i].mask, mask_len);
170 wow_pattern->pattern_len = patterns[i].pattern_len;
171
172 /*
173 * just need to take care of deauth and disssoc pattern,
174 * make sure we don't overwrite them.
175 */
176
177 ath9k_hw_wow_apply_pattern(ah, wow_pattern->pattern_bytes,
178 wow_pattern->mask_bytes,
179 i + 2,
180 wow_pattern->pattern_len);
181 kfree(wow_pattern);
182
183 } 162 }
184 163
164 return ret;
185} 165}
186 166
187int ath9k_suspend(struct ieee80211_hw *hw, 167int ath9k_suspend(struct ieee80211_hw *hw,
@@ -190,41 +170,39 @@ int ath9k_suspend(struct ieee80211_hw *hw,
190 struct ath_softc *sc = hw->priv; 170 struct ath_softc *sc = hw->priv;
191 struct ath_hw *ah = sc->sc_ah; 171 struct ath_hw *ah = sc->sc_ah;
192 struct ath_common *common = ath9k_hw_common(ah); 172 struct ath_common *common = ath9k_hw_common(ah);
193 u32 wow_triggers_enabled = 0; 173 u8 triggers;
194 int ret = 0; 174 int ret = 0;
195 175
196 ath9k_deinit_channel_context(sc); 176 ath9k_deinit_channel_context(sc);
197 177
198 mutex_lock(&sc->mutex); 178 mutex_lock(&sc->mutex);
199 179
200 ath_cancel_work(sc);
201 ath_stop_ani(sc);
202
203 if (test_bit(ATH_OP_INVALID, &common->op_flags)) { 180 if (test_bit(ATH_OP_INVALID, &common->op_flags)) {
204 ath_dbg(common, ANY, "Device not present\n"); 181 ath_err(common, "Device not present\n");
205 ret = -EINVAL; 182 ret = -ENODEV;
206 goto fail_wow; 183 goto fail_wow;
207 } 184 }
208 185
209 if (WARN_ON(!wowlan)) { 186 if (WARN_ON(!wowlan)) {
210 ath_dbg(common, WOW, "None of the WoW triggers enabled\n"); 187 ath_err(common, "None of the WoW triggers enabled\n");
211 ret = -EINVAL; 188 ret = -EINVAL;
212 goto fail_wow; 189 goto fail_wow;
213 } 190 }
214 191
215 if (!device_can_wakeup(sc->dev)) { 192 if (sc->cur_chan->nvifs > 1) {
216 ath_dbg(common, WOW, "device_can_wakeup failed, WoW is not enabled\n"); 193 ath_dbg(common, WOW, "WoW for multivif is not yet supported\n");
217 ret = 1; 194 ret = 1;
218 goto fail_wow; 195 goto fail_wow;
219 } 196 }
220 197
221 /* 198 if (ath9k_is_chanctx_enabled()) {
222 * none of the sta vifs are associated 199 if (test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags)) {
223 * and we are not currently handling multivif 200 ath_dbg(common, WOW,
224 * cases, for instance we have to seperately 201 "Multi-channel WOW is not supported\n");
225 * configure 'keep alive frame' for each 202 ret = 1;
226 * STA. 203 goto fail_wow;
227 */ 204 }
205 }
228 206
229 if (!test_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags)) { 207 if (!test_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags)) {
230 ath_dbg(common, WOW, "None of the STA vifs are associated\n"); 208 ath_dbg(common, WOW, "None of the STA vifs are associated\n");
@@ -232,16 +210,15 @@ int ath9k_suspend(struct ieee80211_hw *hw,
232 goto fail_wow; 210 goto fail_wow;
233 } 211 }
234 212
235 if (sc->cur_chan->nvifs > 1) { 213 triggers = ath9k_wow_map_triggers(sc, wowlan);
236 ath_dbg(common, WOW, "WoW for multivif is not yet supported\n"); 214 if (!triggers) {
215 ath_dbg(common, WOW, "No valid WoW triggers\n");
237 ret = 1; 216 ret = 1;
238 goto fail_wow; 217 goto fail_wow;
239 } 218 }
240 219
241 ath9k_wow_map_triggers(sc, wowlan, &wow_triggers_enabled); 220 ath_cancel_work(sc);
242 221 ath_stop_ani(sc);
243 ath_dbg(common, WOW, "WoW triggers enabled 0x%x\n",
244 wow_triggers_enabled);
245 222
246 ath9k_ps_wakeup(sc); 223 ath9k_ps_wakeup(sc);
247 224
@@ -251,10 +228,21 @@ int ath9k_suspend(struct ieee80211_hw *hw,
251 * Enable wake up on recieving disassoc/deauth 228 * Enable wake up on recieving disassoc/deauth
252 * frame by default. 229 * frame by default.
253 */ 230 */
254 ath9k_wow_add_disassoc_deauth_pattern(sc); 231 ret = ath9k_wow_add_disassoc_deauth_pattern(sc);
232 if (ret) {
233 ath_err(common,
234 "Unable to add disassoc/deauth pattern: %d\n", ret);
235 goto fail_wow;
236 }
255 237
256 if (wow_triggers_enabled & AH_WOW_USER_PATTERN_EN) 238 if (triggers & AH_WOW_USER_PATTERN_EN) {
257 ath9k_wow_add_pattern(sc, wowlan); 239 ret = ath9k_wow_add_pattern(sc, wowlan);
240 if (ret) {
241 ath_err(common,
242 "Unable to add user pattern: %d\n", ret);
243 goto fail_wow;
244 }
245 }
258 246
259 spin_lock_bh(&sc->sc_pcu_lock); 247 spin_lock_bh(&sc->sc_pcu_lock);
260 /* 248 /*
@@ -278,12 +266,12 @@ int ath9k_suspend(struct ieee80211_hw *hw,
278 synchronize_irq(sc->irq); 266 synchronize_irq(sc->irq);
279 tasklet_kill(&sc->intr_tq); 267 tasklet_kill(&sc->intr_tq);
280 268
281 ath9k_hw_wow_enable(ah, wow_triggers_enabled); 269 ath9k_hw_wow_enable(ah, triggers);
282 270
283 ath9k_ps_restore(sc); 271 ath9k_ps_restore(sc);
284 ath_dbg(common, ANY, "WoW enabled in ath9k\n"); 272 ath_dbg(common, WOW, "Suspend with WoW triggers: 0x%x\n", triggers);
285 atomic_inc(&sc->wow_sleep_proc_intr);
286 273
274 set_bit(ATH_OP_WOW_ENABLED, &common->op_flags);
287fail_wow: 275fail_wow:
288 mutex_unlock(&sc->mutex); 276 mutex_unlock(&sc->mutex);
289 return ret; 277 return ret;
@@ -294,7 +282,7 @@ int ath9k_resume(struct ieee80211_hw *hw)
294 struct ath_softc *sc = hw->priv; 282 struct ath_softc *sc = hw->priv;
295 struct ath_hw *ah = sc->sc_ah; 283 struct ath_hw *ah = sc->sc_ah;
296 struct ath_common *common = ath9k_hw_common(ah); 284 struct ath_common *common = ath9k_hw_common(ah);
297 u32 wow_status; 285 u8 status;
298 286
299 mutex_lock(&sc->mutex); 287 mutex_lock(&sc->mutex);
300 288
@@ -309,29 +297,14 @@ int ath9k_resume(struct ieee80211_hw *hw)
309 297
310 spin_unlock_bh(&sc->sc_pcu_lock); 298 spin_unlock_bh(&sc->sc_pcu_lock);
311 299
312 wow_status = ath9k_hw_wow_wakeup(ah); 300 status = ath9k_hw_wow_wakeup(ah);
313 301 ath_dbg(common, WOW, "Resume with WoW status: 0x%x\n", status);
314 if (atomic_read(&sc->wow_got_bmiss_intr) == 0) {
315 /*
316 * some devices may not pick beacon miss
317 * as the reason they woke up so we add
318 * that here for that shortcoming.
319 */
320 wow_status |= AH_WOW_BEACON_MISS;
321 atomic_dec(&sc->wow_got_bmiss_intr);
322 ath_dbg(common, ANY, "Beacon miss interrupt picked up during WoW sleep\n");
323 }
324
325 atomic_dec(&sc->wow_sleep_proc_intr);
326
327 if (wow_status) {
328 ath_dbg(common, ANY, "Waking up due to WoW triggers %s with WoW status = %x\n",
329 ath9k_hw_wow_event_to_string(wow_status), wow_status);
330 }
331 302
332 ath_restart_work(sc); 303 ath_restart_work(sc);
333 ath9k_start_btcoex(sc); 304 ath9k_start_btcoex(sc);
334 305
306 clear_bit(ATH_OP_WOW_ENABLED, &common->op_flags);
307
335 ath9k_ps_restore(sc); 308 ath9k_ps_restore(sc);
336 mutex_unlock(&sc->mutex); 309 mutex_unlock(&sc->mutex);
337 310
@@ -341,22 +314,35 @@ int ath9k_resume(struct ieee80211_hw *hw)
341void ath9k_set_wakeup(struct ieee80211_hw *hw, bool enabled) 314void ath9k_set_wakeup(struct ieee80211_hw *hw, bool enabled)
342{ 315{
343 struct ath_softc *sc = hw->priv; 316 struct ath_softc *sc = hw->priv;
317 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
344 318
345 mutex_lock(&sc->mutex); 319 mutex_lock(&sc->mutex);
346 device_init_wakeup(sc->dev, 1);
347 device_set_wakeup_enable(sc->dev, enabled); 320 device_set_wakeup_enable(sc->dev, enabled);
348 mutex_unlock(&sc->mutex); 321 mutex_unlock(&sc->mutex);
322
323 ath_dbg(common, WOW, "WoW wakeup source is %s\n",
324 (enabled) ? "enabled" : "disabled");
349} 325}
350 326
351void ath9k_init_wow(struct ieee80211_hw *hw) 327void ath9k_init_wow(struct ieee80211_hw *hw)
352{ 328{
353 struct ath_softc *sc = hw->priv; 329 struct ath_softc *sc = hw->priv;
330 struct ath_hw *ah = sc->sc_ah;
331
332 if ((sc->driver_data & ATH9K_PCI_WOW) || sc->force_wow) {
333 if (AR_SREV_9462_20_OR_LATER(ah) || AR_SREV_9565_11_OR_LATER(ah))
334 hw->wiphy->wowlan = &ath9k_wowlan_support;
335 else
336 hw->wiphy->wowlan = &ath9k_wowlan_support_legacy;
354 337
355 if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_WOW_DEVICE_CAPABLE) && 338 device_init_wakeup(sc->dev, 1);
356 (sc->driver_data & ATH9K_PCI_WOW) && 339 }
357 device_can_wakeup(sc->dev)) 340}
358 hw->wiphy->wowlan = &ath9k_wowlan_support; 341
342void ath9k_deinit_wow(struct ieee80211_hw *hw)
343{
344 struct ath_softc *sc = hw->priv;
359 345
360 atomic_set(&sc->wow_sleep_proc_intr, -1); 346 if ((sc->driver_data & ATH9K_PCI_WOW) || sc->force_wow)
361 atomic_set(&sc->wow_got_bmiss_intr, -1); 347 device_init_wakeup(sc->dev, 0);
362} 348}