aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath6kl
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath/ath6kl')
-rw-r--r--drivers/net/wireless/ath/ath6kl/cfg80211.c15
-rw-r--r--drivers/net/wireless/ath/ath6kl/cfg80211.h2
-rw-r--r--drivers/net/wireless/ath/ath6kl/core.h2
-rw-r--r--drivers/net/wireless/ath/ath6kl/main.c55
-rw-r--r--drivers/net/wireless/ath/ath6kl/wmi.h12
5 files changed, 85 insertions, 1 deletions
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index 28a65d3a03d0..6ea5ae54c160 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -1018,6 +1018,20 @@ out:
1018 vif->scan_req = NULL; 1018 vif->scan_req = NULL;
1019} 1019}
1020 1020
1021void ath6kl_cfg80211_ch_switch_notify(struct ath6kl_vif *vif, int freq,
1022 enum wmi_phy_mode mode)
1023{
1024 enum nl80211_channel_type type;
1025
1026 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1027 "channel switch notify nw_type %d freq %d mode %d\n",
1028 vif->nw_type, freq, mode);
1029
1030 type = (mode == WMI_11G_HT20) ? NL80211_CHAN_HT20 : NL80211_CHAN_NO_HT;
1031
1032 cfg80211_ch_switch_notify(vif->ndev, freq, type);
1033}
1034
1021static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, 1035static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
1022 u8 key_index, bool pairwise, 1036 u8 key_index, bool pairwise,
1023 const u8 *mac_addr, 1037 const u8 *mac_addr,
@@ -2766,6 +2780,7 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,
2766 return res; 2780 return res;
2767 } 2781 }
2768 2782
2783 memcpy(&vif->profile, &p, sizeof(p));
2769 res = ath6kl_wmi_ap_profile_commit(ar->wmi, vif->fw_vif_idx, &p); 2784 res = ath6kl_wmi_ap_profile_commit(ar->wmi, vif->fw_vif_idx, &p);
2770 if (res < 0) 2785 if (res < 0)
2771 return res; 2786 return res;
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.h b/drivers/net/wireless/ath/ath6kl/cfg80211.h
index c5def436417f..5ea8cbb79f43 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.h
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.h
@@ -28,6 +28,8 @@ enum ath6kl_cfg_suspend_mode {
28struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name, 28struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name,
29 enum nl80211_iftype type, 29 enum nl80211_iftype type,
30 u8 fw_vif_idx, u8 nw_type); 30 u8 fw_vif_idx, u8 nw_type);
31void ath6kl_cfg80211_ch_switch_notify(struct ath6kl_vif *vif, int freq,
32 enum wmi_phy_mode mode);
31void ath6kl_cfg80211_scan_complete_event(struct ath6kl_vif *vif, bool aborted); 33void ath6kl_cfg80211_scan_complete_event(struct ath6kl_vif *vif, bool aborted);
32 34
33void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel, 35void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel,
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h
index 9d67964a51dd..8ca393fc9f18 100644
--- a/drivers/net/wireless/ath/ath6kl/core.h
+++ b/drivers/net/wireless/ath/ath6kl/core.h
@@ -552,6 +552,7 @@ struct ath6kl_vif {
552 u8 assoc_bss_dtim_period; 552 u8 assoc_bss_dtim_period;
553 struct net_device_stats net_stats; 553 struct net_device_stats net_stats;
554 struct target_stats target_stats; 554 struct target_stats target_stats;
555 struct wmi_connect_cmd profile;
555 556
556 struct list_head mc_filter; 557 struct list_head mc_filter;
557}; 558};
@@ -640,6 +641,7 @@ struct ath6kl {
640 u8 sta_list_index; 641 u8 sta_list_index;
641 struct ath6kl_req_key ap_mode_bkey; 642 struct ath6kl_req_key ap_mode_bkey;
642 struct sk_buff_head mcastpsq; 643 struct sk_buff_head mcastpsq;
644 u32 want_ch_switch;
643 645
644 /* 646 /*
645 * FIXME: protects access to mcastpsq but is actually useless as 647 * 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 4d818f96c415..4602be7ce23b 100644
--- a/drivers/net/wireless/ath/ath6kl/main.c
+++ b/drivers/net/wireless/ath/ath6kl/main.c
@@ -436,6 +436,13 @@ void ath6kl_connect_ap_mode_bss(struct ath6kl_vif *vif, u16 channel)
436 break; 436 break;
437 } 437 }
438 438
439 if (ar->want_ch_switch & (1 << vif->fw_vif_idx)) {
440 ar->want_ch_switch &= ~(1 << vif->fw_vif_idx);
441 /* we actually don't know the phymode, default to HT20 */
442 ath6kl_cfg80211_ch_switch_notify(vif, channel,
443 WMI_11G_HT20);
444 }
445
439 ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx, NONE_BSS_FILTER, 0); 446 ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx, NONE_BSS_FILTER, 0);
440 set_bit(CONNECTED, &vif->flags); 447 set_bit(CONNECTED, &vif->flags);
441 netif_carrier_on(vif->ndev); 448 netif_carrier_on(vif->ndev);
@@ -584,6 +591,45 @@ void ath6kl_scan_complete_evt(struct ath6kl_vif *vif, int status)
584 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "scan complete: %d\n", status); 591 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "scan complete: %d\n", status);
585} 592}
586 593
594static int ath6kl_commit_ch_switch(struct ath6kl_vif *vif, u16 channel)
595{
596
597 struct ath6kl *ar = vif->ar;
598
599 vif->next_chan = channel;
600 vif->profile.ch = cpu_to_le16(channel);
601
602 switch (vif->nw_type) {
603 case AP_NETWORK:
604 return ath6kl_wmi_ap_profile_commit(ar->wmi, vif->fw_vif_idx,
605 &vif->profile);
606 default:
607 ath6kl_err("won't switch channels nw_type=%d\n", vif->nw_type);
608 return -ENOTSUPP;
609 }
610}
611
612static void ath6kl_check_ch_switch(struct ath6kl *ar, u16 channel)
613{
614
615 struct ath6kl_vif *vif;
616 int res = 0;
617
618 if (!ar->want_ch_switch)
619 return;
620
621 spin_lock_bh(&ar->list_lock);
622 list_for_each_entry(vif, &ar->vif_list, list) {
623 if (ar->want_ch_switch & (1 << vif->fw_vif_idx))
624 res = ath6kl_commit_ch_switch(vif, channel);
625
626 if (res)
627 ath6kl_err("channel switch failed nw_type %d res %d\n",
628 vif->nw_type, res);
629 }
630 spin_unlock_bh(&ar->list_lock);
631}
632
587void ath6kl_connect_event(struct ath6kl_vif *vif, u16 channel, u8 *bssid, 633void ath6kl_connect_event(struct ath6kl_vif *vif, u16 channel, u8 *bssid,
588 u16 listen_int, u16 beacon_int, 634 u16 listen_int, u16 beacon_int,
589 enum network_type net_type, u8 beacon_ie_len, 635 enum network_type net_type, u8 beacon_ie_len,
@@ -601,9 +647,11 @@ void ath6kl_connect_event(struct ath6kl_vif *vif, u16 channel, u8 *bssid,
601 memcpy(vif->bssid, bssid, sizeof(vif->bssid)); 647 memcpy(vif->bssid, bssid, sizeof(vif->bssid));
602 vif->bss_ch = channel; 648 vif->bss_ch = channel;
603 649
604 if ((vif->nw_type == INFRA_NETWORK)) 650 if ((vif->nw_type == INFRA_NETWORK)) {
605 ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx, 651 ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx,
606 vif->listen_intvl_t, 0); 652 vif->listen_intvl_t, 0);
653 ath6kl_check_ch_switch(ar, channel);
654 }
607 655
608 netif_wake_queue(vif->ndev); 656 netif_wake_queue(vif->ndev);
609 657
@@ -926,6 +974,11 @@ void ath6kl_disconnect_event(struct ath6kl_vif *vif, u8 reason, u8 *bssid,
926 struct ath6kl *ar = vif->ar; 974 struct ath6kl *ar = vif->ar;
927 975
928 if (vif->nw_type == AP_NETWORK) { 976 if (vif->nw_type == AP_NETWORK) {
977 /* disconnect due to other STA vif switching channels */
978 if (reason == BSS_DISCONNECTED &&
979 prot_reason_status == WMI_AP_REASON_STA_ROAM)
980 ar->want_ch_switch |= 1 << vif->fw_vif_idx;
981
929 if (!ath6kl_remove_sta(ar, bssid, prot_reason_status)) 982 if (!ath6kl_remove_sta(ar, bssid, prot_reason_status))
930 return; 983 return;
931 984
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h
index d3d2ab5c1689..190b2c4e382f 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.h
+++ b/drivers/net/wireless/ath/ath6kl/wmi.h
@@ -1151,6 +1151,7 @@ enum wmi_phy_mode {
1151 WMI_11AG_MODE = 0x3, 1151 WMI_11AG_MODE = 0x3,
1152 WMI_11B_MODE = 0x4, 1152 WMI_11B_MODE = 0x4,
1153 WMI_11GONLY_MODE = 0x5, 1153 WMI_11GONLY_MODE = 0x5,
1154 WMI_11G_HT20 = 0x6,
1154}; 1155};
1155 1156
1156#define WMI_MAX_CHANNELS 32 1157#define WMI_MAX_CHANNELS 32
@@ -1468,6 +1469,17 @@ enum wmi_disconnect_reason {
1468 IBSS_MERGE = 0xe, 1469 IBSS_MERGE = 0xe,
1469}; 1470};
1470 1471
1472/* AP mode disconnect proto_reasons */
1473enum ap_disconnect_reason {
1474 WMI_AP_REASON_STA_LEFT = 101,
1475 WMI_AP_REASON_FROM_HOST = 102,
1476 WMI_AP_REASON_COMM_TIMEOUT = 103,
1477 WMI_AP_REASON_MAX_STA = 104,
1478 WMI_AP_REASON_ACL = 105,
1479 WMI_AP_REASON_STA_ROAM = 106,
1480 WMI_AP_REASON_DFS_CHANNEL = 107,
1481};
1482
1471#define ATH6KL_COUNTRY_RD_SHIFT 16 1483#define ATH6KL_COUNTRY_RD_SHIFT 16
1472 1484
1473struct ath6kl_wmi_regdomain { 1485struct ath6kl_wmi_regdomain {