aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Pedersen <c_tpeder@qca.qualcomm.com>2012-07-26 21:11:11 -0400
committerKalle Valo <kvalo@qca.qualcomm.com>2012-10-24 04:49:40 -0400
commitb5495e666d0b83553f6330e7ba33c0cee2271332 (patch)
tree5db187709d84d53164468789b228664dc541c0d5
parentfd4377b6bacc0f04bb1898f3ccab9510172a7561 (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.h1
-rw-r--r--drivers/net/wireless/ath/ath6kl/main.c18
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);