aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwmc3200wifi/rx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwmc3200wifi/rx.c')
-rw-r--r--drivers/net/wireless/iwmc3200wifi/rx.c87
1 files changed, 71 insertions, 16 deletions
diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c
index 86079a187eef..40dbcbc16593 100644
--- a/drivers/net/wireless/iwmc3200wifi/rx.c
+++ b/drivers/net/wireless/iwmc3200wifi/rx.c
@@ -102,6 +102,8 @@ static int iwm_ntf_error(struct iwm_priv *iwm, u8 *buf,
102 error = (struct iwm_umac_notif_error *)buf; 102 error = (struct iwm_umac_notif_error *)buf;
103 fw_err = &error->err; 103 fw_err = &error->err;
104 104
105 memcpy(iwm->last_fw_err, fw_err, sizeof(struct iwm_fw_error_hdr));
106
105 IWM_ERR(iwm, "%cMAC FW ERROR:\n", 107 IWM_ERR(iwm, "%cMAC FW ERROR:\n",
106 (le32_to_cpu(fw_err->category) == UMAC_SYS_ERR_CAT_LMAC) ? 'L' : 'U'); 108 (le32_to_cpu(fw_err->category) == UMAC_SYS_ERR_CAT_LMAC) ? 'L' : 'U');
107 IWM_ERR(iwm, "\tCategory: %d\n", le32_to_cpu(fw_err->category)); 109 IWM_ERR(iwm, "\tCategory: %d\n", le32_to_cpu(fw_err->category));
@@ -118,6 +120,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)); 120 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)); 121 IWM_ERR(iwm, "\tSDIO status: 0x%x\n", le32_to_cpu(fw_err->sdio_status));
120 122
123 iwm_resetting(iwm);
124
121 return 0; 125 return 0;
122} 126}
123 127
@@ -487,8 +491,6 @@ static int iwm_mlme_assoc_start(struct iwm_priv *iwm, u8 *buf,
487 491
488 start = (struct iwm_umac_notif_assoc_start *)buf; 492 start = (struct iwm_umac_notif_assoc_start *)buf;
489 493
490 set_bit(IWM_STATUS_ASSOCIATING, &iwm->status);
491
492 IWM_DBG_MLME(iwm, INFO, "Association with %pM Started, reason: %d\n", 494 IWM_DBG_MLME(iwm, INFO, "Association with %pM Started, reason: %d\n",
493 start->bssid, le32_to_cpu(start->roam_reason)); 495 start->bssid, le32_to_cpu(start->roam_reason));
494 496
@@ -507,47 +509,80 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf,
507 IWM_DBG_MLME(iwm, INFO, "Association with %pM completed, status: %d\n", 509 IWM_DBG_MLME(iwm, INFO, "Association with %pM completed, status: %d\n",
508 complete->bssid, complete->status); 510 complete->bssid, complete->status);
509 511
510 clear_bit(IWM_STATUS_ASSOCIATING, &iwm->status);
511
512 switch (le32_to_cpu(complete->status)) { 512 switch (le32_to_cpu(complete->status)) {
513 case UMAC_ASSOC_COMPLETE_SUCCESS: 513 case UMAC_ASSOC_COMPLETE_SUCCESS:
514 set_bit(IWM_STATUS_ASSOCIATED, &iwm->status); 514 set_bit(IWM_STATUS_ASSOCIATED, &iwm->status);
515 memcpy(iwm->bssid, complete->bssid, ETH_ALEN); 515 memcpy(iwm->bssid, complete->bssid, ETH_ALEN);
516 iwm->channel = complete->channel; 516 iwm->channel = complete->channel;
517 517
518 /* Internal roaming state, avoid notifying SME. */
519 if (!test_and_clear_bit(IWM_STATUS_SME_CONNECTING, &iwm->status)
520 && iwm->conf.mode == UMAC_MODE_BSS) {
521 cancel_delayed_work(&iwm->disconnect);
522 cfg80211_roamed(iwm_to_ndev(iwm),
523 complete->bssid,
524 iwm->req_ie, iwm->req_ie_len,
525 iwm->resp_ie, iwm->resp_ie_len,
526 GFP_KERNEL);
527 break;
528 }
529
518 iwm_link_on(iwm); 530 iwm_link_on(iwm);
519 531
520 if (iwm->conf.mode == UMAC_MODE_IBSS) 532 if (iwm->conf.mode == UMAC_MODE_IBSS)
521 goto ibss; 533 goto ibss;
522 534
523 cfg80211_connect_result(iwm_to_ndev(iwm), 535 if (!test_bit(IWM_STATUS_RESETTING, &iwm->status))
536 cfg80211_connect_result(iwm_to_ndev(iwm),
537 complete->bssid,
538 iwm->req_ie, iwm->req_ie_len,
539 iwm->resp_ie, iwm->resp_ie_len,
540 WLAN_STATUS_SUCCESS,
541 GFP_KERNEL);
542 else
543 cfg80211_roamed(iwm_to_ndev(iwm),
524 complete->bssid, 544 complete->bssid,
525 iwm->req_ie, iwm->req_ie_len, 545 iwm->req_ie, iwm->req_ie_len,
526 iwm->resp_ie, iwm->resp_ie_len, 546 iwm->resp_ie, iwm->resp_ie_len,
527 WLAN_STATUS_SUCCESS, GFP_KERNEL); 547 GFP_KERNEL);
528 break; 548 break;
529 case UMAC_ASSOC_COMPLETE_FAILURE: 549 case UMAC_ASSOC_COMPLETE_FAILURE:
530 clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status); 550 clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status);
531 memset(iwm->bssid, 0, ETH_ALEN); 551 memset(iwm->bssid, 0, ETH_ALEN);
532 iwm->channel = 0; 552 iwm->channel = 0;
533 553
554 /* Internal roaming state, avoid notifying SME. */
555 if (!test_and_clear_bit(IWM_STATUS_SME_CONNECTING, &iwm->status)
556 && iwm->conf.mode == UMAC_MODE_BSS) {
557 cancel_delayed_work(&iwm->disconnect);
558 break;
559 }
560
534 iwm_link_off(iwm); 561 iwm_link_off(iwm);
535 562
536 if (iwm->conf.mode == UMAC_MODE_IBSS) 563 if (iwm->conf.mode == UMAC_MODE_IBSS)
537 goto ibss; 564 goto ibss;
538 565
539 cfg80211_connect_result(iwm_to_ndev(iwm), complete->bssid, 566 if (!test_bit(IWM_STATUS_RESETTING, &iwm->status))
540 NULL, 0, NULL, 0, 567 cfg80211_connect_result(iwm_to_ndev(iwm),
541 WLAN_STATUS_UNSPECIFIED_FAILURE, 568 complete->bssid,
542 GFP_KERNEL); 569 NULL, 0, NULL, 0,
570 WLAN_STATUS_UNSPECIFIED_FAILURE,
571 GFP_KERNEL);
572 else
573 cfg80211_disconnected(iwm_to_ndev(iwm), 0, NULL, 0,
574 GFP_KERNEL);
575 break;
543 default: 576 default:
544 break; 577 break;
545 } 578 }
546 579
580 clear_bit(IWM_STATUS_RESETTING, &iwm->status);
547 return 0; 581 return 0;
548 582
549 ibss: 583 ibss:
550 cfg80211_ibss_joined(iwm_to_ndev(iwm), iwm->bssid, GFP_KERNEL); 584 cfg80211_ibss_joined(iwm_to_ndev(iwm), iwm->bssid, GFP_KERNEL);
585 clear_bit(IWM_STATUS_RESETTING, &iwm->status);
551 return 0; 586 return 0;
552} 587}
553 588
@@ -556,13 +591,20 @@ static int iwm_mlme_profile_invalidate(struct iwm_priv *iwm, u8 *buf,
556 struct iwm_wifi_cmd *cmd) 591 struct iwm_wifi_cmd *cmd)
557{ 592{
558 struct iwm_umac_notif_profile_invalidate *invalid; 593 struct iwm_umac_notif_profile_invalidate *invalid;
594 u32 reason;
559 595
560 invalid = (struct iwm_umac_notif_profile_invalidate *)buf; 596 invalid = (struct iwm_umac_notif_profile_invalidate *)buf;
597 reason = le32_to_cpu(invalid->reason);
561 598
562 IWM_DBG_MLME(iwm, INFO, "Profile Invalidated. Reason: %d\n", 599 IWM_DBG_MLME(iwm, INFO, "Profile Invalidated. Reason: %d\n", reason);
563 le32_to_cpu(invalid->reason));
564 600
565 clear_bit(IWM_STATUS_ASSOCIATING, &iwm->status); 601 if (reason != UMAC_PROFILE_INVALID_REQUEST &&
602 test_bit(IWM_STATUS_SME_CONNECTING, &iwm->status))
603 cfg80211_connect_result(iwm_to_ndev(iwm), NULL, NULL, 0, NULL,
604 0, WLAN_STATUS_UNSPECIFIED_FAILURE,
605 GFP_KERNEL);
606
607 clear_bit(IWM_STATUS_SME_CONNECTING, &iwm->status);
566 clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status); 608 clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status);
567 609
568 iwm->umac_profile_active = 0; 610 iwm->umac_profile_active = 0;
@@ -576,6 +618,19 @@ static int iwm_mlme_profile_invalidate(struct iwm_priv *iwm, u8 *buf,
576 return 0; 618 return 0;
577} 619}
578 620
621#define IWM_DISCONNECT_INTERVAL (5 * HZ)
622
623static int iwm_mlme_connection_terminated(struct iwm_priv *iwm, u8 *buf,
624 unsigned long buf_size,
625 struct iwm_wifi_cmd *cmd)
626{
627 IWM_DBG_MLME(iwm, DBG, "Connection terminated\n");
628
629 schedule_delayed_work(&iwm->disconnect, IWM_DISCONNECT_INTERVAL);
630
631 return 0;
632}
633
579static int iwm_mlme_scan_complete(struct iwm_priv *iwm, u8 *buf, 634static int iwm_mlme_scan_complete(struct iwm_priv *iwm, u8 *buf,
580 unsigned long buf_size, 635 unsigned long buf_size,
581 struct iwm_wifi_cmd *cmd) 636 struct iwm_wifi_cmd *cmd)
@@ -813,7 +868,8 @@ static int iwm_mlme_mgt_frame(struct iwm_priv *iwm, u8 *buf,
813 iwm->resp_ie = kmemdup(mgt->u.reassoc_resp.variable, 868 iwm->resp_ie = kmemdup(mgt->u.reassoc_resp.variable,
814 iwm->resp_ie_len, GFP_KERNEL); 869 iwm->resp_ie_len, GFP_KERNEL);
815 } else { 870 } else {
816 IWM_ERR(iwm, "Unsupported management frame"); 871 IWM_ERR(iwm, "Unsupported management frame: 0x%x",
872 le16_to_cpu(mgt->frame_control));
817 return 0; 873 return 0;
818 } 874 }
819 875
@@ -834,8 +890,7 @@ static int iwm_ntf_mlme(struct iwm_priv *iwm, u8 *buf,
834 case WIFI_IF_NTFY_PROFILE_INVALIDATE_COMPLETE: 890 case WIFI_IF_NTFY_PROFILE_INVALIDATE_COMPLETE:
835 return iwm_mlme_profile_invalidate(iwm, buf, buf_size, cmd); 891 return iwm_mlme_profile_invalidate(iwm, buf, buf_size, cmd);
836 case WIFI_IF_NTFY_CONNECTION_TERMINATED: 892 case WIFI_IF_NTFY_CONNECTION_TERMINATED:
837 IWM_DBG_MLME(iwm, DBG, "Connection terminated\n"); 893 return iwm_mlme_connection_terminated(iwm, buf, buf_size, cmd);
838 break;
839 case WIFI_IF_NTFY_SCAN_COMPLETE: 894 case WIFI_IF_NTFY_SCAN_COMPLETE:
840 return iwm_mlme_scan_complete(iwm, buf, buf_size, cmd); 895 return iwm_mlme_scan_complete(iwm, buf, buf_size, cmd);
841 case WIFI_IF_NTFY_STA_TABLE_CHANGE: 896 case WIFI_IF_NTFY_STA_TABLE_CHANGE: