aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>2008-06-30 05:23:06 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-06-30 17:37:39 -0400
commit43d59b323743b8a01e9ad1a1b31b0d7c0ef6e35a (patch)
tree8329613e007265c0fc0d4dfb959f7dff69fbdace /drivers/net/wireless
parentebbbdc3fb70ebb4dae1d319b723c14b5dc21cc71 (diff)
iwlwifi: send ADD_STA before RXON with assoc bit
This patch fixes a bug in association flow. As soon as RXON with assoc bit is sent, uCode expects to have an entry in its station table that describe the AP. Receiving a beacon from an HT AP before sending ADD_STA results a uCode error. This patch sends first the ADD_STA (bcast and bssid) and only then RXON with assoc bit set Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com> Signed-off-by: Gregory Greenman <gregory.greenman@intel.com> Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: Zhu Yi <yi.zhu@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl4965-base.c79
1 files changed, 46 insertions, 33 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index a2dffe401c78..0a279d15e058 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -241,16 +241,18 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv)
241 /* cast away the const for active_rxon in this function */ 241 /* cast away the const for active_rxon in this function */
242 struct iwl_rxon_cmd *active_rxon = (void *)&priv->active_rxon; 242 struct iwl_rxon_cmd *active_rxon = (void *)&priv->active_rxon;
243 DECLARE_MAC_BUF(mac); 243 DECLARE_MAC_BUF(mac);
244 int rc = 0; 244 int ret;
245 bool new_assoc =
246 !!(priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK);
245 247
246 if (!iwl_is_alive(priv)) 248 if (!iwl_is_alive(priv))
247 return -1; 249 return -EBUSY;
248 250
249 /* always get timestamp with Rx frame */ 251 /* always get timestamp with Rx frame */
250 priv->staging_rxon.flags |= RXON_FLG_TSF2HOST_MSK; 252 priv->staging_rxon.flags |= RXON_FLG_TSF2HOST_MSK;
251 253
252 rc = iwl4965_check_rxon_cmd(&priv->staging_rxon); 254 ret = iwl4965_check_rxon_cmd(&priv->staging_rxon);
253 if (rc) { 255 if (ret) {
254 IWL_ERROR("Invalid RXON configuration. Not committing.\n"); 256 IWL_ERROR("Invalid RXON configuration. Not committing.\n");
255 return -EINVAL; 257 return -EINVAL;
256 } 258 }
@@ -259,15 +261,13 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv)
259 * iwl4965_rxon_assoc_cmd which is used to reconfigure filter 261 * iwl4965_rxon_assoc_cmd which is used to reconfigure filter
260 * and other flags for the current radio configuration. */ 262 * and other flags for the current radio configuration. */
261 if (!iwl4965_full_rxon_required(priv)) { 263 if (!iwl4965_full_rxon_required(priv)) {
262 rc = iwl_send_rxon_assoc(priv); 264 ret = iwl_send_rxon_assoc(priv);
263 if (rc) { 265 if (ret) {
264 IWL_ERROR("Error setting RXON_ASSOC " 266 IWL_ERROR("Error setting RXON_ASSOC (%d)\n", ret);
265 "configuration (%d).\n", rc); 267 return ret;
266 return rc;
267 } 268 }
268 269
269 memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon)); 270 memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
270
271 return 0; 271 return 0;
272 } 272 }
273 273
@@ -278,22 +278,20 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv)
278 * an RXON_ASSOC and the new config wants the associated mask enabled, 278 * an RXON_ASSOC and the new config wants the associated mask enabled,
279 * we must clear the associated from the active configuration 279 * we must clear the associated from the active configuration
280 * before we apply the new config */ 280 * before we apply the new config */
281 if (iwl_is_associated(priv) && 281 if (iwl_is_associated(priv) && new_assoc) {
282 (priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK)) {
283 IWL_DEBUG_INFO("Toggling associated bit on current RXON\n"); 282 IWL_DEBUG_INFO("Toggling associated bit on current RXON\n");
284 active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; 283 active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
285 284
286 rc = iwl_send_cmd_pdu(priv, REPLY_RXON, 285 ret = iwl_send_cmd_pdu(priv, REPLY_RXON,
287 sizeof(struct iwl_rxon_cmd), 286 sizeof(struct iwl_rxon_cmd),
288 &priv->active_rxon); 287 &priv->active_rxon);
289 288
290 /* If the mask clearing failed then we set 289 /* If the mask clearing failed then we set
291 * active_rxon back to what it was previously */ 290 * active_rxon back to what it was previously */
292 if (rc) { 291 if (ret) {
293 active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK; 292 active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK;
294 IWL_ERROR("Error clearing ASSOC_MSK on current " 293 IWL_ERROR("Error clearing ASSOC_MSK (%d)\n", ret);
295 "configuration (%d).\n", rc); 294 return ret;
296 return rc;
297 } 295 }
298 } 296 }
299 297
@@ -301,18 +299,25 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv)
301 "* with%s RXON_FILTER_ASSOC_MSK\n" 299 "* with%s RXON_FILTER_ASSOC_MSK\n"
302 "* channel = %d\n" 300 "* channel = %d\n"
303 "* bssid = %s\n", 301 "* bssid = %s\n",
304 ((priv->staging_rxon.filter_flags & 302 (new_assoc ? "" : "out"),
305 RXON_FILTER_ASSOC_MSK) ? "" : "out"),
306 le16_to_cpu(priv->staging_rxon.channel), 303 le16_to_cpu(priv->staging_rxon.channel),
307 print_mac(mac, priv->staging_rxon.bssid_addr)); 304 print_mac(mac, priv->staging_rxon.bssid_addr));
308 305
309 iwl4965_set_rxon_hwcrypto(priv, !priv->hw_params.sw_crypto); 306 iwl4965_set_rxon_hwcrypto(priv, !priv->hw_params.sw_crypto);
310 /* Apply the new configuration */ 307
311 rc = iwl_send_cmd_pdu(priv, REPLY_RXON, 308 /* Apply the new configuration
309 * RXON unassoc clears the station table in uCode, send it before
310 * we add the bcast station. If assoc bit is set, we will send RXON
311 * after having added the bcast and bssid station.
312 */
313 if (!new_assoc) {
314 ret = iwl_send_cmd_pdu(priv, REPLY_RXON,
312 sizeof(struct iwl_rxon_cmd), &priv->staging_rxon); 315 sizeof(struct iwl_rxon_cmd), &priv->staging_rxon);
313 if (rc) { 316 if (ret) {
314 IWL_ERROR("Error setting new configuration (%d).\n", rc); 317 IWL_ERROR("Error setting new RXON (%d)\n", ret);
315 return rc; 318 return ret;
319 }
320 memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
316 } 321 }
317 322
318 iwlcore_clear_stations_table(priv); 323 iwlcore_clear_stations_table(priv);
@@ -322,27 +327,24 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv)
322 327
323 iwl_init_sensitivity(priv); 328 iwl_init_sensitivity(priv);
324 329
325 memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
326
327 /* If we issue a new RXON command which required a tune then we must 330 /* If we issue a new RXON command which required a tune then we must
328 * send a new TXPOWER command or we won't be able to Tx any frames */ 331 * send a new TXPOWER command or we won't be able to Tx any frames */
329 rc = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true); 332 ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true);
330 if (rc) { 333 if (ret) {
331 IWL_ERROR("Error sending TX power (%d).\n", rc); 334 IWL_ERROR("Error sending TX power (%d)\n", ret);
332 return rc; 335 return ret;
333 } 336 }
334 337
335 /* Add the broadcast address so we can send broadcast frames */ 338 /* Add the broadcast address so we can send broadcast frames */
336 if (iwl_rxon_add_station(priv, iwl_bcast_addr, 0) == 339 if (iwl_rxon_add_station(priv, iwl_bcast_addr, 0) ==
337 IWL_INVALID_STATION) { 340 IWL_INVALID_STATION) {
338 IWL_ERROR("Error adding BROADCAST address for transmit.\n"); 341 IWL_ERROR("Error adding BROADCAST address for transmit.\n");
339 return -EIO; 342 return -EIO;
340 } 343 }
341 344
342 /* If we have set the ASSOC_MSK and we are in BSS mode then 345 /* If we have set the ASSOC_MSK and we are in BSS mode then
343 * add the IWL_AP_ID to the station rate table */ 346 * add the IWL_AP_ID to the station rate table */
344 if (iwl_is_associated(priv) && 347 if (new_assoc && (priv->iw_mode == IEEE80211_IF_TYPE_STA)) {
345 (priv->iw_mode == IEEE80211_IF_TYPE_STA)) {
346 if (iwl_rxon_add_station(priv, priv->active_rxon.bssid_addr, 1) 348 if (iwl_rxon_add_station(priv, priv->active_rxon.bssid_addr, 1)
347 == IWL_INVALID_STATION) { 349 == IWL_INVALID_STATION) {
348 IWL_ERROR("Error adding AP address for transmit.\n"); 350 IWL_ERROR("Error adding AP address for transmit.\n");
@@ -352,6 +354,17 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv)
352 if (priv->default_wep_key && 354 if (priv->default_wep_key &&
353 iwl_send_static_wepkey_cmd(priv, 0)) 355 iwl_send_static_wepkey_cmd(priv, 0))
354 IWL_ERROR("Could not send WEP static key.\n"); 356 IWL_ERROR("Could not send WEP static key.\n");
357
358 /* Apply the new configuration
359 * RXON assoc doesn't clear the station table in uCode,
360 */
361 ret = iwl_send_cmd_pdu(priv, REPLY_RXON,
362 sizeof(struct iwl_rxon_cmd), &priv->staging_rxon);
363 if (ret) {
364 IWL_ERROR("Error setting new RXON (%d)\n", ret);
365 return ret;
366 }
367 memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
355 } 368 }
356 369
357 return 0; 370 return 0;