diff options
100 files changed, 2886 insertions, 1030 deletions
diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index 32bf79e6a320..a9111e1161fd 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c | |||
@@ -1945,7 +1945,8 @@ static int ar9170_conf_tx(struct ieee80211_hw *hw, u16 queue, | |||
1945 | static int ar9170_ampdu_action(struct ieee80211_hw *hw, | 1945 | static int ar9170_ampdu_action(struct ieee80211_hw *hw, |
1946 | struct ieee80211_vif *vif, | 1946 | struct ieee80211_vif *vif, |
1947 | enum ieee80211_ampdu_mlme_action action, | 1947 | enum ieee80211_ampdu_mlme_action action, |
1948 | struct ieee80211_sta *sta, u16 tid, u16 *ssn) | 1948 | struct ieee80211_sta *sta, u16 tid, u16 *ssn, |
1949 | u8 buf_size) | ||
1949 | { | 1950 | { |
1950 | switch (action) { | 1951 | switch (action) { |
1951 | case IEEE80211_AMPDU_RX_START: | 1952 | case IEEE80211_AMPDU_RX_START: |
diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h index e43210c8585c..a6c6a466000f 100644 --- a/drivers/net/wireless/ath/ath.h +++ b/drivers/net/wireless/ath/ath.h | |||
@@ -108,12 +108,14 @@ enum ath_cipher { | |||
108 | * struct ath_ops - Register read/write operations | 108 | * struct ath_ops - Register read/write operations |
109 | * | 109 | * |
110 | * @read: Register read | 110 | * @read: Register read |
111 | * @multi_read: Multiple register read | ||
111 | * @write: Register write | 112 | * @write: Register write |
112 | * @enable_write_buffer: Enable multiple register writes | 113 | * @enable_write_buffer: Enable multiple register writes |
113 | * @write_flush: flush buffered register writes and disable buffering | 114 | * @write_flush: flush buffered register writes and disable buffering |
114 | */ | 115 | */ |
115 | struct ath_ops { | 116 | struct ath_ops { |
116 | unsigned int (*read)(void *, u32 reg_offset); | 117 | unsigned int (*read)(void *, u32 reg_offset); |
118 | void (*multi_read)(void *, u32 *addr, u32 *val, u16 count); | ||
117 | void (*write)(void *, u32 val, u32 reg_offset); | 119 | void (*write)(void *, u32 val, u32 reg_offset); |
118 | void (*enable_write_buffer)(void *); | 120 | void (*enable_write_buffer)(void *); |
119 | void (*write_flush) (void *); | 121 | void (*write_flush) (void *); |
diff --git a/drivers/net/wireless/ath/ath5k/ahb.c b/drivers/net/wireless/ath/ath5k/ahb.c index 707cde149248..ae84b86c3bf2 100644 --- a/drivers/net/wireless/ath/ath5k/ahb.c +++ b/drivers/net/wireless/ath/ath5k/ahb.c | |||
@@ -31,7 +31,8 @@ static void ath5k_ahb_read_cachesize(struct ath_common *common, int *csz) | |||
31 | *csz = L1_CACHE_BYTES >> 2; | 31 | *csz = L1_CACHE_BYTES >> 2; |
32 | } | 32 | } |
33 | 33 | ||
34 | bool ath5k_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data) | 34 | static bool |
35 | ath5k_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data) | ||
35 | { | 36 | { |
36 | struct ath5k_softc *sc = common->priv; | 37 | struct ath5k_softc *sc = common->priv; |
37 | struct platform_device *pdev = to_platform_device(sc->dev); | 38 | struct platform_device *pdev = to_platform_device(sc->dev); |
@@ -46,10 +47,10 @@ bool ath5k_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data) | |||
46 | 47 | ||
47 | eeprom += off; | 48 | eeprom += off; |
48 | if (eeprom > eeprom_end) | 49 | if (eeprom > eeprom_end) |
49 | return -EINVAL; | 50 | return false; |
50 | 51 | ||
51 | *data = *eeprom; | 52 | *data = *eeprom; |
52 | return 0; | 53 | return true; |
53 | } | 54 | } |
54 | 55 | ||
55 | int ath5k_hw_read_srev(struct ath5k_hw *ah) | 56 | int ath5k_hw_read_srev(struct ath5k_hw *ah) |
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 09ae4ef0fd51..dae0bdcef257 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
@@ -242,73 +242,68 @@ static int ath5k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *re | |||
242 | \********************/ | 242 | \********************/ |
243 | 243 | ||
244 | /* | 244 | /* |
245 | * Convert IEEE channel number to MHz frequency. | ||
246 | */ | ||
247 | static inline short | ||
248 | ath5k_ieee2mhz(short chan) | ||
249 | { | ||
250 | if (chan <= 14 || chan >= 27) | ||
251 | return ieee80211chan2mhz(chan); | ||
252 | else | ||
253 | return 2212 + chan * 20; | ||
254 | } | ||
255 | |||
256 | /* | ||
257 | * Returns true for the channel numbers used without all_channels modparam. | 245 | * Returns true for the channel numbers used without all_channels modparam. |
258 | */ | 246 | */ |
259 | static bool ath5k_is_standard_channel(short chan) | 247 | static bool ath5k_is_standard_channel(short chan, enum ieee80211_band band) |
260 | { | 248 | { |
261 | return ((chan <= 14) || | 249 | if (band == IEEE80211_BAND_2GHZ && chan <= 14) |
262 | /* UNII 1,2 */ | 250 | return true; |
263 | ((chan & 3) == 0 && chan >= 36 && chan <= 64) || | 251 | |
252 | return /* UNII 1,2 */ | ||
253 | (((chan & 3) == 0 && chan >= 36 && chan <= 64) || | ||
264 | /* midband */ | 254 | /* midband */ |
265 | ((chan & 3) == 0 && chan >= 100 && chan <= 140) || | 255 | ((chan & 3) == 0 && chan >= 100 && chan <= 140) || |
266 | /* UNII-3 */ | 256 | /* UNII-3 */ |
267 | ((chan & 3) == 1 && chan >= 149 && chan <= 165)); | 257 | ((chan & 3) == 1 && chan >= 149 && chan <= 165) || |
258 | /* 802.11j 5.030-5.080 GHz (20MHz) */ | ||
259 | (chan == 8 || chan == 12 || chan == 16) || | ||
260 | /* 802.11j 4.9GHz (20MHz) */ | ||
261 | (chan == 184 || chan == 188 || chan == 192 || chan == 196)); | ||
268 | } | 262 | } |
269 | 263 | ||
270 | static unsigned int | 264 | static unsigned int |
271 | ath5k_copy_channels(struct ath5k_hw *ah, | 265 | ath5k_setup_channels(struct ath5k_hw *ah, struct ieee80211_channel *channels, |
272 | struct ieee80211_channel *channels, | 266 | unsigned int mode, unsigned int max) |
273 | unsigned int mode, | ||
274 | unsigned int max) | ||
275 | { | 267 | { |
276 | unsigned int i, count, size, chfreq, freq, ch; | 268 | unsigned int count, size, chfreq, freq, ch; |
277 | 269 | enum ieee80211_band band; | |
278 | if (!test_bit(mode, ah->ah_modes)) | ||
279 | return 0; | ||
280 | 270 | ||
281 | switch (mode) { | 271 | switch (mode) { |
282 | case AR5K_MODE_11A: | 272 | case AR5K_MODE_11A: |
283 | /* 1..220, but 2GHz frequencies are filtered by check_channel */ | 273 | /* 1..220, but 2GHz frequencies are filtered by check_channel */ |
284 | size = 220 ; | 274 | size = 220; |
285 | chfreq = CHANNEL_5GHZ; | 275 | chfreq = CHANNEL_5GHZ; |
276 | band = IEEE80211_BAND_5GHZ; | ||
286 | break; | 277 | break; |
287 | case AR5K_MODE_11B: | 278 | case AR5K_MODE_11B: |
288 | case AR5K_MODE_11G: | 279 | case AR5K_MODE_11G: |
289 | size = 26; | 280 | size = 26; |
290 | chfreq = CHANNEL_2GHZ; | 281 | chfreq = CHANNEL_2GHZ; |
282 | band = IEEE80211_BAND_2GHZ; | ||
291 | break; | 283 | break; |
292 | default: | 284 | default: |
293 | ATH5K_WARN(ah->ah_sc, "bad mode, not copying channels\n"); | 285 | ATH5K_WARN(ah->ah_sc, "bad mode, not copying channels\n"); |
294 | return 0; | 286 | return 0; |
295 | } | 287 | } |
296 | 288 | ||
297 | for (i = 0, count = 0; i < size && max > 0; i++) { | 289 | count = 0; |
298 | ch = i + 1 ; | 290 | for (ch = 1; ch <= size && count < max; ch++) { |
299 | freq = ath5k_ieee2mhz(ch); | 291 | freq = ieee80211_channel_to_frequency(ch, band); |
292 | |||
293 | if (freq == 0) /* mapping failed - not a standard channel */ | ||
294 | continue; | ||
300 | 295 | ||
301 | /* Check if channel is supported by the chipset */ | 296 | /* Check if channel is supported by the chipset */ |
302 | if (!ath5k_channel_ok(ah, freq, chfreq)) | 297 | if (!ath5k_channel_ok(ah, freq, chfreq)) |
303 | continue; | 298 | continue; |
304 | 299 | ||
305 | if (!modparam_all_channels && !ath5k_is_standard_channel(ch)) | 300 | if (!modparam_all_channels && |
301 | !ath5k_is_standard_channel(ch, band)) | ||
306 | continue; | 302 | continue; |
307 | 303 | ||
308 | /* Write channel info and increment counter */ | 304 | /* Write channel info and increment counter */ |
309 | channels[count].center_freq = freq; | 305 | channels[count].center_freq = freq; |
310 | channels[count].band = (chfreq == CHANNEL_2GHZ) ? | 306 | channels[count].band = band; |
311 | IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; | ||
312 | switch (mode) { | 307 | switch (mode) { |
313 | case AR5K_MODE_11A: | 308 | case AR5K_MODE_11A: |
314 | case AR5K_MODE_11G: | 309 | case AR5K_MODE_11G: |
@@ -319,7 +314,6 @@ ath5k_copy_channels(struct ath5k_hw *ah, | |||
319 | } | 314 | } |
320 | 315 | ||
321 | count++; | 316 | count++; |
322 | max--; | ||
323 | } | 317 | } |
324 | 318 | ||
325 | return count; | 319 | return count; |
@@ -364,7 +358,7 @@ ath5k_setup_bands(struct ieee80211_hw *hw) | |||
364 | sband->n_bitrates = 12; | 358 | sband->n_bitrates = 12; |
365 | 359 | ||
366 | sband->channels = sc->channels; | 360 | sband->channels = sc->channels; |
367 | sband->n_channels = ath5k_copy_channels(ah, sband->channels, | 361 | sband->n_channels = ath5k_setup_channels(ah, sband->channels, |
368 | AR5K_MODE_11G, max_c); | 362 | AR5K_MODE_11G, max_c); |
369 | 363 | ||
370 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband; | 364 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband; |
@@ -390,7 +384,7 @@ ath5k_setup_bands(struct ieee80211_hw *hw) | |||
390 | } | 384 | } |
391 | 385 | ||
392 | sband->channels = sc->channels; | 386 | sband->channels = sc->channels; |
393 | sband->n_channels = ath5k_copy_channels(ah, sband->channels, | 387 | sband->n_channels = ath5k_setup_channels(ah, sband->channels, |
394 | AR5K_MODE_11B, max_c); | 388 | AR5K_MODE_11B, max_c); |
395 | 389 | ||
396 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband; | 390 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband; |
@@ -410,7 +404,7 @@ ath5k_setup_bands(struct ieee80211_hw *hw) | |||
410 | sband->n_bitrates = 8; | 404 | sband->n_bitrates = 8; |
411 | 405 | ||
412 | sband->channels = &sc->channels[count_c]; | 406 | sband->channels = &sc->channels[count_c]; |
413 | sband->n_channels = ath5k_copy_channels(ah, sband->channels, | 407 | sband->n_channels = ath5k_setup_channels(ah, sband->channels, |
414 | AR5K_MODE_11A, max_c); | 408 | AR5K_MODE_11A, max_c); |
415 | 409 | ||
416 | hw->wiphy->bands[IEEE80211_BAND_5GHZ] = sband; | 410 | hw->wiphy->bands[IEEE80211_BAND_5GHZ] = sband; |
@@ -445,18 +439,6 @@ ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan) | |||
445 | return ath5k_reset(sc, chan, true); | 439 | return ath5k_reset(sc, chan, true); |
446 | } | 440 | } |
447 | 441 | ||
448 | static void | ||
449 | ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode) | ||
450 | { | ||
451 | sc->curmode = mode; | ||
452 | |||
453 | if (mode == AR5K_MODE_11A) { | ||
454 | sc->curband = &sc->sbands[IEEE80211_BAND_5GHZ]; | ||
455 | } else { | ||
456 | sc->curband = &sc->sbands[IEEE80211_BAND_2GHZ]; | ||
457 | } | ||
458 | } | ||
459 | |||
460 | struct ath_vif_iter_data { | 442 | struct ath_vif_iter_data { |
461 | const u8 *hw_macaddr; | 443 | const u8 *hw_macaddr; |
462 | u8 mask[ETH_ALEN]; | 444 | u8 mask[ETH_ALEN]; |
@@ -569,7 +551,7 @@ ath5k_hw_to_driver_rix(struct ath5k_softc *sc, int hw_rix) | |||
569 | "hw_rix out of bounds: %x\n", hw_rix)) | 551 | "hw_rix out of bounds: %x\n", hw_rix)) |
570 | return 0; | 552 | return 0; |
571 | 553 | ||
572 | rix = sc->rate_idx[sc->curband->band][hw_rix]; | 554 | rix = sc->rate_idx[sc->curchan->band][hw_rix]; |
573 | if (WARN(rix < 0, "invalid hw_rix: %x\n", hw_rix)) | 555 | if (WARN(rix < 0, "invalid hw_rix: %x\n", hw_rix)) |
574 | rix = 0; | 556 | rix = 0; |
575 | 557 | ||
@@ -1379,7 +1361,7 @@ ath5k_receive_frame(struct ath5k_softc *sc, struct sk_buff *skb, | |||
1379 | rxs->flag |= RX_FLAG_TSFT; | 1361 | rxs->flag |= RX_FLAG_TSFT; |
1380 | 1362 | ||
1381 | rxs->freq = sc->curchan->center_freq; | 1363 | rxs->freq = sc->curchan->center_freq; |
1382 | rxs->band = sc->curband->band; | 1364 | rxs->band = sc->curchan->band; |
1383 | 1365 | ||
1384 | rxs->signal = sc->ah->ah_noise_floor + rs->rs_rssi; | 1366 | rxs->signal = sc->ah->ah_noise_floor + rs->rs_rssi; |
1385 | 1367 | ||
@@ -1394,7 +1376,7 @@ ath5k_receive_frame(struct ath5k_softc *sc, struct sk_buff *skb, | |||
1394 | rxs->flag |= ath5k_rx_decrypted(sc, skb, rs); | 1376 | rxs->flag |= ath5k_rx_decrypted(sc, skb, rs); |
1395 | 1377 | ||
1396 | if (rxs->rate_idx >= 0 && rs->rs_rate == | 1378 | if (rxs->rate_idx >= 0 && rs->rs_rate == |
1397 | sc->curband->bitrates[rxs->rate_idx].hw_value_short) | 1379 | sc->sbands[sc->curchan->band].bitrates[rxs->rate_idx].hw_value_short) |
1398 | rxs->flag |= RX_FLAG_SHORTPRE; | 1380 | rxs->flag |= RX_FLAG_SHORTPRE; |
1399 | 1381 | ||
1400 | ath5k_debug_dump_skb(sc, skb, "RX ", 0); | 1382 | ath5k_debug_dump_skb(sc, skb, "RX ", 0); |
@@ -2554,7 +2536,6 @@ ath5k_init_hw(struct ath5k_softc *sc) | |||
2554 | * and then setup of the interrupt mask. | 2536 | * and then setup of the interrupt mask. |
2555 | */ | 2537 | */ |
2556 | sc->curchan = sc->hw->conf.channel; | 2538 | sc->curchan = sc->hw->conf.channel; |
2557 | sc->curband = &sc->sbands[sc->curchan->band]; | ||
2558 | sc->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL | | 2539 | sc->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL | |
2559 | AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL | | 2540 | AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL | |
2560 | AR5K_INT_FATAL | AR5K_INT_GLOBAL | AR5K_INT_MIB; | 2541 | AR5K_INT_FATAL | AR5K_INT_GLOBAL | AR5K_INT_MIB; |
@@ -2681,10 +2662,8 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan, | |||
2681 | * so we should also free any remaining | 2662 | * so we should also free any remaining |
2682 | * tx buffers */ | 2663 | * tx buffers */ |
2683 | ath5k_drain_tx_buffs(sc); | 2664 | ath5k_drain_tx_buffs(sc); |
2684 | if (chan) { | 2665 | if (chan) |
2685 | sc->curchan = chan; | 2666 | sc->curchan = chan; |
2686 | sc->curband = &sc->sbands[chan->band]; | ||
2687 | } | ||
2688 | ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, chan != NULL, | 2667 | ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, chan != NULL, |
2689 | skip_pcu); | 2668 | skip_pcu); |
2690 | if (ret) { | 2669 | if (ret) { |
@@ -2782,12 +2761,6 @@ ath5k_init(struct ieee80211_hw *hw) | |||
2782 | goto err; | 2761 | goto err; |
2783 | } | 2762 | } |
2784 | 2763 | ||
2785 | /* NB: setup here so ath5k_rate_update is happy */ | ||
2786 | if (test_bit(AR5K_MODE_11A, ah->ah_modes)) | ||
2787 | ath5k_setcurmode(sc, AR5K_MODE_11A); | ||
2788 | else | ||
2789 | ath5k_setcurmode(sc, AR5K_MODE_11B); | ||
2790 | |||
2791 | /* | 2764 | /* |
2792 | * Allocate tx+rx descriptors and populate the lists. | 2765 | * Allocate tx+rx descriptors and populate the lists. |
2793 | */ | 2766 | */ |
diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h index 6d511476e4d2..8f919dca95f1 100644 --- a/drivers/net/wireless/ath/ath5k/base.h +++ b/drivers/net/wireless/ath/ath5k/base.h | |||
@@ -183,8 +183,6 @@ struct ath5k_softc { | |||
183 | enum nl80211_iftype opmode; | 183 | enum nl80211_iftype opmode; |
184 | struct ath5k_hw *ah; /* Atheros HW */ | 184 | struct ath5k_hw *ah; /* Atheros HW */ |
185 | 185 | ||
186 | struct ieee80211_supported_band *curband; | ||
187 | |||
188 | #ifdef CONFIG_ATH5K_DEBUG | 186 | #ifdef CONFIG_ATH5K_DEBUG |
189 | struct ath5k_dbg_info debug; /* debug info */ | 187 | struct ath5k_dbg_info debug; /* debug info */ |
190 | #endif /* CONFIG_ATH5K_DEBUG */ | 188 | #endif /* CONFIG_ATH5K_DEBUG */ |
@@ -202,7 +200,6 @@ struct ath5k_softc { | |||
202 | #define ATH_STAT_STARTED 4 /* opened & irqs enabled */ | 200 | #define ATH_STAT_STARTED 4 /* opened & irqs enabled */ |
203 | 201 | ||
204 | unsigned int filter_flags; /* HW flags, AR5K_RX_FILTER_* */ | 202 | unsigned int filter_flags; /* HW flags, AR5K_RX_FILTER_* */ |
205 | unsigned int curmode; /* current phy mode */ | ||
206 | struct ieee80211_channel *curchan; /* current h/w channel */ | 203 | struct ieee80211_channel *curchan; /* current h/w channel */ |
207 | 204 | ||
208 | u16 nvifs; | 205 | u16 nvifs; |
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c index 80e625608bac..b6561f785c6e 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.c +++ b/drivers/net/wireless/ath/ath5k/eeprom.c | |||
@@ -72,7 +72,6 @@ static int | |||
72 | ath5k_eeprom_init_header(struct ath5k_hw *ah) | 72 | ath5k_eeprom_init_header(struct ath5k_hw *ah) |
73 | { | 73 | { |
74 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | 74 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; |
75 | int ret; | ||
76 | u16 val; | 75 | u16 val; |
77 | u32 cksum, offset, eep_max = AR5K_EEPROM_INFO_MAX; | 76 | u32 cksum, offset, eep_max = AR5K_EEPROM_INFO_MAX; |
78 | 77 | ||
@@ -192,7 +191,7 @@ static int ath5k_eeprom_read_ants(struct ath5k_hw *ah, u32 *offset, | |||
192 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | 191 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; |
193 | u32 o = *offset; | 192 | u32 o = *offset; |
194 | u16 val; | 193 | u16 val; |
195 | int ret, i = 0; | 194 | int i = 0; |
196 | 195 | ||
197 | AR5K_EEPROM_READ(o++, val); | 196 | AR5K_EEPROM_READ(o++, val); |
198 | ee->ee_switch_settling[mode] = (val >> 8) & 0x7f; | 197 | ee->ee_switch_settling[mode] = (val >> 8) & 0x7f; |
@@ -252,7 +251,6 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset, | |||
252 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | 251 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; |
253 | u32 o = *offset; | 252 | u32 o = *offset; |
254 | u16 val; | 253 | u16 val; |
255 | int ret; | ||
256 | 254 | ||
257 | ee->ee_n_piers[mode] = 0; | 255 | ee->ee_n_piers[mode] = 0; |
258 | AR5K_EEPROM_READ(o++, val); | 256 | AR5K_EEPROM_READ(o++, val); |
@@ -515,7 +513,6 @@ ath5k_eeprom_read_freq_list(struct ath5k_hw *ah, int *offset, int max, | |||
515 | int o = *offset; | 513 | int o = *offset; |
516 | int i = 0; | 514 | int i = 0; |
517 | u8 freq1, freq2; | 515 | u8 freq1, freq2; |
518 | int ret; | ||
519 | u16 val; | 516 | u16 val; |
520 | 517 | ||
521 | ee->ee_n_piers[mode] = 0; | 518 | ee->ee_n_piers[mode] = 0; |
@@ -551,7 +548,7 @@ ath5k_eeprom_init_11a_pcal_freq(struct ath5k_hw *ah, int offset) | |||
551 | { | 548 | { |
552 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | 549 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; |
553 | struct ath5k_chan_pcal_info *pcal = ee->ee_pwr_cal_a; | 550 | struct ath5k_chan_pcal_info *pcal = ee->ee_pwr_cal_a; |
554 | int i, ret; | 551 | int i; |
555 | u16 val; | 552 | u16 val; |
556 | u8 mask; | 553 | u8 mask; |
557 | 554 | ||
@@ -970,7 +967,6 @@ ath5k_eeprom_read_pcal_info_5112(struct ath5k_hw *ah, int mode) | |||
970 | u32 offset; | 967 | u32 offset; |
971 | u8 i, c; | 968 | u8 i, c; |
972 | u16 val; | 969 | u16 val; |
973 | int ret; | ||
974 | u8 pd_gains = 0; | 970 | u8 pd_gains = 0; |
975 | 971 | ||
976 | /* Count how many curves we have and | 972 | /* Count how many curves we have and |
@@ -1228,7 +1224,7 @@ ath5k_eeprom_read_pcal_info_2413(struct ath5k_hw *ah, int mode) | |||
1228 | struct ath5k_chan_pcal_info *chinfo; | 1224 | struct ath5k_chan_pcal_info *chinfo; |
1229 | u8 *pdgain_idx = ee->ee_pdc_to_idx[mode]; | 1225 | u8 *pdgain_idx = ee->ee_pdc_to_idx[mode]; |
1230 | u32 offset; | 1226 | u32 offset; |
1231 | int idx, i, ret; | 1227 | int idx, i; |
1232 | u16 val; | 1228 | u16 val; |
1233 | u8 pd_gains = 0; | 1229 | u8 pd_gains = 0; |
1234 | 1230 | ||
@@ -1419,7 +1415,7 @@ ath5k_eeprom_read_target_rate_pwr_info(struct ath5k_hw *ah, unsigned int mode) | |||
1419 | u8 *rate_target_pwr_num; | 1415 | u8 *rate_target_pwr_num; |
1420 | u32 offset; | 1416 | u32 offset; |
1421 | u16 val; | 1417 | u16 val; |
1422 | int ret, i; | 1418 | int i; |
1423 | 1419 | ||
1424 | offset = AR5K_EEPROM_TARGET_PWRSTART(ee->ee_misc1); | 1420 | offset = AR5K_EEPROM_TARGET_PWRSTART(ee->ee_misc1); |
1425 | rate_target_pwr_num = &ee->ee_rate_target_pwr_num[mode]; | 1421 | rate_target_pwr_num = &ee->ee_rate_target_pwr_num[mode]; |
@@ -1593,7 +1589,7 @@ ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah) | |||
1593 | struct ath5k_edge_power *rep; | 1589 | struct ath5k_edge_power *rep; |
1594 | unsigned int fmask, pmask; | 1590 | unsigned int fmask, pmask; |
1595 | unsigned int ctl_mode; | 1591 | unsigned int ctl_mode; |
1596 | int ret, i, j; | 1592 | int i, j; |
1597 | u32 offset; | 1593 | u32 offset; |
1598 | u16 val; | 1594 | u16 val; |
1599 | 1595 | ||
@@ -1733,16 +1729,12 @@ int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac) | |||
1733 | u8 mac_d[ETH_ALEN] = {}; | 1729 | u8 mac_d[ETH_ALEN] = {}; |
1734 | u32 total, offset; | 1730 | u32 total, offset; |
1735 | u16 data; | 1731 | u16 data; |
1736 | int octet, ret; | 1732 | int octet; |
1737 | 1733 | ||
1738 | ret = ath5k_hw_nvram_read(ah, 0x20, &data); | 1734 | AR5K_EEPROM_READ(0x20, data); |
1739 | if (ret) | ||
1740 | return ret; | ||
1741 | 1735 | ||
1742 | for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) { | 1736 | for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) { |
1743 | ret = ath5k_hw_nvram_read(ah, offset, &data); | 1737 | AR5K_EEPROM_READ(offset, data); |
1744 | if (ret) | ||
1745 | return ret; | ||
1746 | 1738 | ||
1747 | total += data; | 1739 | total += data; |
1748 | mac_d[octet + 1] = data & 0xff; | 1740 | mac_d[octet + 1] = data & 0xff; |
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.h b/drivers/net/wireless/ath/ath5k/eeprom.h index 7c09e150dbdc..6511c27d938e 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.h +++ b/drivers/net/wireless/ath/ath5k/eeprom.h | |||
@@ -241,9 +241,8 @@ enum ath5k_eeprom_freq_bands{ | |||
241 | #define AR5K_SPUR_SYMBOL_WIDTH_TURBO_100Hz 6250 | 241 | #define AR5K_SPUR_SYMBOL_WIDTH_TURBO_100Hz 6250 |
242 | 242 | ||
243 | #define AR5K_EEPROM_READ(_o, _v) do { \ | 243 | #define AR5K_EEPROM_READ(_o, _v) do { \ |
244 | ret = ath5k_hw_nvram_read(ah, (_o), &(_v)); \ | 244 | if (!ath5k_hw_nvram_read(ah, (_o), &(_v))) \ |
245 | if (ret) \ | 245 | return -EIO; \ |
246 | return ret; \ | ||
247 | } while (0) | 246 | } while (0) |
248 | 247 | ||
249 | #define AR5K_EEPROM_READ_HDR(_o, _v) \ | 248 | #define AR5K_EEPROM_READ_HDR(_o, _v) \ |
@@ -269,29 +268,6 @@ enum ath5k_ctl_mode { | |||
269 | AR5K_CTL_MODE_M = 15, | 268 | AR5K_CTL_MODE_M = 15, |
270 | }; | 269 | }; |
271 | 270 | ||
272 | /* Default CTL ids for the 3 main reg domains. | ||
273 | * Atheros only uses these by default but vendors | ||
274 | * can have up to 32 different CTLs for different | ||
275 | * scenarios. Note that theese values are ORed with | ||
276 | * the mode id (above) so we can have up to 24 CTL | ||
277 | * datasets out of these 3 main regdomains. That leaves | ||
278 | * 8 ids that can be used by vendors and since 0x20 is | ||
279 | * missing from HAL sources i guess this is the set of | ||
280 | * custom CTLs vendors can use. */ | ||
281 | #define AR5K_CTL_FCC 0x10 | ||
282 | #define AR5K_CTL_CUSTOM 0x20 | ||
283 | #define AR5K_CTL_ETSI 0x30 | ||
284 | #define AR5K_CTL_MKK 0x40 | ||
285 | |||
286 | /* Indicates a CTL with only mode set and | ||
287 | * no reg domain mapping, such CTLs are used | ||
288 | * for world roaming domains or simply when | ||
289 | * a reg domain is not set */ | ||
290 | #define AR5K_CTL_NO_REGDOMAIN 0xf0 | ||
291 | |||
292 | /* Indicates an empty (invalid) CTL */ | ||
293 | #define AR5K_CTL_NO_CTL 0xff | ||
294 | |||
295 | /* Per channel calibration data, used for power table setup */ | 271 | /* Per channel calibration data, used for power table setup */ |
296 | struct ath5k_chan_pcal_info_rf5111 { | 272 | struct ath5k_chan_pcal_info_rf5111 { |
297 | /* Power levels in half dbm units | 273 | /* Power levels in half dbm units |
diff --git a/drivers/net/wireless/ath/ath5k/pci.c b/drivers/net/wireless/ath/ath5k/pci.c index 7f8c5b0e9d2a..66598a0d1df0 100644 --- a/drivers/net/wireless/ath/ath5k/pci.c +++ b/drivers/net/wireless/ath/ath5k/pci.c | |||
@@ -69,7 +69,8 @@ static void ath5k_pci_read_cachesize(struct ath_common *common, int *csz) | |||
69 | /* | 69 | /* |
70 | * Read from eeprom | 70 | * Read from eeprom |
71 | */ | 71 | */ |
72 | bool ath5k_pci_eeprom_read(struct ath_common *common, u32 offset, u16 *data) | 72 | static bool |
73 | ath5k_pci_eeprom_read(struct ath_common *common, u32 offset, u16 *data) | ||
73 | { | 74 | { |
74 | struct ath5k_hw *ah = (struct ath5k_hw *) common->ah; | 75 | struct ath5k_hw *ah = (struct ath5k_hw *) common->ah; |
75 | u32 status, timeout; | 76 | u32 status, timeout; |
@@ -90,15 +91,15 @@ bool ath5k_pci_eeprom_read(struct ath_common *common, u32 offset, u16 *data) | |||
90 | status = ath5k_hw_reg_read(ah, AR5K_EEPROM_STATUS); | 91 | status = ath5k_hw_reg_read(ah, AR5K_EEPROM_STATUS); |
91 | if (status & AR5K_EEPROM_STAT_RDDONE) { | 92 | if (status & AR5K_EEPROM_STAT_RDDONE) { |
92 | if (status & AR5K_EEPROM_STAT_RDERR) | 93 | if (status & AR5K_EEPROM_STAT_RDERR) |
93 | return -EIO; | 94 | return false; |
94 | *data = (u16)(ath5k_hw_reg_read(ah, AR5K_EEPROM_DATA) & | 95 | *data = (u16)(ath5k_hw_reg_read(ah, AR5K_EEPROM_DATA) & |
95 | 0xffff); | 96 | 0xffff); |
96 | return 0; | 97 | return true; |
97 | } | 98 | } |
98 | udelay(15); | 99 | udelay(15); |
99 | } | 100 | } |
100 | 101 | ||
101 | return -ETIMEDOUT; | 102 | return false; |
102 | } | 103 | } |
103 | 104 | ||
104 | int ath5k_hw_read_srev(struct ath5k_hw *ah) | 105 | int ath5k_hw_read_srev(struct ath5k_hw *ah) |
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c b/drivers/net/wireless/ath/ath9k/ar9002_calib.c index 5e300bd3d264..76388c6d6692 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c | |||
@@ -805,7 +805,10 @@ static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) | |||
805 | { | 805 | { |
806 | struct ath_common *common = ath9k_hw_common(ah); | 806 | struct ath_common *common = ath9k_hw_common(ah); |
807 | 807 | ||
808 | if (AR_SREV_9271(ah) || AR_SREV_9285_12_OR_LATER(ah)) { | 808 | if (AR_SREV_9271(ah)) { |
809 | if (!ar9285_hw_cl_cal(ah, chan)) | ||
810 | return false; | ||
811 | } else if (AR_SREV_9285_12_OR_LATER(ah)) { | ||
809 | if (!ar9285_hw_clc(ah, chan)) | 812 | if (!ar9285_hw_clc(ah, chan)) |
810 | return false; | 813 | return false; |
811 | } else { | 814 | } else { |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 4819747fa4c3..a25655640f48 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | |||
@@ -3959,19 +3959,19 @@ static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray) | |||
3959 | { | 3959 | { |
3960 | #define POW_SM(_r, _s) (((_r) & 0x3f) << (_s)) | 3960 | #define POW_SM(_r, _s) (((_r) & 0x3f) << (_s)) |
3961 | /* make sure forced gain is not set */ | 3961 | /* make sure forced gain is not set */ |
3962 | REG_WRITE(ah, 0xa458, 0); | 3962 | REG_WRITE(ah, AR_PHY_TX_FORCED_GAIN, 0); |
3963 | 3963 | ||
3964 | /* Write the OFDM power per rate set */ | 3964 | /* Write the OFDM power per rate set */ |
3965 | 3965 | ||
3966 | /* 6 (LSB), 9, 12, 18 (MSB) */ | 3966 | /* 6 (LSB), 9, 12, 18 (MSB) */ |
3967 | REG_WRITE(ah, 0xa3c0, | 3967 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE(0), |
3968 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 24) | | 3968 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 24) | |
3969 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 16) | | 3969 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 16) | |
3970 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 8) | | 3970 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 8) | |
3971 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 0)); | 3971 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 0)); |
3972 | 3972 | ||
3973 | /* 24 (LSB), 36, 48, 54 (MSB) */ | 3973 | /* 24 (LSB), 36, 48, 54 (MSB) */ |
3974 | REG_WRITE(ah, 0xa3c4, | 3974 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE(1), |
3975 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_54], 24) | | 3975 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_54], 24) | |
3976 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_48], 16) | | 3976 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_48], 16) | |
3977 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_36], 8) | | 3977 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_36], 8) | |
@@ -3980,14 +3980,14 @@ static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray) | |||
3980 | /* Write the CCK power per rate set */ | 3980 | /* Write the CCK power per rate set */ |
3981 | 3981 | ||
3982 | /* 1L (LSB), reserved, 2L, 2S (MSB) */ | 3982 | /* 1L (LSB), reserved, 2L, 2S (MSB) */ |
3983 | REG_WRITE(ah, 0xa3c8, | 3983 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE(2), |
3984 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 24) | | 3984 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 24) | |
3985 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 16) | | 3985 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 16) | |
3986 | /* POW_SM(txPowerTimes2, 8) | this is reserved for AR9003 */ | 3986 | /* POW_SM(txPowerTimes2, 8) | this is reserved for AR9003 */ |
3987 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 0)); | 3987 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 0)); |
3988 | 3988 | ||
3989 | /* 5.5L (LSB), 5.5S, 11L, 11S (MSB) */ | 3989 | /* 5.5L (LSB), 5.5S, 11L, 11S (MSB) */ |
3990 | REG_WRITE(ah, 0xa3cc, | 3990 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE(3), |
3991 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_11S], 24) | | 3991 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_11S], 24) | |
3992 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_11L], 16) | | 3992 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_11L], 16) | |
3993 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_5S], 8) | | 3993 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_5S], 8) | |
@@ -3997,7 +3997,7 @@ static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray) | |||
3997 | /* Write the HT20 power per rate set */ | 3997 | /* Write the HT20 power per rate set */ |
3998 | 3998 | ||
3999 | /* 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB) */ | 3999 | /* 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB) */ |
4000 | REG_WRITE(ah, 0xa3d0, | 4000 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE(4), |
4001 | POW_SM(pPwrArray[ALL_TARGET_HT20_5], 24) | | 4001 | POW_SM(pPwrArray[ALL_TARGET_HT20_5], 24) | |
4002 | POW_SM(pPwrArray[ALL_TARGET_HT20_4], 16) | | 4002 | POW_SM(pPwrArray[ALL_TARGET_HT20_4], 16) | |
4003 | POW_SM(pPwrArray[ALL_TARGET_HT20_1_3_9_11_17_19], 8) | | 4003 | POW_SM(pPwrArray[ALL_TARGET_HT20_1_3_9_11_17_19], 8) | |
@@ -4005,7 +4005,7 @@ static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray) | |||
4005 | ); | 4005 | ); |
4006 | 4006 | ||
4007 | /* 6 (LSB), 7, 12, 13 (MSB) */ | 4007 | /* 6 (LSB), 7, 12, 13 (MSB) */ |
4008 | REG_WRITE(ah, 0xa3d4, | 4008 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE(5), |
4009 | POW_SM(pPwrArray[ALL_TARGET_HT20_13], 24) | | 4009 | POW_SM(pPwrArray[ALL_TARGET_HT20_13], 24) | |
4010 | POW_SM(pPwrArray[ALL_TARGET_HT20_12], 16) | | 4010 | POW_SM(pPwrArray[ALL_TARGET_HT20_12], 16) | |
4011 | POW_SM(pPwrArray[ALL_TARGET_HT20_7], 8) | | 4011 | POW_SM(pPwrArray[ALL_TARGET_HT20_7], 8) | |
@@ -4013,7 +4013,7 @@ static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray) | |||
4013 | ); | 4013 | ); |
4014 | 4014 | ||
4015 | /* 14 (LSB), 15, 20, 21 */ | 4015 | /* 14 (LSB), 15, 20, 21 */ |
4016 | REG_WRITE(ah, 0xa3e4, | 4016 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE(9), |
4017 | POW_SM(pPwrArray[ALL_TARGET_HT20_21], 24) | | 4017 | POW_SM(pPwrArray[ALL_TARGET_HT20_21], 24) | |
4018 | POW_SM(pPwrArray[ALL_TARGET_HT20_20], 16) | | 4018 | POW_SM(pPwrArray[ALL_TARGET_HT20_20], 16) | |
4019 | POW_SM(pPwrArray[ALL_TARGET_HT20_15], 8) | | 4019 | POW_SM(pPwrArray[ALL_TARGET_HT20_15], 8) | |
@@ -4023,7 +4023,7 @@ static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray) | |||
4023 | /* Mixed HT20 and HT40 rates */ | 4023 | /* Mixed HT20 and HT40 rates */ |
4024 | 4024 | ||
4025 | /* HT20 22 (LSB), HT20 23, HT40 22, HT40 23 (MSB) */ | 4025 | /* HT20 22 (LSB), HT20 23, HT40 22, HT40 23 (MSB) */ |
4026 | REG_WRITE(ah, 0xa3e8, | 4026 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE(10), |
4027 | POW_SM(pPwrArray[ALL_TARGET_HT40_23], 24) | | 4027 | POW_SM(pPwrArray[ALL_TARGET_HT40_23], 24) | |
4028 | POW_SM(pPwrArray[ALL_TARGET_HT40_22], 16) | | 4028 | POW_SM(pPwrArray[ALL_TARGET_HT40_22], 16) | |
4029 | POW_SM(pPwrArray[ALL_TARGET_HT20_23], 8) | | 4029 | POW_SM(pPwrArray[ALL_TARGET_HT20_23], 8) | |
@@ -4035,7 +4035,7 @@ static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray) | |||
4035 | * correct PAR difference between HT40 and HT20/LEGACY | 4035 | * correct PAR difference between HT40 and HT20/LEGACY |
4036 | * 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB) | 4036 | * 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB) |
4037 | */ | 4037 | */ |
4038 | REG_WRITE(ah, 0xa3d8, | 4038 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE(6), |
4039 | POW_SM(pPwrArray[ALL_TARGET_HT40_5], 24) | | 4039 | POW_SM(pPwrArray[ALL_TARGET_HT40_5], 24) | |
4040 | POW_SM(pPwrArray[ALL_TARGET_HT40_4], 16) | | 4040 | POW_SM(pPwrArray[ALL_TARGET_HT40_4], 16) | |
4041 | POW_SM(pPwrArray[ALL_TARGET_HT40_1_3_9_11_17_19], 8) | | 4041 | POW_SM(pPwrArray[ALL_TARGET_HT40_1_3_9_11_17_19], 8) | |
@@ -4043,7 +4043,7 @@ static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray) | |||
4043 | ); | 4043 | ); |
4044 | 4044 | ||
4045 | /* 6 (LSB), 7, 12, 13 (MSB) */ | 4045 | /* 6 (LSB), 7, 12, 13 (MSB) */ |
4046 | REG_WRITE(ah, 0xa3dc, | 4046 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE(7), |
4047 | POW_SM(pPwrArray[ALL_TARGET_HT40_13], 24) | | 4047 | POW_SM(pPwrArray[ALL_TARGET_HT40_13], 24) | |
4048 | POW_SM(pPwrArray[ALL_TARGET_HT40_12], 16) | | 4048 | POW_SM(pPwrArray[ALL_TARGET_HT40_12], 16) | |
4049 | POW_SM(pPwrArray[ALL_TARGET_HT40_7], 8) | | 4049 | POW_SM(pPwrArray[ALL_TARGET_HT40_7], 8) | |
@@ -4051,7 +4051,7 @@ static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray) | |||
4051 | ); | 4051 | ); |
4052 | 4052 | ||
4053 | /* 14 (LSB), 15, 20, 21 */ | 4053 | /* 14 (LSB), 15, 20, 21 */ |
4054 | REG_WRITE(ah, 0xa3ec, | 4054 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE(11), |
4055 | POW_SM(pPwrArray[ALL_TARGET_HT40_21], 24) | | 4055 | POW_SM(pPwrArray[ALL_TARGET_HT40_21], 24) | |
4056 | POW_SM(pPwrArray[ALL_TARGET_HT40_20], 16) | | 4056 | POW_SM(pPwrArray[ALL_TARGET_HT40_20], 16) | |
4057 | POW_SM(pPwrArray[ALL_TARGET_HT40_15], 8) | | 4057 | POW_SM(pPwrArray[ALL_TARGET_HT40_15], 8) | |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index 4ceddbbdfcee..038a0cbfc6e7 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c | |||
@@ -615,7 +615,7 @@ int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs, | |||
615 | */ | 615 | */ |
616 | if (rxsp->status11 & AR_CRCErr) | 616 | if (rxsp->status11 & AR_CRCErr) |
617 | rxs->rs_status |= ATH9K_RXERR_CRC; | 617 | rxs->rs_status |= ATH9K_RXERR_CRC; |
618 | if (rxsp->status11 & AR_PHYErr) { | 618 | else if (rxsp->status11 & AR_PHYErr) { |
619 | phyerr = MS(rxsp->status11, AR_PHYErrCode); | 619 | phyerr = MS(rxsp->status11, AR_PHYErrCode); |
620 | /* | 620 | /* |
621 | * If we reach a point here where AR_PostDelimCRCErr is | 621 | * If we reach a point here where AR_PostDelimCRCErr is |
@@ -638,11 +638,11 @@ int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs, | |||
638 | rxs->rs_phyerr = phyerr; | 638 | rxs->rs_phyerr = phyerr; |
639 | } | 639 | } |
640 | 640 | ||
641 | } | 641 | } else if (rxsp->status11 & AR_DecryptCRCErr) |
642 | if (rxsp->status11 & AR_DecryptCRCErr) | ||
643 | rxs->rs_status |= ATH9K_RXERR_DECRYPT; | 642 | rxs->rs_status |= ATH9K_RXERR_DECRYPT; |
644 | if (rxsp->status11 & AR_MichaelErr) | 643 | else if (rxsp->status11 & AR_MichaelErr) |
645 | rxs->rs_status |= ATH9K_RXERR_MIC; | 644 | rxs->rs_status |= ATH9K_RXERR_MIC; |
645 | |||
646 | if (rxsp->status11 & AR_KeyMiss) | 646 | if (rxsp->status11 & AR_KeyMiss) |
647 | rxs->rs_status |= ATH9K_RXERR_DECRYPT; | 647 | rxs->rs_status |= ATH9K_RXERR_DECRYPT; |
648 | } | 648 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h index 59bab6bd8a74..8bdda2cf9dd7 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h | |||
@@ -486,6 +486,8 @@ | |||
486 | #define AR_PHY_HEAVYCLIP_40 (AR_SM_BASE + 0x1ac) | 486 | #define AR_PHY_HEAVYCLIP_40 (AR_SM_BASE + 0x1ac) |
487 | #define AR_PHY_ILLEGAL_TXRATE (AR_SM_BASE + 0x1b0) | 487 | #define AR_PHY_ILLEGAL_TXRATE (AR_SM_BASE + 0x1b0) |
488 | 488 | ||
489 | #define AR_PHY_POWER_TX_RATE(_d) (AR_SM_BASE + 0x1c0 + ((_d) << 2)) | ||
490 | |||
489 | #define AR_PHY_PWRTX_MAX (AR_SM_BASE + 0x1f0) | 491 | #define AR_PHY_PWRTX_MAX (AR_SM_BASE + 0x1f0) |
490 | #define AR_PHY_POWER_TX_SUB (AR_SM_BASE + 0x1f4) | 492 | #define AR_PHY_POWER_TX_SUB (AR_SM_BASE + 0x1f4) |
491 | 493 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 3681caf54282..6636f3c6dcf9 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -95,9 +95,9 @@ struct ath_config { | |||
95 | * @BUF_XRETRY: To denote excessive retries of the buffer | 95 | * @BUF_XRETRY: To denote excessive retries of the buffer |
96 | */ | 96 | */ |
97 | enum buffer_type { | 97 | enum buffer_type { |
98 | BUF_AMPDU = BIT(2), | 98 | BUF_AMPDU = BIT(0), |
99 | BUF_AGGR = BIT(3), | 99 | BUF_AGGR = BIT(1), |
100 | BUF_XRETRY = BIT(5), | 100 | BUF_XRETRY = BIT(2), |
101 | }; | 101 | }; |
102 | 102 | ||
103 | #define bf_isampdu(bf) (bf->bf_state.bf_type & BUF_AMPDU) | 103 | #define bf_isampdu(bf) (bf->bf_state.bf_type & BUF_AMPDU) |
@@ -137,7 +137,6 @@ void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd, | |||
137 | (((_tid) == 4) || ((_tid) == 5)) ? WME_AC_VI : \ | 137 | (((_tid) == 4) || ((_tid) == 5)) ? WME_AC_VI : \ |
138 | WME_AC_VO) | 138 | WME_AC_VO) |
139 | 139 | ||
140 | #define ADDBA_EXCHANGE_ATTEMPTS 10 | ||
141 | #define ATH_AGGR_DELIM_SZ 4 | 140 | #define ATH_AGGR_DELIM_SZ 4 |
142 | #define ATH_AGGR_MINPLEN 256 /* in bytes, minimum packet length */ | 141 | #define ATH_AGGR_MINPLEN 256 /* in bytes, minimum packet length */ |
143 | /* number of delimiters for encryption padding */ | 142 | /* number of delimiters for encryption padding */ |
@@ -184,7 +183,8 @@ enum ATH_AGGR_STATUS { | |||
184 | 183 | ||
185 | #define ATH_TXFIFO_DEPTH 8 | 184 | #define ATH_TXFIFO_DEPTH 8 |
186 | struct ath_txq { | 185 | struct ath_txq { |
187 | u32 axq_qnum; | 186 | int mac80211_qnum; /* mac80211 queue number, -1 means not mac80211 Q */ |
187 | u32 axq_qnum; /* ath9k hardware queue number */ | ||
188 | u32 *axq_link; | 188 | u32 *axq_link; |
189 | struct list_head axq_q; | 189 | struct list_head axq_q; |
190 | spinlock_t axq_lock; | 190 | spinlock_t axq_lock; |
@@ -254,7 +254,10 @@ struct ath_atx_tid { | |||
254 | }; | 254 | }; |
255 | 255 | ||
256 | struct ath_node { | 256 | struct ath_node { |
257 | struct ath_common *common; | 257 | #ifdef CONFIG_ATH9K_DEBUGFS |
258 | struct list_head list; /* for sc->nodes */ | ||
259 | struct ieee80211_sta *sta; /* station struct we're part of */ | ||
260 | #endif | ||
258 | struct ath_atx_tid tid[WME_NUM_TID]; | 261 | struct ath_atx_tid tid[WME_NUM_TID]; |
259 | struct ath_atx_ac ac[WME_NUM_AC]; | 262 | struct ath_atx_ac ac[WME_NUM_AC]; |
260 | u16 maxampdu; | 263 | u16 maxampdu; |
@@ -277,6 +280,11 @@ struct ath_tx_control { | |||
277 | #define ATH_TX_XRETRY 0x02 | 280 | #define ATH_TX_XRETRY 0x02 |
278 | #define ATH_TX_BAR 0x04 | 281 | #define ATH_TX_BAR 0x04 |
279 | 282 | ||
283 | /** | ||
284 | * @txq_map: Index is mac80211 queue number. This is | ||
285 | * not necessarily the same as the hardware queue number | ||
286 | * (axq_qnum). | ||
287 | */ | ||
280 | struct ath_tx { | 288 | struct ath_tx { |
281 | u16 seq_no; | 289 | u16 seq_no; |
282 | u32 txqsetup; | 290 | u32 txqsetup; |
@@ -342,7 +350,6 @@ struct ath_vif { | |||
342 | __le64 tsf_adjust; /* TSF adjustment for staggered beacons */ | 350 | __le64 tsf_adjust; /* TSF adjustment for staggered beacons */ |
343 | enum nl80211_iftype av_opmode; | 351 | enum nl80211_iftype av_opmode; |
344 | struct ath_buf *av_bcbuf; | 352 | struct ath_buf *av_bcbuf; |
345 | struct ath_tx_control av_btxctl; | ||
346 | u8 bssid[ETH_ALEN]; /* current BSSID from config_interface */ | 353 | u8 bssid[ETH_ALEN]; /* current BSSID from config_interface */ |
347 | }; | 354 | }; |
348 | 355 | ||
@@ -560,6 +567,20 @@ struct ath_ant_comb { | |||
560 | struct ath_wiphy; | 567 | struct ath_wiphy; |
561 | struct ath_rate_table; | 568 | struct ath_rate_table; |
562 | 569 | ||
570 | struct ath9k_vif_iter_data { | ||
571 | const u8 *hw_macaddr; /* phy's hardware address, set | ||
572 | * before starting iteration for | ||
573 | * valid bssid mask. | ||
574 | */ | ||
575 | u8 mask[ETH_ALEN]; /* bssid mask */ | ||
576 | int naps; /* number of AP vifs */ | ||
577 | int nmeshes; /* number of mesh vifs */ | ||
578 | int nstations; /* number of station vifs */ | ||
579 | int nwds; /* number of nwd vifs */ | ||
580 | int nadhocs; /* number of adhoc vifs */ | ||
581 | int nothers; /* number of vifs not specified above. */ | ||
582 | }; | ||
583 | |||
563 | struct ath_softc { | 584 | struct ath_softc { |
564 | struct ieee80211_hw *hw; | 585 | struct ieee80211_hw *hw; |
565 | struct device *dev; | 586 | struct device *dev; |
@@ -599,10 +620,10 @@ struct ath_softc { | |||
599 | u32 sc_flags; /* SC_OP_* */ | 620 | u32 sc_flags; /* SC_OP_* */ |
600 | u16 ps_flags; /* PS_* */ | 621 | u16 ps_flags; /* PS_* */ |
601 | u16 curtxpow; | 622 | u16 curtxpow; |
602 | u8 nbcnvifs; | ||
603 | u16 nvifs; | ||
604 | bool ps_enabled; | 623 | bool ps_enabled; |
605 | bool ps_idle; | 624 | bool ps_idle; |
625 | short nbcnvifs; | ||
626 | short nvifs; | ||
606 | unsigned long ps_usecount; | 627 | unsigned long ps_usecount; |
607 | 628 | ||
608 | struct ath_config config; | 629 | struct ath_config config; |
@@ -625,6 +646,9 @@ struct ath_softc { | |||
625 | 646 | ||
626 | #ifdef CONFIG_ATH9K_DEBUGFS | 647 | #ifdef CONFIG_ATH9K_DEBUGFS |
627 | struct ath9k_debug debug; | 648 | struct ath9k_debug debug; |
649 | spinlock_t nodes_lock; | ||
650 | struct list_head nodes; /* basically, stations */ | ||
651 | unsigned int tx_complete_poll_work_seen; | ||
628 | #endif | 652 | #endif |
629 | struct ath_beacon_config cur_beacon_conf; | 653 | struct ath_beacon_config cur_beacon_conf; |
630 | struct delayed_work tx_complete_work; | 654 | struct delayed_work tx_complete_work; |
@@ -683,6 +707,7 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | |||
683 | void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw); | 707 | void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw); |
684 | void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw); | 708 | void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw); |
685 | bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode); | 709 | bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode); |
710 | bool ath9k_uses_beacons(int type); | ||
686 | 711 | ||
687 | #ifdef CONFIG_PCI | 712 | #ifdef CONFIG_PCI |
688 | int ath_pci_init(void); | 713 | int ath_pci_init(void); |
@@ -727,5 +752,9 @@ bool ath_mac80211_start_queue(struct ath_softc *sc, u16 skb_queue); | |||
727 | 752 | ||
728 | void ath_start_rfkill_poll(struct ath_softc *sc); | 753 | void ath_start_rfkill_poll(struct ath_softc *sc); |
729 | extern void ath9k_rfkill_poll_state(struct ieee80211_hw *hw); | 754 | extern void ath9k_rfkill_poll_state(struct ieee80211_hw *hw); |
755 | void ath9k_calculate_iter_data(struct ieee80211_hw *hw, | ||
756 | struct ieee80211_vif *vif, | ||
757 | struct ath9k_vif_iter_data *iter_data); | ||
758 | |||
730 | 759 | ||
731 | #endif /* ATH9K_H */ | 760 | #endif /* ATH9K_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 385ba03134ba..ab8c05cf62f3 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c | |||
@@ -244,9 +244,7 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) | |||
244 | struct ath_buf, list); | 244 | struct ath_buf, list); |
245 | list_del(&avp->av_bcbuf->list); | 245 | list_del(&avp->av_bcbuf->list); |
246 | 246 | ||
247 | if (sc->sc_ah->opmode == NL80211_IFTYPE_AP || | 247 | if (ath9k_uses_beacons(vif->type)) { |
248 | sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC || | ||
249 | sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT) { | ||
250 | int slot; | 248 | int slot; |
251 | /* | 249 | /* |
252 | * Assign the vif to a beacon xmit slot. As | 250 | * Assign the vif to a beacon xmit slot. As |
@@ -281,10 +279,8 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) | |||
281 | 279 | ||
282 | /* NB: the beacon data buffer must be 32-bit aligned. */ | 280 | /* NB: the beacon data buffer must be 32-bit aligned. */ |
283 | skb = ieee80211_beacon_get(sc->hw, vif); | 281 | skb = ieee80211_beacon_get(sc->hw, vif); |
284 | if (skb == NULL) { | 282 | if (skb == NULL) |
285 | ath_dbg(common, ATH_DBG_BEACON, "cannot get skb\n"); | ||
286 | return -ENOMEM; | 283 | return -ENOMEM; |
287 | } | ||
288 | 284 | ||
289 | tstamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp; | 285 | tstamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp; |
290 | sc->beacon.bc_tstamp = le64_to_cpu(tstamp); | 286 | sc->beacon.bc_tstamp = le64_to_cpu(tstamp); |
@@ -720,10 +716,10 @@ void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif) | |||
720 | iftype = sc->sc_ah->opmode; | 716 | iftype = sc->sc_ah->opmode; |
721 | } | 717 | } |
722 | 718 | ||
723 | cur_conf->listen_interval = 1; | 719 | cur_conf->listen_interval = 1; |
724 | cur_conf->dtim_count = 1; | 720 | cur_conf->dtim_count = 1; |
725 | cur_conf->bmiss_timeout = | 721 | cur_conf->bmiss_timeout = |
726 | ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval; | 722 | ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval; |
727 | 723 | ||
728 | /* | 724 | /* |
729 | * It looks like mac80211 may end up using beacon interval of zero in | 725 | * It looks like mac80211 may end up using beacon interval of zero in |
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index b68a1acbddd0..b4a92a4313f6 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c | |||
@@ -382,9 +382,8 @@ void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah, | |||
382 | s16 default_nf; | 382 | s16 default_nf; |
383 | int i, j; | 383 | int i, j; |
384 | 384 | ||
385 | if (!ah->caldata) | 385 | ah->caldata->channel = chan->channel; |
386 | return; | 386 | ah->caldata->channelFlags = chan->channelFlags & ~CHANNEL_CW_INT; |
387 | |||
388 | h = ah->caldata->nfCalHist; | 387 | h = ah->caldata->nfCalHist; |
389 | default_nf = ath9k_hw_get_default_nf(ah, chan); | 388 | default_nf = ath9k_hw_get_default_nf(ah, chan); |
390 | for (i = 0; i < NUM_NF_READINGS; i++) { | 389 | for (i = 0; i < NUM_NF_READINGS; i++) { |
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 3586c43077a7..f0c80ec290d1 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c | |||
@@ -587,26 +587,60 @@ static const struct file_operations fops_wiphy = { | |||
587 | sc->debug.stats.txstats[WME_AC_BK].elem, \ | 587 | sc->debug.stats.txstats[WME_AC_BK].elem, \ |
588 | sc->debug.stats.txstats[WME_AC_VI].elem, \ | 588 | sc->debug.stats.txstats[WME_AC_VI].elem, \ |
589 | sc->debug.stats.txstats[WME_AC_VO].elem); \ | 589 | sc->debug.stats.txstats[WME_AC_VO].elem); \ |
590 | if (len >= size) \ | ||
591 | goto done; \ | ||
590 | } while(0) | 592 | } while(0) |
591 | 593 | ||
594 | #define PRX(str, elem) \ | ||
595 | do { \ | ||
596 | len += snprintf(buf + len, size - len, \ | ||
597 | "%s%13u%11u%10u%10u\n", str, \ | ||
598 | (unsigned int)(sc->tx.txq[ATH_TXQ_AC_BE].elem), \ | ||
599 | (unsigned int)(sc->tx.txq[ATH_TXQ_AC_BK].elem), \ | ||
600 | (unsigned int)(sc->tx.txq[ATH_TXQ_AC_VI].elem), \ | ||
601 | (unsigned int)(sc->tx.txq[ATH_TXQ_AC_VO].elem)); \ | ||
602 | if (len >= size) \ | ||
603 | goto done; \ | ||
604 | } while(0) | ||
605 | |||
606 | #define PRQLE(str, elem) \ | ||
607 | do { \ | ||
608 | len += snprintf(buf + len, size - len, \ | ||
609 | "%s%13i%11i%10i%10i\n", str, \ | ||
610 | list_empty(&sc->tx.txq[ATH_TXQ_AC_BE].elem), \ | ||
611 | list_empty(&sc->tx.txq[ATH_TXQ_AC_BK].elem), \ | ||
612 | list_empty(&sc->tx.txq[ATH_TXQ_AC_VI].elem), \ | ||
613 | list_empty(&sc->tx.txq[ATH_TXQ_AC_VO].elem)); \ | ||
614 | if (len >= size) \ | ||
615 | goto done; \ | ||
616 | } while (0) | ||
617 | |||
592 | static ssize_t read_file_xmit(struct file *file, char __user *user_buf, | 618 | static ssize_t read_file_xmit(struct file *file, char __user *user_buf, |
593 | size_t count, loff_t *ppos) | 619 | size_t count, loff_t *ppos) |
594 | { | 620 | { |
595 | struct ath_softc *sc = file->private_data; | 621 | struct ath_softc *sc = file->private_data; |
596 | char *buf; | 622 | char *buf; |
597 | unsigned int len = 0, size = 2048; | 623 | unsigned int len = 0, size = 8000; |
624 | int i; | ||
598 | ssize_t retval = 0; | 625 | ssize_t retval = 0; |
626 | char tmp[32]; | ||
599 | 627 | ||
600 | buf = kzalloc(size, GFP_KERNEL); | 628 | buf = kzalloc(size, GFP_KERNEL); |
601 | if (buf == NULL) | 629 | if (buf == NULL) |
602 | return -ENOMEM; | 630 | return -ENOMEM; |
603 | 631 | ||
604 | len += sprintf(buf, "%30s %10s%10s%10s\n\n", "BE", "BK", "VI", "VO"); | 632 | len += sprintf(buf, "Num-Tx-Queues: %i tx-queues-setup: 0x%x" |
633 | " poll-work-seen: %u\n" | ||
634 | "%30s %10s%10s%10s\n\n", | ||
635 | ATH9K_NUM_TX_QUEUES, sc->tx.txqsetup, | ||
636 | sc->tx_complete_poll_work_seen, | ||
637 | "BE", "BK", "VI", "VO"); | ||
605 | 638 | ||
606 | PR("MPDUs Queued: ", queued); | 639 | PR("MPDUs Queued: ", queued); |
607 | PR("MPDUs Completed: ", completed); | 640 | PR("MPDUs Completed: ", completed); |
608 | PR("Aggregates: ", a_aggr); | 641 | PR("Aggregates: ", a_aggr); |
609 | PR("AMPDUs Queued: ", a_queued); | 642 | PR("AMPDUs Queued HW:", a_queued_hw); |
643 | PR("AMPDUs Queued SW:", a_queued_sw); | ||
610 | PR("AMPDUs Completed:", a_completed); | 644 | PR("AMPDUs Completed:", a_completed); |
611 | PR("AMPDUs Retried: ", a_retries); | 645 | PR("AMPDUs Retried: ", a_retries); |
612 | PR("AMPDUs XRetried: ", a_xretries); | 646 | PR("AMPDUs XRetried: ", a_xretries); |
@@ -618,6 +652,223 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf, | |||
618 | PR("DELIM Underrun: ", delim_underrun); | 652 | PR("DELIM Underrun: ", delim_underrun); |
619 | PR("TX-Pkts-All: ", tx_pkts_all); | 653 | PR("TX-Pkts-All: ", tx_pkts_all); |
620 | PR("TX-Bytes-All: ", tx_bytes_all); | 654 | PR("TX-Bytes-All: ", tx_bytes_all); |
655 | PR("hw-put-tx-buf: ", puttxbuf); | ||
656 | PR("hw-tx-start: ", txstart); | ||
657 | PR("hw-tx-proc-desc: ", txprocdesc); | ||
658 | len += snprintf(buf + len, size - len, | ||
659 | "%s%11p%11p%10p%10p\n", "txq-memory-address:", | ||
660 | &(sc->tx.txq[ATH_TXQ_AC_BE]), | ||
661 | &(sc->tx.txq[ATH_TXQ_AC_BK]), | ||
662 | &(sc->tx.txq[ATH_TXQ_AC_VI]), | ||
663 | &(sc->tx.txq[ATH_TXQ_AC_VO])); | ||
664 | if (len >= size) | ||
665 | goto done; | ||
666 | |||
667 | PRX("axq-qnum: ", axq_qnum); | ||
668 | PRX("axq-depth: ", axq_depth); | ||
669 | PRX("axq-ampdu_depth: ", axq_ampdu_depth); | ||
670 | PRX("axq-stopped ", stopped); | ||
671 | PRX("tx-in-progress ", axq_tx_inprogress); | ||
672 | PRX("pending-frames ", pending_frames); | ||
673 | PRX("txq_headidx: ", txq_headidx); | ||
674 | PRX("txq_tailidx: ", txq_headidx); | ||
675 | |||
676 | PRQLE("axq_q empty: ", axq_q); | ||
677 | PRQLE("axq_acq empty: ", axq_acq); | ||
678 | PRQLE("txq_fifo_pending: ", txq_fifo_pending); | ||
679 | for (i = 0; i < ATH_TXFIFO_DEPTH; i++) { | ||
680 | snprintf(tmp, sizeof(tmp) - 1, "txq_fifo[%i] empty: ", i); | ||
681 | PRQLE(tmp, txq_fifo[i]); | ||
682 | } | ||
683 | |||
684 | /* Print out more detailed queue-info */ | ||
685 | for (i = 0; i <= WME_AC_BK; i++) { | ||
686 | struct ath_txq *txq = &(sc->tx.txq[i]); | ||
687 | struct ath_atx_ac *ac; | ||
688 | struct ath_atx_tid *tid; | ||
689 | if (len >= size) | ||
690 | goto done; | ||
691 | spin_lock_bh(&txq->axq_lock); | ||
692 | if (!list_empty(&txq->axq_acq)) { | ||
693 | ac = list_first_entry(&txq->axq_acq, struct ath_atx_ac, | ||
694 | list); | ||
695 | len += snprintf(buf + len, size - len, | ||
696 | "txq[%i] first-ac: %p sched: %i\n", | ||
697 | i, ac, ac->sched); | ||
698 | if (list_empty(&ac->tid_q) || (len >= size)) | ||
699 | goto done_for; | ||
700 | tid = list_first_entry(&ac->tid_q, struct ath_atx_tid, | ||
701 | list); | ||
702 | len += snprintf(buf + len, size - len, | ||
703 | " first-tid: %p sched: %i paused: %i\n", | ||
704 | tid, tid->sched, tid->paused); | ||
705 | } | ||
706 | done_for: | ||
707 | spin_unlock_bh(&txq->axq_lock); | ||
708 | } | ||
709 | |||
710 | done: | ||
711 | if (len > size) | ||
712 | len = size; | ||
713 | |||
714 | retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
715 | kfree(buf); | ||
716 | |||
717 | return retval; | ||
718 | } | ||
719 | |||
720 | static ssize_t read_file_stations(struct file *file, char __user *user_buf, | ||
721 | size_t count, loff_t *ppos) | ||
722 | { | ||
723 | struct ath_softc *sc = file->private_data; | ||
724 | char *buf; | ||
725 | unsigned int len = 0, size = 64000; | ||
726 | struct ath_node *an = NULL; | ||
727 | ssize_t retval = 0; | ||
728 | int q; | ||
729 | |||
730 | buf = kzalloc(size, GFP_KERNEL); | ||
731 | if (buf == NULL) | ||
732 | return -ENOMEM; | ||
733 | |||
734 | len += snprintf(buf + len, size - len, | ||
735 | "Stations:\n" | ||
736 | " tid: addr sched paused buf_q-empty an ac\n" | ||
737 | " ac: addr sched tid_q-empty txq\n"); | ||
738 | |||
739 | spin_lock(&sc->nodes_lock); | ||
740 | list_for_each_entry(an, &sc->nodes, list) { | ||
741 | len += snprintf(buf + len, size - len, | ||
742 | "%pM\n", an->sta->addr); | ||
743 | if (len >= size) | ||
744 | goto done; | ||
745 | |||
746 | for (q = 0; q < WME_NUM_TID; q++) { | ||
747 | struct ath_atx_tid *tid = &(an->tid[q]); | ||
748 | len += snprintf(buf + len, size - len, | ||
749 | " tid: %p %s %s %i %p %p\n", | ||
750 | tid, tid->sched ? "sched" : "idle", | ||
751 | tid->paused ? "paused" : "running", | ||
752 | list_empty(&tid->buf_q), | ||
753 | tid->an, tid->ac); | ||
754 | if (len >= size) | ||
755 | goto done; | ||
756 | } | ||
757 | |||
758 | for (q = 0; q < WME_NUM_AC; q++) { | ||
759 | struct ath_atx_ac *ac = &(an->ac[q]); | ||
760 | len += snprintf(buf + len, size - len, | ||
761 | " ac: %p %s %i %p\n", | ||
762 | ac, ac->sched ? "sched" : "idle", | ||
763 | list_empty(&ac->tid_q), ac->txq); | ||
764 | if (len >= size) | ||
765 | goto done; | ||
766 | } | ||
767 | } | ||
768 | |||
769 | done: | ||
770 | spin_unlock(&sc->nodes_lock); | ||
771 | if (len > size) | ||
772 | len = size; | ||
773 | |||
774 | retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
775 | kfree(buf); | ||
776 | |||
777 | return retval; | ||
778 | } | ||
779 | |||
780 | static ssize_t read_file_misc(struct file *file, char __user *user_buf, | ||
781 | size_t count, loff_t *ppos) | ||
782 | { | ||
783 | struct ath_softc *sc = file->private_data; | ||
784 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
785 | struct ath_hw *ah = sc->sc_ah; | ||
786 | struct ieee80211_hw *hw = sc->hw; | ||
787 | char *buf; | ||
788 | unsigned int len = 0, size = 8000; | ||
789 | ssize_t retval = 0; | ||
790 | const char *tmp; | ||
791 | unsigned int reg; | ||
792 | struct ath9k_vif_iter_data iter_data; | ||
793 | |||
794 | ath9k_calculate_iter_data(hw, NULL, &iter_data); | ||
795 | |||
796 | buf = kzalloc(size, GFP_KERNEL); | ||
797 | if (buf == NULL) | ||
798 | return -ENOMEM; | ||
799 | |||
800 | switch (sc->sc_ah->opmode) { | ||
801 | case NL80211_IFTYPE_ADHOC: | ||
802 | tmp = "ADHOC"; | ||
803 | break; | ||
804 | case NL80211_IFTYPE_MESH_POINT: | ||
805 | tmp = "MESH"; | ||
806 | break; | ||
807 | case NL80211_IFTYPE_AP: | ||
808 | tmp = "AP"; | ||
809 | break; | ||
810 | case NL80211_IFTYPE_STATION: | ||
811 | tmp = "STATION"; | ||
812 | break; | ||
813 | default: | ||
814 | tmp = "???"; | ||
815 | break; | ||
816 | } | ||
817 | |||
818 | len += snprintf(buf + len, size - len, | ||
819 | "curbssid: %pM\n" | ||
820 | "OP-Mode: %s(%i)\n" | ||
821 | "Beacon-Timer-Register: 0x%x\n", | ||
822 | common->curbssid, | ||
823 | tmp, (int)(sc->sc_ah->opmode), | ||
824 | REG_READ(ah, AR_BEACON_PERIOD)); | ||
825 | |||
826 | reg = REG_READ(ah, AR_TIMER_MODE); | ||
827 | len += snprintf(buf + len, size - len, "Timer-Mode-Register: 0x%x (", | ||
828 | reg); | ||
829 | if (reg & AR_TBTT_TIMER_EN) | ||
830 | len += snprintf(buf + len, size - len, "TBTT "); | ||
831 | if (reg & AR_DBA_TIMER_EN) | ||
832 | len += snprintf(buf + len, size - len, "DBA "); | ||
833 | if (reg & AR_SWBA_TIMER_EN) | ||
834 | len += snprintf(buf + len, size - len, "SWBA "); | ||
835 | if (reg & AR_HCF_TIMER_EN) | ||
836 | len += snprintf(buf + len, size - len, "HCF "); | ||
837 | if (reg & AR_TIM_TIMER_EN) | ||
838 | len += snprintf(buf + len, size - len, "TIM "); | ||
839 | if (reg & AR_DTIM_TIMER_EN) | ||
840 | len += snprintf(buf + len, size - len, "DTIM "); | ||
841 | len += snprintf(buf + len, size - len, ")\n"); | ||
842 | |||
843 | reg = sc->sc_ah->imask; | ||
844 | len += snprintf(buf + len, size - len, "imask: 0x%x (", reg); | ||
845 | if (reg & ATH9K_INT_SWBA) | ||
846 | len += snprintf(buf + len, size - len, "SWBA "); | ||
847 | if (reg & ATH9K_INT_BMISS) | ||
848 | len += snprintf(buf + len, size - len, "BMISS "); | ||
849 | if (reg & ATH9K_INT_CST) | ||
850 | len += snprintf(buf + len, size - len, "CST "); | ||
851 | if (reg & ATH9K_INT_RX) | ||
852 | len += snprintf(buf + len, size - len, "RX "); | ||
853 | if (reg & ATH9K_INT_RXHP) | ||
854 | len += snprintf(buf + len, size - len, "RXHP "); | ||
855 | if (reg & ATH9K_INT_RXLP) | ||
856 | len += snprintf(buf + len, size - len, "RXLP "); | ||
857 | if (reg & ATH9K_INT_BB_WATCHDOG) | ||
858 | len += snprintf(buf + len, size - len, "BB_WATCHDOG "); | ||
859 | /* there are other IRQs if one wanted to add them. */ | ||
860 | len += snprintf(buf + len, size - len, ")\n"); | ||
861 | |||
862 | len += snprintf(buf + len, size - len, | ||
863 | "VIF Counts: AP: %i STA: %i MESH: %i WDS: %i" | ||
864 | " ADHOC: %i OTHER: %i nvifs: %hi beacon-vifs: %hi\n", | ||
865 | iter_data.naps, iter_data.nstations, iter_data.nmeshes, | ||
866 | iter_data.nwds, iter_data.nadhocs, iter_data.nothers, | ||
867 | sc->nvifs, sc->nbcnvifs); | ||
868 | |||
869 | len += snprintf(buf + len, size - len, | ||
870 | "Calculated-BSSID-Mask: %pM\n", | ||
871 | iter_data.mask); | ||
621 | 872 | ||
622 | if (len > size) | 873 | if (len > size) |
623 | len = size; | 874 | len = size; |
@@ -666,6 +917,20 @@ static const struct file_operations fops_xmit = { | |||
666 | .llseek = default_llseek, | 917 | .llseek = default_llseek, |
667 | }; | 918 | }; |
668 | 919 | ||
920 | static const struct file_operations fops_stations = { | ||
921 | .read = read_file_stations, | ||
922 | .open = ath9k_debugfs_open, | ||
923 | .owner = THIS_MODULE, | ||
924 | .llseek = default_llseek, | ||
925 | }; | ||
926 | |||
927 | static const struct file_operations fops_misc = { | ||
928 | .read = read_file_misc, | ||
929 | .open = ath9k_debugfs_open, | ||
930 | .owner = THIS_MODULE, | ||
931 | .llseek = default_llseek, | ||
932 | }; | ||
933 | |||
669 | static ssize_t read_file_recv(struct file *file, char __user *user_buf, | 934 | static ssize_t read_file_recv(struct file *file, char __user *user_buf, |
670 | size_t count, loff_t *ppos) | 935 | size_t count, loff_t *ppos) |
671 | { | 936 | { |
@@ -903,6 +1168,14 @@ int ath9k_init_debug(struct ath_hw *ah) | |||
903 | sc, &fops_xmit)) | 1168 | sc, &fops_xmit)) |
904 | goto err; | 1169 | goto err; |
905 | 1170 | ||
1171 | if (!debugfs_create_file("stations", S_IRUSR, sc->debug.debugfs_phy, | ||
1172 | sc, &fops_stations)) | ||
1173 | goto err; | ||
1174 | |||
1175 | if (!debugfs_create_file("misc", S_IRUSR, sc->debug.debugfs_phy, | ||
1176 | sc, &fops_misc)) | ||
1177 | goto err; | ||
1178 | |||
906 | if (!debugfs_create_file("recv", S_IRUSR, sc->debug.debugfs_phy, | 1179 | if (!debugfs_create_file("recv", S_IRUSR, sc->debug.debugfs_phy, |
907 | sc, &fops_recv)) | 1180 | sc, &fops_recv)) |
908 | goto err; | 1181 | goto err; |
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index 1e5078bd0344..980c9fa194b9 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h | |||
@@ -89,7 +89,8 @@ struct ath_interrupt_stats { | |||
89 | * @queued: Total MPDUs (non-aggr) queued | 89 | * @queued: Total MPDUs (non-aggr) queued |
90 | * @completed: Total MPDUs (non-aggr) completed | 90 | * @completed: Total MPDUs (non-aggr) completed |
91 | * @a_aggr: Total no. of aggregates queued | 91 | * @a_aggr: Total no. of aggregates queued |
92 | * @a_queued: Total AMPDUs queued | 92 | * @a_queued_hw: Total AMPDUs queued to hardware |
93 | * @a_queued_sw: Total AMPDUs queued to software queues | ||
93 | * @a_completed: Total AMPDUs completed | 94 | * @a_completed: Total AMPDUs completed |
94 | * @a_retries: No. of AMPDUs retried (SW) | 95 | * @a_retries: No. of AMPDUs retried (SW) |
95 | * @a_xretries: No. of AMPDUs dropped due to xretries | 96 | * @a_xretries: No. of AMPDUs dropped due to xretries |
@@ -102,6 +103,9 @@ struct ath_interrupt_stats { | |||
102 | * @desc_cfg_err: Descriptor configuration errors | 103 | * @desc_cfg_err: Descriptor configuration errors |
103 | * @data_urn: TX data underrun errors | 104 | * @data_urn: TX data underrun errors |
104 | * @delim_urn: TX delimiter underrun errors | 105 | * @delim_urn: TX delimiter underrun errors |
106 | * @puttxbuf: Number of times hardware was given txbuf to write. | ||
107 | * @txstart: Number of times hardware was told to start tx. | ||
108 | * @txprocdesc: Number of times tx descriptor was processed | ||
105 | */ | 109 | */ |
106 | struct ath_tx_stats { | 110 | struct ath_tx_stats { |
107 | u32 tx_pkts_all; | 111 | u32 tx_pkts_all; |
@@ -109,7 +113,8 @@ struct ath_tx_stats { | |||
109 | u32 queued; | 113 | u32 queued; |
110 | u32 completed; | 114 | u32 completed; |
111 | u32 a_aggr; | 115 | u32 a_aggr; |
112 | u32 a_queued; | 116 | u32 a_queued_hw; |
117 | u32 a_queued_sw; | ||
113 | u32 a_completed; | 118 | u32 a_completed; |
114 | u32 a_retries; | 119 | u32 a_retries; |
115 | u32 a_xretries; | 120 | u32 a_xretries; |
@@ -119,6 +124,9 @@ struct ath_tx_stats { | |||
119 | u32 desc_cfg_err; | 124 | u32 desc_cfg_err; |
120 | u32 data_underrun; | 125 | u32 data_underrun; |
121 | u32 delim_underrun; | 126 | u32 delim_underrun; |
127 | u32 puttxbuf; | ||
128 | u32 txstart; | ||
129 | u32 txprocdesc; | ||
122 | }; | 130 | }; |
123 | 131 | ||
124 | /** | 132 | /** |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c index d05163159572..8c18bed3a558 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.c +++ b/drivers/net/wireless/ath/ath9k/eeprom.c | |||
@@ -89,6 +89,38 @@ bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList, u16 listSize, | |||
89 | return false; | 89 | return false; |
90 | } | 90 | } |
91 | 91 | ||
92 | void ath9k_hw_usb_gen_fill_eeprom(struct ath_hw *ah, u16 *eep_data, | ||
93 | int eep_start_loc, int size) | ||
94 | { | ||
95 | int i = 0, j, addr; | ||
96 | u32 addrdata[8]; | ||
97 | u32 data[8]; | ||
98 | |||
99 | for (addr = 0; addr < size; addr++) { | ||
100 | addrdata[i] = AR5416_EEPROM_OFFSET + | ||
101 | ((addr + eep_start_loc) << AR5416_EEPROM_S); | ||
102 | i++; | ||
103 | if (i == 8) { | ||
104 | REG_READ_MULTI(ah, addrdata, data, i); | ||
105 | |||
106 | for (j = 0; j < i; j++) { | ||
107 | *eep_data = data[j]; | ||
108 | eep_data++; | ||
109 | } | ||
110 | i = 0; | ||
111 | } | ||
112 | } | ||
113 | |||
114 | if (i != 0) { | ||
115 | REG_READ_MULTI(ah, addrdata, data, i); | ||
116 | |||
117 | for (j = 0; j < i; j++) { | ||
118 | *eep_data = data[j]; | ||
119 | eep_data++; | ||
120 | } | ||
121 | } | ||
122 | } | ||
123 | |||
92 | bool ath9k_hw_nvram_read(struct ath_common *common, u32 off, u16 *data) | 124 | bool ath9k_hw_nvram_read(struct ath_common *common, u32 off, u16 *data) |
93 | { | 125 | { |
94 | return common->bus_ops->eeprom_read(common, off, data); | 126 | return common->bus_ops->eeprom_read(common, off, data); |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h index 58e2ddc927a9..bd82447f5b78 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.h +++ b/drivers/net/wireless/ath/ath9k/eeprom.h | |||
@@ -665,6 +665,8 @@ int16_t ath9k_hw_interpolate(u16 target, u16 srcLeft, u16 srcRight, | |||
665 | bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList, u16 listSize, | 665 | bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList, u16 listSize, |
666 | u16 *indexL, u16 *indexR); | 666 | u16 *indexL, u16 *indexR); |
667 | bool ath9k_hw_nvram_read(struct ath_common *common, u32 off, u16 *data); | 667 | bool ath9k_hw_nvram_read(struct ath_common *common, u32 off, u16 *data); |
668 | void ath9k_hw_usb_gen_fill_eeprom(struct ath_hw *ah, u16 *eep_data, | ||
669 | int eep_start_loc, int size); | ||
668 | void ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList, | 670 | void ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList, |
669 | u8 *pVpdList, u16 numIntercepts, | 671 | u8 *pVpdList, u16 numIntercepts, |
670 | u8 *pRetVpdList); | 672 | u8 *pRetVpdList); |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c index fbdff7e47952..bc77a308c901 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c | |||
@@ -27,19 +27,13 @@ static int ath9k_hw_4k_get_eeprom_rev(struct ath_hw *ah) | |||
27 | return ((ah->eeprom.map4k.baseEepHeader.version) & 0xFFF); | 27 | return ((ah->eeprom.map4k.baseEepHeader.version) & 0xFFF); |
28 | } | 28 | } |
29 | 29 | ||
30 | static bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah) | ||
31 | { | ||
32 | #define SIZE_EEPROM_4K (sizeof(struct ar5416_eeprom_4k) / sizeof(u16)) | 30 | #define SIZE_EEPROM_4K (sizeof(struct ar5416_eeprom_4k) / sizeof(u16)) |
31 | |||
32 | static bool __ath9k_hw_4k_fill_eeprom(struct ath_hw *ah) | ||
33 | { | ||
33 | struct ath_common *common = ath9k_hw_common(ah); | 34 | struct ath_common *common = ath9k_hw_common(ah); |
34 | u16 *eep_data = (u16 *)&ah->eeprom.map4k; | 35 | u16 *eep_data = (u16 *)&ah->eeprom.map4k; |
35 | int addr, eep_start_loc = 0; | 36 | int addr, eep_start_loc = 64; |
36 | |||
37 | eep_start_loc = 64; | ||
38 | |||
39 | if (!ath9k_hw_use_flash(ah)) { | ||
40 | ath_dbg(common, ATH_DBG_EEPROM, | ||
41 | "Reading from EEPROM, not flash\n"); | ||
42 | } | ||
43 | 37 | ||
44 | for (addr = 0; addr < SIZE_EEPROM_4K; addr++) { | 38 | for (addr = 0; addr < SIZE_EEPROM_4K; addr++) { |
45 | if (!ath9k_hw_nvram_read(common, addr + eep_start_loc, eep_data)) { | 39 | if (!ath9k_hw_nvram_read(common, addr + eep_start_loc, eep_data)) { |
@@ -51,9 +45,34 @@ static bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah) | |||
51 | } | 45 | } |
52 | 46 | ||
53 | return true; | 47 | return true; |
54 | #undef SIZE_EEPROM_4K | ||
55 | } | 48 | } |
56 | 49 | ||
50 | static bool __ath9k_hw_usb_4k_fill_eeprom(struct ath_hw *ah) | ||
51 | { | ||
52 | u16 *eep_data = (u16 *)&ah->eeprom.map4k; | ||
53 | |||
54 | ath9k_hw_usb_gen_fill_eeprom(ah, eep_data, 64, SIZE_EEPROM_4K); | ||
55 | |||
56 | return true; | ||
57 | } | ||
58 | |||
59 | static bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah) | ||
60 | { | ||
61 | struct ath_common *common = ath9k_hw_common(ah); | ||
62 | |||
63 | if (!ath9k_hw_use_flash(ah)) { | ||
64 | ath_dbg(common, ATH_DBG_EEPROM, | ||
65 | "Reading from EEPROM, not flash\n"); | ||
66 | } | ||
67 | |||
68 | if (common->bus_ops->ath_bus_type == ATH_USB) | ||
69 | return __ath9k_hw_usb_4k_fill_eeprom(ah); | ||
70 | else | ||
71 | return __ath9k_hw_4k_fill_eeprom(ah); | ||
72 | } | ||
73 | |||
74 | #undef SIZE_EEPROM_4K | ||
75 | |||
57 | static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah) | 76 | static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah) |
58 | { | 77 | { |
59 | #define EEPROM_4K_SIZE (sizeof(struct ar5416_eeprom_4k) / sizeof(u16)) | 78 | #define EEPROM_4K_SIZE (sizeof(struct ar5416_eeprom_4k) / sizeof(u16)) |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c index 9b6bc8a953bc..8cd8333cc086 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c | |||
@@ -17,7 +17,7 @@ | |||
17 | #include "hw.h" | 17 | #include "hw.h" |
18 | #include "ar9002_phy.h" | 18 | #include "ar9002_phy.h" |
19 | 19 | ||
20 | #define NUM_EEP_WORDS (sizeof(struct ar9287_eeprom) / sizeof(u16)) | 20 | #define SIZE_EEPROM_AR9287 (sizeof(struct ar9287_eeprom) / sizeof(u16)) |
21 | 21 | ||
22 | static int ath9k_hw_ar9287_get_eeprom_ver(struct ath_hw *ah) | 22 | static int ath9k_hw_ar9287_get_eeprom_ver(struct ath_hw *ah) |
23 | { | 23 | { |
@@ -29,25 +29,15 @@ static int ath9k_hw_ar9287_get_eeprom_rev(struct ath_hw *ah) | |||
29 | return (ah->eeprom.map9287.baseEepHeader.version) & 0xFFF; | 29 | return (ah->eeprom.map9287.baseEepHeader.version) & 0xFFF; |
30 | } | 30 | } |
31 | 31 | ||
32 | static bool ath9k_hw_ar9287_fill_eeprom(struct ath_hw *ah) | 32 | static bool __ath9k_hw_ar9287_fill_eeprom(struct ath_hw *ah) |
33 | { | 33 | { |
34 | struct ar9287_eeprom *eep = &ah->eeprom.map9287; | 34 | struct ar9287_eeprom *eep = &ah->eeprom.map9287; |
35 | struct ath_common *common = ath9k_hw_common(ah); | 35 | struct ath_common *common = ath9k_hw_common(ah); |
36 | u16 *eep_data; | 36 | u16 *eep_data; |
37 | int addr, eep_start_loc; | 37 | int addr, eep_start_loc = AR9287_EEP_START_LOC; |
38 | eep_data = (u16 *)eep; | 38 | eep_data = (u16 *)eep; |
39 | 39 | ||
40 | if (common->bus_ops->ath_bus_type == ATH_USB) | 40 | for (addr = 0; addr < SIZE_EEPROM_AR9287; addr++) { |
41 | eep_start_loc = AR9287_HTC_EEP_START_LOC; | ||
42 | else | ||
43 | eep_start_loc = AR9287_EEP_START_LOC; | ||
44 | |||
45 | if (!ath9k_hw_use_flash(ah)) { | ||
46 | ath_dbg(common, ATH_DBG_EEPROM, | ||
47 | "Reading from EEPROM, not flash\n"); | ||
48 | } | ||
49 | |||
50 | for (addr = 0; addr < NUM_EEP_WORDS; addr++) { | ||
51 | if (!ath9k_hw_nvram_read(common, addr + eep_start_loc, | 41 | if (!ath9k_hw_nvram_read(common, addr + eep_start_loc, |
52 | eep_data)) { | 42 | eep_data)) { |
53 | ath_dbg(common, ATH_DBG_EEPROM, | 43 | ath_dbg(common, ATH_DBG_EEPROM, |
@@ -60,6 +50,31 @@ static bool ath9k_hw_ar9287_fill_eeprom(struct ath_hw *ah) | |||
60 | return true; | 50 | return true; |
61 | } | 51 | } |
62 | 52 | ||
53 | static bool __ath9k_hw_usb_ar9287_fill_eeprom(struct ath_hw *ah) | ||
54 | { | ||
55 | u16 *eep_data = (u16 *)&ah->eeprom.map9287; | ||
56 | |||
57 | ath9k_hw_usb_gen_fill_eeprom(ah, eep_data, | ||
58 | AR9287_HTC_EEP_START_LOC, | ||
59 | SIZE_EEPROM_AR9287); | ||
60 | return true; | ||
61 | } | ||
62 | |||
63 | static bool ath9k_hw_ar9287_fill_eeprom(struct ath_hw *ah) | ||
64 | { | ||
65 | struct ath_common *common = ath9k_hw_common(ah); | ||
66 | |||
67 | if (!ath9k_hw_use_flash(ah)) { | ||
68 | ath_dbg(common, ATH_DBG_EEPROM, | ||
69 | "Reading from EEPROM, not flash\n"); | ||
70 | } | ||
71 | |||
72 | if (common->bus_ops->ath_bus_type == ATH_USB) | ||
73 | return __ath9k_hw_usb_ar9287_fill_eeprom(ah); | ||
74 | else | ||
75 | return __ath9k_hw_ar9287_fill_eeprom(ah); | ||
76 | } | ||
77 | |||
63 | static int ath9k_hw_ar9287_check_eeprom(struct ath_hw *ah) | 78 | static int ath9k_hw_ar9287_check_eeprom(struct ath_hw *ah) |
64 | { | 79 | { |
65 | u32 sum = 0, el, integer; | 80 | u32 sum = 0, el, integer; |
@@ -86,7 +101,7 @@ static int ath9k_hw_ar9287_check_eeprom(struct ath_hw *ah) | |||
86 | need_swap = true; | 101 | need_swap = true; |
87 | eepdata = (u16 *)(&ah->eeprom); | 102 | eepdata = (u16 *)(&ah->eeprom); |
88 | 103 | ||
89 | for (addr = 0; addr < NUM_EEP_WORDS; addr++) { | 104 | for (addr = 0; addr < SIZE_EEPROM_AR9287; addr++) { |
90 | temp = swab16(*eepdata); | 105 | temp = swab16(*eepdata); |
91 | *eepdata = temp; | 106 | *eepdata = temp; |
92 | eepdata++; | 107 | eepdata++; |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c index 749a93608664..c9318ff40964 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c | |||
@@ -86,9 +86,10 @@ static int ath9k_hw_def_get_eeprom_rev(struct ath_hw *ah) | |||
86 | return ((ah->eeprom.def.baseEepHeader.version) & 0xFFF); | 86 | return ((ah->eeprom.def.baseEepHeader.version) & 0xFFF); |
87 | } | 87 | } |
88 | 88 | ||
89 | static bool ath9k_hw_def_fill_eeprom(struct ath_hw *ah) | ||
90 | { | ||
91 | #define SIZE_EEPROM_DEF (sizeof(struct ar5416_eeprom_def) / sizeof(u16)) | 89 | #define SIZE_EEPROM_DEF (sizeof(struct ar5416_eeprom_def) / sizeof(u16)) |
90 | |||
91 | static bool __ath9k_hw_def_fill_eeprom(struct ath_hw *ah) | ||
92 | { | ||
92 | struct ath_common *common = ath9k_hw_common(ah); | 93 | struct ath_common *common = ath9k_hw_common(ah); |
93 | u16 *eep_data = (u16 *)&ah->eeprom.def; | 94 | u16 *eep_data = (u16 *)&ah->eeprom.def; |
94 | int addr, ar5416_eep_start_loc = 0x100; | 95 | int addr, ar5416_eep_start_loc = 0x100; |
@@ -103,9 +104,34 @@ static bool ath9k_hw_def_fill_eeprom(struct ath_hw *ah) | |||
103 | eep_data++; | 104 | eep_data++; |
104 | } | 105 | } |
105 | return true; | 106 | return true; |
106 | #undef SIZE_EEPROM_DEF | ||
107 | } | 107 | } |
108 | 108 | ||
109 | static bool __ath9k_hw_usb_def_fill_eeprom(struct ath_hw *ah) | ||
110 | { | ||
111 | u16 *eep_data = (u16 *)&ah->eeprom.def; | ||
112 | |||
113 | ath9k_hw_usb_gen_fill_eeprom(ah, eep_data, | ||
114 | 0x100, SIZE_EEPROM_DEF); | ||
115 | return true; | ||
116 | } | ||
117 | |||
118 | static bool ath9k_hw_def_fill_eeprom(struct ath_hw *ah) | ||
119 | { | ||
120 | struct ath_common *common = ath9k_hw_common(ah); | ||
121 | |||
122 | if (!ath9k_hw_use_flash(ah)) { | ||
123 | ath_dbg(common, ATH_DBG_EEPROM, | ||
124 | "Reading from EEPROM, not flash\n"); | ||
125 | } | ||
126 | |||
127 | if (common->bus_ops->ath_bus_type == ATH_USB) | ||
128 | return __ath9k_hw_usb_def_fill_eeprom(ah); | ||
129 | else | ||
130 | return __ath9k_hw_def_fill_eeprom(ah); | ||
131 | } | ||
132 | |||
133 | #undef SIZE_EEPROM_DEF | ||
134 | |||
109 | static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) | 135 | static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) |
110 | { | 136 | { |
111 | struct ar5416_eeprom_def *eep = | 137 | struct ar5416_eeprom_def *eep = |
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 780ac5eac501..63549868e686 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h | |||
@@ -366,7 +366,7 @@ struct ath9k_htc_priv { | |||
366 | u16 seq_no; | 366 | u16 seq_no; |
367 | u32 bmiss_cnt; | 367 | u32 bmiss_cnt; |
368 | 368 | ||
369 | struct ath9k_hw_cal_data caldata[ATH9K_NUM_CHANNELS]; | 369 | struct ath9k_hw_cal_data caldata; |
370 | 370 | ||
371 | spinlock_t beacon_lock; | 371 | spinlock_t beacon_lock; |
372 | 372 | ||
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 38433f9bfe59..8e04586c5256 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c | |||
@@ -297,6 +297,34 @@ static unsigned int ath9k_regread(void *hw_priv, u32 reg_offset) | |||
297 | return be32_to_cpu(val); | 297 | return be32_to_cpu(val); |
298 | } | 298 | } |
299 | 299 | ||
300 | static void ath9k_multi_regread(void *hw_priv, u32 *addr, | ||
301 | u32 *val, u16 count) | ||
302 | { | ||
303 | struct ath_hw *ah = (struct ath_hw *) hw_priv; | ||
304 | struct ath_common *common = ath9k_hw_common(ah); | ||
305 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; | ||
306 | __be32 tmpaddr[8]; | ||
307 | __be32 tmpval[8]; | ||
308 | int i, ret; | ||
309 | |||
310 | for (i = 0; i < count; i++) { | ||
311 | tmpaddr[i] = cpu_to_be32(addr[i]); | ||
312 | } | ||
313 | |||
314 | ret = ath9k_wmi_cmd(priv->wmi, WMI_REG_READ_CMDID, | ||
315 | (u8 *)tmpaddr , sizeof(u32) * count, | ||
316 | (u8 *)tmpval, sizeof(u32) * count, | ||
317 | 100); | ||
318 | if (unlikely(ret)) { | ||
319 | ath_dbg(common, ATH_DBG_WMI, | ||
320 | "Multiple REGISTER READ FAILED (count: %d)\n", count); | ||
321 | } | ||
322 | |||
323 | for (i = 0; i < count; i++) { | ||
324 | val[i] = be32_to_cpu(tmpval[i]); | ||
325 | } | ||
326 | } | ||
327 | |||
300 | static void ath9k_regwrite_single(void *hw_priv, u32 val, u32 reg_offset) | 328 | static void ath9k_regwrite_single(void *hw_priv, u32 val, u32 reg_offset) |
301 | { | 329 | { |
302 | struct ath_hw *ah = (struct ath_hw *) hw_priv; | 330 | struct ath_hw *ah = (struct ath_hw *) hw_priv; |
@@ -407,6 +435,7 @@ static void ath9k_regwrite_flush(void *hw_priv) | |||
407 | 435 | ||
408 | static const struct ath_ops ath9k_common_ops = { | 436 | static const struct ath_ops ath9k_common_ops = { |
409 | .read = ath9k_regread, | 437 | .read = ath9k_regread, |
438 | .multi_read = ath9k_multi_regread, | ||
410 | .write = ath9k_regwrite, | 439 | .write = ath9k_regwrite, |
411 | .enable_write_buffer = ath9k_enable_regwrite_buffer, | 440 | .enable_write_buffer = ath9k_enable_regwrite_buffer, |
412 | .write_flush = ath9k_regwrite_flush, | 441 | .write_flush = ath9k_regwrite_flush, |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index f4d576bc3ccd..f14f37d29f45 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c | |||
@@ -121,7 +121,7 @@ void ath9k_htc_reset(struct ath9k_htc_priv *priv) | |||
121 | struct ath_hw *ah = priv->ah; | 121 | struct ath_hw *ah = priv->ah; |
122 | struct ath_common *common = ath9k_hw_common(ah); | 122 | struct ath_common *common = ath9k_hw_common(ah); |
123 | struct ieee80211_channel *channel = priv->hw->conf.channel; | 123 | struct ieee80211_channel *channel = priv->hw->conf.channel; |
124 | struct ath9k_hw_cal_data *caldata; | 124 | struct ath9k_hw_cal_data *caldata = NULL; |
125 | enum htc_phymode mode; | 125 | enum htc_phymode mode; |
126 | __be16 htc_mode; | 126 | __be16 htc_mode; |
127 | u8 cmd_rsp; | 127 | u8 cmd_rsp; |
@@ -139,7 +139,7 @@ void ath9k_htc_reset(struct ath9k_htc_priv *priv) | |||
139 | WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); | 139 | WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); |
140 | WMI_CMD(WMI_STOP_RECV_CMDID); | 140 | WMI_CMD(WMI_STOP_RECV_CMDID); |
141 | 141 | ||
142 | caldata = &priv->caldata[channel->hw_value]; | 142 | caldata = &priv->caldata; |
143 | ret = ath9k_hw_reset(ah, ah->curchan, caldata, false); | 143 | ret = ath9k_hw_reset(ah, ah->curchan, caldata, false); |
144 | if (ret) { | 144 | if (ret) { |
145 | ath_err(common, | 145 | ath_err(common, |
@@ -202,7 +202,8 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, | |||
202 | channel->center_freq, conf_is_ht(conf), conf_is_ht40(conf), | 202 | channel->center_freq, conf_is_ht(conf), conf_is_ht40(conf), |
203 | fastcc); | 203 | fastcc); |
204 | 204 | ||
205 | caldata = &priv->caldata[channel->hw_value]; | 205 | if (!fastcc) |
206 | caldata = &priv->caldata; | ||
206 | ret = ath9k_hw_reset(ah, hchan, caldata, fastcc); | 207 | ret = ath9k_hw_reset(ah, hchan, caldata, fastcc); |
207 | if (ret) { | 208 | if (ret) { |
208 | ath_err(common, | 209 | ath_err(common, |
@@ -1548,7 +1549,7 @@ static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw, | |||
1548 | struct ieee80211_vif *vif, | 1549 | struct ieee80211_vif *vif, |
1549 | enum ieee80211_ampdu_mlme_action action, | 1550 | enum ieee80211_ampdu_mlme_action action, |
1550 | struct ieee80211_sta *sta, | 1551 | struct ieee80211_sta *sta, |
1551 | u16 tid, u16 *ssn) | 1552 | u16 tid, u16 *ssn, u8 buf_size) |
1552 | { | 1553 | { |
1553 | struct ath9k_htc_priv *priv = hw->priv; | 1554 | struct ath9k_htc_priv *priv = hw->priv; |
1554 | struct ath9k_htc_sta *ista; | 1555 | struct ath9k_htc_sta *ista; |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 9f01e50d5cda..4615fd9c9aa0 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -495,6 +495,17 @@ static int __ath9k_hw_init(struct ath_hw *ah) | |||
495 | if (ah->hw_version.devid == AR5416_AR9100_DEVID) | 495 | if (ah->hw_version.devid == AR5416_AR9100_DEVID) |
496 | ah->hw_version.macVersion = AR_SREV_VERSION_9100; | 496 | ah->hw_version.macVersion = AR_SREV_VERSION_9100; |
497 | 497 | ||
498 | ath9k_hw_read_revisions(ah); | ||
499 | |||
500 | /* | ||
501 | * Read back AR_WA into a permanent copy and set bits 14 and 17. | ||
502 | * We need to do this to avoid RMW of this register. We cannot | ||
503 | * read the reg when chip is asleep. | ||
504 | */ | ||
505 | ah->WARegVal = REG_READ(ah, AR_WA); | ||
506 | ah->WARegVal |= (AR_WA_D3_L1_DISABLE | | ||
507 | AR_WA_ASPM_TIMER_BASED_DISABLE); | ||
508 | |||
498 | if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) { | 509 | if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) { |
499 | ath_err(common, "Couldn't reset chip\n"); | 510 | ath_err(common, "Couldn't reset chip\n"); |
500 | return -EIO; | 511 | return -EIO; |
@@ -563,14 +574,6 @@ static int __ath9k_hw_init(struct ath_hw *ah) | |||
563 | 574 | ||
564 | ath9k_hw_init_mode_regs(ah); | 575 | ath9k_hw_init_mode_regs(ah); |
565 | 576 | ||
566 | /* | ||
567 | * Read back AR_WA into a permanent copy and set bits 14 and 17. | ||
568 | * We need to do this to avoid RMW of this register. We cannot | ||
569 | * read the reg when chip is asleep. | ||
570 | */ | ||
571 | ah->WARegVal = REG_READ(ah, AR_WA); | ||
572 | ah->WARegVal |= (AR_WA_D3_L1_DISABLE | | ||
573 | AR_WA_ASPM_TIMER_BASED_DISABLE); | ||
574 | 577 | ||
575 | if (ah->is_pciexpress) | 578 | if (ah->is_pciexpress) |
576 | ath9k_hw_configpcipowersave(ah, 0, 0); | 579 | ath9k_hw_configpcipowersave(ah, 0, 0); |
@@ -1082,8 +1085,6 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah) | |||
1082 | return false; | 1085 | return false; |
1083 | } | 1086 | } |
1084 | 1087 | ||
1085 | ath9k_hw_read_revisions(ah); | ||
1086 | |||
1087 | return ath9k_hw_set_reset(ah, ATH9K_RESET_WARM); | 1088 | return ath9k_hw_set_reset(ah, ATH9K_RESET_WARM); |
1088 | } | 1089 | } |
1089 | 1090 | ||
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index ea9fde670646..ad8c2c702130 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -70,6 +70,9 @@ | |||
70 | #define REG_READ(_ah, _reg) \ | 70 | #define REG_READ(_ah, _reg) \ |
71 | ath9k_hw_common(_ah)->ops->read((_ah), (_reg)) | 71 | ath9k_hw_common(_ah)->ops->read((_ah), (_reg)) |
72 | 72 | ||
73 | #define REG_READ_MULTI(_ah, _addr, _val, _cnt) \ | ||
74 | ath9k_hw_common(_ah)->ops->multi_read((_ah), (_addr), (_val), (_cnt)) | ||
75 | |||
73 | #define ENABLE_REGWRITE_BUFFER(_ah) \ | 76 | #define ENABLE_REGWRITE_BUFFER(_ah) \ |
74 | do { \ | 77 | do { \ |
75 | if (ath9k_hw_common(_ah)->ops->enable_write_buffer) \ | 78 | if (ath9k_hw_common(_ah)->ops->enable_write_buffer) \ |
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 767d8b86f1e1..5279653c90c7 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c | |||
@@ -442,9 +442,10 @@ static int ath9k_init_queues(struct ath_softc *sc) | |||
442 | sc->config.cabqReadytime = ATH_CABQ_READY_TIME; | 442 | sc->config.cabqReadytime = ATH_CABQ_READY_TIME; |
443 | ath_cabq_update(sc); | 443 | ath_cabq_update(sc); |
444 | 444 | ||
445 | for (i = 0; i < WME_NUM_AC; i++) | 445 | for (i = 0; i < WME_NUM_AC; i++) { |
446 | sc->tx.txq_map[i] = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, i); | 446 | sc->tx.txq_map[i] = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, i); |
447 | 447 | sc->tx.txq_map[i]->mac80211_qnum = i; | |
448 | } | ||
448 | return 0; | 449 | return 0; |
449 | } | 450 | } |
450 | 451 | ||
@@ -537,6 +538,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, | |||
537 | if (!ah) | 538 | if (!ah) |
538 | return -ENOMEM; | 539 | return -ENOMEM; |
539 | 540 | ||
541 | ah->hw = sc->hw; | ||
540 | ah->hw_version.devid = devid; | 542 | ah->hw_version.devid = devid; |
541 | ah->hw_version.subsysid = subsysid; | 543 | ah->hw_version.subsysid = subsysid; |
542 | sc->sc_ah = ah; | 544 | sc->sc_ah = ah; |
@@ -558,6 +560,10 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, | |||
558 | spin_lock_init(&sc->sc_serial_rw); | 560 | spin_lock_init(&sc->sc_serial_rw); |
559 | spin_lock_init(&sc->sc_pm_lock); | 561 | spin_lock_init(&sc->sc_pm_lock); |
560 | mutex_init(&sc->mutex); | 562 | mutex_init(&sc->mutex); |
563 | #ifdef CONFIG_ATH9K_DEBUGFS | ||
564 | spin_lock_init(&sc->nodes_lock); | ||
565 | INIT_LIST_HEAD(&sc->nodes); | ||
566 | #endif | ||
561 | tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc); | 567 | tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc); |
562 | tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet, | 568 | tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet, |
563 | (unsigned long)sc); | 569 | (unsigned long)sc); |
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 180170d3ce25..c75d40fb86f1 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c | |||
@@ -690,17 +690,23 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, | |||
690 | rs->rs_flags |= ATH9K_RX_DECRYPT_BUSY; | 690 | rs->rs_flags |= ATH9K_RX_DECRYPT_BUSY; |
691 | 691 | ||
692 | if ((ads.ds_rxstatus8 & AR_RxFrameOK) == 0) { | 692 | if ((ads.ds_rxstatus8 & AR_RxFrameOK) == 0) { |
693 | /* | ||
694 | * Treat these errors as mutually exclusive to avoid spurious | ||
695 | * extra error reports from the hardware. If a CRC error is | ||
696 | * reported, then decryption and MIC errors are irrelevant, | ||
697 | * the frame is going to be dropped either way | ||
698 | */ | ||
693 | if (ads.ds_rxstatus8 & AR_CRCErr) | 699 | if (ads.ds_rxstatus8 & AR_CRCErr) |
694 | rs->rs_status |= ATH9K_RXERR_CRC; | 700 | rs->rs_status |= ATH9K_RXERR_CRC; |
695 | if (ads.ds_rxstatus8 & AR_PHYErr) { | 701 | else if (ads.ds_rxstatus8 & AR_PHYErr) { |
696 | rs->rs_status |= ATH9K_RXERR_PHY; | 702 | rs->rs_status |= ATH9K_RXERR_PHY; |
697 | phyerr = MS(ads.ds_rxstatus8, AR_PHYErrCode); | 703 | phyerr = MS(ads.ds_rxstatus8, AR_PHYErrCode); |
698 | rs->rs_phyerr = phyerr; | 704 | rs->rs_phyerr = phyerr; |
699 | } | 705 | } else if (ads.ds_rxstatus8 & AR_DecryptCRCErr) |
700 | if (ads.ds_rxstatus8 & AR_DecryptCRCErr) | ||
701 | rs->rs_status |= ATH9K_RXERR_DECRYPT; | 706 | rs->rs_status |= ATH9K_RXERR_DECRYPT; |
702 | if (ads.ds_rxstatus8 & AR_MichaelErr) | 707 | else if (ads.ds_rxstatus8 & AR_MichaelErr) |
703 | rs->rs_status |= ATH9K_RXERR_MIC; | 708 | rs->rs_status |= ATH9K_RXERR_MIC; |
709 | |||
704 | if (ads.ds_rxstatus8 & AR_KeyMiss) | 710 | if (ads.ds_rxstatus8 & AR_KeyMiss) |
705 | rs->rs_status |= ATH9K_RXERR_DECRYPT; | 711 | rs->rs_status |= ATH9K_RXERR_DECRYPT; |
706 | } | 712 | } |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index c79c97be6cd4..facff102dd0e 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -251,6 +251,9 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | |||
251 | if (!ath_stoprecv(sc)) | 251 | if (!ath_stoprecv(sc)) |
252 | stopped = false; | 252 | stopped = false; |
253 | 253 | ||
254 | if (!ath9k_hw_check_alive(ah)) | ||
255 | stopped = false; | ||
256 | |||
254 | /* XXX: do not flush receive queue here. We don't want | 257 | /* XXX: do not flush receive queue here. We don't want |
255 | * to flush data frames already in queue because of | 258 | * to flush data frames already in queue because of |
256 | * changing channel. */ | 259 | * changing channel. */ |
@@ -545,6 +548,12 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta) | |||
545 | struct ath_hw *ah = sc->sc_ah; | 548 | struct ath_hw *ah = sc->sc_ah; |
546 | an = (struct ath_node *)sta->drv_priv; | 549 | an = (struct ath_node *)sta->drv_priv; |
547 | 550 | ||
551 | #ifdef CONFIG_ATH9K_DEBUGFS | ||
552 | spin_lock(&sc->nodes_lock); | ||
553 | list_add(&an->list, &sc->nodes); | ||
554 | spin_unlock(&sc->nodes_lock); | ||
555 | an->sta = sta; | ||
556 | #endif | ||
548 | if ((ah->caps.hw_caps) & ATH9K_HW_CAP_APM) | 557 | if ((ah->caps.hw_caps) & ATH9K_HW_CAP_APM) |
549 | sc->sc_flags |= SC_OP_ENABLE_APM; | 558 | sc->sc_flags |= SC_OP_ENABLE_APM; |
550 | 559 | ||
@@ -560,6 +569,13 @@ static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta) | |||
560 | { | 569 | { |
561 | struct ath_node *an = (struct ath_node *)sta->drv_priv; | 570 | struct ath_node *an = (struct ath_node *)sta->drv_priv; |
562 | 571 | ||
572 | #ifdef CONFIG_ATH9K_DEBUGFS | ||
573 | spin_lock(&sc->nodes_lock); | ||
574 | list_del(&an->list); | ||
575 | spin_unlock(&sc->nodes_lock); | ||
576 | an->sta = NULL; | ||
577 | #endif | ||
578 | |||
563 | if (sc->sc_flags & SC_OP_TXAGGR) | 579 | if (sc->sc_flags & SC_OP_TXAGGR) |
564 | ath_tx_node_cleanup(sc, an); | 580 | ath_tx_node_cleanup(sc, an); |
565 | } | 581 | } |
@@ -600,7 +616,15 @@ void ath9k_tasklet(unsigned long data) | |||
600 | ath9k_ps_wakeup(sc); | 616 | ath9k_ps_wakeup(sc); |
601 | spin_lock(&sc->sc_pcu_lock); | 617 | spin_lock(&sc->sc_pcu_lock); |
602 | 618 | ||
603 | if (!ath9k_hw_check_alive(ah)) | 619 | /* |
620 | * Only run the baseband hang check if beacons stop working in AP or | ||
621 | * IBSS mode, because it has a high false positive rate. For station | ||
622 | * mode it should not be necessary, since the upper layers will detect | ||
623 | * this through a beacon miss automatically and the following channel | ||
624 | * change will trigger a hardware reset anyway | ||
625 | */ | ||
626 | if (ath9k_hw_numtxpending(ah, sc->beacon.beaconq) != 0 && | ||
627 | !ath9k_hw_check_alive(ah)) | ||
604 | ieee80211_queue_work(sc->hw, &sc->hw_check_work); | 628 | ieee80211_queue_work(sc->hw, &sc->hw_check_work); |
605 | 629 | ||
606 | if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) | 630 | if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) |
@@ -1341,112 +1365,251 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
1341 | ath_dbg(common, ATH_DBG_CONFIG, "Driver halt\n"); | 1365 | ath_dbg(common, ATH_DBG_CONFIG, "Driver halt\n"); |
1342 | } | 1366 | } |
1343 | 1367 | ||
1344 | static int ath9k_add_interface(struct ieee80211_hw *hw, | 1368 | bool ath9k_uses_beacons(int type) |
1345 | struct ieee80211_vif *vif) | 1369 | { |
1370 | switch (type) { | ||
1371 | case NL80211_IFTYPE_AP: | ||
1372 | case NL80211_IFTYPE_ADHOC: | ||
1373 | case NL80211_IFTYPE_MESH_POINT: | ||
1374 | return true; | ||
1375 | default: | ||
1376 | return false; | ||
1377 | } | ||
1378 | } | ||
1379 | |||
1380 | static void ath9k_reclaim_beacon(struct ath_softc *sc, | ||
1381 | struct ieee80211_vif *vif) | ||
1346 | { | 1382 | { |
1347 | struct ath_wiphy *aphy = hw->priv; | ||
1348 | struct ath_softc *sc = aphy->sc; | ||
1349 | struct ath_hw *ah = sc->sc_ah; | ||
1350 | struct ath_common *common = ath9k_hw_common(ah); | ||
1351 | struct ath_vif *avp = (void *)vif->drv_priv; | 1383 | struct ath_vif *avp = (void *)vif->drv_priv; |
1352 | enum nl80211_iftype ic_opmode = NL80211_IFTYPE_UNSPECIFIED; | ||
1353 | int ret = 0; | ||
1354 | 1384 | ||
1355 | mutex_lock(&sc->mutex); | 1385 | /* Disable SWBA interrupt */ |
1386 | sc->sc_ah->imask &= ~ATH9K_INT_SWBA; | ||
1387 | ath9k_ps_wakeup(sc); | ||
1388 | ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask); | ||
1389 | ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); | ||
1390 | tasklet_kill(&sc->bcon_tasklet); | ||
1391 | ath9k_ps_restore(sc); | ||
1392 | |||
1393 | ath_beacon_return(sc, avp); | ||
1394 | sc->sc_flags &= ~SC_OP_BEACONS; | ||
1395 | |||
1396 | if (sc->nbcnvifs > 0) { | ||
1397 | /* Re-enable beaconing */ | ||
1398 | sc->sc_ah->imask |= ATH9K_INT_SWBA; | ||
1399 | ath9k_ps_wakeup(sc); | ||
1400 | ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask); | ||
1401 | ath9k_ps_restore(sc); | ||
1402 | } | ||
1403 | } | ||
1404 | |||
1405 | static void ath9k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif) | ||
1406 | { | ||
1407 | struct ath9k_vif_iter_data *iter_data = data; | ||
1408 | int i; | ||
1409 | |||
1410 | if (iter_data->hw_macaddr) | ||
1411 | for (i = 0; i < ETH_ALEN; i++) | ||
1412 | iter_data->mask[i] &= | ||
1413 | ~(iter_data->hw_macaddr[i] ^ mac[i]); | ||
1356 | 1414 | ||
1357 | switch (vif->type) { | 1415 | switch (vif->type) { |
1358 | case NL80211_IFTYPE_STATION: | 1416 | case NL80211_IFTYPE_AP: |
1359 | ic_opmode = NL80211_IFTYPE_STATION; | 1417 | iter_data->naps++; |
1360 | break; | 1418 | break; |
1361 | case NL80211_IFTYPE_WDS: | 1419 | case NL80211_IFTYPE_STATION: |
1362 | ic_opmode = NL80211_IFTYPE_WDS; | 1420 | iter_data->nstations++; |
1363 | break; | 1421 | break; |
1364 | case NL80211_IFTYPE_ADHOC: | 1422 | case NL80211_IFTYPE_ADHOC: |
1365 | case NL80211_IFTYPE_AP: | 1423 | iter_data->nadhocs++; |
1424 | break; | ||
1366 | case NL80211_IFTYPE_MESH_POINT: | 1425 | case NL80211_IFTYPE_MESH_POINT: |
1367 | if (sc->nbcnvifs >= ATH_BCBUF) { | 1426 | iter_data->nmeshes++; |
1368 | ret = -ENOBUFS; | 1427 | break; |
1369 | goto out; | 1428 | case NL80211_IFTYPE_WDS: |
1370 | } | 1429 | iter_data->nwds++; |
1371 | ic_opmode = vif->type; | ||
1372 | break; | 1430 | break; |
1373 | default: | 1431 | default: |
1374 | ath_err(common, "Interface type %d not yet supported\n", | 1432 | iter_data->nothers++; |
1375 | vif->type); | 1433 | break; |
1376 | ret = -EOPNOTSUPP; | ||
1377 | goto out; | ||
1378 | } | 1434 | } |
1435 | } | ||
1379 | 1436 | ||
1380 | ath_dbg(common, ATH_DBG_CONFIG, | 1437 | /* Called with sc->mutex held. */ |
1381 | "Attach a VIF of type: %d\n", ic_opmode); | 1438 | void ath9k_calculate_iter_data(struct ieee80211_hw *hw, |
1439 | struct ieee80211_vif *vif, | ||
1440 | struct ath9k_vif_iter_data *iter_data) | ||
1441 | { | ||
1442 | struct ath_wiphy *aphy = hw->priv; | ||
1443 | struct ath_softc *sc = aphy->sc; | ||
1444 | struct ath_hw *ah = sc->sc_ah; | ||
1445 | struct ath_common *common = ath9k_hw_common(ah); | ||
1446 | int i; | ||
1382 | 1447 | ||
1383 | /* Set the VIF opmode */ | 1448 | /* |
1384 | avp->av_opmode = ic_opmode; | 1449 | * Use the hardware MAC address as reference, the hardware uses it |
1385 | avp->av_bslot = -1; | 1450 | * together with the BSSID mask when matching addresses. |
1451 | */ | ||
1452 | memset(iter_data, 0, sizeof(*iter_data)); | ||
1453 | iter_data->hw_macaddr = common->macaddr; | ||
1454 | memset(&iter_data->mask, 0xff, ETH_ALEN); | ||
1386 | 1455 | ||
1387 | sc->nvifs++; | 1456 | if (vif) |
1457 | ath9k_vif_iter(iter_data, vif->addr, vif); | ||
1388 | 1458 | ||
1389 | ath9k_set_bssid_mask(hw, vif); | 1459 | /* Get list of all active MAC addresses */ |
1460 | spin_lock_bh(&sc->wiphy_lock); | ||
1461 | ieee80211_iterate_active_interfaces_atomic(sc->hw, ath9k_vif_iter, | ||
1462 | iter_data); | ||
1463 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
1464 | if (sc->sec_wiphy[i] == NULL) | ||
1465 | continue; | ||
1466 | ieee80211_iterate_active_interfaces_atomic( | ||
1467 | sc->sec_wiphy[i]->hw, ath9k_vif_iter, iter_data); | ||
1468 | } | ||
1469 | spin_unlock_bh(&sc->wiphy_lock); | ||
1470 | } | ||
1390 | 1471 | ||
1391 | if (sc->nvifs > 1) | 1472 | /* Called with sc->mutex held. */ |
1392 | goto out; /* skip global settings for secondary vif */ | 1473 | static void ath9k_calculate_summary_state(struct ieee80211_hw *hw, |
1474 | struct ieee80211_vif *vif) | ||
1475 | { | ||
1476 | struct ath_wiphy *aphy = hw->priv; | ||
1477 | struct ath_softc *sc = aphy->sc; | ||
1478 | struct ath_hw *ah = sc->sc_ah; | ||
1479 | struct ath_common *common = ath9k_hw_common(ah); | ||
1480 | struct ath9k_vif_iter_data iter_data; | ||
1481 | |||
1482 | ath9k_calculate_iter_data(hw, vif, &iter_data); | ||
1393 | 1483 | ||
1394 | if (ic_opmode == NL80211_IFTYPE_AP) { | 1484 | /* Set BSSID mask. */ |
1485 | memcpy(common->bssidmask, iter_data.mask, ETH_ALEN); | ||
1486 | ath_hw_setbssidmask(common); | ||
1487 | |||
1488 | /* Set op-mode & TSF */ | ||
1489 | if (iter_data.naps > 0) { | ||
1395 | ath9k_hw_set_tsfadjust(ah, 1); | 1490 | ath9k_hw_set_tsfadjust(ah, 1); |
1396 | sc->sc_flags |= SC_OP_TSF_RESET; | 1491 | sc->sc_flags |= SC_OP_TSF_RESET; |
1397 | } | 1492 | ah->opmode = NL80211_IFTYPE_AP; |
1493 | } else { | ||
1494 | ath9k_hw_set_tsfadjust(ah, 0); | ||
1495 | sc->sc_flags &= ~SC_OP_TSF_RESET; | ||
1398 | 1496 | ||
1399 | /* Set the device opmode */ | 1497 | if (iter_data.nwds + iter_data.nmeshes) |
1400 | ah->opmode = ic_opmode; | 1498 | ah->opmode = NL80211_IFTYPE_AP; |
1499 | else if (iter_data.nadhocs) | ||
1500 | ah->opmode = NL80211_IFTYPE_ADHOC; | ||
1501 | else | ||
1502 | ah->opmode = NL80211_IFTYPE_STATION; | ||
1503 | } | ||
1401 | 1504 | ||
1402 | /* | 1505 | /* |
1403 | * Enable MIB interrupts when there are hardware phy counters. | 1506 | * Enable MIB interrupts when there are hardware phy counters. |
1404 | * Note we only do this (at the moment) for station mode. | ||
1405 | */ | 1507 | */ |
1406 | if ((vif->type == NL80211_IFTYPE_STATION) || | 1508 | if ((iter_data.nstations + iter_data.nadhocs + iter_data.nmeshes) > 0) { |
1407 | (vif->type == NL80211_IFTYPE_ADHOC) || | ||
1408 | (vif->type == NL80211_IFTYPE_MESH_POINT)) { | ||
1409 | if (ah->config.enable_ani) | 1509 | if (ah->config.enable_ani) |
1410 | ah->imask |= ATH9K_INT_MIB; | 1510 | ah->imask |= ATH9K_INT_MIB; |
1411 | ah->imask |= ATH9K_INT_TSFOOR; | 1511 | ah->imask |= ATH9K_INT_TSFOOR; |
1512 | } else { | ||
1513 | ah->imask &= ~ATH9K_INT_MIB; | ||
1514 | ah->imask &= ~ATH9K_INT_TSFOOR; | ||
1412 | } | 1515 | } |
1413 | 1516 | ||
1414 | ath9k_hw_set_interrupts(ah, ah->imask); | 1517 | ath9k_hw_set_interrupts(ah, ah->imask); |
1415 | 1518 | ||
1416 | if (vif->type == NL80211_IFTYPE_AP || | 1519 | /* Set up ANI */ |
1417 | vif->type == NL80211_IFTYPE_ADHOC) { | 1520 | if ((iter_data.naps + iter_data.nadhocs) > 0) { |
1418 | sc->sc_flags |= SC_OP_ANI_RUN; | 1521 | sc->sc_flags |= SC_OP_ANI_RUN; |
1419 | ath_start_ani(common); | 1522 | ath_start_ani(common); |
1523 | } else { | ||
1524 | sc->sc_flags &= ~SC_OP_ANI_RUN; | ||
1525 | del_timer_sync(&common->ani.timer); | ||
1420 | } | 1526 | } |
1527 | } | ||
1421 | 1528 | ||
1422 | out: | 1529 | /* Called with sc->mutex held, vif counts set up properly. */ |
1423 | mutex_unlock(&sc->mutex); | 1530 | static void ath9k_do_vif_add_setup(struct ieee80211_hw *hw, |
1424 | return ret; | 1531 | struct ieee80211_vif *vif) |
1532 | { | ||
1533 | struct ath_wiphy *aphy = hw->priv; | ||
1534 | struct ath_softc *sc = aphy->sc; | ||
1535 | |||
1536 | ath9k_calculate_summary_state(hw, vif); | ||
1537 | |||
1538 | if (ath9k_uses_beacons(vif->type)) { | ||
1539 | int error; | ||
1540 | ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); | ||
1541 | /* This may fail because upper levels do not have beacons | ||
1542 | * properly configured yet. That's OK, we assume it | ||
1543 | * will be properly configured and then we will be notified | ||
1544 | * in the info_changed method and set up beacons properly | ||
1545 | * there. | ||
1546 | */ | ||
1547 | error = ath_beacon_alloc(aphy, vif); | ||
1548 | if (error) | ||
1549 | ath9k_reclaim_beacon(sc, vif); | ||
1550 | else | ||
1551 | ath_beacon_config(sc, vif); | ||
1552 | } | ||
1425 | } | 1553 | } |
1426 | 1554 | ||
1427 | static void ath9k_reclaim_beacon(struct ath_softc *sc, | 1555 | |
1428 | struct ieee80211_vif *vif) | 1556 | static int ath9k_add_interface(struct ieee80211_hw *hw, |
1557 | struct ieee80211_vif *vif) | ||
1429 | { | 1558 | { |
1559 | struct ath_wiphy *aphy = hw->priv; | ||
1560 | struct ath_softc *sc = aphy->sc; | ||
1561 | struct ath_hw *ah = sc->sc_ah; | ||
1562 | struct ath_common *common = ath9k_hw_common(ah); | ||
1430 | struct ath_vif *avp = (void *)vif->drv_priv; | 1563 | struct ath_vif *avp = (void *)vif->drv_priv; |
1564 | int ret = 0; | ||
1431 | 1565 | ||
1432 | /* Disable SWBA interrupt */ | 1566 | mutex_lock(&sc->mutex); |
1433 | sc->sc_ah->imask &= ~ATH9K_INT_SWBA; | ||
1434 | ath9k_ps_wakeup(sc); | ||
1435 | ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask); | ||
1436 | ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); | ||
1437 | tasklet_kill(&sc->bcon_tasklet); | ||
1438 | ath9k_ps_restore(sc); | ||
1439 | 1567 | ||
1440 | ath_beacon_return(sc, avp); | 1568 | switch (vif->type) { |
1441 | sc->sc_flags &= ~SC_OP_BEACONS; | 1569 | case NL80211_IFTYPE_STATION: |
1570 | case NL80211_IFTYPE_WDS: | ||
1571 | case NL80211_IFTYPE_ADHOC: | ||
1572 | case NL80211_IFTYPE_AP: | ||
1573 | case NL80211_IFTYPE_MESH_POINT: | ||
1574 | break; | ||
1575 | default: | ||
1576 | ath_err(common, "Interface type %d not yet supported\n", | ||
1577 | vif->type); | ||
1578 | ret = -EOPNOTSUPP; | ||
1579 | goto out; | ||
1580 | } | ||
1442 | 1581 | ||
1443 | if (sc->nbcnvifs > 0) { | 1582 | if (ath9k_uses_beacons(vif->type)) { |
1444 | /* Re-enable beaconing */ | 1583 | if (sc->nbcnvifs >= ATH_BCBUF) { |
1445 | sc->sc_ah->imask |= ATH9K_INT_SWBA; | 1584 | ath_err(common, "Not enough beacon buffers when adding" |
1446 | ath9k_ps_wakeup(sc); | 1585 | " new interface of type: %i\n", |
1447 | ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask); | 1586 | vif->type); |
1448 | ath9k_ps_restore(sc); | 1587 | ret = -ENOBUFS; |
1588 | goto out; | ||
1589 | } | ||
1449 | } | 1590 | } |
1591 | |||
1592 | if ((vif->type == NL80211_IFTYPE_ADHOC) && | ||
1593 | sc->nvifs > 0) { | ||
1594 | ath_err(common, "Cannot create ADHOC interface when other" | ||
1595 | " interfaces already exist.\n"); | ||
1596 | ret = -EINVAL; | ||
1597 | goto out; | ||
1598 | } | ||
1599 | |||
1600 | ath_dbg(common, ATH_DBG_CONFIG, | ||
1601 | "Attach a VIF of type: %d\n", vif->type); | ||
1602 | |||
1603 | /* Set the VIF opmode */ | ||
1604 | avp->av_opmode = vif->type; | ||
1605 | avp->av_bslot = -1; | ||
1606 | |||
1607 | sc->nvifs++; | ||
1608 | |||
1609 | ath9k_do_vif_add_setup(hw, vif); | ||
1610 | out: | ||
1611 | mutex_unlock(&sc->mutex); | ||
1612 | return ret; | ||
1450 | } | 1613 | } |
1451 | 1614 | ||
1452 | static int ath9k_change_interface(struct ieee80211_hw *hw, | 1615 | static int ath9k_change_interface(struct ieee80211_hw *hw, |
@@ -1462,32 +1625,33 @@ static int ath9k_change_interface(struct ieee80211_hw *hw, | |||
1462 | ath_dbg(common, ATH_DBG_CONFIG, "Change Interface\n"); | 1625 | ath_dbg(common, ATH_DBG_CONFIG, "Change Interface\n"); |
1463 | mutex_lock(&sc->mutex); | 1626 | mutex_lock(&sc->mutex); |
1464 | 1627 | ||
1465 | switch (new_type) { | 1628 | /* See if new interface type is valid. */ |
1466 | case NL80211_IFTYPE_AP: | 1629 | if ((new_type == NL80211_IFTYPE_ADHOC) && |
1467 | case NL80211_IFTYPE_ADHOC: | 1630 | (sc->nvifs > 1)) { |
1631 | ath_err(common, "When using ADHOC, it must be the only" | ||
1632 | " interface.\n"); | ||
1633 | ret = -EINVAL; | ||
1634 | goto out; | ||
1635 | } | ||
1636 | |||
1637 | if (ath9k_uses_beacons(new_type) && | ||
1638 | !ath9k_uses_beacons(vif->type)) { | ||
1468 | if (sc->nbcnvifs >= ATH_BCBUF) { | 1639 | if (sc->nbcnvifs >= ATH_BCBUF) { |
1469 | ath_err(common, "No beacon slot available\n"); | 1640 | ath_err(common, "No beacon slot available\n"); |
1470 | ret = -ENOBUFS; | 1641 | ret = -ENOBUFS; |
1471 | goto out; | 1642 | goto out; |
1472 | } | 1643 | } |
1473 | break; | ||
1474 | case NL80211_IFTYPE_STATION: | ||
1475 | /* Stop ANI */ | ||
1476 | sc->sc_flags &= ~SC_OP_ANI_RUN; | ||
1477 | del_timer_sync(&common->ani.timer); | ||
1478 | if ((vif->type == NL80211_IFTYPE_AP) || | ||
1479 | (vif->type == NL80211_IFTYPE_ADHOC)) | ||
1480 | ath9k_reclaim_beacon(sc, vif); | ||
1481 | break; | ||
1482 | default: | ||
1483 | ath_err(common, "Interface type %d not yet supported\n", | ||
1484 | vif->type); | ||
1485 | ret = -ENOTSUPP; | ||
1486 | goto out; | ||
1487 | } | 1644 | } |
1645 | |||
1646 | /* Clean up old vif stuff */ | ||
1647 | if (ath9k_uses_beacons(vif->type)) | ||
1648 | ath9k_reclaim_beacon(sc, vif); | ||
1649 | |||
1650 | /* Add new settings */ | ||
1488 | vif->type = new_type; | 1651 | vif->type = new_type; |
1489 | vif->p2p = p2p; | 1652 | vif->p2p = p2p; |
1490 | 1653 | ||
1654 | ath9k_do_vif_add_setup(hw, vif); | ||
1491 | out: | 1655 | out: |
1492 | mutex_unlock(&sc->mutex); | 1656 | mutex_unlock(&sc->mutex); |
1493 | return ret; | 1657 | return ret; |
@@ -1504,17 +1668,13 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw, | |||
1504 | 1668 | ||
1505 | mutex_lock(&sc->mutex); | 1669 | mutex_lock(&sc->mutex); |
1506 | 1670 | ||
1507 | /* Stop ANI */ | 1671 | sc->nvifs--; |
1508 | sc->sc_flags &= ~SC_OP_ANI_RUN; | ||
1509 | del_timer_sync(&common->ani.timer); | ||
1510 | 1672 | ||
1511 | /* Reclaim beacon resources */ | 1673 | /* Reclaim beacon resources */ |
1512 | if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) || | 1674 | if (ath9k_uses_beacons(vif->type)) |
1513 | (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) || | ||
1514 | (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) | ||
1515 | ath9k_reclaim_beacon(sc, vif); | 1675 | ath9k_reclaim_beacon(sc, vif); |
1516 | 1676 | ||
1517 | sc->nvifs--; | 1677 | ath9k_calculate_summary_state(hw, NULL); |
1518 | 1678 | ||
1519 | mutex_unlock(&sc->mutex); | 1679 | mutex_unlock(&sc->mutex); |
1520 | } | 1680 | } |
@@ -2020,7 +2180,7 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, | |||
2020 | struct ieee80211_vif *vif, | 2180 | struct ieee80211_vif *vif, |
2021 | enum ieee80211_ampdu_mlme_action action, | 2181 | enum ieee80211_ampdu_mlme_action action, |
2022 | struct ieee80211_sta *sta, | 2182 | struct ieee80211_sta *sta, |
2023 | u16 tid, u16 *ssn) | 2183 | u16 tid, u16 *ssn, u8 buf_size) |
2024 | { | 2184 | { |
2025 | struct ath_wiphy *aphy = hw->priv; | 2185 | struct ath_wiphy *aphy = hw->priv; |
2026 | struct ath_softc *sc = aphy->sc; | 2186 | struct ath_softc *sc = aphy->sc; |
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index b2497b8601e5..116f0582af24 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
@@ -588,8 +588,14 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb) | |||
588 | return; | 588 | return; |
589 | 589 | ||
590 | mgmt = (struct ieee80211_mgmt *)skb->data; | 590 | mgmt = (struct ieee80211_mgmt *)skb->data; |
591 | if (memcmp(common->curbssid, mgmt->bssid, ETH_ALEN) != 0) | 591 | if (memcmp(common->curbssid, mgmt->bssid, ETH_ALEN) != 0) { |
592 | /* TODO: This doesn't work well if you have stations | ||
593 | * associated to two different APs because curbssid | ||
594 | * is just the last AP that any of the stations associated | ||
595 | * with. | ||
596 | */ | ||
592 | return; /* not from our current AP */ | 597 | return; /* not from our current AP */ |
598 | } | ||
593 | 599 | ||
594 | sc->ps_flags &= ~PS_WAIT_FOR_BEACON; | 600 | sc->ps_flags &= ~PS_WAIT_FOR_BEACON; |
595 | 601 | ||
@@ -984,8 +990,14 @@ static void ath9k_process_rssi(struct ath_common *common, | |||
984 | 990 | ||
985 | fc = hdr->frame_control; | 991 | fc = hdr->frame_control; |
986 | if (!ieee80211_is_beacon(fc) || | 992 | if (!ieee80211_is_beacon(fc) || |
987 | compare_ether_addr(hdr->addr3, common->curbssid)) | 993 | compare_ether_addr(hdr->addr3, common->curbssid)) { |
994 | /* TODO: This doesn't work well if you have stations | ||
995 | * associated to two different APs because curbssid | ||
996 | * is just the last AP that any of the stations associated | ||
997 | * with. | ||
998 | */ | ||
988 | return; | 999 | return; |
1000 | } | ||
989 | 1001 | ||
990 | if (rx_stats->rs_rssi != ATH9K_RSSI_BAD && !rx_stats->rs_moreaggr) | 1002 | if (rx_stats->rs_rssi != ATH9K_RSSI_BAD && !rx_stats->rs_moreaggr) |
991 | ATH_RSSI_LPF(aphy->last_rssi, rx_stats->rs_rssi); | 1003 | ATH_RSSI_LPF(aphy->last_rssi, rx_stats->rs_rssi); |
diff --git a/drivers/net/wireless/ath/ath9k/virtual.c b/drivers/net/wireless/ath/ath9k/virtual.c index 2dc7095e56d1..d205c66cd972 100644 --- a/drivers/net/wireless/ath/ath9k/virtual.c +++ b/drivers/net/wireless/ath/ath9k/virtual.c | |||
@@ -18,54 +18,6 @@ | |||
18 | 18 | ||
19 | #include "ath9k.h" | 19 | #include "ath9k.h" |
20 | 20 | ||
21 | struct ath9k_vif_iter_data { | ||
22 | const u8 *hw_macaddr; | ||
23 | u8 mask[ETH_ALEN]; | ||
24 | }; | ||
25 | |||
26 | static void ath9k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif) | ||
27 | { | ||
28 | struct ath9k_vif_iter_data *iter_data = data; | ||
29 | int i; | ||
30 | |||
31 | for (i = 0; i < ETH_ALEN; i++) | ||
32 | iter_data->mask[i] &= ~(iter_data->hw_macaddr[i] ^ mac[i]); | ||
33 | } | ||
34 | |||
35 | void ath9k_set_bssid_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | ||
36 | { | ||
37 | struct ath_wiphy *aphy = hw->priv; | ||
38 | struct ath_softc *sc = aphy->sc; | ||
39 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
40 | struct ath9k_vif_iter_data iter_data; | ||
41 | int i; | ||
42 | |||
43 | /* | ||
44 | * Use the hardware MAC address as reference, the hardware uses it | ||
45 | * together with the BSSID mask when matching addresses. | ||
46 | */ | ||
47 | iter_data.hw_macaddr = common->macaddr; | ||
48 | memset(&iter_data.mask, 0xff, ETH_ALEN); | ||
49 | |||
50 | if (vif) | ||
51 | ath9k_vif_iter(&iter_data, vif->addr, vif); | ||
52 | |||
53 | /* Get list of all active MAC addresses */ | ||
54 | spin_lock_bh(&sc->wiphy_lock); | ||
55 | ieee80211_iterate_active_interfaces_atomic(sc->hw, ath9k_vif_iter, | ||
56 | &iter_data); | ||
57 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
58 | if (sc->sec_wiphy[i] == NULL) | ||
59 | continue; | ||
60 | ieee80211_iterate_active_interfaces_atomic( | ||
61 | sc->sec_wiphy[i]->hw, ath9k_vif_iter, &iter_data); | ||
62 | } | ||
63 | spin_unlock_bh(&sc->wiphy_lock); | ||
64 | |||
65 | memcpy(common->bssidmask, iter_data.mask, ETH_ALEN); | ||
66 | ath_hw_setbssidmask(common); | ||
67 | } | ||
68 | |||
69 | int ath9k_wiphy_add(struct ath_softc *sc) | 21 | int ath9k_wiphy_add(struct ath_softc *sc) |
70 | { | 22 | { |
71 | int i, error; | 23 | int i, error; |
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 33a37edbaf79..dcac811ddab5 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -19,7 +19,6 @@ | |||
19 | 19 | ||
20 | #define BITS_PER_BYTE 8 | 20 | #define BITS_PER_BYTE 8 |
21 | #define OFDM_PLCP_BITS 22 | 21 | #define OFDM_PLCP_BITS 22 |
22 | #define HT_RC_2_MCS(_rc) ((_rc) & 0x1f) | ||
23 | #define HT_RC_2_STREAMS(_rc) ((((_rc) & 0x78) >> 3) + 1) | 22 | #define HT_RC_2_STREAMS(_rc) ((((_rc) & 0x78) >> 3) + 1) |
24 | #define L_STF 8 | 23 | #define L_STF 8 |
25 | #define L_LTF 8 | 24 | #define L_LTF 8 |
@@ -32,7 +31,6 @@ | |||
32 | #define NUM_SYMBOLS_PER_USEC(_usec) (_usec >> 2) | 31 | #define NUM_SYMBOLS_PER_USEC(_usec) (_usec >> 2) |
33 | #define NUM_SYMBOLS_PER_USEC_HALFGI(_usec) (((_usec*5)-4)/18) | 32 | #define NUM_SYMBOLS_PER_USEC_HALFGI(_usec) (((_usec*5)-4)/18) |
34 | 33 | ||
35 | #define OFDM_SIFS_TIME 16 | ||
36 | 34 | ||
37 | static u16 bits_per_symbol[][2] = { | 35 | static u16 bits_per_symbol[][2] = { |
38 | /* 20MHz 40MHz */ | 36 | /* 20MHz 40MHz */ |
@@ -169,7 +167,7 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) | |||
169 | ath_tx_update_baw(sc, tid, fi->seqno); | 167 | ath_tx_update_baw(sc, tid, fi->seqno); |
170 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0); | 168 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0); |
171 | } else { | 169 | } else { |
172 | ath_tx_send_normal(sc, txq, tid, &bf_head); | 170 | ath_tx_send_normal(sc, txq, NULL, &bf_head); |
173 | } | 171 | } |
174 | spin_lock_bh(&txq->axq_lock); | 172 | spin_lock_bh(&txq->axq_lock); |
175 | } | 173 | } |
@@ -429,7 +427,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
429 | 427 | ||
430 | ath_tx_count_frames(sc, bf, ts, txok, &nframes, &nbad); | 428 | ath_tx_count_frames(sc, bf, ts, txok, &nframes, &nbad); |
431 | while (bf) { | 429 | while (bf) { |
432 | txfail = txpending = 0; | 430 | txfail = txpending = sendbar = 0; |
433 | bf_next = bf->bf_next; | 431 | bf_next = bf->bf_next; |
434 | 432 | ||
435 | skb = bf->bf_mpdu; | 433 | skb = bf->bf_mpdu; |
@@ -856,7 +854,10 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, | |||
856 | 854 | ||
857 | txtid->state |= AGGR_ADDBA_PROGRESS; | 855 | txtid->state |= AGGR_ADDBA_PROGRESS; |
858 | txtid->paused = true; | 856 | txtid->paused = true; |
859 | *ssn = txtid->seq_start; | 857 | *ssn = txtid->seq_start = txtid->seq_next; |
858 | |||
859 | memset(txtid->tx_buf, 0, sizeof(txtid->tx_buf)); | ||
860 | txtid->baw_head = txtid->baw_tail = 0; | ||
860 | 861 | ||
861 | return 0; | 862 | return 0; |
862 | } | 863 | } |
@@ -942,7 +943,7 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype) | |||
942 | [WME_AC_VI] = ATH_TXQ_AC_VI, | 943 | [WME_AC_VI] = ATH_TXQ_AC_VI, |
943 | [WME_AC_VO] = ATH_TXQ_AC_VO, | 944 | [WME_AC_VO] = ATH_TXQ_AC_VO, |
944 | }; | 945 | }; |
945 | int qnum, i; | 946 | int axq_qnum, i; |
946 | 947 | ||
947 | memset(&qi, 0, sizeof(qi)); | 948 | memset(&qi, 0, sizeof(qi)); |
948 | qi.tqi_subtype = subtype_txq_to_hwq[subtype]; | 949 | qi.tqi_subtype = subtype_txq_to_hwq[subtype]; |
@@ -976,24 +977,25 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype) | |||
976 | qi.tqi_qflags = TXQ_FLAG_TXEOLINT_ENABLE | | 977 | qi.tqi_qflags = TXQ_FLAG_TXEOLINT_ENABLE | |
977 | TXQ_FLAG_TXDESCINT_ENABLE; | 978 | TXQ_FLAG_TXDESCINT_ENABLE; |
978 | } | 979 | } |
979 | qnum = ath9k_hw_setuptxqueue(ah, qtype, &qi); | 980 | axq_qnum = ath9k_hw_setuptxqueue(ah, qtype, &qi); |
980 | if (qnum == -1) { | 981 | if (axq_qnum == -1) { |
981 | /* | 982 | /* |
982 | * NB: don't print a message, this happens | 983 | * NB: don't print a message, this happens |
983 | * normally on parts with too few tx queues | 984 | * normally on parts with too few tx queues |
984 | */ | 985 | */ |
985 | return NULL; | 986 | return NULL; |
986 | } | 987 | } |
987 | if (qnum >= ARRAY_SIZE(sc->tx.txq)) { | 988 | if (axq_qnum >= ARRAY_SIZE(sc->tx.txq)) { |
988 | ath_err(common, "qnum %u out of range, max %zu!\n", | 989 | ath_err(common, "qnum %u out of range, max %zu!\n", |
989 | qnum, ARRAY_SIZE(sc->tx.txq)); | 990 | axq_qnum, ARRAY_SIZE(sc->tx.txq)); |
990 | ath9k_hw_releasetxqueue(ah, qnum); | 991 | ath9k_hw_releasetxqueue(ah, axq_qnum); |
991 | return NULL; | 992 | return NULL; |
992 | } | 993 | } |
993 | if (!ATH_TXQ_SETUP(sc, qnum)) { | 994 | if (!ATH_TXQ_SETUP(sc, axq_qnum)) { |
994 | struct ath_txq *txq = &sc->tx.txq[qnum]; | 995 | struct ath_txq *txq = &sc->tx.txq[axq_qnum]; |
995 | 996 | ||
996 | txq->axq_qnum = qnum; | 997 | txq->axq_qnum = axq_qnum; |
998 | txq->mac80211_qnum = -1; | ||
997 | txq->axq_link = NULL; | 999 | txq->axq_link = NULL; |
998 | INIT_LIST_HEAD(&txq->axq_q); | 1000 | INIT_LIST_HEAD(&txq->axq_q); |
999 | INIT_LIST_HEAD(&txq->axq_acq); | 1001 | INIT_LIST_HEAD(&txq->axq_acq); |
@@ -1001,14 +1003,14 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype) | |||
1001 | txq->axq_depth = 0; | 1003 | txq->axq_depth = 0; |
1002 | txq->axq_ampdu_depth = 0; | 1004 | txq->axq_ampdu_depth = 0; |
1003 | txq->axq_tx_inprogress = false; | 1005 | txq->axq_tx_inprogress = false; |
1004 | sc->tx.txqsetup |= 1<<qnum; | 1006 | sc->tx.txqsetup |= 1<<axq_qnum; |
1005 | 1007 | ||
1006 | txq->txq_headidx = txq->txq_tailidx = 0; | 1008 | txq->txq_headidx = txq->txq_tailidx = 0; |
1007 | for (i = 0; i < ATH_TXFIFO_DEPTH; i++) | 1009 | for (i = 0; i < ATH_TXFIFO_DEPTH; i++) |
1008 | INIT_LIST_HEAD(&txq->txq_fifo[i]); | 1010 | INIT_LIST_HEAD(&txq->txq_fifo[i]); |
1009 | INIT_LIST_HEAD(&txq->txq_fifo_pending); | 1011 | INIT_LIST_HEAD(&txq->txq_fifo_pending); |
1010 | } | 1012 | } |
1011 | return &sc->tx.txq[qnum]; | 1013 | return &sc->tx.txq[axq_qnum]; |
1012 | } | 1014 | } |
1013 | 1015 | ||
1014 | int ath_txq_update(struct ath_softc *sc, int qnum, | 1016 | int ath_txq_update(struct ath_softc *sc, int qnum, |
@@ -1218,46 +1220,59 @@ void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq) | |||
1218 | sc->tx.txqsetup &= ~(1<<txq->axq_qnum); | 1220 | sc->tx.txqsetup &= ~(1<<txq->axq_qnum); |
1219 | } | 1221 | } |
1220 | 1222 | ||
1223 | /* For each axq_acq entry, for each tid, try to schedule packets | ||
1224 | * for transmit until ampdu_depth has reached min Q depth. | ||
1225 | */ | ||
1221 | void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) | 1226 | void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) |
1222 | { | 1227 | { |
1223 | struct ath_atx_ac *ac; | 1228 | struct ath_atx_ac *ac, *ac_tmp, *last_ac; |
1224 | struct ath_atx_tid *tid; | 1229 | struct ath_atx_tid *tid, *last_tid; |
1225 | 1230 | ||
1226 | if (list_empty(&txq->axq_acq)) | 1231 | if (list_empty(&txq->axq_acq) || |
1232 | txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) | ||
1227 | return; | 1233 | return; |
1228 | 1234 | ||
1229 | ac = list_first_entry(&txq->axq_acq, struct ath_atx_ac, list); | 1235 | ac = list_first_entry(&txq->axq_acq, struct ath_atx_ac, list); |
1230 | list_del(&ac->list); | 1236 | last_ac = list_entry(txq->axq_acq.prev, struct ath_atx_ac, list); |
1231 | ac->sched = false; | ||
1232 | 1237 | ||
1233 | do { | 1238 | list_for_each_entry_safe(ac, ac_tmp, &txq->axq_acq, list) { |
1234 | if (list_empty(&ac->tid_q)) | 1239 | last_tid = list_entry(ac->tid_q.prev, struct ath_atx_tid, list); |
1235 | return; | 1240 | list_del(&ac->list); |
1241 | ac->sched = false; | ||
1236 | 1242 | ||
1237 | tid = list_first_entry(&ac->tid_q, struct ath_atx_tid, list); | 1243 | while (!list_empty(&ac->tid_q)) { |
1238 | list_del(&tid->list); | 1244 | tid = list_first_entry(&ac->tid_q, struct ath_atx_tid, |
1239 | tid->sched = false; | 1245 | list); |
1246 | list_del(&tid->list); | ||
1247 | tid->sched = false; | ||
1240 | 1248 | ||
1241 | if (tid->paused) | 1249 | if (tid->paused) |
1242 | continue; | 1250 | continue; |
1243 | 1251 | ||
1244 | ath_tx_sched_aggr(sc, txq, tid); | 1252 | ath_tx_sched_aggr(sc, txq, tid); |
1245 | 1253 | ||
1246 | /* | 1254 | /* |
1247 | * add tid to round-robin queue if more frames | 1255 | * add tid to round-robin queue if more frames |
1248 | * are pending for the tid | 1256 | * are pending for the tid |
1249 | */ | 1257 | */ |
1250 | if (!list_empty(&tid->buf_q)) | 1258 | if (!list_empty(&tid->buf_q)) |
1251 | ath_tx_queue_tid(txq, tid); | 1259 | ath_tx_queue_tid(txq, tid); |
1252 | 1260 | ||
1253 | break; | 1261 | if (tid == last_tid || |
1254 | } while (!list_empty(&ac->tid_q)); | 1262 | txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) |
1263 | break; | ||
1264 | } | ||
1255 | 1265 | ||
1256 | if (!list_empty(&ac->tid_q)) { | 1266 | if (!list_empty(&ac->tid_q)) { |
1257 | if (!ac->sched) { | 1267 | if (!ac->sched) { |
1258 | ac->sched = true; | 1268 | ac->sched = true; |
1259 | list_add_tail(&ac->list, &txq->axq_acq); | 1269 | list_add_tail(&ac->list, &txq->axq_acq); |
1270 | } | ||
1260 | } | 1271 | } |
1272 | |||
1273 | if (ac == last_ac || | ||
1274 | txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) | ||
1275 | return; | ||
1261 | } | 1276 | } |
1262 | } | 1277 | } |
1263 | 1278 | ||
@@ -1301,6 +1316,7 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, | |||
1301 | INIT_LIST_HEAD(&txq->txq_fifo[txq->txq_headidx]); | 1316 | INIT_LIST_HEAD(&txq->txq_fifo[txq->txq_headidx]); |
1302 | list_splice_init(head, &txq->txq_fifo[txq->txq_headidx]); | 1317 | list_splice_init(head, &txq->txq_fifo[txq->txq_headidx]); |
1303 | INCR(txq->txq_headidx, ATH_TXFIFO_DEPTH); | 1318 | INCR(txq->txq_headidx, ATH_TXFIFO_DEPTH); |
1319 | TX_STAT_INC(txq->axq_qnum, puttxbuf); | ||
1304 | ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr); | 1320 | ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr); |
1305 | ath_dbg(common, ATH_DBG_XMIT, "TXDP[%u] = %llx (%p)\n", | 1321 | ath_dbg(common, ATH_DBG_XMIT, "TXDP[%u] = %llx (%p)\n", |
1306 | txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc); | 1322 | txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc); |
@@ -1308,6 +1324,7 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, | |||
1308 | list_splice_tail_init(head, &txq->axq_q); | 1324 | list_splice_tail_init(head, &txq->axq_q); |
1309 | 1325 | ||
1310 | if (txq->axq_link == NULL) { | 1326 | if (txq->axq_link == NULL) { |
1327 | TX_STAT_INC(txq->axq_qnum, puttxbuf); | ||
1311 | ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr); | 1328 | ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr); |
1312 | ath_dbg(common, ATH_DBG_XMIT, "TXDP[%u] = %llx (%p)\n", | 1329 | ath_dbg(common, ATH_DBG_XMIT, "TXDP[%u] = %llx (%p)\n", |
1313 | txq->axq_qnum, ito64(bf->bf_daddr), | 1330 | txq->axq_qnum, ito64(bf->bf_daddr), |
@@ -1321,6 +1338,7 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, | |||
1321 | } | 1338 | } |
1322 | ath9k_hw_get_desc_link(ah, bf->bf_lastbf->bf_desc, | 1339 | ath9k_hw_get_desc_link(ah, bf->bf_lastbf->bf_desc, |
1323 | &txq->axq_link); | 1340 | &txq->axq_link); |
1341 | TX_STAT_INC(txq->axq_qnum, txstart); | ||
1324 | ath9k_hw_txstart(ah, txq->axq_qnum); | 1342 | ath9k_hw_txstart(ah, txq->axq_qnum); |
1325 | } | 1343 | } |
1326 | txq->axq_depth++; | 1344 | txq->axq_depth++; |
@@ -1335,7 +1353,6 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, | |||
1335 | struct list_head bf_head; | 1353 | struct list_head bf_head; |
1336 | 1354 | ||
1337 | bf->bf_state.bf_type |= BUF_AMPDU; | 1355 | bf->bf_state.bf_type |= BUF_AMPDU; |
1338 | TX_STAT_INC(txctl->txq->axq_qnum, a_queued); | ||
1339 | 1356 | ||
1340 | /* | 1357 | /* |
1341 | * Do not queue to h/w when any of the following conditions is true: | 1358 | * Do not queue to h/w when any of the following conditions is true: |
@@ -1351,6 +1368,7 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, | |||
1351 | * Add this frame to software queue for scheduling later | 1368 | * Add this frame to software queue for scheduling later |
1352 | * for aggregation. | 1369 | * for aggregation. |
1353 | */ | 1370 | */ |
1371 | TX_STAT_INC(txctl->txq->axq_qnum, a_queued_sw); | ||
1354 | list_add_tail(&bf->list, &tid->buf_q); | 1372 | list_add_tail(&bf->list, &tid->buf_q); |
1355 | ath_tx_queue_tid(txctl->txq, tid); | 1373 | ath_tx_queue_tid(txctl->txq, tid); |
1356 | return; | 1374 | return; |
@@ -1364,6 +1382,7 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, | |||
1364 | ath_tx_addto_baw(sc, tid, fi->seqno); | 1382 | ath_tx_addto_baw(sc, tid, fi->seqno); |
1365 | 1383 | ||
1366 | /* Queue to h/w without aggregation */ | 1384 | /* Queue to h/w without aggregation */ |
1385 | TX_STAT_INC(txctl->txq->axq_qnum, a_queued_hw); | ||
1367 | bf->bf_lastbf = bf; | 1386 | bf->bf_lastbf = bf; |
1368 | ath_buf_set_rate(sc, bf, fi->framelen); | 1387 | ath_buf_set_rate(sc, bf, fi->framelen); |
1369 | ath_tx_txqaddbuf(sc, txctl->txq, &bf_head); | 1388 | ath_tx_txqaddbuf(sc, txctl->txq, &bf_head); |
@@ -1966,17 +1985,16 @@ static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts, | |||
1966 | tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1; | 1985 | tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1; |
1967 | } | 1986 | } |
1968 | 1987 | ||
1969 | static void ath_wake_mac80211_queue(struct ath_softc *sc, int qnum) | 1988 | /* Has no locking. Must hold spin_lock_bh(&txq->axq_lock) |
1989 | * before calling this. | ||
1990 | */ | ||
1991 | static void __ath_wake_mac80211_queue(struct ath_softc *sc, struct ath_txq *txq) | ||
1970 | { | 1992 | { |
1971 | struct ath_txq *txq; | 1993 | if (txq->mac80211_qnum >= 0 && |
1972 | 1994 | txq->stopped && txq->pending_frames < ATH_MAX_QDEPTH) { | |
1973 | txq = sc->tx.txq_map[qnum]; | 1995 | if (ath_mac80211_start_queue(sc, txq->mac80211_qnum)) |
1974 | spin_lock_bh(&txq->axq_lock); | ||
1975 | if (txq->stopped && txq->pending_frames < ATH_MAX_QDEPTH) { | ||
1976 | if (ath_mac80211_start_queue(sc, qnum)) | ||
1977 | txq->stopped = 0; | 1996 | txq->stopped = 0; |
1978 | } | 1997 | } |
1979 | spin_unlock_bh(&txq->axq_lock); | ||
1980 | } | 1998 | } |
1981 | 1999 | ||
1982 | static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | 2000 | static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) |
@@ -1999,6 +2017,8 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
1999 | spin_lock_bh(&txq->axq_lock); | 2017 | spin_lock_bh(&txq->axq_lock); |
2000 | if (list_empty(&txq->axq_q)) { | 2018 | if (list_empty(&txq->axq_q)) { |
2001 | txq->axq_link = NULL; | 2019 | txq->axq_link = NULL; |
2020 | if (sc->sc_flags & SC_OP_TXAGGR) | ||
2021 | ath_txq_schedule(sc, txq); | ||
2002 | spin_unlock_bh(&txq->axq_lock); | 2022 | spin_unlock_bh(&txq->axq_lock); |
2003 | break; | 2023 | break; |
2004 | } | 2024 | } |
@@ -2033,6 +2053,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
2033 | spin_unlock_bh(&txq->axq_lock); | 2053 | spin_unlock_bh(&txq->axq_lock); |
2034 | break; | 2054 | break; |
2035 | } | 2055 | } |
2056 | TX_STAT_INC(txq->axq_qnum, txprocdesc); | ||
2036 | 2057 | ||
2037 | /* | 2058 | /* |
2038 | * Remove ath_buf's of the same transmit unit from txq, | 2059 | * Remove ath_buf's of the same transmit unit from txq, |
@@ -2076,10 +2097,9 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
2076 | else | 2097 | else |
2077 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, txok, 0); | 2098 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, txok, 0); |
2078 | 2099 | ||
2079 | if (txq == sc->tx.txq_map[qnum]) | ||
2080 | ath_wake_mac80211_queue(sc, qnum); | ||
2081 | |||
2082 | spin_lock_bh(&txq->axq_lock); | 2100 | spin_lock_bh(&txq->axq_lock); |
2101 | __ath_wake_mac80211_queue(sc, txq); | ||
2102 | |||
2083 | if (sc->sc_flags & SC_OP_TXAGGR) | 2103 | if (sc->sc_flags & SC_OP_TXAGGR) |
2084 | ath_txq_schedule(sc, txq); | 2104 | ath_txq_schedule(sc, txq); |
2085 | spin_unlock_bh(&txq->axq_lock); | 2105 | spin_unlock_bh(&txq->axq_lock); |
@@ -2093,6 +2113,9 @@ static void ath_tx_complete_poll_work(struct work_struct *work) | |||
2093 | struct ath_txq *txq; | 2113 | struct ath_txq *txq; |
2094 | int i; | 2114 | int i; |
2095 | bool needreset = false; | 2115 | bool needreset = false; |
2116 | #ifdef CONFIG_ATH9K_DEBUGFS | ||
2117 | sc->tx_complete_poll_work_seen++; | ||
2118 | #endif | ||
2096 | 2119 | ||
2097 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) | 2120 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) |
2098 | if (ATH_TXQ_SETUP(sc, i)) { | 2121 | if (ATH_TXQ_SETUP(sc, i)) { |
@@ -2106,6 +2129,34 @@ static void ath_tx_complete_poll_work(struct work_struct *work) | |||
2106 | } else { | 2129 | } else { |
2107 | txq->axq_tx_inprogress = true; | 2130 | txq->axq_tx_inprogress = true; |
2108 | } | 2131 | } |
2132 | } else { | ||
2133 | /* If the queue has pending buffers, then it | ||
2134 | * should be doing tx work (and have axq_depth). | ||
2135 | * Shouldn't get to this state I think..but | ||
2136 | * we do. | ||
2137 | */ | ||
2138 | if (!(sc->sc_flags & (SC_OP_OFFCHANNEL)) && | ||
2139 | (txq->pending_frames > 0 || | ||
2140 | !list_empty(&txq->axq_acq) || | ||
2141 | txq->stopped)) { | ||
2142 | ath_err(ath9k_hw_common(sc->sc_ah), | ||
2143 | "txq: %p axq_qnum: %u," | ||
2144 | " mac80211_qnum: %i" | ||
2145 | " axq_link: %p" | ||
2146 | " pending frames: %i" | ||
2147 | " axq_acq empty: %i" | ||
2148 | " stopped: %i" | ||
2149 | " axq_depth: 0 Attempting to" | ||
2150 | " restart tx logic.\n", | ||
2151 | txq, txq->axq_qnum, | ||
2152 | txq->mac80211_qnum, | ||
2153 | txq->axq_link, | ||
2154 | txq->pending_frames, | ||
2155 | list_empty(&txq->axq_acq), | ||
2156 | txq->stopped); | ||
2157 | __ath_wake_mac80211_queue(sc, txq); | ||
2158 | ath_txq_schedule(sc, txq); | ||
2159 | } | ||
2109 | } | 2160 | } |
2110 | spin_unlock_bh(&txq->axq_lock); | 2161 | spin_unlock_bh(&txq->axq_lock); |
2111 | } | 2162 | } |
@@ -2200,10 +2251,9 @@ void ath_tx_edma_tasklet(struct ath_softc *sc) | |||
2200 | ath_tx_complete_buf(sc, bf, txq, &bf_head, | 2251 | ath_tx_complete_buf(sc, bf, txq, &bf_head, |
2201 | &txs, txok, 0); | 2252 | &txs, txok, 0); |
2202 | 2253 | ||
2203 | if (txq == sc->tx.txq_map[qnum]) | ||
2204 | ath_wake_mac80211_queue(sc, qnum); | ||
2205 | |||
2206 | spin_lock_bh(&txq->axq_lock); | 2254 | spin_lock_bh(&txq->axq_lock); |
2255 | __ath_wake_mac80211_queue(sc, txq); | ||
2256 | |||
2207 | if (!list_empty(&txq->txq_fifo_pending)) { | 2257 | if (!list_empty(&txq->txq_fifo_pending)) { |
2208 | INIT_LIST_HEAD(&bf_head); | 2258 | INIT_LIST_HEAD(&bf_head); |
2209 | bf = list_first_entry(&txq->txq_fifo_pending, | 2259 | bf = list_first_entry(&txq->txq_fifo_pending, |
diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h index d07ff7f2fd92..420d437f9580 100644 --- a/drivers/net/wireless/ath/carl9170/carl9170.h +++ b/drivers/net/wireless/ath/carl9170/carl9170.h | |||
@@ -283,6 +283,7 @@ struct ar9170 { | |||
283 | unsigned int mem_blocks; | 283 | unsigned int mem_blocks; |
284 | unsigned int mem_block_size; | 284 | unsigned int mem_block_size; |
285 | unsigned int rx_size; | 285 | unsigned int rx_size; |
286 | unsigned int tx_seq_table; | ||
286 | } fw; | 287 | } fw; |
287 | 288 | ||
288 | /* reset / stuck frames/queue detection */ | 289 | /* reset / stuck frames/queue detection */ |
diff --git a/drivers/net/wireless/ath/carl9170/fw.c b/drivers/net/wireless/ath/carl9170/fw.c index 546b4e4ec5ea..9517ede9e2df 100644 --- a/drivers/net/wireless/ath/carl9170/fw.c +++ b/drivers/net/wireless/ath/carl9170/fw.c | |||
@@ -150,6 +150,7 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len) | |||
150 | const struct carl9170fw_otus_desc *otus_desc; | 150 | const struct carl9170fw_otus_desc *otus_desc; |
151 | const struct carl9170fw_chk_desc *chk_desc; | 151 | const struct carl9170fw_chk_desc *chk_desc; |
152 | const struct carl9170fw_last_desc *last_desc; | 152 | const struct carl9170fw_last_desc *last_desc; |
153 | const struct carl9170fw_txsq_desc *txsq_desc; | ||
153 | 154 | ||
154 | last_desc = carl9170_fw_find_desc(ar, LAST_MAGIC, | 155 | last_desc = carl9170_fw_find_desc(ar, LAST_MAGIC, |
155 | sizeof(*last_desc), CARL9170FW_LAST_DESC_CUR_VER); | 156 | sizeof(*last_desc), CARL9170FW_LAST_DESC_CUR_VER); |
@@ -264,6 +265,9 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len) | |||
264 | FIF_PROMISC_IN_BSS; | 265 | FIF_PROMISC_IN_BSS; |
265 | } | 266 | } |
266 | 267 | ||
268 | if (SUPP(CARL9170FW_WOL)) | ||
269 | device_set_wakeup_enable(&ar->udev->dev, true); | ||
270 | |||
267 | ar->fw.vif_num = otus_desc->vif_num; | 271 | ar->fw.vif_num = otus_desc->vif_num; |
268 | ar->fw.cmd_bufs = otus_desc->cmd_bufs; | 272 | ar->fw.cmd_bufs = otus_desc->cmd_bufs; |
269 | ar->fw.address = le32_to_cpu(otus_desc->fw_address); | 273 | ar->fw.address = le32_to_cpu(otus_desc->fw_address); |
@@ -296,6 +300,17 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len) | |||
296 | } | 300 | } |
297 | } | 301 | } |
298 | 302 | ||
303 | txsq_desc = carl9170_fw_find_desc(ar, TXSQ_MAGIC, | ||
304 | sizeof(*txsq_desc), CARL9170FW_TXSQ_DESC_CUR_VER); | ||
305 | |||
306 | if (txsq_desc) { | ||
307 | ar->fw.tx_seq_table = le32_to_cpu(txsq_desc->seq_table_addr); | ||
308 | if (!valid_cpu_addr(ar->fw.tx_seq_table)) | ||
309 | return -EINVAL; | ||
310 | } else { | ||
311 | ar->fw.tx_seq_table = 0; | ||
312 | } | ||
313 | |||
299 | #undef SUPPORTED | 314 | #undef SUPPORTED |
300 | return 0; | 315 | return 0; |
301 | } | 316 | } |
diff --git a/drivers/net/wireless/ath/carl9170/fwcmd.h b/drivers/net/wireless/ath/carl9170/fwcmd.h index 3680dfc70f46..30449d21b762 100644 --- a/drivers/net/wireless/ath/carl9170/fwcmd.h +++ b/drivers/net/wireless/ath/carl9170/fwcmd.h | |||
@@ -167,6 +167,7 @@ struct carl9170_rx_filter_cmd { | |||
167 | #define CARL9170_RX_FILTER_CTL_BACKR 0x20 | 167 | #define CARL9170_RX_FILTER_CTL_BACKR 0x20 |
168 | #define CARL9170_RX_FILTER_MGMT 0x40 | 168 | #define CARL9170_RX_FILTER_MGMT 0x40 |
169 | #define CARL9170_RX_FILTER_DATA 0x80 | 169 | #define CARL9170_RX_FILTER_DATA 0x80 |
170 | #define CARL9170_RX_FILTER_EVERYTHING (~0) | ||
170 | 171 | ||
171 | struct carl9170_bcn_ctrl_cmd { | 172 | struct carl9170_bcn_ctrl_cmd { |
172 | __le32 vif_id; | 173 | __le32 vif_id; |
diff --git a/drivers/net/wireless/ath/carl9170/fwdesc.h b/drivers/net/wireless/ath/carl9170/fwdesc.h index 71f3821f6058..921066822dd5 100644 --- a/drivers/net/wireless/ath/carl9170/fwdesc.h +++ b/drivers/net/wireless/ath/carl9170/fwdesc.h | |||
@@ -69,6 +69,9 @@ enum carl9170fw_feature_list { | |||
69 | /* Firmware RX filter | CARL9170_CMD_RX_FILTER */ | 69 | /* Firmware RX filter | CARL9170_CMD_RX_FILTER */ |
70 | CARL9170FW_RX_FILTER, | 70 | CARL9170FW_RX_FILTER, |
71 | 71 | ||
72 | /* Wake up on WLAN */ | ||
73 | CARL9170FW_WOL, | ||
74 | |||
72 | /* KEEP LAST */ | 75 | /* KEEP LAST */ |
73 | __CARL9170FW_FEATURE_NUM | 76 | __CARL9170FW_FEATURE_NUM |
74 | }; | 77 | }; |
@@ -78,6 +81,7 @@ enum carl9170fw_feature_list { | |||
78 | #define FIX_MAGIC "FIX\0" | 81 | #define FIX_MAGIC "FIX\0" |
79 | #define DBG_MAGIC "DBG\0" | 82 | #define DBG_MAGIC "DBG\0" |
80 | #define CHK_MAGIC "CHK\0" | 83 | #define CHK_MAGIC "CHK\0" |
84 | #define TXSQ_MAGIC "TXSQ" | ||
81 | #define LAST_MAGIC "LAST" | 85 | #define LAST_MAGIC "LAST" |
82 | 86 | ||
83 | #define CARL9170FW_SET_DAY(d) (((d) - 1) % 31) | 87 | #define CARL9170FW_SET_DAY(d) (((d) - 1) % 31) |
@@ -88,8 +92,10 @@ enum carl9170fw_feature_list { | |||
88 | #define CARL9170FW_GET_MONTH(m) ((((m) / 31) % 12) + 1) | 92 | #define CARL9170FW_GET_MONTH(m) ((((m) / 31) % 12) + 1) |
89 | #define CARL9170FW_GET_YEAR(y) ((y) / 372 + 10) | 93 | #define CARL9170FW_GET_YEAR(y) ((y) / 372 + 10) |
90 | 94 | ||
95 | #define CARL9170FW_MAGIC_SIZE 4 | ||
96 | |||
91 | struct carl9170fw_desc_head { | 97 | struct carl9170fw_desc_head { |
92 | u8 magic[4]; | 98 | u8 magic[CARL9170FW_MAGIC_SIZE]; |
93 | __le16 length; | 99 | __le16 length; |
94 | u8 min_ver; | 100 | u8 min_ver; |
95 | u8 cur_ver; | 101 | u8 cur_ver; |
@@ -170,6 +176,16 @@ struct carl9170fw_chk_desc { | |||
170 | #define CARL9170FW_CHK_DESC_SIZE \ | 176 | #define CARL9170FW_CHK_DESC_SIZE \ |
171 | (sizeof(struct carl9170fw_chk_desc)) | 177 | (sizeof(struct carl9170fw_chk_desc)) |
172 | 178 | ||
179 | #define CARL9170FW_TXSQ_DESC_MIN_VER 1 | ||
180 | #define CARL9170FW_TXSQ_DESC_CUR_VER 1 | ||
181 | struct carl9170fw_txsq_desc { | ||
182 | struct carl9170fw_desc_head head; | ||
183 | |||
184 | __le32 seq_table_addr; | ||
185 | } __packed; | ||
186 | #define CARL9170FW_TXSQ_DESC_SIZE \ | ||
187 | (sizeof(struct carl9170fw_txsq_desc)) | ||
188 | |||
173 | #define CARL9170FW_LAST_DESC_MIN_VER 1 | 189 | #define CARL9170FW_LAST_DESC_MIN_VER 1 |
174 | #define CARL9170FW_LAST_DESC_CUR_VER 2 | 190 | #define CARL9170FW_LAST_DESC_CUR_VER 2 |
175 | struct carl9170fw_last_desc { | 191 | struct carl9170fw_last_desc { |
@@ -189,8 +205,8 @@ struct carl9170fw_last_desc { | |||
189 | } | 205 | } |
190 | 206 | ||
191 | static inline void carl9170fw_fill_desc(struct carl9170fw_desc_head *head, | 207 | static inline void carl9170fw_fill_desc(struct carl9170fw_desc_head *head, |
192 | u8 magic[4], __le16 length, | 208 | u8 magic[CARL9170FW_MAGIC_SIZE], |
193 | u8 min_ver, u8 cur_ver) | 209 | __le16 length, u8 min_ver, u8 cur_ver) |
194 | { | 210 | { |
195 | head->magic[0] = magic[0]; | 211 | head->magic[0] = magic[0]; |
196 | head->magic[1] = magic[1]; | 212 | head->magic[1] = magic[1]; |
@@ -204,7 +220,7 @@ static inline void carl9170fw_fill_desc(struct carl9170fw_desc_head *head, | |||
204 | 220 | ||
205 | #define carl9170fw_for_each_hdr(desc, fw_desc) \ | 221 | #define carl9170fw_for_each_hdr(desc, fw_desc) \ |
206 | for (desc = fw_desc; \ | 222 | for (desc = fw_desc; \ |
207 | memcmp(desc->magic, LAST_MAGIC, 4) && \ | 223 | memcmp(desc->magic, LAST_MAGIC, CARL9170FW_MAGIC_SIZE) && \ |
208 | le16_to_cpu(desc->length) >= CARL9170FW_DESC_HEAD_SIZE && \ | 224 | le16_to_cpu(desc->length) >= CARL9170FW_DESC_HEAD_SIZE && \ |
209 | le16_to_cpu(desc->length) < CARL9170FW_DESC_MAX_LENGTH; \ | 225 | le16_to_cpu(desc->length) < CARL9170FW_DESC_MAX_LENGTH; \ |
210 | desc = (void *)((unsigned long)desc + le16_to_cpu(desc->length))) | 226 | desc = (void *)((unsigned long)desc + le16_to_cpu(desc->length))) |
@@ -218,8 +234,8 @@ static inline bool carl9170fw_supports(__le32 list, u8 feature) | |||
218 | } | 234 | } |
219 | 235 | ||
220 | static inline bool carl9170fw_desc_cmp(const struct carl9170fw_desc_head *head, | 236 | static inline bool carl9170fw_desc_cmp(const struct carl9170fw_desc_head *head, |
221 | const u8 descid[4], u16 min_len, | 237 | const u8 descid[CARL9170FW_MAGIC_SIZE], |
222 | u8 compatible_revision) | 238 | u16 min_len, u8 compatible_revision) |
223 | { | 239 | { |
224 | if (descid[0] == head->magic[0] && descid[1] == head->magic[1] && | 240 | if (descid[0] == head->magic[0] && descid[1] == head->magic[1] && |
225 | descid[2] == head->magic[2] && descid[3] == head->magic[3] && | 241 | descid[2] == head->magic[2] && descid[3] == head->magic[3] && |
diff --git a/drivers/net/wireless/ath/carl9170/hw.h b/drivers/net/wireless/ath/carl9170/hw.h index e85df6edfed3..4e30762dd903 100644 --- a/drivers/net/wireless/ath/carl9170/hw.h +++ b/drivers/net/wireless/ath/carl9170/hw.h | |||
@@ -463,6 +463,8 @@ | |||
463 | 463 | ||
464 | #define AR9170_PWR_REG_CHIP_REVISION (AR9170_PWR_REG_BASE + 0x010) | 464 | #define AR9170_PWR_REG_CHIP_REVISION (AR9170_PWR_REG_BASE + 0x010) |
465 | #define AR9170_PWR_REG_PLL_ADDAC (AR9170_PWR_REG_BASE + 0x014) | 465 | #define AR9170_PWR_REG_PLL_ADDAC (AR9170_PWR_REG_BASE + 0x014) |
466 | #define AR9170_PWR_PLL_ADDAC_DIV_S 2 | ||
467 | #define AR9170_PWR_PLL_ADDAC_DIV 0xffc | ||
466 | #define AR9170_PWR_REG_WATCH_DOG_MAGIC (AR9170_PWR_REG_BASE + 0x020) | 468 | #define AR9170_PWR_REG_WATCH_DOG_MAGIC (AR9170_PWR_REG_BASE + 0x020) |
467 | 469 | ||
468 | /* Faraday USB Controller */ | 470 | /* Faraday USB Controller */ |
@@ -471,6 +473,9 @@ | |||
471 | #define AR9170_USB_REG_MAIN_CTRL (AR9170_USB_REG_BASE + 0x000) | 473 | #define AR9170_USB_REG_MAIN_CTRL (AR9170_USB_REG_BASE + 0x000) |
472 | #define AR9170_USB_MAIN_CTRL_REMOTE_WAKEUP BIT(0) | 474 | #define AR9170_USB_MAIN_CTRL_REMOTE_WAKEUP BIT(0) |
473 | #define AR9170_USB_MAIN_CTRL_ENABLE_GLOBAL_INT BIT(2) | 475 | #define AR9170_USB_MAIN_CTRL_ENABLE_GLOBAL_INT BIT(2) |
476 | #define AR9170_USB_MAIN_CTRL_GO_TO_SUSPEND BIT(3) | ||
477 | #define AR9170_USB_MAIN_CTRL_RESET BIT(4) | ||
478 | #define AR9170_USB_MAIN_CTRL_CHIP_ENABLE BIT(5) | ||
474 | #define AR9170_USB_MAIN_CTRL_HIGHSPEED BIT(6) | 479 | #define AR9170_USB_MAIN_CTRL_HIGHSPEED BIT(6) |
475 | 480 | ||
476 | #define AR9170_USB_REG_DEVICE_ADDRESS (AR9170_USB_REG_BASE + 0x001) | 481 | #define AR9170_USB_REG_DEVICE_ADDRESS (AR9170_USB_REG_BASE + 0x001) |
@@ -499,6 +504,13 @@ | |||
499 | #define AR9170_USB_REG_INTR_GROUP (AR9170_USB_REG_BASE + 0x020) | 504 | #define AR9170_USB_REG_INTR_GROUP (AR9170_USB_REG_BASE + 0x020) |
500 | 505 | ||
501 | #define AR9170_USB_REG_INTR_SOURCE_0 (AR9170_USB_REG_BASE + 0x021) | 506 | #define AR9170_USB_REG_INTR_SOURCE_0 (AR9170_USB_REG_BASE + 0x021) |
507 | #define AR9170_USB_INTR_SRC0_SETUP BIT(0) | ||
508 | #define AR9170_USB_INTR_SRC0_IN BIT(1) | ||
509 | #define AR9170_USB_INTR_SRC0_OUT BIT(2) | ||
510 | #define AR9170_USB_INTR_SRC0_FAIL BIT(3) /* ??? */ | ||
511 | #define AR9170_USB_INTR_SRC0_END BIT(4) /* ??? */ | ||
512 | #define AR9170_USB_INTR_SRC0_ABORT BIT(7) | ||
513 | |||
502 | #define AR9170_USB_REG_INTR_SOURCE_1 (AR9170_USB_REG_BASE + 0x022) | 514 | #define AR9170_USB_REG_INTR_SOURCE_1 (AR9170_USB_REG_BASE + 0x022) |
503 | #define AR9170_USB_REG_INTR_SOURCE_2 (AR9170_USB_REG_BASE + 0x023) | 515 | #define AR9170_USB_REG_INTR_SOURCE_2 (AR9170_USB_REG_BASE + 0x023) |
504 | #define AR9170_USB_REG_INTR_SOURCE_3 (AR9170_USB_REG_BASE + 0x024) | 516 | #define AR9170_USB_REG_INTR_SOURCE_3 (AR9170_USB_REG_BASE + 0x024) |
@@ -506,6 +518,15 @@ | |||
506 | #define AR9170_USB_REG_INTR_SOURCE_5 (AR9170_USB_REG_BASE + 0x026) | 518 | #define AR9170_USB_REG_INTR_SOURCE_5 (AR9170_USB_REG_BASE + 0x026) |
507 | #define AR9170_USB_REG_INTR_SOURCE_6 (AR9170_USB_REG_BASE + 0x027) | 519 | #define AR9170_USB_REG_INTR_SOURCE_6 (AR9170_USB_REG_BASE + 0x027) |
508 | #define AR9170_USB_REG_INTR_SOURCE_7 (AR9170_USB_REG_BASE + 0x028) | 520 | #define AR9170_USB_REG_INTR_SOURCE_7 (AR9170_USB_REG_BASE + 0x028) |
521 | #define AR9170_USB_INTR_SRC7_USB_RESET BIT(1) | ||
522 | #define AR9170_USB_INTR_SRC7_USB_SUSPEND BIT(2) | ||
523 | #define AR9170_USB_INTR_SRC7_USB_RESUME BIT(3) | ||
524 | #define AR9170_USB_INTR_SRC7_ISO_SEQ_ERR BIT(4) | ||
525 | #define AR9170_USB_INTR_SRC7_ISO_SEQ_ABORT BIT(5) | ||
526 | #define AR9170_USB_INTR_SRC7_TX0BYTE BIT(6) | ||
527 | #define AR9170_USB_INTR_SRC7_RX0BYTE BIT(7) | ||
528 | |||
529 | #define AR9170_USB_REG_IDLE_COUNT (AR9170_USB_REG_BASE + 0x02f) | ||
509 | 530 | ||
510 | #define AR9170_USB_REG_EP_MAP (AR9170_USB_REG_BASE + 0x030) | 531 | #define AR9170_USB_REG_EP_MAP (AR9170_USB_REG_BASE + 0x030) |
511 | #define AR9170_USB_REG_EP1_MAP (AR9170_USB_REG_BASE + 0x030) | 532 | #define AR9170_USB_REG_EP1_MAP (AR9170_USB_REG_BASE + 0x030) |
@@ -581,6 +602,10 @@ | |||
581 | 602 | ||
582 | #define AR9170_USB_REG_MAX_AGG_UPLOAD (AR9170_USB_REG_BASE + 0x110) | 603 | #define AR9170_USB_REG_MAX_AGG_UPLOAD (AR9170_USB_REG_BASE + 0x110) |
583 | #define AR9170_USB_REG_UPLOAD_TIME_CTL (AR9170_USB_REG_BASE + 0x114) | 604 | #define AR9170_USB_REG_UPLOAD_TIME_CTL (AR9170_USB_REG_BASE + 0x114) |
605 | |||
606 | #define AR9170_USB_REG_WAKE_UP (AR9170_USB_REG_BASE + 0x120) | ||
607 | #define AR9170_USB_WAKE_UP_WAKE BIT(0) | ||
608 | |||
584 | #define AR9170_USB_REG_CBUS_CTRL (AR9170_USB_REG_BASE + 0x1f0) | 609 | #define AR9170_USB_REG_CBUS_CTRL (AR9170_USB_REG_BASE + 0x1f0) |
585 | #define AR9170_USB_CBUS_CTRL_BUFFER_END (BIT(1)) | 610 | #define AR9170_USB_CBUS_CTRL_BUFFER_END (BIT(1)) |
586 | 611 | ||
diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c index 870df8c42622..ede3d7e5a048 100644 --- a/drivers/net/wireless/ath/carl9170/main.c +++ b/drivers/net/wireless/ath/carl9170/main.c | |||
@@ -662,6 +662,13 @@ init: | |||
662 | goto unlock; | 662 | goto unlock; |
663 | } | 663 | } |
664 | 664 | ||
665 | if (ar->fw.tx_seq_table) { | ||
666 | err = carl9170_write_reg(ar, ar->fw.tx_seq_table + vif_id * 4, | ||
667 | 0); | ||
668 | if (err) | ||
669 | goto unlock; | ||
670 | } | ||
671 | |||
665 | unlock: | 672 | unlock: |
666 | if (err && (vif_id >= 0)) { | 673 | if (err && (vif_id >= 0)) { |
667 | vif_priv->active = false; | 674 | vif_priv->active = false; |
@@ -1279,7 +1286,7 @@ static int carl9170_op_ampdu_action(struct ieee80211_hw *hw, | |||
1279 | struct ieee80211_vif *vif, | 1286 | struct ieee80211_vif *vif, |
1280 | enum ieee80211_ampdu_mlme_action action, | 1287 | enum ieee80211_ampdu_mlme_action action, |
1281 | struct ieee80211_sta *sta, | 1288 | struct ieee80211_sta *sta, |
1282 | u16 tid, u16 *ssn) | 1289 | u16 tid, u16 *ssn, u8 buf_size) |
1283 | { | 1290 | { |
1284 | struct ar9170 *ar = hw->priv; | 1291 | struct ar9170 *ar = hw->priv; |
1285 | struct carl9170_sta_info *sta_info = (void *) sta->drv_priv; | 1292 | struct carl9170_sta_info *sta_info = (void *) sta->drv_priv; |
diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c index 6cc58e052d10..6f41e21d3a1c 100644 --- a/drivers/net/wireless/ath/carl9170/tx.c +++ b/drivers/net/wireless/ath/carl9170/tx.c | |||
@@ -862,6 +862,9 @@ static int carl9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) | |||
862 | if (unlikely(info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM)) | 862 | if (unlikely(info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM)) |
863 | txc->s.misc |= CARL9170_TX_SUPER_MISC_CAB; | 863 | txc->s.misc |= CARL9170_TX_SUPER_MISC_CAB; |
864 | 864 | ||
865 | if (unlikely(info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)) | ||
866 | txc->s.misc |= CARL9170_TX_SUPER_MISC_ASSIGN_SEQ; | ||
867 | |||
865 | if (unlikely(ieee80211_is_probe_resp(hdr->frame_control))) | 868 | if (unlikely(ieee80211_is_probe_resp(hdr->frame_control))) |
866 | txc->s.misc |= CARL9170_TX_SUPER_MISC_FILL_IN_TSF; | 869 | txc->s.misc |= CARL9170_TX_SUPER_MISC_FILL_IN_TSF; |
867 | 870 | ||
diff --git a/drivers/net/wireless/ath/carl9170/version.h b/drivers/net/wireless/ath/carl9170/version.h index ee0f84f2a2f6..15095c035169 100644 --- a/drivers/net/wireless/ath/carl9170/version.h +++ b/drivers/net/wireless/ath/carl9170/version.h | |||
@@ -1,7 +1,7 @@ | |||
1 | #ifndef __CARL9170_SHARED_VERSION_H | 1 | #ifndef __CARL9170_SHARED_VERSION_H |
2 | #define __CARL9170_SHARED_VERSION_H | 2 | #define __CARL9170_SHARED_VERSION_H |
3 | #define CARL9170FW_VERSION_YEAR 10 | 3 | #define CARL9170FW_VERSION_YEAR 11 |
4 | #define CARL9170FW_VERSION_MONTH 10 | 4 | #define CARL9170FW_VERSION_MONTH 1 |
5 | #define CARL9170FW_VERSION_DAY 29 | 5 | #define CARL9170FW_VERSION_DAY 22 |
6 | #define CARL9170FW_VERSION_GIT "1.9.0" | 6 | #define CARL9170FW_VERSION_GIT "1.9.2" |
7 | #endif /* __CARL9170_SHARED_VERSION_H */ | 7 | #endif /* __CARL9170_SHARED_VERSION_H */ |
diff --git a/drivers/net/wireless/ath/carl9170/wlan.h b/drivers/net/wireless/ath/carl9170/wlan.h index 24d63b583b6b..9e1324b67e08 100644 --- a/drivers/net/wireless/ath/carl9170/wlan.h +++ b/drivers/net/wireless/ath/carl9170/wlan.h | |||
@@ -251,7 +251,7 @@ struct carl9170_tx_superdesc { | |||
251 | u8 ampdu_commit_factor:1; | 251 | u8 ampdu_commit_factor:1; |
252 | u8 ampdu_unused_bit:1; | 252 | u8 ampdu_unused_bit:1; |
253 | u8 queue:2; | 253 | u8 queue:2; |
254 | u8 reserved:1; | 254 | u8 assign_seq:1; |
255 | u8 vif_id:3; | 255 | u8 vif_id:3; |
256 | u8 fill_in_tsf:1; | 256 | u8 fill_in_tsf:1; |
257 | u8 cab:1; | 257 | u8 cab:1; |
@@ -299,6 +299,7 @@ struct _ar9170_tx_hwdesc { | |||
299 | 299 | ||
300 | #define CARL9170_TX_SUPER_MISC_QUEUE 0x3 | 300 | #define CARL9170_TX_SUPER_MISC_QUEUE 0x3 |
301 | #define CARL9170_TX_SUPER_MISC_QUEUE_S 0 | 301 | #define CARL9170_TX_SUPER_MISC_QUEUE_S 0 |
302 | #define CARL9170_TX_SUPER_MISC_ASSIGN_SEQ 0x4 | ||
302 | #define CARL9170_TX_SUPER_MISC_VIF_ID 0x38 | 303 | #define CARL9170_TX_SUPER_MISC_VIF_ID 0x38 |
303 | #define CARL9170_TX_SUPER_MISC_VIF_ID_S 3 | 304 | #define CARL9170_TX_SUPER_MISC_VIF_ID_S 3 |
304 | #define CARL9170_TX_SUPER_MISC_FILL_IN_TSF 0x40 | 305 | #define CARL9170_TX_SUPER_MISC_FILL_IN_TSF 0x40 |
@@ -413,6 +414,23 @@ enum ar9170_txq { | |||
413 | __AR9170_NUM_TXQ, | 414 | __AR9170_NUM_TXQ, |
414 | }; | 415 | }; |
415 | 416 | ||
417 | /* | ||
418 | * This is an workaround for several undocumented bugs. | ||
419 | * Don't mess with the QoS/AC <-> HW Queue map, if you don't | ||
420 | * know what you are doing. | ||
421 | * | ||
422 | * Known problems [hardware]: | ||
423 | * * The MAC does not aggregate frames on anything other | ||
424 | * than the first HW queue. | ||
425 | * * when an AMPDU is placed [in the first hw queue] and | ||
426 | * additional frames are already queued on a different | ||
427 | * hw queue, the MAC will ALWAYS freeze. | ||
428 | * | ||
429 | * In a nutshell: The hardware can either do QoS or | ||
430 | * Aggregation but not both at the same time. As a | ||
431 | * result, this makes the device pretty much useless | ||
432 | * for any serious 802.11n setup. | ||
433 | */ | ||
416 | static const u8 ar9170_qmap[__AR9170_NUM_TXQ] = { 2, 1, 0, 3 }; | 434 | static const u8 ar9170_qmap[__AR9170_NUM_TXQ] = { 2, 1, 0, 3 }; |
417 | 435 | ||
418 | #define AR9170_TXQ_DEPTH 32 | 436 | #define AR9170_TXQ_DEPTH 32 |
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index ed424574160e..e1e3b1cf3cff 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig | |||
@@ -2,6 +2,10 @@ config IWLWIFI | |||
2 | tristate "Intel Wireless Wifi" | 2 | tristate "Intel Wireless Wifi" |
3 | depends on PCI && MAC80211 | 3 | depends on PCI && MAC80211 |
4 | select FW_LOADER | 4 | select FW_LOADER |
5 | select NEW_LEDS | ||
6 | select LEDS_CLASS | ||
7 | select LEDS_TRIGGERS | ||
8 | select MAC80211_LEDS | ||
5 | 9 | ||
6 | menu "Debugging Options" | 10 | menu "Debugging Options" |
7 | depends on IWLWIFI | 11 | depends on IWLWIFI |
@@ -106,9 +110,27 @@ config IWL5000 | |||
106 | Intel WiFi Link 1000BGN | 110 | Intel WiFi Link 1000BGN |
107 | Intel Wireless WiFi 5150AGN | 111 | Intel Wireless WiFi 5150AGN |
108 | Intel Wireless WiFi 5100AGN, 5300AGN, and 5350AGN | 112 | Intel Wireless WiFi 5100AGN, 5300AGN, and 5350AGN |
109 | Intel 6000 Gen 2 Series Wi-Fi Adapters (6000G2A and 6000G2B) | 113 | Intel 6005 Series Wi-Fi Adapters |
110 | Intel WIreless WiFi Link 6050BGN Gen 2 Adapter | 114 | Intel 6030 Series Wi-Fi Adapters |
115 | Intel Wireless WiFi Link 6150BGN 2 Adapter | ||
111 | Intel 100 Series Wi-Fi Adapters (100BGN and 130BGN) | 116 | Intel 100 Series Wi-Fi Adapters (100BGN and 130BGN) |
117 | Intel 2000 Series Wi-Fi Adapters | ||
118 | |||
119 | config IWL_P2P | ||
120 | bool "iwlwifi experimental P2P support" | ||
121 | depends on IWL5000 | ||
122 | help | ||
123 | This option enables experimental P2P support for some devices | ||
124 | based on microcode support. Since P2P support is still under | ||
125 | development, this option may even enable it for some devices | ||
126 | now that turn out to not support it in the future due to | ||
127 | microcode restrictions. | ||
128 | |||
129 | To determine if your microcode supports the experimental P2P | ||
130 | offered by this option, check if the driver advertises AP | ||
131 | support when it is loaded. | ||
132 | |||
133 | Say Y only if you want to experiment with P2P. | ||
112 | 134 | ||
113 | config IWL3945 | 135 | config IWL3945 |
114 | tristate "Intel PRO/Wireless 3945ABG/BG Network Connection (iwl3945)" | 136 | tristate "Intel PRO/Wireless 3945ABG/BG Network Connection (iwl3945)" |
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 93380f97835f..25be742c69c9 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile | |||
@@ -26,6 +26,7 @@ iwlagn-$(CONFIG_IWL5000) += iwl-agn-rxon.o iwl-agn-hcmd.o iwl-agn-ict.o | |||
26 | iwlagn-$(CONFIG_IWL5000) += iwl-5000.o | 26 | iwlagn-$(CONFIG_IWL5000) += iwl-5000.o |
27 | iwlagn-$(CONFIG_IWL5000) += iwl-6000.o | 27 | iwlagn-$(CONFIG_IWL5000) += iwl-6000.o |
28 | iwlagn-$(CONFIG_IWL5000) += iwl-1000.o | 28 | iwlagn-$(CONFIG_IWL5000) += iwl-1000.o |
29 | iwlagn-$(CONFIG_IWL5000) += iwl-2000.o | ||
29 | 30 | ||
30 | # 3945 | 31 | # 3945 |
31 | obj-$(CONFIG_IWL3945) += iwl3945.o | 32 | obj-$(CONFIG_IWL3945) += iwl3945.o |
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index ba78bc8a259f..127723e6319f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c | |||
@@ -270,6 +270,7 @@ static struct iwl_base_params iwl1000_base_params = { | |||
270 | .ucode_tracing = true, | 270 | .ucode_tracing = true, |
271 | .sensitivity_calib_by_driver = true, | 271 | .sensitivity_calib_by_driver = true, |
272 | .chain_noise_calib_by_driver = true, | 272 | .chain_noise_calib_by_driver = true, |
273 | .supports_idle = true, | ||
273 | }; | 274 | }; |
274 | static struct iwl_ht_params iwl1000_ht_params = { | 275 | static struct iwl_ht_params iwl1000_ht_params = { |
275 | .ht_greenfield_support = true, | 276 | .ht_greenfield_support = true, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c new file mode 100644 index 000000000000..3c9e1b5724c7 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c | |||
@@ -0,0 +1,556 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
23 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
24 | * | ||
25 | *****************************************************************************/ | ||
26 | |||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/init.h> | ||
30 | #include <linux/pci.h> | ||
31 | #include <linux/dma-mapping.h> | ||
32 | #include <linux/delay.h> | ||
33 | #include <linux/skbuff.h> | ||
34 | #include <linux/netdevice.h> | ||
35 | #include <linux/wireless.h> | ||
36 | #include <net/mac80211.h> | ||
37 | #include <linux/etherdevice.h> | ||
38 | #include <asm/unaligned.h> | ||
39 | |||
40 | #include "iwl-eeprom.h" | ||
41 | #include "iwl-dev.h" | ||
42 | #include "iwl-core.h" | ||
43 | #include "iwl-io.h" | ||
44 | #include "iwl-sta.h" | ||
45 | #include "iwl-agn.h" | ||
46 | #include "iwl-helpers.h" | ||
47 | #include "iwl-agn-hw.h" | ||
48 | #include "iwl-6000-hw.h" | ||
49 | #include "iwl-agn-led.h" | ||
50 | #include "iwl-agn-debugfs.h" | ||
51 | |||
52 | /* Highest firmware API version supported */ | ||
53 | #define IWL2030_UCODE_API_MAX 5 | ||
54 | #define IWL2000_UCODE_API_MAX 5 | ||
55 | #define IWL200_UCODE_API_MAX 5 | ||
56 | |||
57 | /* Lowest firmware API version supported */ | ||
58 | #define IWL2030_UCODE_API_MIN 5 | ||
59 | #define IWL2000_UCODE_API_MIN 5 | ||
60 | #define IWL200_UCODE_API_MIN 5 | ||
61 | |||
62 | #define IWL2030_FW_PRE "iwlwifi-2030-" | ||
63 | #define _IWL2030_MODULE_FIRMWARE(api) IWL2030_FW_PRE #api ".ucode" | ||
64 | #define IWL2030_MODULE_FIRMWARE(api) _IWL2030_MODULE_FIRMWARE(api) | ||
65 | |||
66 | #define IWL2000_FW_PRE "iwlwifi-2000-" | ||
67 | #define _IWL2000_MODULE_FIRMWARE(api) IWL2000_FW_PRE #api ".ucode" | ||
68 | #define IWL2000_MODULE_FIRMWARE(api) _IWL2000_MODULE_FIRMWARE(api) | ||
69 | |||
70 | #define IWL200_FW_PRE "iwlwifi-200-" | ||
71 | #define _IWL200_MODULE_FIRMWARE(api) IWL200_FW_PRE #api ".ucode" | ||
72 | #define IWL200_MODULE_FIRMWARE(api) _IWL200_MODULE_FIRMWARE(api) | ||
73 | |||
74 | static void iwl2000_set_ct_threshold(struct iwl_priv *priv) | ||
75 | { | ||
76 | /* want Celsius */ | ||
77 | priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD; | ||
78 | priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD; | ||
79 | } | ||
80 | |||
81 | /* NIC configuration for 2000 series */ | ||
82 | static void iwl2000_nic_config(struct iwl_priv *priv) | ||
83 | { | ||
84 | u16 radio_cfg; | ||
85 | |||
86 | radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG); | ||
87 | |||
88 | /* write radio config values to register */ | ||
89 | if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) <= EEPROM_RF_CONFIG_TYPE_MAX) | ||
90 | iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, | ||
91 | EEPROM_RF_CFG_TYPE_MSK(radio_cfg) | | ||
92 | EEPROM_RF_CFG_STEP_MSK(radio_cfg) | | ||
93 | EEPROM_RF_CFG_DASH_MSK(radio_cfg)); | ||
94 | |||
95 | /* set CSR_HW_CONFIG_REG for uCode use */ | ||
96 | iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, | ||
97 | CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | | ||
98 | CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); | ||
99 | |||
100 | } | ||
101 | |||
102 | static struct iwl_sensitivity_ranges iwl2000_sensitivity = { | ||
103 | .min_nrg_cck = 97, | ||
104 | .max_nrg_cck = 0, /* not used, set to 0 */ | ||
105 | .auto_corr_min_ofdm = 80, | ||
106 | .auto_corr_min_ofdm_mrc = 128, | ||
107 | .auto_corr_min_ofdm_x1 = 105, | ||
108 | .auto_corr_min_ofdm_mrc_x1 = 192, | ||
109 | |||
110 | .auto_corr_max_ofdm = 145, | ||
111 | .auto_corr_max_ofdm_mrc = 232, | ||
112 | .auto_corr_max_ofdm_x1 = 110, | ||
113 | .auto_corr_max_ofdm_mrc_x1 = 232, | ||
114 | |||
115 | .auto_corr_min_cck = 125, | ||
116 | .auto_corr_max_cck = 175, | ||
117 | .auto_corr_min_cck_mrc = 160, | ||
118 | .auto_corr_max_cck_mrc = 310, | ||
119 | .nrg_th_cck = 97, | ||
120 | .nrg_th_ofdm = 100, | ||
121 | |||
122 | .barker_corr_th_min = 190, | ||
123 | .barker_corr_th_min_mrc = 390, | ||
124 | .nrg_th_cca = 62, | ||
125 | }; | ||
126 | |||
127 | static int iwl2000_hw_set_hw_params(struct iwl_priv *priv) | ||
128 | { | ||
129 | if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && | ||
130 | priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES) | ||
131 | priv->cfg->base_params->num_of_queues = | ||
132 | priv->cfg->mod_params->num_of_queues; | ||
133 | |||
134 | priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues; | ||
135 | priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; | ||
136 | priv->hw_params.scd_bc_tbls_size = | ||
137 | priv->cfg->base_params->num_of_queues * | ||
138 | sizeof(struct iwlagn_scd_bc_tbl); | ||
139 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); | ||
140 | priv->hw_params.max_stations = IWLAGN_STATION_COUNT; | ||
141 | priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID; | ||
142 | |||
143 | priv->hw_params.max_data_size = IWL60_RTC_DATA_SIZE; | ||
144 | priv->hw_params.max_inst_size = IWL60_RTC_INST_SIZE; | ||
145 | |||
146 | priv->hw_params.max_bsm_size = 0; | ||
147 | priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | | ||
148 | BIT(IEEE80211_BAND_5GHZ); | ||
149 | priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR; | ||
150 | |||
151 | priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); | ||
152 | if (priv->cfg->rx_with_siso_diversity) | ||
153 | priv->hw_params.rx_chains_num = 1; | ||
154 | else | ||
155 | priv->hw_params.rx_chains_num = | ||
156 | num_of_ant(priv->cfg->valid_rx_ant); | ||
157 | priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant; | ||
158 | priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant; | ||
159 | |||
160 | iwl2000_set_ct_threshold(priv); | ||
161 | |||
162 | /* Set initial sensitivity parameters */ | ||
163 | /* Set initial calibration set */ | ||
164 | priv->hw_params.sens = &iwl2000_sensitivity; | ||
165 | priv->hw_params.calib_init_cfg = | ||
166 | BIT(IWL_CALIB_XTAL) | | ||
167 | BIT(IWL_CALIB_LO) | | ||
168 | BIT(IWL_CALIB_TX_IQ) | | ||
169 | BIT(IWL_CALIB_BASE_BAND); | ||
170 | if (priv->cfg->need_dc_calib) | ||
171 | priv->hw_params.calib_rt_cfg |= BIT(IWL_CALIB_CFG_DC_IDX); | ||
172 | if (priv->cfg->need_temp_offset_calib) | ||
173 | priv->hw_params.calib_init_cfg |= BIT(IWL_CALIB_TEMP_OFFSET); | ||
174 | |||
175 | priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; | ||
176 | |||
177 | return 0; | ||
178 | } | ||
179 | |||
180 | static int iwl2030_hw_channel_switch(struct iwl_priv *priv, | ||
181 | struct ieee80211_channel_switch *ch_switch) | ||
182 | { | ||
183 | /* | ||
184 | * MULTI-FIXME | ||
185 | * See iwl_mac_channel_switch. | ||
186 | */ | ||
187 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
188 | struct iwl6000_channel_switch_cmd cmd; | ||
189 | const struct iwl_channel_info *ch_info; | ||
190 | u32 switch_time_in_usec, ucode_switch_time; | ||
191 | u16 ch; | ||
192 | u32 tsf_low; | ||
193 | u8 switch_count; | ||
194 | u16 beacon_interval = le16_to_cpu(ctx->timing.beacon_interval); | ||
195 | struct ieee80211_vif *vif = ctx->vif; | ||
196 | struct iwl_host_cmd hcmd = { | ||
197 | .id = REPLY_CHANNEL_SWITCH, | ||
198 | .len = sizeof(cmd), | ||
199 | .flags = CMD_SYNC, | ||
200 | .data = &cmd, | ||
201 | }; | ||
202 | |||
203 | cmd.band = priv->band == IEEE80211_BAND_2GHZ; | ||
204 | ch = ch_switch->channel->hw_value; | ||
205 | IWL_DEBUG_11H(priv, "channel switch from %u to %u\n", | ||
206 | ctx->active.channel, ch); | ||
207 | cmd.channel = cpu_to_le16(ch); | ||
208 | cmd.rxon_flags = ctx->staging.flags; | ||
209 | cmd.rxon_filter_flags = ctx->staging.filter_flags; | ||
210 | switch_count = ch_switch->count; | ||
211 | tsf_low = ch_switch->timestamp & 0x0ffffffff; | ||
212 | /* | ||
213 | * calculate the ucode channel switch time | ||
214 | * adding TSF as one of the factor for when to switch | ||
215 | */ | ||
216 | if ((priv->ucode_beacon_time > tsf_low) && beacon_interval) { | ||
217 | if (switch_count > ((priv->ucode_beacon_time - tsf_low) / | ||
218 | beacon_interval)) { | ||
219 | switch_count -= (priv->ucode_beacon_time - | ||
220 | tsf_low) / beacon_interval; | ||
221 | } else | ||
222 | switch_count = 0; | ||
223 | } | ||
224 | if (switch_count <= 1) | ||
225 | cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); | ||
226 | else { | ||
227 | switch_time_in_usec = | ||
228 | vif->bss_conf.beacon_int * switch_count * TIME_UNIT; | ||
229 | ucode_switch_time = iwl_usecs_to_beacons(priv, | ||
230 | switch_time_in_usec, | ||
231 | beacon_interval); | ||
232 | cmd.switch_time = iwl_add_beacon_time(priv, | ||
233 | priv->ucode_beacon_time, | ||
234 | ucode_switch_time, | ||
235 | beacon_interval); | ||
236 | } | ||
237 | IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n", | ||
238 | cmd.switch_time); | ||
239 | ch_info = iwl_get_channel_info(priv, priv->band, ch); | ||
240 | if (ch_info) | ||
241 | cmd.expect_beacon = is_channel_radar(ch_info); | ||
242 | else { | ||
243 | IWL_ERR(priv, "invalid channel switch from %u to %u\n", | ||
244 | ctx->active.channel, ch); | ||
245 | return -EFAULT; | ||
246 | } | ||
247 | priv->switch_rxon.channel = cmd.channel; | ||
248 | priv->switch_rxon.switch_in_progress = true; | ||
249 | |||
250 | return iwl_send_cmd_sync(priv, &hcmd); | ||
251 | } | ||
252 | |||
253 | static struct iwl_lib_ops iwl2000_lib = { | ||
254 | .set_hw_params = iwl2000_hw_set_hw_params, | ||
255 | .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, | ||
256 | .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, | ||
257 | .txq_set_sched = iwlagn_txq_set_sched, | ||
258 | .txq_agg_enable = iwlagn_txq_agg_enable, | ||
259 | .txq_agg_disable = iwlagn_txq_agg_disable, | ||
260 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, | ||
261 | .txq_free_tfd = iwl_hw_txq_free_tfd, | ||
262 | .txq_init = iwl_hw_tx_queue_init, | ||
263 | .rx_handler_setup = iwlagn_rx_handler_setup, | ||
264 | .setup_deferred_work = iwlagn_setup_deferred_work, | ||
265 | .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, | ||
266 | .load_ucode = iwlagn_load_ucode, | ||
267 | .dump_nic_event_log = iwl_dump_nic_event_log, | ||
268 | .dump_nic_error_log = iwl_dump_nic_error_log, | ||
269 | .dump_csr = iwl_dump_csr, | ||
270 | .dump_fh = iwl_dump_fh, | ||
271 | .init_alive_start = iwlagn_init_alive_start, | ||
272 | .alive_notify = iwlagn_alive_notify, | ||
273 | .send_tx_power = iwlagn_send_tx_power, | ||
274 | .update_chain_flags = iwl_update_chain_flags, | ||
275 | .set_channel_switch = iwl2030_hw_channel_switch, | ||
276 | .apm_ops = { | ||
277 | .init = iwl_apm_init, | ||
278 | .config = iwl2000_nic_config, | ||
279 | }, | ||
280 | .eeprom_ops = { | ||
281 | .regulatory_bands = { | ||
282 | EEPROM_REG_BAND_1_CHANNELS, | ||
283 | EEPROM_REG_BAND_2_CHANNELS, | ||
284 | EEPROM_REG_BAND_3_CHANNELS, | ||
285 | EEPROM_REG_BAND_4_CHANNELS, | ||
286 | EEPROM_REG_BAND_5_CHANNELS, | ||
287 | EEPROM_6000_REG_BAND_24_HT40_CHANNELS, | ||
288 | EEPROM_REG_BAND_52_HT40_CHANNELS | ||
289 | }, | ||
290 | .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, | ||
291 | .release_semaphore = iwlcore_eeprom_release_semaphore, | ||
292 | .calib_version = iwlagn_eeprom_calib_version, | ||
293 | .query_addr = iwlagn_eeprom_query_addr, | ||
294 | .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, | ||
295 | }, | ||
296 | .isr_ops = { | ||
297 | .isr = iwl_isr_ict, | ||
298 | .free = iwl_free_isr_ict, | ||
299 | .alloc = iwl_alloc_isr_ict, | ||
300 | .reset = iwl_reset_ict, | ||
301 | .disable = iwl_disable_ict, | ||
302 | }, | ||
303 | .temp_ops = { | ||
304 | .temperature = iwlagn_temperature, | ||
305 | }, | ||
306 | .debugfs_ops = { | ||
307 | .rx_stats_read = iwl_ucode_rx_stats_read, | ||
308 | .tx_stats_read = iwl_ucode_tx_stats_read, | ||
309 | .general_stats_read = iwl_ucode_general_stats_read, | ||
310 | .bt_stats_read = iwl_ucode_bt_stats_read, | ||
311 | .reply_tx_error = iwl_reply_tx_error_read, | ||
312 | }, | ||
313 | .check_plcp_health = iwl_good_plcp_health, | ||
314 | .check_ack_health = iwl_good_ack_health, | ||
315 | .txfifo_flush = iwlagn_txfifo_flush, | ||
316 | .dev_txfifo_flush = iwlagn_dev_txfifo_flush, | ||
317 | .tt_ops = { | ||
318 | .lower_power_detection = iwl_tt_is_low_power_state, | ||
319 | .tt_power_mode = iwl_tt_current_power_mode, | ||
320 | .ct_kill_check = iwl_check_for_ct_kill, | ||
321 | } | ||
322 | }; | ||
323 | |||
324 | static const struct iwl_ops iwl2000_ops = { | ||
325 | .lib = &iwl2000_lib, | ||
326 | .hcmd = &iwlagn_hcmd, | ||
327 | .utils = &iwlagn_hcmd_utils, | ||
328 | .led = &iwlagn_led_ops, | ||
329 | .ieee80211_ops = &iwlagn_hw_ops, | ||
330 | }; | ||
331 | |||
332 | static const struct iwl_ops iwl2030_ops = { | ||
333 | .lib = &iwl2000_lib, | ||
334 | .hcmd = &iwlagn_bt_hcmd, | ||
335 | .utils = &iwlagn_hcmd_utils, | ||
336 | .led = &iwlagn_led_ops, | ||
337 | .ieee80211_ops = &iwlagn_hw_ops, | ||
338 | }; | ||
339 | |||
340 | static const struct iwl_ops iwl200_ops = { | ||
341 | .lib = &iwl2000_lib, | ||
342 | .hcmd = &iwlagn_hcmd, | ||
343 | .utils = &iwlagn_hcmd_utils, | ||
344 | .led = &iwlagn_led_ops, | ||
345 | .ieee80211_ops = &iwlagn_hw_ops, | ||
346 | }; | ||
347 | |||
348 | static const struct iwl_ops iwl230_ops = { | ||
349 | .lib = &iwl2000_lib, | ||
350 | .hcmd = &iwlagn_bt_hcmd, | ||
351 | .utils = &iwlagn_hcmd_utils, | ||
352 | .led = &iwlagn_led_ops, | ||
353 | .ieee80211_ops = &iwlagn_hw_ops, | ||
354 | }; | ||
355 | |||
356 | static struct iwl_base_params iwl2000_base_params = { | ||
357 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | ||
358 | .num_of_queues = IWLAGN_NUM_QUEUES, | ||
359 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | ||
360 | .pll_cfg_val = 0, | ||
361 | .set_l0s = true, | ||
362 | .use_bsm = false, | ||
363 | .max_ll_items = OTP_MAX_LL_ITEMS_2x00, | ||
364 | .shadow_ram_support = true, | ||
365 | .led_compensation = 51, | ||
366 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
367 | .supports_idle = true, | ||
368 | .adv_thermal_throttle = true, | ||
369 | .support_ct_kill_exit = true, | ||
370 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
371 | .chain_noise_scale = 1000, | ||
372 | .wd_timeout = IWL_DEF_WD_TIMEOUT, | ||
373 | .max_event_log_size = 512, | ||
374 | .ucode_tracing = true, | ||
375 | .sensitivity_calib_by_driver = true, | ||
376 | .chain_noise_calib_by_driver = true, | ||
377 | .shadow_reg_enable = true, | ||
378 | }; | ||
379 | |||
380 | |||
381 | static struct iwl_base_params iwl2030_base_params = { | ||
382 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | ||
383 | .num_of_queues = IWLAGN_NUM_QUEUES, | ||
384 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | ||
385 | .pll_cfg_val = 0, | ||
386 | .set_l0s = true, | ||
387 | .use_bsm = false, | ||
388 | .max_ll_items = OTP_MAX_LL_ITEMS_2x00, | ||
389 | .shadow_ram_support = true, | ||
390 | .led_compensation = 57, | ||
391 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
392 | .supports_idle = true, | ||
393 | .adv_thermal_throttle = true, | ||
394 | .support_ct_kill_exit = true, | ||
395 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
396 | .chain_noise_scale = 1000, | ||
397 | .wd_timeout = IWL_LONG_WD_TIMEOUT, | ||
398 | .max_event_log_size = 512, | ||
399 | .ucode_tracing = true, | ||
400 | .sensitivity_calib_by_driver = true, | ||
401 | .chain_noise_calib_by_driver = true, | ||
402 | .shadow_reg_enable = true, | ||
403 | }; | ||
404 | |||
405 | static struct iwl_ht_params iwl2000_ht_params = { | ||
406 | .ht_greenfield_support = true, | ||
407 | .use_rts_for_aggregation = true, /* use rts/cts protection */ | ||
408 | }; | ||
409 | |||
410 | static struct iwl_bt_params iwl2030_bt_params = { | ||
411 | .bt_statistics = true, | ||
412 | /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ | ||
413 | .advanced_bt_coexist = true, | ||
414 | .agg_time_limit = BT_AGG_THRESHOLD_DEF, | ||
415 | .bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE, | ||
416 | .bt_prio_boost = IWLAGN_BT_PRIO_BOOST_DEFAULT, | ||
417 | .bt_sco_disable = true, | ||
418 | }; | ||
419 | |||
420 | #define IWL_DEVICE_2000 \ | ||
421 | .fw_name_pre = IWL2000_FW_PRE, \ | ||
422 | .ucode_api_max = IWL2000_UCODE_API_MAX, \ | ||
423 | .ucode_api_min = IWL2000_UCODE_API_MIN, \ | ||
424 | .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \ | ||
425 | .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ | ||
426 | .ops = &iwl2000_ops, \ | ||
427 | .mod_params = &iwlagn_mod_params, \ | ||
428 | .base_params = &iwl2000_base_params, \ | ||
429 | .need_dc_calib = true, \ | ||
430 | .need_temp_offset_calib = true, \ | ||
431 | .led_mode = IWL_LED_RF_STATE \ | ||
432 | |||
433 | struct iwl_cfg iwl2000_2bgn_cfg = { | ||
434 | .name = "2000 Series 2x2 BGN", | ||
435 | IWL_DEVICE_2000, | ||
436 | .ht_params = &iwl2000_ht_params, | ||
437 | }; | ||
438 | |||
439 | struct iwl_cfg iwl2000_2bg_cfg = { | ||
440 | .name = "2000 Series 2x2 BG", | ||
441 | IWL_DEVICE_2000, | ||
442 | }; | ||
443 | |||
444 | #define IWL_DEVICE_2030 \ | ||
445 | .fw_name_pre = IWL2030_FW_PRE, \ | ||
446 | .ucode_api_max = IWL2030_UCODE_API_MAX, \ | ||
447 | .ucode_api_min = IWL2030_UCODE_API_MIN, \ | ||
448 | .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \ | ||
449 | .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ | ||
450 | .ops = &iwl2030_ops, \ | ||
451 | .mod_params = &iwlagn_mod_params, \ | ||
452 | .base_params = &iwl2030_base_params, \ | ||
453 | .bt_params = &iwl2030_bt_params, \ | ||
454 | .need_dc_calib = true, \ | ||
455 | .need_temp_offset_calib = true, \ | ||
456 | .led_mode = IWL_LED_RF_STATE, \ | ||
457 | .adv_pm = true \ | ||
458 | |||
459 | struct iwl_cfg iwl2030_2bgn_cfg = { | ||
460 | .name = "2000 Series 2x2 BGN/BT", | ||
461 | IWL_DEVICE_2000, | ||
462 | .ht_params = &iwl2000_ht_params, | ||
463 | }; | ||
464 | |||
465 | struct iwl_cfg iwl2030_2bg_cfg = { | ||
466 | .name = "2000 Series 2x2 BG/BT", | ||
467 | IWL_DEVICE_2000, | ||
468 | }; | ||
469 | |||
470 | #define IWL_DEVICE_6035 \ | ||
471 | .fw_name_pre = IWL2030_FW_PRE, \ | ||
472 | .ucode_api_max = IWL2030_UCODE_API_MAX, \ | ||
473 | .ucode_api_min = IWL2030_UCODE_API_MIN, \ | ||
474 | .eeprom_ver = EEPROM_6035_EEPROM_VERSION, \ | ||
475 | .eeprom_calib_ver = EEPROM_6035_TX_POWER_VERSION, \ | ||
476 | .ops = &iwl2030_ops, \ | ||
477 | .mod_params = &iwlagn_mod_params, \ | ||
478 | .base_params = &iwl2030_base_params, \ | ||
479 | .bt_params = &iwl2030_bt_params, \ | ||
480 | .need_dc_calib = true, \ | ||
481 | .need_temp_offset_calib = true, \ | ||
482 | .led_mode = IWL_LED_RF_STATE, \ | ||
483 | .adv_pm = true \ | ||
484 | |||
485 | struct iwl_cfg iwl6035_2agn_cfg = { | ||
486 | .name = "2000 Series 2x2 AGN/BT", | ||
487 | IWL_DEVICE_6035, | ||
488 | .ht_params = &iwl2000_ht_params, | ||
489 | }; | ||
490 | |||
491 | struct iwl_cfg iwl6035_2abg_cfg = { | ||
492 | .name = "2000 Series 2x2 ABG/BT", | ||
493 | IWL_DEVICE_6035, | ||
494 | }; | ||
495 | |||
496 | struct iwl_cfg iwl6035_2bg_cfg = { | ||
497 | .name = "2000 Series 2x2 BG/BT", | ||
498 | IWL_DEVICE_6035, | ||
499 | }; | ||
500 | |||
501 | #define IWL_DEVICE_200 \ | ||
502 | .fw_name_pre = IWL200_FW_PRE, \ | ||
503 | .ucode_api_max = IWL200_UCODE_API_MAX, \ | ||
504 | .ucode_api_min = IWL200_UCODE_API_MIN, \ | ||
505 | .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \ | ||
506 | .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ | ||
507 | .ops = &iwl200_ops, \ | ||
508 | .mod_params = &iwlagn_mod_params, \ | ||
509 | .base_params = &iwl2000_base_params, \ | ||
510 | .need_dc_calib = true, \ | ||
511 | .need_temp_offset_calib = true, \ | ||
512 | .led_mode = IWL_LED_RF_STATE, \ | ||
513 | .adv_pm = true, \ | ||
514 | .rx_with_siso_diversity = true \ | ||
515 | |||
516 | struct iwl_cfg iwl200_bg_cfg = { | ||
517 | .name = "200 Series 1x1 BG", | ||
518 | IWL_DEVICE_200, | ||
519 | }; | ||
520 | |||
521 | struct iwl_cfg iwl200_bgn_cfg = { | ||
522 | .name = "200 Series 1x1 BGN", | ||
523 | IWL_DEVICE_200, | ||
524 | .ht_params = &iwl2000_ht_params, | ||
525 | }; | ||
526 | |||
527 | #define IWL_DEVICE_230 \ | ||
528 | .fw_name_pre = IWL200_FW_PRE, \ | ||
529 | .ucode_api_max = IWL200_UCODE_API_MAX, \ | ||
530 | .ucode_api_min = IWL200_UCODE_API_MIN, \ | ||
531 | .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \ | ||
532 | .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ | ||
533 | .ops = &iwl230_ops, \ | ||
534 | .mod_params = &iwlagn_mod_params, \ | ||
535 | .base_params = &iwl2030_base_params, \ | ||
536 | .bt_params = &iwl2030_bt_params, \ | ||
537 | .need_dc_calib = true, \ | ||
538 | .need_temp_offset_calib = true, \ | ||
539 | .led_mode = IWL_LED_RF_STATE, \ | ||
540 | .adv_pm = true, \ | ||
541 | .rx_with_siso_diversity = true \ | ||
542 | |||
543 | struct iwl_cfg iwl230_bg_cfg = { | ||
544 | .name = "200 Series 1x1 BG/BT", | ||
545 | IWL_DEVICE_230, | ||
546 | }; | ||
547 | |||
548 | struct iwl_cfg iwl230_bgn_cfg = { | ||
549 | .name = "200 Series 1x1 BGN/BT", | ||
550 | IWL_DEVICE_230, | ||
551 | .ht_params = &iwl2000_ht_params, | ||
552 | }; | ||
553 | |||
554 | MODULE_FIRMWARE(IWL2000_MODULE_FIRMWARE(IWL2000_UCODE_API_MAX)); | ||
555 | MODULE_FIRMWARE(IWL2030_MODULE_FIRMWARE(IWL2030_UCODE_API_MAX)); | ||
556 | MODULE_FIRMWARE(IWL200_MODULE_FIRMWARE(IWL200_UCODE_API_MAX)); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.c b/drivers/net/wireless/iwlwifi/iwl-3945-led.c index abe2b739c4dc..dc7c3a4167a9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.c | |||
@@ -59,33 +59,6 @@ static int iwl3945_send_led_cmd(struct iwl_priv *priv, | |||
59 | return iwl_send_cmd(priv, &cmd); | 59 | return iwl_send_cmd(priv, &cmd); |
60 | } | 60 | } |
61 | 61 | ||
62 | /* Set led on command */ | ||
63 | static int iwl3945_led_on(struct iwl_priv *priv) | ||
64 | { | ||
65 | struct iwl_led_cmd led_cmd = { | ||
66 | .id = IWL_LED_LINK, | ||
67 | .on = IWL_LED_SOLID, | ||
68 | .off = 0, | ||
69 | .interval = IWL_DEF_LED_INTRVL | ||
70 | }; | ||
71 | return iwl3945_send_led_cmd(priv, &led_cmd); | ||
72 | } | ||
73 | |||
74 | /* Set led off command */ | ||
75 | static int iwl3945_led_off(struct iwl_priv *priv) | ||
76 | { | ||
77 | struct iwl_led_cmd led_cmd = { | ||
78 | .id = IWL_LED_LINK, | ||
79 | .on = 0, | ||
80 | .off = 0, | ||
81 | .interval = IWL_DEF_LED_INTRVL | ||
82 | }; | ||
83 | IWL_DEBUG_LED(priv, "led off\n"); | ||
84 | return iwl3945_send_led_cmd(priv, &led_cmd); | ||
85 | } | ||
86 | |||
87 | const struct iwl_led_ops iwl3945_led_ops = { | 62 | const struct iwl_led_ops iwl3945_led_ops = { |
88 | .cmd = iwl3945_send_led_cmd, | 63 | .cmd = iwl3945_send_led_cmd, |
89 | .on = iwl3945_led_on, | ||
90 | .off = iwl3945_led_off, | ||
91 | }; | 64 | }; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index a9b852be4509..1d9dcd7e3b82 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c | |||
@@ -594,10 +594,11 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv, | |||
594 | 594 | ||
595 | rx_status.flag = 0; | 595 | rx_status.flag = 0; |
596 | rx_status.mactime = le64_to_cpu(rx_end->timestamp); | 596 | rx_status.mactime = le64_to_cpu(rx_end->timestamp); |
597 | rx_status.freq = | ||
598 | ieee80211_channel_to_frequency(le16_to_cpu(rx_hdr->channel)); | ||
599 | rx_status.band = (rx_hdr->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? | 597 | rx_status.band = (rx_hdr->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? |
600 | IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; | 598 | IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; |
599 | rx_status.freq = | ||
600 | ieee80211_channel_to_frequency(le16_to_cpu(rx_hdr->channel), | ||
601 | rx_status.band); | ||
601 | 602 | ||
602 | rx_status.rate_idx = iwl3945_hwrate_to_plcp_idx(rx_hdr->rate); | 603 | rx_status.rate_idx = iwl3945_hwrate_to_plcp_idx(rx_hdr->rate); |
603 | if (rx_status.band == IEEE80211_BAND_5GHZ) | 604 | if (rx_status.band == IEEE80211_BAND_5GHZ) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 91a9f5253469..313e92ed568b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c | |||
@@ -2316,6 +2316,11 @@ static void iwl4965_rx_handler_setup(struct iwl_priv *priv) | |||
2316 | priv->rx_handlers[REPLY_RX] = iwlagn_rx_reply_rx; | 2316 | priv->rx_handlers[REPLY_RX] = iwlagn_rx_reply_rx; |
2317 | /* Tx response */ | 2317 | /* Tx response */ |
2318 | priv->rx_handlers[REPLY_TX] = iwl4965_rx_reply_tx; | 2318 | priv->rx_handlers[REPLY_TX] = iwl4965_rx_reply_tx; |
2319 | |||
2320 | /* set up notification wait support */ | ||
2321 | spin_lock_init(&priv->_agn.notif_wait_lock); | ||
2322 | INIT_LIST_HEAD(&priv->_agn.notif_waits); | ||
2323 | init_waitqueue_head(&priv->_agn.notif_waitq); | ||
2319 | } | 2324 | } |
2320 | 2325 | ||
2321 | static void iwl4965_setup_deferred_work(struct iwl_priv *priv) | 2326 | static void iwl4965_setup_deferred_work(struct iwl_priv *priv) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index af505bcd7ae0..c195674454f4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c | |||
@@ -67,13 +67,13 @@ | |||
67 | #define _IWL6050_MODULE_FIRMWARE(api) IWL6050_FW_PRE #api ".ucode" | 67 | #define _IWL6050_MODULE_FIRMWARE(api) IWL6050_FW_PRE #api ".ucode" |
68 | #define IWL6050_MODULE_FIRMWARE(api) _IWL6050_MODULE_FIRMWARE(api) | 68 | #define IWL6050_MODULE_FIRMWARE(api) _IWL6050_MODULE_FIRMWARE(api) |
69 | 69 | ||
70 | #define IWL6000G2A_FW_PRE "iwlwifi-6000g2a-" | 70 | #define IWL6005_FW_PRE "iwlwifi-6000g2a-" |
71 | #define _IWL6000G2A_MODULE_FIRMWARE(api) IWL6000G2A_FW_PRE #api ".ucode" | 71 | #define _IWL6005_MODULE_FIRMWARE(api) IWL6005_FW_PRE #api ".ucode" |
72 | #define IWL6000G2A_MODULE_FIRMWARE(api) _IWL6000G2A_MODULE_FIRMWARE(api) | 72 | #define IWL6005_MODULE_FIRMWARE(api) _IWL6005_MODULE_FIRMWARE(api) |
73 | 73 | ||
74 | #define IWL6000G2B_FW_PRE "iwlwifi-6000g2b-" | 74 | #define IWL6030_FW_PRE "iwlwifi-6000g2b-" |
75 | #define _IWL6000G2B_MODULE_FIRMWARE(api) IWL6000G2B_FW_PRE #api ".ucode" | 75 | #define _IWL6030_MODULE_FIRMWARE(api) IWL6030_FW_PRE #api ".ucode" |
76 | #define IWL6000G2B_MODULE_FIRMWARE(api) _IWL6000G2B_MODULE_FIRMWARE(api) | 76 | #define IWL6030_MODULE_FIRMWARE(api) _IWL6030_MODULE_FIRMWARE(api) |
77 | 77 | ||
78 | static void iwl6000_set_ct_threshold(struct iwl_priv *priv) | 78 | static void iwl6000_set_ct_threshold(struct iwl_priv *priv) |
79 | { | 79 | { |
@@ -90,7 +90,7 @@ static void iwl6050_additional_nic_config(struct iwl_priv *priv) | |||
90 | CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); | 90 | CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); |
91 | } | 91 | } |
92 | 92 | ||
93 | static void iwl6050g2_additional_nic_config(struct iwl_priv *priv) | 93 | static void iwl6150_additional_nic_config(struct iwl_priv *priv) |
94 | { | 94 | { |
95 | /* Indicate calibration version to uCode. */ | 95 | /* Indicate calibration version to uCode. */ |
96 | if (priv->cfg->ops->lib->eeprom_ops.calib_version(priv) >= 6) | 96 | if (priv->cfg->ops->lib->eeprom_ops.calib_version(priv) >= 6) |
@@ -354,7 +354,7 @@ static struct iwl_lib_ops iwl6000_lib = { | |||
354 | } | 354 | } |
355 | }; | 355 | }; |
356 | 356 | ||
357 | static struct iwl_lib_ops iwl6000g2b_lib = { | 357 | static struct iwl_lib_ops iwl6030_lib = { |
358 | .set_hw_params = iwl6000_hw_set_hw_params, | 358 | .set_hw_params = iwl6000_hw_set_hw_params, |
359 | .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, | 359 | .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, |
360 | .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, | 360 | .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, |
@@ -430,8 +430,8 @@ static struct iwl_nic_ops iwl6050_nic_ops = { | |||
430 | .additional_nic_config = &iwl6050_additional_nic_config, | 430 | .additional_nic_config = &iwl6050_additional_nic_config, |
431 | }; | 431 | }; |
432 | 432 | ||
433 | static struct iwl_nic_ops iwl6050g2_nic_ops = { | 433 | static struct iwl_nic_ops iwl6150_nic_ops = { |
434 | .additional_nic_config = &iwl6050g2_additional_nic_config, | 434 | .additional_nic_config = &iwl6150_additional_nic_config, |
435 | }; | 435 | }; |
436 | 436 | ||
437 | static const struct iwl_ops iwl6000_ops = { | 437 | static const struct iwl_ops iwl6000_ops = { |
@@ -451,17 +451,17 @@ static const struct iwl_ops iwl6050_ops = { | |||
451 | .ieee80211_ops = &iwlagn_hw_ops, | 451 | .ieee80211_ops = &iwlagn_hw_ops, |
452 | }; | 452 | }; |
453 | 453 | ||
454 | static const struct iwl_ops iwl6050g2_ops = { | 454 | static const struct iwl_ops iwl6150_ops = { |
455 | .lib = &iwl6000_lib, | 455 | .lib = &iwl6000_lib, |
456 | .hcmd = &iwlagn_hcmd, | 456 | .hcmd = &iwlagn_hcmd, |
457 | .utils = &iwlagn_hcmd_utils, | 457 | .utils = &iwlagn_hcmd_utils, |
458 | .led = &iwlagn_led_ops, | 458 | .led = &iwlagn_led_ops, |
459 | .nic = &iwl6050g2_nic_ops, | 459 | .nic = &iwl6150_nic_ops, |
460 | .ieee80211_ops = &iwlagn_hw_ops, | 460 | .ieee80211_ops = &iwlagn_hw_ops, |
461 | }; | 461 | }; |
462 | 462 | ||
463 | static const struct iwl_ops iwl6000g2b_ops = { | 463 | static const struct iwl_ops iwl6030_ops = { |
464 | .lib = &iwl6000g2b_lib, | 464 | .lib = &iwl6030_lib, |
465 | .hcmd = &iwlagn_bt_hcmd, | 465 | .hcmd = &iwlagn_bt_hcmd, |
466 | .utils = &iwlagn_hcmd_utils, | 466 | .utils = &iwlagn_hcmd_utils, |
467 | .led = &iwlagn_led_ops, | 467 | .led = &iwlagn_led_ops, |
@@ -555,11 +555,11 @@ static struct iwl_bt_params iwl6000_bt_params = { | |||
555 | }; | 555 | }; |
556 | 556 | ||
557 | #define IWL_DEVICE_6005 \ | 557 | #define IWL_DEVICE_6005 \ |
558 | .fw_name_pre = IWL6000G2A_FW_PRE, \ | 558 | .fw_name_pre = IWL6005_FW_PRE, \ |
559 | .ucode_api_max = IWL6000G2_UCODE_API_MAX, \ | 559 | .ucode_api_max = IWL6000G2_UCODE_API_MAX, \ |
560 | .ucode_api_min = IWL6000G2_UCODE_API_MIN, \ | 560 | .ucode_api_min = IWL6000G2_UCODE_API_MIN, \ |
561 | .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, \ | 561 | .eeprom_ver = EEPROM_6005_EEPROM_VERSION, \ |
562 | .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, \ | 562 | .eeprom_calib_ver = EEPROM_6005_TX_POWER_VERSION, \ |
563 | .ops = &iwl6000_ops, \ | 563 | .ops = &iwl6000_ops, \ |
564 | .mod_params = &iwlagn_mod_params, \ | 564 | .mod_params = &iwlagn_mod_params, \ |
565 | .base_params = &iwl6000_g2_base_params, \ | 565 | .base_params = &iwl6000_g2_base_params, \ |
@@ -584,12 +584,12 @@ struct iwl_cfg iwl6005_2bg_cfg = { | |||
584 | }; | 584 | }; |
585 | 585 | ||
586 | #define IWL_DEVICE_6030 \ | 586 | #define IWL_DEVICE_6030 \ |
587 | .fw_name_pre = IWL6000G2B_FW_PRE, \ | 587 | .fw_name_pre = IWL6030_FW_PRE, \ |
588 | .ucode_api_max = IWL6000G2_UCODE_API_MAX, \ | 588 | .ucode_api_max = IWL6000G2_UCODE_API_MAX, \ |
589 | .ucode_api_min = IWL6000G2_UCODE_API_MIN, \ | 589 | .ucode_api_min = IWL6000G2_UCODE_API_MIN, \ |
590 | .eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, \ | 590 | .eeprom_ver = EEPROM_6030_EEPROM_VERSION, \ |
591 | .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, \ | 591 | .eeprom_calib_ver = EEPROM_6030_TX_POWER_VERSION, \ |
592 | .ops = &iwl6000g2b_ops, \ | 592 | .ops = &iwl6030_ops, \ |
593 | .mod_params = &iwlagn_mod_params, \ | 593 | .mod_params = &iwlagn_mod_params, \ |
594 | .base_params = &iwl6000_g2_base_params, \ | 594 | .base_params = &iwl6000_g2_base_params, \ |
595 | .bt_params = &iwl6000_bt_params, \ | 595 | .bt_params = &iwl6000_bt_params, \ |
@@ -706,9 +706,9 @@ struct iwl_cfg iwl6150_bgn_cfg = { | |||
706 | .fw_name_pre = IWL6050_FW_PRE, | 706 | .fw_name_pre = IWL6050_FW_PRE, |
707 | .ucode_api_max = IWL6050_UCODE_API_MAX, | 707 | .ucode_api_max = IWL6050_UCODE_API_MAX, |
708 | .ucode_api_min = IWL6050_UCODE_API_MIN, | 708 | .ucode_api_min = IWL6050_UCODE_API_MIN, |
709 | .eeprom_ver = EEPROM_6050G2_EEPROM_VERSION, | 709 | .eeprom_ver = EEPROM_6150_EEPROM_VERSION, |
710 | .eeprom_calib_ver = EEPROM_6050G2_TX_POWER_VERSION, | 710 | .eeprom_calib_ver = EEPROM_6150_TX_POWER_VERSION, |
711 | .ops = &iwl6050g2_ops, | 711 | .ops = &iwl6150_ops, |
712 | .mod_params = &iwlagn_mod_params, | 712 | .mod_params = &iwlagn_mod_params, |
713 | .base_params = &iwl6050_base_params, | 713 | .base_params = &iwl6050_base_params, |
714 | .ht_params = &iwl6000_ht_params, | 714 | .ht_params = &iwl6000_ht_params, |
@@ -734,5 +734,5 @@ struct iwl_cfg iwl6000_3agn_cfg = { | |||
734 | 734 | ||
735 | MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); | 735 | MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); |
736 | MODULE_FIRMWARE(IWL6050_MODULE_FIRMWARE(IWL6050_UCODE_API_MAX)); | 736 | MODULE_FIRMWARE(IWL6050_MODULE_FIRMWARE(IWL6050_UCODE_API_MAX)); |
737 | MODULE_FIRMWARE(IWL6000G2A_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX)); | 737 | MODULE_FIRMWARE(IWL6005_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX)); |
738 | MODULE_FIRMWARE(IWL6000G2B_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX)); | 738 | MODULE_FIRMWARE(IWL6030_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX)); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c index 366340f3fb0f..41543ad4cb84 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c | |||
@@ -305,7 +305,11 @@ static int iwlagn_set_pan_params(struct iwl_priv *priv) | |||
305 | cmd.slots[0].type = 0; /* BSS */ | 305 | cmd.slots[0].type = 0; /* BSS */ |
306 | cmd.slots[1].type = 1; /* PAN */ | 306 | cmd.slots[1].type = 1; /* PAN */ |
307 | 307 | ||
308 | if (ctx_bss->vif && ctx_pan->vif) { | 308 | if (priv->_agn.hw_roc_channel) { |
309 | /* both contexts must be used for this to happen */ | ||
310 | slot1 = priv->_agn.hw_roc_duration; | ||
311 | slot0 = IWL_MIN_SLOT_TIME; | ||
312 | } else if (ctx_bss->vif && ctx_pan->vif) { | ||
309 | int bcnint = ctx_pan->vif->bss_conf.beacon_int; | 313 | int bcnint = ctx_pan->vif->bss_conf.beacon_int; |
310 | int dtim = ctx_pan->vif->bss_conf.dtim_period ?: 1; | 314 | int dtim = ctx_pan->vif->bss_conf.dtim_period ?: 1; |
311 | 315 | ||
@@ -330,12 +334,12 @@ static int iwlagn_set_pan_params(struct iwl_priv *priv) | |||
330 | if (test_bit(STATUS_SCAN_HW, &priv->status) || | 334 | if (test_bit(STATUS_SCAN_HW, &priv->status) || |
331 | (!ctx_bss->vif->bss_conf.idle && | 335 | (!ctx_bss->vif->bss_conf.idle && |
332 | !ctx_bss->vif->bss_conf.assoc)) { | 336 | !ctx_bss->vif->bss_conf.assoc)) { |
333 | slot0 = dtim * bcnint * 3 - 20; | 337 | slot0 = dtim * bcnint * 3 - IWL_MIN_SLOT_TIME; |
334 | slot1 = 20; | 338 | slot1 = IWL_MIN_SLOT_TIME; |
335 | } else if (!ctx_pan->vif->bss_conf.idle && | 339 | } else if (!ctx_pan->vif->bss_conf.idle && |
336 | !ctx_pan->vif->bss_conf.assoc) { | 340 | !ctx_pan->vif->bss_conf.assoc) { |
337 | slot1 = bcnint * 3 - 20; | 341 | slot1 = bcnint * 3 - IWL_MIN_SLOT_TIME; |
338 | slot0 = 20; | 342 | slot0 = IWL_MIN_SLOT_TIME; |
339 | } | 343 | } |
340 | } else if (ctx_pan->vif) { | 344 | } else if (ctx_pan->vif) { |
341 | slot0 = 0; | 345 | slot0 = 0; |
@@ -344,8 +348,8 @@ static int iwlagn_set_pan_params(struct iwl_priv *priv) | |||
344 | slot1 = max_t(int, DEFAULT_BEACON_INTERVAL, slot1); | 348 | slot1 = max_t(int, DEFAULT_BEACON_INTERVAL, slot1); |
345 | 349 | ||
346 | if (test_bit(STATUS_SCAN_HW, &priv->status)) { | 350 | if (test_bit(STATUS_SCAN_HW, &priv->status)) { |
347 | slot0 = slot1 * 3 - 20; | 351 | slot0 = slot1 * 3 - IWL_MIN_SLOT_TIME; |
348 | slot1 = 20; | 352 | slot1 = IWL_MIN_SLOT_TIME; |
349 | } | 353 | } |
350 | } | 354 | } |
351 | 355 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-led.c b/drivers/net/wireless/iwlwifi/iwl-agn-led.c index 1a24946bc203..c1190d965614 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-led.c | |||
@@ -63,23 +63,11 @@ static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd) | |||
63 | } | 63 | } |
64 | 64 | ||
65 | /* Set led register off */ | 65 | /* Set led register off */ |
66 | static int iwl_led_on_reg(struct iwl_priv *priv) | 66 | void iwlagn_led_enable(struct iwl_priv *priv) |
67 | { | 67 | { |
68 | IWL_DEBUG_LED(priv, "led on\n"); | ||
69 | iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_ON); | 68 | iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_ON); |
70 | return 0; | ||
71 | } | ||
72 | |||
73 | /* Set led register off */ | ||
74 | static int iwl_led_off_reg(struct iwl_priv *priv) | ||
75 | { | ||
76 | IWL_DEBUG_LED(priv, "LED Reg off\n"); | ||
77 | iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_OFF); | ||
78 | return 0; | ||
79 | } | 69 | } |
80 | 70 | ||
81 | const struct iwl_led_ops iwlagn_led_ops = { | 71 | const struct iwl_led_ops iwlagn_led_ops = { |
82 | .cmd = iwl_send_led_cmd, | 72 | .cmd = iwl_send_led_cmd, |
83 | .on = iwl_led_on_reg, | ||
84 | .off = iwl_led_off_reg, | ||
85 | }; | 73 | }; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-led.h b/drivers/net/wireless/iwlwifi/iwl-agn-led.h index a594e4fdc6b8..96f323dc5dd6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-led.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-led.h | |||
@@ -28,5 +28,6 @@ | |||
28 | #define __iwl_agn_led_h__ | 28 | #define __iwl_agn_led_h__ |
29 | 29 | ||
30 | extern const struct iwl_led_ops iwlagn_led_ops; | 30 | extern const struct iwl_led_ops iwlagn_led_ops; |
31 | void iwlagn_led_enable(struct iwl_priv *priv); | ||
31 | 32 | ||
32 | #endif /* __iwl_agn_led_h__ */ | 33 | #endif /* __iwl_agn_led_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 3dee87e8f55d..c7d03874b380 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c | |||
@@ -473,6 +473,11 @@ void iwlagn_rx_handler_setup(struct iwl_priv *priv) | |||
473 | priv->rx_handlers[CALIBRATION_COMPLETE_NOTIFICATION] = | 473 | priv->rx_handlers[CALIBRATION_COMPLETE_NOTIFICATION] = |
474 | iwlagn_rx_calib_complete; | 474 | iwlagn_rx_calib_complete; |
475 | priv->rx_handlers[REPLY_TX] = iwlagn_rx_reply_tx; | 475 | priv->rx_handlers[REPLY_TX] = iwlagn_rx_reply_tx; |
476 | |||
477 | /* set up notification wait support */ | ||
478 | spin_lock_init(&priv->_agn.notif_wait_lock); | ||
479 | INIT_LIST_HEAD(&priv->_agn.notif_waits); | ||
480 | init_waitqueue_head(&priv->_agn.notif_waitq); | ||
476 | } | 481 | } |
477 | 482 | ||
478 | void iwlagn_setup_deferred_work(struct iwl_priv *priv) | 483 | void iwlagn_setup_deferred_work(struct iwl_priv *priv) |
@@ -1157,10 +1162,11 @@ void iwlagn_rx_reply_rx(struct iwl_priv *priv, | |||
1157 | 1162 | ||
1158 | /* rx_status carries information about the packet to mac80211 */ | 1163 | /* rx_status carries information about the packet to mac80211 */ |
1159 | rx_status.mactime = le64_to_cpu(phy_res->timestamp); | 1164 | rx_status.mactime = le64_to_cpu(phy_res->timestamp); |
1160 | rx_status.freq = | ||
1161 | ieee80211_channel_to_frequency(le16_to_cpu(phy_res->channel)); | ||
1162 | rx_status.band = (phy_res->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? | 1165 | rx_status.band = (phy_res->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? |
1163 | IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; | 1166 | IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; |
1167 | rx_status.freq = | ||
1168 | ieee80211_channel_to_frequency(le16_to_cpu(phy_res->channel), | ||
1169 | rx_status.band); | ||
1164 | rx_status.rate_idx = | 1170 | rx_status.rate_idx = |
1165 | iwlagn_hwrate_to_mac80211_idx(rate_n_flags, rx_status.band); | 1171 | iwlagn_hwrate_to_mac80211_idx(rate_n_flags, rx_status.band); |
1166 | rx_status.flag = 0; | 1172 | rx_status.flag = 0; |
@@ -2389,3 +2395,44 @@ int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display) | |||
2389 | } | 2395 | } |
2390 | return 0; | 2396 | return 0; |
2391 | } | 2397 | } |
2398 | |||
2399 | /* notification wait support */ | ||
2400 | void iwlagn_init_notification_wait(struct iwl_priv *priv, | ||
2401 | struct iwl_notification_wait *wait_entry, | ||
2402 | void (*fn)(struct iwl_priv *priv, | ||
2403 | struct iwl_rx_packet *pkt), | ||
2404 | u8 cmd) | ||
2405 | { | ||
2406 | wait_entry->fn = fn; | ||
2407 | wait_entry->cmd = cmd; | ||
2408 | wait_entry->triggered = false; | ||
2409 | |||
2410 | spin_lock_bh(&priv->_agn.notif_wait_lock); | ||
2411 | list_add(&wait_entry->list, &priv->_agn.notif_waits); | ||
2412 | spin_unlock_bh(&priv->_agn.notif_wait_lock); | ||
2413 | } | ||
2414 | |||
2415 | signed long iwlagn_wait_notification(struct iwl_priv *priv, | ||
2416 | struct iwl_notification_wait *wait_entry, | ||
2417 | unsigned long timeout) | ||
2418 | { | ||
2419 | int ret; | ||
2420 | |||
2421 | ret = wait_event_timeout(priv->_agn.notif_waitq, | ||
2422 | &wait_entry->triggered, | ||
2423 | timeout); | ||
2424 | |||
2425 | spin_lock_bh(&priv->_agn.notif_wait_lock); | ||
2426 | list_del(&wait_entry->list); | ||
2427 | spin_unlock_bh(&priv->_agn.notif_wait_lock); | ||
2428 | |||
2429 | return ret; | ||
2430 | } | ||
2431 | |||
2432 | void iwlagn_remove_notification(struct iwl_priv *priv, | ||
2433 | struct iwl_notification_wait *wait_entry) | ||
2434 | { | ||
2435 | spin_lock_bh(&priv->_agn.notif_wait_lock); | ||
2436 | list_del(&wait_entry->list); | ||
2437 | spin_unlock_bh(&priv->_agn.notif_wait_lock); | ||
2438 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index 6d140bd53291..2a4ff832fbb8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | |||
@@ -52,10 +52,14 @@ static int iwlagn_disable_pan(struct iwl_priv *priv, | |||
52 | struct iwl_rxon_context *ctx, | 52 | struct iwl_rxon_context *ctx, |
53 | struct iwl_rxon_cmd *send) | 53 | struct iwl_rxon_cmd *send) |
54 | { | 54 | { |
55 | struct iwl_notification_wait disable_wait; | ||
55 | __le32 old_filter = send->filter_flags; | 56 | __le32 old_filter = send->filter_flags; |
56 | u8 old_dev_type = send->dev_type; | 57 | u8 old_dev_type = send->dev_type; |
57 | int ret; | 58 | int ret; |
58 | 59 | ||
60 | iwlagn_init_notification_wait(priv, &disable_wait, NULL, | ||
61 | REPLY_WIPAN_DEACTIVATION_COMPLETE); | ||
62 | |||
59 | send->filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 63 | send->filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
60 | send->dev_type = RXON_DEV_TYPE_P2P; | 64 | send->dev_type = RXON_DEV_TYPE_P2P; |
61 | ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, sizeof(*send), send); | 65 | ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, sizeof(*send), send); |
@@ -63,11 +67,18 @@ static int iwlagn_disable_pan(struct iwl_priv *priv, | |||
63 | send->filter_flags = old_filter; | 67 | send->filter_flags = old_filter; |
64 | send->dev_type = old_dev_type; | 68 | send->dev_type = old_dev_type; |
65 | 69 | ||
66 | if (ret) | 70 | if (ret) { |
67 | IWL_ERR(priv, "Error disabling PAN (%d)\n", ret); | 71 | IWL_ERR(priv, "Error disabling PAN (%d)\n", ret); |
68 | 72 | iwlagn_remove_notification(priv, &disable_wait); | |
69 | /* FIXME: WAIT FOR PAN DISABLE */ | 73 | } else { |
70 | msleep(300); | 74 | signed long wait_res; |
75 | |||
76 | wait_res = iwlagn_wait_notification(priv, &disable_wait, HZ); | ||
77 | if (wait_res == 0) { | ||
78 | IWL_ERR(priv, "Timed out waiting for PAN disable\n"); | ||
79 | ret = -EIO; | ||
80 | } | ||
81 | } | ||
71 | 82 | ||
72 | return ret; | 83 | return ret; |
73 | } | 84 | } |
@@ -145,6 +156,23 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | |||
145 | /* always get timestamp with Rx frame */ | 156 | /* always get timestamp with Rx frame */ |
146 | ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK; | 157 | ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK; |
147 | 158 | ||
159 | if (ctx->ctxid == IWL_RXON_CTX_PAN && priv->_agn.hw_roc_channel) { | ||
160 | struct ieee80211_channel *chan = priv->_agn.hw_roc_channel; | ||
161 | |||
162 | iwl_set_rxon_channel(priv, chan, ctx); | ||
163 | iwl_set_flags_for_band(priv, ctx, chan->band, NULL); | ||
164 | ctx->staging.filter_flags |= | ||
165 | RXON_FILTER_ASSOC_MSK | | ||
166 | RXON_FILTER_PROMISC_MSK | | ||
167 | RXON_FILTER_CTL2HOST_MSK; | ||
168 | ctx->staging.dev_type = RXON_DEV_TYPE_P2P; | ||
169 | new_assoc = true; | ||
170 | |||
171 | if (memcmp(&ctx->staging, &ctx->active, | ||
172 | sizeof(ctx->staging)) == 0) | ||
173 | return 0; | ||
174 | } | ||
175 | |||
148 | if ((ctx->vif && ctx->vif->bss_conf.use_short_slot) || | 176 | if ((ctx->vif && ctx->vif->bss_conf.use_short_slot) || |
149 | !(ctx->staging.flags & RXON_FLG_BAND_24G_MSK)) | 177 | !(ctx->staging.flags & RXON_FLG_BAND_24G_MSK)) |
150 | ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; | 178 | ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; |
@@ -546,12 +574,10 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw, | |||
546 | 574 | ||
547 | if (changes & BSS_CHANGED_ASSOC) { | 575 | if (changes & BSS_CHANGED_ASSOC) { |
548 | if (bss_conf->assoc) { | 576 | if (bss_conf->assoc) { |
549 | iwl_led_associate(priv); | ||
550 | priv->timestamp = bss_conf->timestamp; | 577 | priv->timestamp = bss_conf->timestamp; |
551 | ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; | 578 | ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; |
552 | } else { | 579 | } else { |
553 | ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 580 | ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
554 | iwl_led_disassociate(priv); | ||
555 | } | 581 | } |
556 | } | 582 | } |
557 | 583 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 24a11b8f73bc..266490d8a397 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c | |||
@@ -539,7 +539,14 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
539 | unsigned long flags; | 539 | unsigned long flags; |
540 | bool is_agg = false; | 540 | bool is_agg = false; |
541 | 541 | ||
542 | if (info->control.vif) | 542 | /* |
543 | * If the frame needs to go out off-channel, then | ||
544 | * we'll have put the PAN context to that channel, | ||
545 | * so make the frame go out there. | ||
546 | */ | ||
547 | if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) | ||
548 | ctx = &priv->contexts[IWL_RXON_CTX_PAN]; | ||
549 | else if (info->control.vif) | ||
543 | ctx = iwl_rxon_ctx_from_vif(info->control.vif); | 550 | ctx = iwl_rxon_ctx_from_vif(info->control.vif); |
544 | 551 | ||
545 | spin_lock_irqsave(&priv->lock, flags); | 552 | spin_lock_irqsave(&priv->lock, flags); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 36335b1b54d4..eb16647cfbe0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -59,6 +59,7 @@ | |||
59 | #include "iwl-sta.h" | 59 | #include "iwl-sta.h" |
60 | #include "iwl-agn-calib.h" | 60 | #include "iwl-agn-calib.h" |
61 | #include "iwl-agn.h" | 61 | #include "iwl-agn.h" |
62 | #include "iwl-agn-led.h" | ||
62 | 63 | ||
63 | 64 | ||
64 | /****************************************************************************** | 65 | /****************************************************************************** |
@@ -846,7 +847,7 @@ static void iwl_setup_rx_handlers(struct iwl_priv *priv) | |||
846 | * the appropriate handlers, including command responses, | 847 | * the appropriate handlers, including command responses, |
847 | * frame-received notifications, and other notifications. | 848 | * frame-received notifications, and other notifications. |
848 | */ | 849 | */ |
849 | void iwl_rx_handle(struct iwl_priv *priv) | 850 | static void iwl_rx_handle(struct iwl_priv *priv) |
850 | { | 851 | { |
851 | struct iwl_rx_mem_buffer *rxb; | 852 | struct iwl_rx_mem_buffer *rxb; |
852 | struct iwl_rx_packet *pkt; | 853 | struct iwl_rx_packet *pkt; |
@@ -910,6 +911,27 @@ void iwl_rx_handle(struct iwl_priv *priv) | |||
910 | (pkt->hdr.cmd != STATISTICS_NOTIFICATION) && | 911 | (pkt->hdr.cmd != STATISTICS_NOTIFICATION) && |
911 | (pkt->hdr.cmd != REPLY_TX); | 912 | (pkt->hdr.cmd != REPLY_TX); |
912 | 913 | ||
914 | /* | ||
915 | * Do the notification wait before RX handlers so | ||
916 | * even if the RX handler consumes the RXB we have | ||
917 | * access to it in the notification wait entry. | ||
918 | */ | ||
919 | if (!list_empty(&priv->_agn.notif_waits)) { | ||
920 | struct iwl_notification_wait *w; | ||
921 | |||
922 | spin_lock(&priv->_agn.notif_wait_lock); | ||
923 | list_for_each_entry(w, &priv->_agn.notif_waits, list) { | ||
924 | if (w->cmd == pkt->hdr.cmd) { | ||
925 | w->triggered = true; | ||
926 | if (w->fn) | ||
927 | w->fn(priv, pkt); | ||
928 | } | ||
929 | } | ||
930 | spin_unlock(&priv->_agn.notif_wait_lock); | ||
931 | |||
932 | wake_up_all(&priv->_agn.notif_waitq); | ||
933 | } | ||
934 | |||
913 | /* Based on type of command response or notification, | 935 | /* Based on type of command response or notification, |
914 | * handle those that need handling via function in | 936 | * handle those that need handling via function in |
915 | * rx_handlers table. See iwl_setup_rx_handlers() */ | 937 | * rx_handlers table. See iwl_setup_rx_handlers() */ |
@@ -2720,8 +2742,6 @@ static void iwl_alive_start(struct iwl_priv *priv) | |||
2720 | /* At this point, the NIC is initialized and operational */ | 2742 | /* At this point, the NIC is initialized and operational */ |
2721 | iwl_rf_kill_ct_config(priv); | 2743 | iwl_rf_kill_ct_config(priv); |
2722 | 2744 | ||
2723 | iwl_leds_init(priv); | ||
2724 | |||
2725 | IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n"); | 2745 | IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n"); |
2726 | wake_up_interruptible(&priv->wait_command_queue); | 2746 | wake_up_interruptible(&priv->wait_command_queue); |
2727 | 2747 | ||
@@ -3188,6 +3208,8 @@ static int iwl_mac_setup_register(struct iwl_priv *priv, | |||
3188 | hw->wiphy->interface_modes |= ctx->exclusive_interface_modes; | 3208 | hw->wiphy->interface_modes |= ctx->exclusive_interface_modes; |
3189 | } | 3209 | } |
3190 | 3210 | ||
3211 | hw->wiphy->max_remain_on_channel_duration = 1000; | ||
3212 | |||
3191 | hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY | | 3213 | hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY | |
3192 | WIPHY_FLAG_DISABLE_BEACON_HINTS; | 3214 | WIPHY_FLAG_DISABLE_BEACON_HINTS; |
3193 | 3215 | ||
@@ -3213,6 +3235,8 @@ static int iwl_mac_setup_register(struct iwl_priv *priv, | |||
3213 | priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = | 3235 | priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = |
3214 | &priv->bands[IEEE80211_BAND_5GHZ]; | 3236 | &priv->bands[IEEE80211_BAND_5GHZ]; |
3215 | 3237 | ||
3238 | iwl_leds_init(priv); | ||
3239 | |||
3216 | ret = ieee80211_register_hw(priv->hw); | 3240 | ret = ieee80211_register_hw(priv->hw); |
3217 | if (ret) { | 3241 | if (ret) { |
3218 | IWL_ERR(priv, "Failed to register hw (error %d)\n", ret); | 3242 | IWL_ERR(priv, "Failed to register hw (error %d)\n", ret); |
@@ -3257,7 +3281,7 @@ int iwlagn_mac_start(struct ieee80211_hw *hw) | |||
3257 | } | 3281 | } |
3258 | } | 3282 | } |
3259 | 3283 | ||
3260 | iwl_led_start(priv); | 3284 | iwlagn_led_enable(priv); |
3261 | 3285 | ||
3262 | out: | 3286 | out: |
3263 | priv->is_open = 1; | 3287 | priv->is_open = 1; |
@@ -3393,7 +3417,8 @@ int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
3393 | int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, | 3417 | int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, |
3394 | struct ieee80211_vif *vif, | 3418 | struct ieee80211_vif *vif, |
3395 | enum ieee80211_ampdu_mlme_action action, | 3419 | enum ieee80211_ampdu_mlme_action action, |
3396 | struct ieee80211_sta *sta, u16 tid, u16 *ssn) | 3420 | struct ieee80211_sta *sta, u16 tid, u16 *ssn, |
3421 | u8 buf_size) | ||
3397 | { | 3422 | { |
3398 | struct iwl_priv *priv = hw->priv; | 3423 | struct iwl_priv *priv = hw->priv; |
3399 | int ret = -EINVAL; | 3424 | int ret = -EINVAL; |
@@ -3703,6 +3728,95 @@ done: | |||
3703 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 3728 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
3704 | } | 3729 | } |
3705 | 3730 | ||
3731 | static void iwlagn_disable_roc(struct iwl_priv *priv) | ||
3732 | { | ||
3733 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_PAN]; | ||
3734 | struct ieee80211_channel *chan = ACCESS_ONCE(priv->hw->conf.channel); | ||
3735 | |||
3736 | lockdep_assert_held(&priv->mutex); | ||
3737 | |||
3738 | if (!ctx->is_active) | ||
3739 | return; | ||
3740 | |||
3741 | ctx->staging.dev_type = RXON_DEV_TYPE_2STA; | ||
3742 | ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; | ||
3743 | iwl_set_rxon_channel(priv, chan, ctx); | ||
3744 | iwl_set_flags_for_band(priv, ctx, chan->band, NULL); | ||
3745 | |||
3746 | priv->_agn.hw_roc_channel = NULL; | ||
3747 | |||
3748 | iwlagn_commit_rxon(priv, ctx); | ||
3749 | |||
3750 | ctx->is_active = false; | ||
3751 | } | ||
3752 | |||
3753 | static void iwlagn_bg_roc_done(struct work_struct *work) | ||
3754 | { | ||
3755 | struct iwl_priv *priv = container_of(work, struct iwl_priv, | ||
3756 | _agn.hw_roc_work.work); | ||
3757 | |||
3758 | mutex_lock(&priv->mutex); | ||
3759 | ieee80211_remain_on_channel_expired(priv->hw); | ||
3760 | iwlagn_disable_roc(priv); | ||
3761 | mutex_unlock(&priv->mutex); | ||
3762 | } | ||
3763 | |||
3764 | static int iwl_mac_remain_on_channel(struct ieee80211_hw *hw, | ||
3765 | struct ieee80211_channel *channel, | ||
3766 | enum nl80211_channel_type channel_type, | ||
3767 | int duration) | ||
3768 | { | ||
3769 | struct iwl_priv *priv = hw->priv; | ||
3770 | int err = 0; | ||
3771 | |||
3772 | if (!(priv->valid_contexts & BIT(IWL_RXON_CTX_PAN))) | ||
3773 | return -EOPNOTSUPP; | ||
3774 | |||
3775 | if (!(priv->contexts[IWL_RXON_CTX_PAN].interface_modes & | ||
3776 | BIT(NL80211_IFTYPE_P2P_CLIENT))) | ||
3777 | return -EOPNOTSUPP; | ||
3778 | |||
3779 | mutex_lock(&priv->mutex); | ||
3780 | |||
3781 | if (priv->contexts[IWL_RXON_CTX_PAN].is_active || | ||
3782 | test_bit(STATUS_SCAN_HW, &priv->status)) { | ||
3783 | err = -EBUSY; | ||
3784 | goto out; | ||
3785 | } | ||
3786 | |||
3787 | priv->contexts[IWL_RXON_CTX_PAN].is_active = true; | ||
3788 | priv->_agn.hw_roc_channel = channel; | ||
3789 | priv->_agn.hw_roc_chantype = channel_type; | ||
3790 | priv->_agn.hw_roc_duration = DIV_ROUND_UP(duration * 1000, 1024); | ||
3791 | iwlagn_commit_rxon(priv, &priv->contexts[IWL_RXON_CTX_PAN]); | ||
3792 | queue_delayed_work(priv->workqueue, &priv->_agn.hw_roc_work, | ||
3793 | msecs_to_jiffies(duration + 20)); | ||
3794 | |||
3795 | msleep(IWL_MIN_SLOT_TIME); /* TU is almost ms */ | ||
3796 | ieee80211_ready_on_channel(priv->hw); | ||
3797 | |||
3798 | out: | ||
3799 | mutex_unlock(&priv->mutex); | ||
3800 | |||
3801 | return err; | ||
3802 | } | ||
3803 | |||
3804 | static int iwl_mac_cancel_remain_on_channel(struct ieee80211_hw *hw) | ||
3805 | { | ||
3806 | struct iwl_priv *priv = hw->priv; | ||
3807 | |||
3808 | if (!(priv->valid_contexts & BIT(IWL_RXON_CTX_PAN))) | ||
3809 | return -EOPNOTSUPP; | ||
3810 | |||
3811 | cancel_delayed_work_sync(&priv->_agn.hw_roc_work); | ||
3812 | |||
3813 | mutex_lock(&priv->mutex); | ||
3814 | iwlagn_disable_roc(priv); | ||
3815 | mutex_unlock(&priv->mutex); | ||
3816 | |||
3817 | return 0; | ||
3818 | } | ||
3819 | |||
3706 | /***************************************************************************** | 3820 | /***************************************************************************** |
3707 | * | 3821 | * |
3708 | * driver setup and teardown | 3822 | * driver setup and teardown |
@@ -3724,6 +3838,7 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv) | |||
3724 | INIT_WORK(&priv->bt_runtime_config, iwl_bg_bt_runtime_config); | 3838 | INIT_WORK(&priv->bt_runtime_config, iwl_bg_bt_runtime_config); |
3725 | INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start); | 3839 | INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start); |
3726 | INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start); | 3840 | INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start); |
3841 | INIT_DELAYED_WORK(&priv->_agn.hw_roc_work, iwlagn_bg_roc_done); | ||
3727 | 3842 | ||
3728 | iwl_setup_scan_deferred_work(priv); | 3843 | iwl_setup_scan_deferred_work(priv); |
3729 | 3844 | ||
@@ -3892,6 +4007,8 @@ struct ieee80211_ops iwlagn_hw_ops = { | |||
3892 | .channel_switch = iwlagn_mac_channel_switch, | 4007 | .channel_switch = iwlagn_mac_channel_switch, |
3893 | .flush = iwlagn_mac_flush, | 4008 | .flush = iwlagn_mac_flush, |
3894 | .tx_last_beacon = iwl_mac_tx_last_beacon, | 4009 | .tx_last_beacon = iwl_mac_tx_last_beacon, |
4010 | .remain_on_channel = iwl_mac_remain_on_channel, | ||
4011 | .cancel_remain_on_channel = iwl_mac_cancel_remain_on_channel, | ||
3895 | }; | 4012 | }; |
3896 | #endif | 4013 | #endif |
3897 | 4014 | ||
@@ -4019,6 +4136,10 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
4019 | priv->contexts[IWL_RXON_CTX_PAN].mcast_queue = IWL_IPAN_MCAST_QUEUE; | 4136 | priv->contexts[IWL_RXON_CTX_PAN].mcast_queue = IWL_IPAN_MCAST_QUEUE; |
4020 | priv->contexts[IWL_RXON_CTX_PAN].interface_modes = | 4137 | priv->contexts[IWL_RXON_CTX_PAN].interface_modes = |
4021 | BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP); | 4138 | BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP); |
4139 | #ifdef CONFIG_IWL_P2P | ||
4140 | priv->contexts[IWL_RXON_CTX_PAN].interface_modes |= | ||
4141 | BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO); | ||
4142 | #endif | ||
4022 | priv->contexts[IWL_RXON_CTX_PAN].ap_devtype = RXON_DEV_TYPE_CP; | 4143 | priv->contexts[IWL_RXON_CTX_PAN].ap_devtype = RXON_DEV_TYPE_CP; |
4023 | priv->contexts[IWL_RXON_CTX_PAN].station_devtype = RXON_DEV_TYPE_2STA; | 4144 | priv->contexts[IWL_RXON_CTX_PAN].station_devtype = RXON_DEV_TYPE_2STA; |
4024 | priv->contexts[IWL_RXON_CTX_PAN].unused_devtype = RXON_DEV_TYPE_P2P; | 4145 | priv->contexts[IWL_RXON_CTX_PAN].unused_devtype = RXON_DEV_TYPE_P2P; |
@@ -4266,6 +4387,9 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev) | |||
4266 | * we need to set STATUS_EXIT_PENDING bit. | 4387 | * we need to set STATUS_EXIT_PENDING bit. |
4267 | */ | 4388 | */ |
4268 | set_bit(STATUS_EXIT_PENDING, &priv->status); | 4389 | set_bit(STATUS_EXIT_PENDING, &priv->status); |
4390 | |||
4391 | iwl_leds_exit(priv); | ||
4392 | |||
4269 | if (priv->mac80211_registered) { | 4393 | if (priv->mac80211_registered) { |
4270 | ieee80211_unregister_hw(priv->hw); | 4394 | ieee80211_unregister_hw(priv->hw); |
4271 | priv->mac80211_registered = 0; | 4395 | priv->mac80211_registered = 0; |
@@ -4486,6 +4610,49 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { | |||
4486 | {IWL_PCI_DEVICE(0x0896, 0x5025, iwl130_bgn_cfg)}, | 4610 | {IWL_PCI_DEVICE(0x0896, 0x5025, iwl130_bgn_cfg)}, |
4487 | {IWL_PCI_DEVICE(0x0896, 0x5027, iwl130_bg_cfg)}, | 4611 | {IWL_PCI_DEVICE(0x0896, 0x5027, iwl130_bg_cfg)}, |
4488 | 4612 | ||
4613 | /* 2x00 Series */ | ||
4614 | {IWL_PCI_DEVICE(0x0890, 0x4022, iwl2000_2bgn_cfg)}, | ||
4615 | {IWL_PCI_DEVICE(0x0891, 0x4222, iwl2000_2bgn_cfg)}, | ||
4616 | {IWL_PCI_DEVICE(0x0890, 0x4422, iwl2000_2bgn_cfg)}, | ||
4617 | {IWL_PCI_DEVICE(0x0890, 0x4026, iwl2000_2bg_cfg)}, | ||
4618 | {IWL_PCI_DEVICE(0x0891, 0x4226, iwl2000_2bg_cfg)}, | ||
4619 | {IWL_PCI_DEVICE(0x0890, 0x4426, iwl2000_2bg_cfg)}, | ||
4620 | |||
4621 | /* 2x30 Series */ | ||
4622 | {IWL_PCI_DEVICE(0x0887, 0x4062, iwl2030_2bgn_cfg)}, | ||
4623 | {IWL_PCI_DEVICE(0x0888, 0x4262, iwl2030_2bgn_cfg)}, | ||
4624 | {IWL_PCI_DEVICE(0x0887, 0x4462, iwl2030_2bgn_cfg)}, | ||
4625 | {IWL_PCI_DEVICE(0x0887, 0x4066, iwl2030_2bg_cfg)}, | ||
4626 | {IWL_PCI_DEVICE(0x0888, 0x4266, iwl2030_2bg_cfg)}, | ||
4627 | {IWL_PCI_DEVICE(0x0887, 0x4466, iwl2030_2bg_cfg)}, | ||
4628 | |||
4629 | /* 6x35 Series */ | ||
4630 | {IWL_PCI_DEVICE(0x088E, 0x4060, iwl6035_2agn_cfg)}, | ||
4631 | {IWL_PCI_DEVICE(0x088F, 0x4260, iwl6035_2agn_cfg)}, | ||
4632 | {IWL_PCI_DEVICE(0x088E, 0x4460, iwl6035_2agn_cfg)}, | ||
4633 | {IWL_PCI_DEVICE(0x088E, 0x4064, iwl6035_2abg_cfg)}, | ||
4634 | {IWL_PCI_DEVICE(0x088F, 0x4264, iwl6035_2abg_cfg)}, | ||
4635 | {IWL_PCI_DEVICE(0x088E, 0x4464, iwl6035_2abg_cfg)}, | ||
4636 | {IWL_PCI_DEVICE(0x088E, 0x4066, iwl6035_2bg_cfg)}, | ||
4637 | {IWL_PCI_DEVICE(0x088F, 0x4266, iwl6035_2bg_cfg)}, | ||
4638 | {IWL_PCI_DEVICE(0x088E, 0x4466, iwl6035_2bg_cfg)}, | ||
4639 | |||
4640 | /* 200 Series */ | ||
4641 | {IWL_PCI_DEVICE(0x0894, 0x0022, iwl200_bgn_cfg)}, | ||
4642 | {IWL_PCI_DEVICE(0x0895, 0x0222, iwl200_bgn_cfg)}, | ||
4643 | {IWL_PCI_DEVICE(0x0894, 0x0422, iwl200_bgn_cfg)}, | ||
4644 | {IWL_PCI_DEVICE(0x0894, 0x0026, iwl200_bg_cfg)}, | ||
4645 | {IWL_PCI_DEVICE(0x0895, 0x0226, iwl200_bg_cfg)}, | ||
4646 | {IWL_PCI_DEVICE(0x0894, 0x0426, iwl200_bg_cfg)}, | ||
4647 | |||
4648 | /* 230 Series */ | ||
4649 | {IWL_PCI_DEVICE(0x0892, 0x0062, iwl230_bgn_cfg)}, | ||
4650 | {IWL_PCI_DEVICE(0x0893, 0x0262, iwl230_bgn_cfg)}, | ||
4651 | {IWL_PCI_DEVICE(0x0892, 0x0462, iwl230_bgn_cfg)}, | ||
4652 | {IWL_PCI_DEVICE(0x0892, 0x0066, iwl230_bg_cfg)}, | ||
4653 | {IWL_PCI_DEVICE(0x0893, 0x0266, iwl230_bg_cfg)}, | ||
4654 | {IWL_PCI_DEVICE(0x0892, 0x0466, iwl230_bg_cfg)}, | ||
4655 | |||
4489 | #endif /* CONFIG_IWL5000 */ | 4656 | #endif /* CONFIG_IWL5000 */ |
4490 | 4657 | ||
4491 | {0} | 4658 | {0} |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index da303585f801..d00e1ea50a8d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h | |||
@@ -96,6 +96,17 @@ extern struct iwl_cfg iwl100_bgn_cfg; | |||
96 | extern struct iwl_cfg iwl100_bg_cfg; | 96 | extern struct iwl_cfg iwl100_bg_cfg; |
97 | extern struct iwl_cfg iwl130_bgn_cfg; | 97 | extern struct iwl_cfg iwl130_bgn_cfg; |
98 | extern struct iwl_cfg iwl130_bg_cfg; | 98 | extern struct iwl_cfg iwl130_bg_cfg; |
99 | extern struct iwl_cfg iwl2000_2bgn_cfg; | ||
100 | extern struct iwl_cfg iwl2000_2bg_cfg; | ||
101 | extern struct iwl_cfg iwl2030_2bgn_cfg; | ||
102 | extern struct iwl_cfg iwl2030_2bg_cfg; | ||
103 | extern struct iwl_cfg iwl6035_2agn_cfg; | ||
104 | extern struct iwl_cfg iwl6035_2abg_cfg; | ||
105 | extern struct iwl_cfg iwl6035_2bg_cfg; | ||
106 | extern struct iwl_cfg iwl200_bg_cfg; | ||
107 | extern struct iwl_cfg iwl200_bgn_cfg; | ||
108 | extern struct iwl_cfg iwl230_bg_cfg; | ||
109 | extern struct iwl_cfg iwl230_bgn_cfg; | ||
99 | 110 | ||
100 | extern struct iwl_mod_params iwlagn_mod_params; | 111 | extern struct iwl_mod_params iwlagn_mod_params; |
101 | extern struct iwl_hcmd_ops iwlagn_hcmd; | 112 | extern struct iwl_hcmd_ops iwlagn_hcmd; |
@@ -185,7 +196,6 @@ void iwlagn_rx_reply_rx(struct iwl_priv *priv, | |||
185 | struct iwl_rx_mem_buffer *rxb); | 196 | struct iwl_rx_mem_buffer *rxb); |
186 | void iwlagn_rx_reply_rx_phy(struct iwl_priv *priv, | 197 | void iwlagn_rx_reply_rx_phy(struct iwl_priv *priv, |
187 | struct iwl_rx_mem_buffer *rxb); | 198 | struct iwl_rx_mem_buffer *rxb); |
188 | void iwl_rx_handle(struct iwl_priv *priv); | ||
189 | 199 | ||
190 | /* tx */ | 200 | /* tx */ |
191 | void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq); | 201 | void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq); |
@@ -330,6 +340,21 @@ void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac); | |||
330 | int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv); | 340 | int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv); |
331 | void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv); | 341 | void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv); |
332 | 342 | ||
343 | /* notification wait support */ | ||
344 | void __acquires(wait_entry) | ||
345 | iwlagn_init_notification_wait(struct iwl_priv *priv, | ||
346 | struct iwl_notification_wait *wait_entry, | ||
347 | void (*fn)(struct iwl_priv *priv, | ||
348 | struct iwl_rx_packet *pkt), | ||
349 | u8 cmd); | ||
350 | signed long __releases(wait_entry) | ||
351 | iwlagn_wait_notification(struct iwl_priv *priv, | ||
352 | struct iwl_notification_wait *wait_entry, | ||
353 | unsigned long timeout); | ||
354 | void __releases(wait_entry) | ||
355 | iwlagn_remove_notification(struct iwl_priv *priv, | ||
356 | struct iwl_notification_wait *wait_entry); | ||
357 | |||
333 | /* mac80211 handlers (for 4965) */ | 358 | /* mac80211 handlers (for 4965) */ |
334 | int iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb); | 359 | int iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb); |
335 | int iwlagn_mac_start(struct ieee80211_hw *hw); | 360 | int iwlagn_mac_start(struct ieee80211_hw *hw); |
@@ -349,7 +374,8 @@ void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw, | |||
349 | int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, | 374 | int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, |
350 | struct ieee80211_vif *vif, | 375 | struct ieee80211_vif *vif, |
351 | enum ieee80211_ampdu_mlme_action action, | 376 | enum ieee80211_ampdu_mlme_action action, |
352 | struct ieee80211_sta *sta, u16 tid, u16 *ssn); | 377 | struct ieee80211_sta *sta, u16 tid, u16 *ssn, |
378 | u8 buf_size); | ||
353 | int iwlagn_mac_sta_add(struct ieee80211_hw *hw, | 379 | int iwlagn_mac_sta_add(struct ieee80211_hw *hw, |
354 | struct ieee80211_vif *vif, | 380 | struct ieee80211_vif *vif, |
355 | struct ieee80211_sta *sta); | 381 | struct ieee80211_sta *sta); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index f893d4a6aa87..935b19e2c260 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h | |||
@@ -189,6 +189,7 @@ enum { | |||
189 | REPLY_WIPAN_WEPKEY = 0xb8, /* use REPLY_WEPKEY structure */ | 189 | REPLY_WIPAN_WEPKEY = 0xb8, /* use REPLY_WEPKEY structure */ |
190 | REPLY_WIPAN_P2P_CHANNEL_SWITCH = 0xb9, | 190 | REPLY_WIPAN_P2P_CHANNEL_SWITCH = 0xb9, |
191 | REPLY_WIPAN_NOA_NOTIFICATION = 0xbc, | 191 | REPLY_WIPAN_NOA_NOTIFICATION = 0xbc, |
192 | REPLY_WIPAN_DEACTIVATION_COMPLETE = 0xbd, | ||
192 | 193 | ||
193 | REPLY_MAX = 0xff | 194 | REPLY_MAX = 0xff |
194 | }; | 195 | }; |
@@ -4369,6 +4370,11 @@ int iwl_agn_check_rxon_cmd(struct iwl_priv *priv); | |||
4369 | * REPLY_WIPAN_PARAMS = 0xb2 (Commands and Notification) | 4370 | * REPLY_WIPAN_PARAMS = 0xb2 (Commands and Notification) |
4370 | */ | 4371 | */ |
4371 | 4372 | ||
4373 | /* | ||
4374 | * Minimum slot time in TU | ||
4375 | */ | ||
4376 | #define IWL_MIN_SLOT_TIME 20 | ||
4377 | |||
4372 | /** | 4378 | /** |
4373 | * struct iwl_wipan_slot | 4379 | * struct iwl_wipan_slot |
4374 | * @width: Time in TU | 4380 | * @width: Time in TU |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index efbde1f1a8bf..a46ad60216a0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -227,7 +227,8 @@ int iwlcore_init_geos(struct iwl_priv *priv) | |||
227 | geo_ch = &sband->channels[sband->n_channels++]; | 227 | geo_ch = &sband->channels[sband->n_channels++]; |
228 | 228 | ||
229 | geo_ch->center_freq = | 229 | geo_ch->center_freq = |
230 | ieee80211_channel_to_frequency(ch->channel); | 230 | ieee80211_channel_to_frequency(ch->channel, |
231 | sband->band); | ||
231 | geo_ch->max_power = ch->max_power_avg; | 232 | geo_ch->max_power = ch->max_power_avg; |
232 | geo_ch->max_antenna_gain = 0xff; | 233 | geo_ch->max_antenna_gain = 0xff; |
233 | geo_ch->hw_value = ch->channel; | 234 | geo_ch->hw_value = ch->channel; |
@@ -1403,9 +1404,10 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |||
1403 | struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; | 1404 | struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; |
1404 | struct iwl_rxon_context *tmp, *ctx = NULL; | 1405 | struct iwl_rxon_context *tmp, *ctx = NULL; |
1405 | int err; | 1406 | int err; |
1407 | enum nl80211_iftype viftype = ieee80211_vif_type_p2p(vif); | ||
1406 | 1408 | ||
1407 | IWL_DEBUG_MAC80211(priv, "enter: type %d, addr %pM\n", | 1409 | IWL_DEBUG_MAC80211(priv, "enter: type %d, addr %pM\n", |
1408 | vif->type, vif->addr); | 1410 | viftype, vif->addr); |
1409 | 1411 | ||
1410 | mutex_lock(&priv->mutex); | 1412 | mutex_lock(&priv->mutex); |
1411 | 1413 | ||
@@ -1429,7 +1431,7 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |||
1429 | continue; | 1431 | continue; |
1430 | } | 1432 | } |
1431 | 1433 | ||
1432 | if (!(possible_modes & BIT(vif->type))) | 1434 | if (!(possible_modes & BIT(viftype))) |
1433 | continue; | 1435 | continue; |
1434 | 1436 | ||
1435 | /* have maybe usable context w/o interface */ | 1437 | /* have maybe usable context w/o interface */ |
@@ -1675,7 +1677,6 @@ void iwl_clear_traffic_stats(struct iwl_priv *priv) | |||
1675 | { | 1677 | { |
1676 | memset(&priv->tx_stats, 0, sizeof(struct traffic_stats)); | 1678 | memset(&priv->tx_stats, 0, sizeof(struct traffic_stats)); |
1677 | memset(&priv->rx_stats, 0, sizeof(struct traffic_stats)); | 1679 | memset(&priv->rx_stats, 0, sizeof(struct traffic_stats)); |
1678 | priv->led_tpt = 0; | ||
1679 | } | 1680 | } |
1680 | 1681 | ||
1681 | /* | 1682 | /* |
@@ -1768,7 +1769,6 @@ void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, u16 len) | |||
1768 | stats->data_cnt++; | 1769 | stats->data_cnt++; |
1769 | stats->data_bytes += len; | 1770 | stats->data_bytes += len; |
1770 | } | 1771 | } |
1771 | iwl_leds_background(priv); | ||
1772 | } | 1772 | } |
1773 | EXPORT_SYMBOL(iwl_update_stats); | 1773 | EXPORT_SYMBOL(iwl_update_stats); |
1774 | #endif | 1774 | #endif |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index a3474376fdbc..bbc5aa7a7f2f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -227,8 +227,6 @@ struct iwl_lib_ops { | |||
227 | 227 | ||
228 | struct iwl_led_ops { | 228 | struct iwl_led_ops { |
229 | int (*cmd)(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd); | 229 | int (*cmd)(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd); |
230 | int (*on)(struct iwl_priv *priv); | ||
231 | int (*off)(struct iwl_priv *priv); | ||
232 | }; | 230 | }; |
233 | 231 | ||
234 | /* NIC specific ops */ | 232 | /* NIC specific ops */ |
@@ -494,18 +492,6 @@ static inline void iwl_dbg_log_rx_data_frame(struct iwl_priv *priv, | |||
494 | static inline void iwl_update_stats(struct iwl_priv *priv, bool is_tx, | 492 | static inline void iwl_update_stats(struct iwl_priv *priv, bool is_tx, |
495 | __le16 fc, u16 len) | 493 | __le16 fc, u16 len) |
496 | { | 494 | { |
497 | struct traffic_stats *stats; | ||
498 | |||
499 | if (is_tx) | ||
500 | stats = &priv->tx_stats; | ||
501 | else | ||
502 | stats = &priv->rx_stats; | ||
503 | |||
504 | if (ieee80211_is_data(fc)) { | ||
505 | /* data */ | ||
506 | stats->data_bytes += len; | ||
507 | } | ||
508 | iwl_leds_background(priv); | ||
509 | } | 495 | } |
510 | #endif | 496 | #endif |
511 | /***************************************************** | 497 | /***************************************************** |
diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index b80bf7dff55b..6c2b2df7ee7e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h | |||
@@ -290,7 +290,7 @@ | |||
290 | 290 | ||
291 | 291 | ||
292 | /* HW REV */ | 292 | /* HW REV */ |
293 | #define CSR_HW_REV_TYPE_MSK (0x00000F0) | 293 | #define CSR_HW_REV_TYPE_MSK (0x00001F0) |
294 | #define CSR_HW_REV_TYPE_3945 (0x00000D0) | 294 | #define CSR_HW_REV_TYPE_3945 (0x00000D0) |
295 | #define CSR_HW_REV_TYPE_4965 (0x0000000) | 295 | #define CSR_HW_REV_TYPE_4965 (0x0000000) |
296 | #define CSR_HW_REV_TYPE_5300 (0x0000020) | 296 | #define CSR_HW_REV_TYPE_5300 (0x0000020) |
@@ -300,9 +300,15 @@ | |||
300 | #define CSR_HW_REV_TYPE_1000 (0x0000060) | 300 | #define CSR_HW_REV_TYPE_1000 (0x0000060) |
301 | #define CSR_HW_REV_TYPE_6x00 (0x0000070) | 301 | #define CSR_HW_REV_TYPE_6x00 (0x0000070) |
302 | #define CSR_HW_REV_TYPE_6x50 (0x0000080) | 302 | #define CSR_HW_REV_TYPE_6x50 (0x0000080) |
303 | #define CSR_HW_REV_TYPE_6x50g2 (0x0000084) | 303 | #define CSR_HW_REV_TYPE_6150 (0x0000084) |
304 | #define CSR_HW_REV_TYPE_6x00g2 (0x00000B0) | 304 | #define CSR_HW_REV_TYPE_6x05 (0x00000B0) |
305 | #define CSR_HW_REV_TYPE_NONE (0x00000F0) | 305 | #define CSR_HW_REV_TYPE_6x30 CSR_HW_REV_TYPE_6x05 |
306 | #define CSR_HW_REV_TYPE_6x35 CSR_HW_REV_TYPE_6x05 | ||
307 | #define CSR_HW_REV_TYPE_2x30 (0x00000C0) | ||
308 | #define CSR_HW_REV_TYPE_2x00 (0x0000100) | ||
309 | #define CSR_HW_REV_TYPE_200 (0x0000110) | ||
310 | #define CSR_HW_REV_TYPE_230 (0x0000120) | ||
311 | #define CSR_HW_REV_TYPE_NONE (0x00001F0) | ||
306 | 312 | ||
307 | /* EEPROM REG */ | 313 | /* EEPROM REG */ |
308 | #define CSR_EEPROM_REG_READ_VALID_MSK (0x00000001) | 314 | #define CSR_EEPROM_REG_READ_VALID_MSK (0x00000001) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 6fe80b5e7a15..418c8ac26222 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c | |||
@@ -207,18 +207,19 @@ static ssize_t iwl_dbgfs_rx_statistics_read(struct file *file, | |||
207 | return ret; | 207 | return ret; |
208 | } | 208 | } |
209 | 209 | ||
210 | #define BYTE1_MASK 0x000000ff; | ||
211 | #define BYTE2_MASK 0x0000ffff; | ||
212 | #define BYTE3_MASK 0x00ffffff; | ||
213 | static ssize_t iwl_dbgfs_sram_read(struct file *file, | 210 | static ssize_t iwl_dbgfs_sram_read(struct file *file, |
214 | char __user *user_buf, | 211 | char __user *user_buf, |
215 | size_t count, loff_t *ppos) | 212 | size_t count, loff_t *ppos) |
216 | { | 213 | { |
217 | u32 val; | 214 | u32 val = 0; |
218 | char *buf; | 215 | char *buf; |
219 | ssize_t ret; | 216 | ssize_t ret; |
220 | int i; | 217 | int i = 0; |
218 | bool device_format = false; | ||
219 | int offset = 0; | ||
220 | int len = 0; | ||
221 | int pos = 0; | 221 | int pos = 0; |
222 | int sram; | ||
222 | struct iwl_priv *priv = file->private_data; | 223 | struct iwl_priv *priv = file->private_data; |
223 | size_t bufsz; | 224 | size_t bufsz; |
224 | 225 | ||
@@ -230,35 +231,62 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, | |||
230 | else | 231 | else |
231 | priv->dbgfs_sram_len = priv->ucode_data.len; | 232 | priv->dbgfs_sram_len = priv->ucode_data.len; |
232 | } | 233 | } |
233 | bufsz = 30 + priv->dbgfs_sram_len * sizeof(char) * 10; | 234 | len = priv->dbgfs_sram_len; |
235 | |||
236 | if (len == -4) { | ||
237 | device_format = true; | ||
238 | len = 4; | ||
239 | } | ||
240 | |||
241 | bufsz = 50 + len * 4; | ||
234 | buf = kmalloc(bufsz, GFP_KERNEL); | 242 | buf = kmalloc(bufsz, GFP_KERNEL); |
235 | if (!buf) | 243 | if (!buf) |
236 | return -ENOMEM; | 244 | return -ENOMEM; |
245 | |||
237 | pos += scnprintf(buf + pos, bufsz - pos, "sram_len: 0x%x\n", | 246 | pos += scnprintf(buf + pos, bufsz - pos, "sram_len: 0x%x\n", |
238 | priv->dbgfs_sram_len); | 247 | len); |
239 | pos += scnprintf(buf + pos, bufsz - pos, "sram_offset: 0x%x\n", | 248 | pos += scnprintf(buf + pos, bufsz - pos, "sram_offset: 0x%x\n", |
240 | priv->dbgfs_sram_offset); | 249 | priv->dbgfs_sram_offset); |
241 | for (i = priv->dbgfs_sram_len; i > 0; i -= 4) { | 250 | |
242 | val = iwl_read_targ_mem(priv, priv->dbgfs_sram_offset + \ | 251 | /* adjust sram address since reads are only on even u32 boundaries */ |
243 | priv->dbgfs_sram_len - i); | 252 | offset = priv->dbgfs_sram_offset & 0x3; |
244 | if (i < 4) { | 253 | sram = priv->dbgfs_sram_offset & ~0x3; |
245 | switch (i) { | 254 | |
246 | case 1: | 255 | /* read the first u32 from sram */ |
247 | val &= BYTE1_MASK; | 256 | val = iwl_read_targ_mem(priv, sram); |
248 | break; | 257 | |
249 | case 2: | 258 | for (; len; len--) { |
250 | val &= BYTE2_MASK; | 259 | /* put the address at the start of every line */ |
251 | break; | 260 | if (i == 0) |
252 | case 3: | 261 | pos += scnprintf(buf + pos, bufsz - pos, |
253 | val &= BYTE3_MASK; | 262 | "%08X: ", sram + offset); |
254 | break; | 263 | |
255 | } | 264 | if (device_format) |
265 | pos += scnprintf(buf + pos, bufsz - pos, | ||
266 | "%02x", (val >> (8 * (3 - offset))) & 0xff); | ||
267 | else | ||
268 | pos += scnprintf(buf + pos, bufsz - pos, | ||
269 | "%02x ", (val >> (8 * offset)) & 0xff); | ||
270 | |||
271 | /* if all bytes processed, read the next u32 from sram */ | ||
272 | if (++offset == 4) { | ||
273 | sram += 4; | ||
274 | offset = 0; | ||
275 | val = iwl_read_targ_mem(priv, sram); | ||
256 | } | 276 | } |
257 | if (!(i % 16)) | 277 | |
278 | /* put in extra spaces and split lines for human readability */ | ||
279 | if (++i == 16) { | ||
280 | i = 0; | ||
258 | pos += scnprintf(buf + pos, bufsz - pos, "\n"); | 281 | pos += scnprintf(buf + pos, bufsz - pos, "\n"); |
259 | pos += scnprintf(buf + pos, bufsz - pos, "0x%08x ", val); | 282 | } else if (!(i & 7)) { |
283 | pos += scnprintf(buf + pos, bufsz - pos, " "); | ||
284 | } else if (!(i & 3)) { | ||
285 | pos += scnprintf(buf + pos, bufsz - pos, " "); | ||
286 | } | ||
260 | } | 287 | } |
261 | pos += scnprintf(buf + pos, bufsz - pos, "\n"); | 288 | if (i) |
289 | pos += scnprintf(buf + pos, bufsz - pos, "\n"); | ||
262 | 290 | ||
263 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 291 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
264 | kfree(buf); | 292 | kfree(buf); |
@@ -282,6 +310,9 @@ static ssize_t iwl_dbgfs_sram_write(struct file *file, | |||
282 | if (sscanf(buf, "%x,%x", &offset, &len) == 2) { | 310 | if (sscanf(buf, "%x,%x", &offset, &len) == 2) { |
283 | priv->dbgfs_sram_offset = offset; | 311 | priv->dbgfs_sram_offset = offset; |
284 | priv->dbgfs_sram_len = len; | 312 | priv->dbgfs_sram_len = len; |
313 | } else if (sscanf(buf, "%x", &offset) == 1) { | ||
314 | priv->dbgfs_sram_offset = offset; | ||
315 | priv->dbgfs_sram_len = -4; | ||
285 | } else { | 316 | } else { |
286 | priv->dbgfs_sram_offset = 0; | 317 | priv->dbgfs_sram_offset = 0; |
287 | priv->dbgfs_sram_len = 0; | 318 | priv->dbgfs_sram_len = 0; |
@@ -668,29 +699,6 @@ static ssize_t iwl_dbgfs_qos_read(struct file *file, char __user *user_buf, | |||
668 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 699 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
669 | } | 700 | } |
670 | 701 | ||
671 | static ssize_t iwl_dbgfs_led_read(struct file *file, char __user *user_buf, | ||
672 | size_t count, loff_t *ppos) | ||
673 | { | ||
674 | struct iwl_priv *priv = file->private_data; | ||
675 | int pos = 0; | ||
676 | char buf[256]; | ||
677 | const size_t bufsz = sizeof(buf); | ||
678 | |||
679 | pos += scnprintf(buf + pos, bufsz - pos, | ||
680 | "allow blinking: %s\n", | ||
681 | (priv->allow_blinking) ? "True" : "False"); | ||
682 | if (priv->allow_blinking) { | ||
683 | pos += scnprintf(buf + pos, bufsz - pos, | ||
684 | "Led blinking rate: %u\n", | ||
685 | priv->last_blink_rate); | ||
686 | pos += scnprintf(buf + pos, bufsz - pos, | ||
687 | "Last blink time: %lu\n", | ||
688 | priv->last_blink_time); | ||
689 | } | ||
690 | |||
691 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
692 | } | ||
693 | |||
694 | static ssize_t iwl_dbgfs_thermal_throttling_read(struct file *file, | 702 | static ssize_t iwl_dbgfs_thermal_throttling_read(struct file *file, |
695 | char __user *user_buf, | 703 | char __user *user_buf, |
696 | size_t count, loff_t *ppos) | 704 | size_t count, loff_t *ppos) |
@@ -856,7 +864,6 @@ DEBUGFS_READ_FILE_OPS(channels); | |||
856 | DEBUGFS_READ_FILE_OPS(status); | 864 | DEBUGFS_READ_FILE_OPS(status); |
857 | DEBUGFS_READ_WRITE_FILE_OPS(interrupt); | 865 | DEBUGFS_READ_WRITE_FILE_OPS(interrupt); |
858 | DEBUGFS_READ_FILE_OPS(qos); | 866 | DEBUGFS_READ_FILE_OPS(qos); |
859 | DEBUGFS_READ_FILE_OPS(led); | ||
860 | DEBUGFS_READ_FILE_OPS(thermal_throttling); | 867 | DEBUGFS_READ_FILE_OPS(thermal_throttling); |
861 | DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40); | 868 | DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40); |
862 | DEBUGFS_READ_WRITE_FILE_OPS(sleep_level_override); | 869 | DEBUGFS_READ_WRITE_FILE_OPS(sleep_level_override); |
@@ -1725,7 +1732,6 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) | |||
1725 | DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR); | 1732 | DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR); |
1726 | DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR); | 1733 | DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR); |
1727 | DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR); | 1734 | DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR); |
1728 | DEBUGFS_ADD_FILE(led, dir_data, S_IRUSR); | ||
1729 | if (!priv->cfg->base_params->broken_powersave) { | 1735 | if (!priv->cfg->base_params->broken_powersave) { |
1730 | DEBUGFS_ADD_FILE(sleep_level_override, dir_data, | 1736 | DEBUGFS_ADD_FILE(sleep_level_override, dir_data, |
1731 | S_IWUSR | S_IRUSR); | 1737 | S_IWUSR | S_IRUSR); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 8dda67850af4..6fa1383d72ec 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -34,6 +34,8 @@ | |||
34 | 34 | ||
35 | #include <linux/pci.h> /* for struct pci_device_id */ | 35 | #include <linux/pci.h> /* for struct pci_device_id */ |
36 | #include <linux/kernel.h> | 36 | #include <linux/kernel.h> |
37 | #include <linux/wait.h> | ||
38 | #include <linux/leds.h> | ||
37 | #include <net/ieee80211_radiotap.h> | 39 | #include <net/ieee80211_radiotap.h> |
38 | 40 | ||
39 | #include "iwl-eeprom.h" | 41 | #include "iwl-eeprom.h" |
@@ -995,7 +997,6 @@ struct reply_agg_tx_error_statistics { | |||
995 | u32 unknown; | 997 | u32 unknown; |
996 | }; | 998 | }; |
997 | 999 | ||
998 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
999 | /* management statistics */ | 1000 | /* management statistics */ |
1000 | enum iwl_mgmt_stats { | 1001 | enum iwl_mgmt_stats { |
1001 | MANAGEMENT_ASSOC_REQ = 0, | 1002 | MANAGEMENT_ASSOC_REQ = 0, |
@@ -1026,16 +1027,13 @@ enum iwl_ctrl_stats { | |||
1026 | }; | 1027 | }; |
1027 | 1028 | ||
1028 | struct traffic_stats { | 1029 | struct traffic_stats { |
1030 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
1029 | u32 mgmt[MANAGEMENT_MAX]; | 1031 | u32 mgmt[MANAGEMENT_MAX]; |
1030 | u32 ctrl[CONTROL_MAX]; | 1032 | u32 ctrl[CONTROL_MAX]; |
1031 | u32 data_cnt; | 1033 | u32 data_cnt; |
1032 | u64 data_bytes; | 1034 | u64 data_bytes; |
1033 | }; | ||
1034 | #else | ||
1035 | struct traffic_stats { | ||
1036 | u64 data_bytes; | ||
1037 | }; | ||
1038 | #endif | 1035 | #endif |
1036 | }; | ||
1039 | 1037 | ||
1040 | /* | 1038 | /* |
1041 | * iwl_switch_rxon: "channel switch" structure | 1039 | * iwl_switch_rxon: "channel switch" structure |
@@ -1139,6 +1137,33 @@ struct iwl_force_reset { | |||
1139 | */ | 1137 | */ |
1140 | #define IWLAGN_EXT_BEACON_TIME_POS 22 | 1138 | #define IWLAGN_EXT_BEACON_TIME_POS 22 |
1141 | 1139 | ||
1140 | /** | ||
1141 | * struct iwl_notification_wait - notification wait entry | ||
1142 | * @list: list head for global list | ||
1143 | * @fn: function called with the notification | ||
1144 | * @cmd: command ID | ||
1145 | * | ||
1146 | * This structure is not used directly, to wait for a | ||
1147 | * notification declare it on the stack, and call | ||
1148 | * iwlagn_init_notification_wait() with appropriate | ||
1149 | * parameters. Then do whatever will cause the ucode | ||
1150 | * to notify the driver, and to wait for that then | ||
1151 | * call iwlagn_wait_notification(). | ||
1152 | * | ||
1153 | * Each notification is one-shot. If at some point we | ||
1154 | * need to support multi-shot notifications (which | ||
1155 | * can't be allocated on the stack) we need to modify | ||
1156 | * the code for them. | ||
1157 | */ | ||
1158 | struct iwl_notification_wait { | ||
1159 | struct list_head list; | ||
1160 | |||
1161 | void (*fn)(struct iwl_priv *priv, struct iwl_rx_packet *pkt); | ||
1162 | |||
1163 | u8 cmd; | ||
1164 | bool triggered; | ||
1165 | }; | ||
1166 | |||
1142 | enum iwl_rxon_context_id { | 1167 | enum iwl_rxon_context_id { |
1143 | IWL_RXON_CTX_BSS, | 1168 | IWL_RXON_CTX_BSS, |
1144 | IWL_RXON_CTX_PAN, | 1169 | IWL_RXON_CTX_PAN, |
@@ -1310,11 +1335,6 @@ struct iwl_priv { | |||
1310 | struct iwl_init_alive_resp card_alive_init; | 1335 | struct iwl_init_alive_resp card_alive_init; |
1311 | struct iwl_alive_resp card_alive; | 1336 | struct iwl_alive_resp card_alive; |
1312 | 1337 | ||
1313 | unsigned long last_blink_time; | ||
1314 | u8 last_blink_rate; | ||
1315 | u8 allow_blinking; | ||
1316 | u64 led_tpt; | ||
1317 | |||
1318 | u16 active_rate; | 1338 | u16 active_rate; |
1319 | 1339 | ||
1320 | u8 start_calib; | 1340 | u8 start_calib; |
@@ -1463,6 +1483,17 @@ struct iwl_priv { | |||
1463 | struct iwl_bt_notif_statistics delta_statistics_bt; | 1483 | struct iwl_bt_notif_statistics delta_statistics_bt; |
1464 | struct iwl_bt_notif_statistics max_delta_bt; | 1484 | struct iwl_bt_notif_statistics max_delta_bt; |
1465 | #endif | 1485 | #endif |
1486 | |||
1487 | /* notification wait support */ | ||
1488 | struct list_head notif_waits; | ||
1489 | spinlock_t notif_wait_lock; | ||
1490 | wait_queue_head_t notif_waitq; | ||
1491 | |||
1492 | /* remain-on-channel offload support */ | ||
1493 | struct ieee80211_channel *hw_roc_channel; | ||
1494 | struct delayed_work hw_roc_work; | ||
1495 | enum nl80211_channel_type hw_roc_chantype; | ||
1496 | int hw_roc_duration; | ||
1466 | } _agn; | 1497 | } _agn; |
1467 | #endif | 1498 | #endif |
1468 | }; | 1499 | }; |
@@ -1547,6 +1578,10 @@ struct iwl_priv { | |||
1547 | bool hw_ready; | 1578 | bool hw_ready; |
1548 | 1579 | ||
1549 | struct iwl_event_log event_log; | 1580 | struct iwl_event_log event_log; |
1581 | |||
1582 | struct led_classdev led; | ||
1583 | unsigned long blink_on, blink_off; | ||
1584 | bool led_registered; | ||
1550 | }; /*iwl_priv */ | 1585 | }; /*iwl_priv */ |
1551 | 1586 | ||
1552 | static inline void iwl_txq_ctx_activate(struct iwl_priv *priv, int txq_id) | 1587 | static inline void iwl_txq_ctx_activate(struct iwl_priv *priv, int txq_id) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h index 9e6f31355eee..98aa8af01192 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h | |||
@@ -247,13 +247,26 @@ struct iwl_eeprom_enhanced_txpwr { | |||
247 | #define EEPROM_6050_TX_POWER_VERSION (4) | 247 | #define EEPROM_6050_TX_POWER_VERSION (4) |
248 | #define EEPROM_6050_EEPROM_VERSION (0x532) | 248 | #define EEPROM_6050_EEPROM_VERSION (0x532) |
249 | 249 | ||
250 | /* 6x50g2 Specific */ | 250 | /* 6150 Specific */ |
251 | #define EEPROM_6050G2_TX_POWER_VERSION (6) | 251 | #define EEPROM_6150_TX_POWER_VERSION (6) |
252 | #define EEPROM_6050G2_EEPROM_VERSION (0x553) | 252 | #define EEPROM_6150_EEPROM_VERSION (0x553) |
253 | |||
254 | /* 6x05 Specific */ | ||
255 | #define EEPROM_6005_TX_POWER_VERSION (6) | ||
256 | #define EEPROM_6005_EEPROM_VERSION (0x709) | ||
257 | |||
258 | /* 6x30 Specific */ | ||
259 | #define EEPROM_6030_TX_POWER_VERSION (6) | ||
260 | #define EEPROM_6030_EEPROM_VERSION (0x709) | ||
261 | |||
262 | /* 2x00 Specific */ | ||
263 | #define EEPROM_2000_TX_POWER_VERSION (6) | ||
264 | #define EEPROM_2000_EEPROM_VERSION (0x805) | ||
265 | |||
266 | /* 6x35 Specific */ | ||
267 | #define EEPROM_6035_TX_POWER_VERSION (6) | ||
268 | #define EEPROM_6035_EEPROM_VERSION (0x753) | ||
253 | 269 | ||
254 | /* 6x00g2 Specific */ | ||
255 | #define EEPROM_6000G2_TX_POWER_VERSION (6) | ||
256 | #define EEPROM_6000G2_EEPROM_VERSION (0x709) | ||
257 | 270 | ||
258 | /* OTP */ | 271 | /* OTP */ |
259 | /* lower blocks contain EEPROM image and calibration data */ | 272 | /* lower blocks contain EEPROM image and calibration data */ |
@@ -264,6 +277,7 @@ struct iwl_eeprom_enhanced_txpwr { | |||
264 | #define OTP_MAX_LL_ITEMS_1000 (3) /* OTP blocks for 1000 */ | 277 | #define OTP_MAX_LL_ITEMS_1000 (3) /* OTP blocks for 1000 */ |
265 | #define OTP_MAX_LL_ITEMS_6x00 (4) /* OTP blocks for 6x00 */ | 278 | #define OTP_MAX_LL_ITEMS_6x00 (4) /* OTP blocks for 6x00 */ |
266 | #define OTP_MAX_LL_ITEMS_6x50 (7) /* OTP blocks for 6x50 */ | 279 | #define OTP_MAX_LL_ITEMS_6x50 (7) /* OTP blocks for 6x50 */ |
280 | #define OTP_MAX_LL_ITEMS_2x00 (4) /* OTP blocks for 2x00 */ | ||
267 | 281 | ||
268 | /* 2.4 GHz */ | 282 | /* 2.4 GHz */ |
269 | extern const u8 iwl_eeprom_band_1[14]; | 283 | extern const u8 iwl_eeprom_band_1[14]; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c index c373b53babea..e4b953d7b7bf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c | |||
@@ -108,6 +108,7 @@ const char *get_cmd_string(u8 cmd) | |||
108 | IWL_CMD(REPLY_WIPAN_WEPKEY); | 108 | IWL_CMD(REPLY_WIPAN_WEPKEY); |
109 | IWL_CMD(REPLY_WIPAN_P2P_CHANNEL_SWITCH); | 109 | IWL_CMD(REPLY_WIPAN_P2P_CHANNEL_SWITCH); |
110 | IWL_CMD(REPLY_WIPAN_NOA_NOTIFICATION); | 110 | IWL_CMD(REPLY_WIPAN_NOA_NOTIFICATION); |
111 | IWL_CMD(REPLY_WIPAN_DEACTIVATION_COMPLETE); | ||
111 | default: | 112 | default: |
112 | return "UNKNOWN"; | 113 | return "UNKNOWN"; |
113 | 114 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index 46ccdf406e8e..074ad2275228 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c | |||
@@ -48,31 +48,19 @@ module_param(led_mode, int, S_IRUGO); | |||
48 | MODULE_PARM_DESC(led_mode, "0=system default, " | 48 | MODULE_PARM_DESC(led_mode, "0=system default, " |
49 | "1=On(RF On)/Off(RF Off), 2=blinking"); | 49 | "1=On(RF On)/Off(RF Off), 2=blinking"); |
50 | 50 | ||
51 | static const struct { | 51 | static const struct ieee80211_tpt_blink iwl_blink[] = { |
52 | u16 tpt; /* Mb/s */ | 52 | { .throughput = 0 * 1024 - 1, .blink_time = 334 }, |
53 | u8 on_time; | 53 | { .throughput = 1 * 1024 - 1, .blink_time = 260 }, |
54 | u8 off_time; | 54 | { .throughput = 5 * 1024 - 1, .blink_time = 220 }, |
55 | } blink_tbl[] = | 55 | { .throughput = 10 * 1024 - 1, .blink_time = 190 }, |
56 | { | 56 | { .throughput = 20 * 1024 - 1, .blink_time = 170 }, |
57 | {300, 25, 25}, | 57 | { .throughput = 50 * 1024 - 1, .blink_time = 150 }, |
58 | {200, 40, 40}, | 58 | { .throughput = 70 * 1024 - 1, .blink_time = 130 }, |
59 | {100, 55, 55}, | 59 | { .throughput = 100 * 1024 - 1, .blink_time = 110 }, |
60 | {70, 65, 65}, | 60 | { .throughput = 200 * 1024 - 1, .blink_time = 80 }, |
61 | {50, 75, 75}, | 61 | { .throughput = 300 * 1024 - 1, .blink_time = 50 }, |
62 | {20, 85, 85}, | ||
63 | {10, 95, 95}, | ||
64 | {5, 110, 110}, | ||
65 | {1, 130, 130}, | ||
66 | {0, 167, 167}, | ||
67 | /* SOLID_ON */ | ||
68 | {-1, IWL_LED_SOLID, 0} | ||
69 | }; | 62 | }; |
70 | 63 | ||
71 | #define IWL_1MB_RATE (128 * 1024) | ||
72 | #define IWL_LED_THRESHOLD (16) | ||
73 | #define IWL_MAX_BLINK_TBL (ARRAY_SIZE(blink_tbl) - 1) /* exclude SOLID_ON */ | ||
74 | #define IWL_SOLID_BLINK_IDX (ARRAY_SIZE(blink_tbl) - 1) | ||
75 | |||
76 | /* | 64 | /* |
77 | * Adjust led blink rate to compensate on a MAC Clock difference on every HW | 65 | * Adjust led blink rate to compensate on a MAC Clock difference on every HW |
78 | * Led blink rate analysis showed an average deviation of 0% on 3945, | 66 | * Led blink rate analysis showed an average deviation of 0% on 3945, |
@@ -97,133 +85,104 @@ static inline u8 iwl_blink_compensation(struct iwl_priv *priv, | |||
97 | } | 85 | } |
98 | 86 | ||
99 | /* Set led pattern command */ | 87 | /* Set led pattern command */ |
100 | static int iwl_led_pattern(struct iwl_priv *priv, unsigned int idx) | 88 | static int iwl_led_cmd(struct iwl_priv *priv, |
89 | unsigned long on, | ||
90 | unsigned long off) | ||
101 | { | 91 | { |
102 | struct iwl_led_cmd led_cmd = { | 92 | struct iwl_led_cmd led_cmd = { |
103 | .id = IWL_LED_LINK, | 93 | .id = IWL_LED_LINK, |
104 | .interval = IWL_DEF_LED_INTRVL | 94 | .interval = IWL_DEF_LED_INTRVL |
105 | }; | 95 | }; |
96 | int ret; | ||
106 | 97 | ||
107 | BUG_ON(idx > IWL_MAX_BLINK_TBL); | 98 | if (!test_bit(STATUS_READY, &priv->status)) |
99 | return -EBUSY; | ||
108 | 100 | ||
109 | IWL_DEBUG_LED(priv, "Led blink time compensation= %u\n", | 101 | if (priv->blink_on == on && priv->blink_off == off) |
102 | return 0; | ||
103 | |||
104 | IWL_DEBUG_LED(priv, "Led blink time compensation=%u\n", | ||
110 | priv->cfg->base_params->led_compensation); | 105 | priv->cfg->base_params->led_compensation); |
111 | led_cmd.on = | 106 | led_cmd.on = iwl_blink_compensation(priv, on, |
112 | iwl_blink_compensation(priv, blink_tbl[idx].on_time, | ||
113 | priv->cfg->base_params->led_compensation); | 107 | priv->cfg->base_params->led_compensation); |
114 | led_cmd.off = | 108 | led_cmd.off = iwl_blink_compensation(priv, off, |
115 | iwl_blink_compensation(priv, blink_tbl[idx].off_time, | ||
116 | priv->cfg->base_params->led_compensation); | 109 | priv->cfg->base_params->led_compensation); |
117 | 110 | ||
118 | return priv->cfg->ops->led->cmd(priv, &led_cmd); | 111 | ret = priv->cfg->ops->led->cmd(priv, &led_cmd); |
112 | if (!ret) { | ||
113 | priv->blink_on = on; | ||
114 | priv->blink_off = off; | ||
115 | } | ||
116 | return ret; | ||
119 | } | 117 | } |
120 | 118 | ||
121 | int iwl_led_start(struct iwl_priv *priv) | 119 | static void iwl_led_brightness_set(struct led_classdev *led_cdev, |
120 | enum led_brightness brightness) | ||
122 | { | 121 | { |
123 | return priv->cfg->ops->led->on(priv); | 122 | struct iwl_priv *priv = container_of(led_cdev, struct iwl_priv, led); |
124 | } | 123 | unsigned long on = 0; |
125 | EXPORT_SYMBOL(iwl_led_start); | ||
126 | 124 | ||
127 | int iwl_led_associate(struct iwl_priv *priv) | 125 | if (brightness > 0) |
128 | { | 126 | on = IWL_LED_SOLID; |
129 | IWL_DEBUG_LED(priv, "Associated\n"); | ||
130 | if (priv->cfg->led_mode == IWL_LED_BLINK) | ||
131 | priv->allow_blinking = 1; | ||
132 | priv->last_blink_time = jiffies; | ||
133 | 127 | ||
134 | return 0; | 128 | iwl_led_cmd(priv, on, 0); |
135 | } | 129 | } |
136 | EXPORT_SYMBOL(iwl_led_associate); | ||
137 | 130 | ||
138 | int iwl_led_disassociate(struct iwl_priv *priv) | 131 | static int iwl_led_blink_set(struct led_classdev *led_cdev, |
132 | unsigned long *delay_on, | ||
133 | unsigned long *delay_off) | ||
139 | { | 134 | { |
140 | priv->allow_blinking = 0; | 135 | struct iwl_priv *priv = container_of(led_cdev, struct iwl_priv, led); |
141 | 136 | ||
142 | return 0; | 137 | return iwl_led_cmd(priv, *delay_on, *delay_off); |
143 | } | 138 | } |
144 | EXPORT_SYMBOL(iwl_led_disassociate); | ||
145 | 139 | ||
146 | /* | 140 | void iwl_leds_init(struct iwl_priv *priv) |
147 | * calculate blink rate according to last second Tx/Rx activities | ||
148 | */ | ||
149 | static int iwl_get_blink_rate(struct iwl_priv *priv) | ||
150 | { | ||
151 | int i; | ||
152 | /* count both tx and rx traffic to be able to | ||
153 | * handle traffic in either direction | ||
154 | */ | ||
155 | u64 current_tpt = priv->tx_stats.data_bytes + | ||
156 | priv->rx_stats.data_bytes; | ||
157 | s64 tpt = current_tpt - priv->led_tpt; | ||
158 | |||
159 | if (tpt < 0) /* wraparound */ | ||
160 | tpt = -tpt; | ||
161 | |||
162 | IWL_DEBUG_LED(priv, "tpt %lld current_tpt %llu\n", | ||
163 | (long long)tpt, | ||
164 | (unsigned long long)current_tpt); | ||
165 | priv->led_tpt = current_tpt; | ||
166 | |||
167 | if (!priv->allow_blinking) | ||
168 | i = IWL_MAX_BLINK_TBL; | ||
169 | else | ||
170 | for (i = 0; i < IWL_MAX_BLINK_TBL; i++) | ||
171 | if (tpt > (blink_tbl[i].tpt * IWL_1MB_RATE)) | ||
172 | break; | ||
173 | |||
174 | IWL_DEBUG_LED(priv, "LED BLINK IDX=%d\n", i); | ||
175 | return i; | ||
176 | } | ||
177 | |||
178 | /* | ||
179 | * this function called from handler. Since setting Led command can | ||
180 | * happen very frequent we postpone led command to be called from | ||
181 | * REPLY handler so we know ucode is up | ||
182 | */ | ||
183 | void iwl_leds_background(struct iwl_priv *priv) | ||
184 | { | 141 | { |
185 | u8 blink_idx; | 142 | int mode = led_mode; |
186 | 143 | int ret; | |
187 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { | 144 | |
188 | priv->last_blink_time = 0; | 145 | if (mode == IWL_LED_DEFAULT) |
189 | return; | 146 | mode = priv->cfg->led_mode; |
190 | } | 147 | |
191 | if (iwl_is_rfkill(priv)) { | 148 | priv->led.name = kasprintf(GFP_KERNEL, "%s-led", |
192 | priv->last_blink_time = 0; | 149 | wiphy_name(priv->hw->wiphy)); |
193 | return; | 150 | priv->led.brightness_set = iwl_led_brightness_set; |
151 | priv->led.blink_set = iwl_led_blink_set; | ||
152 | priv->led.max_brightness = 1; | ||
153 | |||
154 | switch (mode) { | ||
155 | case IWL_LED_DEFAULT: | ||
156 | WARN_ON(1); | ||
157 | break; | ||
158 | case IWL_LED_BLINK: | ||
159 | priv->led.default_trigger = | ||
160 | ieee80211_create_tpt_led_trigger(priv->hw, | ||
161 | IEEE80211_TPT_LEDTRIG_FL_CONNECTED, | ||
162 | iwl_blink, ARRAY_SIZE(iwl_blink)); | ||
163 | break; | ||
164 | case IWL_LED_RF_STATE: | ||
165 | priv->led.default_trigger = | ||
166 | ieee80211_get_radio_led_name(priv->hw); | ||
167 | break; | ||
194 | } | 168 | } |
195 | 169 | ||
196 | if (!priv->allow_blinking) { | 170 | ret = led_classdev_register(&priv->pci_dev->dev, &priv->led); |
197 | priv->last_blink_time = 0; | 171 | if (ret) { |
198 | if (priv->last_blink_rate != IWL_SOLID_BLINK_IDX) { | 172 | kfree(priv->led.name); |
199 | priv->last_blink_rate = IWL_SOLID_BLINK_IDX; | ||
200 | iwl_led_pattern(priv, IWL_SOLID_BLINK_IDX); | ||
201 | } | ||
202 | return; | 173 | return; |
203 | } | 174 | } |
204 | if (!priv->last_blink_time || | ||
205 | !time_after(jiffies, priv->last_blink_time + | ||
206 | msecs_to_jiffies(1000))) | ||
207 | return; | ||
208 | |||
209 | blink_idx = iwl_get_blink_rate(priv); | ||
210 | 175 | ||
211 | /* call only if blink rate change */ | 176 | priv->led_registered = true; |
212 | if (blink_idx != priv->last_blink_rate) | ||
213 | iwl_led_pattern(priv, blink_idx); | ||
214 | |||
215 | priv->last_blink_time = jiffies; | ||
216 | priv->last_blink_rate = blink_idx; | ||
217 | } | 177 | } |
218 | EXPORT_SYMBOL(iwl_leds_background); | 178 | EXPORT_SYMBOL(iwl_leds_init); |
219 | 179 | ||
220 | void iwl_leds_init(struct iwl_priv *priv) | 180 | void iwl_leds_exit(struct iwl_priv *priv) |
221 | { | 181 | { |
222 | priv->last_blink_rate = 0; | 182 | if (!priv->led_registered) |
223 | priv->last_blink_time = 0; | 183 | return; |
224 | priv->allow_blinking = 0; | 184 | |
225 | if (led_mode != IWL_LED_DEFAULT && | 185 | led_classdev_unregister(&priv->led); |
226 | led_mode != priv->cfg->led_mode) | 186 | kfree(priv->led.name); |
227 | priv->cfg->led_mode = led_mode; | ||
228 | } | 187 | } |
229 | EXPORT_SYMBOL(iwl_leds_init); | 188 | EXPORT_SYMBOL(iwl_leds_exit); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-led.h b/drivers/net/wireless/iwlwifi/iwl-led.h index 9079b33486ef..101eef12b3bb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.h +++ b/drivers/net/wireless/iwlwifi/iwl-led.h | |||
@@ -31,23 +31,14 @@ | |||
31 | struct iwl_priv; | 31 | struct iwl_priv; |
32 | 32 | ||
33 | #define IWL_LED_SOLID 11 | 33 | #define IWL_LED_SOLID 11 |
34 | #define IWL_LED_NAME_LEN 31 | ||
35 | #define IWL_DEF_LED_INTRVL cpu_to_le32(1000) | 34 | #define IWL_DEF_LED_INTRVL cpu_to_le32(1000) |
36 | 35 | ||
37 | #define IWL_LED_ACTIVITY (0<<1) | 36 | #define IWL_LED_ACTIVITY (0<<1) |
38 | #define IWL_LED_LINK (1<<1) | 37 | #define IWL_LED_LINK (1<<1) |
39 | 38 | ||
40 | enum led_type { | ||
41 | IWL_LED_TRG_TX, | ||
42 | IWL_LED_TRG_RX, | ||
43 | IWL_LED_TRG_ASSOC, | ||
44 | IWL_LED_TRG_RADIO, | ||
45 | IWL_LED_TRG_MAX, | ||
46 | }; | ||
47 | |||
48 | /* | 39 | /* |
49 | * LED mode | 40 | * LED mode |
50 | * IWL_LED_DEFAULT: use system default | 41 | * IWL_LED_DEFAULT: use device default |
51 | * IWL_LED_RF_STATE: turn LED on/off based on RF state | 42 | * IWL_LED_RF_STATE: turn LED on/off based on RF state |
52 | * LED ON = RF ON | 43 | * LED ON = RF ON |
53 | * LED OFF = RF OFF | 44 | * LED OFF = RF OFF |
@@ -60,9 +51,6 @@ enum iwl_led_mode { | |||
60 | }; | 51 | }; |
61 | 52 | ||
62 | void iwl_leds_init(struct iwl_priv *priv); | 53 | void iwl_leds_init(struct iwl_priv *priv); |
63 | void iwl_leds_background(struct iwl_priv *priv); | 54 | void iwl_leds_exit(struct iwl_priv *priv); |
64 | int iwl_led_start(struct iwl_priv *priv); | ||
65 | int iwl_led_associate(struct iwl_priv *priv); | ||
66 | int iwl_led_disassociate(struct iwl_priv *priv); | ||
67 | 55 | ||
68 | #endif /* __iwl_leds_h__ */ | 56 | #endif /* __iwl_leds_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-legacy.c b/drivers/net/wireless/iwlwifi/iwl-legacy.c index bb1a742a98a0..927fe37a43ab 100644 --- a/drivers/net/wireless/iwlwifi/iwl-legacy.c +++ b/drivers/net/wireless/iwlwifi/iwl-legacy.c | |||
@@ -332,7 +332,6 @@ static inline void iwl_set_no_assoc(struct iwl_priv *priv, | |||
332 | { | 332 | { |
333 | struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); | 333 | struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); |
334 | 334 | ||
335 | iwl_led_disassociate(priv); | ||
336 | /* | 335 | /* |
337 | * inform the ucode that there is no longer an | 336 | * inform the ucode that there is no longer an |
338 | * association and that no more packets should be | 337 | * association and that no more packets should be |
@@ -520,8 +519,6 @@ void iwl_legacy_mac_bss_info_changed(struct ieee80211_hw *hw, | |||
520 | if (bss_conf->assoc) { | 519 | if (bss_conf->assoc) { |
521 | priv->timestamp = bss_conf->timestamp; | 520 | priv->timestamp = bss_conf->timestamp; |
522 | 521 | ||
523 | iwl_led_associate(priv); | ||
524 | |||
525 | if (!iwl_is_rfkill(priv)) | 522 | if (!iwl_is_rfkill(priv)) |
526 | priv->cfg->ops->legacy->post_associate(priv); | 523 | priv->cfg->ops->legacy->post_associate(priv); |
527 | } else | 524 | } else |
@@ -545,7 +542,6 @@ void iwl_legacy_mac_bss_info_changed(struct ieee80211_hw *hw, | |||
545 | memcpy(ctx->staging.bssid_addr, | 542 | memcpy(ctx->staging.bssid_addr, |
546 | bss_conf->bssid, ETH_ALEN); | 543 | bss_conf->bssid, ETH_ALEN); |
547 | memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN); | 544 | memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN); |
548 | iwl_led_associate(priv); | ||
549 | priv->cfg->ops->legacy->config_ap(priv); | 545 | priv->cfg->ops->legacy->config_ap(priv); |
550 | } else | 546 | } else |
551 | iwl_set_no_assoc(priv, vif); | 547 | iwl_set_no_assoc(priv, vif); |
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 371abbf60eac..9c986f272c2d 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
@@ -2540,8 +2540,6 @@ static void iwl3945_alive_start(struct iwl_priv *priv) | |||
2540 | 2540 | ||
2541 | iwl3945_reg_txpower_periodic(priv); | 2541 | iwl3945_reg_txpower_periodic(priv); |
2542 | 2542 | ||
2543 | iwl_leds_init(priv); | ||
2544 | |||
2545 | IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n"); | 2543 | IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n"); |
2546 | set_bit(STATUS_READY, &priv->status); | 2544 | set_bit(STATUS_READY, &priv->status); |
2547 | wake_up_interruptible(&priv->wait_command_queue); | 2545 | wake_up_interruptible(&priv->wait_command_queue); |
@@ -3170,8 +3168,6 @@ static int iwl3945_mac_start(struct ieee80211_hw *hw) | |||
3170 | * no need to poll the killswitch state anymore */ | 3168 | * no need to poll the killswitch state anymore */ |
3171 | cancel_delayed_work(&priv->_3945.rfkill_poll); | 3169 | cancel_delayed_work(&priv->_3945.rfkill_poll); |
3172 | 3170 | ||
3173 | iwl_led_start(priv); | ||
3174 | |||
3175 | priv->is_open = 1; | 3171 | priv->is_open = 1; |
3176 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 3172 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
3177 | return 0; | 3173 | return 0; |
@@ -3935,6 +3931,8 @@ static int iwl3945_setup_mac(struct iwl_priv *priv) | |||
3935 | priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = | 3931 | priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = |
3936 | &priv->bands[IEEE80211_BAND_5GHZ]; | 3932 | &priv->bands[IEEE80211_BAND_5GHZ]; |
3937 | 3933 | ||
3934 | iwl_leds_init(priv); | ||
3935 | |||
3938 | ret = ieee80211_register_hw(priv->hw); | 3936 | ret = ieee80211_register_hw(priv->hw); |
3939 | if (ret) { | 3937 | if (ret) { |
3940 | IWL_ERR(priv, "Failed to register hw (error %d)\n", ret); | 3938 | IWL_ERR(priv, "Failed to register hw (error %d)\n", ret); |
@@ -4194,6 +4192,8 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) | |||
4194 | 4192 | ||
4195 | set_bit(STATUS_EXIT_PENDING, &priv->status); | 4193 | set_bit(STATUS_EXIT_PENDING, &priv->status); |
4196 | 4194 | ||
4195 | iwl_leds_exit(priv); | ||
4196 | |||
4197 | if (priv->mac80211_registered) { | 4197 | if (priv->mac80211_registered) { |
4198 | ieee80211_unregister_hw(priv->hw); | 4198 | ieee80211_unregister_hw(priv->hw); |
4199 | priv->mac80211_registered = 0; | 4199 | priv->mac80211_registered = 0; |
diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.c b/drivers/net/wireless/iwmc3200wifi/cfg80211.c index 5a4982271e96..ed57e4402800 100644 --- a/drivers/net/wireless/iwmc3200wifi/cfg80211.c +++ b/drivers/net/wireless/iwmc3200wifi/cfg80211.c | |||
@@ -287,7 +287,8 @@ int iwm_cfg80211_inform_bss(struct iwm_priv *iwm) | |||
287 | return -EINVAL; | 287 | return -EINVAL; |
288 | } | 288 | } |
289 | 289 | ||
290 | freq = ieee80211_channel_to_frequency(umac_bss->channel); | 290 | freq = ieee80211_channel_to_frequency(umac_bss->channel, |
291 | band->band); | ||
291 | channel = ieee80211_get_channel(wiphy, freq); | 292 | channel = ieee80211_get_channel(wiphy, freq); |
292 | signal = umac_bss->rssi * 100; | 293 | signal = umac_bss->rssi * 100; |
293 | 294 | ||
diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index a944893ae3ca..9a57cf6a488f 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c | |||
@@ -543,7 +543,10 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, | |||
543 | switch (le32_to_cpu(complete->status)) { | 543 | switch (le32_to_cpu(complete->status)) { |
544 | case UMAC_ASSOC_COMPLETE_SUCCESS: | 544 | case UMAC_ASSOC_COMPLETE_SUCCESS: |
545 | chan = ieee80211_get_channel(wiphy, | 545 | chan = ieee80211_get_channel(wiphy, |
546 | ieee80211_channel_to_frequency(complete->channel)); | 546 | ieee80211_channel_to_frequency(complete->channel, |
547 | complete->band == UMAC_BAND_2GHZ ? | ||
548 | IEEE80211_BAND_2GHZ : | ||
549 | IEEE80211_BAND_5GHZ)); | ||
547 | if (!chan || chan->flags & IEEE80211_CHAN_DISABLED) { | 550 | if (!chan || chan->flags & IEEE80211_CHAN_DISABLED) { |
548 | /* Associated to a unallowed channel, disassociate. */ | 551 | /* Associated to a unallowed channel, disassociate. */ |
549 | __iwm_invalidate_mlme_profile(iwm); | 552 | __iwm_invalidate_mlme_profile(iwm); |
@@ -841,7 +844,7 @@ static int iwm_mlme_update_bss_table(struct iwm_priv *iwm, u8 *buf, | |||
841 | goto err; | 844 | goto err; |
842 | } | 845 | } |
843 | 846 | ||
844 | freq = ieee80211_channel_to_frequency(umac_bss->channel); | 847 | freq = ieee80211_channel_to_frequency(umac_bss->channel, band->band); |
845 | channel = ieee80211_get_channel(wiphy, freq); | 848 | channel = ieee80211_get_channel(wiphy, freq); |
846 | signal = umac_bss->rssi * 100; | 849 | signal = umac_bss->rssi * 100; |
847 | 850 | ||
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c index 698a1f7694ed..30ef0351bfc4 100644 --- a/drivers/net/wireless/libertas/cfg.c +++ b/drivers/net/wireless/libertas/cfg.c | |||
@@ -607,7 +607,8 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy, | |||
607 | /* No channel, no luck */ | 607 | /* No channel, no luck */ |
608 | if (chan_no != -1) { | 608 | if (chan_no != -1) { |
609 | struct wiphy *wiphy = priv->wdev->wiphy; | 609 | struct wiphy *wiphy = priv->wdev->wiphy; |
610 | int freq = ieee80211_channel_to_frequency(chan_no); | 610 | int freq = ieee80211_channel_to_frequency(chan_no, |
611 | IEEE80211_BAND_2GHZ); | ||
611 | struct ieee80211_channel *channel = | 612 | struct ieee80211_channel *channel = |
612 | ieee80211_get_channel(wiphy, freq); | 613 | ieee80211_get_channel(wiphy, freq); |
613 | 614 | ||
@@ -1597,7 +1598,8 @@ static int lbs_get_survey(struct wiphy *wiphy, struct net_device *dev, | |||
1597 | lbs_deb_enter(LBS_DEB_CFG80211); | 1598 | lbs_deb_enter(LBS_DEB_CFG80211); |
1598 | 1599 | ||
1599 | survey->channel = ieee80211_get_channel(wiphy, | 1600 | survey->channel = ieee80211_get_channel(wiphy, |
1600 | ieee80211_channel_to_frequency(priv->channel)); | 1601 | ieee80211_channel_to_frequency(priv->channel, |
1602 | IEEE80211_BAND_2GHZ)); | ||
1601 | 1603 | ||
1602 | ret = lbs_get_rssi(priv, &signal, &noise); | 1604 | ret = lbs_get_rssi(priv, &signal, &noise); |
1603 | if (ret == 0) { | 1605 | if (ret == 0) { |
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 454f045ddff3..5d39b2840584 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -943,7 +943,8 @@ static int mac80211_hwsim_testmode_cmd(struct ieee80211_hw *hw, | |||
943 | static int mac80211_hwsim_ampdu_action(struct ieee80211_hw *hw, | 943 | static int mac80211_hwsim_ampdu_action(struct ieee80211_hw *hw, |
944 | struct ieee80211_vif *vif, | 944 | struct ieee80211_vif *vif, |
945 | enum ieee80211_ampdu_mlme_action action, | 945 | enum ieee80211_ampdu_mlme_action action, |
946 | struct ieee80211_sta *sta, u16 tid, u16 *ssn) | 946 | struct ieee80211_sta *sta, u16 tid, u16 *ssn, |
947 | u8 buf_size) | ||
947 | { | 948 | { |
948 | switch (action) { | 949 | switch (action) { |
949 | case IEEE80211_AMPDU_TX_START: | 950 | case IEEE80211_AMPDU_TX_START: |
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 9ecf8407cb1b..af4f2c64f242 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c | |||
@@ -232,6 +232,9 @@ struct mwl8k_priv { | |||
232 | struct completion firmware_loading_complete; | 232 | struct completion firmware_loading_complete; |
233 | }; | 233 | }; |
234 | 234 | ||
235 | #define MAX_WEP_KEY_LEN 13 | ||
236 | #define NUM_WEP_KEYS 4 | ||
237 | |||
235 | /* Per interface specific private data */ | 238 | /* Per interface specific private data */ |
236 | struct mwl8k_vif { | 239 | struct mwl8k_vif { |
237 | struct list_head list; | 240 | struct list_head list; |
@@ -242,8 +245,21 @@ struct mwl8k_vif { | |||
242 | 245 | ||
243 | /* Non AMPDU sequence number assigned by driver. */ | 246 | /* Non AMPDU sequence number assigned by driver. */ |
244 | u16 seqno; | 247 | u16 seqno; |
248 | |||
249 | /* Saved WEP keys */ | ||
250 | struct { | ||
251 | u8 enabled; | ||
252 | u8 key[sizeof(struct ieee80211_key_conf) + MAX_WEP_KEY_LEN]; | ||
253 | } wep_key_conf[NUM_WEP_KEYS]; | ||
254 | |||
255 | /* BSSID */ | ||
256 | u8 bssid[ETH_ALEN]; | ||
257 | |||
258 | /* A flag to indicate is HW crypto is enabled for this bssid */ | ||
259 | bool is_hw_crypto_enabled; | ||
245 | }; | 260 | }; |
246 | #define MWL8K_VIF(_vif) ((struct mwl8k_vif *)&((_vif)->drv_priv)) | 261 | #define MWL8K_VIF(_vif) ((struct mwl8k_vif *)&((_vif)->drv_priv)) |
262 | #define IEEE80211_KEY_CONF(_u8) ((struct ieee80211_key_conf *)(_u8)) | ||
247 | 263 | ||
248 | struct mwl8k_sta { | 264 | struct mwl8k_sta { |
249 | /* Index into station database. Returned by UPDATE_STADB. */ | 265 | /* Index into station database. Returned by UPDATE_STADB. */ |
@@ -337,6 +353,7 @@ static const struct ieee80211_rate mwl8k_rates_50[] = { | |||
337 | #define MWL8K_CMD_SET_RATEADAPT_MODE 0x0203 | 353 | #define MWL8K_CMD_SET_RATEADAPT_MODE 0x0203 |
338 | #define MWL8K_CMD_BSS_START 0x1100 /* per-vif */ | 354 | #define MWL8K_CMD_BSS_START 0x1100 /* per-vif */ |
339 | #define MWL8K_CMD_SET_NEW_STN 0x1111 /* per-vif */ | 355 | #define MWL8K_CMD_SET_NEW_STN 0x1111 /* per-vif */ |
356 | #define MWL8K_CMD_UPDATE_ENCRYPTION 0x1122 /* per-vif */ | ||
340 | #define MWL8K_CMD_UPDATE_STADB 0x1123 | 357 | #define MWL8K_CMD_UPDATE_STADB 0x1123 |
341 | 358 | ||
342 | static const char *mwl8k_cmd_name(__le16 cmd, char *buf, int bufsize) | 359 | static const char *mwl8k_cmd_name(__le16 cmd, char *buf, int bufsize) |
@@ -375,6 +392,7 @@ static const char *mwl8k_cmd_name(__le16 cmd, char *buf, int bufsize) | |||
375 | MWL8K_CMDNAME(SET_RATEADAPT_MODE); | 392 | MWL8K_CMDNAME(SET_RATEADAPT_MODE); |
376 | MWL8K_CMDNAME(BSS_START); | 393 | MWL8K_CMDNAME(BSS_START); |
377 | MWL8K_CMDNAME(SET_NEW_STN); | 394 | MWL8K_CMDNAME(SET_NEW_STN); |
395 | MWL8K_CMDNAME(UPDATE_ENCRYPTION); | ||
378 | MWL8K_CMDNAME(UPDATE_STADB); | 396 | MWL8K_CMDNAME(UPDATE_STADB); |
379 | default: | 397 | default: |
380 | snprintf(buf, bufsize, "0x%x", cmd); | 398 | snprintf(buf, bufsize, "0x%x", cmd); |
@@ -715,10 +733,12 @@ static inline void mwl8k_remove_dma_header(struct sk_buff *skb, __le16 qos) | |||
715 | skb_pull(skb, sizeof(*tr) - hdrlen); | 733 | skb_pull(skb, sizeof(*tr) - hdrlen); |
716 | } | 734 | } |
717 | 735 | ||
718 | static inline void mwl8k_add_dma_header(struct sk_buff *skb) | 736 | static void |
737 | mwl8k_add_dma_header(struct sk_buff *skb, int tail_pad) | ||
719 | { | 738 | { |
720 | struct ieee80211_hdr *wh; | 739 | struct ieee80211_hdr *wh; |
721 | int hdrlen; | 740 | int hdrlen; |
741 | int reqd_hdrlen; | ||
722 | struct mwl8k_dma_data *tr; | 742 | struct mwl8k_dma_data *tr; |
723 | 743 | ||
724 | /* | 744 | /* |
@@ -730,11 +750,13 @@ static inline void mwl8k_add_dma_header(struct sk_buff *skb) | |||
730 | wh = (struct ieee80211_hdr *)skb->data; | 750 | wh = (struct ieee80211_hdr *)skb->data; |
731 | 751 | ||
732 | hdrlen = ieee80211_hdrlen(wh->frame_control); | 752 | hdrlen = ieee80211_hdrlen(wh->frame_control); |
733 | if (hdrlen != sizeof(*tr)) | 753 | reqd_hdrlen = sizeof(*tr); |
734 | skb_push(skb, sizeof(*tr) - hdrlen); | 754 | |
755 | if (hdrlen != reqd_hdrlen) | ||
756 | skb_push(skb, reqd_hdrlen - hdrlen); | ||
735 | 757 | ||
736 | if (ieee80211_is_data_qos(wh->frame_control)) | 758 | if (ieee80211_is_data_qos(wh->frame_control)) |
737 | hdrlen -= 2; | 759 | hdrlen -= IEEE80211_QOS_CTL_LEN; |
738 | 760 | ||
739 | tr = (struct mwl8k_dma_data *)skb->data; | 761 | tr = (struct mwl8k_dma_data *)skb->data; |
740 | if (wh != &tr->wh) | 762 | if (wh != &tr->wh) |
@@ -747,9 +769,52 @@ static inline void mwl8k_add_dma_header(struct sk_buff *skb) | |||
747 | * payload". That is, everything except for the 802.11 header. | 769 | * payload". That is, everything except for the 802.11 header. |
748 | * This includes all crypto material including the MIC. | 770 | * This includes all crypto material including the MIC. |
749 | */ | 771 | */ |
750 | tr->fwlen = cpu_to_le16(skb->len - sizeof(*tr)); | 772 | tr->fwlen = cpu_to_le16(skb->len - sizeof(*tr) + tail_pad); |
751 | } | 773 | } |
752 | 774 | ||
775 | static void mwl8k_encapsulate_tx_frame(struct sk_buff *skb) | ||
776 | { | ||
777 | struct ieee80211_hdr *wh; | ||
778 | struct ieee80211_tx_info *tx_info; | ||
779 | struct ieee80211_key_conf *key_conf; | ||
780 | int data_pad; | ||
781 | |||
782 | wh = (struct ieee80211_hdr *)skb->data; | ||
783 | |||
784 | tx_info = IEEE80211_SKB_CB(skb); | ||
785 | |||
786 | key_conf = NULL; | ||
787 | if (ieee80211_is_data(wh->frame_control)) | ||
788 | key_conf = tx_info->control.hw_key; | ||
789 | |||
790 | /* | ||
791 | * Make sure the packet header is in the DMA header format (4-address | ||
792 | * without QoS), the necessary crypto padding between the header and the | ||
793 | * payload has already been provided by mac80211, but it doesn't add tail | ||
794 | * padding when HW crypto is enabled. | ||
795 | * | ||
796 | * We have the following trailer padding requirements: | ||
797 | * - WEP: 4 trailer bytes (ICV) | ||
798 | * - TKIP: 12 trailer bytes (8 MIC + 4 ICV) | ||
799 | * - CCMP: 8 trailer bytes (MIC) | ||
800 | */ | ||
801 | data_pad = 0; | ||
802 | if (key_conf != NULL) { | ||
803 | switch (key_conf->cipher) { | ||
804 | case WLAN_CIPHER_SUITE_WEP40: | ||
805 | case WLAN_CIPHER_SUITE_WEP104: | ||
806 | data_pad = 4; | ||
807 | break; | ||
808 | case WLAN_CIPHER_SUITE_TKIP: | ||
809 | data_pad = 12; | ||
810 | break; | ||
811 | case WLAN_CIPHER_SUITE_CCMP: | ||
812 | data_pad = 8; | ||
813 | break; | ||
814 | } | ||
815 | } | ||
816 | mwl8k_add_dma_header(skb, data_pad); | ||
817 | } | ||
753 | 818 | ||
754 | /* | 819 | /* |
755 | * Packet reception for 88w8366 AP firmware. | 820 | * Packet reception for 88w8366 AP firmware. |
@@ -778,6 +843,13 @@ struct mwl8k_rxd_8366_ap { | |||
778 | 843 | ||
779 | #define MWL8K_8366_AP_RX_CTRL_OWNED_BY_HOST 0x80 | 844 | #define MWL8K_8366_AP_RX_CTRL_OWNED_BY_HOST 0x80 |
780 | 845 | ||
846 | /* 8366 AP rx_status bits */ | ||
847 | #define MWL8K_8366_AP_RXSTAT_DECRYPT_ERR_MASK 0x80 | ||
848 | #define MWL8K_8366_AP_RXSTAT_GENERAL_DECRYPT_ERR 0xFF | ||
849 | #define MWL8K_8366_AP_RXSTAT_TKIP_DECRYPT_MIC_ERR 0x02 | ||
850 | #define MWL8K_8366_AP_RXSTAT_WEP_DECRYPT_ICV_ERR 0x04 | ||
851 | #define MWL8K_8366_AP_RXSTAT_TKIP_DECRYPT_ICV_ERR 0x08 | ||
852 | |||
781 | static void mwl8k_rxd_8366_ap_init(void *_rxd, dma_addr_t next_dma_addr) | 853 | static void mwl8k_rxd_8366_ap_init(void *_rxd, dma_addr_t next_dma_addr) |
782 | { | 854 | { |
783 | struct mwl8k_rxd_8366_ap *rxd = _rxd; | 855 | struct mwl8k_rxd_8366_ap *rxd = _rxd; |
@@ -834,10 +906,16 @@ mwl8k_rxd_8366_ap_process(void *_rxd, struct ieee80211_rx_status *status, | |||
834 | } else { | 906 | } else { |
835 | status->band = IEEE80211_BAND_2GHZ; | 907 | status->band = IEEE80211_BAND_2GHZ; |
836 | } | 908 | } |
837 | status->freq = ieee80211_channel_to_frequency(rxd->channel); | 909 | status->freq = ieee80211_channel_to_frequency(rxd->channel, |
910 | status->band); | ||
838 | 911 | ||
839 | *qos = rxd->qos_control; | 912 | *qos = rxd->qos_control; |
840 | 913 | ||
914 | if ((rxd->rx_status != MWL8K_8366_AP_RXSTAT_GENERAL_DECRYPT_ERR) && | ||
915 | (rxd->rx_status & MWL8K_8366_AP_RXSTAT_DECRYPT_ERR_MASK) && | ||
916 | (rxd->rx_status & MWL8K_8366_AP_RXSTAT_TKIP_DECRYPT_MIC_ERR)) | ||
917 | status->flag |= RX_FLAG_MMIC_ERROR; | ||
918 | |||
841 | return le16_to_cpu(rxd->pkt_len); | 919 | return le16_to_cpu(rxd->pkt_len); |
842 | } | 920 | } |
843 | 921 | ||
@@ -876,6 +954,11 @@ struct mwl8k_rxd_sta { | |||
876 | #define MWL8K_STA_RATE_INFO_MCS_FORMAT 0x0001 | 954 | #define MWL8K_STA_RATE_INFO_MCS_FORMAT 0x0001 |
877 | 955 | ||
878 | #define MWL8K_STA_RX_CTRL_OWNED_BY_HOST 0x02 | 956 | #define MWL8K_STA_RX_CTRL_OWNED_BY_HOST 0x02 |
957 | #define MWL8K_STA_RX_CTRL_DECRYPT_ERROR 0x04 | ||
958 | /* ICV=0 or MIC=1 */ | ||
959 | #define MWL8K_STA_RX_CTRL_DEC_ERR_TYPE 0x08 | ||
960 | /* Key is uploaded only in failure case */ | ||
961 | #define MWL8K_STA_RX_CTRL_KEY_INDEX 0x30 | ||
879 | 962 | ||
880 | static void mwl8k_rxd_sta_init(void *_rxd, dma_addr_t next_dma_addr) | 963 | static void mwl8k_rxd_sta_init(void *_rxd, dma_addr_t next_dma_addr) |
881 | { | 964 | { |
@@ -931,9 +1014,13 @@ mwl8k_rxd_sta_process(void *_rxd, struct ieee80211_rx_status *status, | |||
931 | } else { | 1014 | } else { |
932 | status->band = IEEE80211_BAND_2GHZ; | 1015 | status->band = IEEE80211_BAND_2GHZ; |
933 | } | 1016 | } |
934 | status->freq = ieee80211_channel_to_frequency(rxd->channel); | 1017 | status->freq = ieee80211_channel_to_frequency(rxd->channel, |
1018 | status->band); | ||
935 | 1019 | ||
936 | *qos = rxd->qos_control; | 1020 | *qos = rxd->qos_control; |
1021 | if ((rxd->rx_ctrl & MWL8K_STA_RX_CTRL_DECRYPT_ERROR) && | ||
1022 | (rxd->rx_ctrl & MWL8K_STA_RX_CTRL_DEC_ERR_TYPE)) | ||
1023 | status->flag |= RX_FLAG_MMIC_ERROR; | ||
937 | 1024 | ||
938 | return le16_to_cpu(rxd->pkt_len); | 1025 | return le16_to_cpu(rxd->pkt_len); |
939 | } | 1026 | } |
@@ -1092,9 +1179,25 @@ static inline void mwl8k_save_beacon(struct ieee80211_hw *hw, | |||
1092 | ieee80211_queue_work(hw, &priv->finalize_join_worker); | 1179 | ieee80211_queue_work(hw, &priv->finalize_join_worker); |
1093 | } | 1180 | } |
1094 | 1181 | ||
1182 | static inline struct mwl8k_vif *mwl8k_find_vif_bss(struct list_head *vif_list, | ||
1183 | u8 *bssid) | ||
1184 | { | ||
1185 | struct mwl8k_vif *mwl8k_vif; | ||
1186 | |||
1187 | list_for_each_entry(mwl8k_vif, | ||
1188 | vif_list, list) { | ||
1189 | if (memcmp(bssid, mwl8k_vif->bssid, | ||
1190 | ETH_ALEN) == 0) | ||
1191 | return mwl8k_vif; | ||
1192 | } | ||
1193 | |||
1194 | return NULL; | ||
1195 | } | ||
1196 | |||
1095 | static int rxq_process(struct ieee80211_hw *hw, int index, int limit) | 1197 | static int rxq_process(struct ieee80211_hw *hw, int index, int limit) |
1096 | { | 1198 | { |
1097 | struct mwl8k_priv *priv = hw->priv; | 1199 | struct mwl8k_priv *priv = hw->priv; |
1200 | struct mwl8k_vif *mwl8k_vif = NULL; | ||
1098 | struct mwl8k_rx_queue *rxq = priv->rxq + index; | 1201 | struct mwl8k_rx_queue *rxq = priv->rxq + index; |
1099 | int processed; | 1202 | int processed; |
1100 | 1203 | ||
@@ -1104,6 +1207,7 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit) | |||
1104 | void *rxd; | 1207 | void *rxd; |
1105 | int pkt_len; | 1208 | int pkt_len; |
1106 | struct ieee80211_rx_status status; | 1209 | struct ieee80211_rx_status status; |
1210 | struct ieee80211_hdr *wh; | ||
1107 | __le16 qos; | 1211 | __le16 qos; |
1108 | 1212 | ||
1109 | skb = rxq->buf[rxq->head].skb; | 1213 | skb = rxq->buf[rxq->head].skb; |
@@ -1130,8 +1234,7 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit) | |||
1130 | 1234 | ||
1131 | rxq->rxd_count--; | 1235 | rxq->rxd_count--; |
1132 | 1236 | ||
1133 | skb_put(skb, pkt_len); | 1237 | wh = &((struct mwl8k_dma_data *)skb->data)->wh; |
1134 | mwl8k_remove_dma_header(skb, qos); | ||
1135 | 1238 | ||
1136 | /* | 1239 | /* |
1137 | * Check for a pending join operation. Save a | 1240 | * Check for a pending join operation. Save a |
@@ -1141,6 +1244,46 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit) | |||
1141 | if (mwl8k_capture_bssid(priv, (void *)skb->data)) | 1244 | if (mwl8k_capture_bssid(priv, (void *)skb->data)) |
1142 | mwl8k_save_beacon(hw, skb); | 1245 | mwl8k_save_beacon(hw, skb); |
1143 | 1246 | ||
1247 | if (ieee80211_has_protected(wh->frame_control)) { | ||
1248 | |||
1249 | /* Check if hw crypto has been enabled for | ||
1250 | * this bss. If yes, set the status flags | ||
1251 | * accordingly | ||
1252 | */ | ||
1253 | mwl8k_vif = mwl8k_find_vif_bss(&priv->vif_list, | ||
1254 | wh->addr1); | ||
1255 | |||
1256 | if (mwl8k_vif != NULL && | ||
1257 | mwl8k_vif->is_hw_crypto_enabled == true) { | ||
1258 | /* | ||
1259 | * When MMIC ERROR is encountered | ||
1260 | * by the firmware, payload is | ||
1261 | * dropped and only 32 bytes of | ||
1262 | * mwl8k Firmware header is sent | ||
1263 | * to the host. | ||
1264 | * | ||
1265 | * We need to add four bytes of | ||
1266 | * key information. In it | ||
1267 | * MAC80211 expects keyidx set to | ||
1268 | * 0 for triggering Counter | ||
1269 | * Measure of MMIC failure. | ||
1270 | */ | ||
1271 | if (status.flag & RX_FLAG_MMIC_ERROR) { | ||
1272 | struct mwl8k_dma_data *tr; | ||
1273 | tr = (struct mwl8k_dma_data *)skb->data; | ||
1274 | memset((void *)&(tr->data), 0, 4); | ||
1275 | pkt_len += 4; | ||
1276 | } | ||
1277 | |||
1278 | if (!ieee80211_is_auth(wh->frame_control)) | ||
1279 | status.flag |= RX_FLAG_IV_STRIPPED | | ||
1280 | RX_FLAG_DECRYPTED | | ||
1281 | RX_FLAG_MMIC_STRIPPED; | ||
1282 | } | ||
1283 | } | ||
1284 | |||
1285 | skb_put(skb, pkt_len); | ||
1286 | mwl8k_remove_dma_header(skb, qos); | ||
1144 | memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); | 1287 | memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); |
1145 | ieee80211_rx_irqsafe(hw, skb); | 1288 | ieee80211_rx_irqsafe(hw, skb); |
1146 | 1289 | ||
@@ -1443,7 +1586,11 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) | |||
1443 | else | 1586 | else |
1444 | qos = 0; | 1587 | qos = 0; |
1445 | 1588 | ||
1446 | mwl8k_add_dma_header(skb); | 1589 | if (priv->ap_fw) |
1590 | mwl8k_encapsulate_tx_frame(skb); | ||
1591 | else | ||
1592 | mwl8k_add_dma_header(skb, 0); | ||
1593 | |||
1447 | wh = &((struct mwl8k_dma_data *)skb->data)->wh; | 1594 | wh = &((struct mwl8k_dma_data *)skb->data)->wh; |
1448 | 1595 | ||
1449 | tx_info = IEEE80211_SKB_CB(skb); | 1596 | tx_info = IEEE80211_SKB_CB(skb); |
@@ -3099,6 +3246,274 @@ static int mwl8k_cmd_set_new_stn_del(struct ieee80211_hw *hw, | |||
3099 | } | 3246 | } |
3100 | 3247 | ||
3101 | /* | 3248 | /* |
3249 | * CMD_UPDATE_ENCRYPTION. | ||
3250 | */ | ||
3251 | |||
3252 | #define MAX_ENCR_KEY_LENGTH 16 | ||
3253 | #define MIC_KEY_LENGTH 8 | ||
3254 | |||
3255 | struct mwl8k_cmd_update_encryption { | ||
3256 | struct mwl8k_cmd_pkt header; | ||
3257 | |||
3258 | __le32 action; | ||
3259 | __le32 reserved; | ||
3260 | __u8 mac_addr[6]; | ||
3261 | __u8 encr_type; | ||
3262 | |||
3263 | } __attribute__((packed)); | ||
3264 | |||
3265 | struct mwl8k_cmd_set_key { | ||
3266 | struct mwl8k_cmd_pkt header; | ||
3267 | |||
3268 | __le32 action; | ||
3269 | __le32 reserved; | ||
3270 | __le16 length; | ||
3271 | __le16 key_type_id; | ||
3272 | __le32 key_info; | ||
3273 | __le32 key_id; | ||
3274 | __le16 key_len; | ||
3275 | __u8 key_material[MAX_ENCR_KEY_LENGTH]; | ||
3276 | __u8 tkip_tx_mic_key[MIC_KEY_LENGTH]; | ||
3277 | __u8 tkip_rx_mic_key[MIC_KEY_LENGTH]; | ||
3278 | __le16 tkip_rsc_low; | ||
3279 | __le32 tkip_rsc_high; | ||
3280 | __le16 tkip_tsc_low; | ||
3281 | __le32 tkip_tsc_high; | ||
3282 | __u8 mac_addr[6]; | ||
3283 | } __attribute__((packed)); | ||
3284 | |||
3285 | enum { | ||
3286 | MWL8K_ENCR_ENABLE, | ||
3287 | MWL8K_ENCR_SET_KEY, | ||
3288 | MWL8K_ENCR_REMOVE_KEY, | ||
3289 | MWL8K_ENCR_SET_GROUP_KEY, | ||
3290 | }; | ||
3291 | |||
3292 | #define MWL8K_UPDATE_ENCRYPTION_TYPE_WEP 0 | ||
3293 | #define MWL8K_UPDATE_ENCRYPTION_TYPE_DISABLE 1 | ||
3294 | #define MWL8K_UPDATE_ENCRYPTION_TYPE_TKIP 4 | ||
3295 | #define MWL8K_UPDATE_ENCRYPTION_TYPE_MIXED 7 | ||
3296 | #define MWL8K_UPDATE_ENCRYPTION_TYPE_AES 8 | ||
3297 | |||
3298 | enum { | ||
3299 | MWL8K_ALG_WEP, | ||
3300 | MWL8K_ALG_TKIP, | ||
3301 | MWL8K_ALG_CCMP, | ||
3302 | }; | ||
3303 | |||
3304 | #define MWL8K_KEY_FLAG_TXGROUPKEY 0x00000004 | ||
3305 | #define MWL8K_KEY_FLAG_PAIRWISE 0x00000008 | ||
3306 | #define MWL8K_KEY_FLAG_TSC_VALID 0x00000040 | ||
3307 | #define MWL8K_KEY_FLAG_WEP_TXKEY 0x01000000 | ||
3308 | #define MWL8K_KEY_FLAG_MICKEY_VALID 0x02000000 | ||
3309 | |||
3310 | static int mwl8k_cmd_update_encryption_enable(struct ieee80211_hw *hw, | ||
3311 | struct ieee80211_vif *vif, | ||
3312 | u8 *addr, | ||
3313 | u8 encr_type) | ||
3314 | { | ||
3315 | struct mwl8k_cmd_update_encryption *cmd; | ||
3316 | int rc; | ||
3317 | |||
3318 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
3319 | if (cmd == NULL) | ||
3320 | return -ENOMEM; | ||
3321 | |||
3322 | cmd->header.code = cpu_to_le16(MWL8K_CMD_UPDATE_ENCRYPTION); | ||
3323 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | ||
3324 | cmd->action = cpu_to_le32(MWL8K_ENCR_ENABLE); | ||
3325 | memcpy(cmd->mac_addr, addr, ETH_ALEN); | ||
3326 | cmd->encr_type = encr_type; | ||
3327 | |||
3328 | rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header); | ||
3329 | kfree(cmd); | ||
3330 | |||
3331 | return rc; | ||
3332 | } | ||
3333 | |||
3334 | static int mwl8k_encryption_set_cmd_info(struct mwl8k_cmd_set_key *cmd, | ||
3335 | u8 *addr, | ||
3336 | struct ieee80211_key_conf *key) | ||
3337 | { | ||
3338 | cmd->header.code = cpu_to_le16(MWL8K_CMD_UPDATE_ENCRYPTION); | ||
3339 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | ||
3340 | cmd->length = cpu_to_le16(sizeof(*cmd) - | ||
3341 | offsetof(struct mwl8k_cmd_set_key, length)); | ||
3342 | cmd->key_id = cpu_to_le32(key->keyidx); | ||
3343 | cmd->key_len = cpu_to_le16(key->keylen); | ||
3344 | memcpy(cmd->mac_addr, addr, ETH_ALEN); | ||
3345 | |||
3346 | switch (key->cipher) { | ||
3347 | case WLAN_CIPHER_SUITE_WEP40: | ||
3348 | case WLAN_CIPHER_SUITE_WEP104: | ||
3349 | cmd->key_type_id = cpu_to_le16(MWL8K_ALG_WEP); | ||
3350 | if (key->keyidx == 0) | ||
3351 | cmd->key_info = cpu_to_le32(MWL8K_KEY_FLAG_WEP_TXKEY); | ||
3352 | |||
3353 | break; | ||
3354 | case WLAN_CIPHER_SUITE_TKIP: | ||
3355 | cmd->key_type_id = cpu_to_le16(MWL8K_ALG_TKIP); | ||
3356 | cmd->key_info = (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) | ||
3357 | ? cpu_to_le32(MWL8K_KEY_FLAG_PAIRWISE) | ||
3358 | : cpu_to_le32(MWL8K_KEY_FLAG_TXGROUPKEY); | ||
3359 | cmd->key_info |= cpu_to_le32(MWL8K_KEY_FLAG_MICKEY_VALID | ||
3360 | | MWL8K_KEY_FLAG_TSC_VALID); | ||
3361 | break; | ||
3362 | case WLAN_CIPHER_SUITE_CCMP: | ||
3363 | cmd->key_type_id = cpu_to_le16(MWL8K_ALG_CCMP); | ||
3364 | cmd->key_info = (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) | ||
3365 | ? cpu_to_le32(MWL8K_KEY_FLAG_PAIRWISE) | ||
3366 | : cpu_to_le32(MWL8K_KEY_FLAG_TXGROUPKEY); | ||
3367 | break; | ||
3368 | default: | ||
3369 | return -ENOTSUPP; | ||
3370 | } | ||
3371 | |||
3372 | return 0; | ||
3373 | } | ||
3374 | |||
3375 | static int mwl8k_cmd_encryption_set_key(struct ieee80211_hw *hw, | ||
3376 | struct ieee80211_vif *vif, | ||
3377 | u8 *addr, | ||
3378 | struct ieee80211_key_conf *key) | ||
3379 | { | ||
3380 | struct mwl8k_cmd_set_key *cmd; | ||
3381 | int rc; | ||
3382 | int keymlen; | ||
3383 | u32 action; | ||
3384 | u8 idx; | ||
3385 | struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif); | ||
3386 | |||
3387 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
3388 | if (cmd == NULL) | ||
3389 | return -ENOMEM; | ||
3390 | |||
3391 | rc = mwl8k_encryption_set_cmd_info(cmd, addr, key); | ||
3392 | if (rc < 0) | ||
3393 | goto done; | ||
3394 | |||
3395 | idx = key->keyidx; | ||
3396 | |||
3397 | if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) | ||
3398 | action = MWL8K_ENCR_SET_KEY; | ||
3399 | else | ||
3400 | action = MWL8K_ENCR_SET_GROUP_KEY; | ||
3401 | |||
3402 | switch (key->cipher) { | ||
3403 | case WLAN_CIPHER_SUITE_WEP40: | ||
3404 | case WLAN_CIPHER_SUITE_WEP104: | ||
3405 | if (!mwl8k_vif->wep_key_conf[idx].enabled) { | ||
3406 | memcpy(mwl8k_vif->wep_key_conf[idx].key, key, | ||
3407 | sizeof(*key) + key->keylen); | ||
3408 | mwl8k_vif->wep_key_conf[idx].enabled = 1; | ||
3409 | } | ||
3410 | |||
3411 | keymlen = 0; | ||
3412 | action = MWL8K_ENCR_SET_KEY; | ||
3413 | break; | ||
3414 | case WLAN_CIPHER_SUITE_TKIP: | ||
3415 | keymlen = MAX_ENCR_KEY_LENGTH + 2 * MIC_KEY_LENGTH; | ||
3416 | break; | ||
3417 | case WLAN_CIPHER_SUITE_CCMP: | ||
3418 | keymlen = key->keylen; | ||
3419 | break; | ||
3420 | default: | ||
3421 | rc = -ENOTSUPP; | ||
3422 | goto done; | ||
3423 | } | ||
3424 | |||
3425 | memcpy(cmd->key_material, key->key, keymlen); | ||
3426 | cmd->action = cpu_to_le32(action); | ||
3427 | |||
3428 | rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header); | ||
3429 | done: | ||
3430 | kfree(cmd); | ||
3431 | |||
3432 | return rc; | ||
3433 | } | ||
3434 | |||
3435 | static int mwl8k_cmd_encryption_remove_key(struct ieee80211_hw *hw, | ||
3436 | struct ieee80211_vif *vif, | ||
3437 | u8 *addr, | ||
3438 | struct ieee80211_key_conf *key) | ||
3439 | { | ||
3440 | struct mwl8k_cmd_set_key *cmd; | ||
3441 | int rc; | ||
3442 | struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif); | ||
3443 | |||
3444 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
3445 | if (cmd == NULL) | ||
3446 | return -ENOMEM; | ||
3447 | |||
3448 | rc = mwl8k_encryption_set_cmd_info(cmd, addr, key); | ||
3449 | if (rc < 0) | ||
3450 | goto done; | ||
3451 | |||
3452 | if (key->cipher == WLAN_CIPHER_SUITE_WEP40 || | ||
3453 | WLAN_CIPHER_SUITE_WEP104) | ||
3454 | mwl8k_vif->wep_key_conf[key->keyidx].enabled = 0; | ||
3455 | |||
3456 | cmd->action = cpu_to_le32(MWL8K_ENCR_REMOVE_KEY); | ||
3457 | |||
3458 | rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header); | ||
3459 | done: | ||
3460 | kfree(cmd); | ||
3461 | |||
3462 | return rc; | ||
3463 | } | ||
3464 | |||
3465 | static int mwl8k_set_key(struct ieee80211_hw *hw, | ||
3466 | enum set_key_cmd cmd_param, | ||
3467 | struct ieee80211_vif *vif, | ||
3468 | struct ieee80211_sta *sta, | ||
3469 | struct ieee80211_key_conf *key) | ||
3470 | { | ||
3471 | int rc = 0; | ||
3472 | u8 encr_type; | ||
3473 | u8 *addr; | ||
3474 | struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif); | ||
3475 | |||
3476 | if (vif->type == NL80211_IFTYPE_STATION) | ||
3477 | return -EOPNOTSUPP; | ||
3478 | |||
3479 | if (sta == NULL) | ||
3480 | addr = hw->wiphy->perm_addr; | ||
3481 | else | ||
3482 | addr = sta->addr; | ||
3483 | |||
3484 | if (cmd_param == SET_KEY) { | ||
3485 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | ||
3486 | rc = mwl8k_cmd_encryption_set_key(hw, vif, addr, key); | ||
3487 | if (rc) | ||
3488 | goto out; | ||
3489 | |||
3490 | if ((key->cipher == WLAN_CIPHER_SUITE_WEP40) | ||
3491 | || (key->cipher == WLAN_CIPHER_SUITE_WEP104)) | ||
3492 | encr_type = MWL8K_UPDATE_ENCRYPTION_TYPE_WEP; | ||
3493 | else | ||
3494 | encr_type = MWL8K_UPDATE_ENCRYPTION_TYPE_MIXED; | ||
3495 | |||
3496 | rc = mwl8k_cmd_update_encryption_enable(hw, vif, addr, | ||
3497 | encr_type); | ||
3498 | if (rc) | ||
3499 | goto out; | ||
3500 | |||
3501 | mwl8k_vif->is_hw_crypto_enabled = true; | ||
3502 | |||
3503 | } else { | ||
3504 | rc = mwl8k_cmd_encryption_remove_key(hw, vif, addr, key); | ||
3505 | |||
3506 | if (rc) | ||
3507 | goto out; | ||
3508 | |||
3509 | mwl8k_vif->is_hw_crypto_enabled = false; | ||
3510 | |||
3511 | } | ||
3512 | out: | ||
3513 | return rc; | ||
3514 | } | ||
3515 | |||
3516 | /* | ||
3102 | * CMD_UPDATE_STADB. | 3517 | * CMD_UPDATE_STADB. |
3103 | */ | 3518 | */ |
3104 | struct ewc_ht_info { | 3519 | struct ewc_ht_info { |
@@ -3469,6 +3884,8 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw, | |||
3469 | mwl8k_vif->vif = vif; | 3884 | mwl8k_vif->vif = vif; |
3470 | mwl8k_vif->macid = macid; | 3885 | mwl8k_vif->macid = macid; |
3471 | mwl8k_vif->seqno = 0; | 3886 | mwl8k_vif->seqno = 0; |
3887 | memcpy(mwl8k_vif->bssid, vif->addr, ETH_ALEN); | ||
3888 | mwl8k_vif->is_hw_crypto_enabled = false; | ||
3472 | 3889 | ||
3473 | /* Set the mac address. */ | 3890 | /* Set the mac address. */ |
3474 | mwl8k_cmd_set_mac_addr(hw, vif, vif->addr); | 3891 | mwl8k_cmd_set_mac_addr(hw, vif, vif->addr); |
@@ -3866,18 +4283,27 @@ static int mwl8k_sta_add(struct ieee80211_hw *hw, | |||
3866 | { | 4283 | { |
3867 | struct mwl8k_priv *priv = hw->priv; | 4284 | struct mwl8k_priv *priv = hw->priv; |
3868 | int ret; | 4285 | int ret; |
4286 | int i; | ||
4287 | struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif); | ||
4288 | struct ieee80211_key_conf *key; | ||
3869 | 4289 | ||
3870 | if (!priv->ap_fw) { | 4290 | if (!priv->ap_fw) { |
3871 | ret = mwl8k_cmd_update_stadb_add(hw, vif, sta); | 4291 | ret = mwl8k_cmd_update_stadb_add(hw, vif, sta); |
3872 | if (ret >= 0) { | 4292 | if (ret >= 0) { |
3873 | MWL8K_STA(sta)->peer_id = ret; | 4293 | MWL8K_STA(sta)->peer_id = ret; |
3874 | return 0; | 4294 | ret = 0; |
3875 | } | 4295 | } |
3876 | 4296 | ||
3877 | return ret; | 4297 | } else { |
4298 | ret = mwl8k_cmd_set_new_stn_add(hw, vif, sta); | ||
3878 | } | 4299 | } |
3879 | 4300 | ||
3880 | return mwl8k_cmd_set_new_stn_add(hw, vif, sta); | 4301 | for (i = 0; i < NUM_WEP_KEYS; i++) { |
4302 | key = IEEE80211_KEY_CONF(mwl8k_vif->wep_key_conf[i].key); | ||
4303 | if (mwl8k_vif->wep_key_conf[i].enabled) | ||
4304 | mwl8k_set_key(hw, SET_KEY, vif, sta, key); | ||
4305 | } | ||
4306 | return ret; | ||
3881 | } | 4307 | } |
3882 | 4308 | ||
3883 | static int mwl8k_conf_tx(struct ieee80211_hw *hw, u16 queue, | 4309 | static int mwl8k_conf_tx(struct ieee80211_hw *hw, u16 queue, |
@@ -3932,7 +4358,8 @@ static int mwl8k_get_survey(struct ieee80211_hw *hw, int idx, | |||
3932 | static int | 4358 | static int |
3933 | mwl8k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | 4359 | mwl8k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
3934 | enum ieee80211_ampdu_mlme_action action, | 4360 | enum ieee80211_ampdu_mlme_action action, |
3935 | struct ieee80211_sta *sta, u16 tid, u16 *ssn) | 4361 | struct ieee80211_sta *sta, u16 tid, u16 *ssn, |
4362 | u8 buf_size) | ||
3936 | { | 4363 | { |
3937 | switch (action) { | 4364 | switch (action) { |
3938 | case IEEE80211_AMPDU_RX_START: | 4365 | case IEEE80211_AMPDU_RX_START: |
@@ -3955,6 +4382,7 @@ static const struct ieee80211_ops mwl8k_ops = { | |||
3955 | .bss_info_changed = mwl8k_bss_info_changed, | 4382 | .bss_info_changed = mwl8k_bss_info_changed, |
3956 | .prepare_multicast = mwl8k_prepare_multicast, | 4383 | .prepare_multicast = mwl8k_prepare_multicast, |
3957 | .configure_filter = mwl8k_configure_filter, | 4384 | .configure_filter = mwl8k_configure_filter, |
4385 | .set_key = mwl8k_set_key, | ||
3958 | .set_rts_threshold = mwl8k_set_rts_threshold, | 4386 | .set_rts_threshold = mwl8k_set_rts_threshold, |
3959 | .sta_add = mwl8k_sta_add, | 4387 | .sta_add = mwl8k_sta_add, |
3960 | .sta_remove = mwl8k_sta_remove, | 4388 | .sta_remove = mwl8k_sta_remove, |
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index 4c55e8525cad..c7e615cebac1 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h | |||
@@ -1805,6 +1805,12 @@ struct mac_iveiv_entry { | |||
1805 | #define RFCSR30_RF_CALIBRATION FIELD8(0x80) | 1805 | #define RFCSR30_RF_CALIBRATION FIELD8(0x80) |
1806 | 1806 | ||
1807 | /* | 1807 | /* |
1808 | * RFCSR 31: | ||
1809 | */ | ||
1810 | #define RFCSR31_RX_AGC_FC FIELD8(0x1f) | ||
1811 | #define RFCSR31_RX_H20M FIELD8(0x20) | ||
1812 | |||
1813 | /* | ||
1808 | * RF registers | 1814 | * RF registers |
1809 | */ | 1815 | */ |
1810 | 1816 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 54917a281398..f8ba01cbc6dd 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c | |||
@@ -2436,6 +2436,10 @@ static u8 rt2800_init_rx_filter(struct rt2x00_dev *rt2x00dev, | |||
2436 | rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * bw40); | 2436 | rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * bw40); |
2437 | rt2800_bbp_write(rt2x00dev, 4, bbp); | 2437 | rt2800_bbp_write(rt2x00dev, 4, bbp); |
2438 | 2438 | ||
2439 | rt2800_rfcsr_read(rt2x00dev, 31, &rfcsr); | ||
2440 | rt2x00_set_field8(&rfcsr, RFCSR31_RX_H20M, bw40); | ||
2441 | rt2800_rfcsr_write(rt2x00dev, 31, rfcsr); | ||
2442 | |||
2439 | rt2800_rfcsr_read(rt2x00dev, 22, &rfcsr); | 2443 | rt2800_rfcsr_read(rt2x00dev, 22, &rfcsr); |
2440 | rt2x00_set_field8(&rfcsr, RFCSR22_BASEBAND_LOOPBACK, 1); | 2444 | rt2x00_set_field8(&rfcsr, RFCSR22_BASEBAND_LOOPBACK, 1); |
2441 | rt2800_rfcsr_write(rt2x00dev, 22, rfcsr); | 2445 | rt2800_rfcsr_write(rt2x00dev, 22, rfcsr); |
@@ -2510,7 +2514,7 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) | |||
2510 | rt2800_rfcsr_write(rt2x00dev, 4, 0x40); | 2514 | rt2800_rfcsr_write(rt2x00dev, 4, 0x40); |
2511 | rt2800_rfcsr_write(rt2x00dev, 5, 0x03); | 2515 | rt2800_rfcsr_write(rt2x00dev, 5, 0x03); |
2512 | rt2800_rfcsr_write(rt2x00dev, 6, 0x02); | 2516 | rt2800_rfcsr_write(rt2x00dev, 6, 0x02); |
2513 | rt2800_rfcsr_write(rt2x00dev, 7, 0x70); | 2517 | rt2800_rfcsr_write(rt2x00dev, 7, 0x60); |
2514 | rt2800_rfcsr_write(rt2x00dev, 9, 0x0f); | 2518 | rt2800_rfcsr_write(rt2x00dev, 9, 0x0f); |
2515 | rt2800_rfcsr_write(rt2x00dev, 10, 0x41); | 2519 | rt2800_rfcsr_write(rt2x00dev, 10, 0x41); |
2516 | rt2800_rfcsr_write(rt2x00dev, 11, 0x21); | 2520 | rt2800_rfcsr_write(rt2x00dev, 11, 0x21); |
@@ -2602,12 +2606,12 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) | |||
2602 | rt2800_register_write(rt2x00dev, LDO_CFG0, reg); | 2606 | rt2800_register_write(rt2x00dev, LDO_CFG0, reg); |
2603 | } else if (rt2x00_rt(rt2x00dev, RT3071) || | 2607 | } else if (rt2x00_rt(rt2x00dev, RT3071) || |
2604 | rt2x00_rt(rt2x00dev, RT3090)) { | 2608 | rt2x00_rt(rt2x00dev, RT3090)) { |
2609 | rt2800_rfcsr_write(rt2x00dev, 31, 0x14); | ||
2610 | |||
2605 | rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr); | 2611 | rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr); |
2606 | rt2x00_set_field8(&rfcsr, RFCSR6_R2, 1); | 2612 | rt2x00_set_field8(&rfcsr, RFCSR6_R2, 1); |
2607 | rt2800_rfcsr_write(rt2x00dev, 6, rfcsr); | 2613 | rt2800_rfcsr_write(rt2x00dev, 6, rfcsr); |
2608 | 2614 | ||
2609 | rt2800_rfcsr_write(rt2x00dev, 31, 0x14); | ||
2610 | |||
2611 | rt2800_register_read(rt2x00dev, LDO_CFG0, ®); | 2615 | rt2800_register_read(rt2x00dev, LDO_CFG0, ®); |
2612 | rt2x00_set_field32(®, LDO_CFG0_BGSEL, 1); | 2616 | rt2x00_set_field32(®, LDO_CFG0_BGSEL, 1); |
2613 | if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) || | 2617 | if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) || |
@@ -2619,6 +2623,10 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) | |||
2619 | rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 0); | 2623 | rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 0); |
2620 | } | 2624 | } |
2621 | rt2800_register_write(rt2x00dev, LDO_CFG0, reg); | 2625 | rt2800_register_write(rt2x00dev, LDO_CFG0, reg); |
2626 | |||
2627 | rt2800_register_read(rt2x00dev, GPIO_SWITCH, ®); | ||
2628 | rt2x00_set_field32(®, GPIO_SWITCH_5, 0); | ||
2629 | rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg); | ||
2622 | } else if (rt2x00_rt(rt2x00dev, RT3390)) { | 2630 | } else if (rt2x00_rt(rt2x00dev, RT3390)) { |
2623 | rt2800_register_read(rt2x00dev, GPIO_SWITCH, ®); | 2631 | rt2800_register_read(rt2x00dev, GPIO_SWITCH, ®); |
2624 | rt2x00_set_field32(®, GPIO_SWITCH_5, 0); | 2632 | rt2x00_set_field32(®, GPIO_SWITCH_5, 0); |
@@ -2670,10 +2678,11 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) | |||
2670 | 2678 | ||
2671 | rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr); | 2679 | rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr); |
2672 | rt2x00_set_field8(&rfcsr, RFCSR17_TX_LO1_EN, 0); | 2680 | rt2x00_set_field8(&rfcsr, RFCSR17_TX_LO1_EN, 0); |
2673 | if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) || | 2681 | if (rt2x00_rt(rt2x00dev, RT3070) || |
2682 | rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) || | ||
2674 | rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) || | 2683 | rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) || |
2675 | rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) { | 2684 | rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) { |
2676 | if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) | 2685 | if (!test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) |
2677 | rt2x00_set_field8(&rfcsr, RFCSR17_R, 1); | 2686 | rt2x00_set_field8(&rfcsr, RFCSR17_R, 1); |
2678 | } | 2687 | } |
2679 | rt2x00_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &eeprom); | 2688 | rt2x00_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &eeprom); |
@@ -2686,6 +2695,7 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) | |||
2686 | if (rt2x00_rt(rt2x00dev, RT3090)) { | 2695 | if (rt2x00_rt(rt2x00dev, RT3090)) { |
2687 | rt2800_bbp_read(rt2x00dev, 138, &bbp); | 2696 | rt2800_bbp_read(rt2x00dev, 138, &bbp); |
2688 | 2697 | ||
2698 | /* Turn off unused DAC1 and ADC1 to reduce power consumption */ | ||
2689 | rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom); | 2699 | rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom); |
2690 | if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) == 1) | 2700 | if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) == 1) |
2691 | rt2x00_set_field8(&bbp, BBP138_RX_ADC1, 0); | 2701 | rt2x00_set_field8(&bbp, BBP138_RX_ADC1, 0); |
@@ -2719,10 +2729,9 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) | |||
2719 | rt2800_rfcsr_write(rt2x00dev, 21, rfcsr); | 2729 | rt2800_rfcsr_write(rt2x00dev, 21, rfcsr); |
2720 | } | 2730 | } |
2721 | 2731 | ||
2722 | if (rt2x00_rt(rt2x00dev, RT3070) || rt2x00_rt(rt2x00dev, RT3071)) { | 2732 | if (rt2x00_rt(rt2x00dev, RT3070)) { |
2723 | rt2800_rfcsr_read(rt2x00dev, 27, &rfcsr); | 2733 | rt2800_rfcsr_read(rt2x00dev, 27, &rfcsr); |
2724 | if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F) || | 2734 | if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) |
2725 | rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E)) | ||
2726 | rt2x00_set_field8(&rfcsr, RFCSR27_R1, 3); | 2735 | rt2x00_set_field8(&rfcsr, RFCSR27_R1, 3); |
2727 | else | 2736 | else |
2728 | rt2x00_set_field8(&rfcsr, RFCSR27_R1, 0); | 2737 | rt2x00_set_field8(&rfcsr, RFCSR27_R1, 0); |
@@ -2810,10 +2819,7 @@ void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev) | |||
2810 | 2819 | ||
2811 | rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); | 2820 | rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); |
2812 | rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0); | 2821 | rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0); |
2813 | rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_DMA_BUSY, 0); | ||
2814 | rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0); | 2822 | rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0); |
2815 | rt2x00_set_field32(®, WPDMA_GLO_CFG_RX_DMA_BUSY, 0); | ||
2816 | rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1); | ||
2817 | rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); | 2823 | rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); |
2818 | 2824 | ||
2819 | /* Wait for DMA, ignore error */ | 2825 | /* Wait for DMA, ignore error */ |
@@ -2823,9 +2829,6 @@ void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev) | |||
2823 | rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_TX, 0); | 2829 | rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_TX, 0); |
2824 | rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 0); | 2830 | rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 0); |
2825 | rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); | 2831 | rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); |
2826 | |||
2827 | rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0); | ||
2828 | rt2800_register_write(rt2x00dev, TX_PIN_CFG, 0); | ||
2829 | } | 2832 | } |
2830 | EXPORT_SYMBOL_GPL(rt2800_disable_radio); | 2833 | EXPORT_SYMBOL_GPL(rt2800_disable_radio); |
2831 | 2834 | ||
@@ -3530,7 +3533,8 @@ EXPORT_SYMBOL_GPL(rt2800_get_tsf); | |||
3530 | 3533 | ||
3531 | int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | 3534 | int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
3532 | enum ieee80211_ampdu_mlme_action action, | 3535 | enum ieee80211_ampdu_mlme_action action, |
3533 | struct ieee80211_sta *sta, u16 tid, u16 *ssn) | 3536 | struct ieee80211_sta *sta, u16 tid, u16 *ssn, |
3537 | u8 buf_size) | ||
3534 | { | 3538 | { |
3535 | int ret = 0; | 3539 | int ret = 0; |
3536 | 3540 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h index e3c995a9dec4..3efafb78ff77 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.h +++ b/drivers/net/wireless/rt2x00/rt2800lib.h | |||
@@ -198,7 +198,8 @@ int rt2800_conf_tx(struct ieee80211_hw *hw, u16 queue_idx, | |||
198 | u64 rt2800_get_tsf(struct ieee80211_hw *hw); | 198 | u64 rt2800_get_tsf(struct ieee80211_hw *hw); |
199 | int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | 199 | int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
200 | enum ieee80211_ampdu_mlme_action action, | 200 | enum ieee80211_ampdu_mlme_action action, |
201 | struct ieee80211_sta *sta, u16 tid, u16 *ssn); | 201 | struct ieee80211_sta *sta, u16 tid, u16 *ssn, |
202 | u8 buf_size); | ||
202 | int rt2800_get_survey(struct ieee80211_hw *hw, int idx, | 203 | int rt2800_get_survey(struct ieee80211_hw *hw, int idx, |
203 | struct survey_info *survey); | 204 | struct survey_info *survey); |
204 | 205 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index aa97971a38af..bfc2fc5c1c22 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c | |||
@@ -475,39 +475,23 @@ static int rt2800pci_enable_radio(struct rt2x00_dev *rt2x00dev) | |||
475 | 475 | ||
476 | static void rt2800pci_disable_radio(struct rt2x00_dev *rt2x00dev) | 476 | static void rt2800pci_disable_radio(struct rt2x00_dev *rt2x00dev) |
477 | { | 477 | { |
478 | u32 reg; | 478 | if (rt2x00_is_soc(rt2x00dev)) { |
479 | 479 | rt2800_disable_radio(rt2x00dev); | |
480 | rt2800_disable_radio(rt2x00dev); | 480 | rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0); |
481 | 481 | rt2800_register_write(rt2x00dev, TX_PIN_CFG, 0); | |
482 | rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001280); | 482 | } |
483 | |||
484 | rt2800_register_read(rt2x00dev, WPDMA_RST_IDX, ®); | ||
485 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX0, 1); | ||
486 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX1, 1); | ||
487 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX2, 1); | ||
488 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX3, 1); | ||
489 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX4, 1); | ||
490 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX5, 1); | ||
491 | rt2x00_set_field32(®, WPDMA_RST_IDX_DRX_IDX0, 1); | ||
492 | rt2800_register_write(rt2x00dev, WPDMA_RST_IDX, reg); | ||
493 | |||
494 | rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f); | ||
495 | rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00); | ||
496 | } | 483 | } |
497 | 484 | ||
498 | static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev, | 485 | static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev, |
499 | enum dev_state state) | 486 | enum dev_state state) |
500 | { | 487 | { |
501 | /* | ||
502 | * Always put the device to sleep (even when we intend to wakeup!) | ||
503 | * if the device is booting and wasn't asleep it will return | ||
504 | * failure when attempting to wakeup. | ||
505 | */ | ||
506 | rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0xff, 2); | ||
507 | |||
508 | if (state == STATE_AWAKE) { | 488 | if (state == STATE_AWAKE) { |
509 | rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKUP, 0, 0); | 489 | rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKUP, 0, 0x02); |
510 | rt2800pci_mcu_status(rt2x00dev, TOKEN_WAKUP); | 490 | rt2800pci_mcu_status(rt2x00dev, TOKEN_WAKUP); |
491 | } else if (state == STATE_SLEEP) { | ||
492 | rt2800_register_write(rt2x00dev, H2M_MAILBOX_STATUS, 0xffffffff); | ||
493 | rt2800_register_write(rt2x00dev, H2M_MAILBOX_CID, 0xffffffff); | ||
494 | rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0x01, 0xff, 0x01); | ||
511 | } | 495 | } |
512 | 496 | ||
513 | return 0; | 497 | return 0; |
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 9597a03242cc..31b7db05abd9 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c | |||
@@ -649,7 +649,10 @@ static void rt2x00lib_channel(struct ieee80211_channel *entry, | |||
649 | const int channel, const int tx_power, | 649 | const int channel, const int tx_power, |
650 | const int value) | 650 | const int value) |
651 | { | 651 | { |
652 | entry->center_freq = ieee80211_channel_to_frequency(channel); | 652 | /* XXX: this assumption about the band is wrong for 802.11j */ |
653 | entry->band = channel <= 14 ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; | ||
654 | entry->center_freq = ieee80211_channel_to_frequency(channel, | ||
655 | entry->band); | ||
653 | entry->hw_value = value; | 656 | entry->hw_value = value; |
654 | entry->max_power = tx_power; | 657 | entry->max_power = tx_power; |
655 | entry->max_antenna_gain = 0xff; | 658 | entry->max_antenna_gain = 0xff; |
diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c index d6a924a05654..25d2d667ffba 100644 --- a/drivers/net/wireless/rtlwifi/core.c +++ b/drivers/net/wireless/rtlwifi/core.c | |||
@@ -748,7 +748,8 @@ static void rtl_op_sta_notify(struct ieee80211_hw *hw, | |||
748 | static int rtl_op_ampdu_action(struct ieee80211_hw *hw, | 748 | static int rtl_op_ampdu_action(struct ieee80211_hw *hw, |
749 | struct ieee80211_vif *vif, | 749 | struct ieee80211_vif *vif, |
750 | enum ieee80211_ampdu_mlme_action action, | 750 | enum ieee80211_ampdu_mlme_action action, |
751 | struct ieee80211_sta *sta, u16 tid, u16 * ssn) | 751 | struct ieee80211_sta *sta, u16 tid, u16 *ssn, |
752 | u8 buf_size) | ||
752 | { | 753 | { |
753 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 754 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
754 | 755 | ||
diff --git a/drivers/net/wireless/wl1251/rx.c b/drivers/net/wireless/wl1251/rx.c index efa53607d5c9..86eef456d7b2 100644 --- a/drivers/net/wireless/wl1251/rx.c +++ b/drivers/net/wireless/wl1251/rx.c | |||
@@ -78,7 +78,8 @@ static void wl1251_rx_status(struct wl1251 *wl, | |||
78 | */ | 78 | */ |
79 | wl->noise = desc->rssi - desc->snr / 2; | 79 | wl->noise = desc->rssi - desc->snr / 2; |
80 | 80 | ||
81 | status->freq = ieee80211_channel_to_frequency(desc->channel); | 81 | status->freq = ieee80211_channel_to_frequency(desc->channel, |
82 | status->band); | ||
82 | 83 | ||
83 | status->flag |= RX_FLAG_TSFT; | 84 | status->flag |= RX_FLAG_TSFT; |
84 | 85 | ||
diff --git a/drivers/net/wireless/wl12xx/rx.c b/drivers/net/wireless/wl12xx/rx.c index 682304c30b81..ec8d843d41cf 100644 --- a/drivers/net/wireless/wl12xx/rx.c +++ b/drivers/net/wireless/wl12xx/rx.c | |||
@@ -76,7 +76,7 @@ static void wl1271_rx_status(struct wl1271 *wl, | |||
76 | */ | 76 | */ |
77 | wl->noise = desc->rssi - (desc->snr >> 1); | 77 | wl->noise = desc->rssi - (desc->snr >> 1); |
78 | 78 | ||
79 | status->freq = ieee80211_channel_to_frequency(desc->channel); | 79 | status->freq = ieee80211_channel_to_frequency(desc->channel, desc_band); |
80 | 80 | ||
81 | if (desc->flags & WL1271_RX_DESC_ENCRYPT_MASK) { | 81 | if (desc->flags & WL1271_RX_DESC_ENCRYPT_MASK) { |
82 | status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED; | 82 | status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED; |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 1322695beb52..679a0494b5f2 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -1790,8 +1790,9 @@ static inline void *wdev_priv(struct wireless_dev *wdev) | |||
1790 | /** | 1790 | /** |
1791 | * ieee80211_channel_to_frequency - convert channel number to frequency | 1791 | * ieee80211_channel_to_frequency - convert channel number to frequency |
1792 | * @chan: channel number | 1792 | * @chan: channel number |
1793 | * @band: band, necessary due to channel number overlap | ||
1793 | */ | 1794 | */ |
1794 | extern int ieee80211_channel_to_frequency(int chan); | 1795 | extern int ieee80211_channel_to_frequency(int chan, enum ieee80211_band band); |
1795 | 1796 | ||
1796 | /** | 1797 | /** |
1797 | * ieee80211_frequency_to_channel - convert frequency to channel number | 1798 | * ieee80211_frequency_to_channel - convert frequency to channel number |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 62c0ce2d1dc8..d6b0045788ce 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -1147,6 +1147,17 @@ enum ieee80211_hw_flags { | |||
1147 | * @napi_weight: weight used for NAPI polling. You must specify an | 1147 | * @napi_weight: weight used for NAPI polling. You must specify an |
1148 | * appropriate value here if a napi_poll operation is provided | 1148 | * appropriate value here if a napi_poll operation is provided |
1149 | * by your driver. | 1149 | * by your driver. |
1150 | |||
1151 | * @max_rx_aggregation_subframes: maximum buffer size (number of | ||
1152 | * sub-frames) to be used for A-MPDU block ack receiver | ||
1153 | * aggregation. | ||
1154 | * This is only relevant if the device has restrictions on the | ||
1155 | * number of subframes, if it relies on mac80211 to do reordering | ||
1156 | * it shouldn't be set. | ||
1157 | * | ||
1158 | * @max_tx_aggregation_subframes: maximum number of subframes in an | ||
1159 | * aggregate an HT driver will transmit, used by the peer as a | ||
1160 | * hint to size its reorder buffer. | ||
1150 | */ | 1161 | */ |
1151 | struct ieee80211_hw { | 1162 | struct ieee80211_hw { |
1152 | struct ieee80211_conf conf; | 1163 | struct ieee80211_conf conf; |
@@ -1165,6 +1176,8 @@ struct ieee80211_hw { | |||
1165 | u8 max_rates; | 1176 | u8 max_rates; |
1166 | u8 max_report_rates; | 1177 | u8 max_report_rates; |
1167 | u8 max_rate_tries; | 1178 | u8 max_rate_tries; |
1179 | u8 max_rx_aggregation_subframes; | ||
1180 | u8 max_tx_aggregation_subframes; | ||
1168 | }; | 1181 | }; |
1169 | 1182 | ||
1170 | /** | 1183 | /** |
@@ -1723,6 +1736,10 @@ enum ieee80211_ampdu_mlme_action { | |||
1723 | * ieee80211_ampdu_mlme_action. Starting sequence number (@ssn) | 1736 | * ieee80211_ampdu_mlme_action. Starting sequence number (@ssn) |
1724 | * is the first frame we expect to perform the action on. Notice | 1737 | * is the first frame we expect to perform the action on. Notice |
1725 | * that TX/RX_STOP can pass NULL for this parameter. | 1738 | * that TX/RX_STOP can pass NULL for this parameter. |
1739 | * The @buf_size parameter is only valid when the action is set to | ||
1740 | * %IEEE80211_AMPDU_TX_OPERATIONAL and indicates the peer's reorder | ||
1741 | * buffer size (number of subframes) for this session -- aggregates | ||
1742 | * containing more subframes than this may not be transmitted to the peer. | ||
1726 | * Returns a negative error code on failure. | 1743 | * Returns a negative error code on failure. |
1727 | * The callback can sleep. | 1744 | * The callback can sleep. |
1728 | * | 1745 | * |
@@ -1825,7 +1842,8 @@ struct ieee80211_ops { | |||
1825 | int (*ampdu_action)(struct ieee80211_hw *hw, | 1842 | int (*ampdu_action)(struct ieee80211_hw *hw, |
1826 | struct ieee80211_vif *vif, | 1843 | struct ieee80211_vif *vif, |
1827 | enum ieee80211_ampdu_mlme_action action, | 1844 | enum ieee80211_ampdu_mlme_action action, |
1828 | struct ieee80211_sta *sta, u16 tid, u16 *ssn); | 1845 | struct ieee80211_sta *sta, u16 tid, u16 *ssn, |
1846 | u8 buf_size); | ||
1829 | int (*get_survey)(struct ieee80211_hw *hw, int idx, | 1847 | int (*get_survey)(struct ieee80211_hw *hw, int idx, |
1830 | struct survey_info *survey); | 1848 | struct survey_info *survey); |
1831 | void (*rfkill_poll)(struct ieee80211_hw *hw); | 1849 | void (*rfkill_poll)(struct ieee80211_hw *hw); |
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 227ca82eef72..0c9d0c07eae6 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c | |||
@@ -76,7 +76,7 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | |||
76 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 76 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
77 | 77 | ||
78 | if (drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_STOP, | 78 | if (drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_STOP, |
79 | &sta->sta, tid, NULL)) | 79 | &sta->sta, tid, NULL, 0)) |
80 | printk(KERN_DEBUG "HW problem - can not stop rx " | 80 | printk(KERN_DEBUG "HW problem - can not stop rx " |
81 | "aggregation for tid %d\n", tid); | 81 | "aggregation for tid %d\n", tid); |
82 | 82 | ||
@@ -232,6 +232,9 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
232 | if (buf_size == 0) | 232 | if (buf_size == 0) |
233 | buf_size = IEEE80211_MAX_AMPDU_BUF; | 233 | buf_size = IEEE80211_MAX_AMPDU_BUF; |
234 | 234 | ||
235 | /* make sure the size doesn't exceed the maximum supported by the hw */ | ||
236 | if (buf_size > local->hw.max_rx_aggregation_subframes) | ||
237 | buf_size = local->hw.max_rx_aggregation_subframes; | ||
235 | 238 | ||
236 | /* examine state machine */ | 239 | /* examine state machine */ |
237 | mutex_lock(&sta->ampdu_mlme.mtx); | 240 | mutex_lock(&sta->ampdu_mlme.mtx); |
@@ -287,7 +290,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
287 | } | 290 | } |
288 | 291 | ||
289 | ret = drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_START, | 292 | ret = drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_START, |
290 | &sta->sta, tid, &start_seq_num); | 293 | &sta->sta, tid, &start_seq_num, 0); |
291 | #ifdef CONFIG_MAC80211_HT_DEBUG | 294 | #ifdef CONFIG_MAC80211_HT_DEBUG |
292 | printk(KERN_DEBUG "Rx A-MPDU request on tid %d result %d\n", tid, ret); | 295 | printk(KERN_DEBUG "Rx A-MPDU request on tid %d result %d\n", tid, ret); |
293 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 296 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 9cc472c6a6a5..63d852cb4ca2 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
@@ -190,7 +190,7 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | |||
190 | 190 | ||
191 | ret = drv_ampdu_action(local, sta->sdata, | 191 | ret = drv_ampdu_action(local, sta->sdata, |
192 | IEEE80211_AMPDU_TX_STOP, | 192 | IEEE80211_AMPDU_TX_STOP, |
193 | &sta->sta, tid, NULL); | 193 | &sta->sta, tid, NULL, 0); |
194 | 194 | ||
195 | /* HW shall not deny going back to legacy */ | 195 | /* HW shall not deny going back to legacy */ |
196 | if (WARN_ON(ret)) { | 196 | if (WARN_ON(ret)) { |
@@ -311,7 +311,7 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) | |||
311 | start_seq_num = sta->tid_seq[tid] >> 4; | 311 | start_seq_num = sta->tid_seq[tid] >> 4; |
312 | 312 | ||
313 | ret = drv_ampdu_action(local, sdata, IEEE80211_AMPDU_TX_START, | 313 | ret = drv_ampdu_action(local, sdata, IEEE80211_AMPDU_TX_START, |
314 | &sta->sta, tid, &start_seq_num); | 314 | &sta->sta, tid, &start_seq_num, 0); |
315 | if (ret) { | 315 | if (ret) { |
316 | #ifdef CONFIG_MAC80211_HT_DEBUG | 316 | #ifdef CONFIG_MAC80211_HT_DEBUG |
317 | printk(KERN_DEBUG "BA request denied - HW unavailable for" | 317 | printk(KERN_DEBUG "BA request denied - HW unavailable for" |
@@ -342,7 +342,8 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) | |||
342 | /* send AddBA request */ | 342 | /* send AddBA request */ |
343 | ieee80211_send_addba_request(sdata, sta->sta.addr, tid, | 343 | ieee80211_send_addba_request(sdata, sta->sta.addr, tid, |
344 | tid_tx->dialog_token, start_seq_num, | 344 | tid_tx->dialog_token, start_seq_num, |
345 | 0x40, tid_tx->timeout); | 345 | local->hw.max_tx_aggregation_subframes, |
346 | tid_tx->timeout); | ||
346 | } | 347 | } |
347 | 348 | ||
348 | int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, | 349 | int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, |
@@ -487,7 +488,8 @@ static void ieee80211_agg_tx_operational(struct ieee80211_local *local, | |||
487 | 488 | ||
488 | drv_ampdu_action(local, sta->sdata, | 489 | drv_ampdu_action(local, sta->sdata, |
489 | IEEE80211_AMPDU_TX_OPERATIONAL, | 490 | IEEE80211_AMPDU_TX_OPERATIONAL, |
490 | &sta->sta, tid, NULL); | 491 | &sta->sta, tid, NULL, |
492 | sta->ampdu_mlme.tid_tx[tid]->buf_size); | ||
491 | 493 | ||
492 | /* | 494 | /* |
493 | * synchronize with TX path, while splicing the TX path | 495 | * synchronize with TX path, while splicing the TX path |
@@ -742,9 +744,11 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, | |||
742 | { | 744 | { |
743 | struct tid_ampdu_tx *tid_tx; | 745 | struct tid_ampdu_tx *tid_tx; |
744 | u16 capab, tid; | 746 | u16 capab, tid; |
747 | u8 buf_size; | ||
745 | 748 | ||
746 | capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab); | 749 | capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab); |
747 | tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; | 750 | tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; |
751 | buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6; | ||
748 | 752 | ||
749 | mutex_lock(&sta->ampdu_mlme.mtx); | 753 | mutex_lock(&sta->ampdu_mlme.mtx); |
750 | 754 | ||
@@ -767,12 +771,23 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, | |||
767 | 771 | ||
768 | if (le16_to_cpu(mgmt->u.action.u.addba_resp.status) | 772 | if (le16_to_cpu(mgmt->u.action.u.addba_resp.status) |
769 | == WLAN_STATUS_SUCCESS) { | 773 | == WLAN_STATUS_SUCCESS) { |
774 | /* | ||
775 | * IEEE 802.11-2007 7.3.1.14: | ||
776 | * In an ADDBA Response frame, when the Status Code field | ||
777 | * is set to 0, the Buffer Size subfield is set to a value | ||
778 | * of at least 1. | ||
779 | */ | ||
780 | if (!buf_size) | ||
781 | goto out; | ||
782 | |||
770 | if (test_and_set_bit(HT_AGG_STATE_RESPONSE_RECEIVED, | 783 | if (test_and_set_bit(HT_AGG_STATE_RESPONSE_RECEIVED, |
771 | &tid_tx->state)) { | 784 | &tid_tx->state)) { |
772 | /* ignore duplicate response */ | 785 | /* ignore duplicate response */ |
773 | goto out; | 786 | goto out; |
774 | } | 787 | } |
775 | 788 | ||
789 | tid_tx->buf_size = buf_size; | ||
790 | |||
776 | if (test_bit(HT_AGG_STATE_DRV_READY, &tid_tx->state)) | 791 | if (test_bit(HT_AGG_STATE_DRV_READY, &tid_tx->state)) |
777 | ieee80211_agg_tx_operational(local, sta, tid); | 792 | ieee80211_agg_tx_operational(local, sta, tid); |
778 | 793 | ||
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 98d589960a49..78af32d4bc58 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -382,17 +382,17 @@ static inline int drv_ampdu_action(struct ieee80211_local *local, | |||
382 | struct ieee80211_sub_if_data *sdata, | 382 | struct ieee80211_sub_if_data *sdata, |
383 | enum ieee80211_ampdu_mlme_action action, | 383 | enum ieee80211_ampdu_mlme_action action, |
384 | struct ieee80211_sta *sta, u16 tid, | 384 | struct ieee80211_sta *sta, u16 tid, |
385 | u16 *ssn) | 385 | u16 *ssn, u8 buf_size) |
386 | { | 386 | { |
387 | int ret = -EOPNOTSUPP; | 387 | int ret = -EOPNOTSUPP; |
388 | 388 | ||
389 | might_sleep(); | 389 | might_sleep(); |
390 | 390 | ||
391 | trace_drv_ampdu_action(local, sdata, action, sta, tid, ssn); | 391 | trace_drv_ampdu_action(local, sdata, action, sta, tid, ssn, buf_size); |
392 | 392 | ||
393 | if (local->ops->ampdu_action) | 393 | if (local->ops->ampdu_action) |
394 | ret = local->ops->ampdu_action(&local->hw, &sdata->vif, action, | 394 | ret = local->ops->ampdu_action(&local->hw, &sdata->vif, action, |
395 | sta, tid, ssn); | 395 | sta, tid, ssn, buf_size); |
396 | 396 | ||
397 | trace_drv_return_int(local, ret); | 397 | trace_drv_return_int(local, ret); |
398 | 398 | ||
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index 49c84218b2f4..e5cce19a7d65 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h | |||
@@ -9,6 +9,11 @@ | |||
9 | #undef TRACE_EVENT | 9 | #undef TRACE_EVENT |
10 | #define TRACE_EVENT(name, proto, ...) \ | 10 | #define TRACE_EVENT(name, proto, ...) \ |
11 | static inline void trace_ ## name(proto) {} | 11 | static inline void trace_ ## name(proto) {} |
12 | #undef DECLARE_EVENT_CLASS | ||
13 | #define DECLARE_EVENT_CLASS(...) | ||
14 | #undef DEFINE_EVENT | ||
15 | #define DEFINE_EVENT(evt_class, name, proto, ...) \ | ||
16 | static inline void trace_ ## name(proto) {} | ||
12 | #endif | 17 | #endif |
13 | 18 | ||
14 | #undef TRACE_SYSTEM | 19 | #undef TRACE_SYSTEM |
@@ -38,7 +43,7 @@ static inline void trace_ ## name(proto) {} | |||
38 | * Tracing for driver callbacks. | 43 | * Tracing for driver callbacks. |
39 | */ | 44 | */ |
40 | 45 | ||
41 | TRACE_EVENT(drv_return_void, | 46 | DECLARE_EVENT_CLASS(local_only_evt, |
42 | TP_PROTO(struct ieee80211_local *local), | 47 | TP_PROTO(struct ieee80211_local *local), |
43 | TP_ARGS(local), | 48 | TP_ARGS(local), |
44 | TP_STRUCT__entry( | 49 | TP_STRUCT__entry( |
@@ -50,6 +55,11 @@ TRACE_EVENT(drv_return_void, | |||
50 | TP_printk(LOCAL_PR_FMT, LOCAL_PR_ARG) | 55 | TP_printk(LOCAL_PR_FMT, LOCAL_PR_ARG) |
51 | ); | 56 | ); |
52 | 57 | ||
58 | DEFINE_EVENT(local_only_evt, drv_return_void, | ||
59 | TP_PROTO(struct ieee80211_local *local), | ||
60 | TP_ARGS(local) | ||
61 | ); | ||
62 | |||
53 | TRACE_EVENT(drv_return_int, | 63 | TRACE_EVENT(drv_return_int, |
54 | TP_PROTO(struct ieee80211_local *local, int ret), | 64 | TP_PROTO(struct ieee80211_local *local, int ret), |
55 | TP_ARGS(local, ret), | 65 | TP_ARGS(local, ret), |
@@ -78,40 +88,14 @@ TRACE_EVENT(drv_return_u64, | |||
78 | TP_printk(LOCAL_PR_FMT " - %llu", LOCAL_PR_ARG, __entry->ret) | 88 | TP_printk(LOCAL_PR_FMT " - %llu", LOCAL_PR_ARG, __entry->ret) |
79 | ); | 89 | ); |
80 | 90 | ||
81 | TRACE_EVENT(drv_start, | 91 | DEFINE_EVENT(local_only_evt, drv_start, |
82 | TP_PROTO(struct ieee80211_local *local), | 92 | TP_PROTO(struct ieee80211_local *local), |
83 | 93 | TP_ARGS(local) | |
84 | TP_ARGS(local), | ||
85 | |||
86 | TP_STRUCT__entry( | ||
87 | LOCAL_ENTRY | ||
88 | ), | ||
89 | |||
90 | TP_fast_assign( | ||
91 | LOCAL_ASSIGN; | ||
92 | ), | ||
93 | |||
94 | TP_printk( | ||
95 | LOCAL_PR_FMT, LOCAL_PR_ARG | ||
96 | ) | ||
97 | ); | 94 | ); |
98 | 95 | ||
99 | TRACE_EVENT(drv_stop, | 96 | DEFINE_EVENT(local_only_evt, drv_stop, |
100 | TP_PROTO(struct ieee80211_local *local), | 97 | TP_PROTO(struct ieee80211_local *local), |
101 | 98 | TP_ARGS(local) | |
102 | TP_ARGS(local), | ||
103 | |||
104 | TP_STRUCT__entry( | ||
105 | LOCAL_ENTRY | ||
106 | ), | ||
107 | |||
108 | TP_fast_assign( | ||
109 | LOCAL_ASSIGN; | ||
110 | ), | ||
111 | |||
112 | TP_printk( | ||
113 | LOCAL_PR_FMT, LOCAL_PR_ARG | ||
114 | ) | ||
115 | ); | 99 | ); |
116 | 100 | ||
117 | TRACE_EVENT(drv_add_interface, | 101 | TRACE_EVENT(drv_add_interface, |
@@ -439,40 +423,14 @@ TRACE_EVENT(drv_hw_scan, | |||
439 | ) | 423 | ) |
440 | ); | 424 | ); |
441 | 425 | ||
442 | TRACE_EVENT(drv_sw_scan_start, | 426 | DEFINE_EVENT(local_only_evt, drv_sw_scan_start, |
443 | TP_PROTO(struct ieee80211_local *local), | 427 | TP_PROTO(struct ieee80211_local *local), |
444 | 428 | TP_ARGS(local) | |
445 | TP_ARGS(local), | ||
446 | |||
447 | TP_STRUCT__entry( | ||
448 | LOCAL_ENTRY | ||
449 | ), | ||
450 | |||
451 | TP_fast_assign( | ||
452 | LOCAL_ASSIGN; | ||
453 | ), | ||
454 | |||
455 | TP_printk( | ||
456 | LOCAL_PR_FMT, LOCAL_PR_ARG | ||
457 | ) | ||
458 | ); | 429 | ); |
459 | 430 | ||
460 | TRACE_EVENT(drv_sw_scan_complete, | 431 | DEFINE_EVENT(local_only_evt, drv_sw_scan_complete, |
461 | TP_PROTO(struct ieee80211_local *local), | 432 | TP_PROTO(struct ieee80211_local *local), |
462 | 433 | TP_ARGS(local) | |
463 | TP_ARGS(local), | ||
464 | |||
465 | TP_STRUCT__entry( | ||
466 | LOCAL_ENTRY | ||
467 | ), | ||
468 | |||
469 | TP_fast_assign( | ||
470 | LOCAL_ASSIGN; | ||
471 | ), | ||
472 | |||
473 | TP_printk( | ||
474 | LOCAL_PR_FMT, LOCAL_PR_ARG | ||
475 | ) | ||
476 | ); | 434 | ); |
477 | 435 | ||
478 | TRACE_EVENT(drv_get_stats, | 436 | TRACE_EVENT(drv_get_stats, |
@@ -702,23 +660,9 @@ TRACE_EVENT(drv_conf_tx, | |||
702 | ) | 660 | ) |
703 | ); | 661 | ); |
704 | 662 | ||
705 | TRACE_EVENT(drv_get_tsf, | 663 | DEFINE_EVENT(local_only_evt, drv_get_tsf, |
706 | TP_PROTO(struct ieee80211_local *local), | 664 | TP_PROTO(struct ieee80211_local *local), |
707 | 665 | TP_ARGS(local) | |
708 | TP_ARGS(local), | ||
709 | |||
710 | TP_STRUCT__entry( | ||
711 | LOCAL_ENTRY | ||
712 | ), | ||
713 | |||
714 | TP_fast_assign( | ||
715 | LOCAL_ASSIGN; | ||
716 | ), | ||
717 | |||
718 | TP_printk( | ||
719 | LOCAL_PR_FMT, | ||
720 | LOCAL_PR_ARG | ||
721 | ) | ||
722 | ); | 666 | ); |
723 | 667 | ||
724 | TRACE_EVENT(drv_set_tsf, | 668 | TRACE_EVENT(drv_set_tsf, |
@@ -742,41 +686,14 @@ TRACE_EVENT(drv_set_tsf, | |||
742 | ) | 686 | ) |
743 | ); | 687 | ); |
744 | 688 | ||
745 | TRACE_EVENT(drv_reset_tsf, | 689 | DEFINE_EVENT(local_only_evt, drv_reset_tsf, |
746 | TP_PROTO(struct ieee80211_local *local), | 690 | TP_PROTO(struct ieee80211_local *local), |
747 | 691 | TP_ARGS(local) | |
748 | TP_ARGS(local), | ||
749 | |||
750 | TP_STRUCT__entry( | ||
751 | LOCAL_ENTRY | ||
752 | ), | ||
753 | |||
754 | TP_fast_assign( | ||
755 | LOCAL_ASSIGN; | ||
756 | ), | ||
757 | |||
758 | TP_printk( | ||
759 | LOCAL_PR_FMT, LOCAL_PR_ARG | ||
760 | ) | ||
761 | ); | 692 | ); |
762 | 693 | ||
763 | TRACE_EVENT(drv_tx_last_beacon, | 694 | DEFINE_EVENT(local_only_evt, drv_tx_last_beacon, |
764 | TP_PROTO(struct ieee80211_local *local), | 695 | TP_PROTO(struct ieee80211_local *local), |
765 | 696 | TP_ARGS(local) | |
766 | TP_ARGS(local), | ||
767 | |||
768 | TP_STRUCT__entry( | ||
769 | LOCAL_ENTRY | ||
770 | ), | ||
771 | |||
772 | TP_fast_assign( | ||
773 | LOCAL_ASSIGN; | ||
774 | ), | ||
775 | |||
776 | TP_printk( | ||
777 | LOCAL_PR_FMT, | ||
778 | LOCAL_PR_ARG | ||
779 | ) | ||
780 | ); | 697 | ); |
781 | 698 | ||
782 | TRACE_EVENT(drv_ampdu_action, | 699 | TRACE_EVENT(drv_ampdu_action, |
@@ -784,9 +701,9 @@ TRACE_EVENT(drv_ampdu_action, | |||
784 | struct ieee80211_sub_if_data *sdata, | 701 | struct ieee80211_sub_if_data *sdata, |
785 | enum ieee80211_ampdu_mlme_action action, | 702 | enum ieee80211_ampdu_mlme_action action, |
786 | struct ieee80211_sta *sta, u16 tid, | 703 | struct ieee80211_sta *sta, u16 tid, |
787 | u16 *ssn), | 704 | u16 *ssn, u8 buf_size), |
788 | 705 | ||
789 | TP_ARGS(local, sdata, action, sta, tid, ssn), | 706 | TP_ARGS(local, sdata, action, sta, tid, ssn, buf_size), |
790 | 707 | ||
791 | TP_STRUCT__entry( | 708 | TP_STRUCT__entry( |
792 | LOCAL_ENTRY | 709 | LOCAL_ENTRY |
@@ -794,6 +711,7 @@ TRACE_EVENT(drv_ampdu_action, | |||
794 | __field(u32, action) | 711 | __field(u32, action) |
795 | __field(u16, tid) | 712 | __field(u16, tid) |
796 | __field(u16, ssn) | 713 | __field(u16, ssn) |
714 | __field(u8, buf_size) | ||
797 | VIF_ENTRY | 715 | VIF_ENTRY |
798 | ), | 716 | ), |
799 | 717 | ||
@@ -804,11 +722,13 @@ TRACE_EVENT(drv_ampdu_action, | |||
804 | __entry->action = action; | 722 | __entry->action = action; |
805 | __entry->tid = tid; | 723 | __entry->tid = tid; |
806 | __entry->ssn = ssn ? *ssn : 0; | 724 | __entry->ssn = ssn ? *ssn : 0; |
725 | __entry->buf_size = buf_size; | ||
807 | ), | 726 | ), |
808 | 727 | ||
809 | TP_printk( | 728 | TP_printk( |
810 | LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " action:%d tid:%d", | 729 | LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " action:%d tid:%d buf:%d", |
811 | LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->action, __entry->tid | 730 | LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->action, |
731 | __entry->tid, __entry->buf_size | ||
812 | ) | 732 | ) |
813 | ); | 733 | ); |
814 | 734 | ||
@@ -959,22 +879,9 @@ TRACE_EVENT(drv_remain_on_channel, | |||
959 | ) | 879 | ) |
960 | ); | 880 | ); |
961 | 881 | ||
962 | TRACE_EVENT(drv_cancel_remain_on_channel, | 882 | DEFINE_EVENT(local_only_evt, drv_cancel_remain_on_channel, |
963 | TP_PROTO(struct ieee80211_local *local), | 883 | TP_PROTO(struct ieee80211_local *local), |
964 | 884 | TP_ARGS(local) | |
965 | TP_ARGS(local), | ||
966 | |||
967 | TP_STRUCT__entry( | ||
968 | LOCAL_ENTRY | ||
969 | ), | ||
970 | |||
971 | TP_fast_assign( | ||
972 | LOCAL_ASSIGN; | ||
973 | ), | ||
974 | |||
975 | TP_printk( | ||
976 | LOCAL_PR_FMT, LOCAL_PR_ARG | ||
977 | ) | ||
978 | ); | 885 | ); |
979 | 886 | ||
980 | /* | 887 | /* |
@@ -1069,23 +976,9 @@ TRACE_EVENT(api_stop_tx_ba_cb, | |||
1069 | ) | 976 | ) |
1070 | ); | 977 | ); |
1071 | 978 | ||
1072 | TRACE_EVENT(api_restart_hw, | 979 | DEFINE_EVENT(local_only_evt, api_restart_hw, |
1073 | TP_PROTO(struct ieee80211_local *local), | 980 | TP_PROTO(struct ieee80211_local *local), |
1074 | 981 | TP_ARGS(local) | |
1075 | TP_ARGS(local), | ||
1076 | |||
1077 | TP_STRUCT__entry( | ||
1078 | LOCAL_ENTRY | ||
1079 | ), | ||
1080 | |||
1081 | TP_fast_assign( | ||
1082 | LOCAL_ASSIGN; | ||
1083 | ), | ||
1084 | |||
1085 | TP_printk( | ||
1086 | LOCAL_PR_FMT, | ||
1087 | LOCAL_PR_ARG | ||
1088 | ) | ||
1089 | ); | 982 | ); |
1090 | 983 | ||
1091 | TRACE_EVENT(api_beacon_loss, | 984 | TRACE_EVENT(api_beacon_loss, |
@@ -1214,40 +1107,14 @@ TRACE_EVENT(api_chswitch_done, | |||
1214 | ) | 1107 | ) |
1215 | ); | 1108 | ); |
1216 | 1109 | ||
1217 | TRACE_EVENT(api_ready_on_channel, | 1110 | DEFINE_EVENT(local_only_evt, api_ready_on_channel, |
1218 | TP_PROTO(struct ieee80211_local *local), | 1111 | TP_PROTO(struct ieee80211_local *local), |
1219 | 1112 | TP_ARGS(local) | |
1220 | TP_ARGS(local), | ||
1221 | |||
1222 | TP_STRUCT__entry( | ||
1223 | LOCAL_ENTRY | ||
1224 | ), | ||
1225 | |||
1226 | TP_fast_assign( | ||
1227 | LOCAL_ASSIGN; | ||
1228 | ), | ||
1229 | |||
1230 | TP_printk( | ||
1231 | LOCAL_PR_FMT, LOCAL_PR_ARG | ||
1232 | ) | ||
1233 | ); | 1113 | ); |
1234 | 1114 | ||
1235 | TRACE_EVENT(api_remain_on_channel_expired, | 1115 | DEFINE_EVENT(local_only_evt, api_remain_on_channel_expired, |
1236 | TP_PROTO(struct ieee80211_local *local), | 1116 | TP_PROTO(struct ieee80211_local *local), |
1237 | 1117 | TP_ARGS(local) | |
1238 | TP_ARGS(local), | ||
1239 | |||
1240 | TP_STRUCT__entry( | ||
1241 | LOCAL_ENTRY | ||
1242 | ), | ||
1243 | |||
1244 | TP_fast_assign( | ||
1245 | LOCAL_ASSIGN; | ||
1246 | ), | ||
1247 | |||
1248 | TP_printk( | ||
1249 | LOCAL_PR_FMT, LOCAL_PR_ARG | ||
1250 | ) | ||
1251 | ); | 1118 | ); |
1252 | 1119 | ||
1253 | /* | 1120 | /* |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 53c7077ffd4f..775fb63471c4 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -270,7 +270,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
270 | enum ieee80211_band band = rx_status->band; | 270 | enum ieee80211_band band = rx_status->band; |
271 | 271 | ||
272 | if (elems->ds_params && elems->ds_params_len == 1) | 272 | if (elems->ds_params && elems->ds_params_len == 1) |
273 | freq = ieee80211_channel_to_frequency(elems->ds_params[0]); | 273 | freq = ieee80211_channel_to_frequency(elems->ds_params[0], |
274 | band); | ||
274 | else | 275 | else |
275 | freq = rx_status->freq; | 276 | freq = rx_status->freq; |
276 | 277 | ||
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index a46ff06d7cb8..09a27449f3fd 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -554,6 +554,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
554 | local->hw.queues = 1; | 554 | local->hw.queues = 1; |
555 | local->hw.max_rates = 1; | 555 | local->hw.max_rates = 1; |
556 | local->hw.max_report_rates = 0; | 556 | local->hw.max_report_rates = 0; |
557 | local->hw.max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF; | ||
557 | local->hw.conf.long_frame_max_tx_count = wiphy->retry_long; | 558 | local->hw.conf.long_frame_max_tx_count = wiphy->retry_long; |
558 | local->hw.conf.short_frame_max_tx_count = wiphy->retry_short; | 559 | local->hw.conf.short_frame_max_tx_count = wiphy->retry_short; |
559 | local->user_power_level = -1; | 560 | local->user_power_level = -1; |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index ca3af4685b0a..2a57cc02c618 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -574,7 +574,7 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, | |||
574 | &elems); | 574 | &elems); |
575 | 575 | ||
576 | if (elems.ds_params && elems.ds_params_len == 1) | 576 | if (elems.ds_params && elems.ds_params_len == 1) |
577 | freq = ieee80211_channel_to_frequency(elems.ds_params[0]); | 577 | freq = ieee80211_channel_to_frequency(elems.ds_params[0], band); |
578 | else | 578 | else |
579 | freq = rx_status->freq; | 579 | freq = rx_status->freq; |
580 | 580 | ||
@@ -645,7 +645,7 @@ void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata) | |||
645 | if (test_and_clear_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags)) | 645 | if (test_and_clear_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags)) |
646 | mesh_mpath_table_grow(); | 646 | mesh_mpath_table_grow(); |
647 | 647 | ||
648 | if (test_and_clear_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags)) | 648 | if (test_and_clear_bit(MESH_WORK_GROW_MPP_TABLE, &ifmsh->wrkq_flags)) |
649 | mesh_mpp_table_grow(); | 649 | mesh_mpp_table_grow(); |
650 | 650 | ||
651 | if (test_and_clear_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags)) | 651 | if (test_and_clear_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags)) |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 45fbb9e33746..32210695b8b6 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -176,7 +176,7 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | |||
176 | 176 | ||
177 | /* check that channel matches the right operating channel */ | 177 | /* check that channel matches the right operating channel */ |
178 | if (local->hw.conf.channel->center_freq != | 178 | if (local->hw.conf.channel->center_freq != |
179 | ieee80211_channel_to_frequency(hti->control_chan)) | 179 | ieee80211_channel_to_frequency(hti->control_chan, sband->band)) |
180 | enable_ht = false; | 180 | enable_ht = false; |
181 | 181 | ||
182 | if (enable_ht) { | 182 | if (enable_ht) { |
@@ -429,7 +429,8 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
429 | container_of((void *)bss, struct cfg80211_bss, priv); | 429 | container_of((void *)bss, struct cfg80211_bss, priv); |
430 | struct ieee80211_channel *new_ch; | 430 | struct ieee80211_channel *new_ch; |
431 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 431 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
432 | int new_freq = ieee80211_channel_to_frequency(sw_elem->new_ch_num); | 432 | int new_freq = ieee80211_channel_to_frequency(sw_elem->new_ch_num, |
433 | cbss->channel->band); | ||
433 | 434 | ||
434 | ASSERT_MGD_MTX(ifmgd); | 435 | ASSERT_MGD_MTX(ifmgd); |
435 | 436 | ||
@@ -1519,7 +1520,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
1519 | } | 1520 | } |
1520 | 1521 | ||
1521 | if (elems->ds_params && elems->ds_params_len == 1) | 1522 | if (elems->ds_params && elems->ds_params_len == 1) |
1522 | freq = ieee80211_channel_to_frequency(elems->ds_params[0]); | 1523 | freq = ieee80211_channel_to_frequency(elems->ds_params[0], |
1524 | rx_status->band); | ||
1523 | else | 1525 | else |
1524 | freq = rx_status->freq; | 1526 | freq = rx_status->freq; |
1525 | 1527 | ||
@@ -1972,9 +1974,9 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) | |||
1972 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 1974 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
1973 | wiphy_debug(local->hw.wiphy, | 1975 | wiphy_debug(local->hw.wiphy, |
1974 | "%s: No ack for nullfunc frame to" | 1976 | "%s: No ack for nullfunc frame to" |
1975 | " AP %pM, try %d\n", | 1977 | " AP %pM, try %d/%i\n", |
1976 | sdata->name, bssid, | 1978 | sdata->name, bssid, |
1977 | ifmgd->probe_send_count); | 1979 | ifmgd->probe_send_count, max_tries); |
1978 | #endif | 1980 | #endif |
1979 | ieee80211_mgd_probe_ap_send(sdata); | 1981 | ieee80211_mgd_probe_ap_send(sdata); |
1980 | } else { | 1982 | } else { |
@@ -2001,10 +2003,10 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) | |||
2001 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 2003 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
2002 | wiphy_debug(local->hw.wiphy, | 2004 | wiphy_debug(local->hw.wiphy, |
2003 | "%s: No probe response from AP %pM" | 2005 | "%s: No probe response from AP %pM" |
2004 | " after %dms, try %d\n", | 2006 | " after %dms, try %d/%i\n", |
2005 | sdata->name, | 2007 | sdata->name, |
2006 | bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ, | 2008 | bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ, |
2007 | ifmgd->probe_send_count); | 2009 | ifmgd->probe_send_count, max_tries); |
2008 | #endif | 2010 | #endif |
2009 | ieee80211_mgd_probe_ap_send(sdata); | 2011 | ieee80211_mgd_probe_ap_send(sdata); |
2010 | } else { | 2012 | } else { |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index a6701ed87f0d..f36d70f5b062 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -1556,17 +1556,36 @@ __ieee80211_data_to_8023(struct ieee80211_rx_data *rx) | |||
1556 | { | 1556 | { |
1557 | struct ieee80211_sub_if_data *sdata = rx->sdata; | 1557 | struct ieee80211_sub_if_data *sdata = rx->sdata; |
1558 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; | 1558 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; |
1559 | bool check_port_control = false; | ||
1560 | struct ethhdr *ehdr; | ||
1561 | int ret; | ||
1559 | 1562 | ||
1560 | if (ieee80211_has_a4(hdr->frame_control) && | 1563 | if (ieee80211_has_a4(hdr->frame_control) && |
1561 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN && !sdata->u.vlan.sta) | 1564 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN && !sdata->u.vlan.sta) |
1562 | return -1; | 1565 | return -1; |
1563 | 1566 | ||
1567 | if (sdata->vif.type == NL80211_IFTYPE_STATION && | ||
1568 | !!sdata->u.mgd.use_4addr != !!ieee80211_has_a4(hdr->frame_control)) { | ||
1569 | |||
1570 | if (!sdata->u.mgd.use_4addr) | ||
1571 | return -1; | ||
1572 | else | ||
1573 | check_port_control = true; | ||
1574 | } | ||
1575 | |||
1564 | if (is_multicast_ether_addr(hdr->addr1) && | 1576 | if (is_multicast_ether_addr(hdr->addr1) && |
1565 | ((sdata->vif.type == NL80211_IFTYPE_AP_VLAN && sdata->u.vlan.sta) || | 1577 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN && sdata->u.vlan.sta) |
1566 | (sdata->vif.type == NL80211_IFTYPE_STATION && sdata->u.mgd.use_4addr))) | ||
1567 | return -1; | 1578 | return -1; |
1568 | 1579 | ||
1569 | return ieee80211_data_to_8023(rx->skb, sdata->vif.addr, sdata->vif.type); | 1580 | ret = ieee80211_data_to_8023(rx->skb, sdata->vif.addr, sdata->vif.type); |
1581 | if (ret < 0 || !check_port_control) | ||
1582 | return ret; | ||
1583 | |||
1584 | ehdr = (struct ethhdr *) rx->skb->data; | ||
1585 | if (ehdr->h_proto != rx->sdata->control_port_protocol) | ||
1586 | return -1; | ||
1587 | |||
1588 | return 0; | ||
1570 | } | 1589 | } |
1571 | 1590 | ||
1572 | /* | 1591 | /* |
@@ -2692,7 +2711,7 @@ static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx, | |||
2692 | if (!skb) { | 2711 | if (!skb) { |
2693 | if (net_ratelimit()) | 2712 | if (net_ratelimit()) |
2694 | wiphy_debug(local->hw.wiphy, | 2713 | wiphy_debug(local->hw.wiphy, |
2695 | "failed to copy multicast frame for %s\n", | 2714 | "failed to copy skb for %s\n", |
2696 | sdata->name); | 2715 | sdata->name); |
2697 | return true; | 2716 | return true; |
2698 | } | 2717 | } |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index fb274db77e3c..1ef73be76b25 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -196,7 +196,8 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) | |||
196 | ieee802_11_parse_elems(elements, skb->len - baselen, &elems); | 196 | ieee802_11_parse_elems(elements, skb->len - baselen, &elems); |
197 | 197 | ||
198 | if (elems.ds_params && elems.ds_params_len == 1) | 198 | if (elems.ds_params && elems.ds_params_len == 1) |
199 | freq = ieee80211_channel_to_frequency(elems.ds_params[0]); | 199 | freq = ieee80211_channel_to_frequency(elems.ds_params[0], |
200 | rx_status->band); | ||
200 | else | 201 | else |
201 | freq = rx_status->freq; | 202 | freq = rx_status->freq; |
202 | 203 | ||
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index bbdd2a86a94b..ca0b69060ef7 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -82,6 +82,7 @@ enum ieee80211_sta_info_flags { | |||
82 | * @state: session state (see above) | 82 | * @state: session state (see above) |
83 | * @stop_initiator: initiator of a session stop | 83 | * @stop_initiator: initiator of a session stop |
84 | * @tx_stop: TX DelBA frame when stopping | 84 | * @tx_stop: TX DelBA frame when stopping |
85 | * @buf_size: reorder buffer size at receiver | ||
85 | * | 86 | * |
86 | * This structure's lifetime is managed by RCU, assignments to | 87 | * This structure's lifetime is managed by RCU, assignments to |
87 | * the array holding it must hold the aggregation mutex. | 88 | * the array holding it must hold the aggregation mutex. |
@@ -101,6 +102,7 @@ struct tid_ampdu_tx { | |||
101 | u8 dialog_token; | 102 | u8 dialog_token; |
102 | u8 stop_initiator; | 103 | u8 stop_initiator; |
103 | bool tx_stop; | 104 | bool tx_stop; |
105 | u8 buf_size; | ||
104 | }; | 106 | }; |
105 | 107 | ||
106 | /** | 108 | /** |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index b64b42bc774b..ffc67491c38f 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -1750,7 +1750,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1750 | __le16 fc; | 1750 | __le16 fc; |
1751 | struct ieee80211_hdr hdr; | 1751 | struct ieee80211_hdr hdr; |
1752 | struct ieee80211s_hdr mesh_hdr __maybe_unused; | 1752 | struct ieee80211s_hdr mesh_hdr __maybe_unused; |
1753 | struct mesh_path *mppath = NULL; | 1753 | struct mesh_path __maybe_unused *mppath = NULL; |
1754 | const u8 *encaps_data; | 1754 | const u8 *encaps_data; |
1755 | int encaps_len, skip_header_bytes; | 1755 | int encaps_len, skip_header_bytes; |
1756 | int nh_pos, h_pos; | 1756 | int nh_pos, h_pos; |
@@ -1815,19 +1815,19 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1815 | mppath = mpp_path_lookup(skb->data, sdata); | 1815 | mppath = mpp_path_lookup(skb->data, sdata); |
1816 | 1816 | ||
1817 | /* | 1817 | /* |
1818 | * Do not use address extension, if it is a packet from | 1818 | * Use address extension if it is a packet from |
1819 | * the same interface and the destination is not being | 1819 | * another interface or if we know the destination |
1820 | * proxied by any other mest point. | 1820 | * is being proxied by a portal (i.e. portal address |
1821 | * differs from proxied address) | ||
1821 | */ | 1822 | */ |
1822 | if (compare_ether_addr(sdata->vif.addr, | 1823 | if (compare_ether_addr(sdata->vif.addr, |
1823 | skb->data + ETH_ALEN) == 0 && | 1824 | skb->data + ETH_ALEN) == 0 && |
1824 | (!mppath || !compare_ether_addr(mppath->mpp, skb->data))) { | 1825 | !(mppath && compare_ether_addr(mppath->mpp, skb->data))) { |
1825 | hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc, | 1826 | hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc, |
1826 | skb->data, skb->data + ETH_ALEN); | 1827 | skb->data, skb->data + ETH_ALEN); |
1827 | meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, | 1828 | meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, |
1828 | sdata, NULL, NULL); | 1829 | sdata, NULL, NULL); |
1829 | } else { | 1830 | } else { |
1830 | /* packet from other interface */ | ||
1831 | int is_mesh_mcast = 1; | 1831 | int is_mesh_mcast = 1; |
1832 | const u8 *mesh_da; | 1832 | const u8 *mesh_da; |
1833 | 1833 | ||
@@ -2302,6 +2302,11 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2302 | struct ieee80211_mgmt *mgmt; | 2302 | struct ieee80211_mgmt *mgmt; |
2303 | u8 *pos; | 2303 | u8 *pos; |
2304 | 2304 | ||
2305 | #ifdef CONFIG_MAC80211_MESH | ||
2306 | if (!sdata->u.mesh.mesh_id_len) | ||
2307 | goto out; | ||
2308 | #endif | ||
2309 | |||
2305 | /* headroom, head length, tail length and maximum TIM length */ | 2310 | /* headroom, head length, tail length and maximum TIM length */ |
2306 | skb = dev_alloc_skb(local->tx_headroom + 400 + | 2311 | skb = dev_alloc_skb(local->tx_headroom + 400 + |
2307 | sdata->u.mesh.vendor_ie_len); | 2312 | sdata->u.mesh.vendor_ie_len); |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 37693b6ef23a..c565689f0b9f 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -1801,9 +1801,9 @@ void regulatory_hint_disconnect(void) | |||
1801 | 1801 | ||
1802 | static bool freq_is_chan_12_13_14(u16 freq) | 1802 | static bool freq_is_chan_12_13_14(u16 freq) |
1803 | { | 1803 | { |
1804 | if (freq == ieee80211_channel_to_frequency(12) || | 1804 | if (freq == ieee80211_channel_to_frequency(12, IEEE80211_BAND_2GHZ) || |
1805 | freq == ieee80211_channel_to_frequency(13) || | 1805 | freq == ieee80211_channel_to_frequency(13, IEEE80211_BAND_2GHZ) || |
1806 | freq == ieee80211_channel_to_frequency(14)) | 1806 | freq == ieee80211_channel_to_frequency(14, IEEE80211_BAND_2GHZ)) |
1807 | return true; | 1807 | return true; |
1808 | return false; | 1808 | return false; |
1809 | } | 1809 | } |
diff --git a/net/wireless/util.c b/net/wireless/util.c index 7620ae2fcf18..4ed065d8bb51 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -29,29 +29,37 @@ ieee80211_get_response_rate(struct ieee80211_supported_band *sband, | |||
29 | } | 29 | } |
30 | EXPORT_SYMBOL(ieee80211_get_response_rate); | 30 | EXPORT_SYMBOL(ieee80211_get_response_rate); |
31 | 31 | ||
32 | int ieee80211_channel_to_frequency(int chan) | 32 | int ieee80211_channel_to_frequency(int chan, enum ieee80211_band band) |
33 | { | 33 | { |
34 | if (chan < 14) | 34 | /* see 802.11 17.3.8.3.2 and Annex J |
35 | return 2407 + chan * 5; | 35 | * there are overlapping channel numbers in 5GHz and 2GHz bands */ |
36 | 36 | if (band == IEEE80211_BAND_5GHZ) { | |
37 | if (chan == 14) | 37 | if (chan >= 182 && chan <= 196) |
38 | return 2484; | 38 | return 4000 + chan * 5; |
39 | 39 | else | |
40 | /* FIXME: 802.11j 17.3.8.3.2 */ | 40 | return 5000 + chan * 5; |
41 | return (chan + 1000) * 5; | 41 | } else { /* IEEE80211_BAND_2GHZ */ |
42 | if (chan == 14) | ||
43 | return 2484; | ||
44 | else if (chan < 14) | ||
45 | return 2407 + chan * 5; | ||
46 | else | ||
47 | return 0; /* not supported */ | ||
48 | } | ||
42 | } | 49 | } |
43 | EXPORT_SYMBOL(ieee80211_channel_to_frequency); | 50 | EXPORT_SYMBOL(ieee80211_channel_to_frequency); |
44 | 51 | ||
45 | int ieee80211_frequency_to_channel(int freq) | 52 | int ieee80211_frequency_to_channel(int freq) |
46 | { | 53 | { |
54 | /* see 802.11 17.3.8.3.2 and Annex J */ | ||
47 | if (freq == 2484) | 55 | if (freq == 2484) |
48 | return 14; | 56 | return 14; |
49 | 57 | else if (freq < 2484) | |
50 | if (freq < 2484) | ||
51 | return (freq - 2407) / 5; | 58 | return (freq - 2407) / 5; |
52 | 59 | else if (freq >= 4910 && freq <= 4980) | |
53 | /* FIXME: 802.11j 17.3.8.3.2 */ | 60 | return (freq - 4000) / 5; |
54 | return freq/5 - 1000; | 61 | else |
62 | return (freq - 5000) / 5; | ||
55 | } | 63 | } |
56 | EXPORT_SYMBOL(ieee80211_frequency_to_channel); | 64 | EXPORT_SYMBOL(ieee80211_frequency_to_channel); |
57 | 65 | ||
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index 3e5dbd4e4cd5..7f1f4ec49041 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c | |||
@@ -267,9 +267,12 @@ int cfg80211_wext_freq(struct wiphy *wiphy, struct iw_freq *freq) | |||
267 | * -EINVAL for impossible things. | 267 | * -EINVAL for impossible things. |
268 | */ | 268 | */ |
269 | if (freq->e == 0) { | 269 | if (freq->e == 0) { |
270 | enum ieee80211_band band = IEEE80211_BAND_2GHZ; | ||
270 | if (freq->m < 0) | 271 | if (freq->m < 0) |
271 | return 0; | 272 | return 0; |
272 | return ieee80211_channel_to_frequency(freq->m); | 273 | if (freq->m > 14) |
274 | band = IEEE80211_BAND_5GHZ; | ||
275 | return ieee80211_channel_to_frequency(freq->m, band); | ||
273 | } else { | 276 | } else { |
274 | int i, div = 1000000; | 277 | int i, div = 1000000; |
275 | for (i = 0; i < freq->e; i++) | 278 | for (i = 0; i < freq->e; i++) |