diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k')
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) | |||
1203 | static void ar9003_hw_manual_peak_cal(struct ath_hw *ah, u8 chain, bool is_2g) | 1203 | static 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 | ||
1612 | skip_tx_iqcal: | 1641 | skip_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 | ||
22 | const 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 | } | ||
35 | EXPORT_SYMBOL(ath9k_hw_wow_event_to_string); | ||
36 | |||
37 | static void ath9k_hw_set_powermode_wow_sleep(struct ath_hw *ah) | 23 | static 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 | ||
106 | void ath9k_hw_wow_apply_pattern(struct ath_hw *ah, u8 *user_pattern, | 105 | int 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 | } |
172 | EXPORT_SYMBOL(ath9k_hw_wow_apply_pattern); | 165 | EXPORT_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 | } |
240 | EXPORT_SYMBOL(ath9k_hw_wow_wakeup); | 233 | EXPORT_SYMBOL(ath9k_hw_wow_wakeup); |
241 | 234 | ||
242 | void ath9k_hw_wow_enable(struct ath_hw *ah, u32 pattern_enable) | 235 | static 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 | | 255 | void 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 | } |
422 | EXPORT_SYMBOL(ath9k_hw_wow_enable); | 417 | EXPORT_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 | ||
35 | extern struct ieee80211_ops ath9k_ops; | 35 | extern struct ieee80211_ops ath9k_ops; |
36 | extern int ath9k_modparam_nohwcrypt; | 36 | extern int ath9k_modparam_nohwcrypt; |
37 | extern int led_blink; | 37 | extern int ath9k_led_blink; |
38 | extern bool is_ath9k_unloaded; | 38 | extern bool is_ath9k_unloaded; |
39 | extern int ath9k_use_chanctx; | 39 | extern 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 | ||
833 | struct 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 |
840 | void ath9k_init_wow(struct ieee80211_hw *hw); | 834 | void ath9k_init_wow(struct ieee80211_hw *hw); |
835 | void ath9k_deinit_wow(struct ieee80211_hw *hw); | ||
841 | int ath9k_suspend(struct ieee80211_hw *hw, | 836 | int ath9k_suspend(struct ieee80211_hw *hw, |
842 | struct cfg80211_wowlan *wowlan); | 837 | struct cfg80211_wowlan *wowlan); |
843 | int ath9k_resume(struct ieee80211_hw *hw); | 838 | int ath9k_resume(struct ieee80211_hw *hw); |
@@ -846,6 +841,9 @@ void ath9k_set_wakeup(struct ieee80211_hw *hw, bool enabled); | |||
846 | static inline void ath9k_init_wow(struct ieee80211_hw *hw) | 841 | static inline void ath9k_init_wow(struct ieee80211_hw *hw) |
847 | { | 842 | { |
848 | } | 843 | } |
844 | static inline void ath9k_deinit_wow(struct ieee80211_hw *hw) | ||
845 | { | ||
846 | } | ||
849 | static inline int ath9k_suspend(struct ieee80211_hw *hw, | 847 | static 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 | ||
583 | void ath9k_cmn_spectral_deinit_debug(struct ath_spec_scan_priv *spec_priv) | 583 | void 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 | |||
1048 | static 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 | |||
1072 | static 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 | |||
1099 | static 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 | |||
1046 | static ssize_t read_file_tpc(struct file *file, char __user *user_buf, | 1109 | static 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 @@ | |||
45 | extern struct ieee80211_ops ath9k_htc_ops; | 45 | extern struct ieee80211_ops ath9k_htc_ops; |
46 | extern int htc_modparam_nohwcrypt; | 46 | extern int htc_modparam_nohwcrypt; |
47 | #ifdef CONFIG_MAC80211_LEDS | 47 | #ifdef CONFIG_MAC80211_LEDS |
48 | extern int led_blink; | 48 | extern int ath9k_htc_led_blink; |
49 | #endif | 49 | #endif |
50 | 50 | ||
51 | enum htc_phymode { | 51 | enum 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); | |||
39 | MODULE_PARM_DESC(ps_enable, "Enable WLAN PowerSave"); | 39 | MODULE_PARM_DESC(ps_enable, "Enable WLAN PowerSave"); |
40 | 40 | ||
41 | #ifdef CONFIG_MAC80211_LEDS | 41 | #ifdef CONFIG_MAC80211_LEDS |
42 | int led_blink = 1; | 42 | int ath9k_htc_led_blink = 1; |
43 | module_param_named(blink, led_blink, int, 0444); | 43 | module_param_named(blink, ath9k_htc_led_blink, int, 0444); |
44 | MODULE_PARM_DESC(blink, "Enable LED blink on activity"); | 44 | MODULE_PARM_DESC(blink, "Enable LED blink on activity"); |
45 | 45 | ||
46 | static const struct ieee80211_tpt_blink ath9k_htc_tpt_blink[] = { | 46 | static 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 | ||
274 | struct ath9k_hw_wow { | ||
275 | u32 wow_event_mask; | ||
276 | u32 wow_event_mask2; | ||
277 | u8 max_patterns; | ||
278 | }; | ||
279 | |||
275 | struct ath9k_hw_capabilities { | 280 | struct 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 |
1151 | const char *ath9k_hw_wow_event_to_string(u32 wow_event); | 1156 | int ath9k_hw_wow_apply_pattern(struct ath_hw *ah, u8 *user_pattern, |
1152 | void 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); | ||
1155 | u32 ath9k_hw_wow_wakeup(struct ath_hw *ah); | 1159 | u32 ath9k_hw_wow_wakeup(struct ath_hw *ah); |
1156 | void ath9k_hw_wow_enable(struct ath_hw *ah, u32 pattern_enable); | 1160 | void ath9k_hw_wow_enable(struct ath_hw *ah, u32 pattern_enable); |
1157 | #else | 1161 | #else |
1158 | static inline const char *ath9k_hw_wow_event_to_string(u32 wow_event) | 1162 | static 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, |
1162 | static 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 | } |
1169 | static inline u32 ath9k_hw_wow_wakeup(struct ath_hw *ah) | 1170 | static 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; | |||
45 | module_param_named(nohwcrypt, ath9k_modparam_nohwcrypt, int, 0444); | 45 | module_param_named(nohwcrypt, ath9k_modparam_nohwcrypt, int, 0444); |
46 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption"); | 46 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption"); |
47 | 47 | ||
48 | int led_blink; | 48 | int ath9k_led_blink; |
49 | module_param_named(blink, led_blink, int, 0444); | 49 | module_param_named(blink, ath9k_led_blink, int, 0444); |
50 | MODULE_PARM_DESC(blink, "Enable LED blink on activity"); | 50 | MODULE_PARM_DESC(blink, "Enable LED blink on activity"); |
51 | 51 | ||
52 | static int ath9k_btcoex_enable; | 52 | static 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 | ||
19 | static const struct wiphy_wowlan_support ath9k_wowlan_support = { | 19 | static 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 | ||
26 | static void ath9k_wow_map_triggers(struct ath_softc *sc, | 26 | static 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 | |||
33 | static 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 | ||
43 | static void ath9k_wow_add_disassoc_deauth_pattern(struct ath_softc *sc) | 50 | static 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 | 134 | exit: | |
135 | return ret; | ||
135 | } | 136 | } |
136 | 137 | ||
137 | static void ath9k_wow_add_pattern(struct ath_softc *sc, | 138 | static 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 | ||
187 | int ath9k_suspend(struct ieee80211_hw *hw, | 167 | int 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); | ||
287 | fail_wow: | 275 | fail_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) | |||
341 | void ath9k_set_wakeup(struct ieee80211_hw *hw, bool enabled) | 314 | void 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 | ||
351 | void ath9k_init_wow(struct ieee80211_hw *hw) | 327 | void 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 | |
342 | void 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 | } |