aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2012-11-16 14:08:14 -0500
committerJohn W. Linville <linville@tuxdriver.com>2012-11-16 14:08:14 -0500
commit1e5023c7cc11158f74a637aa92897da954572a25 (patch)
treea0b2234b331abf9b2c80dbce20a018d537e541a6
parentdfbebe14428803402293d9a8bf1efef7221d8b78 (diff)
parentff7e68670c49b6404acc4fce6ca90d6c89ef0efe (diff)
Merge branch 'for-linville' of git://github.com/kvalo/ath6kl
-rw-r--r--drivers/net/wireless/ath/ath6kl/Kconfig9
-rw-r--r--drivers/net/wireless/ath/ath6kl/Makefile1
-rw-r--r--drivers/net/wireless/ath/ath6kl/cfg80211.c370
-rw-r--r--drivers/net/wireless/ath/ath6kl/cfg80211.h1
-rw-r--r--drivers/net/wireless/ath/ath6kl/core.c21
-rw-r--r--drivers/net/wireless/ath/ath6kl/core.h69
-rw-r--r--drivers/net/wireless/ath/ath6kl/debug.h1
-rw-r--r--drivers/net/wireless/ath/ath6kl/hif.c6
-rw-r--r--drivers/net/wireless/ath/ath6kl/htc_mbox.c13
-rw-r--r--drivers/net/wireless/ath/ath6kl/htc_pipe.c14
-rw-r--r--drivers/net/wireless/ath/ath6kl/init.c92
-rw-r--r--drivers/net/wireless/ath/ath6kl/main.c55
-rw-r--r--drivers/net/wireless/ath/ath6kl/recovery.c160
-rw-r--r--drivers/net/wireless/ath/ath6kl/sdio.c27
-rw-r--r--drivers/net/wireless/ath/ath6kl/txrx.c47
-rw-r--r--drivers/net/wireless/ath/ath6kl/usb.c32
-rw-r--r--drivers/net/wireless/ath/ath6kl/wmi.c279
-rw-r--r--drivers/net/wireless/ath/ath6kl/wmi.h78
18 files changed, 990 insertions, 285 deletions
diff --git a/drivers/net/wireless/ath/ath6kl/Kconfig b/drivers/net/wireless/ath/ath6kl/Kconfig
index d755a5e7ed2..26c4b722085 100644
--- a/drivers/net/wireless/ath/ath6kl/Kconfig
+++ b/drivers/net/wireless/ath/ath6kl/Kconfig
@@ -30,3 +30,12 @@ config ATH6KL_DEBUG
30 depends on ATH6KL 30 depends on ATH6KL
31 ---help--- 31 ---help---
32 Enables debug support 32 Enables debug support
33
34config ATH6KL_REGDOMAIN
35 bool "Atheros ath6kl regdomain support"
36 depends on ATH6KL
37 depends on CFG80211_CERTIFICATION_ONUS
38 ---help---
39 Enabling this makes it possible to change the regdomain in
40 the firmware. This can be only enabled if regulatory requirements
41 are taken into account.
diff --git a/drivers/net/wireless/ath/ath6kl/Makefile b/drivers/net/wireless/ath/ath6kl/Makefile
index 8cae8886f17..cab0ec0d538 100644
--- a/drivers/net/wireless/ath/ath6kl/Makefile
+++ b/drivers/net/wireless/ath/ath6kl/Makefile
@@ -34,6 +34,7 @@ ath6kl_core-y += main.o
34ath6kl_core-y += txrx.o 34ath6kl_core-y += txrx.o
35ath6kl_core-y += wmi.o 35ath6kl_core-y += wmi.o
36ath6kl_core-y += core.o 36ath6kl_core-y += core.o
37ath6kl_core-y += recovery.o
37ath6kl_core-$(CONFIG_NL80211_TESTMODE) += testmode.o 38ath6kl_core-$(CONFIG_NL80211_TESTMODE) += testmode.o
38 39
39obj-$(CONFIG_ATH6KL_SDIO) += ath6kl_sdio.o 40obj-$(CONFIG_ATH6KL_SDIO) += ath6kl_sdio.o
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index d615f9f7506..83d8c5eabbe 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -147,15 +147,15 @@ static bool __ath6kl_cfg80211_sscan_stop(struct ath6kl_vif *vif)
147{ 147{
148 struct ath6kl *ar = vif->ar; 148 struct ath6kl *ar = vif->ar;
149 149
150 if (ar->state != ATH6KL_STATE_SCHED_SCAN) 150 if (!test_and_clear_bit(SCHED_SCANNING, &vif->flags))
151 return false; 151 return false;
152 152
153 del_timer_sync(&vif->sched_scan_timer); 153 del_timer_sync(&vif->sched_scan_timer);
154 154
155 ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx, 155 if (ar->state == ATH6KL_STATE_RECOVERY)
156 ATH6KL_HOST_MODE_AWAKE); 156 return true;
157 157
158 ar->state = ATH6KL_STATE_ON; 158 ath6kl_wmi_enable_sched_scan_cmd(ar->wmi, vif->fw_vif_idx, false);
159 159
160 return true; 160 return true;
161} 161}
@@ -369,17 +369,13 @@ static int ath6kl_nliftype_to_drv_iftype(enum nl80211_iftype type, u8 *nw_type)
369{ 369{
370 switch (type) { 370 switch (type) {
371 case NL80211_IFTYPE_STATION: 371 case NL80211_IFTYPE_STATION:
372 case NL80211_IFTYPE_P2P_CLIENT:
372 *nw_type = INFRA_NETWORK; 373 *nw_type = INFRA_NETWORK;
373 break; 374 break;
374 case NL80211_IFTYPE_ADHOC: 375 case NL80211_IFTYPE_ADHOC:
375 *nw_type = ADHOC_NETWORK; 376 *nw_type = ADHOC_NETWORK;
376 break; 377 break;
377 case NL80211_IFTYPE_AP: 378 case NL80211_IFTYPE_AP:
378 *nw_type = AP_NETWORK;
379 break;
380 case NL80211_IFTYPE_P2P_CLIENT:
381 *nw_type = INFRA_NETWORK;
382 break;
383 case NL80211_IFTYPE_P2P_GO: 379 case NL80211_IFTYPE_P2P_GO:
384 *nw_type = AP_NETWORK; 380 *nw_type = AP_NETWORK;
385 break; 381 break;
@@ -1031,30 +1027,15 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy,
1031 1027
1032 vif->scan_req = request; 1028 vif->scan_req = request;
1033 1029
1034 if (test_bit(ATH6KL_FW_CAPABILITY_STA_P2PDEV_DUPLEX, 1030 ret = ath6kl_wmi_beginscan_cmd(ar->wmi, vif->fw_vif_idx,
1035 ar->fw_capabilities)) { 1031 WMI_LONG_SCAN, force_fg_scan,
1036 /* 1032 false, 0,
1037 * If capable of doing P2P mgmt operations using 1033 ATH6KL_FG_SCAN_INTERVAL,
1038 * station interface, send additional information like 1034 n_channels, channels,
1039 * supported rates to advertise and xmit rates for 1035 request->no_cck,
1040 * probe requests 1036 request->rates);
1041 */
1042 ret = ath6kl_wmi_beginscan_cmd(ar->wmi, vif->fw_vif_idx,
1043 WMI_LONG_SCAN, force_fg_scan,
1044 false, 0,
1045 ATH6KL_FG_SCAN_INTERVAL,
1046 n_channels, channels,
1047 request->no_cck,
1048 request->rates);
1049 } else {
1050 ret = ath6kl_wmi_startscan_cmd(ar->wmi, vif->fw_vif_idx,
1051 WMI_LONG_SCAN, force_fg_scan,
1052 false, 0,
1053 ATH6KL_FG_SCAN_INTERVAL,
1054 n_channels, channels);
1055 }
1056 if (ret) { 1037 if (ret) {
1057 ath6kl_err("wmi_startscan_cmd failed\n"); 1038 ath6kl_err("failed to start scan: %d\n", ret);
1058 vif->scan_req = NULL; 1039 vif->scan_req = NULL;
1059 } 1040 }
1060 1041
@@ -1888,7 +1869,7 @@ static int ath6kl_wow_usr(struct ath6kl *ar, struct ath6kl_vif *vif,
1888 struct cfg80211_wowlan *wow, u32 *filter) 1869 struct cfg80211_wowlan *wow, u32 *filter)
1889{ 1870{
1890 int ret, pos; 1871 int ret, pos;
1891 u8 mask[WOW_MASK_SIZE]; 1872 u8 mask[WOW_PATTERN_SIZE];
1892 u16 i; 1873 u16 i;
1893 1874
1894 /* Configure the patterns that we received from the user. */ 1875 /* Configure the patterns that we received from the user. */
@@ -2106,33 +2087,16 @@ static int ath6kl_cfg80211_host_sleep(struct ath6kl *ar, struct ath6kl_vif *vif)
2106 return ret; 2087 return ret;
2107} 2088}
2108 2089
2109static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow) 2090static int ath6kl_wow_suspend_vif(struct ath6kl_vif *vif,
2091 struct cfg80211_wowlan *wow, u32 *filter)
2110{ 2092{
2093 struct ath6kl *ar = vif->ar;
2111 struct in_device *in_dev; 2094 struct in_device *in_dev;
2112 struct in_ifaddr *ifa; 2095 struct in_ifaddr *ifa;
2113 struct ath6kl_vif *vif;
2114 int ret; 2096 int ret;
2115 u32 filter = 0;
2116 u16 i, bmiss_time; 2097 u16 i, bmiss_time;
2117 u8 index = 0;
2118 __be32 ips[MAX_IP_ADDRS]; 2098 __be32 ips[MAX_IP_ADDRS];
2119 2099 u8 index = 0;
2120 /* The FW currently can't support multi-vif WoW properly. */
2121 if (ar->num_vif > 1)
2122 return -EIO;
2123
2124 vif = ath6kl_vif_first(ar);
2125 if (!vif)
2126 return -EIO;
2127
2128 if (!ath6kl_cfg80211_ready(vif))
2129 return -EIO;
2130
2131 if (!test_bit(CONNECTED, &vif->flags))
2132 return -ENOTCONN;
2133
2134 if (wow && (wow->n_patterns > WOW_MAX_FILTERS_PER_LIST))
2135 return -EINVAL;
2136 2100
2137 if (!test_bit(NETDEV_MCAST_ALL_ON, &vif->flags) && 2101 if (!test_bit(NETDEV_MCAST_ALL_ON, &vif->flags) &&
2138 test_bit(ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER, 2102 test_bit(ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER,
@@ -2154,7 +2118,7 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
2154 * the user. 2118 * the user.
2155 */ 2119 */
2156 if (wow) 2120 if (wow)
2157 ret = ath6kl_wow_usr(ar, vif, wow, &filter); 2121 ret = ath6kl_wow_usr(ar, vif, wow, filter);
2158 else if (vif->nw_type == AP_NETWORK) 2122 else if (vif->nw_type == AP_NETWORK)
2159 ret = ath6kl_wow_ap(ar, vif); 2123 ret = ath6kl_wow_ap(ar, vif);
2160 else 2124 else
@@ -2189,12 +2153,10 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
2189 return ret; 2153 return ret;
2190 } 2154 }
2191 2155
2192 ar->state = ATH6KL_STATE_SUSPENDING;
2193
2194 /* Setup own IP addr for ARP agent. */ 2156 /* Setup own IP addr for ARP agent. */
2195 in_dev = __in_dev_get_rtnl(vif->ndev); 2157 in_dev = __in_dev_get_rtnl(vif->ndev);
2196 if (!in_dev) 2158 if (!in_dev)
2197 goto skip_arp; 2159 return 0;
2198 2160
2199 ifa = in_dev->ifa_list; 2161 ifa = in_dev->ifa_list;
2200 memset(&ips, 0, sizeof(ips)); 2162 memset(&ips, 0, sizeof(ips));
@@ -2217,41 +2179,61 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
2217 return ret; 2179 return ret;
2218 } 2180 }
2219 2181
2220skip_arp: 2182 return ret;
2221 ret = ath6kl_wmi_set_wow_mode_cmd(ar->wmi, vif->fw_vif_idx, 2183}
2184
2185static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
2186{
2187 struct ath6kl_vif *first_vif, *vif;
2188 int ret = 0;
2189 u32 filter = 0;
2190 bool connected = false;
2191
2192 /* enter / leave wow suspend on first vif always */
2193 first_vif = ath6kl_vif_first(ar);
2194 if (WARN_ON(unlikely(!first_vif)) ||
2195 !ath6kl_cfg80211_ready(first_vif))
2196 return -EIO;
2197
2198 if (wow && (wow->n_patterns > WOW_MAX_FILTERS_PER_LIST))
2199 return -EINVAL;
2200
2201 /* install filters for each connected vif */
2202 spin_lock_bh(&ar->list_lock);
2203 list_for_each_entry(vif, &ar->vif_list, list) {
2204 if (!test_bit(CONNECTED, &vif->flags) ||
2205 !ath6kl_cfg80211_ready(vif))
2206 continue;
2207 connected = true;
2208
2209 ret = ath6kl_wow_suspend_vif(vif, wow, &filter);
2210 if (ret)
2211 break;
2212 }
2213 spin_unlock_bh(&ar->list_lock);
2214
2215 if (!connected)
2216 return -ENOTCONN;
2217 else if (ret)
2218 return ret;
2219
2220 ar->state = ATH6KL_STATE_SUSPENDING;
2221
2222 ret = ath6kl_wmi_set_wow_mode_cmd(ar->wmi, first_vif->fw_vif_idx,
2222 ATH6KL_WOW_MODE_ENABLE, 2223 ATH6KL_WOW_MODE_ENABLE,
2223 filter, 2224 filter,
2224 WOW_HOST_REQ_DELAY); 2225 WOW_HOST_REQ_DELAY);
2225 if (ret) 2226 if (ret)
2226 return ret; 2227 return ret;
2227 2228
2228 ret = ath6kl_cfg80211_host_sleep(ar, vif); 2229 return ath6kl_cfg80211_host_sleep(ar, first_vif);
2229 if (ret)
2230 return ret;
2231
2232 return 0;
2233} 2230}
2234 2231
2235static int ath6kl_wow_resume(struct ath6kl *ar) 2232static int ath6kl_wow_resume_vif(struct ath6kl_vif *vif)
2236{ 2233{
2237 struct ath6kl_vif *vif; 2234 struct ath6kl *ar = vif->ar;
2238 int ret; 2235 int ret;
2239 2236
2240 vif = ath6kl_vif_first(ar);
2241 if (!vif)
2242 return -EIO;
2243
2244 ar->state = ATH6KL_STATE_RESUMING;
2245
2246 ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx,
2247 ATH6KL_HOST_MODE_AWAKE);
2248 if (ret) {
2249 ath6kl_warn("Failed to configure host sleep mode for wow resume: %d\n",
2250 ret);
2251 ar->state = ATH6KL_STATE_WOW;
2252 return ret;
2253 }
2254
2255 if (vif->nw_type != AP_NETWORK) { 2237 if (vif->nw_type != AP_NETWORK) {
2256 ret = ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx, 2238 ret = ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx,
2257 0, 0, 0, 0, 0, 0, 3, 0, 0, 0); 2239 0, 0, 0, 0, 0, 0, 3, 0, 0, 0);
@@ -2269,13 +2251,11 @@ static int ath6kl_wow_resume(struct ath6kl *ar)
2269 return ret; 2251 return ret;
2270 } 2252 }
2271 2253
2272 ar->state = ATH6KL_STATE_ON;
2273
2274 if (!test_bit(NETDEV_MCAST_ALL_OFF, &vif->flags) && 2254 if (!test_bit(NETDEV_MCAST_ALL_OFF, &vif->flags) &&
2275 test_bit(ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER, 2255 test_bit(ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER,
2276 ar->fw_capabilities)) { 2256 ar->fw_capabilities)) {
2277 ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi, 2257 ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi,
2278 vif->fw_vif_idx, true); 2258 vif->fw_vif_idx, true);
2279 if (ret) 2259 if (ret)
2280 return ret; 2260 return ret;
2281 } 2261 }
@@ -2285,6 +2265,48 @@ static int ath6kl_wow_resume(struct ath6kl *ar)
2285 return 0; 2265 return 0;
2286} 2266}
2287 2267
2268static int ath6kl_wow_resume(struct ath6kl *ar)
2269{
2270 struct ath6kl_vif *vif;
2271 int ret;
2272
2273 vif = ath6kl_vif_first(ar);
2274 if (WARN_ON(unlikely(!vif)) ||
2275 !ath6kl_cfg80211_ready(vif))
2276 return -EIO;
2277
2278 ar->state = ATH6KL_STATE_RESUMING;
2279
2280 ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx,
2281 ATH6KL_HOST_MODE_AWAKE);
2282 if (ret) {
2283 ath6kl_warn("Failed to configure host sleep mode for wow resume: %d\n",
2284 ret);
2285 goto cleanup;
2286 }
2287
2288 spin_lock_bh(&ar->list_lock);
2289 list_for_each_entry(vif, &ar->vif_list, list) {
2290 if (!test_bit(CONNECTED, &vif->flags) ||
2291 !ath6kl_cfg80211_ready(vif))
2292 continue;
2293 ret = ath6kl_wow_resume_vif(vif);
2294 if (ret)
2295 break;
2296 }
2297 spin_unlock_bh(&ar->list_lock);
2298
2299 if (ret)
2300 goto cleanup;
2301
2302 ar->state = ATH6KL_STATE_ON;
2303 return 0;
2304
2305cleanup:
2306 ar->state = ATH6KL_STATE_WOW;
2307 return ret;
2308}
2309
2288static int ath6kl_cfg80211_deepsleep_suspend(struct ath6kl *ar) 2310static int ath6kl_cfg80211_deepsleep_suspend(struct ath6kl *ar)
2289{ 2311{
2290 struct ath6kl_vif *vif; 2312 struct ath6kl_vif *vif;
@@ -2421,13 +2443,6 @@ int ath6kl_cfg80211_suspend(struct ath6kl *ar,
2421 2443
2422 break; 2444 break;
2423 2445
2424 case ATH6KL_CFG_SUSPEND_SCHED_SCAN:
2425 /*
2426 * Nothing needed for schedule scan, firmware is already in
2427 * wow mode and sleeping most of the time.
2428 */
2429 break;
2430
2431 default: 2446 default:
2432 break; 2447 break;
2433 } 2448 }
@@ -2475,9 +2490,6 @@ int ath6kl_cfg80211_resume(struct ath6kl *ar)
2475 } 2490 }
2476 break; 2491 break;
2477 2492
2478 case ATH6KL_STATE_SCHED_SCAN:
2479 break;
2480
2481 default: 2493 default:
2482 break; 2494 break;
2483 } 2495 }
@@ -2494,14 +2506,23 @@ static int __ath6kl_cfg80211_suspend(struct wiphy *wiphy,
2494{ 2506{
2495 struct ath6kl *ar = wiphy_priv(wiphy); 2507 struct ath6kl *ar = wiphy_priv(wiphy);
2496 2508
2509 ath6kl_recovery_suspend(ar);
2510
2497 return ath6kl_hif_suspend(ar, wow); 2511 return ath6kl_hif_suspend(ar, wow);
2498} 2512}
2499 2513
2500static int __ath6kl_cfg80211_resume(struct wiphy *wiphy) 2514static int __ath6kl_cfg80211_resume(struct wiphy *wiphy)
2501{ 2515{
2502 struct ath6kl *ar = wiphy_priv(wiphy); 2516 struct ath6kl *ar = wiphy_priv(wiphy);
2517 int err;
2518
2519 err = ath6kl_hif_resume(ar);
2520 if (err)
2521 return err;
2522
2523 ath6kl_recovery_resume(ar);
2503 2524
2504 return ath6kl_hif_resume(ar); 2525 return 0;
2505} 2526}
2506 2527
2507/* 2528/*
@@ -2738,6 +2759,7 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,
2738 int res; 2759 int res;
2739 int i, ret; 2760 int i, ret;
2740 u16 rsn_capab = 0; 2761 u16 rsn_capab = 0;
2762 int inactivity_timeout = 0;
2741 2763
2742 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s:\n", __func__); 2764 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s:\n", __func__);
2743 2765
@@ -2874,8 +2896,15 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,
2874 } 2896 }
2875 2897
2876 if (info->inactivity_timeout) { 2898 if (info->inactivity_timeout) {
2899
2900 inactivity_timeout = info->inactivity_timeout;
2901
2902 if (ar->hw.flags & ATH6KL_HW_AP_INACTIVITY_MINS)
2903 inactivity_timeout = DIV_ROUND_UP(inactivity_timeout,
2904 60);
2905
2877 res = ath6kl_wmi_set_inact_period(ar->wmi, vif->fw_vif_idx, 2906 res = ath6kl_wmi_set_inact_period(ar->wmi, vif->fw_vif_idx,
2878 info->inactivity_timeout); 2907 inactivity_timeout);
2879 if (res < 0) 2908 if (res < 0)
2880 return res; 2909 return res;
2881 } 2910 }
@@ -2897,6 +2926,7 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,
2897 WLAN_EID_RSN, WMI_RSN_IE_CAPB, 2926 WLAN_EID_RSN, WMI_RSN_IE_CAPB,
2898 (const u8 *) &rsn_capab, 2927 (const u8 *) &rsn_capab,
2899 sizeof(rsn_capab)); 2928 sizeof(rsn_capab));
2929 vif->rsn_capab = rsn_capab;
2900 if (res < 0) 2930 if (res < 0)
2901 return res; 2931 return res;
2902 } 2932 }
@@ -3210,7 +3240,7 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
3210 struct ath6kl *ar = ath6kl_priv(dev); 3240 struct ath6kl *ar = ath6kl_priv(dev);
3211 struct ath6kl_vif *vif = netdev_priv(dev); 3241 struct ath6kl_vif *vif = netdev_priv(dev);
3212 u16 interval; 3242 u16 interval;
3213 int ret; 3243 int ret, rssi_thold;
3214 3244
3215 if (ar->state != ATH6KL_STATE_ON) 3245 if (ar->state != ATH6KL_STATE_ON)
3216 return -EIO; 3246 return -EIO;
@@ -3218,10 +3248,6 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
3218 if (vif->sme_state != SME_DISCONNECTED) 3248 if (vif->sme_state != SME_DISCONNECTED)
3219 return -EBUSY; 3249 return -EBUSY;
3220 3250
3221 /* The FW currently can't support multi-vif WoW properly. */
3222 if (ar->num_vif > 1)
3223 return -EIO;
3224
3225 ath6kl_cfg80211_scan_complete_event(vif, true); 3251 ath6kl_cfg80211_scan_complete_event(vif, true);
3226 3252
3227 ret = ath6kl_set_probed_ssids(ar, vif, request->ssids, 3253 ret = ath6kl_set_probed_ssids(ar, vif, request->ssids,
@@ -3243,6 +3269,23 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
3243 return ret; 3269 return ret;
3244 } 3270 }
3245 3271
3272 if (test_bit(ATH6KL_FW_CAPABILITY_RSSI_SCAN_THOLD,
3273 ar->fw_capabilities)) {
3274 if (request->rssi_thold <= NL80211_SCAN_RSSI_THOLD_OFF)
3275 rssi_thold = 0;
3276 else if (request->rssi_thold < -127)
3277 rssi_thold = -127;
3278 else
3279 rssi_thold = request->rssi_thold;
3280
3281 ret = ath6kl_wmi_set_rssi_filter_cmd(ar->wmi, vif->fw_vif_idx,
3282 rssi_thold);
3283 if (ret) {
3284 ath6kl_err("failed to set RSSI threshold for scan\n");
3285 return ret;
3286 }
3287 }
3288
3246 /* fw uses seconds, also make sure that it's >0 */ 3289 /* fw uses seconds, also make sure that it's >0 */
3247 interval = max_t(u16, 1, request->interval / 1000); 3290 interval = max_t(u16, 1, request->interval / 1000);
3248 3291
@@ -3250,15 +3293,6 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
3250 interval, interval, 3293 interval, interval,
3251 vif->bg_scan_period, 0, 0, 0, 3, 0, 0, 0); 3294 vif->bg_scan_period, 0, 0, 0, 3, 0, 0, 0);
3252 3295
3253 ret = ath6kl_wmi_set_wow_mode_cmd(ar->wmi, vif->fw_vif_idx,
3254 ATH6KL_WOW_MODE_ENABLE,
3255 WOW_FILTER_SSID,
3256 WOW_HOST_REQ_DELAY);
3257 if (ret) {
3258 ath6kl_warn("Failed to enable wow with ssid filter: %d\n", ret);
3259 return ret;
3260 }
3261
3262 /* this also clears IE in fw if it's not set */ 3296 /* this also clears IE in fw if it's not set */
3263 ret = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx, 3297 ret = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
3264 WMI_FRAME_PROBE_REQ, 3298 WMI_FRAME_PROBE_REQ,
@@ -3269,17 +3303,13 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
3269 return ret; 3303 return ret;
3270 } 3304 }
3271 3305
3272 ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx, 3306 ret = ath6kl_wmi_enable_sched_scan_cmd(ar->wmi, vif->fw_vif_idx, true);
3273 ATH6KL_HOST_MODE_ASLEEP); 3307 if (ret)
3274 if (ret) {
3275 ath6kl_warn("Failed to enable host sleep mode for sched scan: %d\n",
3276 ret);
3277 return ret; 3308 return ret;
3278 }
3279 3309
3280 ar->state = ATH6KL_STATE_SCHED_SCAN; 3310 set_bit(SCHED_SCANNING, &vif->flags);
3281 3311
3282 return ret; 3312 return 0;
3283} 3313}
3284 3314
3285static int ath6kl_cfg80211_sscan_stop(struct wiphy *wiphy, 3315static int ath6kl_cfg80211_sscan_stop(struct wiphy *wiphy,
@@ -3308,6 +3338,27 @@ static int ath6kl_cfg80211_set_bitrate(struct wiphy *wiphy,
3308 mask); 3338 mask);
3309} 3339}
3310 3340
3341static int ath6kl_cfg80211_set_txe_config(struct wiphy *wiphy,
3342 struct net_device *dev,
3343 u32 rate, u32 pkts, u32 intvl)
3344{
3345 struct ath6kl *ar = ath6kl_priv(dev);
3346 struct ath6kl_vif *vif = netdev_priv(dev);
3347
3348 if (vif->nw_type != INFRA_NETWORK ||
3349 !test_bit(ATH6KL_FW_CAPABILITY_TX_ERR_NOTIFY, ar->fw_capabilities))
3350 return -EOPNOTSUPP;
3351
3352 if (vif->sme_state != SME_CONNECTED)
3353 return -ENOTCONN;
3354
3355 /* save this since the firmware won't report the interval */
3356 vif->txe_intvl = intvl;
3357
3358 return ath6kl_wmi_set_txe_notify(ar->wmi, vif->fw_vif_idx,
3359 rate, pkts, intvl);
3360}
3361
3311static const struct ieee80211_txrx_stypes 3362static const struct ieee80211_txrx_stypes
3312ath6kl_mgmt_stypes[NUM_NL80211_IFTYPES] = { 3363ath6kl_mgmt_stypes[NUM_NL80211_IFTYPES] = {
3313 [NL80211_IFTYPE_STATION] = { 3364 [NL80211_IFTYPE_STATION] = {
@@ -3374,6 +3425,7 @@ static struct cfg80211_ops ath6kl_cfg80211_ops = {
3374 .sched_scan_start = ath6kl_cfg80211_sscan_start, 3425 .sched_scan_start = ath6kl_cfg80211_sscan_start,
3375 .sched_scan_stop = ath6kl_cfg80211_sscan_stop, 3426 .sched_scan_stop = ath6kl_cfg80211_sscan_stop,
3376 .set_bitrate_mask = ath6kl_cfg80211_set_bitrate, 3427 .set_bitrate_mask = ath6kl_cfg80211_set_bitrate,
3428 .set_cqm_txe_config = ath6kl_cfg80211_set_txe_config,
3377}; 3429};
3378 3430
3379void ath6kl_cfg80211_stop(struct ath6kl_vif *vif) 3431void ath6kl_cfg80211_stop(struct ath6kl_vif *vif)
@@ -3394,16 +3446,22 @@ void ath6kl_cfg80211_stop(struct ath6kl_vif *vif)
3394 break; 3446 break;
3395 } 3447 }
3396 3448
3397 if (test_bit(CONNECTED, &vif->flags) || 3449 if (vif->ar->state != ATH6KL_STATE_RECOVERY &&
3398 test_bit(CONNECT_PEND, &vif->flags)) 3450 (test_bit(CONNECTED, &vif->flags) ||
3451 test_bit(CONNECT_PEND, &vif->flags)))
3399 ath6kl_wmi_disconnect_cmd(vif->ar->wmi, vif->fw_vif_idx); 3452 ath6kl_wmi_disconnect_cmd(vif->ar->wmi, vif->fw_vif_idx);
3400 3453
3401 vif->sme_state = SME_DISCONNECTED; 3454 vif->sme_state = SME_DISCONNECTED;
3402 clear_bit(CONNECTED, &vif->flags); 3455 clear_bit(CONNECTED, &vif->flags);
3403 clear_bit(CONNECT_PEND, &vif->flags); 3456 clear_bit(CONNECT_PEND, &vif->flags);
3404 3457
3458 /* Stop netdev queues, needed during recovery */
3459 netif_stop_queue(vif->ndev);
3460 netif_carrier_off(vif->ndev);
3461
3405 /* disable scanning */ 3462 /* disable scanning */
3406 if (ath6kl_wmi_scanparams_cmd(vif->ar->wmi, vif->fw_vif_idx, 0xFFFF, 3463 if (vif->ar->state != ATH6KL_STATE_RECOVERY &&
3464 ath6kl_wmi_scanparams_cmd(vif->ar->wmi, vif->fw_vif_idx, 0xFFFF,
3407 0, 0, 0, 0, 0, 0, 0, 0, 0) != 0) 3465 0, 0, 0, 0, 0, 0, 0, 0, 0) != 0)
3408 ath6kl_warn("failed to disable scan during stop\n"); 3466 ath6kl_warn("failed to disable scan during stop\n");
3409 3467
@@ -3415,7 +3473,7 @@ void ath6kl_cfg80211_stop_all(struct ath6kl *ar)
3415 struct ath6kl_vif *vif; 3473 struct ath6kl_vif *vif;
3416 3474
3417 vif = ath6kl_vif_first(ar); 3475 vif = ath6kl_vif_first(ar);
3418 if (!vif) { 3476 if (!vif && ar->state != ATH6KL_STATE_RECOVERY) {
3419 /* save the current power mode before enabling power save */ 3477 /* save the current power mode before enabling power save */
3420 ar->wmi->saved_pwr_mode = ar->wmi->pwr_mode; 3478 ar->wmi->saved_pwr_mode = ar->wmi->pwr_mode;
3421 3479
@@ -3433,6 +3491,56 @@ void ath6kl_cfg80211_stop_all(struct ath6kl *ar)
3433 ath6kl_cfg80211_stop(vif); 3491 ath6kl_cfg80211_stop(vif);
3434} 3492}
3435 3493
3494static int ath6kl_cfg80211_reg_notify(struct wiphy *wiphy,
3495 struct regulatory_request *request)
3496{
3497 struct ath6kl *ar = wiphy_priv(wiphy);
3498 u32 rates[IEEE80211_NUM_BANDS];
3499 int ret, i;
3500
3501 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
3502 "cfg reg_notify %c%c%s%s initiator %d hint_type %d\n",
3503 request->alpha2[0], request->alpha2[1],
3504 request->intersect ? " intersect" : "",
3505 request->processed ? " processed" : "",
3506 request->initiator, request->user_reg_hint_type);
3507
3508 /*
3509 * As firmware is not able intersect regdoms, we can only listen to
3510 * cellular hints.
3511 */
3512 if (request->user_reg_hint_type != NL80211_USER_REG_HINT_CELL_BASE)
3513 return -EOPNOTSUPP;
3514
3515 ret = ath6kl_wmi_set_regdomain_cmd(ar->wmi, request->alpha2);
3516 if (ret) {
3517 ath6kl_err("failed to set regdomain: %d\n", ret);
3518 return ret;
3519 }
3520
3521 /*
3522 * Firmware will apply the regdomain change only after a scan is
3523 * issued and it will send a WMI_REGDOMAIN_EVENTID when it has been
3524 * changed.
3525 */
3526
3527 for (i = 0; i < IEEE80211_NUM_BANDS; i++)
3528 if (wiphy->bands[i])
3529 rates[i] = (1 << wiphy->bands[i]->n_bitrates) - 1;
3530
3531
3532 ret = ath6kl_wmi_beginscan_cmd(ar->wmi, 0, WMI_LONG_SCAN, false,
3533 false, 0, ATH6KL_FG_SCAN_INTERVAL,
3534 0, NULL, false, rates);
3535 if (ret) {
3536 ath6kl_err("failed to start scan for a regdomain change: %d\n",
3537 ret);
3538 return ret;
3539 }
3540
3541 return 0;
3542}
3543
3436static int ath6kl_cfg80211_vif_init(struct ath6kl_vif *vif) 3544static int ath6kl_cfg80211_vif_init(struct ath6kl_vif *vif)
3437{ 3545{
3438 vif->aggr_cntxt = aggr_init(vif); 3546 vif->aggr_cntxt = aggr_init(vif);
@@ -3505,9 +3613,13 @@ struct wireless_dev *ath6kl_interface_add(struct ath6kl *ar, const char *name,
3505 vif->htcap[IEEE80211_BAND_5GHZ].ht_enable = true; 3613 vif->htcap[IEEE80211_BAND_5GHZ].ht_enable = true;
3506 3614
3507 memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN); 3615 memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN);
3508 if (fw_vif_idx != 0) 3616 if (fw_vif_idx != 0) {
3509 ndev->dev_addr[0] = (ndev->dev_addr[0] ^ (1 << fw_vif_idx)) | 3617 ndev->dev_addr[0] = (ndev->dev_addr[0] ^ (1 << fw_vif_idx)) |
3510 0x2; 3618 0x2;
3619 if (test_bit(ATH6KL_FW_CAPABILITY_CUSTOM_MAC_ADDR,
3620 ar->fw_capabilities))
3621 ndev->dev_addr[4] ^= 0x80;
3622 }
3511 3623
3512 init_netdev(ndev); 3624 init_netdev(ndev);
3513 3625
@@ -3561,6 +3673,12 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
3561 BIT(NL80211_IFTYPE_P2P_CLIENT); 3673 BIT(NL80211_IFTYPE_P2P_CLIENT);
3562 } 3674 }
3563 3675
3676 if (config_enabled(CONFIG_ATH6KL_REGDOMAIN) &&
3677 test_bit(ATH6KL_FW_CAPABILITY_REGDOMAIN, ar->fw_capabilities)) {
3678 wiphy->reg_notifier = ath6kl_cfg80211_reg_notify;
3679 ar->wiphy->features |= NL80211_FEATURE_CELL_BASE_REG_HINTS;
3680 }
3681
3564 /* max num of ssids that can be probed during scanning */ 3682 /* max num of ssids that can be probed during scanning */
3565 wiphy->max_scan_ssids = MAX_PROBED_SSIDS; 3683 wiphy->max_scan_ssids = MAX_PROBED_SSIDS;
3566 3684
@@ -3606,7 +3724,7 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
3606 ath6kl_band_5ghz.ht_cap.ht_supported = false; 3724 ath6kl_band_5ghz.ht_cap.ht_supported = false;
3607 } 3725 }
3608 3726
3609 if (ar->hw.flags & ATH6KL_HW_FLAG_64BIT_RATES) { 3727 if (ar->hw.flags & ATH6KL_HW_64BIT_RATES) {
3610 ath6kl_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff; 3728 ath6kl_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff;
3611 ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff; 3729 ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff;
3612 ath6kl_band_2ghz.ht_cap.mcs.rx_mask[1] = 0xff; 3730 ath6kl_band_2ghz.ht_cap.mcs.rx_mask[1] = 0xff;
@@ -3645,7 +3763,7 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
3645 WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | 3763 WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
3646 WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD; 3764 WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
3647 3765
3648 if (test_bit(ATH6KL_FW_CAPABILITY_SCHED_SCAN, ar->fw_capabilities)) 3766 if (test_bit(ATH6KL_FW_CAPABILITY_SCHED_SCAN_V2, ar->fw_capabilities))
3649 ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; 3767 ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
3650 3768
3651 if (test_bit(ATH6KL_FW_CAPABILITY_INACTIVITY_TIMEOUT, 3769 if (test_bit(ATH6KL_FW_CAPABILITY_INACTIVITY_TIMEOUT,
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.h b/drivers/net/wireless/ath/ath6kl/cfg80211.h
index 780f77775a9..e5e70f3a8ca 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.h
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.h
@@ -22,7 +22,6 @@ enum ath6kl_cfg_suspend_mode {
22 ATH6KL_CFG_SUSPEND_DEEPSLEEP, 22 ATH6KL_CFG_SUSPEND_DEEPSLEEP,
23 ATH6KL_CFG_SUSPEND_CUTPOWER, 23 ATH6KL_CFG_SUSPEND_CUTPOWER,
24 ATH6KL_CFG_SUSPEND_WOW, 24 ATH6KL_CFG_SUSPEND_WOW,
25 ATH6KL_CFG_SUSPEND_SCHED_SCAN,
26}; 25};
27 26
28struct wireless_dev *ath6kl_interface_add(struct ath6kl *ar, const char *name, 27struct wireless_dev *ath6kl_interface_add(struct ath6kl *ar, const char *name,
diff --git a/drivers/net/wireless/ath/ath6kl/core.c b/drivers/net/wireless/ath/ath6kl/core.c
index 82c4dd2a960..4b46adbe8c9 100644
--- a/drivers/net/wireless/ath/ath6kl/core.c
+++ b/drivers/net/wireless/ath/ath6kl/core.c
@@ -33,6 +33,8 @@ static unsigned int wow_mode;
33static unsigned int uart_debug; 33static unsigned int uart_debug;
34static unsigned int ath6kl_p2p; 34static unsigned int ath6kl_p2p;
35static unsigned int testmode; 35static unsigned int testmode;
36static unsigned int recovery_enable;
37static unsigned int heart_beat_poll;
36 38
37module_param(debug_mask, uint, 0644); 39module_param(debug_mask, uint, 0644);
38module_param(suspend_mode, uint, 0644); 40module_param(suspend_mode, uint, 0644);
@@ -40,6 +42,12 @@ module_param(wow_mode, uint, 0644);
40module_param(uart_debug, uint, 0644); 42module_param(uart_debug, uint, 0644);
41module_param(ath6kl_p2p, uint, 0644); 43module_param(ath6kl_p2p, uint, 0644);
42module_param(testmode, uint, 0644); 44module_param(testmode, uint, 0644);
45module_param(recovery_enable, uint, 0644);
46module_param(heart_beat_poll, uint, 0644);
47MODULE_PARM_DESC(recovery_enable, "Enable recovery from firmware error");
48MODULE_PARM_DESC(heart_beat_poll, "Enable fw error detection periodic" \
49 "polling. This also specifies the polling interval in" \
50 "msecs. Set reocvery_enable for this to be effective");
43 51
44void ath6kl_core_tx_complete(struct ath6kl *ar, struct sk_buff *skb) 52void ath6kl_core_tx_complete(struct ath6kl *ar, struct sk_buff *skb)
45{ 53{
@@ -202,6 +210,17 @@ int ath6kl_core_init(struct ath6kl *ar, enum ath6kl_htc_type htc_type)
202 ath6kl_dbg(ATH6KL_DBG_TRC, "%s: name=%s dev=0x%p, ar=0x%p\n", 210 ath6kl_dbg(ATH6KL_DBG_TRC, "%s: name=%s dev=0x%p, ar=0x%p\n",
203 __func__, wdev->netdev->name, wdev->netdev, ar); 211 __func__, wdev->netdev->name, wdev->netdev, ar);
204 212
213 ar->fw_recovery.enable = !!recovery_enable;
214 if (!ar->fw_recovery.enable)
215 return ret;
216
217 if (heart_beat_poll &&
218 test_bit(ATH6KL_FW_CAPABILITY_HEART_BEAT_POLL,
219 ar->fw_capabilities))
220 ar->fw_recovery.hb_poll = heart_beat_poll;
221
222 ath6kl_recovery_init(ar);
223
205 return ret; 224 return ret;
206 225
207err_rxbuf_cleanup: 226err_rxbuf_cleanup:
@@ -291,6 +310,8 @@ void ath6kl_core_cleanup(struct ath6kl *ar)
291{ 310{
292 ath6kl_hif_power_off(ar); 311 ath6kl_hif_power_off(ar);
293 312
313 ath6kl_recovery_cleanup(ar);
314
294 destroy_workqueue(ar->ath6kl_wq); 315 destroy_workqueue(ar->ath6kl_wq);
295 316
296 if (ar->htc_target) 317 if (ar->htc_target)
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h
index cec49a31029..189d8faf8c8 100644
--- a/drivers/net/wireless/ath/ath6kl/core.h
+++ b/drivers/net/wireless/ath/ath6kl/core.h
@@ -115,6 +115,27 @@ enum ath6kl_fw_capability {
115 */ 115 */
116 ATH6KL_FW_CAPABILITY_SCHED_SCAN_MATCH_LIST, 116 ATH6KL_FW_CAPABILITY_SCHED_SCAN_MATCH_LIST,
117 117
118 /* Firmware supports filtering BSS results by RSSI */
119 ATH6KL_FW_CAPABILITY_RSSI_SCAN_THOLD,
120
121 /* FW sets mac_addr[4] ^= 0x80 for newly created interfaces */
122 ATH6KL_FW_CAPABILITY_CUSTOM_MAC_ADDR,
123
124 /* Firmware supports TX error rate notification */
125 ATH6KL_FW_CAPABILITY_TX_ERR_NOTIFY,
126
127 /* supports WMI_SET_REGDOMAIN_CMDID command */
128 ATH6KL_FW_CAPABILITY_REGDOMAIN,
129
130 /* Firmware supports sched scan decoupled from host sleep */
131 ATH6KL_FW_CAPABILITY_SCHED_SCAN_V2,
132
133 /*
134 * Firmware capability for hang detection through heart beat
135 * challenge messages.
136 */
137 ATH6KL_FW_CAPABILITY_HEART_BEAT_POLL,
138
118 /* this needs to be last */ 139 /* this needs to be last */
119 ATH6KL_FW_CAPABILITY_MAX, 140 ATH6KL_FW_CAPABILITY_MAX,
120}; 141};
@@ -128,11 +149,15 @@ struct ath6kl_fw_ie {
128}; 149};
129 150
130enum ath6kl_hw_flags { 151enum ath6kl_hw_flags {
131 ATH6KL_HW_FLAG_64BIT_RATES = BIT(0), 152 ATH6KL_HW_64BIT_RATES = BIT(0),
153 ATH6KL_HW_AP_INACTIVITY_MINS = BIT(1),
154 ATH6KL_HW_MAP_LP_ENDPOINT = BIT(2),
155 ATH6KL_HW_SDIO_CRC_ERROR_WAR = BIT(3),
132}; 156};
133 157
134#define ATH6KL_FW_API2_FILE "fw-2.bin" 158#define ATH6KL_FW_API2_FILE "fw-2.bin"
135#define ATH6KL_FW_API3_FILE "fw-3.bin" 159#define ATH6KL_FW_API3_FILE "fw-3.bin"
160#define ATH6KL_FW_API4_FILE "fw-4.bin"
136 161
137/* AR6003 1.0 definitions */ 162/* AR6003 1.0 definitions */
138#define AR6003_HW_1_0_VERSION 0x300002ba 163#define AR6003_HW_1_0_VERSION 0x300002ba
@@ -186,6 +211,13 @@ enum ath6kl_hw_flags {
186#define AR6004_HW_1_2_DEFAULT_BOARD_DATA_FILE \ 211#define AR6004_HW_1_2_DEFAULT_BOARD_DATA_FILE \
187 AR6004_HW_1_2_FW_DIR "/bdata.bin" 212 AR6004_HW_1_2_FW_DIR "/bdata.bin"
188 213
214/* AR6004 1.3 definitions */
215#define AR6004_HW_1_3_VERSION 0x31c8088a
216#define AR6004_HW_1_3_FW_DIR "ath6k/AR6004/hw1.3"
217#define AR6004_HW_1_3_FIRMWARE_FILE "fw.ram.bin"
218#define AR6004_HW_1_3_BOARD_DATA_FILE "ath6k/AR6004/hw1.3/bdata.bin"
219#define AR6004_HW_1_3_DEFAULT_BOARD_DATA_FILE "ath6k/AR6004/hw1.3/bdata.bin"
220
189/* Per STA data, used in AP mode */ 221/* Per STA data, used in AP mode */
190#define STA_PS_AWAKE BIT(0) 222#define STA_PS_AWAKE BIT(0)
191#define STA_PS_SLEEP BIT(1) 223#define STA_PS_SLEEP BIT(1)
@@ -536,6 +568,7 @@ enum ath6kl_vif_state {
536 HOST_SLEEP_MODE_CMD_PROCESSED, 568 HOST_SLEEP_MODE_CMD_PROCESSED,
537 NETDEV_MCAST_ALL_ON, 569 NETDEV_MCAST_ALL_ON,
538 NETDEV_MCAST_ALL_OFF, 570 NETDEV_MCAST_ALL_OFF,
571 SCHED_SCANNING,
539}; 572};
540 573
541struct ath6kl_vif { 574struct ath6kl_vif {
@@ -580,11 +613,13 @@ struct ath6kl_vif {
580 u16 assoc_bss_beacon_int; 613 u16 assoc_bss_beacon_int;
581 u16 listen_intvl_t; 614 u16 listen_intvl_t;
582 u16 bmiss_time_t; 615 u16 bmiss_time_t;
616 u32 txe_intvl;
583 u16 bg_scan_period; 617 u16 bg_scan_period;
584 u8 assoc_bss_dtim_period; 618 u8 assoc_bss_dtim_period;
585 struct net_device_stats net_stats; 619 struct net_device_stats net_stats;
586 struct target_stats target_stats; 620 struct target_stats target_stats;
587 struct wmi_connect_cmd profile; 621 struct wmi_connect_cmd profile;
622 u16 rsn_capab;
588 623
589 struct list_head mc_filter; 624 struct list_head mc_filter;
590}; 625};
@@ -609,6 +644,7 @@ enum ath6kl_dev_state {
609 SKIP_SCAN, 644 SKIP_SCAN,
610 ROAM_TBL_PEND, 645 ROAM_TBL_PEND,
611 FIRST_BOOT, 646 FIRST_BOOT,
647 RECOVERY_CLEANUP,
612}; 648};
613 649
614enum ath6kl_state { 650enum ath6kl_state {
@@ -619,7 +655,16 @@ enum ath6kl_state {
619 ATH6KL_STATE_DEEPSLEEP, 655 ATH6KL_STATE_DEEPSLEEP,
620 ATH6KL_STATE_CUTPOWER, 656 ATH6KL_STATE_CUTPOWER,
621 ATH6KL_STATE_WOW, 657 ATH6KL_STATE_WOW,
622 ATH6KL_STATE_SCHED_SCAN, 658 ATH6KL_STATE_RECOVERY,
659};
660
661/* Fw error recovery */
662#define ATH6KL_HB_RESP_MISS_THRES 5
663
664enum ath6kl_fw_err {
665 ATH6KL_FW_ASSERT,
666 ATH6KL_FW_HB_RESP_FAILURE,
667 ATH6KL_FW_EP_FULL,
623}; 668};
624 669
625struct ath6kl { 670struct ath6kl {
@@ -679,6 +724,7 @@ struct ath6kl {
679 struct ath6kl_req_key ap_mode_bkey; 724 struct ath6kl_req_key ap_mode_bkey;
680 struct sk_buff_head mcastpsq; 725 struct sk_buff_head mcastpsq;
681 u32 want_ch_switch; 726 u32 want_ch_switch;
727 u16 last_ch;
682 728
683 /* 729 /*
684 * FIXME: protects access to mcastpsq but is actually useless as 730 * FIXME: protects access to mcastpsq but is actually useless as
@@ -764,6 +810,17 @@ struct ath6kl {
764 810
765 bool wiphy_registered; 811 bool wiphy_registered;
766 812
813 struct ath6kl_fw_recovery {
814 struct work_struct recovery_work;
815 unsigned long err_reason;
816 unsigned long hb_poll;
817 struct timer_list hb_timer;
818 u32 seq_num;
819 bool hb_pending;
820 u8 hb_misscnt;
821 bool enable;
822 } fw_recovery;
823
767#ifdef CONFIG_ATH6KL_DEBUG 824#ifdef CONFIG_ATH6KL_DEBUG
768 struct { 825 struct {
769 struct sk_buff_head fwlog_queue; 826 struct sk_buff_head fwlog_queue;
@@ -899,4 +956,12 @@ int ath6kl_core_init(struct ath6kl *ar, enum ath6kl_htc_type htc_type);
899void ath6kl_core_cleanup(struct ath6kl *ar); 956void ath6kl_core_cleanup(struct ath6kl *ar);
900void ath6kl_core_destroy(struct ath6kl *ar); 957void ath6kl_core_destroy(struct ath6kl *ar);
901 958
959/* Fw error recovery */
960void ath6kl_init_hw_restart(struct ath6kl *ar);
961void ath6kl_recovery_err_notify(struct ath6kl *ar, enum ath6kl_fw_err reason);
962void ath6kl_recovery_hb_event(struct ath6kl *ar, u32 cookie);
963void ath6kl_recovery_init(struct ath6kl *ar);
964void ath6kl_recovery_cleanup(struct ath6kl *ar);
965void ath6kl_recovery_suspend(struct ath6kl *ar);
966void ath6kl_recovery_resume(struct ath6kl *ar);
902#endif /* CORE_H */ 967#endif /* CORE_H */
diff --git a/drivers/net/wireless/ath/ath6kl/debug.h b/drivers/net/wireless/ath/ath6kl/debug.h
index 49639d8266c..f97cd4ead54 100644
--- a/drivers/net/wireless/ath/ath6kl/debug.h
+++ b/drivers/net/wireless/ath/ath6kl/debug.h
@@ -44,6 +44,7 @@ enum ATH6K_DEBUG_MASK {
44 ATH6KL_DBG_SUSPEND = BIT(20), 44 ATH6KL_DBG_SUSPEND = BIT(20),
45 ATH6KL_DBG_USB = BIT(21), 45 ATH6KL_DBG_USB = BIT(21),
46 ATH6KL_DBG_USB_BULK = BIT(22), 46 ATH6KL_DBG_USB_BULK = BIT(22),
47 ATH6KL_DBG_RECOVERY = BIT(23),
47 ATH6KL_DBG_ANY = 0xffffffff /* enable all logs */ 48 ATH6KL_DBG_ANY = 0xffffffff /* enable all logs */
48}; 49};
49 50
diff --git a/drivers/net/wireless/ath/ath6kl/hif.c b/drivers/net/wireless/ath/ath6kl/hif.c
index 9e47c4a138a..a6b614421fa 100644
--- a/drivers/net/wireless/ath/ath6kl/hif.c
+++ b/drivers/net/wireless/ath/ath6kl/hif.c
@@ -136,6 +136,7 @@ static int ath6kl_hif_proc_dbg_intr(struct ath6kl_device *dev)
136 136
137 ath6kl_hif_dump_fw_crash(dev->ar); 137 ath6kl_hif_dump_fw_crash(dev->ar);
138 ath6kl_read_fwlogs(dev->ar); 138 ath6kl_read_fwlogs(dev->ar);
139 ath6kl_recovery_err_notify(dev->ar, ATH6KL_FW_ASSERT);
139 140
140 return ret; 141 return ret;
141} 142}
@@ -693,11 +694,6 @@ int ath6kl_hif_setup(struct ath6kl_device *dev)
693 ath6kl_dbg(ATH6KL_DBG_HIF, "hif block size %d mbox addr 0x%x\n", 694 ath6kl_dbg(ATH6KL_DBG_HIF, "hif block size %d mbox addr 0x%x\n",
694 dev->htc_cnxt->block_sz, dev->ar->mbox_info.htc_addr); 695 dev->htc_cnxt->block_sz, dev->ar->mbox_info.htc_addr);
695 696
696 /* usb doesn't support enabling interrupts */
697 /* FIXME: remove check once USB support is implemented */
698 if (dev->ar->hif_type == ATH6KL_HIF_TYPE_USB)
699 return 0;
700
701 status = ath6kl_hif_disable_intrs(dev); 697 status = ath6kl_hif_disable_intrs(dev);
702 698
703fail_setup: 699fail_setup:
diff --git a/drivers/net/wireless/ath/ath6kl/htc_mbox.c b/drivers/net/wireless/ath/ath6kl/htc_mbox.c
index cd0e1ba410d..fbb78dfe078 100644
--- a/drivers/net/wireless/ath/ath6kl/htc_mbox.c
+++ b/drivers/net/wireless/ath/ath6kl/htc_mbox.c
@@ -2492,7 +2492,8 @@ static int ath6kl_htc_mbox_conn_service(struct htc_target *target,
2492 max_msg_sz = le16_to_cpu(resp_msg->max_msg_sz); 2492 max_msg_sz = le16_to_cpu(resp_msg->max_msg_sz);
2493 } 2493 }
2494 2494
2495 if (assigned_ep >= ENDPOINT_MAX || !max_msg_sz) { 2495 if (WARN_ON_ONCE(assigned_ep == ENDPOINT_UNUSED ||
2496 assigned_ep >= ENDPOINT_MAX || !max_msg_sz)) {
2496 status = -ENOMEM; 2497 status = -ENOMEM;
2497 goto fail_tx; 2498 goto fail_tx;
2498 } 2499 }
@@ -2655,12 +2656,6 @@ static int ath6kl_htc_mbox_wait_target(struct htc_target *target)
2655 struct htc_service_connect_resp resp; 2656 struct htc_service_connect_resp resp;
2656 int status; 2657 int status;
2657 2658
2658 /* FIXME: remove once USB support is implemented */
2659 if (target->dev->ar->hif_type == ATH6KL_HIF_TYPE_USB) {
2660 ath6kl_err("HTC doesn't support USB yet. Patience!\n");
2661 return -EOPNOTSUPP;
2662 }
2663
2664 /* we should be getting 1 control message that the target is ready */ 2659 /* we should be getting 1 control message that the target is ready */
2665 packet = htc_wait_for_ctrl_msg(target); 2660 packet = htc_wait_for_ctrl_msg(target);
2666 2661
@@ -2890,9 +2885,7 @@ static void ath6kl_htc_mbox_cleanup(struct htc_target *target)
2890{ 2885{
2891 struct htc_packet *packet, *tmp_packet; 2886 struct htc_packet *packet, *tmp_packet;
2892 2887
2893 /* FIXME: remove check once USB support is implemented */ 2888 ath6kl_hif_cleanup_scatter(target->dev->ar);
2894 if (target->dev->ar->hif_type != ATH6KL_HIF_TYPE_USB)
2895 ath6kl_hif_cleanup_scatter(target->dev->ar);
2896 2889
2897 list_for_each_entry_safe(packet, tmp_packet, 2890 list_for_each_entry_safe(packet, tmp_packet,
2898 &target->free_ctrl_txbuf, list) { 2891 &target->free_ctrl_txbuf, list) {
diff --git a/drivers/net/wireless/ath/ath6kl/htc_pipe.c b/drivers/net/wireless/ath/ath6kl/htc_pipe.c
index f9626c72369..ba6bd497b78 100644
--- a/drivers/net/wireless/ath/ath6kl/htc_pipe.c
+++ b/drivers/net/wireless/ath/ath6kl/htc_pipe.c
@@ -374,9 +374,8 @@ static enum htc_send_queue_result htc_try_send(struct htc_target *target,
374 packet = list_first_entry(txq, 374 packet = list_first_entry(txq,
375 struct htc_packet, 375 struct htc_packet,
376 list); 376 list);
377 list_del(&packet->list); 377 /* move to local queue */
378 /* insert into local queue */ 378 list_move_tail(&packet->list, &send_queue);
379 list_add_tail(&packet->list, &send_queue);
380 } 379 }
381 380
382 /* 381 /*
@@ -399,11 +398,10 @@ static enum htc_send_queue_result htc_try_send(struct htc_target *target,
399 * for cleanup */ 398 * for cleanup */
400 } else { 399 } else {
401 /* callback wants to keep this packet, 400 /* callback wants to keep this packet,
402 * remove from caller's queue */ 401 * move from caller's queue to the send
403 list_del(&packet->list); 402 * queue */
404 /* put it in the send queue */ 403 list_move_tail(&packet->list,
405 list_add_tail(&packet->list, 404 &send_queue);
406 &send_queue);
407 } 405 }
408 406
409 } 407 }
diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c
index f90b5db741c..f21fa322e5c 100644
--- a/drivers/net/wireless/ath/ath6kl/init.c
+++ b/drivers/net/wireless/ath/ath6kl/init.c
@@ -42,7 +42,7 @@ static const struct ath6kl_hw hw_list[] = {
42 .reserved_ram_size = 6912, 42 .reserved_ram_size = 6912,
43 .refclk_hz = 26000000, 43 .refclk_hz = 26000000,
44 .uarttx_pin = 8, 44 .uarttx_pin = 8,
45 .flags = 0, 45 .flags = ATH6KL_HW_SDIO_CRC_ERROR_WAR,
46 46
47 /* hw2.0 needs override address hardcoded */ 47 /* hw2.0 needs override address hardcoded */
48 .app_start_override_addr = 0x944C00, 48 .app_start_override_addr = 0x944C00,
@@ -68,7 +68,7 @@ static const struct ath6kl_hw hw_list[] = {
68 .refclk_hz = 26000000, 68 .refclk_hz = 26000000,
69 .uarttx_pin = 8, 69 .uarttx_pin = 8,
70 .testscript_addr = 0x57ef74, 70 .testscript_addr = 0x57ef74,
71 .flags = 0, 71 .flags = ATH6KL_HW_SDIO_CRC_ERROR_WAR,
72 72
73 .fw = { 73 .fw = {
74 .dir = AR6003_HW_2_1_1_FW_DIR, 74 .dir = AR6003_HW_2_1_1_FW_DIR,
@@ -93,7 +93,8 @@ static const struct ath6kl_hw hw_list[] = {
93 .board_addr = 0x433900, 93 .board_addr = 0x433900,
94 .refclk_hz = 26000000, 94 .refclk_hz = 26000000,
95 .uarttx_pin = 11, 95 .uarttx_pin = 11,
96 .flags = ATH6KL_HW_FLAG_64BIT_RATES, 96 .flags = ATH6KL_HW_64BIT_RATES |
97 ATH6KL_HW_AP_INACTIVITY_MINS,
97 98
98 .fw = { 99 .fw = {
99 .dir = AR6004_HW_1_0_FW_DIR, 100 .dir = AR6004_HW_1_0_FW_DIR,
@@ -113,8 +114,8 @@ static const struct ath6kl_hw hw_list[] = {
113 .board_addr = 0x43d400, 114 .board_addr = 0x43d400,
114 .refclk_hz = 40000000, 115 .refclk_hz = 40000000,
115 .uarttx_pin = 11, 116 .uarttx_pin = 11,
116 .flags = ATH6KL_HW_FLAG_64BIT_RATES, 117 .flags = ATH6KL_HW_64BIT_RATES |
117 118 ATH6KL_HW_AP_INACTIVITY_MINS,
118 .fw = { 119 .fw = {
119 .dir = AR6004_HW_1_1_FW_DIR, 120 .dir = AR6004_HW_1_1_FW_DIR,
120 .fw = AR6004_HW_1_1_FIRMWARE_FILE, 121 .fw = AR6004_HW_1_1_FIRMWARE_FILE,
@@ -133,7 +134,8 @@ static const struct ath6kl_hw hw_list[] = {
133 .board_addr = 0x435c00, 134 .board_addr = 0x435c00,
134 .refclk_hz = 40000000, 135 .refclk_hz = 40000000,
135 .uarttx_pin = 11, 136 .uarttx_pin = 11,
136 .flags = ATH6KL_HW_FLAG_64BIT_RATES, 137 .flags = ATH6KL_HW_64BIT_RATES |
138 ATH6KL_HW_AP_INACTIVITY_MINS,
137 139
138 .fw = { 140 .fw = {
139 .dir = AR6004_HW_1_2_FW_DIR, 141 .dir = AR6004_HW_1_2_FW_DIR,
@@ -142,6 +144,28 @@ static const struct ath6kl_hw hw_list[] = {
142 .fw_board = AR6004_HW_1_2_BOARD_DATA_FILE, 144 .fw_board = AR6004_HW_1_2_BOARD_DATA_FILE,
143 .fw_default_board = AR6004_HW_1_2_DEFAULT_BOARD_DATA_FILE, 145 .fw_default_board = AR6004_HW_1_2_DEFAULT_BOARD_DATA_FILE,
144 }, 146 },
147 {
148 .id = AR6004_HW_1_3_VERSION,
149 .name = "ar6004 hw 1.3",
150 .dataset_patch_addr = 0x437860,
151 .app_load_addr = 0x1234,
152 .board_ext_data_addr = 0x437000,
153 .reserved_ram_size = 7168,
154 .board_addr = 0x436400,
155 .refclk_hz = 40000000,
156 .uarttx_pin = 11,
157 .flags = ATH6KL_HW_64BIT_RATES |
158 ATH6KL_HW_AP_INACTIVITY_MINS |
159 ATH6KL_HW_MAP_LP_ENDPOINT,
160
161 .fw = {
162 .dir = AR6004_HW_1_3_FW_DIR,
163 .fw = AR6004_HW_1_3_FIRMWARE_FILE,
164 },
165
166 .fw_board = AR6004_HW_1_3_BOARD_DATA_FILE,
167 .fw_default_board = AR6004_HW_1_3_DEFAULT_BOARD_DATA_FILE,
168 },
145}; 169};
146 170
147/* 171/*
@@ -337,7 +361,7 @@ static int ath6kl_init_service_ep(struct ath6kl *ar)
337 if (ath6kl_connectservice(ar, &connect, "WMI DATA BK")) 361 if (ath6kl_connectservice(ar, &connect, "WMI DATA BK"))
338 return -EIO; 362 return -EIO;
339 363
340 /* connect to Video service, map this to to HI PRI */ 364 /* connect to Video service, map this to HI PRI */
341 connect.svc_id = WMI_DATA_VI_SVC; 365 connect.svc_id = WMI_DATA_VI_SVC;
342 if (ath6kl_connectservice(ar, &connect, "WMI DATA VI")) 366 if (ath6kl_connectservice(ar, &connect, "WMI DATA VI"))
343 return -EIO; 367 return -EIO;
@@ -1088,6 +1112,12 @@ int ath6kl_init_fetch_firmwares(struct ath6kl *ar)
1088 if (ret) 1112 if (ret)
1089 return ret; 1113 return ret;
1090 1114
1115 ret = ath6kl_fetch_fw_apin(ar, ATH6KL_FW_API4_FILE);
1116 if (ret == 0) {
1117 ar->fw_api = 4;
1118 goto out;
1119 }
1120
1091 ret = ath6kl_fetch_fw_apin(ar, ATH6KL_FW_API3_FILE); 1121 ret = ath6kl_fetch_fw_apin(ar, ATH6KL_FW_API3_FILE);
1092 if (ret == 0) { 1122 if (ret == 0) {
1093 ar->fw_api = 3; 1123 ar->fw_api = 3;
@@ -1401,8 +1431,7 @@ static int ath6kl_init_upload(struct ath6kl *ar)
1401 return status; 1431 return status;
1402 1432
1403 /* WAR to avoid SDIO CRC err */ 1433 /* WAR to avoid SDIO CRC err */
1404 if (ar->version.target_ver == AR6003_HW_2_0_VERSION || 1434 if (ar->hw.flags & ATH6KL_HW_SDIO_CRC_ERROR_WAR) {
1405 ar->version.target_ver == AR6003_HW_2_1_1_VERSION) {
1406 ath6kl_err("temporary war to avoid sdio crc error\n"); 1435 ath6kl_err("temporary war to avoid sdio crc error\n");
1407 1436
1408 param = 0x28; 1437 param = 0x28;
@@ -1520,7 +1549,7 @@ static const char *ath6kl_init_get_hif_name(enum ath6kl_hif_type type)
1520 return NULL; 1549 return NULL;
1521} 1550}
1522 1551
1523int ath6kl_init_hw_start(struct ath6kl *ar) 1552static int __ath6kl_init_hw_start(struct ath6kl *ar)
1524{ 1553{
1525 long timeleft; 1554 long timeleft;
1526 int ret, i; 1555 int ret, i;
@@ -1616,8 +1645,6 @@ int ath6kl_init_hw_start(struct ath6kl *ar)
1616 goto err_htc_stop; 1645 goto err_htc_stop;
1617 } 1646 }
1618 1647
1619 ar->state = ATH6KL_STATE_ON;
1620
1621 return 0; 1648 return 0;
1622 1649
1623err_htc_stop: 1650err_htc_stop:
@@ -1630,7 +1657,18 @@ err_power_off:
1630 return ret; 1657 return ret;
1631} 1658}
1632 1659
1633int ath6kl_init_hw_stop(struct ath6kl *ar) 1660int ath6kl_init_hw_start(struct ath6kl *ar)
1661{
1662 int err;
1663
1664 err = __ath6kl_init_hw_start(ar);
1665 if (err)
1666 return err;
1667 ar->state = ATH6KL_STATE_ON;
1668 return 0;
1669}
1670
1671static int __ath6kl_init_hw_stop(struct ath6kl *ar)
1634{ 1672{
1635 int ret; 1673 int ret;
1636 1674
@@ -1646,11 +1684,37 @@ int ath6kl_init_hw_stop(struct ath6kl *ar)
1646 if (ret) 1684 if (ret)
1647 ath6kl_warn("failed to power off hif: %d\n", ret); 1685 ath6kl_warn("failed to power off hif: %d\n", ret);
1648 1686
1649 ar->state = ATH6KL_STATE_OFF; 1687 return 0;
1688}
1650 1689
1690int ath6kl_init_hw_stop(struct ath6kl *ar)
1691{
1692 int err;
1693
1694 err = __ath6kl_init_hw_stop(ar);
1695 if (err)
1696 return err;
1697 ar->state = ATH6KL_STATE_OFF;
1651 return 0; 1698 return 0;
1652} 1699}
1653 1700
1701void ath6kl_init_hw_restart(struct ath6kl *ar)
1702{
1703 clear_bit(WMI_READY, &ar->flag);
1704
1705 ath6kl_cfg80211_stop_all(ar);
1706
1707 if (__ath6kl_init_hw_stop(ar)) {
1708 ath6kl_dbg(ATH6KL_DBG_RECOVERY, "Failed to stop during fw error recovery\n");
1709 return;
1710 }
1711
1712 if (__ath6kl_init_hw_start(ar)) {
1713 ath6kl_dbg(ATH6KL_DBG_RECOVERY, "Failed to restart during fw error recovery\n");
1714 return;
1715 }
1716}
1717
1654/* FIXME: move this to cfg80211.c and rename to ath6kl_cfg80211_vif_stop() */ 1718/* FIXME: move this to cfg80211.c and rename to ath6kl_cfg80211_vif_stop() */
1655void ath6kl_cleanup_vif(struct ath6kl_vif *vif, bool wmi_ready) 1719void ath6kl_cleanup_vif(struct ath6kl_vif *vif, bool wmi_ready)
1656{ 1720{
diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c
index c189e28e86a..bd50b6b7b49 100644
--- a/drivers/net/wireless/ath/ath6kl/main.c
+++ b/drivers/net/wireless/ath/ath6kl/main.c
@@ -293,13 +293,17 @@ int ath6kl_read_fwlogs(struct ath6kl *ar)
293 } 293 }
294 294
295 address = TARG_VTOP(ar->target_type, debug_hdr_addr); 295 address = TARG_VTOP(ar->target_type, debug_hdr_addr);
296 ath6kl_diag_read(ar, address, &debug_hdr, sizeof(debug_hdr)); 296 ret = ath6kl_diag_read(ar, address, &debug_hdr, sizeof(debug_hdr));
297 if (ret)
298 goto out;
297 299
298 address = TARG_VTOP(ar->target_type, 300 address = TARG_VTOP(ar->target_type,
299 le32_to_cpu(debug_hdr.dbuf_addr)); 301 le32_to_cpu(debug_hdr.dbuf_addr));
300 firstbuf = address; 302 firstbuf = address;
301 dropped = le32_to_cpu(debug_hdr.dropped); 303 dropped = le32_to_cpu(debug_hdr.dropped);
302 ath6kl_diag_read(ar, address, &debug_buf, sizeof(debug_buf)); 304 ret = ath6kl_diag_read(ar, address, &debug_buf, sizeof(debug_buf));
305 if (ret)
306 goto out;
303 307
304 loop = 100; 308 loop = 100;
305 309
@@ -322,7 +326,8 @@ int ath6kl_read_fwlogs(struct ath6kl *ar)
322 326
323 address = TARG_VTOP(ar->target_type, 327 address = TARG_VTOP(ar->target_type,
324 le32_to_cpu(debug_buf.next)); 328 le32_to_cpu(debug_buf.next));
325 ath6kl_diag_read(ar, address, &debug_buf, sizeof(debug_buf)); 329 ret = ath6kl_diag_read(ar, address, &debug_buf,
330 sizeof(debug_buf));
326 if (ret) 331 if (ret)
327 goto out; 332 goto out;
328 333
@@ -436,12 +441,9 @@ void ath6kl_connect_ap_mode_bss(struct ath6kl_vif *vif, u16 channel)
436 break; 441 break;
437 } 442 }
438 443
439 if (ar->want_ch_switch & (1 << vif->fw_vif_idx)) { 444 if (ar->last_ch != channel)
440 ar->want_ch_switch &= ~(1 << vif->fw_vif_idx);
441 /* we actually don't know the phymode, default to HT20 */ 445 /* we actually don't know the phymode, default to HT20 */
442 ath6kl_cfg80211_ch_switch_notify(vif, channel, 446 ath6kl_cfg80211_ch_switch_notify(vif, channel, WMI_11G_HT20);
443 WMI_11G_HT20);
444 }
445 447
446 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);
447 set_bit(CONNECTED, &vif->flags); 449 set_bit(CONNECTED, &vif->flags);
@@ -606,6 +608,18 @@ static int ath6kl_commit_ch_switch(struct ath6kl_vif *vif, u16 channel)
606 608
607 switch (vif->nw_type) { 609 switch (vif->nw_type) {
608 case AP_NETWORK: 610 case AP_NETWORK:
611 /*
612 * reconfigure any saved RSN IE capabilites in the beacon /
613 * probe response to stay in sync with the supplicant.
614 */
615 if (vif->rsn_capab &&
616 test_bit(ATH6KL_FW_CAPABILITY_RSN_CAP_OVERRIDE,
617 ar->fw_capabilities))
618 ath6kl_wmi_set_ie_cmd(ar->wmi, vif->fw_vif_idx,
619 WLAN_EID_RSN, WMI_RSN_IE_CAPB,
620 (const u8 *) &vif->rsn_capab,
621 sizeof(vif->rsn_capab));
622
609 return ath6kl_wmi_ap_profile_commit(ar->wmi, vif->fw_vif_idx, 623 return ath6kl_wmi_ap_profile_commit(ar->wmi, vif->fw_vif_idx,
610 &vif->profile); 624 &vif->profile);
611 default: 625 default:
@@ -628,6 +642,9 @@ static void ath6kl_check_ch_switch(struct ath6kl *ar, u16 channel)
628 if (ar->want_ch_switch & (1 << vif->fw_vif_idx)) 642 if (ar->want_ch_switch & (1 << vif->fw_vif_idx))
629 res = ath6kl_commit_ch_switch(vif, channel); 643 res = ath6kl_commit_ch_switch(vif, channel);
630 644
645 /* if channel switch failed, oh well we tried */
646 ar->want_ch_switch &= ~(1 << vif->fw_vif_idx);
647
631 if (res) 648 if (res)
632 ath6kl_err("channel switch failed nw_type %d res %d\n", 649 ath6kl_err("channel switch failed nw_type %d res %d\n",
633 vif->nw_type, res); 650 vif->nw_type, res);
@@ -981,8 +998,25 @@ void ath6kl_disconnect_event(struct ath6kl_vif *vif, u8 reason, u8 *bssid,
981 if (vif->nw_type == AP_NETWORK) { 998 if (vif->nw_type == AP_NETWORK) {
982 /* disconnect due to other STA vif switching channels */ 999 /* disconnect due to other STA vif switching channels */
983 if (reason == BSS_DISCONNECTED && 1000 if (reason == BSS_DISCONNECTED &&
984 prot_reason_status == WMI_AP_REASON_STA_ROAM) 1001 prot_reason_status == WMI_AP_REASON_STA_ROAM) {
985 ar->want_ch_switch |= 1 << vif->fw_vif_idx; 1002 ar->want_ch_switch |= 1 << vif->fw_vif_idx;
1003 /* bail back to this channel if STA vif fails connect */
1004 ar->last_ch = le16_to_cpu(vif->profile.ch);
1005 }
1006
1007 if (prot_reason_status == WMI_AP_REASON_MAX_STA) {
1008 /* send max client reached notification to user space */
1009 cfg80211_conn_failed(vif->ndev, bssid,
1010 NL80211_CONN_FAIL_MAX_CLIENTS,
1011 GFP_KERNEL);
1012 }
1013
1014 if (prot_reason_status == WMI_AP_REASON_ACL) {
1015 /* send blocked client notification to user space */
1016 cfg80211_conn_failed(vif->ndev, bssid,
1017 NL80211_CONN_FAIL_BLOCKED_CLIENT,
1018 GFP_KERNEL);
1019 }
986 1020
987 if (!ath6kl_remove_sta(ar, bssid, prot_reason_status)) 1021 if (!ath6kl_remove_sta(ar, bssid, prot_reason_status))
988 return; 1022 return;
@@ -1041,6 +1075,9 @@ void ath6kl_disconnect_event(struct ath6kl_vif *vif, u8 reason, u8 *bssid,
1041 } 1075 }
1042 } 1076 }
1043 1077
1078 /* restart disconnected concurrent vifs waiting for new channel */
1079 ath6kl_check_ch_switch(ar, ar->last_ch);
1080
1044 /* update connect & link status atomically */ 1081 /* update connect & link status atomically */
1045 spin_lock_bh(&vif->if_lock); 1082 spin_lock_bh(&vif->if_lock);
1046 clear_bit(CONNECTED, &vif->flags); 1083 clear_bit(CONNECTED, &vif->flags);
diff --git a/drivers/net/wireless/ath/ath6kl/recovery.c b/drivers/net/wireless/ath/ath6kl/recovery.c
new file mode 100644
index 00000000000..3a8d5e97dc8
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/recovery.c
@@ -0,0 +1,160 @@
1/*
2 * Copyright (c) 2012 Qualcomm Atheros, Inc.
3 *
4 * 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 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include "core.h"
18#include "cfg80211.h"
19#include "debug.h"
20
21static void ath6kl_recovery_work(struct work_struct *work)
22{
23 struct ath6kl *ar = container_of(work, struct ath6kl,
24 fw_recovery.recovery_work);
25
26 ar->state = ATH6KL_STATE_RECOVERY;
27
28 del_timer_sync(&ar->fw_recovery.hb_timer);
29
30 ath6kl_init_hw_restart(ar);
31
32 ar->state = ATH6KL_STATE_ON;
33 clear_bit(WMI_CTRL_EP_FULL, &ar->flag);
34
35 ar->fw_recovery.err_reason = 0;
36
37 if (ar->fw_recovery.hb_poll)
38 mod_timer(&ar->fw_recovery.hb_timer, jiffies +
39 msecs_to_jiffies(ar->fw_recovery.hb_poll));
40}
41
42void ath6kl_recovery_err_notify(struct ath6kl *ar, enum ath6kl_fw_err reason)
43{
44 if (!ar->fw_recovery.enable)
45 return;
46
47 ath6kl_dbg(ATH6KL_DBG_RECOVERY, "Fw error detected, reason:%d\n",
48 reason);
49
50 set_bit(reason, &ar->fw_recovery.err_reason);
51
52 if (!test_bit(RECOVERY_CLEANUP, &ar->flag) &&
53 ar->state != ATH6KL_STATE_RECOVERY)
54 queue_work(ar->ath6kl_wq, &ar->fw_recovery.recovery_work);
55}
56
57void ath6kl_recovery_hb_event(struct ath6kl *ar, u32 cookie)
58{
59 if (cookie == ar->fw_recovery.seq_num)
60 ar->fw_recovery.hb_pending = false;
61}
62
63static void ath6kl_recovery_hb_timer(unsigned long data)
64{
65 struct ath6kl *ar = (struct ath6kl *) data;
66 int err;
67
68 if (test_bit(RECOVERY_CLEANUP, &ar->flag) ||
69 (ar->state == ATH6KL_STATE_RECOVERY))
70 return;
71
72 if (ar->fw_recovery.hb_pending)
73 ar->fw_recovery.hb_misscnt++;
74 else
75 ar->fw_recovery.hb_misscnt = 0;
76
77 if (ar->fw_recovery.hb_misscnt > ATH6KL_HB_RESP_MISS_THRES) {
78 ar->fw_recovery.hb_misscnt = 0;
79 ar->fw_recovery.seq_num = 0;
80 ar->fw_recovery.hb_pending = false;
81 ath6kl_recovery_err_notify(ar, ATH6KL_FW_HB_RESP_FAILURE);
82 return;
83 }
84
85 ar->fw_recovery.seq_num++;
86 ar->fw_recovery.hb_pending = true;
87
88 err = ath6kl_wmi_get_challenge_resp_cmd(ar->wmi,
89 ar->fw_recovery.seq_num, 0);
90 if (err)
91 ath6kl_warn("Failed to send hb challenge request, err:%d\n",
92 err);
93
94 mod_timer(&ar->fw_recovery.hb_timer, jiffies +
95 msecs_to_jiffies(ar->fw_recovery.hb_poll));
96}
97
98void ath6kl_recovery_init(struct ath6kl *ar)
99{
100 struct ath6kl_fw_recovery *recovery = &ar->fw_recovery;
101
102 clear_bit(RECOVERY_CLEANUP, &ar->flag);
103 INIT_WORK(&recovery->recovery_work, ath6kl_recovery_work);
104 recovery->seq_num = 0;
105 recovery->hb_misscnt = 0;
106 ar->fw_recovery.hb_pending = false;
107 ar->fw_recovery.hb_timer.function = ath6kl_recovery_hb_timer;
108 ar->fw_recovery.hb_timer.data = (unsigned long) ar;
109 init_timer_deferrable(&ar->fw_recovery.hb_timer);
110
111 if (ar->fw_recovery.hb_poll)
112 mod_timer(&ar->fw_recovery.hb_timer, jiffies +
113 msecs_to_jiffies(ar->fw_recovery.hb_poll));
114}
115
116void ath6kl_recovery_cleanup(struct ath6kl *ar)
117{
118 if (!ar->fw_recovery.enable)
119 return;
120
121 set_bit(RECOVERY_CLEANUP, &ar->flag);
122
123 del_timer_sync(&ar->fw_recovery.hb_timer);
124 cancel_work_sync(&ar->fw_recovery.recovery_work);
125}
126
127void ath6kl_recovery_suspend(struct ath6kl *ar)
128{
129 if (!ar->fw_recovery.enable)
130 return;
131
132 ath6kl_recovery_cleanup(ar);
133
134 if (!ar->fw_recovery.err_reason)
135 return;
136
137 /* Process pending fw error detection */
138 ar->fw_recovery.err_reason = 0;
139 WARN_ON(ar->state != ATH6KL_STATE_ON);
140 ar->state = ATH6KL_STATE_RECOVERY;
141 ath6kl_init_hw_restart(ar);
142 ar->state = ATH6KL_STATE_ON;
143}
144
145void ath6kl_recovery_resume(struct ath6kl *ar)
146{
147 if (!ar->fw_recovery.enable)
148 return;
149
150 clear_bit(RECOVERY_CLEANUP, &ar->flag);
151
152 if (!ar->fw_recovery.hb_poll)
153 return;
154
155 ar->fw_recovery.hb_pending = false;
156 ar->fw_recovery.seq_num = 0;
157 ar->fw_recovery.hb_misscnt = 0;
158 mod_timer(&ar->fw_recovery.hb_timer,
159 jiffies + msecs_to_jiffies(ar->fw_recovery.hb_poll));
160}
diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c
index 05b95405f7b..d111980d44c 100644
--- a/drivers/net/wireless/ath/ath6kl/sdio.c
+++ b/drivers/net/wireless/ath/ath6kl/sdio.c
@@ -709,7 +709,7 @@ static int ath6kl_sdio_enable_scatter(struct ath6kl *ar)
709{ 709{
710 struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar); 710 struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar);
711 struct htc_target *target = ar->htc_target; 711 struct htc_target *target = ar->htc_target;
712 int ret; 712 int ret = 0;
713 bool virt_scat = false; 713 bool virt_scat = false;
714 714
715 if (ar_sdio->scatter_enabled) 715 if (ar_sdio->scatter_enabled)
@@ -844,22 +844,6 @@ static int ath6kl_sdio_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
844 bool try_deepsleep = false; 844 bool try_deepsleep = false;
845 int ret; 845 int ret;
846 846
847 if (ar->state == ATH6KL_STATE_SCHED_SCAN) {
848 ath6kl_dbg(ATH6KL_DBG_SUSPEND, "sched scan is in progress\n");
849
850 ret = ath6kl_set_sdio_pm_caps(ar);
851 if (ret)
852 goto cut_pwr;
853
854 ret = ath6kl_cfg80211_suspend(ar,
855 ATH6KL_CFG_SUSPEND_SCHED_SCAN,
856 NULL);
857 if (ret)
858 goto cut_pwr;
859
860 return 0;
861 }
862
863 if (ar->suspend_mode == WLAN_POWER_STATE_WOW || 847 if (ar->suspend_mode == WLAN_POWER_STATE_WOW ||
864 (!ar->suspend_mode && wow)) { 848 (!ar->suspend_mode && wow)) {
865 849
@@ -942,14 +926,14 @@ static int ath6kl_sdio_resume(struct ath6kl *ar)
942 case ATH6KL_STATE_WOW: 926 case ATH6KL_STATE_WOW:
943 break; 927 break;
944 928
945 case ATH6KL_STATE_SCHED_SCAN:
946 break;
947
948 case ATH6KL_STATE_SUSPENDING: 929 case ATH6KL_STATE_SUSPENDING:
949 break; 930 break;
950 931
951 case ATH6KL_STATE_RESUMING: 932 case ATH6KL_STATE_RESUMING:
952 break; 933 break;
934
935 case ATH6KL_STATE_RECOVERY:
936 break;
953 } 937 }
954 938
955 ath6kl_cfg80211_resume(ar); 939 ath6kl_cfg80211_resume(ar);
@@ -1462,3 +1446,6 @@ MODULE_FIRMWARE(AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE);
1462MODULE_FIRMWARE(AR6004_HW_1_2_FW_DIR "/" AR6004_HW_1_2_FIRMWARE_FILE); 1446MODULE_FIRMWARE(AR6004_HW_1_2_FW_DIR "/" AR6004_HW_1_2_FIRMWARE_FILE);
1463MODULE_FIRMWARE(AR6004_HW_1_2_BOARD_DATA_FILE); 1447MODULE_FIRMWARE(AR6004_HW_1_2_BOARD_DATA_FILE);
1464MODULE_FIRMWARE(AR6004_HW_1_2_DEFAULT_BOARD_DATA_FILE); 1448MODULE_FIRMWARE(AR6004_HW_1_2_DEFAULT_BOARD_DATA_FILE);
1449MODULE_FIRMWARE(AR6004_HW_1_3_FW_DIR "/" AR6004_HW_1_3_FIRMWARE_FILE);
1450MODULE_FIRMWARE(AR6004_HW_1_3_BOARD_DATA_FILE);
1451MODULE_FIRMWARE(AR6004_HW_1_3_DEFAULT_BOARD_DATA_FILE);
diff --git a/drivers/net/wireless/ath/ath6kl/txrx.c b/drivers/net/wireless/ath/ath6kl/txrx.c
index 7dfa0fd86d7..78b36928657 100644
--- a/drivers/net/wireless/ath/ath6kl/txrx.c
+++ b/drivers/net/wireless/ath/ath6kl/txrx.c
@@ -288,8 +288,16 @@ int ath6kl_control_tx(void *devt, struct sk_buff *skb,
288 int status = 0; 288 int status = 0;
289 struct ath6kl_cookie *cookie = NULL; 289 struct ath6kl_cookie *cookie = NULL;
290 290
291 if (WARN_ON_ONCE(ar->state == ATH6KL_STATE_WOW)) 291 if (WARN_ON_ONCE(ar->state == ATH6KL_STATE_WOW)) {
292 dev_kfree_skb(skb);
292 return -EACCES; 293 return -EACCES;
294 }
295
296 if (WARN_ON_ONCE(eid == ENDPOINT_UNUSED ||
297 eid >= ENDPOINT_MAX)) {
298 status = -EINVAL;
299 goto fail_ctrl_tx;
300 }
293 301
294 spin_lock_bh(&ar->lock); 302 spin_lock_bh(&ar->lock);
295 303
@@ -591,6 +599,7 @@ enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target,
591 */ 599 */
592 set_bit(WMI_CTRL_EP_FULL, &ar->flag); 600 set_bit(WMI_CTRL_EP_FULL, &ar->flag);
593 ath6kl_err("wmi ctrl ep is full\n"); 601 ath6kl_err("wmi ctrl ep is full\n");
602 ath6kl_recovery_err_notify(ar, ATH6KL_FW_EP_FULL);
594 return action; 603 return action;
595 } 604 }
596 605
@@ -695,22 +704,31 @@ void ath6kl_tx_complete(struct htc_target *target,
695 list); 704 list);
696 list_del(&packet->list); 705 list_del(&packet->list);
697 706
707 if (WARN_ON_ONCE(packet->endpoint == ENDPOINT_UNUSED ||
708 packet->endpoint >= ENDPOINT_MAX))
709 continue;
710
698 ath6kl_cookie = (struct ath6kl_cookie *)packet->pkt_cntxt; 711 ath6kl_cookie = (struct ath6kl_cookie *)packet->pkt_cntxt;
699 if (!ath6kl_cookie) 712 if (WARN_ON_ONCE(!ath6kl_cookie))
700 goto fatal; 713 continue;
701 714
702 status = packet->status; 715 status = packet->status;
703 skb = ath6kl_cookie->skb; 716 skb = ath6kl_cookie->skb;
704 eid = packet->endpoint; 717 eid = packet->endpoint;
705 map_no = ath6kl_cookie->map_no; 718 map_no = ath6kl_cookie->map_no;
706 719
707 if (!skb || !skb->data) 720 if (WARN_ON_ONCE(!skb || !skb->data)) {
708 goto fatal; 721 dev_kfree_skb(skb);
722 ath6kl_free_cookie(ar, ath6kl_cookie);
723 continue;
724 }
709 725
710 __skb_queue_tail(&skb_queue, skb); 726 __skb_queue_tail(&skb_queue, skb);
711 727
712 if (!status && (packet->act_len != skb->len)) 728 if (WARN_ON_ONCE(!status && (packet->act_len != skb->len))) {
713 goto fatal; 729 ath6kl_free_cookie(ar, ath6kl_cookie);
730 continue;
731 }
714 732
715 ar->tx_pending[eid]--; 733 ar->tx_pending[eid]--;
716 734
@@ -792,11 +810,6 @@ void ath6kl_tx_complete(struct htc_target *target,
792 wake_up(&ar->event_wq); 810 wake_up(&ar->event_wq);
793 811
794 return; 812 return;
795
796fatal:
797 WARN_ON(1);
798 spin_unlock_bh(&ar->lock);
799 return;
800} 813}
801 814
802void ath6kl_tx_data_cleanup(struct ath6kl *ar) 815void ath6kl_tx_data_cleanup(struct ath6kl *ar)
@@ -885,8 +898,11 @@ void ath6kl_rx_refill(struct htc_target *target, enum htc_endpoint_id endpoint)
885 break; 898 break;
886 899
887 packet = (struct htc_packet *) skb->head; 900 packet = (struct htc_packet *) skb->head;
888 if (!IS_ALIGNED((unsigned long) skb->data, 4)) 901 if (!IS_ALIGNED((unsigned long) skb->data, 4)) {
902 size_t len = skb_headlen(skb);
889 skb->data = PTR_ALIGN(skb->data - 4, 4); 903 skb->data = PTR_ALIGN(skb->data - 4, 4);
904 skb_set_tail_pointer(skb, len);
905 }
890 set_htc_rxpkt_info(packet, skb, skb->data, 906 set_htc_rxpkt_info(packet, skb, skb->data,
891 ATH6KL_BUFFER_SIZE, endpoint); 907 ATH6KL_BUFFER_SIZE, endpoint);
892 packet->skb = skb; 908 packet->skb = skb;
@@ -908,8 +924,11 @@ void ath6kl_refill_amsdu_rxbufs(struct ath6kl *ar, int count)
908 return; 924 return;
909 925
910 packet = (struct htc_packet *) skb->head; 926 packet = (struct htc_packet *) skb->head;
911 if (!IS_ALIGNED((unsigned long) skb->data, 4)) 927 if (!IS_ALIGNED((unsigned long) skb->data, 4)) {
928 size_t len = skb_headlen(skb);
912 skb->data = PTR_ALIGN(skb->data - 4, 4); 929 skb->data = PTR_ALIGN(skb->data - 4, 4);
930 skb_set_tail_pointer(skb, len);
931 }
913 set_htc_rxpkt_info(packet, skb, skb->data, 932 set_htc_rxpkt_info(packet, skb, skb->data,
914 ATH6KL_AMSDU_BUFFER_SIZE, 0); 933 ATH6KL_AMSDU_BUFFER_SIZE, 0);
915 packet->skb = skb; 934 packet->skb = skb;
diff --git a/drivers/net/wireless/ath/ath6kl/usb.c b/drivers/net/wireless/ath/ath6kl/usb.c
index 3740c3d6ab8..62bcc0d5bc2 100644
--- a/drivers/net/wireless/ath/ath6kl/usb.c
+++ b/drivers/net/wireless/ath/ath6kl/usb.c
@@ -185,9 +185,10 @@ static int ath6kl_usb_alloc_pipe_resources(struct ath6kl_usb_pipe *pipe,
185 for (i = 0; i < urb_cnt; i++) { 185 for (i = 0; i < urb_cnt; i++) {
186 urb_context = kzalloc(sizeof(struct ath6kl_urb_context), 186 urb_context = kzalloc(sizeof(struct ath6kl_urb_context),
187 GFP_KERNEL); 187 GFP_KERNEL);
188 if (urb_context == NULL) 188 if (urb_context == NULL) {
189 /* FIXME: set status to -ENOMEM */ 189 status = -ENOMEM;
190 break; 190 goto fail_alloc_pipe_resources;
191 }
191 192
192 urb_context->pipe = pipe; 193 urb_context->pipe = pipe;
193 194
@@ -204,6 +205,7 @@ static int ath6kl_usb_alloc_pipe_resources(struct ath6kl_usb_pipe *pipe,
204 pipe->logical_pipe_num, pipe->usb_pipe_handle, 205 pipe->logical_pipe_num, pipe->usb_pipe_handle,
205 pipe->urb_alloc); 206 pipe->urb_alloc);
206 207
208fail_alloc_pipe_resources:
207 return status; 209 return status;
208} 210}
209 211
@@ -803,7 +805,11 @@ static int ath6kl_usb_map_service_pipe(struct ath6kl *ar, u16 svc_id,
803 *dl_pipe = ATH6KL_USB_PIPE_RX_DATA; 805 *dl_pipe = ATH6KL_USB_PIPE_RX_DATA;
804 break; 806 break;
805 case WMI_DATA_VI_SVC: 807 case WMI_DATA_VI_SVC:
806 *ul_pipe = ATH6KL_USB_PIPE_TX_DATA_MP; 808
809 if (ar->hw.flags & ATH6KL_HW_MAP_LP_ENDPOINT)
810 *ul_pipe = ATH6KL_USB_PIPE_TX_DATA_LP;
811 else
812 *ul_pipe = ATH6KL_USB_PIPE_TX_DATA_MP;
807 /* 813 /*
808 * Disable rxdata2 directly, it will be enabled 814 * Disable rxdata2 directly, it will be enabled
809 * if FW enable rxdata2 815 * if FW enable rxdata2
@@ -811,7 +817,11 @@ static int ath6kl_usb_map_service_pipe(struct ath6kl *ar, u16 svc_id,
811 *dl_pipe = ATH6KL_USB_PIPE_RX_DATA; 817 *dl_pipe = ATH6KL_USB_PIPE_RX_DATA;
812 break; 818 break;
813 case WMI_DATA_VO_SVC: 819 case WMI_DATA_VO_SVC:
814 *ul_pipe = ATH6KL_USB_PIPE_TX_DATA_HP; 820
821 if (ar->hw.flags & ATH6KL_HW_MAP_LP_ENDPOINT)
822 *ul_pipe = ATH6KL_USB_PIPE_TX_DATA_LP;
823 else
824 *ul_pipe = ATH6KL_USB_PIPE_TX_DATA_MP;
815 /* 825 /*
816 * Disable rxdata2 directly, it will be enabled 826 * Disable rxdata2 directly, it will be enabled
817 * if FW enable rxdata2 827 * if FW enable rxdata2
@@ -1196,7 +1206,14 @@ static struct usb_driver ath6kl_usb_driver = {
1196 1206
1197static int ath6kl_usb_init(void) 1207static int ath6kl_usb_init(void)
1198{ 1208{
1199 usb_register(&ath6kl_usb_driver); 1209 int ret;
1210
1211 ret = usb_register(&ath6kl_usb_driver);
1212 if (ret) {
1213 ath6kl_err("usb registration failed: %d\n", ret);
1214 return ret;
1215 }
1216
1200 return 0; 1217 return 0;
1201} 1218}
1202 1219
@@ -1220,3 +1237,6 @@ MODULE_FIRMWARE(AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE);
1220MODULE_FIRMWARE(AR6004_HW_1_2_FIRMWARE_FILE); 1237MODULE_FIRMWARE(AR6004_HW_1_2_FIRMWARE_FILE);
1221MODULE_FIRMWARE(AR6004_HW_1_2_BOARD_DATA_FILE); 1238MODULE_FIRMWARE(AR6004_HW_1_2_BOARD_DATA_FILE);
1222MODULE_FIRMWARE(AR6004_HW_1_2_DEFAULT_BOARD_DATA_FILE); 1239MODULE_FIRMWARE(AR6004_HW_1_2_DEFAULT_BOARD_DATA_FILE);
1240MODULE_FIRMWARE(AR6004_HW_1_3_FW_DIR "/" AR6004_HW_1_3_FIRMWARE_FILE);
1241MODULE_FIRMWARE(AR6004_HW_1_3_BOARD_DATA_FILE);
1242MODULE_FIRMWARE(AR6004_HW_1_3_DEFAULT_BOARD_DATA_FILE);
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c
index c30ab4b11d6..55ccf977033 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.c
+++ b/drivers/net/wireless/ath/ath6kl/wmi.c
@@ -936,8 +936,12 @@ static void ath6kl_wmi_regdomain_event(struct wmi *wmi, u8 *datap, int len)
936 936
937 regpair = ath6kl_get_regpair((u16) reg_code); 937 regpair = ath6kl_get_regpair((u16) reg_code);
938 country = ath6kl_regd_find_country_by_rd((u16) reg_code); 938 country = ath6kl_regd_find_country_by_rd((u16) reg_code);
939 ath6kl_dbg(ATH6KL_DBG_WMI, "Regpair used: 0x%0x\n", 939 if (regpair)
940 regpair->regDmnEnum); 940 ath6kl_dbg(ATH6KL_DBG_WMI, "Regpair used: 0x%0x\n",
941 regpair->regDmnEnum);
942 else
943 ath6kl_warn("Regpair not found reg_code 0x%0x\n",
944 reg_code);
941 } 945 }
942 946
943 if (country && wmi->parent_dev->wiphy_registered) { 947 if (country && wmi->parent_dev->wiphy_registered) {
@@ -1116,7 +1120,7 @@ static int ath6kl_wmi_bssinfo_event_rx(struct wmi *wmi, u8 *datap, int len,
1116 * the timer would not ever fire if the scan interval is short 1120 * the timer would not ever fire if the scan interval is short
1117 * enough. 1121 * enough.
1118 */ 1122 */
1119 if (ar->state == ATH6KL_STATE_SCHED_SCAN && 1123 if (test_bit(SCHED_SCANNING, &vif->flags) &&
1120 !timer_pending(&vif->sched_scan_timer)) { 1124 !timer_pending(&vif->sched_scan_timer)) {
1121 mod_timer(&vif->sched_scan_timer, jiffies + 1125 mod_timer(&vif->sched_scan_timer, jiffies +
1122 msecs_to_jiffies(ATH6KL_SCHED_SCAN_RESULT_DELAY)); 1126 msecs_to_jiffies(ATH6KL_SCHED_SCAN_RESULT_DELAY));
@@ -1170,6 +1174,9 @@ static int ath6kl_wmi_bitrate_reply_rx(struct wmi *wmi, u8 *datap, int len)
1170 rate = RATE_AUTO; 1174 rate = RATE_AUTO;
1171 } else { 1175 } else {
1172 index = reply->rate_index & 0x7f; 1176 index = reply->rate_index & 0x7f;
1177 if (WARN_ON_ONCE(index > (RATE_MCS_7_40 + 1)))
1178 return -EINVAL;
1179
1173 sgi = (reply->rate_index & 0x80) ? 1 : 0; 1180 sgi = (reply->rate_index & 0x80) ? 1 : 0;
1174 rate = wmi_rate_tbl[index][sgi]; 1181 rate = wmi_rate_tbl[index][sgi];
1175 } 1182 }
@@ -1531,6 +1538,68 @@ static int ath6kl_wmi_cac_event_rx(struct wmi *wmi, u8 *datap, int len,
1531 return 0; 1538 return 0;
1532} 1539}
1533 1540
1541static int ath6kl_wmi_txe_notify_event_rx(struct wmi *wmi, u8 *datap, int len,
1542 struct ath6kl_vif *vif)
1543{
1544 struct wmi_txe_notify_event *ev;
1545 u32 rate, pkts;
1546
1547 if (len < sizeof(*ev))
1548 return -EINVAL;
1549
1550 if (vif->sme_state != SME_CONNECTED)
1551 return -ENOTCONN;
1552
1553 ev = (struct wmi_txe_notify_event *) datap;
1554 rate = le32_to_cpu(ev->rate);
1555 pkts = le32_to_cpu(ev->pkts);
1556
1557 ath6kl_dbg(ATH6KL_DBG_WMI, "TXE notify event: peer %pM rate %d% pkts %d intvl %ds\n",
1558 vif->bssid, rate, pkts, vif->txe_intvl);
1559
1560 cfg80211_cqm_txe_notify(vif->ndev, vif->bssid, pkts,
1561 rate, vif->txe_intvl, GFP_KERNEL);
1562
1563 return 0;
1564}
1565
1566int ath6kl_wmi_set_txe_notify(struct wmi *wmi, u8 idx,
1567 u32 rate, u32 pkts, u32 intvl)
1568{
1569 struct sk_buff *skb;
1570 struct wmi_txe_notify_cmd *cmd;
1571
1572 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
1573 if (!skb)
1574 return -ENOMEM;
1575
1576 cmd = (struct wmi_txe_notify_cmd *) skb->data;
1577 cmd->rate = cpu_to_le32(rate);
1578 cmd->pkts = cpu_to_le32(pkts);
1579 cmd->intvl = cpu_to_le32(intvl);
1580
1581 return ath6kl_wmi_cmd_send(wmi, idx, skb, WMI_SET_TXE_NOTIFY_CMDID,
1582 NO_SYNC_WMIFLAG);
1583}
1584
1585int ath6kl_wmi_set_rssi_filter_cmd(struct wmi *wmi, u8 if_idx, s8 rssi)
1586{
1587 struct sk_buff *skb;
1588 struct wmi_set_rssi_filter_cmd *cmd;
1589 int ret;
1590
1591 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
1592 if (!skb)
1593 return -ENOMEM;
1594
1595 cmd = (struct wmi_set_rssi_filter_cmd *) skb->data;
1596 cmd->rssi = rssi;
1597
1598 ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_RSSI_FILTER_CMDID,
1599 NO_SYNC_WMIFLAG);
1600 return ret;
1601}
1602
1534static int ath6kl_wmi_send_snr_threshold_params(struct wmi *wmi, 1603static int ath6kl_wmi_send_snr_threshold_params(struct wmi *wmi,
1535 struct wmi_snr_threshold_params_cmd *snr_cmd) 1604 struct wmi_snr_threshold_params_cmd *snr_cmd)
1536{ 1605{
@@ -1677,8 +1746,11 @@ int ath6kl_wmi_cmd_send(struct wmi *wmi, u8 if_idx, struct sk_buff *skb,
1677 int ret; 1746 int ret;
1678 u16 info1; 1747 u16 info1;
1679 1748
1680 if (WARN_ON(skb == NULL || (if_idx > (wmi->parent_dev->vif_max - 1)))) 1749 if (WARN_ON(skb == NULL ||
1750 (if_idx > (wmi->parent_dev->vif_max - 1)))) {
1751 dev_kfree_skb(skb);
1681 return -EINVAL; 1752 return -EINVAL;
1753 }
1682 1754
1683 ath6kl_dbg(ATH6KL_DBG_WMI, "wmi tx id %d len %d flag %d\n", 1755 ath6kl_dbg(ATH6KL_DBG_WMI, "wmi tx id %d len %d flag %d\n",
1684 cmd_id, skb->len, sync_flag); 1756 cmd_id, skb->len, sync_flag);
@@ -1833,6 +1905,59 @@ int ath6kl_wmi_disconnect_cmd(struct wmi *wmi, u8 if_idx)
1833 return ret; 1905 return ret;
1834} 1906}
1835 1907
1908/* ath6kl_wmi_start_scan_cmd is to be deprecated. Use
1909 * ath6kl_wmi_begin_scan_cmd instead. The new function supports P2P
1910 * mgmt operations using station interface.
1911 */
1912static int ath6kl_wmi_startscan_cmd(struct wmi *wmi, u8 if_idx,
1913 enum wmi_scan_type scan_type,
1914 u32 force_fgscan, u32 is_legacy,
1915 u32 home_dwell_time,
1916 u32 force_scan_interval,
1917 s8 num_chan, u16 *ch_list)
1918{
1919 struct sk_buff *skb;
1920 struct wmi_start_scan_cmd *sc;
1921 s8 size;
1922 int i, ret;
1923
1924 size = sizeof(struct wmi_start_scan_cmd);
1925
1926 if ((scan_type != WMI_LONG_SCAN) && (scan_type != WMI_SHORT_SCAN))
1927 return -EINVAL;
1928
1929 if (num_chan > WMI_MAX_CHANNELS)
1930 return -EINVAL;
1931
1932 if (num_chan)
1933 size += sizeof(u16) * (num_chan - 1);
1934
1935 skb = ath6kl_wmi_get_new_buf(size);
1936 if (!skb)
1937 return -ENOMEM;
1938
1939 sc = (struct wmi_start_scan_cmd *) skb->data;
1940 sc->scan_type = scan_type;
1941 sc->force_fg_scan = cpu_to_le32(force_fgscan);
1942 sc->is_legacy = cpu_to_le32(is_legacy);
1943 sc->home_dwell_time = cpu_to_le32(home_dwell_time);
1944 sc->force_scan_intvl = cpu_to_le32(force_scan_interval);
1945 sc->num_ch = num_chan;
1946
1947 for (i = 0; i < num_chan; i++)
1948 sc->ch_list[i] = cpu_to_le16(ch_list[i]);
1949
1950 ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_START_SCAN_CMDID,
1951 NO_SYNC_WMIFLAG);
1952
1953 return ret;
1954}
1955
1956/*
1957 * beginscan supports (compared to old startscan) P2P mgmt operations using
1958 * station interface, send additional information like supported rates to
1959 * advertise and xmit rates for probe requests
1960 */
1836int ath6kl_wmi_beginscan_cmd(struct wmi *wmi, u8 if_idx, 1961int ath6kl_wmi_beginscan_cmd(struct wmi *wmi, u8 if_idx,
1837 enum wmi_scan_type scan_type, 1962 enum wmi_scan_type scan_type,
1838 u32 force_fgscan, u32 is_legacy, 1963 u32 force_fgscan, u32 is_legacy,
@@ -1848,6 +1973,15 @@ int ath6kl_wmi_beginscan_cmd(struct wmi *wmi, u8 if_idx,
1848 int num_rates; 1973 int num_rates;
1849 u32 ratemask; 1974 u32 ratemask;
1850 1975
1976 if (!test_bit(ATH6KL_FW_CAPABILITY_STA_P2PDEV_DUPLEX,
1977 ar->fw_capabilities)) {
1978 return ath6kl_wmi_startscan_cmd(wmi, if_idx,
1979 scan_type, force_fgscan,
1980 is_legacy, home_dwell_time,
1981 force_scan_interval,
1982 num_chan, ch_list);
1983 }
1984
1851 size = sizeof(struct wmi_begin_scan_cmd); 1985 size = sizeof(struct wmi_begin_scan_cmd);
1852 1986
1853 if ((scan_type != WMI_LONG_SCAN) && (scan_type != WMI_SHORT_SCAN)) 1987 if ((scan_type != WMI_LONG_SCAN) && (scan_type != WMI_SHORT_SCAN))
@@ -1900,50 +2034,24 @@ int ath6kl_wmi_beginscan_cmd(struct wmi *wmi, u8 if_idx,
1900 return ret; 2034 return ret;
1901} 2035}
1902 2036
1903/* ath6kl_wmi_start_scan_cmd is to be deprecated. Use 2037int ath6kl_wmi_enable_sched_scan_cmd(struct wmi *wmi, u8 if_idx, bool enable)
1904 * ath6kl_wmi_begin_scan_cmd instead. The new function supports P2P
1905 * mgmt operations using station interface.
1906 */
1907int ath6kl_wmi_startscan_cmd(struct wmi *wmi, u8 if_idx,
1908 enum wmi_scan_type scan_type,
1909 u32 force_fgscan, u32 is_legacy,
1910 u32 home_dwell_time, u32 force_scan_interval,
1911 s8 num_chan, u16 *ch_list)
1912{ 2038{
1913 struct sk_buff *skb; 2039 struct sk_buff *skb;
1914 struct wmi_start_scan_cmd *sc; 2040 struct wmi_enable_sched_scan_cmd *sc;
1915 s8 size; 2041 int ret;
1916 int i, ret;
1917
1918 size = sizeof(struct wmi_start_scan_cmd);
1919
1920 if ((scan_type != WMI_LONG_SCAN) && (scan_type != WMI_SHORT_SCAN))
1921 return -EINVAL;
1922
1923 if (num_chan > WMI_MAX_CHANNELS)
1924 return -EINVAL;
1925
1926 if (num_chan)
1927 size += sizeof(u16) * (num_chan - 1);
1928 2042
1929 skb = ath6kl_wmi_get_new_buf(size); 2043 skb = ath6kl_wmi_get_new_buf(sizeof(*sc));
1930 if (!skb) 2044 if (!skb)
1931 return -ENOMEM; 2045 return -ENOMEM;
1932 2046
1933 sc = (struct wmi_start_scan_cmd *) skb->data; 2047 ath6kl_dbg(ATH6KL_DBG_WMI, "%s scheduled scan on vif %d\n",
1934 sc->scan_type = scan_type; 2048 enable ? "enabling" : "disabling", if_idx);
1935 sc->force_fg_scan = cpu_to_le32(force_fgscan); 2049 sc = (struct wmi_enable_sched_scan_cmd *) skb->data;
1936 sc->is_legacy = cpu_to_le32(is_legacy); 2050 sc->enable = enable ? 1 : 0;
1937 sc->home_dwell_time = cpu_to_le32(home_dwell_time);
1938 sc->force_scan_intvl = cpu_to_le32(force_scan_interval);
1939 sc->num_ch = num_chan;
1940
1941 for (i = 0; i < num_chan; i++)
1942 sc->ch_list[i] = cpu_to_le16(ch_list[i]);
1943 2051
1944 ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_START_SCAN_CMDID, 2052 ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb,
2053 WMI_ENABLE_SCHED_SCAN_CMDID,
1945 NO_SYNC_WMIFLAG); 2054 NO_SYNC_WMIFLAG);
1946
1947 return ret; 2055 return ret;
1948} 2056}
1949 2057
@@ -2275,8 +2383,10 @@ static int ath6kl_wmi_data_sync_send(struct wmi *wmi, struct sk_buff *skb,
2275 struct wmi_data_hdr *data_hdr; 2383 struct wmi_data_hdr *data_hdr;
2276 int ret; 2384 int ret;
2277 2385
2278 if (WARN_ON(skb == NULL || ep_id == wmi->ep_id)) 2386 if (WARN_ON(skb == NULL || ep_id == wmi->ep_id)) {
2387 dev_kfree_skb(skb);
2279 return -EINVAL; 2388 return -EINVAL;
2389 }
2280 2390
2281 skb_push(skb, sizeof(struct wmi_data_hdr)); 2391 skb_push(skb, sizeof(struct wmi_data_hdr));
2282 2392
@@ -2313,10 +2423,8 @@ static int ath6kl_wmi_sync_point(struct wmi *wmi, u8 if_idx)
2313 spin_unlock_bh(&wmi->lock); 2423 spin_unlock_bh(&wmi->lock);
2314 2424
2315 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); 2425 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
2316 if (!skb) { 2426 if (!skb)
2317 ret = -ENOMEM; 2427 return -ENOMEM;
2318 goto free_skb;
2319 }
2320 2428
2321 cmd = (struct wmi_sync_cmd *) skb->data; 2429 cmd = (struct wmi_sync_cmd *) skb->data;
2322 2430
@@ -2339,7 +2447,7 @@ static int ath6kl_wmi_sync_point(struct wmi *wmi, u8 if_idx)
2339 * then do not send the Synchronize cmd on the control ep 2447 * then do not send the Synchronize cmd on the control ep
2340 */ 2448 */
2341 if (ret) 2449 if (ret)
2342 goto free_skb; 2450 goto free_cmd_skb;
2343 2451
2344 /* 2452 /*
2345 * Send sync cmd followed by sync data messages on all 2453 * Send sync cmd followed by sync data messages on all
@@ -2349,15 +2457,12 @@ static int ath6kl_wmi_sync_point(struct wmi *wmi, u8 if_idx)
2349 NO_SYNC_WMIFLAG); 2457 NO_SYNC_WMIFLAG);
2350 2458
2351 if (ret) 2459 if (ret)
2352 goto free_skb; 2460 goto free_data_skb;
2353
2354 /* cmd buffer sent, we no longer own it */
2355 skb = NULL;
2356 2461
2357 for (index = 0; index < num_pri_streams; index++) { 2462 for (index = 0; index < num_pri_streams; index++) {
2358 2463
2359 if (WARN_ON(!data_sync_bufs[index].skb)) 2464 if (WARN_ON(!data_sync_bufs[index].skb))
2360 break; 2465 goto free_data_skb;
2361 2466
2362 ep_id = ath6kl_ac2_endpoint_id(wmi->parent_dev, 2467 ep_id = ath6kl_ac2_endpoint_id(wmi->parent_dev,
2363 data_sync_bufs[index]. 2468 data_sync_bufs[index].
@@ -2366,17 +2471,20 @@ static int ath6kl_wmi_sync_point(struct wmi *wmi, u8 if_idx)
2366 ath6kl_wmi_data_sync_send(wmi, data_sync_bufs[index].skb, 2471 ath6kl_wmi_data_sync_send(wmi, data_sync_bufs[index].skb,
2367 ep_id, if_idx); 2472 ep_id, if_idx);
2368 2473
2369 if (ret)
2370 break;
2371
2372 data_sync_bufs[index].skb = NULL; 2474 data_sync_bufs[index].skb = NULL;
2475
2476 if (ret)
2477 goto free_data_skb;
2373 } 2478 }
2374 2479
2375free_skb: 2480 return 0;
2481
2482free_cmd_skb:
2376 /* free up any resources left over (possibly due to an error) */ 2483 /* free up any resources left over (possibly due to an error) */
2377 if (skb) 2484 if (skb)
2378 dev_kfree_skb(skb); 2485 dev_kfree_skb(skb);
2379 2486
2487free_data_skb:
2380 for (index = 0; index < num_pri_streams; index++) { 2488 for (index = 0; index < num_pri_streams; index++) {
2381 if (data_sync_bufs[index].skb != NULL) { 2489 if (data_sync_bufs[index].skb != NULL) {
2382 dev_kfree_skb((struct sk_buff *)data_sync_bufs[index]. 2490 dev_kfree_skb((struct sk_buff *)data_sync_bufs[index].
@@ -2618,11 +2726,13 @@ static int ath6kl_set_bitrate_mask64(struct wmi *wmi, u8 if_idx,
2618{ 2726{
2619 struct sk_buff *skb; 2727 struct sk_buff *skb;
2620 int ret, mode, band; 2728 int ret, mode, band;
2621 u64 mcsrate, ratemask[IEEE80211_NUM_BANDS]; 2729 u64 mcsrate, ratemask[ATH6KL_NUM_BANDS];
2622 struct wmi_set_tx_select_rates64_cmd *cmd; 2730 struct wmi_set_tx_select_rates64_cmd *cmd;
2623 2731
2624 memset(&ratemask, 0, sizeof(ratemask)); 2732 memset(&ratemask, 0, sizeof(ratemask));
2625 for (band = 0; band < IEEE80211_NUM_BANDS; band++) { 2733
2734 /* only check 2.4 and 5 GHz bands, skip the rest */
2735 for (band = 0; band <= IEEE80211_BAND_5GHZ; band++) {
2626 /* copy legacy rate mask */ 2736 /* copy legacy rate mask */
2627 ratemask[band] = mask->control[band].legacy; 2737 ratemask[band] = mask->control[band].legacy;
2628 if (band == IEEE80211_BAND_5GHZ) 2738 if (band == IEEE80211_BAND_5GHZ)
@@ -2668,11 +2778,13 @@ static int ath6kl_set_bitrate_mask32(struct wmi *wmi, u8 if_idx,
2668{ 2778{
2669 struct sk_buff *skb; 2779 struct sk_buff *skb;
2670 int ret, mode, band; 2780 int ret, mode, band;
2671 u32 mcsrate, ratemask[IEEE80211_NUM_BANDS]; 2781 u32 mcsrate, ratemask[ATH6KL_NUM_BANDS];
2672 struct wmi_set_tx_select_rates32_cmd *cmd; 2782 struct wmi_set_tx_select_rates32_cmd *cmd;
2673 2783
2674 memset(&ratemask, 0, sizeof(ratemask)); 2784 memset(&ratemask, 0, sizeof(ratemask));
2675 for (band = 0; band < IEEE80211_NUM_BANDS; band++) { 2785
2786 /* only check 2.4 and 5 GHz bands, skip the rest */
2787 for (band = 0; band <= IEEE80211_BAND_5GHZ; band++) {
2676 /* copy legacy rate mask */ 2788 /* copy legacy rate mask */
2677 ratemask[band] = mask->control[band].legacy; 2789 ratemask[band] = mask->control[band].legacy;
2678 if (band == IEEE80211_BAND_5GHZ) 2790 if (band == IEEE80211_BAND_5GHZ)
@@ -2716,7 +2828,7 @@ int ath6kl_wmi_set_bitrate_mask(struct wmi *wmi, u8 if_idx,
2716{ 2828{
2717 struct ath6kl *ar = wmi->parent_dev; 2829 struct ath6kl *ar = wmi->parent_dev;
2718 2830
2719 if (ar->hw.flags & ATH6KL_HW_FLAG_64BIT_RATES) 2831 if (ar->hw.flags & ATH6KL_HW_64BIT_RATES)
2720 return ath6kl_set_bitrate_mask64(wmi, if_idx, mask); 2832 return ath6kl_set_bitrate_mask64(wmi, if_idx, mask);
2721 else 2833 else
2722 return ath6kl_set_bitrate_mask32(wmi, if_idx, mask); 2834 return ath6kl_set_bitrate_mask32(wmi, if_idx, mask);
@@ -3139,12 +3251,40 @@ int ath6kl_wmi_sta_bmiss_enhance_cmd(struct wmi *wmi, u8 if_idx, bool enhance)
3139 return ret; 3251 return ret;
3140} 3252}
3141 3253
3254int ath6kl_wmi_set_regdomain_cmd(struct wmi *wmi, const char *alpha2)
3255{
3256 struct sk_buff *skb;
3257 struct wmi_set_regdomain_cmd *cmd;
3258
3259 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
3260 if (!skb)
3261 return -ENOMEM;
3262
3263 cmd = (struct wmi_set_regdomain_cmd *) skb->data;
3264 memcpy(cmd->iso_name, alpha2, 2);
3265
3266 return ath6kl_wmi_cmd_send(wmi, 0, skb,
3267 WMI_SET_REGDOMAIN_CMDID,
3268 NO_SYNC_WMIFLAG);
3269}
3270
3142s32 ath6kl_wmi_get_rate(s8 rate_index) 3271s32 ath6kl_wmi_get_rate(s8 rate_index)
3143{ 3272{
3273 u8 sgi = 0;
3274
3144 if (rate_index == RATE_AUTO) 3275 if (rate_index == RATE_AUTO)
3145 return 0; 3276 return 0;
3146 3277
3147 return wmi_rate_tbl[(u32) rate_index][0]; 3278 /* SGI is stored as the MSB of the rate_index */
3279 if (rate_index & RATE_INDEX_MSB) {
3280 rate_index &= RATE_INDEX_WITHOUT_SGI_MASK;
3281 sgi = 1;
3282 }
3283
3284 if (WARN_ON(rate_index > RATE_MCS_7_40))
3285 rate_index = RATE_MCS_7_40;
3286
3287 return wmi_rate_tbl[(u32) rate_index][sgi];
3148} 3288}
3149 3289
3150static int ath6kl_wmi_get_pmkid_list_event_rx(struct wmi *wmi, u8 *datap, 3290static int ath6kl_wmi_get_pmkid_list_event_rx(struct wmi *wmi, u8 *datap,
@@ -3634,6 +3774,19 @@ int ath6kl_wmi_set_inact_period(struct wmi *wmi, u8 if_idx, int inact_timeout)
3634 NO_SYNC_WMIFLAG); 3774 NO_SYNC_WMIFLAG);
3635} 3775}
3636 3776
3777static void ath6kl_wmi_hb_challenge_resp_event(struct wmi *wmi, u8 *datap,
3778 int len)
3779{
3780 struct wmix_hb_challenge_resp_cmd *cmd;
3781
3782 if (len < sizeof(struct wmix_hb_challenge_resp_cmd))
3783 return;
3784
3785 cmd = (struct wmix_hb_challenge_resp_cmd *) datap;
3786 ath6kl_recovery_hb_event(wmi->parent_dev,
3787 le32_to_cpu(cmd->cookie));
3788}
3789
3637static int ath6kl_wmi_control_rx_xtnd(struct wmi *wmi, struct sk_buff *skb) 3790static int ath6kl_wmi_control_rx_xtnd(struct wmi *wmi, struct sk_buff *skb)
3638{ 3791{
3639 struct wmix_cmd_hdr *cmd; 3792 struct wmix_cmd_hdr *cmd;
@@ -3658,6 +3811,7 @@ static int ath6kl_wmi_control_rx_xtnd(struct wmi *wmi, struct sk_buff *skb)
3658 switch (id) { 3811 switch (id) {
3659 case WMIX_HB_CHALLENGE_RESP_EVENTID: 3812 case WMIX_HB_CHALLENGE_RESP_EVENTID:
3660 ath6kl_dbg(ATH6KL_DBG_WMI, "wmi event hb challenge resp\n"); 3813 ath6kl_dbg(ATH6KL_DBG_WMI, "wmi event hb challenge resp\n");
3814 ath6kl_wmi_hb_challenge_resp_event(wmi, datap, len);
3661 break; 3815 break;
3662 case WMIX_DBGLOG_EVENTID: 3816 case WMIX_DBGLOG_EVENTID:
3663 ath6kl_dbg(ATH6KL_DBG_WMI, "wmi event dbglog len %d\n", len); 3817 ath6kl_dbg(ATH6KL_DBG_WMI, "wmi event dbglog len %d\n", len);
@@ -3750,6 +3904,9 @@ static int ath6kl_wmi_proc_events_vif(struct wmi *wmi, u16 if_idx, u16 cmd_id,
3750 case WMI_RX_ACTION_EVENTID: 3904 case WMI_RX_ACTION_EVENTID:
3751 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_RX_ACTION_EVENTID\n"); 3905 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_RX_ACTION_EVENTID\n");
3752 return ath6kl_wmi_rx_action_event_rx(wmi, datap, len, vif); 3906 return ath6kl_wmi_rx_action_event_rx(wmi, datap, len, vif);
3907 case WMI_TXE_NOTIFY_EVENTID:
3908 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TXE_NOTIFY_EVENTID\n");
3909 return ath6kl_wmi_txe_notify_event_rx(wmi, datap, len, vif);
3753 default: 3910 default:
3754 ath6kl_dbg(ATH6KL_DBG_WMI, "unknown cmd id 0x%x\n", cmd_id); 3911 ath6kl_dbg(ATH6KL_DBG_WMI, "unknown cmd id 0x%x\n", cmd_id);
3755 return -EINVAL; 3912 return -EINVAL;
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h
index 43339aca585..98b1755e67f 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.h
+++ b/drivers/net/wireless/ath/ath6kl/wmi.h
@@ -48,7 +48,7 @@
48 48
49#define A_BAND_24GHZ 0 49#define A_BAND_24GHZ 0
50#define A_BAND_5GHZ 1 50#define A_BAND_5GHZ 1
51#define A_NUM_BANDS 2 51#define ATH6KL_NUM_BANDS 2
52 52
53/* in ms */ 53/* in ms */
54#define WMI_IMPLICIT_PSTREAM_INACTIVITY_INT 5000 54#define WMI_IMPLICIT_PSTREAM_INACTIVITY_INT 5000
@@ -628,6 +628,20 @@ enum wmi_cmd_id {
628 WMI_SET_MCASTRATE, 628 WMI_SET_MCASTRATE,
629 629
630 WMI_STA_BMISS_ENHANCE_CMDID, 630 WMI_STA_BMISS_ENHANCE_CMDID,
631
632 WMI_SET_REGDOMAIN_CMDID,
633
634 WMI_SET_RSSI_FILTER_CMDID,
635
636 WMI_SET_KEEP_ALIVE_EXT,
637
638 WMI_VOICE_DETECTION_ENABLE_CMDID,
639
640 WMI_SET_TXE_NOTIFY_CMDID,
641
642 WMI_SET_RECOVERY_TEST_PARAMETER_CMDID, /*0xf094*/
643
644 WMI_ENABLE_SCHED_SCAN_CMDID,
631}; 645};
632 646
633enum wmi_mgmt_frame_type { 647enum wmi_mgmt_frame_type {
@@ -843,7 +857,7 @@ struct wmi_begin_scan_cmd {
843 u8 scan_type; 857 u8 scan_type;
844 858
845 /* Supported rates to advertise in the probe request frames */ 859 /* Supported rates to advertise in the probe request frames */
846 struct wmi_supp_rates supp_rates[IEEE80211_NUM_BANDS]; 860 struct wmi_supp_rates supp_rates[ATH6KL_NUM_BANDS];
847 861
848 /* how many channels follow */ 862 /* how many channels follow */
849 u8 num_ch; 863 u8 num_ch;
@@ -941,6 +955,11 @@ struct wmi_scan_params_cmd {
941 __le32 max_dfsch_act_time; 955 __le32 max_dfsch_act_time;
942} __packed; 956} __packed;
943 957
958/* WMI_ENABLE_SCHED_SCAN_CMDID */
959struct wmi_enable_sched_scan_cmd {
960 u8 enable;
961} __packed;
962
944/* WMI_SET_BSS_FILTER_CMDID */ 963/* WMI_SET_BSS_FILTER_CMDID */
945enum wmi_bss_filter { 964enum wmi_bss_filter {
946 /* no beacons forwarded */ 965 /* no beacons forwarded */
@@ -1032,6 +1051,11 @@ struct wmi_sta_bmiss_enhance_cmd {
1032 u8 enable; 1051 u8 enable;
1033} __packed; 1052} __packed;
1034 1053
1054struct wmi_set_regdomain_cmd {
1055 u8 length;
1056 u8 iso_name[2];
1057} __packed;
1058
1035/* WMI_SET_POWER_MODE_CMDID */ 1059/* WMI_SET_POWER_MODE_CMDID */
1036enum wmi_power_mode { 1060enum wmi_power_mode {
1037 REC_POWER = 0x01, 1061 REC_POWER = 0x01,
@@ -1276,6 +1300,11 @@ struct wmi_snr_threshold_params_cmd {
1276 u8 reserved[3]; 1300 u8 reserved[3];
1277} __packed; 1301} __packed;
1278 1302
1303/* Don't report BSSs with signal (RSSI) below this threshold */
1304struct wmi_set_rssi_filter_cmd {
1305 s8 rssi;
1306} __packed;
1307
1279enum wmi_preamble_policy { 1308enum wmi_preamble_policy {
1280 WMI_IGNORE_BARKER_IN_ERP = 0, 1309 WMI_IGNORE_BARKER_IN_ERP = 0,
1281 WMI_FOLLOW_BARKER_IN_ERP, 1310 WMI_FOLLOW_BARKER_IN_ERP,
@@ -1455,6 +1484,20 @@ enum wmi_event_id {
1455 WMI_P2P_CAPABILITIES_EVENTID, 1484 WMI_P2P_CAPABILITIES_EVENTID,
1456 WMI_RX_ACTION_EVENTID, 1485 WMI_RX_ACTION_EVENTID,
1457 WMI_P2P_INFO_EVENTID, 1486 WMI_P2P_INFO_EVENTID,
1487
1488 /* WPS Events */
1489 WMI_WPS_GET_STATUS_EVENTID,
1490 WMI_WPS_PROFILE_EVENTID,
1491
1492 /* more P2P events */
1493 WMI_NOA_INFO_EVENTID,
1494 WMI_OPPPS_INFO_EVENTID,
1495 WMI_PORT_STATUS_EVENTID,
1496
1497 /* 802.11w */
1498 WMI_GET_RSN_CAP_EVENTID,
1499
1500 WMI_TXE_NOTIFY_EVENTID,
1458}; 1501};
1459 1502
1460struct wmi_ready_event_2 { 1503struct wmi_ready_event_2 {
@@ -1749,6 +1792,9 @@ struct rx_stats {
1749 a_sle32 ucast_rate; 1792 a_sle32 ucast_rate;
1750} __packed; 1793} __packed;
1751 1794
1795#define RATE_INDEX_WITHOUT_SGI_MASK 0x7f
1796#define RATE_INDEX_MSB 0x80
1797
1752struct tkip_ccmp_stats { 1798struct tkip_ccmp_stats {
1753 __le32 tkip_local_mic_fail; 1799 __le32 tkip_local_mic_fail;
1754 __le32 tkip_cnter_measures_invoked; 1800 __le32 tkip_cnter_measures_invoked;
@@ -2019,7 +2065,6 @@ struct wmi_set_ie_cmd {
2019 2065
2020#define WOW_MAX_FILTERS_PER_LIST 4 2066#define WOW_MAX_FILTERS_PER_LIST 4
2021#define WOW_PATTERN_SIZE 64 2067#define WOW_PATTERN_SIZE 64
2022#define WOW_MASK_SIZE 64
2023 2068
2024#define MAC_MAX_FILTERS_PER_LIST 4 2069#define MAC_MAX_FILTERS_PER_LIST 4
2025 2070
@@ -2028,7 +2073,7 @@ struct wow_filter {
2028 u8 wow_filter_id; 2073 u8 wow_filter_id;
2029 u8 wow_filter_size; 2074 u8 wow_filter_size;
2030 u8 wow_filter_offset; 2075 u8 wow_filter_offset;
2031 u8 wow_filter_mask[WOW_MASK_SIZE]; 2076 u8 wow_filter_mask[WOW_PATTERN_SIZE];
2032 u8 wow_filter_pattern[WOW_PATTERN_SIZE]; 2077 u8 wow_filter_pattern[WOW_PATTERN_SIZE];
2033} __packed; 2078} __packed;
2034 2079
@@ -2087,6 +2132,19 @@ struct wmi_del_wow_pattern_cmd {
2087 __le16 filter_id; 2132 __le16 filter_id;
2088} __packed; 2133} __packed;
2089 2134
2135/* WMI_SET_TXE_NOTIFY_CMDID */
2136struct wmi_txe_notify_cmd {
2137 __le32 rate;
2138 __le32 pkts;
2139 __le32 intvl;
2140} __packed;
2141
2142/* WMI_TXE_NOTIFY_EVENTID */
2143struct wmi_txe_notify_event {
2144 __le32 rate;
2145 __le32 pkts;
2146} __packed;
2147
2090/* WMI_SET_AKMP_PARAMS_CMD */ 2148/* WMI_SET_AKMP_PARAMS_CMD */
2091 2149
2092struct wmi_pmkid { 2150struct wmi_pmkid {
@@ -2505,11 +2563,6 @@ int ath6kl_wmi_connect_cmd(struct wmi *wmi, u8 if_idx,
2505int ath6kl_wmi_reconnect_cmd(struct wmi *wmi, u8 if_idx, u8 *bssid, 2563int ath6kl_wmi_reconnect_cmd(struct wmi *wmi, u8 if_idx, u8 *bssid,
2506 u16 channel); 2564 u16 channel);
2507int ath6kl_wmi_disconnect_cmd(struct wmi *wmi, u8 if_idx); 2565int ath6kl_wmi_disconnect_cmd(struct wmi *wmi, u8 if_idx);
2508int ath6kl_wmi_startscan_cmd(struct wmi *wmi, u8 if_idx,
2509 enum wmi_scan_type scan_type,
2510 u32 force_fgscan, u32 is_legacy,
2511 u32 home_dwell_time, u32 force_scan_interval,
2512 s8 num_chan, u16 *ch_list);
2513 2566
2514int ath6kl_wmi_beginscan_cmd(struct wmi *wmi, u8 if_idx, 2567int ath6kl_wmi_beginscan_cmd(struct wmi *wmi, u8 if_idx,
2515 enum wmi_scan_type scan_type, 2568 enum wmi_scan_type scan_type,
@@ -2517,6 +2570,7 @@ int ath6kl_wmi_beginscan_cmd(struct wmi *wmi, u8 if_idx,
2517 u32 home_dwell_time, u32 force_scan_interval, 2570 u32 home_dwell_time, u32 force_scan_interval,
2518 s8 num_chan, u16 *ch_list, u32 no_cck, 2571 s8 num_chan, u16 *ch_list, u32 no_cck,
2519 u32 *rates); 2572 u32 *rates);
2573int ath6kl_wmi_enable_sched_scan_cmd(struct wmi *wmi, u8 if_idx, bool enable);
2520 2574
2521int ath6kl_wmi_scanparams_cmd(struct wmi *wmi, u8 if_idx, u16 fg_start_sec, 2575int ath6kl_wmi_scanparams_cmd(struct wmi *wmi, u8 if_idx, u16 fg_start_sec,
2522 u16 fg_end_sec, u16 bg_sec, 2576 u16 fg_end_sec, u16 bg_sec,
@@ -2592,6 +2646,7 @@ int ath6kl_wmi_add_wow_pattern_cmd(struct wmi *wmi, u8 if_idx,
2592 const u8 *mask); 2646 const u8 *mask);
2593int ath6kl_wmi_del_wow_pattern_cmd(struct wmi *wmi, u8 if_idx, 2647int ath6kl_wmi_del_wow_pattern_cmd(struct wmi *wmi, u8 if_idx,
2594 u16 list_id, u16 filter_id); 2648 u16 list_id, u16 filter_id);
2649int ath6kl_wmi_set_rssi_filter_cmd(struct wmi *wmi, u8 if_idx, s8 rssi);
2595int ath6kl_wmi_set_roam_lrssi_cmd(struct wmi *wmi, u8 lrssi); 2650int ath6kl_wmi_set_roam_lrssi_cmd(struct wmi *wmi, u8 lrssi);
2596int ath6kl_wmi_ap_set_dtim_cmd(struct wmi *wmi, u8 if_idx, u32 dtim_period); 2651int ath6kl_wmi_ap_set_dtim_cmd(struct wmi *wmi, u8 if_idx, u32 dtim_period);
2597int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid); 2652int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid);
@@ -2600,6 +2655,9 @@ int ath6kl_wmi_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, bool mc_all_on);
2600int ath6kl_wmi_add_del_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, 2655int ath6kl_wmi_add_del_mcast_filter_cmd(struct wmi *wmi, u8 if_idx,
2601 u8 *filter, bool add_filter); 2656 u8 *filter, bool add_filter);
2602int ath6kl_wmi_sta_bmiss_enhance_cmd(struct wmi *wmi, u8 if_idx, bool enable); 2657int ath6kl_wmi_sta_bmiss_enhance_cmd(struct wmi *wmi, u8 if_idx, bool enable);
2658int ath6kl_wmi_set_txe_notify(struct wmi *wmi, u8 idx,
2659 u32 rate, u32 pkts, u32 intvl);
2660int ath6kl_wmi_set_regdomain_cmd(struct wmi *wmi, const char *alpha2);
2603 2661
2604/* AP mode uAPSD */ 2662/* AP mode uAPSD */
2605int ath6kl_wmi_ap_set_apsd(struct wmi *wmi, u8 if_idx, u8 enable); 2663int ath6kl_wmi_ap_set_apsd(struct wmi *wmi, u8 if_idx, u8 enable);
@@ -2658,6 +2716,8 @@ int ath6kl_wmi_set_inact_period(struct wmi *wmi, u8 if_idx, int inact_timeout);
2658 2716
2659void ath6kl_wmi_sscan_timer(unsigned long ptr); 2717void ath6kl_wmi_sscan_timer(unsigned long ptr);
2660 2718
2719int ath6kl_wmi_get_challenge_resp_cmd(struct wmi *wmi, u32 cookie, u32 source);
2720
2661struct ath6kl_vif *ath6kl_get_vif_by_index(struct ath6kl *ar, u8 if_idx); 2721struct ath6kl_vif *ath6kl_get_vif_by_index(struct ath6kl *ar, u8 if_idx);
2662void *ath6kl_wmi_init(struct ath6kl *devt); 2722void *ath6kl_wmi_init(struct ath6kl *devt);
2663void ath6kl_wmi_shutdown(struct wmi *wmi); 2723void ath6kl_wmi_shutdown(struct wmi *wmi);