aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn-rxon.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rxon.c91
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
84static 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
84static void iwlagn_update_qos(struct iwl_priv *priv, 99static 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 */