diff options
author | Thomas Pedersen <c_tpeder@qca.qualcomm.com> | 2012-07-26 21:11:11 -0400 |
---|---|---|
committer | Kalle Valo <kvalo@qca.qualcomm.com> | 2012-10-24 04:49:40 -0400 |
commit | b5495e666d0b83553f6330e7ba33c0cee2271332 (patch) | |
tree | 5db187709d84d53164468789b228664dc541c0d5 | |
parent | fd4377b6bacc0f04bb1898f3ccab9510172a7561 (diff) |
ath6kl: restart concurrent vifs on failed connect
When an ath6kl STA vif is issued a connect command, the firmware will
disconnect all other beaconing vifs in preparation for a potential
channel switch. The case where the connect fails is currently unhandled,
so if a connection attempt on a STA vif fails and any vifs were waiting
for a new channel, simply restart the concurrent vifs on their previous
channel.
Requires that we start tracking the last issued channel in ar->last_ch,
which is valid since ath6kl only supports 1 channel at a time.
Also clear the beaconing vif's want_ch_switch bit regardless of whether
channel switch succeeds, to stop recommitting the same failed profile.
Signed-off-by: Thomas Pedersen <c_tpeder@qca.qualcomm.com>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/core.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/main.c | 18 |
2 files changed, 13 insertions, 6 deletions
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index eb86b315adf..baf149ef346 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h | |||
@@ -699,6 +699,7 @@ struct ath6kl { | |||
699 | struct ath6kl_req_key ap_mode_bkey; | 699 | struct ath6kl_req_key ap_mode_bkey; |
700 | struct sk_buff_head mcastpsq; | 700 | struct sk_buff_head mcastpsq; |
701 | u32 want_ch_switch; | 701 | u32 want_ch_switch; |
702 | u16 last_ch; | ||
702 | 703 | ||
703 | /* | 704 | /* |
704 | * FIXME: protects access to mcastpsq but is actually useless as | 705 | * FIXME: protects access to mcastpsq but is actually useless as |
diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c index 6beffdee9a8..eca4d4704ed 100644 --- a/drivers/net/wireless/ath/ath6kl/main.c +++ b/drivers/net/wireless/ath/ath6kl/main.c | |||
@@ -441,12 +441,9 @@ void ath6kl_connect_ap_mode_bss(struct ath6kl_vif *vif, u16 channel) | |||
441 | break; | 441 | break; |
442 | } | 442 | } |
443 | 443 | ||
444 | if (ar->want_ch_switch & (1 << vif->fw_vif_idx)) { | 444 | if (ar->last_ch != channel) |
445 | ar->want_ch_switch &= ~(1 << vif->fw_vif_idx); | ||
446 | /* we actually don't know the phymode, default to HT20 */ | 445 | /* we actually don't know the phymode, default to HT20 */ |
447 | ath6kl_cfg80211_ch_switch_notify(vif, channel, | 446 | ath6kl_cfg80211_ch_switch_notify(vif, channel, WMI_11G_HT20); |
448 | WMI_11G_HT20); | ||
449 | } | ||
450 | 447 | ||
451 | ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx, NONE_BSS_FILTER, 0); | 448 | ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx, NONE_BSS_FILTER, 0); |
452 | set_bit(CONNECTED, &vif->flags); | 449 | set_bit(CONNECTED, &vif->flags); |
@@ -633,6 +630,9 @@ static void ath6kl_check_ch_switch(struct ath6kl *ar, u16 channel) | |||
633 | if (ar->want_ch_switch & (1 << vif->fw_vif_idx)) | 630 | if (ar->want_ch_switch & (1 << vif->fw_vif_idx)) |
634 | res = ath6kl_commit_ch_switch(vif, channel); | 631 | res = ath6kl_commit_ch_switch(vif, channel); |
635 | 632 | ||
633 | /* if channel switch failed, oh well we tried */ | ||
634 | ar->want_ch_switch &= ~(1 << vif->fw_vif_idx); | ||
635 | |||
636 | if (res) | 636 | if (res) |
637 | ath6kl_err("channel switch failed nw_type %d res %d\n", | 637 | ath6kl_err("channel switch failed nw_type %d res %d\n", |
638 | vif->nw_type, res); | 638 | vif->nw_type, res); |
@@ -986,8 +986,11 @@ void ath6kl_disconnect_event(struct ath6kl_vif *vif, u8 reason, u8 *bssid, | |||
986 | if (vif->nw_type == AP_NETWORK) { | 986 | if (vif->nw_type == AP_NETWORK) { |
987 | /* disconnect due to other STA vif switching channels */ | 987 | /* disconnect due to other STA vif switching channels */ |
988 | if (reason == BSS_DISCONNECTED && | 988 | if (reason == BSS_DISCONNECTED && |
989 | prot_reason_status == WMI_AP_REASON_STA_ROAM) | 989 | prot_reason_status == WMI_AP_REASON_STA_ROAM) { |
990 | ar->want_ch_switch |= 1 << vif->fw_vif_idx; | 990 | ar->want_ch_switch |= 1 << vif->fw_vif_idx; |
991 | /* bail back to this channel if STA vif fails connect */ | ||
992 | ar->last_ch = le16_to_cpu(vif->profile.ch); | ||
993 | } | ||
991 | 994 | ||
992 | if (!ath6kl_remove_sta(ar, bssid, prot_reason_status)) | 995 | if (!ath6kl_remove_sta(ar, bssid, prot_reason_status)) |
993 | return; | 996 | return; |
@@ -1046,6 +1049,9 @@ void ath6kl_disconnect_event(struct ath6kl_vif *vif, u8 reason, u8 *bssid, | |||
1046 | } | 1049 | } |
1047 | } | 1050 | } |
1048 | 1051 | ||
1052 | /* restart disconnected concurrent vifs waiting for new channel */ | ||
1053 | ath6kl_check_ch_switch(ar, ar->last_ch); | ||
1054 | |||
1049 | /* update connect & link status atomically */ | 1055 | /* update connect & link status atomically */ |
1050 | spin_lock_bh(&vif->if_lock); | 1056 | spin_lock_bh(&vif->if_lock); |
1051 | clear_bit(CONNECTED, &vif->flags); | 1057 | clear_bit(CONNECTED, &vif->flags); |