diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath6kl/cfg80211.c')
-rw-r--r-- | drivers/net/wireless/ath/ath6kl/cfg80211.c | 238 |
1 files changed, 167 insertions, 71 deletions
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 28a65d3a03d0..b869a358ce43 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c | |||
@@ -693,8 +693,8 @@ ath6kl_add_bss_if_needed(struct ath6kl_vif *vif, | |||
693 | ie, 2 + vif->ssid_len + beacon_ie_len, | 693 | ie, 2 + vif->ssid_len + beacon_ie_len, |
694 | 0, GFP_KERNEL); | 694 | 0, GFP_KERNEL); |
695 | if (bss) | 695 | if (bss) |
696 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "added bss %pM to " | 696 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, |
697 | "cfg80211\n", bssid); | 697 | "added bss %pM to cfg80211\n", bssid); |
698 | kfree(ie); | 698 | kfree(ie); |
699 | } else | 699 | } else |
700 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "cfg80211 already has a bss\n"); | 700 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "cfg80211 already has a bss\n"); |
@@ -882,6 +882,32 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason, | |||
882 | vif->sme_state = SME_DISCONNECTED; | 882 | vif->sme_state = SME_DISCONNECTED; |
883 | } | 883 | } |
884 | 884 | ||
885 | static int ath6kl_set_probed_ssids(struct ath6kl *ar, | ||
886 | struct ath6kl_vif *vif, | ||
887 | struct cfg80211_ssid *ssids, int n_ssids) | ||
888 | { | ||
889 | u8 i; | ||
890 | |||
891 | if (n_ssids > MAX_PROBED_SSID_INDEX) | ||
892 | return -EINVAL; | ||
893 | |||
894 | for (i = 0; i < n_ssids; i++) { | ||
895 | ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, i, | ||
896 | ssids[i].ssid_len ? | ||
897 | SPECIFIC_SSID_FLAG : ANY_SSID_FLAG, | ||
898 | ssids[i].ssid_len, | ||
899 | ssids[i].ssid); | ||
900 | } | ||
901 | |||
902 | /* Make sure no old entries are left behind */ | ||
903 | for (i = n_ssids; i < MAX_PROBED_SSID_INDEX; i++) { | ||
904 | ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, i, | ||
905 | DISABLE_SSID_FLAG, 0, NULL); | ||
906 | } | ||
907 | |||
908 | return 0; | ||
909 | } | ||
910 | |||
885 | static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, | 911 | static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, |
886 | struct cfg80211_scan_request *request) | 912 | struct cfg80211_scan_request *request) |
887 | { | 913 | { |
@@ -899,36 +925,25 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, | |||
899 | 925 | ||
900 | if (!ar->usr_bss_filter) { | 926 | if (!ar->usr_bss_filter) { |
901 | clear_bit(CLEAR_BSSFILTER_ON_BEACON, &vif->flags); | 927 | clear_bit(CLEAR_BSSFILTER_ON_BEACON, &vif->flags); |
902 | ret = ath6kl_wmi_bssfilter_cmd( | 928 | ret = ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx, |
903 | ar->wmi, vif->fw_vif_idx, | 929 | ALL_BSS_FILTER, 0); |
904 | (test_bit(CONNECTED, &vif->flags) ? | ||
905 | ALL_BUT_BSS_FILTER : ALL_BSS_FILTER), 0); | ||
906 | if (ret) { | 930 | if (ret) { |
907 | ath6kl_err("couldn't set bss filtering\n"); | 931 | ath6kl_err("couldn't set bss filtering\n"); |
908 | return ret; | 932 | return ret; |
909 | } | 933 | } |
910 | } | 934 | } |
911 | 935 | ||
912 | if (request->n_ssids && request->ssids[0].ssid_len) { | 936 | ret = ath6kl_set_probed_ssids(ar, vif, request->ssids, |
913 | u8 i; | 937 | request->n_ssids); |
914 | 938 | if (ret < 0) | |
915 | if (request->n_ssids > (MAX_PROBED_SSID_INDEX - 1)) | 939 | return ret; |
916 | request->n_ssids = MAX_PROBED_SSID_INDEX - 1; | ||
917 | |||
918 | for (i = 0; i < request->n_ssids; i++) | ||
919 | ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, | ||
920 | i + 1, SPECIFIC_SSID_FLAG, | ||
921 | request->ssids[i].ssid_len, | ||
922 | request->ssids[i].ssid); | ||
923 | } | ||
924 | 940 | ||
925 | /* this also clears IE in fw if it's not set */ | 941 | /* this also clears IE in fw if it's not set */ |
926 | ret = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx, | 942 | ret = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx, |
927 | WMI_FRAME_PROBE_REQ, | 943 | WMI_FRAME_PROBE_REQ, |
928 | request->ie, request->ie_len); | 944 | request->ie, request->ie_len); |
929 | if (ret) { | 945 | if (ret) { |
930 | ath6kl_err("failed to set Probe Request appie for " | 946 | ath6kl_err("failed to set Probe Request appie for scan"); |
931 | "scan"); | ||
932 | return ret; | 947 | return ret; |
933 | } | 948 | } |
934 | 949 | ||
@@ -945,8 +960,7 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, | |||
945 | 960 | ||
946 | channels = kzalloc(n_channels * sizeof(u16), GFP_KERNEL); | 961 | channels = kzalloc(n_channels * sizeof(u16), GFP_KERNEL); |
947 | if (channels == NULL) { | 962 | if (channels == NULL) { |
948 | ath6kl_warn("failed to set scan channels, " | 963 | ath6kl_warn("failed to set scan channels, scan all channels"); |
949 | "scan all channels"); | ||
950 | n_channels = 0; | 964 | n_channels = 0; |
951 | } | 965 | } |
952 | 966 | ||
@@ -1018,6 +1032,20 @@ out: | |||
1018 | vif->scan_req = NULL; | 1032 | vif->scan_req = NULL; |
1019 | } | 1033 | } |
1020 | 1034 | ||
1035 | void ath6kl_cfg80211_ch_switch_notify(struct ath6kl_vif *vif, int freq, | ||
1036 | enum wmi_phy_mode mode) | ||
1037 | { | ||
1038 | enum nl80211_channel_type type; | ||
1039 | |||
1040 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, | ||
1041 | "channel switch notify nw_type %d freq %d mode %d\n", | ||
1042 | vif->nw_type, freq, mode); | ||
1043 | |||
1044 | type = (mode == WMI_11G_HT20) ? NL80211_CHAN_HT20 : NL80211_CHAN_NO_HT; | ||
1045 | |||
1046 | cfg80211_ch_switch_notify(vif->ndev, freq, type); | ||
1047 | } | ||
1048 | |||
1021 | static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, | 1049 | static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, |
1022 | u8 key_index, bool pairwise, | 1050 | u8 key_index, bool pairwise, |
1023 | const u8 *mac_addr, | 1051 | const u8 *mac_addr, |
@@ -1111,9 +1139,8 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, | |||
1111 | ar->ap_mode_bkey.key_len = key->key_len; | 1139 | ar->ap_mode_bkey.key_len = key->key_len; |
1112 | memcpy(ar->ap_mode_bkey.key, key->key, key->key_len); | 1140 | memcpy(ar->ap_mode_bkey.key, key->key, key->key_len); |
1113 | if (!test_bit(CONNECTED, &vif->flags)) { | 1141 | if (!test_bit(CONNECTED, &vif->flags)) { |
1114 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delay initial group " | 1142 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, |
1115 | "key configuration until AP mode has been " | 1143 | "Delay initial group key configuration until AP mode has been started\n"); |
1116 | "started\n"); | ||
1117 | /* | 1144 | /* |
1118 | * The key will be set in ath6kl_connect_ap_mode() once | 1145 | * The key will be set in ath6kl_connect_ap_mode() once |
1119 | * the connected event is received from the target. | 1146 | * the connected event is received from the target. |
@@ -1129,8 +1156,8 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, | |||
1129 | * the AP mode has properly started | 1156 | * the AP mode has properly started |
1130 | * (ath6kl_install_statioc_wep_keys). | 1157 | * (ath6kl_install_statioc_wep_keys). |
1131 | */ | 1158 | */ |
1132 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delay WEP key configuration " | 1159 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, |
1133 | "until AP mode has been started\n"); | 1160 | "Delay WEP key configuration until AP mode has been started\n"); |
1134 | vif->wep_key_list[key_index].key_len = key->key_len; | 1161 | vif->wep_key_list[key_index].key_len = key->key_len; |
1135 | memcpy(vif->wep_key_list[key_index].key, key->key, | 1162 | memcpy(vif->wep_key_list[key_index].key, key->key, |
1136 | key->key_len); | 1163 | key->key_len); |
@@ -1962,8 +1989,7 @@ static int ath6kl_wow_sta(struct ath6kl *ar, struct ath6kl_vif *vif) | |||
1962 | sizeof(discvr_pattern), discvr_offset, | 1989 | sizeof(discvr_pattern), discvr_offset, |
1963 | discvr_pattern, discvr_mask); | 1990 | discvr_pattern, discvr_mask); |
1964 | if (ret) { | 1991 | if (ret) { |
1965 | ath6kl_err("failed to add WOW mDNS/SSDP/LLMNR " | 1992 | ath6kl_err("failed to add WOW mDNS/SSDP/LLMNR pattern\n"); |
1966 | "pattern\n"); | ||
1967 | return ret; | 1993 | return ret; |
1968 | } | 1994 | } |
1969 | } | 1995 | } |
@@ -2031,6 +2057,10 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow) | |||
2031 | u8 index = 0; | 2057 | u8 index = 0; |
2032 | __be32 ips[MAX_IP_ADDRS]; | 2058 | __be32 ips[MAX_IP_ADDRS]; |
2033 | 2059 | ||
2060 | /* The FW currently can't support multi-vif WoW properly. */ | ||
2061 | if (ar->num_vif > 1) | ||
2062 | return -EIO; | ||
2063 | |||
2034 | vif = ath6kl_vif_first(ar); | 2064 | vif = ath6kl_vif_first(ar); |
2035 | if (!vif) | 2065 | if (!vif) |
2036 | return -EIO; | 2066 | return -EIO; |
@@ -2044,6 +2074,13 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow) | |||
2044 | if (wow && (wow->n_patterns > WOW_MAX_FILTERS_PER_LIST)) | 2074 | if (wow && (wow->n_patterns > WOW_MAX_FILTERS_PER_LIST)) |
2045 | return -EINVAL; | 2075 | return -EINVAL; |
2046 | 2076 | ||
2077 | if (!test_bit(NETDEV_MCAST_ALL_ON, &vif->flags)) { | ||
2078 | ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi, | ||
2079 | vif->fw_vif_idx, false); | ||
2080 | if (ret) | ||
2081 | return ret; | ||
2082 | } | ||
2083 | |||
2047 | /* Clear existing WOW patterns */ | 2084 | /* Clear existing WOW patterns */ |
2048 | for (i = 0; i < WOW_MAX_FILTERS_PER_LIST; i++) | 2085 | for (i = 0; i < WOW_MAX_FILTERS_PER_LIST; i++) |
2049 | ath6kl_wmi_del_wow_pattern_cmd(ar->wmi, vif->fw_vif_idx, | 2086 | ath6kl_wmi_del_wow_pattern_cmd(ar->wmi, vif->fw_vif_idx, |
@@ -2147,8 +2184,8 @@ static int ath6kl_wow_resume(struct ath6kl *ar) | |||
2147 | ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx, | 2184 | ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx, |
2148 | ATH6KL_HOST_MODE_AWAKE); | 2185 | ATH6KL_HOST_MODE_AWAKE); |
2149 | if (ret) { | 2186 | if (ret) { |
2150 | ath6kl_warn("Failed to configure host sleep mode for " | 2187 | ath6kl_warn("Failed to configure host sleep mode for wow resume: %d\n", |
2151 | "wow resume: %d\n", ret); | 2188 | ret); |
2152 | ar->state = ATH6KL_STATE_WOW; | 2189 | ar->state = ATH6KL_STATE_WOW; |
2153 | return ret; | 2190 | return ret; |
2154 | } | 2191 | } |
@@ -2172,6 +2209,13 @@ static int ath6kl_wow_resume(struct ath6kl *ar) | |||
2172 | 2209 | ||
2173 | ar->state = ATH6KL_STATE_ON; | 2210 | ar->state = ATH6KL_STATE_ON; |
2174 | 2211 | ||
2212 | if (!test_bit(NETDEV_MCAST_ALL_OFF, &vif->flags)) { | ||
2213 | ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi, | ||
2214 | vif->fw_vif_idx, true); | ||
2215 | if (ret) | ||
2216 | return ret; | ||
2217 | } | ||
2218 | |||
2175 | netif_wake_queue(vif->ndev); | 2219 | netif_wake_queue(vif->ndev); |
2176 | 2220 | ||
2177 | return 0; | 2221 | return 0; |
@@ -2186,8 +2230,10 @@ static int ath6kl_cfg80211_deepsleep_suspend(struct ath6kl *ar) | |||
2186 | if (!vif) | 2230 | if (!vif) |
2187 | return -EIO; | 2231 | return -EIO; |
2188 | 2232 | ||
2189 | if (!ath6kl_cfg80211_ready(vif)) | 2233 | if (!test_bit(WMI_READY, &ar->flag)) { |
2234 | ath6kl_err("deepsleep failed as wmi is not ready\n"); | ||
2190 | return -EIO; | 2235 | return -EIO; |
2236 | } | ||
2191 | 2237 | ||
2192 | ath6kl_cfg80211_stop_all(ar); | 2238 | ath6kl_cfg80211_stop_all(ar); |
2193 | 2239 | ||
@@ -2447,6 +2493,24 @@ static int ath6kl_set_htcap(struct ath6kl_vif *vif, enum ieee80211_band band, | |||
2447 | band, htcap); | 2493 | band, htcap); |
2448 | } | 2494 | } |
2449 | 2495 | ||
2496 | static int ath6kl_restore_htcap(struct ath6kl_vif *vif) | ||
2497 | { | ||
2498 | struct wiphy *wiphy = vif->ar->wiphy; | ||
2499 | int band, ret = 0; | ||
2500 | |||
2501 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | ||
2502 | if (!wiphy->bands[band]) | ||
2503 | continue; | ||
2504 | |||
2505 | ret = ath6kl_set_htcap(vif, band, | ||
2506 | wiphy->bands[band]->ht_cap.ht_supported); | ||
2507 | if (ret) | ||
2508 | return ret; | ||
2509 | } | ||
2510 | |||
2511 | return ret; | ||
2512 | } | ||
2513 | |||
2450 | static bool ath6kl_is_p2p_ie(const u8 *pos) | 2514 | static bool ath6kl_is_p2p_ie(const u8 *pos) |
2451 | { | 2515 | { |
2452 | return pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && | 2516 | return pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && |
@@ -2568,28 +2632,34 @@ static int ath6kl_get_rsn_capab(struct cfg80211_beacon_data *beacon, | |||
2568 | /* skip element id and length */ | 2632 | /* skip element id and length */ |
2569 | rsn_ie += 2; | 2633 | rsn_ie += 2; |
2570 | 2634 | ||
2571 | /* skip version, group cipher */ | 2635 | /* skip version */ |
2572 | if (rsn_ie_len < 6) | 2636 | if (rsn_ie_len < 2) |
2573 | return -EINVAL; | 2637 | return -EINVAL; |
2574 | rsn_ie += 6; | 2638 | rsn_ie += 2; |
2575 | rsn_ie_len -= 6; | 2639 | rsn_ie_len -= 2; |
2640 | |||
2641 | /* skip group cipher suite */ | ||
2642 | if (rsn_ie_len < 4) | ||
2643 | return 0; | ||
2644 | rsn_ie += 4; | ||
2645 | rsn_ie_len -= 4; | ||
2576 | 2646 | ||
2577 | /* skip pairwise cipher suite */ | 2647 | /* skip pairwise cipher suite */ |
2578 | if (rsn_ie_len < 2) | 2648 | if (rsn_ie_len < 2) |
2579 | return -EINVAL; | 2649 | return 0; |
2580 | cnt = *((u16 *) rsn_ie); | 2650 | cnt = get_unaligned_le16(rsn_ie); |
2581 | rsn_ie += (2 + cnt * 4); | 2651 | rsn_ie += (2 + cnt * 4); |
2582 | rsn_ie_len -= (2 + cnt * 4); | 2652 | rsn_ie_len -= (2 + cnt * 4); |
2583 | 2653 | ||
2584 | /* skip akm suite */ | 2654 | /* skip akm suite */ |
2585 | if (rsn_ie_len < 2) | 2655 | if (rsn_ie_len < 2) |
2586 | return -EINVAL; | 2656 | return 0; |
2587 | cnt = *((u16 *) rsn_ie); | 2657 | cnt = get_unaligned_le16(rsn_ie); |
2588 | rsn_ie += (2 + cnt * 4); | 2658 | rsn_ie += (2 + cnt * 4); |
2589 | rsn_ie_len -= (2 + cnt * 4); | 2659 | rsn_ie_len -= (2 + cnt * 4); |
2590 | 2660 | ||
2591 | if (rsn_ie_len < 2) | 2661 | if (rsn_ie_len < 2) |
2592 | return -EINVAL; | 2662 | return 0; |
2593 | 2663 | ||
2594 | memcpy(rsn_capab, rsn_ie, 2); | 2664 | memcpy(rsn_capab, rsn_ie, 2); |
2595 | 2665 | ||
@@ -2766,6 +2836,7 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev, | |||
2766 | return res; | 2836 | return res; |
2767 | } | 2837 | } |
2768 | 2838 | ||
2839 | memcpy(&vif->profile, &p, sizeof(p)); | ||
2769 | res = ath6kl_wmi_ap_profile_commit(ar->wmi, vif->fw_vif_idx, &p); | 2840 | res = ath6kl_wmi_ap_profile_commit(ar->wmi, vif->fw_vif_idx, &p); |
2770 | if (res < 0) | 2841 | if (res < 0) |
2771 | return res; | 2842 | return res; |
@@ -2801,13 +2872,7 @@ static int ath6kl_stop_ap(struct wiphy *wiphy, struct net_device *dev) | |||
2801 | clear_bit(CONNECTED, &vif->flags); | 2872 | clear_bit(CONNECTED, &vif->flags); |
2802 | 2873 | ||
2803 | /* Restore ht setting in firmware */ | 2874 | /* Restore ht setting in firmware */ |
2804 | if (ath6kl_set_htcap(vif, IEEE80211_BAND_2GHZ, true)) | 2875 | return ath6kl_restore_htcap(vif); |
2805 | return -EIO; | ||
2806 | |||
2807 | if (ath6kl_set_htcap(vif, IEEE80211_BAND_5GHZ, true)) | ||
2808 | return -EIO; | ||
2809 | |||
2810 | return 0; | ||
2811 | } | 2876 | } |
2812 | 2877 | ||
2813 | static const u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; | 2878 | static const u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; |
@@ -3081,7 +3146,6 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy, | |||
3081 | struct ath6kl_vif *vif = netdev_priv(dev); | 3146 | struct ath6kl_vif *vif = netdev_priv(dev); |
3082 | u16 interval; | 3147 | u16 interval; |
3083 | int ret; | 3148 | int ret; |
3084 | u8 i; | ||
3085 | 3149 | ||
3086 | if (ar->state != ATH6KL_STATE_ON) | 3150 | if (ar->state != ATH6KL_STATE_ON) |
3087 | return -EIO; | 3151 | return -EIO; |
@@ -3089,29 +3153,23 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy, | |||
3089 | if (vif->sme_state != SME_DISCONNECTED) | 3153 | if (vif->sme_state != SME_DISCONNECTED) |
3090 | return -EBUSY; | 3154 | return -EBUSY; |
3091 | 3155 | ||
3156 | /* The FW currently can't support multi-vif WoW properly. */ | ||
3157 | if (ar->num_vif > 1) | ||
3158 | return -EIO; | ||
3159 | |||
3092 | ath6kl_cfg80211_scan_complete_event(vif, true); | 3160 | ath6kl_cfg80211_scan_complete_event(vif, true); |
3093 | 3161 | ||
3094 | for (i = 0; i < ar->wiphy->max_sched_scan_ssids; i++) { | 3162 | ret = ath6kl_set_probed_ssids(ar, vif, request->ssids, |
3095 | ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, | 3163 | request->n_ssids); |
3096 | i, DISABLE_SSID_FLAG, | 3164 | if (ret < 0) |
3097 | 0, NULL); | 3165 | return ret; |
3098 | } | ||
3099 | 3166 | ||
3100 | /* fw uses seconds, also make sure that it's >0 */ | 3167 | /* fw uses seconds, also make sure that it's >0 */ |
3101 | interval = max_t(u16, 1, request->interval / 1000); | 3168 | interval = max_t(u16, 1, request->interval / 1000); |
3102 | 3169 | ||
3103 | ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx, | 3170 | ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx, |
3104 | interval, interval, | 3171 | interval, interval, |
3105 | 10, 0, 0, 0, 3, 0, 0, 0); | 3172 | vif->bg_scan_period, 0, 0, 0, 3, 0, 0, 0); |
3106 | |||
3107 | if (request->n_ssids && request->ssids[0].ssid_len) { | ||
3108 | for (i = 0; i < request->n_ssids; i++) { | ||
3109 | ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, | ||
3110 | i, SPECIFIC_SSID_FLAG, | ||
3111 | request->ssids[i].ssid_len, | ||
3112 | request->ssids[i].ssid); | ||
3113 | } | ||
3114 | } | ||
3115 | 3173 | ||
3116 | ret = ath6kl_wmi_set_wow_mode_cmd(ar->wmi, vif->fw_vif_idx, | 3174 | ret = ath6kl_wmi_set_wow_mode_cmd(ar->wmi, vif->fw_vif_idx, |
3117 | ATH6KL_WOW_MODE_ENABLE, | 3175 | ATH6KL_WOW_MODE_ENABLE, |
@@ -3271,8 +3329,7 @@ void ath6kl_cfg80211_stop_all(struct ath6kl *ar) | |||
3271 | ar->wmi->saved_pwr_mode = ar->wmi->pwr_mode; | 3329 | ar->wmi->saved_pwr_mode = ar->wmi->pwr_mode; |
3272 | 3330 | ||
3273 | if (ath6kl_wmi_powermode_cmd(ar->wmi, 0, REC_POWER) != 0) | 3331 | if (ath6kl_wmi_powermode_cmd(ar->wmi, 0, REC_POWER) != 0) |
3274 | ath6kl_warn("ath6kl_deep_sleep_enable: " | 3332 | ath6kl_warn("ath6kl_deep_sleep_enable: wmi_powermode_cmd failed\n"); |
3275 | "wmi_powermode_cmd failed\n"); | ||
3276 | return; | 3333 | return; |
3277 | } | 3334 | } |
3278 | 3335 | ||
@@ -3352,6 +3409,7 @@ struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name, | |||
3352 | vif->next_mode = nw_type; | 3409 | vif->next_mode = nw_type; |
3353 | vif->listen_intvl_t = ATH6KL_DEFAULT_LISTEN_INTVAL; | 3410 | vif->listen_intvl_t = ATH6KL_DEFAULT_LISTEN_INTVAL; |
3354 | vif->bmiss_time_t = ATH6KL_DEFAULT_BMISS_TIME; | 3411 | vif->bmiss_time_t = ATH6KL_DEFAULT_BMISS_TIME; |
3412 | vif->bg_scan_period = 0; | ||
3355 | vif->htcap.ht_enable = true; | 3413 | vif->htcap.ht_enable = true; |
3356 | 3414 | ||
3357 | memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN); | 3415 | memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN); |
@@ -3393,6 +3451,7 @@ err: | |||
3393 | int ath6kl_cfg80211_init(struct ath6kl *ar) | 3451 | int ath6kl_cfg80211_init(struct ath6kl *ar) |
3394 | { | 3452 | { |
3395 | struct wiphy *wiphy = ar->wiphy; | 3453 | struct wiphy *wiphy = ar->wiphy; |
3454 | bool band_2gig = false, band_5gig = false, ht = false; | ||
3396 | int ret; | 3455 | int ret; |
3397 | 3456 | ||
3398 | wiphy->mgmt_stypes = ath6kl_mgmt_stypes; | 3457 | wiphy->mgmt_stypes = ath6kl_mgmt_stypes; |
@@ -3413,8 +3472,46 @@ int ath6kl_cfg80211_init(struct ath6kl *ar) | |||
3413 | /* max num of ssids that can be probed during scanning */ | 3472 | /* max num of ssids that can be probed during scanning */ |
3414 | wiphy->max_scan_ssids = MAX_PROBED_SSID_INDEX; | 3473 | wiphy->max_scan_ssids = MAX_PROBED_SSID_INDEX; |
3415 | wiphy->max_scan_ie_len = 1000; /* FIX: what is correct limit? */ | 3474 | wiphy->max_scan_ie_len = 1000; /* FIX: what is correct limit? */ |
3416 | wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz; | 3475 | switch (ar->hw.cap) { |
3417 | wiphy->bands[IEEE80211_BAND_5GHZ] = &ath6kl_band_5ghz; | 3476 | case WMI_11AN_CAP: |
3477 | ht = true; | ||
3478 | case WMI_11A_CAP: | ||
3479 | band_5gig = true; | ||
3480 | break; | ||
3481 | case WMI_11GN_CAP: | ||
3482 | ht = true; | ||
3483 | case WMI_11G_CAP: | ||
3484 | band_2gig = true; | ||
3485 | break; | ||
3486 | case WMI_11AGN_CAP: | ||
3487 | ht = true; | ||
3488 | case WMI_11AG_CAP: | ||
3489 | band_2gig = true; | ||
3490 | band_5gig = true; | ||
3491 | break; | ||
3492 | default: | ||
3493 | ath6kl_err("invalid phy capability!\n"); | ||
3494 | return -EINVAL; | ||
3495 | } | ||
3496 | |||
3497 | /* | ||
3498 | * Even if the fw has HT support, advertise HT cap only when | ||
3499 | * the firmware has support to override RSN capability, otherwise | ||
3500 | * 4-way handshake would fail. | ||
3501 | */ | ||
3502 | if (!(ht && | ||
3503 | test_bit(ATH6KL_FW_CAPABILITY_RSN_CAP_OVERRIDE, | ||
3504 | ar->fw_capabilities))) { | ||
3505 | ath6kl_band_2ghz.ht_cap.cap = 0; | ||
3506 | ath6kl_band_2ghz.ht_cap.ht_supported = false; | ||
3507 | ath6kl_band_5ghz.ht_cap.cap = 0; | ||
3508 | ath6kl_band_5ghz.ht_cap.ht_supported = false; | ||
3509 | } | ||
3510 | if (band_2gig) | ||
3511 | wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz; | ||
3512 | if (band_5gig) | ||
3513 | wiphy->bands[IEEE80211_BAND_5GHZ] = &ath6kl_band_5ghz; | ||
3514 | |||
3418 | wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; | 3515 | wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; |
3419 | 3516 | ||
3420 | wiphy->cipher_suites = cipher_suites; | 3517 | wiphy->cipher_suites = cipher_suites; |
@@ -3430,7 +3527,7 @@ int ath6kl_cfg80211_init(struct ath6kl *ar) | |||
3430 | wiphy->wowlan.pattern_min_len = 1; | 3527 | wiphy->wowlan.pattern_min_len = 1; |
3431 | wiphy->wowlan.pattern_max_len = WOW_PATTERN_SIZE; | 3528 | wiphy->wowlan.pattern_max_len = WOW_PATTERN_SIZE; |
3432 | 3529 | ||
3433 | wiphy->max_sched_scan_ssids = 10; | 3530 | wiphy->max_sched_scan_ssids = MAX_PROBED_SSID_INDEX; |
3434 | 3531 | ||
3435 | ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM | | 3532 | ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM | |
3436 | WIPHY_FLAG_HAVE_AP_SME | | 3533 | WIPHY_FLAG_HAVE_AP_SME | |
@@ -3447,8 +3544,7 @@ int ath6kl_cfg80211_init(struct ath6kl *ar) | |||
3447 | ar->wiphy->probe_resp_offload = | 3544 | ar->wiphy->probe_resp_offload = |
3448 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | | 3545 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | |
3449 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | | 3546 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | |
3450 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P | | 3547 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P; |
3451 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U; | ||
3452 | 3548 | ||
3453 | ret = wiphy_register(wiphy); | 3549 | ret = wiphy_register(wiphy); |
3454 | if (ret < 0) { | 3550 | if (ret < 0) { |