Skip to content

Commit

Permalink
iwmc3200wifi: Handle UMAC stalls and UMAC assert properly
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Samuel Ortiz authored and John W. Linville committed Sep 1, 2009
1 parent d04bd62 commit d210176
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 9 deletions.
2 changes: 2 additions & 0 deletions drivers/net/wireless/iwmc3200wifi/iwm.h
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ struct iwm_key {
#define IWM_STATUS_SCAN_ABORTING 2
#define IWM_STATUS_SME_CONNECTING 3
#define IWM_STATUS_ASSOCIATED 4
#define IWM_STATUS_RESETTING 5

struct iwm_tx_queue {
int id;
Expand Down Expand Up @@ -317,6 +318,7 @@ int iwm_mode_to_nl80211_iftype(int mode);
int iwm_priv_init(struct iwm_priv *iwm);
void iwm_priv_deinit(struct iwm_priv *iwm);
void iwm_reset(struct iwm_priv *iwm);
void iwm_resetting(struct iwm_priv *iwm);
void iwm_tx_credit_init_pools(struct iwm_priv *iwm,
struct iwm_umac_notif_alive *alive);
int iwm_tx_credit_alloc(struct iwm_priv *iwm, int id, int nb);
Expand Down
18 changes: 15 additions & 3 deletions drivers/net/wireless/iwmc3200wifi/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,8 @@ static void iwm_reset_worker(struct work_struct *work)
memcpy(iwm->umac_profile, profile, sizeof(*profile));
iwm_send_mlme_profile(iwm);
kfree(profile);
}
} else
clear_bit(IWM_STATUS_RESETTING, &iwm->status);

out:
mutex_unlock(&iwm->mutex);
Expand All @@ -200,7 +201,7 @@ static void iwm_watchdog(unsigned long data)
IWM_WARN(iwm, "Watchdog expired: UMAC stalls!\n");

if (modparam_reset)
schedule_work(&iwm->reset_worker);
iwm_resetting(iwm);
}

int iwm_priv_init(struct iwm_priv *iwm)
Expand Down Expand Up @@ -284,7 +285,11 @@ void iwm_reset(struct iwm_priv *iwm)
if (test_bit(IWM_STATUS_READY, &iwm->status))
iwm_target_reset(iwm);

iwm->status = 0;
if (test_bit(IWM_STATUS_RESETTING, &iwm->status)) {
iwm->status = 0;
set_bit(IWM_STATUS_RESETTING, &iwm->status);
} else
iwm->status = 0;
iwm->scan_id = 1;

list_for_each_entry_safe(notif, next, &iwm->pending_notif, pending) {
Expand All @@ -300,6 +305,13 @@ void iwm_reset(struct iwm_priv *iwm)
iwm_link_off(iwm);
}

void iwm_resetting(struct iwm_priv *iwm)
{
set_bit(IWM_STATUS_RESETTING, &iwm->status);

schedule_work(&iwm->reset_worker);
}

/*
* Notification code:
*
Expand Down
29 changes: 23 additions & 6 deletions drivers/net/wireless/iwmc3200wifi/rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ static int iwm_ntf_error(struct iwm_priv *iwm, u8 *buf,
IWM_ERR(iwm, "\tLMAC status: 0x%x\n", le32_to_cpu(fw_err->lmac_status));
IWM_ERR(iwm, "\tSDIO status: 0x%x\n", le32_to_cpu(fw_err->sdio_status));

iwm_resetting(iwm);

return 0;
}

Expand Down Expand Up @@ -528,11 +530,19 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf,
if (iwm->conf.mode == UMAC_MODE_IBSS)
goto ibss;

cfg80211_connect_result(iwm_to_ndev(iwm),
if (!test_bit(IWM_STATUS_RESETTING, &iwm->status))
cfg80211_connect_result(iwm_to_ndev(iwm),
complete->bssid,
iwm->req_ie, iwm->req_ie_len,
iwm->resp_ie, iwm->resp_ie_len,
WLAN_STATUS_SUCCESS,
GFP_KERNEL);
else
cfg80211_roamed(iwm_to_ndev(iwm),
complete->bssid,
iwm->req_ie, iwm->req_ie_len,
iwm->resp_ie, iwm->resp_ie_len,
WLAN_STATUS_SUCCESS, GFP_KERNEL);
GFP_KERNEL);
break;
case UMAC_ASSOC_COMPLETE_FAILURE:
clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status);
Expand All @@ -551,19 +561,26 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf,
if (iwm->conf.mode == UMAC_MODE_IBSS)
goto ibss;

cfg80211_connect_result(iwm_to_ndev(iwm), complete->bssid,
NULL, 0, NULL, 0,
WLAN_STATUS_UNSPECIFIED_FAILURE,
GFP_KERNEL);
if (!test_bit(IWM_STATUS_RESETTING, &iwm->status))
cfg80211_connect_result(iwm_to_ndev(iwm),
complete->bssid,
NULL, 0, NULL, 0,
WLAN_STATUS_UNSPECIFIED_FAILURE,
GFP_KERNEL);
else
cfg80211_disconnected(iwm_to_ndev(iwm), 0, NULL, 0,
GFP_KERNEL);
break;
default:
break;
}

clear_bit(IWM_STATUS_RESETTING, &iwm->status);
return 0;

ibss:
cfg80211_ibss_joined(iwm_to_ndev(iwm), iwm->bssid, GFP_KERNEL);
clear_bit(IWM_STATUS_RESETTING, &iwm->status);
return 0;
}

Expand Down

0 comments on commit d210176

Please sign in to comment.