aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2008-04-16 22:37:51 -0400
committerDavid S. Miller <davem@davemloft.net>2008-04-16 22:37:51 -0400
commit8c95b4773dd8d0415269ffad7301ef96d75be8ee (patch)
tree996401ce91c2a652fcff690e2c8bf88f2014d307
parentbcff122d478b774f4fd5262f35eedebe2f2fb274 (diff)
parent30b89b0f5e1313c8a5a039abeaa89248b6338d81 (diff)
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/linville/wireless-2.6.26
-rw-r--r--drivers/net/wireless/ath5k/ath5k.h11
-rw-r--r--drivers/net/wireless/ath5k/base.c14
-rw-r--r--drivers/net/wireless/ath5k/hw.c152
-rw-r--r--drivers/net/wireless/ath5k/initvals.c234
-rw-r--r--drivers/net/wireless/ath5k/phy.c123
-rw-r--r--drivers/net/wireless/ath5k/regdom.c121
-rw-r--r--drivers/net/wireless/ath5k/regdom.h500
-rw-r--r--drivers/net/wireless/b43/main.c7
-rw-r--r--drivers/net/wireless/b43legacy/b43legacy.h3
-rw-r--r--drivers/net/wireless/b43legacy/main.c34
-rw-r--r--drivers/net/wireless/iwlwifi/Kconfig2
-rw-r--r--drivers/net/wireless/iwlwifi/Makefile29
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945-hw.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965-commands.h50
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965-hw.h22
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965-rs.c65
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.c373
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.h41
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c13
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h32
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debugfs.c73
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-hcmd.c1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-rfkill.c3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-rfkill.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sta.c355
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sta.h49
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c6
-rw-r--r--drivers/net/wireless/iwlwifi/iwl4965-base.c575
-rw-r--r--drivers/net/wireless/libertas/cmd.c32
-rw-r--r--drivers/net/wireless/libertas/cmdresp.c23
-rw-r--r--drivers/net/wireless/libertas/debugfs.c1
-rw-r--r--drivers/net/wireless/libertas/decl.h10
-rw-r--r--drivers/net/wireless/libertas/defs.h2
-rw-r--r--drivers/net/wireless/libertas/dev.h27
-rw-r--r--drivers/net/wireless/libertas/if_cs.c244
-rw-r--r--drivers/net/wireless/libertas/if_sdio.c65
-rw-r--r--drivers/net/wireless/libertas/if_usb.c71
-rw-r--r--drivers/net/wireless/libertas/if_usb.h2
-rw-r--r--drivers/net/wireless/libertas/main.c158
-rw-r--r--drivers/net/wireless/libertas/rx.c4
-rw-r--r--drivers/net/wireless/libertas/tx.c20
-rw-r--r--drivers/net/wireless/ray_cs.c73
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c6
-rw-r--r--drivers/ssb/driver_pcicore.c12
-rw-r--r--include/net/mac80211.h3
-rw-r--r--net/mac80211/cfg.c22
-rw-r--r--net/mac80211/ieee80211_i.h12
-rw-r--r--net/mac80211/key.c101
-rw-r--r--net/mac80211/key.h11
-rw-r--r--net/mac80211/main.c2
-rw-r--r--net/mac80211/mlme.c144
-rw-r--r--net/mac80211/wext.c8
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
452struct 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);
1069extern bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah); 1062extern bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah);
1070extern int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask); 1063extern int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask);
1071extern enum ath5k_int ath5k_hw_set_intr(struct ath5k_hw *ah, enum ath5k_int new_mask); 1064extern enum ath5k_int ath5k_hw_set_intr(struct ath5k_hw *ah, enum ath5k_int new_mask);
1065extern void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, struct ieee80211_low_level_stats *stats);
1072/* EEPROM access functions */ 1066/* EEPROM access functions */
1073extern int ath5k_hw_set_regdomain(struct ath5k_hw *ah, u16 regdomain); 1067extern 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
1097extern void ath5k_hw_reset_beacon(struct ath5k_hw *ah); 1091extern void ath5k_hw_reset_beacon(struct ath5k_hw *ah);
1098extern int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr); 1092extern int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr);
1099#endif 1093#endif
1100extern void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, struct ath5k_mib_stats *statistics);
1101/* ACK bit rate */ 1094/* ACK bit rate */
1102void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high); 1095void 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 */
125static 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 */
125struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) 182struct 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 */
2851void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, 2957void 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 */
1288static 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 */
670static const struct ath5k_ini_rf rfregs_2413[] = { 670static 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 */
741static 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 */
740static const struct ath5k_ini_rfgain rfgain_5112[] = { 818static 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 */
1353static int ath5k_hw_rf5413_rfregs(struct ath5k_hw *ah, 1432static 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
26static 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
82enum 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
99u16 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
115enum 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
27enum 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
107enum 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
231struct 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
496enum ath5k_regdom ath5k_regdom2flag(enum ath5k_regdom, u16);
497u16 ath5k_regdom_from_ieee(enum ath5k_regdom ieee);
498enum 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
3008static 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. */
3022static 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 */
3010static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev) 3038static 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
9config IWLCORE_RFKILL 9config 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 @@
1obj-$(CONFIG_IWLCORE) += iwlcore.o 1obj-$(CONFIG_IWLCORE) := iwlcore.o
2iwlcore-objs = iwl-core.o iwl-eeprom.o iwl-hcmd.o 2iwlcore-objs := iwl-core.o iwl-eeprom.o iwl-hcmd.o
3 3iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o
4ifeq ($(CONFIG_IWLWIFI_DEBUGFS),y) 4iwlcore-$(CONFIG_IWLWIFI_LEDS) += iwl-led.o
5 iwlcore-objs += iwl-debugfs.o 5iwlcore-$(CONFIG_IWLWIFI_RFKILL) += iwl-rfkill.o
6endif
7
8ifeq ($(CONFIG_IWLWIFI_LEDS),y)
9 iwlcore-objs += iwl-led.o
10endif
11
12ifeq ($(CONFIG_IWLCORE_RFKILL),y)
13 iwlcore-objs += iwl-rfkill.o
14endif
15 6
16obj-$(CONFIG_IWL3945) += iwl3945.o 7obj-$(CONFIG_IWL3945) += iwl3945.o
17iwl3945-objs = iwl3945-base.o iwl-3945.o iwl-3945-rs.o 8iwl3945-objs := iwl3945-base.o iwl-3945.o iwl-3945-rs.o
18 9iwl3945-$(CONFIG_IWL3945_LEDS) += iwl-3945-led.o
19ifeq ($(CONFIG_IWL3945_LEDS),y)
20 iwl3945-objs += iwl-3945-led.o
21endif
22
23 10
24obj-$(CONFIG_IWL4965) += iwl4965.o 11obj-$(CONFIG_IWL4965) += iwl4965.o
25iwl4965-objs = iwl4965-base.o iwl-4965.o iwl-4965-rs.o 12iwl4965-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
461static inline int iwl3945_hw_valid_rtc_data_addr(u32 addr) 461static 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
690struct iwl3945_priv { 692struct 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 */
858struct 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
867struct 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 */
1394struct iwl4965_link_qual_general_params { 1420struct 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 */
1425struct iwl4965_link_qual_agg_params { 1451struct 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 */
1635struct iwl4965_link_quality_cmd { 1661struct 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 */
1554struct iwl4965_shared { 1554struct 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);
174static void rs_fill_link_cmd(struct iwl4965_lq_sta *lq_sta, 174static 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
233static 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
240static inline u8 iwl4965_rate_get_rate(u32 rate_n_flags) 233static 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
245static 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
285static void rs_rate_scale_clear_window(struct iwl4965_rate_scale_data *window) 238static 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
2393static void rs_fill_link_cmd(struct iwl4965_lq_sta *lq_sta, 2346static 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 */
48static struct iwl_mod_params iwl4965_mod_params = { 48static 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 */
118static 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 */
180static 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
117static int iwl4965_init_drv(struct iwl_priv *priv) 262static 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
402static int iwl4965_rx_init(struct iwl_priv *priv, struct iwl4965_rx_queue *rxq) 559static 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 */
833static void iwl4965_bg_statistics_periodic(unsigned long data) 986static 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 */
845static 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 */
1880int iwl4965_hw_set_hw_setting(struct iwl_priv *priv) 2021int 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
1919out: 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
2887static 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
2759int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel) 2927int 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
2870int iwl4965_hw_get_rx_read(struct iwl_priv *priv) 3038int 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
2877int iwl4965_hw_get_temperature(struct iwl_priv *priv) 3044int 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 */
3001int iwl4965_tx_queue_update_wr_ptr(struct iwl_priv *priv, 3168static 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,
4361void iwl4965_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap) 4524void 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)
4767void iwl4965_hw_setup_deferred_work(struct iwl_priv *priv) 4930void 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
4949static struct iwl_hcmd_ops iwl4965_hcmd = {
4950 .rxon_assoc = iwl4965_send_rxon_assoc,
4951};
4952
4786static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = { 4953static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = {
4787 .enqueue_hcmd = iwl4965_enqueue_hcmd, 4954 .enqueue_hcmd = iwl4965_enqueue_hcmd,
4788}; 4955};
4789 4956
4790static struct iwl_lib_ops iwl4965_lib = { 4957static 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
4800static struct iwl_ops iwl4965_ops = { 4973static 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
4805static struct iwl_cfg iwl4965_agn_cfg = { 4979struct 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
4813struct 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
4819MODULE_DEVICE_TABLE(pci, iwl4965_hw_card_ids);
4820
4821module_param_named(antenna, iwl4965_mod_params.antenna, int, 0444); 4987module_param_named(antenna, iwl4965_mod_params.antenna, int, 0444);
4822MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); 4988MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])");
4823module_param_named(disable, iwl4965_mod_params.disable, int, 0444); 4989module_param_named(disable, iwl4965_mod_params.disable, int, 0444);
4824MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])"); 4990MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])");
4825module_param_named(hwcrypto, iwl4965_mod_params.hw_crypto, int, 0444); 4991module_param_named(swcrypto, iwl4965_mod_params.sw_crypto, int, 0444);
4826MODULE_PARM_DESC(hwcrypto, 4992MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])\n");
4827 "using hardware crypto engine (default 0 [software])\n");
4828module_param_named(debug, iwl4965_mod_params.debug, int, 0444); 4993module_param_named(debug, iwl4965_mod_params.debug, int, 0444);
4829MODULE_PARM_DESC(debug, "debug output mask"); 4994MODULE_PARM_DESC(debug, "debug output mask");
4830module_param_named( 4995module_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 */
40extern 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 */
49extern 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 {
461struct iwl4965_hw_key { 461struct 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 */
581struct iwl4965_driver_hw_info { 580struct 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);
642extern int iwl4965_rx_queue_update_write_ptr(struct iwl_priv *priv, 642extern int iwl4965_rx_queue_update_write_ptr(struct iwl_priv *priv,
643 struct iwl4965_rx_queue *q); 643 struct iwl4965_rx_queue *q);
644extern int iwl4965_send_statistics_request(struct iwl_priv *priv);
645extern void iwl4965_set_decrypted_flag(struct iwl_priv *priv, struct sk_buff *skb, 644extern 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);
679extern void iwl4965_hw_setup_deferred_work(struct iwl_priv *priv); 678extern void iwl4965_hw_setup_deferred_work(struct iwl_priv *priv);
680extern void iwl4965_hw_cancel_deferred_work(struct iwl_priv *priv); 679extern void iwl4965_hw_cancel_deferred_work(struct iwl_priv *priv);
681extern int iwl4965_hw_rxq_stop(struct iwl_priv *priv); 680extern int iwl4965_hw_rxq_stop(struct iwl_priv *priv);
682extern int iwl4965_hw_set_hw_setting(struct iwl_priv *priv); 681extern int iwl4965_hw_set_hw_params(struct iwl_priv *priv);
683extern int iwl4965_hw_nic_init(struct iwl_priv *priv); 682extern int iwl4965_hw_nic_init(struct iwl_priv *priv);
684extern int iwl4965_hw_nic_stop_master(struct iwl_priv *priv); 683extern int iwl4965_hw_nic_stop_master(struct iwl_priv *priv);
685extern void iwl4965_hw_txq_ctx_free(struct iwl_priv *priv); 684extern 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
945struct iwl_priv { 946struct 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}
278EXPORT_SYMBOL(iwlcore_low_level_notify); 278EXPORT_SYMBOL(iwlcore_low_level_notify);
279 279
280int 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}
291EXPORT_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
85struct iwl_hcmd_ops {
86 int (*rxon_assoc)(struct iwl_priv *priv);
87};
85struct iwl_hcmd_utils_ops { 88struct 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 {
89struct iwl_lib_ops { 92struct 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
97struct iwl_ops { 115struct 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
102struct iwl_mod_params { 121struct 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
216int iwlcore_low_level_notify(struct iwl_priv *priv, 235int iwlcore_low_level_notify(struct iwl_priv *priv,
217 enum iwlcore_card_notify notify); 236 enum iwlcore_card_notify notify);
237extern int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags);
238int iwl_send_lq_cmd(struct iwl_priv *priv,
239 struct iwl_link_quality_cmd *lq, u8 flags);
240
241static 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
38struct iwl_rfkill_mngr { 38struct 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
41int 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
52int 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
95int 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
115int 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
142static 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
190static 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
230static 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
259int 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
283int 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
309static 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
323static inline void iwl_dump_lq_cmd(struct iwl_priv *priv,
324 struct iwl_link_quality_cmd *lq)
325{
326}
327#endif
328
329int 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}
354EXPORT_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
40int iwl_get_free_ucode_key_index(struct iwl_priv *priv);
41int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty);
42int iwl_remove_default_wep_key(struct iwl_priv *priv,
43 struct ieee80211_key_conf *key);
44int iwl_set_default_wep_key(struct iwl_priv *priv,
45 struct ieee80211_key_conf *key);
46int iwl_remove_dynamic_key(struct iwl_priv *priv, u8 sta_id);
47int 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 */
70static int iwl3945_param_antenna; /* def: 0 = both antennas (use diversity) */ 70static int iwl3945_param_antenna; /* def: 0 = both antennas (use diversity) */
71int iwl3945_param_hwcrypto; /* def: 0 = use software encryption */ 71int iwl3945_param_hwcrypto; /* def: 0 = use software encryption */
72static int iwl3945_param_qos_enable = 1; /* def: 1 = use quality of service */ 72static int iwl3945_param_qos_enable = 1; /* def: 1 = use quality of service */
73int iwl3945_param_queues_num = IWL_MAX_NUM_QUEUES; /* def: 8 Tx queues */ 73int 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
54static int iwl4965_tx_queue_update_write_ptr(struct iwl_priv *priv, 55static 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
598int 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
758static 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
1111static 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
1152static 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
1179static 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
1196static 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
1219static int iwl4965_remove_static_key(struct iwl_priv *priv)
1220{
1221 int ret = -EOPNOTSUPP;
1222
1223 return ret;
1224}
1225
1226static 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
1236static void iwl4965_clear_free_frames(struct iwl_priv *priv) 1054static 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
1356static void iwl4965_unset_hw_setting(struct iwl_priv *priv) 1174static 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 */
5180static 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 */
5242static 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
5328static void iwl4965_nic_start(struct iwl_priv *priv) 5014static 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 */
5635static void iwl4965_alive_start(struct iwl_priv *priv) 5321static 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
5836static int __iwl4965_up(struct iwl_priv *priv) 5522static 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
6275static void iwl4965_bg_post_associate(struct work_struct *data) 5962static 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
6071static 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
6388static void iwl4965_bg_abort_scan(struct work_struct *work) 6082static 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
8276static struct pci_driver iwl4965_driver = { 7983/* Hardware specific file defines the PCI IDs table for that hardware module */
7984static 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};
7989MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids);
7990
7991static 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
8316error_debug: 8031error_debug:
8317 pci_unregister_driver(&iwl4965_driver); 8032 pci_unregister_driver(&iwl_driver);
8318#endif 8033#endif
8319error_register: 8034error_register:
8320 iwl4965_rate_control_unregister(); 8035 iwl4965_rate_control_unregister();
@@ -8324,9 +8039,9 @@ error_register:
8324static void __exit iwl4965_exit(void) 8039static 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
1851out:
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
387int lbs_process_rx_command(struct lbs_private *priv) 387int 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
572int lbs_process_event(struct lbs_private *priv) 572int 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 */
826static struct debug_data items[] = { 826static 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
20void lbs_set_mac_control(struct lbs_private *priv); 20void lbs_set_mac_control(struct lbs_private *priv);
21 21
22void lbs_send_tx_feedback(struct lbs_private *priv); 22void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count);
23 23
24int lbs_free_cmd_buffer(struct lbs_private *priv); 24int 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
31int lbs_allocate_cmd_buffer(struct lbs_private *priv); 31int lbs_allocate_cmd_buffer(struct lbs_private *priv);
32int lbs_execute_next_command(struct lbs_private *priv); 32int lbs_execute_next_command(struct lbs_private *priv);
33int lbs_process_event(struct lbs_private *priv); 33int lbs_process_event(struct lbs_private *priv, u32 event);
34void lbs_interrupt(struct lbs_private *priv); 34void lbs_queue_event(struct lbs_private *priv, u32 event);
35void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx);
36
35int lbs_set_radio_control(struct lbs_private *priv); 37int lbs_set_radio_control(struct lbs_private *priv);
36u32 lbs_fw_index_to_data_rate(u8 index); 38u32 lbs_fw_index_to_data_rate(u8 index);
37u8 lbs_data_rate_to_fw_index(u32 rate); 39u8 lbs_data_rate_to_fw_index(u32 rate);
38 40
39/** The proc fs interface */ 41/** The proc fs interface */
40int lbs_process_rx_command(struct lbs_private *priv); 42int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len);
41void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd, 43void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
42 int result); 44 int result);
43int lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev); 45int 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}
89static inline unsigned int if_cs_read16(struct if_cs_card *card, uint reg) 89static 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}
96static inline void if_cs_read16_rep( 96static 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(
108static inline void if_cs_write8(struct if_cs_card *card, uint reg, u8 val) 108static 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
115static inline void if_cs_write16(struct if_cs_card *card, uint reg, u16 val) 115static 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
232static 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
238static 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
244static 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 */
352static int if_cs_receive_cmdres(struct lbs_private *priv, u8 *data, u32 *len) 292static 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
381out: 328out:
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
376static 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
382static 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
389static 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
645static 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
665sbi_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
685out:
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
691static 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)
129static int if_sdio_handle_cmd(struct if_sdio_card *card, 127static 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
155out: 156out:
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
239out: 227out:
@@ -770,37 +758,6 @@ out:
770 return ret; 758 return ret;
771} 759}
772 760
773static 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
789static 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);
38static int if_usb_prog_firmware(struct if_usb_card *cardp); 38static int if_usb_prog_firmware(struct if_usb_card *cardp);
39static int if_usb_host_to_card(struct lbs_private *priv, uint8_t type, 39static 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);
41static int if_usb_get_int_status(struct lbs_private *priv, uint8_t *);
42static int if_usb_read_event_cause(struct lbs_private *);
43static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload, 41static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload,
44 uint16_t nb); 42 uint16_t nb);
45static void if_usb_free(struct if_usb_card *cardp); 43static 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
588static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff, 583static 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 */
726static 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
738static 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
1052out: 1054out:
@@ -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/** 1441void 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)
1445void 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}
1458EXPORT_SYMBOL_GPL(lbs_queue_event);
1459
1460void 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}
1457EXPORT_SYMBOL_GPL(lbs_interrupt); 1475EXPORT_SYMBOL_GPL(lbs_notify_command_response);
1458 1476
1459static int __init lbs_init_module(void) 1477static 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 */
182void lbs_send_tx_feedback(struct lbs_private *priv) 182void 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 "};
2582static char *framing[] = {"Encapsulation", "Translation"} 2583static char *framing[] = {"Encapsulation", "Translation"}
2583; 2584;
2584/*===========================================================================*/ 2585/*===========================================================================*/
2585static int ray_cs_proc_read(char *buf, char **start, off_t offset, int len) 2586static 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
2685static int ray_cs_proc_open(struct inode *inode, struct file *file)
2686{
2687 return single_open(file, ray_cs_proc_show, NULL);
2688}
2689
2690static 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/*===========================================================================*/
2688static int build_auth_frame(ray_dev_t *local, UCHAR *dest, int auth_type) 2699static 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
361void ieee80211_key_free(struct ieee80211_key *key) 364static 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
381void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata) 376void 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 */
395static 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
398void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata) 411void 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) 421void 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
412static void __ieee80211_key_free(struct ieee80211_key *key) 428static 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)
482void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata) 503void 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 */
61enum ieee80211_internal_key_flags { 63enum 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
69struct ieee80211_key { 72struct 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 353static u32 ieee80211_handle_protect_preamb(struct ieee80211_sub_if_data *sdata,
354static 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
389static 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
399static 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
391int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie, 415int 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