diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath5k')
-rw-r--r-- | drivers/net/wireless/ath/ath5k/Kconfig | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/ath5k.h | 68 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/attach.c | 34 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/base.c | 267 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/base.h | 19 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/eeprom.c | 41 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/eeprom.h | 8 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/initvals.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/led.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/pcu.c | 292 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/phy.c | 235 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/qcu.c | 25 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/reg.h | 20 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/reset.c | 69 |
14 files changed, 607 insertions, 483 deletions
diff --git a/drivers/net/wireless/ath/ath5k/Kconfig b/drivers/net/wireless/ath/ath5k/Kconfig index 06d006675d7d..eb83b7b4d0e3 100644 --- a/drivers/net/wireless/ath/ath5k/Kconfig +++ b/drivers/net/wireless/ath/ath5k/Kconfig | |||
@@ -1,6 +1,6 @@ | |||
1 | config ATH5K | 1 | config ATH5K |
2 | tristate "Atheros 5xxx wireless cards support" | 2 | tristate "Atheros 5xxx wireless cards support" |
3 | depends on PCI && MAC80211 && WLAN_80211 | 3 | depends on PCI && MAC80211 |
4 | select MAC80211_LEDS | 4 | select MAC80211_LEDS |
5 | select LEDS_CLASS | 5 | select LEDS_CLASS |
6 | select NEW_LEDS | 6 | select NEW_LEDS |
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 6cd5efcec417..ac67f02e26d8 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h | |||
@@ -35,6 +35,7 @@ | |||
35 | * TODO: Make a more generic struct (eg. add more stuff to ath5k_capabilities) | 35 | * TODO: Make a more generic struct (eg. add more stuff to ath5k_capabilities) |
36 | * and clean up common bits, then introduce set/get functions in eeprom.c */ | 36 | * and clean up common bits, then introduce set/get functions in eeprom.c */ |
37 | #include "eeprom.h" | 37 | #include "eeprom.h" |
38 | #include "../ath.h" | ||
38 | 39 | ||
39 | /* PCI IDs */ | 40 | /* PCI IDs */ |
40 | #define PCI_DEVICE_ID_ATHEROS_AR5210 0x0007 /* AR5210 */ | 41 | #define PCI_DEVICE_ID_ATHEROS_AR5210 0x0007 /* AR5210 */ |
@@ -165,13 +166,6 @@ | |||
165 | #define AR5K_INI_VAL_XR 0 | 166 | #define AR5K_INI_VAL_XR 0 |
166 | #define AR5K_INI_VAL_MAX 5 | 167 | #define AR5K_INI_VAL_MAX 5 |
167 | 168 | ||
168 | /* Used for BSSID etc manipulation */ | ||
169 | #define AR5K_LOW_ID(_a)( \ | ||
170 | (_a)[0] | (_a)[1] << 8 | (_a)[2] << 16 | (_a)[3] << 24 \ | ||
171 | ) | ||
172 | |||
173 | #define AR5K_HIGH_ID(_a) ((_a)[4] | (_a)[5] << 8) | ||
174 | |||
175 | /* | 169 | /* |
176 | * Some tuneable values (these should be changeable by the user) | 170 | * Some tuneable values (these should be changeable by the user) |
177 | * TODO: Make use of them and add more options OR use debug/configfs | 171 | * TODO: Make use of them and add more options OR use debug/configfs |
@@ -204,6 +198,7 @@ | |||
204 | #define AR5K_TUNE_CWMAX_11B 1023 | 198 | #define AR5K_TUNE_CWMAX_11B 1023 |
205 | #define AR5K_TUNE_CWMAX_XR 7 | 199 | #define AR5K_TUNE_CWMAX_XR 7 |
206 | #define AR5K_TUNE_NOISE_FLOOR -72 | 200 | #define AR5K_TUNE_NOISE_FLOOR -72 |
201 | #define AR5K_TUNE_CCA_MAX_GOOD_VALUE -95 | ||
207 | #define AR5K_TUNE_MAX_TXPOWER 63 | 202 | #define AR5K_TUNE_MAX_TXPOWER 63 |
208 | #define AR5K_TUNE_DEFAULT_TXPOWER 25 | 203 | #define AR5K_TUNE_DEFAULT_TXPOWER 25 |
209 | #define AR5K_TUNE_TPC_TXPOWER false | 204 | #define AR5K_TUNE_TPC_TXPOWER false |
@@ -540,13 +535,12 @@ struct ath5k_txq_info { | |||
540 | u32 tqi_cbr_period; /* Constant bit rate period */ | 535 | u32 tqi_cbr_period; /* Constant bit rate period */ |
541 | u32 tqi_cbr_overflow_limit; | 536 | u32 tqi_cbr_overflow_limit; |
542 | u32 tqi_burst_time; | 537 | u32 tqi_burst_time; |
543 | u32 tqi_ready_time; /* Not used */ | 538 | u32 tqi_ready_time; /* Time queue waits after an event */ |
544 | }; | 539 | }; |
545 | 540 | ||
546 | /* | 541 | /* |
547 | * Transmit packet types. | 542 | * Transmit packet types. |
548 | * used on tx control descriptor | 543 | * used on tx control descriptor |
549 | * TODO: Use them inside base.c corectly | ||
550 | */ | 544 | */ |
551 | enum ath5k_pkt_type { | 545 | enum ath5k_pkt_type { |
552 | AR5K_PKT_TYPE_NORMAL = 0, | 546 | AR5K_PKT_TYPE_NORMAL = 0, |
@@ -1012,6 +1006,14 @@ struct ath5k_capabilities { | |||
1012 | } cap_queues; | 1006 | } cap_queues; |
1013 | }; | 1007 | }; |
1014 | 1008 | ||
1009 | /* size of noise floor history (keep it a power of two) */ | ||
1010 | #define ATH5K_NF_CAL_HIST_MAX 8 | ||
1011 | struct ath5k_nfcal_hist | ||
1012 | { | ||
1013 | s16 index; /* current index into nfval */ | ||
1014 | s16 nfval[ATH5K_NF_CAL_HIST_MAX]; /* last few noise floors */ | ||
1015 | }; | ||
1016 | |||
1015 | 1017 | ||
1016 | /***************************************\ | 1018 | /***************************************\ |
1017 | HARDWARE ABSTRACTION LAYER STRUCTURE | 1019 | HARDWARE ABSTRACTION LAYER STRUCTURE |
@@ -1027,6 +1029,7 @@ struct ath5k_capabilities { | |||
1027 | /* TODO: Clean up and merge with ath5k_softc */ | 1029 | /* TODO: Clean up and merge with ath5k_softc */ |
1028 | struct ath5k_hw { | 1030 | struct ath5k_hw { |
1029 | u32 ah_magic; | 1031 | u32 ah_magic; |
1032 | struct ath_common common; | ||
1030 | 1033 | ||
1031 | struct ath5k_softc *ah_sc; | 1034 | struct ath5k_softc *ah_sc; |
1032 | void __iomem *ah_iobase; | 1035 | void __iomem *ah_iobase; |
@@ -1059,6 +1062,7 @@ struct ath5k_hw { | |||
1059 | u32 ah_cw_min; | 1062 | u32 ah_cw_min; |
1060 | u32 ah_cw_max; | 1063 | u32 ah_cw_max; |
1061 | u32 ah_limit_tx_retries; | 1064 | u32 ah_limit_tx_retries; |
1065 | u8 ah_coverage_class; | ||
1062 | 1066 | ||
1063 | /* Antenna Control */ | 1067 | /* Antenna Control */ |
1064 | u32 ah_ant_ctl[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX]; | 1068 | u32 ah_ant_ctl[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX]; |
@@ -1067,14 +1071,6 @@ struct ath5k_hw { | |||
1067 | u8 ah_def_ant; | 1071 | u8 ah_def_ant; |
1068 | bool ah_software_retry; | 1072 | bool ah_software_retry; |
1069 | 1073 | ||
1070 | u8 ah_sta_id[ETH_ALEN]; | ||
1071 | |||
1072 | /* Current BSSID we are trying to assoc to / create. | ||
1073 | * This is passed by mac80211 on config_interface() and cached here for | ||
1074 | * use in resets */ | ||
1075 | u8 ah_bssid[ETH_ALEN]; | ||
1076 | u8 ah_bssid_mask[ETH_ALEN]; | ||
1077 | |||
1078 | int ah_gpio_npins; | 1074 | int ah_gpio_npins; |
1079 | 1075 | ||
1080 | struct ath5k_capabilities ah_capabilities; | 1076 | struct ath5k_capabilities ah_capabilities; |
@@ -1125,6 +1121,8 @@ struct ath5k_hw { | |||
1125 | struct ieee80211_channel r_last_channel; | 1121 | struct ieee80211_channel r_last_channel; |
1126 | } ah_radar; | 1122 | } ah_radar; |
1127 | 1123 | ||
1124 | struct ath5k_nfcal_hist ah_nfcal_hist; | ||
1125 | |||
1128 | /* noise floor from last periodic calibration */ | 1126 | /* noise floor from last periodic calibration */ |
1129 | s32 ah_noise_floor; | 1127 | s32 ah_noise_floor; |
1130 | 1128 | ||
@@ -1160,7 +1158,7 @@ struct ath5k_hw { | |||
1160 | */ | 1158 | */ |
1161 | 1159 | ||
1162 | /* Attach/Detach Functions */ | 1160 | /* Attach/Detach Functions */ |
1163 | extern struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc); | 1161 | extern int ath5k_hw_attach(struct ath5k_softc *sc); |
1164 | extern void ath5k_hw_detach(struct ath5k_hw *ah); | 1162 | extern void ath5k_hw_detach(struct ath5k_hw *ah); |
1165 | 1163 | ||
1166 | /* LED functions */ | 1164 | /* LED functions */ |
@@ -1202,11 +1200,11 @@ extern bool ath5k_eeprom_is_hb63(struct ath5k_hw *ah); | |||
1202 | 1200 | ||
1203 | /* Protocol Control Unit Functions */ | 1201 | /* Protocol Control Unit Functions */ |
1204 | extern int ath5k_hw_set_opmode(struct ath5k_hw *ah); | 1202 | extern int ath5k_hw_set_opmode(struct ath5k_hw *ah); |
1203 | extern void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class); | ||
1205 | /* BSSID Functions */ | 1204 | /* BSSID Functions */ |
1206 | extern void ath5k_hw_get_lladdr(struct ath5k_hw *ah, u8 *mac); | ||
1207 | extern int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac); | 1205 | extern int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac); |
1208 | extern void ath5k_hw_set_associd(struct ath5k_hw *ah, const u8 *bssid, u16 assoc_id); | 1206 | extern void ath5k_hw_set_associd(struct ath5k_hw *ah); |
1209 | extern int ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask); | 1207 | extern void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask); |
1210 | /* Receive start/stop functions */ | 1208 | /* Receive start/stop functions */ |
1211 | extern void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah); | 1209 | extern void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah); |
1212 | extern void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah); | 1210 | extern void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah); |
@@ -1234,6 +1232,10 @@ extern int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout); | |||
1234 | extern unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah); | 1232 | extern unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah); |
1235 | extern int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout); | 1233 | extern int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout); |
1236 | extern unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah); | 1234 | extern unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah); |
1235 | /* Clock rate related functions */ | ||
1236 | unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec); | ||
1237 | unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock); | ||
1238 | unsigned int ath5k_hw_get_clockrate(struct ath5k_hw *ah); | ||
1237 | /* Key table (WEP) functions */ | 1239 | /* Key table (WEP) functions */ |
1238 | extern int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry); | 1240 | extern int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry); |
1239 | extern int ath5k_hw_is_key_valid(struct ath5k_hw *ah, u16 entry); | 1241 | extern int ath5k_hw_is_key_valid(struct ath5k_hw *ah, u16 entry); |
@@ -1288,8 +1290,10 @@ extern int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah); | |||
1288 | extern bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags); | 1290 | extern bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags); |
1289 | extern int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel); | 1291 | extern int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel); |
1290 | /* PHY calibration */ | 1292 | /* PHY calibration */ |
1293 | void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah); | ||
1291 | extern int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, struct ieee80211_channel *channel); | 1294 | extern int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, struct ieee80211_channel *channel); |
1292 | extern int ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq); | 1295 | extern int ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq); |
1296 | extern s16 ath5k_hw_get_noise_floor(struct ath5k_hw *ah); | ||
1293 | extern void ath5k_hw_calibration_poll(struct ath5k_hw *ah); | 1297 | extern void ath5k_hw_calibration_poll(struct ath5k_hw *ah); |
1294 | /* Spur mitigation */ | 1298 | /* Spur mitigation */ |
1295 | bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, | 1299 | bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, |
@@ -1311,35 +1315,21 @@ extern int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower); | |||
1311 | * Functions used internaly | 1315 | * Functions used internaly |
1312 | */ | 1316 | */ |
1313 | 1317 | ||
1314 | /* | 1318 | static inline struct ath_common *ath5k_hw_common(struct ath5k_hw *ah) |
1315 | * Translate usec to hw clock units | ||
1316 | * TODO: Half/quarter rate | ||
1317 | */ | ||
1318 | static inline unsigned int ath5k_hw_htoclock(unsigned int usec, bool turbo) | ||
1319 | { | 1319 | { |
1320 | return turbo ? (usec * 80) : (usec * 40); | 1320 | return &ah->common; |
1321 | } | 1321 | } |
1322 | 1322 | ||
1323 | /* | 1323 | static inline struct ath_regulatory *ath5k_hw_regulatory(struct ath5k_hw *ah) |
1324 | * Translate hw clock units to usec | ||
1325 | * TODO: Half/quarter rate | ||
1326 | */ | ||
1327 | static inline unsigned int ath5k_hw_clocktoh(unsigned int clock, bool turbo) | ||
1328 | { | 1324 | { |
1329 | return turbo ? (clock / 80) : (clock / 40); | 1325 | return &(ath5k_hw_common(ah)->regulatory); |
1330 | } | 1326 | } |
1331 | 1327 | ||
1332 | /* | ||
1333 | * Read from a register | ||
1334 | */ | ||
1335 | static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg) | 1328 | static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg) |
1336 | { | 1329 | { |
1337 | return ioread32(ah->ah_iobase + reg); | 1330 | return ioread32(ah->ah_iobase + reg); |
1338 | } | 1331 | } |
1339 | 1332 | ||
1340 | /* | ||
1341 | * Write to a register | ||
1342 | */ | ||
1343 | static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg) | 1333 | static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg) |
1344 | { | 1334 | { |
1345 | iowrite32(val, ah->ah_iobase + reg); | 1335 | iowrite32(val, ah->ah_iobase + reg); |
diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c index 71a1bd254517..dc0786cc2639 100644 --- a/drivers/net/wireless/ath/ath5k/attach.c +++ b/drivers/net/wireless/ath/ath5k/attach.c | |||
@@ -21,6 +21,7 @@ | |||
21 | \*************************************/ | 21 | \*************************************/ |
22 | 22 | ||
23 | #include <linux/pci.h> | 23 | #include <linux/pci.h> |
24 | #include <linux/slab.h> | ||
24 | #include "ath5k.h" | 25 | #include "ath5k.h" |
25 | #include "reg.h" | 26 | #include "reg.h" |
26 | #include "debug.h" | 27 | #include "debug.h" |
@@ -101,25 +102,15 @@ static int ath5k_hw_post(struct ath5k_hw *ah) | |||
101 | * -ENODEV if the device is not supported or prints an error msg if something | 102 | * -ENODEV if the device is not supported or prints an error msg if something |
102 | * else went wrong. | 103 | * else went wrong. |
103 | */ | 104 | */ |
104 | struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc) | 105 | int ath5k_hw_attach(struct ath5k_softc *sc) |
105 | { | 106 | { |
106 | struct ath5k_hw *ah; | 107 | struct ath5k_hw *ah = sc->ah; |
108 | struct ath_common *common = ath5k_hw_common(ah); | ||
107 | struct pci_dev *pdev = sc->pdev; | 109 | struct pci_dev *pdev = sc->pdev; |
108 | struct ath5k_eeprom_info *ee; | 110 | struct ath5k_eeprom_info *ee; |
109 | int ret; | 111 | int ret; |
110 | u32 srev; | 112 | u32 srev; |
111 | 113 | ||
112 | /*If we passed the test malloc a ath5k_hw struct*/ | ||
113 | ah = kzalloc(sizeof(struct ath5k_hw), GFP_KERNEL); | ||
114 | if (ah == NULL) { | ||
115 | ret = -ENOMEM; | ||
116 | ATH5K_ERR(sc, "out of memory\n"); | ||
117 | goto err; | ||
118 | } | ||
119 | |||
120 | ah->ah_sc = sc; | ||
121 | ah->ah_iobase = sc->iobase; | ||
122 | |||
123 | /* | 114 | /* |
124 | * HW information | 115 | * HW information |
125 | */ | 116 | */ |
@@ -278,12 +269,12 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc) | |||
278 | goto err_free; | 269 | goto err_free; |
279 | } | 270 | } |
280 | 271 | ||
272 | ee = &ah->ah_capabilities.cap_eeprom; | ||
273 | |||
281 | /* | 274 | /* |
282 | * Write PCI-E power save settings | 275 | * Write PCI-E power save settings |
283 | */ | 276 | */ |
284 | if ((ah->ah_version == AR5K_AR5212) && (pdev->is_pcie)) { | 277 | if ((ah->ah_version == AR5K_AR5212) && (pdev->is_pcie)) { |
285 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | ||
286 | |||
287 | ath5k_hw_reg_write(ah, 0x9248fc00, AR5K_PCIE_SERDES); | 278 | ath5k_hw_reg_write(ah, 0x9248fc00, AR5K_PCIE_SERDES); |
288 | ath5k_hw_reg_write(ah, 0x24924924, AR5K_PCIE_SERDES); | 279 | ath5k_hw_reg_write(ah, 0x24924924, AR5K_PCIE_SERDES); |
289 | 280 | ||
@@ -321,7 +312,6 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc) | |||
321 | } | 312 | } |
322 | 313 | ||
323 | /* Crypto settings */ | 314 | /* Crypto settings */ |
324 | ee = &ah->ah_capabilities.cap_eeprom; | ||
325 | ah->ah_aes_support = srev >= AR5K_SREV_AR5212_V4 && | 315 | ah->ah_aes_support = srev >= AR5K_SREV_AR5212_V4 && |
326 | (ee->ee_version >= AR5K_EEPROM_VERSION_5_0 && | 316 | (ee->ee_version >= AR5K_EEPROM_VERSION_5_0 && |
327 | !AR5K_EEPROM_AES_DIS(ee->ee_misc5)); | 317 | !AR5K_EEPROM_AES_DIS(ee->ee_misc5)); |
@@ -336,20 +326,21 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc) | |||
336 | ath5k_hw_set_lladdr(ah, (u8[ETH_ALEN]){}); | 326 | ath5k_hw_set_lladdr(ah, (u8[ETH_ALEN]){}); |
337 | 327 | ||
338 | /* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */ | 328 | /* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */ |
339 | memset(ah->ah_bssid, 0xff, ETH_ALEN); | 329 | memcpy(common->curbssid, ath_bcast_mac, ETH_ALEN); |
340 | ath5k_hw_set_associd(ah, ah->ah_bssid, 0); | 330 | ath5k_hw_set_associd(ah); |
341 | ath5k_hw_set_opmode(ah); | 331 | ath5k_hw_set_opmode(ah); |
342 | 332 | ||
343 | ath5k_hw_rfgain_opt_init(ah); | 333 | ath5k_hw_rfgain_opt_init(ah); |
344 | 334 | ||
335 | ath5k_hw_init_nfcal_hist(ah); | ||
336 | |||
345 | /* turn on HW LEDs */ | 337 | /* turn on HW LEDs */ |
346 | ath5k_hw_set_ledstate(ah, AR5K_LED_INIT); | 338 | ath5k_hw_set_ledstate(ah, AR5K_LED_INIT); |
347 | 339 | ||
348 | return ah; | 340 | return 0; |
349 | err_free: | 341 | err_free: |
350 | kfree(ah); | 342 | kfree(ah); |
351 | err: | 343 | return ret; |
352 | return ERR_PTR(ret); | ||
353 | } | 344 | } |
354 | 345 | ||
355 | /** | 346 | /** |
@@ -369,5 +360,4 @@ void ath5k_hw_detach(struct ath5k_hw *ah) | |||
369 | ath5k_eeprom_detach(ah); | 360 | ath5k_eeprom_detach(ah); |
370 | 361 | ||
371 | /* assume interrupts are down */ | 362 | /* assume interrupts are down */ |
372 | kfree(ah); | ||
373 | } | 363 | } |
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 95a8e232b58f..3abbe7513ab5 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
@@ -50,6 +50,7 @@ | |||
50 | #include <linux/pci.h> | 50 | #include <linux/pci.h> |
51 | #include <linux/ethtool.h> | 51 | #include <linux/ethtool.h> |
52 | #include <linux/uaccess.h> | 52 | #include <linux/uaccess.h> |
53 | #include <linux/slab.h> | ||
53 | 54 | ||
54 | #include <net/ieee80211_radiotap.h> | 55 | #include <net/ieee80211_radiotap.h> |
55 | 56 | ||
@@ -83,7 +84,7 @@ MODULE_VERSION("0.6.0 (EXPERIMENTAL)"); | |||
83 | 84 | ||
84 | 85 | ||
85 | /* Known PCI ids */ | 86 | /* Known PCI ids */ |
86 | static const struct pci_device_id ath5k_pci_id_table[] = { | 87 | static DEFINE_PCI_DEVICE_TABLE(ath5k_pci_id_table) = { |
87 | { PCI_VDEVICE(ATHEROS, 0x0207) }, /* 5210 early */ | 88 | { PCI_VDEVICE(ATHEROS, 0x0207) }, /* 5210 early */ |
88 | { PCI_VDEVICE(ATHEROS, 0x0007) }, /* 5210 */ | 89 | { PCI_VDEVICE(ATHEROS, 0x0007) }, /* 5210 */ |
89 | { PCI_VDEVICE(ATHEROS, 0x0011) }, /* 5311 - this is on AHB bus !*/ | 90 | { PCI_VDEVICE(ATHEROS, 0x0011) }, /* 5311 - this is on AHB bus !*/ |
@@ -195,12 +196,13 @@ static int __devinit ath5k_pci_probe(struct pci_dev *pdev, | |||
195 | const struct pci_device_id *id); | 196 | const struct pci_device_id *id); |
196 | static void __devexit ath5k_pci_remove(struct pci_dev *pdev); | 197 | static void __devexit ath5k_pci_remove(struct pci_dev *pdev); |
197 | #ifdef CONFIG_PM | 198 | #ifdef CONFIG_PM |
198 | static int ath5k_pci_suspend(struct pci_dev *pdev, | 199 | static int ath5k_pci_suspend(struct device *dev); |
199 | pm_message_t state); | 200 | static int ath5k_pci_resume(struct device *dev); |
200 | static int ath5k_pci_resume(struct pci_dev *pdev); | 201 | |
202 | SIMPLE_DEV_PM_OPS(ath5k_pm_ops, ath5k_pci_suspend, ath5k_pci_resume); | ||
203 | #define ATH5K_PM_OPS (&ath5k_pm_ops) | ||
201 | #else | 204 | #else |
202 | #define ath5k_pci_suspend NULL | 205 | #define ATH5K_PM_OPS NULL |
203 | #define ath5k_pci_resume NULL | ||
204 | #endif /* CONFIG_PM */ | 206 | #endif /* CONFIG_PM */ |
205 | 207 | ||
206 | static struct pci_driver ath5k_pci_driver = { | 208 | static struct pci_driver ath5k_pci_driver = { |
@@ -208,8 +210,7 @@ static struct pci_driver ath5k_pci_driver = { | |||
208 | .id_table = ath5k_pci_id_table, | 210 | .id_table = ath5k_pci_id_table, |
209 | .probe = ath5k_pci_probe, | 211 | .probe = ath5k_pci_probe, |
210 | .remove = __devexit_p(ath5k_pci_remove), | 212 | .remove = __devexit_p(ath5k_pci_remove), |
211 | .suspend = ath5k_pci_suspend, | 213 | .driver.pm = ATH5K_PM_OPS, |
212 | .resume = ath5k_pci_resume, | ||
213 | }; | 214 | }; |
214 | 215 | ||
215 | 216 | ||
@@ -225,9 +226,9 @@ static int ath5k_reset_wake(struct ath5k_softc *sc); | |||
225 | static int ath5k_start(struct ieee80211_hw *hw); | 226 | static int ath5k_start(struct ieee80211_hw *hw); |
226 | static void ath5k_stop(struct ieee80211_hw *hw); | 227 | static void ath5k_stop(struct ieee80211_hw *hw); |
227 | static int ath5k_add_interface(struct ieee80211_hw *hw, | 228 | static int ath5k_add_interface(struct ieee80211_hw *hw, |
228 | struct ieee80211_if_init_conf *conf); | 229 | struct ieee80211_vif *vif); |
229 | static void ath5k_remove_interface(struct ieee80211_hw *hw, | 230 | static void ath5k_remove_interface(struct ieee80211_hw *hw, |
230 | struct ieee80211_if_init_conf *conf); | 231 | struct ieee80211_vif *vif); |
231 | static int ath5k_config(struct ieee80211_hw *hw, u32 changed); | 232 | static int ath5k_config(struct ieee80211_hw *hw, u32 changed); |
232 | static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw, | 233 | static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw, |
233 | int mc_count, struct dev_addr_list *mc_list); | 234 | int mc_count, struct dev_addr_list *mc_list); |
@@ -241,8 +242,6 @@ static int ath5k_set_key(struct ieee80211_hw *hw, | |||
241 | struct ieee80211_key_conf *key); | 242 | struct ieee80211_key_conf *key); |
242 | static int ath5k_get_stats(struct ieee80211_hw *hw, | 243 | static int ath5k_get_stats(struct ieee80211_hw *hw, |
243 | struct ieee80211_low_level_stats *stats); | 244 | struct ieee80211_low_level_stats *stats); |
244 | static int ath5k_get_tx_stats(struct ieee80211_hw *hw, | ||
245 | struct ieee80211_tx_queue_stats *stats); | ||
246 | static u64 ath5k_get_tsf(struct ieee80211_hw *hw); | 245 | static u64 ath5k_get_tsf(struct ieee80211_hw *hw); |
247 | static void ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf); | 246 | static void ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf); |
248 | static void ath5k_reset_tsf(struct ieee80211_hw *hw); | 247 | static void ath5k_reset_tsf(struct ieee80211_hw *hw); |
@@ -254,6 +253,8 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw, | |||
254 | u32 changes); | 253 | u32 changes); |
255 | static void ath5k_sw_scan_start(struct ieee80211_hw *hw); | 254 | static void ath5k_sw_scan_start(struct ieee80211_hw *hw); |
256 | static void ath5k_sw_scan_complete(struct ieee80211_hw *hw); | 255 | static void ath5k_sw_scan_complete(struct ieee80211_hw *hw); |
256 | static void ath5k_set_coverage_class(struct ieee80211_hw *hw, | ||
257 | u8 coverage_class); | ||
257 | 258 | ||
258 | static const struct ieee80211_ops ath5k_hw_ops = { | 259 | static const struct ieee80211_ops ath5k_hw_ops = { |
259 | .tx = ath5k_tx, | 260 | .tx = ath5k_tx, |
@@ -267,13 +268,13 @@ static const struct ieee80211_ops ath5k_hw_ops = { | |||
267 | .set_key = ath5k_set_key, | 268 | .set_key = ath5k_set_key, |
268 | .get_stats = ath5k_get_stats, | 269 | .get_stats = ath5k_get_stats, |
269 | .conf_tx = NULL, | 270 | .conf_tx = NULL, |
270 | .get_tx_stats = ath5k_get_tx_stats, | ||
271 | .get_tsf = ath5k_get_tsf, | 271 | .get_tsf = ath5k_get_tsf, |
272 | .set_tsf = ath5k_set_tsf, | 272 | .set_tsf = ath5k_set_tsf, |
273 | .reset_tsf = ath5k_reset_tsf, | 273 | .reset_tsf = ath5k_reset_tsf, |
274 | .bss_info_changed = ath5k_bss_info_changed, | 274 | .bss_info_changed = ath5k_bss_info_changed, |
275 | .sw_scan_start = ath5k_sw_scan_start, | 275 | .sw_scan_start = ath5k_sw_scan_start, |
276 | .sw_scan_complete = ath5k_sw_scan_complete, | 276 | .sw_scan_complete = ath5k_sw_scan_complete, |
277 | .set_coverage_class = ath5k_set_coverage_class, | ||
277 | }; | 278 | }; |
278 | 279 | ||
279 | /* | 280 | /* |
@@ -323,10 +324,13 @@ static inline void ath5k_txbuf_free(struct ath5k_softc *sc, | |||
323 | static inline void ath5k_rxbuf_free(struct ath5k_softc *sc, | 324 | static inline void ath5k_rxbuf_free(struct ath5k_softc *sc, |
324 | struct ath5k_buf *bf) | 325 | struct ath5k_buf *bf) |
325 | { | 326 | { |
327 | struct ath5k_hw *ah = sc->ah; | ||
328 | struct ath_common *common = ath5k_hw_common(ah); | ||
329 | |||
326 | BUG_ON(!bf); | 330 | BUG_ON(!bf); |
327 | if (!bf->skb) | 331 | if (!bf->skb) |
328 | return; | 332 | return; |
329 | pci_unmap_single(sc->pdev, bf->skbaddr, sc->rxbufsize, | 333 | pci_unmap_single(sc->pdev, bf->skbaddr, common->rx_bufsize, |
330 | PCI_DMA_FROMDEVICE); | 334 | PCI_DMA_FROMDEVICE); |
331 | dev_kfree_skb_any(bf->skb); | 335 | dev_kfree_skb_any(bf->skb); |
332 | bf->skb = NULL; | 336 | bf->skb = NULL; |
@@ -437,6 +441,22 @@ ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val) | |||
437 | 441 | ||
438 | return name; | 442 | return name; |
439 | } | 443 | } |
444 | static unsigned int ath5k_ioread32(void *hw_priv, u32 reg_offset) | ||
445 | { | ||
446 | struct ath5k_hw *ah = (struct ath5k_hw *) hw_priv; | ||
447 | return ath5k_hw_reg_read(ah, reg_offset); | ||
448 | } | ||
449 | |||
450 | static void ath5k_iowrite32(void *hw_priv, u32 val, u32 reg_offset) | ||
451 | { | ||
452 | struct ath5k_hw *ah = (struct ath5k_hw *) hw_priv; | ||
453 | ath5k_hw_reg_write(ah, val, reg_offset); | ||
454 | } | ||
455 | |||
456 | static const struct ath_ops ath5k_common_ops = { | ||
457 | .read = ath5k_ioread32, | ||
458 | .write = ath5k_iowrite32, | ||
459 | }; | ||
440 | 460 | ||
441 | static int __devinit | 461 | static int __devinit |
442 | ath5k_pci_probe(struct pci_dev *pdev, | 462 | ath5k_pci_probe(struct pci_dev *pdev, |
@@ -444,6 +464,7 @@ ath5k_pci_probe(struct pci_dev *pdev, | |||
444 | { | 464 | { |
445 | void __iomem *mem; | 465 | void __iomem *mem; |
446 | struct ath5k_softc *sc; | 466 | struct ath5k_softc *sc; |
467 | struct ath_common *common; | ||
447 | struct ieee80211_hw *hw; | 468 | struct ieee80211_hw *hw; |
448 | int ret; | 469 | int ret; |
449 | u8 csz; | 470 | u8 csz; |
@@ -547,7 +568,6 @@ ath5k_pci_probe(struct pci_dev *pdev, | |||
547 | __set_bit(ATH_STAT_INVALID, sc->status); | 568 | __set_bit(ATH_STAT_INVALID, sc->status); |
548 | 569 | ||
549 | sc->iobase = mem; /* So we can unmap it on detach */ | 570 | sc->iobase = mem; /* So we can unmap it on detach */ |
550 | sc->common.cachelsz = csz << 2; /* convert to bytes */ | ||
551 | sc->opmode = NL80211_IFTYPE_STATION; | 571 | sc->opmode = NL80211_IFTYPE_STATION; |
552 | sc->bintval = 1000; | 572 | sc->bintval = 1000; |
553 | mutex_init(&sc->lock); | 573 | mutex_init(&sc->lock); |
@@ -565,13 +585,28 @@ ath5k_pci_probe(struct pci_dev *pdev, | |||
565 | goto err_free; | 585 | goto err_free; |
566 | } | 586 | } |
567 | 587 | ||
568 | /* Initialize device */ | 588 | /*If we passed the test malloc a ath5k_hw struct*/ |
569 | sc->ah = ath5k_hw_attach(sc); | 589 | sc->ah = kzalloc(sizeof(struct ath5k_hw), GFP_KERNEL); |
570 | if (IS_ERR(sc->ah)) { | 590 | if (!sc->ah) { |
571 | ret = PTR_ERR(sc->ah); | 591 | ret = -ENOMEM; |
592 | ATH5K_ERR(sc, "out of memory\n"); | ||
572 | goto err_irq; | 593 | goto err_irq; |
573 | } | 594 | } |
574 | 595 | ||
596 | sc->ah->ah_sc = sc; | ||
597 | sc->ah->ah_iobase = sc->iobase; | ||
598 | common = ath5k_hw_common(sc->ah); | ||
599 | common->ops = &ath5k_common_ops; | ||
600 | common->ah = sc->ah; | ||
601 | common->hw = hw; | ||
602 | common->cachelsz = csz << 2; /* convert to bytes */ | ||
603 | |||
604 | /* Initialize device */ | ||
605 | ret = ath5k_hw_attach(sc); | ||
606 | if (ret) { | ||
607 | goto err_free_ah; | ||
608 | } | ||
609 | |||
575 | /* set up multi-rate retry capabilities */ | 610 | /* set up multi-rate retry capabilities */ |
576 | if (sc->ah->ah_version == AR5K_AR5212) { | 611 | if (sc->ah->ah_version == AR5K_AR5212) { |
577 | hw->max_rates = 4; | 612 | hw->max_rates = 4; |
@@ -640,6 +675,8 @@ err_ah: | |||
640 | ath5k_hw_detach(sc->ah); | 675 | ath5k_hw_detach(sc->ah); |
641 | err_irq: | 676 | err_irq: |
642 | free_irq(pdev->irq, sc); | 677 | free_irq(pdev->irq, sc); |
678 | err_free_ah: | ||
679 | kfree(sc->ah); | ||
643 | err_free: | 680 | err_free: |
644 | ieee80211_free_hw(hw); | 681 | ieee80211_free_hw(hw); |
645 | err_map: | 682 | err_map: |
@@ -661,6 +698,7 @@ ath5k_pci_remove(struct pci_dev *pdev) | |||
661 | ath5k_debug_finish_device(sc); | 698 | ath5k_debug_finish_device(sc); |
662 | ath5k_detach(pdev, hw); | 699 | ath5k_detach(pdev, hw); |
663 | ath5k_hw_detach(sc->ah); | 700 | ath5k_hw_detach(sc->ah); |
701 | kfree(sc->ah); | ||
664 | free_irq(pdev->irq, sc); | 702 | free_irq(pdev->irq, sc); |
665 | pci_iounmap(pdev, sc->iobase); | 703 | pci_iounmap(pdev, sc->iobase); |
666 | pci_release_region(pdev, 0); | 704 | pci_release_region(pdev, 0); |
@@ -669,33 +707,20 @@ ath5k_pci_remove(struct pci_dev *pdev) | |||
669 | } | 707 | } |
670 | 708 | ||
671 | #ifdef CONFIG_PM | 709 | #ifdef CONFIG_PM |
672 | static int | 710 | static int ath5k_pci_suspend(struct device *dev) |
673 | ath5k_pci_suspend(struct pci_dev *pdev, pm_message_t state) | ||
674 | { | 711 | { |
675 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); | 712 | struct ieee80211_hw *hw = pci_get_drvdata(to_pci_dev(dev)); |
676 | struct ath5k_softc *sc = hw->priv; | 713 | struct ath5k_softc *sc = hw->priv; |
677 | 714 | ||
678 | ath5k_led_off(sc); | 715 | ath5k_led_off(sc); |
679 | |||
680 | pci_save_state(pdev); | ||
681 | pci_disable_device(pdev); | ||
682 | pci_set_power_state(pdev, PCI_D3hot); | ||
683 | |||
684 | return 0; | 716 | return 0; |
685 | } | 717 | } |
686 | 718 | ||
687 | static int | 719 | static int ath5k_pci_resume(struct device *dev) |
688 | ath5k_pci_resume(struct pci_dev *pdev) | ||
689 | { | 720 | { |
721 | struct pci_dev *pdev = to_pci_dev(dev); | ||
690 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); | 722 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); |
691 | struct ath5k_softc *sc = hw->priv; | 723 | struct ath5k_softc *sc = hw->priv; |
692 | int err; | ||
693 | |||
694 | pci_restore_state(pdev); | ||
695 | |||
696 | err = pci_enable_device(pdev); | ||
697 | if (err) | ||
698 | return err; | ||
699 | 724 | ||
700 | /* | 725 | /* |
701 | * Suspend/Resume resets the PCI configuration space, so we have to | 726 | * Suspend/Resume resets the PCI configuration space, so we have to |
@@ -718,7 +743,7 @@ static int ath5k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *re | |||
718 | { | 743 | { |
719 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); | 744 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); |
720 | struct ath5k_softc *sc = hw->priv; | 745 | struct ath5k_softc *sc = hw->priv; |
721 | struct ath_regulatory *regulatory = &sc->common.regulatory; | 746 | struct ath_regulatory *regulatory = ath5k_hw_regulatory(sc->ah); |
722 | 747 | ||
723 | return ath_reg_notifier_apply(wiphy, request, regulatory); | 748 | return ath_reg_notifier_apply(wiphy, request, regulatory); |
724 | } | 749 | } |
@@ -728,7 +753,7 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) | |||
728 | { | 753 | { |
729 | struct ath5k_softc *sc = hw->priv; | 754 | struct ath5k_softc *sc = hw->priv; |
730 | struct ath5k_hw *ah = sc->ah; | 755 | struct ath5k_hw *ah = sc->ah; |
731 | struct ath_regulatory *regulatory = &sc->common.regulatory; | 756 | struct ath_regulatory *regulatory = ath5k_hw_regulatory(ah); |
732 | u8 mac[ETH_ALEN] = {}; | 757 | u8 mac[ETH_ALEN] = {}; |
733 | int ret; | 758 | int ret; |
734 | 759 | ||
@@ -815,7 +840,7 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) | |||
815 | 840 | ||
816 | SET_IEEE80211_PERM_ADDR(hw, mac); | 841 | SET_IEEE80211_PERM_ADDR(hw, mac); |
817 | /* All MAC address bits matter for ACKs */ | 842 | /* All MAC address bits matter for ACKs */ |
818 | memset(sc->bssidmask, 0xff, ETH_ALEN); | 843 | memcpy(sc->bssidmask, ath_bcast_mac, ETH_ALEN); |
819 | ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask); | 844 | ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask); |
820 | 845 | ||
821 | regulatory->current_rd = ah->ah_capabilities.cap_eeprom.ee_regdomain; | 846 | regulatory->current_rd = ah->ah_capabilities.cap_eeprom.ee_regdomain; |
@@ -1152,24 +1177,26 @@ ath5k_hw_to_driver_rix(struct ath5k_softc *sc, int hw_rix) | |||
1152 | static | 1177 | static |
1153 | struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_softc *sc, dma_addr_t *skb_addr) | 1178 | struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_softc *sc, dma_addr_t *skb_addr) |
1154 | { | 1179 | { |
1180 | struct ath_common *common = ath5k_hw_common(sc->ah); | ||
1155 | struct sk_buff *skb; | 1181 | struct sk_buff *skb; |
1156 | 1182 | ||
1157 | /* | 1183 | /* |
1158 | * Allocate buffer with headroom_needed space for the | 1184 | * Allocate buffer with headroom_needed space for the |
1159 | * fake physical layer header at the start. | 1185 | * fake physical layer header at the start. |
1160 | */ | 1186 | */ |
1161 | skb = ath_rxbuf_alloc(&sc->common, | 1187 | skb = ath_rxbuf_alloc(common, |
1162 | sc->rxbufsize + sc->common.cachelsz - 1, | 1188 | common->rx_bufsize, |
1163 | GFP_ATOMIC); | 1189 | GFP_ATOMIC); |
1164 | 1190 | ||
1165 | if (!skb) { | 1191 | if (!skb) { |
1166 | ATH5K_ERR(sc, "can't alloc skbuff of size %u\n", | 1192 | ATH5K_ERR(sc, "can't alloc skbuff of size %u\n", |
1167 | sc->rxbufsize + sc->common.cachelsz - 1); | 1193 | common->rx_bufsize); |
1168 | return NULL; | 1194 | return NULL; |
1169 | } | 1195 | } |
1170 | 1196 | ||
1171 | *skb_addr = pci_map_single(sc->pdev, | 1197 | *skb_addr = pci_map_single(sc->pdev, |
1172 | skb->data, sc->rxbufsize, PCI_DMA_FROMDEVICE); | 1198 | skb->data, common->rx_bufsize, |
1199 | PCI_DMA_FROMDEVICE); | ||
1173 | if (unlikely(pci_dma_mapping_error(sc->pdev, *skb_addr))) { | 1200 | if (unlikely(pci_dma_mapping_error(sc->pdev, *skb_addr))) { |
1174 | ATH5K_ERR(sc, "%s: DMA mapping failed\n", __func__); | 1201 | ATH5K_ERR(sc, "%s: DMA mapping failed\n", __func__); |
1175 | dev_kfree_skb(skb); | 1202 | dev_kfree_skb(skb); |
@@ -1220,6 +1247,29 @@ ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) | |||
1220 | return 0; | 1247 | return 0; |
1221 | } | 1248 | } |
1222 | 1249 | ||
1250 | static enum ath5k_pkt_type get_hw_packet_type(struct sk_buff *skb) | ||
1251 | { | ||
1252 | struct ieee80211_hdr *hdr; | ||
1253 | enum ath5k_pkt_type htype; | ||
1254 | __le16 fc; | ||
1255 | |||
1256 | hdr = (struct ieee80211_hdr *)skb->data; | ||
1257 | fc = hdr->frame_control; | ||
1258 | |||
1259 | if (ieee80211_is_beacon(fc)) | ||
1260 | htype = AR5K_PKT_TYPE_BEACON; | ||
1261 | else if (ieee80211_is_probe_resp(fc)) | ||
1262 | htype = AR5K_PKT_TYPE_PROBE_RESP; | ||
1263 | else if (ieee80211_is_atim(fc)) | ||
1264 | htype = AR5K_PKT_TYPE_ATIM; | ||
1265 | else if (ieee80211_is_pspoll(fc)) | ||
1266 | htype = AR5K_PKT_TYPE_PSPOLL; | ||
1267 | else | ||
1268 | htype = AR5K_PKT_TYPE_NORMAL; | ||
1269 | |||
1270 | return htype; | ||
1271 | } | ||
1272 | |||
1223 | static int | 1273 | static int |
1224 | ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, | 1274 | ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, |
1225 | struct ath5k_txq *txq) | 1275 | struct ath5k_txq *txq) |
@@ -1274,7 +1324,8 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, | |||
1274 | sc->vif, pktlen, info)); | 1324 | sc->vif, pktlen, info)); |
1275 | } | 1325 | } |
1276 | ret = ah->ah_setup_tx_desc(ah, ds, pktlen, | 1326 | ret = ah->ah_setup_tx_desc(ah, ds, pktlen, |
1277 | ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_NORMAL, | 1327 | ieee80211_get_hdrlen_from_skb(skb), |
1328 | get_hw_packet_type(skb), | ||
1278 | (sc->power_level * 2), | 1329 | (sc->power_level * 2), |
1279 | hw_rate, | 1330 | hw_rate, |
1280 | info->control.rates[0].count, keyidx, ah->ah_tx_ant, flags, | 1331 | info->control.rates[0].count, keyidx, ah->ah_tx_ant, flags, |
@@ -1303,7 +1354,6 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, | |||
1303 | 1354 | ||
1304 | spin_lock_bh(&txq->lock); | 1355 | spin_lock_bh(&txq->lock); |
1305 | list_add_tail(&bf->list, &txq->q); | 1356 | list_add_tail(&bf->list, &txq->q); |
1306 | sc->tx_stats[txq->qnum].len++; | ||
1307 | if (txq->link == NULL) /* is this first packet? */ | 1357 | if (txq->link == NULL) /* is this first packet? */ |
1308 | ath5k_hw_set_txdp(ah, txq->qnum, bf->daddr); | 1358 | ath5k_hw_set_txdp(ah, txq->qnum, bf->daddr); |
1309 | else /* no, so only link it */ | 1359 | else /* no, so only link it */ |
@@ -1487,7 +1537,8 @@ ath5k_beaconq_config(struct ath5k_softc *sc) | |||
1487 | 1537 | ||
1488 | ret = ath5k_hw_get_tx_queueprops(ah, sc->bhalq, &qi); | 1538 | ret = ath5k_hw_get_tx_queueprops(ah, sc->bhalq, &qi); |
1489 | if (ret) | 1539 | if (ret) |
1490 | return ret; | 1540 | goto err; |
1541 | |||
1491 | if (sc->opmode == NL80211_IFTYPE_AP || | 1542 | if (sc->opmode == NL80211_IFTYPE_AP || |
1492 | sc->opmode == NL80211_IFTYPE_MESH_POINT) { | 1543 | sc->opmode == NL80211_IFTYPE_MESH_POINT) { |
1493 | /* | 1544 | /* |
@@ -1514,10 +1565,25 @@ ath5k_beaconq_config(struct ath5k_softc *sc) | |||
1514 | if (ret) { | 1565 | if (ret) { |
1515 | ATH5K_ERR(sc, "%s: unable to update parameters for beacon " | 1566 | ATH5K_ERR(sc, "%s: unable to update parameters for beacon " |
1516 | "hardware queue!\n", __func__); | 1567 | "hardware queue!\n", __func__); |
1517 | return ret; | 1568 | goto err; |
1518 | } | 1569 | } |
1570 | ret = ath5k_hw_reset_tx_queue(ah, sc->bhalq); /* push to h/w */ | ||
1571 | if (ret) | ||
1572 | goto err; | ||
1573 | |||
1574 | /* reconfigure cabq with ready time to 80% of beacon_interval */ | ||
1575 | ret = ath5k_hw_get_tx_queueprops(ah, AR5K_TX_QUEUE_ID_CAB, &qi); | ||
1576 | if (ret) | ||
1577 | goto err; | ||
1578 | |||
1579 | qi.tqi_ready_time = (sc->bintval * 80) / 100; | ||
1580 | ret = ath5k_hw_set_tx_queueprops(ah, AR5K_TX_QUEUE_ID_CAB, &qi); | ||
1581 | if (ret) | ||
1582 | goto err; | ||
1519 | 1583 | ||
1520 | return ath5k_hw_reset_tx_queue(ah, sc->bhalq); /* push to h/w */; | 1584 | ret = ath5k_hw_reset_tx_queue(ah, AR5K_TX_QUEUE_ID_CAB); |
1585 | err: | ||
1586 | return ret; | ||
1521 | } | 1587 | } |
1522 | 1588 | ||
1523 | static void | 1589 | static void |
@@ -1536,7 +1602,6 @@ ath5k_txq_drainq(struct ath5k_softc *sc, struct ath5k_txq *txq) | |||
1536 | ath5k_txbuf_free(sc, bf); | 1602 | ath5k_txbuf_free(sc, bf); |
1537 | 1603 | ||
1538 | spin_lock_bh(&sc->txbuflock); | 1604 | spin_lock_bh(&sc->txbuflock); |
1539 | sc->tx_stats[txq->qnum].len--; | ||
1540 | list_move_tail(&bf->list, &sc->txbuf); | 1605 | list_move_tail(&bf->list, &sc->txbuf); |
1541 | sc->txbuf_len++; | 1606 | sc->txbuf_len++; |
1542 | spin_unlock_bh(&sc->txbuflock); | 1607 | spin_unlock_bh(&sc->txbuflock); |
@@ -1605,13 +1670,14 @@ static int | |||
1605 | ath5k_rx_start(struct ath5k_softc *sc) | 1670 | ath5k_rx_start(struct ath5k_softc *sc) |
1606 | { | 1671 | { |
1607 | struct ath5k_hw *ah = sc->ah; | 1672 | struct ath5k_hw *ah = sc->ah; |
1673 | struct ath_common *common = ath5k_hw_common(ah); | ||
1608 | struct ath5k_buf *bf; | 1674 | struct ath5k_buf *bf; |
1609 | int ret; | 1675 | int ret; |
1610 | 1676 | ||
1611 | sc->rxbufsize = roundup(IEEE80211_MAX_LEN, sc->common.cachelsz); | 1677 | common->rx_bufsize = roundup(IEEE80211_MAX_LEN, common->cachelsz); |
1612 | 1678 | ||
1613 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "cachelsz %u rxbufsize %u\n", | 1679 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "cachelsz %u rx_bufsize %u\n", |
1614 | sc->common.cachelsz, sc->rxbufsize); | 1680 | common->cachelsz, common->rx_bufsize); |
1615 | 1681 | ||
1616 | spin_lock_bh(&sc->rxbuflock); | 1682 | spin_lock_bh(&sc->rxbuflock); |
1617 | sc->rxlink = NULL; | 1683 | sc->rxlink = NULL; |
@@ -1656,6 +1722,8 @@ static unsigned int | |||
1656 | ath5k_rx_decrypted(struct ath5k_softc *sc, struct ath5k_desc *ds, | 1722 | ath5k_rx_decrypted(struct ath5k_softc *sc, struct ath5k_desc *ds, |
1657 | struct sk_buff *skb, struct ath5k_rx_status *rs) | 1723 | struct sk_buff *skb, struct ath5k_rx_status *rs) |
1658 | { | 1724 | { |
1725 | struct ath5k_hw *ah = sc->ah; | ||
1726 | struct ath_common *common = ath5k_hw_common(ah); | ||
1659 | struct ieee80211_hdr *hdr = (void *)skb->data; | 1727 | struct ieee80211_hdr *hdr = (void *)skb->data; |
1660 | unsigned int keyix, hlen; | 1728 | unsigned int keyix, hlen; |
1661 | 1729 | ||
@@ -1672,7 +1740,7 @@ ath5k_rx_decrypted(struct ath5k_softc *sc, struct ath5k_desc *ds, | |||
1672 | skb->len >= hlen + 4) { | 1740 | skb->len >= hlen + 4) { |
1673 | keyix = skb->data[hlen + 3] >> 6; | 1741 | keyix = skb->data[hlen + 3] >> 6; |
1674 | 1742 | ||
1675 | if (test_bit(keyix, sc->keymap)) | 1743 | if (test_bit(keyix, common->keymap)) |
1676 | return RX_FLAG_DECRYPTED; | 1744 | return RX_FLAG_DECRYPTED; |
1677 | } | 1745 | } |
1678 | 1746 | ||
@@ -1684,13 +1752,14 @@ static void | |||
1684 | ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb, | 1752 | ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb, |
1685 | struct ieee80211_rx_status *rxs) | 1753 | struct ieee80211_rx_status *rxs) |
1686 | { | 1754 | { |
1755 | struct ath_common *common = ath5k_hw_common(sc->ah); | ||
1687 | u64 tsf, bc_tstamp; | 1756 | u64 tsf, bc_tstamp; |
1688 | u32 hw_tu; | 1757 | u32 hw_tu; |
1689 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; | 1758 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; |
1690 | 1759 | ||
1691 | if (ieee80211_is_beacon(mgmt->frame_control) && | 1760 | if (ieee80211_is_beacon(mgmt->frame_control) && |
1692 | le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS && | 1761 | le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS && |
1693 | memcmp(mgmt->bssid, sc->ah->ah_bssid, ETH_ALEN) == 0) { | 1762 | memcmp(mgmt->bssid, common->curbssid, ETH_ALEN) == 0) { |
1694 | /* | 1763 | /* |
1695 | * Received an IBSS beacon with the same BSSID. Hardware *must* | 1764 | * Received an IBSS beacon with the same BSSID. Hardware *must* |
1696 | * have updated the local TSF. We have to work around various | 1765 | * have updated the local TSF. We have to work around various |
@@ -1745,6 +1814,8 @@ ath5k_tasklet_rx(unsigned long data) | |||
1745 | struct sk_buff *skb, *next_skb; | 1814 | struct sk_buff *skb, *next_skb; |
1746 | dma_addr_t next_skb_addr; | 1815 | dma_addr_t next_skb_addr; |
1747 | struct ath5k_softc *sc = (void *)data; | 1816 | struct ath5k_softc *sc = (void *)data; |
1817 | struct ath5k_hw *ah = sc->ah; | ||
1818 | struct ath_common *common = ath5k_hw_common(ah); | ||
1748 | struct ath5k_buf *bf; | 1819 | struct ath5k_buf *bf; |
1749 | struct ath5k_desc *ds; | 1820 | struct ath5k_desc *ds; |
1750 | int ret; | 1821 | int ret; |
@@ -1822,7 +1893,7 @@ accept: | |||
1822 | if (!next_skb) | 1893 | if (!next_skb) |
1823 | goto next; | 1894 | goto next; |
1824 | 1895 | ||
1825 | pci_unmap_single(sc->pdev, bf->skbaddr, sc->rxbufsize, | 1896 | pci_unmap_single(sc->pdev, bf->skbaddr, common->rx_bufsize, |
1826 | PCI_DMA_FROMDEVICE); | 1897 | PCI_DMA_FROMDEVICE); |
1827 | skb_put(skb, rs.rs_datalen); | 1898 | skb_put(skb, rs.rs_datalen); |
1828 | 1899 | ||
@@ -1871,17 +1942,6 @@ accept: | |||
1871 | rxs->noise = sc->ah->ah_noise_floor; | 1942 | rxs->noise = sc->ah->ah_noise_floor; |
1872 | rxs->signal = rxs->noise + rs.rs_rssi; | 1943 | rxs->signal = rxs->noise + rs.rs_rssi; |
1873 | 1944 | ||
1874 | /* An rssi of 35 indicates you should be able use | ||
1875 | * 54 Mbps reliably. A more elaborate scheme can be used | ||
1876 | * here but it requires a map of SNR/throughput for each | ||
1877 | * possible mode used */ | ||
1878 | rxs->qual = rs.rs_rssi * 100 / 35; | ||
1879 | |||
1880 | /* rssi can be more than 35 though, anything above that | ||
1881 | * should be considered at 100% */ | ||
1882 | if (rxs->qual > 100) | ||
1883 | rxs->qual = 100; | ||
1884 | |||
1885 | rxs->antenna = rs.rs_antenna; | 1945 | rxs->antenna = rs.rs_antenna; |
1886 | rxs->rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate); | 1946 | rxs->rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate); |
1887 | rxs->flag |= ath5k_rx_decrypted(sc, ds, skb, &rs); | 1947 | rxs->flag |= ath5k_rx_decrypted(sc, ds, skb, &rs); |
@@ -1971,10 +2031,8 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) | |||
1971 | } | 2031 | } |
1972 | 2032 | ||
1973 | ieee80211_tx_status(sc->hw, skb); | 2033 | ieee80211_tx_status(sc->hw, skb); |
1974 | sc->tx_stats[txq->qnum].count++; | ||
1975 | 2034 | ||
1976 | spin_lock(&sc->txbuflock); | 2035 | spin_lock(&sc->txbuflock); |
1977 | sc->tx_stats[txq->qnum].len--; | ||
1978 | list_move_tail(&bf->list, &sc->txbuf); | 2036 | list_move_tail(&bf->list, &sc->txbuf); |
1979 | sc->txbuf_len++; | 2037 | sc->txbuf_len++; |
1980 | spin_unlock(&sc->txbuflock); | 2038 | spin_unlock(&sc->txbuflock); |
@@ -2349,6 +2407,9 @@ ath5k_init(struct ath5k_softc *sc) | |||
2349 | */ | 2407 | */ |
2350 | ath5k_stop_locked(sc); | 2408 | ath5k_stop_locked(sc); |
2351 | 2409 | ||
2410 | /* Set PHY calibration interval */ | ||
2411 | ah->ah_cal_intval = ath5k_calinterval; | ||
2412 | |||
2352 | /* | 2413 | /* |
2353 | * The basic interface to setting the hardware in a good | 2414 | * The basic interface to setting the hardware in a good |
2354 | * state is ``reset''. On return the hardware is known to | 2415 | * state is ``reset''. On return the hardware is known to |
@@ -2376,10 +2437,6 @@ ath5k_init(struct ath5k_softc *sc) | |||
2376 | 2437 | ||
2377 | /* Set ack to be sent at low bit-rates */ | 2438 | /* Set ack to be sent at low bit-rates */ |
2378 | ath5k_hw_set_ack_bitrate_high(ah, false); | 2439 | ath5k_hw_set_ack_bitrate_high(ah, false); |
2379 | |||
2380 | /* Set PHY calibration inteval */ | ||
2381 | ah->ah_cal_intval = ath5k_calinterval; | ||
2382 | |||
2383 | ret = 0; | 2440 | ret = 0; |
2384 | done: | 2441 | done: |
2385 | mmiowb(); | 2442 | mmiowb(); |
@@ -2753,7 +2810,7 @@ static void ath5k_stop(struct ieee80211_hw *hw) | |||
2753 | } | 2810 | } |
2754 | 2811 | ||
2755 | static int ath5k_add_interface(struct ieee80211_hw *hw, | 2812 | static int ath5k_add_interface(struct ieee80211_hw *hw, |
2756 | struct ieee80211_if_init_conf *conf) | 2813 | struct ieee80211_vif *vif) |
2757 | { | 2814 | { |
2758 | struct ath5k_softc *sc = hw->priv; | 2815 | struct ath5k_softc *sc = hw->priv; |
2759 | int ret; | 2816 | int ret; |
@@ -2764,22 +2821,22 @@ static int ath5k_add_interface(struct ieee80211_hw *hw, | |||
2764 | goto end; | 2821 | goto end; |
2765 | } | 2822 | } |
2766 | 2823 | ||
2767 | sc->vif = conf->vif; | 2824 | sc->vif = vif; |
2768 | 2825 | ||
2769 | switch (conf->type) { | 2826 | switch (vif->type) { |
2770 | case NL80211_IFTYPE_AP: | 2827 | case NL80211_IFTYPE_AP: |
2771 | case NL80211_IFTYPE_STATION: | 2828 | case NL80211_IFTYPE_STATION: |
2772 | case NL80211_IFTYPE_ADHOC: | 2829 | case NL80211_IFTYPE_ADHOC: |
2773 | case NL80211_IFTYPE_MESH_POINT: | 2830 | case NL80211_IFTYPE_MESH_POINT: |
2774 | case NL80211_IFTYPE_MONITOR: | 2831 | case NL80211_IFTYPE_MONITOR: |
2775 | sc->opmode = conf->type; | 2832 | sc->opmode = vif->type; |
2776 | break; | 2833 | break; |
2777 | default: | 2834 | default: |
2778 | ret = -EOPNOTSUPP; | 2835 | ret = -EOPNOTSUPP; |
2779 | goto end; | 2836 | goto end; |
2780 | } | 2837 | } |
2781 | 2838 | ||
2782 | ath5k_hw_set_lladdr(sc->ah, conf->mac_addr); | 2839 | ath5k_hw_set_lladdr(sc->ah, vif->addr); |
2783 | ath5k_mode_setup(sc); | 2840 | ath5k_mode_setup(sc); |
2784 | 2841 | ||
2785 | ret = 0; | 2842 | ret = 0; |
@@ -2790,13 +2847,13 @@ end: | |||
2790 | 2847 | ||
2791 | static void | 2848 | static void |
2792 | ath5k_remove_interface(struct ieee80211_hw *hw, | 2849 | ath5k_remove_interface(struct ieee80211_hw *hw, |
2793 | struct ieee80211_if_init_conf *conf) | 2850 | struct ieee80211_vif *vif) |
2794 | { | 2851 | { |
2795 | struct ath5k_softc *sc = hw->priv; | 2852 | struct ath5k_softc *sc = hw->priv; |
2796 | u8 mac[ETH_ALEN] = {}; | 2853 | u8 mac[ETH_ALEN] = {}; |
2797 | 2854 | ||
2798 | mutex_lock(&sc->lock); | 2855 | mutex_lock(&sc->lock); |
2799 | if (sc->vif != conf->vif) | 2856 | if (sc->vif != vif) |
2800 | goto end; | 2857 | goto end; |
2801 | 2858 | ||
2802 | ath5k_hw_set_lladdr(sc->ah, mac); | 2859 | ath5k_hw_set_lladdr(sc->ah, mac); |
@@ -3008,6 +3065,8 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
3008 | struct ieee80211_key_conf *key) | 3065 | struct ieee80211_key_conf *key) |
3009 | { | 3066 | { |
3010 | struct ath5k_softc *sc = hw->priv; | 3067 | struct ath5k_softc *sc = hw->priv; |
3068 | struct ath5k_hw *ah = sc->ah; | ||
3069 | struct ath_common *common = ath5k_hw_common(ah); | ||
3011 | int ret = 0; | 3070 | int ret = 0; |
3012 | 3071 | ||
3013 | if (modparam_nohwcrypt) | 3072 | if (modparam_nohwcrypt) |
@@ -3040,14 +3099,14 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
3040 | ATH5K_ERR(sc, "can't set the key\n"); | 3099 | ATH5K_ERR(sc, "can't set the key\n"); |
3041 | goto unlock; | 3100 | goto unlock; |
3042 | } | 3101 | } |
3043 | __set_bit(key->keyidx, sc->keymap); | 3102 | __set_bit(key->keyidx, common->keymap); |
3044 | key->hw_key_idx = key->keyidx; | 3103 | key->hw_key_idx = key->keyidx; |
3045 | key->flags |= (IEEE80211_KEY_FLAG_GENERATE_IV | | 3104 | key->flags |= (IEEE80211_KEY_FLAG_GENERATE_IV | |
3046 | IEEE80211_KEY_FLAG_GENERATE_MMIC); | 3105 | IEEE80211_KEY_FLAG_GENERATE_MMIC); |
3047 | break; | 3106 | break; |
3048 | case DISABLE_KEY: | 3107 | case DISABLE_KEY: |
3049 | ath5k_hw_reset_key(sc->ah, key->keyidx); | 3108 | ath5k_hw_reset_key(sc->ah, key->keyidx); |
3050 | __clear_bit(key->keyidx, sc->keymap); | 3109 | __clear_bit(key->keyidx, common->keymap); |
3051 | break; | 3110 | break; |
3052 | default: | 3111 | default: |
3053 | ret = -EINVAL; | 3112 | ret = -EINVAL; |
@@ -3075,17 +3134,6 @@ ath5k_get_stats(struct ieee80211_hw *hw, | |||
3075 | return 0; | 3134 | return 0; |
3076 | } | 3135 | } |
3077 | 3136 | ||
3078 | static int | ||
3079 | ath5k_get_tx_stats(struct ieee80211_hw *hw, | ||
3080 | struct ieee80211_tx_queue_stats *stats) | ||
3081 | { | ||
3082 | struct ath5k_softc *sc = hw->priv; | ||
3083 | |||
3084 | memcpy(stats, &sc->tx_stats, sizeof(sc->tx_stats)); | ||
3085 | |||
3086 | return 0; | ||
3087 | } | ||
3088 | |||
3089 | static u64 | 3137 | static u64 |
3090 | ath5k_get_tsf(struct ieee80211_hw *hw) | 3138 | ath5k_get_tsf(struct ieee80211_hw *hw) |
3091 | { | 3139 | { |
@@ -3176,6 +3224,7 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw, | |||
3176 | { | 3224 | { |
3177 | struct ath5k_softc *sc = hw->priv; | 3225 | struct ath5k_softc *sc = hw->priv; |
3178 | struct ath5k_hw *ah = sc->ah; | 3226 | struct ath5k_hw *ah = sc->ah; |
3227 | struct ath_common *common = ath5k_hw_common(ah); | ||
3179 | unsigned long flags; | 3228 | unsigned long flags; |
3180 | 3229 | ||
3181 | mutex_lock(&sc->lock); | 3230 | mutex_lock(&sc->lock); |
@@ -3184,10 +3233,9 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw, | |||
3184 | 3233 | ||
3185 | if (changes & BSS_CHANGED_BSSID) { | 3234 | if (changes & BSS_CHANGED_BSSID) { |
3186 | /* Cache for later use during resets */ | 3235 | /* Cache for later use during resets */ |
3187 | memcpy(ah->ah_bssid, bss_conf->bssid, ETH_ALEN); | 3236 | memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); |
3188 | /* XXX: assoc id is set to 0 for now, mac80211 doesn't have | 3237 | common->curaid = 0; |
3189 | * a clean way of letting us retrieve this yet. */ | 3238 | ath5k_hw_set_associd(ah); |
3190 | ath5k_hw_set_associd(ah, ah->ah_bssid, 0); | ||
3191 | mmiowb(); | 3239 | mmiowb(); |
3192 | } | 3240 | } |
3193 | 3241 | ||
@@ -3200,6 +3248,14 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw, | |||
3200 | set_beacon_filter(hw, sc->assoc); | 3248 | set_beacon_filter(hw, sc->assoc); |
3201 | ath5k_hw_set_ledstate(sc->ah, sc->assoc ? | 3249 | ath5k_hw_set_ledstate(sc->ah, sc->assoc ? |
3202 | AR5K_LED_ASSOC : AR5K_LED_INIT); | 3250 | AR5K_LED_ASSOC : AR5K_LED_INIT); |
3251 | if (bss_conf->assoc) { | ||
3252 | ATH5K_DBG(sc, ATH5K_DEBUG_ANY, | ||
3253 | "Bss Info ASSOC %d, bssid: %pM\n", | ||
3254 | bss_conf->aid, common->curbssid); | ||
3255 | common->curaid = bss_conf->aid; | ||
3256 | ath5k_hw_set_associd(ah); | ||
3257 | /* Once ANI is available you would start it here */ | ||
3258 | } | ||
3203 | } | 3259 | } |
3204 | 3260 | ||
3205 | if (changes & BSS_CHANGED_BEACON) { | 3261 | if (changes & BSS_CHANGED_BEACON) { |
@@ -3232,3 +3288,22 @@ static void ath5k_sw_scan_complete(struct ieee80211_hw *hw) | |||
3232 | ath5k_hw_set_ledstate(sc->ah, sc->assoc ? | 3288 | ath5k_hw_set_ledstate(sc->ah, sc->assoc ? |
3233 | AR5K_LED_ASSOC : AR5K_LED_INIT); | 3289 | AR5K_LED_ASSOC : AR5K_LED_INIT); |
3234 | } | 3290 | } |
3291 | |||
3292 | /** | ||
3293 | * ath5k_set_coverage_class - Set IEEE 802.11 coverage class | ||
3294 | * | ||
3295 | * @hw: struct ieee80211_hw pointer | ||
3296 | * @coverage_class: IEEE 802.11 coverage class number | ||
3297 | * | ||
3298 | * Mac80211 callback. Sets slot time, ACK timeout and CTS timeout for given | ||
3299 | * coverage class. The values are persistent, they are restored after device | ||
3300 | * reset. | ||
3301 | */ | ||
3302 | static void ath5k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class) | ||
3303 | { | ||
3304 | struct ath5k_softc *sc = hw->priv; | ||
3305 | |||
3306 | mutex_lock(&sc->lock); | ||
3307 | ath5k_hw_set_coverage_class(sc->ah, coverage_class); | ||
3308 | mutex_unlock(&sc->lock); | ||
3309 | } | ||
diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h index a28c42f32c9d..7e1a88a5abdb 100644 --- a/drivers/net/wireless/ath/ath5k/base.h +++ b/drivers/net/wireless/ath/ath5k/base.h | |||
@@ -36,7 +36,7 @@ | |||
36 | */ | 36 | */ |
37 | 37 | ||
38 | /* | 38 | /* |
39 | * Defintions for the Atheros Wireless LAN controller driver. | 39 | * Definitions for the Atheros Wireless LAN controller driver. |
40 | */ | 40 | */ |
41 | #ifndef _DEV_ATH_ATHVAR_H | 41 | #ifndef _DEV_ATH_ATHVAR_H |
42 | #define _DEV_ATH_ATHVAR_H | 42 | #define _DEV_ATH_ATHVAR_H |
@@ -115,10 +115,8 @@ struct ath5k_rfkill { | |||
115 | * associated with an instance of a device */ | 115 | * associated with an instance of a device */ |
116 | struct ath5k_softc { | 116 | struct ath5k_softc { |
117 | struct pci_dev *pdev; /* for dma mapping */ | 117 | struct pci_dev *pdev; /* for dma mapping */ |
118 | struct ath_common common; | ||
119 | void __iomem *iobase; /* address of the device */ | 118 | void __iomem *iobase; /* address of the device */ |
120 | struct mutex lock; /* dev-level lock */ | 119 | struct mutex lock; /* dev-level lock */ |
121 | struct ieee80211_tx_queue_stats tx_stats[AR5K_NUM_TX_QUEUES]; | ||
122 | struct ieee80211_low_level_stats ll_stats; | 120 | struct ieee80211_low_level_stats ll_stats; |
123 | struct ieee80211_hw *hw; /* IEEE 802.11 common */ | 121 | struct ieee80211_hw *hw; /* IEEE 802.11 common */ |
124 | struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; | 122 | struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; |
@@ -154,8 +152,6 @@ struct ath5k_softc { | |||
154 | 152 | ||
155 | enum ath5k_int imask; /* interrupt mask copy */ | 153 | enum ath5k_int imask; /* interrupt mask copy */ |
156 | 154 | ||
157 | DECLARE_BITMAP(keymap, AR5K_KEYCACHE_SIZE); /* key use bit map */ | ||
158 | |||
159 | u8 bssidmask[ETH_ALEN]; | 155 | u8 bssidmask[ETH_ALEN]; |
160 | 156 | ||
161 | unsigned int led_pin, /* GPIO pin for driving LED */ | 157 | unsigned int led_pin, /* GPIO pin for driving LED */ |
@@ -193,7 +189,7 @@ struct ath5k_softc { | |||
193 | struct ath5k_txq *cabq; /* content after beacon */ | 189 | struct ath5k_txq *cabq; /* content after beacon */ |
194 | 190 | ||
195 | int power_level; /* Requested tx power in dbm */ | 191 | int power_level; /* Requested tx power in dbm */ |
196 | bool assoc; /* assocate state */ | 192 | bool assoc; /* associate state */ |
197 | bool enable_beacon; /* true if beacons are on */ | 193 | bool enable_beacon; /* true if beacons are on */ |
198 | }; | 194 | }; |
199 | 195 | ||
@@ -202,15 +198,4 @@ struct ath5k_softc { | |||
202 | #define ath5k_hw_hasveol(_ah) \ | 198 | #define ath5k_hw_hasveol(_ah) \ |
203 | (ath5k_hw_get_capability(_ah, AR5K_CAP_VEOL, 0, NULL) == 0) | 199 | (ath5k_hw_get_capability(_ah, AR5K_CAP_VEOL, 0, NULL) == 0) |
204 | 200 | ||
205 | static inline struct ath_common *ath5k_hw_common(struct ath5k_hw *ah) | ||
206 | { | ||
207 | return &ah->ah_sc->common; | ||
208 | } | ||
209 | |||
210 | static inline struct ath_regulatory *ath5k_hw_regulatory(struct ath5k_hw *ah) | ||
211 | { | ||
212 | return &(ath5k_hw_common(ah)->regulatory); | ||
213 | |||
214 | } | ||
215 | |||
216 | #endif | 201 | #endif |
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c index 644962adda97..67665cdc7afe 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.c +++ b/drivers/net/wireless/ath/ath5k/eeprom.c | |||
@@ -21,6 +21,8 @@ | |||
21 | * EEPROM access functions and helpers * | 21 | * EEPROM access functions and helpers * |
22 | \*************************************/ | 22 | \*************************************/ |
23 | 23 | ||
24 | #include <linux/slab.h> | ||
25 | |||
24 | #include "ath5k.h" | 26 | #include "ath5k.h" |
25 | #include "reg.h" | 27 | #include "reg.h" |
26 | #include "debug.h" | 28 | #include "debug.h" |
@@ -97,6 +99,7 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah) | |||
97 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | 99 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; |
98 | int ret; | 100 | int ret; |
99 | u16 val; | 101 | u16 val; |
102 | u32 cksum, offset, eep_max = AR5K_EEPROM_INFO_MAX; | ||
100 | 103 | ||
101 | /* | 104 | /* |
102 | * Read values from EEPROM and store them in the capability structure | 105 | * Read values from EEPROM and store them in the capability structure |
@@ -111,20 +114,44 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah) | |||
111 | if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_0) | 114 | if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_0) |
112 | return 0; | 115 | return 0; |
113 | 116 | ||
114 | #ifdef notyet | ||
115 | /* | 117 | /* |
116 | * Validate the checksum of the EEPROM date. There are some | 118 | * Validate the checksum of the EEPROM date. There are some |
117 | * devices with invalid EEPROMs. | 119 | * devices with invalid EEPROMs. |
118 | */ | 120 | */ |
119 | for (cksum = 0, offset = 0; offset < AR5K_EEPROM_INFO_MAX; offset++) { | 121 | AR5K_EEPROM_READ(AR5K_EEPROM_SIZE_UPPER, val); |
122 | if (val) { | ||
123 | eep_max = (val & AR5K_EEPROM_SIZE_UPPER_MASK) << | ||
124 | AR5K_EEPROM_SIZE_ENDLOC_SHIFT; | ||
125 | AR5K_EEPROM_READ(AR5K_EEPROM_SIZE_LOWER, val); | ||
126 | eep_max = (eep_max | val) - AR5K_EEPROM_INFO_BASE; | ||
127 | |||
128 | /* | ||
129 | * Fail safe check to prevent stupid loops due | ||
130 | * to busted EEPROMs. XXX: This value is likely too | ||
131 | * big still, waiting on a better value. | ||
132 | */ | ||
133 | if (eep_max > (3 * AR5K_EEPROM_INFO_MAX)) { | ||
134 | ATH5K_ERR(ah->ah_sc, "Invalid max custom EEPROM size: " | ||
135 | "%d (0x%04x) max expected: %d (0x%04x)\n", | ||
136 | eep_max, eep_max, | ||
137 | 3 * AR5K_EEPROM_INFO_MAX, | ||
138 | 3 * AR5K_EEPROM_INFO_MAX); | ||
139 | return -EIO; | ||
140 | } | ||
141 | } | ||
142 | |||
143 | for (cksum = 0, offset = 0; offset < eep_max; offset++) { | ||
120 | AR5K_EEPROM_READ(AR5K_EEPROM_INFO(offset), val); | 144 | AR5K_EEPROM_READ(AR5K_EEPROM_INFO(offset), val); |
121 | cksum ^= val; | 145 | cksum ^= val; |
122 | } | 146 | } |
123 | if (cksum != AR5K_EEPROM_INFO_CKSUM) { | 147 | if (cksum != AR5K_EEPROM_INFO_CKSUM) { |
124 | ATH5K_ERR(ah->ah_sc, "Invalid EEPROM checksum 0x%04x\n", cksum); | 148 | ATH5K_ERR(ah->ah_sc, "Invalid EEPROM " |
149 | "checksum: 0x%04x eep_max: 0x%04x (%s)\n", | ||
150 | cksum, eep_max, | ||
151 | eep_max == AR5K_EEPROM_INFO_MAX ? | ||
152 | "default size" : "custom size"); | ||
125 | return -EIO; | 153 | return -EIO; |
126 | } | 154 | } |
127 | #endif | ||
128 | 155 | ||
129 | AR5K_EEPROM_READ_HDR(AR5K_EEPROM_ANT_GAIN(ah->ah_ee_version), | 156 | AR5K_EEPROM_READ_HDR(AR5K_EEPROM_ANT_GAIN(ah->ah_ee_version), |
130 | ee_ant_gain); | 157 | ee_ant_gain); |
@@ -404,8 +431,8 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset, | |||
404 | ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f; | 431 | ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f; |
405 | 432 | ||
406 | AR5K_EEPROM_READ(o++, val); | 433 | AR5K_EEPROM_READ(o++, val); |
407 | ee->ee_i_cal[mode] = (val >> 8) & 0x3f; | 434 | ee->ee_i_cal[mode] = (val >> 5) & 0x3f; |
408 | ee->ee_q_cal[mode] = (val >> 3) & 0x1f; | 435 | ee->ee_q_cal[mode] = val & 0x1f; |
409 | 436 | ||
410 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_2) { | 437 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_2) { |
411 | AR5K_EEPROM_READ(o++, val); | 438 | AR5K_EEPROM_READ(o++, val); |
@@ -1492,7 +1519,7 @@ ath5k_eeprom_read_target_rate_pwr_info(struct ath5k_hw *ah, unsigned int mode) | |||
1492 | * This info is used to calibrate the baseband power table. Imagine | 1519 | * This info is used to calibrate the baseband power table. Imagine |
1493 | * that for each channel there is a power curve that's hw specific | 1520 | * that for each channel there is a power curve that's hw specific |
1494 | * (depends on amplifier etc) and we try to "correct" this curve using | 1521 | * (depends on amplifier etc) and we try to "correct" this curve using |
1495 | * offests we pass on to phy chip (baseband -> before amplifier) so that | 1522 | * offsets we pass on to phy chip (baseband -> before amplifier) so that |
1496 | * it can use accurate power values when setting tx power (takes amplifier's | 1523 | * it can use accurate power values when setting tx power (takes amplifier's |
1497 | * performance on each channel into account). | 1524 | * performance on each channel into account). |
1498 | * | 1525 | * |
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.h b/drivers/net/wireless/ath/ath5k/eeprom.h index 0123f3521a0b..473a483bb9c3 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.h +++ b/drivers/net/wireless/ath/ath5k/eeprom.h | |||
@@ -37,6 +37,14 @@ | |||
37 | #define AR5K_EEPROM_RFKILL_POLARITY_S 1 | 37 | #define AR5K_EEPROM_RFKILL_POLARITY_S 1 |
38 | 38 | ||
39 | #define AR5K_EEPROM_REG_DOMAIN 0x00bf /* EEPROM regdom */ | 39 | #define AR5K_EEPROM_REG_DOMAIN 0x00bf /* EEPROM regdom */ |
40 | |||
41 | /* FLASH(EEPROM) Defines for AR531X chips */ | ||
42 | #define AR5K_EEPROM_SIZE_LOWER 0x1b /* size info -- lower */ | ||
43 | #define AR5K_EEPROM_SIZE_UPPER 0x1c /* size info -- upper */ | ||
44 | #define AR5K_EEPROM_SIZE_UPPER_MASK 0xfff0 | ||
45 | #define AR5K_EEPROM_SIZE_UPPER_SHIFT 4 | ||
46 | #define AR5K_EEPROM_SIZE_ENDLOC_SHIFT 12 | ||
47 | |||
40 | #define AR5K_EEPROM_CHECKSUM 0x00c0 /* EEPROM checksum */ | 48 | #define AR5K_EEPROM_CHECKSUM 0x00c0 /* EEPROM checksum */ |
41 | #define AR5K_EEPROM_INFO_BASE 0x00c0 /* EEPROM header */ | 49 | #define AR5K_EEPROM_INFO_BASE 0x00c0 /* EEPROM header */ |
42 | #define AR5K_EEPROM_INFO_MAX (0x400 - AR5K_EEPROM_INFO_BASE) | 50 | #define AR5K_EEPROM_INFO_MAX (0x400 - AR5K_EEPROM_INFO_BASE) |
diff --git a/drivers/net/wireless/ath/ath5k/initvals.c b/drivers/net/wireless/ath/ath5k/initvals.c index 18eb5190ce4b..8fa439308828 100644 --- a/drivers/net/wireless/ath/ath5k/initvals.c +++ b/drivers/net/wireless/ath/ath5k/initvals.c | |||
@@ -560,8 +560,8 @@ static const struct ath5k_ini ar5212_ini_common_start[] = { | |||
560 | { AR5K_SLEEP0, 0x0002aaaa }, | 560 | { AR5K_SLEEP0, 0x0002aaaa }, |
561 | { AR5K_SLEEP1, 0x02005555 }, | 561 | { AR5K_SLEEP1, 0x02005555 }, |
562 | { AR5K_SLEEP2, 0x00000000 }, | 562 | { AR5K_SLEEP2, 0x00000000 }, |
563 | { AR5K_BSS_IDM0, 0xffffffff }, | 563 | { AR_BSSMSKL, 0xffffffff }, |
564 | { AR5K_BSS_IDM1, 0x0000ffff }, | 564 | { AR_BSSMSKU, 0x0000ffff }, |
565 | { AR5K_TXPC, 0x00000000 }, | 565 | { AR5K_TXPC, 0x00000000 }, |
566 | { AR5K_PROFCNT_TX, 0x00000000 }, | 566 | { AR5K_PROFCNT_TX, 0x00000000 }, |
567 | { AR5K_PROFCNT_RX, 0x00000000 }, | 567 | { AR5K_PROFCNT_RX, 0x00000000 }, |
diff --git a/drivers/net/wireless/ath/ath5k/led.c b/drivers/net/wireless/ath/ath5k/led.c index b548c8eaaae1..67aa52e9bf94 100644 --- a/drivers/net/wireless/ath/ath5k/led.c +++ b/drivers/net/wireless/ath/ath5k/led.c | |||
@@ -59,6 +59,8 @@ static const struct pci_device_id ath5k_led_devices[] = { | |||
59 | { ATH_SDEVICE(PCI_VENDOR_ID_COMPAQ, PCI_ANY_ID), ATH_LED(1, 1) }, | 59 | { ATH_SDEVICE(PCI_VENDOR_ID_COMPAQ, PCI_ANY_ID), ATH_LED(1, 1) }, |
60 | /* Acer Aspire One A150 (maximlevitsky@gmail.com) */ | 60 | /* Acer Aspire One A150 (maximlevitsky@gmail.com) */ |
61 | { ATH_SDEVICE(PCI_VENDOR_ID_FOXCONN, 0xe008), ATH_LED(3, 0) }, | 61 | { ATH_SDEVICE(PCI_VENDOR_ID_FOXCONN, 0xe008), ATH_LED(3, 0) }, |
62 | /* Acer Aspire One AO531h AO751h (keng-yu.lin@canonical.com) */ | ||
63 | { ATH_SDEVICE(PCI_VENDOR_ID_FOXCONN, 0xe00d), ATH_LED(3, 0) }, | ||
62 | /* Acer Ferrari 5000 (russ.dill@gmail.com) */ | 64 | /* Acer Ferrari 5000 (russ.dill@gmail.com) */ |
63 | { ATH_SDEVICE(PCI_VENDOR_ID_AMBIT, 0x0422), ATH_LED(1, 1) }, | 65 | { ATH_SDEVICE(PCI_VENDOR_ID_AMBIT, 0x0422), ATH_LED(1, 1) }, |
64 | /* E-machines E510 (tuliom@gmail.com) */ | 66 | /* E-machines E510 (tuliom@gmail.com) */ |
@@ -75,8 +77,12 @@ static const struct pci_device_id ath5k_led_devices[] = { | |||
75 | { ATH_SDEVICE(PCI_VENDOR_ID_HP, 0x0137a), ATH_LED(3, 1) }, | 77 | { ATH_SDEVICE(PCI_VENDOR_ID_HP, 0x0137a), ATH_LED(3, 1) }, |
76 | /* HP Compaq C700 (nitrousnrg@gmail.com) */ | 78 | /* HP Compaq C700 (nitrousnrg@gmail.com) */ |
77 | { ATH_SDEVICE(PCI_VENDOR_ID_HP, 0x0137b), ATH_LED(3, 1) }, | 79 | { ATH_SDEVICE(PCI_VENDOR_ID_HP, 0x0137b), ATH_LED(3, 1) }, |
80 | /* LiteOn AR5BXB63 (magooz@salug.it) */ | ||
81 | { ATH_SDEVICE(PCI_VENDOR_ID_ATHEROS, 0x3067), ATH_LED(3, 0) }, | ||
78 | /* IBM-specific AR5212 (all others) */ | 82 | /* IBM-specific AR5212 (all others) */ |
79 | { PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5212_IBM), ATH_LED(0, 0) }, | 83 | { PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5212_IBM), ATH_LED(0, 0) }, |
84 | /* Dell Vostro A860 (shahar@shahar-or.co.il) */ | ||
85 | { ATH_SDEVICE(PCI_VENDOR_ID_QMI, 0x0112), ATH_LED(3, 0) }, | ||
80 | { } | 86 | { } |
81 | }; | 87 | }; |
82 | 88 | ||
diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index 2942f13c9c4a..aefe84f9c04b 100644 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c | |||
@@ -24,6 +24,8 @@ | |||
24 | * Protocol Control Unit Functions * | 24 | * Protocol Control Unit Functions * |
25 | \*********************************/ | 25 | \*********************************/ |
26 | 26 | ||
27 | #include <asm/unaligned.h> | ||
28 | |||
27 | #include "ath5k.h" | 29 | #include "ath5k.h" |
28 | #include "reg.h" | 30 | #include "reg.h" |
29 | #include "debug.h" | 31 | #include "debug.h" |
@@ -44,6 +46,7 @@ | |||
44 | */ | 46 | */ |
45 | int ath5k_hw_set_opmode(struct ath5k_hw *ah) | 47 | int ath5k_hw_set_opmode(struct ath5k_hw *ah) |
46 | { | 48 | { |
49 | struct ath_common *common = ath5k_hw_common(ah); | ||
47 | u32 pcu_reg, beacon_reg, low_id, high_id; | 50 | u32 pcu_reg, beacon_reg, low_id, high_id; |
48 | 51 | ||
49 | 52 | ||
@@ -95,8 +98,8 @@ int ath5k_hw_set_opmode(struct ath5k_hw *ah) | |||
95 | /* | 98 | /* |
96 | * Set PCU registers | 99 | * Set PCU registers |
97 | */ | 100 | */ |
98 | low_id = AR5K_LOW_ID(ah->ah_sta_id); | 101 | low_id = get_unaligned_le32(common->macaddr); |
99 | high_id = AR5K_HIGH_ID(ah->ah_sta_id); | 102 | high_id = get_unaligned_le16(common->macaddr + 4); |
100 | ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0); | 103 | ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0); |
101 | ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1); | 104 | ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1); |
102 | 105 | ||
@@ -184,8 +187,8 @@ unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah) | |||
184 | { | 187 | { |
185 | ATH5K_TRACE(ah->ah_sc); | 188 | ATH5K_TRACE(ah->ah_sc); |
186 | 189 | ||
187 | return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah, | 190 | return ath5k_hw_clocktoh(ah, AR5K_REG_MS(ath5k_hw_reg_read(ah, |
188 | AR5K_TIME_OUT), AR5K_TIME_OUT_ACK), ah->ah_turbo); | 191 | AR5K_TIME_OUT), AR5K_TIME_OUT_ACK)); |
189 | } | 192 | } |
190 | 193 | ||
191 | /** | 194 | /** |
@@ -197,12 +200,12 @@ unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah) | |||
197 | int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout) | 200 | int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout) |
198 | { | 201 | { |
199 | ATH5K_TRACE(ah->ah_sc); | 202 | ATH5K_TRACE(ah->ah_sc); |
200 | if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK), | 203 | if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK)) |
201 | ah->ah_turbo) <= timeout) | 204 | <= timeout) |
202 | return -EINVAL; | 205 | return -EINVAL; |
203 | 206 | ||
204 | AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_ACK, | 207 | AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_ACK, |
205 | ath5k_hw_htoclock(timeout, ah->ah_turbo)); | 208 | ath5k_hw_htoclock(ah, timeout)); |
206 | 209 | ||
207 | return 0; | 210 | return 0; |
208 | } | 211 | } |
@@ -215,8 +218,8 @@ int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout) | |||
215 | unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah) | 218 | unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah) |
216 | { | 219 | { |
217 | ATH5K_TRACE(ah->ah_sc); | 220 | ATH5K_TRACE(ah->ah_sc); |
218 | return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah, | 221 | return ath5k_hw_clocktoh(ah, AR5K_REG_MS(ath5k_hw_reg_read(ah, |
219 | AR5K_TIME_OUT), AR5K_TIME_OUT_CTS), ah->ah_turbo); | 222 | AR5K_TIME_OUT), AR5K_TIME_OUT_CTS)); |
220 | } | 223 | } |
221 | 224 | ||
222 | /** | 225 | /** |
@@ -228,36 +231,94 @@ unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah) | |||
228 | int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout) | 231 | int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout) |
229 | { | 232 | { |
230 | ATH5K_TRACE(ah->ah_sc); | 233 | ATH5K_TRACE(ah->ah_sc); |
231 | if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS), | 234 | if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS)) |
232 | ah->ah_turbo) <= timeout) | 235 | <= timeout) |
233 | return -EINVAL; | 236 | return -EINVAL; |
234 | 237 | ||
235 | AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_CTS, | 238 | AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_CTS, |
236 | ath5k_hw_htoclock(timeout, ah->ah_turbo)); | 239 | ath5k_hw_htoclock(ah, timeout)); |
237 | 240 | ||
238 | return 0; | 241 | return 0; |
239 | } | 242 | } |
240 | 243 | ||
244 | /** | ||
245 | * ath5k_hw_htoclock - Translate usec to hw clock units | ||
246 | * | ||
247 | * @ah: The &struct ath5k_hw | ||
248 | * @usec: value in microseconds | ||
249 | */ | ||
250 | unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec) | ||
251 | { | ||
252 | return usec * ath5k_hw_get_clockrate(ah); | ||
253 | } | ||
241 | 254 | ||
242 | /****************\ | 255 | /** |
243 | * BSSID handling * | 256 | * ath5k_hw_clocktoh - Translate hw clock units to usec |
244 | \****************/ | 257 | * @clock: value in hw clock units |
258 | */ | ||
259 | unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock) | ||
260 | { | ||
261 | return clock / ath5k_hw_get_clockrate(ah); | ||
262 | } | ||
245 | 263 | ||
246 | /** | 264 | /** |
247 | * ath5k_hw_get_lladdr - Get station id | 265 | * ath5k_hw_get_clockrate - Get the clock rate for current mode |
248 | * | 266 | * |
249 | * @ah: The &struct ath5k_hw | 267 | * @ah: The &struct ath5k_hw |
250 | * @mac: The card's mac address | 268 | */ |
269 | unsigned int ath5k_hw_get_clockrate(struct ath5k_hw *ah) | ||
270 | { | ||
271 | struct ieee80211_channel *channel = ah->ah_current_channel; | ||
272 | int clock; | ||
273 | |||
274 | if (channel->hw_value & CHANNEL_5GHZ) | ||
275 | clock = 40; /* 802.11a */ | ||
276 | else if (channel->hw_value & CHANNEL_CCK) | ||
277 | clock = 22; /* 802.11b */ | ||
278 | else | ||
279 | clock = 44; /* 802.11g */ | ||
280 | |||
281 | /* Clock rate in turbo modes is twice the normal rate */ | ||
282 | if (channel->hw_value & CHANNEL_TURBO) | ||
283 | clock *= 2; | ||
284 | |||
285 | return clock; | ||
286 | } | ||
287 | |||
288 | /** | ||
289 | * ath5k_hw_get_default_slottime - Get the default slot time for current mode | ||
251 | * | 290 | * |
252 | * Initialize ah->ah_sta_id using the mac address provided | 291 | * @ah: The &struct ath5k_hw |
253 | * (just a memcpy). | 292 | */ |
293 | unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah) | ||
294 | { | ||
295 | struct ieee80211_channel *channel = ah->ah_current_channel; | ||
296 | |||
297 | if (channel->hw_value & CHANNEL_TURBO) | ||
298 | return 6; /* both turbo modes */ | ||
299 | |||
300 | if (channel->hw_value & CHANNEL_CCK) | ||
301 | return 20; /* 802.11b */ | ||
302 | |||
303 | return 9; /* 802.11 a/g */ | ||
304 | } | ||
305 | |||
306 | /** | ||
307 | * ath5k_hw_get_default_sifs - Get the default SIFS for current mode | ||
254 | * | 308 | * |
255 | * TODO: Remove it once we merge ath5k_softc and ath5k_hw | 309 | * @ah: The &struct ath5k_hw |
256 | */ | 310 | */ |
257 | void ath5k_hw_get_lladdr(struct ath5k_hw *ah, u8 *mac) | 311 | unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah) |
258 | { | 312 | { |
259 | ATH5K_TRACE(ah->ah_sc); | 313 | struct ieee80211_channel *channel = ah->ah_current_channel; |
260 | memcpy(mac, ah->ah_sta_id, ETH_ALEN); | 314 | |
315 | if (channel->hw_value & CHANNEL_TURBO) | ||
316 | return 8; /* both turbo modes */ | ||
317 | |||
318 | if (channel->hw_value & CHANNEL_5GHZ) | ||
319 | return 16; /* 802.11a */ | ||
320 | |||
321 | return 10; /* 802.11 b/g */ | ||
261 | } | 322 | } |
262 | 323 | ||
263 | /** | 324 | /** |
@@ -270,17 +331,18 @@ void ath5k_hw_get_lladdr(struct ath5k_hw *ah, u8 *mac) | |||
270 | */ | 331 | */ |
271 | int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac) | 332 | int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac) |
272 | { | 333 | { |
334 | struct ath_common *common = ath5k_hw_common(ah); | ||
273 | u32 low_id, high_id; | 335 | u32 low_id, high_id; |
274 | u32 pcu_reg; | 336 | u32 pcu_reg; |
275 | 337 | ||
276 | ATH5K_TRACE(ah->ah_sc); | 338 | ATH5K_TRACE(ah->ah_sc); |
277 | /* Set new station ID */ | 339 | /* Set new station ID */ |
278 | memcpy(ah->ah_sta_id, mac, ETH_ALEN); | 340 | memcpy(common->macaddr, mac, ETH_ALEN); |
279 | 341 | ||
280 | pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000; | 342 | pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000; |
281 | 343 | ||
282 | low_id = AR5K_LOW_ID(mac); | 344 | low_id = get_unaligned_le32(mac); |
283 | high_id = AR5K_HIGH_ID(mac); | 345 | high_id = get_unaligned_le16(mac + 4); |
284 | 346 | ||
285 | ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0); | 347 | ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0); |
286 | ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1); | 348 | ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1); |
@@ -297,159 +359,51 @@ int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac) | |||
297 | * | 359 | * |
298 | * Sets the BSSID which trigers the "SME Join" operation | 360 | * Sets the BSSID which trigers the "SME Join" operation |
299 | */ | 361 | */ |
300 | void ath5k_hw_set_associd(struct ath5k_hw *ah, const u8 *bssid, u16 assoc_id) | 362 | void ath5k_hw_set_associd(struct ath5k_hw *ah) |
301 | { | 363 | { |
302 | u32 low_id, high_id; | 364 | struct ath_common *common = ath5k_hw_common(ah); |
303 | u16 tim_offset = 0; | 365 | u16 tim_offset = 0; |
304 | 366 | ||
305 | /* | 367 | /* |
306 | * Set simple BSSID mask on 5212 | 368 | * Set simple BSSID mask on 5212 |
307 | */ | 369 | */ |
308 | if (ah->ah_version == AR5K_AR5212) { | 370 | if (ah->ah_version == AR5K_AR5212) |
309 | ath5k_hw_reg_write(ah, AR5K_LOW_ID(ah->ah_bssid_mask), | 371 | ath_hw_setbssidmask(common); |
310 | AR5K_BSS_IDM0); | ||
311 | ath5k_hw_reg_write(ah, AR5K_HIGH_ID(ah->ah_bssid_mask), | ||
312 | AR5K_BSS_IDM1); | ||
313 | } | ||
314 | 372 | ||
315 | /* | 373 | /* |
316 | * Set BSSID which triggers the "SME Join" operation | 374 | * Set BSSID which triggers the "SME Join" operation |
317 | */ | 375 | */ |
318 | low_id = AR5K_LOW_ID(bssid); | 376 | ath5k_hw_reg_write(ah, |
319 | high_id = AR5K_HIGH_ID(bssid); | 377 | get_unaligned_le32(common->curbssid), |
320 | ath5k_hw_reg_write(ah, low_id, AR5K_BSS_ID0); | 378 | AR5K_BSS_ID0); |
321 | ath5k_hw_reg_write(ah, high_id | ((assoc_id & 0x3fff) << | 379 | ath5k_hw_reg_write(ah, |
322 | AR5K_BSS_ID1_AID_S), AR5K_BSS_ID1); | 380 | get_unaligned_le16(common->curbssid + 4) | |
323 | 381 | ((common->curaid & 0x3fff) << AR5K_BSS_ID1_AID_S), | |
324 | if (assoc_id == 0) { | 382 | AR5K_BSS_ID1); |
383 | |||
384 | if (common->curaid == 0) { | ||
325 | ath5k_hw_disable_pspoll(ah); | 385 | ath5k_hw_disable_pspoll(ah); |
326 | return; | 386 | return; |
327 | } | 387 | } |
328 | 388 | ||
329 | AR5K_REG_WRITE_BITS(ah, AR5K_BEACON, AR5K_BEACON_TIM, | 389 | AR5K_REG_WRITE_BITS(ah, AR5K_BEACON, AR5K_BEACON_TIM, |
330 | tim_offset ? tim_offset + 4 : 0); | 390 | tim_offset ? tim_offset + 4 : 0); |
331 | 391 | ||
332 | ath5k_hw_enable_pspoll(ah, NULL, 0); | 392 | ath5k_hw_enable_pspoll(ah, NULL, 0); |
333 | } | 393 | } |
334 | 394 | ||
335 | /** | 395 | void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask) |
336 | * ath5k_hw_set_bssid_mask - filter out bssids we listen | ||
337 | * | ||
338 | * @ah: the &struct ath5k_hw | ||
339 | * @mask: the bssid_mask, a u8 array of size ETH_ALEN | ||
340 | * | ||
341 | * BSSID masking is a method used by AR5212 and newer hardware to inform PCU | ||
342 | * which bits of the interface's MAC address should be looked at when trying | ||
343 | * to decide which packets to ACK. In station mode and AP mode with a single | ||
344 | * BSS every bit matters since we lock to only one BSS. In AP mode with | ||
345 | * multiple BSSes (virtual interfaces) not every bit matters because hw must | ||
346 | * accept frames for all BSSes and so we tweak some bits of our mac address | ||
347 | * in order to have multiple BSSes. | ||
348 | * | ||
349 | * NOTE: This is a simple filter and does *not* filter out all | ||
350 | * relevant frames. Some frames that are not for us might get ACKed from us | ||
351 | * by PCU because they just match the mask. | ||
352 | * | ||
353 | * When handling multiple BSSes you can get the BSSID mask by computing the | ||
354 | * set of ~ ( MAC XOR BSSID ) for all bssids we handle. | ||
355 | * | ||
356 | * When you do this you are essentially computing the common bits of all your | ||
357 | * BSSes. Later it is assumed the harware will "and" (&) the BSSID mask with | ||
358 | * the MAC address to obtain the relevant bits and compare the result with | ||
359 | * (frame's BSSID & mask) to see if they match. | ||
360 | */ | ||
361 | /* | ||
362 | * Simple example: on your card you have have two BSSes you have created with | ||
363 | * BSSID-01 and BSSID-02. Lets assume BSSID-01 will not use the MAC address. | ||
364 | * There is another BSSID-03 but you are not part of it. For simplicity's sake, | ||
365 | * assuming only 4 bits for a mac address and for BSSIDs you can then have: | ||
366 | * | ||
367 | * \ | ||
368 | * MAC: 0001 | | ||
369 | * BSSID-01: 0100 | --> Belongs to us | ||
370 | * BSSID-02: 1001 | | ||
371 | * / | ||
372 | * ------------------- | ||
373 | * BSSID-03: 0110 | --> External | ||
374 | * ------------------- | ||
375 | * | ||
376 | * Our bssid_mask would then be: | ||
377 | * | ||
378 | * On loop iteration for BSSID-01: | ||
379 | * ~(0001 ^ 0100) -> ~(0101) | ||
380 | * -> 1010 | ||
381 | * bssid_mask = 1010 | ||
382 | * | ||
383 | * On loop iteration for BSSID-02: | ||
384 | * bssid_mask &= ~(0001 ^ 1001) | ||
385 | * bssid_mask = (1010) & ~(0001 ^ 1001) | ||
386 | * bssid_mask = (1010) & ~(1001) | ||
387 | * bssid_mask = (1010) & (0110) | ||
388 | * bssid_mask = 0010 | ||
389 | * | ||
390 | * A bssid_mask of 0010 means "only pay attention to the second least | ||
391 | * significant bit". This is because its the only bit common | ||
392 | * amongst the MAC and all BSSIDs we support. To findout what the real | ||
393 | * common bit is we can simply "&" the bssid_mask now with any BSSID we have | ||
394 | * or our MAC address (we assume the hardware uses the MAC address). | ||
395 | * | ||
396 | * Now, suppose there's an incoming frame for BSSID-03: | ||
397 | * | ||
398 | * IFRAME-01: 0110 | ||
399 | * | ||
400 | * An easy eye-inspeciton of this already should tell you that this frame | ||
401 | * will not pass our check. This is beacuse the bssid_mask tells the | ||
402 | * hardware to only look at the second least significant bit and the | ||
403 | * common bit amongst the MAC and BSSIDs is 0, this frame has the 2nd LSB | ||
404 | * as 1, which does not match 0. | ||
405 | * | ||
406 | * So with IFRAME-01 we *assume* the hardware will do: | ||
407 | * | ||
408 | * allow = (IFRAME-01 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0; | ||
409 | * --> allow = (0110 & 0010) == (0010 & 0001) ? 1 : 0; | ||
410 | * --> allow = (0010) == 0000 ? 1 : 0; | ||
411 | * --> allow = 0 | ||
412 | * | ||
413 | * Lets now test a frame that should work: | ||
414 | * | ||
415 | * IFRAME-02: 0001 (we should allow) | ||
416 | * | ||
417 | * allow = (0001 & 1010) == 1010 | ||
418 | * | ||
419 | * allow = (IFRAME-02 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0; | ||
420 | * --> allow = (0001 & 0010) == (0010 & 0001) ? 1 :0; | ||
421 | * --> allow = (0010) == (0010) | ||
422 | * --> allow = 1 | ||
423 | * | ||
424 | * Other examples: | ||
425 | * | ||
426 | * IFRAME-03: 0100 --> allowed | ||
427 | * IFRAME-04: 1001 --> allowed | ||
428 | * IFRAME-05: 1101 --> allowed but its not for us!!! | ||
429 | * | ||
430 | */ | ||
431 | int ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask) | ||
432 | { | 396 | { |
433 | u32 low_id, high_id; | 397 | struct ath_common *common = ath5k_hw_common(ah); |
434 | ATH5K_TRACE(ah->ah_sc); | 398 | ATH5K_TRACE(ah->ah_sc); |
435 | 399 | ||
436 | /* Cache bssid mask so that we can restore it | 400 | /* Cache bssid mask so that we can restore it |
437 | * on reset */ | 401 | * on reset */ |
438 | memcpy(ah->ah_bssid_mask, mask, ETH_ALEN); | 402 | memcpy(common->bssidmask, mask, ETH_ALEN); |
439 | if (ah->ah_version == AR5K_AR5212) { | 403 | if (ah->ah_version == AR5K_AR5212) |
440 | low_id = AR5K_LOW_ID(mask); | 404 | ath_hw_setbssidmask(common); |
441 | high_id = AR5K_HIGH_ID(mask); | ||
442 | |||
443 | ath5k_hw_reg_write(ah, low_id, AR5K_BSS_IDM0); | ||
444 | ath5k_hw_reg_write(ah, high_id, AR5K_BSS_IDM1); | ||
445 | |||
446 | return 0; | ||
447 | } | ||
448 | |||
449 | return -EIO; | ||
450 | } | 405 | } |
451 | 406 | ||
452 | |||
453 | /************\ | 407 | /************\ |
454 | * RX Control * | 408 | * RX Control * |
455 | \************/ | 409 | \************/ |
@@ -1157,14 +1111,17 @@ int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac) | |||
1157 | /* Invalid entry (key table overflow) */ | 1111 | /* Invalid entry (key table overflow) */ |
1158 | AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE); | 1112 | AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE); |
1159 | 1113 | ||
1160 | /* MAC may be NULL if it's a broadcast key. In this case no need to | 1114 | /* |
1161 | * to compute AR5K_LOW_ID and AR5K_HIGH_ID as we already know it. */ | 1115 | * MAC may be NULL if it's a broadcast key. In this case no need to |
1116 | * to compute get_unaligned_le32 and get_unaligned_le16 as we | ||
1117 | * already know it. | ||
1118 | */ | ||
1162 | if (!mac) { | 1119 | if (!mac) { |
1163 | low_id = 0xffffffff; | 1120 | low_id = 0xffffffff; |
1164 | high_id = 0xffff | AR5K_KEYTABLE_VALID; | 1121 | high_id = 0xffff | AR5K_KEYTABLE_VALID; |
1165 | } else { | 1122 | } else { |
1166 | low_id = AR5K_LOW_ID(mac); | 1123 | low_id = get_unaligned_le32(mac); |
1167 | high_id = AR5K_HIGH_ID(mac) | AR5K_KEYTABLE_VALID; | 1124 | high_id = get_unaligned_le16(mac + 4) | AR5K_KEYTABLE_VALID; |
1168 | } | 1125 | } |
1169 | 1126 | ||
1170 | ath5k_hw_reg_write(ah, low_id, AR5K_KEYTABLE_MAC0(entry)); | 1127 | ath5k_hw_reg_write(ah, low_id, AR5K_KEYTABLE_MAC0(entry)); |
@@ -1173,3 +1130,24 @@ int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac) | |||
1173 | return 0; | 1130 | return 0; |
1174 | } | 1131 | } |
1175 | 1132 | ||
1133 | /** | ||
1134 | * ath5k_hw_set_coverage_class - Set IEEE 802.11 coverage class | ||
1135 | * | ||
1136 | * @ah: The &struct ath5k_hw | ||
1137 | * @coverage_class: IEEE 802.11 coverage class number | ||
1138 | * | ||
1139 | * Sets slot time, ACK timeout and CTS timeout for given coverage class. | ||
1140 | */ | ||
1141 | void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class) | ||
1142 | { | ||
1143 | /* As defined by IEEE 802.11-2007 17.3.8.6 */ | ||
1144 | int slot_time = ath5k_hw_get_default_slottime(ah) + 3 * coverage_class; | ||
1145 | int ack_timeout = ath5k_hw_get_default_sifs(ah) + slot_time; | ||
1146 | int cts_timeout = ack_timeout; | ||
1147 | |||
1148 | ath5k_hw_set_slot_time(ah, slot_time); | ||
1149 | ath5k_hw_set_ack_timeout(ah, ack_timeout); | ||
1150 | ath5k_hw_set_cts_timeout(ah, cts_timeout); | ||
1151 | |||
1152 | ah->ah_coverage_class = coverage_class; | ||
1153 | } | ||
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 1a039f2bd732..68e2bccd90d3 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #define _ATH5K_PHY | 23 | #define _ATH5K_PHY |
24 | 24 | ||
25 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
26 | #include <linux/slab.h> | ||
26 | 27 | ||
27 | #include "ath5k.h" | 28 | #include "ath5k.h" |
28 | #include "reg.h" | 29 | #include "reg.h" |
@@ -117,7 +118,7 @@ static unsigned int ath5k_hw_rfb_op(struct ath5k_hw *ah, | |||
117 | 118 | ||
118 | /* | 119 | /* |
119 | * This code is used to optimize rf gain on different environments | 120 | * This code is used to optimize rf gain on different environments |
120 | * (temprature mostly) based on feedback from a power detector. | 121 | * (temperature mostly) based on feedback from a power detector. |
121 | * | 122 | * |
122 | * It's only used on RF5111 and RF5112, later RF chips seem to have | 123 | * It's only used on RF5111 and RF5112, later RF chips seem to have |
123 | * auto adjustment on hw -notice they have a much smaller BANK 7 and | 124 | * auto adjustment on hw -notice they have a much smaller BANK 7 and |
@@ -1124,77 +1125,148 @@ ath5k_hw_calibration_poll(struct ath5k_hw *ah) | |||
1124 | ah->ah_swi_mask = AR5K_SWI_FULL_CALIBRATION; | 1125 | ah->ah_swi_mask = AR5K_SWI_FULL_CALIBRATION; |
1125 | AR5K_REG_ENABLE_BITS(ah, AR5K_CR, AR5K_CR_SWI); | 1126 | AR5K_REG_ENABLE_BITS(ah, AR5K_CR, AR5K_CR_SWI); |
1126 | } | 1127 | } |
1128 | } | ||
1127 | 1129 | ||
1130 | static int sign_extend(int val, const int nbits) | ||
1131 | { | ||
1132 | int order = BIT(nbits-1); | ||
1133 | return (val ^ order) - order; | ||
1128 | } | 1134 | } |
1129 | 1135 | ||
1130 | /** | 1136 | static s32 ath5k_hw_read_measured_noise_floor(struct ath5k_hw *ah) |
1131 | * ath5k_hw_noise_floor_calibration - perform PHY noise floor calibration | 1137 | { |
1132 | * | 1138 | s32 val; |
1133 | * @ah: struct ath5k_hw pointer we are operating on | 1139 | |
1134 | * @freq: the channel frequency, just used for error logging | 1140 | val = ath5k_hw_reg_read(ah, AR5K_PHY_NF); |
1135 | * | 1141 | return sign_extend(AR5K_REG_MS(val, AR5K_PHY_NF_MINCCA_PWR), 9); |
1136 | * This function performs a noise floor calibration of the PHY and waits for | 1142 | } |
1137 | * it to complete. Then the noise floor value is compared to some maximum | 1143 | |
1138 | * noise floor we consider valid. | 1144 | void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah) |
1139 | * | 1145 | { |
1140 | * Note that this is different from what the madwifi HAL does: it reads the | 1146 | int i; |
1141 | * noise floor and afterwards initiates the calibration. Since the noise floor | 1147 | |
1142 | * calibration can take some time to finish, depending on the current channel | 1148 | ah->ah_nfcal_hist.index = 0; |
1143 | * use, that avoids the occasional timeout warnings we are seeing now. | 1149 | for (i = 0; i < ATH5K_NF_CAL_HIST_MAX; i++) |
1144 | * | 1150 | ah->ah_nfcal_hist.nfval[i] = AR5K_TUNE_CCA_MAX_GOOD_VALUE; |
1145 | * See the following link for an Atheros patent on noise floor calibration: | 1151 | } |
1146 | * http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&Sect2=HITOFF&d=PALL \ | 1152 | |
1147 | * &p=1&u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&r=1&f=G&l=50&s1=7245893.PN.&OS=PN/7 | 1153 | static void ath5k_hw_update_nfcal_hist(struct ath5k_hw *ah, s16 noise_floor) |
1154 | { | ||
1155 | struct ath5k_nfcal_hist *hist = &ah->ah_nfcal_hist; | ||
1156 | hist->index = (hist->index + 1) & (ATH5K_NF_CAL_HIST_MAX-1); | ||
1157 | hist->nfval[hist->index] = noise_floor; | ||
1158 | } | ||
1159 | |||
1160 | static s16 ath5k_hw_get_median_noise_floor(struct ath5k_hw *ah) | ||
1161 | { | ||
1162 | s16 sort[ATH5K_NF_CAL_HIST_MAX]; | ||
1163 | s16 tmp; | ||
1164 | int i, j; | ||
1165 | |||
1166 | memcpy(sort, ah->ah_nfcal_hist.nfval, sizeof(sort)); | ||
1167 | for (i = 0; i < ATH5K_NF_CAL_HIST_MAX - 1; i++) { | ||
1168 | for (j = 1; j < ATH5K_NF_CAL_HIST_MAX - i; j++) { | ||
1169 | if (sort[j] > sort[j-1]) { | ||
1170 | tmp = sort[j]; | ||
1171 | sort[j] = sort[j-1]; | ||
1172 | sort[j-1] = tmp; | ||
1173 | } | ||
1174 | } | ||
1175 | } | ||
1176 | for (i = 0; i < ATH5K_NF_CAL_HIST_MAX; i++) { | ||
1177 | ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE, | ||
1178 | "cal %d:%d\n", i, sort[i]); | ||
1179 | } | ||
1180 | return sort[(ATH5K_NF_CAL_HIST_MAX-1) / 2]; | ||
1181 | } | ||
1182 | |||
1183 | /* | ||
1184 | * When we tell the hardware to perform a noise floor calibration | ||
1185 | * by setting the AR5K_PHY_AGCCTL_NF bit, it will periodically | ||
1186 | * sample-and-hold the minimum noise level seen at the antennas. | ||
1187 | * This value is then stored in a ring buffer of recently measured | ||
1188 | * noise floor values so we have a moving window of the last few | ||
1189 | * samples. | ||
1148 | * | 1190 | * |
1149 | * XXX: Since during noise floor calibration antennas are detached according to | 1191 | * The median of the values in the history is then loaded into the |
1150 | * the patent, we should stop tx queues here. | 1192 | * hardware for its own use for RSSI and CCA measurements. |
1151 | */ | 1193 | */ |
1152 | int | 1194 | void ath5k_hw_update_noise_floor(struct ath5k_hw *ah) |
1153 | ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq) | ||
1154 | { | 1195 | { |
1155 | int ret; | 1196 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; |
1156 | unsigned int i; | 1197 | u32 val; |
1157 | s32 noise_floor; | 1198 | s16 nf, threshold; |
1199 | u8 ee_mode; | ||
1158 | 1200 | ||
1159 | /* | 1201 | /* keep last value if calibration hasn't completed */ |
1160 | * Enable noise floor calibration | 1202 | if (ath5k_hw_reg_read(ah, AR5K_PHY_AGCCTL) & AR5K_PHY_AGCCTL_NF) { |
1161 | */ | 1203 | ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE, |
1162 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, | 1204 | "NF did not complete in calibration window\n"); |
1163 | AR5K_PHY_AGCCTL_NF); | ||
1164 | 1205 | ||
1165 | ret = ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL, | 1206 | return; |
1166 | AR5K_PHY_AGCCTL_NF, 0, false); | ||
1167 | if (ret) { | ||
1168 | ATH5K_ERR(ah->ah_sc, | ||
1169 | "noise floor calibration timeout (%uMHz)\n", freq); | ||
1170 | return -EAGAIN; | ||
1171 | } | 1207 | } |
1172 | 1208 | ||
1173 | /* Wait until the noise floor is calibrated and read the value */ | 1209 | switch (ah->ah_current_channel->hw_value & CHANNEL_MODES) { |
1174 | for (i = 20; i > 0; i--) { | 1210 | case CHANNEL_A: |
1175 | mdelay(1); | 1211 | case CHANNEL_T: |
1176 | noise_floor = ath5k_hw_reg_read(ah, AR5K_PHY_NF); | 1212 | case CHANNEL_XR: |
1177 | noise_floor = AR5K_PHY_NF_RVAL(noise_floor); | 1213 | ee_mode = AR5K_EEPROM_MODE_11A; |
1178 | if (noise_floor & AR5K_PHY_NF_ACTIVE) { | 1214 | break; |
1179 | noise_floor = AR5K_PHY_NF_AVAL(noise_floor); | 1215 | case CHANNEL_G: |
1180 | 1216 | case CHANNEL_TG: | |
1181 | if (noise_floor <= AR5K_TUNE_NOISE_FLOOR) | 1217 | ee_mode = AR5K_EEPROM_MODE_11G; |
1182 | break; | 1218 | break; |
1183 | } | 1219 | default: |
1220 | case CHANNEL_B: | ||
1221 | ee_mode = AR5K_EEPROM_MODE_11B; | ||
1222 | break; | ||
1184 | } | 1223 | } |
1185 | 1224 | ||
1186 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_CALIBRATE, | ||
1187 | "noise floor %d\n", noise_floor); | ||
1188 | 1225 | ||
1189 | if (noise_floor > AR5K_TUNE_NOISE_FLOOR) { | 1226 | /* completed NF calibration, test threshold */ |
1190 | ATH5K_ERR(ah->ah_sc, | 1227 | nf = ath5k_hw_read_measured_noise_floor(ah); |
1191 | "noise floor calibration failed (%uMHz)\n", freq); | 1228 | threshold = ee->ee_noise_floor_thr[ee_mode]; |
1192 | return -EAGAIN; | 1229 | |
1230 | if (nf > threshold) { | ||
1231 | ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE, | ||
1232 | "noise floor failure detected; " | ||
1233 | "read %d, threshold %d\n", | ||
1234 | nf, threshold); | ||
1235 | |||
1236 | nf = AR5K_TUNE_CCA_MAX_GOOD_VALUE; | ||
1193 | } | 1237 | } |
1194 | 1238 | ||
1195 | ah->ah_noise_floor = noise_floor; | 1239 | ath5k_hw_update_nfcal_hist(ah, nf); |
1240 | nf = ath5k_hw_get_median_noise_floor(ah); | ||
1196 | 1241 | ||
1197 | return 0; | 1242 | /* load noise floor (in .5 dBm) so the hardware will use it */ |
1243 | val = ath5k_hw_reg_read(ah, AR5K_PHY_NF) & ~AR5K_PHY_NF_M; | ||
1244 | val |= (nf * 2) & AR5K_PHY_NF_M; | ||
1245 | ath5k_hw_reg_write(ah, val, AR5K_PHY_NF); | ||
1246 | |||
1247 | AR5K_REG_MASKED_BITS(ah, AR5K_PHY_AGCCTL, AR5K_PHY_AGCCTL_NF, | ||
1248 | ~(AR5K_PHY_AGCCTL_NF_EN | AR5K_PHY_AGCCTL_NF_NOUPDATE)); | ||
1249 | |||
1250 | ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL, AR5K_PHY_AGCCTL_NF, | ||
1251 | 0, false); | ||
1252 | |||
1253 | /* | ||
1254 | * Load a high max CCA Power value (-50 dBm in .5 dBm units) | ||
1255 | * so that we're not capped by the median we just loaded. | ||
1256 | * This will be used as the initial value for the next noise | ||
1257 | * floor calibration. | ||
1258 | */ | ||
1259 | val = (val & ~AR5K_PHY_NF_M) | ((-50 * 2) & AR5K_PHY_NF_M); | ||
1260 | ath5k_hw_reg_write(ah, val, AR5K_PHY_NF); | ||
1261 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, | ||
1262 | AR5K_PHY_AGCCTL_NF_EN | | ||
1263 | AR5K_PHY_AGCCTL_NF_NOUPDATE | | ||
1264 | AR5K_PHY_AGCCTL_NF); | ||
1265 | |||
1266 | ah->ah_noise_floor = nf; | ||
1267 | |||
1268 | ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE, | ||
1269 | "noise floor calibrated: %d\n", nf); | ||
1198 | } | 1270 | } |
1199 | 1271 | ||
1200 | /* | 1272 | /* |
@@ -1287,7 +1359,7 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah, | |||
1287 | return ret; | 1359 | return ret; |
1288 | } | 1360 | } |
1289 | 1361 | ||
1290 | ath5k_hw_noise_floor_calibration(ah, channel->center_freq); | 1362 | ath5k_hw_update_noise_floor(ah); |
1291 | 1363 | ||
1292 | /* | 1364 | /* |
1293 | * Re-enable RX/TX and beacons | 1365 | * Re-enable RX/TX and beacons |
@@ -1315,38 +1387,39 @@ static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah, | |||
1315 | goto done; | 1387 | goto done; |
1316 | 1388 | ||
1317 | /* Calibration has finished, get the results and re-run */ | 1389 | /* Calibration has finished, get the results and re-run */ |
1390 | |||
1391 | /* work around empty results which can apparently happen on 5212 */ | ||
1318 | for (i = 0; i <= 10; i++) { | 1392 | for (i = 0; i <= 10; i++) { |
1319 | iq_corr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_CORR); | 1393 | iq_corr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_CORR); |
1320 | i_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_I); | 1394 | i_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_I); |
1321 | q_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_Q); | 1395 | q_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_Q); |
1396 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_CALIBRATE, | ||
1397 | "iq_corr:%x i_pwr:%x q_pwr:%x", iq_corr, i_pwr, q_pwr); | ||
1398 | if (i_pwr && q_pwr) | ||
1399 | break; | ||
1322 | } | 1400 | } |
1323 | 1401 | ||
1324 | i_coffd = ((i_pwr >> 1) + (q_pwr >> 1)) >> 7; | 1402 | i_coffd = ((i_pwr >> 1) + (q_pwr >> 1)) >> 7; |
1325 | q_coffd = q_pwr >> 7; | 1403 | q_coffd = q_pwr >> 7; |
1326 | 1404 | ||
1327 | /* No correction */ | 1405 | /* protect against divide by 0 and loss of sign bits */ |
1328 | if (i_coffd == 0 || q_coffd == 0) | 1406 | if (i_coffd == 0 || q_coffd < 2) |
1329 | goto done; | 1407 | goto done; |
1330 | 1408 | ||
1331 | i_coff = ((-iq_corr) / i_coffd) & 0x3f; | 1409 | i_coff = (-iq_corr) / i_coffd; |
1410 | i_coff = clamp(i_coff, -32, 31); /* signed 6 bit */ | ||
1332 | 1411 | ||
1333 | /* Boundary check */ | 1412 | q_coff = (i_pwr / q_coffd) - 128; |
1334 | if (i_coff > 31) | 1413 | q_coff = clamp(q_coff, -16, 15); /* signed 5 bit */ |
1335 | i_coff = 31; | ||
1336 | if (i_coff < -32) | ||
1337 | i_coff = -32; | ||
1338 | 1414 | ||
1339 | q_coff = (((s32)i_pwr / q_coffd) - 128) & 0x1f; | 1415 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_CALIBRATE, |
1340 | 1416 | "new I:%d Q:%d (i_coffd:%x q_coffd:%x)", | |
1341 | /* Boundary check */ | 1417 | i_coff, q_coff, i_coffd, q_coffd); |
1342 | if (q_coff > 15) | ||
1343 | q_coff = 15; | ||
1344 | if (q_coff < -16) | ||
1345 | q_coff = -16; | ||
1346 | 1418 | ||
1347 | /* Commit new I/Q value */ | 1419 | /* Commit new I/Q values (set enable bit last to match HAL sources) */ |
1348 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_ENABLE | | 1420 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_Q_I_COFF, i_coff); |
1349 | ((u32)q_coff) | ((u32)i_coff << AR5K_PHY_IQ_CORR_Q_I_COFF_S)); | 1421 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_Q_Q_COFF, q_coff); |
1422 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_ENABLE); | ||
1350 | 1423 | ||
1351 | /* Re-enable calibration -if we don't we'll commit | 1424 | /* Re-enable calibration -if we don't we'll commit |
1352 | * the same values again and again */ | 1425 | * the same values again and again */ |
@@ -1360,7 +1433,7 @@ done: | |||
1360 | * since noise floor calibration interrupts rx path while I/Q | 1433 | * since noise floor calibration interrupts rx path while I/Q |
1361 | * calibration doesn't. We don't need to run noise floor calibration | 1434 | * calibration doesn't. We don't need to run noise floor calibration |
1362 | * as often as I/Q calibration.*/ | 1435 | * as often as I/Q calibration.*/ |
1363 | ath5k_hw_noise_floor_calibration(ah, channel->center_freq); | 1436 | ath5k_hw_update_noise_floor(ah); |
1364 | 1437 | ||
1365 | /* Initiate a gain_F calibration */ | 1438 | /* Initiate a gain_F calibration */ |
1366 | ath5k_hw_request_rfgain_probe(ah); | 1439 | ath5k_hw_request_rfgain_probe(ah); |
@@ -1802,7 +1875,7 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode) | |||
1802 | break; | 1875 | break; |
1803 | case AR5K_ANTMODE_FIXED_A: | 1876 | case AR5K_ANTMODE_FIXED_A: |
1804 | def_ant = 1; | 1877 | def_ant = 1; |
1805 | tx_ant = 0; | 1878 | tx_ant = 1; |
1806 | use_def_for_tx = true; | 1879 | use_def_for_tx = true; |
1807 | update_def_on_tx = false; | 1880 | update_def_on_tx = false; |
1808 | use_def_for_rts = true; | 1881 | use_def_for_rts = true; |
@@ -1811,7 +1884,7 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode) | |||
1811 | break; | 1884 | break; |
1812 | case AR5K_ANTMODE_FIXED_B: | 1885 | case AR5K_ANTMODE_FIXED_B: |
1813 | def_ant = 2; | 1886 | def_ant = 2; |
1814 | tx_ant = 0; | 1887 | tx_ant = 2; |
1815 | use_def_for_tx = true; | 1888 | use_def_for_tx = true; |
1816 | update_def_on_tx = false; | 1889 | update_def_on_tx = false; |
1817 | use_def_for_rts = true; | 1890 | use_def_for_rts = true; |
@@ -2675,7 +2748,7 @@ ath5k_setup_channel_powertable(struct ath5k_hw *ah, | |||
2675 | /* Fill curves in reverse order | 2748 | /* Fill curves in reverse order |
2676 | * from lower power (max gain) | 2749 | * from lower power (max gain) |
2677 | * to higher power. Use curve -> idx | 2750 | * to higher power. Use curve -> idx |
2678 | * backmaping we did on eeprom init */ | 2751 | * backmapping we did on eeprom init */ |
2679 | u8 idx = pdg_curve_to_idx[pdg]; | 2752 | u8 idx = pdg_curve_to_idx[pdg]; |
2680 | 2753 | ||
2681 | /* Grab the needed curves by index */ | 2754 | /* Grab the needed curves by index */ |
@@ -2777,7 +2850,7 @@ ath5k_setup_channel_powertable(struct ath5k_hw *ah, | |||
2777 | /* Now we have a set of curves for this | 2850 | /* Now we have a set of curves for this |
2778 | * channel on tmpL (x range is table_max - table_min | 2851 | * channel on tmpL (x range is table_max - table_min |
2779 | * and y values are tmpL[pdg][]) sorted in the same | 2852 | * and y values are tmpL[pdg][]) sorted in the same |
2780 | * order as EEPROM (because we've used the backmaping). | 2853 | * order as EEPROM (because we've used the backmapping). |
2781 | * So for RF5112 it's from higher power to lower power | 2854 | * So for RF5112 it's from higher power to lower power |
2782 | * and for RF2413 it's from lower power to higher power. | 2855 | * and for RF2413 it's from lower power to higher power. |
2783 | * For RF5111 we only have one curve. */ | 2856 | * For RF5111 we only have one curve. */ |
@@ -2954,8 +3027,6 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, | |||
2954 | ATH5K_ERR(ah->ah_sc, "invalid tx power: %u\n", txpower); | 3027 | ATH5K_ERR(ah->ah_sc, "invalid tx power: %u\n", txpower); |
2955 | return -EINVAL; | 3028 | return -EINVAL; |
2956 | } | 3029 | } |
2957 | if (txpower == 0) | ||
2958 | txpower = AR5K_TUNE_DEFAULT_TXPOWER; | ||
2959 | 3030 | ||
2960 | /* Reset TX power values */ | 3031 | /* Reset TX power values */ |
2961 | memset(&ah->ah_txpower, 0, sizeof(ah->ah_txpower)); | 3032 | memset(&ah->ah_txpower, 0, sizeof(ah->ah_txpower)); |
diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c index eeebb9aef206..9122a8556f45 100644 --- a/drivers/net/wireless/ath/ath5k/qcu.c +++ b/drivers/net/wireless/ath/ath5k/qcu.c | |||
@@ -408,12 +408,13 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) | |||
408 | break; | 408 | break; |
409 | 409 | ||
410 | case AR5K_TX_QUEUE_CAB: | 410 | case AR5K_TX_QUEUE_CAB: |
411 | /* XXX: use BCN_SENT_GT, if we can figure out how */ | ||
411 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), | 412 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), |
412 | AR5K_QCU_MISC_FRSHED_BCN_SENT_GT | | 413 | AR5K_QCU_MISC_FRSHED_DBA_GT | |
413 | AR5K_QCU_MISC_CBREXP_DIS | | 414 | AR5K_QCU_MISC_CBREXP_DIS | |
414 | AR5K_QCU_MISC_CBREXP_BCN_DIS); | 415 | AR5K_QCU_MISC_CBREXP_BCN_DIS); |
415 | 416 | ||
416 | ath5k_hw_reg_write(ah, ((AR5K_TUNE_BEACON_INTERVAL - | 417 | ath5k_hw_reg_write(ah, ((tq->tqi_ready_time - |
417 | (AR5K_TUNE_SW_BEACON_RESP - | 418 | (AR5K_TUNE_SW_BEACON_RESP - |
418 | AR5K_TUNE_DMA_BEACON_RESP) - | 419 | AR5K_TUNE_DMA_BEACON_RESP) - |
419 | AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF) * 1024) | | 420 | AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF) * 1024) | |
@@ -520,12 +521,16 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) | |||
520 | */ | 521 | */ |
521 | unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah) | 522 | unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah) |
522 | { | 523 | { |
524 | unsigned int slot_time_clock; | ||
525 | |||
523 | ATH5K_TRACE(ah->ah_sc); | 526 | ATH5K_TRACE(ah->ah_sc); |
527 | |||
524 | if (ah->ah_version == AR5K_AR5210) | 528 | if (ah->ah_version == AR5K_AR5210) |
525 | return ath5k_hw_clocktoh(ath5k_hw_reg_read(ah, | 529 | slot_time_clock = ath5k_hw_reg_read(ah, AR5K_SLOT_TIME); |
526 | AR5K_SLOT_TIME) & 0xffff, ah->ah_turbo); | ||
527 | else | 530 | else |
528 | return ath5k_hw_reg_read(ah, AR5K_DCU_GBL_IFS_SLOT) & 0xffff; | 531 | slot_time_clock = ath5k_hw_reg_read(ah, AR5K_DCU_GBL_IFS_SLOT); |
532 | |||
533 | return ath5k_hw_clocktoh(ah, slot_time_clock & 0xffff); | ||
529 | } | 534 | } |
530 | 535 | ||
531 | /* | 536 | /* |
@@ -533,15 +538,17 @@ unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah) | |||
533 | */ | 538 | */ |
534 | int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time) | 539 | int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time) |
535 | { | 540 | { |
541 | u32 slot_time_clock = ath5k_hw_htoclock(ah, slot_time); | ||
542 | |||
536 | ATH5K_TRACE(ah->ah_sc); | 543 | ATH5K_TRACE(ah->ah_sc); |
537 | if (slot_time < AR5K_SLOT_TIME_9 || slot_time > AR5K_SLOT_TIME_MAX) | 544 | |
545 | if (slot_time < 6 || slot_time_clock > AR5K_SLOT_TIME_MAX) | ||
538 | return -EINVAL; | 546 | return -EINVAL; |
539 | 547 | ||
540 | if (ah->ah_version == AR5K_AR5210) | 548 | if (ah->ah_version == AR5K_AR5210) |
541 | ath5k_hw_reg_write(ah, ath5k_hw_htoclock(slot_time, | 549 | ath5k_hw_reg_write(ah, slot_time_clock, AR5K_SLOT_TIME); |
542 | ah->ah_turbo), AR5K_SLOT_TIME); | ||
543 | else | 550 | else |
544 | ath5k_hw_reg_write(ah, slot_time, AR5K_DCU_GBL_IFS_SLOT); | 551 | ath5k_hw_reg_write(ah, slot_time_clock, AR5K_DCU_GBL_IFS_SLOT); |
545 | 552 | ||
546 | return 0; | 553 | return 0; |
547 | } | 554 | } |
diff --git a/drivers/net/wireless/ath/ath5k/reg.h b/drivers/net/wireless/ath/ath5k/reg.h index c63ea6afd96f..1464f89b249c 100644 --- a/drivers/net/wireless/ath/ath5k/reg.h +++ b/drivers/net/wireless/ath/ath5k/reg.h | |||
@@ -35,7 +35,7 @@ | |||
35 | * released by Atheros and on various debug messages found on the net. | 35 | * released by Atheros and on various debug messages found on the net. |
36 | */ | 36 | */ |
37 | 37 | ||
38 | 38 | #include "../reg.h" | |
39 | 39 | ||
40 | /*====MAC DMA REGISTERS====*/ | 40 | /*====MAC DMA REGISTERS====*/ |
41 | 41 | ||
@@ -1650,12 +1650,6 @@ | |||
1650 | #define AR5K_SLEEP2_DTIM_PER_S 16 | 1650 | #define AR5K_SLEEP2_DTIM_PER_S 16 |
1651 | 1651 | ||
1652 | /* | 1652 | /* |
1653 | * BSSID mask registers | ||
1654 | */ | ||
1655 | #define AR5K_BSS_IDM0 0x80e0 /* Upper bits */ | ||
1656 | #define AR5K_BSS_IDM1 0x80e4 /* Lower bits */ | ||
1657 | |||
1658 | /* | ||
1659 | * TX power control (TPC) register | 1653 | * TX power control (TPC) register |
1660 | * | 1654 | * |
1661 | * XXX: PCDAC steps (0.5dbm) or DBM ? | 1655 | * XXX: PCDAC steps (0.5dbm) or DBM ? |
@@ -2039,17 +2033,14 @@ | |||
2039 | #define AR5K_PHY_AGCCTL_NF_NOUPDATE 0x00020000 /* Don't update nf automaticaly */ | 2033 | #define AR5K_PHY_AGCCTL_NF_NOUPDATE 0x00020000 /* Don't update nf automaticaly */ |
2040 | 2034 | ||
2041 | /* | 2035 | /* |
2042 | * PHY noise floor status register | 2036 | * PHY noise floor status register (CCA = Clear Channel Assessment) |
2043 | */ | 2037 | */ |
2044 | #define AR5K_PHY_NF 0x9864 /* Register address */ | 2038 | #define AR5K_PHY_NF 0x9864 /* Register address */ |
2045 | #define AR5K_PHY_NF_M 0x000001ff /* Noise floor mask */ | 2039 | #define AR5K_PHY_NF_M 0x000001ff /* Noise floor, written to hardware in 1/2 dBm units */ |
2046 | #define AR5K_PHY_NF_ACTIVE 0x00000100 /* Noise floor calibration still active */ | 2040 | #define AR5K_PHY_NF_SVAL(_n) (((_n) & AR5K_PHY_NF_M) | (1 << 9)) |
2047 | #define AR5K_PHY_NF_RVAL(_n) (((_n) >> 19) & AR5K_PHY_NF_M) | ||
2048 | #define AR5K_PHY_NF_AVAL(_n) (-((_n) ^ AR5K_PHY_NF_M) + 1) | ||
2049 | #define AR5K_PHY_NF_SVAL(_n) (((_n) & AR5K_PHY_NF_M) | (1 << 9)) | ||
2050 | #define AR5K_PHY_NF_THRESH62 0x0007f000 /* Thresh62 -check ANI patent- (field) */ | 2041 | #define AR5K_PHY_NF_THRESH62 0x0007f000 /* Thresh62 -check ANI patent- (field) */ |
2051 | #define AR5K_PHY_NF_THRESH62_S 12 | 2042 | #define AR5K_PHY_NF_THRESH62_S 12 |
2052 | #define AR5K_PHY_NF_MINCCA_PWR 0x0ff80000 /* ??? */ | 2043 | #define AR5K_PHY_NF_MINCCA_PWR 0x0ff80000 /* Minimum measured noise level, read from hardware in 1 dBm units */ |
2053 | #define AR5K_PHY_NF_MINCCA_PWR_S 19 | 2044 | #define AR5K_PHY_NF_MINCCA_PWR_S 19 |
2054 | 2045 | ||
2055 | /* | 2046 | /* |
@@ -2196,6 +2187,7 @@ | |||
2196 | */ | 2187 | */ |
2197 | #define AR5K_PHY_IQ 0x9920 /* Register Address */ | 2188 | #define AR5K_PHY_IQ 0x9920 /* Register Address */ |
2198 | #define AR5K_PHY_IQ_CORR_Q_Q_COFF 0x0000001f /* Mask for q correction info */ | 2189 | #define AR5K_PHY_IQ_CORR_Q_Q_COFF 0x0000001f /* Mask for q correction info */ |
2190 | #define AR5K_PHY_IQ_CORR_Q_Q_COFF_S 0 | ||
2199 | #define AR5K_PHY_IQ_CORR_Q_I_COFF 0x000007e0 /* Mask for i correction info */ | 2191 | #define AR5K_PHY_IQ_CORR_Q_I_COFF 0x000007e0 /* Mask for i correction info */ |
2200 | #define AR5K_PHY_IQ_CORR_Q_I_COFF_S 5 | 2192 | #define AR5K_PHY_IQ_CORR_Q_I_COFF_S 5 |
2201 | #define AR5K_PHY_IQ_CORR_ENABLE 0x00000800 /* Enable i/q correction */ | 2193 | #define AR5K_PHY_IQ_CORR_ENABLE 0x00000800 /* Enable i/q correction */ |
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index 34e13c700849..cbf28e379843 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c | |||
@@ -25,6 +25,8 @@ | |||
25 | Reset functions and helpers | 25 | Reset functions and helpers |
26 | \*****************************/ | 26 | \*****************************/ |
27 | 27 | ||
28 | #include <asm/unaligned.h> | ||
29 | |||
28 | #include <linux/pci.h> /* To determine if a card is pci-e */ | 30 | #include <linux/pci.h> /* To determine if a card is pci-e */ |
29 | #include <linux/log2.h> | 31 | #include <linux/log2.h> |
30 | #include "ath5k.h" | 32 | #include "ath5k.h" |
@@ -58,12 +60,11 @@ static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah, | |||
58 | !(channel->hw_value & CHANNEL_OFDM)); | 60 | !(channel->hw_value & CHANNEL_OFDM)); |
59 | 61 | ||
60 | /* Get coefficient | 62 | /* Get coefficient |
61 | * ALGO: coef = (5 * clock * carrier_freq) / 2) | 63 | * ALGO: coef = (5 * clock / carrier_freq) / 2 |
62 | * we scale coef by shifting clock value by 24 for | 64 | * we scale coef by shifting clock value by 24 for |
63 | * better precision since we use integers */ | 65 | * better precision since we use integers */ |
64 | /* TODO: Half/quarter rate */ | 66 | /* TODO: Half/quarter rate */ |
65 | clock = ath5k_hw_htoclock(1, channel->hw_value & CHANNEL_TURBO); | 67 | clock = (channel->hw_value & CHANNEL_TURBO) ? 80 : 40; |
66 | |||
67 | coef_scaled = ((5 * (clock << 24)) / 2) / channel->center_freq; | 68 | coef_scaled = ((5 * (clock << 24)) / 2) / channel->center_freq; |
68 | 69 | ||
69 | /* Get exponent | 70 | /* Get exponent |
@@ -850,12 +851,15 @@ static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, | |||
850 | AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1, | 851 | AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1, |
851 | AR5K_INIT_CYCRSSI_THR1); | 852 | AR5K_INIT_CYCRSSI_THR1); |
852 | 853 | ||
853 | /* I/Q correction | 854 | /* I/Q correction (set enable bit last to match HAL sources) */ |
854 | * TODO: Per channel i/q infos ? */ | 855 | /* TODO: Per channel i/q infos ? */ |
855 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, | 856 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) { |
856 | AR5K_PHY_IQ_CORR_ENABLE | | 857 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_Q_I_COFF, |
857 | (ee->ee_i_cal[ee_mode] << AR5K_PHY_IQ_CORR_Q_I_COFF_S) | | 858 | ee->ee_i_cal[ee_mode]); |
858 | ee->ee_q_cal[ee_mode]); | 859 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_Q_Q_COFF, |
860 | ee->ee_q_cal[ee_mode]); | ||
861 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_ENABLE); | ||
862 | } | ||
859 | 863 | ||
860 | /* Heavy clipping -disable for now */ | 864 | /* Heavy clipping -disable for now */ |
861 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_1) | 865 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_1) |
@@ -870,6 +874,7 @@ static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, | |||
870 | int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | 874 | int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, |
871 | struct ieee80211_channel *channel, bool change_channel) | 875 | struct ieee80211_channel *channel, bool change_channel) |
872 | { | 876 | { |
877 | struct ath_common *common = ath5k_hw_common(ah); | ||
873 | u32 s_seq[10], s_ant, s_led[3], staid1_flags, tsf_up, tsf_lo; | 878 | u32 s_seq[10], s_ant, s_led[3], staid1_flags, tsf_up, tsf_lo; |
874 | u32 phy_tst1; | 879 | u32 phy_tst1; |
875 | u8 mode, freq, ee_mode, ant[2]; | 880 | u8 mode, freq, ee_mode, ant[2]; |
@@ -1171,10 +1176,12 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
1171 | ath5k_hw_reg_write(ah, s_led[2], AR5K_GPIODO); | 1176 | ath5k_hw_reg_write(ah, s_led[2], AR5K_GPIODO); |
1172 | 1177 | ||
1173 | /* Restore sta_id flags and preserve our mac address*/ | 1178 | /* Restore sta_id flags and preserve our mac address*/ |
1174 | ath5k_hw_reg_write(ah, AR5K_LOW_ID(ah->ah_sta_id), | 1179 | ath5k_hw_reg_write(ah, |
1175 | AR5K_STA_ID0); | 1180 | get_unaligned_le32(common->macaddr), |
1176 | ath5k_hw_reg_write(ah, staid1_flags | AR5K_HIGH_ID(ah->ah_sta_id), | 1181 | AR5K_STA_ID0); |
1177 | AR5K_STA_ID1); | 1182 | ath5k_hw_reg_write(ah, |
1183 | staid1_flags | get_unaligned_le16(common->macaddr + 4), | ||
1184 | AR5K_STA_ID1); | ||
1178 | 1185 | ||
1179 | 1186 | ||
1180 | /* | 1187 | /* |
@@ -1182,8 +1189,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
1182 | */ | 1189 | */ |
1183 | 1190 | ||
1184 | /* Restore bssid and bssid mask */ | 1191 | /* Restore bssid and bssid mask */ |
1185 | /* XXX: add ah->aid once mac80211 gives this to us */ | 1192 | ath5k_hw_set_associd(ah); |
1186 | ath5k_hw_set_associd(ah, ah->ah_bssid, 0); | ||
1187 | 1193 | ||
1188 | /* Set PCU config */ | 1194 | /* Set PCU config */ |
1189 | ath5k_hw_set_opmode(ah); | 1195 | ath5k_hw_set_opmode(ah); |
@@ -1289,7 +1295,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
1289 | * out and/or noise floor calibration might timeout. | 1295 | * out and/or noise floor calibration might timeout. |
1290 | */ | 1296 | */ |
1291 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, | 1297 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, |
1292 | AR5K_PHY_AGCCTL_CAL); | 1298 | AR5K_PHY_AGCCTL_CAL | AR5K_PHY_AGCCTL_NF); |
1293 | 1299 | ||
1294 | /* At the same time start I/Q calibration for QAM constellation | 1300 | /* At the same time start I/Q calibration for QAM constellation |
1295 | * -no need for CCK- */ | 1301 | * -no need for CCK- */ |
@@ -1310,24 +1316,13 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
1310 | channel->center_freq); | 1316 | channel->center_freq); |
1311 | } | 1317 | } |
1312 | 1318 | ||
1313 | /* | ||
1314 | * If we run NF calibration before AGC, it always times out. | ||
1315 | * Binary HAL starts NF and AGC calibration at the same time | ||
1316 | * and only waits for AGC to finish. Also if AGC or NF cal. | ||
1317 | * times out, reset doesn't fail on binary HAL. I believe | ||
1318 | * that's wrong because since rx path is routed to a detector, | ||
1319 | * if cal. doesn't finish we won't have RX. Sam's HAL for AR5210/5211 | ||
1320 | * enables noise floor calibration after offset calibration and if noise | ||
1321 | * floor calibration fails, reset fails. I believe that's | ||
1322 | * a better approach, we just need to find a polling interval | ||
1323 | * that suits best, even if reset continues we need to make | ||
1324 | * sure that rx path is ready. | ||
1325 | */ | ||
1326 | ath5k_hw_noise_floor_calibration(ah, channel->center_freq); | ||
1327 | |||
1328 | /* Restore antenna mode */ | 1319 | /* Restore antenna mode */ |
1329 | ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode); | 1320 | ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode); |
1330 | 1321 | ||
1322 | /* Restore slot time and ACK timeouts */ | ||
1323 | if (ah->ah_coverage_class > 0) | ||
1324 | ath5k_hw_set_coverage_class(ah, ah->ah_coverage_class); | ||
1325 | |||
1331 | /* | 1326 | /* |
1332 | * Configure QCUs/DCUs | 1327 | * Configure QCUs/DCUs |
1333 | */ | 1328 | */ |
@@ -1382,15 +1377,15 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
1382 | * Set clocks to 32KHz operation and use an | 1377 | * Set clocks to 32KHz operation and use an |
1383 | * external 32KHz crystal when sleeping if one | 1378 | * external 32KHz crystal when sleeping if one |
1384 | * exists */ | 1379 | * exists */ |
1385 | if (ah->ah_version == AR5K_AR5212) | 1380 | if (ah->ah_version == AR5K_AR5212 && |
1386 | ath5k_hw_set_sleep_clock(ah, true); | 1381 | ah->ah_op_mode != NL80211_IFTYPE_AP) |
1382 | ath5k_hw_set_sleep_clock(ah, true); | ||
1387 | 1383 | ||
1388 | /* | 1384 | /* |
1389 | * Disable beacons and reset the register | 1385 | * Disable beacons and reset the TSF |
1390 | */ | 1386 | */ |
1391 | AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE | | 1387 | AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE); |
1392 | AR5K_BEACON_RESET_TSF); | 1388 | ath5k_hw_reset_tsf(ah); |
1393 | |||
1394 | return 0; | 1389 | return 0; |
1395 | } | 1390 | } |
1396 | 1391 | ||