diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn-rxon.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 91 |
1 files changed, 73 insertions, 18 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index a95ad84c5377..a7c66c4e5f2a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | |||
@@ -81,6 +81,21 @@ static int iwlagn_disable_pan(struct iwl_priv *priv, | |||
81 | return ret; | 81 | return ret; |
82 | } | 82 | } |
83 | 83 | ||
84 | static int iwlagn_disconn_pan(struct iwl_priv *priv, | ||
85 | struct iwl_rxon_context *ctx, | ||
86 | struct iwl_rxon_cmd *send) | ||
87 | { | ||
88 | __le32 old_filter = send->filter_flags; | ||
89 | int ret; | ||
90 | |||
91 | send->filter_flags &= ~RXON_FILTER_ASSOC_MSK; | ||
92 | ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, sizeof(*send), send); | ||
93 | |||
94 | send->filter_flags = old_filter; | ||
95 | |||
96 | return ret; | ||
97 | } | ||
98 | |||
84 | static void iwlagn_update_qos(struct iwl_priv *priv, | 99 | static void iwlagn_update_qos(struct iwl_priv *priv, |
85 | struct iwl_rxon_context *ctx) | 100 | struct iwl_rxon_context *ctx) |
86 | { | 101 | { |
@@ -163,9 +178,6 @@ static int iwlagn_send_rxon_assoc(struct iwl_priv *priv, | |||
163 | 178 | ||
164 | ret = iwl_send_cmd_pdu_async(priv, ctx->rxon_assoc_cmd, | 179 | ret = iwl_send_cmd_pdu_async(priv, ctx->rxon_assoc_cmd, |
165 | sizeof(rxon_assoc), &rxon_assoc, NULL); | 180 | sizeof(rxon_assoc), &rxon_assoc, NULL); |
166 | if (ret) | ||
167 | return ret; | ||
168 | |||
169 | return ret; | 181 | return ret; |
170 | } | 182 | } |
171 | 183 | ||
@@ -175,10 +187,21 @@ static int iwlagn_rxon_disconn(struct iwl_priv *priv, | |||
175 | int ret; | 187 | int ret; |
176 | struct iwl_rxon_cmd *active = (void *)&ctx->active; | 188 | struct iwl_rxon_cmd *active = (void *)&ctx->active; |
177 | 189 | ||
178 | if (ctx->ctxid == IWL_RXON_CTX_BSS) | 190 | if (ctx->ctxid == IWL_RXON_CTX_BSS) { |
179 | ret = iwlagn_disable_bss(priv, ctx, &ctx->staging); | 191 | ret = iwlagn_disable_bss(priv, ctx, &ctx->staging); |
180 | else | 192 | } else { |
181 | ret = iwlagn_disable_pan(priv, ctx, &ctx->staging); | 193 | ret = iwlagn_disable_pan(priv, ctx, &ctx->staging); |
194 | if (ret) | ||
195 | return ret; | ||
196 | if (ctx->vif) { | ||
197 | ret = iwl_send_rxon_timing(priv, ctx); | ||
198 | if (ret) { | ||
199 | IWL_ERR(priv, "Failed to send timing (%d)!\n", ret); | ||
200 | return ret; | ||
201 | } | ||
202 | ret = iwlagn_disconn_pan(priv, ctx, &ctx->staging); | ||
203 | } | ||
204 | } | ||
182 | if (ret) | 205 | if (ret) |
183 | return ret; | 206 | return ret; |
184 | 207 | ||
@@ -205,10 +228,12 @@ static int iwlagn_rxon_connect(struct iwl_priv *priv, | |||
205 | struct iwl_rxon_cmd *active = (void *)&ctx->active; | 228 | struct iwl_rxon_cmd *active = (void *)&ctx->active; |
206 | 229 | ||
207 | /* RXON timing must be before associated RXON */ | 230 | /* RXON timing must be before associated RXON */ |
208 | ret = iwl_send_rxon_timing(priv, ctx); | 231 | if (ctx->ctxid == IWL_RXON_CTX_BSS) { |
209 | if (ret) { | 232 | ret = iwl_send_rxon_timing(priv, ctx); |
210 | IWL_ERR(priv, "Failed to send timing (%d)!\n", ret); | 233 | if (ret) { |
211 | return ret; | 234 | IWL_ERR(priv, "Failed to send timing (%d)!\n", ret); |
235 | return ret; | ||
236 | } | ||
212 | } | 237 | } |
213 | /* QoS info may be cleared by previous un-assoc RXON */ | 238 | /* QoS info may be cleared by previous un-assoc RXON */ |
214 | iwlagn_update_qos(priv, ctx); | 239 | iwlagn_update_qos(priv, ctx); |
@@ -263,6 +288,12 @@ static int iwlagn_rxon_connect(struct iwl_priv *priv, | |||
263 | IWL_ERR(priv, "Error sending TX power (%d)\n", ret); | 288 | IWL_ERR(priv, "Error sending TX power (%d)\n", ret); |
264 | return ret; | 289 | return ret; |
265 | } | 290 | } |
291 | |||
292 | if ((ctx->vif && ctx->vif->type == NL80211_IFTYPE_STATION) && | ||
293 | priv->cfg->ht_params->smps_mode) | ||
294 | ieee80211_request_smps(ctx->vif, | ||
295 | priv->cfg->ht_params->smps_mode); | ||
296 | |||
266 | return 0; | 297 | return 0; |
267 | } | 298 | } |
268 | 299 | ||
@@ -325,6 +356,14 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | |||
325 | return 0; | 356 | return 0; |
326 | } | 357 | } |
327 | 358 | ||
359 | /* | ||
360 | * force CTS-to-self frames protection if RTS-CTS is not preferred | ||
361 | * one aggregation protection method | ||
362 | */ | ||
363 | if (!(priv->cfg->ht_params && | ||
364 | priv->cfg->ht_params->use_rts_for_aggregation)) | ||
365 | ctx->staging.flags |= RXON_FLG_SELF_CTS_EN; | ||
366 | |||
328 | if ((ctx->vif && ctx->vif->bss_conf.use_short_slot) || | 367 | if ((ctx->vif && ctx->vif->bss_conf.use_short_slot) || |
329 | !(ctx->staging.flags & RXON_FLG_BAND_24G_MSK)) | 368 | !(ctx->staging.flags & RXON_FLG_BAND_24G_MSK)) |
330 | ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; | 369 | ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK; |
@@ -342,10 +381,10 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | |||
342 | * receive commit_rxon request | 381 | * receive commit_rxon request |
343 | * abort any previous channel switch if still in process | 382 | * abort any previous channel switch if still in process |
344 | */ | 383 | */ |
345 | if (priv->switch_rxon.switch_in_progress && | 384 | if (test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status) && |
346 | (priv->switch_rxon.channel != ctx->staging.channel)) { | 385 | (priv->switch_channel != ctx->staging.channel)) { |
347 | IWL_DEBUG_11H(priv, "abort channel switch on %d\n", | 386 | IWL_DEBUG_11H(priv, "abort channel switch on %d\n", |
348 | le16_to_cpu(priv->switch_rxon.channel)); | 387 | le16_to_cpu(priv->switch_channel)); |
349 | iwl_chswitch_done(priv, false); | 388 | iwl_chswitch_done(priv, false); |
350 | } | 389 | } |
351 | 390 | ||
@@ -362,13 +401,16 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | |||
362 | } | 401 | } |
363 | 402 | ||
364 | memcpy(active, &ctx->staging, sizeof(*active)); | 403 | memcpy(active, &ctx->staging, sizeof(*active)); |
365 | return 0; | 404 | /* |
366 | } | 405 | * We do not commit tx power settings while channel changing, |
406 | * do it now if after settings changed. | ||
407 | */ | ||
408 | iwl_set_tx_power(priv, priv->tx_power_next, false); | ||
367 | 409 | ||
368 | if (priv->cfg->ops->hcmd->set_pan_params) { | 410 | /* make sure we are in the right PS state */ |
369 | ret = priv->cfg->ops->hcmd->set_pan_params(priv); | 411 | iwl_power_update_mode(priv, true); |
370 | if (ret) | 412 | |
371 | return ret; | 413 | return 0; |
372 | } | 414 | } |
373 | 415 | ||
374 | iwl_set_rxon_hwcrypto(priv, ctx, !iwlagn_mod_params.sw_crypto); | 416 | iwl_set_rxon_hwcrypto(priv, ctx, !iwlagn_mod_params.sw_crypto); |
@@ -392,6 +434,12 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | |||
392 | if (ret) | 434 | if (ret) |
393 | return ret; | 435 | return ret; |
394 | 436 | ||
437 | if (priv->cfg->ops->hcmd->set_pan_params) { | ||
438 | ret = priv->cfg->ops->hcmd->set_pan_params(priv); | ||
439 | if (ret) | ||
440 | return ret; | ||
441 | } | ||
442 | |||
395 | if (new_assoc) | 443 | if (new_assoc) |
396 | return iwlagn_rxon_connect(priv, ctx); | 444 | return iwlagn_rxon_connect(priv, ctx); |
397 | 445 | ||
@@ -757,6 +805,13 @@ void iwlagn_post_scan(struct iwl_priv *priv) | |||
757 | struct iwl_rxon_context *ctx; | 805 | struct iwl_rxon_context *ctx; |
758 | 806 | ||
759 | /* | 807 | /* |
808 | * We do not commit power settings while scan is pending, | ||
809 | * do it now if the settings changed. | ||
810 | */ | ||
811 | iwl_power_set_mode(priv, &priv->power_data.sleep_cmd_next, false); | ||
812 | iwl_set_tx_power(priv, priv->tx_power_next, false); | ||
813 | |||
814 | /* | ||
760 | * Since setting the RXON may have been deferred while | 815 | * Since setting the RXON may have been deferred while |
761 | * performing the scan, fire one off if needed | 816 | * performing the scan, fire one off if needed |
762 | */ | 817 | */ |