diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 194 |
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 | ||
172 | static 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 | |||
201 | static 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 | */ |
180 | int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | 287 | int 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 | } |