diff options
author | David S. Miller <davem@davemloft.net> | 2008-04-16 22:37:51 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-04-16 22:37:51 -0400 |
commit | 8c95b4773dd8d0415269ffad7301ef96d75be8ee (patch) | |
tree | 996401ce91c2a652fcff690e2c8bf88f2014d307 | |
parent | bcff122d478b774f4fd5262f35eedebe2f2fb274 (diff) | |
parent | 30b89b0f5e1313c8a5a039abeaa89248b6338d81 (diff) |
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/linville/wireless-2.6.26
53 files changed, 2077 insertions, 1870 deletions
diff --git a/drivers/net/wireless/ath5k/ath5k.h b/drivers/net/wireless/ath5k/ath5k.h index b21830771ea5..ba35c30d203c 100644 --- a/drivers/net/wireless/ath5k/ath5k.h +++ b/drivers/net/wireless/ath5k/ath5k.h | |||
@@ -142,6 +142,7 @@ enum ath5k_radio { | |||
142 | AR5K_RF5112 = 2, | 142 | AR5K_RF5112 = 2, |
143 | AR5K_RF2413 = 3, | 143 | AR5K_RF2413 = 3, |
144 | AR5K_RF5413 = 4, | 144 | AR5K_RF5413 = 4, |
145 | AR5K_RF2425 = 5, | ||
145 | }; | 146 | }; |
146 | 147 | ||
147 | /* | 148 | /* |
@@ -449,14 +450,6 @@ struct ath5k_rx_status { | |||
449 | #define AR5K_RXKEYIX_INVALID ((u8) - 1) | 450 | #define AR5K_RXKEYIX_INVALID ((u8) - 1) |
450 | #define AR5K_TXKEYIX_INVALID ((u32) - 1) | 451 | #define AR5K_TXKEYIX_INVALID ((u32) - 1) |
451 | 452 | ||
452 | struct ath5k_mib_stats { | ||
453 | u32 ackrcv_bad; | ||
454 | u32 rts_bad; | ||
455 | u32 rts_good; | ||
456 | u32 fcs_bad; | ||
457 | u32 beacons; | ||
458 | }; | ||
459 | |||
460 | 453 | ||
461 | /**************************\ | 454 | /**************************\ |
462 | BEACON TIMERS DEFINITIONS | 455 | BEACON TIMERS DEFINITIONS |
@@ -1069,6 +1062,7 @@ extern int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase); | |||
1069 | extern bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah); | 1062 | extern bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah); |
1070 | extern int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask); | 1063 | extern int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask); |
1071 | extern enum ath5k_int ath5k_hw_set_intr(struct ath5k_hw *ah, enum ath5k_int new_mask); | 1064 | extern enum ath5k_int ath5k_hw_set_intr(struct ath5k_hw *ah, enum ath5k_int new_mask); |
1065 | extern void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, struct ieee80211_low_level_stats *stats); | ||
1072 | /* EEPROM access functions */ | 1066 | /* EEPROM access functions */ |
1073 | extern int ath5k_hw_set_regdomain(struct ath5k_hw *ah, u16 regdomain); | 1067 | extern int ath5k_hw_set_regdomain(struct ath5k_hw *ah, u16 regdomain); |
1074 | /* Protocol Control Unit Functions */ | 1068 | /* Protocol Control Unit Functions */ |
@@ -1097,7 +1091,6 @@ extern int ath5k_hw_set_beacon_timers(struct ath5k_hw *ah, const struct ath5k_be | |||
1097 | extern void ath5k_hw_reset_beacon(struct ath5k_hw *ah); | 1091 | extern void ath5k_hw_reset_beacon(struct ath5k_hw *ah); |
1098 | extern int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr); | 1092 | extern int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr); |
1099 | #endif | 1093 | #endif |
1100 | extern void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, struct ath5k_mib_stats *statistics); | ||
1101 | /* ACK bit rate */ | 1094 | /* ACK bit rate */ |
1102 | void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high); | 1095 | void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high); |
1103 | /* ACK/CTS Timeouts */ | 1096 | /* ACK/CTS Timeouts */ |
diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index 8862d245c82b..e18305b781c9 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c | |||
@@ -126,6 +126,7 @@ static struct ath5k_srev_name srev_names[] = { | |||
126 | { "5414", AR5K_VERSION_VER, AR5K_SREV_VER_AR5414 }, | 126 | { "5414", AR5K_VERSION_VER, AR5K_SREV_VER_AR5414 }, |
127 | { "5416", AR5K_VERSION_VER, AR5K_SREV_VER_AR5416 }, | 127 | { "5416", AR5K_VERSION_VER, AR5K_SREV_VER_AR5416 }, |
128 | { "5418", AR5K_VERSION_VER, AR5K_SREV_VER_AR5418 }, | 128 | { "5418", AR5K_VERSION_VER, AR5K_SREV_VER_AR5418 }, |
129 | { "2425", AR5K_VERSION_VER, AR5K_SREV_VER_AR2425 }, | ||
129 | { "xxxxx", AR5K_VERSION_VER, AR5K_SREV_UNKNOWN }, | 130 | { "xxxxx", AR5K_VERSION_VER, AR5K_SREV_UNKNOWN }, |
130 | { "5110", AR5K_VERSION_RAD, AR5K_SREV_RAD_5110 }, | 131 | { "5110", AR5K_VERSION_RAD, AR5K_SREV_RAD_5110 }, |
131 | { "5111", AR5K_VERSION_RAD, AR5K_SREV_RAD_5111 }, | 132 | { "5111", AR5K_VERSION_RAD, AR5K_SREV_RAD_5111 }, |
@@ -2341,7 +2342,8 @@ ath5k_init(struct ath5k_softc *sc) | |||
2341 | * Enable interrupts. | 2342 | * Enable interrupts. |
2342 | */ | 2343 | */ |
2343 | sc->imask = AR5K_INT_RX | AR5K_INT_TX | AR5K_INT_RXEOL | | 2344 | sc->imask = AR5K_INT_RX | AR5K_INT_TX | AR5K_INT_RXEOL | |
2344 | AR5K_INT_RXORN | AR5K_INT_FATAL | AR5K_INT_GLOBAL; | 2345 | AR5K_INT_RXORN | AR5K_INT_FATAL | AR5K_INT_GLOBAL | |
2346 | AR5K_INT_MIB; | ||
2345 | 2347 | ||
2346 | ath5k_hw_set_intr(sc->ah, sc->imask); | 2348 | ath5k_hw_set_intr(sc->ah, sc->imask); |
2347 | /* Set ack to be sent at low bit-rates */ | 2349 | /* Set ack to be sent at low bit-rates */ |
@@ -2521,7 +2523,11 @@ ath5k_intr(int irq, void *dev_id) | |||
2521 | if (status & AR5K_INT_BMISS) { | 2523 | if (status & AR5K_INT_BMISS) { |
2522 | } | 2524 | } |
2523 | if (status & AR5K_INT_MIB) { | 2525 | if (status & AR5K_INT_MIB) { |
2524 | /* TODO */ | 2526 | /* |
2527 | * These stats are also used for ANI i think | ||
2528 | * so how about updating them more often ? | ||
2529 | */ | ||
2530 | ath5k_hw_update_mib_counters(ah, &sc->ll_stats); | ||
2525 | } | 2531 | } |
2526 | } | 2532 | } |
2527 | } while (ath5k_hw_is_intr_pending(ah) && counter-- > 0); | 2533 | } while (ath5k_hw_is_intr_pending(ah) && counter-- > 0); |
@@ -3014,6 +3020,10 @@ ath5k_get_stats(struct ieee80211_hw *hw, | |||
3014 | struct ieee80211_low_level_stats *stats) | 3020 | struct ieee80211_low_level_stats *stats) |
3015 | { | 3021 | { |
3016 | struct ath5k_softc *sc = hw->priv; | 3022 | struct ath5k_softc *sc = hw->priv; |
3023 | struct ath5k_hw *ah = sc->ah; | ||
3024 | |||
3025 | /* Force update */ | ||
3026 | ath5k_hw_update_mib_counters(ah, &sc->ll_stats); | ||
3017 | 3027 | ||
3018 | memcpy(stats, &sc->ll_stats, sizeof(sc->ll_stats)); | 3028 | memcpy(stats, &sc->ll_stats, sizeof(sc->ll_stats)); |
3019 | 3029 | ||
diff --git a/drivers/net/wireless/ath5k/hw.c b/drivers/net/wireless/ath5k/hw.c index ff579a223621..87e782291a01 100644 --- a/drivers/net/wireless/ath5k/hw.c +++ b/drivers/net/wireless/ath5k/hw.c | |||
@@ -120,11 +120,69 @@ int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val, | |||
120 | \***************************************/ | 120 | \***************************************/ |
121 | 121 | ||
122 | /* | 122 | /* |
123 | * Power On Self Test helper function | ||
124 | */ | ||
125 | static int ath5k_hw_post(struct ath5k_hw *ah) | ||
126 | { | ||
127 | |||
128 | int i, c; | ||
129 | u16 cur_reg; | ||
130 | u16 regs[2] = {AR5K_STA_ID0, AR5K_PHY(8)}; | ||
131 | u32 var_pattern; | ||
132 | u32 static_pattern[4] = { | ||
133 | 0x55555555, 0xaaaaaaaa, | ||
134 | 0x66666666, 0x99999999 | ||
135 | }; | ||
136 | u32 init_val; | ||
137 | u32 cur_val; | ||
138 | |||
139 | for (c = 0; c < 2; c++) { | ||
140 | |||
141 | cur_reg = regs[c]; | ||
142 | init_val = ath5k_hw_reg_read(ah, cur_reg); | ||
143 | |||
144 | for (i = 0; i < 256; i++) { | ||
145 | var_pattern = i << 16 | i; | ||
146 | ath5k_hw_reg_write(ah, var_pattern, cur_reg); | ||
147 | cur_val = ath5k_hw_reg_read(ah, cur_reg); | ||
148 | |||
149 | if (cur_val != var_pattern) { | ||
150 | ATH5K_ERR(ah->ah_sc, "POST Failed !!!\n"); | ||
151 | return -EAGAIN; | ||
152 | } | ||
153 | |||
154 | /* Found on ndiswrapper dumps */ | ||
155 | var_pattern = 0x0039080f; | ||
156 | ath5k_hw_reg_write(ah, var_pattern, cur_reg); | ||
157 | } | ||
158 | |||
159 | for (i = 0; i < 4; i++) { | ||
160 | var_pattern = static_pattern[i]; | ||
161 | ath5k_hw_reg_write(ah, var_pattern, cur_reg); | ||
162 | cur_val = ath5k_hw_reg_read(ah, cur_reg); | ||
163 | |||
164 | if (cur_val != var_pattern) { | ||
165 | ATH5K_ERR(ah->ah_sc, "POST Failed !!!\n"); | ||
166 | return -EAGAIN; | ||
167 | } | ||
168 | |||
169 | /* Found on ndiswrapper dumps */ | ||
170 | var_pattern = 0x003b080f; | ||
171 | ath5k_hw_reg_write(ah, var_pattern, cur_reg); | ||
172 | } | ||
173 | } | ||
174 | |||
175 | return 0; | ||
176 | |||
177 | } | ||
178 | |||
179 | /* | ||
123 | * Check if the device is supported and initialize the needed structs | 180 | * Check if the device is supported and initialize the needed structs |
124 | */ | 181 | */ |
125 | struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) | 182 | struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) |
126 | { | 183 | { |
127 | struct ath5k_hw *ah; | 184 | struct ath5k_hw *ah; |
185 | struct pci_dev *pdev = sc->pdev; | ||
128 | u8 mac[ETH_ALEN]; | 186 | u8 mac[ETH_ALEN]; |
129 | int ret; | 187 | int ret; |
130 | u32 srev; | 188 | u32 srev; |
@@ -204,15 +262,19 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) | |||
204 | CHANNEL_2GHZ); | 262 | CHANNEL_2GHZ); |
205 | 263 | ||
206 | /* Return on unsuported chips (unsupported eeprom etc) */ | 264 | /* Return on unsuported chips (unsupported eeprom etc) */ |
207 | if(srev >= AR5K_SREV_VER_AR5416){ | 265 | if ((srev >= AR5K_SREV_VER_AR5416) && |
266 | (srev < AR5K_SREV_VER_AR2425)) { | ||
208 | ATH5K_ERR(sc, "Device not yet supported.\n"); | 267 | ATH5K_ERR(sc, "Device not yet supported.\n"); |
209 | ret = -ENODEV; | 268 | ret = -ENODEV; |
210 | goto err_free; | 269 | goto err_free; |
270 | } else if (srev == AR5K_SREV_VER_AR2425) { | ||
271 | ATH5K_WARN(sc, "Support for RF2425 is under development.\n"); | ||
211 | } | 272 | } |
212 | 273 | ||
213 | /* Identify single chip solutions */ | 274 | /* Identify single chip solutions */ |
214 | if((srev <= AR5K_SREV_VER_AR5414) && | 275 | if (((srev <= AR5K_SREV_VER_AR5414) && |
215 | (srev >= AR5K_SREV_VER_AR2413)) { | 276 | (srev >= AR5K_SREV_VER_AR2413)) || |
277 | (srev == AR5K_SREV_VER_AR2425)) { | ||
216 | ah->ah_single_chip = true; | 278 | ah->ah_single_chip = true; |
217 | } else { | 279 | } else { |
218 | ah->ah_single_chip = false; | 280 | ah->ah_single_chip = false; |
@@ -241,22 +303,65 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) | |||
241 | } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC1) { | 303 | } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC1) { |
242 | ah->ah_radio = AR5K_RF2413; | 304 | ah->ah_radio = AR5K_RF2413; |
243 | ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A; | 305 | ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A; |
244 | } else { | 306 | } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC2) { |
245 | 307 | ||
246 | ah->ah_radio = AR5K_RF5413; | 308 | ah->ah_radio = AR5K_RF5413; |
247 | 309 | ||
248 | if (ah->ah_mac_srev <= AR5K_SREV_VER_AR5424 && | 310 | if (ah->ah_mac_srev <= AR5K_SREV_VER_AR5424 && |
249 | ah->ah_mac_srev >= AR5K_SREV_VER_AR2424) | 311 | ah->ah_mac_srev >= AR5K_SREV_VER_AR2424) |
250 | ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5424; | 312 | ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5424; |
251 | else if (ah->ah_mac_srev >= AR5K_SREV_VER_AR2425) | ||
252 | ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112; | ||
253 | else | 313 | else |
254 | ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A; | 314 | ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A; |
315 | /* | ||
316 | * Register returns 0x4 for radio revision | ||
317 | * so ath5k_hw_radio_revision doesn't parse the value | ||
318 | * correctly. For now we are based on mac's srev to | ||
319 | * identify RF2425 radio. | ||
320 | */ | ||
321 | } else if (srev == AR5K_SREV_VER_AR2425) { | ||
322 | ah->ah_radio = AR5K_RF2425; | ||
323 | ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112; | ||
324 | } | ||
255 | 325 | ||
326 | ah->ah_phy = AR5K_PHY(0); | ||
256 | 327 | ||
328 | /* | ||
329 | * Identify AR5212-based PCI-E cards | ||
330 | * And write some initial settings. | ||
331 | * | ||
332 | * (doing a "strings" on ndis driver | ||
333 | * -ar5211.sys- reveals the following | ||
334 | * pci-e related functions: | ||
335 | * | ||
336 | * pcieClockReq | ||
337 | * pcieRxErrNotify | ||
338 | * pcieL1SKPEnable | ||
339 | * pcieAspm | ||
340 | * pcieDisableAspmOnRfWake | ||
341 | * pciePowerSaveEnable | ||
342 | * | ||
343 | * I guess these point to ClockReq but | ||
344 | * i'm not sure.) | ||
345 | */ | ||
346 | if ((ah->ah_version == AR5K_AR5212) && (pdev->is_pcie)) { | ||
347 | ath5k_hw_reg_write(ah, 0x9248fc00, 0x4080); | ||
348 | ath5k_hw_reg_write(ah, 0x24924924, 0x4080); | ||
349 | ath5k_hw_reg_write(ah, 0x28000039, 0x4080); | ||
350 | ath5k_hw_reg_write(ah, 0x53160824, 0x4080); | ||
351 | ath5k_hw_reg_write(ah, 0xe5980579, 0x4080); | ||
352 | ath5k_hw_reg_write(ah, 0x001defff, 0x4080); | ||
353 | ath5k_hw_reg_write(ah, 0x1aaabe40, 0x4080); | ||
354 | ath5k_hw_reg_write(ah, 0xbe105554, 0x4080); | ||
355 | ath5k_hw_reg_write(ah, 0x000e3007, 0x4080); | ||
356 | ath5k_hw_reg_write(ah, 0x00000000, 0x4084); | ||
257 | } | 357 | } |
258 | 358 | ||
259 | ah->ah_phy = AR5K_PHY(0); | 359 | /* |
360 | * POST | ||
361 | */ | ||
362 | ret = ath5k_hw_post(ah); | ||
363 | if (ret) | ||
364 | goto err_free; | ||
260 | 365 | ||
261 | /* | 366 | /* |
262 | * Get card capabilities, values, ... | 367 | * Get card capabilities, values, ... |
@@ -391,7 +496,7 @@ static int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) | |||
391 | ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | | 496 | ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | |
392 | AR5K_RESET_CTL_BASEBAND | bus_flags); | 497 | AR5K_RESET_CTL_BASEBAND | bus_flags); |
393 | if (ret) { | 498 | if (ret) { |
394 | ATH5K_ERR(ah->ah_sc, "failed to reset the MAC Chip + PCI\n"); | 499 | ATH5K_ERR(ah->ah_sc, "failed to reset the MAC Chip\n"); |
395 | return -EIO; | 500 | return -EIO; |
396 | } | 501 | } |
397 | 502 | ||
@@ -655,7 +760,8 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, | |||
655 | if (ah->ah_radio != AR5K_RF5111 && | 760 | if (ah->ah_radio != AR5K_RF5111 && |
656 | ah->ah_radio != AR5K_RF5112 && | 761 | ah->ah_radio != AR5K_RF5112 && |
657 | ah->ah_radio != AR5K_RF5413 && | 762 | ah->ah_radio != AR5K_RF5413 && |
658 | ah->ah_radio != AR5K_RF2413) { | 763 | ah->ah_radio != AR5K_RF2413 && |
764 | ah->ah_radio != AR5K_RF2425) { | ||
659 | ATH5K_ERR(ah->ah_sc, | 765 | ATH5K_ERR(ah->ah_sc, |
660 | "invalid phy radio: %u\n", ah->ah_radio); | 766 | "invalid phy radio: %u\n", ah->ah_radio); |
661 | return -EINVAL; | 767 | return -EINVAL; |
@@ -2849,15 +2955,19 @@ int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr) | |||
2849 | * Update mib counters (statistics) | 2955 | * Update mib counters (statistics) |
2850 | */ | 2956 | */ |
2851 | void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, | 2957 | void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, |
2852 | struct ath5k_mib_stats *statistics) | 2958 | struct ieee80211_low_level_stats *stats) |
2853 | { | 2959 | { |
2854 | ATH5K_TRACE(ah->ah_sc); | 2960 | ATH5K_TRACE(ah->ah_sc); |
2961 | |||
2855 | /* Read-And-Clear */ | 2962 | /* Read-And-Clear */ |
2856 | statistics->ackrcv_bad += ath5k_hw_reg_read(ah, AR5K_ACK_FAIL); | 2963 | stats->dot11ACKFailureCount += ath5k_hw_reg_read(ah, AR5K_ACK_FAIL); |
2857 | statistics->rts_bad += ath5k_hw_reg_read(ah, AR5K_RTS_FAIL); | 2964 | stats->dot11RTSFailureCount += ath5k_hw_reg_read(ah, AR5K_RTS_FAIL); |
2858 | statistics->rts_good += ath5k_hw_reg_read(ah, AR5K_RTS_OK); | 2965 | stats->dot11RTSSuccessCount += ath5k_hw_reg_read(ah, AR5K_RTS_OK); |
2859 | statistics->fcs_bad += ath5k_hw_reg_read(ah, AR5K_FCS_FAIL); | 2966 | stats->dot11FCSErrorCount += ath5k_hw_reg_read(ah, AR5K_FCS_FAIL); |
2860 | statistics->beacons += ath5k_hw_reg_read(ah, AR5K_BEACON_CNT); | 2967 | |
2968 | /* XXX: Should we use this to track beacon count ? | ||
2969 | * -we read it anyway to clear the register */ | ||
2970 | ath5k_hw_reg_read(ah, AR5K_BEACON_CNT); | ||
2861 | 2971 | ||
2862 | /* Reset profile count registers on 5212*/ | 2972 | /* Reset profile count registers on 5212*/ |
2863 | if (ah->ah_version == AR5K_AR5212) { | 2973 | if (ah->ah_version == AR5K_AR5212) { |
@@ -2958,8 +3068,16 @@ int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry) | |||
2958 | for (i = 0; i < AR5K_KEYCACHE_SIZE; i++) | 3068 | for (i = 0; i < AR5K_KEYCACHE_SIZE; i++) |
2959 | ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_OFF(entry, i)); | 3069 | ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_OFF(entry, i)); |
2960 | 3070 | ||
2961 | /* Set NULL encryption on non-5210*/ | 3071 | /* |
2962 | if (ah->ah_version != AR5K_AR5210) | 3072 | * Set NULL encryption on AR5212+ |
3073 | * | ||
3074 | * Note: AR5K_KEYTABLE_TYPE -> AR5K_KEYTABLE_OFF(entry, 5) | ||
3075 | * AR5K_KEYTABLE_TYPE_NULL -> 0x00000007 | ||
3076 | * | ||
3077 | * Note2: Windows driver (ndiswrapper) sets this to | ||
3078 | * 0x00000714 instead of 0x00000007 | ||
3079 | */ | ||
3080 | if (ah->ah_version > AR5K_AR5211) | ||
2963 | ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL, | 3081 | ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL, |
2964 | AR5K_KEYTABLE_TYPE(entry)); | 3082 | AR5K_KEYTABLE_TYPE(entry)); |
2965 | 3083 | ||
diff --git a/drivers/net/wireless/ath5k/initvals.c b/drivers/net/wireless/ath5k/initvals.c index fdbab2f08178..04c84e9da89d 100644 --- a/drivers/net/wireless/ath5k/initvals.c +++ b/drivers/net/wireless/ath5k/initvals.c | |||
@@ -1282,6 +1282,213 @@ static const struct ath5k_ini_mode rf2413_ini_mode_end[] = { | |||
1282 | { 0xf3307ff0, 0xf3307ff0, 0xf3307ff0 } }, | 1282 | { 0xf3307ff0, 0xf3307ff0, 0xf3307ff0 } }, |
1283 | }; | 1283 | }; |
1284 | 1284 | ||
1285 | /* Initial mode-specific settings for RF2425 (Written after ar5212_ini) */ | ||
1286 | /* XXX: No dumps for turbog yet, so turbog is the same with g here with some | ||
1287 | * minor tweaking based on dumps from other chips */ | ||
1288 | static const struct ath5k_ini_mode rf2425_ini_mode_end[] = { | ||
1289 | { AR5K_TXCFG, | ||
1290 | /* g gTurbo */ | ||
1291 | { 0x00000015, 0x00000015 } }, | ||
1292 | { AR5K_USEC_5211, | ||
1293 | { 0x12e013ab, 0x098813cf } }, | ||
1294 | { AR5K_PHY_TURBO, | ||
1295 | { 0x00000000, 0x00000003 } }, | ||
1296 | { AR5K_PHY(10), | ||
1297 | { 0x0a020001, 0x0a020001 } }, | ||
1298 | { AR5K_PHY(13), | ||
1299 | { 0x00000e0e, 0x00000e0e } }, | ||
1300 | { AR5K_PHY(14), | ||
1301 | { 0x0000000b, 0x0000000b } }, | ||
1302 | { AR5K_PHY(17), | ||
1303 | { 0x13721422, 0x13721422 } }, | ||
1304 | { AR5K_PHY(18), | ||
1305 | { 0x00199a65, 0x00199a65 } }, | ||
1306 | { AR5K_PHY(20), | ||
1307 | { 0x0c98b0da, 0x0c98b0da } }, | ||
1308 | { AR5K_PHY_SIG, | ||
1309 | { 0x7ec80d2e, 0x7ec80d2e } }, | ||
1310 | { AR5K_PHY_AGCCOARSE, | ||
1311 | { 0x3139605e, 0x3139605e } }, | ||
1312 | { AR5K_PHY(27), | ||
1313 | { 0x050cb081, 0x050cb081 } }, | ||
1314 | { AR5K_PHY_RX_DELAY, | ||
1315 | { 0x00000898, 0x000007d0 } }, | ||
1316 | { AR5K_PHY_FRAME_CTL_5211, | ||
1317 | { 0xf7b81000, 0xf7b81000 } }, | ||
1318 | { AR5K_PHY_CCKTXCTL, | ||
1319 | { 0x00000000, 0x00000000 } }, | ||
1320 | { AR5K_PHY(642), | ||
1321 | { 0xd03e6788, 0xd03e6788 } }, | ||
1322 | { AR5K_PHY_GAIN_2GHZ, | ||
1323 | { 0x0052c140, 0x0052c140 } }, | ||
1324 | { 0xa21c, | ||
1325 | { 0x1883800a, 0x1883800a } }, | ||
1326 | { 0xa324, | ||
1327 | { 0xa7cfa7cf, 0xa7cfa7cf } }, | ||
1328 | { 0xa328, | ||
1329 | { 0xa7cfa7cf, 0xa7cfa7cf } }, | ||
1330 | { 0xa32c, | ||
1331 | { 0xa7cfa7cf, 0xa7cfa7cf } }, | ||
1332 | { 0xa330, | ||
1333 | { 0xa7cfa7cf, 0xa7cfa7cf } }, | ||
1334 | { 0xa334, | ||
1335 | { 0xa7cfa7cf, 0xa7cfa7cf } }, | ||
1336 | { AR5K_DCU_FP, | ||
1337 | { 0x000003e0, 0x000003e0 } }, | ||
1338 | { 0x8060, | ||
1339 | { 0x0000000f, 0x0000000f } }, | ||
1340 | { 0x809c, | ||
1341 | { 0x00000000, 0x00000000 } }, | ||
1342 | { 0x80a0, | ||
1343 | { 0x00000000, 0x00000000 } }, | ||
1344 | { 0x8118, | ||
1345 | { 0x00000000, 0x00000000 } }, | ||
1346 | { 0x811c, | ||
1347 | { 0x00000000, 0x00000000 } }, | ||
1348 | { 0x8120, | ||
1349 | { 0x00000000, 0x00000000 } }, | ||
1350 | { 0x8124, | ||
1351 | { 0x00000000, 0x00000000 } }, | ||
1352 | { 0x8128, | ||
1353 | { 0x00000000, 0x00000000 } }, | ||
1354 | { 0x812c, | ||
1355 | { 0x00000000, 0x00000000 } }, | ||
1356 | { 0x8130, | ||
1357 | { 0x00000000, 0x00000000 } }, | ||
1358 | { 0x8134, | ||
1359 | { 0x00000000, 0x00000000 } }, | ||
1360 | { 0x8138, | ||
1361 | { 0x00000000, 0x00000000 } }, | ||
1362 | { 0x813c, | ||
1363 | { 0x00000000, 0x00000000 } }, | ||
1364 | { 0x8140, | ||
1365 | { 0x800003f9, 0x800003f9 } }, | ||
1366 | { 0x8144, | ||
1367 | { 0x00000000, 0x00000000 } }, | ||
1368 | { AR5K_PHY_AGC, | ||
1369 | { 0x00000000, 0x00000000 } }, | ||
1370 | { AR5K_PHY(11), | ||
1371 | { 0x0000a000, 0x0000a000 } }, | ||
1372 | { AR5K_PHY(15), | ||
1373 | { 0x00200400, 0x00200400 } }, | ||
1374 | { AR5K_PHY(19), | ||
1375 | { 0x1284233c, 0x1284233c } }, | ||
1376 | { AR5K_PHY_SCR, | ||
1377 | { 0x0000001f, 0x0000001f } }, | ||
1378 | { AR5K_PHY_SLMT, | ||
1379 | { 0x00000080, 0x00000080 } }, | ||
1380 | { AR5K_PHY_SCAL, | ||
1381 | { 0x0000000e, 0x0000000e } }, | ||
1382 | { AR5K_PHY(86), | ||
1383 | { 0x00081fff, 0x00081fff } }, | ||
1384 | { AR5K_PHY(96), | ||
1385 | { 0x00000000, 0x00000000 } }, | ||
1386 | { AR5K_PHY(97), | ||
1387 | { 0x02800000, 0x02800000 } }, | ||
1388 | { AR5K_PHY(104), | ||
1389 | { 0x00000000, 0x00000000 } }, | ||
1390 | { AR5K_PHY(119), | ||
1391 | { 0xfebadbe8, 0xfebadbe8 } }, | ||
1392 | { AR5K_PHY(120), | ||
1393 | { 0x00000000, 0x00000000 } }, | ||
1394 | { AR5K_PHY(121), | ||
1395 | { 0xaaaaaaaa, 0xaaaaaaaa } }, | ||
1396 | { AR5K_PHY(122), | ||
1397 | { 0x3c466478, 0x3c466478 } }, | ||
1398 | { AR5K_PHY(123), | ||
1399 | { 0x000000aa, 0x000000aa } }, | ||
1400 | { AR5K_PHY_SCLOCK, | ||
1401 | { 0x0000000c, 0x0000000c } }, | ||
1402 | { AR5K_PHY_SDELAY, | ||
1403 | { 0x000000ff, 0x000000ff } }, | ||
1404 | { AR5K_PHY_SPENDING, | ||
1405 | { 0x00000014, 0x00000014 } }, | ||
1406 | { 0xa228, | ||
1407 | { 0x000009b5, 0x000009b5 } }, | ||
1408 | { AR5K_PHY_TXPOWER_RATE3, | ||
1409 | { 0x20202020, 0x20202020 } }, | ||
1410 | { AR5K_PHY_TXPOWER_RATE4, | ||
1411 | { 0x20202020, 0x20202020 } }, | ||
1412 | { 0xa23c, | ||
1413 | { 0x93c889af, 0x93c889af } }, | ||
1414 | { 0xa24c, | ||
1415 | { 0x00000001, 0x00000001 } }, | ||
1416 | { 0xa250, | ||
1417 | { 0x0000a000, 0x0000a000 } }, | ||
1418 | { 0xa254, | ||
1419 | { 0x00000000, 0x00000000 } }, | ||
1420 | { 0xa258, | ||
1421 | { 0x0cc75380, 0x0cc75380 } }, | ||
1422 | { 0xa25c, | ||
1423 | { 0x0f0f0f01, 0x0f0f0f01 } }, | ||
1424 | { 0xa260, | ||
1425 | { 0x5f690f01, 0x5f690f01 } }, | ||
1426 | { 0xa264, | ||
1427 | { 0x00418a11, 0x00418a11 } }, | ||
1428 | { 0xa268, | ||
1429 | { 0x00000000, 0x00000000 } }, | ||
1430 | { 0xa26c, | ||
1431 | { 0x0c30c166, 0x0c30c166 } }, | ||
1432 | { 0xa270, | ||
1433 | { 0x00820820, 0x00820820 } }, | ||
1434 | { 0xa274, | ||
1435 | { 0x081a3caa, 0x081a3caa } }, | ||
1436 | { 0xa278, | ||
1437 | { 0x1ce739ce, 0x1ce739ce } }, | ||
1438 | { 0xa27c, | ||
1439 | { 0x051701ce, 0x051701ce } }, | ||
1440 | { 0xa300, | ||
1441 | { 0x16010000, 0x16010000 } }, | ||
1442 | { 0xa304, | ||
1443 | { 0x2c032402, 0x2c032402 } }, | ||
1444 | { 0xa308, | ||
1445 | { 0x48433e42, 0x48433e42 } }, | ||
1446 | { 0xa30c, | ||
1447 | { 0x5a0f500b, 0x5a0f500b } }, | ||
1448 | { 0xa310, | ||
1449 | { 0x6c4b624a, 0x6c4b624a } }, | ||
1450 | { 0xa314, | ||
1451 | { 0x7e8b748a, 0x7e8b748a } }, | ||
1452 | { 0xa318, | ||
1453 | { 0x96cf8ccb, 0x96cf8ccb } }, | ||
1454 | { 0xa31c, | ||
1455 | { 0xa34f9d0f, 0xa34f9d0f } }, | ||
1456 | { 0xa320, | ||
1457 | { 0xa7cfa58f, 0xa7cfa58f } }, | ||
1458 | { 0xa348, | ||
1459 | { 0x3fffffff, 0x3fffffff } }, | ||
1460 | { 0xa34c, | ||
1461 | { 0x3fffffff, 0x3fffffff } }, | ||
1462 | { 0xa350, | ||
1463 | { 0x3fffffff, 0x3fffffff } }, | ||
1464 | { 0xa354, | ||
1465 | { 0x0003ffff, 0x0003ffff } }, | ||
1466 | { 0xa358, | ||
1467 | { 0x79a8aa1f, 0x79a8aa1f } }, | ||
1468 | { 0xa35c, | ||
1469 | { 0x066c420f, 0x066c420f } }, | ||
1470 | { 0xa360, | ||
1471 | { 0x0f282207, 0x0f282207 } }, | ||
1472 | { 0xa364, | ||
1473 | { 0x17601685, 0x17601685 } }, | ||
1474 | { 0xa368, | ||
1475 | { 0x1f801104, 0x1f801104 } }, | ||
1476 | { 0xa36c, | ||
1477 | { 0x37a00c03, 0x37a00c03 } }, | ||
1478 | { 0xa370, | ||
1479 | { 0x3fc40883, 0x3fc40883 } }, | ||
1480 | { 0xa374, | ||
1481 | { 0x57c00803, 0x57c00803 } }, | ||
1482 | { 0xa378, | ||
1483 | { 0x5fd80682, 0x5fd80682 } }, | ||
1484 | { 0xa37c, | ||
1485 | { 0x7fe00482, 0x7fe00482 } }, | ||
1486 | { 0xa380, | ||
1487 | { 0x7f3c7bba, 0x7f3c7bba } }, | ||
1488 | { 0xa384, | ||
1489 | { 0xf3307ff0, 0xf3307ff0 } }, | ||
1490 | }; | ||
1491 | |||
1285 | /* | 1492 | /* |
1286 | * Initial BaseBand Gain settings for RF5111/5112 (AR5210 comes with | 1493 | * Initial BaseBand Gain settings for RF5111/5112 (AR5210 comes with |
1287 | * RF5110 only so initial BB Gain settings are included in AR5K_AR5210_INI) | 1494 | * RF5110 only so initial BB Gain settings are included in AR5K_AR5210_INI) |
@@ -1542,7 +1749,34 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel) | |||
1542 | ARRAY_SIZE(rf5112_ini_bbgain), | 1749 | ARRAY_SIZE(rf5112_ini_bbgain), |
1543 | rf5112_ini_bbgain, change_channel); | 1750 | rf5112_ini_bbgain, change_channel); |
1544 | 1751 | ||
1752 | } else if (ah->ah_radio == AR5K_RF2425) { | ||
1753 | |||
1754 | if (mode < 2) { | ||
1755 | ATH5K_ERR(ah->ah_sc, | ||
1756 | "unsupported channel mode: %d\n", mode); | ||
1757 | return -EINVAL; | ||
1758 | } | ||
1759 | |||
1760 | /* Map b to g */ | ||
1761 | if (mode == 2) | ||
1762 | mode = 0; | ||
1763 | else | ||
1764 | mode = mode - 3; | ||
1765 | |||
1766 | /* Override a setting from ar5212_ini */ | ||
1767 | ath5k_hw_reg_write(ah, 0x018830c6, AR5K_PHY(648)); | ||
1768 | |||
1769 | ath5k_hw_ini_mode_registers(ah, | ||
1770 | ARRAY_SIZE(rf2425_ini_mode_end), | ||
1771 | rf2425_ini_mode_end, mode); | ||
1772 | |||
1773 | /* Baseband gain table */ | ||
1774 | ath5k_hw_ini_registers(ah, | ||
1775 | ARRAY_SIZE(rf5112_ini_bbgain), | ||
1776 | rf5112_ini_bbgain, change_channel); | ||
1777 | |||
1545 | } | 1778 | } |
1779 | |||
1546 | /* For AR5211 */ | 1780 | /* For AR5211 */ |
1547 | } else if (ah->ah_version == AR5K_AR5211) { | 1781 | } else if (ah->ah_version == AR5K_AR5211) { |
1548 | 1782 | ||
diff --git a/drivers/net/wireless/ath5k/phy.c b/drivers/net/wireless/ath5k/phy.c index 890ecce8bedc..afd8689e5c03 100644 --- a/drivers/net/wireless/ath5k/phy.c +++ b/drivers/net/wireless/ath5k/phy.c | |||
@@ -669,6 +669,7 @@ static const struct ath5k_ini_rf rfregs_5413[] = { | |||
669 | /* RF2413/2414 mode-specific init registers */ | 669 | /* RF2413/2414 mode-specific init registers */ |
670 | static const struct ath5k_ini_rf rfregs_2413[] = { | 670 | static const struct ath5k_ini_rf rfregs_2413[] = { |
671 | { 1, AR5K_RF_BUFFER_CONTROL_4, | 671 | { 1, AR5K_RF_BUFFER_CONTROL_4, |
672 | /* mode b mode g mode gTurbo */ | ||
672 | { 0x00000020, 0x00000020, 0x00000020 } }, | 673 | { 0x00000020, 0x00000020, 0x00000020 } }, |
673 | { 2, AR5K_RF_BUFFER_CONTROL_3, | 674 | { 2, AR5K_RF_BUFFER_CONTROL_3, |
674 | { 0x02001408, 0x02001408, 0x02001408 } }, | 675 | { 0x02001408, 0x02001408, 0x02001408 } }, |
@@ -736,6 +737,83 @@ static const struct ath5k_ini_rf rfregs_2413[] = { | |||
736 | { 0x0000000e, 0x0000000e, 0x0000000e } }, | 737 | { 0x0000000e, 0x0000000e, 0x0000000e } }, |
737 | }; | 738 | }; |
738 | 739 | ||
740 | /* RF2425 mode-specific init registers */ | ||
741 | static const struct ath5k_ini_rf rfregs_2425[] = { | ||
742 | { 1, AR5K_RF_BUFFER_CONTROL_4, | ||
743 | /* mode g mode gTurbo */ | ||
744 | { 0x00000020, 0x00000020 } }, | ||
745 | { 2, AR5K_RF_BUFFER_CONTROL_3, | ||
746 | { 0x02001408, 0x02001408 } }, | ||
747 | { 3, AR5K_RF_BUFFER_CONTROL_6, | ||
748 | { 0x00e020c0, 0x00e020c0 } }, | ||
749 | { 6, AR5K_RF_BUFFER, | ||
750 | { 0x10000000, 0x10000000 } }, | ||
751 | { 6, AR5K_RF_BUFFER, | ||
752 | { 0x00000000, 0x00000000 } }, | ||
753 | { 6, AR5K_RF_BUFFER, | ||
754 | { 0x00000000, 0x00000000 } }, | ||
755 | { 6, AR5K_RF_BUFFER, | ||
756 | { 0x00000000, 0x00000000 } }, | ||
757 | { 6, AR5K_RF_BUFFER, | ||
758 | { 0x00000000, 0x00000000 } }, | ||
759 | { 6, AR5K_RF_BUFFER, | ||
760 | { 0x00000000, 0x00000000 } }, | ||
761 | { 6, AR5K_RF_BUFFER, | ||
762 | { 0x00000000, 0x00000000 } }, | ||
763 | { 6, AR5K_RF_BUFFER, | ||
764 | { 0x00000000, 0x00000000 } }, | ||
765 | { 6, AR5K_RF_BUFFER, | ||
766 | { 0x00000000, 0x00000000 } }, | ||
767 | { 6, AR5K_RF_BUFFER, | ||
768 | { 0x00000000, 0x00000000 } }, | ||
769 | { 6, AR5K_RF_BUFFER, | ||
770 | { 0x00000000, 0x00000000 } }, | ||
771 | { 6, AR5K_RF_BUFFER, | ||
772 | { 0x002a0000, 0x002a0000 } }, | ||
773 | { 6, AR5K_RF_BUFFER, | ||
774 | { 0x00000000, 0x00000000 } }, | ||
775 | { 6, AR5K_RF_BUFFER, | ||
776 | { 0x00000000, 0x00000000 } }, | ||
777 | { 6, AR5K_RF_BUFFER, | ||
778 | { 0x00100000, 0x00100000 } }, | ||
779 | { 6, AR5K_RF_BUFFER, | ||
780 | { 0x00020000, 0x00020000 } }, | ||
781 | { 6, AR5K_RF_BUFFER, | ||
782 | { 0x00730000, 0x00730000 } }, | ||
783 | { 6, AR5K_RF_BUFFER, | ||
784 | { 0x00f80000, 0x00f80000 } }, | ||
785 | { 6, AR5K_RF_BUFFER, | ||
786 | { 0x00e70000, 0x00e70000 } }, | ||
787 | { 6, AR5K_RF_BUFFER, | ||
788 | { 0x00140000, 0x00140000 } }, | ||
789 | { 6, AR5K_RF_BUFFER, | ||
790 | { 0x00910040, 0x00910040 } }, | ||
791 | { 6, AR5K_RF_BUFFER, | ||
792 | { 0x0007001a, 0x0007001a } }, | ||
793 | { 6, AR5K_RF_BUFFER, | ||
794 | { 0x00410000, 0x00410000 } }, | ||
795 | { 6, AR5K_RF_BUFFER, | ||
796 | { 0x00810060, 0x00810060 } }, | ||
797 | { 6, AR5K_RF_BUFFER, | ||
798 | { 0x00020803, 0x00020803 } }, | ||
799 | { 6, AR5K_RF_BUFFER, | ||
800 | { 0x00000000, 0x00000000 } }, | ||
801 | { 6, AR5K_RF_BUFFER, | ||
802 | { 0x00000000, 0x00000000 } }, | ||
803 | { 6, AR5K_RF_BUFFER, | ||
804 | { 0x00001660, 0x00001660 } }, | ||
805 | { 6, AR5K_RF_BUFFER, | ||
806 | { 0x00001688, 0x00001688 } }, | ||
807 | { 6, AR5K_RF_BUFFER_CONTROL_1, | ||
808 | { 0x00000001, 0x00000001 } }, | ||
809 | { 7, AR5K_RF_BUFFER, | ||
810 | { 0x00006400, 0x00006400 } }, | ||
811 | { 7, AR5K_RF_BUFFER, | ||
812 | { 0x00000800, 0x00000800 } }, | ||
813 | { 7, AR5K_RF_BUFFER_CONTROL_2, | ||
814 | { 0x0000000e, 0x0000000e } }, | ||
815 | }; | ||
816 | |||
739 | /* Initial RF Gain settings for RF5112 */ | 817 | /* Initial RF Gain settings for RF5112 */ |
740 | static const struct ath5k_ini_rfgain rfgain_5112[] = { | 818 | static const struct ath5k_ini_rfgain rfgain_5112[] = { |
741 | /* 5Ghz 2Ghz */ | 819 | /* 5Ghz 2Ghz */ |
@@ -1348,7 +1426,8 @@ static int ath5k_hw_rf5112_rfregs(struct ath5k_hw *ah, | |||
1348 | } | 1426 | } |
1349 | 1427 | ||
1350 | /* | 1428 | /* |
1351 | * Initialize RF5413/5414 | 1429 | * Initialize RF5413/5414 and future chips |
1430 | * (until we come up with a better solution) | ||
1352 | */ | 1431 | */ |
1353 | static int ath5k_hw_rf5413_rfregs(struct ath5k_hw *ah, | 1432 | static int ath5k_hw_rf5413_rfregs(struct ath5k_hw *ah, |
1354 | struct ieee80211_channel *channel, unsigned int mode) | 1433 | struct ieee80211_channel *channel, unsigned int mode) |
@@ -1362,19 +1441,41 @@ static int ath5k_hw_rf5413_rfregs(struct ath5k_hw *ah, | |||
1362 | 1441 | ||
1363 | rf = ah->ah_rf_banks; | 1442 | rf = ah->ah_rf_banks; |
1364 | 1443 | ||
1365 | if (ah->ah_radio == AR5K_RF5413) { | 1444 | switch (ah->ah_radio) { |
1445 | case AR5K_RF5413: | ||
1366 | rf_ini = rfregs_5413; | 1446 | rf_ini = rfregs_5413; |
1367 | rf_size = ARRAY_SIZE(rfregs_5413); | 1447 | rf_size = ARRAY_SIZE(rfregs_5413); |
1368 | } else if (ah->ah_radio == AR5K_RF2413) { | 1448 | break; |
1449 | case AR5K_RF2413: | ||
1369 | rf_ini = rfregs_2413; | 1450 | rf_ini = rfregs_2413; |
1370 | rf_size = ARRAY_SIZE(rfregs_2413); | 1451 | rf_size = ARRAY_SIZE(rfregs_2413); |
1452 | |||
1371 | if (mode < 2) { | 1453 | if (mode < 2) { |
1372 | ATH5K_ERR(ah->ah_sc, | 1454 | ATH5K_ERR(ah->ah_sc, |
1373 | "invalid channel mode: %i\n", mode); | 1455 | "invalid channel mode: %i\n", mode); |
1374 | return -EINVAL; | 1456 | return -EINVAL; |
1375 | } | 1457 | } |
1458 | |||
1376 | mode = mode - 2; | 1459 | mode = mode - 2; |
1377 | } else { | 1460 | break; |
1461 | case AR5K_RF2425: | ||
1462 | rf_ini = rfregs_2425; | ||
1463 | rf_size = ARRAY_SIZE(rfregs_2425); | ||
1464 | |||
1465 | if (mode < 2) { | ||
1466 | ATH5K_ERR(ah->ah_sc, | ||
1467 | "invalid channel mode: %i\n", mode); | ||
1468 | return -EINVAL; | ||
1469 | } | ||
1470 | |||
1471 | /* Map b to g */ | ||
1472 | if (mode == 2) | ||
1473 | mode = 0; | ||
1474 | else | ||
1475 | mode = mode - 3; | ||
1476 | |||
1477 | break; | ||
1478 | default: | ||
1378 | return -EINVAL; | 1479 | return -EINVAL; |
1379 | } | 1480 | } |
1380 | 1481 | ||
@@ -1439,6 +1540,10 @@ int ath5k_hw_rfregs(struct ath5k_hw *ah, struct ieee80211_channel *channel, | |||
1439 | ah->ah_rf_banks_size = sizeof(rfregs_2413); | 1540 | ah->ah_rf_banks_size = sizeof(rfregs_2413); |
1440 | func = ath5k_hw_rf5413_rfregs; | 1541 | func = ath5k_hw_rf5413_rfregs; |
1441 | break; | 1542 | break; |
1543 | case AR5K_RF2425: | ||
1544 | ah->ah_rf_banks_size = sizeof(rfregs_2425); | ||
1545 | func = ath5k_hw_rf5413_rfregs; | ||
1546 | break; | ||
1442 | default: | 1547 | default: |
1443 | return -EINVAL; | 1548 | return -EINVAL; |
1444 | } | 1549 | } |
@@ -1482,6 +1587,11 @@ int ath5k_hw_rfgain(struct ath5k_hw *ah, unsigned int freq) | |||
1482 | size = ARRAY_SIZE(rfgain_2413); | 1587 | size = ARRAY_SIZE(rfgain_2413); |
1483 | freq = 0; /* only 2Ghz */ | 1588 | freq = 0; /* only 2Ghz */ |
1484 | break; | 1589 | break; |
1590 | case AR5K_RF2425: | ||
1591 | ath5k_rfg = rfgain_2413; | ||
1592 | size = ARRAY_SIZE(rfgain_2413); | ||
1593 | freq = 0; /* only 2Ghz */ | ||
1594 | break; | ||
1485 | default: | 1595 | default: |
1486 | return -EINVAL; | 1596 | return -EINVAL; |
1487 | } | 1597 | } |
@@ -2181,8 +2291,11 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, | |||
2181 | * transmit anything if we call | 2291 | * transmit anything if we call |
2182 | * this funtion, so we skip it | 2292 | * this funtion, so we skip it |
2183 | * until we fix txpower. | 2293 | * until we fix txpower. |
2294 | * | ||
2295 | * XXX: Assume same for RF2425 | ||
2296 | * to be safe. | ||
2184 | */ | 2297 | */ |
2185 | if (ah->ah_radio == AR5K_RF2413) | 2298 | if ((ah->ah_radio == AR5K_RF2413) || (ah->ah_radio == AR5K_RF2425)) |
2186 | return 0; | 2299 | return 0; |
2187 | 2300 | ||
2188 | /* Reset TX power values */ | 2301 | /* Reset TX power values */ |
diff --git a/drivers/net/wireless/ath5k/regdom.c b/drivers/net/wireless/ath5k/regdom.c deleted file mode 100644 index e851957dacfd..000000000000 --- a/drivers/net/wireless/ath5k/regdom.c +++ /dev/null | |||
@@ -1,121 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2004, 2005 Reyk Floeter <reyk@vantronix.net> | ||
3 | * | ||
4 | * Permission to use, copy, modify, and distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | /* | ||
18 | * Basic regulation domain extensions for the IEEE 802.11 stack | ||
19 | */ | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/string.h> | ||
23 | |||
24 | #include "regdom.h" | ||
25 | |||
26 | static const struct ath5k_regdommap { | ||
27 | enum ath5k_regdom dmn; | ||
28 | enum ath5k_regdom dmn5; | ||
29 | enum ath5k_regdom dmn2; | ||
30 | } r_map[] = { | ||
31 | { DMN_DEFAULT, DMN_DEBUG, DMN_DEBUG }, | ||
32 | { DMN_NULL_WORLD, DMN_NULL, DMN_WORLD }, | ||
33 | { DMN_NULL_ETSIB, DMN_NULL, DMN_ETSIB }, | ||
34 | { DMN_NULL_ETSIC, DMN_NULL, DMN_ETSIC }, | ||
35 | { DMN_FCC1_FCCA, DMN_FCC1, DMN_FCCA }, | ||
36 | { DMN_FCC1_WORLD, DMN_FCC1, DMN_WORLD }, | ||
37 | { DMN_FCC2_FCCA, DMN_FCC2, DMN_FCCA }, | ||
38 | { DMN_FCC2_WORLD, DMN_FCC2, DMN_WORLD }, | ||
39 | { DMN_FCC2_ETSIC, DMN_FCC2, DMN_ETSIC }, | ||
40 | { DMN_FRANCE_NULL, DMN_ETSI3, DMN_ETSI3 }, | ||
41 | { DMN_FCC3_FCCA, DMN_FCC3, DMN_WORLD }, | ||
42 | { DMN_ETSI1_WORLD, DMN_ETSI1, DMN_WORLD }, | ||
43 | { DMN_ETSI3_ETSIA, DMN_ETSI3, DMN_WORLD }, | ||
44 | { DMN_ETSI2_WORLD, DMN_ETSI2, DMN_WORLD }, | ||
45 | { DMN_ETSI3_WORLD, DMN_ETSI3, DMN_WORLD }, | ||
46 | { DMN_ETSI4_WORLD, DMN_ETSI4, DMN_WORLD }, | ||
47 | { DMN_ETSI4_ETSIC, DMN_ETSI4, DMN_ETSIC }, | ||
48 | { DMN_ETSI5_WORLD, DMN_ETSI5, DMN_WORLD }, | ||
49 | { DMN_ETSI6_WORLD, DMN_ETSI6, DMN_WORLD }, | ||
50 | { DMN_ETSI_NULL, DMN_ETSI1, DMN_ETSI1 }, | ||
51 | { DMN_MKK1_MKKA, DMN_MKK1, DMN_MKKA }, | ||
52 | { DMN_MKK1_MKKB, DMN_MKK1, DMN_MKKA }, | ||
53 | { DMN_APL4_WORLD, DMN_APL4, DMN_WORLD }, | ||
54 | { DMN_MKK2_MKKA, DMN_MKK2, DMN_MKKA }, | ||
55 | { DMN_APL_NULL, DMN_APL1, DMN_NULL }, | ||
56 | { DMN_APL2_WORLD, DMN_APL2, DMN_WORLD }, | ||
57 | { DMN_APL2_APLC, DMN_APL2, DMN_WORLD }, | ||
58 | { DMN_APL3_WORLD, DMN_APL3, DMN_WORLD }, | ||
59 | { DMN_MKK1_FCCA, DMN_MKK1, DMN_FCCA }, | ||
60 | { DMN_APL2_APLD, DMN_APL2, DMN_APLD }, | ||
61 | { DMN_MKK1_MKKA1, DMN_MKK1, DMN_MKKA }, | ||
62 | { DMN_MKK1_MKKA2, DMN_MKK1, DMN_MKKA }, | ||
63 | { DMN_APL1_WORLD, DMN_APL1, DMN_WORLD }, | ||
64 | { DMN_APL1_FCCA, DMN_APL1, DMN_FCCA }, | ||
65 | { DMN_APL1_APLA, DMN_APL1, DMN_WORLD }, | ||
66 | { DMN_APL1_ETSIC, DMN_APL1, DMN_ETSIC }, | ||
67 | { DMN_APL2_ETSIC, DMN_APL2, DMN_ETSIC }, | ||
68 | { DMN_APL5_WORLD, DMN_APL5, DMN_WORLD }, | ||
69 | { DMN_WOR0_WORLD, DMN_WORLD, DMN_WORLD }, | ||
70 | { DMN_WOR1_WORLD, DMN_WORLD, DMN_WORLD }, | ||
71 | { DMN_WOR2_WORLD, DMN_WORLD, DMN_WORLD }, | ||
72 | { DMN_WOR3_WORLD, DMN_WORLD, DMN_WORLD }, | ||
73 | { DMN_WOR4_WORLD, DMN_WORLD, DMN_WORLD }, | ||
74 | { DMN_WOR5_ETSIC, DMN_WORLD, DMN_WORLD }, | ||
75 | { DMN_WOR01_WORLD, DMN_WORLD, DMN_WORLD }, | ||
76 | { DMN_WOR02_WORLD, DMN_WORLD, DMN_WORLD }, | ||
77 | { DMN_EU1_WORLD, DMN_ETSI1, DMN_WORLD }, | ||
78 | { DMN_WOR9_WORLD, DMN_WORLD, DMN_WORLD }, | ||
79 | { DMN_WORA_WORLD, DMN_WORLD, DMN_WORLD }, | ||
80 | }; | ||
81 | |||
82 | enum ath5k_regdom ath5k_regdom2flag(enum ath5k_regdom dmn, u16 mhz) | ||
83 | { | ||
84 | unsigned int i; | ||
85 | |||
86 | for (i = 0; i < ARRAY_SIZE(r_map); i++) { | ||
87 | if (r_map[i].dmn == dmn) { | ||
88 | if (mhz >= 2000 && mhz <= 3000) | ||
89 | return r_map[i].dmn2; | ||
90 | if (mhz >= IEEE80211_CHANNELS_5GHZ_MIN && | ||
91 | mhz <= IEEE80211_CHANNELS_5GHZ_MAX) | ||
92 | return r_map[i].dmn5; | ||
93 | } | ||
94 | } | ||
95 | |||
96 | return DMN_DEBUG; | ||
97 | } | ||
98 | |||
99 | u16 ath5k_regdom_from_ieee(enum ath5k_regdom ieee) | ||
100 | { | ||
101 | u32 regdomain = (u32)ieee; | ||
102 | |||
103 | /* | ||
104 | * Use the default regulation domain if the value is empty | ||
105 | * or not supported by the net80211 regulation code. | ||
106 | */ | ||
107 | if (ath5k_regdom2flag(regdomain, IEEE80211_CHANNELS_5GHZ_MIN) == | ||
108 | DMN_DEBUG) | ||
109 | return (u16)AR5K_TUNE_REGDOMAIN; | ||
110 | |||
111 | /* It is supported, just return the value */ | ||
112 | return regdomain; | ||
113 | } | ||
114 | |||
115 | enum ath5k_regdom ath5k_regdom_to_ieee(u16 regdomain) | ||
116 | { | ||
117 | enum ath5k_regdom ieee = (enum ath5k_regdom)regdomain; | ||
118 | |||
119 | return ieee; | ||
120 | } | ||
121 | |||
diff --git a/drivers/net/wireless/ath5k/regdom.h b/drivers/net/wireless/ath5k/regdom.h deleted file mode 100644 index f7d3c66e594e..000000000000 --- a/drivers/net/wireless/ath5k/regdom.h +++ /dev/null | |||
@@ -1,500 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2004, 2005 Reyk Floeter <reyk@openbsd.org> | ||
3 | * | ||
4 | * Permission to use, copy, modify, and distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef _IEEE80211_REGDOMAIN_H_ | ||
18 | #define _IEEE80211_REGDOMAIN_H_ | ||
19 | |||
20 | #include <linux/types.h> | ||
21 | |||
22 | /* Default regulation domain if stored value EEPROM value is invalid */ | ||
23 | #define AR5K_TUNE_REGDOMAIN DMN_FCC2_FCCA /* Canada */ | ||
24 | #define AR5K_TUNE_CTRY CTRY_DEFAULT | ||
25 | |||
26 | |||
27 | enum ath5k_regdom { | ||
28 | DMN_DEFAULT = 0x00, | ||
29 | DMN_NULL_WORLD = 0x03, | ||
30 | DMN_NULL_ETSIB = 0x07, | ||
31 | DMN_NULL_ETSIC = 0x08, | ||
32 | DMN_FCC1_FCCA = 0x10, | ||
33 | DMN_FCC1_WORLD = 0x11, | ||
34 | DMN_FCC2_FCCA = 0x20, | ||
35 | DMN_FCC2_WORLD = 0x21, | ||
36 | DMN_FCC2_ETSIC = 0x22, | ||
37 | DMN_FRANCE_NULL = 0x31, | ||
38 | DMN_FCC3_FCCA = 0x3A, | ||
39 | DMN_ETSI1_WORLD = 0x37, | ||
40 | DMN_ETSI3_ETSIA = 0x32, | ||
41 | DMN_ETSI2_WORLD = 0x35, | ||
42 | DMN_ETSI3_WORLD = 0x36, | ||
43 | DMN_ETSI4_WORLD = 0x30, | ||
44 | DMN_ETSI4_ETSIC = 0x38, | ||
45 | DMN_ETSI5_WORLD = 0x39, | ||
46 | DMN_ETSI6_WORLD = 0x34, | ||
47 | DMN_ETSI_NULL = 0x33, | ||
48 | DMN_MKK1_MKKA = 0x40, | ||
49 | DMN_MKK1_MKKB = 0x41, | ||
50 | DMN_APL4_WORLD = 0x42, | ||
51 | DMN_MKK2_MKKA = 0x43, | ||
52 | DMN_APL_NULL = 0x44, | ||
53 | DMN_APL2_WORLD = 0x45, | ||
54 | DMN_APL2_APLC = 0x46, | ||
55 | DMN_APL3_WORLD = 0x47, | ||
56 | DMN_MKK1_FCCA = 0x48, | ||
57 | DMN_APL2_APLD = 0x49, | ||
58 | DMN_MKK1_MKKA1 = 0x4A, | ||
59 | DMN_MKK1_MKKA2 = 0x4B, | ||
60 | DMN_APL1_WORLD = 0x52, | ||
61 | DMN_APL1_FCCA = 0x53, | ||
62 | DMN_APL1_APLA = 0x54, | ||
63 | DMN_APL1_ETSIC = 0x55, | ||
64 | DMN_APL2_ETSIC = 0x56, | ||
65 | DMN_APL5_WORLD = 0x58, | ||
66 | DMN_WOR0_WORLD = 0x60, | ||
67 | DMN_WOR1_WORLD = 0x61, | ||
68 | DMN_WOR2_WORLD = 0x62, | ||
69 | DMN_WOR3_WORLD = 0x63, | ||
70 | DMN_WOR4_WORLD = 0x64, | ||
71 | DMN_WOR5_ETSIC = 0x65, | ||
72 | DMN_WOR01_WORLD = 0x66, | ||
73 | DMN_WOR02_WORLD = 0x67, | ||
74 | DMN_EU1_WORLD = 0x68, | ||
75 | DMN_WOR9_WORLD = 0x69, | ||
76 | DMN_WORA_WORLD = 0x6A, | ||
77 | |||
78 | DMN_APL1 = 0xf0000001, | ||
79 | DMN_APL2 = 0xf0000002, | ||
80 | DMN_APL3 = 0xf0000004, | ||
81 | DMN_APL4 = 0xf0000008, | ||
82 | DMN_APL5 = 0xf0000010, | ||
83 | DMN_ETSI1 = 0xf0000020, | ||
84 | DMN_ETSI2 = 0xf0000040, | ||
85 | DMN_ETSI3 = 0xf0000080, | ||
86 | DMN_ETSI4 = 0xf0000100, | ||
87 | DMN_ETSI5 = 0xf0000200, | ||
88 | DMN_ETSI6 = 0xf0000400, | ||
89 | DMN_ETSIA = 0xf0000800, | ||
90 | DMN_ETSIB = 0xf0001000, | ||
91 | DMN_ETSIC = 0xf0002000, | ||
92 | DMN_FCC1 = 0xf0004000, | ||
93 | DMN_FCC2 = 0xf0008000, | ||
94 | DMN_FCC3 = 0xf0010000, | ||
95 | DMN_FCCA = 0xf0020000, | ||
96 | DMN_APLD = 0xf0040000, | ||
97 | DMN_MKK1 = 0xf0080000, | ||
98 | DMN_MKK2 = 0xf0100000, | ||
99 | DMN_MKKA = 0xf0200000, | ||
100 | DMN_NULL = 0xf0400000, | ||
101 | DMN_WORLD = 0xf0800000, | ||
102 | DMN_DEBUG = 0xf1000000 /* used for debugging */ | ||
103 | }; | ||
104 | |||
105 | #define IEEE80211_DMN(_d) ((_d) & ~0xf0000000) | ||
106 | |||
107 | enum ath5k_countrycode { | ||
108 | CTRY_DEFAULT = 0, /* Default domain (NA) */ | ||
109 | CTRY_ALBANIA = 8, /* Albania */ | ||
110 | CTRY_ALGERIA = 12, /* Algeria */ | ||
111 | CTRY_ARGENTINA = 32, /* Argentina */ | ||
112 | CTRY_ARMENIA = 51, /* Armenia */ | ||
113 | CTRY_AUSTRALIA = 36, /* Australia */ | ||
114 | CTRY_AUSTRIA = 40, /* Austria */ | ||
115 | CTRY_AZERBAIJAN = 31, /* Azerbaijan */ | ||
116 | CTRY_BAHRAIN = 48, /* Bahrain */ | ||
117 | CTRY_BELARUS = 112, /* Belarus */ | ||
118 | CTRY_BELGIUM = 56, /* Belgium */ | ||
119 | CTRY_BELIZE = 84, /* Belize */ | ||
120 | CTRY_BOLIVIA = 68, /* Bolivia */ | ||
121 | CTRY_BRAZIL = 76, /* Brazil */ | ||
122 | CTRY_BRUNEI_DARUSSALAM = 96, /* Brunei Darussalam */ | ||
123 | CTRY_BULGARIA = 100, /* Bulgaria */ | ||
124 | CTRY_CANADA = 124, /* Canada */ | ||
125 | CTRY_CHILE = 152, /* Chile */ | ||
126 | CTRY_CHINA = 156, /* People's Republic of China */ | ||
127 | CTRY_COLOMBIA = 170, /* Colombia */ | ||
128 | CTRY_COSTA_RICA = 188, /* Costa Rica */ | ||
129 | CTRY_CROATIA = 191, /* Croatia */ | ||
130 | CTRY_CYPRUS = 196, /* Cyprus */ | ||
131 | CTRY_CZECH = 203, /* Czech Republic */ | ||
132 | CTRY_DENMARK = 208, /* Denmark */ | ||
133 | CTRY_DOMINICAN_REPUBLIC = 214, /* Dominican Republic */ | ||
134 | CTRY_ECUADOR = 218, /* Ecuador */ | ||
135 | CTRY_EGYPT = 818, /* Egypt */ | ||
136 | CTRY_EL_SALVADOR = 222, /* El Salvador */ | ||
137 | CTRY_ESTONIA = 233, /* Estonia */ | ||
138 | CTRY_FAEROE_ISLANDS = 234, /* Faeroe Islands */ | ||
139 | CTRY_FINLAND = 246, /* Finland */ | ||
140 | CTRY_FRANCE = 250, /* France */ | ||
141 | CTRY_FRANCE2 = 255, /* France2 */ | ||
142 | CTRY_GEORGIA = 268, /* Georgia */ | ||
143 | CTRY_GERMANY = 276, /* Germany */ | ||
144 | CTRY_GREECE = 300, /* Greece */ | ||
145 | CTRY_GUATEMALA = 320, /* Guatemala */ | ||
146 | CTRY_HONDURAS = 340, /* Honduras */ | ||
147 | CTRY_HONG_KONG = 344, /* Hong Kong S.A.R., P.R.C. */ | ||
148 | CTRY_HUNGARY = 348, /* Hungary */ | ||
149 | CTRY_ICELAND = 352, /* Iceland */ | ||
150 | CTRY_INDIA = 356, /* India */ | ||
151 | CTRY_INDONESIA = 360, /* Indonesia */ | ||
152 | CTRY_IRAN = 364, /* Iran */ | ||
153 | CTRY_IRAQ = 368, /* Iraq */ | ||
154 | CTRY_IRELAND = 372, /* Ireland */ | ||
155 | CTRY_ISRAEL = 376, /* Israel */ | ||
156 | CTRY_ITALY = 380, /* Italy */ | ||
157 | CTRY_JAMAICA = 388, /* Jamaica */ | ||
158 | CTRY_JAPAN = 392, /* Japan */ | ||
159 | CTRY_JAPAN1 = 393, /* Japan (JP1) */ | ||
160 | CTRY_JAPAN2 = 394, /* Japan (JP0) */ | ||
161 | CTRY_JAPAN3 = 395, /* Japan (JP1-1) */ | ||
162 | CTRY_JAPAN4 = 396, /* Japan (JE1) */ | ||
163 | CTRY_JAPAN5 = 397, /* Japan (JE2) */ | ||
164 | CTRY_JORDAN = 400, /* Jordan */ | ||
165 | CTRY_KAZAKHSTAN = 398, /* Kazakhstan */ | ||
166 | CTRY_KENYA = 404, /* Kenya */ | ||
167 | CTRY_KOREA_NORTH = 408, /* North Korea */ | ||
168 | CTRY_KOREA_ROC = 410, /* South Korea */ | ||
169 | CTRY_KOREA_ROC2 = 411, /* South Korea */ | ||
170 | CTRY_KUWAIT = 414, /* Kuwait */ | ||
171 | CTRY_LATVIA = 428, /* Latvia */ | ||
172 | CTRY_LEBANON = 422, /* Lebanon */ | ||
173 | CTRY_LIBYA = 434, /* Libya */ | ||
174 | CTRY_LIECHTENSTEIN = 438, /* Liechtenstein */ | ||
175 | CTRY_LITHUANIA = 440, /* Lithuania */ | ||
176 | CTRY_LUXEMBOURG = 442, /* Luxembourg */ | ||
177 | CTRY_MACAU = 446, /* Macau */ | ||
178 | CTRY_MACEDONIA = 807, /* Republic of Macedonia */ | ||
179 | CTRY_MALAYSIA = 458, /* Malaysia */ | ||
180 | CTRY_MEXICO = 484, /* Mexico */ | ||
181 | CTRY_MONACO = 492, /* Principality of Monaco */ | ||
182 | CTRY_MOROCCO = 504, /* Morocco */ | ||
183 | CTRY_NETHERLANDS = 528, /* Netherlands */ | ||
184 | CTRY_NEW_ZEALAND = 554, /* New Zealand */ | ||
185 | CTRY_NICARAGUA = 558, /* Nicaragua */ | ||
186 | CTRY_NORWAY = 578, /* Norway */ | ||
187 | CTRY_OMAN = 512, /* Oman */ | ||
188 | CTRY_PAKISTAN = 586, /* Islamic Republic of Pakistan */ | ||
189 | CTRY_PANAMA = 591, /* Panama */ | ||
190 | CTRY_PARAGUAY = 600, /* Paraguay */ | ||
191 | CTRY_PERU = 604, /* Peru */ | ||
192 | CTRY_PHILIPPINES = 608, /* Republic of the Philippines */ | ||
193 | CTRY_POLAND = 616, /* Poland */ | ||
194 | CTRY_PORTUGAL = 620, /* Portugal */ | ||
195 | CTRY_PUERTO_RICO = 630, /* Puerto Rico */ | ||
196 | CTRY_QATAR = 634, /* Qatar */ | ||
197 | CTRY_ROMANIA = 642, /* Romania */ | ||
198 | CTRY_RUSSIA = 643, /* Russia */ | ||
199 | CTRY_SAUDI_ARABIA = 682, /* Saudi Arabia */ | ||
200 | CTRY_SINGAPORE = 702, /* Singapore */ | ||
201 | CTRY_SLOVAKIA = 703, /* Slovak Republic */ | ||
202 | CTRY_SLOVENIA = 705, /* Slovenia */ | ||
203 | CTRY_SOUTH_AFRICA = 710, /* South Africa */ | ||
204 | CTRY_SPAIN = 724, /* Spain */ | ||
205 | CTRY_SRI_LANKA = 728, /* Sri Lanka */ | ||
206 | CTRY_SWEDEN = 752, /* Sweden */ | ||
207 | CTRY_SWITZERLAND = 756, /* Switzerland */ | ||
208 | CTRY_SYRIA = 760, /* Syria */ | ||
209 | CTRY_TAIWAN = 158, /* Taiwan */ | ||
210 | CTRY_THAILAND = 764, /* Thailand */ | ||
211 | CTRY_TRINIDAD_Y_TOBAGO = 780, /* Trinidad y Tobago */ | ||
212 | CTRY_TUNISIA = 788, /* Tunisia */ | ||
213 | CTRY_TURKEY = 792, /* Turkey */ | ||
214 | CTRY_UAE = 784, /* U.A.E. */ | ||
215 | CTRY_UKRAINE = 804, /* Ukraine */ | ||
216 | CTRY_UNITED_KINGDOM = 826, /* United Kingdom */ | ||
217 | CTRY_UNITED_STATES = 840, /* United States */ | ||
218 | CTRY_URUGUAY = 858, /* Uruguay */ | ||
219 | CTRY_UZBEKISTAN = 860, /* Uzbekistan */ | ||
220 | CTRY_VENEZUELA = 862, /* Venezuela */ | ||
221 | CTRY_VIET_NAM = 704, /* Viet Nam */ | ||
222 | CTRY_YEMEN = 887, /* Yemen */ | ||
223 | CTRY_ZIMBABWE = 716, /* Zimbabwe */ | ||
224 | }; | ||
225 | |||
226 | #define IEEE80211_CHANNELS_2GHZ_MIN 2412 /* 2GHz channel 1 */ | ||
227 | #define IEEE80211_CHANNELS_2GHZ_MAX 2732 /* 2GHz channel 26 */ | ||
228 | #define IEEE80211_CHANNELS_5GHZ_MIN 5005 /* 5GHz channel 1 */ | ||
229 | #define IEEE80211_CHANNELS_5GHZ_MAX 6100 /* 5GHz channel 220 */ | ||
230 | |||
231 | struct ath5k_regchannel { | ||
232 | u16 chan; | ||
233 | enum ath5k_regdom domain; | ||
234 | u32 mode; | ||
235 | }; | ||
236 | |||
237 | #define IEEE80211_CHANNELS_2GHZ { \ | ||
238 | /*2412*/ { 1, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
239 | /*2417*/ { 2, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
240 | /*2422*/ { 3, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
241 | /*2427*/ { 4, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
242 | /*2432*/ { 5, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
243 | /*2437*/ { 6, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
244 | /*2442*/ { 7, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
245 | /*2447*/ { 8, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
246 | /*2452*/ { 9, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
247 | /*2457*/ { 10, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
248 | /*2462*/ { 11, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
249 | /*2467*/ { 12, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
250 | /*2472*/ { 13, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
251 | \ | ||
252 | /*2432*/ { 5, DMN_ETSIB, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
253 | /*2437*/ { 6, DMN_ETSIB, CHANNEL_CCK|CHANNEL_OFDM|CHANNEL_TURBO }, \ | ||
254 | /*2442*/ { 7, DMN_ETSIB, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
255 | \ | ||
256 | /*2412*/ { 1, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
257 | /*2417*/ { 2, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
258 | /*2422*/ { 3, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
259 | /*2427*/ { 4, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
260 | /*2432*/ { 5, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
261 | /*2437*/ { 6, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM|CHANNEL_TURBO }, \ | ||
262 | /*2442*/ { 7, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
263 | /*2447*/ { 8, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
264 | /*2452*/ { 9, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
265 | /*2457*/ { 10, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
266 | /*2462*/ { 11, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
267 | /*2467*/ { 12, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
268 | /*2472*/ { 13, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
269 | \ | ||
270 | /*2412*/ { 1, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
271 | /*2417*/ { 2, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
272 | /*2422*/ { 3, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
273 | /*2427*/ { 4, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
274 | /*2432*/ { 5, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
275 | /*2437*/ { 6, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM|CHANNEL_TURBO }, \ | ||
276 | /*2442*/ { 7, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
277 | /*2447*/ { 8, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
278 | /*2452*/ { 9, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
279 | /*2457*/ { 10, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
280 | /*2462*/ { 11, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
281 | \ | ||
282 | /*2412*/ { 1, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
283 | /*2417*/ { 2, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
284 | /*2422*/ { 3, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
285 | /*2427*/ { 4, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
286 | /*2432*/ { 5, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
287 | /*2437*/ { 6, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
288 | /*2442*/ { 7, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
289 | /*2447*/ { 8, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
290 | /*2452*/ { 9, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
291 | /*2457*/ { 10, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
292 | /*2462*/ { 11, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
293 | /*2467*/ { 12, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
294 | /*2472*/ { 13, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
295 | /*2484*/ { 14, DMN_MKKA, CHANNEL_CCK }, \ | ||
296 | \ | ||
297 | /*2412*/ { 1, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
298 | /*2417*/ { 2, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
299 | /*2422*/ { 3, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
300 | /*2427*/ { 4, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
301 | /*2432*/ { 5, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
302 | /*2437*/ { 6, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM|CHANNEL_TURBO }, \ | ||
303 | /*2442*/ { 7, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
304 | /*2447*/ { 8, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
305 | /*2452*/ { 9, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
306 | /*2457*/ { 10, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
307 | /*2462*/ { 11, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
308 | /*2467*/ { 12, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
309 | /*2472*/ { 13, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \ | ||
310 | } | ||
311 | |||
312 | #define IEEE80211_CHANNELS_5GHZ { \ | ||
313 | /*5745*/ { 149, DMN_APL1, CHANNEL_OFDM }, \ | ||
314 | /*5765*/ { 153, DMN_APL1, CHANNEL_OFDM }, \ | ||
315 | /*5785*/ { 157, DMN_APL1, CHANNEL_OFDM }, \ | ||
316 | /*5805*/ { 161, DMN_APL1, CHANNEL_OFDM }, \ | ||
317 | /*5825*/ { 165, DMN_APL1, CHANNEL_OFDM }, \ | ||
318 | \ | ||
319 | /*5745*/ { 149, DMN_APL2, CHANNEL_OFDM }, \ | ||
320 | /*5765*/ { 153, DMN_APL2, CHANNEL_OFDM }, \ | ||
321 | /*5785*/ { 157, DMN_APL2, CHANNEL_OFDM }, \ | ||
322 | /*5805*/ { 161, DMN_APL2, CHANNEL_OFDM }, \ | ||
323 | \ | ||
324 | /*5280*/ { 56, DMN_APL3, CHANNEL_OFDM }, \ | ||
325 | /*5300*/ { 60, DMN_APL3, CHANNEL_OFDM }, \ | ||
326 | /*5320*/ { 64, DMN_APL3, CHANNEL_OFDM }, \ | ||
327 | /*5745*/ { 149, DMN_APL3, CHANNEL_OFDM }, \ | ||
328 | /*5765*/ { 153, DMN_APL3, CHANNEL_OFDM }, \ | ||
329 | /*5785*/ { 157, DMN_APL3, CHANNEL_OFDM }, \ | ||
330 | /*5805*/ { 161, DMN_APL3, CHANNEL_OFDM }, \ | ||
331 | \ | ||
332 | /*5180*/ { 36, DMN_APL4, CHANNEL_OFDM }, \ | ||
333 | /*5200*/ { 40, DMN_APL4, CHANNEL_OFDM }, \ | ||
334 | /*5220*/ { 44, DMN_APL4, CHANNEL_OFDM }, \ | ||
335 | /*5240*/ { 48, DMN_APL4, CHANNEL_OFDM }, \ | ||
336 | /*5745*/ { 149, DMN_APL4, CHANNEL_OFDM }, \ | ||
337 | /*5765*/ { 153, DMN_APL4, CHANNEL_OFDM }, \ | ||
338 | /*5785*/ { 157, DMN_APL4, CHANNEL_OFDM }, \ | ||
339 | /*5805*/ { 161, DMN_APL4, CHANNEL_OFDM }, \ | ||
340 | /*5825*/ { 165, DMN_APL4, CHANNEL_OFDM }, \ | ||
341 | \ | ||
342 | /*5745*/ { 149, DMN_APL5, CHANNEL_OFDM }, \ | ||
343 | /*5765*/ { 153, DMN_APL5, CHANNEL_OFDM }, \ | ||
344 | /*5785*/ { 157, DMN_APL5, CHANNEL_OFDM }, \ | ||
345 | /*5805*/ { 161, DMN_APL5, CHANNEL_OFDM }, \ | ||
346 | /*5825*/ { 165, DMN_APL5, CHANNEL_OFDM }, \ | ||
347 | \ | ||
348 | /*5180*/ { 36, DMN_ETSI1, CHANNEL_OFDM }, \ | ||
349 | /*5200*/ { 40, DMN_ETSI1, CHANNEL_OFDM }, \ | ||
350 | /*5220*/ { 44, DMN_ETSI1, CHANNEL_OFDM }, \ | ||
351 | /*5240*/ { 48, DMN_ETSI1, CHANNEL_OFDM }, \ | ||
352 | /*5260*/ { 52, DMN_ETSI1, CHANNEL_OFDM }, \ | ||
353 | /*5280*/ { 56, DMN_ETSI1, CHANNEL_OFDM }, \ | ||
354 | /*5300*/ { 60, DMN_ETSI1, CHANNEL_OFDM }, \ | ||
355 | /*5320*/ { 64, DMN_ETSI1, CHANNEL_OFDM }, \ | ||
356 | /*5500*/ { 100, DMN_ETSI1, CHANNEL_OFDM }, \ | ||
357 | /*5520*/ { 104, DMN_ETSI1, CHANNEL_OFDM }, \ | ||
358 | /*5540*/ { 108, DMN_ETSI1, CHANNEL_OFDM }, \ | ||
359 | /*5560*/ { 112, DMN_ETSI1, CHANNEL_OFDM }, \ | ||
360 | /*5580*/ { 116, DMN_ETSI1, CHANNEL_OFDM }, \ | ||
361 | /*5600*/ { 120, DMN_ETSI1, CHANNEL_OFDM }, \ | ||
362 | /*5620*/ { 124, DMN_ETSI1, CHANNEL_OFDM }, \ | ||
363 | /*5640*/ { 128, DMN_ETSI1, CHANNEL_OFDM }, \ | ||
364 | /*5660*/ { 132, DMN_ETSI1, CHANNEL_OFDM }, \ | ||
365 | /*5680*/ { 136, DMN_ETSI1, CHANNEL_OFDM }, \ | ||
366 | /*5700*/ { 140, DMN_ETSI1, CHANNEL_OFDM }, \ | ||
367 | \ | ||
368 | /*5180*/ { 36, DMN_ETSI2, CHANNEL_OFDM }, \ | ||
369 | /*5200*/ { 40, DMN_ETSI2, CHANNEL_OFDM }, \ | ||
370 | /*5220*/ { 44, DMN_ETSI2, CHANNEL_OFDM }, \ | ||
371 | /*5240*/ { 48, DMN_ETSI2, CHANNEL_OFDM }, \ | ||
372 | \ | ||
373 | /*5180*/ { 36, DMN_ETSI3, CHANNEL_OFDM }, \ | ||
374 | /*5200*/ { 40, DMN_ETSI3, CHANNEL_OFDM }, \ | ||
375 | /*5220*/ { 44, DMN_ETSI3, CHANNEL_OFDM }, \ | ||
376 | /*5240*/ { 48, DMN_ETSI3, CHANNEL_OFDM }, \ | ||
377 | /*5260*/ { 52, DMN_ETSI3, CHANNEL_OFDM }, \ | ||
378 | /*5280*/ { 56, DMN_ETSI3, CHANNEL_OFDM }, \ | ||
379 | /*5300*/ { 60, DMN_ETSI3, CHANNEL_OFDM }, \ | ||
380 | /*5320*/ { 64, DMN_ETSI3, CHANNEL_OFDM }, \ | ||
381 | \ | ||
382 | /*5180*/ { 36, DMN_ETSI4, CHANNEL_OFDM }, \ | ||
383 | /*5200*/ { 40, DMN_ETSI4, CHANNEL_OFDM }, \ | ||
384 | /*5220*/ { 44, DMN_ETSI4, CHANNEL_OFDM }, \ | ||
385 | /*5240*/ { 48, DMN_ETSI4, CHANNEL_OFDM }, \ | ||
386 | /*5260*/ { 52, DMN_ETSI4, CHANNEL_OFDM }, \ | ||
387 | /*5280*/ { 56, DMN_ETSI4, CHANNEL_OFDM }, \ | ||
388 | /*5300*/ { 60, DMN_ETSI4, CHANNEL_OFDM }, \ | ||
389 | /*5320*/ { 64, DMN_ETSI4, CHANNEL_OFDM }, \ | ||
390 | \ | ||
391 | /*5180*/ { 36, DMN_ETSI5, CHANNEL_OFDM }, \ | ||
392 | /*5200*/ { 40, DMN_ETSI5, CHANNEL_OFDM }, \ | ||
393 | /*5220*/ { 44, DMN_ETSI5, CHANNEL_OFDM }, \ | ||
394 | /*5240*/ { 48, DMN_ETSI5, CHANNEL_OFDM }, \ | ||
395 | \ | ||
396 | /*5180*/ { 36, DMN_ETSI6, CHANNEL_OFDM }, \ | ||
397 | /*5200*/ { 40, DMN_ETSI6, CHANNEL_OFDM }, \ | ||
398 | /*5220*/ { 44, DMN_ETSI6, CHANNEL_OFDM }, \ | ||
399 | /*5240*/ { 48, DMN_ETSI6, CHANNEL_OFDM }, \ | ||
400 | /*5260*/ { 52, DMN_ETSI6, CHANNEL_OFDM }, \ | ||
401 | /*5280*/ { 56, DMN_ETSI6, CHANNEL_OFDM }, \ | ||
402 | /*5500*/ { 100, DMN_ETSI6, CHANNEL_OFDM }, \ | ||
403 | /*5520*/ { 104, DMN_ETSI6, CHANNEL_OFDM }, \ | ||
404 | /*5540*/ { 108, DMN_ETSI6, CHANNEL_OFDM }, \ | ||
405 | /*5560*/ { 112, DMN_ETSI6, CHANNEL_OFDM }, \ | ||
406 | /*5580*/ { 116, DMN_ETSI6, CHANNEL_OFDM }, \ | ||
407 | /*5600*/ { 120, DMN_ETSI6, CHANNEL_OFDM }, \ | ||
408 | /*5620*/ { 124, DMN_ETSI6, CHANNEL_OFDM }, \ | ||
409 | /*5640*/ { 128, DMN_ETSI6, CHANNEL_OFDM }, \ | ||
410 | /*5660*/ { 132, DMN_ETSI6, CHANNEL_OFDM }, \ | ||
411 | /*5680*/ { 136, DMN_ETSI6, CHANNEL_OFDM }, \ | ||
412 | /*5700*/ { 140, DMN_ETSI6, CHANNEL_OFDM }, \ | ||
413 | \ | ||
414 | /*5180*/ { 36, DMN_FCC1, CHANNEL_OFDM }, \ | ||
415 | /*5200*/ { 40, DMN_FCC1, CHANNEL_OFDM }, \ | ||
416 | /*5210*/ { 42, DMN_FCC1, CHANNEL_OFDM|CHANNEL_TURBO }, \ | ||
417 | /*5220*/ { 44, DMN_FCC1, CHANNEL_OFDM }, \ | ||
418 | /*5240*/ { 48, DMN_FCC1, CHANNEL_OFDM }, \ | ||
419 | /*5250*/ { 50, DMN_FCC1, CHANNEL_OFDM|CHANNEL_TURBO }, \ | ||
420 | /*5260*/ { 52, DMN_FCC1, CHANNEL_OFDM }, \ | ||
421 | /*5280*/ { 56, DMN_FCC1, CHANNEL_OFDM }, \ | ||
422 | /*5290*/ { 58, DMN_FCC1, CHANNEL_OFDM|CHANNEL_TURBO }, \ | ||
423 | /*5300*/ { 60, DMN_FCC1, CHANNEL_OFDM }, \ | ||
424 | /*5320*/ { 64, DMN_FCC1, CHANNEL_OFDM }, \ | ||
425 | /*5745*/ { 149, DMN_FCC1, CHANNEL_OFDM }, \ | ||
426 | /*5760*/ { 152, DMN_FCC1, CHANNEL_OFDM|CHANNEL_TURBO }, \ | ||
427 | /*5765*/ { 153, DMN_FCC1, CHANNEL_OFDM }, \ | ||
428 | /*5785*/ { 157, DMN_FCC1, CHANNEL_OFDM }, \ | ||
429 | /*5800*/ { 160, DMN_FCC1, CHANNEL_OFDM|CHANNEL_TURBO }, \ | ||
430 | /*5805*/ { 161, DMN_FCC1, CHANNEL_OFDM }, \ | ||
431 | /*5825*/ { 165, DMN_FCC1, CHANNEL_OFDM }, \ | ||
432 | \ | ||
433 | /*5180*/ { 36, DMN_FCC2, CHANNEL_OFDM }, \ | ||
434 | /*5200*/ { 40, DMN_FCC2, CHANNEL_OFDM }, \ | ||
435 | /*5220*/ { 44, DMN_FCC2, CHANNEL_OFDM }, \ | ||
436 | /*5240*/ { 48, DMN_FCC2, CHANNEL_OFDM }, \ | ||
437 | /*5260*/ { 52, DMN_FCC2, CHANNEL_OFDM }, \ | ||
438 | /*5280*/ { 56, DMN_FCC2, CHANNEL_OFDM }, \ | ||
439 | /*5300*/ { 60, DMN_FCC2, CHANNEL_OFDM }, \ | ||
440 | /*5320*/ { 64, DMN_FCC2, CHANNEL_OFDM }, \ | ||
441 | /*5745*/ { 149, DMN_FCC2, CHANNEL_OFDM }, \ | ||
442 | /*5765*/ { 153, DMN_FCC2, CHANNEL_OFDM }, \ | ||
443 | /*5785*/ { 157, DMN_FCC2, CHANNEL_OFDM }, \ | ||
444 | /*5805*/ { 161, DMN_FCC2, CHANNEL_OFDM }, \ | ||
445 | /*5825*/ { 165, DMN_FCC2, CHANNEL_OFDM }, \ | ||
446 | \ | ||
447 | /*5180*/ { 36, DMN_FCC3, CHANNEL_OFDM }, \ | ||
448 | /*5200*/ { 40, DMN_FCC3, CHANNEL_OFDM }, \ | ||
449 | /*5210*/ { 42, DMN_FCC3, CHANNEL_OFDM|CHANNEL_TURBO }, \ | ||
450 | /*5220*/ { 44, DMN_FCC3, CHANNEL_OFDM }, \ | ||
451 | /*5240*/ { 48, DMN_FCC3, CHANNEL_OFDM }, \ | ||
452 | /*5250*/ { 50, DMN_FCC3, CHANNEL_OFDM|CHANNEL_TURBO }, \ | ||
453 | /*5260*/ { 52, DMN_FCC3, CHANNEL_OFDM }, \ | ||
454 | /*5280*/ { 56, DMN_FCC3, CHANNEL_OFDM }, \ | ||
455 | /*5290*/ { 58, DMN_FCC3, CHANNEL_OFDM|CHANNEL_TURBO }, \ | ||
456 | /*5300*/ { 60, DMN_FCC3, CHANNEL_OFDM }, \ | ||
457 | /*5320*/ { 64, DMN_FCC3, CHANNEL_OFDM }, \ | ||
458 | /*5500*/ { 100, DMN_FCC3, CHANNEL_OFDM }, \ | ||
459 | /*5520*/ { 104, DMN_FCC3, CHANNEL_OFDM }, \ | ||
460 | /*5540*/ { 108, DMN_FCC3, CHANNEL_OFDM }, \ | ||
461 | /*5560*/ { 112, DMN_FCC3, CHANNEL_OFDM }, \ | ||
462 | /*5580*/ { 116, DMN_FCC3, CHANNEL_OFDM }, \ | ||
463 | /*5600*/ { 120, DMN_FCC3, CHANNEL_OFDM }, \ | ||
464 | /*5620*/ { 124, DMN_FCC3, CHANNEL_OFDM }, \ | ||
465 | /*5640*/ { 128, DMN_FCC3, CHANNEL_OFDM }, \ | ||
466 | /*5660*/ { 132, DMN_FCC3, CHANNEL_OFDM }, \ | ||
467 | /*5680*/ { 136, DMN_FCC3, CHANNEL_OFDM }, \ | ||
468 | /*5700*/ { 140, DMN_FCC3, CHANNEL_OFDM }, \ | ||
469 | /*5745*/ { 149, DMN_FCC3, CHANNEL_OFDM }, \ | ||
470 | /*5760*/ { 152, DMN_FCC3, CHANNEL_OFDM|CHANNEL_TURBO }, \ | ||
471 | /*5765*/ { 153, DMN_FCC3, CHANNEL_OFDM }, \ | ||
472 | /*5785*/ { 157, DMN_FCC3, CHANNEL_OFDM }, \ | ||
473 | /*5800*/ { 160, DMN_FCC3, CHANNEL_OFDM|CHANNEL_TURBO }, \ | ||
474 | /*5805*/ { 161, DMN_FCC3, CHANNEL_OFDM }, \ | ||
475 | /*5825*/ { 165, DMN_FCC3, CHANNEL_OFDM }, \ | ||
476 | \ | ||
477 | /*5170*/ { 34, DMN_MKK1, CHANNEL_OFDM }, \ | ||
478 | /*5190*/ { 38, DMN_MKK1, CHANNEL_OFDM }, \ | ||
479 | /*5210*/ { 42, DMN_MKK1, CHANNEL_OFDM }, \ | ||
480 | /*5230*/ { 46, DMN_MKK1, CHANNEL_OFDM }, \ | ||
481 | \ | ||
482 | /*5040*/ { 8, DMN_MKK2, CHANNEL_OFDM }, \ | ||
483 | /*5060*/ { 12, DMN_MKK2, CHANNEL_OFDM }, \ | ||
484 | /*5080*/ { 16, DMN_MKK2, CHANNEL_OFDM }, \ | ||
485 | /*5170*/ { 34, DMN_MKK2, CHANNEL_OFDM }, \ | ||
486 | /*5190*/ { 38, DMN_MKK2, CHANNEL_OFDM }, \ | ||
487 | /*5210*/ { 42, DMN_MKK2, CHANNEL_OFDM }, \ | ||
488 | /*5230*/ { 46, DMN_MKK2, CHANNEL_OFDM }, \ | ||
489 | \ | ||
490 | /*5180*/ { 36, DMN_WORLD, CHANNEL_OFDM }, \ | ||
491 | /*5200*/ { 40, DMN_WORLD, CHANNEL_OFDM }, \ | ||
492 | /*5220*/ { 44, DMN_WORLD, CHANNEL_OFDM }, \ | ||
493 | /*5240*/ { 48, DMN_WORLD, CHANNEL_OFDM }, \ | ||
494 | } | ||
495 | |||
496 | enum ath5k_regdom ath5k_regdom2flag(enum ath5k_regdom, u16); | ||
497 | u16 ath5k_regdom_from_ieee(enum ath5k_regdom ieee); | ||
498 | enum ath5k_regdom ath5k_regdom_to_ieee(u16 regdomain); | ||
499 | |||
500 | #endif | ||
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 345c34bdae9a..cf5c046c9fa8 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
@@ -2343,6 +2343,13 @@ static void b43_mac_suspend(struct b43_wldev *dev) | |||
2343 | & ~B43_MACCTL_ENABLED); | 2343 | & ~B43_MACCTL_ENABLED); |
2344 | /* force pci to flush the write */ | 2344 | /* force pci to flush the write */ |
2345 | b43_read32(dev, B43_MMIO_MACCTL); | 2345 | b43_read32(dev, B43_MMIO_MACCTL); |
2346 | for (i = 35; i; i--) { | ||
2347 | tmp = b43_read32(dev, B43_MMIO_GEN_IRQ_REASON); | ||
2348 | if (tmp & B43_IRQ_MAC_SUSPENDED) | ||
2349 | goto out; | ||
2350 | udelay(10); | ||
2351 | } | ||
2352 | /* Hm, it seems this will take some time. Use msleep(). */ | ||
2346 | for (i = 40; i; i--) { | 2353 | for (i = 40; i; i--) { |
2347 | tmp = b43_read32(dev, B43_MMIO_GEN_IRQ_REASON); | 2354 | tmp = b43_read32(dev, B43_MMIO_GEN_IRQ_REASON); |
2348 | if (tmp & B43_IRQ_MAC_SUSPENDED) | 2355 | if (tmp & B43_IRQ_MAC_SUSPENDED) |
diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h index 242b8ad4e33c..ded3cd31b3df 100644 --- a/drivers/net/wireless/b43legacy/b43legacy.h +++ b/drivers/net/wireless/b43legacy/b43legacy.h | |||
@@ -97,6 +97,7 @@ | |||
97 | #define B43legacy_MMIO_RADIO_HWENABLED_LO 0x49A | 97 | #define B43legacy_MMIO_RADIO_HWENABLED_LO 0x49A |
98 | #define B43legacy_MMIO_GPIO_CONTROL 0x49C | 98 | #define B43legacy_MMIO_GPIO_CONTROL 0x49C |
99 | #define B43legacy_MMIO_GPIO_MASK 0x49E | 99 | #define B43legacy_MMIO_GPIO_MASK 0x49E |
100 | #define B43legacy_MMIO_TSF_CFP_PRETBTT 0x612 | ||
100 | #define B43legacy_MMIO_TSF_0 0x632 /* core rev < 3 only */ | 101 | #define B43legacy_MMIO_TSF_0 0x632 /* core rev < 3 only */ |
101 | #define B43legacy_MMIO_TSF_1 0x634 /* core rev < 3 only */ | 102 | #define B43legacy_MMIO_TSF_1 0x634 /* core rev < 3 only */ |
102 | #define B43legacy_MMIO_TSF_2 0x636 /* core rev < 3 only */ | 103 | #define B43legacy_MMIO_TSF_2 0x636 /* core rev < 3 only */ |
@@ -149,6 +150,8 @@ | |||
149 | #define B43legacy_SHM_SH_UCODEPATCH 0x0002 /* Microcode patchlevel */ | 150 | #define B43legacy_SHM_SH_UCODEPATCH 0x0002 /* Microcode patchlevel */ |
150 | #define B43legacy_SHM_SH_UCODEDATE 0x0004 /* Microcode date */ | 151 | #define B43legacy_SHM_SH_UCODEDATE 0x0004 /* Microcode date */ |
151 | #define B43legacy_SHM_SH_UCODETIME 0x0006 /* Microcode time */ | 152 | #define B43legacy_SHM_SH_UCODETIME 0x0006 /* Microcode time */ |
153 | #define B43legacy_SHM_SH_SPUWKUP 0x0094 /* pre-wakeup for synth PU in us */ | ||
154 | #define B43legacy_SHM_SH_PRETBTT 0x0096 /* pre-TBTT in us */ | ||
152 | 155 | ||
153 | #define B43legacy_UCODEFLAGS_OFFSET 0x005E | 156 | #define B43legacy_UCODEFLAGS_OFFSET 0x005E |
154 | 157 | ||
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index f518e796bdec..2422a5dab1d2 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c | |||
@@ -3005,6 +3005,34 @@ static void b43legacy_set_retry_limits(struct b43legacy_wldev *dev, | |||
3005 | b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS, 0x0007, long_retry); | 3005 | b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS, 0x0007, long_retry); |
3006 | } | 3006 | } |
3007 | 3007 | ||
3008 | static void b43legacy_set_synth_pu_delay(struct b43legacy_wldev *dev, | ||
3009 | bool idle) { | ||
3010 | u16 pu_delay = 1050; | ||
3011 | |||
3012 | if (b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS) || idle) | ||
3013 | pu_delay = 500; | ||
3014 | if ((dev->phy.radio_ver == 0x2050) && (dev->phy.radio_rev == 8)) | ||
3015 | pu_delay = max(pu_delay, (u16)2400); | ||
3016 | |||
3017 | b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, | ||
3018 | B43legacy_SHM_SH_SPUWKUP, pu_delay); | ||
3019 | } | ||
3020 | |||
3021 | /* Set the TSF CFP pre-TargetBeaconTransmissionTime. */ | ||
3022 | static void b43legacy_set_pretbtt(struct b43legacy_wldev *dev) | ||
3023 | { | ||
3024 | u16 pretbtt; | ||
3025 | |||
3026 | /* The time value is in microseconds. */ | ||
3027 | if (b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS)) | ||
3028 | pretbtt = 2; | ||
3029 | else | ||
3030 | pretbtt = 250; | ||
3031 | b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, | ||
3032 | B43legacy_SHM_SH_PRETBTT, pretbtt); | ||
3033 | b43legacy_write16(dev, B43legacy_MMIO_TSF_CFP_PRETBTT, pretbtt); | ||
3034 | } | ||
3035 | |||
3008 | /* Shutdown a wireless core */ | 3036 | /* Shutdown a wireless core */ |
3009 | /* Locking: wl->mutex */ | 3037 | /* Locking: wl->mutex */ |
3010 | static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev) | 3038 | static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev) |
@@ -3191,9 +3219,7 @@ static int b43legacy_wireless_core_init(struct b43legacy_wldev *dev) | |||
3191 | if (err) | 3219 | if (err) |
3192 | goto err_chip_exit; | 3220 | goto err_chip_exit; |
3193 | 3221 | ||
3194 | b43legacy_write16(dev, 0x0612, 0x0050); | 3222 | b43legacy_set_synth_pu_delay(dev, 1); |
3195 | b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0416, 0x0050); | ||
3196 | b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0414, 0x01F4); | ||
3197 | 3223 | ||
3198 | ssb_bus_powerup(bus, 1); /* Enable dynamic PCTL */ | 3224 | ssb_bus_powerup(bus, 1); /* Enable dynamic PCTL */ |
3199 | b43legacy_upload_card_macaddress(dev); | 3225 | b43legacy_upload_card_macaddress(dev); |
@@ -3249,6 +3275,8 @@ static int b43legacy_op_add_interface(struct ieee80211_hw *hw, | |||
3249 | 3275 | ||
3250 | spin_lock_irqsave(&wl->irq_lock, flags); | 3276 | spin_lock_irqsave(&wl->irq_lock, flags); |
3251 | b43legacy_adjust_opmode(dev); | 3277 | b43legacy_adjust_opmode(dev); |
3278 | b43legacy_set_pretbtt(dev); | ||
3279 | b43legacy_set_synth_pu_delay(dev, 0); | ||
3252 | b43legacy_upload_card_macaddress(dev); | 3280 | b43legacy_upload_card_macaddress(dev); |
3253 | spin_unlock_irqrestore(&wl->irq_lock, flags); | 3281 | spin_unlock_irqrestore(&wl->irq_lock, flags); |
3254 | 3282 | ||
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index bcaa61b7c563..f844b738d34e 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig | |||
@@ -6,7 +6,7 @@ config IWLWIFI_LEDS | |||
6 | bool | 6 | bool |
7 | default n | 7 | default n |
8 | 8 | ||
9 | config IWLCORE_RFKILL | 9 | config IWLWIFI_RFKILL |
10 | boolean "IWLWIFI RF kill support" | 10 | boolean "IWLWIFI RF kill support" |
11 | depends on IWLCORE | 11 | depends on IWLCORE |
12 | select RFKILL | 12 | select RFKILL |
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 2751e8aa97d7..4f3e88b12e3a 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile | |||
@@ -1,26 +1,13 @@ | |||
1 | obj-$(CONFIG_IWLCORE) += iwlcore.o | 1 | obj-$(CONFIG_IWLCORE) := iwlcore.o |
2 | iwlcore-objs = iwl-core.o iwl-eeprom.o iwl-hcmd.o | 2 | iwlcore-objs := iwl-core.o iwl-eeprom.o iwl-hcmd.o |
3 | 3 | iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o | |
4 | ifeq ($(CONFIG_IWLWIFI_DEBUGFS),y) | 4 | iwlcore-$(CONFIG_IWLWIFI_LEDS) += iwl-led.o |
5 | iwlcore-objs += iwl-debugfs.o | 5 | iwlcore-$(CONFIG_IWLWIFI_RFKILL) += iwl-rfkill.o |
6 | endif | ||
7 | |||
8 | ifeq ($(CONFIG_IWLWIFI_LEDS),y) | ||
9 | iwlcore-objs += iwl-led.o | ||
10 | endif | ||
11 | |||
12 | ifeq ($(CONFIG_IWLCORE_RFKILL),y) | ||
13 | iwlcore-objs += iwl-rfkill.o | ||
14 | endif | ||
15 | 6 | ||
16 | obj-$(CONFIG_IWL3945) += iwl3945.o | 7 | obj-$(CONFIG_IWL3945) += iwl3945.o |
17 | iwl3945-objs = iwl3945-base.o iwl-3945.o iwl-3945-rs.o | 8 | iwl3945-objs := iwl3945-base.o iwl-3945.o iwl-3945-rs.o |
18 | 9 | iwl3945-$(CONFIG_IWL3945_LEDS) += iwl-3945-led.o | |
19 | ifeq ($(CONFIG_IWL3945_LEDS),y) | ||
20 | iwl3945-objs += iwl-3945-led.o | ||
21 | endif | ||
22 | |||
23 | 10 | ||
24 | obj-$(CONFIG_IWL4965) += iwl4965.o | 11 | obj-$(CONFIG_IWL4965) += iwl4965.o |
25 | iwl4965-objs = iwl4965-base.o iwl-4965.o iwl-4965-rs.o | 12 | iwl4965-objs := iwl4965-base.o iwl-4965.o iwl-4965-rs.o iwl-sta.o |
26 | 13 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h index 368da9852aab..ad612a8719f4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h | |||
@@ -456,7 +456,7 @@ struct iwl3945_eeprom { | |||
456 | /* Size of uCode instruction memory in bootstrap state machine */ | 456 | /* Size of uCode instruction memory in bootstrap state machine */ |
457 | #define IWL_MAX_BSM_SIZE ALM_RTC_INST_SIZE | 457 | #define IWL_MAX_BSM_SIZE ALM_RTC_INST_SIZE |
458 | 458 | ||
459 | #define IWL_MAX_NUM_QUEUES 8 | 459 | #define IWL39_MAX_NUM_QUEUES 8 |
460 | 460 | ||
461 | static inline int iwl3945_hw_valid_rtc_data_addr(u32 addr) | 461 | static inline int iwl3945_hw_valid_rtc_data_addr(u32 addr) |
462 | { | 462 | { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 3dc7f0fbf02f..45c1c5533bf0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h | |||
@@ -687,6 +687,8 @@ enum { | |||
687 | 687 | ||
688 | #endif | 688 | #endif |
689 | 689 | ||
690 | #define IWL_MAX_NUM_QUEUES IWL39_MAX_NUM_QUEUES | ||
691 | |||
690 | struct iwl3945_priv { | 692 | struct iwl3945_priv { |
691 | 693 | ||
692 | /* ieee device used by generic ieee processing code */ | 694 | /* ieee device used by generic ieee processing code */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h index 7e36ecb27575..3bcd107e2d71 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h | |||
@@ -84,6 +84,9 @@ enum { | |||
84 | REPLY_REMOVE_STA = 0x19, /* not used */ | 84 | REPLY_REMOVE_STA = 0x19, /* not used */ |
85 | REPLY_REMOVE_ALL_STA = 0x1a, /* not used */ | 85 | REPLY_REMOVE_ALL_STA = 0x1a, /* not used */ |
86 | 86 | ||
87 | /* Security */ | ||
88 | REPLY_WEPKEY = 0x20, | ||
89 | |||
87 | /* RX, TX, LEDs */ | 90 | /* RX, TX, LEDs */ |
88 | REPLY_TX = 0x1c, | 91 | REPLY_TX = 0x1c, |
89 | REPLY_RATE_SCALE = 0x47, /* 3945 only */ | 92 | REPLY_RATE_SCALE = 0x47, /* 3945 only */ |
@@ -266,11 +269,10 @@ struct iwl_cmd_header { | |||
266 | * 10 B active, A inactive | 269 | * 10 B active, A inactive |
267 | * 11 Both active | 270 | * 11 Both active |
268 | */ | 271 | */ |
269 | #define RATE_MCS_ANT_A_POS 14 | 272 | #define RATE_MCS_ANT_POS 14 |
270 | #define RATE_MCS_ANT_B_POS 15 | 273 | #define RATE_MCS_ANT_A_MSK 0x04000 |
271 | #define RATE_MCS_ANT_A_MSK 0x4000 | 274 | #define RATE_MCS_ANT_B_MSK 0x08000 |
272 | #define RATE_MCS_ANT_B_MSK 0x8000 | 275 | #define RATE_MCS_ANT_AB_MSK 0x0C000 |
273 | #define RATE_MCS_ANT_AB_MSK 0xc000 | ||
274 | 276 | ||
275 | 277 | ||
276 | /** | 278 | /** |
@@ -850,6 +852,30 @@ struct iwl4965_add_sta_resp { | |||
850 | u8 status; /* ADD_STA_* */ | 852 | u8 status; /* ADD_STA_* */ |
851 | } __attribute__ ((packed)); | 853 | } __attribute__ ((packed)); |
852 | 854 | ||
855 | /* | ||
856 | * REPLY_WEP_KEY = 0x20 | ||
857 | */ | ||
858 | struct iwl_wep_key { | ||
859 | u8 key_index; | ||
860 | u8 key_offset; | ||
861 | u8 reserved1[2]; | ||
862 | u8 key_size; | ||
863 | u8 reserved2[3]; | ||
864 | u8 key[16]; | ||
865 | } __attribute__ ((packed)); | ||
866 | |||
867 | struct iwl_wep_cmd { | ||
868 | u8 num_keys; | ||
869 | u8 global_key_type; | ||
870 | u8 flags; | ||
871 | u8 reserved; | ||
872 | struct iwl_wep_key key[0]; | ||
873 | } __attribute__ ((packed)); | ||
874 | |||
875 | #define WEP_KEY_WEP_TYPE 1 | ||
876 | #define WEP_KEYS_MAX 4 | ||
877 | #define WEP_INVALID_OFFSET 0xff | ||
878 | #define WEP_KEY_LEN_128 13 | ||
853 | 879 | ||
854 | /****************************************************************************** | 880 | /****************************************************************************** |
855 | * (4) | 881 | * (4) |
@@ -1387,11 +1413,11 @@ struct iwl4965_txpowertable_cmd { | |||
1387 | 1413 | ||
1388 | 1414 | ||
1389 | /** | 1415 | /** |
1390 | * struct iwl4965_link_qual_general_params | 1416 | * struct iwl_link_qual_general_params |
1391 | * | 1417 | * |
1392 | * Used in REPLY_TX_LINK_QUALITY_CMD | 1418 | * Used in REPLY_TX_LINK_QUALITY_CMD |
1393 | */ | 1419 | */ |
1394 | struct iwl4965_link_qual_general_params { | 1420 | struct iwl_link_qual_general_params { |
1395 | u8 flags; | 1421 | u8 flags; |
1396 | 1422 | ||
1397 | /* No entries at or above this (driver chosen) index contain MIMO */ | 1423 | /* No entries at or above this (driver chosen) index contain MIMO */ |
@@ -1418,11 +1444,11 @@ struct iwl4965_link_qual_general_params { | |||
1418 | } __attribute__ ((packed)); | 1444 | } __attribute__ ((packed)); |
1419 | 1445 | ||
1420 | /** | 1446 | /** |
1421 | * struct iwl4965_link_qual_agg_params | 1447 | * struct iwl_link_qual_agg_params |
1422 | * | 1448 | * |
1423 | * Used in REPLY_TX_LINK_QUALITY_CMD | 1449 | * Used in REPLY_TX_LINK_QUALITY_CMD |
1424 | */ | 1450 | */ |
1425 | struct iwl4965_link_qual_agg_params { | 1451 | struct iwl_link_qual_agg_params { |
1426 | 1452 | ||
1427 | /* Maximum number of uSec in aggregation. | 1453 | /* Maximum number of uSec in aggregation. |
1428 | * Driver should set this to 4000 (4 milliseconds). */ | 1454 | * Driver should set this to 4000 (4 milliseconds). */ |
@@ -1632,14 +1658,14 @@ struct iwl4965_link_qual_agg_params { | |||
1632 | * legacy), and then repeat the search process. | 1658 | * legacy), and then repeat the search process. |
1633 | * | 1659 | * |
1634 | */ | 1660 | */ |
1635 | struct iwl4965_link_quality_cmd { | 1661 | struct iwl_link_quality_cmd { |
1636 | 1662 | ||
1637 | /* Index of destination/recipient station in uCode's station table */ | 1663 | /* Index of destination/recipient station in uCode's station table */ |
1638 | u8 sta_id; | 1664 | u8 sta_id; |
1639 | u8 reserved1; | 1665 | u8 reserved1; |
1640 | __le16 control; /* not used */ | 1666 | __le16 control; /* not used */ |
1641 | struct iwl4965_link_qual_general_params general_params; | 1667 | struct iwl_link_qual_general_params general_params; |
1642 | struct iwl4965_link_qual_agg_params agg_params; | 1668 | struct iwl_link_qual_agg_params agg_params; |
1643 | 1669 | ||
1644 | /* | 1670 | /* |
1645 | * Rate info; when using rate-scaling, Tx command's initial_rate_index | 1671 | * Rate info; when using rate-scaling, Tx command's initial_rate_index |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h index de7bac149723..1a66b508a8ea 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h | |||
@@ -1385,10 +1385,10 @@ static inline __le32 iwl4965_hw_set_rate_n_flags(u8 rate, u16 flags) | |||
1385 | * up to 7 DMA channels (FIFOs). Each Tx queue is supported by a circular array | 1385 | * up to 7 DMA channels (FIFOs). Each Tx queue is supported by a circular array |
1386 | * in DRAM containing 256 Transmit Frame Descriptors (TFDs). | 1386 | * in DRAM containing 256 Transmit Frame Descriptors (TFDs). |
1387 | */ | 1387 | */ |
1388 | #define IWL4965_MAX_WIN_SIZE 64 | 1388 | #define IWL4965_MAX_WIN_SIZE 64 |
1389 | #define IWL4965_QUEUE_SIZE 256 | 1389 | #define IWL4965_QUEUE_SIZE 256 |
1390 | #define IWL4965_NUM_FIFOS 7 | 1390 | #define IWL4965_NUM_FIFOS 7 |
1391 | #define IWL_MAX_NUM_QUEUES 16 | 1391 | #define IWL4965_MAX_NUM_QUEUES 16 |
1392 | 1392 | ||
1393 | 1393 | ||
1394 | /** | 1394 | /** |
@@ -1553,30 +1553,30 @@ struct iwl4965_sched_queue_byte_cnt_tbl { | |||
1553 | */ | 1553 | */ |
1554 | struct iwl4965_shared { | 1554 | struct iwl4965_shared { |
1555 | struct iwl4965_sched_queue_byte_cnt_tbl | 1555 | struct iwl4965_sched_queue_byte_cnt_tbl |
1556 | queues_byte_cnt_tbls[IWL_MAX_NUM_QUEUES]; | 1556 | queues_byte_cnt_tbls[IWL4965_MAX_NUM_QUEUES]; |
1557 | __le32 val0; | 1557 | __le32 rb_closed; |
1558 | 1558 | ||
1559 | /* __le32 rb_closed_stts_rb_num:12; */ | 1559 | /* __le32 rb_closed_stts_rb_num:12; */ |
1560 | #define IWL_rb_closed_stts_rb_num_POS 0 | 1560 | #define IWL_rb_closed_stts_rb_num_POS 0 |
1561 | #define IWL_rb_closed_stts_rb_num_LEN 12 | 1561 | #define IWL_rb_closed_stts_rb_num_LEN 12 |
1562 | #define IWL_rb_closed_stts_rb_num_SYM val0 | 1562 | #define IWL_rb_closed_stts_rb_num_SYM rb_closed |
1563 | /* __le32 rsrv1:4; */ | 1563 | /* __le32 rsrv1:4; */ |
1564 | /* __le32 rb_closed_stts_rx_frame_num:12; */ | 1564 | /* __le32 rb_closed_stts_rx_frame_num:12; */ |
1565 | #define IWL_rb_closed_stts_rx_frame_num_POS 16 | 1565 | #define IWL_rb_closed_stts_rx_frame_num_POS 16 |
1566 | #define IWL_rb_closed_stts_rx_frame_num_LEN 12 | 1566 | #define IWL_rb_closed_stts_rx_frame_num_LEN 12 |
1567 | #define IWL_rb_closed_stts_rx_frame_num_SYM val0 | 1567 | #define IWL_rb_closed_stts_rx_frame_num_SYM rb_closed |
1568 | /* __le32 rsrv2:4; */ | 1568 | /* __le32 rsrv2:4; */ |
1569 | 1569 | ||
1570 | __le32 val1; | 1570 | __le32 frm_finished; |
1571 | /* __le32 frame_finished_stts_rb_num:12; */ | 1571 | /* __le32 frame_finished_stts_rb_num:12; */ |
1572 | #define IWL_frame_finished_stts_rb_num_POS 0 | 1572 | #define IWL_frame_finished_stts_rb_num_POS 0 |
1573 | #define IWL_frame_finished_stts_rb_num_LEN 12 | 1573 | #define IWL_frame_finished_stts_rb_num_LEN 12 |
1574 | #define IWL_frame_finished_stts_rb_num_SYM val1 | 1574 | #define IWL_frame_finished_stts_rb_num_SYM frm_finished |
1575 | /* __le32 rsrv3:4; */ | 1575 | /* __le32 rsrv3:4; */ |
1576 | /* __le32 frame_finished_stts_rx_frame_num:12; */ | 1576 | /* __le32 frame_finished_stts_rx_frame_num:12; */ |
1577 | #define IWL_frame_finished_stts_rx_frame_num_POS 16 | 1577 | #define IWL_frame_finished_stts_rx_frame_num_POS 16 |
1578 | #define IWL_frame_finished_stts_rx_frame_num_LEN 12 | 1578 | #define IWL_frame_finished_stts_rx_frame_num_LEN 12 |
1579 | #define IWL_frame_finished_stts_rx_frame_num_SYM val1 | 1579 | #define IWL_frame_finished_stts_rx_frame_num_SYM frm_finished |
1580 | /* __le32 rsrv4:4; */ | 1580 | /* __le32 rsrv4:4; */ |
1581 | 1581 | ||
1582 | __le32 padding1; /* so that allocation will be aligned to 16B */ | 1582 | __le32 padding1; /* so that allocation will be aligned to 16B */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c index 315b0433801e..b608e1ca8b40 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c | |||
@@ -150,7 +150,7 @@ struct iwl4965_lq_sta { | |||
150 | u16 active_mimo_rate; | 150 | u16 active_mimo_rate; |
151 | u16 active_rate_basic; | 151 | u16 active_rate_basic; |
152 | 152 | ||
153 | struct iwl4965_link_quality_cmd lq; | 153 | struct iwl_link_quality_cmd lq; |
154 | struct iwl4965_scale_tbl_info lq_info[LQ_SIZE]; /* "active", "search" */ | 154 | struct iwl4965_scale_tbl_info lq_info[LQ_SIZE]; /* "active", "search" */ |
155 | #ifdef CONFIG_IWL4965_HT | 155 | #ifdef CONFIG_IWL4965_HT |
156 | struct iwl4965_traffic_load load[TID_MAX_LOAD_COUNT]; | 156 | struct iwl4965_traffic_load load[TID_MAX_LOAD_COUNT]; |
@@ -173,7 +173,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, | |||
173 | struct sta_info *sta); | 173 | struct sta_info *sta); |
174 | static void rs_fill_link_cmd(struct iwl4965_lq_sta *lq_sta, | 174 | static void rs_fill_link_cmd(struct iwl4965_lq_sta *lq_sta, |
175 | struct iwl4965_rate *tx_mcs, | 175 | struct iwl4965_rate *tx_mcs, |
176 | struct iwl4965_link_quality_cmd *tbl); | 176 | struct iwl_link_quality_cmd *tbl); |
177 | 177 | ||
178 | 178 | ||
179 | #ifdef CONFIG_MAC80211_DEBUGFS | 179 | #ifdef CONFIG_MAC80211_DEBUGFS |
@@ -230,58 +230,11 @@ static s32 expected_tpt_mimo40MHzSGI[IWL_RATE_COUNT] = { | |||
230 | 0, 0, 0, 0, 131, 131, 191, 222, 242, 270, 284, 289, 293 | 230 | 0, 0, 0, 0, 131, 131, 191, 222, 242, 270, 284, 289, 293 |
231 | }; | 231 | }; |
232 | 232 | ||
233 | static int iwl4965_lq_sync_callback(struct iwl_priv *priv, | ||
234 | struct iwl_cmd *cmd, struct sk_buff *skb) | ||
235 | { | ||
236 | /*We didn't cache the SKB; let the caller free it */ | ||
237 | return 1; | ||
238 | } | ||
239 | |||
240 | static inline u8 iwl4965_rate_get_rate(u32 rate_n_flags) | 233 | static inline u8 iwl4965_rate_get_rate(u32 rate_n_flags) |
241 | { | 234 | { |
242 | return (u8)(rate_n_flags & 0xFF); | 235 | return (u8)(rate_n_flags & 0xFF); |
243 | } | 236 | } |
244 | 237 | ||
245 | static int rs_send_lq_cmd(struct iwl_priv *priv, | ||
246 | struct iwl4965_link_quality_cmd *lq, u8 flags) | ||
247 | { | ||
248 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
249 | int i; | ||
250 | #endif | ||
251 | struct iwl_host_cmd cmd = { | ||
252 | .id = REPLY_TX_LINK_QUALITY_CMD, | ||
253 | .len = sizeof(struct iwl4965_link_quality_cmd), | ||
254 | .meta.flags = flags, | ||
255 | .data = lq, | ||
256 | }; | ||
257 | |||
258 | if ((lq->sta_id == 0xFF) && | ||
259 | (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)) | ||
260 | return -EINVAL; | ||
261 | |||
262 | if (lq->sta_id == 0xFF) | ||
263 | lq->sta_id = IWL_AP_ID; | ||
264 | |||
265 | IWL_DEBUG_RATE("lq station id 0x%x\n", lq->sta_id); | ||
266 | IWL_DEBUG_RATE("lq dta 0x%X 0x%X\n", | ||
267 | lq->general_params.single_stream_ant_msk, | ||
268 | lq->general_params.dual_stream_ant_msk); | ||
269 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
270 | for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) | ||
271 | IWL_DEBUG_RATE("lq index %d 0x%X\n", | ||
272 | i, lq->rs_table[i].rate_n_flags); | ||
273 | #endif | ||
274 | |||
275 | if (flags & CMD_ASYNC) | ||
276 | cmd.meta.u.callback = iwl4965_lq_sync_callback; | ||
277 | |||
278 | if (iwl_is_associated(priv) && priv->assoc_station_added && | ||
279 | priv->lq_mngr.lq_ready) | ||
280 | return iwl_send_cmd(priv, &cmd); | ||
281 | |||
282 | return 0; | ||
283 | } | ||
284 | |||
285 | static void rs_rate_scale_clear_window(struct iwl4965_rate_scale_data *window) | 238 | static void rs_rate_scale_clear_window(struct iwl4965_rate_scale_data *window) |
286 | { | 239 | { |
287 | window->data = 0; | 240 | window->data = 0; |
@@ -819,7 +772,7 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, | |||
819 | u8 retries; | 772 | u8 retries; |
820 | int rs_index, index = 0; | 773 | int rs_index, index = 0; |
821 | struct iwl4965_lq_sta *lq_sta; | 774 | struct iwl4965_lq_sta *lq_sta; |
822 | struct iwl4965_link_quality_cmd *table; | 775 | struct iwl_link_quality_cmd *table; |
823 | struct sta_info *sta; | 776 | struct sta_info *sta; |
824 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 777 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
825 | struct iwl_priv *priv = (struct iwl_priv *)priv_rate; | 778 | struct iwl_priv *priv = (struct iwl_priv *)priv_rate; |
@@ -1879,7 +1832,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, | |||
1879 | if (update_lq) { | 1832 | if (update_lq) { |
1880 | rs_mcs_from_tbl(&mcs_rate, tbl, index, is_green); | 1833 | rs_mcs_from_tbl(&mcs_rate, tbl, index, is_green); |
1881 | rs_fill_link_cmd(lq_sta, &mcs_rate, &lq_sta->lq); | 1834 | rs_fill_link_cmd(lq_sta, &mcs_rate, &lq_sta->lq); |
1882 | rs_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); | 1835 | iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); |
1883 | } | 1836 | } |
1884 | goto out; | 1837 | goto out; |
1885 | 1838 | ||
@@ -2044,7 +1997,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, | |||
2044 | if (update_lq) { | 1997 | if (update_lq) { |
2045 | rs_mcs_from_tbl(&mcs_rate, tbl, index, is_green); | 1998 | rs_mcs_from_tbl(&mcs_rate, tbl, index, is_green); |
2046 | rs_fill_link_cmd(lq_sta, &mcs_rate, &lq_sta->lq); | 1999 | rs_fill_link_cmd(lq_sta, &mcs_rate, &lq_sta->lq); |
2047 | rs_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); | 2000 | iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); |
2048 | } | 2001 | } |
2049 | 2002 | ||
2050 | /* Should we stay with this modulation mode, or search for a new one? */ | 2003 | /* Should we stay with this modulation mode, or search for a new one? */ |
@@ -2084,7 +2037,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, | |||
2084 | tbl->current_rate.rate_n_flags, index); | 2037 | tbl->current_rate.rate_n_flags, index); |
2085 | rs_fill_link_cmd(lq_sta, &tbl->current_rate, | 2038 | rs_fill_link_cmd(lq_sta, &tbl->current_rate, |
2086 | &lq_sta->lq); | 2039 | &lq_sta->lq); |
2087 | rs_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); | 2040 | iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); |
2088 | } | 2041 | } |
2089 | 2042 | ||
2090 | /* If the "active" (non-search) mode was legacy, | 2043 | /* If the "active" (non-search) mode was legacy, |
@@ -2197,7 +2150,7 @@ static void rs_initialize_lq(struct iwl_priv *priv, | |||
2197 | tbl->current_rate.rate_n_flags = mcs_rate.rate_n_flags; | 2150 | tbl->current_rate.rate_n_flags = mcs_rate.rate_n_flags; |
2198 | rs_get_expected_tpt_table(lq_sta, tbl); | 2151 | rs_get_expected_tpt_table(lq_sta, tbl); |
2199 | rs_fill_link_cmd(lq_sta, &mcs_rate, &lq_sta->lq); | 2152 | rs_fill_link_cmd(lq_sta, &mcs_rate, &lq_sta->lq); |
2200 | rs_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); | 2153 | iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); |
2201 | out: | 2154 | out: |
2202 | return; | 2155 | return; |
2203 | } | 2156 | } |
@@ -2392,7 +2345,7 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, | |||
2392 | 2345 | ||
2393 | static void rs_fill_link_cmd(struct iwl4965_lq_sta *lq_sta, | 2346 | static void rs_fill_link_cmd(struct iwl4965_lq_sta *lq_sta, |
2394 | struct iwl4965_rate *tx_mcs, | 2347 | struct iwl4965_rate *tx_mcs, |
2395 | struct iwl4965_link_quality_cmd *lq_cmd) | 2348 | struct iwl_link_quality_cmd *lq_cmd) |
2396 | { | 2349 | { |
2397 | int index = 0; | 2350 | int index = 0; |
2398 | int rate_idx; | 2351 | int rate_idx; |
@@ -2591,7 +2544,7 @@ static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file, | |||
2591 | 2544 | ||
2592 | if (lq_sta->dbg_fixed.rate_n_flags) { | 2545 | if (lq_sta->dbg_fixed.rate_n_flags) { |
2593 | rs_fill_link_cmd(lq_sta, &lq_sta->dbg_fixed, &lq_sta->lq); | 2546 | rs_fill_link_cmd(lq_sta, &lq_sta->dbg_fixed, &lq_sta->lq); |
2594 | rs_send_lq_cmd(lq_sta->drv, &lq_sta->lq, CMD_ASYNC); | 2547 | iwl_send_lq_cmd(lq_sta->drv, &lq_sta->lq, CMD_ASYNC); |
2595 | } | 2548 | } |
2596 | 2549 | ||
2597 | return count; | 2550 | return count; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 472ca3d7e034..17f629fb96ff 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c | |||
@@ -46,7 +46,7 @@ | |||
46 | 46 | ||
47 | /* module parameters */ | 47 | /* module parameters */ |
48 | static struct iwl_mod_params iwl4965_mod_params = { | 48 | static struct iwl_mod_params iwl4965_mod_params = { |
49 | .num_of_queues = IWL_MAX_NUM_QUEUES, | 49 | .num_of_queues = IWL4965_MAX_NUM_QUEUES, |
50 | .enable_qos = 1, | 50 | .enable_qos = 1, |
51 | .amsdu_size_8K = 1, | 51 | .amsdu_size_8K = 1, |
52 | /* the rest are 0 by default */ | 52 | /* the rest are 0 by default */ |
@@ -114,6 +114,151 @@ static const u16 default_tid_to_tx_fifo[] = { | |||
114 | 114 | ||
115 | #endif /*CONFIG_IWL4965_HT */ | 115 | #endif /*CONFIG_IWL4965_HT */ |
116 | 116 | ||
117 | /* check contents of special bootstrap uCode SRAM */ | ||
118 | static int iwl4965_verify_bsm(struct iwl_priv *priv) | ||
119 | { | ||
120 | __le32 *image = priv->ucode_boot.v_addr; | ||
121 | u32 len = priv->ucode_boot.len; | ||
122 | u32 reg; | ||
123 | u32 val; | ||
124 | |||
125 | IWL_DEBUG_INFO("Begin verify bsm\n"); | ||
126 | |||
127 | /* verify BSM SRAM contents */ | ||
128 | val = iwl_read_prph(priv, BSM_WR_DWCOUNT_REG); | ||
129 | for (reg = BSM_SRAM_LOWER_BOUND; | ||
130 | reg < BSM_SRAM_LOWER_BOUND + len; | ||
131 | reg += sizeof(u32), image++) { | ||
132 | val = iwl_read_prph(priv, reg); | ||
133 | if (val != le32_to_cpu(*image)) { | ||
134 | IWL_ERROR("BSM uCode verification failed at " | ||
135 | "addr 0x%08X+%u (of %u), is 0x%x, s/b 0x%x\n", | ||
136 | BSM_SRAM_LOWER_BOUND, | ||
137 | reg - BSM_SRAM_LOWER_BOUND, len, | ||
138 | val, le32_to_cpu(*image)); | ||
139 | return -EIO; | ||
140 | } | ||
141 | } | ||
142 | |||
143 | IWL_DEBUG_INFO("BSM bootstrap uCode image OK\n"); | ||
144 | |||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | /** | ||
149 | * iwl4965_load_bsm - Load bootstrap instructions | ||
150 | * | ||
151 | * BSM operation: | ||
152 | * | ||
153 | * The Bootstrap State Machine (BSM) stores a short bootstrap uCode program | ||
154 | * in special SRAM that does not power down during RFKILL. When powering back | ||
155 | * up after power-saving sleeps (or during initial uCode load), the BSM loads | ||
156 | * the bootstrap program into the on-board processor, and starts it. | ||
157 | * | ||
158 | * The bootstrap program loads (via DMA) instructions and data for a new | ||
159 | * program from host DRAM locations indicated by the host driver in the | ||
160 | * BSM_DRAM_* registers. Once the new program is loaded, it starts | ||
161 | * automatically. | ||
162 | * | ||
163 | * When initializing the NIC, the host driver points the BSM to the | ||
164 | * "initialize" uCode image. This uCode sets up some internal data, then | ||
165 | * notifies host via "initialize alive" that it is complete. | ||
166 | * | ||
167 | * The host then replaces the BSM_DRAM_* pointer values to point to the | ||
168 | * normal runtime uCode instructions and a backup uCode data cache buffer | ||
169 | * (filled initially with starting data values for the on-board processor), | ||
170 | * then triggers the "initialize" uCode to load and launch the runtime uCode, | ||
171 | * which begins normal operation. | ||
172 | * | ||
173 | * When doing a power-save shutdown, runtime uCode saves data SRAM into | ||
174 | * the backup data cache in DRAM before SRAM is powered down. | ||
175 | * | ||
176 | * When powering back up, the BSM loads the bootstrap program. This reloads | ||
177 | * the runtime uCode instructions and the backup data cache into SRAM, | ||
178 | * and re-launches the runtime uCode from where it left off. | ||
179 | */ | ||
180 | static int iwl4965_load_bsm(struct iwl_priv *priv) | ||
181 | { | ||
182 | __le32 *image = priv->ucode_boot.v_addr; | ||
183 | u32 len = priv->ucode_boot.len; | ||
184 | dma_addr_t pinst; | ||
185 | dma_addr_t pdata; | ||
186 | u32 inst_len; | ||
187 | u32 data_len; | ||
188 | int i; | ||
189 | u32 done; | ||
190 | u32 reg_offset; | ||
191 | int ret; | ||
192 | |||
193 | IWL_DEBUG_INFO("Begin load bsm\n"); | ||
194 | |||
195 | /* make sure bootstrap program is no larger than BSM's SRAM size */ | ||
196 | if (len > IWL_MAX_BSM_SIZE) | ||
197 | return -EINVAL; | ||
198 | |||
199 | /* Tell bootstrap uCode where to find the "Initialize" uCode | ||
200 | * in host DRAM ... host DRAM physical address bits 35:4 for 4965. | ||
201 | * NOTE: iwl4965_initialize_alive_start() will replace these values, | ||
202 | * after the "initialize" uCode has run, to point to | ||
203 | * runtime/protocol instructions and backup data cache. */ | ||
204 | pinst = priv->ucode_init.p_addr >> 4; | ||
205 | pdata = priv->ucode_init_data.p_addr >> 4; | ||
206 | inst_len = priv->ucode_init.len; | ||
207 | data_len = priv->ucode_init_data.len; | ||
208 | |||
209 | ret = iwl_grab_nic_access(priv); | ||
210 | if (ret) | ||
211 | return ret; | ||
212 | |||
213 | iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst); | ||
214 | iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata); | ||
215 | iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len); | ||
216 | iwl_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG, data_len); | ||
217 | |||
218 | /* Fill BSM memory with bootstrap instructions */ | ||
219 | for (reg_offset = BSM_SRAM_LOWER_BOUND; | ||
220 | reg_offset < BSM_SRAM_LOWER_BOUND + len; | ||
221 | reg_offset += sizeof(u32), image++) | ||
222 | _iwl_write_prph(priv, reg_offset, le32_to_cpu(*image)); | ||
223 | |||
224 | ret = iwl4965_verify_bsm(priv); | ||
225 | if (ret) { | ||
226 | iwl_release_nic_access(priv); | ||
227 | return ret; | ||
228 | } | ||
229 | |||
230 | /* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */ | ||
231 | iwl_write_prph(priv, BSM_WR_MEM_SRC_REG, 0x0); | ||
232 | iwl_write_prph(priv, BSM_WR_MEM_DST_REG, RTC_INST_LOWER_BOUND); | ||
233 | iwl_write_prph(priv, BSM_WR_DWCOUNT_REG, len / sizeof(u32)); | ||
234 | |||
235 | /* Load bootstrap code into instruction SRAM now, | ||
236 | * to prepare to load "initialize" uCode */ | ||
237 | iwl_write_prph(priv, BSM_WR_CTRL_REG, BSM_WR_CTRL_REG_BIT_START); | ||
238 | |||
239 | /* Wait for load of bootstrap uCode to finish */ | ||
240 | for (i = 0; i < 100; i++) { | ||
241 | done = iwl_read_prph(priv, BSM_WR_CTRL_REG); | ||
242 | if (!(done & BSM_WR_CTRL_REG_BIT_START)) | ||
243 | break; | ||
244 | udelay(10); | ||
245 | } | ||
246 | if (i < 100) | ||
247 | IWL_DEBUG_INFO("BSM write complete, poll %d iterations\n", i); | ||
248 | else { | ||
249 | IWL_ERROR("BSM write did not complete!\n"); | ||
250 | return -EIO; | ||
251 | } | ||
252 | |||
253 | /* Enable future boot loads whenever power management unit triggers it | ||
254 | * (e.g. when powering back up after power-save shutdown) */ | ||
255 | iwl_write_prph(priv, BSM_WR_CTRL_REG, BSM_WR_CTRL_REG_BIT_START_EN); | ||
256 | |||
257 | iwl_release_nic_access(priv); | ||
258 | |||
259 | return 0; | ||
260 | } | ||
261 | |||
117 | static int iwl4965_init_drv(struct iwl_priv *priv) | 262 | static int iwl4965_init_drv(struct iwl_priv *priv) |
118 | { | 263 | { |
119 | int ret; | 264 | int ret; |
@@ -129,6 +274,18 @@ static int iwl4965_init_drv(struct iwl_priv *priv) | |||
129 | spin_lock_init(&priv->hcmd_lock); | 274 | spin_lock_init(&priv->hcmd_lock); |
130 | spin_lock_init(&priv->lq_mngr.lock); | 275 | spin_lock_init(&priv->lq_mngr.lock); |
131 | 276 | ||
277 | priv->shared_virt = pci_alloc_consistent(priv->pci_dev, | ||
278 | sizeof(struct iwl4965_shared), | ||
279 | &priv->shared_phys); | ||
280 | |||
281 | if (!priv->shared_virt) { | ||
282 | ret = -ENOMEM; | ||
283 | goto err; | ||
284 | } | ||
285 | |||
286 | memset(priv->shared_virt, 0, sizeof(struct iwl4965_shared)); | ||
287 | |||
288 | |||
132 | for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++) | 289 | for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++) |
133 | INIT_LIST_HEAD(&priv->ibss_mac_hash[i]); | 290 | INIT_LIST_HEAD(&priv->ibss_mac_hash[i]); |
134 | 291 | ||
@@ -253,7 +410,7 @@ void iwl4965_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, | |||
253 | int rate_index; | 410 | int rate_index; |
254 | 411 | ||
255 | control->antenna_sel_tx = | 412 | control->antenna_sel_tx = |
256 | ((rate_n_flags & RATE_MCS_ANT_AB_MSK) >> RATE_MCS_ANT_A_POS); | 413 | ((rate_n_flags & RATE_MCS_ANT_AB_MSK) >> RATE_MCS_ANT_POS); |
257 | if (rate_n_flags & RATE_MCS_HT_MSK) | 414 | if (rate_n_flags & RATE_MCS_HT_MSK) |
258 | control->flags |= IEEE80211_TXCTL_OFDM_HT; | 415 | control->flags |= IEEE80211_TXCTL_OFDM_HT; |
259 | if (rate_n_flags & RATE_MCS_GF_MSK) | 416 | if (rate_n_flags & RATE_MCS_GF_MSK) |
@@ -347,10 +504,10 @@ u8 iwl4965_hw_find_station(struct iwl_priv *priv, const u8 *addr) | |||
347 | start = IWL_STA_ID; | 504 | start = IWL_STA_ID; |
348 | 505 | ||
349 | if (is_broadcast_ether_addr(addr)) | 506 | if (is_broadcast_ether_addr(addr)) |
350 | return priv->hw_setting.bcast_sta_id; | 507 | return priv->hw_params.bcast_sta_id; |
351 | 508 | ||
352 | spin_lock_irqsave(&priv->sta_lock, flags); | 509 | spin_lock_irqsave(&priv->sta_lock, flags); |
353 | for (i = start; i < priv->hw_setting.max_stations; i++) | 510 | for (i = start; i < priv->hw_params.max_stations; i++) |
354 | if ((priv->stations[i].used) && | 511 | if ((priv->stations[i].used) && |
355 | (!compare_ether_addr | 512 | (!compare_ether_addr |
356 | (priv->stations[i].sta.sta.addr, addr))) { | 513 | (priv->stations[i].sta.sta.addr, addr))) { |
@@ -401,15 +558,15 @@ static int iwl4965_nic_set_pwr_src(struct iwl_priv *priv, int pwr_max) | |||
401 | 558 | ||
402 | static int iwl4965_rx_init(struct iwl_priv *priv, struct iwl4965_rx_queue *rxq) | 559 | static int iwl4965_rx_init(struct iwl_priv *priv, struct iwl4965_rx_queue *rxq) |
403 | { | 560 | { |
404 | int rc; | 561 | int ret; |
405 | unsigned long flags; | 562 | unsigned long flags; |
406 | unsigned int rb_size; | 563 | unsigned int rb_size; |
407 | 564 | ||
408 | spin_lock_irqsave(&priv->lock, flags); | 565 | spin_lock_irqsave(&priv->lock, flags); |
409 | rc = iwl_grab_nic_access(priv); | 566 | ret = iwl_grab_nic_access(priv); |
410 | if (rc) { | 567 | if (ret) { |
411 | spin_unlock_irqrestore(&priv->lock, flags); | 568 | spin_unlock_irqrestore(&priv->lock, flags); |
412 | return rc; | 569 | return ret; |
413 | } | 570 | } |
414 | 571 | ||
415 | if (priv->cfg->mod_params->amsdu_size_8K) | 572 | if (priv->cfg->mod_params->amsdu_size_8K) |
@@ -429,15 +586,15 @@ static int iwl4965_rx_init(struct iwl_priv *priv, struct iwl4965_rx_queue *rxq) | |||
429 | 586 | ||
430 | /* Tell device where in DRAM to update its Rx status */ | 587 | /* Tell device where in DRAM to update its Rx status */ |
431 | iwl_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG, | 588 | iwl_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG, |
432 | (priv->hw_setting.shared_phys + | 589 | (priv->shared_phys + |
433 | offsetof(struct iwl4965_shared, val0)) >> 4); | 590 | offsetof(struct iwl4965_shared, rb_closed)) >> 4); |
434 | 591 | ||
435 | /* Enable Rx DMA, enable host interrupt, Rx buffer size 4k, 256 RBDs */ | 592 | /* Enable Rx DMA, enable host interrupt, Rx buffer size 4k, 256 RBDs */ |
436 | iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, | 593 | iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, |
437 | FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL | | 594 | FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL | |
438 | FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL | | 595 | FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL | |
439 | rb_size | | 596 | rb_size | |
440 | /*0x10 << 4 | */ | 597 | /* 0x10 << 4 | */ |
441 | (RX_QUEUE_SIZE_LOG << | 598 | (RX_QUEUE_SIZE_LOG << |
442 | FH_RCSR_RX_CONFIG_RBDCB_SIZE_BITSHIFT)); | 599 | FH_RCSR_RX_CONFIG_RBDCB_SIZE_BITSHIFT)); |
443 | 600 | ||
@@ -545,7 +702,7 @@ static int iwl4965_txq_ctx_reset(struct iwl_priv *priv) | |||
545 | 702 | ||
546 | /* Alloc and init all (default 16) Tx queues, | 703 | /* Alloc and init all (default 16) Tx queues, |
547 | * including the command queue (#4) */ | 704 | * including the command queue (#4) */ |
548 | for (txq_id = 0; txq_id < priv->hw_setting.max_txq_num; txq_id++) { | 705 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { |
549 | slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ? | 706 | slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ? |
550 | TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; | 707 | TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; |
551 | rc = iwl4965_tx_queue_init(priv, &priv->txq[txq_id], slots_num, | 708 | rc = iwl4965_tx_queue_init(priv, &priv->txq[txq_id], slots_num, |
@@ -751,7 +908,7 @@ void iwl4965_hw_txq_ctx_stop(struct iwl_priv *priv) | |||
751 | unsigned long flags; | 908 | unsigned long flags; |
752 | 909 | ||
753 | /* Stop each Tx DMA channel, and wait for it to be idle */ | 910 | /* Stop each Tx DMA channel, and wait for it to be idle */ |
754 | for (txq_id = 0; txq_id < priv->hw_setting.max_txq_num; txq_id++) { | 911 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { |
755 | spin_lock_irqsave(&priv->lock, flags); | 912 | spin_lock_irqsave(&priv->lock, flags); |
756 | if (iwl_grab_nic_access(priv)) { | 913 | if (iwl_grab_nic_access(priv)) { |
757 | spin_unlock_irqrestore(&priv->lock, flags); | 914 | spin_unlock_irqrestore(&priv->lock, flags); |
@@ -819,40 +976,21 @@ int iwl4965_hw_nic_reset(struct iwl_priv *priv) | |||
819 | /** | 976 | /** |
820 | * iwl4965_bg_statistics_periodic - Timer callback to queue statistics | 977 | * iwl4965_bg_statistics_periodic - Timer callback to queue statistics |
821 | * | 978 | * |
822 | * This callback is provided in order to queue the statistics_work | 979 | * This callback is provided in order to send a statistics request. |
823 | * in work_queue context (v. softirq) | ||
824 | * | 980 | * |
825 | * This timer function is continually reset to execute within | 981 | * This timer function is continually reset to execute within |
826 | * REG_RECALIB_PERIOD seconds since the last STATISTICS_NOTIFICATION | 982 | * REG_RECALIB_PERIOD seconds since the last STATISTICS_NOTIFICATION |
827 | * was received. We need to ensure we receive the statistics in order | 983 | * was received. We need to ensure we receive the statistics in order |
828 | * to update the temperature used for calibrating the TXPOWER. However, | 984 | * to update the temperature used for calibrating the TXPOWER. |
829 | * we can't send the statistics command from softirq context (which | ||
830 | * is the context which timers run at) so we have to queue off the | ||
831 | * statistics_work to actually send the command to the hardware. | ||
832 | */ | 985 | */ |
833 | static void iwl4965_bg_statistics_periodic(unsigned long data) | 986 | static void iwl4965_bg_statistics_periodic(unsigned long data) |
834 | { | 987 | { |
835 | struct iwl_priv *priv = (struct iwl_priv *)data; | 988 | struct iwl_priv *priv = (struct iwl_priv *)data; |
836 | 989 | ||
837 | queue_work(priv->workqueue, &priv->statistics_work); | ||
838 | } | ||
839 | |||
840 | /** | ||
841 | * iwl4965_bg_statistics_work - Send the statistics request to the hardware. | ||
842 | * | ||
843 | * This is queued by iwl4965_bg_statistics_periodic. | ||
844 | */ | ||
845 | static void iwl4965_bg_statistics_work(struct work_struct *work) | ||
846 | { | ||
847 | struct iwl_priv *priv = container_of(work, struct iwl_priv, | ||
848 | statistics_work); | ||
849 | |||
850 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 990 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
851 | return; | 991 | return; |
852 | 992 | ||
853 | mutex_lock(&priv->mutex); | 993 | iwl_send_statistics_request(priv, CMD_ASYNC); |
854 | iwl4965_send_statistics_request(priv); | ||
855 | mutex_unlock(&priv->mutex); | ||
856 | } | 994 | } |
857 | 995 | ||
858 | #define CT_LIMIT_CONST 259 | 996 | #define CT_LIMIT_CONST 259 |
@@ -1816,19 +1954,19 @@ int iwl4965_alive_notify(struct iwl_priv *priv) | |||
1816 | iwl_write_targ_mem(priv, a, 0); | 1954 | iwl_write_targ_mem(priv, a, 0); |
1817 | for (; a < priv->scd_base_addr + SCD_TRANSLATE_TBL_OFFSET; a += 4) | 1955 | for (; a < priv->scd_base_addr + SCD_TRANSLATE_TBL_OFFSET; a += 4) |
1818 | iwl_write_targ_mem(priv, a, 0); | 1956 | iwl_write_targ_mem(priv, a, 0); |
1819 | for (; a < sizeof(u16) * priv->hw_setting.max_txq_num; a += 4) | 1957 | for (; a < sizeof(u16) * priv->hw_params.max_txq_num; a += 4) |
1820 | iwl_write_targ_mem(priv, a, 0); | 1958 | iwl_write_targ_mem(priv, a, 0); |
1821 | 1959 | ||
1822 | /* Tel 4965 where to find Tx byte count tables */ | 1960 | /* Tel 4965 where to find Tx byte count tables */ |
1823 | iwl_write_prph(priv, IWL49_SCD_DRAM_BASE_ADDR, | 1961 | iwl_write_prph(priv, IWL49_SCD_DRAM_BASE_ADDR, |
1824 | (priv->hw_setting.shared_phys + | 1962 | (priv->shared_phys + |
1825 | offsetof(struct iwl4965_shared, queues_byte_cnt_tbls)) >> 10); | 1963 | offsetof(struct iwl4965_shared, queues_byte_cnt_tbls)) >> 10); |
1826 | 1964 | ||
1827 | /* Disable chain mode for all queues */ | 1965 | /* Disable chain mode for all queues */ |
1828 | iwl_write_prph(priv, IWL49_SCD_QUEUECHAIN_SEL, 0); | 1966 | iwl_write_prph(priv, IWL49_SCD_QUEUECHAIN_SEL, 0); |
1829 | 1967 | ||
1830 | /* Initialize each Tx queue (including the command queue) */ | 1968 | /* Initialize each Tx queue (including the command queue) */ |
1831 | for (i = 0; i < priv->hw_setting.max_txq_num; i++) { | 1969 | for (i = 0; i < priv->hw_params.max_txq_num; i++) { |
1832 | 1970 | ||
1833 | /* TFD circular buffer read/write indexes */ | 1971 | /* TFD circular buffer read/write indexes */ |
1834 | iwl_write_prph(priv, IWL49_SCD_QUEUE_RDPTR(i), 0); | 1972 | iwl_write_prph(priv, IWL49_SCD_QUEUE_RDPTR(i), 0); |
@@ -1851,7 +1989,7 @@ int iwl4965_alive_notify(struct iwl_priv *priv) | |||
1851 | 1989 | ||
1852 | } | 1990 | } |
1853 | iwl_write_prph(priv, IWL49_SCD_INTERRUPT_MASK, | 1991 | iwl_write_prph(priv, IWL49_SCD_INTERRUPT_MASK, |
1854 | (1 << priv->hw_setting.max_txq_num) - 1); | 1992 | (1 << priv->hw_params.max_txq_num) - 1); |
1855 | 1993 | ||
1856 | /* Activate all Tx DMA/FIFO channels */ | 1994 | /* Activate all Tx DMA/FIFO channels */ |
1857 | iwl_write_prph(priv, IWL49_SCD_TXFACT, | 1995 | iwl_write_prph(priv, IWL49_SCD_TXFACT, |
@@ -1869,55 +2007,45 @@ int iwl4965_alive_notify(struct iwl_priv *priv) | |||
1869 | iwl_release_nic_access(priv); | 2007 | iwl_release_nic_access(priv); |
1870 | spin_unlock_irqrestore(&priv->lock, flags); | 2008 | spin_unlock_irqrestore(&priv->lock, flags); |
1871 | 2009 | ||
2010 | /* Ask for statistics now, the uCode will send statistics notification | ||
2011 | * periodically after association */ | ||
2012 | iwl_send_statistics_request(priv, CMD_ASYNC); | ||
1872 | return ret; | 2013 | return ret; |
1873 | } | 2014 | } |
1874 | 2015 | ||
1875 | /** | 2016 | /** |
1876 | * iwl4965_hw_set_hw_setting | 2017 | * iwl4965_hw_set_hw_params |
1877 | * | 2018 | * |
1878 | * Called when initializing driver | 2019 | * Called when initializing driver |
1879 | */ | 2020 | */ |
1880 | int iwl4965_hw_set_hw_setting(struct iwl_priv *priv) | 2021 | int iwl4965_hw_set_hw_params(struct iwl_priv *priv) |
1881 | { | 2022 | { |
1882 | int ret = 0; | ||
1883 | 2023 | ||
1884 | if ((priv->cfg->mod_params->num_of_queues > IWL_MAX_NUM_QUEUES) || | 2024 | if ((priv->cfg->mod_params->num_of_queues > IWL4965_MAX_NUM_QUEUES) || |
1885 | (priv->cfg->mod_params->num_of_queues < IWL_MIN_NUM_QUEUES)) { | 2025 | (priv->cfg->mod_params->num_of_queues < IWL_MIN_NUM_QUEUES)) { |
1886 | IWL_ERROR("invalid queues_num, should be between %d and %d\n", | 2026 | IWL_ERROR("invalid queues_num, should be between %d and %d\n", |
1887 | IWL_MIN_NUM_QUEUES, IWL_MAX_NUM_QUEUES); | 2027 | IWL_MIN_NUM_QUEUES, IWL4965_MAX_NUM_QUEUES); |
1888 | ret = -EINVAL; | 2028 | return -EINVAL; |
1889 | goto out; | ||
1890 | } | ||
1891 | |||
1892 | /* Allocate area for Tx byte count tables and Rx queue status */ | ||
1893 | priv->hw_setting.shared_virt = | ||
1894 | pci_alloc_consistent(priv->pci_dev, | ||
1895 | sizeof(struct iwl4965_shared), | ||
1896 | &priv->hw_setting.shared_phys); | ||
1897 | |||
1898 | if (!priv->hw_setting.shared_virt) { | ||
1899 | ret = -ENOMEM; | ||
1900 | goto out; | ||
1901 | } | 2029 | } |
1902 | 2030 | ||
1903 | memset(priv->hw_setting.shared_virt, 0, sizeof(struct iwl4965_shared)); | 2031 | priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues; |
1904 | 2032 | priv->hw_params.tx_cmd_len = sizeof(struct iwl4965_tx_cmd); | |
1905 | priv->hw_setting.max_txq_num = priv->cfg->mod_params->num_of_queues; | 2033 | priv->hw_params.max_rxq_size = RX_QUEUE_SIZE; |
1906 | priv->hw_setting.tx_cmd_len = sizeof(struct iwl4965_tx_cmd); | 2034 | priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG; |
1907 | priv->hw_setting.max_rxq_size = RX_QUEUE_SIZE; | ||
1908 | priv->hw_setting.max_rxq_log = RX_QUEUE_SIZE_LOG; | ||
1909 | if (priv->cfg->mod_params->amsdu_size_8K) | 2035 | if (priv->cfg->mod_params->amsdu_size_8K) |
1910 | priv->hw_setting.rx_buf_size = IWL_RX_BUF_SIZE_8K; | 2036 | priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_8K; |
1911 | else | 2037 | else |
1912 | priv->hw_setting.rx_buf_size = IWL_RX_BUF_SIZE_4K; | 2038 | priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_4K; |
1913 | priv->hw_setting.max_pkt_size = priv->hw_setting.rx_buf_size - 256; | 2039 | priv->hw_params.max_pkt_size = priv->hw_params.rx_buf_size - 256; |
1914 | priv->hw_setting.max_stations = IWL4965_STATION_COUNT; | 2040 | priv->hw_params.max_stations = IWL4965_STATION_COUNT; |
1915 | priv->hw_setting.bcast_sta_id = IWL4965_BROADCAST_ID; | 2041 | priv->hw_params.bcast_sta_id = IWL4965_BROADCAST_ID; |
1916 | 2042 | ||
1917 | priv->hw_setting.tx_ant_num = 2; | 2043 | priv->hw_params.tx_chains_num = 2; |
2044 | priv->hw_params.rx_chains_num = 2; | ||
2045 | priv->hw_params.valid_tx_ant = (IWL_ANTENNA_MAIN | IWL_ANTENNA_AUX); | ||
2046 | priv->hw_params.valid_rx_ant = (IWL_ANTENNA_MAIN | IWL_ANTENNA_AUX); | ||
1918 | 2047 | ||
1919 | out: | 2048 | return 0; |
1920 | return ret; | ||
1921 | } | 2049 | } |
1922 | 2050 | ||
1923 | /** | 2051 | /** |
@@ -1930,7 +2058,7 @@ void iwl4965_hw_txq_ctx_free(struct iwl_priv *priv) | |||
1930 | int txq_id; | 2058 | int txq_id; |
1931 | 2059 | ||
1932 | /* Tx queues */ | 2060 | /* Tx queues */ |
1933 | for (txq_id = 0; txq_id < priv->hw_setting.max_txq_num; txq_id++) | 2061 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) |
1934 | iwl4965_tx_queue_free(priv, &priv->txq[txq_id]); | 2062 | iwl4965_tx_queue_free(priv, &priv->txq[txq_id]); |
1935 | 2063 | ||
1936 | /* Keep-warm buffer */ | 2064 | /* Keep-warm buffer */ |
@@ -2756,6 +2884,46 @@ out: | |||
2756 | return ret; | 2884 | return ret; |
2757 | } | 2885 | } |
2758 | 2886 | ||
2887 | static int iwl4965_send_rxon_assoc(struct iwl_priv *priv) | ||
2888 | { | ||
2889 | int ret = 0; | ||
2890 | struct iwl4965_rxon_assoc_cmd rxon_assoc; | ||
2891 | const struct iwl4965_rxon_cmd *rxon1 = &priv->staging_rxon; | ||
2892 | const struct iwl4965_rxon_cmd *rxon2 = &priv->active_rxon; | ||
2893 | |||
2894 | if ((rxon1->flags == rxon2->flags) && | ||
2895 | (rxon1->filter_flags == rxon2->filter_flags) && | ||
2896 | (rxon1->cck_basic_rates == rxon2->cck_basic_rates) && | ||
2897 | (rxon1->ofdm_ht_single_stream_basic_rates == | ||
2898 | rxon2->ofdm_ht_single_stream_basic_rates) && | ||
2899 | (rxon1->ofdm_ht_dual_stream_basic_rates == | ||
2900 | rxon2->ofdm_ht_dual_stream_basic_rates) && | ||
2901 | (rxon1->rx_chain == rxon2->rx_chain) && | ||
2902 | (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) { | ||
2903 | IWL_DEBUG_INFO("Using current RXON_ASSOC. Not resending.\n"); | ||
2904 | return 0; | ||
2905 | } | ||
2906 | |||
2907 | rxon_assoc.flags = priv->staging_rxon.flags; | ||
2908 | rxon_assoc.filter_flags = priv->staging_rxon.filter_flags; | ||
2909 | rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates; | ||
2910 | rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates; | ||
2911 | rxon_assoc.reserved = 0; | ||
2912 | rxon_assoc.ofdm_ht_single_stream_basic_rates = | ||
2913 | priv->staging_rxon.ofdm_ht_single_stream_basic_rates; | ||
2914 | rxon_assoc.ofdm_ht_dual_stream_basic_rates = | ||
2915 | priv->staging_rxon.ofdm_ht_dual_stream_basic_rates; | ||
2916 | rxon_assoc.rx_chain_select_flags = priv->staging_rxon.rx_chain; | ||
2917 | |||
2918 | ret = iwl_send_cmd_pdu_async(priv, REPLY_RXON_ASSOC, | ||
2919 | sizeof(rxon_assoc), &rxon_assoc, NULL); | ||
2920 | if (ret) | ||
2921 | return ret; | ||
2922 | |||
2923 | return ret; | ||
2924 | } | ||
2925 | |||
2926 | |||
2759 | int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel) | 2927 | int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel) |
2760 | { | 2928 | { |
2761 | int rc; | 2929 | int rc; |
@@ -2869,9 +3037,8 @@ void iwl4965_hw_build_tx_cmd_rate(struct iwl_priv *priv, | |||
2869 | 3037 | ||
2870 | int iwl4965_hw_get_rx_read(struct iwl_priv *priv) | 3038 | int iwl4965_hw_get_rx_read(struct iwl_priv *priv) |
2871 | { | 3039 | { |
2872 | struct iwl4965_shared *shared_data = priv->hw_setting.shared_virt; | 3040 | struct iwl4965_shared *s = priv->shared_virt; |
2873 | 3041 | return le32_to_cpu(s->rb_closed) & 0xFFF; | |
2874 | return IWL_GET_BITS(*shared_data, rb_closed_stts_rb_num); | ||
2875 | } | 3042 | } |
2876 | 3043 | ||
2877 | int iwl4965_hw_get_temperature(struct iwl_priv *priv) | 3044 | int iwl4965_hw_get_temperature(struct iwl_priv *priv) |
@@ -2888,7 +3055,7 @@ unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv, | |||
2888 | tx_beacon_cmd = &frame->u.beacon; | 3055 | tx_beacon_cmd = &frame->u.beacon; |
2889 | memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd)); | 3056 | memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd)); |
2890 | 3057 | ||
2891 | tx_beacon_cmd->tx.sta_id = priv->hw_setting.bcast_sta_id; | 3058 | tx_beacon_cmd->tx.sta_id = priv->hw_params.bcast_sta_id; |
2892 | tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; | 3059 | tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; |
2893 | 3060 | ||
2894 | frame_size = iwl4965_fill_beacon_frame(priv, | 3061 | frame_size = iwl4965_fill_beacon_frame(priv, |
@@ -2996,17 +3163,15 @@ static void iwl4965_hw_card_show_info(struct iwl_priv *priv) | |||
2996 | #define IWL_TX_DELIMITER_SIZE 4 | 3163 | #define IWL_TX_DELIMITER_SIZE 4 |
2997 | 3164 | ||
2998 | /** | 3165 | /** |
2999 | * iwl4965_tx_queue_update_wr_ptr - Set up entry in Tx byte-count array | 3166 | * iwl4965_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array |
3000 | */ | 3167 | */ |
3001 | int iwl4965_tx_queue_update_wr_ptr(struct iwl_priv *priv, | 3168 | static void iwl4965_txq_update_byte_cnt_tbl(struct iwl_priv *priv, |
3002 | struct iwl4965_tx_queue *txq, u16 byte_cnt) | 3169 | struct iwl4965_tx_queue *txq, |
3170 | u16 byte_cnt) | ||
3003 | { | 3171 | { |
3004 | int len; | 3172 | int len; |
3005 | int txq_id = txq->q.id; | 3173 | int txq_id = txq->q.id; |
3006 | struct iwl4965_shared *shared_data = priv->hw_setting.shared_virt; | 3174 | struct iwl4965_shared *shared_data = priv->shared_virt; |
3007 | |||
3008 | if (txq->need_update == 0) | ||
3009 | return 0; | ||
3010 | 3175 | ||
3011 | len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE; | 3176 | len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE; |
3012 | 3177 | ||
@@ -3019,8 +3184,6 @@ int iwl4965_tx_queue_update_wr_ptr(struct iwl_priv *priv, | |||
3019 | IWL_SET_BITS16(shared_data->queues_byte_cnt_tbls[txq_id]. | 3184 | IWL_SET_BITS16(shared_data->queues_byte_cnt_tbls[txq_id]. |
3020 | tfd_offset[IWL4965_QUEUE_SIZE + txq->q.write_ptr], | 3185 | tfd_offset[IWL4965_QUEUE_SIZE + txq->q.write_ptr], |
3021 | byte_cnt, len); | 3186 | byte_cnt, len); |
3022 | |||
3023 | return 0; | ||
3024 | } | 3187 | } |
3025 | 3188 | ||
3026 | /** | 3189 | /** |
@@ -3500,7 +3663,7 @@ static void iwl4965_handle_data_packet(struct iwl_priv *priv, int is_data, | |||
3500 | rx_start->byte_count = amsdu->byte_count; | 3663 | rx_start->byte_count = amsdu->byte_count; |
3501 | rx_end = (__le32 *) (((u8 *) hdr) + len); | 3664 | rx_end = (__le32 *) (((u8 *) hdr) + len); |
3502 | } | 3665 | } |
3503 | if (len > priv->hw_setting.max_pkt_size || len < 16) { | 3666 | if (len > priv->hw_params.max_pkt_size || len < 16) { |
3504 | IWL_WARNING("byte count out of range [16,4K] : %d\n", len); | 3667 | IWL_WARNING("byte count out of range [16,4K] : %d\n", len); |
3505 | return; | 3668 | return; |
3506 | } | 3669 | } |
@@ -3528,7 +3691,7 @@ static void iwl4965_handle_data_packet(struct iwl_priv *priv, int is_data, | |||
3528 | stats->flag = 0; | 3691 | stats->flag = 0; |
3529 | hdr = (struct ieee80211_hdr *)rxb->skb->data; | 3692 | hdr = (struct ieee80211_hdr *)rxb->skb->data; |
3530 | 3693 | ||
3531 | if (priv->cfg->mod_params->hw_crypto) | 3694 | if (!priv->cfg->mod_params->sw_crypto) |
3532 | iwl4965_set_decrypted_flag(priv, rxb->skb, ampdu_status, stats); | 3695 | iwl4965_set_decrypted_flag(priv, rxb->skb, ampdu_status, stats); |
3533 | 3696 | ||
3534 | if (priv->add_radiotap) | 3697 | if (priv->add_radiotap) |
@@ -4199,7 +4362,7 @@ static void iwl4965_rx_reply_compressed_ba(struct iwl_priv *priv, | |||
4199 | * (in Tx queue's circular buffer) of first TFD/frame in window */ | 4362 | * (in Tx queue's circular buffer) of first TFD/frame in window */ |
4200 | u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn); | 4363 | u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn); |
4201 | 4364 | ||
4202 | if (scd_flow >= ARRAY_SIZE(priv->txq)) { | 4365 | if (scd_flow >= priv->hw_params.max_txq_num) { |
4203 | IWL_ERROR("BUG_ON scd_flow is bigger than number of queues"); | 4366 | IWL_ERROR("BUG_ON scd_flow is bigger than number of queues"); |
4204 | return; | 4367 | return; |
4205 | } | 4368 | } |
@@ -4361,7 +4524,7 @@ static int iwl4965_tx_queue_agg_enable(struct iwl_priv *priv, int txq_id, | |||
4361 | void iwl4965_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap) | 4524 | void iwl4965_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap) |
4362 | { | 4525 | { |
4363 | int i, r; | 4526 | int i, r; |
4364 | struct iwl4965_link_quality_cmd link_cmd = { | 4527 | struct iwl_link_quality_cmd link_cmd = { |
4365 | .reserved1 = 0, | 4528 | .reserved1 = 0, |
4366 | }; | 4529 | }; |
4367 | u16 rate_flags; | 4530 | u16 rate_flags; |
@@ -4395,7 +4558,7 @@ void iwl4965_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap) | |||
4395 | link_cmd.agg_params.agg_time_limit = cpu_to_le16(4000); | 4558 | link_cmd.agg_params.agg_time_limit = cpu_to_le16(4000); |
4396 | 4559 | ||
4397 | /* Update the rate scaling for control frame Tx to AP */ | 4560 | /* Update the rate scaling for control frame Tx to AP */ |
4398 | link_cmd.sta_id = is_ap ? IWL_AP_ID : priv->hw_setting.bcast_sta_id; | 4561 | link_cmd.sta_id = is_ap ? IWL_AP_ID : priv->hw_params.bcast_sta_id; |
4399 | 4562 | ||
4400 | iwl_send_cmd_pdu_async(priv, REPLY_TX_LINK_QUALITY_CMD, | 4563 | iwl_send_cmd_pdu_async(priv, REPLY_TX_LINK_QUALITY_CMD, |
4401 | sizeof(link_cmd), &link_cmd, NULL); | 4564 | sizeof(link_cmd), &link_cmd, NULL); |
@@ -4584,7 +4747,7 @@ static int iwl4965_txq_ctx_activate_free(struct iwl_priv *priv) | |||
4584 | { | 4747 | { |
4585 | int txq_id; | 4748 | int txq_id; |
4586 | 4749 | ||
4587 | for (txq_id = 0; txq_id < priv->hw_setting.max_txq_num; txq_id++) | 4750 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) |
4588 | if (!test_and_set_bit(txq_id, &priv->txq_ctx_active_msk)) | 4751 | if (!test_and_set_bit(txq_id, &priv->txq_ctx_active_msk)) |
4589 | return txq_id; | 4752 | return txq_id; |
4590 | return -1; | 4753 | return -1; |
@@ -4767,7 +4930,6 @@ void iwl4965_hw_rx_handler_setup(struct iwl_priv *priv) | |||
4767 | void iwl4965_hw_setup_deferred_work(struct iwl_priv *priv) | 4930 | void iwl4965_hw_setup_deferred_work(struct iwl_priv *priv) |
4768 | { | 4931 | { |
4769 | INIT_WORK(&priv->txpower_work, iwl4965_bg_txpower_work); | 4932 | INIT_WORK(&priv->txpower_work, iwl4965_bg_txpower_work); |
4770 | INIT_WORK(&priv->statistics_work, iwl4965_bg_statistics_work); | ||
4771 | #ifdef CONFIG_IWL4965_SENSITIVITY | 4933 | #ifdef CONFIG_IWL4965_SENSITIVITY |
4772 | INIT_WORK(&priv->sensitivity_work, iwl4965_bg_sensitivity_work); | 4934 | INIT_WORK(&priv->sensitivity_work, iwl4965_bg_sensitivity_work); |
4773 | #endif | 4935 | #endif |
@@ -4783,12 +4945,23 @@ void iwl4965_hw_cancel_deferred_work(struct iwl_priv *priv) | |||
4783 | cancel_delayed_work(&priv->init_alive_start); | 4945 | cancel_delayed_work(&priv->init_alive_start); |
4784 | } | 4946 | } |
4785 | 4947 | ||
4948 | |||
4949 | static struct iwl_hcmd_ops iwl4965_hcmd = { | ||
4950 | .rxon_assoc = iwl4965_send_rxon_assoc, | ||
4951 | }; | ||
4952 | |||
4786 | static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = { | 4953 | static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = { |
4787 | .enqueue_hcmd = iwl4965_enqueue_hcmd, | 4954 | .enqueue_hcmd = iwl4965_enqueue_hcmd, |
4788 | }; | 4955 | }; |
4789 | 4956 | ||
4790 | static struct iwl_lib_ops iwl4965_lib = { | 4957 | static struct iwl_lib_ops iwl4965_lib = { |
4791 | .init_drv = iwl4965_init_drv, | 4958 | .init_drv = iwl4965_init_drv, |
4959 | .set_hw_params = iwl4965_hw_set_hw_params, | ||
4960 | .txq_update_byte_cnt_tbl = iwl4965_txq_update_byte_cnt_tbl, | ||
4961 | .hw_nic_init = iwl4965_hw_nic_init, | ||
4962 | .is_valid_rtc_data_addr = iwl4965_hw_valid_rtc_data_addr, | ||
4963 | .alive_notify = iwl4965_alive_notify, | ||
4964 | .load_ucode = iwl4965_load_bsm, | ||
4792 | .eeprom_ops = { | 4965 | .eeprom_ops = { |
4793 | .verify_signature = iwlcore_eeprom_verify_signature, | 4966 | .verify_signature = iwlcore_eeprom_verify_signature, |
4794 | .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, | 4967 | .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, |
@@ -4799,10 +4972,11 @@ static struct iwl_lib_ops iwl4965_lib = { | |||
4799 | 4972 | ||
4800 | static struct iwl_ops iwl4965_ops = { | 4973 | static struct iwl_ops iwl4965_ops = { |
4801 | .lib = &iwl4965_lib, | 4974 | .lib = &iwl4965_lib, |
4975 | .hcmd = &iwl4965_hcmd, | ||
4802 | .utils = &iwl4965_hcmd_utils, | 4976 | .utils = &iwl4965_hcmd_utils, |
4803 | }; | 4977 | }; |
4804 | 4978 | ||
4805 | static struct iwl_cfg iwl4965_agn_cfg = { | 4979 | struct iwl_cfg iwl4965_agn_cfg = { |
4806 | .name = "4965AGN", | 4980 | .name = "4965AGN", |
4807 | .fw_name = "iwlwifi-4965" IWL4965_UCODE_API ".ucode", | 4981 | .fw_name = "iwlwifi-4965" IWL4965_UCODE_API ".ucode", |
4808 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | 4982 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, |
@@ -4810,21 +4984,12 @@ static struct iwl_cfg iwl4965_agn_cfg = { | |||
4810 | .mod_params = &iwl4965_mod_params, | 4984 | .mod_params = &iwl4965_mod_params, |
4811 | }; | 4985 | }; |
4812 | 4986 | ||
4813 | struct pci_device_id iwl4965_hw_card_ids[] = { | ||
4814 | {IWL_PCI_DEVICE(0x4229, PCI_ANY_ID, iwl4965_agn_cfg)}, | ||
4815 | {IWL_PCI_DEVICE(0x4230, PCI_ANY_ID, iwl4965_agn_cfg)}, | ||
4816 | {0} | ||
4817 | }; | ||
4818 | |||
4819 | MODULE_DEVICE_TABLE(pci, iwl4965_hw_card_ids); | ||
4820 | |||
4821 | module_param_named(antenna, iwl4965_mod_params.antenna, int, 0444); | 4987 | module_param_named(antenna, iwl4965_mod_params.antenna, int, 0444); |
4822 | MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); | 4988 | MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); |
4823 | module_param_named(disable, iwl4965_mod_params.disable, int, 0444); | 4989 | module_param_named(disable, iwl4965_mod_params.disable, int, 0444); |
4824 | MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])"); | 4990 | MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])"); |
4825 | module_param_named(hwcrypto, iwl4965_mod_params.hw_crypto, int, 0444); | 4991 | module_param_named(swcrypto, iwl4965_mod_params.sw_crypto, int, 0444); |
4826 | MODULE_PARM_DESC(hwcrypto, | 4992 | MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])\n"); |
4827 | "using hardware crypto engine (default 0 [software])\n"); | ||
4828 | module_param_named(debug, iwl4965_mod_params.debug, int, 0444); | 4993 | module_param_named(debug, iwl4965_mod_params.debug, int, 0444); |
4829 | MODULE_PARM_DESC(debug, "debug output mask"); | 4994 | MODULE_PARM_DESC(debug, "debug output mask"); |
4830 | module_param_named( | 4995 | module_param_named( |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index 65e536782706..9ed13cb0a2a9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h | |||
@@ -36,9 +36,6 @@ | |||
36 | #include <linux/kernel.h> | 36 | #include <linux/kernel.h> |
37 | #include <net/ieee80211_radiotap.h> | 37 | #include <net/ieee80211_radiotap.h> |
38 | 38 | ||
39 | /* Hardware specific file defines the PCI IDs table for that hardware module */ | ||
40 | extern struct pci_device_id iwl4965_hw_card_ids[]; | ||
41 | |||
42 | #define DRV_NAME "iwl4965" | 39 | #define DRV_NAME "iwl4965" |
43 | #include "iwl-rfkill.h" | 40 | #include "iwl-rfkill.h" |
44 | #include "iwl-eeprom.h" | 41 | #include "iwl-eeprom.h" |
@@ -48,6 +45,9 @@ extern struct pci_device_id iwl4965_hw_card_ids[]; | |||
48 | #include "iwl-debug.h" | 45 | #include "iwl-debug.h" |
49 | #include "iwl-led.h" | 46 | #include "iwl-led.h" |
50 | 47 | ||
48 | /* configuration for the iwl4965 */ | ||
49 | extern struct iwl_cfg iwl4965_agn_cfg; | ||
50 | |||
51 | /* Change firmware file name, using "-" and incrementing number, | 51 | /* Change firmware file name, using "-" and incrementing number, |
52 | * *only* when uCode interface or architecture changes so that it | 52 | * *only* when uCode interface or architecture changes so that it |
53 | * is not compatible with earlier drivers. | 53 | * is not compatible with earlier drivers. |
@@ -461,6 +461,7 @@ struct iwl4965_tid_data { | |||
461 | struct iwl4965_hw_key { | 461 | struct iwl4965_hw_key { |
462 | enum ieee80211_key_alg alg; | 462 | enum ieee80211_key_alg alg; |
463 | int keylen; | 463 | int keylen; |
464 | u8 keyidx; | ||
464 | struct ieee80211_key_conf *conf; | 465 | struct ieee80211_key_conf *conf; |
465 | u8 key[32]; | 466 | u8 key[32]; |
466 | }; | 467 | }; |
@@ -566,7 +567,7 @@ struct iwl4965_ibss_seq { | |||
566 | }; | 567 | }; |
567 | 568 | ||
568 | /** | 569 | /** |
569 | * struct iwl4965_driver_hw_info | 570 | * struct iwl_hw_params |
570 | * @max_txq_num: Max # Tx queues supported | 571 | * @max_txq_num: Max # Tx queues supported |
571 | * @tx_cmd_len: Size of Tx command (but not including frame itself) | 572 | * @tx_cmd_len: Size of Tx command (but not including frame itself) |
572 | * @tx_ant_num: Number of TX antennas | 573 | * @tx_ant_num: Number of TX antennas |
@@ -575,21 +576,20 @@ struct iwl4965_ibss_seq { | |||
575 | * @max_rxq_log: Log-base-2 of max_rxq_size | 576 | * @max_rxq_log: Log-base-2 of max_rxq_size |
576 | * @max_stations: | 577 | * @max_stations: |
577 | * @bcast_sta_id: | 578 | * @bcast_sta_id: |
578 | * @shared_virt: Pointer to driver/uCode shared Tx Byte Counts and Rx status | ||
579 | * @shared_phys: Physical Pointer to Tx Byte Counts and Rx status | ||
580 | */ | 579 | */ |
581 | struct iwl4965_driver_hw_info { | 580 | struct iwl_hw_params { |
582 | u16 max_txq_num; | 581 | u16 max_txq_num; |
583 | u16 tx_cmd_len; | 582 | u16 tx_cmd_len; |
584 | u16 tx_ant_num; | 583 | u8 tx_chains_num; |
584 | u8 rx_chains_num; | ||
585 | u8 valid_tx_ant; | ||
586 | u8 valid_rx_ant; | ||
585 | u16 max_rxq_size; | 587 | u16 max_rxq_size; |
588 | u16 max_rxq_log; | ||
586 | u32 rx_buf_size; | 589 | u32 rx_buf_size; |
587 | u32 max_pkt_size; | 590 | u32 max_pkt_size; |
588 | u16 max_rxq_log; | ||
589 | u8 max_stations; | 591 | u8 max_stations; |
590 | u8 bcast_sta_id; | 592 | u8 bcast_sta_id; |
591 | void *shared_virt; | ||
592 | dma_addr_t shared_phys; | ||
593 | }; | 593 | }; |
594 | 594 | ||
595 | #define HT_SHORT_GI_20MHZ_ONLY (1 << 0) | 595 | #define HT_SHORT_GI_20MHZ_ONLY (1 << 0) |
@@ -641,7 +641,6 @@ extern unsigned int iwl4965_fill_beacon_frame(struct iwl_priv *priv, | |||
641 | const u8 *dest, int left); | 641 | const u8 *dest, int left); |
642 | extern int iwl4965_rx_queue_update_write_ptr(struct iwl_priv *priv, | 642 | extern int iwl4965_rx_queue_update_write_ptr(struct iwl_priv *priv, |
643 | struct iwl4965_rx_queue *q); | 643 | struct iwl4965_rx_queue *q); |
644 | extern int iwl4965_send_statistics_request(struct iwl_priv *priv); | ||
645 | extern void iwl4965_set_decrypted_flag(struct iwl_priv *priv, struct sk_buff *skb, | 644 | extern void iwl4965_set_decrypted_flag(struct iwl_priv *priv, struct sk_buff *skb, |
646 | u32 decrypt_res, | 645 | u32 decrypt_res, |
647 | struct ieee80211_rx_status *stats); | 646 | struct ieee80211_rx_status *stats); |
@@ -679,7 +678,7 @@ extern void iwl4965_hw_rx_handler_setup(struct iwl_priv *priv); | |||
679 | extern void iwl4965_hw_setup_deferred_work(struct iwl_priv *priv); | 678 | extern void iwl4965_hw_setup_deferred_work(struct iwl_priv *priv); |
680 | extern void iwl4965_hw_cancel_deferred_work(struct iwl_priv *priv); | 679 | extern void iwl4965_hw_cancel_deferred_work(struct iwl_priv *priv); |
681 | extern int iwl4965_hw_rxq_stop(struct iwl_priv *priv); | 680 | extern int iwl4965_hw_rxq_stop(struct iwl_priv *priv); |
682 | extern int iwl4965_hw_set_hw_setting(struct iwl_priv *priv); | 681 | extern int iwl4965_hw_set_hw_params(struct iwl_priv *priv); |
683 | extern int iwl4965_hw_nic_init(struct iwl_priv *priv); | 682 | extern int iwl4965_hw_nic_init(struct iwl_priv *priv); |
684 | extern int iwl4965_hw_nic_stop_master(struct iwl_priv *priv); | 683 | extern int iwl4965_hw_nic_stop_master(struct iwl_priv *priv); |
685 | extern void iwl4965_hw_txq_ctx_free(struct iwl_priv *priv); | 684 | extern void iwl4965_hw_txq_ctx_free(struct iwl_priv *priv); |
@@ -942,6 +941,8 @@ enum { | |||
942 | 941 | ||
943 | #endif | 942 | #endif |
944 | 943 | ||
944 | #define IWL_MAX_NUM_QUEUES 20 /* FIXME: do dynamic allocation */ | ||
945 | |||
945 | struct iwl_priv { | 946 | struct iwl_priv { |
946 | 947 | ||
947 | /* ieee device used by generic ieee processing code */ | 948 | /* ieee device used by generic ieee processing code */ |
@@ -1033,7 +1034,7 @@ struct iwl_priv { | |||
1033 | * 4965's initialize alive response contains some calibration data. */ | 1034 | * 4965's initialize alive response contains some calibration data. */ |
1034 | struct iwl4965_init_alive_resp card_alive_init; | 1035 | struct iwl4965_init_alive_resp card_alive_init; |
1035 | struct iwl4965_alive_resp card_alive; | 1036 | struct iwl4965_alive_resp card_alive; |
1036 | #ifdef CONFIG_IWLCORE_RFKILL | 1037 | #ifdef CONFIG_IWLWIFI_RFKILL |
1037 | struct iwl_rfkill_mngr rfkill_mngr; | 1038 | struct iwl_rfkill_mngr rfkill_mngr; |
1038 | #endif | 1039 | #endif |
1039 | 1040 | ||
@@ -1112,6 +1113,10 @@ struct iwl_priv { | |||
1112 | spinlock_t sta_lock; | 1113 | spinlock_t sta_lock; |
1113 | int num_stations; | 1114 | int num_stations; |
1114 | struct iwl4965_station_entry stations[IWL_STATION_COUNT]; | 1115 | struct iwl4965_station_entry stations[IWL_STATION_COUNT]; |
1116 | struct iwl_wep_key wep_keys[WEP_KEYS_MAX]; | ||
1117 | u8 default_wep_key; | ||
1118 | u8 key_mapping_key; | ||
1119 | unsigned long ucode_key_table; | ||
1115 | 1120 | ||
1116 | /* Indication if ieee80211_ops->open has been called */ | 1121 | /* Indication if ieee80211_ops->open has been called */ |
1117 | u8 is_open; | 1122 | u8 is_open; |
@@ -1142,9 +1147,14 @@ struct iwl_priv { | |||
1142 | /* Last Rx'd beacon timestamp */ | 1147 | /* Last Rx'd beacon timestamp */ |
1143 | u64 timestamp; | 1148 | u64 timestamp; |
1144 | u16 beacon_int; | 1149 | u16 beacon_int; |
1145 | struct iwl4965_driver_hw_info hw_setting; | ||
1146 | struct ieee80211_vif *vif; | 1150 | struct ieee80211_vif *vif; |
1147 | 1151 | ||
1152 | struct iwl_hw_params hw_params; | ||
1153 | /* driver/uCode shared Tx Byte Counts and Rx status */ | ||
1154 | void *shared_virt; | ||
1155 | /* Physical Pointer to Tx Byte Counts and Rx status */ | ||
1156 | dma_addr_t shared_phys; | ||
1157 | |||
1148 | /* Current association information needed to configure the | 1158 | /* Current association information needed to configure the |
1149 | * hardware */ | 1159 | * hardware */ |
1150 | u16 assoc_id; | 1160 | u16 assoc_id; |
@@ -1200,7 +1210,6 @@ struct iwl_priv { | |||
1200 | #ifdef CONFIG_IWL4965_SENSITIVITY | 1210 | #ifdef CONFIG_IWL4965_SENSITIVITY |
1201 | struct work_struct sensitivity_work; | 1211 | struct work_struct sensitivity_work; |
1202 | #endif | 1212 | #endif |
1203 | struct work_struct statistics_work; | ||
1204 | struct timer_list statistics_periodic; | 1213 | struct timer_list statistics_periodic; |
1205 | }; /*iwl_priv */ | 1214 | }; /*iwl_priv */ |
1206 | 1215 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index d8a226e68ed1..2dfd982d7d1f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -277,3 +277,16 @@ int iwlcore_low_level_notify(struct iwl_priv *priv, | |||
277 | } | 277 | } |
278 | EXPORT_SYMBOL(iwlcore_low_level_notify); | 278 | EXPORT_SYMBOL(iwlcore_low_level_notify); |
279 | 279 | ||
280 | int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags) | ||
281 | { | ||
282 | u32 stat_flags = 0; | ||
283 | struct iwl_host_cmd cmd = { | ||
284 | .id = REPLY_STATISTICS_CMD, | ||
285 | .meta.flags = flags, | ||
286 | .len = sizeof(stat_flags), | ||
287 | .data = (u8 *) &stat_flags, | ||
288 | }; | ||
289 | return iwl_send_cmd(priv, &cmd); | ||
290 | } | ||
291 | EXPORT_SYMBOL(iwl_send_statistics_request); | ||
292 | |||
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 6d82376f43f9..7193d97630dc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -82,6 +82,9 @@ struct iwl_cmd; | |||
82 | #define IWL_SKU_A 0x2 | 82 | #define IWL_SKU_A 0x2 |
83 | #define IWL_SKU_N 0x8 | 83 | #define IWL_SKU_N 0x8 |
84 | 84 | ||
85 | struct iwl_hcmd_ops { | ||
86 | int (*rxon_assoc)(struct iwl_priv *priv); | ||
87 | }; | ||
85 | struct iwl_hcmd_utils_ops { | 88 | struct iwl_hcmd_utils_ops { |
86 | int (*enqueue_hcmd)(struct iwl_priv *priv, struct iwl_host_cmd *cmd); | 89 | int (*enqueue_hcmd)(struct iwl_priv *priv, struct iwl_host_cmd *cmd); |
87 | }; | 90 | }; |
@@ -89,19 +92,35 @@ struct iwl_hcmd_utils_ops { | |||
89 | struct iwl_lib_ops { | 92 | struct iwl_lib_ops { |
90 | /* iwlwifi driver (priv) init */ | 93 | /* iwlwifi driver (priv) init */ |
91 | int (*init_drv)(struct iwl_priv *priv); | 94 | int (*init_drv)(struct iwl_priv *priv); |
95 | /* set hw dependant perameters */ | ||
96 | int (*set_hw_params)(struct iwl_priv *priv); | ||
97 | |||
98 | void (*txq_update_byte_cnt_tbl)(struct iwl_priv *priv, | ||
99 | struct iwl4965_tx_queue *txq, | ||
100 | u16 byte_cnt); | ||
101 | /* nic init */ | ||
102 | int (*hw_nic_init)(struct iwl_priv *priv); | ||
103 | /* alive notification */ | ||
104 | int (*alive_notify)(struct iwl_priv *priv); | ||
105 | /* check validity of rtc data address */ | ||
106 | int (*is_valid_rtc_data_addr)(u32 addr); | ||
107 | /* 1st ucode load */ | ||
108 | int (*load_ucode)(struct iwl_priv *priv); | ||
109 | /* rfkill */ | ||
110 | void (*radio_kill_sw)(struct iwl_priv *priv, int disable_radio); | ||
92 | /* eeprom operations (as defined in iwl-eeprom.h) */ | 111 | /* eeprom operations (as defined in iwl-eeprom.h) */ |
93 | struct iwl_eeprom_ops eeprom_ops; | 112 | struct iwl_eeprom_ops eeprom_ops; |
94 | void (*radio_kill_sw)(struct iwl_priv *priv, int disable_radio); | ||
95 | }; | 113 | }; |
96 | 114 | ||
97 | struct iwl_ops { | 115 | struct iwl_ops { |
98 | const struct iwl_lib_ops *lib; | 116 | const struct iwl_lib_ops *lib; |
117 | const struct iwl_hcmd_ops *hcmd; | ||
99 | const struct iwl_hcmd_utils_ops *utils; | 118 | const struct iwl_hcmd_utils_ops *utils; |
100 | }; | 119 | }; |
101 | 120 | ||
102 | struct iwl_mod_params { | 121 | struct iwl_mod_params { |
103 | int disable; /* def: 0 = enable radio */ | 122 | int disable; /* def: 0 = enable radio */ |
104 | int hw_crypto; /* def: 0 = using software encryption */ | 123 | int sw_crypto; /* def: 0 = using hardware encryption */ |
105 | int debug; /* def: 0 = minimal debug log messages */ | 124 | int debug; /* def: 0 = minimal debug log messages */ |
106 | int disable_hw_scan; /* def: 0 = use h/w scan */ | 125 | int disable_hw_scan; /* def: 0 = use h/w scan */ |
107 | int num_of_queues; /* def: HW dependent */ | 126 | int num_of_queues; /* def: HW dependent */ |
@@ -215,4 +234,13 @@ enum iwlcore_card_notify { | |||
215 | 234 | ||
216 | int iwlcore_low_level_notify(struct iwl_priv *priv, | 235 | int iwlcore_low_level_notify(struct iwl_priv *priv, |
217 | enum iwlcore_card_notify notify); | 236 | enum iwlcore_card_notify notify); |
237 | extern int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags); | ||
238 | int iwl_send_lq_cmd(struct iwl_priv *priv, | ||
239 | struct iwl_link_quality_cmd *lq, u8 flags); | ||
240 | |||
241 | static inline int iwl_send_rxon_assoc(struct iwl_priv *priv) | ||
242 | { | ||
243 | return priv->cfg->ops->hcmd->rxon_assoc(priv); | ||
244 | } | ||
245 | |||
218 | #endif /* __iwl_core_h__ */ | 246 | #endif /* __iwl_core_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 23632e54aab2..0f16f2606f29 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c | |||
@@ -102,10 +102,14 @@ static ssize_t iwl_dbgfs_tx_statistics_read(struct file *file, | |||
102 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 102 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; |
103 | char buf[256]; | 103 | char buf[256]; |
104 | int pos = 0; | 104 | int pos = 0; |
105 | const size_t bufsz = sizeof(buf); | ||
105 | 106 | ||
106 | pos += sprintf(buf+pos, "mgmt: %u\n", priv->tx_stats[0].cnt); | 107 | pos += scnprintf(buf + pos, bufsz - pos, "mgmt: %u\n", |
107 | pos += sprintf(buf+pos, "ctrl: %u\n", priv->tx_stats[1].cnt); | 108 | priv->tx_stats[0].cnt); |
108 | pos += sprintf(buf+pos, "data: %u\n", priv->tx_stats[2].cnt); | 109 | pos += scnprintf(buf + pos, bufsz - pos, "ctrl: %u\n", |
110 | priv->tx_stats[1].cnt); | ||
111 | pos += scnprintf(buf + pos, bufsz - pos, "data: %u\n", | ||
112 | priv->tx_stats[2].cnt); | ||
109 | 113 | ||
110 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 114 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
111 | } | 115 | } |
@@ -117,10 +121,14 @@ static ssize_t iwl_dbgfs_rx_statistics_read(struct file *file, | |||
117 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 121 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; |
118 | char buf[256]; | 122 | char buf[256]; |
119 | int pos = 0; | 123 | int pos = 0; |
124 | const size_t bufsz = sizeof(buf); | ||
120 | 125 | ||
121 | pos += sprintf(buf+pos, "mgmt: %u\n", priv->rx_stats[0].cnt); | 126 | pos += scnprintf(buf + pos, bufsz - pos, "mgmt: %u\n", |
122 | pos += sprintf(buf+pos, "ctrl: %u\n", priv->rx_stats[1].cnt); | 127 | priv->rx_stats[0].cnt); |
123 | pos += sprintf(buf+pos, "data: %u\n", priv->rx_stats[2].cnt); | 128 | pos += scnprintf(buf + pos, bufsz - pos, "ctrl: %u\n", |
129 | priv->rx_stats[1].cnt); | ||
130 | pos += scnprintf(buf + pos, bufsz - pos, "data: %u\n", | ||
131 | priv->rx_stats[2].cnt); | ||
124 | 132 | ||
125 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 133 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
126 | } | 134 | } |
@@ -138,6 +146,7 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, | |||
138 | int i; | 146 | int i; |
139 | int pos = 0; | 147 | int pos = 0; |
140 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 148 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; |
149 | const size_t bufsz = sizeof(buf); | ||
141 | 150 | ||
142 | printk(KERN_DEBUG "offset is: 0x%x\tlen is: 0x%x\n", | 151 | printk(KERN_DEBUG "offset is: 0x%x\tlen is: 0x%x\n", |
143 | priv->dbgfs->sram_offset, priv->dbgfs->sram_len); | 152 | priv->dbgfs->sram_offset, priv->dbgfs->sram_len); |
@@ -159,9 +168,9 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, | |||
159 | break; | 168 | break; |
160 | } | 169 | } |
161 | } | 170 | } |
162 | pos += sprintf(buf+pos, "0x%08x ", val); | 171 | pos += scnprintf(buf + pos, bufsz - pos, "0x%08x ", val); |
163 | } | 172 | } |
164 | pos += sprintf(buf+pos, "\n"); | 173 | pos += scnprintf(buf + pos, bufsz - pos, "\n"); |
165 | iwl_release_nic_access(priv); | 174 | iwl_release_nic_access(priv); |
166 | 175 | ||
167 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 176 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
@@ -198,7 +207,7 @@ static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf, | |||
198 | { | 207 | { |
199 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 208 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; |
200 | struct iwl4965_station_entry *station; | 209 | struct iwl4965_station_entry *station; |
201 | int max_sta = priv->hw_setting.max_stations; | 210 | int max_sta = priv->hw_params.max_stations; |
202 | char *buf; | 211 | char *buf; |
203 | int i, j, pos = 0; | 212 | int i, j, pos = 0; |
204 | ssize_t ret; | 213 | ssize_t ret; |
@@ -210,44 +219,50 @@ static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf, | |||
210 | if(!buf) | 219 | if(!buf) |
211 | return -ENOMEM; | 220 | return -ENOMEM; |
212 | 221 | ||
213 | pos += sprintf(buf+pos, "num of stations: %d\n\n", | 222 | pos += scnprintf(buf + pos, bufsz - pos, "num of stations: %d\n\n", |
214 | priv->num_stations); | 223 | priv->num_stations); |
215 | 224 | ||
216 | for (i = 0; i < max_sta; i++) { | 225 | for (i = 0; i < max_sta; i++) { |
217 | station = &priv->stations[i]; | 226 | station = &priv->stations[i]; |
218 | if (station->used) { | 227 | if (station->used) { |
219 | pos += sprintf(buf+pos, "station %d:\ngeneral data:\n", | 228 | pos += scnprintf(buf + pos, bufsz - pos, |
220 | i+1); | 229 | "station %d:\ngeneral data:\n", i+1); |
221 | print_mac(mac, station->sta.sta.addr); | 230 | print_mac(mac, station->sta.sta.addr); |
222 | pos += sprintf(buf+pos, "id: %u\n", | 231 | pos += scnprintf(buf + pos, bufsz - pos, "id: %u\n", |
223 | station->sta.sta.sta_id); | 232 | station->sta.sta.sta_id); |
224 | pos += sprintf(buf+pos, "mode: %u\n", | 233 | pos += scnprintf(buf + pos, bufsz - pos, "mode: %u\n", |
225 | station->sta.mode); | 234 | station->sta.mode); |
226 | pos += sprintf(buf+pos, "flags: 0x%x\n", | 235 | pos += scnprintf(buf + pos, bufsz - pos, |
236 | "flags: 0x%x\n", | ||
227 | station->sta.station_flags_msk); | 237 | station->sta.station_flags_msk); |
228 | pos += sprintf(buf+pos, "ps_status: %u\n", | 238 | pos += scnprintf(buf + pos, bufsz - pos, |
229 | station->ps_status); | 239 | "ps_status: %u\n", station->ps_status); |
230 | 240 | pos += scnprintf(buf + pos, bufsz - pos, "tid data:\n"); | |
231 | pos += sprintf(buf+pos, "tid data:\n"); | 241 | pos += scnprintf(buf + pos, bufsz - pos, |
232 | 242 | "seq_num\t\ttxq_id\t"); | |
233 | pos += sprintf(buf+pos, "seq_num\t\ttxq_id\t"); | 243 | pos += scnprintf(buf + pos, bufsz - pos, |
234 | pos += sprintf(buf+pos, "frame_count\twait_for_ba\t"); | 244 | "frame_count\twait_for_ba\t"); |
235 | pos += sprintf(buf+pos, "start_idx\tbitmap0\t"); | 245 | pos += scnprintf(buf + pos, bufsz - pos, |
236 | pos += sprintf(buf+pos, "bitmap1\trate_n_flags\n"); | 246 | "start_idx\tbitmap0\t"); |
247 | pos += scnprintf(buf + pos, bufsz - pos, | ||
248 | "bitmap1\trate_n_flags\n"); | ||
237 | 249 | ||
238 | for (j = 0; j < MAX_TID_COUNT; j++) { | 250 | for (j = 0; j < MAX_TID_COUNT; j++) { |
239 | pos += sprintf(buf+pos, "[%d]:\t\t%u\t", | 251 | pos += scnprintf(buf + pos, bufsz - pos, |
240 | j, station->tid[j].seq_number); | 252 | "[%d]:\t\t%u\t", j, |
241 | pos += sprintf(buf+pos, "%u\t\t%u\t\t%u\t\t", | 253 | station->tid[j].seq_number); |
254 | pos += scnprintf(buf + pos, bufsz - pos, | ||
255 | "%u\t\t%u\t\t%u\t\t", | ||
242 | station->tid[j].agg.txq_id, | 256 | station->tid[j].agg.txq_id, |
243 | station->tid[j].agg.frame_count, | 257 | station->tid[j].agg.frame_count, |
244 | station->tid[j].agg.wait_for_ba); | 258 | station->tid[j].agg.wait_for_ba); |
245 | pos += sprintf(buf+pos, "%u\t%llu\t%u\n", | 259 | pos += scnprintf(buf + pos, bufsz - pos, |
260 | "%u\t%llu\t%u\n", | ||
246 | station->tid[j].agg.start_idx, | 261 | station->tid[j].agg.start_idx, |
247 | (unsigned long long)station->tid[j].agg.bitmap, | 262 | (unsigned long long)station->tid[j].agg.bitmap, |
248 | station->tid[j].agg.rate_n_flags); | 263 | station->tid[j].agg.rate_n_flags); |
249 | } | 264 | } |
250 | pos += sprintf(buf+pos, "\n"); | 265 | pos += scnprintf(buf + pos, bufsz - pos, "\n"); |
251 | } | 266 | } |
252 | } | 267 | } |
253 | 268 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c index 1f8c2999805b..fdb27f1cdc08 100644 --- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c | |||
@@ -51,6 +51,7 @@ const char *get_cmd_string(u8 cmd) | |||
51 | IWL_CMD(REPLY_ADD_STA); | 51 | IWL_CMD(REPLY_ADD_STA); |
52 | IWL_CMD(REPLY_REMOVE_STA); | 52 | IWL_CMD(REPLY_REMOVE_STA); |
53 | IWL_CMD(REPLY_REMOVE_ALL_STA); | 53 | IWL_CMD(REPLY_REMOVE_ALL_STA); |
54 | IWL_CMD(REPLY_WEPKEY); | ||
54 | IWL_CMD(REPLY_TX); | 55 | IWL_CMD(REPLY_TX); |
55 | IWL_CMD(REPLY_RATE_SCALE); | 56 | IWL_CMD(REPLY_RATE_SCALE); |
56 | IWL_CMD(REPLY_LEDS_CMD); | 57 | IWL_CMD(REPLY_LEDS_CMD); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.c b/drivers/net/wireless/iwlwifi/iwl-rfkill.c index 8f38c24491cd..5980a5621cb8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rfkill.c +++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.c | |||
@@ -47,6 +47,9 @@ static int iwl_rfkill_soft_rf_kill(void *data, enum rfkill_state state) | |||
47 | if (!priv->rfkill_mngr.rfkill) | 47 | if (!priv->rfkill_mngr.rfkill) |
48 | return 0; | 48 | return 0; |
49 | 49 | ||
50 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
51 | return 0; | ||
52 | |||
50 | IWL_DEBUG_RF_KILL("we recieved soft RFKILL set to state %d\n", state); | 53 | IWL_DEBUG_RF_KILL("we recieved soft RFKILL set to state %d\n", state); |
51 | mutex_lock(&priv->mutex); | 54 | mutex_lock(&priv->mutex); |
52 | 55 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.h b/drivers/net/wireless/iwlwifi/iwl-rfkill.h index e7aa51a1db18..a7f04b855403 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rfkill.h +++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.h | |||
@@ -34,7 +34,7 @@ struct iwl_priv; | |||
34 | #include <linux/input.h> | 34 | #include <linux/input.h> |
35 | 35 | ||
36 | 36 | ||
37 | #ifdef CONFIG_IWLCORE_RFKILL | 37 | #ifdef CONFIG_IWLWIFI_RFKILL |
38 | struct iwl_rfkill_mngr { | 38 | struct iwl_rfkill_mngr { |
39 | struct rfkill *rfkill; | 39 | struct rfkill *rfkill; |
40 | struct input_dev *input_dev; | 40 | struct input_dev *input_dev; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c new file mode 100644 index 000000000000..e4fdfaa2b9b2 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c | |||
@@ -0,0 +1,355 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. | ||
4 | * | ||
5 | * Portions of this file are derived from the ipw3945 project, as well | ||
6 | * as portions of the ieee80211 subsystem header files. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of version 2 of the GNU General Public License as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
15 | * more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License along with | ||
18 | * this program; if not, write to the Free Software Foundation, Inc., | ||
19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
20 | * | ||
21 | * The full GNU General Public License is included in this distribution in the | ||
22 | * file called LICENSE. | ||
23 | * | ||
24 | * Contact Information: | ||
25 | * James P. Ketrenos <ipw2100-admin@linux.intel.com> | ||
26 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #include <net/mac80211.h> | ||
31 | |||
32 | #include "iwl-eeprom.h" | ||
33 | #include "iwl-4965.h" | ||
34 | #include "iwl-core.h" | ||
35 | #include "iwl-sta.h" | ||
36 | #include "iwl-io.h" | ||
37 | #include "iwl-helpers.h" | ||
38 | #include "iwl-4965.h" | ||
39 | #include "iwl-sta.h" | ||
40 | |||
41 | int iwl_get_free_ucode_key_index(struct iwl_priv *priv) | ||
42 | { | ||
43 | int i; | ||
44 | |||
45 | for (i = 0; i < STA_KEY_MAX_NUM; i++) | ||
46 | if (!test_and_set_bit(i, &priv->ucode_key_table)) | ||
47 | return i; | ||
48 | |||
49 | return -1; | ||
50 | } | ||
51 | |||
52 | int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty) | ||
53 | { | ||
54 | int i, not_empty = 0; | ||
55 | u8 buff[sizeof(struct iwl_wep_cmd) + | ||
56 | sizeof(struct iwl_wep_key) * WEP_KEYS_MAX]; | ||
57 | struct iwl_wep_cmd *wep_cmd = (struct iwl_wep_cmd *)buff; | ||
58 | size_t cmd_size = sizeof(struct iwl_wep_cmd); | ||
59 | struct iwl_host_cmd cmd = { | ||
60 | .id = REPLY_WEPKEY, | ||
61 | .data = wep_cmd, | ||
62 | .meta.flags = CMD_ASYNC, | ||
63 | }; | ||
64 | |||
65 | memset(wep_cmd, 0, cmd_size + | ||
66 | (sizeof(struct iwl_wep_key) * WEP_KEYS_MAX)); | ||
67 | |||
68 | for (i = 0; i < WEP_KEYS_MAX ; i++) { | ||
69 | wep_cmd->key[i].key_index = i; | ||
70 | if (priv->wep_keys[i].key_size) { | ||
71 | wep_cmd->key[i].key_offset = i; | ||
72 | not_empty = 1; | ||
73 | } else { | ||
74 | wep_cmd->key[i].key_offset = WEP_INVALID_OFFSET; | ||
75 | } | ||
76 | |||
77 | wep_cmd->key[i].key_size = priv->wep_keys[i].key_size; | ||
78 | memcpy(&wep_cmd->key[i].key[3], priv->wep_keys[i].key, | ||
79 | priv->wep_keys[i].key_size); | ||
80 | } | ||
81 | |||
82 | wep_cmd->global_key_type = WEP_KEY_WEP_TYPE; | ||
83 | wep_cmd->num_keys = WEP_KEYS_MAX; | ||
84 | |||
85 | cmd_size += sizeof(struct iwl_wep_key) * WEP_KEYS_MAX; | ||
86 | |||
87 | cmd.len = cmd_size; | ||
88 | |||
89 | if (not_empty || send_if_empty) | ||
90 | return iwl_send_cmd(priv, &cmd); | ||
91 | else | ||
92 | return 0; | ||
93 | } | ||
94 | |||
95 | int iwl_remove_default_wep_key(struct iwl_priv *priv, | ||
96 | struct ieee80211_key_conf *keyconf) | ||
97 | { | ||
98 | int ret; | ||
99 | unsigned long flags; | ||
100 | |||
101 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
102 | |||
103 | if (!test_and_clear_bit(keyconf->keyidx, &priv->ucode_key_table)) | ||
104 | IWL_ERROR("index %d not used in uCode key table.\n", | ||
105 | keyconf->keyidx); | ||
106 | |||
107 | priv->default_wep_key--; | ||
108 | memset(&priv->wep_keys[keyconf->keyidx], 0, sizeof(priv->wep_keys[0])); | ||
109 | ret = iwl_send_static_wepkey_cmd(priv, 1); | ||
110 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
111 | |||
112 | return ret; | ||
113 | } | ||
114 | |||
115 | int iwl_set_default_wep_key(struct iwl_priv *priv, | ||
116 | struct ieee80211_key_conf *keyconf) | ||
117 | { | ||
118 | int ret; | ||
119 | unsigned long flags; | ||
120 | |||
121 | keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV; | ||
122 | keyconf->hw_key_idx = keyconf->keyidx; | ||
123 | priv->stations[IWL_AP_ID].keyinfo.alg = ALG_WEP; | ||
124 | |||
125 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
126 | priv->default_wep_key++; | ||
127 | |||
128 | if (test_and_set_bit(keyconf->keyidx, &priv->ucode_key_table)) | ||
129 | IWL_ERROR("index %d already used in uCode key table.\n", | ||
130 | keyconf->keyidx); | ||
131 | |||
132 | priv->wep_keys[keyconf->keyidx].key_size = keyconf->keylen; | ||
133 | memcpy(&priv->wep_keys[keyconf->keyidx].key, &keyconf->key, | ||
134 | keyconf->keylen); | ||
135 | |||
136 | ret = iwl_send_static_wepkey_cmd(priv, 0); | ||
137 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
138 | |||
139 | return ret; | ||
140 | } | ||
141 | |||
142 | static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv, | ||
143 | struct ieee80211_key_conf *keyconf, | ||
144 | u8 sta_id) | ||
145 | { | ||
146 | unsigned long flags; | ||
147 | __le16 key_flags = 0; | ||
148 | int ret; | ||
149 | |||
150 | keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV; | ||
151 | keyconf->hw_key_idx = keyconf->keyidx; | ||
152 | |||
153 | key_flags |= (STA_KEY_FLG_WEP | STA_KEY_FLG_MAP_KEY_MSK); | ||
154 | key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); | ||
155 | key_flags &= ~STA_KEY_FLG_INVALID; | ||
156 | |||
157 | if (keyconf->keylen == WEP_KEY_LEN_128) | ||
158 | key_flags |= STA_KEY_FLG_KEY_SIZE_MSK; | ||
159 | |||
160 | if (sta_id == priv->hw_params.bcast_sta_id) | ||
161 | key_flags |= STA_KEY_MULTICAST_MSK; | ||
162 | |||
163 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
164 | |||
165 | priv->stations[sta_id].keyinfo.alg = keyconf->alg; | ||
166 | priv->stations[sta_id].keyinfo.keylen = keyconf->keylen; | ||
167 | priv->stations[sta_id].keyinfo.keyidx = keyconf->keyidx; | ||
168 | |||
169 | memcpy(priv->stations[sta_id].keyinfo.key, | ||
170 | keyconf->key, keyconf->keylen); | ||
171 | |||
172 | memcpy(&priv->stations[sta_id].sta.key.key[3], | ||
173 | keyconf->key, keyconf->keylen); | ||
174 | |||
175 | priv->stations[sta_id].sta.key.key_offset = | ||
176 | iwl_get_free_ucode_key_index(priv); | ||
177 | priv->stations[sta_id].sta.key.key_flags = key_flags; | ||
178 | |||
179 | priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; | ||
180 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; | ||
181 | |||
182 | ret = iwl4965_send_add_station(priv, | ||
183 | &priv->stations[sta_id].sta, CMD_ASYNC); | ||
184 | |||
185 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
186 | |||
187 | return ret; | ||
188 | } | ||
189 | |||
190 | static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv, | ||
191 | struct ieee80211_key_conf *keyconf, | ||
192 | u8 sta_id) | ||
193 | { | ||
194 | unsigned long flags; | ||
195 | __le16 key_flags = 0; | ||
196 | |||
197 | key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK); | ||
198 | key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); | ||
199 | key_flags &= ~STA_KEY_FLG_INVALID; | ||
200 | |||
201 | if (sta_id == priv->hw_params.bcast_sta_id) | ||
202 | key_flags |= STA_KEY_MULTICAST_MSK; | ||
203 | |||
204 | keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | ||
205 | keyconf->hw_key_idx = keyconf->keyidx; | ||
206 | |||
207 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
208 | priv->stations[sta_id].keyinfo.alg = keyconf->alg; | ||
209 | priv->stations[sta_id].keyinfo.keylen = keyconf->keylen; | ||
210 | |||
211 | memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, | ||
212 | keyconf->keylen); | ||
213 | |||
214 | memcpy(priv->stations[sta_id].sta.key.key, keyconf->key, | ||
215 | keyconf->keylen); | ||
216 | |||
217 | priv->stations[sta_id].sta.key.key_offset = | ||
218 | iwl_get_free_ucode_key_index(priv); | ||
219 | priv->stations[sta_id].sta.key.key_flags = key_flags; | ||
220 | priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; | ||
221 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; | ||
222 | |||
223 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
224 | |||
225 | IWL_DEBUG_INFO("hwcrypto: modify ucode station key info\n"); | ||
226 | return iwl4965_send_add_station(priv, | ||
227 | &priv->stations[sta_id].sta, CMD_ASYNC); | ||
228 | } | ||
229 | |||
230 | static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv, | ||
231 | struct ieee80211_key_conf *keyconf, | ||
232 | u8 sta_id) | ||
233 | { | ||
234 | unsigned long flags; | ||
235 | int ret = 0; | ||
236 | |||
237 | keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | ||
238 | keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; | ||
239 | keyconf->hw_key_idx = keyconf->keyidx; | ||
240 | |||
241 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
242 | |||
243 | priv->stations[sta_id].keyinfo.alg = keyconf->alg; | ||
244 | priv->stations[sta_id].keyinfo.conf = keyconf; | ||
245 | priv->stations[sta_id].keyinfo.keylen = 16; | ||
246 | priv->stations[sta_id].sta.key.key_offset = | ||
247 | iwl_get_free_ucode_key_index(priv); | ||
248 | |||
249 | /* This copy is acutally not needed: we get the key with each TX */ | ||
250 | memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, 16); | ||
251 | |||
252 | memcpy(priv->stations[sta_id].sta.key.key, keyconf->key, 16); | ||
253 | |||
254 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
255 | |||
256 | return ret; | ||
257 | } | ||
258 | |||
259 | int iwl_remove_dynamic_key(struct iwl_priv *priv, u8 sta_id) | ||
260 | { | ||
261 | unsigned long flags; | ||
262 | |||
263 | priv->key_mapping_key = 0; | ||
264 | |||
265 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
266 | if (!test_and_clear_bit(priv->stations[sta_id].sta.key.key_offset, | ||
267 | &priv->ucode_key_table)) | ||
268 | IWL_ERROR("index %d not used in uCode key table.\n", | ||
269 | priv->stations[sta_id].sta.key.key_offset); | ||
270 | memset(&priv->stations[sta_id].keyinfo, 0, | ||
271 | sizeof(struct iwl4965_hw_key)); | ||
272 | memset(&priv->stations[sta_id].sta.key, 0, | ||
273 | sizeof(struct iwl4965_keyinfo)); | ||
274 | priv->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC; | ||
275 | priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; | ||
276 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; | ||
277 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
278 | |||
279 | IWL_DEBUG_INFO("hwcrypto: clear ucode station key info\n"); | ||
280 | return iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, 0); | ||
281 | } | ||
282 | |||
283 | int iwl_set_dynamic_key(struct iwl_priv *priv, | ||
284 | struct ieee80211_key_conf *key, u8 sta_id) | ||
285 | { | ||
286 | int ret; | ||
287 | |||
288 | priv->key_mapping_key = 1; | ||
289 | |||
290 | switch (key->alg) { | ||
291 | case ALG_CCMP: | ||
292 | ret = iwl_set_ccmp_dynamic_key_info(priv, key, sta_id); | ||
293 | break; | ||
294 | case ALG_TKIP: | ||
295 | ret = iwl_set_tkip_dynamic_key_info(priv, key, sta_id); | ||
296 | break; | ||
297 | case ALG_WEP: | ||
298 | ret = iwl_set_wep_dynamic_key_info(priv, key, sta_id); | ||
299 | break; | ||
300 | default: | ||
301 | IWL_ERROR("Unknown alg: %s alg = %d\n", __func__, key->alg); | ||
302 | ret = -EINVAL; | ||
303 | } | ||
304 | |||
305 | return ret; | ||
306 | } | ||
307 | |||
308 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
309 | static void iwl_dump_lq_cmd(struct iwl_priv *priv, | ||
310 | struct iwl_link_quality_cmd *lq) | ||
311 | { | ||
312 | int i; | ||
313 | IWL_DEBUG_RATE("lq station id 0x%x\n", lq->sta_id); | ||
314 | IWL_DEBUG_RATE("lq dta 0x%X 0x%X\n", | ||
315 | lq->general_params.single_stream_ant_msk, | ||
316 | lq->general_params.dual_stream_ant_msk); | ||
317 | |||
318 | for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) | ||
319 | IWL_DEBUG_RATE("lq index %d 0x%X\n", | ||
320 | i, lq->rs_table[i].rate_n_flags); | ||
321 | } | ||
322 | #else | ||
323 | static inline void iwl_dump_lq_cmd(struct iwl_priv *priv, | ||
324 | struct iwl_link_quality_cmd *lq) | ||
325 | { | ||
326 | } | ||
327 | #endif | ||
328 | |||
329 | int iwl_send_lq_cmd(struct iwl_priv *priv, | ||
330 | struct iwl_link_quality_cmd *lq, u8 flags) | ||
331 | { | ||
332 | struct iwl_host_cmd cmd = { | ||
333 | .id = REPLY_TX_LINK_QUALITY_CMD, | ||
334 | .len = sizeof(struct iwl_link_quality_cmd), | ||
335 | .meta.flags = flags, | ||
336 | .data = lq, | ||
337 | }; | ||
338 | |||
339 | if ((lq->sta_id == 0xFF) && | ||
340 | (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)) | ||
341 | return -EINVAL; | ||
342 | |||
343 | if (lq->sta_id == 0xFF) | ||
344 | lq->sta_id = IWL_AP_ID; | ||
345 | |||
346 | iwl_dump_lq_cmd(priv,lq); | ||
347 | |||
348 | if (iwl_is_associated(priv) && priv->assoc_station_added && | ||
349 | priv->lq_mngr.lq_ready) | ||
350 | return iwl_send_cmd(priv, &cmd); | ||
351 | |||
352 | return 0; | ||
353 | } | ||
354 | EXPORT_SYMBOL(iwl_send_lq_cmd); | ||
355 | |||
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h new file mode 100644 index 000000000000..44f272ecc827 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h | |||
@@ -0,0 +1,49 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. | ||
4 | * | ||
5 | * Portions of this file are derived from the ipw3945 project, as well | ||
6 | * as portions of the ieee80211 subsystem header files. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of version 2 of the GNU General Public License as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
15 | * more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License along with | ||
18 | * this program; if not, write to the Free Software Foundation, Inc., | ||
19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
20 | * | ||
21 | * The full GNU General Public License is included in this distribution in the | ||
22 | * file called LICENSE. | ||
23 | * | ||
24 | * Contact Information: | ||
25 | * James P. Ketrenos <ipw2100-admin@linux.intel.com> | ||
26 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | #ifndef __iwl_sta_h__ | ||
30 | #define __iwl_sta_h__ | ||
31 | |||
32 | #include <net/mac80211.h> | ||
33 | |||
34 | #include "iwl-eeprom.h" | ||
35 | #include "iwl-core.h" | ||
36 | #include "iwl-4965.h" | ||
37 | #include "iwl-io.h" | ||
38 | #include "iwl-helpers.h" | ||
39 | |||
40 | int iwl_get_free_ucode_key_index(struct iwl_priv *priv); | ||
41 | int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty); | ||
42 | int iwl_remove_default_wep_key(struct iwl_priv *priv, | ||
43 | struct ieee80211_key_conf *key); | ||
44 | int iwl_set_default_wep_key(struct iwl_priv *priv, | ||
45 | struct ieee80211_key_conf *key); | ||
46 | int iwl_remove_dynamic_key(struct iwl_priv *priv, u8 sta_id); | ||
47 | int iwl_set_dynamic_key(struct iwl_priv *priv, | ||
48 | struct ieee80211_key_conf *key, u8 sta_id); | ||
49 | #endif /* __iwl_sta_h__ */ | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 29a9ecdcbf35..1a5678fe4224 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
@@ -70,7 +70,7 @@ static int iwl3945_param_disable; /* def: 0 = enable radio */ | |||
70 | static int iwl3945_param_antenna; /* def: 0 = both antennas (use diversity) */ | 70 | static int iwl3945_param_antenna; /* def: 0 = both antennas (use diversity) */ |
71 | int iwl3945_param_hwcrypto; /* def: 0 = use software encryption */ | 71 | int iwl3945_param_hwcrypto; /* def: 0 = use software encryption */ |
72 | static int iwl3945_param_qos_enable = 1; /* def: 1 = use quality of service */ | 72 | static int iwl3945_param_qos_enable = 1; /* def: 1 = use quality of service */ |
73 | int iwl3945_param_queues_num = IWL_MAX_NUM_QUEUES; /* def: 8 Tx queues */ | 73 | int iwl3945_param_queues_num = IWL39_MAX_NUM_QUEUES; /* def: 8 Tx queues */ |
74 | 74 | ||
75 | /* | 75 | /* |
76 | * module name, copyright, version, etc. | 76 | * module name, copyright, version, etc. |
@@ -7974,10 +7974,10 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
7974 | iwl3945_hw_ops.hw_scan = NULL; | 7974 | iwl3945_hw_ops.hw_scan = NULL; |
7975 | } | 7975 | } |
7976 | 7976 | ||
7977 | if ((iwl3945_param_queues_num > IWL_MAX_NUM_QUEUES) || | 7977 | if ((iwl3945_param_queues_num > IWL39_MAX_NUM_QUEUES) || |
7978 | (iwl3945_param_queues_num < IWL_MIN_NUM_QUEUES)) { | 7978 | (iwl3945_param_queues_num < IWL_MIN_NUM_QUEUES)) { |
7979 | IWL_ERROR("invalid queues_num, should be between %d and %d\n", | 7979 | IWL_ERROR("invalid queues_num, should be between %d and %d\n", |
7980 | IWL_MIN_NUM_QUEUES, IWL_MAX_NUM_QUEUES); | 7980 | IWL_MIN_NUM_QUEUES, IWL39_MAX_NUM_QUEUES); |
7981 | err = -EINVAL; | 7981 | err = -EINVAL; |
7982 | goto out; | 7982 | goto out; |
7983 | } | 7983 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 06e44dad5f02..d7e2358a213a 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c | |||
@@ -50,6 +50,7 @@ | |||
50 | #include "iwl-core.h" | 50 | #include "iwl-core.h" |
51 | #include "iwl-io.h" | 51 | #include "iwl-io.h" |
52 | #include "iwl-helpers.h" | 52 | #include "iwl-helpers.h" |
53 | #include "iwl-sta.h" | ||
53 | 54 | ||
54 | static int iwl4965_tx_queue_update_write_ptr(struct iwl_priv *priv, | 55 | static int iwl4965_tx_queue_update_write_ptr(struct iwl_priv *priv, |
55 | struct iwl4965_tx_queue *txq); | 56 | struct iwl4965_tx_queue *txq); |
@@ -397,9 +398,9 @@ static u8 iwl4965_remove_station(struct iwl_priv *priv, const u8 *addr, int is_a | |||
397 | if (is_ap) | 398 | if (is_ap) |
398 | index = IWL_AP_ID; | 399 | index = IWL_AP_ID; |
399 | else if (is_broadcast_ether_addr(addr)) | 400 | else if (is_broadcast_ether_addr(addr)) |
400 | index = priv->hw_setting.bcast_sta_id; | 401 | index = priv->hw_params.bcast_sta_id; |
401 | else | 402 | else |
402 | for (i = IWL_STA_ID; i < priv->hw_setting.max_stations; i++) | 403 | for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) |
403 | if (priv->stations[i].used && | 404 | if (priv->stations[i].used && |
404 | !compare_ether_addr(priv->stations[i].sta.sta.addr, | 405 | !compare_ether_addr(priv->stations[i].sta.sta.addr, |
405 | addr)) { | 406 | addr)) { |
@@ -439,9 +440,9 @@ u8 iwl4965_add_station_flags(struct iwl_priv *priv, const u8 *addr, | |||
439 | if (is_ap) | 440 | if (is_ap) |
440 | index = IWL_AP_ID; | 441 | index = IWL_AP_ID; |
441 | else if (is_broadcast_ether_addr(addr)) | 442 | else if (is_broadcast_ether_addr(addr)) |
442 | index = priv->hw_setting.bcast_sta_id; | 443 | index = priv->hw_params.bcast_sta_id; |
443 | else | 444 | else |
444 | for (i = IWL_STA_ID; i < priv->hw_setting.max_stations; i++) { | 445 | for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) { |
445 | if (!compare_ether_addr(priv->stations[i].sta.sta.addr, | 446 | if (!compare_ether_addr(priv->stations[i].sta.sta.addr, |
446 | addr)) { | 447 | addr)) { |
447 | index = i; | 448 | index = i; |
@@ -482,7 +483,7 @@ u8 iwl4965_add_station_flags(struct iwl_priv *priv, const u8 *addr, | |||
482 | 483 | ||
483 | #ifdef CONFIG_IWL4965_HT | 484 | #ifdef CONFIG_IWL4965_HT |
484 | /* BCAST station and IBSS stations do not work in HT mode */ | 485 | /* BCAST station and IBSS stations do not work in HT mode */ |
485 | if (index != priv->hw_setting.bcast_sta_id && | 486 | if (index != priv->hw_params.bcast_sta_id && |
486 | priv->iw_mode != IEEE80211_IF_TYPE_IBSS) | 487 | priv->iw_mode != IEEE80211_IF_TYPE_IBSS) |
487 | iwl4965_set_ht_add_station(priv, index, | 488 | iwl4965_set_ht_add_station(priv, index, |
488 | (struct ieee80211_ht_info *) ht_data); | 489 | (struct ieee80211_ht_info *) ht_data); |
@@ -574,11 +575,11 @@ int iwl4965_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
574 | txq->need_update = 1; | 575 | txq->need_update = 1; |
575 | 576 | ||
576 | /* Set up entry in queue's byte count circular buffer */ | 577 | /* Set up entry in queue's byte count circular buffer */ |
577 | ret = iwl4965_tx_queue_update_wr_ptr(priv, txq, 0); | 578 | priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq, 0); |
578 | 579 | ||
579 | /* Increment and update queue's write index */ | 580 | /* Increment and update queue's write index */ |
580 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); | 581 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); |
581 | iwl4965_tx_queue_update_write_ptr(priv, txq); | 582 | ret = iwl4965_tx_queue_update_write_ptr(priv, txq); |
582 | 583 | ||
583 | spin_unlock_irqrestore(&priv->hcmd_lock, flags); | 584 | spin_unlock_irqrestore(&priv->hcmd_lock, flags); |
584 | return ret ? ret : idx; | 585 | return ret ? ret : idx; |
@@ -595,13 +596,6 @@ static void iwl4965_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt) | |||
595 | 596 | ||
596 | } | 597 | } |
597 | 598 | ||
598 | int iwl4965_send_statistics_request(struct iwl_priv *priv) | ||
599 | { | ||
600 | u32 flags = 0; | ||
601 | return iwl_send_cmd_pdu(priv, REPLY_STATISTICS_CMD, | ||
602 | sizeof(flags), &flags); | ||
603 | } | ||
604 | |||
605 | /** | 599 | /** |
606 | * iwl4965_rxon_add_station - add station into station table. | 600 | * iwl4965_rxon_add_station - add station into station table. |
607 | * | 601 | * |
@@ -755,60 +749,6 @@ static int iwl4965_full_rxon_required(struct iwl_priv *priv) | |||
755 | return 0; | 749 | return 0; |
756 | } | 750 | } |
757 | 751 | ||
758 | static int iwl4965_send_rxon_assoc(struct iwl_priv *priv) | ||
759 | { | ||
760 | int rc = 0; | ||
761 | struct iwl4965_rx_packet *res = NULL; | ||
762 | struct iwl4965_rxon_assoc_cmd rxon_assoc; | ||
763 | struct iwl_host_cmd cmd = { | ||
764 | .id = REPLY_RXON_ASSOC, | ||
765 | .len = sizeof(rxon_assoc), | ||
766 | .meta.flags = CMD_WANT_SKB, | ||
767 | .data = &rxon_assoc, | ||
768 | }; | ||
769 | const struct iwl4965_rxon_cmd *rxon1 = &priv->staging_rxon; | ||
770 | const struct iwl4965_rxon_cmd *rxon2 = &priv->active_rxon; | ||
771 | |||
772 | if ((rxon1->flags == rxon2->flags) && | ||
773 | (rxon1->filter_flags == rxon2->filter_flags) && | ||
774 | (rxon1->cck_basic_rates == rxon2->cck_basic_rates) && | ||
775 | (rxon1->ofdm_ht_single_stream_basic_rates == | ||
776 | rxon2->ofdm_ht_single_stream_basic_rates) && | ||
777 | (rxon1->ofdm_ht_dual_stream_basic_rates == | ||
778 | rxon2->ofdm_ht_dual_stream_basic_rates) && | ||
779 | (rxon1->rx_chain == rxon2->rx_chain) && | ||
780 | (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) { | ||
781 | IWL_DEBUG_INFO("Using current RXON_ASSOC. Not resending.\n"); | ||
782 | return 0; | ||
783 | } | ||
784 | |||
785 | rxon_assoc.flags = priv->staging_rxon.flags; | ||
786 | rxon_assoc.filter_flags = priv->staging_rxon.filter_flags; | ||
787 | rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates; | ||
788 | rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates; | ||
789 | rxon_assoc.reserved = 0; | ||
790 | rxon_assoc.ofdm_ht_single_stream_basic_rates = | ||
791 | priv->staging_rxon.ofdm_ht_single_stream_basic_rates; | ||
792 | rxon_assoc.ofdm_ht_dual_stream_basic_rates = | ||
793 | priv->staging_rxon.ofdm_ht_dual_stream_basic_rates; | ||
794 | rxon_assoc.rx_chain_select_flags = priv->staging_rxon.rx_chain; | ||
795 | |||
796 | rc = iwl_send_cmd_sync(priv, &cmd); | ||
797 | if (rc) | ||
798 | return rc; | ||
799 | |||
800 | res = (struct iwl4965_rx_packet *)cmd.meta.u.skb->data; | ||
801 | if (res->hdr.flags & IWL_CMD_FAILED_MSK) { | ||
802 | IWL_ERROR("Bad return from REPLY_RXON_ASSOC command\n"); | ||
803 | rc = -EIO; | ||
804 | } | ||
805 | |||
806 | priv->alloc_rxb_skb--; | ||
807 | dev_kfree_skb_any(cmd.meta.u.skb); | ||
808 | |||
809 | return rc; | ||
810 | } | ||
811 | |||
812 | /** | 752 | /** |
813 | * iwl4965_commit_rxon - commit staging_rxon to hardware | 753 | * iwl4965_commit_rxon - commit staging_rxon to hardware |
814 | * | 754 | * |
@@ -840,7 +780,7 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv) | |||
840 | * iwl4965_rxon_assoc_cmd which is used to reconfigure filter | 780 | * iwl4965_rxon_assoc_cmd which is used to reconfigure filter |
841 | * and other flags for the current radio configuration. */ | 781 | * and other flags for the current radio configuration. */ |
842 | if (!iwl4965_full_rxon_required(priv)) { | 782 | if (!iwl4965_full_rxon_required(priv)) { |
843 | rc = iwl4965_send_rxon_assoc(priv); | 783 | rc = iwl_send_rxon_assoc(priv); |
844 | if (rc) { | 784 | if (rc) { |
845 | IWL_ERROR("Error setting RXON_ASSOC " | 785 | IWL_ERROR("Error setting RXON_ASSOC " |
846 | "configuration (%d).\n", rc); | 786 | "configuration (%d).\n", rc); |
@@ -895,7 +835,7 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv) | |||
895 | le16_to_cpu(priv->staging_rxon.channel), | 835 | le16_to_cpu(priv->staging_rxon.channel), |
896 | print_mac(mac, priv->staging_rxon.bssid_addr)); | 836 | print_mac(mac, priv->staging_rxon.bssid_addr)); |
897 | 837 | ||
898 | iwl4965_set_rxon_hwcrypto(priv, priv->cfg->mod_params->hw_crypto); | 838 | iwl4965_set_rxon_hwcrypto(priv, !priv->cfg->mod_params->sw_crypto); |
899 | /* Apply the new configuration */ | 839 | /* Apply the new configuration */ |
900 | rc = iwl_send_cmd_pdu(priv, REPLY_RXON, | 840 | rc = iwl_send_cmd_pdu(priv, REPLY_RXON, |
901 | sizeof(struct iwl4965_rxon_cmd), &priv->staging_rxon); | 841 | sizeof(struct iwl4965_rxon_cmd), &priv->staging_rxon); |
@@ -941,6 +881,9 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv) | |||
941 | return -EIO; | 881 | return -EIO; |
942 | } | 882 | } |
943 | priv->assoc_station_added = 1; | 883 | priv->assoc_station_added = 1; |
884 | if (priv->default_wep_key && | ||
885 | iwl_send_static_wepkey_cmd(priv, 0)) | ||
886 | IWL_ERROR("Could not send WEP static key.\n"); | ||
944 | } | 887 | } |
945 | 888 | ||
946 | return 0; | 889 | return 0; |
@@ -1108,131 +1051,6 @@ int iwl4965_send_add_station(struct iwl_priv *priv, | |||
1108 | return rc; | 1051 | return rc; |
1109 | } | 1052 | } |
1110 | 1053 | ||
1111 | static int iwl4965_set_ccmp_dynamic_key_info(struct iwl_priv *priv, | ||
1112 | struct ieee80211_key_conf *keyconf, | ||
1113 | u8 sta_id) | ||
1114 | { | ||
1115 | unsigned long flags; | ||
1116 | __le16 key_flags = 0; | ||
1117 | |||
1118 | key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK); | ||
1119 | key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); | ||
1120 | |||
1121 | if (sta_id == priv->hw_setting.bcast_sta_id) | ||
1122 | key_flags |= STA_KEY_MULTICAST_MSK; | ||
1123 | |||
1124 | keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | ||
1125 | keyconf->hw_key_idx = keyconf->keyidx; | ||
1126 | |||
1127 | key_flags &= ~STA_KEY_FLG_INVALID; | ||
1128 | |||
1129 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
1130 | priv->stations[sta_id].keyinfo.alg = keyconf->alg; | ||
1131 | priv->stations[sta_id].keyinfo.keylen = keyconf->keylen; | ||
1132 | |||
1133 | memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, | ||
1134 | keyconf->keylen); | ||
1135 | |||
1136 | memcpy(priv->stations[sta_id].sta.key.key, keyconf->key, | ||
1137 | keyconf->keylen); | ||
1138 | |||
1139 | priv->stations[sta_id].sta.key.key_offset | ||
1140 | = (sta_id % STA_KEY_MAX_NUM);/*FIXME*/ | ||
1141 | priv->stations[sta_id].sta.key.key_flags = key_flags; | ||
1142 | priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; | ||
1143 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; | ||
1144 | |||
1145 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
1146 | |||
1147 | IWL_DEBUG_INFO("hwcrypto: modify ucode station key info\n"); | ||
1148 | return iwl4965_send_add_station(priv, | ||
1149 | &priv->stations[sta_id].sta, CMD_ASYNC); | ||
1150 | } | ||
1151 | |||
1152 | static int iwl4965_set_tkip_dynamic_key_info(struct iwl_priv *priv, | ||
1153 | struct ieee80211_key_conf *keyconf, | ||
1154 | u8 sta_id) | ||
1155 | { | ||
1156 | unsigned long flags; | ||
1157 | int ret = 0; | ||
1158 | |||
1159 | keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | ||
1160 | keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; | ||
1161 | keyconf->hw_key_idx = keyconf->keyidx; | ||
1162 | |||
1163 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
1164 | |||
1165 | priv->stations[sta_id].keyinfo.alg = keyconf->alg; | ||
1166 | priv->stations[sta_id].keyinfo.conf = keyconf; | ||
1167 | priv->stations[sta_id].keyinfo.keylen = 16; | ||
1168 | |||
1169 | /* This copy is acutally not needed: we get the key with each TX */ | ||
1170 | memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, 16); | ||
1171 | |||
1172 | memcpy(priv->stations[sta_id].sta.key.key, keyconf->key, 16); | ||
1173 | |||
1174 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
1175 | |||
1176 | return ret; | ||
1177 | } | ||
1178 | |||
1179 | static int iwl4965_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id) | ||
1180 | { | ||
1181 | unsigned long flags; | ||
1182 | |||
1183 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
1184 | memset(&priv->stations[sta_id].keyinfo, 0, sizeof(struct iwl4965_hw_key)); | ||
1185 | memset(&priv->stations[sta_id].sta.key, 0, sizeof(struct iwl4965_keyinfo)); | ||
1186 | priv->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC; | ||
1187 | priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; | ||
1188 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; | ||
1189 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
1190 | |||
1191 | IWL_DEBUG_INFO("hwcrypto: clear ucode station key info\n"); | ||
1192 | iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, 0); | ||
1193 | return 0; | ||
1194 | } | ||
1195 | |||
1196 | static int iwl4965_set_dynamic_key(struct iwl_priv *priv, | ||
1197 | struct ieee80211_key_conf *key, u8 sta_id) | ||
1198 | { | ||
1199 | int ret; | ||
1200 | |||
1201 | switch (key->alg) { | ||
1202 | case ALG_CCMP: | ||
1203 | ret = iwl4965_set_ccmp_dynamic_key_info(priv, key, sta_id); | ||
1204 | break; | ||
1205 | case ALG_TKIP: | ||
1206 | ret = iwl4965_set_tkip_dynamic_key_info(priv, key, sta_id); | ||
1207 | break; | ||
1208 | case ALG_WEP: | ||
1209 | ret = -EOPNOTSUPP; | ||
1210 | break; | ||
1211 | default: | ||
1212 | IWL_ERROR("Unknown alg: %s alg = %d\n", __func__, key->alg); | ||
1213 | ret = -EINVAL; | ||
1214 | } | ||
1215 | |||
1216 | return ret; | ||
1217 | } | ||
1218 | |||
1219 | static int iwl4965_remove_static_key(struct iwl_priv *priv) | ||
1220 | { | ||
1221 | int ret = -EOPNOTSUPP; | ||
1222 | |||
1223 | return ret; | ||
1224 | } | ||
1225 | |||
1226 | static int iwl4965_set_static_key(struct iwl_priv *priv, | ||
1227 | struct ieee80211_key_conf *key) | ||
1228 | { | ||
1229 | if (key->alg == ALG_WEP) | ||
1230 | return -EOPNOTSUPP; | ||
1231 | |||
1232 | IWL_ERROR("Static key invalid: alg %d\n", key->alg); | ||
1233 | return -EINVAL; | ||
1234 | } | ||
1235 | |||
1236 | static void iwl4965_clear_free_frames(struct iwl_priv *priv) | 1054 | static void iwl4965_clear_free_frames(struct iwl_priv *priv) |
1237 | { | 1055 | { |
1238 | struct list_head *element; | 1056 | struct list_head *element; |
@@ -1353,13 +1171,13 @@ static int iwl4965_send_beacon_cmd(struct iwl_priv *priv) | |||
1353 | * | 1171 | * |
1354 | ******************************************************************************/ | 1172 | ******************************************************************************/ |
1355 | 1173 | ||
1356 | static void iwl4965_unset_hw_setting(struct iwl_priv *priv) | 1174 | static void iwl4965_unset_hw_params(struct iwl_priv *priv) |
1357 | { | 1175 | { |
1358 | if (priv->hw_setting.shared_virt) | 1176 | if (priv->shared_virt) |
1359 | pci_free_consistent(priv->pci_dev, | 1177 | pci_free_consistent(priv->pci_dev, |
1360 | sizeof(struct iwl4965_shared), | 1178 | sizeof(struct iwl4965_shared), |
1361 | priv->hw_setting.shared_virt, | 1179 | priv->shared_virt, |
1362 | priv->hw_setting.shared_phys); | 1180 | priv->shared_phys); |
1363 | } | 1181 | } |
1364 | 1182 | ||
1365 | /** | 1183 | /** |
@@ -1976,7 +1794,7 @@ static void iwl4965_set_flags_for_phymode(struct iwl_priv *priv, | |||
1976 | | RXON_FLG_CCK_MSK); | 1794 | | RXON_FLG_CCK_MSK); |
1977 | priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; | 1795 | priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; |
1978 | } else { | 1796 | } else { |
1979 | /* Copied from iwl4965_bg_post_associate() */ | 1797 | /* Copied from iwl4965_post_associate() */ |
1980 | if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) | 1798 | if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) |
1981 | priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; | 1799 | priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; |
1982 | else | 1800 | else |
@@ -2115,6 +1933,10 @@ static void iwl4965_build_tx_cmd_hwcrypto(struct iwl_priv *priv, | |||
2115 | int sta_id) | 1933 | int sta_id) |
2116 | { | 1934 | { |
2117 | struct iwl4965_hw_key *keyinfo = &priv->stations[sta_id].keyinfo; | 1935 | struct iwl4965_hw_key *keyinfo = &priv->stations[sta_id].keyinfo; |
1936 | struct iwl_wep_key *wepkey; | ||
1937 | int keyidx = 0; | ||
1938 | |||
1939 | BUG_ON(ctl->key_idx > 3); | ||
2118 | 1940 | ||
2119 | switch (keyinfo->alg) { | 1941 | switch (keyinfo->alg) { |
2120 | case ALG_CCMP: | 1942 | case ALG_CCMP: |
@@ -2133,16 +1955,29 @@ static void iwl4965_build_tx_cmd_hwcrypto(struct iwl_priv *priv, | |||
2133 | break; | 1955 | break; |
2134 | 1956 | ||
2135 | case ALG_WEP: | 1957 | case ALG_WEP: |
2136 | cmd->cmd.tx.sec_ctl = TX_CMD_SEC_WEP | | 1958 | wepkey = &priv->wep_keys[ctl->key_idx]; |
2137 | (ctl->key_idx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT; | 1959 | cmd->cmd.tx.sec_ctl = 0; |
2138 | 1960 | if (priv->default_wep_key) { | |
2139 | if (keyinfo->keylen == 13) | 1961 | /* the WEP key was sent as static */ |
2140 | cmd->cmd.tx.sec_ctl |= TX_CMD_SEC_KEY128; | 1962 | keyidx = ctl->key_idx; |
1963 | memcpy(&cmd->cmd.tx.key[3], wepkey->key, | ||
1964 | wepkey->key_size); | ||
1965 | if (wepkey->key_size == WEP_KEY_LEN_128) | ||
1966 | cmd->cmd.tx.sec_ctl |= TX_CMD_SEC_KEY128; | ||
1967 | } else { | ||
1968 | /* the WEP key was sent as dynamic */ | ||
1969 | keyidx = keyinfo->keyidx; | ||
1970 | memcpy(&cmd->cmd.tx.key[3], keyinfo->key, | ||
1971 | keyinfo->keylen); | ||
1972 | if (keyinfo->keylen == WEP_KEY_LEN_128) | ||
1973 | cmd->cmd.tx.sec_ctl |= TX_CMD_SEC_KEY128; | ||
1974 | } | ||
2141 | 1975 | ||
2142 | memcpy(&cmd->cmd.tx.key[3], keyinfo->key, keyinfo->keylen); | 1976 | cmd->cmd.tx.sec_ctl |= (TX_CMD_SEC_WEP | |
1977 | (keyidx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT); | ||
2143 | 1978 | ||
2144 | IWL_DEBUG_TX("Configuring packet for WEP encryption " | 1979 | IWL_DEBUG_TX("Configuring packet for WEP encryption " |
2145 | "with key %d\n", ctl->key_idx); | 1980 | "with key %d\n", keyidx); |
2146 | break; | 1981 | break; |
2147 | 1982 | ||
2148 | default: | 1983 | default: |
@@ -2240,7 +2075,7 @@ static int iwl4965_get_sta_id(struct iwl_priv *priv, | |||
2240 | /* If this frame is broadcast or management, use broadcast station id */ | 2075 | /* If this frame is broadcast or management, use broadcast station id */ |
2241 | if (((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA) || | 2076 | if (((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA) || |
2242 | is_multicast_ether_addr(hdr->addr1)) | 2077 | is_multicast_ether_addr(hdr->addr1)) |
2243 | return priv->hw_setting.bcast_sta_id; | 2078 | return priv->hw_params.bcast_sta_id; |
2244 | 2079 | ||
2245 | switch (priv->iw_mode) { | 2080 | switch (priv->iw_mode) { |
2246 | 2081 | ||
@@ -2254,7 +2089,7 @@ static int iwl4965_get_sta_id(struct iwl_priv *priv, | |||
2254 | sta_id = iwl4965_hw_find_station(priv, hdr->addr1); | 2089 | sta_id = iwl4965_hw_find_station(priv, hdr->addr1); |
2255 | if (sta_id != IWL_INVALID_STATION) | 2090 | if (sta_id != IWL_INVALID_STATION) |
2256 | return sta_id; | 2091 | return sta_id; |
2257 | return priv->hw_setting.bcast_sta_id; | 2092 | return priv->hw_params.bcast_sta_id; |
2258 | 2093 | ||
2259 | /* If this frame is going out to an IBSS network, find the station, | 2094 | /* If this frame is going out to an IBSS network, find the station, |
2260 | * or create a new station table entry */ | 2095 | * or create a new station table entry */ |
@@ -2274,11 +2109,11 @@ static int iwl4965_get_sta_id(struct iwl_priv *priv, | |||
2274 | "Defaulting to broadcast...\n", | 2109 | "Defaulting to broadcast...\n", |
2275 | print_mac(mac, hdr->addr1)); | 2110 | print_mac(mac, hdr->addr1)); |
2276 | iwl_print_hex_dump(IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr)); | 2111 | iwl_print_hex_dump(IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr)); |
2277 | return priv->hw_setting.bcast_sta_id; | 2112 | return priv->hw_params.bcast_sta_id; |
2278 | 2113 | ||
2279 | default: | 2114 | default: |
2280 | IWL_WARNING("Unknown mode of operation: %d", priv->iw_mode); | 2115 | IWL_WARNING("Unknown mode of operation: %d", priv->iw_mode); |
2281 | return priv->hw_setting.bcast_sta_id; | 2116 | return priv->hw_params.bcast_sta_id; |
2282 | } | 2117 | } |
2283 | } | 2118 | } |
2284 | 2119 | ||
@@ -2425,7 +2260,7 @@ static int iwl4965_tx_skb(struct iwl_priv *priv, | |||
2425 | * of the MAC header (device reads on dword boundaries). | 2260 | * of the MAC header (device reads on dword boundaries). |
2426 | * We'll tell device about this padding later. | 2261 | * We'll tell device about this padding later. |
2427 | */ | 2262 | */ |
2428 | len = priv->hw_setting.tx_cmd_len + | 2263 | len = priv->hw_params.tx_cmd_len + |
2429 | sizeof(struct iwl_cmd_header) + hdr_len; | 2264 | sizeof(struct iwl_cmd_header) + hdr_len; |
2430 | 2265 | ||
2431 | len_org = len; | 2266 | len_org = len; |
@@ -2496,7 +2331,7 @@ static int iwl4965_tx_skb(struct iwl_priv *priv, | |||
2496 | ieee80211_get_hdrlen(fc)); | 2331 | ieee80211_get_hdrlen(fc)); |
2497 | 2332 | ||
2498 | /* Set up entry for this TFD in Tx byte-count array */ | 2333 | /* Set up entry for this TFD in Tx byte-count array */ |
2499 | iwl4965_tx_queue_update_wr_ptr(priv, txq, len); | 2334 | priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq, len); |
2500 | 2335 | ||
2501 | /* Tell device the write index *just past* this latest filled TFD */ | 2336 | /* Tell device the write index *just past* this latest filled TFD */ |
2502 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); | 2337 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); |
@@ -2592,7 +2427,8 @@ void iwl4965_radio_kill_sw(struct iwl_priv *priv, int disable_radio) | |||
2592 | CSR_UCODE_SW_BIT_RFKILL); | 2427 | CSR_UCODE_SW_BIT_RFKILL); |
2593 | spin_unlock_irqrestore(&priv->lock, flags); | 2428 | spin_unlock_irqrestore(&priv->lock, flags); |
2594 | /* call the host command only if no hw rf-kill set */ | 2429 | /* call the host command only if no hw rf-kill set */ |
2595 | if (!test_bit(STATUS_RF_KILL_HW, &priv->status)) | 2430 | if (!test_bit(STATUS_RF_KILL_HW, &priv->status) && |
2431 | iwl_is_ready(priv)) | ||
2596 | iwl4965_send_card_state(priv, | 2432 | iwl4965_send_card_state(priv, |
2597 | CARD_STATE_CMD_DISABLE, | 2433 | CARD_STATE_CMD_DISABLE, |
2598 | 0); | 2434 | 0); |
@@ -3852,7 +3688,7 @@ static void iwl4965_rx_allocate(struct iwl_priv *priv) | |||
3852 | 3688 | ||
3853 | /* Alloc a new receive buffer */ | 3689 | /* Alloc a new receive buffer */ |
3854 | rxb->skb = | 3690 | rxb->skb = |
3855 | alloc_skb(priv->hw_setting.rx_buf_size, | 3691 | alloc_skb(priv->hw_params.rx_buf_size, |
3856 | __GFP_NOWARN | GFP_ATOMIC); | 3692 | __GFP_NOWARN | GFP_ATOMIC); |
3857 | if (!rxb->skb) { | 3693 | if (!rxb->skb) { |
3858 | if (net_ratelimit()) | 3694 | if (net_ratelimit()) |
@@ -3869,7 +3705,7 @@ static void iwl4965_rx_allocate(struct iwl_priv *priv) | |||
3869 | /* Get physical address of RB/SKB */ | 3705 | /* Get physical address of RB/SKB */ |
3870 | rxb->dma_addr = | 3706 | rxb->dma_addr = |
3871 | pci_map_single(priv->pci_dev, rxb->skb->data, | 3707 | pci_map_single(priv->pci_dev, rxb->skb->data, |
3872 | priv->hw_setting.rx_buf_size, PCI_DMA_FROMDEVICE); | 3708 | priv->hw_params.rx_buf_size, PCI_DMA_FROMDEVICE); |
3873 | list_add_tail(&rxb->list, &rxq->rx_free); | 3709 | list_add_tail(&rxb->list, &rxq->rx_free); |
3874 | rxq->free_count++; | 3710 | rxq->free_count++; |
3875 | } | 3711 | } |
@@ -3912,7 +3748,7 @@ static void iwl4965_rx_queue_free(struct iwl_priv *priv, struct iwl4965_rx_queue | |||
3912 | if (rxq->pool[i].skb != NULL) { | 3748 | if (rxq->pool[i].skb != NULL) { |
3913 | pci_unmap_single(priv->pci_dev, | 3749 | pci_unmap_single(priv->pci_dev, |
3914 | rxq->pool[i].dma_addr, | 3750 | rxq->pool[i].dma_addr, |
3915 | priv->hw_setting.rx_buf_size, | 3751 | priv->hw_params.rx_buf_size, |
3916 | PCI_DMA_FROMDEVICE); | 3752 | PCI_DMA_FROMDEVICE); |
3917 | dev_kfree_skb(rxq->pool[i].skb); | 3753 | dev_kfree_skb(rxq->pool[i].skb); |
3918 | } | 3754 | } |
@@ -3964,7 +3800,7 @@ void iwl4965_rx_queue_reset(struct iwl_priv *priv, struct iwl4965_rx_queue *rxq) | |||
3964 | if (rxq->pool[i].skb != NULL) { | 3800 | if (rxq->pool[i].skb != NULL) { |
3965 | pci_unmap_single(priv->pci_dev, | 3801 | pci_unmap_single(priv->pci_dev, |
3966 | rxq->pool[i].dma_addr, | 3802 | rxq->pool[i].dma_addr, |
3967 | priv->hw_setting.rx_buf_size, | 3803 | priv->hw_params.rx_buf_size, |
3968 | PCI_DMA_FROMDEVICE); | 3804 | PCI_DMA_FROMDEVICE); |
3969 | priv->alloc_rxb_skb--; | 3805 | priv->alloc_rxb_skb--; |
3970 | dev_kfree_skb(rxq->pool[i].skb); | 3806 | dev_kfree_skb(rxq->pool[i].skb); |
@@ -4099,7 +3935,7 @@ static void iwl4965_rx_handle(struct iwl_priv *priv) | |||
4099 | rxq->queue[i] = NULL; | 3935 | rxq->queue[i] = NULL; |
4100 | 3936 | ||
4101 | pci_dma_sync_single_for_cpu(priv->pci_dev, rxb->dma_addr, | 3937 | pci_dma_sync_single_for_cpu(priv->pci_dev, rxb->dma_addr, |
4102 | priv->hw_setting.rx_buf_size, | 3938 | priv->hw_params.rx_buf_size, |
4103 | PCI_DMA_FROMDEVICE); | 3939 | PCI_DMA_FROMDEVICE); |
4104 | pkt = (struct iwl4965_rx_packet *)rxb->skb->data; | 3940 | pkt = (struct iwl4965_rx_packet *)rxb->skb->data; |
4105 | 3941 | ||
@@ -4152,7 +3988,7 @@ static void iwl4965_rx_handle(struct iwl_priv *priv) | |||
4152 | } | 3988 | } |
4153 | 3989 | ||
4154 | pci_unmap_single(priv->pci_dev, rxb->dma_addr, | 3990 | pci_unmap_single(priv->pci_dev, rxb->dma_addr, |
4155 | priv->hw_setting.rx_buf_size, | 3991 | priv->hw_params.rx_buf_size, |
4156 | PCI_DMA_FROMDEVICE); | 3992 | PCI_DMA_FROMDEVICE); |
4157 | spin_lock_irqsave(&rxq->lock, flags); | 3993 | spin_lock_irqsave(&rxq->lock, flags); |
4158 | list_add_tail(&rxb->list, &priv->rxq.rx_used); | 3994 | list_add_tail(&rxb->list, &priv->rxq.rx_used); |
@@ -4305,7 +4141,7 @@ static void iwl4965_dump_nic_error_log(struct iwl_priv *priv) | |||
4305 | 4141 | ||
4306 | base = le32_to_cpu(priv->card_alive.error_event_table_ptr); | 4142 | base = le32_to_cpu(priv->card_alive.error_event_table_ptr); |
4307 | 4143 | ||
4308 | if (!iwl4965_hw_valid_rtc_data_addr(base)) { | 4144 | if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { |
4309 | IWL_ERROR("Not valid error log pointer 0x%08X\n", base); | 4145 | IWL_ERROR("Not valid error log pointer 0x%08X\n", base); |
4310 | return; | 4146 | return; |
4311 | } | 4147 | } |
@@ -4400,7 +4236,7 @@ static void iwl4965_dump_nic_event_log(struct iwl_priv *priv) | |||
4400 | u32 size; /* # entries that we'll print */ | 4236 | u32 size; /* # entries that we'll print */ |
4401 | 4237 | ||
4402 | base = le32_to_cpu(priv->card_alive.log_event_table_ptr); | 4238 | base = le32_to_cpu(priv->card_alive.log_event_table_ptr); |
4403 | if (!iwl4965_hw_valid_rtc_data_addr(base)) { | 4239 | if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { |
4404 | IWL_ERROR("Invalid event log pointer 0x%08X\n", base); | 4240 | IWL_ERROR("Invalid event log pointer 0x%08X\n", base); |
4405 | return; | 4241 | return; |
4406 | } | 4242 | } |
@@ -5175,156 +5011,6 @@ static int iwl4965_verify_ucode(struct iwl_priv *priv) | |||
5175 | return rc; | 5011 | return rc; |
5176 | } | 5012 | } |
5177 | 5013 | ||
5178 | |||
5179 | /* check contents of special bootstrap uCode SRAM */ | ||
5180 | static int iwl4965_verify_bsm(struct iwl_priv *priv) | ||
5181 | { | ||
5182 | __le32 *image = priv->ucode_boot.v_addr; | ||
5183 | u32 len = priv->ucode_boot.len; | ||
5184 | u32 reg; | ||
5185 | u32 val; | ||
5186 | |||
5187 | IWL_DEBUG_INFO("Begin verify bsm\n"); | ||
5188 | |||
5189 | /* verify BSM SRAM contents */ | ||
5190 | val = iwl_read_prph(priv, BSM_WR_DWCOUNT_REG); | ||
5191 | for (reg = BSM_SRAM_LOWER_BOUND; | ||
5192 | reg < BSM_SRAM_LOWER_BOUND + len; | ||
5193 | reg += sizeof(u32), image ++) { | ||
5194 | val = iwl_read_prph(priv, reg); | ||
5195 | if (val != le32_to_cpu(*image)) { | ||
5196 | IWL_ERROR("BSM uCode verification failed at " | ||
5197 | "addr 0x%08X+%u (of %u), is 0x%x, s/b 0x%x\n", | ||
5198 | BSM_SRAM_LOWER_BOUND, | ||
5199 | reg - BSM_SRAM_LOWER_BOUND, len, | ||
5200 | val, le32_to_cpu(*image)); | ||
5201 | return -EIO; | ||
5202 | } | ||
5203 | } | ||
5204 | |||
5205 | IWL_DEBUG_INFO("BSM bootstrap uCode image OK\n"); | ||
5206 | |||
5207 | return 0; | ||
5208 | } | ||
5209 | |||
5210 | /** | ||
5211 | * iwl4965_load_bsm - Load bootstrap instructions | ||
5212 | * | ||
5213 | * BSM operation: | ||
5214 | * | ||
5215 | * The Bootstrap State Machine (BSM) stores a short bootstrap uCode program | ||
5216 | * in special SRAM that does not power down during RFKILL. When powering back | ||
5217 | * up after power-saving sleeps (or during initial uCode load), the BSM loads | ||
5218 | * the bootstrap program into the on-board processor, and starts it. | ||
5219 | * | ||
5220 | * The bootstrap program loads (via DMA) instructions and data for a new | ||
5221 | * program from host DRAM locations indicated by the host driver in the | ||
5222 | * BSM_DRAM_* registers. Once the new program is loaded, it starts | ||
5223 | * automatically. | ||
5224 | * | ||
5225 | * When initializing the NIC, the host driver points the BSM to the | ||
5226 | * "initialize" uCode image. This uCode sets up some internal data, then | ||
5227 | * notifies host via "initialize alive" that it is complete. | ||
5228 | * | ||
5229 | * The host then replaces the BSM_DRAM_* pointer values to point to the | ||
5230 | * normal runtime uCode instructions and a backup uCode data cache buffer | ||
5231 | * (filled initially with starting data values for the on-board processor), | ||
5232 | * then triggers the "initialize" uCode to load and launch the runtime uCode, | ||
5233 | * which begins normal operation. | ||
5234 | * | ||
5235 | * When doing a power-save shutdown, runtime uCode saves data SRAM into | ||
5236 | * the backup data cache in DRAM before SRAM is powered down. | ||
5237 | * | ||
5238 | * When powering back up, the BSM loads the bootstrap program. This reloads | ||
5239 | * the runtime uCode instructions and the backup data cache into SRAM, | ||
5240 | * and re-launches the runtime uCode from where it left off. | ||
5241 | */ | ||
5242 | static int iwl4965_load_bsm(struct iwl_priv *priv) | ||
5243 | { | ||
5244 | __le32 *image = priv->ucode_boot.v_addr; | ||
5245 | u32 len = priv->ucode_boot.len; | ||
5246 | dma_addr_t pinst; | ||
5247 | dma_addr_t pdata; | ||
5248 | u32 inst_len; | ||
5249 | u32 data_len; | ||
5250 | int rc; | ||
5251 | int i; | ||
5252 | u32 done; | ||
5253 | u32 reg_offset; | ||
5254 | |||
5255 | IWL_DEBUG_INFO("Begin load bsm\n"); | ||
5256 | |||
5257 | /* make sure bootstrap program is no larger than BSM's SRAM size */ | ||
5258 | if (len > IWL_MAX_BSM_SIZE) | ||
5259 | return -EINVAL; | ||
5260 | |||
5261 | /* Tell bootstrap uCode where to find the "Initialize" uCode | ||
5262 | * in host DRAM ... host DRAM physical address bits 35:4 for 4965. | ||
5263 | * NOTE: iwl4965_initialize_alive_start() will replace these values, | ||
5264 | * after the "initialize" uCode has run, to point to | ||
5265 | * runtime/protocol instructions and backup data cache. */ | ||
5266 | pinst = priv->ucode_init.p_addr >> 4; | ||
5267 | pdata = priv->ucode_init_data.p_addr >> 4; | ||
5268 | inst_len = priv->ucode_init.len; | ||
5269 | data_len = priv->ucode_init_data.len; | ||
5270 | |||
5271 | rc = iwl_grab_nic_access(priv); | ||
5272 | if (rc) | ||
5273 | return rc; | ||
5274 | |||
5275 | iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst); | ||
5276 | iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata); | ||
5277 | iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len); | ||
5278 | iwl_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG, data_len); | ||
5279 | |||
5280 | /* Fill BSM memory with bootstrap instructions */ | ||
5281 | for (reg_offset = BSM_SRAM_LOWER_BOUND; | ||
5282 | reg_offset < BSM_SRAM_LOWER_BOUND + len; | ||
5283 | reg_offset += sizeof(u32), image++) | ||
5284 | _iwl_write_prph(priv, reg_offset, | ||
5285 | le32_to_cpu(*image)); | ||
5286 | |||
5287 | rc = iwl4965_verify_bsm(priv); | ||
5288 | if (rc) { | ||
5289 | iwl_release_nic_access(priv); | ||
5290 | return rc; | ||
5291 | } | ||
5292 | |||
5293 | /* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */ | ||
5294 | iwl_write_prph(priv, BSM_WR_MEM_SRC_REG, 0x0); | ||
5295 | iwl_write_prph(priv, BSM_WR_MEM_DST_REG, | ||
5296 | RTC_INST_LOWER_BOUND); | ||
5297 | iwl_write_prph(priv, BSM_WR_DWCOUNT_REG, len / sizeof(u32)); | ||
5298 | |||
5299 | /* Load bootstrap code into instruction SRAM now, | ||
5300 | * to prepare to load "initialize" uCode */ | ||
5301 | iwl_write_prph(priv, BSM_WR_CTRL_REG, | ||
5302 | BSM_WR_CTRL_REG_BIT_START); | ||
5303 | |||
5304 | /* Wait for load of bootstrap uCode to finish */ | ||
5305 | for (i = 0; i < 100; i++) { | ||
5306 | done = iwl_read_prph(priv, BSM_WR_CTRL_REG); | ||
5307 | if (!(done & BSM_WR_CTRL_REG_BIT_START)) | ||
5308 | break; | ||
5309 | udelay(10); | ||
5310 | } | ||
5311 | if (i < 100) | ||
5312 | IWL_DEBUG_INFO("BSM write complete, poll %d iterations\n", i); | ||
5313 | else { | ||
5314 | IWL_ERROR("BSM write did not complete!\n"); | ||
5315 | return -EIO; | ||
5316 | } | ||
5317 | |||
5318 | /* Enable future boot loads whenever power management unit triggers it | ||
5319 | * (e.g. when powering back up after power-save shutdown) */ | ||
5320 | iwl_write_prph(priv, BSM_WR_CTRL_REG, | ||
5321 | BSM_WR_CTRL_REG_BIT_START_EN); | ||
5322 | |||
5323 | iwl_release_nic_access(priv); | ||
5324 | |||
5325 | return 0; | ||
5326 | } | ||
5327 | |||
5328 | static void iwl4965_nic_start(struct iwl_priv *priv) | 5014 | static void iwl4965_nic_start(struct iwl_priv *priv) |
5329 | { | 5015 | { |
5330 | /* Remove all resets to allow NIC to operate */ | 5016 | /* Remove all resets to allow NIC to operate */ |
@@ -5634,7 +5320,7 @@ static void iwl4965_init_alive_start(struct iwl_priv *priv) | |||
5634 | */ | 5320 | */ |
5635 | static void iwl4965_alive_start(struct iwl_priv *priv) | 5321 | static void iwl4965_alive_start(struct iwl_priv *priv) |
5636 | { | 5322 | { |
5637 | int rc = 0; | 5323 | int ret = 0; |
5638 | 5324 | ||
5639 | IWL_DEBUG_INFO("Runtime Alive received.\n"); | 5325 | IWL_DEBUG_INFO("Runtime Alive received.\n"); |
5640 | 5326 | ||
@@ -5657,10 +5343,10 @@ static void iwl4965_alive_start(struct iwl_priv *priv) | |||
5657 | 5343 | ||
5658 | iwlcore_clear_stations_table(priv); | 5344 | iwlcore_clear_stations_table(priv); |
5659 | 5345 | ||
5660 | rc = iwl4965_alive_notify(priv); | 5346 | ret = priv->cfg->ops->lib->alive_notify(priv); |
5661 | if (rc) { | 5347 | if (ret) { |
5662 | IWL_WARNING("Could not complete ALIVE transition [ntf]: %d\n", | 5348 | IWL_WARNING("Could not complete ALIVE transition [ntf]: %d\n", |
5663 | rc); | 5349 | ret); |
5664 | goto restart; | 5350 | goto restart; |
5665 | } | 5351 | } |
5666 | 5352 | ||
@@ -5835,7 +5521,8 @@ static void iwl4965_down(struct iwl_priv *priv) | |||
5835 | 5521 | ||
5836 | static int __iwl4965_up(struct iwl_priv *priv) | 5522 | static int __iwl4965_up(struct iwl_priv *priv) |
5837 | { | 5523 | { |
5838 | int rc, i; | 5524 | int i; |
5525 | int ret; | ||
5839 | 5526 | ||
5840 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { | 5527 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { |
5841 | IWL_WARNING("Exit pending; will not bring the NIC up\n"); | 5528 | IWL_WARNING("Exit pending; will not bring the NIC up\n"); |
@@ -5870,10 +5557,10 @@ static int __iwl4965_up(struct iwl_priv *priv) | |||
5870 | iwl_rfkill_set_hw_state(priv); | 5557 | iwl_rfkill_set_hw_state(priv); |
5871 | iwl_write32(priv, CSR_INT, 0xFFFFFFFF); | 5558 | iwl_write32(priv, CSR_INT, 0xFFFFFFFF); |
5872 | 5559 | ||
5873 | rc = iwl4965_hw_nic_init(priv); | 5560 | ret = priv->cfg->ops->lib->hw_nic_init(priv); |
5874 | if (rc) { | 5561 | if (ret) { |
5875 | IWL_ERROR("Unable to int nic\n"); | 5562 | IWL_ERROR("Unable to init nic\n"); |
5876 | return rc; | 5563 | return ret; |
5877 | } | 5564 | } |
5878 | 5565 | ||
5879 | /* make sure rfkill handshake bits are cleared */ | 5566 | /* make sure rfkill handshake bits are cleared */ |
@@ -5906,10 +5593,10 @@ static int __iwl4965_up(struct iwl_priv *priv) | |||
5906 | /* load bootstrap state machine, | 5593 | /* load bootstrap state machine, |
5907 | * load bootstrap program into processor's memory, | 5594 | * load bootstrap program into processor's memory, |
5908 | * prepare to load the "initialize" uCode */ | 5595 | * prepare to load the "initialize" uCode */ |
5909 | rc = iwl4965_load_bsm(priv); | 5596 | ret = priv->cfg->ops->lib->load_ucode(priv); |
5910 | 5597 | ||
5911 | if (rc) { | 5598 | if (ret) { |
5912 | IWL_ERROR("Unable to set up bootstrap uCode: %d\n", rc); | 5599 | IWL_ERROR("Unable to set up bootstrap uCode: %d\n", ret); |
5913 | continue; | 5600 | continue; |
5914 | } | 5601 | } |
5915 | 5602 | ||
@@ -6146,7 +5833,7 @@ static void iwl4965_bg_request_scan(struct work_struct *data) | |||
6146 | } | 5833 | } |
6147 | 5834 | ||
6148 | scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; | 5835 | scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; |
6149 | scan->tx_cmd.sta_id = priv->hw_setting.bcast_sta_id; | 5836 | scan->tx_cmd.sta_id = priv->hw_params.bcast_sta_id; |
6150 | scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; | 5837 | scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; |
6151 | 5838 | ||
6152 | 5839 | ||
@@ -6272,10 +5959,8 @@ static void iwl4965_bg_rx_replenish(struct work_struct *data) | |||
6272 | 5959 | ||
6273 | #define IWL_DELAY_NEXT_SCAN (HZ*2) | 5960 | #define IWL_DELAY_NEXT_SCAN (HZ*2) |
6274 | 5961 | ||
6275 | static void iwl4965_bg_post_associate(struct work_struct *data) | 5962 | static void iwl4965_post_associate(struct iwl_priv *priv) |
6276 | { | 5963 | { |
6277 | struct iwl_priv *priv = container_of(data, struct iwl_priv, | ||
6278 | post_associate.work); | ||
6279 | struct ieee80211_conf *conf = NULL; | 5964 | struct ieee80211_conf *conf = NULL; |
6280 | int ret = 0; | 5965 | int ret = 0; |
6281 | DECLARE_MAC_BUF(mac); | 5966 | DECLARE_MAC_BUF(mac); |
@@ -6293,12 +5978,10 @@ static void iwl4965_bg_post_associate(struct work_struct *data) | |||
6293 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 5978 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
6294 | return; | 5979 | return; |
6295 | 5980 | ||
6296 | mutex_lock(&priv->mutex); | ||
6297 | 5981 | ||
6298 | if (!priv->vif || !priv->is_open) { | 5982 | if (!priv->vif || !priv->is_open) |
6299 | mutex_unlock(&priv->mutex); | ||
6300 | return; | 5983 | return; |
6301 | } | 5984 | |
6302 | iwl4965_scan_cancel_timeout(priv, 200); | 5985 | iwl4965_scan_cancel_timeout(priv, 200); |
6303 | 5986 | ||
6304 | conf = ieee80211_get_hw_conf(priv->hw); | 5987 | conf = ieee80211_get_hw_conf(priv->hw); |
@@ -6382,7 +6065,18 @@ static void iwl4965_bg_post_associate(struct work_struct *data) | |||
6382 | 6065 | ||
6383 | /* we have just associated, don't start scan too early */ | 6066 | /* we have just associated, don't start scan too early */ |
6384 | priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN; | 6067 | priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN; |
6068 | } | ||
6069 | |||
6070 | |||
6071 | static void iwl4965_bg_post_associate(struct work_struct *data) | ||
6072 | { | ||
6073 | struct iwl_priv *priv = container_of(data, struct iwl_priv, | ||
6074 | post_associate.work); | ||
6075 | |||
6076 | mutex_lock(&priv->mutex); | ||
6077 | iwl4965_post_associate(priv); | ||
6385 | mutex_unlock(&priv->mutex); | 6078 | mutex_unlock(&priv->mutex); |
6079 | |||
6386 | } | 6080 | } |
6387 | 6081 | ||
6388 | static void iwl4965_bg_abort_scan(struct work_struct *work) | 6082 | static void iwl4965_bg_abort_scan(struct work_struct *work) |
@@ -7004,6 +6698,10 @@ static void iwl4965_bss_info_changed(struct ieee80211_hw *hw, | |||
7004 | 6698 | ||
7005 | if (changes & BSS_CHANGED_ASSOC) { | 6699 | if (changes & BSS_CHANGED_ASSOC) { |
7006 | IWL_DEBUG_MAC80211("ASSOC %d\n", bss_conf->assoc); | 6700 | IWL_DEBUG_MAC80211("ASSOC %d\n", bss_conf->assoc); |
6701 | /* This should never happen as this function should | ||
6702 | * never be called from interrupt context. */ | ||
6703 | if (WARN_ON_ONCE(in_interrupt())) | ||
6704 | return; | ||
7007 | if (bss_conf->assoc) { | 6705 | if (bss_conf->assoc) { |
7008 | priv->assoc_id = bss_conf->aid; | 6706 | priv->assoc_id = bss_conf->aid; |
7009 | priv->beacon_int = bss_conf->beacon_int; | 6707 | priv->beacon_int = bss_conf->beacon_int; |
@@ -7011,14 +6709,16 @@ static void iwl4965_bss_info_changed(struct ieee80211_hw *hw, | |||
7011 | priv->assoc_capability = bss_conf->assoc_capability; | 6709 | priv->assoc_capability = bss_conf->assoc_capability; |
7012 | priv->next_scan_jiffies = jiffies + | 6710 | priv->next_scan_jiffies = jiffies + |
7013 | IWL_DELAY_NEXT_SCAN_AFTER_ASSOC; | 6711 | IWL_DELAY_NEXT_SCAN_AFTER_ASSOC; |
7014 | queue_work(priv->workqueue, &priv->post_associate.work); | 6712 | mutex_lock(&priv->mutex); |
6713 | iwl4965_post_associate(priv); | ||
6714 | mutex_unlock(&priv->mutex); | ||
7015 | } else { | 6715 | } else { |
7016 | priv->assoc_id = 0; | 6716 | priv->assoc_id = 0; |
7017 | IWL_DEBUG_MAC80211("DISASSOC %d\n", bss_conf->assoc); | 6717 | IWL_DEBUG_MAC80211("DISASSOC %d\n", bss_conf->assoc); |
7018 | } | 6718 | } |
7019 | } else if (changes && iwl_is_associated(priv) && priv->assoc_id) { | 6719 | } else if (changes && iwl_is_associated(priv) && priv->assoc_id) { |
7020 | IWL_DEBUG_MAC80211("Associated Changes %d\n", changes); | 6720 | IWL_DEBUG_MAC80211("Associated Changes %d\n", changes); |
7021 | iwl4965_send_rxon_assoc(priv); | 6721 | iwl_send_rxon_assoc(priv); |
7022 | } | 6722 | } |
7023 | 6723 | ||
7024 | } | 6724 | } |
@@ -7106,13 +6806,11 @@ static void iwl4965_mac_update_tkip_key(struct ieee80211_hw *hw, | |||
7106 | key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); | 6806 | key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); |
7107 | key_flags &= ~STA_KEY_FLG_INVALID; | 6807 | key_flags &= ~STA_KEY_FLG_INVALID; |
7108 | 6808 | ||
7109 | if (sta_id == priv->hw_setting.bcast_sta_id) | 6809 | if (sta_id == priv->hw_params.bcast_sta_id) |
7110 | key_flags |= STA_KEY_MULTICAST_MSK; | 6810 | key_flags |= STA_KEY_MULTICAST_MSK; |
7111 | 6811 | ||
7112 | spin_lock_irqsave(&priv->sta_lock, flags); | 6812 | spin_lock_irqsave(&priv->sta_lock, flags); |
7113 | 6813 | ||
7114 | priv->stations[sta_id].sta.key.key_offset = | ||
7115 | (sta_id % STA_KEY_MAX_NUM);/* FIXME */ | ||
7116 | priv->stations[sta_id].sta.key.key_flags = key_flags; | 6814 | priv->stations[sta_id].sta.key.key_flags = key_flags; |
7117 | priv->stations[sta_id].sta.key.tkip_rx_tsc_byte2 = (u8) iv32; | 6815 | priv->stations[sta_id].sta.key.tkip_rx_tsc_byte2 = (u8) iv32; |
7118 | 6816 | ||
@@ -7138,11 +6836,11 @@ static int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
7138 | DECLARE_MAC_BUF(mac); | 6836 | DECLARE_MAC_BUF(mac); |
7139 | int ret = 0; | 6837 | int ret = 0; |
7140 | u8 sta_id = IWL_INVALID_STATION; | 6838 | u8 sta_id = IWL_INVALID_STATION; |
7141 | u8 static_key; | 6839 | u8 is_default_wep_key = 0; |
7142 | 6840 | ||
7143 | IWL_DEBUG_MAC80211("enter\n"); | 6841 | IWL_DEBUG_MAC80211("enter\n"); |
7144 | 6842 | ||
7145 | if (!priv->cfg->mod_params->hw_crypto) { | 6843 | if (priv->cfg->mod_params->sw_crypto) { |
7146 | IWL_DEBUG_MAC80211("leave - hwcrypto disabled\n"); | 6844 | IWL_DEBUG_MAC80211("leave - hwcrypto disabled\n"); |
7147 | return -EOPNOTSUPP; | 6845 | return -EOPNOTSUPP; |
7148 | } | 6846 | } |
@@ -7151,35 +6849,44 @@ static int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
7151 | /* only support pairwise keys */ | 6849 | /* only support pairwise keys */ |
7152 | return -EOPNOTSUPP; | 6850 | return -EOPNOTSUPP; |
7153 | 6851 | ||
7154 | /* FIXME: need to differenciate between static and dynamic key | 6852 | sta_id = iwl4965_hw_find_station(priv, addr); |
7155 | * in the level of mac80211 */ | 6853 | if (sta_id == IWL_INVALID_STATION) { |
7156 | static_key = !iwl_is_associated(priv); | 6854 | IWL_DEBUG_MAC80211("leave - %s not in station map.\n", |
6855 | print_mac(mac, addr)); | ||
6856 | return -EINVAL; | ||
7157 | 6857 | ||
7158 | if (!static_key) { | ||
7159 | sta_id = iwl4965_hw_find_station(priv, addr); | ||
7160 | if (sta_id == IWL_INVALID_STATION) { | ||
7161 | IWL_DEBUG_MAC80211("leave - %s not in station map.\n", | ||
7162 | print_mac(mac, addr)); | ||
7163 | return -EINVAL; | ||
7164 | } | ||
7165 | } | 6858 | } |
7166 | 6859 | ||
6860 | mutex_lock(&priv->mutex); | ||
7167 | iwl4965_scan_cancel_timeout(priv, 100); | 6861 | iwl4965_scan_cancel_timeout(priv, 100); |
6862 | mutex_unlock(&priv->mutex); | ||
6863 | |||
6864 | /* If we are getting WEP group key and we didn't receive any key mapping | ||
6865 | * so far, we are in legacy wep mode (group key only), otherwise we are | ||
6866 | * in 1X mode. | ||
6867 | * In legacy wep mode, we use another host command to the uCode */ | ||
6868 | if (key->alg == ALG_WEP && sta_id == priv->hw_params.bcast_sta_id && | ||
6869 | priv->iw_mode != IEEE80211_IF_TYPE_AP) { | ||
6870 | if (cmd == SET_KEY) | ||
6871 | is_default_wep_key = !priv->key_mapping_key; | ||
6872 | else | ||
6873 | is_default_wep_key = priv->default_wep_key; | ||
6874 | } | ||
7168 | 6875 | ||
7169 | switch (cmd) { | 6876 | switch (cmd) { |
7170 | case SET_KEY: | 6877 | case SET_KEY: |
7171 | if (static_key) | 6878 | if (is_default_wep_key) |
7172 | ret = iwl4965_set_static_key(priv, key); | 6879 | ret = iwl_set_default_wep_key(priv, key); |
7173 | else | 6880 | else |
7174 | ret = iwl4965_set_dynamic_key(priv, key, sta_id); | 6881 | ret = iwl_set_dynamic_key(priv, key, sta_id); |
7175 | 6882 | ||
7176 | IWL_DEBUG_MAC80211("enable hwcrypto key\n"); | 6883 | IWL_DEBUG_MAC80211("enable hwcrypto key\n"); |
7177 | break; | 6884 | break; |
7178 | case DISABLE_KEY: | 6885 | case DISABLE_KEY: |
7179 | if (static_key) | 6886 | if (is_default_wep_key) |
7180 | ret = iwl4965_remove_static_key(priv); | 6887 | ret = iwl_remove_default_wep_key(priv, key); |
7181 | else | 6888 | else |
7182 | ret = iwl4965_clear_sta_key_info(priv, sta_id); | 6889 | ret = iwl_remove_dynamic_key(priv, sta_id); |
7183 | 6890 | ||
7184 | IWL_DEBUG_MAC80211("disable hwcrypto key\n"); | 6891 | IWL_DEBUG_MAC80211("disable hwcrypto key\n"); |
7185 | break; | 6892 | break; |
@@ -7776,7 +7483,7 @@ static ssize_t show_statistics(struct device *d, | |||
7776 | return -EAGAIN; | 7483 | return -EAGAIN; |
7777 | 7484 | ||
7778 | mutex_lock(&priv->mutex); | 7485 | mutex_lock(&priv->mutex); |
7779 | rc = iwl4965_send_statistics_request(priv); | 7486 | rc = iwl_send_statistics_request(priv, 0); |
7780 | mutex_unlock(&priv->mutex); | 7487 | mutex_unlock(&priv->mutex); |
7781 | 7488 | ||
7782 | if (rc) { | 7489 | if (rc) { |
@@ -8084,8 +7791,8 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
8084 | * 5. Setup HW constants | 7791 | * 5. Setup HW constants |
8085 | ************************/ | 7792 | ************************/ |
8086 | /* Device-specific setup */ | 7793 | /* Device-specific setup */ |
8087 | if (iwl4965_hw_set_hw_setting(priv)) { | 7794 | if (priv->cfg->ops->lib->set_hw_params(priv)) { |
8088 | IWL_ERROR("failed to set hw settings\n"); | 7795 | IWL_ERROR("failed to set hw parameters\n"); |
8089 | goto out_iounmap; | 7796 | goto out_iounmap; |
8090 | } | 7797 | } |
8091 | 7798 | ||
@@ -8095,7 +7802,7 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
8095 | 7802 | ||
8096 | err = iwl_setup(priv); | 7803 | err = iwl_setup(priv); |
8097 | if (err) | 7804 | if (err) |
8098 | goto out_unset_hw_settings; | 7805 | goto out_unset_hw_params; |
8099 | /* At this point both hw and priv are initialized. */ | 7806 | /* At this point both hw and priv are initialized. */ |
8100 | 7807 | ||
8101 | /********************************** | 7808 | /********************************** |
@@ -8121,7 +7828,7 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
8121 | err = sysfs_create_group(&pdev->dev.kobj, &iwl4965_attribute_group); | 7828 | err = sysfs_create_group(&pdev->dev.kobj, &iwl4965_attribute_group); |
8122 | if (err) { | 7829 | if (err) { |
8123 | IWL_ERROR("failed to create sysfs device attributes\n"); | 7830 | IWL_ERROR("failed to create sysfs device attributes\n"); |
8124 | goto out_unset_hw_settings; | 7831 | goto out_unset_hw_params; |
8125 | } | 7832 | } |
8126 | 7833 | ||
8127 | err = iwl_dbgfs_register(priv, DRV_NAME); | 7834 | err = iwl_dbgfs_register(priv, DRV_NAME); |
@@ -8145,8 +7852,8 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
8145 | 7852 | ||
8146 | out_remove_sysfs: | 7853 | out_remove_sysfs: |
8147 | sysfs_remove_group(&pdev->dev.kobj, &iwl4965_attribute_group); | 7854 | sysfs_remove_group(&pdev->dev.kobj, &iwl4965_attribute_group); |
8148 | out_unset_hw_settings: | 7855 | out_unset_hw_params: |
8149 | iwl4965_unset_hw_setting(priv); | 7856 | iwl4965_unset_hw_params(priv); |
8150 | out_iounmap: | 7857 | out_iounmap: |
8151 | pci_iounmap(pdev, priv->hw_base); | 7858 | pci_iounmap(pdev, priv->hw_base); |
8152 | out_pci_release_regions: | 7859 | out_pci_release_regions: |
@@ -8208,7 +7915,7 @@ static void __devexit iwl4965_pci_remove(struct pci_dev *pdev) | |||
8208 | iwl4965_rx_queue_free(priv, &priv->rxq); | 7915 | iwl4965_rx_queue_free(priv, &priv->rxq); |
8209 | iwl4965_hw_txq_ctx_free(priv); | 7916 | iwl4965_hw_txq_ctx_free(priv); |
8210 | 7917 | ||
8211 | iwl4965_unset_hw_setting(priv); | 7918 | iwl4965_unset_hw_params(priv); |
8212 | iwlcore_clear_stations_table(priv); | 7919 | iwlcore_clear_stations_table(priv); |
8213 | 7920 | ||
8214 | 7921 | ||
@@ -8273,9 +7980,17 @@ static int iwl4965_pci_resume(struct pci_dev *pdev) | |||
8273 | * | 7980 | * |
8274 | *****************************************************************************/ | 7981 | *****************************************************************************/ |
8275 | 7982 | ||
8276 | static struct pci_driver iwl4965_driver = { | 7983 | /* Hardware specific file defines the PCI IDs table for that hardware module */ |
7984 | static struct pci_device_id iwl_hw_card_ids[] = { | ||
7985 | {IWL_PCI_DEVICE(0x4229, PCI_ANY_ID, iwl4965_agn_cfg)}, | ||
7986 | {IWL_PCI_DEVICE(0x4230, PCI_ANY_ID, iwl4965_agn_cfg)}, | ||
7987 | {0} | ||
7988 | }; | ||
7989 | MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids); | ||
7990 | |||
7991 | static struct pci_driver iwl_driver = { | ||
8277 | .name = DRV_NAME, | 7992 | .name = DRV_NAME, |
8278 | .id_table = iwl4965_hw_card_ids, | 7993 | .id_table = iwl_hw_card_ids, |
8279 | .probe = iwl4965_pci_probe, | 7994 | .probe = iwl4965_pci_probe, |
8280 | .remove = __devexit_p(iwl4965_pci_remove), | 7995 | .remove = __devexit_p(iwl4965_pci_remove), |
8281 | #ifdef CONFIG_PM | 7996 | #ifdef CONFIG_PM |
@@ -8297,13 +8012,13 @@ static int __init iwl4965_init(void) | |||
8297 | return ret; | 8012 | return ret; |
8298 | } | 8013 | } |
8299 | 8014 | ||
8300 | ret = pci_register_driver(&iwl4965_driver); | 8015 | ret = pci_register_driver(&iwl_driver); |
8301 | if (ret) { | 8016 | if (ret) { |
8302 | IWL_ERROR("Unable to initialize PCI module\n"); | 8017 | IWL_ERROR("Unable to initialize PCI module\n"); |
8303 | goto error_register; | 8018 | goto error_register; |
8304 | } | 8019 | } |
8305 | #ifdef CONFIG_IWLWIFI_DEBUG | 8020 | #ifdef CONFIG_IWLWIFI_DEBUG |
8306 | ret = driver_create_file(&iwl4965_driver.driver, &driver_attr_debug_level); | 8021 | ret = driver_create_file(&iwl_driver.driver, &driver_attr_debug_level); |
8307 | if (ret) { | 8022 | if (ret) { |
8308 | IWL_ERROR("Unable to create driver sysfs file\n"); | 8023 | IWL_ERROR("Unable to create driver sysfs file\n"); |
8309 | goto error_debug; | 8024 | goto error_debug; |
@@ -8314,7 +8029,7 @@ static int __init iwl4965_init(void) | |||
8314 | 8029 | ||
8315 | #ifdef CONFIG_IWLWIFI_DEBUG | 8030 | #ifdef CONFIG_IWLWIFI_DEBUG |
8316 | error_debug: | 8031 | error_debug: |
8317 | pci_unregister_driver(&iwl4965_driver); | 8032 | pci_unregister_driver(&iwl_driver); |
8318 | #endif | 8033 | #endif |
8319 | error_register: | 8034 | error_register: |
8320 | iwl4965_rate_control_unregister(); | 8035 | iwl4965_rate_control_unregister(); |
@@ -8324,9 +8039,9 @@ error_register: | |||
8324 | static void __exit iwl4965_exit(void) | 8039 | static void __exit iwl4965_exit(void) |
8325 | { | 8040 | { |
8326 | #ifdef CONFIG_IWLWIFI_DEBUG | 8041 | #ifdef CONFIG_IWLWIFI_DEBUG |
8327 | driver_remove_file(&iwl4965_driver.driver, &driver_attr_debug_level); | 8042 | driver_remove_file(&iwl_driver.driver, &driver_attr_debug_level); |
8328 | #endif | 8043 | #endif |
8329 | pci_unregister_driver(&iwl4965_driver); | 8044 | pci_unregister_driver(&iwl_driver); |
8330 | iwl4965_rate_control_unregister(); | 8045 | iwl4965_rate_control_unregister(); |
8331 | } | 8046 | } |
8332 | 8047 | ||
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index 4a82f5114ca0..6328b9593877 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c | |||
@@ -4,6 +4,7 @@ | |||
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <net/iw_handler.h> | 6 | #include <net/iw_handler.h> |
7 | #include <linux/kfifo.h> | ||
7 | #include "host.h" | 8 | #include "host.h" |
8 | #include "hostcmd.h" | 9 | #include "hostcmd.h" |
9 | #include "decl.h" | 10 | #include "decl.h" |
@@ -295,6 +296,7 @@ int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action, | |||
295 | 296 | ||
296 | lbs_deb_enter(LBS_DEB_CMD); | 297 | lbs_deb_enter(LBS_DEB_CMD); |
297 | 298 | ||
299 | memset(&cmd, 0, sizeof(cmd)); | ||
298 | cmd.hdr.command = cpu_to_le16(CMD_802_11_SET_WEP); | 300 | cmd.hdr.command = cpu_to_le16(CMD_802_11_SET_WEP); |
299 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | 301 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); |
300 | 302 | ||
@@ -358,7 +360,9 @@ int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action, | |||
358 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | 360 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); |
359 | cmd.action = cpu_to_le16(cmd_action); | 361 | cmd.action = cpu_to_le16(cmd_action); |
360 | 362 | ||
361 | if (cmd_action == CMD_ACT_SET) { | 363 | if (cmd_action == CMD_ACT_GET) |
364 | cmd.enable = 0; | ||
365 | else { | ||
362 | if (*enable) | 366 | if (*enable) |
363 | cmd.enable = cpu_to_le16(CMD_ENABLE_RSN); | 367 | cmd.enable = cpu_to_le16(CMD_ENABLE_RSN); |
364 | else | 368 | else |
@@ -810,6 +814,7 @@ int lbs_get_channel(struct lbs_private *priv) | |||
810 | 814 | ||
811 | lbs_deb_enter(LBS_DEB_CMD); | 815 | lbs_deb_enter(LBS_DEB_CMD); |
812 | 816 | ||
817 | memset(&cmd, 0, sizeof(cmd)); | ||
813 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | 818 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); |
814 | cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_GET); | 819 | cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_GET); |
815 | 820 | ||
@@ -857,6 +862,7 @@ int lbs_set_channel(struct lbs_private *priv, u8 channel) | |||
857 | 862 | ||
858 | lbs_deb_enter(LBS_DEB_CMD); | 863 | lbs_deb_enter(LBS_DEB_CMD); |
859 | 864 | ||
865 | memset(&cmd, 0, sizeof(cmd)); | ||
860 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | 866 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); |
861 | cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_SET); | 867 | cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_SET); |
862 | cmd.channel = cpu_to_le16(channel); | 868 | cmd.channel = cpu_to_le16(channel); |
@@ -1829,15 +1835,20 @@ static void lbs_send_confirmsleep(struct lbs_private *priv) | |||
1829 | 1835 | ||
1830 | ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) &confirm_sleep, | 1836 | ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) &confirm_sleep, |
1831 | sizeof(confirm_sleep)); | 1837 | sizeof(confirm_sleep)); |
1832 | |||
1833 | if (ret) { | 1838 | if (ret) { |
1834 | lbs_pr_alert("confirm_sleep failed\n"); | 1839 | lbs_pr_alert("confirm_sleep failed\n"); |
1835 | } else { | 1840 | goto out; |
1836 | spin_lock_irqsave(&priv->driver_lock, flags); | ||
1837 | if (!priv->intcounter) | ||
1838 | priv->psstate = PS_STATE_SLEEP; | ||
1839 | spin_unlock_irqrestore(&priv->driver_lock, flags); | ||
1840 | } | 1841 | } |
1842 | |||
1843 | spin_lock_irqsave(&priv->driver_lock, flags); | ||
1844 | |||
1845 | /* If nothing to do, go back to sleep (?) */ | ||
1846 | if (!__kfifo_len(priv->event_fifo) && !priv->resp_len[priv->resp_idx]) | ||
1847 | priv->psstate = PS_STATE_SLEEP; | ||
1848 | |||
1849 | spin_unlock_irqrestore(&priv->driver_lock, flags); | ||
1850 | |||
1851 | out: | ||
1841 | lbs_deb_leave(LBS_DEB_HOST); | 1852 | lbs_deb_leave(LBS_DEB_HOST); |
1842 | } | 1853 | } |
1843 | 1854 | ||
@@ -1899,13 +1910,16 @@ void lbs_ps_confirm_sleep(struct lbs_private *priv) | |||
1899 | } | 1910 | } |
1900 | 1911 | ||
1901 | spin_lock_irqsave(&priv->driver_lock, flags); | 1912 | spin_lock_irqsave(&priv->driver_lock, flags); |
1913 | /* In-progress command? */ | ||
1902 | if (priv->cur_cmd) { | 1914 | if (priv->cur_cmd) { |
1903 | allowed = 0; | 1915 | allowed = 0; |
1904 | lbs_deb_host("cur_cmd was set\n"); | 1916 | lbs_deb_host("cur_cmd was set\n"); |
1905 | } | 1917 | } |
1906 | if (priv->intcounter > 0) { | 1918 | |
1919 | /* Pending events or command responses? */ | ||
1920 | if (__kfifo_len(priv->event_fifo) || priv->resp_len[priv->resp_idx]) { | ||
1907 | allowed = 0; | 1921 | allowed = 0; |
1908 | lbs_deb_host("intcounter %d\n", priv->intcounter); | 1922 | lbs_deb_host("pending events or command responses\n"); |
1909 | } | 1923 | } |
1910 | spin_unlock_irqrestore(&priv->driver_lock, flags); | 1924 | spin_unlock_irqrestore(&priv->driver_lock, flags); |
1911 | 1925 | ||
diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c index 245d3c3a9274..5abecb7673e6 100644 --- a/drivers/net/wireless/libertas/cmdresp.c +++ b/drivers/net/wireless/libertas/cmdresp.c | |||
@@ -384,7 +384,7 @@ static inline int handle_cmd_response(struct lbs_private *priv, | |||
384 | return ret; | 384 | return ret; |
385 | } | 385 | } |
386 | 386 | ||
387 | int lbs_process_rx_command(struct lbs_private *priv) | 387 | int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len) |
388 | { | 388 | { |
389 | uint16_t respcmd, curcmd; | 389 | uint16_t respcmd, curcmd; |
390 | struct cmd_header *resp; | 390 | struct cmd_header *resp; |
@@ -404,14 +404,14 @@ int lbs_process_rx_command(struct lbs_private *priv) | |||
404 | goto done; | 404 | goto done; |
405 | } | 405 | } |
406 | 406 | ||
407 | resp = (void *)priv->upld_buf; | 407 | resp = (void *)data; |
408 | curcmd = le16_to_cpu(priv->cur_cmd->cmdbuf->command); | 408 | curcmd = le16_to_cpu(priv->cur_cmd->cmdbuf->command); |
409 | respcmd = le16_to_cpu(resp->command); | 409 | respcmd = le16_to_cpu(resp->command); |
410 | result = le16_to_cpu(resp->result); | 410 | result = le16_to_cpu(resp->result); |
411 | 411 | ||
412 | lbs_deb_cmd("CMD_RESP: response 0x%04x, seq %d, size %d\n", | 412 | lbs_deb_cmd("CMD_RESP: response 0x%04x, seq %d, size %d\n", |
413 | respcmd, le16_to_cpu(resp->seqnum), priv->upld_len); | 413 | respcmd, le16_to_cpu(resp->seqnum), len); |
414 | lbs_deb_hex(LBS_DEB_CMD, "CMD_RESP", (void *) resp, priv->upld_len); | 414 | lbs_deb_hex(LBS_DEB_CMD, "CMD_RESP", (void *) resp, len); |
415 | 415 | ||
416 | if (resp->seqnum != priv->cur_cmd->cmdbuf->seqnum) { | 416 | if (resp->seqnum != priv->cur_cmd->cmdbuf->seqnum) { |
417 | lbs_pr_info("Received CMD_RESP with invalid sequence %d (expected %d)\n", | 417 | lbs_pr_info("Received CMD_RESP with invalid sequence %d (expected %d)\n", |
@@ -569,18 +569,13 @@ static int lbs_send_confirmwake(struct lbs_private *priv) | |||
569 | return ret; | 569 | return ret; |
570 | } | 570 | } |
571 | 571 | ||
572 | int lbs_process_event(struct lbs_private *priv) | 572 | int lbs_process_event(struct lbs_private *priv, u32 event) |
573 | { | 573 | { |
574 | int ret = 0; | 574 | int ret = 0; |
575 | u32 eventcause; | ||
576 | 575 | ||
577 | lbs_deb_enter(LBS_DEB_CMD); | 576 | lbs_deb_enter(LBS_DEB_CMD); |
578 | 577 | ||
579 | spin_lock_irq(&priv->driver_lock); | 578 | switch (event) { |
580 | eventcause = priv->eventcause >> SBI_EVENT_CAUSE_SHIFT; | ||
581 | spin_unlock_irq(&priv->driver_lock); | ||
582 | |||
583 | switch (eventcause) { | ||
584 | case MACREG_INT_CODE_LINK_SENSED: | 579 | case MACREG_INT_CODE_LINK_SENSED: |
585 | lbs_deb_cmd("EVENT: link sensed\n"); | 580 | lbs_deb_cmd("EVENT: link sensed\n"); |
586 | break; | 581 | break; |
@@ -696,14 +691,10 @@ int lbs_process_event(struct lbs_private *priv) | |||
696 | break; | 691 | break; |
697 | 692 | ||
698 | default: | 693 | default: |
699 | lbs_pr_alert("EVENT: unknown event id %d\n", eventcause); | 694 | lbs_pr_alert("EVENT: unknown event id %d\n", event); |
700 | break; | 695 | break; |
701 | } | 696 | } |
702 | 697 | ||
703 | spin_lock_irq(&priv->driver_lock); | ||
704 | priv->eventcause = 0; | ||
705 | spin_unlock_irq(&priv->driver_lock); | ||
706 | |||
707 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); | 698 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); |
708 | return ret; | 699 | return ret; |
709 | } | 700 | } |
diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c index 7072e26b42d9..ad2fabca9116 100644 --- a/drivers/net/wireless/libertas/debugfs.c +++ b/drivers/net/wireless/libertas/debugfs.c | |||
@@ -824,7 +824,6 @@ struct debug_data { | |||
824 | /* To debug any member of struct lbs_private, simply add one line here. | 824 | /* To debug any member of struct lbs_private, simply add one line here. |
825 | */ | 825 | */ |
826 | static struct debug_data items[] = { | 826 | static struct debug_data items[] = { |
827 | {"intcounter", item_size(intcounter), item_addr(intcounter)}, | ||
828 | {"psmode", item_size(psmode), item_addr(psmode)}, | 827 | {"psmode", item_size(psmode), item_addr(psmode)}, |
829 | {"psstate", item_size(psstate), item_addr(psstate)}, | 828 | {"psstate", item_size(psstate), item_addr(psstate)}, |
830 | }; | 829 | }; |
diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h index 4aea421f07ce..b652fa301e19 100644 --- a/drivers/net/wireless/libertas/decl.h +++ b/drivers/net/wireless/libertas/decl.h | |||
@@ -19,7 +19,7 @@ struct cmd_ds_command; | |||
19 | 19 | ||
20 | void lbs_set_mac_control(struct lbs_private *priv); | 20 | void lbs_set_mac_control(struct lbs_private *priv); |
21 | 21 | ||
22 | void lbs_send_tx_feedback(struct lbs_private *priv); | 22 | void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count); |
23 | 23 | ||
24 | int lbs_free_cmd_buffer(struct lbs_private *priv); | 24 | int lbs_free_cmd_buffer(struct lbs_private *priv); |
25 | 25 | ||
@@ -30,14 +30,16 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, | |||
30 | 30 | ||
31 | int lbs_allocate_cmd_buffer(struct lbs_private *priv); | 31 | int lbs_allocate_cmd_buffer(struct lbs_private *priv); |
32 | int lbs_execute_next_command(struct lbs_private *priv); | 32 | int lbs_execute_next_command(struct lbs_private *priv); |
33 | int lbs_process_event(struct lbs_private *priv); | 33 | int lbs_process_event(struct lbs_private *priv, u32 event); |
34 | void lbs_interrupt(struct lbs_private *priv); | 34 | void lbs_queue_event(struct lbs_private *priv, u32 event); |
35 | void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx); | ||
36 | |||
35 | int lbs_set_radio_control(struct lbs_private *priv); | 37 | int lbs_set_radio_control(struct lbs_private *priv); |
36 | u32 lbs_fw_index_to_data_rate(u8 index); | 38 | u32 lbs_fw_index_to_data_rate(u8 index); |
37 | u8 lbs_data_rate_to_fw_index(u32 rate); | 39 | u8 lbs_data_rate_to_fw_index(u32 rate); |
38 | 40 | ||
39 | /** The proc fs interface */ | 41 | /** The proc fs interface */ |
40 | int lbs_process_rx_command(struct lbs_private *priv); | 42 | int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len); |
41 | void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd, | 43 | void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd, |
42 | int result); | 44 | int result); |
43 | int lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev); | 45 | int lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev); |
diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h index 84e8de5e21da..d39520111062 100644 --- a/drivers/net/wireless/libertas/defs.h +++ b/drivers/net/wireless/libertas/defs.h | |||
@@ -177,8 +177,6 @@ static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in | |||
177 | #define MRVDRV_CMD_UPLD_RDY 0x0008 | 177 | #define MRVDRV_CMD_UPLD_RDY 0x0008 |
178 | #define MRVDRV_CARDEVENT 0x0010 | 178 | #define MRVDRV_CARDEVENT 0x0010 |
179 | 179 | ||
180 | #define SBI_EVENT_CAUSE_SHIFT 3 | ||
181 | |||
182 | /** TxPD status */ | 180 | /** TxPD status */ |
183 | 181 | ||
184 | /* Station firmware use TxPD status field to report final Tx transmit | 182 | /* Station firmware use TxPD status field to report final Tx transmit |
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index 1e6bae80396b..0d9edb9b11f5 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h | |||
@@ -129,10 +129,6 @@ struct lbs_private { | |||
129 | u32 bbp_offset; | 129 | u32 bbp_offset; |
130 | u32 rf_offset; | 130 | u32 rf_offset; |
131 | 131 | ||
132 | /** Upload length */ | ||
133 | u32 upld_len; | ||
134 | /* Upload buffer */ | ||
135 | u8 upld_buf[LBS_UPLD_SIZE]; | ||
136 | /* Download sent: | 132 | /* Download sent: |
137 | bit0 1/0=data_sent/data_tx_done, | 133 | bit0 1/0=data_sent/data_tx_done, |
138 | bit1 1/0=cmd_sent/cmd_tx_done, | 134 | bit1 1/0=cmd_sent/cmd_tx_done, |
@@ -155,21 +151,16 @@ struct lbs_private { | |||
155 | 151 | ||
156 | /** Hardware access */ | 152 | /** Hardware access */ |
157 | int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb); | 153 | int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb); |
158 | int (*hw_get_int_status) (struct lbs_private *priv, u8 *); | ||
159 | int (*hw_read_event_cause) (struct lbs_private *); | ||
160 | 154 | ||
161 | /* Wake On LAN */ | 155 | /* Wake On LAN */ |
162 | uint32_t wol_criteria; | 156 | uint32_t wol_criteria; |
163 | uint8_t wol_gpio; | 157 | uint8_t wol_gpio; |
164 | uint8_t wol_gap; | 158 | uint8_t wol_gap; |
165 | 159 | ||
166 | /* was struct lbs_adapter from here... */ | ||
167 | |||
168 | /** Wlan adapter data structure*/ | 160 | /** Wlan adapter data structure*/ |
169 | /** STATUS variables */ | 161 | /** STATUS variables */ |
170 | u32 fwrelease; | 162 | u32 fwrelease; |
171 | u32 fwcapinfo; | 163 | u32 fwcapinfo; |
172 | /* protected with big lock */ | ||
173 | 164 | ||
174 | struct mutex lock; | 165 | struct mutex lock; |
175 | 166 | ||
@@ -181,7 +172,6 @@ struct lbs_private { | |||
181 | 172 | ||
182 | /** command-related variables */ | 173 | /** command-related variables */ |
183 | u16 seqnum; | 174 | u16 seqnum; |
184 | /* protected by big lock */ | ||
185 | 175 | ||
186 | struct cmd_ctrl_node *cmd_array; | 176 | struct cmd_ctrl_node *cmd_array; |
187 | /** Current command */ | 177 | /** Current command */ |
@@ -194,12 +184,17 @@ struct lbs_private { | |||
194 | struct list_head cmdpendingq; | 184 | struct list_head cmdpendingq; |
195 | 185 | ||
196 | wait_queue_head_t cmd_pending; | 186 | wait_queue_head_t cmd_pending; |
197 | /* command related variables protected by priv->driver_lock */ | ||
198 | 187 | ||
199 | /** Async and Sync Event variables */ | 188 | /* Command responses sent from the hardware to the driver */ |
200 | u32 intcounter; | 189 | u8 resp_idx; |
201 | u32 eventcause; | 190 | u8 resp_buf[2][LBS_UPLD_SIZE]; |
202 | u8 nodename[16]; /* nickname */ | 191 | u32 resp_len[2]; |
192 | |||
193 | /* Events sent from hardware to driver */ | ||
194 | struct kfifo *event_fifo; | ||
195 | |||
196 | /* nickname */ | ||
197 | u8 nodename[16]; | ||
203 | 198 | ||
204 | /** spin locks */ | 199 | /** spin locks */ |
205 | spinlock_t driver_lock; | 200 | spinlock_t driver_lock; |
@@ -209,8 +204,6 @@ struct lbs_private { | |||
209 | int nr_retries; | 204 | int nr_retries; |
210 | int cmd_timed_out; | 205 | int cmd_timed_out; |
211 | 206 | ||
212 | u8 hisregcpy; | ||
213 | |||
214 | /** current ssid/bssid related parameters*/ | 207 | /** current ssid/bssid related parameters*/ |
215 | struct current_bss_params curbssparams; | 208 | struct current_bss_params curbssparams; |
216 | 209 | ||
diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c index 53afebac7146..54280e292ea5 100644 --- a/drivers/net/wireless/libertas/if_cs.c +++ b/drivers/net/wireless/libertas/if_cs.c | |||
@@ -83,14 +83,14 @@ static inline unsigned int if_cs_read8(struct if_cs_card *card, uint reg) | |||
83 | { | 83 | { |
84 | unsigned int val = ioread8(card->iobase + reg); | 84 | unsigned int val = ioread8(card->iobase + reg); |
85 | if (debug_output) | 85 | if (debug_output) |
86 | printk(KERN_INFO "##inb %08x<%02x\n", reg, val); | 86 | printk(KERN_INFO "inb %08x<%02x\n", reg, val); |
87 | return val; | 87 | return val; |
88 | } | 88 | } |
89 | static inline unsigned int if_cs_read16(struct if_cs_card *card, uint reg) | 89 | static inline unsigned int if_cs_read16(struct if_cs_card *card, uint reg) |
90 | { | 90 | { |
91 | unsigned int val = ioread16(card->iobase + reg); | 91 | unsigned int val = ioread16(card->iobase + reg); |
92 | if (debug_output) | 92 | if (debug_output) |
93 | printk(KERN_INFO "##inw %08x<%04x\n", reg, val); | 93 | printk(KERN_INFO "inw %08x<%04x\n", reg, val); |
94 | return val; | 94 | return val; |
95 | } | 95 | } |
96 | static inline void if_cs_read16_rep( | 96 | static inline void if_cs_read16_rep( |
@@ -100,7 +100,7 @@ static inline void if_cs_read16_rep( | |||
100 | unsigned long count) | 100 | unsigned long count) |
101 | { | 101 | { |
102 | if (debug_output) | 102 | if (debug_output) |
103 | printk(KERN_INFO "##insw %08x<(0x%lx words)\n", | 103 | printk(KERN_INFO "insw %08x<(0x%lx words)\n", |
104 | reg, count); | 104 | reg, count); |
105 | ioread16_rep(card->iobase + reg, buf, count); | 105 | ioread16_rep(card->iobase + reg, buf, count); |
106 | } | 106 | } |
@@ -108,14 +108,14 @@ static inline void if_cs_read16_rep( | |||
108 | static inline void if_cs_write8(struct if_cs_card *card, uint reg, u8 val) | 108 | static inline void if_cs_write8(struct if_cs_card *card, uint reg, u8 val) |
109 | { | 109 | { |
110 | if (debug_output) | 110 | if (debug_output) |
111 | printk(KERN_INFO "##outb %08x>%02x\n", reg, val); | 111 | printk(KERN_INFO "outb %08x>%02x\n", reg, val); |
112 | iowrite8(val, card->iobase + reg); | 112 | iowrite8(val, card->iobase + reg); |
113 | } | 113 | } |
114 | 114 | ||
115 | static inline void if_cs_write16(struct if_cs_card *card, uint reg, u16 val) | 115 | static inline void if_cs_write16(struct if_cs_card *card, uint reg, u16 val) |
116 | { | 116 | { |
117 | if (debug_output) | 117 | if (debug_output) |
118 | printk(KERN_INFO "##outw %08x>%04x\n", reg, val); | 118 | printk(KERN_INFO "outw %08x>%04x\n", reg, val); |
119 | iowrite16(val, card->iobase + reg); | 119 | iowrite16(val, card->iobase + reg); |
120 | } | 120 | } |
121 | 121 | ||
@@ -126,7 +126,7 @@ static inline void if_cs_write16_rep( | |||
126 | unsigned long count) | 126 | unsigned long count) |
127 | { | 127 | { |
128 | if (debug_output) | 128 | if (debug_output) |
129 | printk(KERN_INFO "##outsw %08x>(0x%lx words)\n", | 129 | printk(KERN_INFO "outsw %08x>(0x%lx words)\n", |
130 | reg, count); | 130 | reg, count); |
131 | iowrite16_rep(card->iobase + reg, buf, count); | 131 | iowrite16_rep(card->iobase + reg, buf, count); |
132 | } | 132 | } |
@@ -199,17 +199,6 @@ static int if_cs_poll_while_fw_download(struct if_cs_card *card, uint addr, u8 r | |||
199 | #define IF_CS_C_S_CARDEVENT 0x0010 | 199 | #define IF_CS_C_S_CARDEVENT 0x0010 |
200 | #define IF_CS_C_S_MASK 0x001f | 200 | #define IF_CS_C_S_MASK 0x001f |
201 | #define IF_CS_C_S_STATUS_MASK 0x7f00 | 201 | #define IF_CS_C_S_STATUS_MASK 0x7f00 |
202 | /* The following definitions should be the same as the MRVDRV_ ones */ | ||
203 | |||
204 | #if MRVDRV_CMD_DNLD_RDY != IF_CS_C_S_CMD_DNLD_RDY | ||
205 | #error MRVDRV_CMD_DNLD_RDY and IF_CS_C_S_CMD_DNLD_RDY not in sync | ||
206 | #endif | ||
207 | #if MRVDRV_CMD_UPLD_RDY != IF_CS_C_S_CMD_UPLD_RDY | ||
208 | #error MRVDRV_CMD_UPLD_RDY and IF_CS_C_S_CMD_UPLD_RDY not in sync | ||
209 | #endif | ||
210 | #if MRVDRV_CARDEVENT != IF_CS_C_S_CARDEVENT | ||
211 | #error MRVDRV_CARDEVENT and IF_CS_C_S_CARDEVENT not in sync | ||
212 | #endif | ||
213 | 202 | ||
214 | #define IF_CS_C_INT_CAUSE 0x00000022 | 203 | #define IF_CS_C_INT_CAUSE 0x00000022 |
215 | #define IF_CS_C_IC_MASK 0x001f | 204 | #define IF_CS_C_IC_MASK 0x001f |
@@ -226,55 +215,6 @@ static int if_cs_poll_while_fw_download(struct if_cs_card *card, uint addr, u8 r | |||
226 | 215 | ||
227 | 216 | ||
228 | /********************************************************************/ | 217 | /********************************************************************/ |
229 | /* Interrupts */ | ||
230 | /********************************************************************/ | ||
231 | |||
232 | static inline void if_cs_enable_ints(struct if_cs_card *card) | ||
233 | { | ||
234 | lbs_deb_enter(LBS_DEB_CS); | ||
235 | if_cs_write16(card, IF_CS_H_INT_MASK, 0); | ||
236 | } | ||
237 | |||
238 | static inline void if_cs_disable_ints(struct if_cs_card *card) | ||
239 | { | ||
240 | lbs_deb_enter(LBS_DEB_CS); | ||
241 | if_cs_write16(card, IF_CS_H_INT_MASK, IF_CS_H_IM_MASK); | ||
242 | } | ||
243 | |||
244 | static irqreturn_t if_cs_interrupt(int irq, void *data) | ||
245 | { | ||
246 | struct if_cs_card *card = data; | ||
247 | u16 int_cause; | ||
248 | |||
249 | lbs_deb_enter(LBS_DEB_CS); | ||
250 | |||
251 | int_cause = if_cs_read16(card, IF_CS_C_INT_CAUSE); | ||
252 | if (int_cause == 0x0) { | ||
253 | /* Not for us */ | ||
254 | return IRQ_NONE; | ||
255 | |||
256 | } else if (int_cause == 0xffff) { | ||
257 | /* Read in junk, the card has probably been removed */ | ||
258 | card->priv->surpriseremoved = 1; | ||
259 | return IRQ_HANDLED; | ||
260 | } else { | ||
261 | if (int_cause & IF_CS_H_IC_TX_OVER) | ||
262 | lbs_host_to_card_done(card->priv); | ||
263 | |||
264 | /* clear interrupt */ | ||
265 | if_cs_write16(card, IF_CS_C_INT_CAUSE, int_cause & IF_CS_C_IC_MASK); | ||
266 | } | ||
267 | spin_lock(&card->priv->driver_lock); | ||
268 | lbs_interrupt(card->priv); | ||
269 | spin_unlock(&card->priv->driver_lock); | ||
270 | |||
271 | return IRQ_HANDLED; | ||
272 | } | ||
273 | |||
274 | |||
275 | |||
276 | |||
277 | /********************************************************************/ | ||
278 | /* I/O */ | 218 | /* I/O */ |
279 | /********************************************************************/ | 219 | /********************************************************************/ |
280 | 220 | ||
@@ -351,6 +291,7 @@ static void if_cs_send_data(struct lbs_private *priv, u8 *buf, u16 nb) | |||
351 | */ | 291 | */ |
352 | static int if_cs_receive_cmdres(struct lbs_private *priv, u8 *data, u32 *len) | 292 | static int if_cs_receive_cmdres(struct lbs_private *priv, u8 *data, u32 *len) |
353 | { | 293 | { |
294 | unsigned long flags; | ||
354 | int ret = -1; | 295 | int ret = -1; |
355 | u16 val; | 296 | u16 val; |
356 | 297 | ||
@@ -378,6 +319,12 @@ static int if_cs_receive_cmdres(struct lbs_private *priv, u8 *data, u32 *len) | |||
378 | * bytes */ | 319 | * bytes */ |
379 | *len -= 8; | 320 | *len -= 8; |
380 | ret = 0; | 321 | ret = 0; |
322 | |||
323 | /* Clear this flag again */ | ||
324 | spin_lock_irqsave(&priv->driver_lock, flags); | ||
325 | priv->dnld_sent = DNLD_RES_RECEIVED; | ||
326 | spin_unlock_irqrestore(&priv->driver_lock, flags); | ||
327 | |||
381 | out: | 328 | out: |
382 | lbs_deb_leave_args(LBS_DEB_CS, "ret %d, len %d", ret, *len); | 329 | lbs_deb_leave_args(LBS_DEB_CS, "ret %d, len %d", ret, *len); |
383 | return ret; | 330 | return ret; |
@@ -396,11 +343,9 @@ static struct sk_buff *if_cs_receive_data(struct lbs_private *priv) | |||
396 | if (len == 0 || len > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) { | 343 | if (len == 0 || len > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) { |
397 | lbs_pr_err("card data buffer has invalid # of bytes (%d)\n", len); | 344 | lbs_pr_err("card data buffer has invalid # of bytes (%d)\n", len); |
398 | priv->stats.rx_dropped++; | 345 | priv->stats.rx_dropped++; |
399 | printk(KERN_INFO "##HS %s:%d TODO\n", __FUNCTION__, __LINE__); | ||
400 | goto dat_err; | 346 | goto dat_err; |
401 | } | 347 | } |
402 | 348 | ||
403 | //TODO: skb = dev_alloc_skb(len+ETH_FRAME_LEN+MRVDRV_SNAP_HEADER_LEN+EXTRA_LEN); | ||
404 | skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE + 2); | 349 | skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE + 2); |
405 | if (!skb) | 350 | if (!skb) |
406 | goto out; | 351 | goto out; |
@@ -425,6 +370,96 @@ out: | |||
425 | 370 | ||
426 | 371 | ||
427 | /********************************************************************/ | 372 | /********************************************************************/ |
373 | /* Interrupts */ | ||
374 | /********************************************************************/ | ||
375 | |||
376 | static inline void if_cs_enable_ints(struct if_cs_card *card) | ||
377 | { | ||
378 | lbs_deb_enter(LBS_DEB_CS); | ||
379 | if_cs_write16(card, IF_CS_H_INT_MASK, 0); | ||
380 | } | ||
381 | |||
382 | static inline void if_cs_disable_ints(struct if_cs_card *card) | ||
383 | { | ||
384 | lbs_deb_enter(LBS_DEB_CS); | ||
385 | if_cs_write16(card, IF_CS_H_INT_MASK, IF_CS_H_IM_MASK); | ||
386 | } | ||
387 | |||
388 | |||
389 | static irqreturn_t if_cs_interrupt(int irq, void *data) | ||
390 | { | ||
391 | struct if_cs_card *card = data; | ||
392 | struct lbs_private *priv = card->priv; | ||
393 | u16 cause; | ||
394 | |||
395 | lbs_deb_enter(LBS_DEB_CS); | ||
396 | |||
397 | cause = if_cs_read16(card, IF_CS_C_INT_CAUSE); | ||
398 | if_cs_write16(card, IF_CS_C_INT_CAUSE, cause & IF_CS_C_IC_MASK); | ||
399 | |||
400 | lbs_deb_cs("cause 0x%04x\n", cause); | ||
401 | if (cause == 0) { | ||
402 | /* Not for us */ | ||
403 | return IRQ_NONE; | ||
404 | } | ||
405 | |||
406 | if (cause == 0xffff) { | ||
407 | /* Read in junk, the card has probably been removed */ | ||
408 | card->priv->surpriseremoved = 1; | ||
409 | return IRQ_HANDLED; | ||
410 | } | ||
411 | |||
412 | /* TODO: I'm not sure what the best ordering is */ | ||
413 | |||
414 | cause = if_cs_read16(card, IF_CS_C_STATUS) & IF_CS_C_S_MASK; | ||
415 | |||
416 | if (cause & IF_CS_C_S_RX_UPLD_RDY) { | ||
417 | struct sk_buff *skb; | ||
418 | lbs_deb_cs("rx packet\n"); | ||
419 | skb = if_cs_receive_data(priv); | ||
420 | if (skb) | ||
421 | lbs_process_rxed_packet(priv, skb); | ||
422 | } | ||
423 | |||
424 | if (cause & IF_CS_H_IC_TX_OVER) { | ||
425 | lbs_deb_cs("tx over\n"); | ||
426 | lbs_host_to_card_done(priv); | ||
427 | } | ||
428 | |||
429 | if (cause & IF_CS_C_S_CMD_UPLD_RDY) { | ||
430 | unsigned long flags; | ||
431 | u8 i; | ||
432 | |||
433 | lbs_deb_cs("cmd upload ready\n"); | ||
434 | spin_lock_irqsave(&priv->driver_lock, flags); | ||
435 | i = (priv->resp_idx == 0) ? 1 : 0; | ||
436 | spin_unlock_irqrestore(&priv->driver_lock, flags); | ||
437 | |||
438 | BUG_ON(priv->resp_len[i]); | ||
439 | if_cs_receive_cmdres(priv, priv->resp_buf[i], | ||
440 | &priv->resp_len[i]); | ||
441 | |||
442 | spin_lock_irqsave(&priv->driver_lock, flags); | ||
443 | lbs_notify_command_response(priv, i); | ||
444 | spin_unlock_irqrestore(&priv->driver_lock, flags); | ||
445 | } | ||
446 | |||
447 | if (cause & IF_CS_H_IC_HOST_EVENT) { | ||
448 | u16 event = if_cs_read16(priv->card, IF_CS_C_STATUS) | ||
449 | & IF_CS_C_S_STATUS_MASK; | ||
450 | if_cs_write16(priv->card, IF_CS_H_INT_CAUSE, | ||
451 | IF_CS_H_IC_HOST_EVENT); | ||
452 | lbs_deb_cs("eventcause 0x%04x\n", event); | ||
453 | lbs_queue_event(priv, event >> 8 & 0xff); | ||
454 | } | ||
455 | |||
456 | return IRQ_HANDLED; | ||
457 | } | ||
458 | |||
459 | |||
460 | |||
461 | |||
462 | /********************************************************************/ | ||
428 | /* Firmware */ | 463 | /* Firmware */ |
429 | /********************************************************************/ | 464 | /********************************************************************/ |
430 | 465 | ||
@@ -476,8 +511,6 @@ static int if_cs_prog_helper(struct if_cs_card *card) | |||
476 | 511 | ||
477 | if (remain < count) | 512 | if (remain < count) |
478 | count = remain; | 513 | count = remain; |
479 | /* printk(KERN_INFO "//HS %d loading %d of %d bytes\n", | ||
480 | __LINE__, sent, fw->size); */ | ||
481 | 514 | ||
482 | /* "write the number of bytes to be sent to the I/O Command | 515 | /* "write the number of bytes to be sent to the I/O Command |
483 | * write length register" */ | 516 | * write length register" */ |
@@ -544,18 +577,12 @@ static int if_cs_prog_real(struct if_cs_card *card) | |||
544 | 577 | ||
545 | ret = if_cs_poll_while_fw_download(card, IF_CS_C_SQ_READ_LOW, IF_CS_C_SQ_HELPER_OK); | 578 | ret = if_cs_poll_while_fw_download(card, IF_CS_C_SQ_READ_LOW, IF_CS_C_SQ_HELPER_OK); |
546 | if (ret < 0) { | 579 | if (ret < 0) { |
547 | int i; | ||
548 | lbs_pr_err("helper firmware doesn't answer\n"); | 580 | lbs_pr_err("helper firmware doesn't answer\n"); |
549 | for (i = 0; i < 0x50; i += 2) | ||
550 | printk(KERN_INFO "## HS %02x: %04x\n", | ||
551 | i, if_cs_read16(card, i)); | ||
552 | goto err_release; | 581 | goto err_release; |
553 | } | 582 | } |
554 | 583 | ||
555 | for (sent = 0; sent < fw->size; sent += len) { | 584 | for (sent = 0; sent < fw->size; sent += len) { |
556 | len = if_cs_read16(card, IF_CS_C_SQ_READ_LOW); | 585 | len = if_cs_read16(card, IF_CS_C_SQ_READ_LOW); |
557 | /* printk(KERN_INFO "//HS %d loading %d of %d bytes\n", | ||
558 | __LINE__, sent, fw->size); */ | ||
559 | if (len & 1) { | 586 | if (len & 1) { |
560 | retry++; | 587 | retry++; |
561 | lbs_pr_info("odd, need to retry this firmware block\n"); | 588 | lbs_pr_info("odd, need to retry this firmware block\n"); |
@@ -642,64 +669,6 @@ static int if_cs_host_to_card(struct lbs_private *priv, | |||
642 | } | 669 | } |
643 | 670 | ||
644 | 671 | ||
645 | static int if_cs_get_int_status(struct lbs_private *priv, u8 *ireg) | ||
646 | { | ||
647 | struct if_cs_card *card = (struct if_cs_card *)priv->card; | ||
648 | int ret = 0; | ||
649 | u16 int_cause; | ||
650 | *ireg = 0; | ||
651 | |||
652 | lbs_deb_enter(LBS_DEB_CS); | ||
653 | |||
654 | if (priv->surpriseremoved) | ||
655 | goto out; | ||
656 | |||
657 | int_cause = if_cs_read16(card, IF_CS_C_INT_CAUSE) & IF_CS_C_IC_MASK; | ||
658 | if_cs_write16(card, IF_CS_C_INT_CAUSE, int_cause); | ||
659 | |||
660 | *ireg = if_cs_read16(card, IF_CS_C_STATUS) & IF_CS_C_S_MASK; | ||
661 | |||
662 | if (!*ireg) | ||
663 | goto sbi_get_int_status_exit; | ||
664 | |||
665 | sbi_get_int_status_exit: | ||
666 | |||
667 | /* is there a data packet for us? */ | ||
668 | if (*ireg & IF_CS_C_S_RX_UPLD_RDY) { | ||
669 | struct sk_buff *skb = if_cs_receive_data(priv); | ||
670 | lbs_process_rxed_packet(priv, skb); | ||
671 | *ireg &= ~IF_CS_C_S_RX_UPLD_RDY; | ||
672 | } | ||
673 | |||
674 | if (*ireg & IF_CS_C_S_TX_DNLD_RDY) { | ||
675 | priv->dnld_sent = DNLD_RES_RECEIVED; | ||
676 | } | ||
677 | |||
678 | /* Card has a command result for us */ | ||
679 | if (*ireg & IF_CS_C_S_CMD_UPLD_RDY) { | ||
680 | ret = if_cs_receive_cmdres(priv, priv->upld_buf, &priv->upld_len); | ||
681 | if (ret < 0) | ||
682 | lbs_pr_err("could not receive cmd from card\n"); | ||
683 | } | ||
684 | |||
685 | out: | ||
686 | lbs_deb_leave_args(LBS_DEB_CS, "ret %d, ireg 0x%x, hisregcpy 0x%x", ret, *ireg, priv->hisregcpy); | ||
687 | return ret; | ||
688 | } | ||
689 | |||
690 | |||
691 | static int if_cs_read_event_cause(struct lbs_private *priv) | ||
692 | { | ||
693 | lbs_deb_enter(LBS_DEB_CS); | ||
694 | |||
695 | priv->eventcause = (if_cs_read16(priv->card, IF_CS_C_STATUS) & IF_CS_C_S_STATUS_MASK) >> 5; | ||
696 | if_cs_write16(priv->card, IF_CS_H_INT_CAUSE, IF_CS_H_IC_HOST_EVENT); | ||
697 | |||
698 | return 0; | ||
699 | } | ||
700 | |||
701 | |||
702 | |||
703 | /********************************************************************/ | 672 | /********************************************************************/ |
704 | /* Card Services */ | 673 | /* Card Services */ |
705 | /********************************************************************/ | 674 | /********************************************************************/ |
@@ -852,13 +821,10 @@ static int if_cs_probe(struct pcmcia_device *p_dev) | |||
852 | goto out2; | 821 | goto out2; |
853 | } | 822 | } |
854 | 823 | ||
855 | /* Store pointers to our call-back functions */ | 824 | /* Finish setting up fields in lbs_private */ |
856 | card->priv = priv; | 825 | card->priv = priv; |
857 | priv->card = card; | 826 | priv->card = card; |
858 | priv->hw_host_to_card = if_cs_host_to_card; | 827 | priv->hw_host_to_card = if_cs_host_to_card; |
859 | priv->hw_get_int_status = if_cs_get_int_status; | ||
860 | priv->hw_read_event_cause = if_cs_read_event_cause; | ||
861 | |||
862 | priv->fw_ready = 1; | 828 | priv->fw_ready = 1; |
863 | 829 | ||
864 | /* Now actually get the IRQ */ | 830 | /* Now actually get the IRQ */ |
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index eed73204bcc9..51f664bbee9d 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c | |||
@@ -91,8 +91,6 @@ struct if_sdio_card { | |||
91 | const char *firmware; | 91 | const char *firmware; |
92 | 92 | ||
93 | u8 buffer[65536]; | 93 | u8 buffer[65536]; |
94 | u8 int_cause; | ||
95 | u32 event; | ||
96 | 94 | ||
97 | spinlock_t lock; | 95 | spinlock_t lock; |
98 | struct if_sdio_packet *packets; | 96 | struct if_sdio_packet *packets; |
@@ -129,13 +127,13 @@ static u16 if_sdio_read_scratch(struct if_sdio_card *card, int *err) | |||
129 | static int if_sdio_handle_cmd(struct if_sdio_card *card, | 127 | static int if_sdio_handle_cmd(struct if_sdio_card *card, |
130 | u8 *buffer, unsigned size) | 128 | u8 *buffer, unsigned size) |
131 | { | 129 | { |
130 | struct lbs_private *priv = card->priv; | ||
132 | int ret; | 131 | int ret; |
133 | unsigned long flags; | 132 | unsigned long flags; |
133 | u8 i; | ||
134 | 134 | ||
135 | lbs_deb_enter(LBS_DEB_SDIO); | 135 | lbs_deb_enter(LBS_DEB_SDIO); |
136 | 136 | ||
137 | spin_lock_irqsave(&card->priv->driver_lock, flags); | ||
138 | |||
139 | if (size > LBS_CMD_BUFFER_SIZE) { | 137 | if (size > LBS_CMD_BUFFER_SIZE) { |
140 | lbs_deb_sdio("response packet too large (%d bytes)\n", | 138 | lbs_deb_sdio("response packet too large (%d bytes)\n", |
141 | (int)size); | 139 | (int)size); |
@@ -143,20 +141,20 @@ static int if_sdio_handle_cmd(struct if_sdio_card *card, | |||
143 | goto out; | 141 | goto out; |
144 | } | 142 | } |
145 | 143 | ||
146 | memcpy(card->priv->upld_buf, buffer, size); | 144 | spin_lock_irqsave(&priv->driver_lock, flags); |
147 | card->priv->upld_len = size; | ||
148 | 145 | ||
149 | card->int_cause |= MRVDRV_CMD_UPLD_RDY; | 146 | i = (priv->resp_idx == 0) ? 1 : 0; |
147 | BUG_ON(priv->resp_len[i]); | ||
148 | priv->resp_len[i] = size; | ||
149 | memcpy(priv->resp_buf[i], buffer, size); | ||
150 | lbs_notify_command_response(priv, i); | ||
150 | 151 | ||
151 | lbs_interrupt(card->priv); | 152 | spin_unlock_irqrestore(&card->priv->driver_lock, flags); |
152 | 153 | ||
153 | ret = 0; | 154 | ret = 0; |
154 | 155 | ||
155 | out: | 156 | out: |
156 | spin_unlock_irqrestore(&card->priv->driver_lock, flags); | ||
157 | |||
158 | lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); | 157 | lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); |
159 | |||
160 | return ret; | 158 | return ret; |
161 | } | 159 | } |
162 | 160 | ||
@@ -202,7 +200,6 @@ static int if_sdio_handle_event(struct if_sdio_card *card, | |||
202 | u8 *buffer, unsigned size) | 200 | u8 *buffer, unsigned size) |
203 | { | 201 | { |
204 | int ret; | 202 | int ret; |
205 | unsigned long flags; | ||
206 | u32 event; | 203 | u32 event; |
207 | 204 | ||
208 | lbs_deb_enter(LBS_DEB_SDIO); | 205 | lbs_deb_enter(LBS_DEB_SDIO); |
@@ -222,18 +219,9 @@ static int if_sdio_handle_event(struct if_sdio_card *card, | |||
222 | event |= buffer[2] << 16; | 219 | event |= buffer[2] << 16; |
223 | event |= buffer[1] << 8; | 220 | event |= buffer[1] << 8; |
224 | event |= buffer[0] << 0; | 221 | event |= buffer[0] << 0; |
225 | event <<= SBI_EVENT_CAUSE_SHIFT; | ||
226 | } | 222 | } |
227 | 223 | ||
228 | spin_lock_irqsave(&card->priv->driver_lock, flags); | 224 | lbs_queue_event(card->priv, event & 0xFF); |
229 | |||
230 | card->event = event; | ||
231 | card->int_cause |= MRVDRV_CARDEVENT; | ||
232 | |||
233 | lbs_interrupt(card->priv); | ||
234 | |||
235 | spin_unlock_irqrestore(&card->priv->driver_lock, flags); | ||
236 | |||
237 | ret = 0; | 225 | ret = 0; |
238 | 226 | ||
239 | out: | 227 | out: |
@@ -770,37 +758,6 @@ out: | |||
770 | return ret; | 758 | return ret; |
771 | } | 759 | } |
772 | 760 | ||
773 | static int if_sdio_get_int_status(struct lbs_private *priv, u8 *ireg) | ||
774 | { | ||
775 | struct if_sdio_card *card; | ||
776 | |||
777 | lbs_deb_enter(LBS_DEB_SDIO); | ||
778 | |||
779 | card = priv->card; | ||
780 | |||
781 | *ireg = card->int_cause; | ||
782 | card->int_cause = 0; | ||
783 | |||
784 | lbs_deb_leave(LBS_DEB_SDIO); | ||
785 | |||
786 | return 0; | ||
787 | } | ||
788 | |||
789 | static int if_sdio_read_event_cause(struct lbs_private *priv) | ||
790 | { | ||
791 | struct if_sdio_card *card; | ||
792 | |||
793 | lbs_deb_enter(LBS_DEB_SDIO); | ||
794 | |||
795 | card = priv->card; | ||
796 | |||
797 | priv->eventcause = card->event; | ||
798 | |||
799 | lbs_deb_leave(LBS_DEB_SDIO); | ||
800 | |||
801 | return 0; | ||
802 | } | ||
803 | |||
804 | /*******************************************************************/ | 761 | /*******************************************************************/ |
805 | /* SDIO callbacks */ | 762 | /* SDIO callbacks */ |
806 | /*******************************************************************/ | 763 | /*******************************************************************/ |
@@ -953,8 +910,6 @@ static int if_sdio_probe(struct sdio_func *func, | |||
953 | 910 | ||
954 | priv->card = card; | 911 | priv->card = card; |
955 | priv->hw_host_to_card = if_sdio_host_to_card; | 912 | priv->hw_host_to_card = if_sdio_host_to_card; |
956 | priv->hw_get_int_status = if_sdio_get_int_status; | ||
957 | priv->hw_read_event_cause = if_sdio_read_event_cause; | ||
958 | 913 | ||
959 | priv->fw_ready = 1; | 914 | priv->fw_ready = 1; |
960 | 915 | ||
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c index 75aed9d07367..8032df72aaab 100644 --- a/drivers/net/wireless/libertas/if_usb.c +++ b/drivers/net/wireless/libertas/if_usb.c | |||
@@ -38,8 +38,6 @@ static void if_usb_receive_fwload(struct urb *urb); | |||
38 | static int if_usb_prog_firmware(struct if_usb_card *cardp); | 38 | static int if_usb_prog_firmware(struct if_usb_card *cardp); |
39 | static int if_usb_host_to_card(struct lbs_private *priv, uint8_t type, | 39 | static int if_usb_host_to_card(struct lbs_private *priv, uint8_t type, |
40 | uint8_t *payload, uint16_t nb); | 40 | uint8_t *payload, uint16_t nb); |
41 | static int if_usb_get_int_status(struct lbs_private *priv, uint8_t *); | ||
42 | static int if_usb_read_event_cause(struct lbs_private *); | ||
43 | static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload, | 41 | static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload, |
44 | uint16_t nb); | 42 | uint16_t nb); |
45 | static void if_usb_free(struct if_usb_card *cardp); | 43 | static void if_usb_free(struct if_usb_card *cardp); |
@@ -233,8 +231,6 @@ static int if_usb_probe(struct usb_interface *intf, | |||
233 | cardp->priv->fw_ready = 1; | 231 | cardp->priv->fw_ready = 1; |
234 | 232 | ||
235 | priv->hw_host_to_card = if_usb_host_to_card; | 233 | priv->hw_host_to_card = if_usb_host_to_card; |
236 | priv->hw_get_int_status = if_usb_get_int_status; | ||
237 | priv->hw_read_event_cause = if_usb_read_event_cause; | ||
238 | cardp->boot2_version = udev->descriptor.bcdDevice; | 234 | cardp->boot2_version = udev->descriptor.bcdDevice; |
239 | 235 | ||
240 | if_usb_submit_rx_urb(cardp); | 236 | if_usb_submit_rx_urb(cardp); |
@@ -582,7 +578,6 @@ static inline void process_cmdtypedata(int recvlength, struct sk_buff *skb, | |||
582 | skb_pull(skb, MESSAGE_HEADER_LEN); | 578 | skb_pull(skb, MESSAGE_HEADER_LEN); |
583 | 579 | ||
584 | lbs_process_rxed_packet(priv, skb); | 580 | lbs_process_rxed_packet(priv, skb); |
585 | priv->upld_len = (recvlength - MESSAGE_HEADER_LEN); | ||
586 | } | 581 | } |
587 | 582 | ||
588 | static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff, | 583 | static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff, |
@@ -590,6 +585,8 @@ static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff, | |||
590 | struct if_usb_card *cardp, | 585 | struct if_usb_card *cardp, |
591 | struct lbs_private *priv) | 586 | struct lbs_private *priv) |
592 | { | 587 | { |
588 | u8 i; | ||
589 | |||
593 | if (recvlength > LBS_CMD_BUFFER_SIZE) { | 590 | if (recvlength > LBS_CMD_BUFFER_SIZE) { |
594 | lbs_deb_usbd(&cardp->udev->dev, | 591 | lbs_deb_usbd(&cardp->udev->dev, |
595 | "The receive buffer is too large\n"); | 592 | "The receive buffer is too large\n"); |
@@ -601,12 +598,15 @@ static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff, | |||
601 | BUG(); | 598 | BUG(); |
602 | 599 | ||
603 | spin_lock(&priv->driver_lock); | 600 | spin_lock(&priv->driver_lock); |
604 | cardp->usb_int_cause |= MRVDRV_CMD_UPLD_RDY; | ||
605 | priv->upld_len = (recvlength - MESSAGE_HEADER_LEN); | ||
606 | memcpy(priv->upld_buf, recvbuff + MESSAGE_HEADER_LEN, priv->upld_len); | ||
607 | 601 | ||
602 | i = (priv->resp_idx == 0) ? 1 : 0; | ||
603 | BUG_ON(priv->resp_len[i]); | ||
604 | priv->resp_len[i] = (recvlength - MESSAGE_HEADER_LEN); | ||
605 | memcpy(priv->resp_buf[i], recvbuff + MESSAGE_HEADER_LEN, | ||
606 | priv->resp_len[i]); | ||
608 | kfree_skb(skb); | 607 | kfree_skb(skb); |
609 | lbs_interrupt(priv); | 608 | lbs_notify_command_response(priv, i); |
609 | |||
610 | spin_unlock(&priv->driver_lock); | 610 | spin_unlock(&priv->driver_lock); |
611 | 611 | ||
612 | lbs_deb_usbd(&cardp->udev->dev, | 612 | lbs_deb_usbd(&cardp->udev->dev, |
@@ -629,6 +629,7 @@ static void if_usb_receive(struct urb *urb) | |||
629 | uint8_t *recvbuff = NULL; | 629 | uint8_t *recvbuff = NULL; |
630 | uint32_t recvtype = 0; | 630 | uint32_t recvtype = 0; |
631 | __le32 *pkt = (__le32 *)(skb->data + IPFIELD_ALIGN_OFFSET); | 631 | __le32 *pkt = (__le32 *)(skb->data + IPFIELD_ALIGN_OFFSET); |
632 | uint32_t event; | ||
632 | 633 | ||
633 | lbs_deb_enter(LBS_DEB_USB); | 634 | lbs_deb_enter(LBS_DEB_USB); |
634 | 635 | ||
@@ -660,26 +661,20 @@ static void if_usb_receive(struct urb *urb) | |||
660 | break; | 661 | break; |
661 | 662 | ||
662 | case CMD_TYPE_INDICATION: | 663 | case CMD_TYPE_INDICATION: |
663 | /* Event cause handling */ | 664 | /* Event handling */ |
664 | spin_lock(&priv->driver_lock); | 665 | event = le32_to_cpu(pkt[1]); |
666 | lbs_deb_usbd(&cardp->udev->dev, "**EVENT** 0x%X\n", event); | ||
667 | kfree_skb(skb); | ||
665 | 668 | ||
666 | cardp->usb_event_cause = le32_to_cpu(pkt[1]); | 669 | /* Icky undocumented magic special case */ |
670 | if (event & 0xffff0000) { | ||
671 | u32 trycount = (event & 0xffff0000) >> 16; | ||
667 | 672 | ||
668 | lbs_deb_usbd(&cardp->udev->dev,"**EVENT** 0x%X\n", | 673 | lbs_send_tx_feedback(priv, trycount); |
669 | cardp->usb_event_cause); | 674 | } else |
675 | lbs_queue_event(priv, event & 0xFF); | ||
676 | break; | ||
670 | 677 | ||
671 | /* Icky undocumented magic special case */ | ||
672 | if (cardp->usb_event_cause & 0xffff0000) { | ||
673 | lbs_send_tx_feedback(priv); | ||
674 | spin_unlock(&priv->driver_lock); | ||
675 | break; | ||
676 | } | ||
677 | cardp->usb_event_cause <<= 3; | ||
678 | cardp->usb_int_cause |= MRVDRV_CARDEVENT; | ||
679 | kfree_skb(skb); | ||
680 | lbs_interrupt(priv); | ||
681 | spin_unlock(&priv->driver_lock); | ||
682 | goto rx_exit; | ||
683 | default: | 678 | default: |
684 | lbs_deb_usbd(&cardp->udev->dev, "Unknown command type 0x%X\n", | 679 | lbs_deb_usbd(&cardp->udev->dev, "Unknown command type 0x%X\n", |
685 | recvtype); | 680 | recvtype); |
@@ -722,30 +717,6 @@ static int if_usb_host_to_card(struct lbs_private *priv, uint8_t type, | |||
722 | return usb_tx_block(cardp, cardp->ep_out_buf, nb + MESSAGE_HEADER_LEN); | 717 | return usb_tx_block(cardp, cardp->ep_out_buf, nb + MESSAGE_HEADER_LEN); |
723 | } | 718 | } |
724 | 719 | ||
725 | /* called with priv->driver_lock held */ | ||
726 | static int if_usb_get_int_status(struct lbs_private *priv, uint8_t *ireg) | ||
727 | { | ||
728 | struct if_usb_card *cardp = priv->card; | ||
729 | |||
730 | *ireg = cardp->usb_int_cause; | ||
731 | cardp->usb_int_cause = 0; | ||
732 | |||
733 | lbs_deb_usbd(&cardp->udev->dev, "Int cause is 0x%X\n", *ireg); | ||
734 | |||
735 | return 0; | ||
736 | } | ||
737 | |||
738 | static int if_usb_read_event_cause(struct lbs_private *priv) | ||
739 | { | ||
740 | struct if_usb_card *cardp = priv->card; | ||
741 | |||
742 | priv->eventcause = cardp->usb_event_cause; | ||
743 | /* Re-submit rx urb here to avoid event lost issue */ | ||
744 | if_usb_submit_rx_urb(cardp); | ||
745 | |||
746 | return 0; | ||
747 | } | ||
748 | |||
749 | /** | 720 | /** |
750 | * @brief This function issues Boot command to the Boot2 code | 721 | * @brief This function issues Boot command to the Boot2 code |
751 | * @param ivalue 1:Boot from FW by USB-Download | 722 | * @param ivalue 1:Boot from FW by USB-Download |
diff --git a/drivers/net/wireless/libertas/if_usb.h b/drivers/net/wireless/libertas/if_usb.h index e4829a391eb9..5771a83a43f0 100644 --- a/drivers/net/wireless/libertas/if_usb.h +++ b/drivers/net/wireless/libertas/if_usb.h | |||
@@ -46,8 +46,6 @@ struct if_usb_card { | |||
46 | struct lbs_private *priv; | 46 | struct lbs_private *priv; |
47 | 47 | ||
48 | struct sk_buff *rx_skb; | 48 | struct sk_buff *rx_skb; |
49 | uint32_t usb_event_cause; | ||
50 | uint8_t usb_int_cause; | ||
51 | 49 | ||
52 | uint8_t ep_in; | 50 | uint8_t ep_in; |
53 | uint8_t ep_out; | 51 | uint8_t ep_out; |
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 8f1122610974..406f54d40956 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/netdevice.h> | 10 | #include <linux/netdevice.h> |
11 | #include <linux/if_arp.h> | 11 | #include <linux/if_arp.h> |
12 | #include <linux/kthread.h> | 12 | #include <linux/kthread.h> |
13 | #include <linux/kfifo.h> | ||
13 | 14 | ||
14 | #include <net/iw_handler.h> | 15 | #include <net/iw_handler.h> |
15 | #include <net/ieee80211.h> | 16 | #include <net/ieee80211.h> |
@@ -480,10 +481,9 @@ static void lbs_tx_timeout(struct net_device *dev) | |||
480 | 481 | ||
481 | dev->trans_start = jiffies; | 482 | dev->trans_start = jiffies; |
482 | 483 | ||
483 | if (priv->currenttxskb) { | 484 | if (priv->currenttxskb) |
484 | priv->eventcause = 0x01000000; | 485 | lbs_send_tx_feedback(priv, 0); |
485 | lbs_send_tx_feedback(priv); | 486 | |
486 | } | ||
487 | /* XX: Shouldn't we also call into the hw-specific driver | 487 | /* XX: Shouldn't we also call into the hw-specific driver |
488 | to kick it somehow? */ | 488 | to kick it somehow? */ |
489 | lbs_host_to_card_done(priv); | 489 | lbs_host_to_card_done(priv); |
@@ -659,7 +659,6 @@ static int lbs_thread(void *data) | |||
659 | struct net_device *dev = data; | 659 | struct net_device *dev = data; |
660 | struct lbs_private *priv = dev->priv; | 660 | struct lbs_private *priv = dev->priv; |
661 | wait_queue_t wait; | 661 | wait_queue_t wait; |
662 | u8 ireg = 0; | ||
663 | 662 | ||
664 | lbs_deb_enter(LBS_DEB_THREAD); | 663 | lbs_deb_enter(LBS_DEB_THREAD); |
665 | 664 | ||
@@ -667,9 +666,10 @@ static int lbs_thread(void *data) | |||
667 | 666 | ||
668 | for (;;) { | 667 | for (;;) { |
669 | int shouldsleep; | 668 | int shouldsleep; |
669 | u8 resp_idx; | ||
670 | 670 | ||
671 | lbs_deb_thread( "main-thread 111: intcounter=%d currenttxskb=%p dnld_sent=%d\n", | 671 | lbs_deb_thread("1: currenttxskb %p, dnld_sent %d\n", |
672 | priv->intcounter, priv->currenttxskb, priv->dnld_sent); | 672 | priv->currenttxskb, priv->dnld_sent); |
673 | 673 | ||
674 | add_wait_queue(&priv->waitq, &wait); | 674 | add_wait_queue(&priv->waitq, &wait); |
675 | set_current_state(TASK_INTERRUPTIBLE); | 675 | set_current_state(TASK_INTERRUPTIBLE); |
@@ -681,8 +681,6 @@ static int lbs_thread(void *data) | |||
681 | shouldsleep = 1; /* We need to wait until we're _told_ to die */ | 681 | shouldsleep = 1; /* We need to wait until we're _told_ to die */ |
682 | else if (priv->psstate == PS_STATE_SLEEP) | 682 | else if (priv->psstate == PS_STATE_SLEEP) |
683 | shouldsleep = 1; /* Sleep mode. Nothing we can do till it wakes */ | 683 | shouldsleep = 1; /* Sleep mode. Nothing we can do till it wakes */ |
684 | else if (priv->intcounter) | ||
685 | shouldsleep = 0; /* Interrupt pending. Deal with it now */ | ||
686 | else if (priv->cmd_timed_out) | 684 | else if (priv->cmd_timed_out) |
687 | shouldsleep = 0; /* Command timed out. Recover */ | 685 | shouldsleep = 0; /* Command timed out. Recover */ |
688 | else if (!priv->fw_ready) | 686 | else if (!priv->fw_ready) |
@@ -695,29 +693,34 @@ static int lbs_thread(void *data) | |||
695 | shouldsleep = 1; /* Can't send a command; one already running */ | 693 | shouldsleep = 1; /* Can't send a command; one already running */ |
696 | else if (!list_empty(&priv->cmdpendingq)) | 694 | else if (!list_empty(&priv->cmdpendingq)) |
697 | shouldsleep = 0; /* We have a command to send */ | 695 | shouldsleep = 0; /* We have a command to send */ |
696 | else if (__kfifo_len(priv->event_fifo)) | ||
697 | shouldsleep = 0; /* We have an event to process */ | ||
698 | else if (priv->resp_len[priv->resp_idx]) | ||
699 | shouldsleep = 0; /* We have a command response */ | ||
698 | else | 700 | else |
699 | shouldsleep = 1; /* No command */ | 701 | shouldsleep = 1; /* No command */ |
700 | 702 | ||
701 | if (shouldsleep) { | 703 | if (shouldsleep) { |
702 | lbs_deb_thread("main-thread sleeping... Conn=%d IntC=%d PS_mode=%d PS_State=%d\n", | 704 | lbs_deb_thread("sleeping, connect_status %d, " |
703 | priv->connect_status, priv->intcounter, | 705 | "ps_mode %d, ps_state %d\n", |
704 | priv->psmode, priv->psstate); | 706 | priv->connect_status, |
707 | priv->psmode, priv->psstate); | ||
705 | spin_unlock_irq(&priv->driver_lock); | 708 | spin_unlock_irq(&priv->driver_lock); |
706 | schedule(); | 709 | schedule(); |
707 | } else | 710 | } else |
708 | spin_unlock_irq(&priv->driver_lock); | 711 | spin_unlock_irq(&priv->driver_lock); |
709 | 712 | ||
710 | lbs_deb_thread("main-thread 222 (waking up): intcounter=%d currenttxskb=%p dnld_sent=%d\n", | 713 | lbs_deb_thread("2: currenttxskb %p, dnld_send %d\n", |
711 | priv->intcounter, priv->currenttxskb, priv->dnld_sent); | 714 | priv->currenttxskb, priv->dnld_sent); |
712 | 715 | ||
713 | set_current_state(TASK_RUNNING); | 716 | set_current_state(TASK_RUNNING); |
714 | remove_wait_queue(&priv->waitq, &wait); | 717 | remove_wait_queue(&priv->waitq, &wait); |
715 | 718 | ||
716 | lbs_deb_thread("main-thread 333: intcounter=%d currenttxskb=%p dnld_sent=%d\n", | 719 | lbs_deb_thread("3: currenttxskb %p, dnld_sent %d\n", |
717 | priv->intcounter, priv->currenttxskb, priv->dnld_sent); | 720 | priv->currenttxskb, priv->dnld_sent); |
718 | 721 | ||
719 | if (kthread_should_stop()) { | 722 | if (kthread_should_stop()) { |
720 | lbs_deb_thread("main-thread: break from main thread\n"); | 723 | lbs_deb_thread("break from main thread\n"); |
721 | break; | 724 | break; |
722 | } | 725 | } |
723 | 726 | ||
@@ -726,35 +729,23 @@ static int lbs_thread(void *data) | |||
726 | continue; | 729 | continue; |
727 | } | 730 | } |
728 | 731 | ||
729 | spin_lock_irq(&priv->driver_lock); | 732 | lbs_deb_thread("4: currenttxskb %p, dnld_sent %d\n", |
730 | 733 | priv->currenttxskb, priv->dnld_sent); | |
731 | if (priv->intcounter) { | ||
732 | u8 int_status; | ||
733 | 734 | ||
734 | priv->intcounter = 0; | 735 | spin_lock_irq(&priv->driver_lock); |
735 | int_status = priv->hw_get_int_status(priv, &ireg); | 736 | /* Process any pending command response */ |
736 | 737 | resp_idx = priv->resp_idx; | |
737 | if (int_status) { | 738 | if (priv->resp_len[resp_idx]) { |
738 | lbs_deb_thread("main-thread: reading HOST_INT_STATUS_REG failed\n"); | ||
739 | spin_unlock_irq(&priv->driver_lock); | ||
740 | continue; | ||
741 | } | ||
742 | priv->hisregcpy |= ireg; | ||
743 | } | ||
744 | |||
745 | lbs_deb_thread("main-thread 444: intcounter=%d currenttxskb=%p dnld_sent=%d\n", | ||
746 | priv->intcounter, priv->currenttxskb, priv->dnld_sent); | ||
747 | |||
748 | /* command response? */ | ||
749 | if (priv->hisregcpy & MRVDRV_CMD_UPLD_RDY) { | ||
750 | lbs_deb_thread("main-thread: cmd response ready\n"); | ||
751 | |||
752 | priv->hisregcpy &= ~MRVDRV_CMD_UPLD_RDY; | ||
753 | spin_unlock_irq(&priv->driver_lock); | 739 | spin_unlock_irq(&priv->driver_lock); |
754 | lbs_process_rx_command(priv); | 740 | lbs_process_command_response(priv, |
741 | priv->resp_buf[resp_idx], | ||
742 | priv->resp_len[resp_idx]); | ||
755 | spin_lock_irq(&priv->driver_lock); | 743 | spin_lock_irq(&priv->driver_lock); |
744 | priv->resp_len[resp_idx] = 0; | ||
756 | } | 745 | } |
746 | spin_unlock_irq(&priv->driver_lock); | ||
757 | 747 | ||
748 | /* command timeout stuff */ | ||
758 | if (priv->cmd_timed_out && priv->cur_cmd) { | 749 | if (priv->cmd_timed_out && priv->cur_cmd) { |
759 | struct cmd_ctrl_node *cmdnode = priv->cur_cmd; | 750 | struct cmd_ctrl_node *cmdnode = priv->cur_cmd; |
760 | 751 | ||
@@ -775,21 +766,18 @@ static int lbs_thread(void *data) | |||
775 | } | 766 | } |
776 | priv->cmd_timed_out = 0; | 767 | priv->cmd_timed_out = 0; |
777 | 768 | ||
778 | /* Any Card Event */ | 769 | /* Process hardware events, e.g. card removed, link lost */ |
779 | if (priv->hisregcpy & MRVDRV_CARDEVENT) { | 770 | spin_lock_irq(&priv->driver_lock); |
780 | lbs_deb_thread("main-thread: Card Event Activity\n"); | 771 | while (__kfifo_len(priv->event_fifo)) { |
781 | 772 | u32 event; | |
782 | priv->hisregcpy &= ~MRVDRV_CARDEVENT; | ||
783 | 773 | ||
784 | if (priv->hw_read_event_cause(priv)) { | 774 | __kfifo_get(priv->event_fifo, (unsigned char *) &event, |
785 | lbs_pr_alert("main-thread: hw_read_event_cause failed\n"); | 775 | sizeof(event)); |
786 | spin_unlock_irq(&priv->driver_lock); | ||
787 | continue; | ||
788 | } | ||
789 | spin_unlock_irq(&priv->driver_lock); | ||
790 | lbs_process_event(priv); | ||
791 | } else | ||
792 | spin_unlock_irq(&priv->driver_lock); | 776 | spin_unlock_irq(&priv->driver_lock); |
777 | lbs_process_event(priv, event); | ||
778 | spin_lock_irq(&priv->driver_lock); | ||
779 | } | ||
780 | spin_unlock_irq(&priv->driver_lock); | ||
793 | 781 | ||
794 | if (!priv->fw_ready) | 782 | if (!priv->fw_ready) |
795 | continue; | 783 | continue; |
@@ -798,8 +786,10 @@ static int lbs_thread(void *data) | |||
798 | if (priv->psstate == PS_STATE_PRE_SLEEP && | 786 | if (priv->psstate == PS_STATE_PRE_SLEEP && |
799 | !priv->dnld_sent && !priv->cur_cmd) { | 787 | !priv->dnld_sent && !priv->cur_cmd) { |
800 | if (priv->connect_status == LBS_CONNECTED) { | 788 | if (priv->connect_status == LBS_CONNECTED) { |
801 | lbs_deb_thread("main_thread: PRE_SLEEP--intcounter=%d currenttxskb=%p dnld_sent=%d cur_cmd=%p, confirm now\n", | 789 | lbs_deb_thread("pre-sleep, currenttxskb %p, " |
802 | priv->intcounter, priv->currenttxskb, priv->dnld_sent, priv->cur_cmd); | 790 | "dnld_sent %d, cur_cmd %p\n", |
791 | priv->currenttxskb, priv->dnld_sent, | ||
792 | priv->cur_cmd); | ||
803 | 793 | ||
804 | lbs_ps_confirm_sleep(priv); | 794 | lbs_ps_confirm_sleep(priv); |
805 | } else { | 795 | } else { |
@@ -809,7 +799,8 @@ static int lbs_thread(void *data) | |||
809 | * after firmware fixes it | 799 | * after firmware fixes it |
810 | */ | 800 | */ |
811 | priv->psstate = PS_STATE_AWAKE; | 801 | priv->psstate = PS_STATE_AWAKE; |
812 | lbs_pr_alert("main-thread: ignore PS_SleepConfirm in non-connected state\n"); | 802 | lbs_pr_alert("ignore PS_SleepConfirm in " |
803 | "non-connected state\n"); | ||
813 | } | 804 | } |
814 | } | 805 | } |
815 | 806 | ||
@@ -1046,7 +1037,18 @@ static int lbs_init_adapter(struct lbs_private *priv) | |||
1046 | /* Allocate the command buffers */ | 1037 | /* Allocate the command buffers */ |
1047 | if (lbs_allocate_cmd_buffer(priv)) { | 1038 | if (lbs_allocate_cmd_buffer(priv)) { |
1048 | lbs_pr_err("Out of memory allocating command buffers\n"); | 1039 | lbs_pr_err("Out of memory allocating command buffers\n"); |
1049 | ret = -1; | 1040 | ret = -ENOMEM; |
1041 | goto out; | ||
1042 | } | ||
1043 | priv->resp_idx = 0; | ||
1044 | priv->resp_len[0] = priv->resp_len[1] = 0; | ||
1045 | |||
1046 | /* Create the event FIFO */ | ||
1047 | priv->event_fifo = kfifo_alloc(sizeof(u32) * 16, GFP_KERNEL, NULL); | ||
1048 | if (IS_ERR(priv->event_fifo)) { | ||
1049 | lbs_pr_err("Out of memory allocating event FIFO buffer\n"); | ||
1050 | ret = -ENOMEM; | ||
1051 | goto out; | ||
1050 | } | 1052 | } |
1051 | 1053 | ||
1052 | out: | 1054 | out: |
@@ -1060,6 +1062,8 @@ static void lbs_free_adapter(struct lbs_private *priv) | |||
1060 | lbs_deb_enter(LBS_DEB_MAIN); | 1062 | lbs_deb_enter(LBS_DEB_MAIN); |
1061 | 1063 | ||
1062 | lbs_free_cmd_buffer(priv); | 1064 | lbs_free_cmd_buffer(priv); |
1065 | if (priv->event_fifo) | ||
1066 | kfifo_free(priv->event_fifo); | ||
1063 | del_timer(&priv->command_timer); | 1067 | del_timer(&priv->command_timer); |
1064 | kfree(priv->networks); | 1068 | kfree(priv->networks); |
1065 | priv->networks = NULL; | 1069 | priv->networks = NULL; |
@@ -1434,27 +1438,41 @@ out: | |||
1434 | return ret; | 1438 | return ret; |
1435 | } | 1439 | } |
1436 | 1440 | ||
1437 | /** | 1441 | void lbs_queue_event(struct lbs_private *priv, u32 event) |
1438 | * @brief This function handles the interrupt. it will change PS | 1442 | { |
1439 | * state if applicable. it will wake up main_thread to handle | 1443 | unsigned long flags; |
1440 | * the interrupt event as well. | 1444 | |
1441 | * | 1445 | lbs_deb_enter(LBS_DEB_THREAD); |
1442 | * @param dev A pointer to net_device structure | 1446 | spin_lock_irqsave(&priv->driver_lock, flags); |
1443 | * @return n/a | 1447 | |
1444 | */ | 1448 | if (priv->psstate == PS_STATE_SLEEP) |
1445 | void lbs_interrupt(struct lbs_private *priv) | 1449 | priv->psstate = PS_STATE_AWAKE; |
1450 | |||
1451 | __kfifo_put(priv->event_fifo, (unsigned char *) &event, sizeof(u32)); | ||
1452 | |||
1453 | wake_up_interruptible(&priv->waitq); | ||
1454 | |||
1455 | spin_unlock_irqrestore(&priv->driver_lock, flags); | ||
1456 | lbs_deb_leave(LBS_DEB_THREAD); | ||
1457 | } | ||
1458 | EXPORT_SYMBOL_GPL(lbs_queue_event); | ||
1459 | |||
1460 | void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx) | ||
1446 | { | 1461 | { |
1447 | lbs_deb_enter(LBS_DEB_THREAD); | 1462 | lbs_deb_enter(LBS_DEB_THREAD); |
1448 | 1463 | ||
1449 | lbs_deb_thread("lbs_interrupt: intcounter=%d\n", priv->intcounter); | ||
1450 | priv->intcounter++; | ||
1451 | if (priv->psstate == PS_STATE_SLEEP) | 1464 | if (priv->psstate == PS_STATE_SLEEP) |
1452 | priv->psstate = PS_STATE_AWAKE; | 1465 | priv->psstate = PS_STATE_AWAKE; |
1466 | |||
1467 | /* Swap buffers by flipping the response index */ | ||
1468 | BUG_ON(resp_idx > 1); | ||
1469 | priv->resp_idx = resp_idx; | ||
1470 | |||
1453 | wake_up_interruptible(&priv->waitq); | 1471 | wake_up_interruptible(&priv->waitq); |
1454 | 1472 | ||
1455 | lbs_deb_leave(LBS_DEB_THREAD); | 1473 | lbs_deb_leave(LBS_DEB_THREAD); |
1456 | } | 1474 | } |
1457 | EXPORT_SYMBOL_GPL(lbs_interrupt); | 1475 | EXPORT_SYMBOL_GPL(lbs_notify_command_response); |
1458 | 1476 | ||
1459 | static int __init lbs_init_module(void) | 1477 | static int __init lbs_init_module(void) |
1460 | { | 1478 | { |
diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c index 09f023089ea4..05af7316f698 100644 --- a/drivers/net/wireless/libertas/rx.c +++ b/drivers/net/wireless/libertas/rx.c | |||
@@ -145,14 +145,14 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb) | |||
145 | struct net_device *dev = priv->dev; | 145 | struct net_device *dev = priv->dev; |
146 | struct rxpackethdr *p_rx_pkt; | 146 | struct rxpackethdr *p_rx_pkt; |
147 | struct rxpd *p_rx_pd; | 147 | struct rxpd *p_rx_pd; |
148 | |||
149 | int hdrchop; | 148 | int hdrchop; |
150 | struct ethhdr *p_ethhdr; | 149 | struct ethhdr *p_ethhdr; |
151 | |||
152 | const u8 rfc1042_eth_hdr[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; | 150 | const u8 rfc1042_eth_hdr[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; |
153 | 151 | ||
154 | lbs_deb_enter(LBS_DEB_RX); | 152 | lbs_deb_enter(LBS_DEB_RX); |
155 | 153 | ||
154 | BUG_ON(!skb); | ||
155 | |||
156 | skb->ip_summed = CHECKSUM_NONE; | 156 | skb->ip_summed = CHECKSUM_NONE; |
157 | 157 | ||
158 | if (priv->monitormode) | 158 | if (priv->monitormode) |
diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c index 77f1f9525b81..a4972fed2941 100644 --- a/drivers/net/wireless/libertas/tx.c +++ b/drivers/net/wireless/libertas/tx.c | |||
@@ -179,31 +179,17 @@ int lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
179 | * | 179 | * |
180 | * @returns void | 180 | * @returns void |
181 | */ | 181 | */ |
182 | void lbs_send_tx_feedback(struct lbs_private *priv) | 182 | void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count) |
183 | { | 183 | { |
184 | struct tx_radiotap_hdr *radiotap_hdr; | 184 | struct tx_radiotap_hdr *radiotap_hdr; |
185 | u32 status = priv->eventcause; | ||
186 | int txfail; | ||
187 | int try_count; | ||
188 | 185 | ||
189 | if (!priv->monitormode || priv->currenttxskb == NULL) | 186 | if (!priv->monitormode || priv->currenttxskb == NULL) |
190 | return; | 187 | return; |
191 | 188 | ||
192 | radiotap_hdr = (struct tx_radiotap_hdr *)priv->currenttxskb->data; | 189 | radiotap_hdr = (struct tx_radiotap_hdr *)priv->currenttxskb->data; |
193 | 190 | ||
194 | txfail = (status >> 24); | 191 | radiotap_hdr->data_retries = try_count ? |
195 | 192 | (1 + priv->txretrycount - try_count) : 0; | |
196 | #if 0 | ||
197 | /* The version of roofnet that we've tested does not use this yet | ||
198 | * But it may be used in the future. | ||
199 | */ | ||
200 | if (txfail) | ||
201 | radiotap_hdr->flags &= IEEE80211_RADIOTAP_F_TX_FAIL; | ||
202 | #endif | ||
203 | try_count = (status >> 16) & 0xff; | ||
204 | radiotap_hdr->data_retries = (try_count) ? | ||
205 | (1 + priv->txretrycount - try_count) : 0; | ||
206 | |||
207 | 193 | ||
208 | priv->currenttxskb->protocol = eth_type_trans(priv->currenttxskb, | 194 | priv->currenttxskb->protocol = eth_type_trans(priv->currenttxskb, |
209 | priv->rtap_net_dev); | 195 | priv->rtap_net_dev); |
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index f3858ee36f32..963960dc30f2 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/kernel.h> | 34 | #include <linux/kernel.h> |
35 | #include <linux/proc_fs.h> | 35 | #include <linux/proc_fs.h> |
36 | #include <linux/ptrace.h> | 36 | #include <linux/ptrace.h> |
37 | #include <linux/seq_file.h> | ||
37 | #include <linux/slab.h> | 38 | #include <linux/slab.h> |
38 | #include <linux/string.h> | 39 | #include <linux/string.h> |
39 | #include <linux/timer.h> | 40 | #include <linux/timer.h> |
@@ -2582,7 +2583,7 @@ static char *nettype[] = {"Adhoc", "Infra "}; | |||
2582 | static char *framing[] = {"Encapsulation", "Translation"} | 2583 | static char *framing[] = {"Encapsulation", "Translation"} |
2583 | ; | 2584 | ; |
2584 | /*===========================================================================*/ | 2585 | /*===========================================================================*/ |
2585 | static int ray_cs_proc_read(char *buf, char **start, off_t offset, int len) | 2586 | static int ray_cs_proc_show(struct seq_file *m, void *v) |
2586 | { | 2587 | { |
2587 | /* Print current values which are not available via other means | 2588 | /* Print current values which are not available via other means |
2588 | * eg ifconfig | 2589 | * eg ifconfig |
@@ -2606,83 +2607,93 @@ static int ray_cs_proc_read(char *buf, char **start, off_t offset, int len) | |||
2606 | if (!local) | 2607 | if (!local) |
2607 | return 0; | 2608 | return 0; |
2608 | 2609 | ||
2609 | len = 0; | 2610 | seq_puts(m, "Raylink Wireless LAN driver status\n"); |
2610 | 2611 | seq_printf(m, "%s\n", rcsid); | |
2611 | len += sprintf(buf + len, "Raylink Wireless LAN driver status\n"); | ||
2612 | len += sprintf(buf + len, "%s\n", rcsid); | ||
2613 | /* build 4 does not report version, and field is 0x55 after memtest */ | 2612 | /* build 4 does not report version, and field is 0x55 after memtest */ |
2614 | len += sprintf(buf + len, "Firmware version = "); | 2613 | seq_puts(m, "Firmware version = "); |
2615 | if (local->fw_ver == 0x55) | 2614 | if (local->fw_ver == 0x55) |
2616 | len += sprintf(buf + len, "4 - Use dump_cis for more details\n"); | 2615 | seq_puts(m, "4 - Use dump_cis for more details\n"); |
2617 | else | 2616 | else |
2618 | len += sprintf(buf + len, "%2d.%02d.%02d\n", | 2617 | seq_printf(m, "%2d.%02d.%02d\n", |
2619 | local->fw_ver, local->fw_bld, local->fw_var); | 2618 | local->fw_ver, local->fw_bld, local->fw_var); |
2620 | 2619 | ||
2621 | for (i=0; i<32; i++) c[i] = local->sparm.b5.a_current_ess_id[i]; | 2620 | for (i=0; i<32; i++) c[i] = local->sparm.b5.a_current_ess_id[i]; |
2622 | c[32] = 0; | 2621 | c[32] = 0; |
2623 | len += sprintf(buf + len, "%s network ESSID = \"%s\"\n", | 2622 | seq_printf(m, "%s network ESSID = \"%s\"\n", |
2624 | nettype[local->sparm.b5.a_network_type], c); | 2623 | nettype[local->sparm.b5.a_network_type], c); |
2625 | 2624 | ||
2626 | p = local->bss_id; | 2625 | p = local->bss_id; |
2627 | len += sprintf(buf + len, "BSSID = %s\n", | 2626 | seq_printf(m, "BSSID = %s\n", |
2628 | print_mac(mac, p)); | 2627 | print_mac(mac, p)); |
2629 | 2628 | ||
2630 | len += sprintf(buf + len, "Country code = %d\n", | 2629 | seq_printf(m, "Country code = %d\n", |
2631 | local->sparm.b5.a_curr_country_code); | 2630 | local->sparm.b5.a_curr_country_code); |
2632 | 2631 | ||
2633 | i = local->card_status; | 2632 | i = local->card_status; |
2634 | if (i < 0) i = 10; | 2633 | if (i < 0) i = 10; |
2635 | if (i > 16) i = 10; | 2634 | if (i > 16) i = 10; |
2636 | len += sprintf(buf + len, "Card status = %s\n", card_status[i]); | 2635 | seq_printf(m, "Card status = %s\n", card_status[i]); |
2637 | 2636 | ||
2638 | len += sprintf(buf + len, "Framing mode = %s\n",framing[translate]); | 2637 | seq_printf(m, "Framing mode = %s\n",framing[translate]); |
2639 | 2638 | ||
2640 | len += sprintf(buf + len, "Last pkt signal lvl = %d\n", local->last_rsl); | 2639 | seq_printf(m, "Last pkt signal lvl = %d\n", local->last_rsl); |
2641 | 2640 | ||
2642 | if (local->beacon_rxed) { | 2641 | if (local->beacon_rxed) { |
2643 | /* Pull some fields out of last beacon received */ | 2642 | /* Pull some fields out of last beacon received */ |
2644 | len += sprintf(buf + len, "Beacon Interval = %d Kus\n", | 2643 | seq_printf(m, "Beacon Interval = %d Kus\n", |
2645 | local->last_bcn.beacon_intvl[0] | 2644 | local->last_bcn.beacon_intvl[0] |
2646 | + 256 * local->last_bcn.beacon_intvl[1]); | 2645 | + 256 * local->last_bcn.beacon_intvl[1]); |
2647 | 2646 | ||
2648 | p = local->last_bcn.elements; | 2647 | p = local->last_bcn.elements; |
2649 | if (p[0] == C_ESSID_ELEMENT_ID) p += p[1] + 2; | 2648 | if (p[0] == C_ESSID_ELEMENT_ID) p += p[1] + 2; |
2650 | else { | 2649 | else { |
2651 | len += sprintf(buf + len, "Parse beacon failed at essid element id = %d\n",p[0]); | 2650 | seq_printf(m, "Parse beacon failed at essid element id = %d\n",p[0]); |
2652 | return len; | 2651 | return 0; |
2653 | } | 2652 | } |
2654 | 2653 | ||
2655 | if (p[0] == C_SUPPORTED_RATES_ELEMENT_ID) { | 2654 | if (p[0] == C_SUPPORTED_RATES_ELEMENT_ID) { |
2656 | len += sprintf(buf + len, "Supported rate codes = "); | 2655 | seq_puts(m, "Supported rate codes = "); |
2657 | for (i=2; i<p[1] + 2; i++) | 2656 | for (i=2; i<p[1] + 2; i++) |
2658 | len += sprintf(buf + len, "0x%02x ", p[i]); | 2657 | seq_printf(m, "0x%02x ", p[i]); |
2659 | len += sprintf(buf + len, "\n"); | 2658 | seq_putc(m, '\n'); |
2660 | p += p[1] + 2; | 2659 | p += p[1] + 2; |
2661 | } | 2660 | } |
2662 | else { | 2661 | else { |
2663 | len += sprintf(buf + len, "Parse beacon failed at rates element\n"); | 2662 | seq_puts(m, "Parse beacon failed at rates element\n"); |
2664 | return len; | 2663 | return 0; |
2665 | } | 2664 | } |
2666 | 2665 | ||
2667 | if (p[0] == C_FH_PARAM_SET_ELEMENT_ID) { | 2666 | if (p[0] == C_FH_PARAM_SET_ELEMENT_ID) { |
2668 | pfh = (struct freq_hop_element *)p; | 2667 | pfh = (struct freq_hop_element *)p; |
2669 | len += sprintf(buf + len, "Hop dwell = %d Kus\n", | 2668 | seq_printf(m, "Hop dwell = %d Kus\n", |
2670 | pfh->dwell_time[0] + 256 * pfh->dwell_time[1]); | 2669 | pfh->dwell_time[0] + 256 * pfh->dwell_time[1]); |
2671 | len += sprintf(buf + len, "Hop set = %d \n", pfh->hop_set); | 2670 | seq_printf(m, "Hop set = %d \n", pfh->hop_set); |
2672 | len += sprintf(buf + len, "Hop pattern = %d \n", pfh->hop_pattern); | 2671 | seq_printf(m, "Hop pattern = %d \n", pfh->hop_pattern); |
2673 | len += sprintf(buf + len, "Hop index = %d \n", pfh->hop_index); | 2672 | seq_printf(m, "Hop index = %d \n", pfh->hop_index); |
2674 | p += p[1] + 2; | 2673 | p += p[1] + 2; |
2675 | } | 2674 | } |
2676 | else { | 2675 | else { |
2677 | len += sprintf(buf + len, "Parse beacon failed at FH param element\n"); | 2676 | seq_puts(m, "Parse beacon failed at FH param element\n"); |
2678 | return len; | 2677 | return 0; |
2679 | } | 2678 | } |
2680 | } else { | 2679 | } else { |
2681 | len += sprintf(buf + len, "No beacons received\n"); | 2680 | seq_puts(m, "No beacons received\n"); |
2682 | } | 2681 | } |
2683 | return len; | 2682 | return 0; |
2684 | } | 2683 | } |
2685 | 2684 | ||
2685 | static int ray_cs_proc_open(struct inode *inode, struct file *file) | ||
2686 | { | ||
2687 | return single_open(file, ray_cs_proc_show, NULL); | ||
2688 | } | ||
2689 | |||
2690 | static const struct file_operations ray_cs_proc_fops = { | ||
2691 | .owner = THIS_MODULE, | ||
2692 | .open = ray_cs_proc_open, | ||
2693 | .read = seq_read, | ||
2694 | .llseek = seq_lseek, | ||
2695 | .release = single_release, | ||
2696 | }; | ||
2686 | #endif | 2697 | #endif |
2687 | /*===========================================================================*/ | 2698 | /*===========================================================================*/ |
2688 | static int build_auth_frame(ray_dev_t *local, UCHAR *dest, int auth_type) | 2699 | static int build_auth_frame(ray_dev_t *local, UCHAR *dest, int auth_type) |
@@ -2815,7 +2826,7 @@ static int __init init_ray_cs(void) | |||
2815 | #ifdef CONFIG_PROC_FS | 2826 | #ifdef CONFIG_PROC_FS |
2816 | proc_mkdir("driver/ray_cs", NULL); | 2827 | proc_mkdir("driver/ray_cs", NULL); |
2817 | 2828 | ||
2818 | create_proc_info_entry("driver/ray_cs/ray_cs", 0, NULL, &ray_cs_proc_read); | 2829 | proc_create("driver/ray_cs/ray_cs", 0, NULL, &ray_cs_proc_fops); |
2819 | raycs_write("driver/ray_cs/essid", write_essid, NULL); | 2830 | raycs_write("driver/ray_cs/essid", write_essid, NULL); |
2820 | raycs_write("driver/ray_cs/net_type", write_int, &net_type); | 2831 | raycs_write("driver/ray_cs/net_type", write_int, &net_type); |
2821 | raycs_write("driver/ray_cs/translate", write_int, &translate); | 2832 | raycs_write("driver/ray_cs/translate", write_int, &translate); |
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 0361524d193c..f8fe7a139a8a 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c | |||
@@ -433,11 +433,9 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac, | |||
433 | 433 | ||
434 | if (delayed_flags & DELAYED_UPDATE_BEACON) { | 434 | if (delayed_flags & DELAYED_UPDATE_BEACON) { |
435 | skb = ieee80211_beacon_get(rt2x00dev->hw, vif, &control); | 435 | skb = ieee80211_beacon_get(rt2x00dev->hw, vif, &control); |
436 | if (skb) { | 436 | if (skb && rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw, |
437 | rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw, skb, | 437 | skb, &control)) |
438 | &control); | ||
439 | dev_kfree_skb(skb); | 438 | dev_kfree_skb(skb); |
440 | } | ||
441 | } | 439 | } |
442 | 440 | ||
443 | if (delayed_flags & DELAYED_CONFIG_ERP) | 441 | if (delayed_flags & DELAYED_CONFIG_ERP) |
diff --git a/drivers/ssb/driver_pcicore.c b/drivers/ssb/driver_pcicore.c index 2cc668ac5609..75def13e797d 100644 --- a/drivers/ssb/driver_pcicore.c +++ b/drivers/ssb/driver_pcicore.c | |||
@@ -562,15 +562,9 @@ int ssb_pcicore_dev_irqvecs_enable(struct ssb_pcicore *pc, | |||
562 | u32 intvec; | 562 | u32 intvec; |
563 | 563 | ||
564 | intvec = ssb_read32(pdev, SSB_INTVEC); | 564 | intvec = ssb_read32(pdev, SSB_INTVEC); |
565 | if ((bus->chip_id & 0xFF00) == 0x4400) { | 565 | tmp = ssb_read32(dev, SSB_TPSFLAG); |
566 | /* Workaround: On the BCM44XX the BPFLAG routing | 566 | tmp &= SSB_TPSFLAG_BPFLAG; |
567 | * bit is wrong. Use a hardcoded constant. */ | 567 | intvec |= (1 << tmp); |
568 | intvec |= 0x00000002; | ||
569 | } else { | ||
570 | tmp = ssb_read32(dev, SSB_TPSFLAG); | ||
571 | tmp &= SSB_TPSFLAG_BPFLAG; | ||
572 | intvec |= (1 << tmp); | ||
573 | } | ||
574 | ssb_write32(pdev, SSB_INTVEC, intvec); | 568 | ssb_write32(pdev, SSB_INTVEC, intvec); |
575 | } | 569 | } |
576 | 570 | ||
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 079e7bd86c90..4a80d74975e8 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -1020,8 +1020,7 @@ enum ieee80211_ampdu_mlme_action { | |||
1020 | * level driver (e.g. assoc/disassoc status, erp parameters). | 1020 | * level driver (e.g. assoc/disassoc status, erp parameters). |
1021 | * This function should not be used if no BSS has been set, unless | 1021 | * This function should not be used if no BSS has been set, unless |
1022 | * for association indication. The @changed parameter indicates which | 1022 | * for association indication. The @changed parameter indicates which |
1023 | * of the bss parameters has changed when a call is made. This callback | 1023 | * of the bss parameters has changed when a call is made. |
1024 | * has to be atomic. | ||
1025 | * | 1024 | * |
1026 | * @configure_filter: Configure the device's RX filter. | 1025 | * @configure_filter: Configure the device's RX filter. |
1027 | * See the section "Frame filtering" for more information. | 1026 | * See the section "Frame filtering" for more information. |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 8af576c1d2f1..699d97b8de5e 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -33,6 +33,8 @@ nl80211_type_to_mac80211_type(enum nl80211_iftype type) | |||
33 | case NL80211_IFTYPE_MESH_POINT: | 33 | case NL80211_IFTYPE_MESH_POINT: |
34 | return IEEE80211_IF_TYPE_MESH_POINT; | 34 | return IEEE80211_IF_TYPE_MESH_POINT; |
35 | #endif | 35 | #endif |
36 | case NL80211_IFTYPE_WDS: | ||
37 | return IEEE80211_IF_TYPE_WDS; | ||
36 | default: | 38 | default: |
37 | return IEEE80211_IF_TYPE_INVALID; | 39 | return IEEE80211_IF_TYPE_INVALID; |
38 | } | 40 | } |
@@ -718,12 +720,18 @@ static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev, | |||
718 | struct sta_info *sta; | 720 | struct sta_info *sta; |
719 | 721 | ||
720 | if (mac) { | 722 | if (mac) { |
723 | rcu_read_lock(); | ||
724 | |||
721 | /* XXX: get sta belonging to dev */ | 725 | /* XXX: get sta belonging to dev */ |
722 | sta = sta_info_get(local, mac); | 726 | sta = sta_info_get(local, mac); |
723 | if (!sta) | 727 | if (!sta) { |
728 | rcu_read_unlock(); | ||
724 | return -ENOENT; | 729 | return -ENOENT; |
730 | } | ||
725 | 731 | ||
726 | sta_info_unlink(&sta); | 732 | sta_info_unlink(&sta); |
733 | rcu_read_unlock(); | ||
734 | |||
727 | sta_info_destroy(sta); | 735 | sta_info_destroy(sta); |
728 | } else | 736 | } else |
729 | sta_info_flush(local, sdata); | 737 | sta_info_flush(local, sdata); |
@@ -740,17 +748,23 @@ static int ieee80211_change_station(struct wiphy *wiphy, | |||
740 | struct sta_info *sta; | 748 | struct sta_info *sta; |
741 | struct ieee80211_sub_if_data *vlansdata; | 749 | struct ieee80211_sub_if_data *vlansdata; |
742 | 750 | ||
751 | rcu_read_lock(); | ||
752 | |||
743 | /* XXX: get sta belonging to dev */ | 753 | /* XXX: get sta belonging to dev */ |
744 | sta = sta_info_get(local, mac); | 754 | sta = sta_info_get(local, mac); |
745 | if (!sta) | 755 | if (!sta) { |
756 | rcu_read_unlock(); | ||
746 | return -ENOENT; | 757 | return -ENOENT; |
758 | } | ||
747 | 759 | ||
748 | if (params->vlan && params->vlan != sta->sdata->dev) { | 760 | if (params->vlan && params->vlan != sta->sdata->dev) { |
749 | vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan); | 761 | vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan); |
750 | 762 | ||
751 | if (vlansdata->vif.type != IEEE80211_IF_TYPE_VLAN || | 763 | if (vlansdata->vif.type != IEEE80211_IF_TYPE_VLAN || |
752 | vlansdata->vif.type != IEEE80211_IF_TYPE_AP) | 764 | vlansdata->vif.type != IEEE80211_IF_TYPE_AP) { |
765 | rcu_read_unlock(); | ||
753 | return -EINVAL; | 766 | return -EINVAL; |
767 | } | ||
754 | 768 | ||
755 | sta->sdata = IEEE80211_DEV_TO_SUB_IF(params->vlan); | 769 | sta->sdata = IEEE80211_DEV_TO_SUB_IF(params->vlan); |
756 | ieee80211_send_layer2_update(sta); | 770 | ieee80211_send_layer2_update(sta); |
@@ -758,6 +772,8 @@ static int ieee80211_change_station(struct wiphy *wiphy, | |||
758 | 772 | ||
759 | sta_apply_parameters(local, sta, params); | 773 | sta_apply_parameters(local, sta, params); |
760 | 774 | ||
775 | rcu_read_unlock(); | ||
776 | |||
761 | return 0; | 777 | return 0; |
762 | } | 778 | } |
763 | 779 | ||
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index c642538e8282..8e53ce7ed444 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -102,7 +102,7 @@ struct ieee80211_sta_bss { | |||
102 | u64 timestamp; | 102 | u64 timestamp; |
103 | int beacon_int; | 103 | int beacon_int; |
104 | 104 | ||
105 | int probe_resp; | 105 | bool probe_resp; |
106 | unsigned long last_update; | 106 | unsigned long last_update; |
107 | 107 | ||
108 | /* during assocation, we save an ERP value from a probe response so | 108 | /* during assocation, we save an ERP value from a probe response so |
@@ -600,8 +600,7 @@ struct ieee80211_local { | |||
600 | /* | 600 | /* |
601 | * The lock only protects the list, hash, timer and counter | 601 | * The lock only protects the list, hash, timer and counter |
602 | * against manipulation, reads are done in RCU. Additionally, | 602 | * against manipulation, reads are done in RCU. Additionally, |
603 | * the lock protects each BSS's TIM bitmap, a few items in | 603 | * the lock protects each BSS's TIM bitmap. |
604 | * STA info structures and various key pointers. | ||
605 | */ | 604 | */ |
606 | spinlock_t sta_lock; | 605 | spinlock_t sta_lock; |
607 | unsigned long num_sta; | 606 | unsigned long num_sta; |
@@ -635,6 +634,13 @@ struct ieee80211_local { | |||
635 | 634 | ||
636 | struct list_head interfaces; | 635 | struct list_head interfaces; |
637 | 636 | ||
637 | /* | ||
638 | * Key lock, protects sdata's key_list and sta_info's | ||
639 | * key pointers (write access, they're RCU.) | ||
640 | */ | ||
641 | spinlock_t key_lock; | ||
642 | |||
643 | |||
638 | bool sta_sw_scanning; | 644 | bool sta_sw_scanning; |
639 | bool sta_hw_scanning; | 645 | bool sta_hw_scanning; |
640 | int scan_channel_idx; | 646 | int scan_channel_idx; |
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 711e36e54ff8..150d66dbda9d 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
@@ -74,9 +74,12 @@ static void add_todo(struct ieee80211_key *key, u32 flag) | |||
74 | 74 | ||
75 | spin_lock(&todo_lock); | 75 | spin_lock(&todo_lock); |
76 | key->flags |= flag; | 76 | key->flags |= flag; |
77 | /* only add if not already added */ | 77 | /* |
78 | if (list_empty(&key->todo)) | 78 | * Remove again if already on the list so that we move it to the end. |
79 | list_add(&key->todo, &todo_list); | 79 | */ |
80 | if (!list_empty(&key->todo)) | ||
81 | list_del(&key->todo); | ||
82 | list_add_tail(&key->todo, &todo_list); | ||
80 | schedule_work(&todo_work); | 83 | schedule_work(&todo_work); |
81 | spin_unlock(&todo_lock); | 84 | spin_unlock(&todo_lock); |
82 | } | 85 | } |
@@ -210,9 +213,9 @@ void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx) | |||
210 | { | 213 | { |
211 | unsigned long flags; | 214 | unsigned long flags; |
212 | 215 | ||
213 | spin_lock_irqsave(&sdata->local->sta_lock, flags); | 216 | spin_lock_irqsave(&sdata->local->key_lock, flags); |
214 | __ieee80211_set_default_key(sdata, idx); | 217 | __ieee80211_set_default_key(sdata, idx); |
215 | spin_unlock_irqrestore(&sdata->local->sta_lock, flags); | 218 | spin_unlock_irqrestore(&sdata->local->key_lock, flags); |
216 | } | 219 | } |
217 | 220 | ||
218 | 221 | ||
@@ -339,7 +342,7 @@ void ieee80211_key_link(struct ieee80211_key *key, | |||
339 | } | 342 | } |
340 | } | 343 | } |
341 | 344 | ||
342 | spin_lock_irqsave(&sdata->local->sta_lock, flags); | 345 | spin_lock_irqsave(&sdata->local->key_lock, flags); |
343 | 346 | ||
344 | if (sta) | 347 | if (sta) |
345 | old_key = sta->key; | 348 | old_key = sta->key; |
@@ -348,68 +351,81 @@ void ieee80211_key_link(struct ieee80211_key *key, | |||
348 | 351 | ||
349 | __ieee80211_key_replace(sdata, sta, old_key, key); | 352 | __ieee80211_key_replace(sdata, sta, old_key, key); |
350 | 353 | ||
351 | spin_unlock_irqrestore(&sdata->local->sta_lock, flags); | 354 | spin_unlock_irqrestore(&sdata->local->key_lock, flags); |
352 | 355 | ||
353 | /* free old key later */ | 356 | /* free old key later */ |
354 | add_todo(old_key, KEY_FLAG_TODO_DELETE); | 357 | add_todo(old_key, KEY_FLAG_TODO_DELETE); |
355 | 358 | ||
356 | add_todo(key, KEY_FLAG_TODO_ADD_DEBUGFS); | 359 | add_todo(key, KEY_FLAG_TODO_ADD_DEBUGFS); |
357 | if (netif_running(sdata->dev)) | 360 | if (netif_running(sdata->dev)) |
358 | add_todo(key, KEY_FLAG_TODO_HWACCEL); | 361 | add_todo(key, KEY_FLAG_TODO_HWACCEL_ADD); |
359 | } | 362 | } |
360 | 363 | ||
361 | void ieee80211_key_free(struct ieee80211_key *key) | 364 | static void __ieee80211_key_free(struct ieee80211_key *key) |
362 | { | 365 | { |
363 | unsigned long flags; | ||
364 | |||
365 | if (!key) | ||
366 | return; | ||
367 | |||
368 | /* | 366 | /* |
369 | * Replace key with nothingness if it was ever used. | 367 | * Replace key with nothingness if it was ever used. |
370 | */ | 368 | */ |
371 | if (key->sdata) { | 369 | if (key->sdata) |
372 | spin_lock_irqsave(&key->sdata->local->sta_lock, flags); | ||
373 | __ieee80211_key_replace(key->sdata, key->sta, | 370 | __ieee80211_key_replace(key->sdata, key->sta, |
374 | key, NULL); | 371 | key, NULL); |
375 | spin_unlock_irqrestore(&key->sdata->local->sta_lock, flags); | ||
376 | } | ||
377 | 372 | ||
378 | add_todo(key, KEY_FLAG_TODO_DELETE); | 373 | add_todo(key, KEY_FLAG_TODO_DELETE); |
379 | } | 374 | } |
380 | 375 | ||
381 | void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata) | 376 | void ieee80211_key_free(struct ieee80211_key *key) |
382 | { | 377 | { |
383 | struct ieee80211_key *key; | 378 | unsigned long flags; |
384 | |||
385 | might_sleep(); | ||
386 | 379 | ||
387 | if (WARN_ON(!netif_running(sdata->dev))) | 380 | if (!key) |
388 | return; | 381 | return; |
389 | 382 | ||
390 | ieee80211_key_lock(); | 383 | spin_lock_irqsave(&key->sdata->local->key_lock, flags); |
384 | __ieee80211_key_free(key); | ||
385 | spin_unlock_irqrestore(&key->sdata->local->key_lock, flags); | ||
386 | } | ||
387 | |||
388 | /* | ||
389 | * To be safe against concurrent manipulations of the list (which shouldn't | ||
390 | * actually happen) we need to hold the spinlock. But under the spinlock we | ||
391 | * can't actually do much, so we defer processing to the todo list. Then run | ||
392 | * the todo list to be sure the operation and possibly previously pending | ||
393 | * operations are completed. | ||
394 | */ | ||
395 | static void ieee80211_todo_for_each_key(struct ieee80211_sub_if_data *sdata, | ||
396 | u32 todo_flags) | ||
397 | { | ||
398 | struct ieee80211_key *key; | ||
399 | unsigned long flags; | ||
391 | 400 | ||
401 | might_sleep(); | ||
402 | |||
403 | spin_lock_irqsave(&sdata->local->key_lock, flags); | ||
392 | list_for_each_entry(key, &sdata->key_list, list) | 404 | list_for_each_entry(key, &sdata->key_list, list) |
393 | ieee80211_key_enable_hw_accel(key); | 405 | add_todo(key, todo_flags); |
406 | spin_unlock_irqrestore(&sdata->local->key_lock, flags); | ||
394 | 407 | ||
395 | ieee80211_key_unlock(); | 408 | ieee80211_key_todo(); |
396 | } | 409 | } |
397 | 410 | ||
398 | void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata) | 411 | void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata) |
399 | { | 412 | { |
400 | struct ieee80211_key *key; | 413 | ASSERT_RTNL(); |
401 | 414 | ||
402 | might_sleep(); | 415 | if (WARN_ON(!netif_running(sdata->dev))) |
416 | return; | ||
403 | 417 | ||
404 | ieee80211_key_lock(); | 418 | ieee80211_todo_for_each_key(sdata, KEY_FLAG_TODO_HWACCEL_ADD); |
419 | } | ||
405 | 420 | ||
406 | list_for_each_entry(key, &sdata->key_list, list) | 421 | void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata) |
407 | ieee80211_key_disable_hw_accel(key); | 422 | { |
423 | ASSERT_RTNL(); | ||
408 | 424 | ||
409 | ieee80211_key_unlock(); | 425 | ieee80211_todo_for_each_key(sdata, KEY_FLAG_TODO_HWACCEL_REMOVE); |
410 | } | 426 | } |
411 | 427 | ||
412 | static void __ieee80211_key_free(struct ieee80211_key *key) | 428 | static void __ieee80211_key_destroy(struct ieee80211_key *key) |
413 | { | 429 | { |
414 | if (!key) | 430 | if (!key) |
415 | return; | 431 | return; |
@@ -440,7 +456,8 @@ static void __ieee80211_key_todo(void) | |||
440 | list_del_init(&key->todo); | 456 | list_del_init(&key->todo); |
441 | todoflags = key->flags & (KEY_FLAG_TODO_ADD_DEBUGFS | | 457 | todoflags = key->flags & (KEY_FLAG_TODO_ADD_DEBUGFS | |
442 | KEY_FLAG_TODO_DEFKEY | | 458 | KEY_FLAG_TODO_DEFKEY | |
443 | KEY_FLAG_TODO_HWACCEL | | 459 | KEY_FLAG_TODO_HWACCEL_ADD | |
460 | KEY_FLAG_TODO_HWACCEL_REMOVE | | ||
444 | KEY_FLAG_TODO_DELETE); | 461 | KEY_FLAG_TODO_DELETE); |
445 | key->flags &= ~todoflags; | 462 | key->flags &= ~todoflags; |
446 | spin_unlock(&todo_lock); | 463 | spin_unlock(&todo_lock); |
@@ -456,12 +473,16 @@ static void __ieee80211_key_todo(void) | |||
456 | ieee80211_debugfs_key_add_default(key->sdata); | 473 | ieee80211_debugfs_key_add_default(key->sdata); |
457 | work_done = true; | 474 | work_done = true; |
458 | } | 475 | } |
459 | if (todoflags & KEY_FLAG_TODO_HWACCEL) { | 476 | if (todoflags & KEY_FLAG_TODO_HWACCEL_ADD) { |
460 | ieee80211_key_enable_hw_accel(key); | 477 | ieee80211_key_enable_hw_accel(key); |
461 | work_done = true; | 478 | work_done = true; |
462 | } | 479 | } |
480 | if (todoflags & KEY_FLAG_TODO_HWACCEL_REMOVE) { | ||
481 | ieee80211_key_disable_hw_accel(key); | ||
482 | work_done = true; | ||
483 | } | ||
463 | if (todoflags & KEY_FLAG_TODO_DELETE) { | 484 | if (todoflags & KEY_FLAG_TODO_DELETE) { |
464 | __ieee80211_key_free(key); | 485 | __ieee80211_key_destroy(key); |
465 | work_done = true; | 486 | work_done = true; |
466 | } | 487 | } |
467 | 488 | ||
@@ -482,14 +503,16 @@ void ieee80211_key_todo(void) | |||
482 | void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata) | 503 | void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata) |
483 | { | 504 | { |
484 | struct ieee80211_key *key, *tmp; | 505 | struct ieee80211_key *key, *tmp; |
485 | LIST_HEAD(tmp_list); | 506 | unsigned long flags; |
486 | 507 | ||
487 | ieee80211_key_lock(); | 508 | ieee80211_key_lock(); |
488 | 509 | ||
489 | ieee80211_debugfs_key_remove_default(sdata); | 510 | ieee80211_debugfs_key_remove_default(sdata); |
490 | 511 | ||
512 | spin_lock_irqsave(&sdata->local->key_lock, flags); | ||
491 | list_for_each_entry_safe(key, tmp, &sdata->key_list, list) | 513 | list_for_each_entry_safe(key, tmp, &sdata->key_list, list) |
492 | ieee80211_key_free(key); | 514 | __ieee80211_key_free(key); |
515 | spin_unlock_irqrestore(&sdata->local->key_lock, flags); | ||
493 | 516 | ||
494 | __ieee80211_key_todo(); | 517 | __ieee80211_key_todo(); |
495 | 518 | ||
diff --git a/net/mac80211/key.h b/net/mac80211/key.h index 5d48518985b3..f52c3df1fe9a 100644 --- a/net/mac80211/key.h +++ b/net/mac80211/key.h | |||
@@ -54,16 +54,19 @@ struct sta_info; | |||
54 | * @KEY_FLAG_TODO_DELETE: Key is marked for deletion and will, after an | 54 | * @KEY_FLAG_TODO_DELETE: Key is marked for deletion and will, after an |
55 | * RCU grace period, no longer be reachable other than from the | 55 | * RCU grace period, no longer be reachable other than from the |
56 | * todo list. | 56 | * todo list. |
57 | * @KEY_FLAG_TODO_HWACCEL: Key needs to be added to hardware acceleration. | 57 | * @KEY_FLAG_TODO_HWACCEL_ADD: Key needs to be added to hardware acceleration. |
58 | * @KEY_FLAG_TODO_HWACCEL_REMOVE: Key needs to be removed from hardware | ||
59 | * acceleration. | ||
58 | * @KEY_FLAG_TODO_DEFKEY: Key is default key and debugfs needs to be updated. | 60 | * @KEY_FLAG_TODO_DEFKEY: Key is default key and debugfs needs to be updated. |
59 | * @KEY_FLAG_TODO_ADD_DEBUGFS: Key needs to be added to debugfs. | 61 | * @KEY_FLAG_TODO_ADD_DEBUGFS: Key needs to be added to debugfs. |
60 | */ | 62 | */ |
61 | enum ieee80211_internal_key_flags { | 63 | enum ieee80211_internal_key_flags { |
62 | KEY_FLAG_UPLOADED_TO_HARDWARE = BIT(0), | 64 | KEY_FLAG_UPLOADED_TO_HARDWARE = BIT(0), |
63 | KEY_FLAG_TODO_DELETE = BIT(1), | 65 | KEY_FLAG_TODO_DELETE = BIT(1), |
64 | KEY_FLAG_TODO_HWACCEL = BIT(2), | 66 | KEY_FLAG_TODO_HWACCEL_ADD = BIT(2), |
65 | KEY_FLAG_TODO_DEFKEY = BIT(3), | 67 | KEY_FLAG_TODO_HWACCEL_REMOVE = BIT(3), |
66 | KEY_FLAG_TODO_ADD_DEBUGFS = BIT(4), | 68 | KEY_FLAG_TODO_DEFKEY = BIT(4), |
69 | KEY_FLAG_TODO_ADD_DEBUGFS = BIT(5), | ||
67 | }; | 70 | }; |
68 | 71 | ||
69 | struct ieee80211_key { | 72 | struct ieee80211_key { |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index bfcbcf5353ad..e9a978979d38 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -1587,6 +1587,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
1587 | 1587 | ||
1588 | INIT_LIST_HEAD(&local->interfaces); | 1588 | INIT_LIST_HEAD(&local->interfaces); |
1589 | 1589 | ||
1590 | spin_lock_init(&local->key_lock); | ||
1591 | |||
1590 | INIT_DELAYED_WORK(&local->scan_work, ieee80211_sta_scan_work); | 1592 | INIT_DELAYED_WORK(&local->scan_work, ieee80211_sta_scan_work); |
1591 | 1593 | ||
1592 | sta_info_init(local); | 1594 | sta_info_init(local); |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index bdaab1391d4e..6b75cb6c6300 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -350,14 +350,12 @@ static void ieee80211_sta_wmm_params(struct net_device *dev, | |||
350 | } | 350 | } |
351 | } | 351 | } |
352 | 352 | ||
353 | 353 | static u32 ieee80211_handle_protect_preamb(struct ieee80211_sub_if_data *sdata, | |
354 | static u32 ieee80211_handle_erp_ie(struct ieee80211_sub_if_data *sdata, | 354 | bool use_protection, |
355 | u8 erp_value) | 355 | bool use_short_preamble) |
356 | { | 356 | { |
357 | struct ieee80211_bss_conf *bss_conf = &sdata->bss_conf; | 357 | struct ieee80211_bss_conf *bss_conf = &sdata->bss_conf; |
358 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | 358 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; |
359 | bool use_protection = (erp_value & WLAN_ERP_USE_PROTECTION) != 0; | ||
360 | bool use_short_preamble = (erp_value & WLAN_ERP_BARKER_PREAMBLE) == 0; | ||
361 | DECLARE_MAC_BUF(mac); | 359 | DECLARE_MAC_BUF(mac); |
362 | u32 changed = 0; | 360 | u32 changed = 0; |
363 | 361 | ||
@@ -388,6 +386,32 @@ static u32 ieee80211_handle_erp_ie(struct ieee80211_sub_if_data *sdata, | |||
388 | return changed; | 386 | return changed; |
389 | } | 387 | } |
390 | 388 | ||
389 | static u32 ieee80211_handle_erp_ie(struct ieee80211_sub_if_data *sdata, | ||
390 | u8 erp_value) | ||
391 | { | ||
392 | bool use_protection = (erp_value & WLAN_ERP_USE_PROTECTION) != 0; | ||
393 | bool use_short_preamble = (erp_value & WLAN_ERP_BARKER_PREAMBLE) == 0; | ||
394 | |||
395 | return ieee80211_handle_protect_preamb(sdata, | ||
396 | use_protection, use_short_preamble); | ||
397 | } | ||
398 | |||
399 | static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata, | ||
400 | struct ieee80211_sta_bss *bss) | ||
401 | { | ||
402 | u32 changed = 0; | ||
403 | |||
404 | if (bss->has_erp_value) | ||
405 | changed |= ieee80211_handle_erp_ie(sdata, bss->erp_value); | ||
406 | else { | ||
407 | u16 capab = bss->capability; | ||
408 | changed |= ieee80211_handle_protect_preamb(sdata, false, | ||
409 | (capab & WLAN_CAPABILITY_SHORT_PREAMBLE) != 0); | ||
410 | } | ||
411 | |||
412 | return changed; | ||
413 | } | ||
414 | |||
391 | int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie, | 415 | int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie, |
392 | struct ieee80211_ht_info *ht_info) | 416 | struct ieee80211_ht_info *ht_info) |
393 | { | 417 | { |
@@ -511,9 +535,7 @@ static void ieee80211_set_associated(struct net_device *dev, | |||
511 | sdata->bss_conf.beacon_int = bss->beacon_int; | 535 | sdata->bss_conf.beacon_int = bss->beacon_int; |
512 | sdata->bss_conf.timestamp = bss->timestamp; | 536 | sdata->bss_conf.timestamp = bss->timestamp; |
513 | 537 | ||
514 | if (bss->has_erp_value) | 538 | changed |= ieee80211_handle_bss_capability(sdata, bss); |
515 | changed |= ieee80211_handle_erp_ie( | ||
516 | sdata, bss->erp_value); | ||
517 | 539 | ||
518 | ieee80211_rx_bss_put(dev, bss); | 540 | ieee80211_rx_bss_put(dev, bss); |
519 | } | 541 | } |
@@ -2566,22 +2588,29 @@ static void ieee80211_rx_bss_info(struct net_device *dev, | |||
2566 | #endif | 2588 | #endif |
2567 | } | 2589 | } |
2568 | 2590 | ||
2569 | bss->band = rx_status->band; | ||
2570 | |||
2571 | if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS && | ||
2572 | bss->probe_resp && beacon) { | ||
2573 | /* STA mode: | ||
2574 | * Do not allow beacon to override data from Probe Response. */ | ||
2575 | ieee80211_rx_bss_put(dev, bss); | ||
2576 | return; | ||
2577 | } | ||
2578 | |||
2579 | /* save the ERP value so that it is available at association time */ | 2591 | /* save the ERP value so that it is available at association time */ |
2580 | if (elems.erp_info && elems.erp_info_len >= 1) { | 2592 | if (elems.erp_info && elems.erp_info_len >= 1) { |
2581 | bss->erp_value = elems.erp_info[0]; | 2593 | bss->erp_value = elems.erp_info[0]; |
2582 | bss->has_erp_value = 1; | 2594 | bss->has_erp_value = 1; |
2583 | } | 2595 | } |
2584 | 2596 | ||
2597 | if (elems.ht_cap_elem && | ||
2598 | (!bss->ht_ie || bss->ht_ie_len != elems.ht_cap_elem_len || | ||
2599 | memcmp(bss->ht_ie, elems.ht_cap_elem, elems.ht_cap_elem_len))) { | ||
2600 | kfree(bss->ht_ie); | ||
2601 | bss->ht_ie = kmalloc(elems.ht_cap_elem_len + 2, GFP_ATOMIC); | ||
2602 | if (bss->ht_ie) { | ||
2603 | memcpy(bss->ht_ie, elems.ht_cap_elem - 2, | ||
2604 | elems.ht_cap_elem_len + 2); | ||
2605 | bss->ht_ie_len = elems.ht_cap_elem_len + 2; | ||
2606 | } else | ||
2607 | bss->ht_ie_len = 0; | ||
2608 | } else if (!elems.ht_cap_elem && bss->ht_ie) { | ||
2609 | kfree(bss->ht_ie); | ||
2610 | bss->ht_ie = NULL; | ||
2611 | bss->ht_ie_len = 0; | ||
2612 | } | ||
2613 | |||
2585 | bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int); | 2614 | bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int); |
2586 | bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info); | 2615 | bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info); |
2587 | 2616 | ||
@@ -2603,6 +2632,26 @@ static void ieee80211_rx_bss_info(struct net_device *dev, | |||
2603 | bss->supp_rates_len += clen; | 2632 | bss->supp_rates_len += clen; |
2604 | } | 2633 | } |
2605 | 2634 | ||
2635 | bss->band = rx_status->band; | ||
2636 | |||
2637 | bss->timestamp = beacon_timestamp; | ||
2638 | bss->last_update = jiffies; | ||
2639 | bss->rssi = rx_status->ssi; | ||
2640 | bss->signal = rx_status->signal; | ||
2641 | bss->noise = rx_status->noise; | ||
2642 | if (!beacon && !bss->probe_resp) | ||
2643 | bss->probe_resp = true; | ||
2644 | |||
2645 | /* | ||
2646 | * In STA mode, the remaining parameters should not be overridden | ||
2647 | * by beacons because they're not necessarily accurate there. | ||
2648 | */ | ||
2649 | if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS && | ||
2650 | bss->probe_resp && beacon) { | ||
2651 | ieee80211_rx_bss_put(dev, bss); | ||
2652 | return; | ||
2653 | } | ||
2654 | |||
2606 | if (elems.wpa && | 2655 | if (elems.wpa && |
2607 | (!bss->wpa_ie || bss->wpa_ie_len != elems.wpa_len || | 2656 | (!bss->wpa_ie || bss->wpa_ie_len != elems.wpa_len || |
2608 | memcmp(bss->wpa_ie, elems.wpa, elems.wpa_len))) { | 2657 | memcmp(bss->wpa_ie, elems.wpa, elems.wpa_len))) { |
@@ -2635,6 +2684,20 @@ static void ieee80211_rx_bss_info(struct net_device *dev, | |||
2635 | bss->rsn_ie_len = 0; | 2684 | bss->rsn_ie_len = 0; |
2636 | } | 2685 | } |
2637 | 2686 | ||
2687 | /* | ||
2688 | * Cf. | ||
2689 | * http://www.wipo.int/pctdb/en/wo.jsp?wo=2007047181&IA=WO2007047181&DISPLAY=DESC | ||
2690 | * | ||
2691 | * quoting: | ||
2692 | * | ||
2693 | * In particular, "Wi-Fi CERTIFIED for WMM - Support for Multimedia | ||
2694 | * Applications with Quality of Service in Wi-Fi Networks," Wi- Fi | ||
2695 | * Alliance (September 1, 2004) is incorporated by reference herein. | ||
2696 | * The inclusion of the WMM Parameters in probe responses and | ||
2697 | * association responses is mandatory for WMM enabled networks. The | ||
2698 | * inclusion of the WMM Parameters in beacons, however, is optional. | ||
2699 | */ | ||
2700 | |||
2638 | if (elems.wmm_param && | 2701 | if (elems.wmm_param && |
2639 | (!bss->wmm_ie || bss->wmm_ie_len != elems.wmm_param_len || | 2702 | (!bss->wmm_ie || bss->wmm_ie_len != elems.wmm_param_len || |
2640 | memcmp(bss->wmm_ie, elems.wmm_param, elems.wmm_param_len))) { | 2703 | memcmp(bss->wmm_ie, elems.wmm_param, elems.wmm_param_len))) { |
@@ -2651,30 +2714,6 @@ static void ieee80211_rx_bss_info(struct net_device *dev, | |||
2651 | bss->wmm_ie = NULL; | 2714 | bss->wmm_ie = NULL; |
2652 | bss->wmm_ie_len = 0; | 2715 | bss->wmm_ie_len = 0; |
2653 | } | 2716 | } |
2654 | if (elems.ht_cap_elem && | ||
2655 | (!bss->ht_ie || bss->ht_ie_len != elems.ht_cap_elem_len || | ||
2656 | memcmp(bss->ht_ie, elems.ht_cap_elem, elems.ht_cap_elem_len))) { | ||
2657 | kfree(bss->ht_ie); | ||
2658 | bss->ht_ie = kmalloc(elems.ht_cap_elem_len + 2, GFP_ATOMIC); | ||
2659 | if (bss->ht_ie) { | ||
2660 | memcpy(bss->ht_ie, elems.ht_cap_elem - 2, | ||
2661 | elems.ht_cap_elem_len + 2); | ||
2662 | bss->ht_ie_len = elems.ht_cap_elem_len + 2; | ||
2663 | } else | ||
2664 | bss->ht_ie_len = 0; | ||
2665 | } else if (!elems.ht_cap_elem && bss->ht_ie) { | ||
2666 | kfree(bss->ht_ie); | ||
2667 | bss->ht_ie = NULL; | ||
2668 | bss->ht_ie_len = 0; | ||
2669 | } | ||
2670 | |||
2671 | bss->timestamp = beacon_timestamp; | ||
2672 | bss->last_update = jiffies; | ||
2673 | bss->rssi = rx_status->ssi; | ||
2674 | bss->signal = rx_status->signal; | ||
2675 | bss->noise = rx_status->noise; | ||
2676 | if (!beacon) | ||
2677 | bss->probe_resp++; | ||
2678 | 2717 | ||
2679 | /* check if we need to merge IBSS */ | 2718 | /* check if we need to merge IBSS */ |
2680 | if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && beacon && | 2719 | if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && beacon && |
@@ -2775,8 +2814,24 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev, | |||
2775 | 2814 | ||
2776 | ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems); | 2815 | ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems); |
2777 | 2816 | ||
2817 | if (elems.wmm_param && (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) { | ||
2818 | ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param, | ||
2819 | elems.wmm_param_len); | ||
2820 | } | ||
2821 | |||
2822 | /* Do not send changes to driver if we are scanning. This removes | ||
2823 | * requirement that driver's bss_info_changed function needs to be | ||
2824 | * atomic. */ | ||
2825 | if (local->sta_sw_scanning || local->sta_hw_scanning) | ||
2826 | return; | ||
2827 | |||
2778 | if (elems.erp_info && elems.erp_info_len >= 1) | 2828 | if (elems.erp_info && elems.erp_info_len >= 1) |
2779 | changed |= ieee80211_handle_erp_ie(sdata, elems.erp_info[0]); | 2829 | changed |= ieee80211_handle_erp_ie(sdata, elems.erp_info[0]); |
2830 | else { | ||
2831 | u16 capab = le16_to_cpu(mgmt->u.beacon.capab_info); | ||
2832 | changed |= ieee80211_handle_protect_preamb(sdata, false, | ||
2833 | (capab & WLAN_CAPABILITY_SHORT_PREAMBLE) != 0); | ||
2834 | } | ||
2780 | 2835 | ||
2781 | if (elems.ht_cap_elem && elems.ht_info_elem && | 2836 | if (elems.ht_cap_elem && elems.ht_info_elem && |
2782 | elems.wmm_param && conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) { | 2837 | elems.wmm_param && conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) { |
@@ -2789,11 +2844,6 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev, | |||
2789 | &bss_info); | 2844 | &bss_info); |
2790 | } | 2845 | } |
2791 | 2846 | ||
2792 | if (elems.wmm_param && (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) { | ||
2793 | ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param, | ||
2794 | elems.wmm_param_len); | ||
2795 | } | ||
2796 | |||
2797 | ieee80211_bss_info_change_notify(sdata, changed); | 2847 | ieee80211_bss_info_change_notify(sdata, changed); |
2798 | } | 2848 | } |
2799 | 2849 | ||
diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 69aed16faff3..76e1de1dc735 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c | |||
@@ -236,6 +236,9 @@ static int ieee80211_ioctl_siwmode(struct net_device *dev, | |||
236 | case IW_MODE_ADHOC: | 236 | case IW_MODE_ADHOC: |
237 | type = IEEE80211_IF_TYPE_IBSS; | 237 | type = IEEE80211_IF_TYPE_IBSS; |
238 | break; | 238 | break; |
239 | case IW_MODE_REPEAT: | ||
240 | type = IEEE80211_IF_TYPE_WDS; | ||
241 | break; | ||
239 | case IW_MODE_MONITOR: | 242 | case IW_MODE_MONITOR: |
240 | type = IEEE80211_IF_TYPE_MNTR; | 243 | type = IEEE80211_IF_TYPE_MNTR; |
241 | break; | 244 | break; |
@@ -980,6 +983,8 @@ static struct iw_statistics *ieee80211_get_wireless_stats(struct net_device *dev | |||
980 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 983 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
981 | struct sta_info *sta = NULL; | 984 | struct sta_info *sta = NULL; |
982 | 985 | ||
986 | rcu_read_lock(); | ||
987 | |||
983 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA || | 988 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA || |
984 | sdata->vif.type == IEEE80211_IF_TYPE_IBSS) | 989 | sdata->vif.type == IEEE80211_IF_TYPE_IBSS) |
985 | sta = sta_info_get(local, sdata->u.sta.bssid); | 990 | sta = sta_info_get(local, sdata->u.sta.bssid); |
@@ -996,6 +1001,9 @@ static struct iw_statistics *ieee80211_get_wireless_stats(struct net_device *dev | |||
996 | wstats->qual.noise = sta->last_noise; | 1001 | wstats->qual.noise = sta->last_noise; |
997 | wstats->qual.updated = local->wstats_flags; | 1002 | wstats->qual.updated = local->wstats_flags; |
998 | } | 1003 | } |
1004 | |||
1005 | rcu_read_unlock(); | ||
1006 | |||
999 | return wstats; | 1007 | return wstats; |
1000 | } | 1008 | } |
1001 | 1009 | ||