diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/hw.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hw.c | 150 |
1 files changed, 42 insertions, 108 deletions
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index ae371448b5a..1a27f39c1ad 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -52,28 +52,6 @@ module_exit(ath9k_exit); | |||
52 | /* Helper Functions */ | 52 | /* Helper Functions */ |
53 | /********************/ | 53 | /********************/ |
54 | 54 | ||
55 | static u32 ath9k_hw_mac_usec(struct ath_hw *ah, u32 clks) | ||
56 | { | ||
57 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; | ||
58 | |||
59 | if (!ah->curchan) /* should really check for CCK instead */ | ||
60 | return clks / ATH9K_CLOCK_RATE_CCK; | ||
61 | if (conf->channel->band == IEEE80211_BAND_2GHZ) | ||
62 | return clks / ATH9K_CLOCK_RATE_2GHZ_OFDM; | ||
63 | |||
64 | return clks / ATH9K_CLOCK_RATE_5GHZ_OFDM; | ||
65 | } | ||
66 | |||
67 | static u32 ath9k_hw_mac_to_usec(struct ath_hw *ah, u32 clks) | ||
68 | { | ||
69 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; | ||
70 | |||
71 | if (conf_is_ht40(conf)) | ||
72 | return ath9k_hw_mac_usec(ah, clks) / 2; | ||
73 | else | ||
74 | return ath9k_hw_mac_usec(ah, clks); | ||
75 | } | ||
76 | |||
77 | static u32 ath9k_hw_mac_clks(struct ath_hw *ah, u32 usecs) | 55 | static u32 ath9k_hw_mac_clks(struct ath_hw *ah, u32 usecs) |
78 | { | 56 | { |
79 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; | 57 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; |
@@ -343,30 +321,6 @@ static bool ath9k_hw_chip_test(struct ath_hw *ah) | |||
343 | return true; | 321 | return true; |
344 | } | 322 | } |
345 | 323 | ||
346 | static const char *ath9k_hw_devname(u16 devid) | ||
347 | { | ||
348 | switch (devid) { | ||
349 | case AR5416_DEVID_PCI: | ||
350 | return "Atheros 5416"; | ||
351 | case AR5416_DEVID_PCIE: | ||
352 | return "Atheros 5418"; | ||
353 | case AR9160_DEVID_PCI: | ||
354 | return "Atheros 9160"; | ||
355 | case AR5416_AR9100_DEVID: | ||
356 | return "Atheros 9100"; | ||
357 | case AR9280_DEVID_PCI: | ||
358 | case AR9280_DEVID_PCIE: | ||
359 | return "Atheros 9280"; | ||
360 | case AR9285_DEVID_PCIE: | ||
361 | return "Atheros 9285"; | ||
362 | case AR5416_DEVID_AR9287_PCI: | ||
363 | case AR5416_DEVID_AR9287_PCIE: | ||
364 | return "Atheros 9287"; | ||
365 | } | ||
366 | |||
367 | return NULL; | ||
368 | } | ||
369 | |||
370 | static void ath9k_hw_init_config(struct ath_hw *ah) | 324 | static void ath9k_hw_init_config(struct ath_hw *ah) |
371 | { | 325 | { |
372 | int i; | 326 | int i; |
@@ -392,7 +346,7 @@ static void ath9k_hw_init_config(struct ath_hw *ah) | |||
392 | ah->config.spurchans[i][1] = AR_NO_SPUR; | 346 | ah->config.spurchans[i][1] = AR_NO_SPUR; |
393 | } | 347 | } |
394 | 348 | ||
395 | ah->config.intr_mitigation = true; | 349 | ah->config.rx_intr_mitigation = true; |
396 | 350 | ||
397 | /* | 351 | /* |
398 | * We need this for PCI devices only (Cardbus, PCI, miniPCI) | 352 | * We need this for PCI devices only (Cardbus, PCI, miniPCI) |
@@ -437,8 +391,6 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah) | |||
437 | ah->beacon_interval = 100; | 391 | ah->beacon_interval = 100; |
438 | ah->enable_32kHz_clock = DONT_USE_32KHZ; | 392 | ah->enable_32kHz_clock = DONT_USE_32KHZ; |
439 | ah->slottime = (u32) -1; | 393 | ah->slottime = (u32) -1; |
440 | ah->acktimeout = (u32) -1; | ||
441 | ah->ctstimeout = (u32) -1; | ||
442 | ah->globaltxtimeout = (u32) -1; | 394 | ah->globaltxtimeout = (u32) -1; |
443 | ah->power_mode = ATH9K_PM_UNDEFINED; | 395 | ah->power_mode = ATH9K_PM_UNDEFINED; |
444 | } | 396 | } |
@@ -1183,7 +1135,7 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, | |||
1183 | AR_IMR_RXORN | | 1135 | AR_IMR_RXORN | |
1184 | AR_IMR_BCNMISC; | 1136 | AR_IMR_BCNMISC; |
1185 | 1137 | ||
1186 | if (ah->config.intr_mitigation) | 1138 | if (ah->config.rx_intr_mitigation) |
1187 | ah->mask_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR; | 1139 | ah->mask_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR; |
1188 | else | 1140 | else |
1189 | ah->mask_reg |= AR_IMR_RXOK; | 1141 | ah->mask_reg |= AR_IMR_RXOK; |
@@ -1203,34 +1155,25 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, | |||
1203 | } | 1155 | } |
1204 | } | 1156 | } |
1205 | 1157 | ||
1206 | static bool ath9k_hw_set_ack_timeout(struct ath_hw *ah, u32 us) | 1158 | static void ath9k_hw_setslottime(struct ath_hw *ah, u32 us) |
1207 | { | 1159 | { |
1208 | if (us > ath9k_hw_mac_to_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) { | 1160 | u32 val = ath9k_hw_mac_to_clks(ah, us); |
1209 | ath_print(ath9k_hw_common(ah), ATH_DBG_RESET, | 1161 | val = min(val, (u32) 0xFFFF); |
1210 | "bad ack timeout %u\n", us); | 1162 | REG_WRITE(ah, AR_D_GBL_IFS_SLOT, val); |
1211 | ah->acktimeout = (u32) -1; | ||
1212 | return false; | ||
1213 | } else { | ||
1214 | REG_RMW_FIELD(ah, AR_TIME_OUT, | ||
1215 | AR_TIME_OUT_ACK, ath9k_hw_mac_to_clks(ah, us)); | ||
1216 | ah->acktimeout = us; | ||
1217 | return true; | ||
1218 | } | ||
1219 | } | 1163 | } |
1220 | 1164 | ||
1221 | static bool ath9k_hw_set_cts_timeout(struct ath_hw *ah, u32 us) | 1165 | static void ath9k_hw_set_ack_timeout(struct ath_hw *ah, u32 us) |
1222 | { | 1166 | { |
1223 | if (us > ath9k_hw_mac_to_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) { | 1167 | u32 val = ath9k_hw_mac_to_clks(ah, us); |
1224 | ath_print(ath9k_hw_common(ah), ATH_DBG_RESET, | 1168 | val = min(val, (u32) MS(0xFFFFFFFF, AR_TIME_OUT_ACK)); |
1225 | "bad cts timeout %u\n", us); | 1169 | REG_RMW_FIELD(ah, AR_TIME_OUT, AR_TIME_OUT_ACK, val); |
1226 | ah->ctstimeout = (u32) -1; | 1170 | } |
1227 | return false; | 1171 | |
1228 | } else { | 1172 | static void ath9k_hw_set_cts_timeout(struct ath_hw *ah, u32 us) |
1229 | REG_RMW_FIELD(ah, AR_TIME_OUT, | 1173 | { |
1230 | AR_TIME_OUT_CTS, ath9k_hw_mac_to_clks(ah, us)); | 1174 | u32 val = ath9k_hw_mac_to_clks(ah, us); |
1231 | ah->ctstimeout = us; | 1175 | val = min(val, (u32) MS(0xFFFFFFFF, AR_TIME_OUT_CTS)); |
1232 | return true; | 1176 | REG_RMW_FIELD(ah, AR_TIME_OUT, AR_TIME_OUT_CTS, val); |
1233 | } | ||
1234 | } | 1177 | } |
1235 | 1178 | ||
1236 | static bool ath9k_hw_set_global_txtimeout(struct ath_hw *ah, u32 tu) | 1179 | static bool ath9k_hw_set_global_txtimeout(struct ath_hw *ah, u32 tu) |
@@ -1247,31 +1190,37 @@ static bool ath9k_hw_set_global_txtimeout(struct ath_hw *ah, u32 tu) | |||
1247 | } | 1190 | } |
1248 | } | 1191 | } |
1249 | 1192 | ||
1250 | static void ath9k_hw_init_user_settings(struct ath_hw *ah) | 1193 | void ath9k_hw_init_global_settings(struct ath_hw *ah) |
1251 | { | 1194 | { |
1195 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; | ||
1196 | int acktimeout; | ||
1197 | int slottime; | ||
1198 | int sifstime; | ||
1199 | |||
1252 | ath_print(ath9k_hw_common(ah), ATH_DBG_RESET, "ah->misc_mode 0x%x\n", | 1200 | ath_print(ath9k_hw_common(ah), ATH_DBG_RESET, "ah->misc_mode 0x%x\n", |
1253 | ah->misc_mode); | 1201 | ah->misc_mode); |
1254 | 1202 | ||
1255 | if (ah->misc_mode != 0) | 1203 | if (ah->misc_mode != 0) |
1256 | REG_WRITE(ah, AR_PCU_MISC, | 1204 | REG_WRITE(ah, AR_PCU_MISC, |
1257 | REG_READ(ah, AR_PCU_MISC) | ah->misc_mode); | 1205 | REG_READ(ah, AR_PCU_MISC) | ah->misc_mode); |
1258 | if (ah->slottime != (u32) -1) | 1206 | |
1259 | ath9k_hw_setslottime(ah, ah->slottime); | 1207 | if (conf->channel && conf->channel->band == IEEE80211_BAND_5GHZ) |
1260 | if (ah->acktimeout != (u32) -1) | 1208 | sifstime = 16; |
1261 | ath9k_hw_set_ack_timeout(ah, ah->acktimeout); | 1209 | else |
1262 | if (ah->ctstimeout != (u32) -1) | 1210 | sifstime = 10; |
1263 | ath9k_hw_set_cts_timeout(ah, ah->ctstimeout); | 1211 | |
1212 | /* As defined by IEEE 802.11-2007 17.3.8.6 */ | ||
1213 | slottime = ah->slottime + 3 * ah->coverage_class; | ||
1214 | acktimeout = slottime + sifstime; | ||
1215 | ath9k_hw_setslottime(ah, slottime); | ||
1216 | ath9k_hw_set_ack_timeout(ah, acktimeout); | ||
1217 | ath9k_hw_set_cts_timeout(ah, acktimeout); | ||
1264 | if (ah->globaltxtimeout != (u32) -1) | 1218 | if (ah->globaltxtimeout != (u32) -1) |
1265 | ath9k_hw_set_global_txtimeout(ah, ah->globaltxtimeout); | 1219 | ath9k_hw_set_global_txtimeout(ah, ah->globaltxtimeout); |
1266 | } | 1220 | } |
1221 | EXPORT_SYMBOL(ath9k_hw_init_global_settings); | ||
1267 | 1222 | ||
1268 | const char *ath9k_hw_probe(u16 vendorid, u16 devid) | 1223 | void ath9k_hw_deinit(struct ath_hw *ah) |
1269 | { | ||
1270 | return vendorid == ATHEROS_VENDOR_ID ? | ||
1271 | ath9k_hw_devname(devid) : NULL; | ||
1272 | } | ||
1273 | |||
1274 | void ath9k_hw_detach(struct ath_hw *ah) | ||
1275 | { | 1224 | { |
1276 | struct ath_common *common = ath9k_hw_common(ah); | 1225 | struct ath_common *common = ath9k_hw_common(ah); |
1277 | 1226 | ||
@@ -1289,7 +1238,7 @@ free_hw: | |||
1289 | kfree(ah); | 1238 | kfree(ah); |
1290 | ah = NULL; | 1239 | ah = NULL; |
1291 | } | 1240 | } |
1292 | EXPORT_SYMBOL(ath9k_hw_detach); | 1241 | EXPORT_SYMBOL(ath9k_hw_deinit); |
1293 | 1242 | ||
1294 | /*******/ | 1243 | /*******/ |
1295 | /* INI */ | 1244 | /* INI */ |
@@ -2090,7 +2039,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
2090 | if (ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) | 2039 | if (ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) |
2091 | ath9k_enable_rfkill(ah); | 2040 | ath9k_enable_rfkill(ah); |
2092 | 2041 | ||
2093 | ath9k_hw_init_user_settings(ah); | 2042 | ath9k_hw_init_global_settings(ah); |
2094 | 2043 | ||
2095 | if (AR_SREV_9287_12_OR_LATER(ah)) { | 2044 | if (AR_SREV_9287_12_OR_LATER(ah)) { |
2096 | REG_WRITE(ah, AR_D_GBL_IFS_SIFS, | 2045 | REG_WRITE(ah, AR_D_GBL_IFS_SIFS, |
@@ -2120,7 +2069,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
2120 | 2069 | ||
2121 | REG_WRITE(ah, AR_OBS, 8); | 2070 | REG_WRITE(ah, AR_OBS, 8); |
2122 | 2071 | ||
2123 | if (ah->config.intr_mitigation) { | 2072 | if (ah->config.rx_intr_mitigation) { |
2124 | REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, 500); | 2073 | REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, 500); |
2125 | REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, 2000); | 2074 | REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, 2000); |
2126 | } | 2075 | } |
@@ -2780,7 +2729,7 @@ bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked) | |||
2780 | 2729 | ||
2781 | *masked = isr & ATH9K_INT_COMMON; | 2730 | *masked = isr & ATH9K_INT_COMMON; |
2782 | 2731 | ||
2783 | if (ah->config.intr_mitigation) { | 2732 | if (ah->config.rx_intr_mitigation) { |
2784 | if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM)) | 2733 | if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM)) |
2785 | *masked |= ATH9K_INT_RX; | 2734 | *masked |= ATH9K_INT_RX; |
2786 | } | 2735 | } |
@@ -2913,7 +2862,7 @@ enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints) | |||
2913 | } | 2862 | } |
2914 | if (ints & ATH9K_INT_RX) { | 2863 | if (ints & ATH9K_INT_RX) { |
2915 | mask |= AR_IMR_RXERR; | 2864 | mask |= AR_IMR_RXERR; |
2916 | if (ah->config.intr_mitigation) | 2865 | if (ah->config.rx_intr_mitigation) |
2917 | mask |= AR_IMR_RXMINTR | AR_IMR_RXINTM; | 2866 | mask |= AR_IMR_RXMINTR | AR_IMR_RXINTM; |
2918 | else | 2867 | else |
2919 | mask |= AR_IMR_RXOK | AR_IMR_RXDESC; | 2868 | mask |= AR_IMR_RXOK | AR_IMR_RXDESC; |
@@ -3687,21 +3636,6 @@ u64 ath9k_hw_extend_tsf(struct ath_hw *ah, u32 rstamp) | |||
3687 | } | 3636 | } |
3688 | EXPORT_SYMBOL(ath9k_hw_extend_tsf); | 3637 | EXPORT_SYMBOL(ath9k_hw_extend_tsf); |
3689 | 3638 | ||
3690 | bool ath9k_hw_setslottime(struct ath_hw *ah, u32 us) | ||
3691 | { | ||
3692 | if (us < ATH9K_SLOT_TIME_9 || us > ath9k_hw_mac_to_usec(ah, 0xffff)) { | ||
3693 | ath_print(ath9k_hw_common(ah), ATH_DBG_RESET, | ||
3694 | "bad slot time %u\n", us); | ||
3695 | ah->slottime = (u32) -1; | ||
3696 | return false; | ||
3697 | } else { | ||
3698 | REG_WRITE(ah, AR_D_GBL_IFS_SLOT, ath9k_hw_mac_to_clks(ah, us)); | ||
3699 | ah->slottime = us; | ||
3700 | return true; | ||
3701 | } | ||
3702 | } | ||
3703 | EXPORT_SYMBOL(ath9k_hw_setslottime); | ||
3704 | |||
3705 | void ath9k_hw_set11nmac2040(struct ath_hw *ah) | 3639 | void ath9k_hw_set11nmac2040(struct ath_hw *ah) |
3706 | { | 3640 | { |
3707 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; | 3641 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; |