aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rxon.c194
1 files changed, 111 insertions, 83 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
index 7f52ab8f5848..178b2b5a53b4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
@@ -169,6 +169,103 @@ static int iwlagn_send_rxon_assoc(struct iwl_priv *priv,
169 return ret; 169 return ret;
170} 170}
171 171
172static int iwlagn_rxon_disconn(struct iwl_priv *priv,
173 struct iwl_rxon_context *ctx)
174{
175 int ret;
176 struct iwl_rxon_cmd *active = (void *)&ctx->active;
177
178 if (ctx->ctxid == IWL_RXON_CTX_BSS)
179 ret = iwlagn_disable_bss(priv, ctx, &ctx->staging);
180 else
181 ret = iwlagn_disable_pan(priv, ctx, &ctx->staging);
182 if (ret)
183 return ret;
184
185 /*
186 * Un-assoc RXON clears the station table and WEP
187 * keys, so we have to restore those afterwards.
188 */
189 iwl_clear_ucode_stations(priv, ctx);
190 iwl_restore_stations(priv, ctx);
191 ret = iwl_restore_default_wep_keys(priv, ctx);
192 if (ret) {
193 IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret);
194 return ret;
195 }
196
197 memcpy(active, &ctx->staging, sizeof(*active));
198 return 0;
199}
200
201static int iwlagn_rxon_connect(struct iwl_priv *priv,
202 struct iwl_rxon_context *ctx)
203{
204 int ret;
205 struct iwl_rxon_cmd *active = (void *)&ctx->active;
206
207 /* RXON timing must be before associated RXON */
208 ret = iwl_send_rxon_timing(priv, ctx);
209 if (ret) {
210 IWL_ERR(priv, "Failed to send timing (%d)!\n", ret);
211 return ret;
212 }
213 /* QoS info may be cleared by previous un-assoc RXON */
214 iwlagn_update_qos(priv, ctx);
215
216 /*
217 * We'll run into this code path when beaconing is
218 * enabled, but then we also need to send the beacon
219 * to the device.
220 */
221 if (ctx->vif && (ctx->vif->type == NL80211_IFTYPE_AP)) {
222 ret = iwlagn_update_beacon(priv, ctx->vif);
223 if (ret) {
224 IWL_ERR(priv,
225 "Error sending required beacon (%d)!\n",
226 ret);
227 return ret;
228 }
229 }
230
231 priv->start_calib = 0;
232 /*
233 * Apply the new configuration.
234 *
235 * Associated RXON doesn't clear the station table in uCode,
236 * so we don't need to restore stations etc. after this.
237 */
238 ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd,
239 sizeof(struct iwl_rxon_cmd), &ctx->staging);
240 if (ret) {
241 IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
242 return ret;
243 }
244 memcpy(active, &ctx->staging, sizeof(*active));
245
246 iwl_reprogram_ap_sta(priv, ctx);
247
248 /* IBSS beacon needs to be sent after setting assoc */
249 if (ctx->vif && (ctx->vif->type == NL80211_IFTYPE_ADHOC))
250 if (iwlagn_update_beacon(priv, ctx->vif))
251 IWL_ERR(priv, "Error sending IBSS beacon\n");
252 iwl_init_sensitivity(priv);
253
254 /*
255 * If we issue a new RXON command which required a tune then
256 * we must send a new TXPOWER command or we won't be able to
257 * Tx any frames.
258 *
259 * It's expected we set power here if channel is changing.
260 */
261 ret = iwl_set_tx_power(priv, priv->tx_power_next, true);
262 if (ret) {
263 IWL_ERR(priv, "Error sending TX power (%d)\n", ret);
264 return ret;
265 }
266 return 0;
267}
268
172/** 269/**
173 * iwlagn_commit_rxon - commit staging_rxon to hardware 270 * iwlagn_commit_rxon - commit staging_rxon to hardware
174 * 271 *
@@ -176,6 +273,16 @@ static int iwlagn_send_rxon_assoc(struct iwl_priv *priv,
176 * the active_rxon structure is updated with the new data. This 273 * the active_rxon structure is updated with the new data. This
177 * function correctly transitions out of the RXON_ASSOC_MSK state if 274 * function correctly transitions out of the RXON_ASSOC_MSK state if
178 * a HW tune is required based on the RXON structure changes. 275 * a HW tune is required based on the RXON structure changes.
276 *
277 * The connect/disconnect flow should be as the following:
278 *
279 * 1. make sure send RXON command with association bit unset if not connect
280 * this should include the channel and the band for the candidate
281 * to be connected to
282 * 2. Add Station before RXON association with the AP
283 * 3. RXON_timing has to send before RXON for connection
284 * 4. full RXON command - associated bit set
285 * 5. use RXON_ASSOC command to update any flags changes
179 */ 286 */
180int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) 287int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
181{ 288{
@@ -225,6 +332,7 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
225 else 332 else
226 ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK; 333 ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
227 334
335 iwl_print_rx_config_cmd(priv, ctx);
228 ret = iwl_check_rxon_cmd(priv, ctx); 336 ret = iwl_check_rxon_cmd(priv, ctx);
229 if (ret) { 337 if (ret) {
230 IWL_ERR(priv, "Invalid RXON configuration. Not committing.\n"); 338 IWL_ERR(priv, "Invalid RXON configuration. Not committing.\n");
@@ -255,7 +363,6 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
255 } 363 }
256 364
257 memcpy(active, &ctx->staging, sizeof(*active)); 365 memcpy(active, &ctx->staging, sizeof(*active));
258 iwl_print_rx_config_cmd(priv, ctx);
259 return 0; 366 return 0;
260 } 367 }
261 368
@@ -283,92 +390,13 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
283 * set up filters in the device. 390 * set up filters in the device.
284 */ 391 */
285 if ((old_assoc && new_assoc) || !new_assoc) { 392 if ((old_assoc && new_assoc) || !new_assoc) {
286 if (ctx->ctxid == IWL_RXON_CTX_BSS) 393 ret = iwlagn_rxon_disconn(priv, ctx);
287 ret = iwlagn_disable_bss(priv, ctx, &ctx->staging);
288 else
289 ret = iwlagn_disable_pan(priv, ctx, &ctx->staging);
290 if (ret) 394 if (ret)
291 return ret; 395 return ret;
292
293 memcpy(active, &ctx->staging, sizeof(*active));
294
295 /*
296 * Un-assoc RXON clears the station table and WEP
297 * keys, so we have to restore those afterwards.
298 */
299 iwl_clear_ucode_stations(priv, ctx);
300 iwl_restore_stations(priv, ctx);
301 ret = iwl_restore_default_wep_keys(priv, ctx);
302 if (ret) {
303 IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret);
304 return ret;
305 }
306 } 396 }
307 397
308 /* RXON timing must be before associated RXON */ 398 if (new_assoc)
309 ret = iwl_send_rxon_timing(priv, ctx); 399 return iwlagn_rxon_connect(priv, ctx);
310 if (ret) {
311 IWL_ERR(priv, "Failed to send timing (%d)!\n", ret);
312 return ret;
313 }
314
315 if (new_assoc) {
316 /* QoS info may be cleared by previous un-assoc RXON */
317 iwlagn_update_qos(priv, ctx);
318
319 /*
320 * We'll run into this code path when beaconing is
321 * enabled, but then we also need to send the beacon
322 * to the device.
323 */
324 if (ctx->vif && (ctx->vif->type == NL80211_IFTYPE_AP)) {
325 ret = iwlagn_update_beacon(priv, ctx->vif);
326 if (ret) {
327 IWL_ERR(priv,
328 "Error sending required beacon (%d)!\n",
329 ret);
330 return ret;
331 }
332 }
333
334 priv->start_calib = 0;
335 /*
336 * Apply the new configuration.
337 *
338 * Associated RXON doesn't clear the station table in uCode,
339 * so we don't need to restore stations etc. after this.
340 */
341 ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd,
342 sizeof(struct iwl_rxon_cmd), &ctx->staging);
343 if (ret) {
344 IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
345 return ret;
346 }
347 memcpy(active, &ctx->staging, sizeof(*active));
348
349 iwl_reprogram_ap_sta(priv, ctx);
350
351 /* IBSS beacon needs to be sent after setting assoc */
352 if (ctx->vif && (ctx->vif->type == NL80211_IFTYPE_ADHOC))
353 if (iwlagn_update_beacon(priv, ctx->vif))
354 IWL_ERR(priv, "Error sending IBSS beacon\n");
355 }
356
357 iwl_print_rx_config_cmd(priv, ctx);
358
359 iwl_init_sensitivity(priv);
360
361 /*
362 * If we issue a new RXON command which required a tune then we must
363 * send a new TXPOWER command or we won't be able to Tx any frames.
364 *
365 * It's expected we set power here if channel is changing.
366 */
367 ret = iwl_set_tx_power(priv, priv->tx_power_next, true);
368 if (ret) {
369 IWL_ERR(priv, "Error sending TX power (%d)\n", ret);
370 return ret;
371 }
372 400
373 return 0; 401 return 0;
374} 402}