diff options
61 files changed, 2215 insertions, 872 deletions
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 78c26fdccad1..d673ab2f6cda 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c | |||
@@ -282,6 +282,34 @@ int ath5k_hw_phy_disable(struct ath5k_hw *ah) | |||
282 | return 0; | 282 | return 0; |
283 | } | 283 | } |
284 | 284 | ||
285 | /* | ||
286 | * Wait for synth to settle | ||
287 | */ | ||
288 | static void ath5k_hw_wait_for_synth(struct ath5k_hw *ah, | ||
289 | struct ieee80211_channel *channel) | ||
290 | { | ||
291 | /* | ||
292 | * On 5211+ read activation -> rx delay | ||
293 | * and use it (100ns steps). | ||
294 | */ | ||
295 | if (ah->ah_version != AR5K_AR5210) { | ||
296 | u32 delay; | ||
297 | delay = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) & | ||
298 | AR5K_PHY_RX_DELAY_M; | ||
299 | delay = (channel->hw_value & CHANNEL_CCK) ? | ||
300 | ((delay << 2) / 22) : (delay / 10); | ||
301 | if (ah->ah_bwmode == AR5K_BWMODE_10MHZ) | ||
302 | delay = delay << 1; | ||
303 | if (ah->ah_bwmode == AR5K_BWMODE_5MHZ) | ||
304 | delay = delay << 2; | ||
305 | /* XXX: /2 on turbo ? Let's be safe | ||
306 | * for now */ | ||
307 | udelay(100 + delay); | ||
308 | } else { | ||
309 | mdelay(1); | ||
310 | } | ||
311 | } | ||
312 | |||
285 | 313 | ||
286 | /**********************\ | 314 | /**********************\ |
287 | * RF Gain optimization * | 315 | * RF Gain optimization * |
@@ -3237,6 +3265,13 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, | |||
3237 | /* Failed */ | 3265 | /* Failed */ |
3238 | if (i >= 100) | 3266 | if (i >= 100) |
3239 | return -EIO; | 3267 | return -EIO; |
3268 | |||
3269 | /* Set channel and wait for synth */ | ||
3270 | ret = ath5k_hw_channel(ah, channel); | ||
3271 | if (ret) | ||
3272 | return ret; | ||
3273 | |||
3274 | ath5k_hw_wait_for_synth(ah, channel); | ||
3240 | } | 3275 | } |
3241 | 3276 | ||
3242 | /* | 3277 | /* |
@@ -3251,13 +3286,53 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, | |||
3251 | if (ret) | 3286 | if (ret) |
3252 | return ret; | 3287 | return ret; |
3253 | 3288 | ||
3289 | /* Write OFDM timings on 5212*/ | ||
3290 | if (ah->ah_version == AR5K_AR5212 && | ||
3291 | channel->hw_value & CHANNEL_OFDM) { | ||
3292 | |||
3293 | ret = ath5k_hw_write_ofdm_timings(ah, channel); | ||
3294 | if (ret) | ||
3295 | return ret; | ||
3296 | |||
3297 | /* Spur info is available only from EEPROM versions | ||
3298 | * greater than 5.3, but the EEPROM routines will use | ||
3299 | * static values for older versions */ | ||
3300 | if (ah->ah_mac_srev >= AR5K_SREV_AR5424) | ||
3301 | ath5k_hw_set_spur_mitigation_filter(ah, | ||
3302 | channel); | ||
3303 | } | ||
3304 | |||
3305 | /* If we used fast channel switching | ||
3306 | * we are done, release RF bus and | ||
3307 | * fire up NF calibration. | ||
3308 | * | ||
3309 | * Note: Only NF calibration due to | ||
3310 | * channel change, not AGC calibration | ||
3311 | * since AGC is still running ! | ||
3312 | */ | ||
3313 | if (fast) { | ||
3314 | /* | ||
3315 | * Release RF Bus grant | ||
3316 | */ | ||
3317 | AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_RFBUS_REQ, | ||
3318 | AR5K_PHY_RFBUS_REQ_REQUEST); | ||
3319 | |||
3320 | /* | ||
3321 | * Start NF calibration | ||
3322 | */ | ||
3323 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, | ||
3324 | AR5K_PHY_AGCCTL_NF); | ||
3325 | |||
3326 | return ret; | ||
3327 | } | ||
3328 | |||
3254 | /* | 3329 | /* |
3255 | * For 5210 we do all initialization using | 3330 | * For 5210 we do all initialization using |
3256 | * initvals, so we don't have to modify | 3331 | * initvals, so we don't have to modify |
3257 | * any settings (5210 also only supports | 3332 | * any settings (5210 also only supports |
3258 | * a/aturbo modes) | 3333 | * a/aturbo modes) |
3259 | */ | 3334 | */ |
3260 | if ((ah->ah_version != AR5K_AR5210) && !fast) { | 3335 | if (ah->ah_version != AR5K_AR5210) { |
3261 | 3336 | ||
3262 | /* | 3337 | /* |
3263 | * Write initial RF gain settings | 3338 | * Write initial RF gain settings |
@@ -3276,22 +3351,6 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, | |||
3276 | if (ret) | 3351 | if (ret) |
3277 | return ret; | 3352 | return ret; |
3278 | 3353 | ||
3279 | /* Write OFDM timings on 5212*/ | ||
3280 | if (ah->ah_version == AR5K_AR5212 && | ||
3281 | channel->hw_value & CHANNEL_OFDM) { | ||
3282 | |||
3283 | ret = ath5k_hw_write_ofdm_timings(ah, channel); | ||
3284 | if (ret) | ||
3285 | return ret; | ||
3286 | |||
3287 | /* Spur info is available only from EEPROM versions | ||
3288 | * greater than 5.3, but the EEPROM routines will use | ||
3289 | * static values for older versions */ | ||
3290 | if (ah->ah_mac_srev >= AR5K_SREV_AR5424) | ||
3291 | ath5k_hw_set_spur_mitigation_filter(ah, | ||
3292 | channel); | ||
3293 | } | ||
3294 | |||
3295 | /*Enable/disable 802.11b mode on 5111 | 3354 | /*Enable/disable 802.11b mode on 5111 |
3296 | (enable 2111 frequency converter + CCK)*/ | 3355 | (enable 2111 frequency converter + CCK)*/ |
3297 | if (ah->ah_radio == AR5K_RF5111) { | 3356 | if (ah->ah_radio == AR5K_RF5111) { |
@@ -3322,47 +3381,20 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, | |||
3322 | */ | 3381 | */ |
3323 | ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT); | 3382 | ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT); |
3324 | 3383 | ||
3384 | ath5k_hw_wait_for_synth(ah, channel); | ||
3385 | |||
3325 | /* | 3386 | /* |
3326 | * On 5211+ read activation -> rx delay | 3387 | * Perform ADC test to see if baseband is ready |
3327 | * and use it. | 3388 | * Set tx hold and check adc test register |
3328 | */ | 3389 | */ |
3329 | if (ah->ah_version != AR5K_AR5210) { | 3390 | phy_tst1 = ath5k_hw_reg_read(ah, AR5K_PHY_TST1); |
3330 | u32 delay; | 3391 | ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1); |
3331 | delay = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) & | 3392 | for (i = 0; i <= 20; i++) { |
3332 | AR5K_PHY_RX_DELAY_M; | 3393 | if (!(ath5k_hw_reg_read(ah, AR5K_PHY_ADC_TEST) & 0x10)) |
3333 | delay = (channel->hw_value & CHANNEL_CCK) ? | 3394 | break; |
3334 | ((delay << 2) / 22) : (delay / 10); | 3395 | udelay(200); |
3335 | if (ah->ah_bwmode == AR5K_BWMODE_10MHZ) | ||
3336 | delay = delay << 1; | ||
3337 | if (ah->ah_bwmode == AR5K_BWMODE_5MHZ) | ||
3338 | delay = delay << 2; | ||
3339 | /* XXX: /2 on turbo ? Let's be safe | ||
3340 | * for now */ | ||
3341 | udelay(100 + delay); | ||
3342 | } else { | ||
3343 | mdelay(1); | ||
3344 | } | ||
3345 | |||
3346 | if (fast) | ||
3347 | /* | ||
3348 | * Release RF Bus grant | ||
3349 | */ | ||
3350 | AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_RFBUS_REQ, | ||
3351 | AR5K_PHY_RFBUS_REQ_REQUEST); | ||
3352 | else { | ||
3353 | /* | ||
3354 | * Perform ADC test to see if baseband is ready | ||
3355 | * Set tx hold and check adc test register | ||
3356 | */ | ||
3357 | phy_tst1 = ath5k_hw_reg_read(ah, AR5K_PHY_TST1); | ||
3358 | ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1); | ||
3359 | for (i = 0; i <= 20; i++) { | ||
3360 | if (!(ath5k_hw_reg_read(ah, AR5K_PHY_ADC_TEST) & 0x10)) | ||
3361 | break; | ||
3362 | udelay(200); | ||
3363 | } | ||
3364 | ath5k_hw_reg_write(ah, phy_tst1, AR5K_PHY_TST1); | ||
3365 | } | 3396 | } |
3397 | ath5k_hw_reg_write(ah, phy_tst1, AR5K_PHY_TST1); | ||
3366 | 3398 | ||
3367 | /* | 3399 | /* |
3368 | * Start automatic gain control calibration | 3400 | * Start automatic gain control calibration |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index bd85e311c51b..7c8409e53598 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -602,6 +602,8 @@ struct ath_softc { | |||
602 | struct completion paprd_complete; | 602 | struct completion paprd_complete; |
603 | bool paprd_pending; | 603 | bool paprd_pending; |
604 | 604 | ||
605 | unsigned int hw_busy_count; | ||
606 | |||
605 | u32 intrstatus; | 607 | u32 intrstatus; |
606 | u32 sc_flags; /* SC_OP_* */ | 608 | u32 sc_flags; /* SC_OP_* */ |
607 | u16 ps_flags; /* PS_* */ | 609 | u16 ps_flags; /* PS_* */ |
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 87ba44c06692..fcb36abfc309 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c | |||
@@ -721,8 +721,9 @@ void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif) | |||
721 | cur_conf->beacon_interval = 100; | 721 | cur_conf->beacon_interval = 100; |
722 | 722 | ||
723 | /* | 723 | /* |
724 | * Some times we dont parse dtim period from mac80211, in that case | 724 | * We don't parse dtim period from mac80211 during the driver |
725 | * use a default value | 725 | * initialization as it breaks association with hidden-ssid |
726 | * AP and it causes latency in roaming | ||
726 | */ | 727 | */ |
727 | if (cur_conf->dtim_period == 0) | 728 | if (cur_conf->dtim_period == 0) |
728 | cur_conf->dtim_period = 1; | 729 | cur_conf->dtim_period = 1; |
diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c index df1998d48253..615e68276e72 100644 --- a/drivers/net/wireless/ath/ath9k/common.c +++ b/drivers/net/wireless/ath/ath9k/common.c | |||
@@ -189,6 +189,17 @@ void ath9k_cmn_btcoex_bt_stomp(struct ath_common *common, | |||
189 | } | 189 | } |
190 | EXPORT_SYMBOL(ath9k_cmn_btcoex_bt_stomp); | 190 | EXPORT_SYMBOL(ath9k_cmn_btcoex_bt_stomp); |
191 | 191 | ||
192 | void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow, | ||
193 | u16 new_txpow, u16 *txpower) | ||
194 | { | ||
195 | if (cur_txpow != new_txpow) { | ||
196 | ath9k_hw_set_txpowerlimit(ah, new_txpow, false); | ||
197 | /* read back in case value is clamped */ | ||
198 | *txpower = ath9k_hw_regulatory(ah)->power_limit; | ||
199 | } | ||
200 | } | ||
201 | EXPORT_SYMBOL(ath9k_cmn_update_txpow); | ||
202 | |||
192 | static int __init ath9k_cmn_init(void) | 203 | static int __init ath9k_cmn_init(void) |
193 | { | 204 | { |
194 | return 0; | 205 | return 0; |
diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h index 4c7020b3a5a0..b2f7b5f89097 100644 --- a/drivers/net/wireless/ath/ath9k/common.h +++ b/drivers/net/wireless/ath/ath9k/common.h | |||
@@ -68,3 +68,5 @@ struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw, | |||
68 | int ath9k_cmn_count_streams(unsigned int chainmask, int max); | 68 | int ath9k_cmn_count_streams(unsigned int chainmask, int max); |
69 | void ath9k_cmn_btcoex_bt_stomp(struct ath_common *common, | 69 | void ath9k_cmn_btcoex_bt_stomp(struct ath_common *common, |
70 | enum ath_stomp_type stomp_type); | 70 | enum ath_stomp_type stomp_type); |
71 | void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow, | ||
72 | u16 new_txpow, u16 *txpower); | ||
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 9cdc41b0ec44..5cfcf8c235a4 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c | |||
@@ -381,21 +381,40 @@ static const struct file_operations fops_interrupt = { | |||
381 | .llseek = default_llseek, | 381 | .llseek = default_llseek, |
382 | }; | 382 | }; |
383 | 383 | ||
384 | static const char *channel_type_str(enum nl80211_channel_type t) | ||
385 | { | ||
386 | switch (t) { | ||
387 | case NL80211_CHAN_NO_HT: | ||
388 | return "no ht"; | ||
389 | case NL80211_CHAN_HT20: | ||
390 | return "ht20"; | ||
391 | case NL80211_CHAN_HT40MINUS: | ||
392 | return "ht40-"; | ||
393 | case NL80211_CHAN_HT40PLUS: | ||
394 | return "ht40+"; | ||
395 | default: | ||
396 | return "???"; | ||
397 | } | ||
398 | } | ||
399 | |||
384 | static ssize_t read_file_wiphy(struct file *file, char __user *user_buf, | 400 | static ssize_t read_file_wiphy(struct file *file, char __user *user_buf, |
385 | size_t count, loff_t *ppos) | 401 | size_t count, loff_t *ppos) |
386 | { | 402 | { |
387 | struct ath_softc *sc = file->private_data; | 403 | struct ath_softc *sc = file->private_data; |
388 | struct ieee80211_channel *chan = sc->hw->conf.channel; | 404 | struct ieee80211_channel *chan = sc->hw->conf.channel; |
405 | struct ieee80211_conf *conf = &(sc->hw->conf); | ||
389 | char buf[512]; | 406 | char buf[512]; |
390 | unsigned int len = 0; | 407 | unsigned int len = 0; |
391 | u8 addr[ETH_ALEN]; | 408 | u8 addr[ETH_ALEN]; |
392 | u32 tmp; | 409 | u32 tmp; |
393 | 410 | ||
394 | len += snprintf(buf + len, sizeof(buf) - len, | 411 | len += snprintf(buf + len, sizeof(buf) - len, |
395 | "%s (chan=%d ht=%d)\n", | 412 | "%s (chan=%d center-freq: %d MHz channel-type: %d (%s))\n", |
396 | wiphy_name(sc->hw->wiphy), | 413 | wiphy_name(sc->hw->wiphy), |
397 | ieee80211_frequency_to_channel(chan->center_freq), | 414 | ieee80211_frequency_to_channel(chan->center_freq), |
398 | conf_is_ht(&sc->hw->conf)); | 415 | chan->center_freq, |
416 | conf->channel_type, | ||
417 | channel_type_str(conf->channel_type)); | ||
399 | 418 | ||
400 | put_unaligned_le32(REG_READ_D(sc->sc_ah, AR_STA_ID0), addr); | 419 | put_unaligned_le32(REG_READ_D(sc->sc_ah, AR_STA_ID0), addr); |
401 | put_unaligned_le16(REG_READ_D(sc->sc_ah, AR_STA_ID1) & 0xffff, addr + 4); | 420 | put_unaligned_le16(REG_READ_D(sc->sc_ah, AR_STA_ID1) & 0xffff, addr + 4); |
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 63549868e686..0cb504d7b8c4 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h | |||
@@ -460,7 +460,6 @@ void ath9k_htc_ps_restore(struct ath9k_htc_priv *priv); | |||
460 | void ath9k_ps_work(struct work_struct *work); | 460 | void ath9k_ps_work(struct work_struct *work); |
461 | bool ath9k_htc_setpower(struct ath9k_htc_priv *priv, | 461 | bool ath9k_htc_setpower(struct ath9k_htc_priv *priv, |
462 | enum ath9k_power_mode mode); | 462 | enum ath9k_power_mode mode); |
463 | void ath_update_txpow(struct ath9k_htc_priv *priv); | ||
464 | 463 | ||
465 | void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv); | 464 | void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv); |
466 | void ath9k_htc_rfkill_poll_state(struct ieee80211_hw *hw); | 465 | void ath9k_htc_rfkill_poll_state(struct ieee80211_hw *hw); |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c index fe70f67aa088..7e630a81b453 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c | |||
@@ -389,7 +389,8 @@ void ath9k_htc_radio_enable(struct ieee80211_hw *hw) | |||
389 | ret, ah->curchan->channel); | 389 | ret, ah->curchan->channel); |
390 | } | 390 | } |
391 | 391 | ||
392 | ath_update_txpow(priv); | 392 | ath9k_cmn_update_txpow(ah, priv->curtxpow, priv->txpowlimit, |
393 | &priv->curtxpow); | ||
393 | 394 | ||
394 | /* Start RX */ | 395 | /* Start RX */ |
395 | WMI_CMD(WMI_START_RECV_CMDID); | 396 | WMI_CMD(WMI_START_RECV_CMDID); |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index a702089f18d0..953036a4ed53 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c | |||
@@ -24,17 +24,6 @@ static struct dentry *ath9k_debugfs_root; | |||
24 | /* Utilities */ | 24 | /* Utilities */ |
25 | /*************/ | 25 | /*************/ |
26 | 26 | ||
27 | void ath_update_txpow(struct ath9k_htc_priv *priv) | ||
28 | { | ||
29 | struct ath_hw *ah = priv->ah; | ||
30 | |||
31 | if (priv->curtxpow != priv->txpowlimit) { | ||
32 | ath9k_hw_set_txpowerlimit(ah, priv->txpowlimit, false); | ||
33 | /* read back in case value is clamped */ | ||
34 | priv->curtxpow = ath9k_hw_regulatory(ah)->power_limit; | ||
35 | } | ||
36 | } | ||
37 | |||
38 | /* HACK Alert: Use 11NG for 2.4, use 11NA for 5 */ | 27 | /* HACK Alert: Use 11NG for 2.4, use 11NA for 5 */ |
39 | static enum htc_phymode ath9k_htc_get_curmode(struct ath9k_htc_priv *priv, | 28 | static enum htc_phymode ath9k_htc_get_curmode(struct ath9k_htc_priv *priv, |
40 | struct ath9k_channel *ichan) | 29 | struct ath9k_channel *ichan) |
@@ -147,7 +136,8 @@ void ath9k_htc_reset(struct ath9k_htc_priv *priv) | |||
147 | channel->center_freq, ret); | 136 | channel->center_freq, ret); |
148 | } | 137 | } |
149 | 138 | ||
150 | ath_update_txpow(priv); | 139 | ath9k_cmn_update_txpow(ah, priv->curtxpow, priv->txpowlimit, |
140 | &priv->curtxpow); | ||
151 | 141 | ||
152 | WMI_CMD(WMI_START_RECV_CMDID); | 142 | WMI_CMD(WMI_START_RECV_CMDID); |
153 | ath9k_host_rx_init(priv); | 143 | ath9k_host_rx_init(priv); |
@@ -212,7 +202,8 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, | |||
212 | goto err; | 202 | goto err; |
213 | } | 203 | } |
214 | 204 | ||
215 | ath_update_txpow(priv); | 205 | ath9k_cmn_update_txpow(ah, priv->curtxpow, priv->txpowlimit, |
206 | &priv->curtxpow); | ||
216 | 207 | ||
217 | WMI_CMD(WMI_START_RECV_CMDID); | 208 | WMI_CMD(WMI_START_RECV_CMDID); |
218 | if (ret) | 209 | if (ret) |
@@ -988,7 +979,8 @@ static int ath9k_htc_start(struct ieee80211_hw *hw) | |||
988 | return ret; | 979 | return ret; |
989 | } | 980 | } |
990 | 981 | ||
991 | ath_update_txpow(priv); | 982 | ath9k_cmn_update_txpow(ah, priv->curtxpow, priv->txpowlimit, |
983 | &priv->curtxpow); | ||
992 | 984 | ||
993 | mode = ath9k_htc_get_curmode(priv, init_channel); | 985 | mode = ath9k_htc_get_curmode(priv, init_channel); |
994 | htc_mode = cpu_to_be16(mode); | 986 | htc_mode = cpu_to_be16(mode); |
@@ -1052,6 +1044,7 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) | |||
1052 | cancel_work_sync(&priv->fatal_work); | 1044 | cancel_work_sync(&priv->fatal_work); |
1053 | cancel_work_sync(&priv->ps_work); | 1045 | cancel_work_sync(&priv->ps_work); |
1054 | cancel_delayed_work_sync(&priv->ath9k_led_blink_work); | 1046 | cancel_delayed_work_sync(&priv->ath9k_led_blink_work); |
1047 | cancel_delayed_work_sync(&priv->ath9k_ani_work); | ||
1055 | ath9k_led_stop_brightness(priv); | 1048 | ath9k_led_stop_brightness(priv); |
1056 | 1049 | ||
1057 | mutex_lock(&priv->mutex); | 1050 | mutex_lock(&priv->mutex); |
@@ -1253,7 +1246,8 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed) | |||
1253 | 1246 | ||
1254 | if (changed & IEEE80211_CONF_CHANGE_POWER) { | 1247 | if (changed & IEEE80211_CONF_CHANGE_POWER) { |
1255 | priv->txpowlimit = 2 * conf->power_level; | 1248 | priv->txpowlimit = 2 * conf->power_level; |
1256 | ath_update_txpow(priv); | 1249 | ath9k_cmn_update_txpow(priv->ah, priv->curtxpow, |
1250 | priv->txpowlimit, &priv->curtxpow); | ||
1257 | } | 1251 | } |
1258 | 1252 | ||
1259 | if (changed & IEEE80211_CONF_CHANGE_IDLE) { | 1253 | if (changed & IEEE80211_CONF_CHANGE_IDLE) { |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 1447b55a8d0a..2d4e9b861b60 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -18,17 +18,6 @@ | |||
18 | #include "ath9k.h" | 18 | #include "ath9k.h" |
19 | #include "btcoex.h" | 19 | #include "btcoex.h" |
20 | 20 | ||
21 | static void ath_update_txpow(struct ath_softc *sc) | ||
22 | { | ||
23 | struct ath_hw *ah = sc->sc_ah; | ||
24 | |||
25 | if (sc->curtxpow != sc->config.txpowlimit) { | ||
26 | ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit, false); | ||
27 | /* read back in case value is clamped */ | ||
28 | sc->curtxpow = ath9k_hw_regulatory(ah)->power_limit; | ||
29 | } | ||
30 | } | ||
31 | |||
32 | static u8 parse_mpdudensity(u8 mpdudensity) | 21 | static u8 parse_mpdudensity(u8 mpdudensity) |
33 | { | 22 | { |
34 | /* | 23 | /* |
@@ -64,19 +53,6 @@ static u8 parse_mpdudensity(u8 mpdudensity) | |||
64 | } | 53 | } |
65 | } | 54 | } |
66 | 55 | ||
67 | static struct ath9k_channel *ath_get_curchannel(struct ath_softc *sc, | ||
68 | struct ieee80211_hw *hw) | ||
69 | { | ||
70 | struct ieee80211_channel *curchan = hw->conf.channel; | ||
71 | struct ath9k_channel *channel; | ||
72 | u8 chan_idx; | ||
73 | |||
74 | chan_idx = curchan->hw_value; | ||
75 | channel = &sc->sc_ah->channels[chan_idx]; | ||
76 | ath9k_cmn_update_ichannel(channel, curchan, hw->conf.channel_type); | ||
77 | return channel; | ||
78 | } | ||
79 | |||
80 | bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode) | 56 | bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode) |
81 | { | 57 | { |
82 | unsigned long flags; | 58 | unsigned long flags; |
@@ -177,7 +153,12 @@ static void ath_update_survey_nf(struct ath_softc *sc, int channel) | |||
177 | } | 153 | } |
178 | } | 154 | } |
179 | 155 | ||
180 | static void ath_update_survey_stats(struct ath_softc *sc) | 156 | /* |
157 | * Updates the survey statistics and returns the busy time since last | ||
158 | * update in %, if the measurement duration was long enough for the | ||
159 | * result to be useful, -1 otherwise. | ||
160 | */ | ||
161 | static int ath_update_survey_stats(struct ath_softc *sc) | ||
181 | { | 162 | { |
182 | struct ath_hw *ah = sc->sc_ah; | 163 | struct ath_hw *ah = sc->sc_ah; |
183 | struct ath_common *common = ath9k_hw_common(ah); | 164 | struct ath_common *common = ath9k_hw_common(ah); |
@@ -185,9 +166,10 @@ static void ath_update_survey_stats(struct ath_softc *sc) | |||
185 | struct survey_info *survey = &sc->survey[pos]; | 166 | struct survey_info *survey = &sc->survey[pos]; |
186 | struct ath_cycle_counters *cc = &common->cc_survey; | 167 | struct ath_cycle_counters *cc = &common->cc_survey; |
187 | unsigned int div = common->clockrate * 1000; | 168 | unsigned int div = common->clockrate * 1000; |
169 | int ret = 0; | ||
188 | 170 | ||
189 | if (!ah->curchan) | 171 | if (!ah->curchan) |
190 | return; | 172 | return -1; |
191 | 173 | ||
192 | if (ah->power_mode == ATH9K_PM_AWAKE) | 174 | if (ah->power_mode == ATH9K_PM_AWAKE) |
193 | ath_hw_cycle_counters_update(common); | 175 | ath_hw_cycle_counters_update(common); |
@@ -202,9 +184,18 @@ static void ath_update_survey_stats(struct ath_softc *sc) | |||
202 | survey->channel_time_rx += cc->rx_frame / div; | 184 | survey->channel_time_rx += cc->rx_frame / div; |
203 | survey->channel_time_tx += cc->tx_frame / div; | 185 | survey->channel_time_tx += cc->tx_frame / div; |
204 | } | 186 | } |
187 | |||
188 | if (cc->cycles < div) | ||
189 | return -1; | ||
190 | |||
191 | if (cc->cycles > 0) | ||
192 | ret = cc->rx_busy * 100 / cc->cycles; | ||
193 | |||
205 | memset(cc, 0, sizeof(*cc)); | 194 | memset(cc, 0, sizeof(*cc)); |
206 | 195 | ||
207 | ath_update_survey_nf(sc, pos); | 196 | ath_update_survey_nf(sc, pos); |
197 | |||
198 | return ret; | ||
208 | } | 199 | } |
209 | 200 | ||
210 | /* | 201 | /* |
@@ -226,6 +217,8 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | |||
226 | if (sc->sc_flags & SC_OP_INVALID) | 217 | if (sc->sc_flags & SC_OP_INVALID) |
227 | return -EIO; | 218 | return -EIO; |
228 | 219 | ||
220 | sc->hw_busy_count = 0; | ||
221 | |||
229 | del_timer_sync(&common->ani.timer); | 222 | del_timer_sync(&common->ani.timer); |
230 | cancel_work_sync(&sc->paprd_work); | 223 | cancel_work_sync(&sc->paprd_work); |
231 | cancel_work_sync(&sc->hw_check_work); | 224 | cancel_work_sync(&sc->hw_check_work); |
@@ -284,7 +277,8 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | |||
284 | goto ps_restore; | 277 | goto ps_restore; |
285 | } | 278 | } |
286 | 279 | ||
287 | ath_update_txpow(sc); | 280 | ath9k_cmn_update_txpow(ah, sc->curtxpow, |
281 | sc->config.txpowlimit, &sc->curtxpow); | ||
288 | ath9k_hw_set_interrupts(ah, ah->imask); | 282 | ath9k_hw_set_interrupts(ah, ah->imask); |
289 | 283 | ||
290 | if (!(sc->sc_flags & (SC_OP_OFFCHANNEL))) { | 284 | if (!(sc->sc_flags & (SC_OP_OFFCHANNEL))) { |
@@ -592,17 +586,25 @@ static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta) | |||
592 | void ath_hw_check(struct work_struct *work) | 586 | void ath_hw_check(struct work_struct *work) |
593 | { | 587 | { |
594 | struct ath_softc *sc = container_of(work, struct ath_softc, hw_check_work); | 588 | struct ath_softc *sc = container_of(work, struct ath_softc, hw_check_work); |
595 | int i; | 589 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
590 | unsigned long flags; | ||
591 | int busy; | ||
596 | 592 | ||
597 | ath9k_ps_wakeup(sc); | 593 | ath9k_ps_wakeup(sc); |
594 | if (ath9k_hw_check_alive(sc->sc_ah)) | ||
595 | goto out; | ||
598 | 596 | ||
599 | for (i = 0; i < 3; i++) { | 597 | spin_lock_irqsave(&common->cc_lock, flags); |
600 | if (ath9k_hw_check_alive(sc->sc_ah)) | 598 | busy = ath_update_survey_stats(sc); |
601 | goto out; | 599 | spin_unlock_irqrestore(&common->cc_lock, flags); |
602 | 600 | ||
603 | msleep(1); | 601 | ath_dbg(common, ATH_DBG_RESET, "Possible baseband hang, " |
604 | } | 602 | "busy=%d (try %d)\n", busy, sc->hw_busy_count + 1); |
605 | ath_reset(sc, true); | 603 | if (busy >= 99) { |
604 | if (++sc->hw_busy_count >= 3) | ||
605 | ath_reset(sc, true); | ||
606 | } else if (busy >= 0) | ||
607 | sc->hw_busy_count = 0; | ||
606 | 608 | ||
607 | out: | 609 | out: |
608 | ath9k_ps_restore(sc); | 610 | ath9k_ps_restore(sc); |
@@ -867,7 +869,7 @@ void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
867 | ath9k_hw_configpcipowersave(ah, 0, 0); | 869 | ath9k_hw_configpcipowersave(ah, 0, 0); |
868 | 870 | ||
869 | if (!ah->curchan) | 871 | if (!ah->curchan) |
870 | ah->curchan = ath_get_curchannel(sc, sc->hw); | 872 | ah->curchan = ath9k_cmn_get_curchannel(sc->hw, ah); |
871 | 873 | ||
872 | r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); | 874 | r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); |
873 | if (r) { | 875 | if (r) { |
@@ -876,7 +878,8 @@ void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
876 | channel->center_freq, r); | 878 | channel->center_freq, r); |
877 | } | 879 | } |
878 | 880 | ||
879 | ath_update_txpow(sc); | 881 | ath9k_cmn_update_txpow(ah, sc->curtxpow, |
882 | sc->config.txpowlimit, &sc->curtxpow); | ||
880 | if (ath_startrecv(sc) != 0) { | 883 | if (ath_startrecv(sc) != 0) { |
881 | ath_err(common, "Unable to restart recv logic\n"); | 884 | ath_err(common, "Unable to restart recv logic\n"); |
882 | goto out; | 885 | goto out; |
@@ -928,7 +931,7 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
928 | ath_flushrecv(sc); /* flush recv queue */ | 931 | ath_flushrecv(sc); /* flush recv queue */ |
929 | 932 | ||
930 | if (!ah->curchan) | 933 | if (!ah->curchan) |
931 | ah->curchan = ath_get_curchannel(sc, hw); | 934 | ah->curchan = ath9k_cmn_get_curchannel(hw, ah); |
932 | 935 | ||
933 | r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); | 936 | r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); |
934 | if (r) { | 937 | if (r) { |
@@ -952,6 +955,8 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) | |||
952 | struct ieee80211_hw *hw = sc->hw; | 955 | struct ieee80211_hw *hw = sc->hw; |
953 | int r; | 956 | int r; |
954 | 957 | ||
958 | sc->hw_busy_count = 0; | ||
959 | |||
955 | /* Stop ANI */ | 960 | /* Stop ANI */ |
956 | del_timer_sync(&common->ani.timer); | 961 | del_timer_sync(&common->ani.timer); |
957 | 962 | ||
@@ -979,7 +984,8 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) | |||
979 | * that changes the channel so update any state that | 984 | * that changes the channel so update any state that |
980 | * might change as a result. | 985 | * might change as a result. |
981 | */ | 986 | */ |
982 | ath_update_txpow(sc); | 987 | ath9k_cmn_update_txpow(ah, sc->curtxpow, |
988 | sc->config.txpowlimit, &sc->curtxpow); | ||
983 | 989 | ||
984 | if ((sc->sc_flags & SC_OP_BEACONS) || !(sc->sc_flags & (SC_OP_OFFCHANNEL))) | 990 | if ((sc->sc_flags & SC_OP_BEACONS) || !(sc->sc_flags & (SC_OP_OFFCHANNEL))) |
985 | ath_beacon_config(sc, NULL); /* restart beacons */ | 991 | ath_beacon_config(sc, NULL); /* restart beacons */ |
@@ -1029,7 +1035,7 @@ static int ath9k_start(struct ieee80211_hw *hw) | |||
1029 | /* setup initial channel */ | 1035 | /* setup initial channel */ |
1030 | sc->chan_idx = curchan->hw_value; | 1036 | sc->chan_idx = curchan->hw_value; |
1031 | 1037 | ||
1032 | init_channel = ath_get_curchannel(sc, hw); | 1038 | init_channel = ath9k_cmn_get_curchannel(hw, ah); |
1033 | 1039 | ||
1034 | /* Reset SERDES registers */ | 1040 | /* Reset SERDES registers */ |
1035 | ath9k_hw_configpcipowersave(ah, 0, 0); | 1041 | ath9k_hw_configpcipowersave(ah, 0, 0); |
@@ -1055,7 +1061,8 @@ static int ath9k_start(struct ieee80211_hw *hw) | |||
1055 | * This is needed only to setup initial state | 1061 | * This is needed only to setup initial state |
1056 | * but it's best done after a reset. | 1062 | * but it's best done after a reset. |
1057 | */ | 1063 | */ |
1058 | ath_update_txpow(sc); | 1064 | ath9k_cmn_update_txpow(ah, sc->curtxpow, |
1065 | sc->config.txpowlimit, &sc->curtxpow); | ||
1059 | 1066 | ||
1060 | /* | 1067 | /* |
1061 | * Setup the hardware after reset: | 1068 | * Setup the hardware after reset: |
@@ -1374,6 +1381,7 @@ static void ath9k_calculate_summary_state(struct ieee80211_hw *hw, | |||
1374 | 1381 | ||
1375 | ath9k_calculate_iter_data(hw, vif, &iter_data); | 1382 | ath9k_calculate_iter_data(hw, vif, &iter_data); |
1376 | 1383 | ||
1384 | ath9k_ps_wakeup(sc); | ||
1377 | /* Set BSSID mask. */ | 1385 | /* Set BSSID mask. */ |
1378 | memcpy(common->bssidmask, iter_data.mask, ETH_ALEN); | 1386 | memcpy(common->bssidmask, iter_data.mask, ETH_ALEN); |
1379 | ath_hw_setbssidmask(common); | 1387 | ath_hw_setbssidmask(common); |
@@ -1408,6 +1416,7 @@ static void ath9k_calculate_summary_state(struct ieee80211_hw *hw, | |||
1408 | } | 1416 | } |
1409 | 1417 | ||
1410 | ath9k_hw_set_interrupts(ah, ah->imask); | 1418 | ath9k_hw_set_interrupts(ah, ah->imask); |
1419 | ath9k_ps_restore(sc); | ||
1411 | 1420 | ||
1412 | /* Set up ANI */ | 1421 | /* Set up ANI */ |
1413 | if ((iter_data.naps + iter_data.nadhocs) > 0) { | 1422 | if ((iter_data.naps + iter_data.nadhocs) > 0) { |
@@ -1437,9 +1446,7 @@ static void ath9k_do_vif_add_setup(struct ieee80211_hw *hw, | |||
1437 | * there. | 1446 | * there. |
1438 | */ | 1447 | */ |
1439 | error = ath_beacon_alloc(sc, vif); | 1448 | error = ath_beacon_alloc(sc, vif); |
1440 | if (error) | 1449 | if (!error) |
1441 | ath9k_reclaim_beacon(sc, vif); | ||
1442 | else | ||
1443 | ath_beacon_config(sc, vif); | 1450 | ath_beacon_config(sc, vif); |
1444 | } | 1451 | } |
1445 | } | 1452 | } |
@@ -1720,7 +1727,8 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
1720 | if (changed & IEEE80211_CONF_CHANGE_POWER) { | 1727 | if (changed & IEEE80211_CONF_CHANGE_POWER) { |
1721 | sc->config.txpowlimit = 2 * conf->power_level; | 1728 | sc->config.txpowlimit = 2 * conf->power_level; |
1722 | ath9k_ps_wakeup(sc); | 1729 | ath9k_ps_wakeup(sc); |
1723 | ath_update_txpow(sc); | 1730 | ath9k_cmn_update_txpow(ah, sc->curtxpow, |
1731 | sc->config.txpowlimit, &sc->curtxpow); | ||
1724 | ath9k_ps_restore(sc); | 1732 | ath9k_ps_restore(sc); |
1725 | } | 1733 | } |
1726 | 1734 | ||
diff --git a/drivers/net/wireless/ath/key.c b/drivers/net/wireless/ath/key.c index 5d465e5fcf24..37b8e115375a 100644 --- a/drivers/net/wireless/ath/key.c +++ b/drivers/net/wireless/ath/key.c | |||
@@ -58,8 +58,11 @@ bool ath_hw_keyreset(struct ath_common *common, u16 entry) | |||
58 | REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0); | 58 | REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0); |
59 | REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), 0); | 59 | REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), 0); |
60 | REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0); | 60 | REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0); |
61 | if (common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED) | 61 | if (common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED) { |
62 | REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), 0); | 62 | REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), 0); |
63 | REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry), | ||
64 | AR_KEYTABLE_TYPE_CLR); | ||
65 | } | ||
63 | 66 | ||
64 | } | 67 | } |
65 | 68 | ||
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index 61915f371416..da60faee74fc 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c | |||
@@ -1397,7 +1397,7 @@ static int ipw2100_power_cycle_adapter(struct ipw2100_priv *priv) | |||
1397 | } | 1397 | } |
1398 | 1398 | ||
1399 | /* | 1399 | /* |
1400 | * Send the CARD_DISABLE_PHY_OFF comamnd to the card to disable it | 1400 | * Send the CARD_DISABLE_PHY_OFF command to the card to disable it |
1401 | * | 1401 | * |
1402 | * After disabling, if the card was associated, a STATUS_ASSN_LOST will be sent. | 1402 | * After disabling, if the card was associated, a STATUS_ASSN_LOST will be sent. |
1403 | * | 1403 | * |
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 127723e6319f..ba78bc8a259f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c | |||
@@ -270,7 +270,6 @@ 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, | ||
274 | }; | 273 | }; |
275 | static struct iwl_ht_params iwl1000_ht_params = { | 274 | static struct iwl_ht_params iwl1000_ht_params = { |
276 | .ht_greenfield_support = true, | 275 | .ht_greenfield_support = true, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index 3c9e1b5724c7..3c5dd36ff417 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c | |||
@@ -97,6 +97,10 @@ static void iwl2000_nic_config(struct iwl_priv *priv) | |||
97 | CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | | 97 | CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | |
98 | CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); | 98 | CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); |
99 | 99 | ||
100 | if (priv->cfg->iq_invert) | ||
101 | iwl_set_bit(priv, CSR_GP_DRIVER_REG, | ||
102 | CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER); | ||
103 | |||
100 | } | 104 | } |
101 | 105 | ||
102 | static struct iwl_sensitivity_ranges iwl2000_sensitivity = { | 106 | static struct iwl_sensitivity_ranges iwl2000_sensitivity = { |
@@ -364,7 +368,6 @@ static struct iwl_base_params iwl2000_base_params = { | |||
364 | .shadow_ram_support = true, | 368 | .shadow_ram_support = true, |
365 | .led_compensation = 51, | 369 | .led_compensation = 51, |
366 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 370 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
367 | .supports_idle = true, | ||
368 | .adv_thermal_throttle = true, | 371 | .adv_thermal_throttle = true, |
369 | .support_ct_kill_exit = true, | 372 | .support_ct_kill_exit = true, |
370 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | 373 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, |
@@ -389,7 +392,6 @@ static struct iwl_base_params iwl2030_base_params = { | |||
389 | .shadow_ram_support = true, | 392 | .shadow_ram_support = true, |
390 | .led_compensation = 57, | 393 | .led_compensation = 57, |
391 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 394 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
392 | .supports_idle = true, | ||
393 | .adv_thermal_throttle = true, | 395 | .adv_thermal_throttle = true, |
394 | .support_ct_kill_exit = true, | 396 | .support_ct_kill_exit = true, |
395 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | 397 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, |
@@ -428,7 +430,8 @@ static struct iwl_bt_params iwl2030_bt_params = { | |||
428 | .base_params = &iwl2000_base_params, \ | 430 | .base_params = &iwl2000_base_params, \ |
429 | .need_dc_calib = true, \ | 431 | .need_dc_calib = true, \ |
430 | .need_temp_offset_calib = true, \ | 432 | .need_temp_offset_calib = true, \ |
431 | .led_mode = IWL_LED_RF_STATE \ | 433 | .led_mode = IWL_LED_RF_STATE, \ |
434 | .iq_invert = true \ | ||
432 | 435 | ||
433 | struct iwl_cfg iwl2000_2bgn_cfg = { | 436 | struct iwl_cfg iwl2000_2bgn_cfg = { |
434 | .name = "2000 Series 2x2 BGN", | 437 | .name = "2000 Series 2x2 BGN", |
@@ -454,17 +457,18 @@ struct iwl_cfg iwl2000_2bg_cfg = { | |||
454 | .need_dc_calib = true, \ | 457 | .need_dc_calib = true, \ |
455 | .need_temp_offset_calib = true, \ | 458 | .need_temp_offset_calib = true, \ |
456 | .led_mode = IWL_LED_RF_STATE, \ | 459 | .led_mode = IWL_LED_RF_STATE, \ |
457 | .adv_pm = true \ | 460 | .adv_pm = true, \ |
461 | .iq_invert = true \ | ||
458 | 462 | ||
459 | struct iwl_cfg iwl2030_2bgn_cfg = { | 463 | struct iwl_cfg iwl2030_2bgn_cfg = { |
460 | .name = "2000 Series 2x2 BGN/BT", | 464 | .name = "2000 Series 2x2 BGN/BT", |
461 | IWL_DEVICE_2000, | 465 | IWL_DEVICE_2030, |
462 | .ht_params = &iwl2000_ht_params, | 466 | .ht_params = &iwl2000_ht_params, |
463 | }; | 467 | }; |
464 | 468 | ||
465 | struct iwl_cfg iwl2030_2bg_cfg = { | 469 | struct iwl_cfg iwl2030_2bg_cfg = { |
466 | .name = "2000 Series 2x2 BG/BT", | 470 | .name = "2000 Series 2x2 BG/BT", |
467 | IWL_DEVICE_2000, | 471 | IWL_DEVICE_2030, |
468 | }; | 472 | }; |
469 | 473 | ||
470 | #define IWL_DEVICE_6035 \ | 474 | #define IWL_DEVICE_6035 \ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 7c14eb31d954..8998ed134d1a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c | |||
@@ -251,14 +251,6 @@ static int iwl4965_set_ucode_ptrs(struct iwl_priv *priv) | |||
251 | */ | 251 | */ |
252 | static void iwl4965_init_alive_start(struct iwl_priv *priv) | 252 | static void iwl4965_init_alive_start(struct iwl_priv *priv) |
253 | { | 253 | { |
254 | /* Check alive response for "valid" sign from uCode */ | ||
255 | if (priv->card_alive_init.is_valid != UCODE_VALID_OK) { | ||
256 | /* We had an error bringing up the hardware, so take it | ||
257 | * all the way back down so we can try again */ | ||
258 | IWL_DEBUG_INFO(priv, "Initialize Alive failed.\n"); | ||
259 | goto restart; | ||
260 | } | ||
261 | |||
262 | /* Bootstrap uCode has loaded initialize uCode ... verify inst image. | 254 | /* Bootstrap uCode has loaded initialize uCode ... verify inst image. |
263 | * This is a paranoid check, because we would not have gotten the | 255 | * This is a paranoid check, because we would not have gotten the |
264 | * "initialize" alive if code weren't properly loaded. */ | 256 | * "initialize" alive if code weren't properly loaded. */ |
@@ -2274,6 +2266,29 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, | |||
2274 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 2266 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
2275 | } | 2267 | } |
2276 | 2268 | ||
2269 | static void iwl4965_rx_beacon_notif(struct iwl_priv *priv, | ||
2270 | struct iwl_rx_mem_buffer *rxb) | ||
2271 | { | ||
2272 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
2273 | struct iwl4965_beacon_notif *beacon = (void *)pkt->u.raw; | ||
2274 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
2275 | u8 rate = iwl_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags); | ||
2276 | |||
2277 | IWL_DEBUG_RX(priv, "beacon status %#x, retries:%d ibssmgr:%d " | ||
2278 | "tsf:0x%.8x%.8x rate:%d\n", | ||
2279 | le32_to_cpu(beacon->beacon_notify_hdr.u.status) & TX_STATUS_MSK, | ||
2280 | beacon->beacon_notify_hdr.failure_frame, | ||
2281 | le32_to_cpu(beacon->ibss_mgr_status), | ||
2282 | le32_to_cpu(beacon->high_tsf), | ||
2283 | le32_to_cpu(beacon->low_tsf), rate); | ||
2284 | #endif | ||
2285 | |||
2286 | priv->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status); | ||
2287 | |||
2288 | if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
2289 | queue_work(priv->workqueue, &priv->beacon_update); | ||
2290 | } | ||
2291 | |||
2277 | static int iwl4965_calc_rssi(struct iwl_priv *priv, | 2292 | static int iwl4965_calc_rssi(struct iwl_priv *priv, |
2278 | struct iwl_rx_phy_res *rx_resp) | 2293 | struct iwl_rx_phy_res *rx_resp) |
2279 | { | 2294 | { |
@@ -2316,6 +2331,7 @@ static void iwl4965_rx_handler_setup(struct iwl_priv *priv) | |||
2316 | priv->rx_handlers[REPLY_RX] = iwlagn_rx_reply_rx; | 2331 | priv->rx_handlers[REPLY_RX] = iwlagn_rx_reply_rx; |
2317 | /* Tx response */ | 2332 | /* Tx response */ |
2318 | priv->rx_handlers[REPLY_TX] = iwl4965_rx_reply_tx; | 2333 | priv->rx_handlers[REPLY_TX] = iwl4965_rx_reply_tx; |
2334 | priv->rx_handlers[BEACON_NOTIFICATION] = iwl4965_rx_beacon_notif; | ||
2319 | 2335 | ||
2320 | /* set up notification wait support */ | 2336 | /* set up notification wait support */ |
2321 | spin_lock_init(&priv->_agn.notif_wait_lock); | 2337 | spin_lock_init(&priv->_agn.notif_wait_lock); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index c195674454f4..aa32b1e05dff 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c | |||
@@ -479,7 +479,6 @@ static struct iwl_base_params iwl6000_base_params = { | |||
479 | .shadow_ram_support = true, | 479 | .shadow_ram_support = true, |
480 | .led_compensation = 51, | 480 | .led_compensation = 51, |
481 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 481 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
482 | .supports_idle = true, | ||
483 | .adv_thermal_throttle = true, | 482 | .adv_thermal_throttle = true, |
484 | .support_ct_kill_exit = true, | 483 | .support_ct_kill_exit = true, |
485 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | 484 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, |
@@ -503,7 +502,6 @@ static struct iwl_base_params iwl6050_base_params = { | |||
503 | .shadow_ram_support = true, | 502 | .shadow_ram_support = true, |
504 | .led_compensation = 51, | 503 | .led_compensation = 51, |
505 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 504 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
506 | .supports_idle = true, | ||
507 | .adv_thermal_throttle = true, | 505 | .adv_thermal_throttle = true, |
508 | .support_ct_kill_exit = true, | 506 | .support_ct_kill_exit = true, |
509 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | 507 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, |
@@ -526,7 +524,6 @@ static struct iwl_base_params iwl6000_g2_base_params = { | |||
526 | .shadow_ram_support = true, | 524 | .shadow_ram_support = true, |
527 | .led_compensation = 57, | 525 | .led_compensation = 57, |
528 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 526 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
529 | .supports_idle = true, | ||
530 | .adv_thermal_throttle = true, | 527 | .adv_thermal_throttle = true, |
531 | .support_ct_kill_exit = true, | 528 | .support_ct_kill_exit = true, |
532 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | 529 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index c7d03874b380..3aa486437509 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c | |||
@@ -1395,15 +1395,12 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
1395 | u32 extra; | 1395 | u32 extra; |
1396 | u32 suspend_time = 100; | 1396 | u32 suspend_time = 100; |
1397 | u32 scan_suspend_time = 100; | 1397 | u32 scan_suspend_time = 100; |
1398 | unsigned long flags; | ||
1399 | 1398 | ||
1400 | IWL_DEBUG_INFO(priv, "Scanning while associated...\n"); | 1399 | IWL_DEBUG_INFO(priv, "Scanning while associated...\n"); |
1401 | spin_lock_irqsave(&priv->lock, flags); | ||
1402 | if (priv->is_internal_short_scan) | 1400 | if (priv->is_internal_short_scan) |
1403 | interval = 0; | 1401 | interval = 0; |
1404 | else | 1402 | else |
1405 | interval = vif->bss_conf.beacon_int; | 1403 | interval = vif->bss_conf.beacon_int; |
1406 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1407 | 1404 | ||
1408 | scan->suspend_time = 0; | 1405 | scan->suspend_time = 0; |
1409 | scan->max_out_time = cpu_to_le32(200 * 1024); | 1406 | scan->max_out_time = cpu_to_le32(200 * 1024); |
@@ -1863,21 +1860,6 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv) | |||
1863 | if (iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG, sizeof(bt_cmd), &bt_cmd)) | 1860 | if (iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG, sizeof(bt_cmd), &bt_cmd)) |
1864 | IWL_ERR(priv, "failed to send BT Coex Config\n"); | 1861 | IWL_ERR(priv, "failed to send BT Coex Config\n"); |
1865 | 1862 | ||
1866 | /* | ||
1867 | * When we are doing a restart, need to also reconfigure BT | ||
1868 | * SCO to the device. If not doing a restart, bt_sco_active | ||
1869 | * will always be false, so there's no need to have an extra | ||
1870 | * variable to check for it. | ||
1871 | */ | ||
1872 | if (priv->bt_sco_active) { | ||
1873 | struct iwlagn_bt_sco_cmd sco_cmd = { .flags = 0 }; | ||
1874 | |||
1875 | if (priv->bt_sco_active) | ||
1876 | sco_cmd.flags |= IWLAGN_BT_SCO_ACTIVE; | ||
1877 | if (iwl_send_cmd_pdu(priv, REPLY_BT_COEX_SCO, | ||
1878 | sizeof(sco_cmd), &sco_cmd)) | ||
1879 | IWL_ERR(priv, "failed to send BT SCO command\n"); | ||
1880 | } | ||
1881 | } | 1863 | } |
1882 | 1864 | ||
1883 | static void iwlagn_bt_traffic_change_work(struct work_struct *work) | 1865 | static void iwlagn_bt_traffic_change_work(struct work_struct *work) |
@@ -2038,7 +2020,6 @@ void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv, | |||
2038 | unsigned long flags; | 2020 | unsigned long flags; |
2039 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 2021 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
2040 | struct iwl_bt_coex_profile_notif *coex = &pkt->u.bt_coex_profile_notif; | 2022 | struct iwl_bt_coex_profile_notif *coex = &pkt->u.bt_coex_profile_notif; |
2041 | struct iwlagn_bt_sco_cmd sco_cmd = { .flags = 0 }; | ||
2042 | struct iwl_bt_uart_msg *uart_msg = &coex->last_bt_uart_msg; | 2023 | struct iwl_bt_uart_msg *uart_msg = &coex->last_bt_uart_msg; |
2043 | 2024 | ||
2044 | IWL_DEBUG_NOTIF(priv, "BT Coex notification:\n"); | 2025 | IWL_DEBUG_NOTIF(priv, "BT Coex notification:\n"); |
@@ -2069,15 +2050,6 @@ void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv, | |||
2069 | queue_work(priv->workqueue, | 2050 | queue_work(priv->workqueue, |
2070 | &priv->bt_traffic_change_work); | 2051 | &priv->bt_traffic_change_work); |
2071 | } | 2052 | } |
2072 | if (priv->bt_sco_active != | ||
2073 | (uart_msg->frame3 & BT_UART_MSG_FRAME3SCOESCO_MSK)) { | ||
2074 | priv->bt_sco_active = uart_msg->frame3 & | ||
2075 | BT_UART_MSG_FRAME3SCOESCO_MSK; | ||
2076 | if (priv->bt_sco_active) | ||
2077 | sco_cmd.flags |= IWLAGN_BT_SCO_ACTIVE; | ||
2078 | iwl_send_cmd_pdu_async(priv, REPLY_BT_COEX_SCO, | ||
2079 | sizeof(sco_cmd), &sco_cmd, NULL); | ||
2080 | } | ||
2081 | } | 2053 | } |
2082 | 2054 | ||
2083 | iwlagn_set_kill_msk(priv, uart_msg); | 2055 | iwlagn_set_kill_msk(priv, uart_msg); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 75fcd30a7c13..d03b4734c892 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c | |||
@@ -179,31 +179,31 @@ static s32 expected_tpt_legacy[IWL_RATE_COUNT] = { | |||
179 | }; | 179 | }; |
180 | 180 | ||
181 | static s32 expected_tpt_siso20MHz[4][IWL_RATE_COUNT] = { | 181 | static s32 expected_tpt_siso20MHz[4][IWL_RATE_COUNT] = { |
182 | {0, 0, 0, 0, 42, 0, 76, 102, 124, 158, 183, 193, 202}, /* Norm */ | 182 | {0, 0, 0, 0, 42, 0, 76, 102, 124, 159, 183, 193, 202}, /* Norm */ |
183 | {0, 0, 0, 0, 46, 0, 82, 110, 132, 167, 192, 202, 210}, /* SGI */ | 183 | {0, 0, 0, 0, 46, 0, 82, 110, 132, 168, 192, 202, 210}, /* SGI */ |
184 | {0, 0, 0, 0, 48, 0, 93, 135, 176, 251, 319, 351, 381}, /* AGG */ | 184 | {0, 0, 0, 0, 47, 0, 91, 133, 171, 242, 305, 334, 362}, /* AGG */ |
185 | {0, 0, 0, 0, 53, 0, 102, 149, 193, 275, 348, 381, 413}, /* AGG+SGI */ | 185 | {0, 0, 0, 0, 52, 0, 101, 145, 187, 264, 330, 361, 390}, /* AGG+SGI */ |
186 | }; | 186 | }; |
187 | 187 | ||
188 | static s32 expected_tpt_siso40MHz[4][IWL_RATE_COUNT] = { | 188 | static s32 expected_tpt_siso40MHz[4][IWL_RATE_COUNT] = { |
189 | {0, 0, 0, 0, 77, 0, 127, 160, 184, 220, 242, 250, 257}, /* Norm */ | 189 | {0, 0, 0, 0, 77, 0, 127, 160, 184, 220, 242, 250, 257}, /* Norm */ |
190 | {0, 0, 0, 0, 83, 0, 135, 169, 193, 229, 250, 257, 264}, /* SGI */ | 190 | {0, 0, 0, 0, 83, 0, 135, 169, 193, 229, 250, 257, 264}, /* SGI */ |
191 | {0, 0, 0, 0, 96, 0, 182, 259, 328, 451, 553, 598, 640}, /* AGG */ | 191 | {0, 0, 0, 0, 94, 0, 177, 249, 313, 423, 512, 550, 586}, /* AGG */ |
192 | {0, 0, 0, 0, 106, 0, 199, 282, 357, 487, 593, 640, 683}, /* AGG+SGI */ | 192 | {0, 0, 0, 0, 104, 0, 193, 270, 338, 454, 545, 584, 620}, /* AGG+SGI */ |
193 | }; | 193 | }; |
194 | 194 | ||
195 | static s32 expected_tpt_mimo2_20MHz[4][IWL_RATE_COUNT] = { | 195 | static s32 expected_tpt_mimo2_20MHz[4][IWL_RATE_COUNT] = { |
196 | {0, 0, 0, 0, 74, 0, 123, 155, 179, 213, 235, 243, 250}, /* Norm */ | 196 | {0, 0, 0, 0, 74, 0, 123, 155, 179, 214, 236, 244, 251}, /* Norm */ |
197 | {0, 0, 0, 0, 81, 0, 131, 164, 187, 221, 242, 250, 256}, /* SGI */ | 197 | {0, 0, 0, 0, 81, 0, 131, 164, 188, 223, 243, 251, 257}, /* SGI */ |
198 | {0, 0, 0, 0, 92, 0, 175, 250, 317, 436, 534, 578, 619}, /* AGG */ | 198 | {0, 0, 0, 0, 89, 0, 167, 235, 296, 402, 488, 526, 560}, /* AGG */ |
199 | {0, 0, 0, 0, 102, 0, 192, 273, 344, 470, 573, 619, 660}, /* AGG+SGI*/ | 199 | {0, 0, 0, 0, 97, 0, 182, 255, 320, 431, 520, 558, 593}, /* AGG+SGI*/ |
200 | }; | 200 | }; |
201 | 201 | ||
202 | static s32 expected_tpt_mimo2_40MHz[4][IWL_RATE_COUNT] = { | 202 | static s32 expected_tpt_mimo2_40MHz[4][IWL_RATE_COUNT] = { |
203 | {0, 0, 0, 0, 123, 0, 182, 214, 235, 264, 279, 285, 289}, /* Norm */ | 203 | {0, 0, 0, 0, 123, 0, 182, 214, 235, 264, 279, 285, 289}, /* Norm */ |
204 | {0, 0, 0, 0, 131, 0, 191, 222, 242, 270, 284, 289, 293}, /* SGI */ | 204 | {0, 0, 0, 0, 131, 0, 191, 222, 242, 270, 284, 289, 293}, /* SGI */ |
205 | {0, 0, 0, 0, 180, 0, 327, 446, 545, 708, 828, 878, 922}, /* AGG */ | 205 | {0, 0, 0, 0, 171, 0, 305, 410, 496, 634, 731, 771, 805}, /* AGG */ |
206 | {0, 0, 0, 0, 197, 0, 355, 481, 584, 752, 872, 922, 966}, /* AGG+SGI */ | 206 | {0, 0, 0, 0, 186, 0, 329, 439, 527, 667, 764, 803, 838}, /* AGG+SGI */ |
207 | }; | 207 | }; |
208 | 208 | ||
209 | static s32 expected_tpt_mimo3_20MHz[4][IWL_RATE_COUNT] = { | 209 | static s32 expected_tpt_mimo3_20MHz[4][IWL_RATE_COUNT] = { |
@@ -2890,6 +2890,8 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, | |||
2890 | u8 ant_toggle_cnt = 0; | 2890 | u8 ant_toggle_cnt = 0; |
2891 | u8 use_ht_possible = 1; | 2891 | u8 use_ht_possible = 1; |
2892 | u8 valid_tx_ant = 0; | 2892 | u8 valid_tx_ant = 0; |
2893 | struct iwl_station_priv *sta_priv = | ||
2894 | container_of(lq_sta, struct iwl_station_priv, lq_sta); | ||
2893 | struct iwl_link_quality_cmd *lq_cmd = &lq_sta->lq; | 2895 | struct iwl_link_quality_cmd *lq_cmd = &lq_sta->lq; |
2894 | 2896 | ||
2895 | /* Override starting rate (index 0) if needed for debug purposes */ | 2897 | /* Override starting rate (index 0) if needed for debug purposes */ |
@@ -3008,7 +3010,8 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, | |||
3008 | repeat_rate--; | 3010 | repeat_rate--; |
3009 | } | 3011 | } |
3010 | 3012 | ||
3011 | lq_cmd->agg_params.agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_DEF; | 3013 | lq_cmd->agg_params.agg_frame_cnt_limit = |
3014 | sta_priv->max_agg_bufsize ?: LINK_QUAL_AGG_FRAME_LIMIT_DEF; | ||
3012 | lq_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF; | 3015 | lq_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF; |
3013 | 3016 | ||
3014 | lq_cmd->agg_params.agg_time_limit = | 3017 | lq_cmd->agg_params.agg_time_limit = |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index 24dabcd2a36c..d807e5e2b718 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | |||
@@ -308,14 +308,6 @@ void iwlagn_init_alive_start(struct iwl_priv *priv) | |||
308 | { | 308 | { |
309 | int ret = 0; | 309 | int ret = 0; |
310 | 310 | ||
311 | /* Check alive response for "valid" sign from uCode */ | ||
312 | if (priv->card_alive_init.is_valid != UCODE_VALID_OK) { | ||
313 | /* We had an error bringing up the hardware, so take it | ||
314 | * all the way back down so we can try again */ | ||
315 | IWL_DEBUG_INFO(priv, "Initialize Alive failed.\n"); | ||
316 | goto restart; | ||
317 | } | ||
318 | |||
319 | /* initialize uCode was loaded... verify inst image. | 311 | /* initialize uCode was loaded... verify inst image. |
320 | * This is a paranoid check, because we would not have gotten the | 312 | * This is a paranoid check, because we would not have gotten the |
321 | * "initialize" alive if code weren't properly loaded. */ | 313 | * "initialize" alive if code weren't properly loaded. */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 646ccb2430b4..096f8ad0f1b1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -462,8 +462,12 @@ static void iwl_rx_reply_alive(struct iwl_priv *priv, | |||
462 | if (palive->is_valid == UCODE_VALID_OK) | 462 | if (palive->is_valid == UCODE_VALID_OK) |
463 | queue_delayed_work(priv->workqueue, pwork, | 463 | queue_delayed_work(priv->workqueue, pwork, |
464 | msecs_to_jiffies(5)); | 464 | msecs_to_jiffies(5)); |
465 | else | 465 | else { |
466 | IWL_WARN(priv, "uCode did not respond OK.\n"); | 466 | IWL_WARN(priv, "%s uCode did not respond OK.\n", |
467 | (palive->ver_subtype == INITIALIZE_SUBTYPE) ? | ||
468 | "init" : "runtime"); | ||
469 | queue_work(priv->workqueue, &priv->restart); | ||
470 | } | ||
467 | } | 471 | } |
468 | 472 | ||
469 | static void iwl_bg_beacon_update(struct work_struct *work) | 473 | static void iwl_bg_beacon_update(struct work_struct *work) |
@@ -700,18 +704,18 @@ static void iwl_bg_ucode_trace(unsigned long data) | |||
700 | } | 704 | } |
701 | } | 705 | } |
702 | 706 | ||
703 | static void iwl_rx_beacon_notif(struct iwl_priv *priv, | 707 | static void iwlagn_rx_beacon_notif(struct iwl_priv *priv, |
704 | struct iwl_rx_mem_buffer *rxb) | 708 | struct iwl_rx_mem_buffer *rxb) |
705 | { | 709 | { |
706 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 710 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
707 | struct iwl4965_beacon_notif *beacon = | 711 | struct iwlagn_beacon_notif *beacon = (void *)pkt->u.raw; |
708 | (struct iwl4965_beacon_notif *)pkt->u.raw; | ||
709 | #ifdef CONFIG_IWLWIFI_DEBUG | 712 | #ifdef CONFIG_IWLWIFI_DEBUG |
713 | u16 status = le16_to_cpu(beacon->beacon_notify_hdr.status.status); | ||
710 | u8 rate = iwl_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags); | 714 | u8 rate = iwl_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags); |
711 | 715 | ||
712 | IWL_DEBUG_RX(priv, "beacon status %x retries %d iss %d " | 716 | IWL_DEBUG_RX(priv, "beacon status %#x, retries:%d ibssmgr:%d " |
713 | "tsf %d %d rate %d\n", | 717 | "tsf:0x%.8x%.8x rate:%d\n", |
714 | le32_to_cpu(beacon->beacon_notify_hdr.u.status) & TX_STATUS_MSK, | 718 | status & TX_STATUS_MSK, |
715 | beacon->beacon_notify_hdr.failure_frame, | 719 | beacon->beacon_notify_hdr.failure_frame, |
716 | le32_to_cpu(beacon->ibss_mgr_status), | 720 | le32_to_cpu(beacon->ibss_mgr_status), |
717 | le32_to_cpu(beacon->high_tsf), | 721 | le32_to_cpu(beacon->high_tsf), |
@@ -814,7 +818,7 @@ static void iwl_setup_rx_handlers(struct iwl_priv *priv) | |||
814 | priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif; | 818 | priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif; |
815 | priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] = | 819 | priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] = |
816 | iwl_rx_pm_debug_statistics_notif; | 820 | iwl_rx_pm_debug_statistics_notif; |
817 | priv->rx_handlers[BEACON_NOTIFICATION] = iwl_rx_beacon_notif; | 821 | priv->rx_handlers[BEACON_NOTIFICATION] = iwlagn_rx_beacon_notif; |
818 | 822 | ||
819 | /* | 823 | /* |
820 | * The same handler is used for both the REPLY to a discrete | 824 | * The same handler is used for both the REPLY to a discrete |
@@ -2648,13 +2652,6 @@ static void iwl_alive_start(struct iwl_priv *priv) | |||
2648 | 2652 | ||
2649 | IWL_DEBUG_INFO(priv, "Runtime Alive received.\n"); | 2653 | IWL_DEBUG_INFO(priv, "Runtime Alive received.\n"); |
2650 | 2654 | ||
2651 | if (priv->card_alive.is_valid != UCODE_VALID_OK) { | ||
2652 | /* We had an error bringing up the hardware, so take it | ||
2653 | * all the way back down so we can try again */ | ||
2654 | IWL_DEBUG_INFO(priv, "Alive failed.\n"); | ||
2655 | goto restart; | ||
2656 | } | ||
2657 | |||
2658 | /* Initialize uCode has loaded Runtime uCode ... verify inst image. | 2655 | /* Initialize uCode has loaded Runtime uCode ... verify inst image. |
2659 | * This is a paranoid check, because we would not have gotten the | 2656 | * This is a paranoid check, because we would not have gotten the |
2660 | * "runtime" alive if code weren't properly loaded. */ | 2657 | * "runtime" alive if code weren't properly loaded. */ |
@@ -2783,7 +2780,6 @@ static void __iwl_down(struct iwl_priv *priv) | |||
2783 | priv->cfg->bt_params->bt_init_traffic_load; | 2780 | priv->cfg->bt_params->bt_init_traffic_load; |
2784 | else | 2781 | else |
2785 | priv->bt_traffic_load = 0; | 2782 | priv->bt_traffic_load = 0; |
2786 | priv->bt_sco_active = false; | ||
2787 | priv->bt_full_concurrent = false; | 2783 | priv->bt_full_concurrent = false; |
2788 | priv->bt_ci_compliance = 0; | 2784 | priv->bt_ci_compliance = 0; |
2789 | 2785 | ||
@@ -3102,7 +3098,7 @@ static void iwl_bg_restart(struct work_struct *data) | |||
3102 | 3098 | ||
3103 | if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) { | 3099 | if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) { |
3104 | struct iwl_rxon_context *ctx; | 3100 | struct iwl_rxon_context *ctx; |
3105 | bool bt_sco, bt_full_concurrent; | 3101 | bool bt_full_concurrent; |
3106 | u8 bt_ci_compliance; | 3102 | u8 bt_ci_compliance; |
3107 | u8 bt_load; | 3103 | u8 bt_load; |
3108 | u8 bt_status; | 3104 | u8 bt_status; |
@@ -3121,7 +3117,6 @@ static void iwl_bg_restart(struct work_struct *data) | |||
3121 | * re-configure the hw when we reconfigure the BT | 3117 | * re-configure the hw when we reconfigure the BT |
3122 | * command. | 3118 | * command. |
3123 | */ | 3119 | */ |
3124 | bt_sco = priv->bt_sco_active; | ||
3125 | bt_full_concurrent = priv->bt_full_concurrent; | 3120 | bt_full_concurrent = priv->bt_full_concurrent; |
3126 | bt_ci_compliance = priv->bt_ci_compliance; | 3121 | bt_ci_compliance = priv->bt_ci_compliance; |
3127 | bt_load = priv->bt_traffic_load; | 3122 | bt_load = priv->bt_traffic_load; |
@@ -3129,7 +3124,6 @@ static void iwl_bg_restart(struct work_struct *data) | |||
3129 | 3124 | ||
3130 | __iwl_down(priv); | 3125 | __iwl_down(priv); |
3131 | 3126 | ||
3132 | priv->bt_sco_active = bt_sco; | ||
3133 | priv->bt_full_concurrent = bt_full_concurrent; | 3127 | priv->bt_full_concurrent = bt_full_concurrent; |
3134 | priv->bt_ci_compliance = bt_ci_compliance; | 3128 | priv->bt_ci_compliance = bt_ci_compliance; |
3135 | priv->bt_traffic_load = bt_load; | 3129 | priv->bt_traffic_load = bt_load; |
@@ -3191,6 +3185,8 @@ static int iwl_mac_setup_register(struct iwl_priv *priv, | |||
3191 | IEEE80211_HW_SPECTRUM_MGMT | | 3185 | IEEE80211_HW_SPECTRUM_MGMT | |
3192 | IEEE80211_HW_REPORTS_TX_ACK_STATUS; | 3186 | IEEE80211_HW_REPORTS_TX_ACK_STATUS; |
3193 | 3187 | ||
3188 | hw->max_tx_aggregation_subframes = LINK_QUAL_AGG_FRAME_LIMIT_DEF; | ||
3189 | |||
3194 | if (!priv->cfg->base_params->broken_powersave) | 3190 | if (!priv->cfg->base_params->broken_powersave) |
3195 | hw->flags |= IEEE80211_HW_SUPPORTS_PS | | 3191 | hw->flags |= IEEE80211_HW_SUPPORTS_PS | |
3196 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS; | 3192 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS; |
@@ -3210,7 +3206,8 @@ static int iwl_mac_setup_register(struct iwl_priv *priv, | |||
3210 | hw->wiphy->max_remain_on_channel_duration = 1000; | 3206 | hw->wiphy->max_remain_on_channel_duration = 1000; |
3211 | 3207 | ||
3212 | hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY | | 3208 | hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY | |
3213 | WIPHY_FLAG_DISABLE_BEACON_HINTS; | 3209 | WIPHY_FLAG_DISABLE_BEACON_HINTS | |
3210 | WIPHY_FLAG_IBSS_RSN; | ||
3214 | 3211 | ||
3215 | /* | 3212 | /* |
3216 | * For now, disable PS by default because it affects | 3213 | * For now, disable PS by default because it affects |
@@ -3362,6 +3359,14 @@ int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
3362 | return -EOPNOTSUPP; | 3359 | return -EOPNOTSUPP; |
3363 | } | 3360 | } |
3364 | 3361 | ||
3362 | /* | ||
3363 | * To support IBSS RSN, don't program group keys in IBSS, the | ||
3364 | * hardware will then not attempt to decrypt the frames. | ||
3365 | */ | ||
3366 | if (vif->type == NL80211_IFTYPE_ADHOC && | ||
3367 | !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) | ||
3368 | return -EOPNOTSUPP; | ||
3369 | |||
3365 | sta_id = iwl_sta_id_or_broadcast(priv, vif_priv->ctx, sta); | 3370 | sta_id = iwl_sta_id_or_broadcast(priv, vif_priv->ctx, sta); |
3366 | if (sta_id == IWL_INVALID_STATION) | 3371 | if (sta_id == IWL_INVALID_STATION) |
3367 | return -EINVAL; | 3372 | return -EINVAL; |
@@ -3421,6 +3426,7 @@ int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, | |||
3421 | { | 3426 | { |
3422 | struct iwl_priv *priv = hw->priv; | 3427 | struct iwl_priv *priv = hw->priv; |
3423 | int ret = -EINVAL; | 3428 | int ret = -EINVAL; |
3429 | struct iwl_station_priv *sta_priv = (void *) sta->drv_priv; | ||
3424 | 3430 | ||
3425 | IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n", | 3431 | IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n", |
3426 | sta->addr, tid); | 3432 | sta->addr, tid); |
@@ -3475,11 +3481,28 @@ int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, | |||
3475 | } | 3481 | } |
3476 | break; | 3482 | break; |
3477 | case IEEE80211_AMPDU_TX_OPERATIONAL: | 3483 | case IEEE80211_AMPDU_TX_OPERATIONAL: |
3484 | /* | ||
3485 | * If the limit is 0, then it wasn't initialised yet, | ||
3486 | * use the default. We can do that since we take the | ||
3487 | * minimum below, and we don't want to go above our | ||
3488 | * default due to hardware restrictions. | ||
3489 | */ | ||
3490 | if (sta_priv->max_agg_bufsize == 0) | ||
3491 | sta_priv->max_agg_bufsize = | ||
3492 | LINK_QUAL_AGG_FRAME_LIMIT_DEF; | ||
3493 | |||
3494 | /* | ||
3495 | * Even though in theory the peer could have different | ||
3496 | * aggregation reorder buffer sizes for different sessions, | ||
3497 | * our ucode doesn't allow for that and has a global limit | ||
3498 | * for each station. Therefore, use the minimum of all the | ||
3499 | * aggregation sessions and our default value. | ||
3500 | */ | ||
3501 | sta_priv->max_agg_bufsize = | ||
3502 | min(sta_priv->max_agg_bufsize, buf_size); | ||
3503 | |||
3478 | if (priv->cfg->ht_params && | 3504 | if (priv->cfg->ht_params && |
3479 | priv->cfg->ht_params->use_rts_for_aggregation) { | 3505 | priv->cfg->ht_params->use_rts_for_aggregation) { |
3480 | struct iwl_station_priv *sta_priv = | ||
3481 | (void *) sta->drv_priv; | ||
3482 | |||
3483 | /* | 3506 | /* |
3484 | * switch to RTS/CTS if it is the prefer protection | 3507 | * switch to RTS/CTS if it is the prefer protection |
3485 | * method for HT traffic | 3508 | * method for HT traffic |
@@ -3487,9 +3510,13 @@ int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, | |||
3487 | 3510 | ||
3488 | sta_priv->lq_sta.lq.general_params.flags |= | 3511 | sta_priv->lq_sta.lq.general_params.flags |= |
3489 | LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK; | 3512 | LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK; |
3490 | iwl_send_lq_cmd(priv, iwl_rxon_ctx_from_vif(vif), | ||
3491 | &sta_priv->lq_sta.lq, CMD_ASYNC, false); | ||
3492 | } | 3513 | } |
3514 | |||
3515 | sta_priv->lq_sta.lq.agg_params.agg_frame_cnt_limit = | ||
3516 | sta_priv->max_agg_bufsize; | ||
3517 | |||
3518 | iwl_send_lq_cmd(priv, iwl_rxon_ctx_from_vif(vif), | ||
3519 | &sta_priv->lq_sta.lq, CMD_ASYNC, false); | ||
3493 | ret = 0; | 3520 | ret = 0; |
3494 | break; | 3521 | break; |
3495 | } | 3522 | } |
@@ -3744,7 +3771,7 @@ static void iwlagn_disable_roc(struct iwl_priv *priv) | |||
3744 | 3771 | ||
3745 | priv->_agn.hw_roc_channel = NULL; | 3772 | priv->_agn.hw_roc_channel = NULL; |
3746 | 3773 | ||
3747 | iwlagn_commit_rxon(priv, ctx); | 3774 | iwlcore_commit_rxon(priv, ctx); |
3748 | 3775 | ||
3749 | ctx->is_active = false; | 3776 | ctx->is_active = false; |
3750 | } | 3777 | } |
@@ -3760,6 +3787,7 @@ static void iwlagn_bg_roc_done(struct work_struct *work) | |||
3760 | mutex_unlock(&priv->mutex); | 3787 | mutex_unlock(&priv->mutex); |
3761 | } | 3788 | } |
3762 | 3789 | ||
3790 | #ifdef CONFIG_IWL5000 | ||
3763 | static int iwl_mac_remain_on_channel(struct ieee80211_hw *hw, | 3791 | static int iwl_mac_remain_on_channel(struct ieee80211_hw *hw, |
3764 | struct ieee80211_channel *channel, | 3792 | struct ieee80211_channel *channel, |
3765 | enum nl80211_channel_type channel_type, | 3793 | enum nl80211_channel_type channel_type, |
@@ -3787,7 +3815,7 @@ static int iwl_mac_remain_on_channel(struct ieee80211_hw *hw, | |||
3787 | priv->_agn.hw_roc_channel = channel; | 3815 | priv->_agn.hw_roc_channel = channel; |
3788 | priv->_agn.hw_roc_chantype = channel_type; | 3816 | priv->_agn.hw_roc_chantype = channel_type; |
3789 | priv->_agn.hw_roc_duration = DIV_ROUND_UP(duration * 1000, 1024); | 3817 | priv->_agn.hw_roc_duration = DIV_ROUND_UP(duration * 1000, 1024); |
3790 | iwlagn_commit_rxon(priv, &priv->contexts[IWL_RXON_CTX_PAN]); | 3818 | iwlcore_commit_rxon(priv, &priv->contexts[IWL_RXON_CTX_PAN]); |
3791 | queue_delayed_work(priv->workqueue, &priv->_agn.hw_roc_work, | 3819 | queue_delayed_work(priv->workqueue, &priv->_agn.hw_roc_work, |
3792 | msecs_to_jiffies(duration + 20)); | 3820 | msecs_to_jiffies(duration + 20)); |
3793 | 3821 | ||
@@ -3815,6 +3843,7 @@ static int iwl_mac_cancel_remain_on_channel(struct ieee80211_hw *hw) | |||
3815 | 3843 | ||
3816 | return 0; | 3844 | return 0; |
3817 | } | 3845 | } |
3846 | #endif | ||
3818 | 3847 | ||
3819 | /***************************************************************************** | 3848 | /***************************************************************************** |
3820 | * | 3849 | * |
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 935b19e2c260..0a1d4aeb36aa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h | |||
@@ -178,7 +178,6 @@ enum { | |||
178 | REPLY_BT_COEX_PRIO_TABLE = 0xcc, | 178 | REPLY_BT_COEX_PRIO_TABLE = 0xcc, |
179 | REPLY_BT_COEX_PROT_ENV = 0xcd, | 179 | REPLY_BT_COEX_PROT_ENV = 0xcd, |
180 | REPLY_BT_COEX_PROFILE_NOTIF = 0xce, | 180 | REPLY_BT_COEX_PROFILE_NOTIF = 0xce, |
181 | REPLY_BT_COEX_SCO = 0xcf, | ||
182 | 181 | ||
183 | /* PAN commands */ | 182 | /* PAN commands */ |
184 | REPLY_WIPAN_PARAMS = 0xb2, | 183 | REPLY_WIPAN_PARAMS = 0xb2, |
@@ -3083,6 +3082,13 @@ struct iwl4965_beacon_notif { | |||
3083 | __le32 ibss_mgr_status; | 3082 | __le32 ibss_mgr_status; |
3084 | } __packed; | 3083 | } __packed; |
3085 | 3084 | ||
3085 | struct iwlagn_beacon_notif { | ||
3086 | struct iwlagn_tx_resp beacon_notify_hdr; | ||
3087 | __le32 low_tsf; | ||
3088 | __le32 high_tsf; | ||
3089 | __le32 ibss_mgr_status; | ||
3090 | } __packed; | ||
3091 | |||
3086 | /* | 3092 | /* |
3087 | * REPLY_TX_BEACON = 0x91 (command, has simple generic response) | 3093 | * REPLY_TX_BEACON = 0x91 (command, has simple generic response) |
3088 | */ | 3094 | */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index c83fcc60ccc5..e0ec17079dc0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -305,7 +305,6 @@ struct iwl_base_params { | |||
305 | u16 led_compensation; | 305 | u16 led_compensation; |
306 | const bool broken_powersave; | 306 | const bool broken_powersave; |
307 | int chain_noise_num_beacons; | 307 | int chain_noise_num_beacons; |
308 | const bool supports_idle; | ||
309 | bool adv_thermal_throttle; | 308 | bool adv_thermal_throttle; |
310 | bool support_ct_kill_exit; | 309 | bool support_ct_kill_exit; |
311 | const bool support_wimax_coexist; | 310 | const bool support_wimax_coexist; |
@@ -364,6 +363,7 @@ struct iwl_ht_params { | |||
364 | * @adv_pm: advance power management | 363 | * @adv_pm: advance power management |
365 | * @rx_with_siso_diversity: 1x1 device with rx antenna diversity | 364 | * @rx_with_siso_diversity: 1x1 device with rx antenna diversity |
366 | * @internal_wimax_coex: internal wifi/wimax combo device | 365 | * @internal_wimax_coex: internal wifi/wimax combo device |
366 | * @iq_invert: I/Q inversion | ||
367 | * | 367 | * |
368 | * We enable the driver to be backward compatible wrt API version. The | 368 | * We enable the driver to be backward compatible wrt API version. The |
369 | * driver specifies which APIs it supports (with @ucode_api_max being the | 369 | * driver specifies which APIs it supports (with @ucode_api_max being the |
@@ -413,6 +413,7 @@ struct iwl_cfg { | |||
413 | const bool adv_pm; | 413 | const bool adv_pm; |
414 | const bool rx_with_siso_diversity; | 414 | const bool rx_with_siso_diversity; |
415 | const bool internal_wimax_coex; | 415 | const bool internal_wimax_coex; |
416 | const bool iq_invert; | ||
416 | }; | 417 | }; |
417 | 418 | ||
418 | /*************************** | 419 | /*************************** |
diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index 6c2b2df7ee7e..f52bc040bcbf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h | |||
@@ -382,6 +382,8 @@ | |||
382 | #define CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6 (0x00000004) | 382 | #define CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6 (0x00000004) |
383 | #define CSR_GP_DRIVER_REG_BIT_6050_1x2 (0x00000008) | 383 | #define CSR_GP_DRIVER_REG_BIT_6050_1x2 (0x00000008) |
384 | 384 | ||
385 | #define CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER (0x00000080) | ||
386 | |||
385 | /* GIO Chicken Bits (PCI Express bus link power management) */ | 387 | /* GIO Chicken Bits (PCI Express bus link power management) */ |
386 | #define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX (0x00800000) | 388 | #define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX (0x00800000) |
387 | #define CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER (0x20000000) | 389 | #define CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER (0x20000000) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index bdcb74279f1e..bc7a965c18f9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c | |||
@@ -1587,10 +1587,9 @@ static ssize_t iwl_dbgfs_bt_traffic_read(struct file *file, | |||
1587 | "last traffic notif: %d\n", | 1587 | "last traffic notif: %d\n", |
1588 | priv->bt_status ? "On" : "Off", priv->last_bt_traffic_load); | 1588 | priv->bt_status ? "On" : "Off", priv->last_bt_traffic_load); |
1589 | pos += scnprintf(buf + pos, bufsz - pos, "ch_announcement: %d, " | 1589 | pos += scnprintf(buf + pos, bufsz - pos, "ch_announcement: %d, " |
1590 | "sco_active: %d, kill_ack_mask: %x, " | 1590 | "kill_ack_mask: %x, kill_cts_mask: %x\n", |
1591 | "kill_cts_mask: %x\n", | 1591 | priv->bt_ch_announce, priv->kill_ack_mask, |
1592 | priv->bt_ch_announce, priv->bt_sco_active, | 1592 | priv->kill_cts_mask); |
1593 | priv->kill_ack_mask, priv->kill_cts_mask); | ||
1594 | 1593 | ||
1595 | pos += scnprintf(buf + pos, bufsz - pos, "bluetooth traffic load: "); | 1594 | pos += scnprintf(buf + pos, bufsz - pos, "bluetooth traffic load: "); |
1596 | switch (priv->bt_traffic_load) { | 1595 | switch (priv->bt_traffic_load) { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index b5f21e041953..ecfbef402781 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -509,6 +509,7 @@ struct iwl_station_priv { | |||
509 | atomic_t pending_frames; | 509 | atomic_t pending_frames; |
510 | bool client; | 510 | bool client; |
511 | bool asleep; | 511 | bool asleep; |
512 | u8 max_agg_bufsize; | ||
512 | }; | 513 | }; |
513 | 514 | ||
514 | /** | 515 | /** |
@@ -1503,7 +1504,6 @@ struct iwl_priv { | |||
1503 | u8 bt_status; | 1504 | u8 bt_status; |
1504 | u8 bt_traffic_load, last_bt_traffic_load; | 1505 | u8 bt_traffic_load, last_bt_traffic_load; |
1505 | bool bt_ch_announce; | 1506 | bool bt_ch_announce; |
1506 | bool bt_sco_active; | ||
1507 | bool bt_full_concurrent; | 1507 | bool bt_full_concurrent; |
1508 | bool bt_ant_couple_ok; | 1508 | bool bt_ant_couple_ok; |
1509 | __le32 kill_ack_mask; | 1509 | __le32 kill_ack_mask; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index 25f7d474f346..1d1bf3234d8d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c | |||
@@ -356,8 +356,7 @@ static void iwl_power_build_cmd(struct iwl_priv *priv, | |||
356 | 356 | ||
357 | if (priv->cfg->base_params->broken_powersave) | 357 | if (priv->cfg->base_params->broken_powersave) |
358 | iwl_power_sleep_cam_cmd(priv, cmd); | 358 | iwl_power_sleep_cam_cmd(priv, cmd); |
359 | else if (priv->cfg->base_params->supports_idle && | 359 | else if (priv->hw->conf.flags & IEEE80211_CONF_IDLE) |
360 | priv->hw->conf.flags & IEEE80211_CONF_IDLE) | ||
361 | iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, 20); | 360 | iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, 20); |
362 | else if (priv->cfg->ops->lib->tt_ops.lower_power_detection && | 361 | else if (priv->cfg->ops->lib->tt_ops.lower_power_detection && |
363 | priv->cfg->ops->lib->tt_ops.tt_power_mode && | 362 | priv->cfg->ops->lib->tt_ops.tt_power_mode && |
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 2945acd955f0..adcef735180a 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
@@ -2860,16 +2860,13 @@ int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
2860 | u32 extra; | 2860 | u32 extra; |
2861 | u32 suspend_time = 100; | 2861 | u32 suspend_time = 100; |
2862 | u32 scan_suspend_time = 100; | 2862 | u32 scan_suspend_time = 100; |
2863 | unsigned long flags; | ||
2864 | 2863 | ||
2865 | IWL_DEBUG_INFO(priv, "Scanning while associated...\n"); | 2864 | IWL_DEBUG_INFO(priv, "Scanning while associated...\n"); |
2866 | 2865 | ||
2867 | spin_lock_irqsave(&priv->lock, flags); | ||
2868 | if (priv->is_internal_short_scan) | 2866 | if (priv->is_internal_short_scan) |
2869 | interval = 0; | 2867 | interval = 0; |
2870 | else | 2868 | else |
2871 | interval = vif->bss_conf.beacon_int; | 2869 | interval = vif->bss_conf.beacon_int; |
2872 | spin_unlock_irqrestore(&priv->lock, flags); | ||
2873 | 2870 | ||
2874 | scan->suspend_time = 0; | 2871 | scan->suspend_time = 0; |
2875 | scan->max_out_time = cpu_to_le32(200 * 1024); | 2872 | scan->max_out_time = cpu_to_le32(200 * 1024); |
@@ -3286,6 +3283,14 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
3286 | return -EOPNOTSUPP; | 3283 | return -EOPNOTSUPP; |
3287 | } | 3284 | } |
3288 | 3285 | ||
3286 | /* | ||
3287 | * To support IBSS RSN, don't program group keys in IBSS, the | ||
3288 | * hardware will then not attempt to decrypt the frames. | ||
3289 | */ | ||
3290 | if (vif->type == NL80211_IFTYPE_ADHOC && | ||
3291 | !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) | ||
3292 | return -EOPNOTSUPP; | ||
3293 | |||
3289 | static_key = !iwl_is_associated(priv, IWL_RXON_CTX_BSS); | 3294 | static_key = !iwl_is_associated(priv, IWL_RXON_CTX_BSS); |
3290 | 3295 | ||
3291 | if (!static_key) { | 3296 | if (!static_key) { |
@@ -3915,7 +3920,8 @@ static int iwl3945_setup_mac(struct iwl_priv *priv) | |||
3915 | priv->contexts[IWL_RXON_CTX_BSS].interface_modes; | 3920 | priv->contexts[IWL_RXON_CTX_BSS].interface_modes; |
3916 | 3921 | ||
3917 | hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY | | 3922 | hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY | |
3918 | WIPHY_FLAG_DISABLE_BEACON_HINTS; | 3923 | WIPHY_FLAG_DISABLE_BEACON_HINTS | |
3924 | WIPHY_FLAG_IBSS_RSN; | ||
3919 | 3925 | ||
3920 | hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX_3945; | 3926 | hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX_3945; |
3921 | /* we create the 802.11 header and a zero-length SSID element */ | 3927 | /* we create the 802.11 header and a zero-length SSID element */ |
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index 78c4da150a74..7e8a658b7670 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c | |||
@@ -145,9 +145,13 @@ int lbs_update_hw_spec(struct lbs_private *priv) | |||
145 | if (priv->current_addr[0] == 0xff) | 145 | if (priv->current_addr[0] == 0xff) |
146 | memmove(priv->current_addr, cmd.permanentaddr, ETH_ALEN); | 146 | memmove(priv->current_addr, cmd.permanentaddr, ETH_ALEN); |
147 | 147 | ||
148 | memcpy(priv->dev->dev_addr, priv->current_addr, ETH_ALEN); | 148 | if (!priv->copied_hwaddr) { |
149 | if (priv->mesh_dev) | 149 | memcpy(priv->dev->dev_addr, priv->current_addr, ETH_ALEN); |
150 | memcpy(priv->mesh_dev->dev_addr, priv->current_addr, ETH_ALEN); | 150 | if (priv->mesh_dev) |
151 | memcpy(priv->mesh_dev->dev_addr, | ||
152 | priv->current_addr, ETH_ALEN); | ||
153 | priv->copied_hwaddr = 1; | ||
154 | } | ||
151 | 155 | ||
152 | out: | 156 | out: |
153 | lbs_deb_leave(LBS_DEB_CMD); | 157 | lbs_deb_leave(LBS_DEB_CMD); |
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index 18dd9a02c459..bc461eb39660 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h | |||
@@ -90,6 +90,7 @@ struct lbs_private { | |||
90 | void *card; | 90 | void *card; |
91 | u8 fw_ready; | 91 | u8 fw_ready; |
92 | u8 surpriseremoved; | 92 | u8 surpriseremoved; |
93 | u8 setup_fw_on_resume; | ||
93 | int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb); | 94 | int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb); |
94 | void (*reset_card) (struct lbs_private *priv); | 95 | void (*reset_card) (struct lbs_private *priv); |
95 | int (*enter_deep_sleep) (struct lbs_private *priv); | 96 | int (*enter_deep_sleep) (struct lbs_private *priv); |
@@ -101,6 +102,7 @@ struct lbs_private { | |||
101 | u32 fwcapinfo; | 102 | u32 fwcapinfo; |
102 | u16 regioncode; | 103 | u16 regioncode; |
103 | u8 current_addr[ETH_ALEN]; | 104 | u8 current_addr[ETH_ALEN]; |
105 | u8 copied_hwaddr; | ||
104 | 106 | ||
105 | /* Command download */ | 107 | /* Command download */ |
106 | u8 dnld_sent; | 108 | u8 dnld_sent; |
diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c index 00600239a053..f6c2cd665f49 100644 --- a/drivers/net/wireless/libertas/if_spi.c +++ b/drivers/net/wireless/libertas/if_spi.c | |||
@@ -20,10 +20,8 @@ | |||
20 | #include <linux/moduleparam.h> | 20 | #include <linux/moduleparam.h> |
21 | #include <linux/firmware.h> | 21 | #include <linux/firmware.h> |
22 | #include <linux/jiffies.h> | 22 | #include <linux/jiffies.h> |
23 | #include <linux/kthread.h> | ||
24 | #include <linux/list.h> | 23 | #include <linux/list.h> |
25 | #include <linux/netdevice.h> | 24 | #include <linux/netdevice.h> |
26 | #include <linux/semaphore.h> | ||
27 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
28 | #include <linux/spi/libertas_spi.h> | 26 | #include <linux/spi/libertas_spi.h> |
29 | #include <linux/spi/spi.h> | 27 | #include <linux/spi/spi.h> |
@@ -34,6 +32,12 @@ | |||
34 | #include "dev.h" | 32 | #include "dev.h" |
35 | #include "if_spi.h" | 33 | #include "if_spi.h" |
36 | 34 | ||
35 | struct if_spi_packet { | ||
36 | struct list_head list; | ||
37 | u16 blen; | ||
38 | u8 buffer[0] __attribute__((aligned(4))); | ||
39 | }; | ||
40 | |||
37 | struct if_spi_card { | 41 | struct if_spi_card { |
38 | struct spi_device *spi; | 42 | struct spi_device *spi; |
39 | struct lbs_private *priv; | 43 | struct lbs_private *priv; |
@@ -51,18 +55,36 @@ struct if_spi_card { | |||
51 | unsigned long spu_reg_delay; | 55 | unsigned long spu_reg_delay; |
52 | 56 | ||
53 | /* Handles all SPI communication (except for FW load) */ | 57 | /* Handles all SPI communication (except for FW load) */ |
54 | struct task_struct *spi_thread; | 58 | struct workqueue_struct *workqueue; |
55 | int run_thread; | 59 | struct work_struct packet_work; |
56 | |||
57 | /* Used to wake up the spi_thread */ | ||
58 | struct semaphore spi_ready; | ||
59 | struct semaphore spi_thread_terminated; | ||
60 | 60 | ||
61 | u8 cmd_buffer[IF_SPI_CMD_BUF_SIZE]; | 61 | u8 cmd_buffer[IF_SPI_CMD_BUF_SIZE]; |
62 | |||
63 | /* A buffer of incoming packets from libertas core. | ||
64 | * Since we can't sleep in hw_host_to_card, we have to buffer | ||
65 | * them. */ | ||
66 | struct list_head cmd_packet_list; | ||
67 | struct list_head data_packet_list; | ||
68 | |||
69 | /* Protects cmd_packet_list and data_packet_list */ | ||
70 | spinlock_t buffer_lock; | ||
62 | }; | 71 | }; |
63 | 72 | ||
64 | static void free_if_spi_card(struct if_spi_card *card) | 73 | static void free_if_spi_card(struct if_spi_card *card) |
65 | { | 74 | { |
75 | struct list_head *cursor, *next; | ||
76 | struct if_spi_packet *packet; | ||
77 | |||
78 | list_for_each_safe(cursor, next, &card->cmd_packet_list) { | ||
79 | packet = container_of(cursor, struct if_spi_packet, list); | ||
80 | list_del(&packet->list); | ||
81 | kfree(packet); | ||
82 | } | ||
83 | list_for_each_safe(cursor, next, &card->data_packet_list) { | ||
84 | packet = container_of(cursor, struct if_spi_packet, list); | ||
85 | list_del(&packet->list); | ||
86 | kfree(packet); | ||
87 | } | ||
66 | spi_set_drvdata(card->spi, NULL); | 88 | spi_set_drvdata(card->spi, NULL); |
67 | kfree(card); | 89 | kfree(card); |
68 | } | 90 | } |
@@ -622,7 +644,7 @@ out: | |||
622 | /* | 644 | /* |
623 | * SPI Transfer Thread | 645 | * SPI Transfer Thread |
624 | * | 646 | * |
625 | * The SPI thread handles all SPI transfers, so there is no need for a lock. | 647 | * The SPI worker handles all SPI transfers, so there is no need for a lock. |
626 | */ | 648 | */ |
627 | 649 | ||
628 | /* Move a command from the card to the host */ | 650 | /* Move a command from the card to the host */ |
@@ -742,6 +764,40 @@ out: | |||
742 | return err; | 764 | return err; |
743 | } | 765 | } |
744 | 766 | ||
767 | /* Move data or a command from the host to the card. */ | ||
768 | static void if_spi_h2c(struct if_spi_card *card, | ||
769 | struct if_spi_packet *packet, int type) | ||
770 | { | ||
771 | int err = 0; | ||
772 | u16 int_type, port_reg; | ||
773 | |||
774 | switch (type) { | ||
775 | case MVMS_DAT: | ||
776 | int_type = IF_SPI_CIC_TX_DOWNLOAD_OVER; | ||
777 | port_reg = IF_SPI_DATA_RDWRPORT_REG; | ||
778 | break; | ||
779 | case MVMS_CMD: | ||
780 | int_type = IF_SPI_CIC_CMD_DOWNLOAD_OVER; | ||
781 | port_reg = IF_SPI_CMD_RDWRPORT_REG; | ||
782 | break; | ||
783 | default: | ||
784 | lbs_pr_err("can't transfer buffer of type %d\n", type); | ||
785 | err = -EINVAL; | ||
786 | goto out; | ||
787 | } | ||
788 | |||
789 | /* Write the data to the card */ | ||
790 | err = spu_write(card, port_reg, packet->buffer, packet->blen); | ||
791 | if (err) | ||
792 | goto out; | ||
793 | |||
794 | out: | ||
795 | kfree(packet); | ||
796 | |||
797 | if (err) | ||
798 | lbs_pr_err("%s: error %d\n", __func__, err); | ||
799 | } | ||
800 | |||
745 | /* Inform the host about a card event */ | 801 | /* Inform the host about a card event */ |
746 | static void if_spi_e2h(struct if_spi_card *card) | 802 | static void if_spi_e2h(struct if_spi_card *card) |
747 | { | 803 | { |
@@ -766,71 +822,88 @@ out: | |||
766 | lbs_pr_err("%s: error %d\n", __func__, err); | 822 | lbs_pr_err("%s: error %d\n", __func__, err); |
767 | } | 823 | } |
768 | 824 | ||
769 | static int lbs_spi_thread(void *data) | 825 | static void if_spi_host_to_card_worker(struct work_struct *work) |
770 | { | 826 | { |
771 | int err; | 827 | int err; |
772 | struct if_spi_card *card = data; | 828 | struct if_spi_card *card; |
773 | u16 hiStatus; | 829 | u16 hiStatus; |
830 | unsigned long flags; | ||
831 | struct if_spi_packet *packet; | ||
774 | 832 | ||
775 | while (1) { | 833 | card = container_of(work, struct if_spi_card, packet_work); |
776 | /* Wait to be woken up by one of two things. First, our ISR | ||
777 | * could tell us that something happened on the WLAN. | ||
778 | * Secondly, libertas could call hw_host_to_card with more | ||
779 | * data, which we might be able to send. | ||
780 | */ | ||
781 | do { | ||
782 | err = down_interruptible(&card->spi_ready); | ||
783 | if (!card->run_thread) { | ||
784 | up(&card->spi_thread_terminated); | ||
785 | do_exit(0); | ||
786 | } | ||
787 | } while (err == -EINTR); | ||
788 | 834 | ||
789 | /* Read the host interrupt status register to see what we | 835 | lbs_deb_enter(LBS_DEB_SPI); |
790 | * can do. */ | 836 | |
791 | err = spu_read_u16(card, IF_SPI_HOST_INT_STATUS_REG, | 837 | /* Read the host interrupt status register to see what we |
792 | &hiStatus); | 838 | * can do. */ |
793 | if (err) { | 839 | err = spu_read_u16(card, IF_SPI_HOST_INT_STATUS_REG, |
794 | lbs_pr_err("I/O error\n"); | 840 | &hiStatus); |
841 | if (err) { | ||
842 | lbs_pr_err("I/O error\n"); | ||
843 | goto err; | ||
844 | } | ||
845 | |||
846 | if (hiStatus & IF_SPI_HIST_CMD_UPLOAD_RDY) { | ||
847 | err = if_spi_c2h_cmd(card); | ||
848 | if (err) | ||
795 | goto err; | 849 | goto err; |
796 | } | 850 | } |
851 | if (hiStatus & IF_SPI_HIST_RX_UPLOAD_RDY) { | ||
852 | err = if_spi_c2h_data(card); | ||
853 | if (err) | ||
854 | goto err; | ||
855 | } | ||
797 | 856 | ||
798 | if (hiStatus & IF_SPI_HIST_CMD_UPLOAD_RDY) { | 857 | /* workaround: in PS mode, the card does not set the Command |
799 | err = if_spi_c2h_cmd(card); | 858 | * Download Ready bit, but it sets TX Download Ready. */ |
800 | if (err) | 859 | if (hiStatus & IF_SPI_HIST_CMD_DOWNLOAD_RDY || |
801 | goto err; | 860 | (card->priv->psstate != PS_STATE_FULL_POWER && |
802 | } | 861 | (hiStatus & IF_SPI_HIST_TX_DOWNLOAD_RDY))) { |
803 | if (hiStatus & IF_SPI_HIST_RX_UPLOAD_RDY) { | 862 | /* This means two things. First of all, |
804 | err = if_spi_c2h_data(card); | 863 | * if there was a previous command sent, the card has |
805 | if (err) | 864 | * successfully received it. |
806 | goto err; | 865 | * Secondly, it is now ready to download another |
866 | * command. | ||
867 | */ | ||
868 | lbs_host_to_card_done(card->priv); | ||
869 | |||
870 | /* Do we have any command packets from the host to | ||
871 | * send? */ | ||
872 | packet = NULL; | ||
873 | spin_lock_irqsave(&card->buffer_lock, flags); | ||
874 | if (!list_empty(&card->cmd_packet_list)) { | ||
875 | packet = (struct if_spi_packet *)(card-> | ||
876 | cmd_packet_list.next); | ||
877 | list_del(&packet->list); | ||
807 | } | 878 | } |
879 | spin_unlock_irqrestore(&card->buffer_lock, flags); | ||
808 | 880 | ||
809 | /* workaround: in PS mode, the card does not set the Command | 881 | if (packet) |
810 | * Download Ready bit, but it sets TX Download Ready. */ | 882 | if_spi_h2c(card, packet, MVMS_CMD); |
811 | if (hiStatus & IF_SPI_HIST_CMD_DOWNLOAD_RDY || | 883 | } |
812 | (card->priv->psstate != PS_STATE_FULL_POWER && | 884 | if (hiStatus & IF_SPI_HIST_TX_DOWNLOAD_RDY) { |
813 | (hiStatus & IF_SPI_HIST_TX_DOWNLOAD_RDY))) { | 885 | /* Do we have any data packets from the host to |
814 | lbs_host_to_card_done(card->priv); | 886 | * send? */ |
887 | packet = NULL; | ||
888 | spin_lock_irqsave(&card->buffer_lock, flags); | ||
889 | if (!list_empty(&card->data_packet_list)) { | ||
890 | packet = (struct if_spi_packet *)(card-> | ||
891 | data_packet_list.next); | ||
892 | list_del(&packet->list); | ||
815 | } | 893 | } |
894 | spin_unlock_irqrestore(&card->buffer_lock, flags); | ||
816 | 895 | ||
817 | if (hiStatus & IF_SPI_HIST_CARD_EVENT) | 896 | if (packet) |
818 | if_spi_e2h(card); | 897 | if_spi_h2c(card, packet, MVMS_DAT); |
898 | } | ||
899 | if (hiStatus & IF_SPI_HIST_CARD_EVENT) | ||
900 | if_spi_e2h(card); | ||
819 | 901 | ||
820 | err: | 902 | err: |
821 | if (err) | 903 | if (err) |
822 | lbs_pr_err("%s: got error %d\n", __func__, err); | 904 | lbs_pr_err("%s: got error %d\n", __func__, err); |
823 | } | ||
824 | } | ||
825 | 905 | ||
826 | /* Block until lbs_spi_thread thread has terminated */ | 906 | lbs_deb_leave(LBS_DEB_SPI); |
827 | static void if_spi_terminate_spi_thread(struct if_spi_card *card) | ||
828 | { | ||
829 | /* It would be nice to use kthread_stop here, but that function | ||
830 | * can't wake threads waiting for a semaphore. */ | ||
831 | card->run_thread = 0; | ||
832 | up(&card->spi_ready); | ||
833 | down(&card->spi_thread_terminated); | ||
834 | } | 907 | } |
835 | 908 | ||
836 | /* | 909 | /* |
@@ -842,18 +915,40 @@ static int if_spi_host_to_card(struct lbs_private *priv, | |||
842 | u8 type, u8 *buf, u16 nb) | 915 | u8 type, u8 *buf, u16 nb) |
843 | { | 916 | { |
844 | int err = 0; | 917 | int err = 0; |
918 | unsigned long flags; | ||
845 | struct if_spi_card *card = priv->card; | 919 | struct if_spi_card *card = priv->card; |
920 | struct if_spi_packet *packet; | ||
921 | u16 blen; | ||
846 | 922 | ||
847 | lbs_deb_enter_args(LBS_DEB_SPI, "type %d, bytes %d", type, nb); | 923 | lbs_deb_enter_args(LBS_DEB_SPI, "type %d, bytes %d", type, nb); |
848 | 924 | ||
849 | nb = ALIGN(nb, 4); | 925 | if (nb == 0) { |
926 | lbs_pr_err("%s: invalid size requested: %d\n", __func__, nb); | ||
927 | err = -EINVAL; | ||
928 | goto out; | ||
929 | } | ||
930 | blen = ALIGN(nb, 4); | ||
931 | packet = kzalloc(sizeof(struct if_spi_packet) + blen, GFP_ATOMIC); | ||
932 | if (!packet) { | ||
933 | err = -ENOMEM; | ||
934 | goto out; | ||
935 | } | ||
936 | packet->blen = blen; | ||
937 | memcpy(packet->buffer, buf, nb); | ||
938 | memset(packet->buffer + nb, 0, blen - nb); | ||
850 | 939 | ||
851 | switch (type) { | 940 | switch (type) { |
852 | case MVMS_CMD: | 941 | case MVMS_CMD: |
853 | err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG, buf, nb); | 942 | priv->dnld_sent = DNLD_CMD_SENT; |
943 | spin_lock_irqsave(&card->buffer_lock, flags); | ||
944 | list_add_tail(&packet->list, &card->cmd_packet_list); | ||
945 | spin_unlock_irqrestore(&card->buffer_lock, flags); | ||
854 | break; | 946 | break; |
855 | case MVMS_DAT: | 947 | case MVMS_DAT: |
856 | err = spu_write(card, IF_SPI_DATA_RDWRPORT_REG, buf, nb); | 948 | priv->dnld_sent = DNLD_DATA_SENT; |
949 | spin_lock_irqsave(&card->buffer_lock, flags); | ||
950 | list_add_tail(&packet->list, &card->data_packet_list); | ||
951 | spin_unlock_irqrestore(&card->buffer_lock, flags); | ||
857 | break; | 952 | break; |
858 | default: | 953 | default: |
859 | lbs_pr_err("can't transfer buffer of type %d", type); | 954 | lbs_pr_err("can't transfer buffer of type %d", type); |
@@ -861,6 +956,9 @@ static int if_spi_host_to_card(struct lbs_private *priv, | |||
861 | break; | 956 | break; |
862 | } | 957 | } |
863 | 958 | ||
959 | /* Queue spi xfer work */ | ||
960 | queue_work(card->workqueue, &card->packet_work); | ||
961 | out: | ||
864 | lbs_deb_leave_args(LBS_DEB_SPI, "err=%d", err); | 962 | lbs_deb_leave_args(LBS_DEB_SPI, "err=%d", err); |
865 | return err; | 963 | return err; |
866 | } | 964 | } |
@@ -869,13 +967,14 @@ static int if_spi_host_to_card(struct lbs_private *priv, | |||
869 | * Host Interrupts | 967 | * Host Interrupts |
870 | * | 968 | * |
871 | * Service incoming interrupts from the WLAN device. We can't sleep here, so | 969 | * Service incoming interrupts from the WLAN device. We can't sleep here, so |
872 | * don't try to talk on the SPI bus, just wake up the SPI thread. | 970 | * don't try to talk on the SPI bus, just queue the SPI xfer work. |
873 | */ | 971 | */ |
874 | static irqreturn_t if_spi_host_interrupt(int irq, void *dev_id) | 972 | static irqreturn_t if_spi_host_interrupt(int irq, void *dev_id) |
875 | { | 973 | { |
876 | struct if_spi_card *card = dev_id; | 974 | struct if_spi_card *card = dev_id; |
877 | 975 | ||
878 | up(&card->spi_ready); | 976 | queue_work(card->workqueue, &card->packet_work); |
977 | |||
879 | return IRQ_HANDLED; | 978 | return IRQ_HANDLED; |
880 | } | 979 | } |
881 | 980 | ||
@@ -883,56 +982,26 @@ static irqreturn_t if_spi_host_interrupt(int irq, void *dev_id) | |||
883 | * SPI callbacks | 982 | * SPI callbacks |
884 | */ | 983 | */ |
885 | 984 | ||
886 | static int __devinit if_spi_probe(struct spi_device *spi) | 985 | static int if_spi_init_card(struct if_spi_card *card) |
887 | { | 986 | { |
888 | struct if_spi_card *card; | 987 | struct spi_device *spi = card->spi; |
889 | struct lbs_private *priv = NULL; | 988 | int err, i; |
890 | struct libertas_spi_platform_data *pdata = spi->dev.platform_data; | ||
891 | int err = 0, i; | ||
892 | u32 scratch; | 989 | u32 scratch; |
893 | struct sched_param param = { .sched_priority = 1 }; | ||
894 | const struct firmware *helper = NULL; | 990 | const struct firmware *helper = NULL; |
895 | const struct firmware *mainfw = NULL; | 991 | const struct firmware *mainfw = NULL; |
896 | 992 | ||
897 | lbs_deb_enter(LBS_DEB_SPI); | 993 | lbs_deb_enter(LBS_DEB_SPI); |
898 | 994 | ||
899 | if (!pdata) { | 995 | err = spu_init(card, card->pdata->use_dummy_writes); |
900 | err = -EINVAL; | ||
901 | goto out; | ||
902 | } | ||
903 | |||
904 | if (pdata->setup) { | ||
905 | err = pdata->setup(spi); | ||
906 | if (err) | ||
907 | goto out; | ||
908 | } | ||
909 | |||
910 | /* Allocate card structure to represent this specific device */ | ||
911 | card = kzalloc(sizeof(struct if_spi_card), GFP_KERNEL); | ||
912 | if (!card) { | ||
913 | err = -ENOMEM; | ||
914 | goto out; | ||
915 | } | ||
916 | spi_set_drvdata(spi, card); | ||
917 | card->pdata = pdata; | ||
918 | card->spi = spi; | ||
919 | card->prev_xfer_time = jiffies; | ||
920 | |||
921 | sema_init(&card->spi_ready, 0); | ||
922 | sema_init(&card->spi_thread_terminated, 0); | ||
923 | |||
924 | /* Initialize the SPI Interface Unit */ | ||
925 | err = spu_init(card, pdata->use_dummy_writes); | ||
926 | if (err) | 996 | if (err) |
927 | goto free_card; | 997 | goto out; |
928 | err = spu_get_chip_revision(card, &card->card_id, &card->card_rev); | 998 | err = spu_get_chip_revision(card, &card->card_id, &card->card_rev); |
929 | if (err) | 999 | if (err) |
930 | goto free_card; | 1000 | goto out; |
931 | 1001 | ||
932 | /* Firmware load */ | ||
933 | err = spu_read_u32(card, IF_SPI_SCRATCH_4_REG, &scratch); | 1002 | err = spu_read_u32(card, IF_SPI_SCRATCH_4_REG, &scratch); |
934 | if (err) | 1003 | if (err) |
935 | goto free_card; | 1004 | goto out; |
936 | if (scratch == SUCCESSFUL_FW_DOWNLOAD_MAGIC) | 1005 | if (scratch == SUCCESSFUL_FW_DOWNLOAD_MAGIC) |
937 | lbs_deb_spi("Firmware is already loaded for " | 1006 | lbs_deb_spi("Firmware is already loaded for " |
938 | "Marvell WLAN 802.11 adapter\n"); | 1007 | "Marvell WLAN 802.11 adapter\n"); |
@@ -946,7 +1015,7 @@ static int __devinit if_spi_probe(struct spi_device *spi) | |||
946 | lbs_pr_err("Unsupported chip_id: 0x%02x\n", | 1015 | lbs_pr_err("Unsupported chip_id: 0x%02x\n", |
947 | card->card_id); | 1016 | card->card_id); |
948 | err = -ENODEV; | 1017 | err = -ENODEV; |
949 | goto free_card; | 1018 | goto out; |
950 | } | 1019 | } |
951 | 1020 | ||
952 | err = lbs_get_firmware(&card->spi->dev, NULL, NULL, | 1021 | err = lbs_get_firmware(&card->spi->dev, NULL, NULL, |
@@ -954,7 +1023,7 @@ static int __devinit if_spi_probe(struct spi_device *spi) | |||
954 | &mainfw); | 1023 | &mainfw); |
955 | if (err) { | 1024 | if (err) { |
956 | lbs_pr_err("failed to find firmware (%d)\n", err); | 1025 | lbs_pr_err("failed to find firmware (%d)\n", err); |
957 | goto free_card; | 1026 | goto out; |
958 | } | 1027 | } |
959 | 1028 | ||
960 | lbs_deb_spi("Initializing FW for Marvell WLAN 802.11 adapter " | 1029 | lbs_deb_spi("Initializing FW for Marvell WLAN 802.11 adapter " |
@@ -966,15 +1035,68 @@ static int __devinit if_spi_probe(struct spi_device *spi) | |||
966 | spi->max_speed_hz); | 1035 | spi->max_speed_hz); |
967 | err = if_spi_prog_helper_firmware(card, helper); | 1036 | err = if_spi_prog_helper_firmware(card, helper); |
968 | if (err) | 1037 | if (err) |
969 | goto free_card; | 1038 | goto out; |
970 | err = if_spi_prog_main_firmware(card, mainfw); | 1039 | err = if_spi_prog_main_firmware(card, mainfw); |
971 | if (err) | 1040 | if (err) |
972 | goto free_card; | 1041 | goto out; |
973 | lbs_deb_spi("loaded FW for Marvell WLAN 802.11 adapter\n"); | 1042 | lbs_deb_spi("loaded FW for Marvell WLAN 802.11 adapter\n"); |
974 | } | 1043 | } |
975 | 1044 | ||
976 | err = spu_set_interrupt_mode(card, 0, 1); | 1045 | err = spu_set_interrupt_mode(card, 0, 1); |
977 | if (err) | 1046 | if (err) |
1047 | goto out; | ||
1048 | |||
1049 | out: | ||
1050 | if (helper) | ||
1051 | release_firmware(helper); | ||
1052 | if (mainfw) | ||
1053 | release_firmware(mainfw); | ||
1054 | |||
1055 | lbs_deb_leave_args(LBS_DEB_SPI, "err %d\n", err); | ||
1056 | |||
1057 | return err; | ||
1058 | } | ||
1059 | |||
1060 | static int __devinit if_spi_probe(struct spi_device *spi) | ||
1061 | { | ||
1062 | struct if_spi_card *card; | ||
1063 | struct lbs_private *priv = NULL; | ||
1064 | struct libertas_spi_platform_data *pdata = spi->dev.platform_data; | ||
1065 | int err = 0; | ||
1066 | |||
1067 | lbs_deb_enter(LBS_DEB_SPI); | ||
1068 | |||
1069 | if (!pdata) { | ||
1070 | err = -EINVAL; | ||
1071 | goto out; | ||
1072 | } | ||
1073 | |||
1074 | if (pdata->setup) { | ||
1075 | err = pdata->setup(spi); | ||
1076 | if (err) | ||
1077 | goto out; | ||
1078 | } | ||
1079 | |||
1080 | /* Allocate card structure to represent this specific device */ | ||
1081 | card = kzalloc(sizeof(struct if_spi_card), GFP_KERNEL); | ||
1082 | if (!card) { | ||
1083 | err = -ENOMEM; | ||
1084 | goto teardown; | ||
1085 | } | ||
1086 | spi_set_drvdata(spi, card); | ||
1087 | card->pdata = pdata; | ||
1088 | card->spi = spi; | ||
1089 | card->prev_xfer_time = jiffies; | ||
1090 | |||
1091 | INIT_LIST_HEAD(&card->cmd_packet_list); | ||
1092 | INIT_LIST_HEAD(&card->data_packet_list); | ||
1093 | spin_lock_init(&card->buffer_lock); | ||
1094 | |||
1095 | /* Initialize the SPI Interface Unit */ | ||
1096 | |||
1097 | /* Firmware load */ | ||
1098 | err = if_spi_init_card(card); | ||
1099 | if (err) | ||
978 | goto free_card; | 1100 | goto free_card; |
979 | 1101 | ||
980 | /* Register our card with libertas. | 1102 | /* Register our card with libertas. |
@@ -993,27 +1115,16 @@ static int __devinit if_spi_probe(struct spi_device *spi) | |||
993 | priv->fw_ready = 1; | 1115 | priv->fw_ready = 1; |
994 | 1116 | ||
995 | /* Initialize interrupt handling stuff. */ | 1117 | /* Initialize interrupt handling stuff. */ |
996 | card->run_thread = 1; | 1118 | card->workqueue = create_workqueue("libertas_spi"); |
997 | card->spi_thread = kthread_run(lbs_spi_thread, card, "lbs_spi_thread"); | 1119 | INIT_WORK(&card->packet_work, if_spi_host_to_card_worker); |
998 | if (IS_ERR(card->spi_thread)) { | ||
999 | card->run_thread = 0; | ||
1000 | err = PTR_ERR(card->spi_thread); | ||
1001 | lbs_pr_err("error creating SPI thread: err=%d\n", err); | ||
1002 | goto remove_card; | ||
1003 | } | ||
1004 | if (sched_setscheduler(card->spi_thread, SCHED_FIFO, ¶m)) | ||
1005 | lbs_pr_err("Error setting scheduler, using default.\n"); | ||
1006 | 1120 | ||
1007 | err = request_irq(spi->irq, if_spi_host_interrupt, | 1121 | err = request_irq(spi->irq, if_spi_host_interrupt, |
1008 | IRQF_TRIGGER_FALLING, "libertas_spi", card); | 1122 | IRQF_TRIGGER_FALLING, "libertas_spi", card); |
1009 | if (err) { | 1123 | if (err) { |
1010 | lbs_pr_err("can't get host irq line-- request_irq failed\n"); | 1124 | lbs_pr_err("can't get host irq line-- request_irq failed\n"); |
1011 | goto terminate_thread; | 1125 | goto terminate_workqueue; |
1012 | } | 1126 | } |
1013 | 1127 | ||
1014 | /* poke the IRQ handler so that we don't miss the first interrupt */ | ||
1015 | up(&card->spi_ready); | ||
1016 | |||
1017 | /* Start the card. | 1128 | /* Start the card. |
1018 | * This will call register_netdev, and we'll start | 1129 | * This will call register_netdev, and we'll start |
1019 | * getting interrupts... */ | 1130 | * getting interrupts... */ |
@@ -1028,18 +1139,16 @@ static int __devinit if_spi_probe(struct spi_device *spi) | |||
1028 | 1139 | ||
1029 | release_irq: | 1140 | release_irq: |
1030 | free_irq(spi->irq, card); | 1141 | free_irq(spi->irq, card); |
1031 | terminate_thread: | 1142 | terminate_workqueue: |
1032 | if_spi_terminate_spi_thread(card); | 1143 | flush_workqueue(card->workqueue); |
1033 | remove_card: | 1144 | destroy_workqueue(card->workqueue); |
1034 | lbs_remove_card(priv); /* will call free_netdev */ | 1145 | lbs_remove_card(priv); /* will call free_netdev */ |
1035 | free_card: | 1146 | free_card: |
1036 | free_if_spi_card(card); | 1147 | free_if_spi_card(card); |
1148 | teardown: | ||
1149 | if (pdata->teardown) | ||
1150 | pdata->teardown(spi); | ||
1037 | out: | 1151 | out: |
1038 | if (helper) | ||
1039 | release_firmware(helper); | ||
1040 | if (mainfw) | ||
1041 | release_firmware(mainfw); | ||
1042 | |||
1043 | lbs_deb_leave_args(LBS_DEB_SPI, "err %d\n", err); | 1152 | lbs_deb_leave_args(LBS_DEB_SPI, "err %d\n", err); |
1044 | return err; | 1153 | return err; |
1045 | } | 1154 | } |
@@ -1056,7 +1165,8 @@ static int __devexit libertas_spi_remove(struct spi_device *spi) | |||
1056 | lbs_remove_card(priv); /* will call free_netdev */ | 1165 | lbs_remove_card(priv); /* will call free_netdev */ |
1057 | 1166 | ||
1058 | free_irq(spi->irq, card); | 1167 | free_irq(spi->irq, card); |
1059 | if_spi_terminate_spi_thread(card); | 1168 | flush_workqueue(card->workqueue); |
1169 | destroy_workqueue(card->workqueue); | ||
1060 | if (card->pdata->teardown) | 1170 | if (card->pdata->teardown) |
1061 | card->pdata->teardown(spi); | 1171 | card->pdata->teardown(spi); |
1062 | free_if_spi_card(card); | 1172 | free_if_spi_card(card); |
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 6836a6dd9853..ca8149cd5bd9 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c | |||
@@ -539,6 +539,43 @@ static int lbs_thread(void *data) | |||
539 | return 0; | 539 | return 0; |
540 | } | 540 | } |
541 | 541 | ||
542 | /** | ||
543 | * @brief This function gets the HW spec from the firmware and sets | ||
544 | * some basic parameters. | ||
545 | * | ||
546 | * @param priv A pointer to struct lbs_private structure | ||
547 | * @return 0 or -1 | ||
548 | */ | ||
549 | static int lbs_setup_firmware(struct lbs_private *priv) | ||
550 | { | ||
551 | int ret = -1; | ||
552 | s16 curlevel = 0, minlevel = 0, maxlevel = 0; | ||
553 | |||
554 | lbs_deb_enter(LBS_DEB_FW); | ||
555 | |||
556 | /* Read MAC address from firmware */ | ||
557 | memset(priv->current_addr, 0xff, ETH_ALEN); | ||
558 | ret = lbs_update_hw_spec(priv); | ||
559 | if (ret) | ||
560 | goto done; | ||
561 | |||
562 | /* Read power levels if available */ | ||
563 | ret = lbs_get_tx_power(priv, &curlevel, &minlevel, &maxlevel); | ||
564 | if (ret == 0) { | ||
565 | priv->txpower_cur = curlevel; | ||
566 | priv->txpower_min = minlevel; | ||
567 | priv->txpower_max = maxlevel; | ||
568 | } | ||
569 | |||
570 | /* Send cmd to FW to enable 11D function */ | ||
571 | ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_11D_ENABLE, 1); | ||
572 | |||
573 | lbs_set_mac_control(priv); | ||
574 | done: | ||
575 | lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret); | ||
576 | return ret; | ||
577 | } | ||
578 | |||
542 | int lbs_suspend(struct lbs_private *priv) | 579 | int lbs_suspend(struct lbs_private *priv) |
543 | { | 580 | { |
544 | int ret; | 581 | int ret; |
@@ -584,47 +621,13 @@ int lbs_resume(struct lbs_private *priv) | |||
584 | lbs_pr_err("deep sleep activation failed: %d\n", ret); | 621 | lbs_pr_err("deep sleep activation failed: %d\n", ret); |
585 | } | 622 | } |
586 | 623 | ||
587 | lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret); | 624 | if (priv->setup_fw_on_resume) |
588 | return ret; | 625 | ret = lbs_setup_firmware(priv); |
589 | } | ||
590 | EXPORT_SYMBOL_GPL(lbs_resume); | ||
591 | |||
592 | /** | ||
593 | * @brief This function gets the HW spec from the firmware and sets | ||
594 | * some basic parameters. | ||
595 | * | ||
596 | * @param priv A pointer to struct lbs_private structure | ||
597 | * @return 0 or -1 | ||
598 | */ | ||
599 | static int lbs_setup_firmware(struct lbs_private *priv) | ||
600 | { | ||
601 | int ret = -1; | ||
602 | s16 curlevel = 0, minlevel = 0, maxlevel = 0; | ||
603 | |||
604 | lbs_deb_enter(LBS_DEB_FW); | ||
605 | |||
606 | /* Read MAC address from firmware */ | ||
607 | memset(priv->current_addr, 0xff, ETH_ALEN); | ||
608 | ret = lbs_update_hw_spec(priv); | ||
609 | if (ret) | ||
610 | goto done; | ||
611 | |||
612 | /* Read power levels if available */ | ||
613 | ret = lbs_get_tx_power(priv, &curlevel, &minlevel, &maxlevel); | ||
614 | if (ret == 0) { | ||
615 | priv->txpower_cur = curlevel; | ||
616 | priv->txpower_min = minlevel; | ||
617 | priv->txpower_max = maxlevel; | ||
618 | } | ||
619 | 626 | ||
620 | /* Send cmd to FW to enable 11D function */ | ||
621 | ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_11D_ENABLE, 1); | ||
622 | |||
623 | lbs_set_mac_control(priv); | ||
624 | done: | ||
625 | lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret); | 627 | lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret); |
626 | return ret; | 628 | return ret; |
627 | } | 629 | } |
630 | EXPORT_SYMBOL_GPL(lbs_resume); | ||
628 | 631 | ||
629 | /** | 632 | /** |
630 | * This function handles the timeout of command sending. | 633 | * This function handles the timeout of command sending. |
diff --git a/drivers/net/wireless/wl1251/acx.c b/drivers/net/wireless/wl1251/acx.c index 64a0214cfb29..ef8370edace7 100644 --- a/drivers/net/wireless/wl1251/acx.c +++ b/drivers/net/wireless/wl1251/acx.c | |||
@@ -776,6 +776,31 @@ out: | |||
776 | return ret; | 776 | return ret; |
777 | } | 777 | } |
778 | 778 | ||
779 | int wl1251_acx_low_rssi(struct wl1251 *wl, s8 threshold, u8 weight, | ||
780 | u8 depth, enum wl1251_acx_low_rssi_type type) | ||
781 | { | ||
782 | struct acx_low_rssi *rssi; | ||
783 | int ret; | ||
784 | |||
785 | wl1251_debug(DEBUG_ACX, "acx low rssi"); | ||
786 | |||
787 | rssi = kzalloc(sizeof(*rssi), GFP_KERNEL); | ||
788 | if (!rssi) | ||
789 | return -ENOMEM; | ||
790 | |||
791 | rssi->threshold = threshold; | ||
792 | rssi->weight = weight; | ||
793 | rssi->depth = depth; | ||
794 | rssi->type = type; | ||
795 | |||
796 | ret = wl1251_cmd_configure(wl, ACX_LOW_RSSI, rssi, sizeof(*rssi)); | ||
797 | if (ret < 0) | ||
798 | wl1251_warning("failed to set low rssi threshold: %d", ret); | ||
799 | |||
800 | kfree(rssi); | ||
801 | return ret; | ||
802 | } | ||
803 | |||
779 | int wl1251_acx_set_preamble(struct wl1251 *wl, enum acx_preamble_type preamble) | 804 | int wl1251_acx_set_preamble(struct wl1251 *wl, enum acx_preamble_type preamble) |
780 | { | 805 | { |
781 | struct acx_preamble *acx; | 806 | struct acx_preamble *acx; |
@@ -978,6 +1003,34 @@ out: | |||
978 | return ret; | 1003 | return ret; |
979 | } | 1004 | } |
980 | 1005 | ||
1006 | int wl1251_acx_bet_enable(struct wl1251 *wl, enum wl1251_acx_bet_mode mode, | ||
1007 | u8 max_consecutive) | ||
1008 | { | ||
1009 | struct wl1251_acx_bet_enable *acx; | ||
1010 | int ret; | ||
1011 | |||
1012 | wl1251_debug(DEBUG_ACX, "acx bet enable"); | ||
1013 | |||
1014 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
1015 | if (!acx) { | ||
1016 | ret = -ENOMEM; | ||
1017 | goto out; | ||
1018 | } | ||
1019 | |||
1020 | acx->enable = mode; | ||
1021 | acx->max_consecutive = max_consecutive; | ||
1022 | |||
1023 | ret = wl1251_cmd_configure(wl, ACX_BET_ENABLE, acx, sizeof(*acx)); | ||
1024 | if (ret < 0) { | ||
1025 | wl1251_warning("wl1251 acx bet enable failed: %d", ret); | ||
1026 | goto out; | ||
1027 | } | ||
1028 | |||
1029 | out: | ||
1030 | kfree(acx); | ||
1031 | return ret; | ||
1032 | } | ||
1033 | |||
981 | int wl1251_acx_ac_cfg(struct wl1251 *wl, u8 ac, u8 cw_min, u16 cw_max, | 1034 | int wl1251_acx_ac_cfg(struct wl1251 *wl, u8 ac, u8 cw_min, u16 cw_max, |
982 | u8 aifs, u16 txop) | 1035 | u8 aifs, u16 txop) |
983 | { | 1036 | { |
diff --git a/drivers/net/wireless/wl1251/acx.h b/drivers/net/wireless/wl1251/acx.h index efcc3aaca14f..c2ba100f9b1a 100644 --- a/drivers/net/wireless/wl1251/acx.h +++ b/drivers/net/wireless/wl1251/acx.h | |||
@@ -399,6 +399,49 @@ struct acx_rts_threshold { | |||
399 | u8 pad[2]; | 399 | u8 pad[2]; |
400 | } __packed; | 400 | } __packed; |
401 | 401 | ||
402 | enum wl1251_acx_low_rssi_type { | ||
403 | /* | ||
404 | * The event is a "Level" indication which keeps triggering | ||
405 | * as long as the average RSSI is below the threshold. | ||
406 | */ | ||
407 | WL1251_ACX_LOW_RSSI_TYPE_LEVEL = 0, | ||
408 | |||
409 | /* | ||
410 | * The event is an "Edge" indication which triggers | ||
411 | * only when the RSSI threshold is crossed from above. | ||
412 | */ | ||
413 | WL1251_ACX_LOW_RSSI_TYPE_EDGE = 1, | ||
414 | }; | ||
415 | |||
416 | struct acx_low_rssi { | ||
417 | struct acx_header header; | ||
418 | |||
419 | /* | ||
420 | * The threshold (in dBm) below (or above after low rssi | ||
421 | * indication) which the firmware generates an interrupt to the | ||
422 | * host. This parameter is signed. | ||
423 | */ | ||
424 | s8 threshold; | ||
425 | |||
426 | /* | ||
427 | * The weight of the current RSSI sample, before adding the new | ||
428 | * sample, that is used to calculate the average RSSI. | ||
429 | */ | ||
430 | u8 weight; | ||
431 | |||
432 | /* | ||
433 | * The number of Beacons/Probe response frames that will be | ||
434 | * received before issuing the Low or Regained RSSI event. | ||
435 | */ | ||
436 | u8 depth; | ||
437 | |||
438 | /* | ||
439 | * Configures how the Low RSSI Event is triggered. Refer to | ||
440 | * enum wl1251_acx_low_rssi_type for more. | ||
441 | */ | ||
442 | u8 type; | ||
443 | } __packed; | ||
444 | |||
402 | struct acx_beacon_filter_option { | 445 | struct acx_beacon_filter_option { |
403 | struct acx_header header; | 446 | struct acx_header header; |
404 | 447 | ||
@@ -1164,6 +1207,31 @@ struct wl1251_acx_wr_tbtt_and_dtim { | |||
1164 | u8 padding; | 1207 | u8 padding; |
1165 | } __packed; | 1208 | } __packed; |
1166 | 1209 | ||
1210 | enum wl1251_acx_bet_mode { | ||
1211 | WL1251_ACX_BET_DISABLE = 0, | ||
1212 | WL1251_ACX_BET_ENABLE = 1, | ||
1213 | }; | ||
1214 | |||
1215 | struct wl1251_acx_bet_enable { | ||
1216 | struct acx_header header; | ||
1217 | |||
1218 | /* | ||
1219 | * Specifies if beacon early termination procedure is enabled or | ||
1220 | * disabled, see enum wl1251_acx_bet_mode. | ||
1221 | */ | ||
1222 | u8 enable; | ||
1223 | |||
1224 | /* | ||
1225 | * Specifies the maximum number of consecutive beacons that may be | ||
1226 | * early terminated. After this number is reached at least one full | ||
1227 | * beacon must be correctly received in FW before beacon ET | ||
1228 | * resumes. Range 0 - 255. | ||
1229 | */ | ||
1230 | u8 max_consecutive; | ||
1231 | |||
1232 | u8 padding[2]; | ||
1233 | } __packed; | ||
1234 | |||
1167 | struct wl1251_acx_ac_cfg { | 1235 | struct wl1251_acx_ac_cfg { |
1168 | struct acx_header header; | 1236 | struct acx_header header; |
1169 | 1237 | ||
@@ -1393,6 +1461,8 @@ int wl1251_acx_cca_threshold(struct wl1251 *wl); | |||
1393 | int wl1251_acx_bcn_dtim_options(struct wl1251 *wl); | 1461 | int wl1251_acx_bcn_dtim_options(struct wl1251 *wl); |
1394 | int wl1251_acx_aid(struct wl1251 *wl, u16 aid); | 1462 | int wl1251_acx_aid(struct wl1251 *wl, u16 aid); |
1395 | int wl1251_acx_event_mbox_mask(struct wl1251 *wl, u32 event_mask); | 1463 | int wl1251_acx_event_mbox_mask(struct wl1251 *wl, u32 event_mask); |
1464 | int wl1251_acx_low_rssi(struct wl1251 *wl, s8 threshold, u8 weight, | ||
1465 | u8 depth, enum wl1251_acx_low_rssi_type type); | ||
1396 | int wl1251_acx_set_preamble(struct wl1251 *wl, enum acx_preamble_type preamble); | 1466 | int wl1251_acx_set_preamble(struct wl1251 *wl, enum acx_preamble_type preamble); |
1397 | int wl1251_acx_cts_protect(struct wl1251 *wl, | 1467 | int wl1251_acx_cts_protect(struct wl1251 *wl, |
1398 | enum acx_ctsprotect_type ctsprotect); | 1468 | enum acx_ctsprotect_type ctsprotect); |
@@ -1401,6 +1471,8 @@ int wl1251_acx_tsf_info(struct wl1251 *wl, u64 *mactime); | |||
1401 | int wl1251_acx_rate_policies(struct wl1251 *wl); | 1471 | int wl1251_acx_rate_policies(struct wl1251 *wl); |
1402 | int wl1251_acx_mem_cfg(struct wl1251 *wl); | 1472 | int wl1251_acx_mem_cfg(struct wl1251 *wl); |
1403 | int wl1251_acx_wr_tbtt_and_dtim(struct wl1251 *wl, u16 tbtt, u8 dtim); | 1473 | int wl1251_acx_wr_tbtt_and_dtim(struct wl1251 *wl, u16 tbtt, u8 dtim); |
1474 | int wl1251_acx_bet_enable(struct wl1251 *wl, enum wl1251_acx_bet_mode mode, | ||
1475 | u8 max_consecutive); | ||
1404 | int wl1251_acx_ac_cfg(struct wl1251 *wl, u8 ac, u8 cw_min, u16 cw_max, | 1476 | int wl1251_acx_ac_cfg(struct wl1251 *wl, u8 ac, u8 cw_min, u16 cw_max, |
1405 | u8 aifs, u16 txop); | 1477 | u8 aifs, u16 txop); |
1406 | int wl1251_acx_tid_cfg(struct wl1251 *wl, u8 queue, | 1478 | int wl1251_acx_tid_cfg(struct wl1251 *wl, u8 queue, |
diff --git a/drivers/net/wireless/wl1251/event.c b/drivers/net/wireless/wl1251/event.c index 712372e50a87..dfc4579acb06 100644 --- a/drivers/net/wireless/wl1251/event.c +++ b/drivers/net/wireless/wl1251/event.c | |||
@@ -90,6 +90,24 @@ static int wl1251_event_process(struct wl1251 *wl, struct event_mailbox *mbox) | |||
90 | } | 90 | } |
91 | } | 91 | } |
92 | 92 | ||
93 | if (wl->vif && wl->rssi_thold) { | ||
94 | if (vector & ROAMING_TRIGGER_LOW_RSSI_EVENT_ID) { | ||
95 | wl1251_debug(DEBUG_EVENT, | ||
96 | "ROAMING_TRIGGER_LOW_RSSI_EVENT"); | ||
97 | ieee80211_cqm_rssi_notify(wl->vif, | ||
98 | NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW, | ||
99 | GFP_KERNEL); | ||
100 | } | ||
101 | |||
102 | if (vector & ROAMING_TRIGGER_REGAINED_RSSI_EVENT_ID) { | ||
103 | wl1251_debug(DEBUG_EVENT, | ||
104 | "ROAMING_TRIGGER_REGAINED_RSSI_EVENT"); | ||
105 | ieee80211_cqm_rssi_notify(wl->vif, | ||
106 | NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH, | ||
107 | GFP_KERNEL); | ||
108 | } | ||
109 | } | ||
110 | |||
93 | return 0; | 111 | return 0; |
94 | } | 112 | } |
95 | 113 | ||
diff --git a/drivers/net/wireless/wl1251/main.c b/drivers/net/wireless/wl1251/main.c index 012e1a4016fe..1c8b0775d849 100644 --- a/drivers/net/wireless/wl1251/main.c +++ b/drivers/net/wireless/wl1251/main.c | |||
@@ -502,6 +502,7 @@ static void wl1251_op_stop(struct ieee80211_hw *hw) | |||
502 | wl->psm = 0; | 502 | wl->psm = 0; |
503 | wl->tx_queue_stopped = false; | 503 | wl->tx_queue_stopped = false; |
504 | wl->power_level = WL1251_DEFAULT_POWER_LEVEL; | 504 | wl->power_level = WL1251_DEFAULT_POWER_LEVEL; |
505 | wl->rssi_thold = 0; | ||
505 | wl->channel = WL1251_DEFAULT_CHANNEL; | 506 | wl->channel = WL1251_DEFAULT_CHANNEL; |
506 | 507 | ||
507 | wl1251_debugfs_reset(wl); | 508 | wl1251_debugfs_reset(wl); |
@@ -959,6 +960,16 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw, | |||
959 | if (ret < 0) | 960 | if (ret < 0) |
960 | goto out; | 961 | goto out; |
961 | 962 | ||
963 | if (changed & BSS_CHANGED_CQM) { | ||
964 | ret = wl1251_acx_low_rssi(wl, bss_conf->cqm_rssi_thold, | ||
965 | WL1251_DEFAULT_LOW_RSSI_WEIGHT, | ||
966 | WL1251_DEFAULT_LOW_RSSI_DEPTH, | ||
967 | WL1251_ACX_LOW_RSSI_TYPE_EDGE); | ||
968 | if (ret < 0) | ||
969 | goto out; | ||
970 | wl->rssi_thold = bss_conf->cqm_rssi_thold; | ||
971 | } | ||
972 | |||
962 | if (changed & BSS_CHANGED_BSSID) { | 973 | if (changed & BSS_CHANGED_BSSID) { |
963 | memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN); | 974 | memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN); |
964 | 975 | ||
@@ -1310,9 +1321,11 @@ int wl1251_init_ieee80211(struct wl1251 *wl) | |||
1310 | wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | | 1321 | wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | |
1311 | IEEE80211_HW_SUPPORTS_PS | | 1322 | IEEE80211_HW_SUPPORTS_PS | |
1312 | IEEE80211_HW_BEACON_FILTER | | 1323 | IEEE80211_HW_BEACON_FILTER | |
1313 | IEEE80211_HW_SUPPORTS_UAPSD; | 1324 | IEEE80211_HW_SUPPORTS_UAPSD | |
1325 | IEEE80211_HW_SUPPORTS_CQM_RSSI; | ||
1314 | 1326 | ||
1315 | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); | 1327 | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | |
1328 | BIT(NL80211_IFTYPE_ADHOC); | ||
1316 | wl->hw->wiphy->max_scan_ssids = 1; | 1329 | wl->hw->wiphy->max_scan_ssids = 1; |
1317 | wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1251_band_2ghz; | 1330 | wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1251_band_2ghz; |
1318 | 1331 | ||
@@ -1374,6 +1387,7 @@ struct ieee80211_hw *wl1251_alloc_hw(void) | |||
1374 | wl->psm_requested = false; | 1387 | wl->psm_requested = false; |
1375 | wl->tx_queue_stopped = false; | 1388 | wl->tx_queue_stopped = false; |
1376 | wl->power_level = WL1251_DEFAULT_POWER_LEVEL; | 1389 | wl->power_level = WL1251_DEFAULT_POWER_LEVEL; |
1390 | wl->rssi_thold = 0; | ||
1377 | wl->beacon_int = WL1251_DEFAULT_BEACON_INT; | 1391 | wl->beacon_int = WL1251_DEFAULT_BEACON_INT; |
1378 | wl->dtim_period = WL1251_DEFAULT_DTIM_PERIOD; | 1392 | wl->dtim_period = WL1251_DEFAULT_DTIM_PERIOD; |
1379 | wl->vif = NULL; | 1393 | wl->vif = NULL; |
diff --git a/drivers/net/wireless/wl1251/ps.c b/drivers/net/wireless/wl1251/ps.c index 5ed47c8373d2..9ba23ede51bd 100644 --- a/drivers/net/wireless/wl1251/ps.c +++ b/drivers/net/wireless/wl1251/ps.c | |||
@@ -153,6 +153,11 @@ int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_cmd_ps_mode mode) | |||
153 | if (ret < 0) | 153 | if (ret < 0) |
154 | return ret; | 154 | return ret; |
155 | 155 | ||
156 | ret = wl1251_acx_bet_enable(wl, WL1251_ACX_BET_ENABLE, | ||
157 | WL1251_DEFAULT_BET_CONSECUTIVE); | ||
158 | if (ret < 0) | ||
159 | return ret; | ||
160 | |||
156 | ret = wl1251_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE); | 161 | ret = wl1251_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE); |
157 | if (ret < 0) | 162 | if (ret < 0) |
158 | return ret; | 163 | return ret; |
@@ -170,6 +175,12 @@ int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_cmd_ps_mode mode) | |||
170 | if (ret < 0) | 175 | if (ret < 0) |
171 | return ret; | 176 | return ret; |
172 | 177 | ||
178 | /* disable BET */ | ||
179 | ret = wl1251_acx_bet_enable(wl, WL1251_ACX_BET_DISABLE, | ||
180 | WL1251_DEFAULT_BET_CONSECUTIVE); | ||
181 | if (ret < 0) | ||
182 | return ret; | ||
183 | |||
173 | /* disable beacon filtering */ | 184 | /* disable beacon filtering */ |
174 | ret = wl1251_acx_beacon_filter_opt(wl, false); | 185 | ret = wl1251_acx_beacon_filter_opt(wl, false); |
175 | if (ret < 0) | 186 | if (ret < 0) |
diff --git a/drivers/net/wireless/wl1251/rx.c b/drivers/net/wireless/wl1251/rx.c index 86eef456d7b2..b659e15c78df 100644 --- a/drivers/net/wireless/wl1251/rx.c +++ b/drivers/net/wireless/wl1251/rx.c | |||
@@ -96,8 +96,52 @@ static void wl1251_rx_status(struct wl1251 *wl, | |||
96 | if (unlikely(!(desc->flags & RX_DESC_VALID_FCS))) | 96 | if (unlikely(!(desc->flags & RX_DESC_VALID_FCS))) |
97 | status->flag |= RX_FLAG_FAILED_FCS_CRC; | 97 | status->flag |= RX_FLAG_FAILED_FCS_CRC; |
98 | 98 | ||
99 | switch (desc->rate) { | ||
100 | /* skip 1 and 12 Mbps because they have same value 0x0a */ | ||
101 | case RATE_2MBPS: | ||
102 | status->rate_idx = 1; | ||
103 | break; | ||
104 | case RATE_5_5MBPS: | ||
105 | status->rate_idx = 2; | ||
106 | break; | ||
107 | case RATE_11MBPS: | ||
108 | status->rate_idx = 3; | ||
109 | break; | ||
110 | case RATE_6MBPS: | ||
111 | status->rate_idx = 4; | ||
112 | break; | ||
113 | case RATE_9MBPS: | ||
114 | status->rate_idx = 5; | ||
115 | break; | ||
116 | case RATE_18MBPS: | ||
117 | status->rate_idx = 7; | ||
118 | break; | ||
119 | case RATE_24MBPS: | ||
120 | status->rate_idx = 8; | ||
121 | break; | ||
122 | case RATE_36MBPS: | ||
123 | status->rate_idx = 9; | ||
124 | break; | ||
125 | case RATE_48MBPS: | ||
126 | status->rate_idx = 10; | ||
127 | break; | ||
128 | case RATE_54MBPS: | ||
129 | status->rate_idx = 11; | ||
130 | break; | ||
131 | } | ||
132 | |||
133 | /* for 1 and 12 Mbps we have to check the modulation */ | ||
134 | if (desc->rate == RATE_1MBPS) { | ||
135 | if (!(desc->mod_pre & OFDM_RATE_BIT)) | ||
136 | /* CCK -> RATE_1MBPS */ | ||
137 | status->rate_idx = 0; | ||
138 | else | ||
139 | /* OFDM -> RATE_12MBPS */ | ||
140 | status->rate_idx = 6; | ||
141 | } | ||
99 | 142 | ||
100 | /* FIXME: set status->rate_idx */ | 143 | if (desc->mod_pre & SHORT_PREAMBLE_BIT) |
144 | status->flag |= RX_FLAG_SHORTPRE; | ||
101 | } | 145 | } |
102 | 146 | ||
103 | static void wl1251_rx_body(struct wl1251 *wl, | 147 | static void wl1251_rx_body(struct wl1251 *wl, |
diff --git a/drivers/net/wireless/wl1251/tx.c b/drivers/net/wireless/wl1251/tx.c index 554b4f9a3d3e..28121c590a2b 100644 --- a/drivers/net/wireless/wl1251/tx.c +++ b/drivers/net/wireless/wl1251/tx.c | |||
@@ -213,16 +213,30 @@ static int wl1251_tx_send_packet(struct wl1251 *wl, struct sk_buff *skb, | |||
213 | wl1251_debug(DEBUG_TX, "skb offset %d", offset); | 213 | wl1251_debug(DEBUG_TX, "skb offset %d", offset); |
214 | 214 | ||
215 | /* check whether the current skb can be used */ | 215 | /* check whether the current skb can be used */ |
216 | if (!skb_cloned(skb) && (skb_tailroom(skb) >= offset)) { | 216 | if (skb_cloned(skb) || (skb_tailroom(skb) < offset)) { |
217 | unsigned char *src = skb->data; | 217 | struct sk_buff *newskb = skb_copy_expand(skb, 0, 3, |
218 | GFP_KERNEL); | ||
219 | |||
220 | if (unlikely(newskb == NULL)) { | ||
221 | wl1251_error("Can't allocate skb!"); | ||
222 | return -EINVAL; | ||
223 | } | ||
218 | 224 | ||
219 | /* align the buffer on a 4-byte boundary */ | 225 | tx_hdr = (struct tx_double_buffer_desc *) newskb->data; |
226 | |||
227 | dev_kfree_skb_any(skb); | ||
228 | wl->tx_frames[tx_hdr->id] = skb = newskb; | ||
229 | |||
230 | offset = (4 - (long)skb->data) & 0x03; | ||
231 | wl1251_debug(DEBUG_TX, "new skb offset %d", offset); | ||
232 | } | ||
233 | |||
234 | /* align the buffer on a 4-byte boundary */ | ||
235 | if (offset) { | ||
236 | unsigned char *src = skb->data; | ||
220 | skb_reserve(skb, offset); | 237 | skb_reserve(skb, offset); |
221 | memmove(skb->data, src, skb->len); | 238 | memmove(skb->data, src, skb->len); |
222 | tx_hdr = (struct tx_double_buffer_desc *) skb->data; | 239 | tx_hdr = (struct tx_double_buffer_desc *) skb->data; |
223 | } else { | ||
224 | wl1251_info("No handler, fixme!"); | ||
225 | return -EINVAL; | ||
226 | } | 240 | } |
227 | } | 241 | } |
228 | 242 | ||
@@ -368,7 +382,7 @@ static void wl1251_tx_packet_cb(struct wl1251 *wl, | |||
368 | { | 382 | { |
369 | struct ieee80211_tx_info *info; | 383 | struct ieee80211_tx_info *info; |
370 | struct sk_buff *skb; | 384 | struct sk_buff *skb; |
371 | int hdrlen, ret; | 385 | int hdrlen; |
372 | u8 *frame; | 386 | u8 *frame; |
373 | 387 | ||
374 | skb = wl->tx_frames[result->id]; | 388 | skb = wl->tx_frames[result->id]; |
@@ -407,40 +421,12 @@ static void wl1251_tx_packet_cb(struct wl1251 *wl, | |||
407 | ieee80211_tx_status(wl->hw, skb); | 421 | ieee80211_tx_status(wl->hw, skb); |
408 | 422 | ||
409 | wl->tx_frames[result->id] = NULL; | 423 | wl->tx_frames[result->id] = NULL; |
410 | |||
411 | if (wl->tx_queue_stopped) { | ||
412 | wl1251_debug(DEBUG_TX, "cb: queue was stopped"); | ||
413 | |||
414 | skb = skb_dequeue(&wl->tx_queue); | ||
415 | |||
416 | /* The skb can be NULL because tx_work might have been | ||
417 | scheduled before the queue was stopped making the | ||
418 | queue empty */ | ||
419 | |||
420 | if (skb) { | ||
421 | ret = wl1251_tx_frame(wl, skb); | ||
422 | if (ret == -EBUSY) { | ||
423 | /* firmware buffer is still full */ | ||
424 | wl1251_debug(DEBUG_TX, "cb: fw buffer " | ||
425 | "still full"); | ||
426 | skb_queue_head(&wl->tx_queue, skb); | ||
427 | return; | ||
428 | } else if (ret < 0) { | ||
429 | dev_kfree_skb(skb); | ||
430 | return; | ||
431 | } | ||
432 | } | ||
433 | |||
434 | wl1251_debug(DEBUG_TX, "cb: waking queues"); | ||
435 | ieee80211_wake_queues(wl->hw); | ||
436 | wl->tx_queue_stopped = false; | ||
437 | } | ||
438 | } | 424 | } |
439 | 425 | ||
440 | /* Called upon reception of a TX complete interrupt */ | 426 | /* Called upon reception of a TX complete interrupt */ |
441 | void wl1251_tx_complete(struct wl1251 *wl) | 427 | void wl1251_tx_complete(struct wl1251 *wl) |
442 | { | 428 | { |
443 | int i, result_index, num_complete = 0; | 429 | int i, result_index, num_complete = 0, queue_len; |
444 | struct tx_result result[FW_TX_CMPLT_BLOCK_SIZE], *result_ptr; | 430 | struct tx_result result[FW_TX_CMPLT_BLOCK_SIZE], *result_ptr; |
445 | unsigned long flags; | 431 | unsigned long flags; |
446 | 432 | ||
@@ -471,18 +457,22 @@ void wl1251_tx_complete(struct wl1251 *wl) | |||
471 | } | 457 | } |
472 | } | 458 | } |
473 | 459 | ||
474 | if (wl->tx_queue_stopped | 460 | queue_len = skb_queue_len(&wl->tx_queue); |
475 | && | ||
476 | skb_queue_len(&wl->tx_queue) <= WL1251_TX_QUEUE_LOW_WATERMARK){ | ||
477 | 461 | ||
478 | /* firmware buffer has space, restart queues */ | 462 | if ((num_complete > 0) && (queue_len > 0)) { |
463 | /* firmware buffer has space, reschedule tx_work */ | ||
464 | wl1251_debug(DEBUG_TX, "tx_complete: reschedule tx_work"); | ||
465 | ieee80211_queue_work(wl->hw, &wl->tx_work); | ||
466 | } | ||
467 | |||
468 | if (wl->tx_queue_stopped && | ||
469 | queue_len <= WL1251_TX_QUEUE_LOW_WATERMARK) { | ||
470 | /* tx_queue has space, restart queues */ | ||
479 | wl1251_debug(DEBUG_TX, "tx_complete: waking queues"); | 471 | wl1251_debug(DEBUG_TX, "tx_complete: waking queues"); |
480 | spin_lock_irqsave(&wl->wl_lock, flags); | 472 | spin_lock_irqsave(&wl->wl_lock, flags); |
481 | ieee80211_wake_queues(wl->hw); | 473 | ieee80211_wake_queues(wl->hw); |
482 | wl->tx_queue_stopped = false; | 474 | wl->tx_queue_stopped = false; |
483 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 475 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
484 | ieee80211_queue_work(wl->hw, &wl->tx_work); | ||
485 | |||
486 | } | 476 | } |
487 | 477 | ||
488 | /* Every completed frame needs to be acknowledged */ | 478 | /* Every completed frame needs to be acknowledged */ |
diff --git a/drivers/net/wireless/wl1251/wl1251.h b/drivers/net/wireless/wl1251/wl1251.h index c0ce2c8b43b8..bb23cd522b22 100644 --- a/drivers/net/wireless/wl1251/wl1251.h +++ b/drivers/net/wireless/wl1251/wl1251.h | |||
@@ -370,6 +370,8 @@ struct wl1251 { | |||
370 | /* in dBm */ | 370 | /* in dBm */ |
371 | int power_level; | 371 | int power_level; |
372 | 372 | ||
373 | int rssi_thold; | ||
374 | |||
373 | struct wl1251_stats stats; | 375 | struct wl1251_stats stats; |
374 | struct wl1251_debugfs debugfs; | 376 | struct wl1251_debugfs debugfs; |
375 | 377 | ||
@@ -410,6 +412,8 @@ void wl1251_disable_interrupts(struct wl1251 *wl); | |||
410 | 412 | ||
411 | #define WL1251_DEFAULT_CHANNEL 0 | 413 | #define WL1251_DEFAULT_CHANNEL 0 |
412 | 414 | ||
415 | #define WL1251_DEFAULT_BET_CONSECUTIVE 10 | ||
416 | |||
413 | #define CHIP_ID_1251_PG10 (0x7010101) | 417 | #define CHIP_ID_1251_PG10 (0x7010101) |
414 | #define CHIP_ID_1251_PG11 (0x7020101) | 418 | #define CHIP_ID_1251_PG11 (0x7020101) |
415 | #define CHIP_ID_1251_PG12 (0x7030101) | 419 | #define CHIP_ID_1251_PG12 (0x7030101) |
@@ -431,4 +435,7 @@ void wl1251_disable_interrupts(struct wl1251 *wl); | |||
431 | #define WL1251_PART_WORK_REG_START REGISTERS_BASE | 435 | #define WL1251_PART_WORK_REG_START REGISTERS_BASE |
432 | #define WL1251_PART_WORK_REG_SIZE REGISTERS_WORK_SIZE | 436 | #define WL1251_PART_WORK_REG_SIZE REGISTERS_WORK_SIZE |
433 | 437 | ||
438 | #define WL1251_DEFAULT_LOW_RSSI_WEIGHT 10 | ||
439 | #define WL1251_DEFAULT_LOW_RSSI_DEPTH 10 | ||
440 | |||
434 | #endif | 441 | #endif |
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c index 6a9b66051cf7..54f68f134ea7 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.c +++ b/drivers/net/wireless/zd1211rw/zd_chip.c | |||
@@ -108,25 +108,17 @@ int zd_ioread32v_locked(struct zd_chip *chip, u32 *values, const zd_addr_t *addr | |||
108 | { | 108 | { |
109 | int r; | 109 | int r; |
110 | int i; | 110 | int i; |
111 | zd_addr_t *a16; | 111 | zd_addr_t a16[USB_MAX_IOREAD32_COUNT * 2]; |
112 | u16 *v16; | 112 | u16 v16[USB_MAX_IOREAD32_COUNT * 2]; |
113 | unsigned int count16; | 113 | unsigned int count16; |
114 | 114 | ||
115 | if (count > USB_MAX_IOREAD32_COUNT) | 115 | if (count > USB_MAX_IOREAD32_COUNT) |
116 | return -EINVAL; | 116 | return -EINVAL; |
117 | 117 | ||
118 | /* Allocate a single memory block for values and addresses. */ | 118 | /* Use stack for values and addresses. */ |
119 | count16 = 2*count; | 119 | count16 = 2 * count; |
120 | /* zd_addr_t is __nocast, so the kmalloc needs an explicit cast */ | 120 | BUG_ON(count16 * sizeof(zd_addr_t) > sizeof(a16)); |
121 | a16 = (zd_addr_t *) kmalloc(count16 * (sizeof(zd_addr_t) + sizeof(u16)), | 121 | BUG_ON(count16 * sizeof(u16) > sizeof(v16)); |
122 | GFP_KERNEL); | ||
123 | if (!a16) { | ||
124 | dev_dbg_f(zd_chip_dev(chip), | ||
125 | "error ENOMEM in allocation of a16\n"); | ||
126 | r = -ENOMEM; | ||
127 | goto out; | ||
128 | } | ||
129 | v16 = (u16 *)(a16 + count16); | ||
130 | 122 | ||
131 | for (i = 0; i < count; i++) { | 123 | for (i = 0; i < count; i++) { |
132 | int j = 2*i; | 124 | int j = 2*i; |
@@ -139,7 +131,7 @@ int zd_ioread32v_locked(struct zd_chip *chip, u32 *values, const zd_addr_t *addr | |||
139 | if (r) { | 131 | if (r) { |
140 | dev_dbg_f(zd_chip_dev(chip), | 132 | dev_dbg_f(zd_chip_dev(chip), |
141 | "error: zd_ioread16v_locked. Error number %d\n", r); | 133 | "error: zd_ioread16v_locked. Error number %d\n", r); |
142 | goto out; | 134 | return r; |
143 | } | 135 | } |
144 | 136 | ||
145 | for (i = 0; i < count; i++) { | 137 | for (i = 0; i < count; i++) { |
@@ -147,18 +139,18 @@ int zd_ioread32v_locked(struct zd_chip *chip, u32 *values, const zd_addr_t *addr | |||
147 | values[i] = (v16[j] << 16) | v16[j+1]; | 139 | values[i] = (v16[j] << 16) | v16[j+1]; |
148 | } | 140 | } |
149 | 141 | ||
150 | out: | 142 | return 0; |
151 | kfree((void *)a16); | ||
152 | return r; | ||
153 | } | 143 | } |
154 | 144 | ||
155 | int _zd_iowrite32v_locked(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs, | 145 | int _zd_iowrite32v_locked(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs, |
156 | unsigned int count) | 146 | unsigned int count) |
157 | { | 147 | { |
158 | int i, j, r; | 148 | int i, j, r; |
159 | struct zd_ioreq16 *ioreqs16; | 149 | struct zd_ioreq16 ioreqs16[USB_MAX_IOWRITE32_COUNT * 2]; |
160 | unsigned int count16; | 150 | unsigned int count16; |
161 | 151 | ||
152 | /* Use stack for values and addresses. */ | ||
153 | |||
162 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | 154 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); |
163 | 155 | ||
164 | if (count == 0) | 156 | if (count == 0) |
@@ -166,15 +158,8 @@ int _zd_iowrite32v_locked(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs, | |||
166 | if (count > USB_MAX_IOWRITE32_COUNT) | 158 | if (count > USB_MAX_IOWRITE32_COUNT) |
167 | return -EINVAL; | 159 | return -EINVAL; |
168 | 160 | ||
169 | /* Allocate a single memory block for values and addresses. */ | 161 | count16 = 2 * count; |
170 | count16 = 2*count; | 162 | BUG_ON(count16 * sizeof(struct zd_ioreq16) > sizeof(ioreqs16)); |
171 | ioreqs16 = kmalloc(count16 * sizeof(struct zd_ioreq16), GFP_KERNEL); | ||
172 | if (!ioreqs16) { | ||
173 | r = -ENOMEM; | ||
174 | dev_dbg_f(zd_chip_dev(chip), | ||
175 | "error %d in ioreqs16 allocation\n", r); | ||
176 | goto out; | ||
177 | } | ||
178 | 163 | ||
179 | for (i = 0; i < count; i++) { | 164 | for (i = 0; i < count; i++) { |
180 | j = 2*i; | 165 | j = 2*i; |
@@ -192,8 +177,6 @@ int _zd_iowrite32v_locked(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs, | |||
192 | "error %d in zd_usb_write16v\n", r); | 177 | "error %d in zd_usb_write16v\n", r); |
193 | } | 178 | } |
194 | #endif /* DEBUG */ | 179 | #endif /* DEBUG */ |
195 | out: | ||
196 | kfree(ioreqs16); | ||
197 | return r; | 180 | return r; |
198 | } | 181 | } |
199 | 182 | ||
@@ -370,16 +353,12 @@ error: | |||
370 | return r; | 353 | return r; |
371 | } | 354 | } |
372 | 355 | ||
373 | /* MAC address: if custom mac addresses are to be used CR_MAC_ADDR_P1 and | 356 | static int zd_write_mac_addr_common(struct zd_chip *chip, const u8 *mac_addr, |
374 | * CR_MAC_ADDR_P2 must be overwritten | 357 | const struct zd_ioreq32 *in_reqs, |
375 | */ | 358 | const char *type) |
376 | int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr) | ||
377 | { | 359 | { |
378 | int r; | 360 | int r; |
379 | struct zd_ioreq32 reqs[2] = { | 361 | struct zd_ioreq32 reqs[2] = {in_reqs[0], in_reqs[1]}; |
380 | [0] = { .addr = CR_MAC_ADDR_P1 }, | ||
381 | [1] = { .addr = CR_MAC_ADDR_P2 }, | ||
382 | }; | ||
383 | 362 | ||
384 | if (mac_addr) { | 363 | if (mac_addr) { |
385 | reqs[0].value = (mac_addr[3] << 24) | 364 | reqs[0].value = (mac_addr[3] << 24) |
@@ -388,9 +367,9 @@ int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr) | |||
388 | | mac_addr[0]; | 367 | | mac_addr[0]; |
389 | reqs[1].value = (mac_addr[5] << 8) | 368 | reqs[1].value = (mac_addr[5] << 8) |
390 | | mac_addr[4]; | 369 | | mac_addr[4]; |
391 | dev_dbg_f(zd_chip_dev(chip), "mac addr %pM\n", mac_addr); | 370 | dev_dbg_f(zd_chip_dev(chip), "%s addr %pM\n", type, mac_addr); |
392 | } else { | 371 | } else { |
393 | dev_dbg_f(zd_chip_dev(chip), "set NULL mac\n"); | 372 | dev_dbg_f(zd_chip_dev(chip), "set NULL %s\n", type); |
394 | } | 373 | } |
395 | 374 | ||
396 | mutex_lock(&chip->mutex); | 375 | mutex_lock(&chip->mutex); |
@@ -399,6 +378,29 @@ int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr) | |||
399 | return r; | 378 | return r; |
400 | } | 379 | } |
401 | 380 | ||
381 | /* MAC address: if custom mac addresses are to be used CR_MAC_ADDR_P1 and | ||
382 | * CR_MAC_ADDR_P2 must be overwritten | ||
383 | */ | ||
384 | int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr) | ||
385 | { | ||
386 | static const struct zd_ioreq32 reqs[2] = { | ||
387 | [0] = { .addr = CR_MAC_ADDR_P1 }, | ||
388 | [1] = { .addr = CR_MAC_ADDR_P2 }, | ||
389 | }; | ||
390 | |||
391 | return zd_write_mac_addr_common(chip, mac_addr, reqs, "mac"); | ||
392 | } | ||
393 | |||
394 | int zd_write_bssid(struct zd_chip *chip, const u8 *bssid) | ||
395 | { | ||
396 | static const struct zd_ioreq32 reqs[2] = { | ||
397 | [0] = { .addr = CR_BSSID_P1 }, | ||
398 | [1] = { .addr = CR_BSSID_P2 }, | ||
399 | }; | ||
400 | |||
401 | return zd_write_mac_addr_common(chip, bssid, reqs, "bssid"); | ||
402 | } | ||
403 | |||
402 | int zd_read_regdomain(struct zd_chip *chip, u8 *regdomain) | 404 | int zd_read_regdomain(struct zd_chip *chip, u8 *regdomain) |
403 | { | 405 | { |
404 | int r; | 406 | int r; |
@@ -849,11 +851,12 @@ static int get_aw_pt_bi(struct zd_chip *chip, struct aw_pt_bi *s) | |||
849 | static int set_aw_pt_bi(struct zd_chip *chip, struct aw_pt_bi *s) | 851 | static int set_aw_pt_bi(struct zd_chip *chip, struct aw_pt_bi *s) |
850 | { | 852 | { |
851 | struct zd_ioreq32 reqs[3]; | 853 | struct zd_ioreq32 reqs[3]; |
854 | u16 b_interval = s->beacon_interval & 0xffff; | ||
852 | 855 | ||
853 | if (s->beacon_interval <= 5) | 856 | if (b_interval <= 5) |
854 | s->beacon_interval = 5; | 857 | b_interval = 5; |
855 | if (s->pre_tbtt < 4 || s->pre_tbtt >= s->beacon_interval) | 858 | if (s->pre_tbtt < 4 || s->pre_tbtt >= b_interval) |
856 | s->pre_tbtt = s->beacon_interval - 1; | 859 | s->pre_tbtt = b_interval - 1; |
857 | if (s->atim_wnd_period >= s->pre_tbtt) | 860 | if (s->atim_wnd_period >= s->pre_tbtt) |
858 | s->atim_wnd_period = s->pre_tbtt - 1; | 861 | s->atim_wnd_period = s->pre_tbtt - 1; |
859 | 862 | ||
@@ -862,31 +865,57 @@ static int set_aw_pt_bi(struct zd_chip *chip, struct aw_pt_bi *s) | |||
862 | reqs[1].addr = CR_PRE_TBTT; | 865 | reqs[1].addr = CR_PRE_TBTT; |
863 | reqs[1].value = s->pre_tbtt; | 866 | reqs[1].value = s->pre_tbtt; |
864 | reqs[2].addr = CR_BCN_INTERVAL; | 867 | reqs[2].addr = CR_BCN_INTERVAL; |
865 | reqs[2].value = s->beacon_interval; | 868 | reqs[2].value = (s->beacon_interval & ~0xffff) | b_interval; |
866 | 869 | ||
867 | return zd_iowrite32a_locked(chip, reqs, ARRAY_SIZE(reqs)); | 870 | return zd_iowrite32a_locked(chip, reqs, ARRAY_SIZE(reqs)); |
868 | } | 871 | } |
869 | 872 | ||
870 | 873 | ||
871 | static int set_beacon_interval(struct zd_chip *chip, u32 interval) | 874 | static int set_beacon_interval(struct zd_chip *chip, u16 interval, |
875 | u8 dtim_period, int type) | ||
872 | { | 876 | { |
873 | int r; | 877 | int r; |
874 | struct aw_pt_bi s; | 878 | struct aw_pt_bi s; |
879 | u32 b_interval, mode_flag; | ||
875 | 880 | ||
876 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); | 881 | ZD_ASSERT(mutex_is_locked(&chip->mutex)); |
882 | |||
883 | if (interval > 0) { | ||
884 | switch (type) { | ||
885 | case NL80211_IFTYPE_ADHOC: | ||
886 | case NL80211_IFTYPE_MESH_POINT: | ||
887 | mode_flag = BCN_MODE_IBSS; | ||
888 | break; | ||
889 | case NL80211_IFTYPE_AP: | ||
890 | mode_flag = BCN_MODE_AP; | ||
891 | break; | ||
892 | default: | ||
893 | mode_flag = 0; | ||
894 | break; | ||
895 | } | ||
896 | } else { | ||
897 | dtim_period = 0; | ||
898 | mode_flag = 0; | ||
899 | } | ||
900 | |||
901 | b_interval = mode_flag | (dtim_period << 16) | interval; | ||
902 | |||
903 | r = zd_iowrite32_locked(chip, b_interval, CR_BCN_INTERVAL); | ||
904 | if (r) | ||
905 | return r; | ||
877 | r = get_aw_pt_bi(chip, &s); | 906 | r = get_aw_pt_bi(chip, &s); |
878 | if (r) | 907 | if (r) |
879 | return r; | 908 | return r; |
880 | s.beacon_interval = interval; | ||
881 | return set_aw_pt_bi(chip, &s); | 909 | return set_aw_pt_bi(chip, &s); |
882 | } | 910 | } |
883 | 911 | ||
884 | int zd_set_beacon_interval(struct zd_chip *chip, u32 interval) | 912 | int zd_set_beacon_interval(struct zd_chip *chip, u16 interval, u8 dtim_period, |
913 | int type) | ||
885 | { | 914 | { |
886 | int r; | 915 | int r; |
887 | 916 | ||
888 | mutex_lock(&chip->mutex); | 917 | mutex_lock(&chip->mutex); |
889 | r = set_beacon_interval(chip, interval); | 918 | r = set_beacon_interval(chip, interval, dtim_period, type); |
890 | mutex_unlock(&chip->mutex); | 919 | mutex_unlock(&chip->mutex); |
891 | return r; | 920 | return r; |
892 | } | 921 | } |
@@ -905,7 +934,7 @@ static int hw_init(struct zd_chip *chip) | |||
905 | if (r) | 934 | if (r) |
906 | return r; | 935 | return r; |
907 | 936 | ||
908 | return set_beacon_interval(chip, 100); | 937 | return set_beacon_interval(chip, 100, 0, NL80211_IFTYPE_UNSPECIFIED); |
909 | } | 938 | } |
910 | 939 | ||
911 | static zd_addr_t fw_reg_addr(struct zd_chip *chip, u16 offset) | 940 | static zd_addr_t fw_reg_addr(struct zd_chip *chip, u16 offset) |
@@ -1407,6 +1436,9 @@ void zd_chip_disable_int(struct zd_chip *chip) | |||
1407 | mutex_lock(&chip->mutex); | 1436 | mutex_lock(&chip->mutex); |
1408 | zd_usb_disable_int(&chip->usb); | 1437 | zd_usb_disable_int(&chip->usb); |
1409 | mutex_unlock(&chip->mutex); | 1438 | mutex_unlock(&chip->mutex); |
1439 | |||
1440 | /* cancel pending interrupt work */ | ||
1441 | cancel_work_sync(&zd_chip_to_mac(chip)->process_intr); | ||
1410 | } | 1442 | } |
1411 | 1443 | ||
1412 | int zd_chip_enable_rxtx(struct zd_chip *chip) | 1444 | int zd_chip_enable_rxtx(struct zd_chip *chip) |
@@ -1416,6 +1448,7 @@ int zd_chip_enable_rxtx(struct zd_chip *chip) | |||
1416 | mutex_lock(&chip->mutex); | 1448 | mutex_lock(&chip->mutex); |
1417 | zd_usb_enable_tx(&chip->usb); | 1449 | zd_usb_enable_tx(&chip->usb); |
1418 | r = zd_usb_enable_rx(&chip->usb); | 1450 | r = zd_usb_enable_rx(&chip->usb); |
1451 | zd_tx_watchdog_enable(&chip->usb); | ||
1419 | mutex_unlock(&chip->mutex); | 1452 | mutex_unlock(&chip->mutex); |
1420 | return r; | 1453 | return r; |
1421 | } | 1454 | } |
@@ -1423,6 +1456,7 @@ int zd_chip_enable_rxtx(struct zd_chip *chip) | |||
1423 | void zd_chip_disable_rxtx(struct zd_chip *chip) | 1456 | void zd_chip_disable_rxtx(struct zd_chip *chip) |
1424 | { | 1457 | { |
1425 | mutex_lock(&chip->mutex); | 1458 | mutex_lock(&chip->mutex); |
1459 | zd_tx_watchdog_disable(&chip->usb); | ||
1426 | zd_usb_disable_rx(&chip->usb); | 1460 | zd_usb_disable_rx(&chip->usb); |
1427 | zd_usb_disable_tx(&chip->usb); | 1461 | zd_usb_disable_tx(&chip->usb); |
1428 | mutex_unlock(&chip->mutex); | 1462 | mutex_unlock(&chip->mutex); |
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h index f8bbf7d302ae..14e4402a6111 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.h +++ b/drivers/net/wireless/zd1211rw/zd_chip.h | |||
@@ -546,6 +546,7 @@ enum { | |||
546 | #define RX_FILTER_CTRL (RX_FILTER_RTS | RX_FILTER_CTS | \ | 546 | #define RX_FILTER_CTRL (RX_FILTER_RTS | RX_FILTER_CTS | \ |
547 | RX_FILTER_CFEND | RX_FILTER_CFACK) | 547 | RX_FILTER_CFEND | RX_FILTER_CFACK) |
548 | 548 | ||
549 | #define BCN_MODE_AP 0x1000000 | ||
549 | #define BCN_MODE_IBSS 0x2000000 | 550 | #define BCN_MODE_IBSS 0x2000000 |
550 | 551 | ||
551 | /* Monitor mode sets filter to 0xfffff */ | 552 | /* Monitor mode sets filter to 0xfffff */ |
@@ -881,6 +882,7 @@ static inline u8 _zd_chip_get_channel(struct zd_chip *chip) | |||
881 | u8 zd_chip_get_channel(struct zd_chip *chip); | 882 | u8 zd_chip_get_channel(struct zd_chip *chip); |
882 | int zd_read_regdomain(struct zd_chip *chip, u8 *regdomain); | 883 | int zd_read_regdomain(struct zd_chip *chip, u8 *regdomain); |
883 | int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr); | 884 | int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr); |
885 | int zd_write_bssid(struct zd_chip *chip, const u8 *bssid); | ||
884 | int zd_chip_switch_radio_on(struct zd_chip *chip); | 886 | int zd_chip_switch_radio_on(struct zd_chip *chip); |
885 | int zd_chip_switch_radio_off(struct zd_chip *chip); | 887 | int zd_chip_switch_radio_off(struct zd_chip *chip); |
886 | int zd_chip_enable_int(struct zd_chip *chip); | 888 | int zd_chip_enable_int(struct zd_chip *chip); |
@@ -920,7 +922,8 @@ enum led_status { | |||
920 | 922 | ||
921 | int zd_chip_control_leds(struct zd_chip *chip, enum led_status status); | 923 | int zd_chip_control_leds(struct zd_chip *chip, enum led_status status); |
922 | 924 | ||
923 | int zd_set_beacon_interval(struct zd_chip *chip, u32 interval); | 925 | int zd_set_beacon_interval(struct zd_chip *chip, u16 interval, u8 dtim_period, |
926 | int type); | ||
924 | 927 | ||
925 | static inline int zd_get_beacon_interval(struct zd_chip *chip, u32 *interval) | 928 | static inline int zd_get_beacon_interval(struct zd_chip *chip, u32 *interval) |
926 | { | 929 | { |
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index 6107304cb94c..74a269ebbeb9 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c | |||
@@ -138,6 +138,12 @@ static const struct ieee80211_channel zd_channels[] = { | |||
138 | static void housekeeping_init(struct zd_mac *mac); | 138 | static void housekeeping_init(struct zd_mac *mac); |
139 | static void housekeeping_enable(struct zd_mac *mac); | 139 | static void housekeeping_enable(struct zd_mac *mac); |
140 | static void housekeeping_disable(struct zd_mac *mac); | 140 | static void housekeeping_disable(struct zd_mac *mac); |
141 | static void beacon_init(struct zd_mac *mac); | ||
142 | static void beacon_enable(struct zd_mac *mac); | ||
143 | static void beacon_disable(struct zd_mac *mac); | ||
144 | static void set_rts_cts(struct zd_mac *mac, unsigned int short_preamble); | ||
145 | static int zd_mac_config_beacon(struct ieee80211_hw *hw, | ||
146 | struct sk_buff *beacon); | ||
141 | 147 | ||
142 | static int zd_reg2alpha2(u8 regdomain, char *alpha2) | 148 | static int zd_reg2alpha2(u8 regdomain, char *alpha2) |
143 | { | 149 | { |
@@ -231,6 +237,26 @@ static int set_rx_filter(struct zd_mac *mac) | |||
231 | return zd_iowrite32(&mac->chip, CR_RX_FILTER, filter); | 237 | return zd_iowrite32(&mac->chip, CR_RX_FILTER, filter); |
232 | } | 238 | } |
233 | 239 | ||
240 | static int set_mac_and_bssid(struct zd_mac *mac) | ||
241 | { | ||
242 | int r; | ||
243 | |||
244 | if (!mac->vif) | ||
245 | return -1; | ||
246 | |||
247 | r = zd_write_mac_addr(&mac->chip, mac->vif->addr); | ||
248 | if (r) | ||
249 | return r; | ||
250 | |||
251 | /* Vendor driver after setting MAC either sets BSSID for AP or | ||
252 | * filter for other modes. | ||
253 | */ | ||
254 | if (mac->type != NL80211_IFTYPE_AP) | ||
255 | return set_rx_filter(mac); | ||
256 | else | ||
257 | return zd_write_bssid(&mac->chip, mac->vif->addr); | ||
258 | } | ||
259 | |||
234 | static int set_mc_hash(struct zd_mac *mac) | 260 | static int set_mc_hash(struct zd_mac *mac) |
235 | { | 261 | { |
236 | struct zd_mc_hash hash; | 262 | struct zd_mc_hash hash; |
@@ -238,7 +264,7 @@ static int set_mc_hash(struct zd_mac *mac) | |||
238 | return zd_chip_set_multicast_hash(&mac->chip, &hash); | 264 | return zd_chip_set_multicast_hash(&mac->chip, &hash); |
239 | } | 265 | } |
240 | 266 | ||
241 | static int zd_op_start(struct ieee80211_hw *hw) | 267 | int zd_op_start(struct ieee80211_hw *hw) |
242 | { | 268 | { |
243 | struct zd_mac *mac = zd_hw_mac(hw); | 269 | struct zd_mac *mac = zd_hw_mac(hw); |
244 | struct zd_chip *chip = &mac->chip; | 270 | struct zd_chip *chip = &mac->chip; |
@@ -275,6 +301,8 @@ static int zd_op_start(struct ieee80211_hw *hw) | |||
275 | goto disable_rxtx; | 301 | goto disable_rxtx; |
276 | 302 | ||
277 | housekeeping_enable(mac); | 303 | housekeeping_enable(mac); |
304 | beacon_enable(mac); | ||
305 | set_bit(ZD_DEVICE_RUNNING, &mac->flags); | ||
278 | return 0; | 306 | return 0; |
279 | disable_rxtx: | 307 | disable_rxtx: |
280 | zd_chip_disable_rxtx(chip); | 308 | zd_chip_disable_rxtx(chip); |
@@ -286,19 +314,22 @@ out: | |||
286 | return r; | 314 | return r; |
287 | } | 315 | } |
288 | 316 | ||
289 | static void zd_op_stop(struct ieee80211_hw *hw) | 317 | void zd_op_stop(struct ieee80211_hw *hw) |
290 | { | 318 | { |
291 | struct zd_mac *mac = zd_hw_mac(hw); | 319 | struct zd_mac *mac = zd_hw_mac(hw); |
292 | struct zd_chip *chip = &mac->chip; | 320 | struct zd_chip *chip = &mac->chip; |
293 | struct sk_buff *skb; | 321 | struct sk_buff *skb; |
294 | struct sk_buff_head *ack_wait_queue = &mac->ack_wait_queue; | 322 | struct sk_buff_head *ack_wait_queue = &mac->ack_wait_queue; |
295 | 323 | ||
324 | clear_bit(ZD_DEVICE_RUNNING, &mac->flags); | ||
325 | |||
296 | /* The order here deliberately is a little different from the open() | 326 | /* The order here deliberately is a little different from the open() |
297 | * method, since we need to make sure there is no opportunity for RX | 327 | * method, since we need to make sure there is no opportunity for RX |
298 | * frames to be processed by mac80211 after we have stopped it. | 328 | * frames to be processed by mac80211 after we have stopped it. |
299 | */ | 329 | */ |
300 | 330 | ||
301 | zd_chip_disable_rxtx(chip); | 331 | zd_chip_disable_rxtx(chip); |
332 | beacon_disable(mac); | ||
302 | housekeeping_disable(mac); | 333 | housekeeping_disable(mac); |
303 | flush_workqueue(zd_workqueue); | 334 | flush_workqueue(zd_workqueue); |
304 | 335 | ||
@@ -311,6 +342,68 @@ static void zd_op_stop(struct ieee80211_hw *hw) | |||
311 | dev_kfree_skb_any(skb); | 342 | dev_kfree_skb_any(skb); |
312 | } | 343 | } |
313 | 344 | ||
345 | int zd_restore_settings(struct zd_mac *mac) | ||
346 | { | ||
347 | struct sk_buff *beacon; | ||
348 | struct zd_mc_hash multicast_hash; | ||
349 | unsigned int short_preamble; | ||
350 | int r, beacon_interval, beacon_period; | ||
351 | u8 channel; | ||
352 | |||
353 | dev_dbg_f(zd_mac_dev(mac), "\n"); | ||
354 | |||
355 | spin_lock_irq(&mac->lock); | ||
356 | multicast_hash = mac->multicast_hash; | ||
357 | short_preamble = mac->short_preamble; | ||
358 | beacon_interval = mac->beacon.interval; | ||
359 | beacon_period = mac->beacon.period; | ||
360 | channel = mac->channel; | ||
361 | spin_unlock_irq(&mac->lock); | ||
362 | |||
363 | r = set_mac_and_bssid(mac); | ||
364 | if (r < 0) { | ||
365 | dev_dbg_f(zd_mac_dev(mac), "set_mac_and_bssid failed, %d\n", r); | ||
366 | return r; | ||
367 | } | ||
368 | |||
369 | r = zd_chip_set_channel(&mac->chip, channel); | ||
370 | if (r < 0) { | ||
371 | dev_dbg_f(zd_mac_dev(mac), "zd_chip_set_channel failed, %d\n", | ||
372 | r); | ||
373 | return r; | ||
374 | } | ||
375 | |||
376 | set_rts_cts(mac, short_preamble); | ||
377 | |||
378 | r = zd_chip_set_multicast_hash(&mac->chip, &multicast_hash); | ||
379 | if (r < 0) { | ||
380 | dev_dbg_f(zd_mac_dev(mac), | ||
381 | "zd_chip_set_multicast_hash failed, %d\n", r); | ||
382 | return r; | ||
383 | } | ||
384 | |||
385 | if (mac->type == NL80211_IFTYPE_MESH_POINT || | ||
386 | mac->type == NL80211_IFTYPE_ADHOC || | ||
387 | mac->type == NL80211_IFTYPE_AP) { | ||
388 | if (mac->vif != NULL) { | ||
389 | beacon = ieee80211_beacon_get(mac->hw, mac->vif); | ||
390 | if (beacon) { | ||
391 | zd_mac_config_beacon(mac->hw, beacon); | ||
392 | kfree_skb(beacon); | ||
393 | } | ||
394 | } | ||
395 | |||
396 | zd_set_beacon_interval(&mac->chip, beacon_interval, | ||
397 | beacon_period, mac->type); | ||
398 | |||
399 | spin_lock_irq(&mac->lock); | ||
400 | mac->beacon.last_update = jiffies; | ||
401 | spin_unlock_irq(&mac->lock); | ||
402 | } | ||
403 | |||
404 | return 0; | ||
405 | } | ||
406 | |||
314 | /** | 407 | /** |
315 | * zd_mac_tx_status - reports tx status of a packet if required | 408 | * zd_mac_tx_status - reports tx status of a packet if required |
316 | * @hw - a &struct ieee80211_hw pointer | 409 | * @hw - a &struct ieee80211_hw pointer |
@@ -574,64 +667,120 @@ static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs, | |||
574 | static int zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon) | 667 | static int zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon) |
575 | { | 668 | { |
576 | struct zd_mac *mac = zd_hw_mac(hw); | 669 | struct zd_mac *mac = zd_hw_mac(hw); |
577 | int r; | 670 | int r, ret, num_cmds, req_pos = 0; |
578 | u32 tmp, j = 0; | 671 | u32 tmp, j = 0; |
579 | /* 4 more bytes for tail CRC */ | 672 | /* 4 more bytes for tail CRC */ |
580 | u32 full_len = beacon->len + 4; | 673 | u32 full_len = beacon->len + 4; |
674 | unsigned long end_jiffies, message_jiffies; | ||
675 | struct zd_ioreq32 *ioreqs; | ||
676 | |||
677 | /* Alloc memory for full beacon write at once. */ | ||
678 | num_cmds = 1 + zd_chip_is_zd1211b(&mac->chip) + full_len; | ||
679 | ioreqs = kmalloc(num_cmds * sizeof(struct zd_ioreq32), GFP_KERNEL); | ||
680 | if (!ioreqs) | ||
681 | return -ENOMEM; | ||
581 | 682 | ||
582 | r = zd_iowrite32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, 0); | 683 | mutex_lock(&mac->chip.mutex); |
684 | |||
685 | r = zd_iowrite32_locked(&mac->chip, 0, CR_BCN_FIFO_SEMAPHORE); | ||
583 | if (r < 0) | 686 | if (r < 0) |
584 | return r; | 687 | goto out; |
585 | r = zd_ioread32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, &tmp); | 688 | r = zd_ioread32_locked(&mac->chip, &tmp, CR_BCN_FIFO_SEMAPHORE); |
586 | if (r < 0) | 689 | if (r < 0) |
587 | return r; | 690 | goto release_sema; |
588 | 691 | ||
692 | end_jiffies = jiffies + HZ / 2; /*~500ms*/ | ||
693 | message_jiffies = jiffies + HZ / 10; /*~100ms*/ | ||
589 | while (tmp & 0x2) { | 694 | while (tmp & 0x2) { |
590 | r = zd_ioread32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, &tmp); | 695 | r = zd_ioread32_locked(&mac->chip, &tmp, CR_BCN_FIFO_SEMAPHORE); |
591 | if (r < 0) | 696 | if (r < 0) |
592 | return r; | 697 | goto release_sema; |
593 | if ((++j % 100) == 0) { | 698 | if (time_is_before_eq_jiffies(message_jiffies)) { |
594 | printk(KERN_ERR "CR_BCN_FIFO_SEMAPHORE not ready\n"); | 699 | message_jiffies = jiffies + HZ / 10; |
595 | if (j >= 500) { | 700 | dev_err(zd_mac_dev(mac), |
596 | printk(KERN_ERR "Giving up beacon config.\n"); | 701 | "CR_BCN_FIFO_SEMAPHORE not ready\n"); |
597 | return -ETIMEDOUT; | 702 | if (time_is_before_eq_jiffies(end_jiffies)) { |
703 | dev_err(zd_mac_dev(mac), | ||
704 | "Giving up beacon config.\n"); | ||
705 | r = -ETIMEDOUT; | ||
706 | goto reset_device; | ||
598 | } | 707 | } |
599 | } | 708 | } |
600 | msleep(1); | 709 | msleep(20); |
601 | } | 710 | } |
602 | 711 | ||
603 | r = zd_iowrite32(&mac->chip, CR_BCN_FIFO, full_len - 1); | 712 | ioreqs[req_pos].addr = CR_BCN_FIFO; |
604 | if (r < 0) | 713 | ioreqs[req_pos].value = full_len - 1; |
605 | return r; | 714 | req_pos++; |
606 | if (zd_chip_is_zd1211b(&mac->chip)) { | 715 | if (zd_chip_is_zd1211b(&mac->chip)) { |
607 | r = zd_iowrite32(&mac->chip, CR_BCN_LENGTH, full_len - 1); | 716 | ioreqs[req_pos].addr = CR_BCN_LENGTH; |
608 | if (r < 0) | 717 | ioreqs[req_pos].value = full_len - 1; |
609 | return r; | 718 | req_pos++; |
610 | } | 719 | } |
611 | 720 | ||
612 | for (j = 0 ; j < beacon->len; j++) { | 721 | for (j = 0 ; j < beacon->len; j++) { |
613 | r = zd_iowrite32(&mac->chip, CR_BCN_FIFO, | 722 | ioreqs[req_pos].addr = CR_BCN_FIFO; |
614 | *((u8 *)(beacon->data + j))); | 723 | ioreqs[req_pos].value = *((u8 *)(beacon->data + j)); |
615 | if (r < 0) | 724 | req_pos++; |
616 | return r; | ||
617 | } | 725 | } |
618 | 726 | ||
619 | for (j = 0; j < 4; j++) { | 727 | for (j = 0; j < 4; j++) { |
620 | r = zd_iowrite32(&mac->chip, CR_BCN_FIFO, 0x0); | 728 | ioreqs[req_pos].addr = CR_BCN_FIFO; |
621 | if (r < 0) | 729 | ioreqs[req_pos].value = 0x0; |
622 | return r; | 730 | req_pos++; |
623 | } | 731 | } |
624 | 732 | ||
625 | r = zd_iowrite32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, 1); | 733 | BUG_ON(req_pos != num_cmds); |
626 | if (r < 0) | 734 | |
627 | return r; | 735 | r = zd_iowrite32a_locked(&mac->chip, ioreqs, num_cmds); |
736 | |||
737 | release_sema: | ||
738 | /* | ||
739 | * Try very hard to release device beacon semaphore, as otherwise | ||
740 | * device/driver can be left in unusable state. | ||
741 | */ | ||
742 | end_jiffies = jiffies + HZ / 2; /*~500ms*/ | ||
743 | ret = zd_iowrite32_locked(&mac->chip, 1, CR_BCN_FIFO_SEMAPHORE); | ||
744 | while (ret < 0) { | ||
745 | if (time_is_before_eq_jiffies(end_jiffies)) { | ||
746 | ret = -ETIMEDOUT; | ||
747 | break; | ||
748 | } | ||
749 | |||
750 | msleep(20); | ||
751 | ret = zd_iowrite32_locked(&mac->chip, 1, CR_BCN_FIFO_SEMAPHORE); | ||
752 | } | ||
753 | |||
754 | if (ret < 0) | ||
755 | dev_err(zd_mac_dev(mac), "Could not release " | ||
756 | "CR_BCN_FIFO_SEMAPHORE!\n"); | ||
757 | if (r < 0 || ret < 0) { | ||
758 | if (r >= 0) | ||
759 | r = ret; | ||
760 | goto out; | ||
761 | } | ||
628 | 762 | ||
629 | /* 802.11b/g 2.4G CCK 1Mb | 763 | /* 802.11b/g 2.4G CCK 1Mb |
630 | * 802.11a, not yet implemented, uses different values (see GPL vendor | 764 | * 802.11a, not yet implemented, uses different values (see GPL vendor |
631 | * driver) | 765 | * driver) |
632 | */ | 766 | */ |
633 | return zd_iowrite32(&mac->chip, CR_BCN_PLCP_CFG, 0x00000400 | | 767 | r = zd_iowrite32_locked(&mac->chip, 0x00000400 | (full_len << 19), |
634 | (full_len << 19)); | 768 | CR_BCN_PLCP_CFG); |
769 | out: | ||
770 | mutex_unlock(&mac->chip.mutex); | ||
771 | kfree(ioreqs); | ||
772 | return r; | ||
773 | |||
774 | reset_device: | ||
775 | mutex_unlock(&mac->chip.mutex); | ||
776 | kfree(ioreqs); | ||
777 | |||
778 | /* semaphore stuck, reset device to avoid fw freeze later */ | ||
779 | dev_warn(zd_mac_dev(mac), "CR_BCN_FIFO_SEMAPHORE stuck, " | ||
780 | "reseting device..."); | ||
781 | usb_queue_reset_device(mac->chip.usb.intf); | ||
782 | |||
783 | return r; | ||
635 | } | 784 | } |
636 | 785 | ||
637 | static int fill_ctrlset(struct zd_mac *mac, | 786 | static int fill_ctrlset(struct zd_mac *mac, |
@@ -779,6 +928,13 @@ static int filter_ack(struct ieee80211_hw *hw, struct ieee80211_hdr *rx_hdr, | |||
779 | 928 | ||
780 | mac->ack_pending = 1; | 929 | mac->ack_pending = 1; |
781 | mac->ack_signal = stats->signal; | 930 | mac->ack_signal = stats->signal; |
931 | |||
932 | /* Prevent pending tx-packet on AP-mode */ | ||
933 | if (mac->type == NL80211_IFTYPE_AP) { | ||
934 | skb = __skb_dequeue(q); | ||
935 | zd_mac_tx_status(hw, skb, mac->ack_signal, NULL); | ||
936 | mac->ack_pending = 0; | ||
937 | } | ||
782 | } | 938 | } |
783 | 939 | ||
784 | spin_unlock_irqrestore(&q->lock, flags); | 940 | spin_unlock_irqrestore(&q->lock, flags); |
@@ -882,13 +1038,16 @@ static int zd_op_add_interface(struct ieee80211_hw *hw, | |||
882 | case NL80211_IFTYPE_MESH_POINT: | 1038 | case NL80211_IFTYPE_MESH_POINT: |
883 | case NL80211_IFTYPE_STATION: | 1039 | case NL80211_IFTYPE_STATION: |
884 | case NL80211_IFTYPE_ADHOC: | 1040 | case NL80211_IFTYPE_ADHOC: |
1041 | case NL80211_IFTYPE_AP: | ||
885 | mac->type = vif->type; | 1042 | mac->type = vif->type; |
886 | break; | 1043 | break; |
887 | default: | 1044 | default: |
888 | return -EOPNOTSUPP; | 1045 | return -EOPNOTSUPP; |
889 | } | 1046 | } |
890 | 1047 | ||
891 | return zd_write_mac_addr(&mac->chip, vif->addr); | 1048 | mac->vif = vif; |
1049 | |||
1050 | return set_mac_and_bssid(mac); | ||
892 | } | 1051 | } |
893 | 1052 | ||
894 | static void zd_op_remove_interface(struct ieee80211_hw *hw, | 1053 | static void zd_op_remove_interface(struct ieee80211_hw *hw, |
@@ -896,7 +1055,8 @@ static void zd_op_remove_interface(struct ieee80211_hw *hw, | |||
896 | { | 1055 | { |
897 | struct zd_mac *mac = zd_hw_mac(hw); | 1056 | struct zd_mac *mac = zd_hw_mac(hw); |
898 | mac->type = NL80211_IFTYPE_UNSPECIFIED; | 1057 | mac->type = NL80211_IFTYPE_UNSPECIFIED; |
899 | zd_set_beacon_interval(&mac->chip, 0); | 1058 | mac->vif = NULL; |
1059 | zd_set_beacon_interval(&mac->chip, 0, 0, NL80211_IFTYPE_UNSPECIFIED); | ||
900 | zd_write_mac_addr(&mac->chip, NULL); | 1060 | zd_write_mac_addr(&mac->chip, NULL); |
901 | } | 1061 | } |
902 | 1062 | ||
@@ -905,49 +1065,67 @@ static int zd_op_config(struct ieee80211_hw *hw, u32 changed) | |||
905 | struct zd_mac *mac = zd_hw_mac(hw); | 1065 | struct zd_mac *mac = zd_hw_mac(hw); |
906 | struct ieee80211_conf *conf = &hw->conf; | 1066 | struct ieee80211_conf *conf = &hw->conf; |
907 | 1067 | ||
1068 | spin_lock_irq(&mac->lock); | ||
1069 | mac->channel = conf->channel->hw_value; | ||
1070 | spin_unlock_irq(&mac->lock); | ||
1071 | |||
908 | return zd_chip_set_channel(&mac->chip, conf->channel->hw_value); | 1072 | return zd_chip_set_channel(&mac->chip, conf->channel->hw_value); |
909 | } | 1073 | } |
910 | 1074 | ||
911 | static void zd_process_intr(struct work_struct *work) | 1075 | static void zd_beacon_done(struct zd_mac *mac) |
912 | { | 1076 | { |
913 | u16 int_status; | 1077 | struct sk_buff *skb, *beacon; |
914 | struct zd_mac *mac = container_of(work, struct zd_mac, process_intr); | ||
915 | 1078 | ||
916 | int_status = le16_to_cpu(*(__le16 *)(mac->intr_buffer+4)); | 1079 | if (!test_bit(ZD_DEVICE_RUNNING, &mac->flags)) |
917 | if (int_status & INT_CFG_NEXT_BCN) | 1080 | return; |
918 | dev_dbg_f_limit(zd_mac_dev(mac), "INT_CFG_NEXT_BCN\n"); | 1081 | if (!mac->vif || mac->vif->type != NL80211_IFTYPE_AP) |
919 | else | 1082 | return; |
920 | dev_dbg_f(zd_mac_dev(mac), "Unsupported interrupt\n"); | ||
921 | |||
922 | zd_chip_enable_hwint(&mac->chip); | ||
923 | } | ||
924 | 1083 | ||
1084 | /* | ||
1085 | * Send out buffered broad- and multicast frames. | ||
1086 | */ | ||
1087 | while (!ieee80211_queue_stopped(mac->hw, 0)) { | ||
1088 | skb = ieee80211_get_buffered_bc(mac->hw, mac->vif); | ||
1089 | if (!skb) | ||
1090 | break; | ||
1091 | zd_op_tx(mac->hw, skb); | ||
1092 | } | ||
925 | 1093 | ||
926 | static void set_multicast_hash_handler(struct work_struct *work) | 1094 | /* |
927 | { | 1095 | * Fetch next beacon so that tim_count is updated. |
928 | struct zd_mac *mac = | 1096 | */ |
929 | container_of(work, struct zd_mac, set_multicast_hash_work); | 1097 | beacon = ieee80211_beacon_get(mac->hw, mac->vif); |
930 | struct zd_mc_hash hash; | 1098 | if (beacon) { |
1099 | zd_mac_config_beacon(mac->hw, beacon); | ||
1100 | kfree_skb(beacon); | ||
1101 | } | ||
931 | 1102 | ||
932 | spin_lock_irq(&mac->lock); | 1103 | spin_lock_irq(&mac->lock); |
933 | hash = mac->multicast_hash; | 1104 | mac->beacon.last_update = jiffies; |
934 | spin_unlock_irq(&mac->lock); | 1105 | spin_unlock_irq(&mac->lock); |
935 | |||
936 | zd_chip_set_multicast_hash(&mac->chip, &hash); | ||
937 | } | 1106 | } |
938 | 1107 | ||
939 | static void set_rx_filter_handler(struct work_struct *work) | 1108 | static void zd_process_intr(struct work_struct *work) |
940 | { | 1109 | { |
941 | struct zd_mac *mac = | 1110 | u16 int_status; |
942 | container_of(work, struct zd_mac, set_rx_filter_work); | 1111 | unsigned long flags; |
943 | int r; | 1112 | struct zd_mac *mac = container_of(work, struct zd_mac, process_intr); |
944 | 1113 | ||
945 | dev_dbg_f(zd_mac_dev(mac), "\n"); | 1114 | spin_lock_irqsave(&mac->lock, flags); |
946 | r = set_rx_filter(mac); | 1115 | int_status = le16_to_cpu(*(__le16 *)(mac->intr_buffer + 4)); |
947 | if (r) | 1116 | spin_unlock_irqrestore(&mac->lock, flags); |
948 | dev_err(zd_mac_dev(mac), "set_rx_filter_handler error %d\n", r); | 1117 | |
1118 | if (int_status & INT_CFG_NEXT_BCN) { | ||
1119 | /*dev_dbg_f_limit(zd_mac_dev(mac), "INT_CFG_NEXT_BCN\n");*/ | ||
1120 | zd_beacon_done(mac); | ||
1121 | } else { | ||
1122 | dev_dbg_f(zd_mac_dev(mac), "Unsupported interrupt\n"); | ||
1123 | } | ||
1124 | |||
1125 | zd_chip_enable_hwint(&mac->chip); | ||
949 | } | 1126 | } |
950 | 1127 | ||
1128 | |||
951 | static u64 zd_op_prepare_multicast(struct ieee80211_hw *hw, | 1129 | static u64 zd_op_prepare_multicast(struct ieee80211_hw *hw, |
952 | struct netdev_hw_addr_list *mc_list) | 1130 | struct netdev_hw_addr_list *mc_list) |
953 | { | 1131 | { |
@@ -979,6 +1157,7 @@ static void zd_op_configure_filter(struct ieee80211_hw *hw, | |||
979 | }; | 1157 | }; |
980 | struct zd_mac *mac = zd_hw_mac(hw); | 1158 | struct zd_mac *mac = zd_hw_mac(hw); |
981 | unsigned long flags; | 1159 | unsigned long flags; |
1160 | int r; | ||
982 | 1161 | ||
983 | /* Only deal with supported flags */ | 1162 | /* Only deal with supported flags */ |
984 | changed_flags &= SUPPORTED_FIF_FLAGS; | 1163 | changed_flags &= SUPPORTED_FIF_FLAGS; |
@@ -1000,11 +1179,13 @@ static void zd_op_configure_filter(struct ieee80211_hw *hw, | |||
1000 | mac->multicast_hash = hash; | 1179 | mac->multicast_hash = hash; |
1001 | spin_unlock_irqrestore(&mac->lock, flags); | 1180 | spin_unlock_irqrestore(&mac->lock, flags); |
1002 | 1181 | ||
1003 | /* XXX: these can be called here now, can sleep now! */ | 1182 | zd_chip_set_multicast_hash(&mac->chip, &hash); |
1004 | queue_work(zd_workqueue, &mac->set_multicast_hash_work); | ||
1005 | 1183 | ||
1006 | if (changed_flags & FIF_CONTROL) | 1184 | if (changed_flags & FIF_CONTROL) { |
1007 | queue_work(zd_workqueue, &mac->set_rx_filter_work); | 1185 | r = set_rx_filter(mac); |
1186 | if (r) | ||
1187 | dev_err(zd_mac_dev(mac), "set_rx_filter error %d\n", r); | ||
1188 | } | ||
1008 | 1189 | ||
1009 | /* no handling required for FIF_OTHER_BSS as we don't currently | 1190 | /* no handling required for FIF_OTHER_BSS as we don't currently |
1010 | * do BSSID filtering */ | 1191 | * do BSSID filtering */ |
@@ -1016,20 +1197,9 @@ static void zd_op_configure_filter(struct ieee80211_hw *hw, | |||
1016 | * time. */ | 1197 | * time. */ |
1017 | } | 1198 | } |
1018 | 1199 | ||
1019 | static void set_rts_cts_work(struct work_struct *work) | 1200 | static void set_rts_cts(struct zd_mac *mac, unsigned int short_preamble) |
1020 | { | 1201 | { |
1021 | struct zd_mac *mac = | ||
1022 | container_of(work, struct zd_mac, set_rts_cts_work); | ||
1023 | unsigned long flags; | ||
1024 | unsigned int short_preamble; | ||
1025 | |||
1026 | mutex_lock(&mac->chip.mutex); | 1202 | mutex_lock(&mac->chip.mutex); |
1027 | |||
1028 | spin_lock_irqsave(&mac->lock, flags); | ||
1029 | mac->updating_rts_rate = 0; | ||
1030 | short_preamble = mac->short_preamble; | ||
1031 | spin_unlock_irqrestore(&mac->lock, flags); | ||
1032 | |||
1033 | zd_chip_set_rts_cts_rate_locked(&mac->chip, short_preamble); | 1203 | zd_chip_set_rts_cts_rate_locked(&mac->chip, short_preamble); |
1034 | mutex_unlock(&mac->chip.mutex); | 1204 | mutex_unlock(&mac->chip.mutex); |
1035 | } | 1205 | } |
@@ -1040,33 +1210,42 @@ static void zd_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1040 | u32 changes) | 1210 | u32 changes) |
1041 | { | 1211 | { |
1042 | struct zd_mac *mac = zd_hw_mac(hw); | 1212 | struct zd_mac *mac = zd_hw_mac(hw); |
1043 | unsigned long flags; | ||
1044 | int associated; | 1213 | int associated; |
1045 | 1214 | ||
1046 | dev_dbg_f(zd_mac_dev(mac), "changes: %x\n", changes); | 1215 | dev_dbg_f(zd_mac_dev(mac), "changes: %x\n", changes); |
1047 | 1216 | ||
1048 | if (mac->type == NL80211_IFTYPE_MESH_POINT || | 1217 | if (mac->type == NL80211_IFTYPE_MESH_POINT || |
1049 | mac->type == NL80211_IFTYPE_ADHOC) { | 1218 | mac->type == NL80211_IFTYPE_ADHOC || |
1219 | mac->type == NL80211_IFTYPE_AP) { | ||
1050 | associated = true; | 1220 | associated = true; |
1051 | if (changes & BSS_CHANGED_BEACON) { | 1221 | if (changes & BSS_CHANGED_BEACON) { |
1052 | struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); | 1222 | struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); |
1053 | 1223 | ||
1054 | if (beacon) { | 1224 | if (beacon) { |
1225 | zd_chip_disable_hwint(&mac->chip); | ||
1055 | zd_mac_config_beacon(hw, beacon); | 1226 | zd_mac_config_beacon(hw, beacon); |
1227 | zd_chip_enable_hwint(&mac->chip); | ||
1056 | kfree_skb(beacon); | 1228 | kfree_skb(beacon); |
1057 | } | 1229 | } |
1058 | } | 1230 | } |
1059 | 1231 | ||
1060 | if (changes & BSS_CHANGED_BEACON_ENABLED) { | 1232 | if (changes & BSS_CHANGED_BEACON_ENABLED) { |
1061 | u32 interval; | 1233 | u16 interval = 0; |
1234 | u8 period = 0; | ||
1062 | 1235 | ||
1063 | if (bss_conf->enable_beacon) | 1236 | if (bss_conf->enable_beacon) { |
1064 | interval = BCN_MODE_IBSS | | 1237 | period = bss_conf->dtim_period; |
1065 | bss_conf->beacon_int; | 1238 | interval = bss_conf->beacon_int; |
1066 | else | 1239 | } |
1067 | interval = 0; | ||
1068 | 1240 | ||
1069 | zd_set_beacon_interval(&mac->chip, interval); | 1241 | spin_lock_irq(&mac->lock); |
1242 | mac->beacon.period = period; | ||
1243 | mac->beacon.interval = interval; | ||
1244 | mac->beacon.last_update = jiffies; | ||
1245 | spin_unlock_irq(&mac->lock); | ||
1246 | |||
1247 | zd_set_beacon_interval(&mac->chip, interval, period, | ||
1248 | mac->type); | ||
1070 | } | 1249 | } |
1071 | } else | 1250 | } else |
1072 | associated = is_valid_ether_addr(bss_conf->bssid); | 1251 | associated = is_valid_ether_addr(bss_conf->bssid); |
@@ -1078,15 +1257,11 @@ static void zd_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1078 | /* TODO: do hardware bssid filtering */ | 1257 | /* TODO: do hardware bssid filtering */ |
1079 | 1258 | ||
1080 | if (changes & BSS_CHANGED_ERP_PREAMBLE) { | 1259 | if (changes & BSS_CHANGED_ERP_PREAMBLE) { |
1081 | spin_lock_irqsave(&mac->lock, flags); | 1260 | spin_lock_irq(&mac->lock); |
1082 | mac->short_preamble = bss_conf->use_short_preamble; | 1261 | mac->short_preamble = bss_conf->use_short_preamble; |
1083 | if (!mac->updating_rts_rate) { | 1262 | spin_unlock_irq(&mac->lock); |
1084 | mac->updating_rts_rate = 1; | 1263 | |
1085 | /* FIXME: should disable TX here, until work has | 1264 | set_rts_cts(mac, bss_conf->use_short_preamble); |
1086 | * completed and RTS_CTS reg is updated */ | ||
1087 | queue_work(zd_workqueue, &mac->set_rts_cts_work); | ||
1088 | } | ||
1089 | spin_unlock_irqrestore(&mac->lock, flags); | ||
1090 | } | 1265 | } |
1091 | } | 1266 | } |
1092 | 1267 | ||
@@ -1138,12 +1313,14 @@ struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf) | |||
1138 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &mac->band; | 1313 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &mac->band; |
1139 | 1314 | ||
1140 | hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | | 1315 | hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | |
1141 | IEEE80211_HW_SIGNAL_UNSPEC; | 1316 | IEEE80211_HW_SIGNAL_UNSPEC | |
1317 | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING; | ||
1142 | 1318 | ||
1143 | hw->wiphy->interface_modes = | 1319 | hw->wiphy->interface_modes = |
1144 | BIT(NL80211_IFTYPE_MESH_POINT) | | 1320 | BIT(NL80211_IFTYPE_MESH_POINT) | |
1145 | BIT(NL80211_IFTYPE_STATION) | | 1321 | BIT(NL80211_IFTYPE_STATION) | |
1146 | BIT(NL80211_IFTYPE_ADHOC); | 1322 | BIT(NL80211_IFTYPE_ADHOC) | |
1323 | BIT(NL80211_IFTYPE_AP); | ||
1147 | 1324 | ||
1148 | hw->max_signal = 100; | 1325 | hw->max_signal = 100; |
1149 | hw->queues = 1; | 1326 | hw->queues = 1; |
@@ -1160,15 +1337,82 @@ struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf) | |||
1160 | 1337 | ||
1161 | zd_chip_init(&mac->chip, hw, intf); | 1338 | zd_chip_init(&mac->chip, hw, intf); |
1162 | housekeeping_init(mac); | 1339 | housekeeping_init(mac); |
1163 | INIT_WORK(&mac->set_multicast_hash_work, set_multicast_hash_handler); | 1340 | beacon_init(mac); |
1164 | INIT_WORK(&mac->set_rts_cts_work, set_rts_cts_work); | ||
1165 | INIT_WORK(&mac->set_rx_filter_work, set_rx_filter_handler); | ||
1166 | INIT_WORK(&mac->process_intr, zd_process_intr); | 1341 | INIT_WORK(&mac->process_intr, zd_process_intr); |
1167 | 1342 | ||
1168 | SET_IEEE80211_DEV(hw, &intf->dev); | 1343 | SET_IEEE80211_DEV(hw, &intf->dev); |
1169 | return hw; | 1344 | return hw; |
1170 | } | 1345 | } |
1171 | 1346 | ||
1347 | #define BEACON_WATCHDOG_DELAY round_jiffies_relative(HZ) | ||
1348 | |||
1349 | static void beacon_watchdog_handler(struct work_struct *work) | ||
1350 | { | ||
1351 | struct zd_mac *mac = | ||
1352 | container_of(work, struct zd_mac, beacon.watchdog_work.work); | ||
1353 | struct sk_buff *beacon; | ||
1354 | unsigned long timeout; | ||
1355 | int interval, period; | ||
1356 | |||
1357 | if (!test_bit(ZD_DEVICE_RUNNING, &mac->flags)) | ||
1358 | goto rearm; | ||
1359 | if (mac->type != NL80211_IFTYPE_AP || !mac->vif) | ||
1360 | goto rearm; | ||
1361 | |||
1362 | spin_lock_irq(&mac->lock); | ||
1363 | interval = mac->beacon.interval; | ||
1364 | period = mac->beacon.period; | ||
1365 | timeout = mac->beacon.last_update + msecs_to_jiffies(interval) + HZ; | ||
1366 | spin_unlock_irq(&mac->lock); | ||
1367 | |||
1368 | if (interval > 0 && time_is_before_jiffies(timeout)) { | ||
1369 | dev_dbg_f(zd_mac_dev(mac), "beacon interrupt stalled, " | ||
1370 | "restarting. " | ||
1371 | "(interval: %d, dtim: %d)\n", | ||
1372 | interval, period); | ||
1373 | |||
1374 | zd_chip_disable_hwint(&mac->chip); | ||
1375 | |||
1376 | beacon = ieee80211_beacon_get(mac->hw, mac->vif); | ||
1377 | if (beacon) { | ||
1378 | zd_mac_config_beacon(mac->hw, beacon); | ||
1379 | kfree_skb(beacon); | ||
1380 | } | ||
1381 | |||
1382 | zd_set_beacon_interval(&mac->chip, interval, period, mac->type); | ||
1383 | |||
1384 | zd_chip_enable_hwint(&mac->chip); | ||
1385 | |||
1386 | spin_lock_irq(&mac->lock); | ||
1387 | mac->beacon.last_update = jiffies; | ||
1388 | spin_unlock_irq(&mac->lock); | ||
1389 | } | ||
1390 | |||
1391 | rearm: | ||
1392 | queue_delayed_work(zd_workqueue, &mac->beacon.watchdog_work, | ||
1393 | BEACON_WATCHDOG_DELAY); | ||
1394 | } | ||
1395 | |||
1396 | static void beacon_init(struct zd_mac *mac) | ||
1397 | { | ||
1398 | INIT_DELAYED_WORK(&mac->beacon.watchdog_work, beacon_watchdog_handler); | ||
1399 | } | ||
1400 | |||
1401 | static void beacon_enable(struct zd_mac *mac) | ||
1402 | { | ||
1403 | dev_dbg_f(zd_mac_dev(mac), "\n"); | ||
1404 | |||
1405 | mac->beacon.last_update = jiffies; | ||
1406 | queue_delayed_work(zd_workqueue, &mac->beacon.watchdog_work, | ||
1407 | BEACON_WATCHDOG_DELAY); | ||
1408 | } | ||
1409 | |||
1410 | static void beacon_disable(struct zd_mac *mac) | ||
1411 | { | ||
1412 | dev_dbg_f(zd_mac_dev(mac), "\n"); | ||
1413 | cancel_delayed_work_sync(&mac->beacon.watchdog_work); | ||
1414 | } | ||
1415 | |||
1172 | #define LINK_LED_WORK_DELAY HZ | 1416 | #define LINK_LED_WORK_DELAY HZ |
1173 | 1417 | ||
1174 | static void link_led_handler(struct work_struct *work) | 1418 | static void link_led_handler(struct work_struct *work) |
@@ -1179,6 +1423,9 @@ static void link_led_handler(struct work_struct *work) | |||
1179 | int is_associated; | 1423 | int is_associated; |
1180 | int r; | 1424 | int r; |
1181 | 1425 | ||
1426 | if (!test_bit(ZD_DEVICE_RUNNING, &mac->flags)) | ||
1427 | goto requeue; | ||
1428 | |||
1182 | spin_lock_irq(&mac->lock); | 1429 | spin_lock_irq(&mac->lock); |
1183 | is_associated = mac->associated; | 1430 | is_associated = mac->associated; |
1184 | spin_unlock_irq(&mac->lock); | 1431 | spin_unlock_irq(&mac->lock); |
@@ -1188,6 +1435,7 @@ static void link_led_handler(struct work_struct *work) | |||
1188 | if (r) | 1435 | if (r) |
1189 | dev_dbg_f(zd_mac_dev(mac), "zd_chip_control_leds error %d\n", r); | 1436 | dev_dbg_f(zd_mac_dev(mac), "zd_chip_control_leds error %d\n", r); |
1190 | 1437 | ||
1438 | requeue: | ||
1191 | queue_delayed_work(zd_workqueue, &mac->housekeeping.link_led_work, | 1439 | queue_delayed_work(zd_workqueue, &mac->housekeeping.link_led_work, |
1192 | LINK_LED_WORK_DELAY); | 1440 | LINK_LED_WORK_DELAY); |
1193 | } | 1441 | } |
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h index a6d86b996c79..f8c93c3fe755 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.h +++ b/drivers/net/wireless/zd1211rw/zd_mac.h | |||
@@ -163,6 +163,17 @@ struct housekeeping { | |||
163 | struct delayed_work link_led_work; | 163 | struct delayed_work link_led_work; |
164 | }; | 164 | }; |
165 | 165 | ||
166 | struct beacon { | ||
167 | struct delayed_work watchdog_work; | ||
168 | unsigned long last_update; | ||
169 | u16 interval; | ||
170 | u8 period; | ||
171 | }; | ||
172 | |||
173 | enum zd_device_flags { | ||
174 | ZD_DEVICE_RUNNING, | ||
175 | }; | ||
176 | |||
166 | #define ZD_MAC_STATS_BUFFER_SIZE 16 | 177 | #define ZD_MAC_STATS_BUFFER_SIZE 16 |
167 | 178 | ||
168 | #define ZD_MAC_MAX_ACK_WAITERS 50 | 179 | #define ZD_MAC_MAX_ACK_WAITERS 50 |
@@ -172,17 +183,19 @@ struct zd_mac { | |||
172 | spinlock_t lock; | 183 | spinlock_t lock; |
173 | spinlock_t intr_lock; | 184 | spinlock_t intr_lock; |
174 | struct ieee80211_hw *hw; | 185 | struct ieee80211_hw *hw; |
186 | struct ieee80211_vif *vif; | ||
175 | struct housekeeping housekeeping; | 187 | struct housekeeping housekeeping; |
176 | struct work_struct set_multicast_hash_work; | 188 | struct beacon beacon; |
177 | struct work_struct set_rts_cts_work; | 189 | struct work_struct set_rts_cts_work; |
178 | struct work_struct set_rx_filter_work; | ||
179 | struct work_struct process_intr; | 190 | struct work_struct process_intr; |
180 | struct zd_mc_hash multicast_hash; | 191 | struct zd_mc_hash multicast_hash; |
181 | u8 intr_buffer[USB_MAX_EP_INT_BUFFER]; | 192 | u8 intr_buffer[USB_MAX_EP_INT_BUFFER]; |
182 | u8 regdomain; | 193 | u8 regdomain; |
183 | u8 default_regdomain; | 194 | u8 default_regdomain; |
195 | u8 channel; | ||
184 | int type; | 196 | int type; |
185 | int associated; | 197 | int associated; |
198 | unsigned long flags; | ||
186 | struct sk_buff_head ack_wait_queue; | 199 | struct sk_buff_head ack_wait_queue; |
187 | struct ieee80211_channel channels[14]; | 200 | struct ieee80211_channel channels[14]; |
188 | struct ieee80211_rate rates[12]; | 201 | struct ieee80211_rate rates[12]; |
@@ -191,9 +204,6 @@ struct zd_mac { | |||
191 | /* Short preamble (used for RTS/CTS) */ | 204 | /* Short preamble (used for RTS/CTS) */ |
192 | unsigned int short_preamble:1; | 205 | unsigned int short_preamble:1; |
193 | 206 | ||
194 | /* flags to indicate update in progress */ | ||
195 | unsigned int updating_rts_rate:1; | ||
196 | |||
197 | /* whether to pass frames with CRC errors to stack */ | 207 | /* whether to pass frames with CRC errors to stack */ |
198 | unsigned int pass_failed_fcs:1; | 208 | unsigned int pass_failed_fcs:1; |
199 | 209 | ||
@@ -304,6 +314,10 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length); | |||
304 | void zd_mac_tx_failed(struct urb *urb); | 314 | void zd_mac_tx_failed(struct urb *urb); |
305 | void zd_mac_tx_to_dev(struct sk_buff *skb, int error); | 315 | void zd_mac_tx_to_dev(struct sk_buff *skb, int error); |
306 | 316 | ||
317 | int zd_op_start(struct ieee80211_hw *hw); | ||
318 | void zd_op_stop(struct ieee80211_hw *hw); | ||
319 | int zd_restore_settings(struct zd_mac *mac); | ||
320 | |||
307 | #ifdef DEBUG | 321 | #ifdef DEBUG |
308 | void zd_dump_rx_status(const struct rx_status *status); | 322 | void zd_dump_rx_status(const struct rx_status *status); |
309 | #else | 323 | #else |
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index 06041cb1c422..f6df3665fdb6 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c | |||
@@ -377,8 +377,10 @@ static inline void handle_regs_int(struct urb *urb) | |||
377 | int_num = le16_to_cpu(*(__le16 *)(urb->transfer_buffer+2)); | 377 | int_num = le16_to_cpu(*(__le16 *)(urb->transfer_buffer+2)); |
378 | if (int_num == CR_INTERRUPT) { | 378 | if (int_num == CR_INTERRUPT) { |
379 | struct zd_mac *mac = zd_hw_mac(zd_usb_to_hw(urb->context)); | 379 | struct zd_mac *mac = zd_hw_mac(zd_usb_to_hw(urb->context)); |
380 | spin_lock(&mac->lock); | ||
380 | memcpy(&mac->intr_buffer, urb->transfer_buffer, | 381 | memcpy(&mac->intr_buffer, urb->transfer_buffer, |
381 | USB_MAX_EP_INT_BUFFER); | 382 | USB_MAX_EP_INT_BUFFER); |
383 | spin_unlock(&mac->lock); | ||
382 | schedule_work(&mac->process_intr); | 384 | schedule_work(&mac->process_intr); |
383 | } else if (intr->read_regs_enabled) { | 385 | } else if (intr->read_regs_enabled) { |
384 | intr->read_regs.length = len = urb->actual_length; | 386 | intr->read_regs.length = len = urb->actual_length; |
@@ -409,8 +411,10 @@ static void int_urb_complete(struct urb *urb) | |||
409 | case -ENOENT: | 411 | case -ENOENT: |
410 | case -ECONNRESET: | 412 | case -ECONNRESET: |
411 | case -EPIPE: | 413 | case -EPIPE: |
412 | goto kfree; | 414 | dev_dbg_f(urb_dev(urb), "urb %p error %d\n", urb, urb->status); |
415 | return; | ||
413 | default: | 416 | default: |
417 | dev_dbg_f(urb_dev(urb), "urb %p error %d\n", urb, urb->status); | ||
414 | goto resubmit; | 418 | goto resubmit; |
415 | } | 419 | } |
416 | 420 | ||
@@ -441,12 +445,11 @@ static void int_urb_complete(struct urb *urb) | |||
441 | resubmit: | 445 | resubmit: |
442 | r = usb_submit_urb(urb, GFP_ATOMIC); | 446 | r = usb_submit_urb(urb, GFP_ATOMIC); |
443 | if (r) { | 447 | if (r) { |
444 | dev_dbg_f(urb_dev(urb), "resubmit urb %p\n", urb); | 448 | dev_dbg_f(urb_dev(urb), "error: resubmit urb %p err code %d\n", |
445 | goto kfree; | 449 | urb, r); |
450 | /* TODO: add worker to reset intr->urb */ | ||
446 | } | 451 | } |
447 | return; | 452 | return; |
448 | kfree: | ||
449 | kfree(urb->transfer_buffer); | ||
450 | } | 453 | } |
451 | 454 | ||
452 | static inline int int_urb_interval(struct usb_device *udev) | 455 | static inline int int_urb_interval(struct usb_device *udev) |
@@ -477,9 +480,8 @@ static inline int usb_int_enabled(struct zd_usb *usb) | |||
477 | int zd_usb_enable_int(struct zd_usb *usb) | 480 | int zd_usb_enable_int(struct zd_usb *usb) |
478 | { | 481 | { |
479 | int r; | 482 | int r; |
480 | struct usb_device *udev; | 483 | struct usb_device *udev = zd_usb_to_usbdev(usb); |
481 | struct zd_usb_interrupt *intr = &usb->intr; | 484 | struct zd_usb_interrupt *intr = &usb->intr; |
482 | void *transfer_buffer = NULL; | ||
483 | struct urb *urb; | 485 | struct urb *urb; |
484 | 486 | ||
485 | dev_dbg_f(zd_usb_dev(usb), "\n"); | 487 | dev_dbg_f(zd_usb_dev(usb), "\n"); |
@@ -500,20 +502,21 @@ int zd_usb_enable_int(struct zd_usb *usb) | |||
500 | intr->urb = urb; | 502 | intr->urb = urb; |
501 | spin_unlock_irq(&intr->lock); | 503 | spin_unlock_irq(&intr->lock); |
502 | 504 | ||
503 | /* TODO: make it a DMA buffer */ | ||
504 | r = -ENOMEM; | 505 | r = -ENOMEM; |
505 | transfer_buffer = kmalloc(USB_MAX_EP_INT_BUFFER, GFP_KERNEL); | 506 | intr->buffer = usb_alloc_coherent(udev, USB_MAX_EP_INT_BUFFER, |
506 | if (!transfer_buffer) { | 507 | GFP_KERNEL, &intr->buffer_dma); |
508 | if (!intr->buffer) { | ||
507 | dev_dbg_f(zd_usb_dev(usb), | 509 | dev_dbg_f(zd_usb_dev(usb), |
508 | "couldn't allocate transfer_buffer\n"); | 510 | "couldn't allocate transfer_buffer\n"); |
509 | goto error_set_urb_null; | 511 | goto error_set_urb_null; |
510 | } | 512 | } |
511 | 513 | ||
512 | udev = zd_usb_to_usbdev(usb); | ||
513 | usb_fill_int_urb(urb, udev, usb_rcvintpipe(udev, EP_INT_IN), | 514 | usb_fill_int_urb(urb, udev, usb_rcvintpipe(udev, EP_INT_IN), |
514 | transfer_buffer, USB_MAX_EP_INT_BUFFER, | 515 | intr->buffer, USB_MAX_EP_INT_BUFFER, |
515 | int_urb_complete, usb, | 516 | int_urb_complete, usb, |
516 | intr->interval); | 517 | intr->interval); |
518 | urb->transfer_dma = intr->buffer_dma; | ||
519 | urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
517 | 520 | ||
518 | dev_dbg_f(zd_usb_dev(usb), "submit urb %p\n", intr->urb); | 521 | dev_dbg_f(zd_usb_dev(usb), "submit urb %p\n", intr->urb); |
519 | r = usb_submit_urb(urb, GFP_KERNEL); | 522 | r = usb_submit_urb(urb, GFP_KERNEL); |
@@ -525,7 +528,8 @@ int zd_usb_enable_int(struct zd_usb *usb) | |||
525 | 528 | ||
526 | return 0; | 529 | return 0; |
527 | error: | 530 | error: |
528 | kfree(transfer_buffer); | 531 | usb_free_coherent(udev, USB_MAX_EP_INT_BUFFER, |
532 | intr->buffer, intr->buffer_dma); | ||
529 | error_set_urb_null: | 533 | error_set_urb_null: |
530 | spin_lock_irq(&intr->lock); | 534 | spin_lock_irq(&intr->lock); |
531 | intr->urb = NULL; | 535 | intr->urb = NULL; |
@@ -539,8 +543,11 @@ out: | |||
539 | void zd_usb_disable_int(struct zd_usb *usb) | 543 | void zd_usb_disable_int(struct zd_usb *usb) |
540 | { | 544 | { |
541 | unsigned long flags; | 545 | unsigned long flags; |
546 | struct usb_device *udev = zd_usb_to_usbdev(usb); | ||
542 | struct zd_usb_interrupt *intr = &usb->intr; | 547 | struct zd_usb_interrupt *intr = &usb->intr; |
543 | struct urb *urb; | 548 | struct urb *urb; |
549 | void *buffer; | ||
550 | dma_addr_t buffer_dma; | ||
544 | 551 | ||
545 | spin_lock_irqsave(&intr->lock, flags); | 552 | spin_lock_irqsave(&intr->lock, flags); |
546 | urb = intr->urb; | 553 | urb = intr->urb; |
@@ -549,11 +556,18 @@ void zd_usb_disable_int(struct zd_usb *usb) | |||
549 | return; | 556 | return; |
550 | } | 557 | } |
551 | intr->urb = NULL; | 558 | intr->urb = NULL; |
559 | buffer = intr->buffer; | ||
560 | buffer_dma = intr->buffer_dma; | ||
561 | intr->buffer = NULL; | ||
552 | spin_unlock_irqrestore(&intr->lock, flags); | 562 | spin_unlock_irqrestore(&intr->lock, flags); |
553 | 563 | ||
554 | usb_kill_urb(urb); | 564 | usb_kill_urb(urb); |
555 | dev_dbg_f(zd_usb_dev(usb), "urb %p killed\n", urb); | 565 | dev_dbg_f(zd_usb_dev(usb), "urb %p killed\n", urb); |
556 | usb_free_urb(urb); | 566 | usb_free_urb(urb); |
567 | |||
568 | if (buffer) | ||
569 | usb_free_coherent(udev, USB_MAX_EP_INT_BUFFER, | ||
570 | buffer, buffer_dma); | ||
557 | } | 571 | } |
558 | 572 | ||
559 | static void handle_rx_packet(struct zd_usb *usb, const u8 *buffer, | 573 | static void handle_rx_packet(struct zd_usb *usb, const u8 *buffer, |
@@ -601,6 +615,7 @@ static void handle_rx_packet(struct zd_usb *usb, const u8 *buffer, | |||
601 | 615 | ||
602 | static void rx_urb_complete(struct urb *urb) | 616 | static void rx_urb_complete(struct urb *urb) |
603 | { | 617 | { |
618 | int r; | ||
604 | struct zd_usb *usb; | 619 | struct zd_usb *usb; |
605 | struct zd_usb_rx *rx; | 620 | struct zd_usb_rx *rx; |
606 | const u8 *buffer; | 621 | const u8 *buffer; |
@@ -615,6 +630,7 @@ static void rx_urb_complete(struct urb *urb) | |||
615 | case -ENOENT: | 630 | case -ENOENT: |
616 | case -ECONNRESET: | 631 | case -ECONNRESET: |
617 | case -EPIPE: | 632 | case -EPIPE: |
633 | dev_dbg_f(urb_dev(urb), "urb %p error %d\n", urb, urb->status); | ||
618 | return; | 634 | return; |
619 | default: | 635 | default: |
620 | dev_dbg_f(urb_dev(urb), "urb %p error %d\n", urb, urb->status); | 636 | dev_dbg_f(urb_dev(urb), "urb %p error %d\n", urb, urb->status); |
@@ -626,6 +642,8 @@ static void rx_urb_complete(struct urb *urb) | |||
626 | usb = urb->context; | 642 | usb = urb->context; |
627 | rx = &usb->rx; | 643 | rx = &usb->rx; |
628 | 644 | ||
645 | zd_usb_reset_rx_idle_timer(usb); | ||
646 | |||
629 | if (length%rx->usb_packet_size > rx->usb_packet_size-4) { | 647 | if (length%rx->usb_packet_size > rx->usb_packet_size-4) { |
630 | /* If there is an old first fragment, we don't care. */ | 648 | /* If there is an old first fragment, we don't care. */ |
631 | dev_dbg_f(urb_dev(urb), "*** first fragment ***\n"); | 649 | dev_dbg_f(urb_dev(urb), "*** first fragment ***\n"); |
@@ -654,7 +672,9 @@ static void rx_urb_complete(struct urb *urb) | |||
654 | } | 672 | } |
655 | 673 | ||
656 | resubmit: | 674 | resubmit: |
657 | usb_submit_urb(urb, GFP_ATOMIC); | 675 | r = usb_submit_urb(urb, GFP_ATOMIC); |
676 | if (r) | ||
677 | dev_dbg_f(urb_dev(urb), "urb %p resubmit error %d\n", urb, r); | ||
658 | } | 678 | } |
659 | 679 | ||
660 | static struct urb *alloc_rx_urb(struct zd_usb *usb) | 680 | static struct urb *alloc_rx_urb(struct zd_usb *usb) |
@@ -690,7 +710,7 @@ static void free_rx_urb(struct urb *urb) | |||
690 | usb_free_urb(urb); | 710 | usb_free_urb(urb); |
691 | } | 711 | } |
692 | 712 | ||
693 | int zd_usb_enable_rx(struct zd_usb *usb) | 713 | static int __zd_usb_enable_rx(struct zd_usb *usb) |
694 | { | 714 | { |
695 | int i, r; | 715 | int i, r; |
696 | struct zd_usb_rx *rx = &usb->rx; | 716 | struct zd_usb_rx *rx = &usb->rx; |
@@ -742,7 +762,21 @@ error: | |||
742 | return r; | 762 | return r; |
743 | } | 763 | } |
744 | 764 | ||
745 | void zd_usb_disable_rx(struct zd_usb *usb) | 765 | int zd_usb_enable_rx(struct zd_usb *usb) |
766 | { | ||
767 | int r; | ||
768 | struct zd_usb_rx *rx = &usb->rx; | ||
769 | |||
770 | mutex_lock(&rx->setup_mutex); | ||
771 | r = __zd_usb_enable_rx(usb); | ||
772 | mutex_unlock(&rx->setup_mutex); | ||
773 | |||
774 | zd_usb_reset_rx_idle_timer(usb); | ||
775 | |||
776 | return r; | ||
777 | } | ||
778 | |||
779 | static void __zd_usb_disable_rx(struct zd_usb *usb) | ||
746 | { | 780 | { |
747 | int i; | 781 | int i; |
748 | unsigned long flags; | 782 | unsigned long flags; |
@@ -769,6 +803,40 @@ void zd_usb_disable_rx(struct zd_usb *usb) | |||
769 | spin_unlock_irqrestore(&rx->lock, flags); | 803 | spin_unlock_irqrestore(&rx->lock, flags); |
770 | } | 804 | } |
771 | 805 | ||
806 | void zd_usb_disable_rx(struct zd_usb *usb) | ||
807 | { | ||
808 | struct zd_usb_rx *rx = &usb->rx; | ||
809 | |||
810 | mutex_lock(&rx->setup_mutex); | ||
811 | __zd_usb_disable_rx(usb); | ||
812 | mutex_unlock(&rx->setup_mutex); | ||
813 | |||
814 | cancel_delayed_work_sync(&rx->idle_work); | ||
815 | } | ||
816 | |||
817 | static void zd_usb_reset_rx(struct zd_usb *usb) | ||
818 | { | ||
819 | bool do_reset; | ||
820 | struct zd_usb_rx *rx = &usb->rx; | ||
821 | unsigned long flags; | ||
822 | |||
823 | mutex_lock(&rx->setup_mutex); | ||
824 | |||
825 | spin_lock_irqsave(&rx->lock, flags); | ||
826 | do_reset = rx->urbs != NULL; | ||
827 | spin_unlock_irqrestore(&rx->lock, flags); | ||
828 | |||
829 | if (do_reset) { | ||
830 | __zd_usb_disable_rx(usb); | ||
831 | __zd_usb_enable_rx(usb); | ||
832 | } | ||
833 | |||
834 | mutex_unlock(&rx->setup_mutex); | ||
835 | |||
836 | if (do_reset) | ||
837 | zd_usb_reset_rx_idle_timer(usb); | ||
838 | } | ||
839 | |||
772 | /** | 840 | /** |
773 | * zd_usb_disable_tx - disable transmission | 841 | * zd_usb_disable_tx - disable transmission |
774 | * @usb: the zd1211rw-private USB structure | 842 | * @usb: the zd1211rw-private USB structure |
@@ -779,19 +847,21 @@ void zd_usb_disable_tx(struct zd_usb *usb) | |||
779 | { | 847 | { |
780 | struct zd_usb_tx *tx = &usb->tx; | 848 | struct zd_usb_tx *tx = &usb->tx; |
781 | unsigned long flags; | 849 | unsigned long flags; |
782 | struct list_head *pos, *n; | 850 | |
851 | atomic_set(&tx->enabled, 0); | ||
852 | |||
853 | /* kill all submitted tx-urbs */ | ||
854 | usb_kill_anchored_urbs(&tx->submitted); | ||
783 | 855 | ||
784 | spin_lock_irqsave(&tx->lock, flags); | 856 | spin_lock_irqsave(&tx->lock, flags); |
785 | list_for_each_safe(pos, n, &tx->free_urb_list) { | 857 | WARN_ON(!skb_queue_empty(&tx->submitted_skbs)); |
786 | list_del(pos); | 858 | WARN_ON(tx->submitted_urbs != 0); |
787 | usb_free_urb(list_entry(pos, struct urb, urb_list)); | ||
788 | } | ||
789 | tx->enabled = 0; | ||
790 | tx->submitted_urbs = 0; | 859 | tx->submitted_urbs = 0; |
860 | spin_unlock_irqrestore(&tx->lock, flags); | ||
861 | |||
791 | /* The stopped state is ignored, relying on ieee80211_wake_queues() | 862 | /* The stopped state is ignored, relying on ieee80211_wake_queues() |
792 | * in a potentionally following zd_usb_enable_tx(). | 863 | * in a potentionally following zd_usb_enable_tx(). |
793 | */ | 864 | */ |
794 | spin_unlock_irqrestore(&tx->lock, flags); | ||
795 | } | 865 | } |
796 | 866 | ||
797 | /** | 867 | /** |
@@ -807,63 +877,13 @@ void zd_usb_enable_tx(struct zd_usb *usb) | |||
807 | struct zd_usb_tx *tx = &usb->tx; | 877 | struct zd_usb_tx *tx = &usb->tx; |
808 | 878 | ||
809 | spin_lock_irqsave(&tx->lock, flags); | 879 | spin_lock_irqsave(&tx->lock, flags); |
810 | tx->enabled = 1; | 880 | atomic_set(&tx->enabled, 1); |
811 | tx->submitted_urbs = 0; | 881 | tx->submitted_urbs = 0; |
812 | ieee80211_wake_queues(zd_usb_to_hw(usb)); | 882 | ieee80211_wake_queues(zd_usb_to_hw(usb)); |
813 | tx->stopped = 0; | 883 | tx->stopped = 0; |
814 | spin_unlock_irqrestore(&tx->lock, flags); | 884 | spin_unlock_irqrestore(&tx->lock, flags); |
815 | } | 885 | } |
816 | 886 | ||
817 | /** | ||
818 | * alloc_tx_urb - provides an tx URB | ||
819 | * @usb: a &struct zd_usb pointer | ||
820 | * | ||
821 | * Allocates a new URB. If possible takes the urb from the free list in | ||
822 | * usb->tx. | ||
823 | */ | ||
824 | static struct urb *alloc_tx_urb(struct zd_usb *usb) | ||
825 | { | ||
826 | struct zd_usb_tx *tx = &usb->tx; | ||
827 | unsigned long flags; | ||
828 | struct list_head *entry; | ||
829 | struct urb *urb; | ||
830 | |||
831 | spin_lock_irqsave(&tx->lock, flags); | ||
832 | if (list_empty(&tx->free_urb_list)) { | ||
833 | urb = usb_alloc_urb(0, GFP_ATOMIC); | ||
834 | goto out; | ||
835 | } | ||
836 | entry = tx->free_urb_list.next; | ||
837 | list_del(entry); | ||
838 | urb = list_entry(entry, struct urb, urb_list); | ||
839 | out: | ||
840 | spin_unlock_irqrestore(&tx->lock, flags); | ||
841 | return urb; | ||
842 | } | ||
843 | |||
844 | /** | ||
845 | * free_tx_urb - frees a used tx URB | ||
846 | * @usb: a &struct zd_usb pointer | ||
847 | * @urb: URB to be freed | ||
848 | * | ||
849 | * Frees the transmission URB, which means to put it on the free URB | ||
850 | * list. | ||
851 | */ | ||
852 | static void free_tx_urb(struct zd_usb *usb, struct urb *urb) | ||
853 | { | ||
854 | struct zd_usb_tx *tx = &usb->tx; | ||
855 | unsigned long flags; | ||
856 | |||
857 | spin_lock_irqsave(&tx->lock, flags); | ||
858 | if (!tx->enabled) { | ||
859 | usb_free_urb(urb); | ||
860 | goto out; | ||
861 | } | ||
862 | list_add(&urb->urb_list, &tx->free_urb_list); | ||
863 | out: | ||
864 | spin_unlock_irqrestore(&tx->lock, flags); | ||
865 | } | ||
866 | |||
867 | static void tx_dec_submitted_urbs(struct zd_usb *usb) | 887 | static void tx_dec_submitted_urbs(struct zd_usb *usb) |
868 | { | 888 | { |
869 | struct zd_usb_tx *tx = &usb->tx; | 889 | struct zd_usb_tx *tx = &usb->tx; |
@@ -905,6 +925,16 @@ static void tx_urb_complete(struct urb *urb) | |||
905 | struct sk_buff *skb; | 925 | struct sk_buff *skb; |
906 | struct ieee80211_tx_info *info; | 926 | struct ieee80211_tx_info *info; |
907 | struct zd_usb *usb; | 927 | struct zd_usb *usb; |
928 | struct zd_usb_tx *tx; | ||
929 | |||
930 | skb = (struct sk_buff *)urb->context; | ||
931 | info = IEEE80211_SKB_CB(skb); | ||
932 | /* | ||
933 | * grab 'usb' pointer before handing off the skb (since | ||
934 | * it might be freed by zd_mac_tx_to_dev or mac80211) | ||
935 | */ | ||
936 | usb = &zd_hw_mac(info->rate_driver_data[0])->chip.usb; | ||
937 | tx = &usb->tx; | ||
908 | 938 | ||
909 | switch (urb->status) { | 939 | switch (urb->status) { |
910 | case 0: | 940 | case 0: |
@@ -922,20 +952,16 @@ static void tx_urb_complete(struct urb *urb) | |||
922 | goto resubmit; | 952 | goto resubmit; |
923 | } | 953 | } |
924 | free_urb: | 954 | free_urb: |
925 | skb = (struct sk_buff *)urb->context; | 955 | skb_unlink(skb, &usb->tx.submitted_skbs); |
926 | /* | ||
927 | * grab 'usb' pointer before handing off the skb (since | ||
928 | * it might be freed by zd_mac_tx_to_dev or mac80211) | ||
929 | */ | ||
930 | info = IEEE80211_SKB_CB(skb); | ||
931 | usb = &zd_hw_mac(info->rate_driver_data[0])->chip.usb; | ||
932 | zd_mac_tx_to_dev(skb, urb->status); | 956 | zd_mac_tx_to_dev(skb, urb->status); |
933 | free_tx_urb(usb, urb); | 957 | usb_free_urb(urb); |
934 | tx_dec_submitted_urbs(usb); | 958 | tx_dec_submitted_urbs(usb); |
935 | return; | 959 | return; |
936 | resubmit: | 960 | resubmit: |
961 | usb_anchor_urb(urb, &tx->submitted); | ||
937 | r = usb_submit_urb(urb, GFP_ATOMIC); | 962 | r = usb_submit_urb(urb, GFP_ATOMIC); |
938 | if (r) { | 963 | if (r) { |
964 | usb_unanchor_urb(urb); | ||
939 | dev_dbg_f(urb_dev(urb), "error resubmit urb %p %d\n", urb, r); | 965 | dev_dbg_f(urb_dev(urb), "error resubmit urb %p %d\n", urb, r); |
940 | goto free_urb; | 966 | goto free_urb; |
941 | } | 967 | } |
@@ -956,10 +982,17 @@ resubmit: | |||
956 | int zd_usb_tx(struct zd_usb *usb, struct sk_buff *skb) | 982 | int zd_usb_tx(struct zd_usb *usb, struct sk_buff *skb) |
957 | { | 983 | { |
958 | int r; | 984 | int r; |
985 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
959 | struct usb_device *udev = zd_usb_to_usbdev(usb); | 986 | struct usb_device *udev = zd_usb_to_usbdev(usb); |
960 | struct urb *urb; | 987 | struct urb *urb; |
988 | struct zd_usb_tx *tx = &usb->tx; | ||
961 | 989 | ||
962 | urb = alloc_tx_urb(usb); | 990 | if (!atomic_read(&tx->enabled)) { |
991 | r = -ENOENT; | ||
992 | goto out; | ||
993 | } | ||
994 | |||
995 | urb = usb_alloc_urb(0, GFP_ATOMIC); | ||
963 | if (!urb) { | 996 | if (!urb) { |
964 | r = -ENOMEM; | 997 | r = -ENOMEM; |
965 | goto out; | 998 | goto out; |
@@ -968,17 +1001,118 @@ int zd_usb_tx(struct zd_usb *usb, struct sk_buff *skb) | |||
968 | usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, EP_DATA_OUT), | 1001 | usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, EP_DATA_OUT), |
969 | skb->data, skb->len, tx_urb_complete, skb); | 1002 | skb->data, skb->len, tx_urb_complete, skb); |
970 | 1003 | ||
1004 | info->rate_driver_data[1] = (void *)jiffies; | ||
1005 | skb_queue_tail(&tx->submitted_skbs, skb); | ||
1006 | usb_anchor_urb(urb, &tx->submitted); | ||
1007 | |||
971 | r = usb_submit_urb(urb, GFP_ATOMIC); | 1008 | r = usb_submit_urb(urb, GFP_ATOMIC); |
972 | if (r) | 1009 | if (r) { |
1010 | dev_dbg_f(zd_usb_dev(usb), "error submit urb %p %d\n", urb, r); | ||
1011 | usb_unanchor_urb(urb); | ||
1012 | skb_unlink(skb, &tx->submitted_skbs); | ||
973 | goto error; | 1013 | goto error; |
1014 | } | ||
974 | tx_inc_submitted_urbs(usb); | 1015 | tx_inc_submitted_urbs(usb); |
975 | return 0; | 1016 | return 0; |
976 | error: | 1017 | error: |
977 | free_tx_urb(usb, urb); | 1018 | usb_free_urb(urb); |
978 | out: | 1019 | out: |
979 | return r; | 1020 | return r; |
980 | } | 1021 | } |
981 | 1022 | ||
1023 | static bool zd_tx_timeout(struct zd_usb *usb) | ||
1024 | { | ||
1025 | struct zd_usb_tx *tx = &usb->tx; | ||
1026 | struct sk_buff_head *q = &tx->submitted_skbs; | ||
1027 | struct sk_buff *skb, *skbnext; | ||
1028 | struct ieee80211_tx_info *info; | ||
1029 | unsigned long flags, trans_start; | ||
1030 | bool have_timedout = false; | ||
1031 | |||
1032 | spin_lock_irqsave(&q->lock, flags); | ||
1033 | skb_queue_walk_safe(q, skb, skbnext) { | ||
1034 | info = IEEE80211_SKB_CB(skb); | ||
1035 | trans_start = (unsigned long)info->rate_driver_data[1]; | ||
1036 | |||
1037 | if (time_is_before_jiffies(trans_start + ZD_TX_TIMEOUT)) { | ||
1038 | have_timedout = true; | ||
1039 | break; | ||
1040 | } | ||
1041 | } | ||
1042 | spin_unlock_irqrestore(&q->lock, flags); | ||
1043 | |||
1044 | return have_timedout; | ||
1045 | } | ||
1046 | |||
1047 | static void zd_tx_watchdog_handler(struct work_struct *work) | ||
1048 | { | ||
1049 | struct zd_usb *usb = | ||
1050 | container_of(work, struct zd_usb, tx.watchdog_work.work); | ||
1051 | struct zd_usb_tx *tx = &usb->tx; | ||
1052 | |||
1053 | if (!atomic_read(&tx->enabled) || !tx->watchdog_enabled) | ||
1054 | goto out; | ||
1055 | if (!zd_tx_timeout(usb)) | ||
1056 | goto out; | ||
1057 | |||
1058 | /* TX halted, try reset */ | ||
1059 | dev_warn(zd_usb_dev(usb), "TX-stall detected, reseting device..."); | ||
1060 | |||
1061 | usb_queue_reset_device(usb->intf); | ||
1062 | |||
1063 | /* reset will stop this worker, don't rearm */ | ||
1064 | return; | ||
1065 | out: | ||
1066 | queue_delayed_work(zd_workqueue, &tx->watchdog_work, | ||
1067 | ZD_TX_WATCHDOG_INTERVAL); | ||
1068 | } | ||
1069 | |||
1070 | void zd_tx_watchdog_enable(struct zd_usb *usb) | ||
1071 | { | ||
1072 | struct zd_usb_tx *tx = &usb->tx; | ||
1073 | |||
1074 | if (!tx->watchdog_enabled) { | ||
1075 | dev_dbg_f(zd_usb_dev(usb), "\n"); | ||
1076 | queue_delayed_work(zd_workqueue, &tx->watchdog_work, | ||
1077 | ZD_TX_WATCHDOG_INTERVAL); | ||
1078 | tx->watchdog_enabled = 1; | ||
1079 | } | ||
1080 | } | ||
1081 | |||
1082 | void zd_tx_watchdog_disable(struct zd_usb *usb) | ||
1083 | { | ||
1084 | struct zd_usb_tx *tx = &usb->tx; | ||
1085 | |||
1086 | if (tx->watchdog_enabled) { | ||
1087 | dev_dbg_f(zd_usb_dev(usb), "\n"); | ||
1088 | tx->watchdog_enabled = 0; | ||
1089 | cancel_delayed_work_sync(&tx->watchdog_work); | ||
1090 | } | ||
1091 | } | ||
1092 | |||
1093 | static void zd_rx_idle_timer_handler(struct work_struct *work) | ||
1094 | { | ||
1095 | struct zd_usb *usb = | ||
1096 | container_of(work, struct zd_usb, rx.idle_work.work); | ||
1097 | struct zd_mac *mac = zd_usb_to_mac(usb); | ||
1098 | |||
1099 | if (!test_bit(ZD_DEVICE_RUNNING, &mac->flags)) | ||
1100 | return; | ||
1101 | |||
1102 | dev_dbg_f(zd_usb_dev(usb), "\n"); | ||
1103 | |||
1104 | /* 30 seconds since last rx, reset rx */ | ||
1105 | zd_usb_reset_rx(usb); | ||
1106 | } | ||
1107 | |||
1108 | void zd_usb_reset_rx_idle_timer(struct zd_usb *usb) | ||
1109 | { | ||
1110 | struct zd_usb_rx *rx = &usb->rx; | ||
1111 | |||
1112 | cancel_delayed_work(&rx->idle_work); | ||
1113 | queue_delayed_work(zd_workqueue, &rx->idle_work, ZD_RX_IDLE_INTERVAL); | ||
1114 | } | ||
1115 | |||
982 | static inline void init_usb_interrupt(struct zd_usb *usb) | 1116 | static inline void init_usb_interrupt(struct zd_usb *usb) |
983 | { | 1117 | { |
984 | struct zd_usb_interrupt *intr = &usb->intr; | 1118 | struct zd_usb_interrupt *intr = &usb->intr; |
@@ -993,22 +1127,27 @@ static inline void init_usb_rx(struct zd_usb *usb) | |||
993 | { | 1127 | { |
994 | struct zd_usb_rx *rx = &usb->rx; | 1128 | struct zd_usb_rx *rx = &usb->rx; |
995 | spin_lock_init(&rx->lock); | 1129 | spin_lock_init(&rx->lock); |
1130 | mutex_init(&rx->setup_mutex); | ||
996 | if (interface_to_usbdev(usb->intf)->speed == USB_SPEED_HIGH) { | 1131 | if (interface_to_usbdev(usb->intf)->speed == USB_SPEED_HIGH) { |
997 | rx->usb_packet_size = 512; | 1132 | rx->usb_packet_size = 512; |
998 | } else { | 1133 | } else { |
999 | rx->usb_packet_size = 64; | 1134 | rx->usb_packet_size = 64; |
1000 | } | 1135 | } |
1001 | ZD_ASSERT(rx->fragment_length == 0); | 1136 | ZD_ASSERT(rx->fragment_length == 0); |
1137 | INIT_DELAYED_WORK(&rx->idle_work, zd_rx_idle_timer_handler); | ||
1002 | } | 1138 | } |
1003 | 1139 | ||
1004 | static inline void init_usb_tx(struct zd_usb *usb) | 1140 | static inline void init_usb_tx(struct zd_usb *usb) |
1005 | { | 1141 | { |
1006 | struct zd_usb_tx *tx = &usb->tx; | 1142 | struct zd_usb_tx *tx = &usb->tx; |
1007 | spin_lock_init(&tx->lock); | 1143 | spin_lock_init(&tx->lock); |
1008 | tx->enabled = 0; | 1144 | atomic_set(&tx->enabled, 0); |
1009 | tx->stopped = 0; | 1145 | tx->stopped = 0; |
1010 | INIT_LIST_HEAD(&tx->free_urb_list); | 1146 | skb_queue_head_init(&tx->submitted_skbs); |
1147 | init_usb_anchor(&tx->submitted); | ||
1011 | tx->submitted_urbs = 0; | 1148 | tx->submitted_urbs = 0; |
1149 | tx->watchdog_enabled = 0; | ||
1150 | INIT_DELAYED_WORK(&tx->watchdog_work, zd_tx_watchdog_handler); | ||
1012 | } | 1151 | } |
1013 | 1152 | ||
1014 | void zd_usb_init(struct zd_usb *usb, struct ieee80211_hw *hw, | 1153 | void zd_usb_init(struct zd_usb *usb, struct ieee80211_hw *hw, |
@@ -1240,6 +1379,7 @@ static void disconnect(struct usb_interface *intf) | |||
1240 | ieee80211_unregister_hw(hw); | 1379 | ieee80211_unregister_hw(hw); |
1241 | 1380 | ||
1242 | /* Just in case something has gone wrong! */ | 1381 | /* Just in case something has gone wrong! */ |
1382 | zd_usb_disable_tx(usb); | ||
1243 | zd_usb_disable_rx(usb); | 1383 | zd_usb_disable_rx(usb); |
1244 | zd_usb_disable_int(usb); | 1384 | zd_usb_disable_int(usb); |
1245 | 1385 | ||
@@ -1255,11 +1395,92 @@ static void disconnect(struct usb_interface *intf) | |||
1255 | dev_dbg(&intf->dev, "disconnected\n"); | 1395 | dev_dbg(&intf->dev, "disconnected\n"); |
1256 | } | 1396 | } |
1257 | 1397 | ||
1398 | static void zd_usb_resume(struct zd_usb *usb) | ||
1399 | { | ||
1400 | struct zd_mac *mac = zd_usb_to_mac(usb); | ||
1401 | int r; | ||
1402 | |||
1403 | dev_dbg_f(zd_usb_dev(usb), "\n"); | ||
1404 | |||
1405 | r = zd_op_start(zd_usb_to_hw(usb)); | ||
1406 | if (r < 0) { | ||
1407 | dev_warn(zd_usb_dev(usb), "Device resume failed " | ||
1408 | "with error code %d. Retrying...\n", r); | ||
1409 | if (usb->was_running) | ||
1410 | set_bit(ZD_DEVICE_RUNNING, &mac->flags); | ||
1411 | usb_queue_reset_device(usb->intf); | ||
1412 | return; | ||
1413 | } | ||
1414 | |||
1415 | if (mac->type != NL80211_IFTYPE_UNSPECIFIED) { | ||
1416 | r = zd_restore_settings(mac); | ||
1417 | if (r < 0) { | ||
1418 | dev_dbg(zd_usb_dev(usb), | ||
1419 | "failed to restore settings, %d\n", r); | ||
1420 | return; | ||
1421 | } | ||
1422 | } | ||
1423 | } | ||
1424 | |||
1425 | static void zd_usb_stop(struct zd_usb *usb) | ||
1426 | { | ||
1427 | dev_dbg_f(zd_usb_dev(usb), "\n"); | ||
1428 | |||
1429 | zd_op_stop(zd_usb_to_hw(usb)); | ||
1430 | |||
1431 | zd_usb_disable_tx(usb); | ||
1432 | zd_usb_disable_rx(usb); | ||
1433 | zd_usb_disable_int(usb); | ||
1434 | |||
1435 | usb->initialized = 0; | ||
1436 | } | ||
1437 | |||
1438 | static int pre_reset(struct usb_interface *intf) | ||
1439 | { | ||
1440 | struct ieee80211_hw *hw = usb_get_intfdata(intf); | ||
1441 | struct zd_mac *mac; | ||
1442 | struct zd_usb *usb; | ||
1443 | |||
1444 | if (!hw || intf->condition != USB_INTERFACE_BOUND) | ||
1445 | return 0; | ||
1446 | |||
1447 | mac = zd_hw_mac(hw); | ||
1448 | usb = &mac->chip.usb; | ||
1449 | |||
1450 | usb->was_running = test_bit(ZD_DEVICE_RUNNING, &mac->flags); | ||
1451 | |||
1452 | zd_usb_stop(usb); | ||
1453 | |||
1454 | mutex_lock(&mac->chip.mutex); | ||
1455 | return 0; | ||
1456 | } | ||
1457 | |||
1458 | static int post_reset(struct usb_interface *intf) | ||
1459 | { | ||
1460 | struct ieee80211_hw *hw = usb_get_intfdata(intf); | ||
1461 | struct zd_mac *mac; | ||
1462 | struct zd_usb *usb; | ||
1463 | |||
1464 | if (!hw || intf->condition != USB_INTERFACE_BOUND) | ||
1465 | return 0; | ||
1466 | |||
1467 | mac = zd_hw_mac(hw); | ||
1468 | usb = &mac->chip.usb; | ||
1469 | |||
1470 | mutex_unlock(&mac->chip.mutex); | ||
1471 | |||
1472 | if (usb->was_running) | ||
1473 | zd_usb_resume(usb); | ||
1474 | return 0; | ||
1475 | } | ||
1476 | |||
1258 | static struct usb_driver driver = { | 1477 | static struct usb_driver driver = { |
1259 | .name = KBUILD_MODNAME, | 1478 | .name = KBUILD_MODNAME, |
1260 | .id_table = usb_ids, | 1479 | .id_table = usb_ids, |
1261 | .probe = probe, | 1480 | .probe = probe, |
1262 | .disconnect = disconnect, | 1481 | .disconnect = disconnect, |
1482 | .pre_reset = pre_reset, | ||
1483 | .post_reset = post_reset, | ||
1263 | }; | 1484 | }; |
1264 | 1485 | ||
1265 | struct workqueue_struct *zd_workqueue; | 1486 | struct workqueue_struct *zd_workqueue; |
@@ -1393,15 +1614,20 @@ int zd_usb_ioread16v(struct zd_usb *usb, u16 *values, | |||
1393 | return -EWOULDBLOCK; | 1614 | return -EWOULDBLOCK; |
1394 | } | 1615 | } |
1395 | if (!usb_int_enabled(usb)) { | 1616 | if (!usb_int_enabled(usb)) { |
1396 | dev_dbg_f(zd_usb_dev(usb), | 1617 | dev_dbg_f(zd_usb_dev(usb), |
1397 | "error: usb interrupt not enabled\n"); | 1618 | "error: usb interrupt not enabled\n"); |
1398 | return -EWOULDBLOCK; | 1619 | return -EWOULDBLOCK; |
1399 | } | 1620 | } |
1400 | 1621 | ||
1622 | ZD_ASSERT(mutex_is_locked(&zd_usb_to_chip(usb)->mutex)); | ||
1623 | BUILD_BUG_ON(sizeof(struct usb_req_read_regs) + USB_MAX_IOREAD16_COUNT * | ||
1624 | sizeof(__le16) > sizeof(usb->req_buf)); | ||
1625 | BUG_ON(sizeof(struct usb_req_read_regs) + count * sizeof(__le16) > | ||
1626 | sizeof(usb->req_buf)); | ||
1627 | |||
1401 | req_len = sizeof(struct usb_req_read_regs) + count * sizeof(__le16); | 1628 | req_len = sizeof(struct usb_req_read_regs) + count * sizeof(__le16); |
1402 | req = kmalloc(req_len, GFP_KERNEL); | 1629 | req = (void *)usb->req_buf; |
1403 | if (!req) | 1630 | |
1404 | return -ENOMEM; | ||
1405 | req->id = cpu_to_le16(USB_REQ_READ_REGS); | 1631 | req->id = cpu_to_le16(USB_REQ_READ_REGS); |
1406 | for (i = 0; i < count; i++) | 1632 | for (i = 0; i < count; i++) |
1407 | req->addr[i] = cpu_to_le16((u16)addresses[i]); | 1633 | req->addr[i] = cpu_to_le16((u16)addresses[i]); |
@@ -1409,7 +1635,7 @@ int zd_usb_ioread16v(struct zd_usb *usb, u16 *values, | |||
1409 | udev = zd_usb_to_usbdev(usb); | 1635 | udev = zd_usb_to_usbdev(usb); |
1410 | prepare_read_regs_int(usb); | 1636 | prepare_read_regs_int(usb); |
1411 | r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, EP_REGS_OUT), | 1637 | r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, EP_REGS_OUT), |
1412 | req, req_len, &actual_req_len, 1000 /* ms */); | 1638 | req, req_len, &actual_req_len, 50 /* ms */); |
1413 | if (r) { | 1639 | if (r) { |
1414 | dev_dbg_f(zd_usb_dev(usb), | 1640 | dev_dbg_f(zd_usb_dev(usb), |
1415 | "error in usb_bulk_msg(). Error number %d\n", r); | 1641 | "error in usb_bulk_msg(). Error number %d\n", r); |
@@ -1424,7 +1650,7 @@ int zd_usb_ioread16v(struct zd_usb *usb, u16 *values, | |||
1424 | } | 1650 | } |
1425 | 1651 | ||
1426 | timeout = wait_for_completion_timeout(&usb->intr.read_regs.completion, | 1652 | timeout = wait_for_completion_timeout(&usb->intr.read_regs.completion, |
1427 | msecs_to_jiffies(1000)); | 1653 | msecs_to_jiffies(50)); |
1428 | if (!timeout) { | 1654 | if (!timeout) { |
1429 | disable_read_regs_int(usb); | 1655 | disable_read_regs_int(usb); |
1430 | dev_dbg_f(zd_usb_dev(usb), "read timed out\n"); | 1656 | dev_dbg_f(zd_usb_dev(usb), "read timed out\n"); |
@@ -1434,7 +1660,6 @@ int zd_usb_ioread16v(struct zd_usb *usb, u16 *values, | |||
1434 | 1660 | ||
1435 | r = get_results(usb, values, req, count); | 1661 | r = get_results(usb, values, req, count); |
1436 | error: | 1662 | error: |
1437 | kfree(req); | ||
1438 | return r; | 1663 | return r; |
1439 | } | 1664 | } |
1440 | 1665 | ||
@@ -1460,11 +1685,17 @@ int zd_usb_iowrite16v(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs, | |||
1460 | return -EWOULDBLOCK; | 1685 | return -EWOULDBLOCK; |
1461 | } | 1686 | } |
1462 | 1687 | ||
1688 | ZD_ASSERT(mutex_is_locked(&zd_usb_to_chip(usb)->mutex)); | ||
1689 | BUILD_BUG_ON(sizeof(struct usb_req_write_regs) + | ||
1690 | USB_MAX_IOWRITE16_COUNT * sizeof(struct reg_data) > | ||
1691 | sizeof(usb->req_buf)); | ||
1692 | BUG_ON(sizeof(struct usb_req_write_regs) + | ||
1693 | count * sizeof(struct reg_data) > | ||
1694 | sizeof(usb->req_buf)); | ||
1695 | |||
1463 | req_len = sizeof(struct usb_req_write_regs) + | 1696 | req_len = sizeof(struct usb_req_write_regs) + |
1464 | count * sizeof(struct reg_data); | 1697 | count * sizeof(struct reg_data); |
1465 | req = kmalloc(req_len, GFP_KERNEL); | 1698 | req = (void *)usb->req_buf; |
1466 | if (!req) | ||
1467 | return -ENOMEM; | ||
1468 | 1699 | ||
1469 | req->id = cpu_to_le16(USB_REQ_WRITE_REGS); | 1700 | req->id = cpu_to_le16(USB_REQ_WRITE_REGS); |
1470 | for (i = 0; i < count; i++) { | 1701 | for (i = 0; i < count; i++) { |
@@ -1475,7 +1706,7 @@ int zd_usb_iowrite16v(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs, | |||
1475 | 1706 | ||
1476 | udev = zd_usb_to_usbdev(usb); | 1707 | udev = zd_usb_to_usbdev(usb); |
1477 | r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, EP_REGS_OUT), | 1708 | r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, EP_REGS_OUT), |
1478 | req, req_len, &actual_req_len, 1000 /* ms */); | 1709 | req, req_len, &actual_req_len, 50 /* ms */); |
1479 | if (r) { | 1710 | if (r) { |
1480 | dev_dbg_f(zd_usb_dev(usb), | 1711 | dev_dbg_f(zd_usb_dev(usb), |
1481 | "error in usb_bulk_msg(). Error number %d\n", r); | 1712 | "error in usb_bulk_msg(). Error number %d\n", r); |
@@ -1492,7 +1723,6 @@ int zd_usb_iowrite16v(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs, | |||
1492 | 1723 | ||
1493 | /* FALL-THROUGH with r == 0 */ | 1724 | /* FALL-THROUGH with r == 0 */ |
1494 | error: | 1725 | error: |
1495 | kfree(req); | ||
1496 | return r; | 1726 | return r; |
1497 | } | 1727 | } |
1498 | 1728 | ||
@@ -1537,14 +1767,19 @@ int zd_usb_rfwrite(struct zd_usb *usb, u32 value, u8 bits) | |||
1537 | if (r) { | 1767 | if (r) { |
1538 | dev_dbg_f(zd_usb_dev(usb), | 1768 | dev_dbg_f(zd_usb_dev(usb), |
1539 | "error %d: Couldn't read CR203\n", r); | 1769 | "error %d: Couldn't read CR203\n", r); |
1540 | goto out; | 1770 | return r; |
1541 | } | 1771 | } |
1542 | bit_value_template &= ~(RF_IF_LE|RF_CLK|RF_DATA); | 1772 | bit_value_template &= ~(RF_IF_LE|RF_CLK|RF_DATA); |
1543 | 1773 | ||
1774 | ZD_ASSERT(mutex_is_locked(&zd_usb_to_chip(usb)->mutex)); | ||
1775 | BUILD_BUG_ON(sizeof(struct usb_req_rfwrite) + | ||
1776 | USB_MAX_RFWRITE_BIT_COUNT * sizeof(__le16) > | ||
1777 | sizeof(usb->req_buf)); | ||
1778 | BUG_ON(sizeof(struct usb_req_rfwrite) + bits * sizeof(__le16) > | ||
1779 | sizeof(usb->req_buf)); | ||
1780 | |||
1544 | req_len = sizeof(struct usb_req_rfwrite) + bits * sizeof(__le16); | 1781 | req_len = sizeof(struct usb_req_rfwrite) + bits * sizeof(__le16); |
1545 | req = kmalloc(req_len, GFP_KERNEL); | 1782 | req = (void *)usb->req_buf; |
1546 | if (!req) | ||
1547 | return -ENOMEM; | ||
1548 | 1783 | ||
1549 | req->id = cpu_to_le16(USB_REQ_WRITE_RF); | 1784 | req->id = cpu_to_le16(USB_REQ_WRITE_RF); |
1550 | /* 1: 3683a, but not used in ZYDAS driver */ | 1785 | /* 1: 3683a, but not used in ZYDAS driver */ |
@@ -1560,7 +1795,7 @@ int zd_usb_rfwrite(struct zd_usb *usb, u32 value, u8 bits) | |||
1560 | 1795 | ||
1561 | udev = zd_usb_to_usbdev(usb); | 1796 | udev = zd_usb_to_usbdev(usb); |
1562 | r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, EP_REGS_OUT), | 1797 | r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, EP_REGS_OUT), |
1563 | req, req_len, &actual_req_len, 1000 /* ms */); | 1798 | req, req_len, &actual_req_len, 50 /* ms */); |
1564 | if (r) { | 1799 | if (r) { |
1565 | dev_dbg_f(zd_usb_dev(usb), | 1800 | dev_dbg_f(zd_usb_dev(usb), |
1566 | "error in usb_bulk_msg(). Error number %d\n", r); | 1801 | "error in usb_bulk_msg(). Error number %d\n", r); |
@@ -1576,6 +1811,5 @@ int zd_usb_rfwrite(struct zd_usb *usb, u32 value, u8 bits) | |||
1576 | 1811 | ||
1577 | /* FALL-THROUGH with r == 0 */ | 1812 | /* FALL-THROUGH with r == 0 */ |
1578 | out: | 1813 | out: |
1579 | kfree(req); | ||
1580 | return r; | 1814 | return r; |
1581 | } | 1815 | } |
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.h b/drivers/net/wireless/zd1211rw/zd_usb.h index 1b1655cb7cb4..2d688f48a34c 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.h +++ b/drivers/net/wireless/zd1211rw/zd_usb.h | |||
@@ -32,6 +32,10 @@ | |||
32 | #define ZD_USB_TX_HIGH 5 | 32 | #define ZD_USB_TX_HIGH 5 |
33 | #define ZD_USB_TX_LOW 2 | 33 | #define ZD_USB_TX_LOW 2 |
34 | 34 | ||
35 | #define ZD_TX_TIMEOUT (HZ * 5) | ||
36 | #define ZD_TX_WATCHDOG_INTERVAL round_jiffies_relative(HZ) | ||
37 | #define ZD_RX_IDLE_INTERVAL round_jiffies_relative(30 * HZ) | ||
38 | |||
35 | enum devicetype { | 39 | enum devicetype { |
36 | DEVICE_ZD1211 = 0, | 40 | DEVICE_ZD1211 = 0, |
37 | DEVICE_ZD1211B = 1, | 41 | DEVICE_ZD1211B = 1, |
@@ -162,6 +166,8 @@ struct zd_usb_interrupt { | |||
162 | struct read_regs_int read_regs; | 166 | struct read_regs_int read_regs; |
163 | spinlock_t lock; | 167 | spinlock_t lock; |
164 | struct urb *urb; | 168 | struct urb *urb; |
169 | void *buffer; | ||
170 | dma_addr_t buffer_dma; | ||
165 | int interval; | 171 | int interval; |
166 | u8 read_regs_enabled:1; | 172 | u8 read_regs_enabled:1; |
167 | }; | 173 | }; |
@@ -175,7 +181,9 @@ static inline struct usb_int_regs *get_read_regs(struct zd_usb_interrupt *intr) | |||
175 | 181 | ||
176 | struct zd_usb_rx { | 182 | struct zd_usb_rx { |
177 | spinlock_t lock; | 183 | spinlock_t lock; |
178 | u8 fragment[2*USB_MAX_RX_SIZE]; | 184 | struct mutex setup_mutex; |
185 | struct delayed_work idle_work; | ||
186 | u8 fragment[2 * USB_MAX_RX_SIZE]; | ||
179 | unsigned int fragment_length; | 187 | unsigned int fragment_length; |
180 | unsigned int usb_packet_size; | 188 | unsigned int usb_packet_size; |
181 | struct urb **urbs; | 189 | struct urb **urbs; |
@@ -184,19 +192,21 @@ struct zd_usb_rx { | |||
184 | 192 | ||
185 | /** | 193 | /** |
186 | * struct zd_usb_tx - structure used for transmitting frames | 194 | * struct zd_usb_tx - structure used for transmitting frames |
195 | * @enabled: atomic enabled flag, indicates whether tx is enabled | ||
187 | * @lock: lock for transmission | 196 | * @lock: lock for transmission |
188 | * @free_urb_list: list of free URBs, contains all the URBs, which can be used | 197 | * @submitted: anchor for URBs sent to device |
189 | * @submitted_urbs: atomic integer that counts the URBs having sent to the | 198 | * @submitted_urbs: atomic integer that counts the URBs having sent to the |
190 | * device, which haven't been completed | 199 | * device, which haven't been completed |
191 | * @enabled: enabled flag, indicates whether tx is enabled | ||
192 | * @stopped: indicates whether higher level tx queues are stopped | 200 | * @stopped: indicates whether higher level tx queues are stopped |
193 | */ | 201 | */ |
194 | struct zd_usb_tx { | 202 | struct zd_usb_tx { |
203 | atomic_t enabled; | ||
195 | spinlock_t lock; | 204 | spinlock_t lock; |
196 | struct list_head free_urb_list; | 205 | struct delayed_work watchdog_work; |
206 | struct sk_buff_head submitted_skbs; | ||
207 | struct usb_anchor submitted; | ||
197 | int submitted_urbs; | 208 | int submitted_urbs; |
198 | int enabled; | 209 | u8 stopped:1, watchdog_enabled:1; |
199 | int stopped; | ||
200 | }; | 210 | }; |
201 | 211 | ||
202 | /* Contains the usb parts. The structure doesn't require a lock because intf | 212 | /* Contains the usb parts. The structure doesn't require a lock because intf |
@@ -207,7 +217,8 @@ struct zd_usb { | |||
207 | struct zd_usb_rx rx; | 217 | struct zd_usb_rx rx; |
208 | struct zd_usb_tx tx; | 218 | struct zd_usb_tx tx; |
209 | struct usb_interface *intf; | 219 | struct usb_interface *intf; |
210 | u8 is_zd1211b:1, initialized:1; | 220 | u8 req_buf[64]; /* zd_usb_iowrite16v needs 62 bytes */ |
221 | u8 is_zd1211b:1, initialized:1, was_running:1; | ||
211 | }; | 222 | }; |
212 | 223 | ||
213 | #define zd_usb_dev(usb) (&usb->intf->dev) | 224 | #define zd_usb_dev(usb) (&usb->intf->dev) |
@@ -234,12 +245,17 @@ void zd_usb_clear(struct zd_usb *usb); | |||
234 | 245 | ||
235 | int zd_usb_scnprint_id(struct zd_usb *usb, char *buffer, size_t size); | 246 | int zd_usb_scnprint_id(struct zd_usb *usb, char *buffer, size_t size); |
236 | 247 | ||
248 | void zd_tx_watchdog_enable(struct zd_usb *usb); | ||
249 | void zd_tx_watchdog_disable(struct zd_usb *usb); | ||
250 | |||
237 | int zd_usb_enable_int(struct zd_usb *usb); | 251 | int zd_usb_enable_int(struct zd_usb *usb); |
238 | void zd_usb_disable_int(struct zd_usb *usb); | 252 | void zd_usb_disable_int(struct zd_usb *usb); |
239 | 253 | ||
240 | int zd_usb_enable_rx(struct zd_usb *usb); | 254 | int zd_usb_enable_rx(struct zd_usb *usb); |
241 | void zd_usb_disable_rx(struct zd_usb *usb); | 255 | void zd_usb_disable_rx(struct zd_usb *usb); |
242 | 256 | ||
257 | void zd_usb_reset_rx_idle_timer(struct zd_usb *usb); | ||
258 | |||
243 | void zd_usb_enable_tx(struct zd_usb *usb); | 259 | void zd_usb_enable_tx(struct zd_usb *usb); |
244 | void zd_usb_disable_tx(struct zd_usb *usb); | 260 | void zd_usb_disable_tx(struct zd_usb *usb); |
245 | 261 | ||
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index d6b0045788ce..8fcd1691cfb7 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -341,6 +341,9 @@ struct ieee80211_bss_conf { | |||
341 | * the off-channel channel when a remain-on-channel offload is done | 341 | * the off-channel channel when a remain-on-channel offload is done |
342 | * in hardware -- normal packets still flow and are expected to be | 342 | * in hardware -- normal packets still flow and are expected to be |
343 | * handled properly by the device. | 343 | * handled properly by the device. |
344 | * @IEEE80211_TX_INTFL_TKIP_MIC_FAILURE: Marks this packet to be used for TKIP | ||
345 | * testing. It will be sent out with incorrect Michael MIC key to allow | ||
346 | * TKIP countermeasures to be tested. | ||
344 | * | 347 | * |
345 | * Note: If you have to add new flags to the enumeration, then don't | 348 | * Note: If you have to add new flags to the enumeration, then don't |
346 | * forget to update %IEEE80211_TX_TEMPORARY_FLAGS when necessary. | 349 | * forget to update %IEEE80211_TX_TEMPORARY_FLAGS when necessary. |
@@ -370,6 +373,7 @@ enum mac80211_tx_control_flags { | |||
370 | IEEE80211_TX_CTL_LDPC = BIT(22), | 373 | IEEE80211_TX_CTL_LDPC = BIT(22), |
371 | IEEE80211_TX_CTL_STBC = BIT(23) | BIT(24), | 374 | IEEE80211_TX_CTL_STBC = BIT(23) | BIT(24), |
372 | IEEE80211_TX_CTL_TX_OFFCHAN = BIT(25), | 375 | IEEE80211_TX_CTL_TX_OFFCHAN = BIT(25), |
376 | IEEE80211_TX_INTFL_TKIP_MIC_FAILURE = BIT(26), | ||
373 | }; | 377 | }; |
374 | 378 | ||
375 | #define IEEE80211_TX_CTL_STBC_SHIFT 23 | 379 | #define IEEE80211_TX_CTL_STBC_SHIFT 23 |
@@ -1069,6 +1073,13 @@ enum ieee80211_tkip_key_type { | |||
1069 | * to decrypt group addressed frames, then IBSS RSN support is still | 1073 | * to decrypt group addressed frames, then IBSS RSN support is still |
1070 | * possible but software crypto will be used. Advertise the wiphy flag | 1074 | * possible but software crypto will be used. Advertise the wiphy flag |
1071 | * only in that case. | 1075 | * only in that case. |
1076 | * | ||
1077 | * @IEEE80211_HW_AP_LINK_PS: When operating in AP mode the device | ||
1078 | * autonomously manages the PS status of connected stations. When | ||
1079 | * this flag is set mac80211 will not trigger PS mode for connected | ||
1080 | * stations based on the PM bit of incoming frames. | ||
1081 | * Use ieee80211_start_ps()/ieee8021_end_ps() to manually configure | ||
1082 | * the PS mode of connected stations. | ||
1072 | */ | 1083 | */ |
1073 | enum ieee80211_hw_flags { | 1084 | enum ieee80211_hw_flags { |
1074 | IEEE80211_HW_HAS_RATE_CONTROL = 1<<0, | 1085 | IEEE80211_HW_HAS_RATE_CONTROL = 1<<0, |
@@ -1093,6 +1104,7 @@ enum ieee80211_hw_flags { | |||
1093 | IEEE80211_HW_CONNECTION_MONITOR = 1<<19, | 1104 | IEEE80211_HW_CONNECTION_MONITOR = 1<<19, |
1094 | IEEE80211_HW_SUPPORTS_CQM_RSSI = 1<<20, | 1105 | IEEE80211_HW_SUPPORTS_CQM_RSSI = 1<<20, |
1095 | IEEE80211_HW_SUPPORTS_PER_STA_GTK = 1<<21, | 1106 | IEEE80211_HW_SUPPORTS_PER_STA_GTK = 1<<21, |
1107 | IEEE80211_HW_AP_LINK_PS = 1<<22, | ||
1096 | }; | 1108 | }; |
1097 | 1109 | ||
1098 | /** | 1110 | /** |
@@ -1701,7 +1713,9 @@ enum ieee80211_ampdu_mlme_action { | |||
1701 | * station, AP, IBSS/WDS/mesh peer etc. This callback can sleep. | 1713 | * station, AP, IBSS/WDS/mesh peer etc. This callback can sleep. |
1702 | * | 1714 | * |
1703 | * @sta_notify: Notifies low level driver about power state transition of an | 1715 | * @sta_notify: Notifies low level driver about power state transition of an |
1704 | * associated station, AP, IBSS/WDS/mesh peer etc. Must be atomic. | 1716 | * associated station, AP, IBSS/WDS/mesh peer etc. For a VIF operating |
1717 | * in AP mode, this callback will not be called when the flag | ||
1718 | * %IEEE80211_HW_AP_LINK_PS is set. Must be atomic. | ||
1705 | * | 1719 | * |
1706 | * @conf_tx: Configure TX queue parameters (EDCF (aifs, cw_min, cw_max), | 1720 | * @conf_tx: Configure TX queue parameters (EDCF (aifs, cw_min, cw_max), |
1707 | * bursting) for a hardware TX queue. | 1721 | * bursting) for a hardware TX queue. |
@@ -2131,6 +2145,48 @@ static inline void ieee80211_rx_ni(struct ieee80211_hw *hw, | |||
2131 | local_bh_enable(); | 2145 | local_bh_enable(); |
2132 | } | 2146 | } |
2133 | 2147 | ||
2148 | /** | ||
2149 | * ieee80211_sta_ps_transition - PS transition for connected sta | ||
2150 | * | ||
2151 | * When operating in AP mode with the %IEEE80211_HW_AP_LINK_PS | ||
2152 | * flag set, use this function to inform mac80211 about a connected station | ||
2153 | * entering/leaving PS mode. | ||
2154 | * | ||
2155 | * This function may not be called in IRQ context or with softirqs enabled. | ||
2156 | * | ||
2157 | * Calls to this function for a single hardware must be synchronized against | ||
2158 | * each other. | ||
2159 | * | ||
2160 | * The function returns -EINVAL when the requested PS mode is already set. | ||
2161 | * | ||
2162 | * @sta: currently connected sta | ||
2163 | * @start: start or stop PS | ||
2164 | */ | ||
2165 | int ieee80211_sta_ps_transition(struct ieee80211_sta *sta, bool start); | ||
2166 | |||
2167 | /** | ||
2168 | * ieee80211_sta_ps_transition_ni - PS transition for connected sta | ||
2169 | * (in process context) | ||
2170 | * | ||
2171 | * Like ieee80211_sta_ps_transition() but can be called in process context | ||
2172 | * (internally disables bottom halves). Concurrent call restriction still | ||
2173 | * applies. | ||
2174 | * | ||
2175 | * @sta: currently connected sta | ||
2176 | * @start: start or stop PS | ||
2177 | */ | ||
2178 | static inline int ieee80211_sta_ps_transition_ni(struct ieee80211_sta *sta, | ||
2179 | bool start) | ||
2180 | { | ||
2181 | int ret; | ||
2182 | |||
2183 | local_bh_disable(); | ||
2184 | ret = ieee80211_sta_ps_transition(sta, start); | ||
2185 | local_bh_enable(); | ||
2186 | |||
2187 | return ret; | ||
2188 | } | ||
2189 | |||
2134 | /* | 2190 | /* |
2135 | * The TX headroom reserved by mac80211 for its own tx_status functions. | 2191 | * The TX headroom reserved by mac80211 for its own tx_status functions. |
2136 | * This is enough for the radiotap header. | 2192 | * This is enough for the radiotap header. |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 4bc8a9250cfd..845c76d58d25 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -1215,6 +1215,9 @@ static int ieee80211_set_channel(struct wiphy *wiphy, | |||
1215 | { | 1215 | { |
1216 | struct ieee80211_local *local = wiphy_priv(wiphy); | 1216 | struct ieee80211_local *local = wiphy_priv(wiphy); |
1217 | struct ieee80211_sub_if_data *sdata = NULL; | 1217 | struct ieee80211_sub_if_data *sdata = NULL; |
1218 | struct ieee80211_channel *old_oper; | ||
1219 | enum nl80211_channel_type old_oper_type; | ||
1220 | enum nl80211_channel_type old_vif_oper_type= NL80211_CHAN_NO_HT; | ||
1218 | 1221 | ||
1219 | if (netdev) | 1222 | if (netdev) |
1220 | sdata = IEEE80211_DEV_TO_SUB_IF(netdev); | 1223 | sdata = IEEE80211_DEV_TO_SUB_IF(netdev); |
@@ -1232,13 +1235,23 @@ static int ieee80211_set_channel(struct wiphy *wiphy, | |||
1232 | break; | 1235 | break; |
1233 | } | 1236 | } |
1234 | 1237 | ||
1235 | local->oper_channel = chan; | 1238 | if (sdata) |
1239 | old_vif_oper_type = sdata->vif.bss_conf.channel_type; | ||
1240 | old_oper_type = local->_oper_channel_type; | ||
1236 | 1241 | ||
1237 | if (!ieee80211_set_channel_type(local, sdata, channel_type)) | 1242 | if (!ieee80211_set_channel_type(local, sdata, channel_type)) |
1238 | return -EBUSY; | 1243 | return -EBUSY; |
1239 | 1244 | ||
1240 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | 1245 | old_oper = local->oper_channel; |
1241 | if (sdata && sdata->vif.type != NL80211_IFTYPE_MONITOR) | 1246 | local->oper_channel = chan; |
1247 | |||
1248 | /* Update driver if changes were actually made. */ | ||
1249 | if ((old_oper != local->oper_channel) || | ||
1250 | (old_oper_type != local->_oper_channel_type)) | ||
1251 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | ||
1252 | |||
1253 | if ((sdata && sdata->vif.type != NL80211_IFTYPE_MONITOR) && | ||
1254 | old_vif_oper_type != sdata->vif.bss_conf.channel_type) | ||
1242 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_HT); | 1255 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_HT); |
1243 | 1256 | ||
1244 | return 0; | 1257 | return 0; |
@@ -1274,8 +1287,11 @@ static int ieee80211_scan(struct wiphy *wiphy, | |||
1274 | case NL80211_IFTYPE_P2P_GO: | 1287 | case NL80211_IFTYPE_P2P_GO: |
1275 | if (sdata->local->ops->hw_scan) | 1288 | if (sdata->local->ops->hw_scan) |
1276 | break; | 1289 | break; |
1277 | /* FIXME: implement NoA while scanning in software */ | 1290 | /* |
1278 | return -EOPNOTSUPP; | 1291 | * FIXME: implement NoA while scanning in software, |
1292 | * for now fall through to allow scanning only when | ||
1293 | * beaconing hasn't been configured yet | ||
1294 | */ | ||
1279 | case NL80211_IFTYPE_AP: | 1295 | case NL80211_IFTYPE_AP: |
1280 | if (sdata->u.ap.beacon) | 1296 | if (sdata->u.ap.beacon) |
1281 | return -EOPNOTSUPP; | 1297 | return -EOPNOTSUPP; |
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 872adb86200c..dacace6b1393 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c | |||
@@ -36,7 +36,7 @@ static ssize_t ieee80211_if_read( | |||
36 | ret = (*format)(sdata, buf, sizeof(buf)); | 36 | ret = (*format)(sdata, buf, sizeof(buf)); |
37 | read_unlock(&dev_base_lock); | 37 | read_unlock(&dev_base_lock); |
38 | 38 | ||
39 | if (ret != -EINVAL) | 39 | if (ret >= 0) |
40 | ret = simple_read_from_buffer(userbuf, count, ppos, buf, ret); | 40 | ret = simple_read_from_buffer(userbuf, count, ppos, buf, ret); |
41 | 41 | ||
42 | return ret; | 42 | return ret; |
@@ -149,6 +149,7 @@ IEEE80211_IF_FILE(rc_rateidx_mask_5ghz, rc_rateidx_mask[IEEE80211_BAND_5GHZ], | |||
149 | HEX); | 149 | HEX); |
150 | IEEE80211_IF_FILE(flags, flags, HEX); | 150 | IEEE80211_IF_FILE(flags, flags, HEX); |
151 | IEEE80211_IF_FILE(state, state, LHEX); | 151 | IEEE80211_IF_FILE(state, state, LHEX); |
152 | IEEE80211_IF_FILE(channel_type, vif.bss_conf.channel_type, DEC); | ||
152 | 153 | ||
153 | /* STA attributes */ | 154 | /* STA attributes */ |
154 | IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC); | 155 | IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC); |
@@ -220,6 +221,104 @@ static ssize_t ieee80211_if_parse_smps(struct ieee80211_sub_if_data *sdata, | |||
220 | 221 | ||
221 | __IEEE80211_IF_FILE_W(smps); | 222 | __IEEE80211_IF_FILE_W(smps); |
222 | 223 | ||
224 | static ssize_t ieee80211_if_fmt_tkip_mic_test( | ||
225 | const struct ieee80211_sub_if_data *sdata, char *buf, int buflen) | ||
226 | { | ||
227 | return -EOPNOTSUPP; | ||
228 | } | ||
229 | |||
230 | static int hwaddr_aton(const char *txt, u8 *addr) | ||
231 | { | ||
232 | int i; | ||
233 | |||
234 | for (i = 0; i < ETH_ALEN; i++) { | ||
235 | int a, b; | ||
236 | |||
237 | a = hex_to_bin(*txt++); | ||
238 | if (a < 0) | ||
239 | return -1; | ||
240 | b = hex_to_bin(*txt++); | ||
241 | if (b < 0) | ||
242 | return -1; | ||
243 | *addr++ = (a << 4) | b; | ||
244 | if (i < 5 && *txt++ != ':') | ||
245 | return -1; | ||
246 | } | ||
247 | |||
248 | return 0; | ||
249 | } | ||
250 | |||
251 | static ssize_t ieee80211_if_parse_tkip_mic_test( | ||
252 | struct ieee80211_sub_if_data *sdata, const char *buf, int buflen) | ||
253 | { | ||
254 | struct ieee80211_local *local = sdata->local; | ||
255 | u8 addr[ETH_ALEN]; | ||
256 | struct sk_buff *skb; | ||
257 | struct ieee80211_hdr *hdr; | ||
258 | __le16 fc; | ||
259 | |||
260 | /* | ||
261 | * Assume colon-delimited MAC address with possible white space | ||
262 | * following. | ||
263 | */ | ||
264 | if (buflen < 3 * ETH_ALEN - 1) | ||
265 | return -EINVAL; | ||
266 | if (hwaddr_aton(buf, addr) < 0) | ||
267 | return -EINVAL; | ||
268 | |||
269 | if (!ieee80211_sdata_running(sdata)) | ||
270 | return -ENOTCONN; | ||
271 | |||
272 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + 24 + 100); | ||
273 | if (!skb) | ||
274 | return -ENOMEM; | ||
275 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
276 | |||
277 | hdr = (struct ieee80211_hdr *) skb_put(skb, 24); | ||
278 | memset(hdr, 0, 24); | ||
279 | fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA); | ||
280 | |||
281 | switch (sdata->vif.type) { | ||
282 | case NL80211_IFTYPE_AP: | ||
283 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS); | ||
284 | /* DA BSSID SA */ | ||
285 | memcpy(hdr->addr1, addr, ETH_ALEN); | ||
286 | memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN); | ||
287 | memcpy(hdr->addr3, sdata->vif.addr, ETH_ALEN); | ||
288 | break; | ||
289 | case NL80211_IFTYPE_STATION: | ||
290 | fc |= cpu_to_le16(IEEE80211_FCTL_TODS); | ||
291 | /* BSSID SA DA */ | ||
292 | if (sdata->vif.bss_conf.bssid == NULL) { | ||
293 | dev_kfree_skb(skb); | ||
294 | return -ENOTCONN; | ||
295 | } | ||
296 | memcpy(hdr->addr1, sdata->vif.bss_conf.bssid, ETH_ALEN); | ||
297 | memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN); | ||
298 | memcpy(hdr->addr3, addr, ETH_ALEN); | ||
299 | break; | ||
300 | default: | ||
301 | dev_kfree_skb(skb); | ||
302 | return -EOPNOTSUPP; | ||
303 | } | ||
304 | hdr->frame_control = fc; | ||
305 | |||
306 | /* | ||
307 | * Add some length to the test frame to make it look bit more valid. | ||
308 | * The exact contents does not matter since the recipient is required | ||
309 | * to drop this because of the Michael MIC failure. | ||
310 | */ | ||
311 | memset(skb_put(skb, 50), 0, 50); | ||
312 | |||
313 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_TKIP_MIC_FAILURE; | ||
314 | |||
315 | ieee80211_tx_skb(sdata, skb); | ||
316 | |||
317 | return buflen; | ||
318 | } | ||
319 | |||
320 | __IEEE80211_IF_FILE_W(tkip_mic_test); | ||
321 | |||
223 | /* AP attributes */ | 322 | /* AP attributes */ |
224 | IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC); | 323 | IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC); |
225 | IEEE80211_IF_FILE(dtim_count, u.ap.dtim_count, DEC); | 324 | IEEE80211_IF_FILE(dtim_count, u.ap.dtim_count, DEC); |
@@ -289,6 +388,7 @@ static void add_sta_files(struct ieee80211_sub_if_data *sdata) | |||
289 | DEBUGFS_ADD(drop_unencrypted); | 388 | DEBUGFS_ADD(drop_unencrypted); |
290 | DEBUGFS_ADD(flags); | 389 | DEBUGFS_ADD(flags); |
291 | DEBUGFS_ADD(state); | 390 | DEBUGFS_ADD(state); |
391 | DEBUGFS_ADD(channel_type); | ||
292 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); | 392 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); |
293 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); | 393 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); |
294 | 394 | ||
@@ -297,6 +397,7 @@ static void add_sta_files(struct ieee80211_sub_if_data *sdata) | |||
297 | DEBUGFS_ADD(last_beacon); | 397 | DEBUGFS_ADD(last_beacon); |
298 | DEBUGFS_ADD(ave_beacon); | 398 | DEBUGFS_ADD(ave_beacon); |
299 | DEBUGFS_ADD_MODE(smps, 0600); | 399 | DEBUGFS_ADD_MODE(smps, 0600); |
400 | DEBUGFS_ADD_MODE(tkip_mic_test, 0200); | ||
300 | } | 401 | } |
301 | 402 | ||
302 | static void add_ap_files(struct ieee80211_sub_if_data *sdata) | 403 | static void add_ap_files(struct ieee80211_sub_if_data *sdata) |
@@ -304,12 +405,14 @@ static void add_ap_files(struct ieee80211_sub_if_data *sdata) | |||
304 | DEBUGFS_ADD(drop_unencrypted); | 405 | DEBUGFS_ADD(drop_unencrypted); |
305 | DEBUGFS_ADD(flags); | 406 | DEBUGFS_ADD(flags); |
306 | DEBUGFS_ADD(state); | 407 | DEBUGFS_ADD(state); |
408 | DEBUGFS_ADD(channel_type); | ||
307 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); | 409 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); |
308 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); | 410 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); |
309 | 411 | ||
310 | DEBUGFS_ADD(num_sta_ps); | 412 | DEBUGFS_ADD(num_sta_ps); |
311 | DEBUGFS_ADD(dtim_count); | 413 | DEBUGFS_ADD(dtim_count); |
312 | DEBUGFS_ADD(num_buffered_multicast); | 414 | DEBUGFS_ADD(num_buffered_multicast); |
415 | DEBUGFS_ADD_MODE(tkip_mic_test, 0200); | ||
313 | } | 416 | } |
314 | 417 | ||
315 | static void add_wds_files(struct ieee80211_sub_if_data *sdata) | 418 | static void add_wds_files(struct ieee80211_sub_if_data *sdata) |
@@ -317,6 +420,7 @@ static void add_wds_files(struct ieee80211_sub_if_data *sdata) | |||
317 | DEBUGFS_ADD(drop_unencrypted); | 420 | DEBUGFS_ADD(drop_unencrypted); |
318 | DEBUGFS_ADD(flags); | 421 | DEBUGFS_ADD(flags); |
319 | DEBUGFS_ADD(state); | 422 | DEBUGFS_ADD(state); |
423 | DEBUGFS_ADD(channel_type); | ||
320 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); | 424 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); |
321 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); | 425 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); |
322 | 426 | ||
@@ -328,6 +432,7 @@ static void add_vlan_files(struct ieee80211_sub_if_data *sdata) | |||
328 | DEBUGFS_ADD(drop_unencrypted); | 432 | DEBUGFS_ADD(drop_unencrypted); |
329 | DEBUGFS_ADD(flags); | 433 | DEBUGFS_ADD(flags); |
330 | DEBUGFS_ADD(state); | 434 | DEBUGFS_ADD(state); |
435 | DEBUGFS_ADD(channel_type); | ||
331 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); | 436 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); |
332 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); | 437 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); |
333 | } | 438 | } |
@@ -336,6 +441,7 @@ static void add_monitor_files(struct ieee80211_sub_if_data *sdata) | |||
336 | { | 441 | { |
337 | DEBUGFS_ADD(flags); | 442 | DEBUGFS_ADD(flags); |
338 | DEBUGFS_ADD(state); | 443 | DEBUGFS_ADD(state); |
444 | DEBUGFS_ADD(channel_type); | ||
339 | } | 445 | } |
340 | 446 | ||
341 | #ifdef CONFIG_MAC80211_MESH | 447 | #ifdef CONFIG_MAC80211_MESH |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index c47d7c0e48a4..44eea1af1553 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -225,6 +225,7 @@ struct ieee80211_if_ap { | |||
225 | struct sk_buff_head ps_bc_buf; | 225 | struct sk_buff_head ps_bc_buf; |
226 | atomic_t num_sta_ps; /* number of stations in PS mode */ | 226 | atomic_t num_sta_ps; /* number of stations in PS mode */ |
227 | int dtim_count; | 227 | int dtim_count; |
228 | bool dtim_bc_mc; | ||
228 | }; | 229 | }; |
229 | 230 | ||
230 | struct ieee80211_if_wds { | 231 | struct ieee80211_if_wds { |
@@ -654,8 +655,6 @@ struct tpt_led_trigger { | |||
654 | * well be on the operating channel | 655 | * well be on the operating channel |
655 | * @SCAN_HW_SCANNING: The hardware is scanning for us, we have no way to | 656 | * @SCAN_HW_SCANNING: The hardware is scanning for us, we have no way to |
656 | * determine if we are on the operating channel or not | 657 | * determine if we are on the operating channel or not |
657 | * @SCAN_OFF_CHANNEL: We're off our operating channel for scanning, | ||
658 | * gets only set in conjunction with SCAN_SW_SCANNING | ||
659 | * @SCAN_COMPLETED: Set for our scan work function when the driver reported | 658 | * @SCAN_COMPLETED: Set for our scan work function when the driver reported |
660 | * that the scan completed. | 659 | * that the scan completed. |
661 | * @SCAN_ABORTED: Set for our scan work function when the driver reported | 660 | * @SCAN_ABORTED: Set for our scan work function when the driver reported |
@@ -664,7 +663,6 @@ struct tpt_led_trigger { | |||
664 | enum { | 663 | enum { |
665 | SCAN_SW_SCANNING, | 664 | SCAN_SW_SCANNING, |
666 | SCAN_HW_SCANNING, | 665 | SCAN_HW_SCANNING, |
667 | SCAN_OFF_CHANNEL, | ||
668 | SCAN_COMPLETED, | 666 | SCAN_COMPLETED, |
669 | SCAN_ABORTED, | 667 | SCAN_ABORTED, |
670 | }; | 668 | }; |
@@ -1147,10 +1145,14 @@ void ieee80211_rx_bss_put(struct ieee80211_local *local, | |||
1147 | struct ieee80211_bss *bss); | 1145 | struct ieee80211_bss *bss); |
1148 | 1146 | ||
1149 | /* off-channel helpers */ | 1147 | /* off-channel helpers */ |
1150 | void ieee80211_offchannel_stop_beaconing(struct ieee80211_local *local); | 1148 | bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local); |
1151 | void ieee80211_offchannel_stop_station(struct ieee80211_local *local); | 1149 | void ieee80211_offchannel_enable_all_ps(struct ieee80211_local *local, |
1150 | bool tell_ap); | ||
1151 | void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local, | ||
1152 | bool offchannel_ps_enable); | ||
1152 | void ieee80211_offchannel_return(struct ieee80211_local *local, | 1153 | void ieee80211_offchannel_return(struct ieee80211_local *local, |
1153 | bool enable_beaconing); | 1154 | bool enable_beaconing, |
1155 | bool offchannel_ps_disable); | ||
1154 | void ieee80211_hw_roc_setup(struct ieee80211_local *local); | 1156 | void ieee80211_hw_roc_setup(struct ieee80211_local *local); |
1155 | 1157 | ||
1156 | /* interface handling */ | 1158 | /* interface handling */ |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 8acba456744e..5a4e19b88032 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -382,6 +382,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
382 | struct sk_buff *skb, *tmp; | 382 | struct sk_buff *skb, *tmp; |
383 | u32 hw_reconf_flags = 0; | 383 | u32 hw_reconf_flags = 0; |
384 | int i; | 384 | int i; |
385 | enum nl80211_channel_type orig_ct; | ||
385 | 386 | ||
386 | if (local->scan_sdata == sdata) | 387 | if (local->scan_sdata == sdata) |
387 | ieee80211_scan_cancel(local); | 388 | ieee80211_scan_cancel(local); |
@@ -542,8 +543,14 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
542 | hw_reconf_flags = 0; | 543 | hw_reconf_flags = 0; |
543 | } | 544 | } |
544 | 545 | ||
546 | /* Re-calculate channel-type, in case there are multiple vifs | ||
547 | * on different channel types. | ||
548 | */ | ||
549 | orig_ct = local->_oper_channel_type; | ||
550 | ieee80211_set_channel_type(local, NULL, NL80211_CHAN_NO_HT); | ||
551 | |||
545 | /* do after stop to avoid reconfiguring when we stop anyway */ | 552 | /* do after stop to avoid reconfiguring when we stop anyway */ |
546 | if (hw_reconf_flags) | 553 | if (hw_reconf_flags || (orig_ct != local->_oper_channel_type)) |
547 | ieee80211_hw_config(local, hw_reconf_flags); | 554 | ieee80211_hw_config(local, hw_reconf_flags); |
548 | 555 | ||
549 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | 556 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 09a27449f3fd..c155c0b69426 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -98,6 +98,41 @@ static void ieee80211_reconfig_filter(struct work_struct *work) | |||
98 | ieee80211_configure_filter(local); | 98 | ieee80211_configure_filter(local); |
99 | } | 99 | } |
100 | 100 | ||
101 | /* | ||
102 | * Returns true if we are logically configured to be on | ||
103 | * the operating channel AND the hardware-conf is currently | ||
104 | * configured on the operating channel. Compares channel-type | ||
105 | * as well. | ||
106 | */ | ||
107 | bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local) | ||
108 | { | ||
109 | struct ieee80211_channel *chan, *scan_chan; | ||
110 | enum nl80211_channel_type channel_type; | ||
111 | |||
112 | /* This logic needs to match logic in ieee80211_hw_config */ | ||
113 | if (local->scan_channel) { | ||
114 | chan = local->scan_channel; | ||
115 | channel_type = NL80211_CHAN_NO_HT; | ||
116 | } else if (local->tmp_channel) { | ||
117 | chan = scan_chan = local->tmp_channel; | ||
118 | channel_type = local->tmp_channel_type; | ||
119 | } else { | ||
120 | chan = local->oper_channel; | ||
121 | channel_type = local->_oper_channel_type; | ||
122 | } | ||
123 | |||
124 | if (chan != local->oper_channel || | ||
125 | channel_type != local->_oper_channel_type) | ||
126 | return false; | ||
127 | |||
128 | /* Check current hardware-config against oper_channel. */ | ||
129 | if ((local->oper_channel != local->hw.conf.channel) || | ||
130 | (local->_oper_channel_type != local->hw.conf.channel_type)) | ||
131 | return false; | ||
132 | |||
133 | return true; | ||
134 | } | ||
135 | |||
101 | int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | 136 | int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) |
102 | { | 137 | { |
103 | struct ieee80211_channel *chan, *scan_chan; | 138 | struct ieee80211_channel *chan, *scan_chan; |
@@ -110,21 +145,27 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | |||
110 | 145 | ||
111 | scan_chan = local->scan_channel; | 146 | scan_chan = local->scan_channel; |
112 | 147 | ||
148 | /* If this off-channel logic ever changes, ieee80211_on_oper_channel | ||
149 | * may need to change as well. | ||
150 | */ | ||
113 | offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; | 151 | offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; |
114 | if (scan_chan) { | 152 | if (scan_chan) { |
115 | chan = scan_chan; | 153 | chan = scan_chan; |
116 | channel_type = NL80211_CHAN_NO_HT; | 154 | channel_type = NL80211_CHAN_NO_HT; |
117 | local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL; | 155 | } else if (local->tmp_channel) { |
118 | } else if (local->tmp_channel && | ||
119 | local->oper_channel != local->tmp_channel) { | ||
120 | chan = scan_chan = local->tmp_channel; | 156 | chan = scan_chan = local->tmp_channel; |
121 | channel_type = local->tmp_channel_type; | 157 | channel_type = local->tmp_channel_type; |
122 | local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL; | ||
123 | } else { | 158 | } else { |
124 | chan = local->oper_channel; | 159 | chan = local->oper_channel; |
125 | channel_type = local->_oper_channel_type; | 160 | channel_type = local->_oper_channel_type; |
126 | local->hw.conf.flags &= ~IEEE80211_CONF_OFFCHANNEL; | ||
127 | } | 161 | } |
162 | |||
163 | if (chan != local->oper_channel || | ||
164 | channel_type != local->_oper_channel_type) | ||
165 | local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL; | ||
166 | else | ||
167 | local->hw.conf.flags &= ~IEEE80211_CONF_OFFCHANNEL; | ||
168 | |||
128 | offchannel_flag ^= local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; | 169 | offchannel_flag ^= local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; |
129 | 170 | ||
130 | if (offchannel_flag || chan != local->hw.conf.channel || | 171 | if (offchannel_flag || chan != local->hw.conf.channel || |
@@ -231,7 +272,7 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | |||
231 | 272 | ||
232 | if (changed & BSS_CHANGED_BEACON_ENABLED) { | 273 | if (changed & BSS_CHANGED_BEACON_ENABLED) { |
233 | if (local->quiescing || !ieee80211_sdata_running(sdata) || | 274 | if (local->quiescing || !ieee80211_sdata_running(sdata) || |
234 | test_bit(SCAN_SW_SCANNING, &local->scanning)) { | 275 | test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state)) { |
235 | sdata->vif.bss_conf.enable_beacon = false; | 276 | sdata->vif.bss_conf.enable_beacon = false; |
236 | } else { | 277 | } else { |
237 | /* | 278 | /* |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index dfa752e5520b..f77adf1a520e 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -28,8 +28,15 @@ | |||
28 | #include "rate.h" | 28 | #include "rate.h" |
29 | #include "led.h" | 29 | #include "led.h" |
30 | 30 | ||
31 | #define IEEE80211_MAX_NULLFUNC_TRIES 2 | 31 | static int max_nullfunc_tries = 2; |
32 | #define IEEE80211_MAX_PROBE_TRIES 5 | 32 | module_param(max_nullfunc_tries, int, 0644); |
33 | MODULE_PARM_DESC(max_nullfunc_tries, | ||
34 | "Maximum nullfunc tx tries before disconnecting (reason 4)."); | ||
35 | |||
36 | static int max_probe_tries = 5; | ||
37 | module_param(max_probe_tries, int, 0644); | ||
38 | MODULE_PARM_DESC(max_probe_tries, | ||
39 | "Maximum probe tries before disconnecting (reason 4)."); | ||
33 | 40 | ||
34 | /* | 41 | /* |
35 | * Beacon loss timeout is calculated as N frames times the | 42 | * Beacon loss timeout is calculated as N frames times the |
@@ -51,7 +58,11 @@ | |||
51 | * a probe request because of beacon loss or for | 58 | * a probe request because of beacon loss or for |
52 | * checking the connection still works. | 59 | * checking the connection still works. |
53 | */ | 60 | */ |
54 | #define IEEE80211_PROBE_WAIT (HZ / 2) | 61 | static int probe_wait_ms = 500; |
62 | module_param(probe_wait_ms, int, 0644); | ||
63 | MODULE_PARM_DESC(probe_wait_ms, | ||
64 | "Maximum time(ms) to wait for probe response" | ||
65 | " before disconnecting (reason 4)."); | ||
55 | 66 | ||
56 | /* | 67 | /* |
57 | * Weight given to the latest Beacon frame when calculating average signal | 68 | * Weight given to the latest Beacon frame when calculating average signal |
@@ -161,6 +172,7 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | |||
161 | struct ieee80211_supported_band *sband; | 172 | struct ieee80211_supported_band *sband; |
162 | struct sta_info *sta; | 173 | struct sta_info *sta; |
163 | u32 changed = 0; | 174 | u32 changed = 0; |
175 | int hti_cfreq; | ||
164 | u16 ht_opmode; | 176 | u16 ht_opmode; |
165 | bool enable_ht = true; | 177 | bool enable_ht = true; |
166 | enum nl80211_channel_type prev_chantype; | 178 | enum nl80211_channel_type prev_chantype; |
@@ -174,10 +186,27 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | |||
174 | if (!sband->ht_cap.ht_supported) | 186 | if (!sband->ht_cap.ht_supported) |
175 | enable_ht = false; | 187 | enable_ht = false; |
176 | 188 | ||
177 | /* check that channel matches the right operating channel */ | 189 | if (enable_ht) { |
178 | if (local->hw.conf.channel->center_freq != | 190 | hti_cfreq = ieee80211_channel_to_frequency(hti->control_chan, |
179 | ieee80211_channel_to_frequency(hti->control_chan, sband->band)) | 191 | sband->band); |
180 | enable_ht = false; | 192 | /* check that channel matches the right operating channel */ |
193 | if (local->hw.conf.channel->center_freq != hti_cfreq) { | ||
194 | /* Some APs mess this up, evidently. | ||
195 | * Netgear WNDR3700 sometimes reports 4 higher than | ||
196 | * the actual channel, for instance. | ||
197 | */ | ||
198 | printk(KERN_DEBUG | ||
199 | "%s: Wrong control channel in association" | ||
200 | " response: configured center-freq: %d" | ||
201 | " hti-cfreq: %d hti->control_chan: %d" | ||
202 | " band: %d. Disabling HT.\n", | ||
203 | sdata->name, | ||
204 | local->hw.conf.channel->center_freq, | ||
205 | hti_cfreq, hti->control_chan, | ||
206 | sband->band); | ||
207 | enable_ht = false; | ||
208 | } | ||
209 | } | ||
181 | 210 | ||
182 | if (enable_ht) { | 211 | if (enable_ht) { |
183 | channel_type = NL80211_CHAN_HT20; | 212 | channel_type = NL80211_CHAN_HT20; |
@@ -1098,7 +1127,7 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) | |||
1098 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 1127 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
1099 | const u8 *ssid; | 1128 | const u8 *ssid; |
1100 | u8 *dst = ifmgd->associated->bssid; | 1129 | u8 *dst = ifmgd->associated->bssid; |
1101 | u8 unicast_limit = max(1, IEEE80211_MAX_PROBE_TRIES - 3); | 1130 | u8 unicast_limit = max(1, max_probe_tries - 3); |
1102 | 1131 | ||
1103 | /* | 1132 | /* |
1104 | * Try sending broadcast probe requests for the last three | 1133 | * Try sending broadcast probe requests for the last three |
@@ -1124,7 +1153,7 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) | |||
1124 | } | 1153 | } |
1125 | 1154 | ||
1126 | ifmgd->probe_send_count++; | 1155 | ifmgd->probe_send_count++; |
1127 | ifmgd->probe_timeout = jiffies + IEEE80211_PROBE_WAIT; | 1156 | ifmgd->probe_timeout = jiffies + msecs_to_jiffies(probe_wait_ms); |
1128 | run_again(ifmgd, ifmgd->probe_timeout); | 1157 | run_again(ifmgd, ifmgd->probe_timeout); |
1129 | } | 1158 | } |
1130 | 1159 | ||
@@ -1225,7 +1254,8 @@ static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata) | |||
1225 | 1254 | ||
1226 | memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN); | 1255 | memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN); |
1227 | 1256 | ||
1228 | printk(KERN_DEBUG "Connection to AP %pM lost.\n", bssid); | 1257 | printk(KERN_DEBUG "%s: Connection to AP %pM lost.\n", |
1258 | sdata->name, bssid); | ||
1229 | 1259 | ||
1230 | ieee80211_set_disassoc(sdata, true, true); | 1260 | ieee80211_set_disassoc(sdata, true, true); |
1231 | mutex_unlock(&ifmgd->mtx); | 1261 | mutex_unlock(&ifmgd->mtx); |
@@ -1970,9 +2000,9 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) | |||
1970 | memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN); | 2000 | memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN); |
1971 | 2001 | ||
1972 | if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) | 2002 | if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) |
1973 | max_tries = IEEE80211_MAX_NULLFUNC_TRIES; | 2003 | max_tries = max_nullfunc_tries; |
1974 | else | 2004 | else |
1975 | max_tries = IEEE80211_MAX_PROBE_TRIES; | 2005 | max_tries = max_probe_tries; |
1976 | 2006 | ||
1977 | /* ACK received for nullfunc probing frame */ | 2007 | /* ACK received for nullfunc probing frame */ |
1978 | if (!ifmgd->probe_send_count) | 2008 | if (!ifmgd->probe_send_count) |
@@ -2004,7 +2034,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) | |||
2004 | "%s: Failed to send nullfunc to AP %pM" | 2034 | "%s: Failed to send nullfunc to AP %pM" |
2005 | " after %dms, disconnecting.\n", | 2035 | " after %dms, disconnecting.\n", |
2006 | sdata->name, | 2036 | sdata->name, |
2007 | bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); | 2037 | bssid, probe_wait_ms); |
2008 | #endif | 2038 | #endif |
2009 | ieee80211_sta_connection_lost(sdata, bssid); | 2039 | ieee80211_sta_connection_lost(sdata, bssid); |
2010 | } else if (ifmgd->probe_send_count < max_tries) { | 2040 | } else if (ifmgd->probe_send_count < max_tries) { |
@@ -2013,7 +2043,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) | |||
2013 | "%s: No probe response from AP %pM" | 2043 | "%s: No probe response from AP %pM" |
2014 | " after %dms, try %d/%i\n", | 2044 | " after %dms, try %d/%i\n", |
2015 | sdata->name, | 2045 | sdata->name, |
2016 | bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ, | 2046 | bssid, probe_wait_ms, |
2017 | ifmgd->probe_send_count, max_tries); | 2047 | ifmgd->probe_send_count, max_tries); |
2018 | #endif | 2048 | #endif |
2019 | ieee80211_mgd_probe_ap_send(sdata); | 2049 | ieee80211_mgd_probe_ap_send(sdata); |
@@ -2026,7 +2056,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) | |||
2026 | "%s: No probe response from AP %pM" | 2056 | "%s: No probe response from AP %pM" |
2027 | " after %dms, disconnecting.\n", | 2057 | " after %dms, disconnecting.\n", |
2028 | sdata->name, | 2058 | sdata->name, |
2029 | bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); | 2059 | bssid, probe_wait_ms); |
2030 | 2060 | ||
2031 | ieee80211_sta_connection_lost(sdata, bssid); | 2061 | ieee80211_sta_connection_lost(sdata, bssid); |
2032 | } | 2062 | } |
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index b4e52676f3fb..13427b194ced 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c | |||
@@ -17,10 +17,14 @@ | |||
17 | #include "driver-trace.h" | 17 | #include "driver-trace.h" |
18 | 18 | ||
19 | /* | 19 | /* |
20 | * inform AP that we will go to sleep so that it will buffer the frames | 20 | * Tell our hardware to disable PS. |
21 | * while we scan | 21 | * Optionally inform AP that we will go to sleep so that it will buffer |
22 | * the frames while we are doing off-channel work. This is optional | ||
23 | * because we *may* be doing work on-operating channel, and want our | ||
24 | * hardware unconditionally awake, but still let the AP send us normal frames. | ||
22 | */ | 25 | */ |
23 | static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata) | 26 | static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata, |
27 | bool tell_ap) | ||
24 | { | 28 | { |
25 | struct ieee80211_local *local = sdata->local; | 29 | struct ieee80211_local *local = sdata->local; |
26 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 30 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
@@ -41,8 +45,8 @@ static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata) | |||
41 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); | 45 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); |
42 | } | 46 | } |
43 | 47 | ||
44 | if (!(local->offchannel_ps_enabled) || | 48 | if (tell_ap && (!local->offchannel_ps_enabled || |
45 | !(local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)) | 49 | !(local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK))) |
46 | /* | 50 | /* |
47 | * If power save was enabled, no need to send a nullfunc | 51 | * If power save was enabled, no need to send a nullfunc |
48 | * frame because AP knows that we are sleeping. But if the | 52 | * frame because AP knows that we are sleeping. But if the |
@@ -77,6 +81,9 @@ static void ieee80211_offchannel_ps_disable(struct ieee80211_sub_if_data *sdata) | |||
77 | * we are sleeping, let's just enable power save mode in | 81 | * we are sleeping, let's just enable power save mode in |
78 | * hardware. | 82 | * hardware. |
79 | */ | 83 | */ |
84 | /* TODO: Only set hardware if CONF_PS changed? | ||
85 | * TODO: Should we set offchannel_ps_enabled to false? | ||
86 | */ | ||
80 | local->hw.conf.flags |= IEEE80211_CONF_PS; | 87 | local->hw.conf.flags |= IEEE80211_CONF_PS; |
81 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); | 88 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); |
82 | } else if (local->hw.conf.dynamic_ps_timeout > 0) { | 89 | } else if (local->hw.conf.dynamic_ps_timeout > 0) { |
@@ -95,63 +102,61 @@ static void ieee80211_offchannel_ps_disable(struct ieee80211_sub_if_data *sdata) | |||
95 | ieee80211_sta_reset_conn_monitor(sdata); | 102 | ieee80211_sta_reset_conn_monitor(sdata); |
96 | } | 103 | } |
97 | 104 | ||
98 | void ieee80211_offchannel_stop_beaconing(struct ieee80211_local *local) | 105 | void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local, |
106 | bool offchannel_ps_enable) | ||
99 | { | 107 | { |
100 | struct ieee80211_sub_if_data *sdata; | 108 | struct ieee80211_sub_if_data *sdata; |
101 | 109 | ||
110 | /* | ||
111 | * notify the AP about us leaving the channel and stop all | ||
112 | * STA interfaces. | ||
113 | */ | ||
102 | mutex_lock(&local->iflist_mtx); | 114 | mutex_lock(&local->iflist_mtx); |
103 | list_for_each_entry(sdata, &local->interfaces, list) { | 115 | list_for_each_entry(sdata, &local->interfaces, list) { |
104 | if (!ieee80211_sdata_running(sdata)) | 116 | if (!ieee80211_sdata_running(sdata)) |
105 | continue; | 117 | continue; |
106 | 118 | ||
107 | /* disable beaconing */ | 119 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR) |
120 | set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state); | ||
121 | |||
122 | /* Check to see if we should disable beaconing. */ | ||
108 | if (sdata->vif.type == NL80211_IFTYPE_AP || | 123 | if (sdata->vif.type == NL80211_IFTYPE_AP || |
109 | sdata->vif.type == NL80211_IFTYPE_ADHOC || | 124 | sdata->vif.type == NL80211_IFTYPE_ADHOC || |
110 | sdata->vif.type == NL80211_IFTYPE_MESH_POINT) | 125 | sdata->vif.type == NL80211_IFTYPE_MESH_POINT) |
111 | ieee80211_bss_info_change_notify( | 126 | ieee80211_bss_info_change_notify( |
112 | sdata, BSS_CHANGED_BEACON_ENABLED); | 127 | sdata, BSS_CHANGED_BEACON_ENABLED); |
113 | 128 | ||
114 | /* | 129 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR) { |
115 | * only handle non-STA interfaces here, STA interfaces | ||
116 | * are handled in ieee80211_offchannel_stop_station(), | ||
117 | * e.g., from the background scan state machine. | ||
118 | * | ||
119 | * In addition, do not stop monitor interface to allow it to be | ||
120 | * used from user space controlled off-channel operations. | ||
121 | */ | ||
122 | if (sdata->vif.type != NL80211_IFTYPE_STATION && | ||
123 | sdata->vif.type != NL80211_IFTYPE_MONITOR) { | ||
124 | set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state); | ||
125 | netif_tx_stop_all_queues(sdata->dev); | 130 | netif_tx_stop_all_queues(sdata->dev); |
131 | if (offchannel_ps_enable && | ||
132 | (sdata->vif.type == NL80211_IFTYPE_STATION) && | ||
133 | sdata->u.mgd.associated) | ||
134 | ieee80211_offchannel_ps_enable(sdata, true); | ||
126 | } | 135 | } |
127 | } | 136 | } |
128 | mutex_unlock(&local->iflist_mtx); | 137 | mutex_unlock(&local->iflist_mtx); |
129 | } | 138 | } |
130 | 139 | ||
131 | void ieee80211_offchannel_stop_station(struct ieee80211_local *local) | 140 | void ieee80211_offchannel_enable_all_ps(struct ieee80211_local *local, |
141 | bool tell_ap) | ||
132 | { | 142 | { |
133 | struct ieee80211_sub_if_data *sdata; | 143 | struct ieee80211_sub_if_data *sdata; |
134 | 144 | ||
135 | /* | ||
136 | * notify the AP about us leaving the channel and stop all STA interfaces | ||
137 | */ | ||
138 | mutex_lock(&local->iflist_mtx); | 145 | mutex_lock(&local->iflist_mtx); |
139 | list_for_each_entry(sdata, &local->interfaces, list) { | 146 | list_for_each_entry(sdata, &local->interfaces, list) { |
140 | if (!ieee80211_sdata_running(sdata)) | 147 | if (!ieee80211_sdata_running(sdata)) |
141 | continue; | 148 | continue; |
142 | 149 | ||
143 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | 150 | if (sdata->vif.type == NL80211_IFTYPE_STATION && |
144 | set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state); | 151 | sdata->u.mgd.associated) |
145 | netif_tx_stop_all_queues(sdata->dev); | 152 | ieee80211_offchannel_ps_enable(sdata, tell_ap); |
146 | if (sdata->u.mgd.associated) | ||
147 | ieee80211_offchannel_ps_enable(sdata); | ||
148 | } | ||
149 | } | 153 | } |
150 | mutex_unlock(&local->iflist_mtx); | 154 | mutex_unlock(&local->iflist_mtx); |
151 | } | 155 | } |
152 | 156 | ||
153 | void ieee80211_offchannel_return(struct ieee80211_local *local, | 157 | void ieee80211_offchannel_return(struct ieee80211_local *local, |
154 | bool enable_beaconing) | 158 | bool enable_beaconing, |
159 | bool offchannel_ps_disable) | ||
155 | { | 160 | { |
156 | struct ieee80211_sub_if_data *sdata; | 161 | struct ieee80211_sub_if_data *sdata; |
157 | 162 | ||
@@ -161,7 +166,8 @@ void ieee80211_offchannel_return(struct ieee80211_local *local, | |||
161 | continue; | 166 | continue; |
162 | 167 | ||
163 | /* Tell AP we're back */ | 168 | /* Tell AP we're back */ |
164 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | 169 | if (offchannel_ps_disable && |
170 | sdata->vif.type == NL80211_IFTYPE_STATION) { | ||
165 | if (sdata->u.mgd.associated) | 171 | if (sdata->u.mgd.associated) |
166 | ieee80211_offchannel_ps_disable(sdata); | 172 | ieee80211_offchannel_ps_disable(sdata); |
167 | } | 173 | } |
@@ -181,7 +187,7 @@ void ieee80211_offchannel_return(struct ieee80211_local *local, | |||
181 | netif_tx_wake_all_queues(sdata->dev); | 187 | netif_tx_wake_all_queues(sdata->dev); |
182 | } | 188 | } |
183 | 189 | ||
184 | /* re-enable beaconing */ | 190 | /* Check to see if we should re-enable beaconing */ |
185 | if (enable_beaconing && | 191 | if (enable_beaconing && |
186 | (sdata->vif.type == NL80211_IFTYPE_AP || | 192 | (sdata->vif.type == NL80211_IFTYPE_AP || |
187 | sdata->vif.type == NL80211_IFTYPE_ADHOC || | 193 | sdata->vif.type == NL80211_IFTYPE_ADHOC || |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 7185c9316be2..045b2fe4a414 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -142,11 +142,8 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
142 | /* IEEE80211_RADIOTAP_RATE */ | 142 | /* IEEE80211_RADIOTAP_RATE */ |
143 | if (status->flag & RX_FLAG_HT) { | 143 | if (status->flag & RX_FLAG_HT) { |
144 | /* | 144 | /* |
145 | * TODO: add following information into radiotap header once | 145 | * MCS information is a separate field in radiotap, |
146 | * suitable fields are defined for it: | 146 | * added below. |
147 | * - MCS index (status->rate_idx) | ||
148 | * - HT40 (status->flag & RX_FLAG_40MHZ) | ||
149 | * - short-GI (status->flag & RX_FLAG_SHORT_GI) | ||
150 | */ | 147 | */ |
151 | *pos = 0; | 148 | *pos = 0; |
152 | } else { | 149 | } else { |
@@ -409,16 +406,10 @@ ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx) | |||
409 | if (likely(!(status->rx_flags & IEEE80211_RX_IN_SCAN))) | 406 | if (likely(!(status->rx_flags & IEEE80211_RX_IN_SCAN))) |
410 | return RX_CONTINUE; | 407 | return RX_CONTINUE; |
411 | 408 | ||
412 | if (test_bit(SCAN_HW_SCANNING, &local->scanning)) | 409 | if (test_bit(SCAN_HW_SCANNING, &local->scanning) || |
410 | test_bit(SCAN_SW_SCANNING, &local->scanning)) | ||
413 | return ieee80211_scan_rx(rx->sdata, skb); | 411 | return ieee80211_scan_rx(rx->sdata, skb); |
414 | 412 | ||
415 | if (test_bit(SCAN_SW_SCANNING, &local->scanning)) { | ||
416 | /* drop all the other packets during a software scan anyway */ | ||
417 | if (ieee80211_scan_rx(rx->sdata, skb) != RX_QUEUED) | ||
418 | dev_kfree_skb(skb); | ||
419 | return RX_QUEUED; | ||
420 | } | ||
421 | |||
422 | /* scanning finished during invoking of handlers */ | 413 | /* scanning finished during invoking of handlers */ |
423 | I802_DEBUG_INC(local->rx_handlers_drop_passive_scan); | 414 | I802_DEBUG_INC(local->rx_handlers_drop_passive_scan); |
424 | return RX_DROP_UNUSABLE; | 415 | return RX_DROP_UNUSABLE; |
@@ -815,7 +806,7 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx) | |||
815 | rx->local->dot11FrameDuplicateCount++; | 806 | rx->local->dot11FrameDuplicateCount++; |
816 | rx->sta->num_duplicates++; | 807 | rx->sta->num_duplicates++; |
817 | } | 808 | } |
818 | return RX_DROP_MONITOR; | 809 | return RX_DROP_UNUSABLE; |
819 | } else | 810 | } else |
820 | rx->sta->last_seq_ctrl[rx->queue] = hdr->seq_ctrl; | 811 | rx->sta->last_seq_ctrl[rx->queue] = hdr->seq_ctrl; |
821 | } | 812 | } |
@@ -1105,7 +1096,8 @@ static void ap_sta_ps_start(struct sta_info *sta) | |||
1105 | 1096 | ||
1106 | atomic_inc(&sdata->bss->num_sta_ps); | 1097 | atomic_inc(&sdata->bss->num_sta_ps); |
1107 | set_sta_flags(sta, WLAN_STA_PS_STA); | 1098 | set_sta_flags(sta, WLAN_STA_PS_STA); |
1108 | drv_sta_notify(local, sdata, STA_NOTIFY_SLEEP, &sta->sta); | 1099 | if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS)) |
1100 | drv_sta_notify(local, sdata, STA_NOTIFY_SLEEP, &sta->sta); | ||
1109 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 1101 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
1110 | printk(KERN_DEBUG "%s: STA %pM aid %d enters power save mode\n", | 1102 | printk(KERN_DEBUG "%s: STA %pM aid %d enters power save mode\n", |
1111 | sdata->name, sta->sta.addr, sta->sta.aid); | 1103 | sdata->name, sta->sta.addr, sta->sta.aid); |
@@ -1134,6 +1126,27 @@ static void ap_sta_ps_end(struct sta_info *sta) | |||
1134 | ieee80211_sta_ps_deliver_wakeup(sta); | 1126 | ieee80211_sta_ps_deliver_wakeup(sta); |
1135 | } | 1127 | } |
1136 | 1128 | ||
1129 | int ieee80211_sta_ps_transition(struct ieee80211_sta *sta, bool start) | ||
1130 | { | ||
1131 | struct sta_info *sta_inf = container_of(sta, struct sta_info, sta); | ||
1132 | bool in_ps; | ||
1133 | |||
1134 | WARN_ON(!(sta_inf->local->hw.flags & IEEE80211_HW_AP_LINK_PS)); | ||
1135 | |||
1136 | /* Don't let the same PS state be set twice */ | ||
1137 | in_ps = test_sta_flags(sta_inf, WLAN_STA_PS_STA); | ||
1138 | if ((start && in_ps) || (!start && !in_ps)) | ||
1139 | return -EINVAL; | ||
1140 | |||
1141 | if (start) | ||
1142 | ap_sta_ps_start(sta_inf); | ||
1143 | else | ||
1144 | ap_sta_ps_end(sta_inf); | ||
1145 | |||
1146 | return 0; | ||
1147 | } | ||
1148 | EXPORT_SYMBOL(ieee80211_sta_ps_transition); | ||
1149 | |||
1137 | static ieee80211_rx_result debug_noinline | 1150 | static ieee80211_rx_result debug_noinline |
1138 | ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | 1151 | ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) |
1139 | { | 1152 | { |
@@ -1178,7 +1191,8 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | |||
1178 | * Change STA power saving mode only at the end of a frame | 1191 | * Change STA power saving mode only at the end of a frame |
1179 | * exchange sequence. | 1192 | * exchange sequence. |
1180 | */ | 1193 | */ |
1181 | if (!ieee80211_has_morefrags(hdr->frame_control) && | 1194 | if (!(sta->local->hw.flags & IEEE80211_HW_AP_LINK_PS) && |
1195 | !ieee80211_has_morefrags(hdr->frame_control) && | ||
1182 | !(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) && | 1196 | !(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) && |
1183 | (rx->sdata->vif.type == NL80211_IFTYPE_AP || | 1197 | (rx->sdata->vif.type == NL80211_IFTYPE_AP || |
1184 | rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) { | 1198 | rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) { |
@@ -1929,7 +1943,10 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx) | |||
1929 | dev->stats.rx_bytes += rx->skb->len; | 1943 | dev->stats.rx_bytes += rx->skb->len; |
1930 | 1944 | ||
1931 | if (local->ps_sdata && local->hw.conf.dynamic_ps_timeout > 0 && | 1945 | if (local->ps_sdata && local->hw.conf.dynamic_ps_timeout > 0 && |
1932 | !is_multicast_ether_addr(((struct ethhdr *)rx->skb->data)->h_dest)) { | 1946 | !is_multicast_ether_addr( |
1947 | ((struct ethhdr *)rx->skb->data)->h_dest) && | ||
1948 | (!local->scanning && | ||
1949 | !test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state))) { | ||
1933 | mod_timer(&local->dynamic_ps_timer, jiffies + | 1950 | mod_timer(&local->dynamic_ps_timer, jiffies + |
1934 | msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout)); | 1951 | msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout)); |
1935 | } | 1952 | } |
@@ -2626,7 +2643,8 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx, | |||
2626 | return 0; | 2643 | return 0; |
2627 | if (!multicast && | 2644 | if (!multicast && |
2628 | compare_ether_addr(sdata->vif.addr, hdr->addr1) != 0) { | 2645 | compare_ether_addr(sdata->vif.addr, hdr->addr1) != 0) { |
2629 | if (!(sdata->dev->flags & IFF_PROMISC)) | 2646 | if (!(sdata->dev->flags & IFF_PROMISC) || |
2647 | sdata->u.mgd.use_4addr) | ||
2630 | return 0; | 2648 | return 0; |
2631 | status->rx_flags &= ~IEEE80211_RX_RA_MATCH; | 2649 | status->rx_flags &= ~IEEE80211_RX_RA_MATCH; |
2632 | } | 2650 | } |
@@ -2675,7 +2693,8 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx, | |||
2675 | return 0; | 2693 | return 0; |
2676 | } else if (!ieee80211_bssid_match(bssid, | 2694 | } else if (!ieee80211_bssid_match(bssid, |
2677 | sdata->vif.addr)) { | 2695 | sdata->vif.addr)) { |
2678 | if (!(status->rx_flags & IEEE80211_RX_IN_SCAN)) | 2696 | if (!(status->rx_flags & IEEE80211_RX_IN_SCAN) && |
2697 | !ieee80211_is_beacon(hdr->frame_control)) | ||
2679 | return 0; | 2698 | return 0; |
2680 | status->rx_flags &= ~IEEE80211_RX_RA_MATCH; | 2699 | status->rx_flags &= ~IEEE80211_RX_RA_MATCH; |
2681 | } | 2700 | } |
@@ -2766,7 +2785,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
2766 | local->dot11ReceivedFragmentCount++; | 2785 | local->dot11ReceivedFragmentCount++; |
2767 | 2786 | ||
2768 | if (unlikely(test_bit(SCAN_HW_SCANNING, &local->scanning) || | 2787 | if (unlikely(test_bit(SCAN_HW_SCANNING, &local->scanning) || |
2769 | test_bit(SCAN_OFF_CHANNEL, &local->scanning))) | 2788 | test_bit(SCAN_SW_SCANNING, &local->scanning))) |
2770 | status->rx_flags |= IEEE80211_RX_IN_SCAN; | 2789 | status->rx_flags |= IEEE80211_RX_IN_SCAN; |
2771 | 2790 | ||
2772 | if (ieee80211_is_mgmt(fc)) | 2791 | if (ieee80211_is_mgmt(fc)) |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 1ef73be76b25..0ea6adae3e06 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -212,6 +212,14 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) | |||
212 | if (bss) | 212 | if (bss) |
213 | ieee80211_rx_bss_put(sdata->local, bss); | 213 | ieee80211_rx_bss_put(sdata->local, bss); |
214 | 214 | ||
215 | /* If we are on-operating-channel, and this packet is for the | ||
216 | * current channel, pass the pkt on up the stack so that | ||
217 | * the rest of the stack can make use of it. | ||
218 | */ | ||
219 | if (ieee80211_cfg_on_oper_channel(sdata->local) | ||
220 | && (channel == sdata->local->oper_channel)) | ||
221 | return RX_CONTINUE; | ||
222 | |||
215 | dev_kfree_skb(skb); | 223 | dev_kfree_skb(skb); |
216 | return RX_QUEUED; | 224 | return RX_QUEUED; |
217 | } | 225 | } |
@@ -293,15 +301,31 @@ static void __ieee80211_scan_completed_finish(struct ieee80211_hw *hw, | |||
293 | bool was_hw_scan) | 301 | bool was_hw_scan) |
294 | { | 302 | { |
295 | struct ieee80211_local *local = hw_to_local(hw); | 303 | struct ieee80211_local *local = hw_to_local(hw); |
304 | bool on_oper_chan; | ||
305 | bool enable_beacons = false; | ||
306 | |||
307 | mutex_lock(&local->mtx); | ||
308 | on_oper_chan = ieee80211_cfg_on_oper_channel(local); | ||
309 | |||
310 | if (was_hw_scan || !on_oper_chan) { | ||
311 | if (WARN_ON(local->scan_channel)) | ||
312 | local->scan_channel = NULL; | ||
313 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | ||
314 | } | ||
296 | 315 | ||
297 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | ||
298 | if (!was_hw_scan) { | 316 | if (!was_hw_scan) { |
317 | bool on_oper_chan2; | ||
299 | ieee80211_configure_filter(local); | 318 | ieee80211_configure_filter(local); |
300 | drv_sw_scan_complete(local); | 319 | drv_sw_scan_complete(local); |
301 | ieee80211_offchannel_return(local, true); | 320 | on_oper_chan2 = ieee80211_cfg_on_oper_channel(local); |
321 | /* We should always be on-channel at this point. */ | ||
322 | WARN_ON(!on_oper_chan2); | ||
323 | if (on_oper_chan2 && (on_oper_chan != on_oper_chan2)) | ||
324 | enable_beacons = true; | ||
325 | |||
326 | ieee80211_offchannel_return(local, enable_beacons, true); | ||
302 | } | 327 | } |
303 | 328 | ||
304 | mutex_lock(&local->mtx); | ||
305 | ieee80211_recalc_idle(local); | 329 | ieee80211_recalc_idle(local); |
306 | mutex_unlock(&local->mtx); | 330 | mutex_unlock(&local->mtx); |
307 | 331 | ||
@@ -341,13 +365,15 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local) | |||
341 | */ | 365 | */ |
342 | drv_sw_scan_start(local); | 366 | drv_sw_scan_start(local); |
343 | 367 | ||
344 | ieee80211_offchannel_stop_beaconing(local); | ||
345 | |||
346 | local->leave_oper_channel_time = 0; | 368 | local->leave_oper_channel_time = 0; |
347 | local->next_scan_state = SCAN_DECISION; | 369 | local->next_scan_state = SCAN_DECISION; |
348 | local->scan_channel_idx = 0; | 370 | local->scan_channel_idx = 0; |
349 | 371 | ||
350 | drv_flush(local, false); | 372 | /* We always want to use off-channel PS, even if we |
373 | * are not really leaving oper-channel. Don't | ||
374 | * tell the AP though, as long as we are on-channel. | ||
375 | */ | ||
376 | ieee80211_offchannel_enable_all_ps(local, false); | ||
351 | 377 | ||
352 | ieee80211_configure_filter(local); | 378 | ieee80211_configure_filter(local); |
353 | 379 | ||
@@ -487,7 +513,21 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local, | |||
487 | } | 513 | } |
488 | mutex_unlock(&local->iflist_mtx); | 514 | mutex_unlock(&local->iflist_mtx); |
489 | 515 | ||
490 | if (local->scan_channel) { | 516 | next_chan = local->scan_req->channels[local->scan_channel_idx]; |
517 | |||
518 | if (ieee80211_cfg_on_oper_channel(local)) { | ||
519 | /* We're currently on operating channel. */ | ||
520 | if ((next_chan == local->oper_channel) && | ||
521 | (local->_oper_channel_type == NL80211_CHAN_NO_HT)) | ||
522 | /* We don't need to move off of operating channel. */ | ||
523 | local->next_scan_state = SCAN_SET_CHANNEL; | ||
524 | else | ||
525 | /* | ||
526 | * We do need to leave operating channel, as next | ||
527 | * scan is somewhere else. | ||
528 | */ | ||
529 | local->next_scan_state = SCAN_LEAVE_OPER_CHANNEL; | ||
530 | } else { | ||
491 | /* | 531 | /* |
492 | * we're currently scanning a different channel, let's | 532 | * we're currently scanning a different channel, let's |
493 | * see if we can scan another channel without interfering | 533 | * see if we can scan another channel without interfering |
@@ -503,7 +543,6 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local, | |||
503 | * | 543 | * |
504 | * Otherwise switch back to the operating channel. | 544 | * Otherwise switch back to the operating channel. |
505 | */ | 545 | */ |
506 | next_chan = local->scan_req->channels[local->scan_channel_idx]; | ||
507 | 546 | ||
508 | bad_latency = time_after(jiffies + | 547 | bad_latency = time_after(jiffies + |
509 | ieee80211_scan_get_channel_time(next_chan), | 548 | ieee80211_scan_get_channel_time(next_chan), |
@@ -521,12 +560,6 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local, | |||
521 | local->next_scan_state = SCAN_ENTER_OPER_CHANNEL; | 560 | local->next_scan_state = SCAN_ENTER_OPER_CHANNEL; |
522 | else | 561 | else |
523 | local->next_scan_state = SCAN_SET_CHANNEL; | 562 | local->next_scan_state = SCAN_SET_CHANNEL; |
524 | } else { | ||
525 | /* | ||
526 | * we're on the operating channel currently, let's | ||
527 | * leave that channel now to scan another one | ||
528 | */ | ||
529 | local->next_scan_state = SCAN_LEAVE_OPER_CHANNEL; | ||
530 | } | 563 | } |
531 | 564 | ||
532 | *next_delay = 0; | 565 | *next_delay = 0; |
@@ -535,9 +568,10 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local, | |||
535 | static void ieee80211_scan_state_leave_oper_channel(struct ieee80211_local *local, | 568 | static void ieee80211_scan_state_leave_oper_channel(struct ieee80211_local *local, |
536 | unsigned long *next_delay) | 569 | unsigned long *next_delay) |
537 | { | 570 | { |
538 | ieee80211_offchannel_stop_station(local); | 571 | /* PS will already be in off-channel mode, |
539 | 572 | * we do that once at the beginning of scanning. | |
540 | __set_bit(SCAN_OFF_CHANNEL, &local->scanning); | 573 | */ |
574 | ieee80211_offchannel_stop_vifs(local, false); | ||
541 | 575 | ||
542 | /* | 576 | /* |
543 | * What if the nullfunc frames didn't arrive? | 577 | * What if the nullfunc frames didn't arrive? |
@@ -560,15 +594,15 @@ static void ieee80211_scan_state_enter_oper_channel(struct ieee80211_local *loca | |||
560 | { | 594 | { |
561 | /* switch back to the operating channel */ | 595 | /* switch back to the operating channel */ |
562 | local->scan_channel = NULL; | 596 | local->scan_channel = NULL; |
563 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | 597 | if (!ieee80211_cfg_on_oper_channel(local)) |
598 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | ||
564 | 599 | ||
565 | /* | 600 | /* |
566 | * Only re-enable station mode interface now; beaconing will be | 601 | * Re-enable vifs and beaconing. Leave PS |
567 | * re-enabled once the full scan has been completed. | 602 | * in off-channel state..will put that back |
603 | * on-channel at the end of scanning. | ||
568 | */ | 604 | */ |
569 | ieee80211_offchannel_return(local, false); | 605 | ieee80211_offchannel_return(local, true, false); |
570 | |||
571 | __clear_bit(SCAN_OFF_CHANNEL, &local->scanning); | ||
572 | 606 | ||
573 | *next_delay = HZ / 5; | 607 | *next_delay = HZ / 5; |
574 | local->next_scan_state = SCAN_DECISION; | 608 | local->next_scan_state = SCAN_DECISION; |
@@ -584,8 +618,12 @@ static void ieee80211_scan_state_set_channel(struct ieee80211_local *local, | |||
584 | chan = local->scan_req->channels[local->scan_channel_idx]; | 618 | chan = local->scan_req->channels[local->scan_channel_idx]; |
585 | 619 | ||
586 | local->scan_channel = chan; | 620 | local->scan_channel = chan; |
587 | if (ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL)) | 621 | |
588 | skip = 1; | 622 | /* Only call hw-config if we really need to change channels. */ |
623 | if ((chan != local->hw.conf.channel) || | ||
624 | (local->hw.conf.channel_type != NL80211_CHAN_NO_HT)) | ||
625 | if (ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL)) | ||
626 | skip = 1; | ||
589 | 627 | ||
590 | /* advance state machine to next channel/band */ | 628 | /* advance state machine to next channel/band */ |
591 | local->scan_channel_idx++; | 629 | local->scan_channel_idx++; |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index c426504ed1cf..5a11078827ab 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -899,7 +899,8 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) | |||
899 | struct ieee80211_local *local = sdata->local; | 899 | struct ieee80211_local *local = sdata->local; |
900 | int sent, buffered; | 900 | int sent, buffered; |
901 | 901 | ||
902 | drv_sta_notify(local, sdata, STA_NOTIFY_AWAKE, &sta->sta); | 902 | if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS)) |
903 | drv_sta_notify(local, sdata, STA_NOTIFY_AWAKE, &sta->sta); | ||
903 | 904 | ||
904 | if (!skb_queue_empty(&sta->ps_tx_buf)) | 905 | if (!skb_queue_empty(&sta->ps_tx_buf)) |
905 | sta_info_clear_tim_bit(sta); | 906 | sta_info_clear_tim_bit(sta); |
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 38a797217a91..ffb0de9bc2fa 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -98,6 +98,10 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, | |||
98 | * (b) always process RX events before TX status events if ordering | 98 | * (b) always process RX events before TX status events if ordering |
99 | * can be unknown, for example with different interrupt status | 99 | * can be unknown, for example with different interrupt status |
100 | * bits. | 100 | * bits. |
101 | * (c) if PS mode transitions are manual (i.e. the flag | ||
102 | * %IEEE80211_HW_AP_LINK_PS is set), always process PS state | ||
103 | * changes before calling TX status events if ordering can be | ||
104 | * unknown. | ||
101 | */ | 105 | */ |
102 | if (test_sta_flags(sta, WLAN_STA_PS_STA) && | 106 | if (test_sta_flags(sta, WLAN_STA_PS_STA) && |
103 | skb_queue_len(&sta->tx_filtered) < STA_MAX_TX_BUFFER) { | 107 | skb_queue_len(&sta->tx_filtered) < STA_MAX_TX_BUFFER) { |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index ffc67491c38f..38e593939727 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -257,7 +257,8 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) | |||
257 | if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED)) | 257 | if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED)) |
258 | return TX_CONTINUE; | 258 | return TX_CONTINUE; |
259 | 259 | ||
260 | if (unlikely(test_bit(SCAN_OFF_CHANNEL, &tx->local->scanning)) && | 260 | if (unlikely(test_bit(SCAN_SW_SCANNING, &tx->local->scanning)) && |
261 | test_bit(SDATA_STATE_OFFCHANNEL, &tx->sdata->state) && | ||
261 | !ieee80211_is_probe_req(hdr->frame_control) && | 262 | !ieee80211_is_probe_req(hdr->frame_control) && |
262 | !ieee80211_is_nullfunc(hdr->frame_control)) | 263 | !ieee80211_is_nullfunc(hdr->frame_control)) |
263 | /* | 264 | /* |
@@ -1394,7 +1395,8 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx) | |||
1394 | /* handlers after fragment must be aware of tx info fragmentation! */ | 1395 | /* handlers after fragment must be aware of tx info fragmentation! */ |
1395 | CALL_TXH(ieee80211_tx_h_stats); | 1396 | CALL_TXH(ieee80211_tx_h_stats); |
1396 | CALL_TXH(ieee80211_tx_h_encrypt); | 1397 | CALL_TXH(ieee80211_tx_h_encrypt); |
1397 | CALL_TXH(ieee80211_tx_h_calculate_duration); | 1398 | if (!(tx->local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL)) |
1399 | CALL_TXH(ieee80211_tx_h_calculate_duration); | ||
1398 | #undef CALL_TXH | 1400 | #undef CALL_TXH |
1399 | 1401 | ||
1400 | txh_done: | 1402 | txh_done: |
@@ -2178,6 +2180,8 @@ static void ieee80211_beacon_add_tim(struct ieee80211_if_ap *bss, | |||
2178 | if (bss->dtim_count == 0 && !skb_queue_empty(&bss->ps_bc_buf)) | 2180 | if (bss->dtim_count == 0 && !skb_queue_empty(&bss->ps_bc_buf)) |
2179 | aid0 = 1; | 2181 | aid0 = 1; |
2180 | 2182 | ||
2183 | bss->dtim_bc_mc = aid0 == 1; | ||
2184 | |||
2181 | if (have_bits) { | 2185 | if (have_bits) { |
2182 | /* Find largest even number N1 so that bits numbered 1 through | 2186 | /* Find largest even number N1 so that bits numbered 1 through |
2183 | * (N1 x 8) - 1 in the bitmap are 0 and number N2 so that bits | 2187 | * (N1 x 8) - 1 in the bitmap are 0 and number N2 so that bits |
@@ -2241,7 +2245,7 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2241 | if (sdata->vif.type == NL80211_IFTYPE_AP) { | 2245 | if (sdata->vif.type == NL80211_IFTYPE_AP) { |
2242 | ap = &sdata->u.ap; | 2246 | ap = &sdata->u.ap; |
2243 | beacon = rcu_dereference(ap->beacon); | 2247 | beacon = rcu_dereference(ap->beacon); |
2244 | if (ap && beacon) { | 2248 | if (beacon) { |
2245 | /* | 2249 | /* |
2246 | * headroom, head length, | 2250 | * headroom, head length, |
2247 | * tail length and maximum TIM length | 2251 | * tail length and maximum TIM length |
@@ -2548,7 +2552,7 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, | |||
2548 | if (sdata->vif.type != NL80211_IFTYPE_AP || !beacon || !beacon->head) | 2552 | if (sdata->vif.type != NL80211_IFTYPE_AP || !beacon || !beacon->head) |
2549 | goto out; | 2553 | goto out; |
2550 | 2554 | ||
2551 | if (bss->dtim_count != 0) | 2555 | if (bss->dtim_count != 0 || !bss->dtim_bc_mc) |
2552 | goto out; /* send buffered bc/mc only after DTIM beacon */ | 2556 | goto out; /* send buffered bc/mc only after DTIM beacon */ |
2553 | 2557 | ||
2554 | while (1) { | 2558 | while (1) { |
diff --git a/net/mac80211/work.c b/net/mac80211/work.c index 36305e0d06ef..6bf787a5b38a 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c | |||
@@ -924,18 +924,44 @@ static void ieee80211_work_work(struct work_struct *work) | |||
924 | } | 924 | } |
925 | 925 | ||
926 | if (!started && !local->tmp_channel) { | 926 | if (!started && !local->tmp_channel) { |
927 | /* | 927 | bool on_oper_chan; |
928 | * TODO: could optimize this by leaving the | 928 | bool tmp_chan_changed = false; |
929 | * station vifs in awake mode if they | 929 | bool on_oper_chan2; |
930 | * happen to be on the same channel as | 930 | on_oper_chan = ieee80211_cfg_on_oper_channel(local); |
931 | * the requested channel | 931 | if (local->tmp_channel) |
932 | */ | 932 | if ((local->tmp_channel != wk->chan) || |
933 | ieee80211_offchannel_stop_beaconing(local); | 933 | (local->tmp_channel_type != wk->chan_type)) |
934 | ieee80211_offchannel_stop_station(local); | 934 | tmp_chan_changed = true; |
935 | 935 | ||
936 | local->tmp_channel = wk->chan; | 936 | local->tmp_channel = wk->chan; |
937 | local->tmp_channel_type = wk->chan_type; | 937 | local->tmp_channel_type = wk->chan_type; |
938 | ieee80211_hw_config(local, 0); | 938 | /* |
939 | * Leave the station vifs in awake mode if they | ||
940 | * happen to be on the same channel as | ||
941 | * the requested channel. | ||
942 | */ | ||
943 | on_oper_chan2 = ieee80211_cfg_on_oper_channel(local); | ||
944 | if (on_oper_chan != on_oper_chan2) { | ||
945 | if (on_oper_chan2) { | ||
946 | /* going off oper channel, PS too */ | ||
947 | ieee80211_offchannel_stop_vifs(local, | ||
948 | true); | ||
949 | ieee80211_hw_config(local, 0); | ||
950 | } else { | ||
951 | /* going on channel, but leave PS | ||
952 | * off-channel. */ | ||
953 | ieee80211_hw_config(local, 0); | ||
954 | ieee80211_offchannel_return(local, | ||
955 | true, | ||
956 | false); | ||
957 | } | ||
958 | } else if (tmp_chan_changed) | ||
959 | /* Still off-channel, but on some other | ||
960 | * channel, so update hardware. | ||
961 | * PS should already be off-channel. | ||
962 | */ | ||
963 | ieee80211_hw_config(local, 0); | ||
964 | |||
939 | started = true; | 965 | started = true; |
940 | wk->timeout = jiffies; | 966 | wk->timeout = jiffies; |
941 | } | 967 | } |
@@ -1011,9 +1037,27 @@ static void ieee80211_work_work(struct work_struct *work) | |||
1011 | } | 1037 | } |
1012 | 1038 | ||
1013 | if (!remain_off_channel && local->tmp_channel) { | 1039 | if (!remain_off_channel && local->tmp_channel) { |
1040 | bool on_oper_chan = ieee80211_cfg_on_oper_channel(local); | ||
1014 | local->tmp_channel = NULL; | 1041 | local->tmp_channel = NULL; |
1015 | ieee80211_hw_config(local, 0); | 1042 | /* If tmp_channel wasn't operating channel, then |
1016 | ieee80211_offchannel_return(local, true); | 1043 | * we need to go back on-channel. |
1044 | * NOTE: If we can ever be here while scannning, | ||
1045 | * or if the hw_config() channel config logic changes, | ||
1046 | * then we may need to do a more thorough check to see if | ||
1047 | * we still need to do a hardware config. Currently, | ||
1048 | * we cannot be here while scanning, however. | ||
1049 | */ | ||
1050 | if (ieee80211_cfg_on_oper_channel(local) && !on_oper_chan) | ||
1051 | ieee80211_hw_config(local, 0); | ||
1052 | |||
1053 | /* At the least, we need to disable offchannel_ps, | ||
1054 | * so just go ahead and run the entire offchannel | ||
1055 | * return logic here. We *could* skip enabling | ||
1056 | * beaconing if we were already on-oper-channel | ||
1057 | * as a future optimization. | ||
1058 | */ | ||
1059 | ieee80211_offchannel_return(local, true, true); | ||
1060 | |||
1017 | /* give connection some time to breathe */ | 1061 | /* give connection some time to breathe */ |
1018 | run_again(local, jiffies + HZ/2); | 1062 | run_again(local, jiffies + HZ/2); |
1019 | } | 1063 | } |
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index bee230d8fd11..f1765de2f4bf 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c | |||
@@ -26,13 +26,12 @@ | |||
26 | ieee80211_tx_result | 26 | ieee80211_tx_result |
27 | ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) | 27 | ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) |
28 | { | 28 | { |
29 | u8 *data, *key, *mic, key_offset; | 29 | u8 *data, *key, *mic; |
30 | size_t data_len; | 30 | size_t data_len; |
31 | unsigned int hdrlen; | 31 | unsigned int hdrlen; |
32 | struct ieee80211_hdr *hdr; | 32 | struct ieee80211_hdr *hdr; |
33 | struct sk_buff *skb = tx->skb; | 33 | struct sk_buff *skb = tx->skb; |
34 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 34 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
35 | int authenticator; | ||
36 | int tail; | 35 | int tail; |
37 | 36 | ||
38 | hdr = (struct ieee80211_hdr *)skb->data; | 37 | hdr = (struct ieee80211_hdr *)skb->data; |
@@ -47,6 +46,11 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) | |||
47 | data = skb->data + hdrlen; | 46 | data = skb->data + hdrlen; |
48 | data_len = skb->len - hdrlen; | 47 | data_len = skb->len - hdrlen; |
49 | 48 | ||
49 | if (unlikely(info->flags & IEEE80211_TX_INTFL_TKIP_MIC_FAILURE)) { | ||
50 | /* Need to use software crypto for the test */ | ||
51 | info->control.hw_key = NULL; | ||
52 | } | ||
53 | |||
50 | if (info->control.hw_key && | 54 | if (info->control.hw_key && |
51 | !(tx->flags & IEEE80211_TX_FRAGMENTED) && | 55 | !(tx->flags & IEEE80211_TX_FRAGMENTED) && |
52 | !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) { | 56 | !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) { |
@@ -62,17 +66,11 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) | |||
62 | skb_headroom(skb) < TKIP_IV_LEN)) | 66 | skb_headroom(skb) < TKIP_IV_LEN)) |
63 | return TX_DROP; | 67 | return TX_DROP; |
64 | 68 | ||
65 | #if 0 | 69 | key = &tx->key->conf.key[NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY]; |
66 | authenticator = fc & IEEE80211_FCTL_FROMDS; /* FIX */ | ||
67 | #else | ||
68 | authenticator = 1; | ||
69 | #endif | ||
70 | key_offset = authenticator ? | ||
71 | NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY : | ||
72 | NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY; | ||
73 | key = &tx->key->conf.key[key_offset]; | ||
74 | mic = skb_put(skb, MICHAEL_MIC_LEN); | 70 | mic = skb_put(skb, MICHAEL_MIC_LEN); |
75 | michael_mic(key, hdr, data, data_len, mic); | 71 | michael_mic(key, hdr, data, data_len, mic); |
72 | if (unlikely(info->flags & IEEE80211_TX_INTFL_TKIP_MIC_FAILURE)) | ||
73 | mic[0]++; | ||
76 | 74 | ||
77 | return TX_CONTINUE; | 75 | return TX_CONTINUE; |
78 | } | 76 | } |
@@ -81,14 +79,13 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) | |||
81 | ieee80211_rx_result | 79 | ieee80211_rx_result |
82 | ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) | 80 | ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) |
83 | { | 81 | { |
84 | u8 *data, *key = NULL, key_offset; | 82 | u8 *data, *key = NULL; |
85 | size_t data_len; | 83 | size_t data_len; |
86 | unsigned int hdrlen; | 84 | unsigned int hdrlen; |
87 | u8 mic[MICHAEL_MIC_LEN]; | 85 | u8 mic[MICHAEL_MIC_LEN]; |
88 | struct sk_buff *skb = rx->skb; | 86 | struct sk_buff *skb = rx->skb; |
89 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | 87 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); |
90 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 88 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
91 | int authenticator = 1, wpa_test = 0; | ||
92 | 89 | ||
93 | /* No way to verify the MIC if the hardware stripped it */ | 90 | /* No way to verify the MIC if the hardware stripped it */ |
94 | if (status->flag & RX_FLAG_MMIC_STRIPPED) | 91 | if (status->flag & RX_FLAG_MMIC_STRIPPED) |
@@ -106,17 +103,9 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) | |||
106 | data = skb->data + hdrlen; | 103 | data = skb->data + hdrlen; |
107 | data_len = skb->len - hdrlen - MICHAEL_MIC_LEN; | 104 | data_len = skb->len - hdrlen - MICHAEL_MIC_LEN; |
108 | 105 | ||
109 | #if 0 | 106 | key = &rx->key->conf.key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY]; |
110 | authenticator = fc & IEEE80211_FCTL_TODS; /* FIX */ | ||
111 | #else | ||
112 | authenticator = 1; | ||
113 | #endif | ||
114 | key_offset = authenticator ? | ||
115 | NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY : | ||
116 | NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY; | ||
117 | key = &rx->key->conf.key[key_offset]; | ||
118 | michael_mic(key, hdr, data, data_len, mic); | 107 | michael_mic(key, hdr, data, data_len, mic); |
119 | if (memcmp(mic, data + data_len, MICHAEL_MIC_LEN) != 0 || wpa_test) { | 108 | if (memcmp(mic, data + data_len, MICHAEL_MIC_LEN) != 0) { |
120 | if (!(status->rx_flags & IEEE80211_RX_RA_MATCH)) | 109 | if (!(status->rx_flags & IEEE80211_RX_RA_MATCH)) |
121 | return RX_DROP_UNUSABLE; | 110 | return RX_DROP_UNUSABLE; |
122 | 111 | ||
@@ -208,7 +197,7 @@ ieee80211_rx_result | |||
208 | ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx) | 197 | ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx) |
209 | { | 198 | { |
210 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data; | 199 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data; |
211 | int hdrlen, res, hwaccel = 0, wpa_test = 0; | 200 | int hdrlen, res, hwaccel = 0; |
212 | struct ieee80211_key *key = rx->key; | 201 | struct ieee80211_key *key = rx->key; |
213 | struct sk_buff *skb = rx->skb; | 202 | struct sk_buff *skb = rx->skb; |
214 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | 203 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); |
@@ -235,7 +224,7 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx) | |||
235 | hdr->addr1, hwaccel, rx->queue, | 224 | hdr->addr1, hwaccel, rx->queue, |
236 | &rx->tkip_iv32, | 225 | &rx->tkip_iv32, |
237 | &rx->tkip_iv16); | 226 | &rx->tkip_iv16); |
238 | if (res != TKIP_DECRYPT_OK || wpa_test) | 227 | if (res != TKIP_DECRYPT_OK) |
239 | return RX_DROP_UNUSABLE; | 228 | return RX_DROP_UNUSABLE; |
240 | 229 | ||
241 | /* Trim ICV */ | 230 | /* Trim ICV */ |
diff --git a/net/wireless/core.c b/net/wireless/core.c index e9a5f8ca4c27..fe01de29bfe8 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -718,13 +718,6 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | |||
718 | wdev->ps = false; | 718 | wdev->ps = false; |
719 | /* allow mac80211 to determine the timeout */ | 719 | /* allow mac80211 to determine the timeout */ |
720 | wdev->ps_timeout = -1; | 720 | wdev->ps_timeout = -1; |
721 | if (rdev->ops->set_power_mgmt) | ||
722 | if (rdev->ops->set_power_mgmt(wdev->wiphy, dev, | ||
723 | wdev->ps, | ||
724 | wdev->ps_timeout)) { | ||
725 | /* assume this means it's off */ | ||
726 | wdev->ps = false; | ||
727 | } | ||
728 | 721 | ||
729 | if (!dev->ethtool_ops) | 722 | if (!dev->ethtool_ops) |
730 | dev->ethtool_ops = &cfg80211_ethtool_ops; | 723 | dev->ethtool_ops = &cfg80211_ethtool_ops; |
@@ -813,6 +806,19 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | |||
813 | rdev->opencount++; | 806 | rdev->opencount++; |
814 | mutex_unlock(&rdev->devlist_mtx); | 807 | mutex_unlock(&rdev->devlist_mtx); |
815 | cfg80211_unlock_rdev(rdev); | 808 | cfg80211_unlock_rdev(rdev); |
809 | |||
810 | /* | ||
811 | * Configure power management to the driver here so that its | ||
812 | * correctly set also after interface type changes etc. | ||
813 | */ | ||
814 | if (wdev->iftype == NL80211_IFTYPE_STATION && | ||
815 | rdev->ops->set_power_mgmt) | ||
816 | if (rdev->ops->set_power_mgmt(wdev->wiphy, dev, | ||
817 | wdev->ps, | ||
818 | wdev->ps_timeout)) { | ||
819 | /* assume this means it's off */ | ||
820 | wdev->ps = false; | ||
821 | } | ||
816 | break; | 822 | break; |
817 | case NETDEV_UNREGISTER: | 823 | case NETDEV_UNREGISTER: |
818 | /* | 824 | /* |