aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorSamuel Ortiz <sameo@linux.intel.com>2009-09-01 09:14:05 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-09-01 12:48:28 -0400
commitd210176eaaed0c7883caba52665bcfb5d420c660 (patch)
tree1ac8c392c188e330be24496d42f9e5d9846ef36b /drivers/net/wireless
parentd04bd6283cf7433d56f3d8f648f1d6963fda4fdc (diff)
iwmc3200wifi: Handle UMAC stalls and UMAC assert properly
When UMAC stalls or asserts, we want to reset the device. But when we're associated, the current reset worker will end up calling cfg80211_connect_result() with the cfg80211 sme layer knowing that we're reassociating. That ends up with some ugly warnings. With this patch we're telling the upper layer that we've roamed if reassociation succeeds, and that we're disconnected if it fails. Signed-off-by: Samuel Ortiz <sameo@linux.intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/iwmc3200wifi/iwm.h2
-rw-r--r--drivers/net/wireless/iwmc3200wifi/main.c18
-rw-r--r--drivers/net/wireless/iwmc3200wifi/rx.c29
3 files changed, 40 insertions, 9 deletions
diff --git a/drivers/net/wireless/iwmc3200wifi/iwm.h b/drivers/net/wireless/iwmc3200wifi/iwm.h
index 74964ee93bb7..f5c2d6f3fd43 100644
--- a/drivers/net/wireless/iwmc3200wifi/iwm.h
+++ b/drivers/net/wireless/iwmc3200wifi/iwm.h
@@ -178,6 +178,7 @@ struct iwm_key {
178#define IWM_STATUS_SCAN_ABORTING 2 178#define IWM_STATUS_SCAN_ABORTING 2
179#define IWM_STATUS_SME_CONNECTING 3 179#define IWM_STATUS_SME_CONNECTING 3
180#define IWM_STATUS_ASSOCIATED 4 180#define IWM_STATUS_ASSOCIATED 4
181#define IWM_STATUS_RESETTING 5
181 182
182struct iwm_tx_queue { 183struct iwm_tx_queue {
183 int id; 184 int id;
@@ -317,6 +318,7 @@ int iwm_mode_to_nl80211_iftype(int mode);
317int iwm_priv_init(struct iwm_priv *iwm); 318int iwm_priv_init(struct iwm_priv *iwm);
318void iwm_priv_deinit(struct iwm_priv *iwm); 319void iwm_priv_deinit(struct iwm_priv *iwm);
319void iwm_reset(struct iwm_priv *iwm); 320void iwm_reset(struct iwm_priv *iwm);
321void iwm_resetting(struct iwm_priv *iwm);
320void iwm_tx_credit_init_pools(struct iwm_priv *iwm, 322void iwm_tx_credit_init_pools(struct iwm_priv *iwm,
321 struct iwm_umac_notif_alive *alive); 323 struct iwm_umac_notif_alive *alive);
322int iwm_tx_credit_alloc(struct iwm_priv *iwm, int id, int nb); 324int iwm_tx_credit_alloc(struct iwm_priv *iwm, int id, int nb);
diff --git a/drivers/net/wireless/iwmc3200wifi/main.c b/drivers/net/wireless/iwmc3200wifi/main.c
index fc7fce44a9d7..6a5b76acb645 100644
--- a/drivers/net/wireless/iwmc3200wifi/main.c
+++ b/drivers/net/wireless/iwmc3200wifi/main.c
@@ -187,7 +187,8 @@ static void iwm_reset_worker(struct work_struct *work)
187 memcpy(iwm->umac_profile, profile, sizeof(*profile)); 187 memcpy(iwm->umac_profile, profile, sizeof(*profile));
188 iwm_send_mlme_profile(iwm); 188 iwm_send_mlme_profile(iwm);
189 kfree(profile); 189 kfree(profile);
190 } 190 } else
191 clear_bit(IWM_STATUS_RESETTING, &iwm->status);
191 192
192 out: 193 out:
193 mutex_unlock(&iwm->mutex); 194 mutex_unlock(&iwm->mutex);
@@ -200,7 +201,7 @@ static void iwm_watchdog(unsigned long data)
200 IWM_WARN(iwm, "Watchdog expired: UMAC stalls!\n"); 201 IWM_WARN(iwm, "Watchdog expired: UMAC stalls!\n");
201 202
202 if (modparam_reset) 203 if (modparam_reset)
203 schedule_work(&iwm->reset_worker); 204 iwm_resetting(iwm);
204} 205}
205 206
206int iwm_priv_init(struct iwm_priv *iwm) 207int iwm_priv_init(struct iwm_priv *iwm)
@@ -284,7 +285,11 @@ void iwm_reset(struct iwm_priv *iwm)
284 if (test_bit(IWM_STATUS_READY, &iwm->status)) 285 if (test_bit(IWM_STATUS_READY, &iwm->status))
285 iwm_target_reset(iwm); 286 iwm_target_reset(iwm);
286 287
287 iwm->status = 0; 288 if (test_bit(IWM_STATUS_RESETTING, &iwm->status)) {
289 iwm->status = 0;
290 set_bit(IWM_STATUS_RESETTING, &iwm->status);
291 } else
292 iwm->status = 0;
288 iwm->scan_id = 1; 293 iwm->scan_id = 1;
289 294
290 list_for_each_entry_safe(notif, next, &iwm->pending_notif, pending) { 295 list_for_each_entry_safe(notif, next, &iwm->pending_notif, pending) {
@@ -300,6 +305,13 @@ void iwm_reset(struct iwm_priv *iwm)
300 iwm_link_off(iwm); 305 iwm_link_off(iwm);
301} 306}
302 307
308void iwm_resetting(struct iwm_priv *iwm)
309{
310 set_bit(IWM_STATUS_RESETTING, &iwm->status);
311
312 schedule_work(&iwm->reset_worker);
313}
314
303/* 315/*
304 * Notification code: 316 * Notification code:
305 * 317 *
diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c
index 2daa58633e6f..14950b147f91 100644
--- a/drivers/net/wireless/iwmc3200wifi/rx.c
+++ b/drivers/net/wireless/iwmc3200wifi/rx.c
@@ -118,6 +118,8 @@ static int iwm_ntf_error(struct iwm_priv *iwm, u8 *buf,
118 IWM_ERR(iwm, "\tLMAC status: 0x%x\n", le32_to_cpu(fw_err->lmac_status)); 118 IWM_ERR(iwm, "\tLMAC status: 0x%x\n", le32_to_cpu(fw_err->lmac_status));
119 IWM_ERR(iwm, "\tSDIO status: 0x%x\n", le32_to_cpu(fw_err->sdio_status)); 119 IWM_ERR(iwm, "\tSDIO status: 0x%x\n", le32_to_cpu(fw_err->sdio_status));
120 120
121 iwm_resetting(iwm);
122
121 return 0; 123 return 0;
122} 124}
123 125
@@ -528,11 +530,19 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf,
528 if (iwm->conf.mode == UMAC_MODE_IBSS) 530 if (iwm->conf.mode == UMAC_MODE_IBSS)
529 goto ibss; 531 goto ibss;
530 532
531 cfg80211_connect_result(iwm_to_ndev(iwm), 533 if (!test_bit(IWM_STATUS_RESETTING, &iwm->status))
534 cfg80211_connect_result(iwm_to_ndev(iwm),
535 complete->bssid,
536 iwm->req_ie, iwm->req_ie_len,
537 iwm->resp_ie, iwm->resp_ie_len,
538 WLAN_STATUS_SUCCESS,
539 GFP_KERNEL);
540 else
541 cfg80211_roamed(iwm_to_ndev(iwm),
532 complete->bssid, 542 complete->bssid,
533 iwm->req_ie, iwm->req_ie_len, 543 iwm->req_ie, iwm->req_ie_len,
534 iwm->resp_ie, iwm->resp_ie_len, 544 iwm->resp_ie, iwm->resp_ie_len,
535 WLAN_STATUS_SUCCESS, GFP_KERNEL); 545 GFP_KERNEL);
536 break; 546 break;
537 case UMAC_ASSOC_COMPLETE_FAILURE: 547 case UMAC_ASSOC_COMPLETE_FAILURE:
538 clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status); 548 clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status);
@@ -551,19 +561,26 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf,
551 if (iwm->conf.mode == UMAC_MODE_IBSS) 561 if (iwm->conf.mode == UMAC_MODE_IBSS)
552 goto ibss; 562 goto ibss;
553 563
554 cfg80211_connect_result(iwm_to_ndev(iwm), complete->bssid, 564 if (!test_bit(IWM_STATUS_RESETTING, &iwm->status))
555 NULL, 0, NULL, 0, 565 cfg80211_connect_result(iwm_to_ndev(iwm),
556 WLAN_STATUS_UNSPECIFIED_FAILURE, 566 complete->bssid,
557 GFP_KERNEL); 567 NULL, 0, NULL, 0,
568 WLAN_STATUS_UNSPECIFIED_FAILURE,
569 GFP_KERNEL);
570 else
571 cfg80211_disconnected(iwm_to_ndev(iwm), 0, NULL, 0,
572 GFP_KERNEL);
558 break; 573 break;
559 default: 574 default:
560 break; 575 break;
561 } 576 }
562 577
578 clear_bit(IWM_STATUS_RESETTING, &iwm->status);
563 return 0; 579 return 0;
564 580
565 ibss: 581 ibss:
566 cfg80211_ibss_joined(iwm_to_ndev(iwm), iwm->bssid, GFP_KERNEL); 582 cfg80211_ibss_joined(iwm_to_ndev(iwm), iwm->bssid, GFP_KERNEL);
583 clear_bit(IWM_STATUS_RESETTING, &iwm->status);
567 return 0; 584 return 0;
568} 585}
569 586