ath6kl: restart concurrent vifs on failed connect
authorThomas Pedersen <c_tpeder@qca.qualcomm.com>
Fri, 27 Jul 2012 01:11:11 +0000 (18:11 -0700)
committerKalle Valo <kvalo@qca.qualcomm.com>
Wed, 24 Oct 2012 08:49:40 +0000 (11:49 +0300)
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>
drivers/net/wireless/ath/ath6kl/core.h
drivers/net/wireless/ath/ath6kl/main.c

index eb86b315adffdf4b29efe94b961c2db26f2d2fd0..baf149ef346522fc648f99eeae0e9f21a60ea25e 100644 (file)
@@ -699,6 +699,7 @@ struct ath6kl {
        struct ath6kl_req_key ap_mode_bkey;
        struct sk_buff_head mcastpsq;
        u32 want_ch_switch;
+       u16 last_ch;
 
        /*
         * FIXME: protects access to mcastpsq but is actually useless as
index 6beffdee9a8210760d5b7308363f2d4985942cd9..eca4d4704edc2501660df17c889339b7d7590e87 100644 (file)
@@ -441,12 +441,9 @@ void ath6kl_connect_ap_mode_bss(struct ath6kl_vif *vif, u16 channel)
                break;
        }
 
-       if (ar->want_ch_switch & (1 << vif->fw_vif_idx)) {
-               ar->want_ch_switch &= ~(1 << vif->fw_vif_idx);
+       if (ar->last_ch != channel)
                /* we actually don't know the phymode, default to HT20 */
-               ath6kl_cfg80211_ch_switch_notify(vif, channel,
-                                                WMI_11G_HT20);
-       }
+               ath6kl_cfg80211_ch_switch_notify(vif, channel, WMI_11G_HT20);
 
        ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx, NONE_BSS_FILTER, 0);
        set_bit(CONNECTED, &vif->flags);
@@ -633,6 +630,9 @@ static void ath6kl_check_ch_switch(struct ath6kl *ar, u16 channel)
                if (ar->want_ch_switch & (1 << vif->fw_vif_idx))
                        res = ath6kl_commit_ch_switch(vif, channel);
 
+               /* if channel switch failed, oh well we tried */
+               ar->want_ch_switch &= ~(1 << vif->fw_vif_idx);
+
                if (res)
                        ath6kl_err("channel switch failed nw_type %d res %d\n",
                                   vif->nw_type, res);
@@ -986,8 +986,11 @@ void ath6kl_disconnect_event(struct ath6kl_vif *vif, u8 reason, u8 *bssid,
        if (vif->nw_type == AP_NETWORK) {
                /* disconnect due to other STA vif switching channels */
                if (reason == BSS_DISCONNECTED &&
-                   prot_reason_status == WMI_AP_REASON_STA_ROAM)
+                   prot_reason_status == WMI_AP_REASON_STA_ROAM) {
                        ar->want_ch_switch |= 1 << vif->fw_vif_idx;
+                       /* bail back to this channel if STA vif fails connect */
+                       ar->last_ch = le16_to_cpu(vif->profile.ch);
+               }
 
                if (!ath6kl_remove_sta(ar, bssid, prot_reason_status))
                        return;
@@ -1046,6 +1049,9 @@ void ath6kl_disconnect_event(struct ath6kl_vif *vif, u8 reason, u8 *bssid,
                }
        }
 
+       /* restart disconnected concurrent vifs waiting for new channel */
+       ath6kl_check_ch_switch(ar, ar->last_ch);
+
        /* update connect & link status atomically */
        spin_lock_bh(&vif->if_lock);
        clear_bit(CONNECTED, &vif->flags);
This page took 0.027058 seconds and 5 git commands to generate.