aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath6kl/cfg80211.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath/ath6kl/cfg80211.c')
-rw-r--r--drivers/net/wireless/ath/ath6kl/cfg80211.c342
1 files changed, 262 insertions, 80 deletions
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index 5370333883e4..00d38952b5fb 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (c) 2004-2011 Atheros Communications Inc. 2 * Copyright (c) 2004-2011 Atheros Communications Inc.
3 * Copyright (c) 2011-2012 Qualcomm Atheros, Inc.
3 * 4 *
4 * Permission to use, copy, modify, and/or distribute this software for any 5 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above 6 * purpose with or without fee is hereby granted, provided that the above
@@ -68,6 +69,10 @@ static struct ieee80211_rate ath6kl_rates[] = {
68#define ath6kl_g_rates (ath6kl_rates + 0) 69#define ath6kl_g_rates (ath6kl_rates + 0)
69#define ath6kl_g_rates_size 12 70#define ath6kl_g_rates_size 12
70 71
72#define ath6kl_g_htcap (IEEE80211_HT_CAP_SUP_WIDTH_20_40 | \
73 IEEE80211_HT_CAP_SGI_20 | \
74 IEEE80211_HT_CAP_SGI_40)
75
71static struct ieee80211_channel ath6kl_2ghz_channels[] = { 76static struct ieee80211_channel ath6kl_2ghz_channels[] = {
72 CHAN2G(1, 2412, 0), 77 CHAN2G(1, 2412, 0),
73 CHAN2G(2, 2417, 0), 78 CHAN2G(2, 2417, 0),
@@ -112,6 +117,8 @@ static struct ieee80211_supported_band ath6kl_band_2ghz = {
112 .channels = ath6kl_2ghz_channels, 117 .channels = ath6kl_2ghz_channels,
113 .n_bitrates = ath6kl_g_rates_size, 118 .n_bitrates = ath6kl_g_rates_size,
114 .bitrates = ath6kl_g_rates, 119 .bitrates = ath6kl_g_rates,
120 .ht_cap.cap = ath6kl_g_htcap,
121 .ht_cap.ht_supported = true,
115}; 122};
116 123
117static struct ieee80211_supported_band ath6kl_band_5ghz = { 124static struct ieee80211_supported_band ath6kl_band_5ghz = {
@@ -119,6 +126,8 @@ static struct ieee80211_supported_band ath6kl_band_5ghz = {
119 .channels = ath6kl_5ghz_a_channels, 126 .channels = ath6kl_5ghz_a_channels,
120 .n_bitrates = ath6kl_a_rates_size, 127 .n_bitrates = ath6kl_a_rates_size,
121 .bitrates = ath6kl_a_rates, 128 .bitrates = ath6kl_a_rates,
129 .ht_cap.cap = ath6kl_g_htcap,
130 .ht_cap.ht_supported = true,
122}; 131};
123 132
124#define CCKM_KRK_CIPHER_SUITE 0x004096ff /* use for KRK */ 133#define CCKM_KRK_CIPHER_SUITE 0x004096ff /* use for KRK */
@@ -381,7 +390,7 @@ static bool ath6kl_is_valid_iftype(struct ath6kl *ar, enum nl80211_iftype type,
381 return false; 390 return false;
382 391
383 if (ar->ibss_if_active || ((type == NL80211_IFTYPE_ADHOC) && 392 if (ar->ibss_if_active || ((type == NL80211_IFTYPE_ADHOC) &&
384 ar->num_vif)) 393 ar->num_vif))
385 return false; 394 return false;
386 395
387 if (type == NL80211_IFTYPE_STATION || 396 if (type == NL80211_IFTYPE_STATION ||
@@ -407,6 +416,12 @@ static bool ath6kl_is_valid_iftype(struct ath6kl *ar, enum nl80211_iftype type,
407 return false; 416 return false;
408} 417}
409 418
419static bool ath6kl_is_tx_pending(struct ath6kl *ar)
420{
421 return ar->tx_pending[ath6kl_wmi_get_control_ep(ar->wmi)] == 0;
422}
423
424
410static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, 425static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
411 struct cfg80211_connect_params *sme) 426 struct cfg80211_connect_params *sme)
412{ 427{
@@ -414,6 +429,7 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
414 struct ath6kl_vif *vif = netdev_priv(dev); 429 struct ath6kl_vif *vif = netdev_priv(dev);
415 int status; 430 int status;
416 u8 nw_subtype = (ar->p2p) ? SUBTYPE_P2PDEV : SUBTYPE_NONE; 431 u8 nw_subtype = (ar->p2p) ? SUBTYPE_P2PDEV : SUBTYPE_NONE;
432 u16 interval;
417 433
418 ath6kl_cfg80211_sscan_disable(vif); 434 ath6kl_cfg80211_sscan_disable(vif);
419 435
@@ -450,8 +466,8 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
450 * sleep until the command queue drains 466 * sleep until the command queue drains
451 */ 467 */
452 wait_event_interruptible_timeout(ar->event_wq, 468 wait_event_interruptible_timeout(ar->event_wq,
453 ar->tx_pending[ath6kl_wmi_get_control_ep(ar->wmi)] == 0, 469 ath6kl_is_tx_pending(ar),
454 WMI_TIMEOUT); 470 WMI_TIMEOUT);
455 if (signal_pending(current)) { 471 if (signal_pending(current)) {
456 ath6kl_err("cmd queue drain timeout\n"); 472 ath6kl_err("cmd queue drain timeout\n");
457 up(&ar->sem); 473 up(&ar->sem);
@@ -546,7 +562,7 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
546 if (!ar->usr_bss_filter) { 562 if (!ar->usr_bss_filter) {
547 clear_bit(CLEAR_BSSFILTER_ON_BEACON, &vif->flags); 563 clear_bit(CLEAR_BSSFILTER_ON_BEACON, &vif->flags);
548 if (ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx, 564 if (ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx,
549 ALL_BSS_FILTER, 0) != 0) { 565 ALL_BSS_FILTER, 0) != 0) {
550 ath6kl_err("couldn't set bss filtering\n"); 566 ath6kl_err("couldn't set bss filtering\n");
551 up(&ar->sem); 567 up(&ar->sem);
552 return -EIO; 568 return -EIO;
@@ -568,6 +584,20 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
568 vif->grp_crypto_len, vif->ch_hint); 584 vif->grp_crypto_len, vif->ch_hint);
569 585
570 vif->reconnect_flag = 0; 586 vif->reconnect_flag = 0;
587
588 if (vif->nw_type == INFRA_NETWORK) {
589 interval = max_t(u16, vif->listen_intvl_t,
590 ATH6KL_MAX_WOW_LISTEN_INTL);
591 status = ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx,
592 interval,
593 0);
594 if (status) {
595 ath6kl_err("couldn't set listen intervel\n");
596 up(&ar->sem);
597 return status;
598 }
599 }
600
571 status = ath6kl_wmi_connect_cmd(ar->wmi, vif->fw_vif_idx, vif->nw_type, 601 status = ath6kl_wmi_connect_cmd(ar->wmi, vif->fw_vif_idx, vif->nw_type,
572 vif->dot11_auth_mode, vif->auth_mode, 602 vif->dot11_auth_mode, vif->auth_mode,
573 vif->prwise_crypto, 603 vif->prwise_crypto,
@@ -590,8 +620,8 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
590 } 620 }
591 621
592 if ((!(ar->connect_ctrl_flags & CONNECT_DO_WPA_OFFLOAD)) && 622 if ((!(ar->connect_ctrl_flags & CONNECT_DO_WPA_OFFLOAD)) &&
593 ((vif->auth_mode == WPA_PSK_AUTH) 623 ((vif->auth_mode == WPA_PSK_AUTH) ||
594 || (vif->auth_mode == WPA2_PSK_AUTH))) { 624 (vif->auth_mode == WPA2_PSK_AUTH))) {
595 mod_timer(&vif->disconnect_timer, 625 mod_timer(&vif->disconnect_timer,
596 jiffies + msecs_to_jiffies(DISCON_TIMER_INTVAL)); 626 jiffies + msecs_to_jiffies(DISCON_TIMER_INTVAL));
597 } 627 }
@@ -824,13 +854,13 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason,
824 854
825 if (vif->sme_state == SME_CONNECTING) { 855 if (vif->sme_state == SME_CONNECTING) {
826 cfg80211_connect_result(vif->ndev, 856 cfg80211_connect_result(vif->ndev,
827 bssid, NULL, 0, 857 bssid, NULL, 0,
828 NULL, 0, 858 NULL, 0,
829 WLAN_STATUS_UNSPECIFIED_FAILURE, 859 WLAN_STATUS_UNSPECIFIED_FAILURE,
830 GFP_KERNEL); 860 GFP_KERNEL);
831 } else if (vif->sme_state == SME_CONNECTED) { 861 } else if (vif->sme_state == SME_CONNECTED) {
832 cfg80211_disconnected(vif->ndev, reason, 862 cfg80211_disconnected(vif->ndev, reason,
833 NULL, 0, GFP_KERNEL); 863 NULL, 0, GFP_KERNEL);
834 } 864 }
835 865
836 vif->sme_state = SME_DISCONNECTED; 866 vif->sme_state = SME_DISCONNECTED;
@@ -876,19 +906,14 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
876 request->ssids[i].ssid); 906 request->ssids[i].ssid);
877 } 907 }
878 908
879 /* 909 /* this also clears IE in fw if it's not set */
880 * FIXME: we should clear the IE in fw if it's not set so just 910 ret = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
881 * remove the check altogether 911 WMI_FRAME_PROBE_REQ,
882 */ 912 request->ie, request->ie_len);
883 if (request->ie) { 913 if (ret) {
884 ret = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx, 914 ath6kl_err("failed to set Probe Request appie for "
885 WMI_FRAME_PROBE_REQ, 915 "scan");
886 request->ie, request->ie_len); 916 return ret;
887 if (ret) {
888 ath6kl_err("failed to set Probe Request appie for "
889 "scan");
890 return ret;
891 }
892 } 917 }
893 918
894 /* 919 /*
@@ -917,7 +942,7 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
917 force_fg_scan = 1; 942 force_fg_scan = 1;
918 943
919 if (test_bit(ATH6KL_FW_CAPABILITY_STA_P2PDEV_DUPLEX, 944 if (test_bit(ATH6KL_FW_CAPABILITY_STA_P2PDEV_DUPLEX,
920 ar->fw_capabilities)) { 945 ar->fw_capabilities)) {
921 /* 946 /*
922 * If capable of doing P2P mgmt operations using 947 * If capable of doing P2P mgmt operations using
923 * station interface, send additional information like 948 * station interface, send additional information like
@@ -926,14 +951,17 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
926 */ 951 */
927 ret = ath6kl_wmi_beginscan_cmd(ar->wmi, vif->fw_vif_idx, 952 ret = ath6kl_wmi_beginscan_cmd(ar->wmi, vif->fw_vif_idx,
928 WMI_LONG_SCAN, force_fg_scan, 953 WMI_LONG_SCAN, force_fg_scan,
929 false, 0, 0, n_channels, 954 false, 0,
930 channels, request->no_cck, 955 ATH6KL_FG_SCAN_INTERVAL,
956 n_channels, channels,
957 request->no_cck,
931 request->rates); 958 request->rates);
932 } else { 959 } else {
933 ret = ath6kl_wmi_startscan_cmd(ar->wmi, vif->fw_vif_idx, 960 ret = ath6kl_wmi_startscan_cmd(ar->wmi, vif->fw_vif_idx,
934 WMI_LONG_SCAN, force_fg_scan, 961 WMI_LONG_SCAN, force_fg_scan,
935 false, 0, 0, n_channels, 962 false, 0,
936 channels); 963 ATH6KL_FG_SCAN_INTERVAL,
964 n_channels, channels);
937 } 965 }
938 if (ret) 966 if (ret)
939 ath6kl_err("wmi_startscan_cmd failed\n"); 967 ath6kl_err("wmi_startscan_cmd failed\n");
@@ -1046,9 +1074,9 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
1046 return -ENOTSUPP; 1074 return -ENOTSUPP;
1047 } 1075 }
1048 1076
1049 if (((vif->auth_mode == WPA_PSK_AUTH) 1077 if (((vif->auth_mode == WPA_PSK_AUTH) ||
1050 || (vif->auth_mode == WPA2_PSK_AUTH)) 1078 (vif->auth_mode == WPA2_PSK_AUTH)) &&
1051 && (key_usage & GROUP_USAGE)) 1079 (key_usage & GROUP_USAGE))
1052 del_timer(&vif->disconnect_timer); 1080 del_timer(&vif->disconnect_timer);
1053 1081
1054 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, 1082 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
@@ -1058,7 +1086,7 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
1058 1086
1059 if (vif->nw_type == AP_NETWORK && !pairwise && 1087 if (vif->nw_type == AP_NETWORK && !pairwise &&
1060 (key_type == TKIP_CRYPT || key_type == AES_CRYPT || 1088 (key_type == TKIP_CRYPT || key_type == AES_CRYPT ||
1061 key_type == WAPI_CRYPT) && params) { 1089 key_type == WAPI_CRYPT)) {
1062 ar->ap_mode_bkey.valid = true; 1090 ar->ap_mode_bkey.valid = true;
1063 ar->ap_mode_bkey.key_index = key_index; 1091 ar->ap_mode_bkey.key_index = key_index;
1064 ar->ap_mode_bkey.key_type = key_type; 1092 ar->ap_mode_bkey.key_type = key_type;
@@ -1263,7 +1291,6 @@ static int ath6kl_cfg80211_set_txpower(struct wiphy *wiphy,
1263{ 1291{
1264 struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy); 1292 struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy);
1265 struct ath6kl_vif *vif; 1293 struct ath6kl_vif *vif;
1266 u8 ath6kl_dbm;
1267 int dbm = MBM_TO_DBM(mbm); 1294 int dbm = MBM_TO_DBM(mbm);
1268 1295
1269 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type 0x%x, dbm %d\n", __func__, 1296 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type 0x%x, dbm %d\n", __func__,
@@ -1280,7 +1307,7 @@ static int ath6kl_cfg80211_set_txpower(struct wiphy *wiphy,
1280 case NL80211_TX_POWER_AUTOMATIC: 1307 case NL80211_TX_POWER_AUTOMATIC:
1281 return 0; 1308 return 0;
1282 case NL80211_TX_POWER_LIMITED: 1309 case NL80211_TX_POWER_LIMITED:
1283 ar->tx_pwr = ath6kl_dbm = dbm; 1310 ar->tx_pwr = dbm;
1284 break; 1311 break;
1285 default: 1312 default:
1286 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type 0x%x not supported\n", 1313 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type 0x%x not supported\n",
@@ -1288,7 +1315,7 @@ static int ath6kl_cfg80211_set_txpower(struct wiphy *wiphy,
1288 return -EOPNOTSUPP; 1315 return -EOPNOTSUPP;
1289 } 1316 }
1290 1317
1291 ath6kl_wmi_set_tx_pwr_cmd(ar->wmi, vif->fw_vif_idx, ath6kl_dbm); 1318 ath6kl_wmi_set_tx_pwr_cmd(ar->wmi, vif->fw_vif_idx, dbm);
1292 1319
1293 return 0; 1320 return 0;
1294} 1321}
@@ -1349,7 +1376,7 @@ static int ath6kl_cfg80211_set_power_mgmt(struct wiphy *wiphy,
1349 } 1376 }
1350 1377
1351 if (ath6kl_wmi_powermode_cmd(ar->wmi, vif->fw_vif_idx, 1378 if (ath6kl_wmi_powermode_cmd(ar->wmi, vif->fw_vif_idx,
1352 mode.pwr_mode) != 0) { 1379 mode.pwr_mode) != 0) {
1353 ath6kl_err("wmi_powermode_cmd failed\n"); 1380 ath6kl_err("wmi_powermode_cmd failed\n");
1354 return -EIO; 1381 return -EIO;
1355 } 1382 }
@@ -1904,7 +1931,7 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
1904 struct ath6kl_vif *vif; 1931 struct ath6kl_vif *vif;
1905 int ret, left; 1932 int ret, left;
1906 u32 filter = 0; 1933 u32 filter = 0;
1907 u16 i; 1934 u16 i, bmiss_time;
1908 u8 index = 0; 1935 u8 index = 0;
1909 __be32 ips[MAX_IP_ADDRS]; 1936 __be32 ips[MAX_IP_ADDRS];
1910 1937
@@ -1941,6 +1968,34 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
1941 if (ret) 1968 if (ret)
1942 return ret; 1969 return ret;
1943 1970
1971 netif_stop_queue(vif->ndev);
1972
1973 if (vif->nw_type != AP_NETWORK) {
1974 ret = ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx,
1975 ATH6KL_MAX_WOW_LISTEN_INTL,
1976 0);
1977 if (ret)
1978 return ret;
1979
1980 /* Set listen interval x 15 times as bmiss time */
1981 bmiss_time = ATH6KL_MAX_WOW_LISTEN_INTL * 15;
1982 if (bmiss_time > ATH6KL_MAX_BMISS_TIME)
1983 bmiss_time = ATH6KL_MAX_BMISS_TIME;
1984
1985 ret = ath6kl_wmi_bmisstime_cmd(ar->wmi, vif->fw_vif_idx,
1986 bmiss_time, 0);
1987 if (ret)
1988 return ret;
1989
1990 ret = ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx,
1991 0xFFFF, 0, 0xFFFF, 0, 0, 0,
1992 0, 0, 0, 0);
1993 if (ret)
1994 return ret;
1995 }
1996
1997 ar->state = ATH6KL_STATE_SUSPENDING;
1998
1944 /* Setup own IP addr for ARP agent. */ 1999 /* Setup own IP addr for ARP agent. */
1945 in_dev = __in_dev_get_rtnl(vif->ndev); 2000 in_dev = __in_dev_get_rtnl(vif->ndev);
1946 if (!in_dev) 2001 if (!in_dev)
@@ -2019,15 +2074,46 @@ static int ath6kl_wow_resume(struct ath6kl *ar)
2019 if (!vif) 2074 if (!vif)
2020 return -EIO; 2075 return -EIO;
2021 2076
2077 ar->state = ATH6KL_STATE_RESUMING;
2078
2022 ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx, 2079 ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx,
2023 ATH6KL_HOST_MODE_AWAKE); 2080 ATH6KL_HOST_MODE_AWAKE);
2024 return ret; 2081 if (ret) {
2082 ath6kl_warn("Failed to configure host sleep mode for "
2083 "wow resume: %d\n", ret);
2084 ar->state = ATH6KL_STATE_WOW;
2085 return ret;
2086 }
2087
2088 if (vif->nw_type != AP_NETWORK) {
2089 ret = ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx,
2090 0, 0, 0, 0, 0, 0, 3, 0, 0, 0);
2091 if (ret)
2092 return ret;
2093
2094 ret = ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx,
2095 vif->listen_intvl_t, 0);
2096 if (ret)
2097 return ret;
2098
2099 ret = ath6kl_wmi_bmisstime_cmd(ar->wmi, vif->fw_vif_idx,
2100 vif->bmiss_time_t, 0);
2101 if (ret)
2102 return ret;
2103 }
2104
2105 ar->state = ATH6KL_STATE_ON;
2106
2107 netif_wake_queue(vif->ndev);
2108
2109 return 0;
2025} 2110}
2026 2111
2027int ath6kl_cfg80211_suspend(struct ath6kl *ar, 2112int ath6kl_cfg80211_suspend(struct ath6kl *ar,
2028 enum ath6kl_cfg_suspend_mode mode, 2113 enum ath6kl_cfg_suspend_mode mode,
2029 struct cfg80211_wowlan *wow) 2114 struct cfg80211_wowlan *wow)
2030{ 2115{
2116 enum ath6kl_state prev_state;
2031 int ret; 2117 int ret;
2032 2118
2033 switch (mode) { 2119 switch (mode) {
@@ -2038,11 +2124,14 @@ int ath6kl_cfg80211_suspend(struct ath6kl *ar,
2038 /* Flush all non control pkts in TX path */ 2124 /* Flush all non control pkts in TX path */
2039 ath6kl_tx_data_cleanup(ar); 2125 ath6kl_tx_data_cleanup(ar);
2040 2126
2127 prev_state = ar->state;
2128
2041 ret = ath6kl_wow_suspend(ar, wow); 2129 ret = ath6kl_wow_suspend(ar, wow);
2042 if (ret) { 2130 if (ret) {
2043 ath6kl_err("wow suspend failed: %d\n", ret); 2131 ar->state = prev_state;
2044 return ret; 2132 return ret;
2045 } 2133 }
2134
2046 ar->state = ATH6KL_STATE_WOW; 2135 ar->state = ATH6KL_STATE_WOW;
2047 break; 2136 break;
2048 2137
@@ -2114,7 +2203,6 @@ int ath6kl_cfg80211_resume(struct ath6kl *ar)
2114 return ret; 2203 return ret;
2115 } 2204 }
2116 2205
2117 ar->state = ATH6KL_STATE_ON;
2118 break; 2206 break;
2119 2207
2120 case ATH6KL_STATE_DEEPSLEEP: 2208 case ATH6KL_STATE_DEEPSLEEP:
@@ -2188,6 +2276,9 @@ static int __ath6kl_cfg80211_resume(struct wiphy *wiphy)
2188 */ 2276 */
2189void ath6kl_check_wow_status(struct ath6kl *ar) 2277void ath6kl_check_wow_status(struct ath6kl *ar)
2190{ 2278{
2279 if (ar->state == ATH6KL_STATE_SUSPENDING)
2280 return;
2281
2191 if (ar->state == ATH6KL_STATE_WOW) 2282 if (ar->state == ATH6KL_STATE_WOW)
2192 ath6kl_cfg80211_resume(ar); 2283 ath6kl_cfg80211_resume(ar);
2193} 2284}
@@ -2275,30 +2366,27 @@ static int ath6kl_set_ies(struct ath6kl_vif *vif,
2275 struct ath6kl *ar = vif->ar; 2366 struct ath6kl *ar = vif->ar;
2276 int res; 2367 int res;
2277 2368
2278 if (info->beacon_ies) { 2369 /* this also clears IE in fw if it's not set */
2279 res = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx, 2370 res = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
2280 WMI_FRAME_BEACON, 2371 WMI_FRAME_BEACON,
2281 info->beacon_ies, 2372 info->beacon_ies,
2282 info->beacon_ies_len); 2373 info->beacon_ies_len);
2283 if (res) 2374 if (res)
2284 return res; 2375 return res;
2285 }
2286 2376
2287 if (info->proberesp_ies) { 2377 /* this also clears IE in fw if it's not set */
2288 res = ath6kl_set_ap_probe_resp_ies(vif, info->proberesp_ies, 2378 res = ath6kl_set_ap_probe_resp_ies(vif, info->proberesp_ies,
2289 info->proberesp_ies_len); 2379 info->proberesp_ies_len);
2290 if (res) 2380 if (res)
2291 return res; 2381 return res;
2292 }
2293 2382
2294 if (info->assocresp_ies) { 2383 /* this also clears IE in fw if it's not set */
2295 res = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx, 2384 res = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
2296 WMI_FRAME_ASSOC_RESP, 2385 WMI_FRAME_ASSOC_RESP,
2297 info->assocresp_ies, 2386 info->assocresp_ies,
2298 info->assocresp_ies_len); 2387 info->assocresp_ies_len);
2299 if (res) 2388 if (res)
2300 return res; 2389 return res;
2301 }
2302 2390
2303 return 0; 2391 return 0;
2304} 2392}
@@ -2309,6 +2397,7 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,
2309 struct ath6kl *ar = ath6kl_priv(dev); 2397 struct ath6kl *ar = ath6kl_priv(dev);
2310 struct ath6kl_vif *vif = netdev_priv(dev); 2398 struct ath6kl_vif *vif = netdev_priv(dev);
2311 struct ieee80211_mgmt *mgmt; 2399 struct ieee80211_mgmt *mgmt;
2400 bool hidden = false;
2312 u8 *ies; 2401 u8 *ies;
2313 int ies_len; 2402 int ies_len;
2314 struct wmi_connect_cmd p; 2403 struct wmi_connect_cmd p;
@@ -2345,7 +2434,11 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,
2345 memcpy(vif->ssid, info->ssid, info->ssid_len); 2434 memcpy(vif->ssid, info->ssid, info->ssid_len);
2346 vif->ssid_len = info->ssid_len; 2435 vif->ssid_len = info->ssid_len;
2347 if (info->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE) 2436 if (info->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
2348 return -EOPNOTSUPP; /* TODO */ 2437 hidden = true;
2438
2439 res = ath6kl_wmi_ap_hidden_ssid(ar->wmi, vif->fw_vif_idx, hidden);
2440 if (res)
2441 return res;
2349 2442
2350 ret = ath6kl_set_auth_type(vif, info->auth_type); 2443 ret = ath6kl_set_auth_type(vif, info->auth_type);
2351 if (ret) 2444 if (ret)
@@ -2584,6 +2677,76 @@ static int ath6kl_send_go_probe_resp(struct ath6kl_vif *vif,
2584 return ret; 2677 return ret;
2585} 2678}
2586 2679
2680static bool ath6kl_mgmt_powersave_ap(struct ath6kl_vif *vif,
2681 u32 id,
2682 u32 freq,
2683 u32 wait,
2684 const u8 *buf,
2685 size_t len,
2686 bool *more_data,
2687 bool no_cck)
2688{
2689 struct ieee80211_mgmt *mgmt;
2690 struct ath6kl_sta *conn;
2691 bool is_psq_empty = false;
2692 struct ath6kl_mgmt_buff *mgmt_buf;
2693 size_t mgmt_buf_size;
2694 struct ath6kl *ar = vif->ar;
2695
2696 mgmt = (struct ieee80211_mgmt *) buf;
2697 if (is_multicast_ether_addr(mgmt->da))
2698 return false;
2699
2700 conn = ath6kl_find_sta(vif, mgmt->da);
2701 if (!conn)
2702 return false;
2703
2704 if (conn->sta_flags & STA_PS_SLEEP) {
2705 if (!(conn->sta_flags & STA_PS_POLLED)) {
2706 /* Queue the frames if the STA is sleeping */
2707 mgmt_buf_size = len + sizeof(struct ath6kl_mgmt_buff);
2708 mgmt_buf = kmalloc(mgmt_buf_size, GFP_KERNEL);
2709 if (!mgmt_buf)
2710 return false;
2711
2712 INIT_LIST_HEAD(&mgmt_buf->list);
2713 mgmt_buf->id = id;
2714 mgmt_buf->freq = freq;
2715 mgmt_buf->wait = wait;
2716 mgmt_buf->len = len;
2717 mgmt_buf->no_cck = no_cck;
2718 memcpy(mgmt_buf->buf, buf, len);
2719 spin_lock_bh(&conn->psq_lock);
2720 is_psq_empty = skb_queue_empty(&conn->psq) &&
2721 (conn->mgmt_psq_len == 0);
2722 list_add_tail(&mgmt_buf->list, &conn->mgmt_psq);
2723 conn->mgmt_psq_len++;
2724 spin_unlock_bh(&conn->psq_lock);
2725
2726 /*
2727 * If this is the first pkt getting queued
2728 * for this STA, update the PVB for this
2729 * STA.
2730 */
2731 if (is_psq_empty)
2732 ath6kl_wmi_set_pvb_cmd(ar->wmi, vif->fw_vif_idx,
2733 conn->aid, 1);
2734 return true;
2735 }
2736
2737 /*
2738 * This tx is because of a PsPoll.
2739 * Determine if MoreData bit has to be set.
2740 */
2741 spin_lock_bh(&conn->psq_lock);
2742 if (!skb_queue_empty(&conn->psq) || (conn->mgmt_psq_len != 0))
2743 *more_data = true;
2744 spin_unlock_bh(&conn->psq_lock);
2745 }
2746
2747 return false;
2748}
2749
2587static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, 2750static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
2588 struct ieee80211_channel *chan, bool offchan, 2751 struct ieee80211_channel *chan, bool offchan,
2589 enum nl80211_channel_type channel_type, 2752 enum nl80211_channel_type channel_type,
@@ -2595,6 +2758,7 @@ static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
2595 struct ath6kl_vif *vif = netdev_priv(dev); 2758 struct ath6kl_vif *vif = netdev_priv(dev);
2596 u32 id; 2759 u32 id;
2597 const struct ieee80211_mgmt *mgmt; 2760 const struct ieee80211_mgmt *mgmt;
2761 bool more_data, queued;
2598 2762
2599 mgmt = (const struct ieee80211_mgmt *) buf; 2763 mgmt = (const struct ieee80211_mgmt *) buf;
2600 if (buf + len >= mgmt->u.probe_resp.variable && 2764 if (buf + len >= mgmt->u.probe_resp.variable &&
@@ -2620,22 +2784,19 @@ static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
2620 2784
2621 *cookie = id; 2785 *cookie = id;
2622 2786
2623 if (test_bit(ATH6KL_FW_CAPABILITY_STA_P2PDEV_DUPLEX, 2787 /* AP mode Power saving processing */
2624 ar->fw_capabilities)) { 2788 if (vif->nw_type == AP_NETWORK) {
2625 /* 2789 queued = ath6kl_mgmt_powersave_ap(vif,
2626 * If capable of doing P2P mgmt operations using 2790 id, chan->center_freq,
2627 * station interface, send additional information like 2791 wait, buf,
2628 * supported rates to advertise and xmit rates for 2792 len, &more_data, no_cck);
2629 * probe requests 2793 if (queued)
2630 */ 2794 return 0;
2631 return ath6kl_wmi_send_mgmt_cmd(ar->wmi, vif->fw_vif_idx, id,
2632 chan->center_freq, wait,
2633 buf, len, no_cck);
2634 } else {
2635 return ath6kl_wmi_send_action_cmd(ar->wmi, vif->fw_vif_idx, id,
2636 chan->center_freq, wait,
2637 buf, len);
2638 } 2795 }
2796
2797 return ath6kl_wmi_send_mgmt_cmd(ar->wmi, vif->fw_vif_idx, id,
2798 chan->center_freq, wait,
2799 buf, len, no_cck);
2639} 2800}
2640 2801
2641static void ath6kl_mgmt_frame_register(struct wiphy *wiphy, 2802static void ath6kl_mgmt_frame_register(struct wiphy *wiphy,
@@ -2929,7 +3090,10 @@ struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name,
2929 vif->wdev.netdev = ndev; 3090 vif->wdev.netdev = ndev;
2930 vif->wdev.iftype = type; 3091 vif->wdev.iftype = type;
2931 vif->fw_vif_idx = fw_vif_idx; 3092 vif->fw_vif_idx = fw_vif_idx;
2932 vif->nw_type = vif->next_mode = nw_type; 3093 vif->nw_type = nw_type;
3094 vif->next_mode = nw_type;
3095 vif->listen_intvl_t = ATH6KL_DEFAULT_LISTEN_INTVAL;
3096 vif->bmiss_time_t = ATH6KL_DEFAULT_BMISS_TIME;
2933 3097
2934 memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN); 3098 memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN);
2935 if (fw_vif_idx != 0) 3099 if (fw_vif_idx != 0)
@@ -3009,18 +3173,36 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
3009 3173
3010 wiphy->max_sched_scan_ssids = 10; 3174 wiphy->max_sched_scan_ssids = 10;
3011 3175
3176 ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM |
3177 WIPHY_FLAG_HAVE_AP_SME |
3178 WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
3179 WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
3180
3181 if (test_bit(ATH6KL_FW_CAPABILITY_SCHED_SCAN, ar->fw_capabilities))
3182 ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
3183
3184 ar->wiphy->probe_resp_offload =
3185 NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |
3186 NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 |
3187 NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P |
3188 NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U;
3189
3012 ret = wiphy_register(wiphy); 3190 ret = wiphy_register(wiphy);
3013 if (ret < 0) { 3191 if (ret < 0) {
3014 ath6kl_err("couldn't register wiphy device\n"); 3192 ath6kl_err("couldn't register wiphy device\n");
3015 return ret; 3193 return ret;
3016 } 3194 }
3017 3195
3196 ar->wiphy_registered = true;
3197
3018 return 0; 3198 return 0;
3019} 3199}
3020 3200
3021void ath6kl_cfg80211_cleanup(struct ath6kl *ar) 3201void ath6kl_cfg80211_cleanup(struct ath6kl *ar)
3022{ 3202{
3023 wiphy_unregister(ar->wiphy); 3203 wiphy_unregister(ar->wiphy);
3204
3205 ar->wiphy_registered = false;
3024} 3206}
3025 3207
3026struct ath6kl *ath6kl_cfg80211_create(void) 3208struct ath6kl *ath6kl_cfg80211_create(void)