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 | 53 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/attach.c | 33 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/base.c | 140 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/base.h | 14 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/initvals.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/led.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/pcu.c | 193 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/phy.c | 187 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/reg.h | 19 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/reset.c | 33 |
11 files changed, 314 insertions, 366 deletions
diff --git a/drivers/net/wireless/ath/ath5k/Kconfig b/drivers/net/wireless/ath/ath5k/Kconfig index 06d006675d7..eb83b7b4d0e 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 6cd5efcec41..6a2a9676111 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 |
@@ -1012,6 +1007,14 @@ struct ath5k_capabilities { | |||
1012 | } cap_queues; | 1007 | } cap_queues; |
1013 | }; | 1008 | }; |
1014 | 1009 | ||
1010 | /* size of noise floor history (keep it a power of two) */ | ||
1011 | #define ATH5K_NF_CAL_HIST_MAX 8 | ||
1012 | struct ath5k_nfcal_hist | ||
1013 | { | ||
1014 | s16 index; /* current index into nfval */ | ||
1015 | s16 nfval[ATH5K_NF_CAL_HIST_MAX]; /* last few noise floors */ | ||
1016 | }; | ||
1017 | |||
1015 | 1018 | ||
1016 | /***************************************\ | 1019 | /***************************************\ |
1017 | HARDWARE ABSTRACTION LAYER STRUCTURE | 1020 | HARDWARE ABSTRACTION LAYER STRUCTURE |
@@ -1027,6 +1030,7 @@ struct ath5k_capabilities { | |||
1027 | /* TODO: Clean up and merge with ath5k_softc */ | 1030 | /* TODO: Clean up and merge with ath5k_softc */ |
1028 | struct ath5k_hw { | 1031 | struct ath5k_hw { |
1029 | u32 ah_magic; | 1032 | u32 ah_magic; |
1033 | struct ath_common common; | ||
1030 | 1034 | ||
1031 | struct ath5k_softc *ah_sc; | 1035 | struct ath5k_softc *ah_sc; |
1032 | void __iomem *ah_iobase; | 1036 | void __iomem *ah_iobase; |
@@ -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 */ |
@@ -1203,10 +1201,9 @@ extern bool ath5k_eeprom_is_hb63(struct ath5k_hw *ah); | |||
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); |
1205 | /* BSSID Functions */ | 1203 | /* 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); | 1204 | 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); | 1205 | 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); | 1206 | extern void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask); |
1210 | /* Receive start/stop functions */ | 1207 | /* Receive start/stop functions */ |
1211 | extern void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah); | 1208 | extern void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah); |
1212 | extern void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah); | 1209 | extern void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah); |
@@ -1288,8 +1285,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); | 1285 | 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); | 1286 | extern int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel); |
1290 | /* PHY calibration */ | 1287 | /* PHY calibration */ |
1288 | 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); | 1289 | 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); | 1290 | extern int ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq); |
1291 | extern s16 ath5k_hw_get_noise_floor(struct ath5k_hw *ah); | ||
1293 | extern void ath5k_hw_calibration_poll(struct ath5k_hw *ah); | 1292 | extern void ath5k_hw_calibration_poll(struct ath5k_hw *ah); |
1294 | /* Spur mitigation */ | 1293 | /* Spur mitigation */ |
1295 | bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, | 1294 | bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, |
@@ -1329,17 +1328,21 @@ static inline unsigned int ath5k_hw_clocktoh(unsigned int clock, bool turbo) | |||
1329 | return turbo ? (clock / 80) : (clock / 40); | 1328 | return turbo ? (clock / 80) : (clock / 40); |
1330 | } | 1329 | } |
1331 | 1330 | ||
1332 | /* | 1331 | static inline struct ath_common *ath5k_hw_common(struct ath5k_hw *ah) |
1333 | * Read from a register | 1332 | { |
1334 | */ | 1333 | return &ah->common; |
1334 | } | ||
1335 | |||
1336 | static inline struct ath_regulatory *ath5k_hw_regulatory(struct ath5k_hw *ah) | ||
1337 | { | ||
1338 | return &(ath5k_hw_common(ah)->regulatory); | ||
1339 | } | ||
1340 | |||
1335 | static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg) | 1341 | static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg) |
1336 | { | 1342 | { |
1337 | return ioread32(ah->ah_iobase + reg); | 1343 | return ioread32(ah->ah_iobase + reg); |
1338 | } | 1344 | } |
1339 | 1345 | ||
1340 | /* | ||
1341 | * Write to a register | ||
1342 | */ | ||
1343 | static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg) | 1346 | static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg) |
1344 | { | 1347 | { |
1345 | iowrite32(val, ah->ah_iobase + reg); | 1348 | 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 71a1bd25451..42284445b75 100644 --- a/drivers/net/wireless/ath/ath5k/attach.c +++ b/drivers/net/wireless/ath/ath5k/attach.c | |||
@@ -101,25 +101,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 | 101 | * -ENODEV if the device is not supported or prints an error msg if something |
102 | * else went wrong. | 102 | * else went wrong. |
103 | */ | 103 | */ |
104 | struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc) | 104 | int ath5k_hw_attach(struct ath5k_softc *sc) |
105 | { | 105 | { |
106 | struct ath5k_hw *ah; | 106 | struct ath5k_hw *ah = sc->ah; |
107 | struct ath_common *common = ath5k_hw_common(ah); | ||
107 | struct pci_dev *pdev = sc->pdev; | 108 | struct pci_dev *pdev = sc->pdev; |
108 | struct ath5k_eeprom_info *ee; | 109 | struct ath5k_eeprom_info *ee; |
109 | int ret; | 110 | int ret; |
110 | u32 srev; | 111 | u32 srev; |
111 | 112 | ||
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 | /* | 113 | /* |
124 | * HW information | 114 | * HW information |
125 | */ | 115 | */ |
@@ -278,12 +268,12 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc) | |||
278 | goto err_free; | 268 | goto err_free; |
279 | } | 269 | } |
280 | 270 | ||
271 | ee = &ah->ah_capabilities.cap_eeprom; | ||
272 | |||
281 | /* | 273 | /* |
282 | * Write PCI-E power save settings | 274 | * Write PCI-E power save settings |
283 | */ | 275 | */ |
284 | if ((ah->ah_version == AR5K_AR5212) && (pdev->is_pcie)) { | 276 | 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); | 277 | ath5k_hw_reg_write(ah, 0x9248fc00, AR5K_PCIE_SERDES); |
288 | ath5k_hw_reg_write(ah, 0x24924924, AR5K_PCIE_SERDES); | 278 | ath5k_hw_reg_write(ah, 0x24924924, AR5K_PCIE_SERDES); |
289 | 279 | ||
@@ -321,7 +311,6 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc) | |||
321 | } | 311 | } |
322 | 312 | ||
323 | /* Crypto settings */ | 313 | /* Crypto settings */ |
324 | ee = &ah->ah_capabilities.cap_eeprom; | ||
325 | ah->ah_aes_support = srev >= AR5K_SREV_AR5212_V4 && | 314 | ah->ah_aes_support = srev >= AR5K_SREV_AR5212_V4 && |
326 | (ee->ee_version >= AR5K_EEPROM_VERSION_5_0 && | 315 | (ee->ee_version >= AR5K_EEPROM_VERSION_5_0 && |
327 | !AR5K_EEPROM_AES_DIS(ee->ee_misc5)); | 316 | !AR5K_EEPROM_AES_DIS(ee->ee_misc5)); |
@@ -336,20 +325,21 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc) | |||
336 | ath5k_hw_set_lladdr(ah, (u8[ETH_ALEN]){}); | 325 | ath5k_hw_set_lladdr(ah, (u8[ETH_ALEN]){}); |
337 | 326 | ||
338 | /* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */ | 327 | /* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */ |
339 | memset(ah->ah_bssid, 0xff, ETH_ALEN); | 328 | memcpy(common->curbssid, ath_bcast_mac, ETH_ALEN); |
340 | ath5k_hw_set_associd(ah, ah->ah_bssid, 0); | 329 | ath5k_hw_set_associd(ah); |
341 | ath5k_hw_set_opmode(ah); | 330 | ath5k_hw_set_opmode(ah); |
342 | 331 | ||
343 | ath5k_hw_rfgain_opt_init(ah); | 332 | ath5k_hw_rfgain_opt_init(ah); |
344 | 333 | ||
334 | ath5k_hw_init_nfcal_hist(ah); | ||
335 | |||
345 | /* turn on HW LEDs */ | 336 | /* turn on HW LEDs */ |
346 | ath5k_hw_set_ledstate(ah, AR5K_LED_INIT); | 337 | ath5k_hw_set_ledstate(ah, AR5K_LED_INIT); |
347 | 338 | ||
348 | return ah; | 339 | return 0; |
349 | err_free: | 340 | err_free: |
350 | kfree(ah); | 341 | kfree(ah); |
351 | err: | 342 | return ret; |
352 | return ERR_PTR(ret); | ||
353 | } | 343 | } |
354 | 344 | ||
355 | /** | 345 | /** |
@@ -369,5 +359,4 @@ void ath5k_hw_detach(struct ath5k_hw *ah) | |||
369 | ath5k_eeprom_detach(ah); | 359 | ath5k_eeprom_detach(ah); |
370 | 360 | ||
371 | /* assume interrupts are down */ | 361 | /* assume interrupts are down */ |
372 | kfree(ah); | ||
373 | } | 362 | } |
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 95a8e232b58..a4c086f069b 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
@@ -195,12 +195,13 @@ static int __devinit ath5k_pci_probe(struct pci_dev *pdev, | |||
195 | const struct pci_device_id *id); | 195 | const struct pci_device_id *id); |
196 | static void __devexit ath5k_pci_remove(struct pci_dev *pdev); | 196 | static void __devexit ath5k_pci_remove(struct pci_dev *pdev); |
197 | #ifdef CONFIG_PM | 197 | #ifdef CONFIG_PM |
198 | static int ath5k_pci_suspend(struct pci_dev *pdev, | 198 | static int ath5k_pci_suspend(struct device *dev); |
199 | pm_message_t state); | 199 | static int ath5k_pci_resume(struct device *dev); |
200 | static int ath5k_pci_resume(struct pci_dev *pdev); | 200 | |
201 | SIMPLE_DEV_PM_OPS(ath5k_pm_ops, ath5k_pci_suspend, ath5k_pci_resume); | ||
202 | #define ATH5K_PM_OPS (&ath5k_pm_ops) | ||
201 | #else | 203 | #else |
202 | #define ath5k_pci_suspend NULL | 204 | #define ATH5K_PM_OPS NULL |
203 | #define ath5k_pci_resume NULL | ||
204 | #endif /* CONFIG_PM */ | 205 | #endif /* CONFIG_PM */ |
205 | 206 | ||
206 | static struct pci_driver ath5k_pci_driver = { | 207 | static struct pci_driver ath5k_pci_driver = { |
@@ -208,8 +209,7 @@ static struct pci_driver ath5k_pci_driver = { | |||
208 | .id_table = ath5k_pci_id_table, | 209 | .id_table = ath5k_pci_id_table, |
209 | .probe = ath5k_pci_probe, | 210 | .probe = ath5k_pci_probe, |
210 | .remove = __devexit_p(ath5k_pci_remove), | 211 | .remove = __devexit_p(ath5k_pci_remove), |
211 | .suspend = ath5k_pci_suspend, | 212 | .driver.pm = ATH5K_PM_OPS, |
212 | .resume = ath5k_pci_resume, | ||
213 | }; | 213 | }; |
214 | 214 | ||
215 | 215 | ||
@@ -323,10 +323,13 @@ static inline void ath5k_txbuf_free(struct ath5k_softc *sc, | |||
323 | static inline void ath5k_rxbuf_free(struct ath5k_softc *sc, | 323 | static inline void ath5k_rxbuf_free(struct ath5k_softc *sc, |
324 | struct ath5k_buf *bf) | 324 | struct ath5k_buf *bf) |
325 | { | 325 | { |
326 | struct ath5k_hw *ah = sc->ah; | ||
327 | struct ath_common *common = ath5k_hw_common(ah); | ||
328 | |||
326 | BUG_ON(!bf); | 329 | BUG_ON(!bf); |
327 | if (!bf->skb) | 330 | if (!bf->skb) |
328 | return; | 331 | return; |
329 | pci_unmap_single(sc->pdev, bf->skbaddr, sc->rxbufsize, | 332 | pci_unmap_single(sc->pdev, bf->skbaddr, common->rx_bufsize, |
330 | PCI_DMA_FROMDEVICE); | 333 | PCI_DMA_FROMDEVICE); |
331 | dev_kfree_skb_any(bf->skb); | 334 | dev_kfree_skb_any(bf->skb); |
332 | bf->skb = NULL; | 335 | bf->skb = NULL; |
@@ -437,6 +440,22 @@ ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val) | |||
437 | 440 | ||
438 | return name; | 441 | return name; |
439 | } | 442 | } |
443 | static unsigned int ath5k_ioread32(void *hw_priv, u32 reg_offset) | ||
444 | { | ||
445 | struct ath5k_hw *ah = (struct ath5k_hw *) hw_priv; | ||
446 | return ath5k_hw_reg_read(ah, reg_offset); | ||
447 | } | ||
448 | |||
449 | static void ath5k_iowrite32(void *hw_priv, u32 val, u32 reg_offset) | ||
450 | { | ||
451 | struct ath5k_hw *ah = (struct ath5k_hw *) hw_priv; | ||
452 | ath5k_hw_reg_write(ah, val, reg_offset); | ||
453 | } | ||
454 | |||
455 | static const struct ath_ops ath5k_common_ops = { | ||
456 | .read = ath5k_ioread32, | ||
457 | .write = ath5k_iowrite32, | ||
458 | }; | ||
440 | 459 | ||
441 | static int __devinit | 460 | static int __devinit |
442 | ath5k_pci_probe(struct pci_dev *pdev, | 461 | ath5k_pci_probe(struct pci_dev *pdev, |
@@ -444,6 +463,7 @@ ath5k_pci_probe(struct pci_dev *pdev, | |||
444 | { | 463 | { |
445 | void __iomem *mem; | 464 | void __iomem *mem; |
446 | struct ath5k_softc *sc; | 465 | struct ath5k_softc *sc; |
466 | struct ath_common *common; | ||
447 | struct ieee80211_hw *hw; | 467 | struct ieee80211_hw *hw; |
448 | int ret; | 468 | int ret; |
449 | u8 csz; | 469 | u8 csz; |
@@ -547,7 +567,6 @@ ath5k_pci_probe(struct pci_dev *pdev, | |||
547 | __set_bit(ATH_STAT_INVALID, sc->status); | 567 | __set_bit(ATH_STAT_INVALID, sc->status); |
548 | 568 | ||
549 | sc->iobase = mem; /* So we can unmap it on detach */ | 569 | 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; | 570 | sc->opmode = NL80211_IFTYPE_STATION; |
552 | sc->bintval = 1000; | 571 | sc->bintval = 1000; |
553 | mutex_init(&sc->lock); | 572 | mutex_init(&sc->lock); |
@@ -565,13 +584,28 @@ ath5k_pci_probe(struct pci_dev *pdev, | |||
565 | goto err_free; | 584 | goto err_free; |
566 | } | 585 | } |
567 | 586 | ||
568 | /* Initialize device */ | 587 | /*If we passed the test malloc a ath5k_hw struct*/ |
569 | sc->ah = ath5k_hw_attach(sc); | 588 | sc->ah = kzalloc(sizeof(struct ath5k_hw), GFP_KERNEL); |
570 | if (IS_ERR(sc->ah)) { | 589 | if (!sc->ah) { |
571 | ret = PTR_ERR(sc->ah); | 590 | ret = -ENOMEM; |
591 | ATH5K_ERR(sc, "out of memory\n"); | ||
572 | goto err_irq; | 592 | goto err_irq; |
573 | } | 593 | } |
574 | 594 | ||
595 | sc->ah->ah_sc = sc; | ||
596 | sc->ah->ah_iobase = sc->iobase; | ||
597 | common = ath5k_hw_common(sc->ah); | ||
598 | common->ops = &ath5k_common_ops; | ||
599 | common->ah = sc->ah; | ||
600 | common->hw = hw; | ||
601 | common->cachelsz = csz << 2; /* convert to bytes */ | ||
602 | |||
603 | /* Initialize device */ | ||
604 | ret = ath5k_hw_attach(sc); | ||
605 | if (ret) { | ||
606 | goto err_free_ah; | ||
607 | } | ||
608 | |||
575 | /* set up multi-rate retry capabilities */ | 609 | /* set up multi-rate retry capabilities */ |
576 | if (sc->ah->ah_version == AR5K_AR5212) { | 610 | if (sc->ah->ah_version == AR5K_AR5212) { |
577 | hw->max_rates = 4; | 611 | hw->max_rates = 4; |
@@ -640,6 +674,8 @@ err_ah: | |||
640 | ath5k_hw_detach(sc->ah); | 674 | ath5k_hw_detach(sc->ah); |
641 | err_irq: | 675 | err_irq: |
642 | free_irq(pdev->irq, sc); | 676 | free_irq(pdev->irq, sc); |
677 | err_free_ah: | ||
678 | kfree(sc->ah); | ||
643 | err_free: | 679 | err_free: |
644 | ieee80211_free_hw(hw); | 680 | ieee80211_free_hw(hw); |
645 | err_map: | 681 | err_map: |
@@ -661,6 +697,7 @@ ath5k_pci_remove(struct pci_dev *pdev) | |||
661 | ath5k_debug_finish_device(sc); | 697 | ath5k_debug_finish_device(sc); |
662 | ath5k_detach(pdev, hw); | 698 | ath5k_detach(pdev, hw); |
663 | ath5k_hw_detach(sc->ah); | 699 | ath5k_hw_detach(sc->ah); |
700 | kfree(sc->ah); | ||
664 | free_irq(pdev->irq, sc); | 701 | free_irq(pdev->irq, sc); |
665 | pci_iounmap(pdev, sc->iobase); | 702 | pci_iounmap(pdev, sc->iobase); |
666 | pci_release_region(pdev, 0); | 703 | pci_release_region(pdev, 0); |
@@ -669,33 +706,20 @@ ath5k_pci_remove(struct pci_dev *pdev) | |||
669 | } | 706 | } |
670 | 707 | ||
671 | #ifdef CONFIG_PM | 708 | #ifdef CONFIG_PM |
672 | static int | 709 | static int ath5k_pci_suspend(struct device *dev) |
673 | ath5k_pci_suspend(struct pci_dev *pdev, pm_message_t state) | ||
674 | { | 710 | { |
675 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); | 711 | struct ieee80211_hw *hw = pci_get_drvdata(to_pci_dev(dev)); |
676 | struct ath5k_softc *sc = hw->priv; | 712 | struct ath5k_softc *sc = hw->priv; |
677 | 713 | ||
678 | ath5k_led_off(sc); | 714 | 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; | 715 | return 0; |
685 | } | 716 | } |
686 | 717 | ||
687 | static int | 718 | static int ath5k_pci_resume(struct device *dev) |
688 | ath5k_pci_resume(struct pci_dev *pdev) | ||
689 | { | 719 | { |
720 | struct pci_dev *pdev = to_pci_dev(dev); | ||
690 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); | 721 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); |
691 | struct ath5k_softc *sc = hw->priv; | 722 | 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 | 723 | ||
700 | /* | 724 | /* |
701 | * Suspend/Resume resets the PCI configuration space, so we have to | 725 | * Suspend/Resume resets the PCI configuration space, so we have to |
@@ -718,7 +742,7 @@ static int ath5k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *re | |||
718 | { | 742 | { |
719 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); | 743 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); |
720 | struct ath5k_softc *sc = hw->priv; | 744 | struct ath5k_softc *sc = hw->priv; |
721 | struct ath_regulatory *regulatory = &sc->common.regulatory; | 745 | struct ath_regulatory *regulatory = ath5k_hw_regulatory(sc->ah); |
722 | 746 | ||
723 | return ath_reg_notifier_apply(wiphy, request, regulatory); | 747 | return ath_reg_notifier_apply(wiphy, request, regulatory); |
724 | } | 748 | } |
@@ -728,7 +752,7 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) | |||
728 | { | 752 | { |
729 | struct ath5k_softc *sc = hw->priv; | 753 | struct ath5k_softc *sc = hw->priv; |
730 | struct ath5k_hw *ah = sc->ah; | 754 | struct ath5k_hw *ah = sc->ah; |
731 | struct ath_regulatory *regulatory = &sc->common.regulatory; | 755 | struct ath_regulatory *regulatory = ath5k_hw_regulatory(ah); |
732 | u8 mac[ETH_ALEN] = {}; | 756 | u8 mac[ETH_ALEN] = {}; |
733 | int ret; | 757 | int ret; |
734 | 758 | ||
@@ -815,7 +839,7 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) | |||
815 | 839 | ||
816 | SET_IEEE80211_PERM_ADDR(hw, mac); | 840 | SET_IEEE80211_PERM_ADDR(hw, mac); |
817 | /* All MAC address bits matter for ACKs */ | 841 | /* All MAC address bits matter for ACKs */ |
818 | memset(sc->bssidmask, 0xff, ETH_ALEN); | 842 | memcpy(sc->bssidmask, ath_bcast_mac, ETH_ALEN); |
819 | ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask); | 843 | ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask); |
820 | 844 | ||
821 | regulatory->current_rd = ah->ah_capabilities.cap_eeprom.ee_regdomain; | 845 | regulatory->current_rd = ah->ah_capabilities.cap_eeprom.ee_regdomain; |
@@ -1152,24 +1176,26 @@ ath5k_hw_to_driver_rix(struct ath5k_softc *sc, int hw_rix) | |||
1152 | static | 1176 | static |
1153 | struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_softc *sc, dma_addr_t *skb_addr) | 1177 | struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_softc *sc, dma_addr_t *skb_addr) |
1154 | { | 1178 | { |
1179 | struct ath_common *common = ath5k_hw_common(sc->ah); | ||
1155 | struct sk_buff *skb; | 1180 | struct sk_buff *skb; |
1156 | 1181 | ||
1157 | /* | 1182 | /* |
1158 | * Allocate buffer with headroom_needed space for the | 1183 | * Allocate buffer with headroom_needed space for the |
1159 | * fake physical layer header at the start. | 1184 | * fake physical layer header at the start. |
1160 | */ | 1185 | */ |
1161 | skb = ath_rxbuf_alloc(&sc->common, | 1186 | skb = ath_rxbuf_alloc(common, |
1162 | sc->rxbufsize + sc->common.cachelsz - 1, | 1187 | common->rx_bufsize, |
1163 | GFP_ATOMIC); | 1188 | GFP_ATOMIC); |
1164 | 1189 | ||
1165 | if (!skb) { | 1190 | if (!skb) { |
1166 | ATH5K_ERR(sc, "can't alloc skbuff of size %u\n", | 1191 | ATH5K_ERR(sc, "can't alloc skbuff of size %u\n", |
1167 | sc->rxbufsize + sc->common.cachelsz - 1); | 1192 | common->rx_bufsize); |
1168 | return NULL; | 1193 | return NULL; |
1169 | } | 1194 | } |
1170 | 1195 | ||
1171 | *skb_addr = pci_map_single(sc->pdev, | 1196 | *skb_addr = pci_map_single(sc->pdev, |
1172 | skb->data, sc->rxbufsize, PCI_DMA_FROMDEVICE); | 1197 | skb->data, common->rx_bufsize, |
1198 | PCI_DMA_FROMDEVICE); | ||
1173 | if (unlikely(pci_dma_mapping_error(sc->pdev, *skb_addr))) { | 1199 | if (unlikely(pci_dma_mapping_error(sc->pdev, *skb_addr))) { |
1174 | ATH5K_ERR(sc, "%s: DMA mapping failed\n", __func__); | 1200 | ATH5K_ERR(sc, "%s: DMA mapping failed\n", __func__); |
1175 | dev_kfree_skb(skb); | 1201 | dev_kfree_skb(skb); |
@@ -1605,13 +1631,14 @@ static int | |||
1605 | ath5k_rx_start(struct ath5k_softc *sc) | 1631 | ath5k_rx_start(struct ath5k_softc *sc) |
1606 | { | 1632 | { |
1607 | struct ath5k_hw *ah = sc->ah; | 1633 | struct ath5k_hw *ah = sc->ah; |
1634 | struct ath_common *common = ath5k_hw_common(ah); | ||
1608 | struct ath5k_buf *bf; | 1635 | struct ath5k_buf *bf; |
1609 | int ret; | 1636 | int ret; |
1610 | 1637 | ||
1611 | sc->rxbufsize = roundup(IEEE80211_MAX_LEN, sc->common.cachelsz); | 1638 | common->rx_bufsize = roundup(IEEE80211_MAX_LEN, common->cachelsz); |
1612 | 1639 | ||
1613 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "cachelsz %u rxbufsize %u\n", | 1640 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "cachelsz %u rx_bufsize %u\n", |
1614 | sc->common.cachelsz, sc->rxbufsize); | 1641 | common->cachelsz, common->rx_bufsize); |
1615 | 1642 | ||
1616 | spin_lock_bh(&sc->rxbuflock); | 1643 | spin_lock_bh(&sc->rxbuflock); |
1617 | sc->rxlink = NULL; | 1644 | sc->rxlink = NULL; |
@@ -1656,6 +1683,8 @@ static unsigned int | |||
1656 | ath5k_rx_decrypted(struct ath5k_softc *sc, struct ath5k_desc *ds, | 1683 | ath5k_rx_decrypted(struct ath5k_softc *sc, struct ath5k_desc *ds, |
1657 | struct sk_buff *skb, struct ath5k_rx_status *rs) | 1684 | struct sk_buff *skb, struct ath5k_rx_status *rs) |
1658 | { | 1685 | { |
1686 | struct ath5k_hw *ah = sc->ah; | ||
1687 | struct ath_common *common = ath5k_hw_common(ah); | ||
1659 | struct ieee80211_hdr *hdr = (void *)skb->data; | 1688 | struct ieee80211_hdr *hdr = (void *)skb->data; |
1660 | unsigned int keyix, hlen; | 1689 | unsigned int keyix, hlen; |
1661 | 1690 | ||
@@ -1672,7 +1701,7 @@ ath5k_rx_decrypted(struct ath5k_softc *sc, struct ath5k_desc *ds, | |||
1672 | skb->len >= hlen + 4) { | 1701 | skb->len >= hlen + 4) { |
1673 | keyix = skb->data[hlen + 3] >> 6; | 1702 | keyix = skb->data[hlen + 3] >> 6; |
1674 | 1703 | ||
1675 | if (test_bit(keyix, sc->keymap)) | 1704 | if (test_bit(keyix, common->keymap)) |
1676 | return RX_FLAG_DECRYPTED; | 1705 | return RX_FLAG_DECRYPTED; |
1677 | } | 1706 | } |
1678 | 1707 | ||
@@ -1684,13 +1713,14 @@ static void | |||
1684 | ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb, | 1713 | ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb, |
1685 | struct ieee80211_rx_status *rxs) | 1714 | struct ieee80211_rx_status *rxs) |
1686 | { | 1715 | { |
1716 | struct ath_common *common = ath5k_hw_common(sc->ah); | ||
1687 | u64 tsf, bc_tstamp; | 1717 | u64 tsf, bc_tstamp; |
1688 | u32 hw_tu; | 1718 | u32 hw_tu; |
1689 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; | 1719 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; |
1690 | 1720 | ||
1691 | if (ieee80211_is_beacon(mgmt->frame_control) && | 1721 | if (ieee80211_is_beacon(mgmt->frame_control) && |
1692 | le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS && | 1722 | le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS && |
1693 | memcmp(mgmt->bssid, sc->ah->ah_bssid, ETH_ALEN) == 0) { | 1723 | memcmp(mgmt->bssid, common->curbssid, ETH_ALEN) == 0) { |
1694 | /* | 1724 | /* |
1695 | * Received an IBSS beacon with the same BSSID. Hardware *must* | 1725 | * Received an IBSS beacon with the same BSSID. Hardware *must* |
1696 | * have updated the local TSF. We have to work around various | 1726 | * have updated the local TSF. We have to work around various |
@@ -1745,6 +1775,8 @@ ath5k_tasklet_rx(unsigned long data) | |||
1745 | struct sk_buff *skb, *next_skb; | 1775 | struct sk_buff *skb, *next_skb; |
1746 | dma_addr_t next_skb_addr; | 1776 | dma_addr_t next_skb_addr; |
1747 | struct ath5k_softc *sc = (void *)data; | 1777 | struct ath5k_softc *sc = (void *)data; |
1778 | struct ath5k_hw *ah = sc->ah; | ||
1779 | struct ath_common *common = ath5k_hw_common(ah); | ||
1748 | struct ath5k_buf *bf; | 1780 | struct ath5k_buf *bf; |
1749 | struct ath5k_desc *ds; | 1781 | struct ath5k_desc *ds; |
1750 | int ret; | 1782 | int ret; |
@@ -1822,7 +1854,7 @@ accept: | |||
1822 | if (!next_skb) | 1854 | if (!next_skb) |
1823 | goto next; | 1855 | goto next; |
1824 | 1856 | ||
1825 | pci_unmap_single(sc->pdev, bf->skbaddr, sc->rxbufsize, | 1857 | pci_unmap_single(sc->pdev, bf->skbaddr, common->rx_bufsize, |
1826 | PCI_DMA_FROMDEVICE); | 1858 | PCI_DMA_FROMDEVICE); |
1827 | skb_put(skb, rs.rs_datalen); | 1859 | skb_put(skb, rs.rs_datalen); |
1828 | 1860 | ||
@@ -3008,6 +3040,8 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
3008 | struct ieee80211_key_conf *key) | 3040 | struct ieee80211_key_conf *key) |
3009 | { | 3041 | { |
3010 | struct ath5k_softc *sc = hw->priv; | 3042 | struct ath5k_softc *sc = hw->priv; |
3043 | struct ath5k_hw *ah = sc->ah; | ||
3044 | struct ath_common *common = ath5k_hw_common(ah); | ||
3011 | int ret = 0; | 3045 | int ret = 0; |
3012 | 3046 | ||
3013 | if (modparam_nohwcrypt) | 3047 | if (modparam_nohwcrypt) |
@@ -3040,14 +3074,14 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
3040 | ATH5K_ERR(sc, "can't set the key\n"); | 3074 | ATH5K_ERR(sc, "can't set the key\n"); |
3041 | goto unlock; | 3075 | goto unlock; |
3042 | } | 3076 | } |
3043 | __set_bit(key->keyidx, sc->keymap); | 3077 | __set_bit(key->keyidx, common->keymap); |
3044 | key->hw_key_idx = key->keyidx; | 3078 | key->hw_key_idx = key->keyidx; |
3045 | key->flags |= (IEEE80211_KEY_FLAG_GENERATE_IV | | 3079 | key->flags |= (IEEE80211_KEY_FLAG_GENERATE_IV | |
3046 | IEEE80211_KEY_FLAG_GENERATE_MMIC); | 3080 | IEEE80211_KEY_FLAG_GENERATE_MMIC); |
3047 | break; | 3081 | break; |
3048 | case DISABLE_KEY: | 3082 | case DISABLE_KEY: |
3049 | ath5k_hw_reset_key(sc->ah, key->keyidx); | 3083 | ath5k_hw_reset_key(sc->ah, key->keyidx); |
3050 | __clear_bit(key->keyidx, sc->keymap); | 3084 | __clear_bit(key->keyidx, common->keymap); |
3051 | break; | 3085 | break; |
3052 | default: | 3086 | default: |
3053 | ret = -EINVAL; | 3087 | ret = -EINVAL; |
@@ -3176,6 +3210,7 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw, | |||
3176 | { | 3210 | { |
3177 | struct ath5k_softc *sc = hw->priv; | 3211 | struct ath5k_softc *sc = hw->priv; |
3178 | struct ath5k_hw *ah = sc->ah; | 3212 | struct ath5k_hw *ah = sc->ah; |
3213 | struct ath_common *common = ath5k_hw_common(ah); | ||
3179 | unsigned long flags; | 3214 | unsigned long flags; |
3180 | 3215 | ||
3181 | mutex_lock(&sc->lock); | 3216 | mutex_lock(&sc->lock); |
@@ -3184,10 +3219,9 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw, | |||
3184 | 3219 | ||
3185 | if (changes & BSS_CHANGED_BSSID) { | 3220 | if (changes & BSS_CHANGED_BSSID) { |
3186 | /* Cache for later use during resets */ | 3221 | /* Cache for later use during resets */ |
3187 | memcpy(ah->ah_bssid, bss_conf->bssid, ETH_ALEN); | 3222 | memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); |
3188 | /* XXX: assoc id is set to 0 for now, mac80211 doesn't have | 3223 | common->curaid = 0; |
3189 | * a clean way of letting us retrieve this yet. */ | 3224 | ath5k_hw_set_associd(ah); |
3190 | ath5k_hw_set_associd(ah, ah->ah_bssid, 0); | ||
3191 | mmiowb(); | 3225 | mmiowb(); |
3192 | } | 3226 | } |
3193 | 3227 | ||
@@ -3200,6 +3234,14 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw, | |||
3200 | set_beacon_filter(hw, sc->assoc); | 3234 | set_beacon_filter(hw, sc->assoc); |
3201 | ath5k_hw_set_ledstate(sc->ah, sc->assoc ? | 3235 | ath5k_hw_set_ledstate(sc->ah, sc->assoc ? |
3202 | AR5K_LED_ASSOC : AR5K_LED_INIT); | 3236 | AR5K_LED_ASSOC : AR5K_LED_INIT); |
3237 | if (bss_conf->assoc) { | ||
3238 | ATH5K_DBG(sc, ATH5K_DEBUG_ANY, | ||
3239 | "Bss Info ASSOC %d, bssid: %pM\n", | ||
3240 | bss_conf->aid, common->curbssid); | ||
3241 | common->curaid = bss_conf->aid; | ||
3242 | ath5k_hw_set_associd(ah); | ||
3243 | /* Once ANI is available you would start it here */ | ||
3244 | } | ||
3203 | } | 3245 | } |
3204 | 3246 | ||
3205 | if (changes & BSS_CHANGED_BEACON) { | 3247 | if (changes & BSS_CHANGED_BEACON) { |
diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h index a28c42f32c9..b72338c9bde 100644 --- a/drivers/net/wireless/ath/ath5k/base.h +++ b/drivers/net/wireless/ath/ath5k/base.h | |||
@@ -115,7 +115,6 @@ 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]; | 120 | struct ieee80211_tx_queue_stats tx_stats[AR5K_NUM_TX_QUEUES]; |
@@ -154,8 +153,6 @@ struct ath5k_softc { | |||
154 | 153 | ||
155 | enum ath5k_int imask; /* interrupt mask copy */ | 154 | enum ath5k_int imask; /* interrupt mask copy */ |
156 | 155 | ||
157 | DECLARE_BITMAP(keymap, AR5K_KEYCACHE_SIZE); /* key use bit map */ | ||
158 | |||
159 | u8 bssidmask[ETH_ALEN]; | 156 | u8 bssidmask[ETH_ALEN]; |
160 | 157 | ||
161 | unsigned int led_pin, /* GPIO pin for driving LED */ | 158 | unsigned int led_pin, /* GPIO pin for driving LED */ |
@@ -202,15 +199,4 @@ struct ath5k_softc { | |||
202 | #define ath5k_hw_hasveol(_ah) \ | 199 | #define ath5k_hw_hasveol(_ah) \ |
203 | (ath5k_hw_get_capability(_ah, AR5K_CAP_VEOL, 0, NULL) == 0) | 200 | (ath5k_hw_get_capability(_ah, AR5K_CAP_VEOL, 0, NULL) == 0) |
204 | 201 | ||
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 | 202 | #endif |
diff --git a/drivers/net/wireless/ath/ath5k/initvals.c b/drivers/net/wireless/ath/ath5k/initvals.c index 18eb5190ce4..8fa43930882 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 b548c8eaaae..d495890355d 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) */ |
diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index 2942f13c9c4..64fc1eb9b6d 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 | ||
@@ -238,28 +241,6 @@ int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout) | |||
238 | return 0; | 241 | return 0; |
239 | } | 242 | } |
240 | 243 | ||
241 | |||
242 | /****************\ | ||
243 | * BSSID handling * | ||
244 | \****************/ | ||
245 | |||
246 | /** | ||
247 | * ath5k_hw_get_lladdr - Get station id | ||
248 | * | ||
249 | * @ah: The &struct ath5k_hw | ||
250 | * @mac: The card's mac address | ||
251 | * | ||
252 | * Initialize ah->ah_sta_id using the mac address provided | ||
253 | * (just a memcpy). | ||
254 | * | ||
255 | * TODO: Remove it once we merge ath5k_softc and ath5k_hw | ||
256 | */ | ||
257 | void ath5k_hw_get_lladdr(struct ath5k_hw *ah, u8 *mac) | ||
258 | { | ||
259 | ATH5K_TRACE(ah->ah_sc); | ||
260 | memcpy(mac, ah->ah_sta_id, ETH_ALEN); | ||
261 | } | ||
262 | |||
263 | /** | 244 | /** |
264 | * ath5k_hw_set_lladdr - Set station id | 245 | * ath5k_hw_set_lladdr - Set station id |
265 | * | 246 | * |
@@ -270,17 +251,18 @@ void ath5k_hw_get_lladdr(struct ath5k_hw *ah, u8 *mac) | |||
270 | */ | 251 | */ |
271 | int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac) | 252 | int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac) |
272 | { | 253 | { |
254 | struct ath_common *common = ath5k_hw_common(ah); | ||
273 | u32 low_id, high_id; | 255 | u32 low_id, high_id; |
274 | u32 pcu_reg; | 256 | u32 pcu_reg; |
275 | 257 | ||
276 | ATH5K_TRACE(ah->ah_sc); | 258 | ATH5K_TRACE(ah->ah_sc); |
277 | /* Set new station ID */ | 259 | /* Set new station ID */ |
278 | memcpy(ah->ah_sta_id, mac, ETH_ALEN); | 260 | memcpy(common->macaddr, mac, ETH_ALEN); |
279 | 261 | ||
280 | pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000; | 262 | pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000; |
281 | 263 | ||
282 | low_id = AR5K_LOW_ID(mac); | 264 | low_id = get_unaligned_le32(mac); |
283 | high_id = AR5K_HIGH_ID(mac); | 265 | high_id = get_unaligned_le16(mac + 4); |
284 | 266 | ||
285 | ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0); | 267 | ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0); |
286 | ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1); | 268 | ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1); |
@@ -297,159 +279,51 @@ int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac) | |||
297 | * | 279 | * |
298 | * Sets the BSSID which trigers the "SME Join" operation | 280 | * Sets the BSSID which trigers the "SME Join" operation |
299 | */ | 281 | */ |
300 | void ath5k_hw_set_associd(struct ath5k_hw *ah, const u8 *bssid, u16 assoc_id) | 282 | void ath5k_hw_set_associd(struct ath5k_hw *ah) |
301 | { | 283 | { |
302 | u32 low_id, high_id; | 284 | struct ath_common *common = ath5k_hw_common(ah); |
303 | u16 tim_offset = 0; | 285 | u16 tim_offset = 0; |
304 | 286 | ||
305 | /* | 287 | /* |
306 | * Set simple BSSID mask on 5212 | 288 | * Set simple BSSID mask on 5212 |
307 | */ | 289 | */ |
308 | if (ah->ah_version == AR5K_AR5212) { | 290 | if (ah->ah_version == AR5K_AR5212) |
309 | ath5k_hw_reg_write(ah, AR5K_LOW_ID(ah->ah_bssid_mask), | 291 | 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 | 292 | ||
315 | /* | 293 | /* |
316 | * Set BSSID which triggers the "SME Join" operation | 294 | * Set BSSID which triggers the "SME Join" operation |
317 | */ | 295 | */ |
318 | low_id = AR5K_LOW_ID(bssid); | 296 | ath5k_hw_reg_write(ah, |
319 | high_id = AR5K_HIGH_ID(bssid); | 297 | get_unaligned_le32(common->curbssid), |
320 | ath5k_hw_reg_write(ah, low_id, AR5K_BSS_ID0); | 298 | AR5K_BSS_ID0); |
321 | ath5k_hw_reg_write(ah, high_id | ((assoc_id & 0x3fff) << | 299 | ath5k_hw_reg_write(ah, |
322 | AR5K_BSS_ID1_AID_S), AR5K_BSS_ID1); | 300 | get_unaligned_le16(common->curbssid + 4) | |
323 | 301 | ((common->curaid & 0x3fff) << AR5K_BSS_ID1_AID_S), | |
324 | if (assoc_id == 0) { | 302 | AR5K_BSS_ID1); |
303 | |||
304 | if (common->curaid == 0) { | ||
325 | ath5k_hw_disable_pspoll(ah); | 305 | ath5k_hw_disable_pspoll(ah); |
326 | return; | 306 | return; |
327 | } | 307 | } |
328 | 308 | ||
329 | AR5K_REG_WRITE_BITS(ah, AR5K_BEACON, AR5K_BEACON_TIM, | 309 | AR5K_REG_WRITE_BITS(ah, AR5K_BEACON, AR5K_BEACON_TIM, |
330 | tim_offset ? tim_offset + 4 : 0); | 310 | tim_offset ? tim_offset + 4 : 0); |
331 | 311 | ||
332 | ath5k_hw_enable_pspoll(ah, NULL, 0); | 312 | ath5k_hw_enable_pspoll(ah, NULL, 0); |
333 | } | 313 | } |
334 | 314 | ||
335 | /** | 315 | 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 | { | 316 | { |
433 | u32 low_id, high_id; | 317 | struct ath_common *common = ath5k_hw_common(ah); |
434 | ATH5K_TRACE(ah->ah_sc); | 318 | ATH5K_TRACE(ah->ah_sc); |
435 | 319 | ||
436 | /* Cache bssid mask so that we can restore it | 320 | /* Cache bssid mask so that we can restore it |
437 | * on reset */ | 321 | * on reset */ |
438 | memcpy(ah->ah_bssid_mask, mask, ETH_ALEN); | 322 | memcpy(common->bssidmask, mask, ETH_ALEN); |
439 | if (ah->ah_version == AR5K_AR5212) { | 323 | if (ah->ah_version == AR5K_AR5212) |
440 | low_id = AR5K_LOW_ID(mask); | 324 | 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 | } | 325 | } |
451 | 326 | ||
452 | |||
453 | /************\ | 327 | /************\ |
454 | * RX Control * | 328 | * RX Control * |
455 | \************/ | 329 | \************/ |
@@ -1157,14 +1031,17 @@ int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac) | |||
1157 | /* Invalid entry (key table overflow) */ | 1031 | /* Invalid entry (key table overflow) */ |
1158 | AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE); | 1032 | AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE); |
1159 | 1033 | ||
1160 | /* MAC may be NULL if it's a broadcast key. In this case no need to | 1034 | /* |
1161 | * to compute AR5K_LOW_ID and AR5K_HIGH_ID as we already know it. */ | 1035 | * MAC may be NULL if it's a broadcast key. In this case no need to |
1036 | * to compute get_unaligned_le32 and get_unaligned_le16 as we | ||
1037 | * already know it. | ||
1038 | */ | ||
1162 | if (!mac) { | 1039 | if (!mac) { |
1163 | low_id = 0xffffffff; | 1040 | low_id = 0xffffffff; |
1164 | high_id = 0xffff | AR5K_KEYTABLE_VALID; | 1041 | high_id = 0xffff | AR5K_KEYTABLE_VALID; |
1165 | } else { | 1042 | } else { |
1166 | low_id = AR5K_LOW_ID(mac); | 1043 | low_id = get_unaligned_le32(mac); |
1167 | high_id = AR5K_HIGH_ID(mac) | AR5K_KEYTABLE_VALID; | 1044 | high_id = get_unaligned_le16(mac + 4) | AR5K_KEYTABLE_VALID; |
1168 | } | 1045 | } |
1169 | 1046 | ||
1170 | ath5k_hw_reg_write(ah, low_id, AR5K_KEYTABLE_MAC0(entry)); | 1047 | ath5k_hw_reg_write(ah, low_id, AR5K_KEYTABLE_MAC0(entry)); |
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 1a039f2bd73..721ec5ee381 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c | |||
@@ -1124,77 +1124,148 @@ ath5k_hw_calibration_poll(struct ath5k_hw *ah) | |||
1124 | ah->ah_swi_mask = AR5K_SWI_FULL_CALIBRATION; | 1124 | ah->ah_swi_mask = AR5K_SWI_FULL_CALIBRATION; |
1125 | AR5K_REG_ENABLE_BITS(ah, AR5K_CR, AR5K_CR_SWI); | 1125 | AR5K_REG_ENABLE_BITS(ah, AR5K_CR, AR5K_CR_SWI); |
1126 | } | 1126 | } |
1127 | } | ||
1127 | 1128 | ||
1129 | static int sign_extend(int val, const int nbits) | ||
1130 | { | ||
1131 | int order = BIT(nbits-1); | ||
1132 | return (val ^ order) - order; | ||
1128 | } | 1133 | } |
1129 | 1134 | ||
1130 | /** | 1135 | static s32 ath5k_hw_read_measured_noise_floor(struct ath5k_hw *ah) |
1131 | * ath5k_hw_noise_floor_calibration - perform PHY noise floor calibration | 1136 | { |
1132 | * | 1137 | s32 val; |
1133 | * @ah: struct ath5k_hw pointer we are operating on | 1138 | |
1134 | * @freq: the channel frequency, just used for error logging | 1139 | val = ath5k_hw_reg_read(ah, AR5K_PHY_NF); |
1135 | * | 1140 | 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 | 1141 | } |
1137 | * it to complete. Then the noise floor value is compared to some maximum | 1142 | |
1138 | * noise floor we consider valid. | 1143 | void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah) |
1139 | * | 1144 | { |
1140 | * Note that this is different from what the madwifi HAL does: it reads the | 1145 | int i; |
1141 | * noise floor and afterwards initiates the calibration. Since the noise floor | 1146 | |
1142 | * calibration can take some time to finish, depending on the current channel | 1147 | ah->ah_nfcal_hist.index = 0; |
1143 | * use, that avoids the occasional timeout warnings we are seeing now. | 1148 | for (i = 0; i < ATH5K_NF_CAL_HIST_MAX; i++) |
1144 | * | 1149 | 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: | 1150 | } |
1146 | * http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&Sect2=HITOFF&d=PALL \ | 1151 | |
1147 | * &p=1&u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&r=1&f=G&l=50&s1=7245893.PN.&OS=PN/7 | 1152 | static void ath5k_hw_update_nfcal_hist(struct ath5k_hw *ah, s16 noise_floor) |
1153 | { | ||
1154 | struct ath5k_nfcal_hist *hist = &ah->ah_nfcal_hist; | ||
1155 | hist->index = (hist->index + 1) & (ATH5K_NF_CAL_HIST_MAX-1); | ||
1156 | hist->nfval[hist->index] = noise_floor; | ||
1157 | } | ||
1158 | |||
1159 | static s16 ath5k_hw_get_median_noise_floor(struct ath5k_hw *ah) | ||
1160 | { | ||
1161 | s16 sort[ATH5K_NF_CAL_HIST_MAX]; | ||
1162 | s16 tmp; | ||
1163 | int i, j; | ||
1164 | |||
1165 | memcpy(sort, ah->ah_nfcal_hist.nfval, sizeof(sort)); | ||
1166 | for (i = 0; i < ATH5K_NF_CAL_HIST_MAX - 1; i++) { | ||
1167 | for (j = 1; j < ATH5K_NF_CAL_HIST_MAX - i; j++) { | ||
1168 | if (sort[j] > sort[j-1]) { | ||
1169 | tmp = sort[j]; | ||
1170 | sort[j] = sort[j-1]; | ||
1171 | sort[j-1] = tmp; | ||
1172 | } | ||
1173 | } | ||
1174 | } | ||
1175 | for (i = 0; i < ATH5K_NF_CAL_HIST_MAX; i++) { | ||
1176 | ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE, | ||
1177 | "cal %d:%d\n", i, sort[i]); | ||
1178 | } | ||
1179 | return sort[(ATH5K_NF_CAL_HIST_MAX-1) / 2]; | ||
1180 | } | ||
1181 | |||
1182 | /* | ||
1183 | * When we tell the hardware to perform a noise floor calibration | ||
1184 | * by setting the AR5K_PHY_AGCCTL_NF bit, it will periodically | ||
1185 | * sample-and-hold the minimum noise level seen at the antennas. | ||
1186 | * This value is then stored in a ring buffer of recently measured | ||
1187 | * noise floor values so we have a moving window of the last few | ||
1188 | * samples. | ||
1148 | * | 1189 | * |
1149 | * XXX: Since during noise floor calibration antennas are detached according to | 1190 | * The median of the values in the history is then loaded into the |
1150 | * the patent, we should stop tx queues here. | 1191 | * hardware for its own use for RSSI and CCA measurements. |
1151 | */ | 1192 | */ |
1152 | int | 1193 | void ath5k_hw_update_noise_floor(struct ath5k_hw *ah) |
1153 | ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq) | ||
1154 | { | 1194 | { |
1155 | int ret; | 1195 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; |
1156 | unsigned int i; | 1196 | u32 val; |
1157 | s32 noise_floor; | 1197 | s16 nf, threshold; |
1198 | u8 ee_mode; | ||
1158 | 1199 | ||
1159 | /* | 1200 | /* keep last value if calibration hasn't completed */ |
1160 | * Enable noise floor calibration | 1201 | if (ath5k_hw_reg_read(ah, AR5K_PHY_AGCCTL) & AR5K_PHY_AGCCTL_NF) { |
1161 | */ | 1202 | ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE, |
1162 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, | 1203 | "NF did not complete in calibration window\n"); |
1163 | AR5K_PHY_AGCCTL_NF); | ||
1164 | 1204 | ||
1165 | ret = ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL, | 1205 | 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 | } | 1206 | } |
1172 | 1207 | ||
1173 | /* Wait until the noise floor is calibrated and read the value */ | 1208 | switch (ah->ah_current_channel->hw_value & CHANNEL_MODES) { |
1174 | for (i = 20; i > 0; i--) { | 1209 | case CHANNEL_A: |
1175 | mdelay(1); | 1210 | case CHANNEL_T: |
1176 | noise_floor = ath5k_hw_reg_read(ah, AR5K_PHY_NF); | 1211 | case CHANNEL_XR: |
1177 | noise_floor = AR5K_PHY_NF_RVAL(noise_floor); | 1212 | ee_mode = AR5K_EEPROM_MODE_11A; |
1178 | if (noise_floor & AR5K_PHY_NF_ACTIVE) { | 1213 | break; |
1179 | noise_floor = AR5K_PHY_NF_AVAL(noise_floor); | 1214 | case CHANNEL_G: |
1180 | 1215 | case CHANNEL_TG: | |
1181 | if (noise_floor <= AR5K_TUNE_NOISE_FLOOR) | 1216 | ee_mode = AR5K_EEPROM_MODE_11G; |
1182 | break; | 1217 | break; |
1183 | } | 1218 | default: |
1219 | case CHANNEL_B: | ||
1220 | ee_mode = AR5K_EEPROM_MODE_11B; | ||
1221 | break; | ||
1184 | } | 1222 | } |
1185 | 1223 | ||
1186 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_CALIBRATE, | ||
1187 | "noise floor %d\n", noise_floor); | ||
1188 | 1224 | ||
1189 | if (noise_floor > AR5K_TUNE_NOISE_FLOOR) { | 1225 | /* completed NF calibration, test threshold */ |
1190 | ATH5K_ERR(ah->ah_sc, | 1226 | nf = ath5k_hw_read_measured_noise_floor(ah); |
1191 | "noise floor calibration failed (%uMHz)\n", freq); | 1227 | threshold = ee->ee_noise_floor_thr[ee_mode]; |
1192 | return -EAGAIN; | 1228 | |
1229 | if (nf > threshold) { | ||
1230 | ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE, | ||
1231 | "noise floor failure detected; " | ||
1232 | "read %d, threshold %d\n", | ||
1233 | nf, threshold); | ||
1234 | |||
1235 | nf = AR5K_TUNE_CCA_MAX_GOOD_VALUE; | ||
1193 | } | 1236 | } |
1194 | 1237 | ||
1195 | ah->ah_noise_floor = noise_floor; | 1238 | ath5k_hw_update_nfcal_hist(ah, nf); |
1239 | nf = ath5k_hw_get_median_noise_floor(ah); | ||
1196 | 1240 | ||
1197 | return 0; | 1241 | /* load noise floor (in .5 dBm) so the hardware will use it */ |
1242 | val = ath5k_hw_reg_read(ah, AR5K_PHY_NF) & ~AR5K_PHY_NF_M; | ||
1243 | val |= (nf * 2) & AR5K_PHY_NF_M; | ||
1244 | ath5k_hw_reg_write(ah, val, AR5K_PHY_NF); | ||
1245 | |||
1246 | AR5K_REG_MASKED_BITS(ah, AR5K_PHY_AGCCTL, AR5K_PHY_AGCCTL_NF, | ||
1247 | ~(AR5K_PHY_AGCCTL_NF_EN | AR5K_PHY_AGCCTL_NF_NOUPDATE)); | ||
1248 | |||
1249 | ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL, AR5K_PHY_AGCCTL_NF, | ||
1250 | 0, false); | ||
1251 | |||
1252 | /* | ||
1253 | * Load a high max CCA Power value (-50 dBm in .5 dBm units) | ||
1254 | * so that we're not capped by the median we just loaded. | ||
1255 | * This will be used as the initial value for the next noise | ||
1256 | * floor calibration. | ||
1257 | */ | ||
1258 | val = (val & ~AR5K_PHY_NF_M) | ((-50 * 2) & AR5K_PHY_NF_M); | ||
1259 | ath5k_hw_reg_write(ah, val, AR5K_PHY_NF); | ||
1260 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, | ||
1261 | AR5K_PHY_AGCCTL_NF_EN | | ||
1262 | AR5K_PHY_AGCCTL_NF_NOUPDATE | | ||
1263 | AR5K_PHY_AGCCTL_NF); | ||
1264 | |||
1265 | ah->ah_noise_floor = nf; | ||
1266 | |||
1267 | ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE, | ||
1268 | "noise floor calibrated: %d\n", nf); | ||
1198 | } | 1269 | } |
1199 | 1270 | ||
1200 | /* | 1271 | /* |
@@ -1287,7 +1358,7 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah, | |||
1287 | return ret; | 1358 | return ret; |
1288 | } | 1359 | } |
1289 | 1360 | ||
1290 | ath5k_hw_noise_floor_calibration(ah, channel->center_freq); | 1361 | ath5k_hw_update_noise_floor(ah); |
1291 | 1362 | ||
1292 | /* | 1363 | /* |
1293 | * Re-enable RX/TX and beacons | 1364 | * Re-enable RX/TX and beacons |
@@ -1360,7 +1431,7 @@ done: | |||
1360 | * since noise floor calibration interrupts rx path while I/Q | 1431 | * since noise floor calibration interrupts rx path while I/Q |
1361 | * calibration doesn't. We don't need to run noise floor calibration | 1432 | * calibration doesn't. We don't need to run noise floor calibration |
1362 | * as often as I/Q calibration.*/ | 1433 | * as often as I/Q calibration.*/ |
1363 | ath5k_hw_noise_floor_calibration(ah, channel->center_freq); | 1434 | ath5k_hw_update_noise_floor(ah); |
1364 | 1435 | ||
1365 | /* Initiate a gain_F calibration */ | 1436 | /* Initiate a gain_F calibration */ |
1366 | ath5k_hw_request_rfgain_probe(ah); | 1437 | ath5k_hw_request_rfgain_probe(ah); |
@@ -2954,8 +3025,6 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, | |||
2954 | ATH5K_ERR(ah->ah_sc, "invalid tx power: %u\n", txpower); | 3025 | ATH5K_ERR(ah->ah_sc, "invalid tx power: %u\n", txpower); |
2955 | return -EINVAL; | 3026 | return -EINVAL; |
2956 | } | 3027 | } |
2957 | if (txpower == 0) | ||
2958 | txpower = AR5K_TUNE_DEFAULT_TXPOWER; | ||
2959 | 3028 | ||
2960 | /* Reset TX power values */ | 3029 | /* Reset TX power values */ |
2961 | memset(&ah->ah_txpower, 0, sizeof(ah->ah_txpower)); | 3030 | memset(&ah->ah_txpower, 0, sizeof(ah->ah_txpower)); |
diff --git a/drivers/net/wireless/ath/ath5k/reg.h b/drivers/net/wireless/ath/ath5k/reg.h index c63ea6afd96..4cb9c5df9f4 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 | /* |
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index 34e13c70084..62954fc7786 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" |
@@ -870,6 +872,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, | 872 | int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, |
871 | struct ieee80211_channel *channel, bool change_channel) | 873 | struct ieee80211_channel *channel, bool change_channel) |
872 | { | 874 | { |
875 | struct ath_common *common = ath5k_hw_common(ah); | ||
873 | u32 s_seq[10], s_ant, s_led[3], staid1_flags, tsf_up, tsf_lo; | 876 | u32 s_seq[10], s_ant, s_led[3], staid1_flags, tsf_up, tsf_lo; |
874 | u32 phy_tst1; | 877 | u32 phy_tst1; |
875 | u8 mode, freq, ee_mode, ant[2]; | 878 | u8 mode, freq, ee_mode, ant[2]; |
@@ -1171,10 +1174,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); | 1174 | ath5k_hw_reg_write(ah, s_led[2], AR5K_GPIODO); |
1172 | 1175 | ||
1173 | /* Restore sta_id flags and preserve our mac address*/ | 1176 | /* Restore sta_id flags and preserve our mac address*/ |
1174 | ath5k_hw_reg_write(ah, AR5K_LOW_ID(ah->ah_sta_id), | 1177 | ath5k_hw_reg_write(ah, |
1175 | AR5K_STA_ID0); | 1178 | get_unaligned_le32(common->macaddr), |
1176 | ath5k_hw_reg_write(ah, staid1_flags | AR5K_HIGH_ID(ah->ah_sta_id), | 1179 | AR5K_STA_ID0); |
1177 | AR5K_STA_ID1); | 1180 | ath5k_hw_reg_write(ah, |
1181 | staid1_flags | get_unaligned_le16(common->macaddr + 4), | ||
1182 | AR5K_STA_ID1); | ||
1178 | 1183 | ||
1179 | 1184 | ||
1180 | /* | 1185 | /* |
@@ -1182,8 +1187,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
1182 | */ | 1187 | */ |
1183 | 1188 | ||
1184 | /* Restore bssid and bssid mask */ | 1189 | /* Restore bssid and bssid mask */ |
1185 | /* XXX: add ah->aid once mac80211 gives this to us */ | 1190 | ath5k_hw_set_associd(ah); |
1186 | ath5k_hw_set_associd(ah, ah->ah_bssid, 0); | ||
1187 | 1191 | ||
1188 | /* Set PCU config */ | 1192 | /* Set PCU config */ |
1189 | ath5k_hw_set_opmode(ah); | 1193 | ath5k_hw_set_opmode(ah); |
@@ -1289,7 +1293,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
1289 | * out and/or noise floor calibration might timeout. | 1293 | * out and/or noise floor calibration might timeout. |
1290 | */ | 1294 | */ |
1291 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, | 1295 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, |
1292 | AR5K_PHY_AGCCTL_CAL); | 1296 | AR5K_PHY_AGCCTL_CAL | AR5K_PHY_AGCCTL_NF); |
1293 | 1297 | ||
1294 | /* At the same time start I/Q calibration for QAM constellation | 1298 | /* At the same time start I/Q calibration for QAM constellation |
1295 | * -no need for CCK- */ | 1299 | * -no need for CCK- */ |
@@ -1310,21 +1314,6 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
1310 | channel->center_freq); | 1314 | channel->center_freq); |
1311 | } | 1315 | } |
1312 | 1316 | ||
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 */ | 1317 | /* Restore antenna mode */ |
1329 | ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode); | 1318 | ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode); |
1330 | 1319 | ||