aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath6kl
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2012-03-13 14:45:40 -0400
committerJohn W. Linville <linville@tuxdriver.com>2012-03-13 14:45:40 -0400
commit843dc6644be05edfcb14f7f7ce5b2ab2bc15b429 (patch)
tree0e2c580ac949d2619522a64cc5a52585645491f5 /drivers/net/wireless/ath/ath6kl
parent5d6a1b069b7f72298aff2306a2d02b0188668218 (diff)
parent9df2a0b7096873e91d1b6b0e842e9f6bdc7ee9fd (diff)
Merge branch 'for-linville' of git://github.com/kvalo/ath6kl
Diffstat (limited to 'drivers/net/wireless/ath/ath6kl')
-rw-r--r--drivers/net/wireless/ath/ath6kl/Makefile3
-rw-r--r--drivers/net/wireless/ath/ath6kl/bmi.c7
-rw-r--r--drivers/net/wireless/ath/ath6kl/bmi.h24
-rw-r--r--drivers/net/wireless/ath/ath6kl/cfg80211.c342
-rw-r--r--drivers/net/wireless/ath/ath6kl/cfg80211.h1
-rw-r--r--drivers/net/wireless/ath/ath6kl/common.h1
-rw-r--r--drivers/net/wireless/ath/ath6kl/core.c117
-rw-r--r--drivers/net/wireless/ath/ath6kl/core.h64
-rw-r--r--drivers/net/wireless/ath/ath6kl/debug.c325
-rw-r--r--drivers/net/wireless/ath/ath6kl/debug.h10
-rw-r--r--drivers/net/wireless/ath/ath6kl/hif-ops.h1
-rw-r--r--drivers/net/wireless/ath/ath6kl/hif.c12
-rw-r--r--drivers/net/wireless/ath/ath6kl/hif.h4
-rw-r--r--drivers/net/wireless/ath/ath6kl/htc.c202
-rw-r--r--drivers/net/wireless/ath/ath6kl/htc.h16
-rw-r--r--drivers/net/wireless/ath/ath6kl/init.c210
-rw-r--r--drivers/net/wireless/ath/ath6kl/main.c72
-rw-r--r--drivers/net/wireless/ath/ath6kl/sdio.c77
-rw-r--r--drivers/net/wireless/ath/ath6kl/target.h2
-rw-r--r--drivers/net/wireless/ath/ath6kl/testmode.c1
-rw-r--r--drivers/net/wireless/ath/ath6kl/testmode.h1
-rw-r--r--drivers/net/wireless/ath/ath6kl/txrx.c72
-rw-r--r--drivers/net/wireless/ath/ath6kl/usb.c1
-rw-r--r--drivers/net/wireless/ath/ath6kl/wmi.c307
-rw-r--r--drivers/net/wireless/ath/ath6kl/wmi.h23
25 files changed, 1228 insertions, 667 deletions
diff --git a/drivers/net/wireless/ath/ath6kl/Makefile b/drivers/net/wireless/ath/ath6kl/Makefile
index 9ba42fa04962..85746c3eb027 100644
--- a/drivers/net/wireless/ath/ath6kl/Makefile
+++ b/drivers/net/wireless/ath/ath6kl/Makefile
@@ -1,5 +1,6 @@
1#------------------------------------------------------------------------------ 1#------------------------------------------------------------------------------
2# Copyright (c) 2004-2010 Atheros Communications Inc. 2# Copyright (c) 2004-2011 Atheros Communications Inc.
3# Copyright (c) 2011-2012 Qualcomm Atheros, Inc.
3# All rights reserved. 4# All rights reserved.
4# 5#
5# 6#
diff --git a/drivers/net/wireless/ath/ath6kl/bmi.c b/drivers/net/wireless/ath/ath6kl/bmi.c
index aef00d5a1438..334dbd834b3a 100644
--- a/drivers/net/wireless/ath/ath6kl/bmi.c
+++ b/drivers/net/wireless/ath/ath6kl/bmi.c
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (c) 2004-2011 Atheros Communications Inc. 2 * Copyright (c) 2004-2011 Atheros Communications Inc.
3 * Copyright (c) 2011-2012 Qualcomm Atheros, Inc.
3 * 4 *
4 * Permission to use, copy, modify, and/or distribute this software for any 5 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above 6 * purpose with or without fee is hereby granted, provided that the above
@@ -105,7 +106,7 @@ int ath6kl_bmi_get_target_info(struct ath6kl *ar,
105 } 106 }
106 107
107 ath6kl_dbg(ATH6KL_DBG_BMI, "target info (ver: 0x%x type: 0x%x)\n", 108 ath6kl_dbg(ATH6KL_DBG_BMI, "target info (ver: 0x%x type: 0x%x)\n",
108 targ_info->version, targ_info->type); 109 targ_info->version, targ_info->type);
109 110
110 return 0; 111 return 0;
111} 112}
@@ -192,7 +193,7 @@ int ath6kl_bmi_write(struct ath6kl *ar, u32 addr, u8 *buf, u32 len)
192 memset(ar->bmi.cmd_buf, 0, ar->bmi.max_data_size + header); 193 memset(ar->bmi.cmd_buf, 0, ar->bmi.max_data_size + header);
193 194
194 ath6kl_dbg(ATH6KL_DBG_BMI, 195 ath6kl_dbg(ATH6KL_DBG_BMI,
195 "bmi write memory: addr: 0x%x, len: %d\n", addr, len); 196 "bmi write memory: addr: 0x%x, len: %d\n", addr, len);
196 197
197 len_remain = len; 198 len_remain = len;
198 while (len_remain) { 199 while (len_remain) {
@@ -434,7 +435,7 @@ int ath6kl_bmi_lz_data(struct ath6kl *ar, u8 *buf, u32 len)
434 memcpy(&(ar->bmi.cmd_buf[offset]), &tx_len, sizeof(tx_len)); 435 memcpy(&(ar->bmi.cmd_buf[offset]), &tx_len, sizeof(tx_len));
435 offset += sizeof(tx_len); 436 offset += sizeof(tx_len);
436 memcpy(&(ar->bmi.cmd_buf[offset]), &buf[len - len_remain], 437 memcpy(&(ar->bmi.cmd_buf[offset]), &buf[len - len_remain],
437 tx_len); 438 tx_len);
438 offset += tx_len; 439 offset += tx_len;
439 440
440 ret = ath6kl_hif_bmi_write(ar, ar->bmi.cmd_buf, offset); 441 ret = ath6kl_hif_bmi_write(ar, ar->bmi.cmd_buf, offset);
diff --git a/drivers/net/wireless/ath/ath6kl/bmi.h b/drivers/net/wireless/ath/ath6kl/bmi.h
index f1ca6812456d..18fdd69e1f71 100644
--- a/drivers/net/wireless/ath/ath6kl/bmi.h
+++ b/drivers/net/wireless/ath/ath6kl/bmi.h
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (c) 2004-2011 Atheros Communications Inc. 2 * Copyright (c) 2004-2011 Atheros Communications Inc.
3 * Copyright (c) 2011 Qualcomm Atheros, Inc.
3 * 4 *
4 * Permission to use, copy, modify, and/or distribute this software for any 5 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above 6 * purpose with or without fee is hereby granted, provided that the above
@@ -222,6 +223,29 @@ struct ath6kl_bmi_target_info {
222 __le32 type; /* target type */ 223 __le32 type; /* target type */
223} __packed; 224} __packed;
224 225
226#define ath6kl_bmi_write_hi32(ar, item, val) \
227 ({ \
228 u32 addr; \
229 __le32 v; \
230 \
231 addr = ath6kl_get_hi_item_addr(ar, HI_ITEM(item)); \
232 v = cpu_to_le32(val); \
233 ath6kl_bmi_write(ar, addr, (u8 *) &v, sizeof(v)); \
234 })
235
236#define ath6kl_bmi_read_hi32(ar, item, val) \
237 ({ \
238 u32 addr, *check_type = val; \
239 __le32 tmp; \
240 int ret; \
241 \
242 (void) (check_type == val); \
243 addr = ath6kl_get_hi_item_addr(ar, HI_ITEM(item)); \
244 ret = ath6kl_bmi_read(ar, addr, (u8 *) &tmp, 4); \
245 *val = le32_to_cpu(tmp); \
246 ret; \
247 })
248
225int ath6kl_bmi_init(struct ath6kl *ar); 249int ath6kl_bmi_init(struct ath6kl *ar);
226void ath6kl_bmi_cleanup(struct ath6kl *ar); 250void ath6kl_bmi_cleanup(struct ath6kl *ar);
227void ath6kl_bmi_reset(struct ath6kl *ar); 251void ath6kl_bmi_reset(struct ath6kl *ar);
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index 5370333883e4..00d38952b5fb 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (c) 2004-2011 Atheros Communications Inc. 2 * Copyright (c) 2004-2011 Atheros Communications Inc.
3 * Copyright (c) 2011-2012 Qualcomm Atheros, Inc.
3 * 4 *
4 * Permission to use, copy, modify, and/or distribute this software for any 5 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above 6 * purpose with or without fee is hereby granted, provided that the above
@@ -68,6 +69,10 @@ static struct ieee80211_rate ath6kl_rates[] = {
68#define ath6kl_g_rates (ath6kl_rates + 0) 69#define ath6kl_g_rates (ath6kl_rates + 0)
69#define ath6kl_g_rates_size 12 70#define ath6kl_g_rates_size 12
70 71
72#define ath6kl_g_htcap (IEEE80211_HT_CAP_SUP_WIDTH_20_40 | \
73 IEEE80211_HT_CAP_SGI_20 | \
74 IEEE80211_HT_CAP_SGI_40)
75
71static struct ieee80211_channel ath6kl_2ghz_channels[] = { 76static struct ieee80211_channel ath6kl_2ghz_channels[] = {
72 CHAN2G(1, 2412, 0), 77 CHAN2G(1, 2412, 0),
73 CHAN2G(2, 2417, 0), 78 CHAN2G(2, 2417, 0),
@@ -112,6 +117,8 @@ static struct ieee80211_supported_band ath6kl_band_2ghz = {
112 .channels = ath6kl_2ghz_channels, 117 .channels = ath6kl_2ghz_channels,
113 .n_bitrates = ath6kl_g_rates_size, 118 .n_bitrates = ath6kl_g_rates_size,
114 .bitrates = ath6kl_g_rates, 119 .bitrates = ath6kl_g_rates,
120 .ht_cap.cap = ath6kl_g_htcap,
121 .ht_cap.ht_supported = true,
115}; 122};
116 123
117static struct ieee80211_supported_band ath6kl_band_5ghz = { 124static struct ieee80211_supported_band ath6kl_band_5ghz = {
@@ -119,6 +126,8 @@ static struct ieee80211_supported_band ath6kl_band_5ghz = {
119 .channels = ath6kl_5ghz_a_channels, 126 .channels = ath6kl_5ghz_a_channels,
120 .n_bitrates = ath6kl_a_rates_size, 127 .n_bitrates = ath6kl_a_rates_size,
121 .bitrates = ath6kl_a_rates, 128 .bitrates = ath6kl_a_rates,
129 .ht_cap.cap = ath6kl_g_htcap,
130 .ht_cap.ht_supported = true,
122}; 131};
123 132
124#define CCKM_KRK_CIPHER_SUITE 0x004096ff /* use for KRK */ 133#define CCKM_KRK_CIPHER_SUITE 0x004096ff /* use for KRK */
@@ -381,7 +390,7 @@ static bool ath6kl_is_valid_iftype(struct ath6kl *ar, enum nl80211_iftype type,
381 return false; 390 return false;
382 391
383 if (ar->ibss_if_active || ((type == NL80211_IFTYPE_ADHOC) && 392 if (ar->ibss_if_active || ((type == NL80211_IFTYPE_ADHOC) &&
384 ar->num_vif)) 393 ar->num_vif))
385 return false; 394 return false;
386 395
387 if (type == NL80211_IFTYPE_STATION || 396 if (type == NL80211_IFTYPE_STATION ||
@@ -407,6 +416,12 @@ static bool ath6kl_is_valid_iftype(struct ath6kl *ar, enum nl80211_iftype type,
407 return false; 416 return false;
408} 417}
409 418
419static bool ath6kl_is_tx_pending(struct ath6kl *ar)
420{
421 return ar->tx_pending[ath6kl_wmi_get_control_ep(ar->wmi)] == 0;
422}
423
424
410static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, 425static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
411 struct cfg80211_connect_params *sme) 426 struct cfg80211_connect_params *sme)
412{ 427{
@@ -414,6 +429,7 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
414 struct ath6kl_vif *vif = netdev_priv(dev); 429 struct ath6kl_vif *vif = netdev_priv(dev);
415 int status; 430 int status;
416 u8 nw_subtype = (ar->p2p) ? SUBTYPE_P2PDEV : SUBTYPE_NONE; 431 u8 nw_subtype = (ar->p2p) ? SUBTYPE_P2PDEV : SUBTYPE_NONE;
432 u16 interval;
417 433
418 ath6kl_cfg80211_sscan_disable(vif); 434 ath6kl_cfg80211_sscan_disable(vif);
419 435
@@ -450,8 +466,8 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
450 * sleep until the command queue drains 466 * sleep until the command queue drains
451 */ 467 */
452 wait_event_interruptible_timeout(ar->event_wq, 468 wait_event_interruptible_timeout(ar->event_wq,
453 ar->tx_pending[ath6kl_wmi_get_control_ep(ar->wmi)] == 0, 469 ath6kl_is_tx_pending(ar),
454 WMI_TIMEOUT); 470 WMI_TIMEOUT);
455 if (signal_pending(current)) { 471 if (signal_pending(current)) {
456 ath6kl_err("cmd queue drain timeout\n"); 472 ath6kl_err("cmd queue drain timeout\n");
457 up(&ar->sem); 473 up(&ar->sem);
@@ -546,7 +562,7 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
546 if (!ar->usr_bss_filter) { 562 if (!ar->usr_bss_filter) {
547 clear_bit(CLEAR_BSSFILTER_ON_BEACON, &vif->flags); 563 clear_bit(CLEAR_BSSFILTER_ON_BEACON, &vif->flags);
548 if (ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx, 564 if (ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx,
549 ALL_BSS_FILTER, 0) != 0) { 565 ALL_BSS_FILTER, 0) != 0) {
550 ath6kl_err("couldn't set bss filtering\n"); 566 ath6kl_err("couldn't set bss filtering\n");
551 up(&ar->sem); 567 up(&ar->sem);
552 return -EIO; 568 return -EIO;
@@ -568,6 +584,20 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
568 vif->grp_crypto_len, vif->ch_hint); 584 vif->grp_crypto_len, vif->ch_hint);
569 585
570 vif->reconnect_flag = 0; 586 vif->reconnect_flag = 0;
587
588 if (vif->nw_type == INFRA_NETWORK) {
589 interval = max_t(u16, vif->listen_intvl_t,
590 ATH6KL_MAX_WOW_LISTEN_INTL);
591 status = ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx,
592 interval,
593 0);
594 if (status) {
595 ath6kl_err("couldn't set listen intervel\n");
596 up(&ar->sem);
597 return status;
598 }
599 }
600
571 status = ath6kl_wmi_connect_cmd(ar->wmi, vif->fw_vif_idx, vif->nw_type, 601 status = ath6kl_wmi_connect_cmd(ar->wmi, vif->fw_vif_idx, vif->nw_type,
572 vif->dot11_auth_mode, vif->auth_mode, 602 vif->dot11_auth_mode, vif->auth_mode,
573 vif->prwise_crypto, 603 vif->prwise_crypto,
@@ -590,8 +620,8 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
590 } 620 }
591 621
592 if ((!(ar->connect_ctrl_flags & CONNECT_DO_WPA_OFFLOAD)) && 622 if ((!(ar->connect_ctrl_flags & CONNECT_DO_WPA_OFFLOAD)) &&
593 ((vif->auth_mode == WPA_PSK_AUTH) 623 ((vif->auth_mode == WPA_PSK_AUTH) ||
594 || (vif->auth_mode == WPA2_PSK_AUTH))) { 624 (vif->auth_mode == WPA2_PSK_AUTH))) {
595 mod_timer(&vif->disconnect_timer, 625 mod_timer(&vif->disconnect_timer,
596 jiffies + msecs_to_jiffies(DISCON_TIMER_INTVAL)); 626 jiffies + msecs_to_jiffies(DISCON_TIMER_INTVAL));
597 } 627 }
@@ -824,13 +854,13 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason,
824 854
825 if (vif->sme_state == SME_CONNECTING) { 855 if (vif->sme_state == SME_CONNECTING) {
826 cfg80211_connect_result(vif->ndev, 856 cfg80211_connect_result(vif->ndev,
827 bssid, NULL, 0, 857 bssid, NULL, 0,
828 NULL, 0, 858 NULL, 0,
829 WLAN_STATUS_UNSPECIFIED_FAILURE, 859 WLAN_STATUS_UNSPECIFIED_FAILURE,
830 GFP_KERNEL); 860 GFP_KERNEL);
831 } else if (vif->sme_state == SME_CONNECTED) { 861 } else if (vif->sme_state == SME_CONNECTED) {
832 cfg80211_disconnected(vif->ndev, reason, 862 cfg80211_disconnected(vif->ndev, reason,
833 NULL, 0, GFP_KERNEL); 863 NULL, 0, GFP_KERNEL);
834 } 864 }
835 865
836 vif->sme_state = SME_DISCONNECTED; 866 vif->sme_state = SME_DISCONNECTED;
@@ -876,19 +906,14 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
876 request->ssids[i].ssid); 906 request->ssids[i].ssid);
877 } 907 }
878 908
879 /* 909 /* this also clears IE in fw if it's not set */
880 * FIXME: we should clear the IE in fw if it's not set so just 910 ret = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
881 * remove the check altogether 911 WMI_FRAME_PROBE_REQ,
882 */ 912 request->ie, request->ie_len);
883 if (request->ie) { 913 if (ret) {
884 ret = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx, 914 ath6kl_err("failed to set Probe Request appie for "
885 WMI_FRAME_PROBE_REQ, 915 "scan");
886 request->ie, request->ie_len); 916 return ret;
887 if (ret) {
888 ath6kl_err("failed to set Probe Request appie for "
889 "scan");
890 return ret;
891 }
892 } 917 }
893 918
894 /* 919 /*
@@ -917,7 +942,7 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
917 force_fg_scan = 1; 942 force_fg_scan = 1;
918 943
919 if (test_bit(ATH6KL_FW_CAPABILITY_STA_P2PDEV_DUPLEX, 944 if (test_bit(ATH6KL_FW_CAPABILITY_STA_P2PDEV_DUPLEX,
920 ar->fw_capabilities)) { 945 ar->fw_capabilities)) {
921 /* 946 /*
922 * If capable of doing P2P mgmt operations using 947 * If capable of doing P2P mgmt operations using
923 * station interface, send additional information like 948 * station interface, send additional information like
@@ -926,14 +951,17 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
926 */ 951 */
927 ret = ath6kl_wmi_beginscan_cmd(ar->wmi, vif->fw_vif_idx, 952 ret = ath6kl_wmi_beginscan_cmd(ar->wmi, vif->fw_vif_idx,
928 WMI_LONG_SCAN, force_fg_scan, 953 WMI_LONG_SCAN, force_fg_scan,
929 false, 0, 0, n_channels, 954 false, 0,
930 channels, request->no_cck, 955 ATH6KL_FG_SCAN_INTERVAL,
956 n_channels, channels,
957 request->no_cck,
931 request->rates); 958 request->rates);
932 } else { 959 } else {
933 ret = ath6kl_wmi_startscan_cmd(ar->wmi, vif->fw_vif_idx, 960 ret = ath6kl_wmi_startscan_cmd(ar->wmi, vif->fw_vif_idx,
934 WMI_LONG_SCAN, force_fg_scan, 961 WMI_LONG_SCAN, force_fg_scan,
935 false, 0, 0, n_channels, 962 false, 0,
936 channels); 963 ATH6KL_FG_SCAN_INTERVAL,
964 n_channels, channels);
937 } 965 }
938 if (ret) 966 if (ret)
939 ath6kl_err("wmi_startscan_cmd failed\n"); 967 ath6kl_err("wmi_startscan_cmd failed\n");
@@ -1046,9 +1074,9 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
1046 return -ENOTSUPP; 1074 return -ENOTSUPP;
1047 } 1075 }
1048 1076
1049 if (((vif->auth_mode == WPA_PSK_AUTH) 1077 if (((vif->auth_mode == WPA_PSK_AUTH) ||
1050 || (vif->auth_mode == WPA2_PSK_AUTH)) 1078 (vif->auth_mode == WPA2_PSK_AUTH)) &&
1051 && (key_usage & GROUP_USAGE)) 1079 (key_usage & GROUP_USAGE))
1052 del_timer(&vif->disconnect_timer); 1080 del_timer(&vif->disconnect_timer);
1053 1081
1054 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, 1082 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
@@ -1058,7 +1086,7 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
1058 1086
1059 if (vif->nw_type == AP_NETWORK && !pairwise && 1087 if (vif->nw_type == AP_NETWORK && !pairwise &&
1060 (key_type == TKIP_CRYPT || key_type == AES_CRYPT || 1088 (key_type == TKIP_CRYPT || key_type == AES_CRYPT ||
1061 key_type == WAPI_CRYPT) && params) { 1089 key_type == WAPI_CRYPT)) {
1062 ar->ap_mode_bkey.valid = true; 1090 ar->ap_mode_bkey.valid = true;
1063 ar->ap_mode_bkey.key_index = key_index; 1091 ar->ap_mode_bkey.key_index = key_index;
1064 ar->ap_mode_bkey.key_type = key_type; 1092 ar->ap_mode_bkey.key_type = key_type;
@@ -1263,7 +1291,6 @@ static int ath6kl_cfg80211_set_txpower(struct wiphy *wiphy,
1263{ 1291{
1264 struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy); 1292 struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy);
1265 struct ath6kl_vif *vif; 1293 struct ath6kl_vif *vif;
1266 u8 ath6kl_dbm;
1267 int dbm = MBM_TO_DBM(mbm); 1294 int dbm = MBM_TO_DBM(mbm);
1268 1295
1269 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type 0x%x, dbm %d\n", __func__, 1296 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type 0x%x, dbm %d\n", __func__,
@@ -1280,7 +1307,7 @@ static int ath6kl_cfg80211_set_txpower(struct wiphy *wiphy,
1280 case NL80211_TX_POWER_AUTOMATIC: 1307 case NL80211_TX_POWER_AUTOMATIC:
1281 return 0; 1308 return 0;
1282 case NL80211_TX_POWER_LIMITED: 1309 case NL80211_TX_POWER_LIMITED:
1283 ar->tx_pwr = ath6kl_dbm = dbm; 1310 ar->tx_pwr = dbm;
1284 break; 1311 break;
1285 default: 1312 default:
1286 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type 0x%x not supported\n", 1313 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type 0x%x not supported\n",
@@ -1288,7 +1315,7 @@ static int ath6kl_cfg80211_set_txpower(struct wiphy *wiphy,
1288 return -EOPNOTSUPP; 1315 return -EOPNOTSUPP;
1289 } 1316 }
1290 1317
1291 ath6kl_wmi_set_tx_pwr_cmd(ar->wmi, vif->fw_vif_idx, ath6kl_dbm); 1318 ath6kl_wmi_set_tx_pwr_cmd(ar->wmi, vif->fw_vif_idx, dbm);
1292 1319
1293 return 0; 1320 return 0;
1294} 1321}
@@ -1349,7 +1376,7 @@ static int ath6kl_cfg80211_set_power_mgmt(struct wiphy *wiphy,
1349 } 1376 }
1350 1377
1351 if (ath6kl_wmi_powermode_cmd(ar->wmi, vif->fw_vif_idx, 1378 if (ath6kl_wmi_powermode_cmd(ar->wmi, vif->fw_vif_idx,
1352 mode.pwr_mode) != 0) { 1379 mode.pwr_mode) != 0) {
1353 ath6kl_err("wmi_powermode_cmd failed\n"); 1380 ath6kl_err("wmi_powermode_cmd failed\n");
1354 return -EIO; 1381 return -EIO;
1355 } 1382 }
@@ -1904,7 +1931,7 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
1904 struct ath6kl_vif *vif; 1931 struct ath6kl_vif *vif;
1905 int ret, left; 1932 int ret, left;
1906 u32 filter = 0; 1933 u32 filter = 0;
1907 u16 i; 1934 u16 i, bmiss_time;
1908 u8 index = 0; 1935 u8 index = 0;
1909 __be32 ips[MAX_IP_ADDRS]; 1936 __be32 ips[MAX_IP_ADDRS];
1910 1937
@@ -1941,6 +1968,34 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
1941 if (ret) 1968 if (ret)
1942 return ret; 1969 return ret;
1943 1970
1971 netif_stop_queue(vif->ndev);
1972
1973 if (vif->nw_type != AP_NETWORK) {
1974 ret = ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx,
1975 ATH6KL_MAX_WOW_LISTEN_INTL,
1976 0);
1977 if (ret)
1978 return ret;
1979
1980 /* Set listen interval x 15 times as bmiss time */
1981 bmiss_time = ATH6KL_MAX_WOW_LISTEN_INTL * 15;
1982 if (bmiss_time > ATH6KL_MAX_BMISS_TIME)
1983 bmiss_time = ATH6KL_MAX_BMISS_TIME;
1984
1985 ret = ath6kl_wmi_bmisstime_cmd(ar->wmi, vif->fw_vif_idx,
1986 bmiss_time, 0);
1987 if (ret)
1988 return ret;
1989
1990 ret = ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx,
1991 0xFFFF, 0, 0xFFFF, 0, 0, 0,
1992 0, 0, 0, 0);
1993 if (ret)
1994 return ret;
1995 }
1996
1997 ar->state = ATH6KL_STATE_SUSPENDING;
1998
1944 /* Setup own IP addr for ARP agent. */ 1999 /* Setup own IP addr for ARP agent. */
1945 in_dev = __in_dev_get_rtnl(vif->ndev); 2000 in_dev = __in_dev_get_rtnl(vif->ndev);
1946 if (!in_dev) 2001 if (!in_dev)
@@ -2019,15 +2074,46 @@ static int ath6kl_wow_resume(struct ath6kl *ar)
2019 if (!vif) 2074 if (!vif)
2020 return -EIO; 2075 return -EIO;
2021 2076
2077 ar->state = ATH6KL_STATE_RESUMING;
2078
2022 ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx, 2079 ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx,
2023 ATH6KL_HOST_MODE_AWAKE); 2080 ATH6KL_HOST_MODE_AWAKE);
2024 return ret; 2081 if (ret) {
2082 ath6kl_warn("Failed to configure host sleep mode for "
2083 "wow resume: %d\n", ret);
2084 ar->state = ATH6KL_STATE_WOW;
2085 return ret;
2086 }
2087
2088 if (vif->nw_type != AP_NETWORK) {
2089 ret = ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx,
2090 0, 0, 0, 0, 0, 0, 3, 0, 0, 0);
2091 if (ret)
2092 return ret;
2093
2094 ret = ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx,
2095 vif->listen_intvl_t, 0);
2096 if (ret)
2097 return ret;
2098
2099 ret = ath6kl_wmi_bmisstime_cmd(ar->wmi, vif->fw_vif_idx,
2100 vif->bmiss_time_t, 0);
2101 if (ret)
2102 return ret;
2103 }
2104
2105 ar->state = ATH6KL_STATE_ON;
2106
2107 netif_wake_queue(vif->ndev);
2108
2109 return 0;
2025} 2110}
2026 2111
2027int ath6kl_cfg80211_suspend(struct ath6kl *ar, 2112int ath6kl_cfg80211_suspend(struct ath6kl *ar,
2028 enum ath6kl_cfg_suspend_mode mode, 2113 enum ath6kl_cfg_suspend_mode mode,
2029 struct cfg80211_wowlan *wow) 2114 struct cfg80211_wowlan *wow)
2030{ 2115{
2116 enum ath6kl_state prev_state;
2031 int ret; 2117 int ret;
2032 2118
2033 switch (mode) { 2119 switch (mode) {
@@ -2038,11 +2124,14 @@ int ath6kl_cfg80211_suspend(struct ath6kl *ar,
2038 /* Flush all non control pkts in TX path */ 2124 /* Flush all non control pkts in TX path */
2039 ath6kl_tx_data_cleanup(ar); 2125 ath6kl_tx_data_cleanup(ar);
2040 2126
2127 prev_state = ar->state;
2128
2041 ret = ath6kl_wow_suspend(ar, wow); 2129 ret = ath6kl_wow_suspend(ar, wow);
2042 if (ret) { 2130 if (ret) {
2043 ath6kl_err("wow suspend failed: %d\n", ret); 2131 ar->state = prev_state;
2044 return ret; 2132 return ret;
2045 } 2133 }
2134
2046 ar->state = ATH6KL_STATE_WOW; 2135 ar->state = ATH6KL_STATE_WOW;
2047 break; 2136 break;
2048 2137
@@ -2114,7 +2203,6 @@ int ath6kl_cfg80211_resume(struct ath6kl *ar)
2114 return ret; 2203 return ret;
2115 } 2204 }
2116 2205
2117 ar->state = ATH6KL_STATE_ON;
2118 break; 2206 break;
2119 2207
2120 case ATH6KL_STATE_DEEPSLEEP: 2208 case ATH6KL_STATE_DEEPSLEEP:
@@ -2188,6 +2276,9 @@ static int __ath6kl_cfg80211_resume(struct wiphy *wiphy)
2188 */ 2276 */
2189void ath6kl_check_wow_status(struct ath6kl *ar) 2277void ath6kl_check_wow_status(struct ath6kl *ar)
2190{ 2278{
2279 if (ar->state == ATH6KL_STATE_SUSPENDING)
2280 return;
2281
2191 if (ar->state == ATH6KL_STATE_WOW) 2282 if (ar->state == ATH6KL_STATE_WOW)
2192 ath6kl_cfg80211_resume(ar); 2283 ath6kl_cfg80211_resume(ar);
2193} 2284}
@@ -2275,30 +2366,27 @@ static int ath6kl_set_ies(struct ath6kl_vif *vif,
2275 struct ath6kl *ar = vif->ar; 2366 struct ath6kl *ar = vif->ar;
2276 int res; 2367 int res;
2277 2368
2278 if (info->beacon_ies) { 2369 /* this also clears IE in fw if it's not set */
2279 res = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx, 2370 res = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
2280 WMI_FRAME_BEACON, 2371 WMI_FRAME_BEACON,
2281 info->beacon_ies, 2372 info->beacon_ies,
2282 info->beacon_ies_len); 2373 info->beacon_ies_len);
2283 if (res) 2374 if (res)
2284 return res; 2375 return res;
2285 }
2286 2376
2287 if (info->proberesp_ies) { 2377 /* this also clears IE in fw if it's not set */
2288 res = ath6kl_set_ap_probe_resp_ies(vif, info->proberesp_ies, 2378 res = ath6kl_set_ap_probe_resp_ies(vif, info->proberesp_ies,
2289 info->proberesp_ies_len); 2379 info->proberesp_ies_len);
2290 if (res) 2380 if (res)
2291 return res; 2381 return res;
2292 }
2293 2382
2294 if (info->assocresp_ies) { 2383 /* this also clears IE in fw if it's not set */
2295 res = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx, 2384 res = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,
2296 WMI_FRAME_ASSOC_RESP, 2385 WMI_FRAME_ASSOC_RESP,
2297 info->assocresp_ies, 2386 info->assocresp_ies,
2298 info->assocresp_ies_len); 2387 info->assocresp_ies_len);
2299 if (res) 2388 if (res)
2300 return res; 2389 return res;
2301 }
2302 2390
2303 return 0; 2391 return 0;
2304} 2392}
@@ -2309,6 +2397,7 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,
2309 struct ath6kl *ar = ath6kl_priv(dev); 2397 struct ath6kl *ar = ath6kl_priv(dev);
2310 struct ath6kl_vif *vif = netdev_priv(dev); 2398 struct ath6kl_vif *vif = netdev_priv(dev);
2311 struct ieee80211_mgmt *mgmt; 2399 struct ieee80211_mgmt *mgmt;
2400 bool hidden = false;
2312 u8 *ies; 2401 u8 *ies;
2313 int ies_len; 2402 int ies_len;
2314 struct wmi_connect_cmd p; 2403 struct wmi_connect_cmd p;
@@ -2345,7 +2434,11 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,
2345 memcpy(vif->ssid, info->ssid, info->ssid_len); 2434 memcpy(vif->ssid, info->ssid, info->ssid_len);
2346 vif->ssid_len = info->ssid_len; 2435 vif->ssid_len = info->ssid_len;
2347 if (info->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE) 2436 if (info->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE)
2348 return -EOPNOTSUPP; /* TODO */ 2437 hidden = true;
2438
2439 res = ath6kl_wmi_ap_hidden_ssid(ar->wmi, vif->fw_vif_idx, hidden);
2440 if (res)
2441 return res;
2349 2442
2350 ret = ath6kl_set_auth_type(vif, info->auth_type); 2443 ret = ath6kl_set_auth_type(vif, info->auth_type);
2351 if (ret) 2444 if (ret)
@@ -2584,6 +2677,76 @@ static int ath6kl_send_go_probe_resp(struct ath6kl_vif *vif,
2584 return ret; 2677 return ret;
2585} 2678}
2586 2679
2680static bool ath6kl_mgmt_powersave_ap(struct ath6kl_vif *vif,
2681 u32 id,
2682 u32 freq,
2683 u32 wait,
2684 const u8 *buf,
2685 size_t len,
2686 bool *more_data,
2687 bool no_cck)
2688{
2689 struct ieee80211_mgmt *mgmt;
2690 struct ath6kl_sta *conn;
2691 bool is_psq_empty = false;
2692 struct ath6kl_mgmt_buff *mgmt_buf;
2693 size_t mgmt_buf_size;
2694 struct ath6kl *ar = vif->ar;
2695
2696 mgmt = (struct ieee80211_mgmt *) buf;
2697 if (is_multicast_ether_addr(mgmt->da))
2698 return false;
2699
2700 conn = ath6kl_find_sta(vif, mgmt->da);
2701 if (!conn)
2702 return false;
2703
2704 if (conn->sta_flags & STA_PS_SLEEP) {
2705 if (!(conn->sta_flags & STA_PS_POLLED)) {
2706 /* Queue the frames if the STA is sleeping */
2707 mgmt_buf_size = len + sizeof(struct ath6kl_mgmt_buff);
2708 mgmt_buf = kmalloc(mgmt_buf_size, GFP_KERNEL);
2709 if (!mgmt_buf)
2710 return false;
2711
2712 INIT_LIST_HEAD(&mgmt_buf->list);
2713 mgmt_buf->id = id;
2714 mgmt_buf->freq = freq;
2715 mgmt_buf->wait = wait;
2716 mgmt_buf->len = len;
2717 mgmt_buf->no_cck = no_cck;
2718 memcpy(mgmt_buf->buf, buf, len);
2719 spin_lock_bh(&conn->psq_lock);
2720 is_psq_empty = skb_queue_empty(&conn->psq) &&
2721 (conn->mgmt_psq_len == 0);
2722 list_add_tail(&mgmt_buf->list, &conn->mgmt_psq);
2723 conn->mgmt_psq_len++;
2724 spin_unlock_bh(&conn->psq_lock);
2725
2726 /*
2727 * If this is the first pkt getting queued
2728 * for this STA, update the PVB for this
2729 * STA.
2730 */
2731 if (is_psq_empty)
2732 ath6kl_wmi_set_pvb_cmd(ar->wmi, vif->fw_vif_idx,
2733 conn->aid, 1);
2734 return true;
2735 }
2736
2737 /*
2738 * This tx is because of a PsPoll.
2739 * Determine if MoreData bit has to be set.
2740 */
2741 spin_lock_bh(&conn->psq_lock);
2742 if (!skb_queue_empty(&conn->psq) || (conn->mgmt_psq_len != 0))
2743 *more_data = true;
2744 spin_unlock_bh(&conn->psq_lock);
2745 }
2746
2747 return false;
2748}
2749
2587static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, 2750static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
2588 struct ieee80211_channel *chan, bool offchan, 2751 struct ieee80211_channel *chan, bool offchan,
2589 enum nl80211_channel_type channel_type, 2752 enum nl80211_channel_type channel_type,
@@ -2595,6 +2758,7 @@ static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
2595 struct ath6kl_vif *vif = netdev_priv(dev); 2758 struct ath6kl_vif *vif = netdev_priv(dev);
2596 u32 id; 2759 u32 id;
2597 const struct ieee80211_mgmt *mgmt; 2760 const struct ieee80211_mgmt *mgmt;
2761 bool more_data, queued;
2598 2762
2599 mgmt = (const struct ieee80211_mgmt *) buf; 2763 mgmt = (const struct ieee80211_mgmt *) buf;
2600 if (buf + len >= mgmt->u.probe_resp.variable && 2764 if (buf + len >= mgmt->u.probe_resp.variable &&
@@ -2620,22 +2784,19 @@ static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
2620 2784
2621 *cookie = id; 2785 *cookie = id;
2622 2786
2623 if (test_bit(ATH6KL_FW_CAPABILITY_STA_P2PDEV_DUPLEX, 2787 /* AP mode Power saving processing */
2624 ar->fw_capabilities)) { 2788 if (vif->nw_type == AP_NETWORK) {
2625 /* 2789 queued = ath6kl_mgmt_powersave_ap(vif,
2626 * If capable of doing P2P mgmt operations using 2790 id, chan->center_freq,
2627 * station interface, send additional information like 2791 wait, buf,
2628 * supported rates to advertise and xmit rates for 2792 len, &more_data, no_cck);
2629 * probe requests 2793 if (queued)
2630 */ 2794 return 0;
2631 return ath6kl_wmi_send_mgmt_cmd(ar->wmi, vif->fw_vif_idx, id,
2632 chan->center_freq, wait,
2633 buf, len, no_cck);
2634 } else {
2635 return ath6kl_wmi_send_action_cmd(ar->wmi, vif->fw_vif_idx, id,
2636 chan->center_freq, wait,
2637 buf, len);
2638 } 2795 }
2796
2797 return ath6kl_wmi_send_mgmt_cmd(ar->wmi, vif->fw_vif_idx, id,
2798 chan->center_freq, wait,
2799 buf, len, no_cck);
2639} 2800}
2640 2801
2641static void ath6kl_mgmt_frame_register(struct wiphy *wiphy, 2802static void ath6kl_mgmt_frame_register(struct wiphy *wiphy,
@@ -2929,7 +3090,10 @@ struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name,
2929 vif->wdev.netdev = ndev; 3090 vif->wdev.netdev = ndev;
2930 vif->wdev.iftype = type; 3091 vif->wdev.iftype = type;
2931 vif->fw_vif_idx = fw_vif_idx; 3092 vif->fw_vif_idx = fw_vif_idx;
2932 vif->nw_type = vif->next_mode = nw_type; 3093 vif->nw_type = nw_type;
3094 vif->next_mode = nw_type;
3095 vif->listen_intvl_t = ATH6KL_DEFAULT_LISTEN_INTVAL;
3096 vif->bmiss_time_t = ATH6KL_DEFAULT_BMISS_TIME;
2933 3097
2934 memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN); 3098 memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN);
2935 if (fw_vif_idx != 0) 3099 if (fw_vif_idx != 0)
@@ -3009,18 +3173,36 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
3009 3173
3010 wiphy->max_sched_scan_ssids = 10; 3174 wiphy->max_sched_scan_ssids = 10;
3011 3175
3176 ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM |
3177 WIPHY_FLAG_HAVE_AP_SME |
3178 WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
3179 WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
3180
3181 if (test_bit(ATH6KL_FW_CAPABILITY_SCHED_SCAN, ar->fw_capabilities))
3182 ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
3183
3184 ar->wiphy->probe_resp_offload =
3185 NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |
3186 NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 |
3187 NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P |
3188 NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U;
3189
3012 ret = wiphy_register(wiphy); 3190 ret = wiphy_register(wiphy);
3013 if (ret < 0) { 3191 if (ret < 0) {
3014 ath6kl_err("couldn't register wiphy device\n"); 3192 ath6kl_err("couldn't register wiphy device\n");
3015 return ret; 3193 return ret;
3016 } 3194 }
3017 3195
3196 ar->wiphy_registered = true;
3197
3018 return 0; 3198 return 0;
3019} 3199}
3020 3200
3021void ath6kl_cfg80211_cleanup(struct ath6kl *ar) 3201void ath6kl_cfg80211_cleanup(struct ath6kl *ar)
3022{ 3202{
3023 wiphy_unregister(ar->wiphy); 3203 wiphy_unregister(ar->wiphy);
3204
3205 ar->wiphy_registered = false;
3024} 3206}
3025 3207
3026struct ath6kl *ath6kl_cfg80211_create(void) 3208struct ath6kl *ath6kl_cfg80211_create(void)
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.h b/drivers/net/wireless/ath/ath6kl/cfg80211.h
index 3c693b7c0efd..c5def436417f 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.h
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.h
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (c) 2011 Atheros Communications Inc. 2 * Copyright (c) 2011 Atheros Communications Inc.
3 * Copyright (c) 2011-2012 Qualcomm Atheros, Inc.
3 * 4 *
4 * Permission to use, copy, modify, and/or distribute this software for any 5 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above 6 * purpose with or without fee is hereby granted, provided that the above
diff --git a/drivers/net/wireless/ath/ath6kl/common.h b/drivers/net/wireless/ath/ath6kl/common.h
index f89f1e180da3..a60e78c0472f 100644
--- a/drivers/net/wireless/ath/ath6kl/common.h
+++ b/drivers/net/wireless/ath/ath6kl/common.h
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (c) 2010-2011 Atheros Communications Inc. 2 * Copyright (c) 2010-2011 Atheros Communications Inc.
3 * Copyright (c) 2011-2012 Qualcomm Atheros, Inc.
3 * 4 *
4 * Permission to use, copy, modify, and/or distribute this software for any 5 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above 6 * purpose with or without fee is hereby granted, provided that the above
diff --git a/drivers/net/wireless/ath/ath6kl/core.c b/drivers/net/wireless/ath/ath6kl/core.c
index 722ca59b88ce..45e641f3a41b 100644
--- a/drivers/net/wireless/ath/ath6kl/core.c
+++ b/drivers/net/wireless/ath/ath6kl/core.c
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (c) 2004-2011 Atheros Communications Inc. 2 * Copyright (c) 2004-2011 Atheros Communications Inc.
3 * Copyright (c) 2011-2012 Qualcomm Atheros, Inc.
3 * 4 *
4 * Permission to use, copy, modify, and/or distribute this software for any 5 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above 6 * purpose with or without fee is hereby granted, provided that the above
@@ -26,12 +27,14 @@
26 27
27unsigned int debug_mask; 28unsigned int debug_mask;
28static unsigned int suspend_mode; 29static unsigned int suspend_mode;
30static unsigned int wow_mode;
29static unsigned int uart_debug; 31static unsigned int uart_debug;
30static unsigned int ath6kl_p2p; 32static unsigned int ath6kl_p2p;
31static unsigned int testmode; 33static unsigned int testmode;
32 34
33module_param(debug_mask, uint, 0644); 35module_param(debug_mask, uint, 0644);
34module_param(suspend_mode, uint, 0644); 36module_param(suspend_mode, uint, 0644);
37module_param(wow_mode, uint, 0644);
35module_param(uart_debug, uint, 0644); 38module_param(uart_debug, uint, 0644);
36module_param(ath6kl_p2p, uint, 0644); 39module_param(ath6kl_p2p, uint, 0644);
37module_param(testmode, uint, 0644); 40module_param(testmode, uint, 0644);
@@ -97,48 +100,12 @@ int ath6kl_core_init(struct ath6kl *ar)
97 100
98 ath6kl_dbg(ATH6KL_DBG_TRC, "%s: got wmi @ 0x%p.\n", __func__, ar->wmi); 101 ath6kl_dbg(ATH6KL_DBG_TRC, "%s: got wmi @ 0x%p.\n", __func__, ar->wmi);
99 102
100 ret = ath6kl_cfg80211_init(ar);
101 if (ret)
102 goto err_node_cleanup;
103
104 ret = ath6kl_debug_init(ar);
105 if (ret) {
106 wiphy_unregister(ar->wiphy);
107 goto err_node_cleanup;
108 }
109
110 for (i = 0; i < ar->vif_max; i++)
111 ar->avail_idx_map |= BIT(i);
112
113 rtnl_lock();
114
115 /* Add an initial station interface */
116 ndev = ath6kl_interface_add(ar, "wlan%d", NL80211_IFTYPE_STATION, 0,
117 INFRA_NETWORK);
118
119 rtnl_unlock();
120
121 if (!ndev) {
122 ath6kl_err("Failed to instantiate a network device\n");
123 ret = -ENOMEM;
124 wiphy_unregister(ar->wiphy);
125 goto err_debug_init;
126 }
127
128
129 ath6kl_dbg(ATH6KL_DBG_TRC, "%s: name=%s dev=0x%p, ar=0x%p\n",
130 __func__, ndev->name, ndev, ar);
131
132 /* setup access class priority mappings */ 103 /* setup access class priority mappings */
133 ar->ac_stream_pri_map[WMM_AC_BK] = 0; /* lowest */ 104 ar->ac_stream_pri_map[WMM_AC_BK] = 0; /* lowest */
134 ar->ac_stream_pri_map[WMM_AC_BE] = 1; 105 ar->ac_stream_pri_map[WMM_AC_BE] = 1;
135 ar->ac_stream_pri_map[WMM_AC_VI] = 2; 106 ar->ac_stream_pri_map[WMM_AC_VI] = 2;
136 ar->ac_stream_pri_map[WMM_AC_VO] = 3; /* highest */ 107 ar->ac_stream_pri_map[WMM_AC_VO] = 3; /* highest */
137 108
138 /* give our connected endpoints some buffers */
139 ath6kl_rx_refill(ar->htc_target, ar->ctrl_ep);
140 ath6kl_rx_refill(ar->htc_target, ar->ac2ep_map[WMM_AC_BE]);
141
142 /* allocate some buffers that handle larger AMSDU frames */ 109 /* allocate some buffers that handle larger AMSDU frames */
143 ath6kl_refill_amsdu_rxbufs(ar, ATH6KL_MAX_AMSDU_RX_BUFFERS); 110 ath6kl_refill_amsdu_rxbufs(ar, ATH6KL_MAX_AMSDU_RX_BUFFERS);
144 111
@@ -148,32 +115,25 @@ int ath6kl_core_init(struct ath6kl *ar)
148 ATH6KL_CONF_ENABLE_11N | ATH6KL_CONF_ENABLE_TX_BURST; 115 ATH6KL_CONF_ENABLE_11N | ATH6KL_CONF_ENABLE_TX_BURST;
149 116
150 if (suspend_mode && 117 if (suspend_mode &&
151 suspend_mode >= WLAN_POWER_STATE_CUT_PWR && 118 suspend_mode >= WLAN_POWER_STATE_CUT_PWR &&
152 suspend_mode <= WLAN_POWER_STATE_WOW) 119 suspend_mode <= WLAN_POWER_STATE_WOW)
153 ar->suspend_mode = suspend_mode; 120 ar->suspend_mode = suspend_mode;
154 else 121 else
155 ar->suspend_mode = 0; 122 ar->suspend_mode = 0;
156 123
124 if (suspend_mode == WLAN_POWER_STATE_WOW &&
125 (wow_mode == WLAN_POWER_STATE_CUT_PWR ||
126 wow_mode == WLAN_POWER_STATE_DEEP_SLEEP))
127 ar->wow_suspend_mode = wow_mode;
128 else
129 ar->wow_suspend_mode = 0;
130
157 if (uart_debug) 131 if (uart_debug)
158 ar->conf_flags |= ATH6KL_CONF_UART_DEBUG; 132 ar->conf_flags |= ATH6KL_CONF_UART_DEBUG;
159 133
160 ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM |
161 WIPHY_FLAG_HAVE_AP_SME |
162 WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
163 WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
164
165 if (test_bit(ATH6KL_FW_CAPABILITY_SCHED_SCAN, ar->fw_capabilities))
166 ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
167
168 ar->wiphy->probe_resp_offload =
169 NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |
170 NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 |
171 NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P |
172 NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U;
173
174 set_bit(FIRST_BOOT, &ar->flag); 134 set_bit(FIRST_BOOT, &ar->flag);
175 135
176 ndev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_RXCSUM; 136 ath6kl_debug_init(ar);
177 137
178 ret = ath6kl_init_hw_start(ar); 138 ret = ath6kl_init_hw_start(ar);
179 if (ret) { 139 if (ret) {
@@ -181,24 +141,47 @@ int ath6kl_core_init(struct ath6kl *ar)
181 goto err_rxbuf_cleanup; 141 goto err_rxbuf_cleanup;
182 } 142 }
183 143
184 /* 144 /* give our connected endpoints some buffers */
185 * Set mac address which is received in ready event 145 ath6kl_rx_refill(ar->htc_target, ar->ctrl_ep);
186 * FIXME: Move to ath6kl_interface_add() 146 ath6kl_rx_refill(ar->htc_target, ar->ac2ep_map[WMM_AC_BE]);
187 */ 147
188 memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN); 148 ret = ath6kl_cfg80211_init(ar);
149 if (ret)
150 goto err_rxbuf_cleanup;
151
152 ret = ath6kl_debug_init_fs(ar);
153 if (ret) {
154 wiphy_unregister(ar->wiphy);
155 goto err_rxbuf_cleanup;
156 }
157
158 for (i = 0; i < ar->vif_max; i++)
159 ar->avail_idx_map |= BIT(i);
160
161 rtnl_lock();
162
163 /* Add an initial station interface */
164 ndev = ath6kl_interface_add(ar, "wlan%d", NL80211_IFTYPE_STATION, 0,
165 INFRA_NETWORK);
166
167 rtnl_unlock();
168
169 if (!ndev) {
170 ath6kl_err("Failed to instantiate a network device\n");
171 ret = -ENOMEM;
172 wiphy_unregister(ar->wiphy);
173 goto err_rxbuf_cleanup;
174 }
175
176 ath6kl_dbg(ATH6KL_DBG_TRC, "%s: name=%s dev=0x%p, ar=0x%p\n",
177 __func__, ndev->name, ndev, ar);
189 178
190 return ret; 179 return ret;
191 180
192err_rxbuf_cleanup: 181err_rxbuf_cleanup:
182 ath6kl_debug_cleanup(ar);
193 ath6kl_htc_flush_rx_buf(ar->htc_target); 183 ath6kl_htc_flush_rx_buf(ar->htc_target);
194 ath6kl_cleanup_amsdu_rxbufs(ar); 184 ath6kl_cleanup_amsdu_rxbufs(ar);
195 rtnl_lock();
196 ath6kl_cfg80211_vif_cleanup(netdev_priv(ndev));
197 rtnl_unlock();
198 wiphy_unregister(ar->wiphy);
199err_debug_init:
200 ath6kl_debug_cleanup(ar);
201err_node_cleanup:
202 ath6kl_wmi_shutdown(ar->wmi); 185 ath6kl_wmi_shutdown(ar->wmi);
203 clear_bit(WMI_ENABLED, &ar->flag); 186 clear_bit(WMI_ENABLED, &ar->flag);
204 ar->wmi = NULL; 187 ar->wmi = NULL;
@@ -245,9 +228,7 @@ struct ath6kl *ath6kl_core_create(struct device *dev)
245 clear_bit(SKIP_SCAN, &ar->flag); 228 clear_bit(SKIP_SCAN, &ar->flag);
246 clear_bit(DESTROY_IN_PROGRESS, &ar->flag); 229 clear_bit(DESTROY_IN_PROGRESS, &ar->flag);
247 230
248 ar->listen_intvl_b = A_DEFAULT_LISTEN_INTERVAL;
249 ar->tx_pwr = 0; 231 ar->tx_pwr = 0;
250
251 ar->intra_bss = 1; 232 ar->intra_bss = 1;
252 ar->lrssi_roam_threshold = DEF_LRSSI_ROAM_THRESHOLD; 233 ar->lrssi_roam_threshold = DEF_LRSSI_ROAM_THRESHOLD;
253 234
@@ -261,6 +242,8 @@ struct ath6kl *ath6kl_core_create(struct device *dev)
261 spin_lock_init(&ar->sta_list[ctr].psq_lock); 242 spin_lock_init(&ar->sta_list[ctr].psq_lock);
262 skb_queue_head_init(&ar->sta_list[ctr].psq); 243 skb_queue_head_init(&ar->sta_list[ctr].psq);
263 skb_queue_head_init(&ar->sta_list[ctr].apsdq); 244 skb_queue_head_init(&ar->sta_list[ctr].apsdq);
245 ar->sta_list[ctr].mgmt_psq_len = 0;
246 INIT_LIST_HEAD(&ar->sta_list[ctr].mgmt_psq);
264 ar->sta_list[ctr].aggr_conn = 247 ar->sta_list[ctr].aggr_conn =
265 kzalloc(sizeof(struct aggr_info_conn), GFP_KERNEL); 248 kzalloc(sizeof(struct aggr_info_conn), GFP_KERNEL);
266 if (!ar->sta_list[ctr].aggr_conn) { 249 if (!ar->sta_list[ctr].aggr_conn) {
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h
index c4d66e066dc9..f1dd8906be45 100644
--- a/drivers/net/wireless/ath/ath6kl/core.h
+++ b/drivers/net/wireless/ath/ath6kl/core.h
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (c) 2010-2011 Atheros Communications Inc. 2 * Copyright (c) 2010-2011 Atheros Communications Inc.
3 * Copyright (c) 2011-2012 Qualcomm Atheros, Inc.
3 * 4 *
4 * Permission to use, copy, modify, and/or distribute this software for any 5 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above 6 * purpose with or without fee is hereby granted, provided that the above
@@ -59,8 +60,9 @@
59#define MAX_DEFAULT_SEND_QUEUE_DEPTH (MAX_DEF_COOKIE_NUM / WMM_NUM_AC) 60#define MAX_DEFAULT_SEND_QUEUE_DEPTH (MAX_DEF_COOKIE_NUM / WMM_NUM_AC)
60 61
61#define DISCON_TIMER_INTVAL 10000 /* in msec */ 62#define DISCON_TIMER_INTVAL 10000 /* in msec */
62#define A_DEFAULT_LISTEN_INTERVAL 1 /* beacon intervals */ 63
63#define A_MAX_WOW_LISTEN_INTERVAL 1000 64/* Channel dwell time in fg scan */
65#define ATH6KL_FG_SCAN_INTERVAL 50 /* in ms */
64 66
65/* includes also the null byte */ 67/* includes also the null byte */
66#define ATH6KL_FIRMWARE_MAGIC "QCA-ATH6KL" 68#define ATH6KL_FIRMWARE_MAGIC "QCA-ATH6KL"
@@ -183,6 +185,11 @@ struct ath6kl_fw_ie {
183 185
184#define MBOX_YIELD_LIMIT 99 186#define MBOX_YIELD_LIMIT 99
185 187
188#define ATH6KL_DEFAULT_LISTEN_INTVAL 100 /* in TUs */
189#define ATH6KL_DEFAULT_BMISS_TIME 1500
190#define ATH6KL_MAX_WOW_LISTEN_INTL 300 /* in TUs */
191#define ATH6KL_MAX_BMISS_TIME 5000
192
186/* configuration lags */ 193/* configuration lags */
187/* 194/*
188 * ATH6KL_CONF_IGNORE_ERP_BARKER: Ignore the barker premable in 195 * ATH6KL_CONF_IGNORE_ERP_BARKER: Ignore the barker premable in
@@ -226,6 +233,12 @@ struct rxtid {
226 u32 hold_q_sz; 233 u32 hold_q_sz;
227 struct skb_hold_q *hold_q; 234 struct skb_hold_q *hold_q;
228 struct sk_buff_head q; 235 struct sk_buff_head q;
236
237 /*
238 * FIXME: No clue what this should protect. Apparently it should
239 * protect some of the fields above but they are also accessed
240 * without taking the lock.
241 */
229 spinlock_t lock; 242 spinlock_t lock;
230}; 243};
231 244
@@ -285,6 +298,16 @@ struct ath6kl_cookie {
285 struct ath6kl_cookie *arc_list_next; 298 struct ath6kl_cookie *arc_list_next;
286}; 299};
287 300
301struct ath6kl_mgmt_buff {
302 struct list_head list;
303 u32 freq;
304 u32 wait;
305 u32 id;
306 bool no_cck;
307 size_t len;
308 u8 buf[0];
309};
310
288struct ath6kl_sta { 311struct ath6kl_sta {
289 u16 sta_flags; 312 u16 sta_flags;
290 u8 mac[ETH_ALEN]; 313 u8 mac[ETH_ALEN];
@@ -294,7 +317,12 @@ struct ath6kl_sta {
294 u8 auth; 317 u8 auth;
295 u8 wpa_ie[ATH6KL_MAX_IE]; 318 u8 wpa_ie[ATH6KL_MAX_IE];
296 struct sk_buff_head psq; 319 struct sk_buff_head psq;
320
321 /* protects psq, mgmt_psq, apsdq, and mgmt_psq_len fields */
297 spinlock_t psq_lock; 322 spinlock_t psq_lock;
323
324 struct list_head mgmt_psq;
325 size_t mgmt_psq_len;
298 u8 apsd_info; 326 u8 apsd_info;
299 struct sk_buff_head apsdq; 327 struct sk_buff_head apsdq;
300 struct aggr_info_conn *aggr_conn; 328 struct aggr_info_conn *aggr_conn;
@@ -494,6 +522,8 @@ struct ath6kl_vif {
494 bool probe_req_report; 522 bool probe_req_report;
495 u16 next_chan; 523 u16 next_chan;
496 u16 assoc_bss_beacon_int; 524 u16 assoc_bss_beacon_int;
525 u16 listen_intvl_t;
526 u16 bmiss_time_t;
497 u8 assoc_bss_dtim_period; 527 u8 assoc_bss_dtim_period;
498 struct net_device_stats net_stats; 528 struct net_device_stats net_stats;
499 struct target_stats target_stats; 529 struct target_stats target_stats;
@@ -521,6 +551,8 @@ enum ath6kl_dev_state {
521enum ath6kl_state { 551enum ath6kl_state {
522 ATH6KL_STATE_OFF, 552 ATH6KL_STATE_OFF,
523 ATH6KL_STATE_ON, 553 ATH6KL_STATE_ON,
554 ATH6KL_STATE_SUSPENDING,
555 ATH6KL_STATE_RESUMING,
524 ATH6KL_STATE_DEEPSLEEP, 556 ATH6KL_STATE_DEEPSLEEP,
525 ATH6KL_STATE_CUTPOWER, 557 ATH6KL_STATE_CUTPOWER,
526 ATH6KL_STATE_WOW, 558 ATH6KL_STATE_WOW,
@@ -549,9 +581,14 @@ struct ath6kl {
549 unsigned int vif_max; 581 unsigned int vif_max;
550 u8 max_norm_iface; 582 u8 max_norm_iface;
551 u8 avail_idx_map; 583 u8 avail_idx_map;
584
585 /*
586 * Protects at least amsdu_rx_buffer_queue, ath6kl_alloc_cookie()
587 * calls, tx_pending and total_tx_data_pend.
588 */
552 spinlock_t lock; 589 spinlock_t lock;
590
553 struct semaphore sem; 591 struct semaphore sem;
554 u16 listen_intvl_b;
555 u8 lrssi_roam_threshold; 592 u8 lrssi_roam_threshold;
556 struct ath6kl_version version; 593 struct ath6kl_version version;
557 u32 target_type; 594 u32 target_type;
@@ -577,7 +614,13 @@ struct ath6kl {
577 u8 sta_list_index; 614 u8 sta_list_index;
578 struct ath6kl_req_key ap_mode_bkey; 615 struct ath6kl_req_key ap_mode_bkey;
579 struct sk_buff_head mcastpsq; 616 struct sk_buff_head mcastpsq;
617
618 /*
619 * FIXME: protects access to mcastpsq but is actually useless as
620 * all skbe_queue_*() functions provide serialisation themselves
621 */
580 spinlock_t mcastpsq_lock; 622 spinlock_t mcastpsq_lock;
623
581 u8 intra_bss; 624 u8 intra_bss;
582 struct wmi_ap_mode_stat ap_stats; 625 struct wmi_ap_mode_stat ap_stats;
583 u8 ap_country_code[3]; 626 u8 ap_country_code[3];
@@ -620,6 +663,7 @@ struct ath6kl {
620 663
621 u16 conf_flags; 664 u16 conf_flags;
622 u16 suspend_mode; 665 u16 suspend_mode;
666 u16 wow_suspend_mode;
623 wait_queue_head_t event_wq; 667 wait_queue_head_t event_wq;
624 struct ath6kl_mbox_info mbox_info; 668 struct ath6kl_mbox_info mbox_info;
625 669
@@ -650,12 +694,16 @@ struct ath6kl {
650 694
651 bool p2p; 695 bool p2p;
652 696
697 bool wiphy_registered;
698
653#ifdef CONFIG_ATH6KL_DEBUG 699#ifdef CONFIG_ATH6KL_DEBUG
654 struct { 700 struct {
655 struct circ_buf fwlog_buf; 701 struct sk_buff_head fwlog_queue;
656 spinlock_t fwlog_lock; 702 struct completion fwlog_completion;
657 void *fwlog_tmp; 703 bool fwlog_open;
704
658 u32 fwlog_mask; 705 u32 fwlog_mask;
706
659 unsigned int dbgfs_diag_reg; 707 unsigned int dbgfs_diag_reg;
660 u32 diag_reg_addr_wr; 708 u32 diag_reg_addr_wr;
661 u32 diag_reg_val_wr; 709 u32 diag_reg_val_wr;
@@ -727,10 +775,10 @@ struct htc_packet *ath6kl_alloc_amsdu_rxbuf(struct htc_target *target,
727void aggr_module_destroy(struct aggr_info *aggr_info); 775void aggr_module_destroy(struct aggr_info *aggr_info);
728void aggr_reset_state(struct aggr_info_conn *aggr_conn); 776void aggr_reset_state(struct aggr_info_conn *aggr_conn);
729 777
730struct ath6kl_sta *ath6kl_find_sta(struct ath6kl_vif *vif, u8 * node_addr); 778struct ath6kl_sta *ath6kl_find_sta(struct ath6kl_vif *vif, u8 *node_addr);
731struct ath6kl_sta *ath6kl_find_sta_by_aid(struct ath6kl *ar, u8 aid); 779struct ath6kl_sta *ath6kl_find_sta_by_aid(struct ath6kl *ar, u8 aid);
732 780
733void ath6kl_ready_event(void *devt, u8 * datap, u32 sw_ver, u32 abi_ver); 781void ath6kl_ready_event(void *devt, u8 *datap, u32 sw_ver, u32 abi_ver);
734int ath6kl_control_tx(void *devt, struct sk_buff *skb, 782int ath6kl_control_tx(void *devt, struct sk_buff *skb,
735 enum htc_endpoint_id eid); 783 enum htc_endpoint_id eid);
736void ath6kl_connect_event(struct ath6kl_vif *vif, u16 channel, 784void ath6kl_connect_event(struct ath6kl_vif *vif, u16 channel,
diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c
index d832058816fe..552adb3f80d0 100644
--- a/drivers/net/wireless/ath/ath6kl/debug.c
+++ b/drivers/net/wireless/ath/ath6kl/debug.c
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (c) 2004-2011 Atheros Communications Inc. 2 * Copyright (c) 2004-2011 Atheros Communications Inc.
3 * Copyright (c) 2011-2012 Qualcomm Atheros, Inc.
3 * 4 *
4 * Permission to use, copy, modify, and/or distribute this software for any 5 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above 6 * purpose with or without fee is hereby granted, provided that the above
@@ -16,7 +17,7 @@
16 17
17#include "core.h" 18#include "core.h"
18 19
19#include <linux/circ_buf.h> 20#include <linux/skbuff.h>
20#include <linux/fs.h> 21#include <linux/fs.h>
21#include <linux/vmalloc.h> 22#include <linux/vmalloc.h>
22#include <linux/export.h> 23#include <linux/export.h>
@@ -32,9 +33,8 @@ struct ath6kl_fwlog_slot {
32 u8 payload[0]; 33 u8 payload[0];
33}; 34};
34 35
35#define ATH6KL_FWLOG_SIZE 32768 36#define ATH6KL_FWLOG_MAX_ENTRIES 20
36#define ATH6KL_FWLOG_SLOT_SIZE (sizeof(struct ath6kl_fwlog_slot) + \ 37
37 ATH6KL_FWLOG_PAYLOAD_SIZE)
38#define ATH6KL_FWLOG_VALID_MASK 0x1ffff 38#define ATH6KL_FWLOG_VALID_MASK 0x1ffff
39 39
40int ath6kl_printk(const char *level, const char *fmt, ...) 40int ath6kl_printk(const char *level, const char *fmt, ...)
@@ -119,29 +119,29 @@ void ath6kl_dump_registers(struct ath6kl_device *dev,
119 119
120 if (irq_proc_reg != NULL) { 120 if (irq_proc_reg != NULL) {
121 ath6kl_dbg(ATH6KL_DBG_IRQ, 121 ath6kl_dbg(ATH6KL_DBG_IRQ,
122 "Host Int status: 0x%x\n", 122 "Host Int status: 0x%x\n",
123 irq_proc_reg->host_int_status); 123 irq_proc_reg->host_int_status);
124 ath6kl_dbg(ATH6KL_DBG_IRQ, 124 ath6kl_dbg(ATH6KL_DBG_IRQ,
125 "CPU Int status: 0x%x\n", 125 "CPU Int status: 0x%x\n",
126 irq_proc_reg->cpu_int_status); 126 irq_proc_reg->cpu_int_status);
127 ath6kl_dbg(ATH6KL_DBG_IRQ, 127 ath6kl_dbg(ATH6KL_DBG_IRQ,
128 "Error Int status: 0x%x\n", 128 "Error Int status: 0x%x\n",
129 irq_proc_reg->error_int_status); 129 irq_proc_reg->error_int_status);
130 ath6kl_dbg(ATH6KL_DBG_IRQ, 130 ath6kl_dbg(ATH6KL_DBG_IRQ,
131 "Counter Int status: 0x%x\n", 131 "Counter Int status: 0x%x\n",
132 irq_proc_reg->counter_int_status); 132 irq_proc_reg->counter_int_status);
133 ath6kl_dbg(ATH6KL_DBG_IRQ, 133 ath6kl_dbg(ATH6KL_DBG_IRQ,
134 "Mbox Frame: 0x%x\n", 134 "Mbox Frame: 0x%x\n",
135 irq_proc_reg->mbox_frame); 135 irq_proc_reg->mbox_frame);
136 ath6kl_dbg(ATH6KL_DBG_IRQ, 136 ath6kl_dbg(ATH6KL_DBG_IRQ,
137 "Rx Lookahead Valid: 0x%x\n", 137 "Rx Lookahead Valid: 0x%x\n",
138 irq_proc_reg->rx_lkahd_valid); 138 irq_proc_reg->rx_lkahd_valid);
139 ath6kl_dbg(ATH6KL_DBG_IRQ, 139 ath6kl_dbg(ATH6KL_DBG_IRQ,
140 "Rx Lookahead 0: 0x%x\n", 140 "Rx Lookahead 0: 0x%x\n",
141 irq_proc_reg->rx_lkahd[0]); 141 irq_proc_reg->rx_lkahd[0]);
142 ath6kl_dbg(ATH6KL_DBG_IRQ, 142 ath6kl_dbg(ATH6KL_DBG_IRQ,
143 "Rx Lookahead 1: 0x%x\n", 143 "Rx Lookahead 1: 0x%x\n",
144 irq_proc_reg->rx_lkahd[1]); 144 irq_proc_reg->rx_lkahd[1]);
145 145
146 if (dev->ar->mbox_info.gmbox_addr != 0) { 146 if (dev->ar->mbox_info.gmbox_addr != 0) {
147 /* 147 /*
@@ -149,27 +149,27 @@ void ath6kl_dump_registers(struct ath6kl_device *dev,
149 * additional state. 149 * additional state.
150 */ 150 */
151 ath6kl_dbg(ATH6KL_DBG_IRQ, 151 ath6kl_dbg(ATH6KL_DBG_IRQ,
152 "GMBOX Host Int status 2: 0x%x\n", 152 "GMBOX Host Int status 2: 0x%x\n",
153 irq_proc_reg->host_int_status2); 153 irq_proc_reg->host_int_status2);
154 ath6kl_dbg(ATH6KL_DBG_IRQ, 154 ath6kl_dbg(ATH6KL_DBG_IRQ,
155 "GMBOX RX Avail: 0x%x\n", 155 "GMBOX RX Avail: 0x%x\n",
156 irq_proc_reg->gmbox_rx_avail); 156 irq_proc_reg->gmbox_rx_avail);
157 ath6kl_dbg(ATH6KL_DBG_IRQ, 157 ath6kl_dbg(ATH6KL_DBG_IRQ,
158 "GMBOX lookahead alias 0: 0x%x\n", 158 "GMBOX lookahead alias 0: 0x%x\n",
159 irq_proc_reg->rx_gmbox_lkahd_alias[0]); 159 irq_proc_reg->rx_gmbox_lkahd_alias[0]);
160 ath6kl_dbg(ATH6KL_DBG_IRQ, 160 ath6kl_dbg(ATH6KL_DBG_IRQ,
161 "GMBOX lookahead alias 1: 0x%x\n", 161 "GMBOX lookahead alias 1: 0x%x\n",
162 irq_proc_reg->rx_gmbox_lkahd_alias[1]); 162 irq_proc_reg->rx_gmbox_lkahd_alias[1]);
163 } 163 }
164 164
165 } 165 }
166 166
167 if (irq_enable_reg != NULL) { 167 if (irq_enable_reg != NULL) {
168 ath6kl_dbg(ATH6KL_DBG_IRQ, 168 ath6kl_dbg(ATH6KL_DBG_IRQ,
169 "Int status Enable: 0x%x\n", 169 "Int status Enable: 0x%x\n",
170 irq_enable_reg->int_status_en); 170 irq_enable_reg->int_status_en);
171 ath6kl_dbg(ATH6KL_DBG_IRQ, "Counter Int status Enable: 0x%x\n", 171 ath6kl_dbg(ATH6KL_DBG_IRQ, "Counter Int status Enable: 0x%x\n",
172 irq_enable_reg->cntr_int_status_en); 172 irq_enable_reg->cntr_int_status_en);
173 } 173 }
174 ath6kl_dbg(ATH6KL_DBG_IRQ, "<------------------------------->\n"); 174 ath6kl_dbg(ATH6KL_DBG_IRQ, "<------------------------------->\n");
175} 175}
@@ -268,105 +268,103 @@ static const struct file_operations fops_war_stats = {
268 .llseek = default_llseek, 268 .llseek = default_llseek,
269}; 269};
270 270
271static void ath6kl_debug_fwlog_add(struct ath6kl *ar, const void *buf, 271void ath6kl_debug_fwlog_event(struct ath6kl *ar, const void *buf, size_t len)
272 size_t buf_len)
273{ 272{
274 struct circ_buf *fwlog = &ar->debug.fwlog_buf; 273 struct ath6kl_fwlog_slot *slot;
275 size_t space; 274 struct sk_buff *skb;
276 int i; 275 size_t slot_len;
277 276
278 /* entries must all be equal size */ 277 if (WARN_ON(len > ATH6KL_FWLOG_PAYLOAD_SIZE))
279 if (WARN_ON(buf_len != ATH6KL_FWLOG_SLOT_SIZE))
280 return; 278 return;
281 279
282 space = CIRC_SPACE(fwlog->head, fwlog->tail, ATH6KL_FWLOG_SIZE); 280 slot_len = sizeof(*slot) + ATH6KL_FWLOG_PAYLOAD_SIZE;
283 if (space < buf_len)
284 /* discard oldest slot */
285 fwlog->tail = (fwlog->tail + ATH6KL_FWLOG_SLOT_SIZE) &
286 (ATH6KL_FWLOG_SIZE - 1);
287 281
288 for (i = 0; i < buf_len; i += space) { 282 skb = alloc_skb(slot_len, GFP_KERNEL);
289 space = CIRC_SPACE_TO_END(fwlog->head, fwlog->tail, 283 if (!skb)
290 ATH6KL_FWLOG_SIZE); 284 return;
291 285
292 if ((size_t) space > buf_len - i) 286 slot = (struct ath6kl_fwlog_slot *) skb_put(skb, slot_len);
293 space = buf_len - i; 287 slot->timestamp = cpu_to_le32(jiffies);
288 slot->length = cpu_to_le32(len);
289 memcpy(slot->payload, buf, len);
294 290
295 memcpy(&fwlog->buf[fwlog->head], buf, space); 291 /* Need to pad each record to fixed length ATH6KL_FWLOG_PAYLOAD_SIZE */
296 fwlog->head = (fwlog->head + space) & (ATH6KL_FWLOG_SIZE - 1); 292 memset(slot->payload + len, 0, ATH6KL_FWLOG_PAYLOAD_SIZE - len);
297 }
298 293
299} 294 spin_lock(&ar->debug.fwlog_queue.lock);
300 295
301void ath6kl_debug_fwlog_event(struct ath6kl *ar, const void *buf, size_t len) 296 __skb_queue_tail(&ar->debug.fwlog_queue, skb);
302{ 297 complete(&ar->debug.fwlog_completion);
303 struct ath6kl_fwlog_slot *slot = ar->debug.fwlog_tmp;
304 size_t slot_len;
305 298
306 if (WARN_ON(len > ATH6KL_FWLOG_PAYLOAD_SIZE)) 299 /* drop oldest entries */
307 return; 300 while (skb_queue_len(&ar->debug.fwlog_queue) >
301 ATH6KL_FWLOG_MAX_ENTRIES) {
302 skb = __skb_dequeue(&ar->debug.fwlog_queue);
303 kfree_skb(skb);
304 }
308 305
309 spin_lock_bh(&ar->debug.fwlog_lock); 306 spin_unlock(&ar->debug.fwlog_queue.lock);
310 307
311 slot->timestamp = cpu_to_le32(jiffies); 308 return;
312 slot->length = cpu_to_le32(len); 309}
313 memcpy(slot->payload, buf, len);
314 310
315 slot_len = sizeof(*slot) + len; 311static int ath6kl_fwlog_open(struct inode *inode, struct file *file)
312{
313 struct ath6kl *ar = inode->i_private;
316 314
317 if (slot_len < ATH6KL_FWLOG_SLOT_SIZE) 315 if (ar->debug.fwlog_open)
318 memset(slot->payload + len, 0, 316 return -EBUSY;
319 ATH6KL_FWLOG_SLOT_SIZE - slot_len);
320 317
321 ath6kl_debug_fwlog_add(ar, slot, ATH6KL_FWLOG_SLOT_SIZE); 318 ar->debug.fwlog_open = true;
322 319
323 spin_unlock_bh(&ar->debug.fwlog_lock); 320 file->private_data = inode->i_private;
321 return 0;
324} 322}
325 323
326static bool ath6kl_debug_fwlog_empty(struct ath6kl *ar) 324static int ath6kl_fwlog_release(struct inode *inode, struct file *file)
327{ 325{
328 return CIRC_CNT(ar->debug.fwlog_buf.head, 326 struct ath6kl *ar = inode->i_private;
329 ar->debug.fwlog_buf.tail, 327
330 ATH6KL_FWLOG_SLOT_SIZE) == 0; 328 ar->debug.fwlog_open = false;
329
330 return 0;
331} 331}
332 332
333static ssize_t ath6kl_fwlog_read(struct file *file, char __user *user_buf, 333static ssize_t ath6kl_fwlog_read(struct file *file, char __user *user_buf,
334 size_t count, loff_t *ppos) 334 size_t count, loff_t *ppos)
335{ 335{
336 struct ath6kl *ar = file->private_data; 336 struct ath6kl *ar = file->private_data;
337 struct circ_buf *fwlog = &ar->debug.fwlog_buf; 337 struct sk_buff *skb;
338 size_t len = 0, buf_len = count;
339 ssize_t ret_cnt; 338 ssize_t ret_cnt;
339 size_t len = 0;
340 char *buf; 340 char *buf;
341 int ccnt;
342 341
343 buf = vmalloc(buf_len); 342 buf = vmalloc(count);
344 if (!buf) 343 if (!buf)
345 return -ENOMEM; 344 return -ENOMEM;
346 345
347 /* read undelivered logs from firmware */ 346 /* read undelivered logs from firmware */
348 ath6kl_read_fwlogs(ar); 347 ath6kl_read_fwlogs(ar);
349 348
350 spin_lock_bh(&ar->debug.fwlog_lock); 349 spin_lock(&ar->debug.fwlog_queue.lock);
351 350
352 while (len < buf_len && !ath6kl_debug_fwlog_empty(ar)) { 351 while ((skb = __skb_dequeue(&ar->debug.fwlog_queue))) {
353 ccnt = CIRC_CNT_TO_END(fwlog->head, fwlog->tail, 352 if (skb->len > count - len) {
354 ATH6KL_FWLOG_SIZE); 353 /* not enough space, put skb back and leave */
354 __skb_queue_head(&ar->debug.fwlog_queue, skb);
355 break;
356 }
355 357
356 if ((size_t) ccnt > buf_len - len)
357 ccnt = buf_len - len;
358 358
359 memcpy(buf + len, &fwlog->buf[fwlog->tail], ccnt); 359 memcpy(buf + len, skb->data, skb->len);
360 len += ccnt; 360 len += skb->len;
361 361
362 fwlog->tail = (fwlog->tail + ccnt) & 362 kfree_skb(skb);
363 (ATH6KL_FWLOG_SIZE - 1);
364 } 363 }
365 364
366 spin_unlock_bh(&ar->debug.fwlog_lock); 365 spin_unlock(&ar->debug.fwlog_queue.lock);
367 366
368 if (WARN_ON(len > buf_len)) 367 /* FIXME: what to do if len == 0? */
369 len = buf_len;
370 368
371 ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len); 369 ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
372 370
@@ -376,12 +374,87 @@ static ssize_t ath6kl_fwlog_read(struct file *file, char __user *user_buf,
376} 374}
377 375
378static const struct file_operations fops_fwlog = { 376static const struct file_operations fops_fwlog = {
379 .open = ath6kl_debugfs_open, 377 .open = ath6kl_fwlog_open,
378 .release = ath6kl_fwlog_release,
380 .read = ath6kl_fwlog_read, 379 .read = ath6kl_fwlog_read,
381 .owner = THIS_MODULE, 380 .owner = THIS_MODULE,
382 .llseek = default_llseek, 381 .llseek = default_llseek,
383}; 382};
384 383
384static ssize_t ath6kl_fwlog_block_read(struct file *file,
385 char __user *user_buf,
386 size_t count,
387 loff_t *ppos)
388{
389 struct ath6kl *ar = file->private_data;
390 struct sk_buff *skb;
391 ssize_t ret_cnt;
392 size_t len = 0, not_copied;
393 char *buf;
394 int ret;
395
396 buf = vmalloc(count);
397 if (!buf)
398 return -ENOMEM;
399
400 spin_lock(&ar->debug.fwlog_queue.lock);
401
402 if (skb_queue_len(&ar->debug.fwlog_queue) == 0) {
403 /* we must init under queue lock */
404 init_completion(&ar->debug.fwlog_completion);
405
406 spin_unlock(&ar->debug.fwlog_queue.lock);
407
408 ret = wait_for_completion_interruptible(
409 &ar->debug.fwlog_completion);
410 if (ret == -ERESTARTSYS)
411 return ret;
412
413 spin_lock(&ar->debug.fwlog_queue.lock);
414 }
415
416 while ((skb = __skb_dequeue(&ar->debug.fwlog_queue))) {
417 if (skb->len > count - len) {
418 /* not enough space, put skb back and leave */
419 __skb_queue_head(&ar->debug.fwlog_queue, skb);
420 break;
421 }
422
423
424 memcpy(buf + len, skb->data, skb->len);
425 len += skb->len;
426
427 kfree_skb(skb);
428 }
429
430 spin_unlock(&ar->debug.fwlog_queue.lock);
431
432 /* FIXME: what to do if len == 0? */
433
434 not_copied = copy_to_user(user_buf, buf, len);
435 if (not_copied != 0) {
436 ret_cnt = -EFAULT;
437 goto out;
438 }
439
440 *ppos = *ppos + len;
441
442 ret_cnt = len;
443
444out:
445 vfree(buf);
446
447 return ret_cnt;
448}
449
450static const struct file_operations fops_fwlog_block = {
451 .open = ath6kl_fwlog_open,
452 .release = ath6kl_fwlog_release,
453 .read = ath6kl_fwlog_block_read,
454 .owner = THIS_MODULE,
455 .llseek = default_llseek,
456};
457
385static ssize_t ath6kl_fwlog_mask_read(struct file *file, char __user *user_buf, 458static ssize_t ath6kl_fwlog_mask_read(struct file *file, char __user *user_buf,
386 size_t count, loff_t *ppos) 459 size_t count, loff_t *ppos)
387{ 460{
@@ -667,9 +740,13 @@ static ssize_t ath6kl_endpoint_stats_read(struct file *file,
667 return -ENOMEM; 740 return -ENOMEM;
668 741
669#define EPSTAT(name) \ 742#define EPSTAT(name) \
670 len = print_endpoint_stat(target, buf, buf_len, len, \ 743 do { \
671 offsetof(struct htc_endpoint_stats, name), \ 744 len = print_endpoint_stat(target, buf, buf_len, len, \
672 #name) 745 offsetof(struct htc_endpoint_stats, \
746 name), \
747 #name); \
748 } while (0)
749
673 EPSTAT(cred_low_indicate); 750 EPSTAT(cred_low_indicate);
674 EPSTAT(tx_issued); 751 EPSTAT(tx_issued);
675 EPSTAT(tx_pkt_bundled); 752 EPSTAT(tx_pkt_bundled);
@@ -779,17 +856,9 @@ static ssize_t ath6kl_regread_write(struct file *file,
779 size_t count, loff_t *ppos) 856 size_t count, loff_t *ppos)
780{ 857{
781 struct ath6kl *ar = file->private_data; 858 struct ath6kl *ar = file->private_data;
782 u8 buf[50];
783 unsigned int len;
784 unsigned long reg_addr; 859 unsigned long reg_addr;
785 860
786 len = min(count, sizeof(buf) - 1); 861 if (kstrtoul_from_user(user_buf, count, 0, &reg_addr))
787 if (copy_from_user(buf, user_buf, len))
788 return -EFAULT;
789
790 buf[len] = '\0';
791
792 if (strict_strtoul(buf, 0, &reg_addr))
793 return -EINVAL; 862 return -EINVAL;
794 863
795 if ((reg_addr % 4) != 0) 864 if ((reg_addr % 4) != 0)
@@ -903,15 +972,8 @@ static ssize_t ath6kl_lrssi_roam_write(struct file *file,
903{ 972{
904 struct ath6kl *ar = file->private_data; 973 struct ath6kl *ar = file->private_data;
905 unsigned long lrssi_roam_threshold; 974 unsigned long lrssi_roam_threshold;
906 char buf[32];
907 ssize_t len;
908 975
909 len = min(count, sizeof(buf) - 1); 976 if (kstrtoul_from_user(user_buf, count, 0, &lrssi_roam_threshold))
910 if (copy_from_user(buf, user_buf, len))
911 return -EFAULT;
912
913 buf[len] = '\0';
914 if (strict_strtoul(buf, 0, &lrssi_roam_threshold))
915 return -EINVAL; 977 return -EINVAL;
916 978
917 ar->lrssi_roam_threshold = lrssi_roam_threshold; 979 ar->lrssi_roam_threshold = lrssi_roam_threshold;
@@ -1558,12 +1620,12 @@ static ssize_t ath6kl_listen_int_write(struct file *file,
1558 if (kstrtou16(buf, 0, &listen_interval)) 1620 if (kstrtou16(buf, 0, &listen_interval))
1559 return -EINVAL; 1621 return -EINVAL;
1560 1622
1561 if ((listen_interval < 1) || (listen_interval > 50)) 1623 if ((listen_interval < 15) || (listen_interval > 3000))
1562 return -EINVAL; 1624 return -EINVAL;
1563 1625
1564 ar->listen_intvl_b = listen_interval; 1626 vif->listen_intvl_t = listen_interval;
1565 ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx, 0, 1627 ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx,
1566 ar->listen_intvl_b); 1628 vif->listen_intvl_t, 0);
1567 1629
1568 return count; 1630 return count;
1569} 1631}
@@ -1573,10 +1635,15 @@ static ssize_t ath6kl_listen_int_read(struct file *file,
1573 size_t count, loff_t *ppos) 1635 size_t count, loff_t *ppos)
1574{ 1636{
1575 struct ath6kl *ar = file->private_data; 1637 struct ath6kl *ar = file->private_data;
1638 struct ath6kl_vif *vif;
1576 char buf[32]; 1639 char buf[32];
1577 int len; 1640 int len;
1578 1641
1579 len = scnprintf(buf, sizeof(buf), "%u\n", ar->listen_intvl_b); 1642 vif = ath6kl_vif_first(ar);
1643 if (!vif)
1644 return -EIO;
1645
1646 len = scnprintf(buf, sizeof(buf), "%u\n", vif->listen_intvl_t);
1580 1647
1581 return simple_read_from_buffer(user_buf, count, ppos, buf, len); 1648 return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1582} 1649}
@@ -1649,33 +1716,29 @@ static const struct file_operations fops_power_params = {
1649 .llseek = default_llseek, 1716 .llseek = default_llseek,
1650}; 1717};
1651 1718
1652int ath6kl_debug_init(struct ath6kl *ar) 1719void ath6kl_debug_init(struct ath6kl *ar)
1653{ 1720{
1654 ar->debug.fwlog_buf.buf = vmalloc(ATH6KL_FWLOG_SIZE); 1721 skb_queue_head_init(&ar->debug.fwlog_queue);
1655 if (ar->debug.fwlog_buf.buf == NULL) 1722 init_completion(&ar->debug.fwlog_completion);
1656 return -ENOMEM;
1657
1658 ar->debug.fwlog_tmp = kmalloc(ATH6KL_FWLOG_SLOT_SIZE, GFP_KERNEL);
1659 if (ar->debug.fwlog_tmp == NULL) {
1660 vfree(ar->debug.fwlog_buf.buf);
1661 return -ENOMEM;
1662 }
1663
1664 spin_lock_init(&ar->debug.fwlog_lock);
1665 1723
1666 /* 1724 /*
1667 * Actually we are lying here but don't know how to read the mask 1725 * Actually we are lying here but don't know how to read the mask
1668 * value from the firmware. 1726 * value from the firmware.
1669 */ 1727 */
1670 ar->debug.fwlog_mask = 0; 1728 ar->debug.fwlog_mask = 0;
1729}
1671 1730
1731/*
1732 * Initialisation needs to happen in two stages as fwlog events can come
1733 * before cfg80211 is initialised, and debugfs depends on cfg80211
1734 * initialisation.
1735 */
1736int ath6kl_debug_init_fs(struct ath6kl *ar)
1737{
1672 ar->debugfs_phy = debugfs_create_dir("ath6kl", 1738 ar->debugfs_phy = debugfs_create_dir("ath6kl",
1673 ar->wiphy->debugfsdir); 1739 ar->wiphy->debugfsdir);
1674 if (!ar->debugfs_phy) { 1740 if (!ar->debugfs_phy)
1675 vfree(ar->debug.fwlog_buf.buf);
1676 kfree(ar->debug.fwlog_tmp);
1677 return -ENOMEM; 1741 return -ENOMEM;
1678 }
1679 1742
1680 debugfs_create_file("tgt_stats", S_IRUSR, ar->debugfs_phy, ar, 1743 debugfs_create_file("tgt_stats", S_IRUSR, ar->debugfs_phy, ar,
1681 &fops_tgt_stats); 1744 &fops_tgt_stats);
@@ -1689,6 +1752,9 @@ int ath6kl_debug_init(struct ath6kl *ar)
1689 debugfs_create_file("fwlog", S_IRUSR, ar->debugfs_phy, ar, 1752 debugfs_create_file("fwlog", S_IRUSR, ar->debugfs_phy, ar,
1690 &fops_fwlog); 1753 &fops_fwlog);
1691 1754
1755 debugfs_create_file("fwlog_block", S_IRUSR, ar->debugfs_phy, ar,
1756 &fops_fwlog_block);
1757
1692 debugfs_create_file("fwlog_mask", S_IRUSR | S_IWUSR, ar->debugfs_phy, 1758 debugfs_create_file("fwlog_mask", S_IRUSR | S_IWUSR, ar->debugfs_phy,
1693 ar, &fops_fwlog_mask); 1759 ar, &fops_fwlog_mask);
1694 1760
@@ -1723,27 +1789,26 @@ int ath6kl_debug_init(struct ath6kl *ar)
1723 ar->debugfs_phy, ar, &fops_disconnect_timeout); 1789 ar->debugfs_phy, ar, &fops_disconnect_timeout);
1724 1790
1725 debugfs_create_file("create_qos", S_IWUSR, ar->debugfs_phy, ar, 1791 debugfs_create_file("create_qos", S_IWUSR, ar->debugfs_phy, ar,
1726 &fops_create_qos); 1792 &fops_create_qos);
1727 1793
1728 debugfs_create_file("delete_qos", S_IWUSR, ar->debugfs_phy, ar, 1794 debugfs_create_file("delete_qos", S_IWUSR, ar->debugfs_phy, ar,
1729 &fops_delete_qos); 1795 &fops_delete_qos);
1730 1796
1731 debugfs_create_file("bgscan_interval", S_IWUSR, 1797 debugfs_create_file("bgscan_interval", S_IWUSR,
1732 ar->debugfs_phy, ar, &fops_bgscan_int); 1798 ar->debugfs_phy, ar, &fops_bgscan_int);
1733 1799
1734 debugfs_create_file("listen_interval", S_IRUSR | S_IWUSR, 1800 debugfs_create_file("listen_interval", S_IRUSR | S_IWUSR,
1735 ar->debugfs_phy, ar, &fops_listen_int); 1801 ar->debugfs_phy, ar, &fops_listen_int);
1736 1802
1737 debugfs_create_file("power_params", S_IWUSR, ar->debugfs_phy, ar, 1803 debugfs_create_file("power_params", S_IWUSR, ar->debugfs_phy, ar,
1738 &fops_power_params); 1804 &fops_power_params);
1739 1805
1740 return 0; 1806 return 0;
1741} 1807}
1742 1808
1743void ath6kl_debug_cleanup(struct ath6kl *ar) 1809void ath6kl_debug_cleanup(struct ath6kl *ar)
1744{ 1810{
1745 vfree(ar->debug.fwlog_buf.buf); 1811 skb_queue_purge(&ar->debug.fwlog_queue);
1746 kfree(ar->debug.fwlog_tmp);
1747 kfree(ar->debug.roam_tbl); 1812 kfree(ar->debug.roam_tbl);
1748} 1813}
1749 1814
diff --git a/drivers/net/wireless/ath/ath6kl/debug.h b/drivers/net/wireless/ath/ath6kl/debug.h
index c4be6e50996b..1803a0baae82 100644
--- a/drivers/net/wireless/ath/ath6kl/debug.h
+++ b/drivers/net/wireless/ath/ath6kl/debug.h
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (c) 2011 Atheros Communications Inc. 2 * Copyright (c) 2011 Atheros Communications Inc.
3 * Copyright (c) 2011-2012 Qualcomm Atheros, Inc.
3 * 4 *
4 * Permission to use, copy, modify, and/or distribute this software for any 5 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above 6 * purpose with or without fee is hereby granted, provided that the above
@@ -77,7 +78,8 @@ int ath6kl_debug_roam_tbl_event(struct ath6kl *ar, const void *buf,
77 size_t len); 78 size_t len);
78void ath6kl_debug_set_keepalive(struct ath6kl *ar, u8 keepalive); 79void ath6kl_debug_set_keepalive(struct ath6kl *ar, u8 keepalive);
79void ath6kl_debug_set_disconnect_timeout(struct ath6kl *ar, u8 timeout); 80void ath6kl_debug_set_disconnect_timeout(struct ath6kl *ar, u8 timeout);
80int ath6kl_debug_init(struct ath6kl *ar); 81void ath6kl_debug_init(struct ath6kl *ar);
82int ath6kl_debug_init_fs(struct ath6kl *ar);
81void ath6kl_debug_cleanup(struct ath6kl *ar); 83void ath6kl_debug_cleanup(struct ath6kl *ar);
82 84
83#else 85#else
@@ -127,7 +129,11 @@ static inline void ath6kl_debug_set_disconnect_timeout(struct ath6kl *ar,
127{ 129{
128} 130}
129 131
130static inline int ath6kl_debug_init(struct ath6kl *ar) 132static inline void ath6kl_debug_init(struct ath6kl *ar)
133{
134}
135
136static inline int ath6kl_debug_init_fs(struct ath6kl *ar)
131{ 137{
132 return 0; 138 return 0;
133} 139}
diff --git a/drivers/net/wireless/ath/ath6kl/hif-ops.h b/drivers/net/wireless/ath/ath6kl/hif-ops.h
index 2fe1dadfc77a..fd84086638e3 100644
--- a/drivers/net/wireless/ath/ath6kl/hif-ops.h
+++ b/drivers/net/wireless/ath/ath6kl/hif-ops.h
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (c) 2004-2011 Atheros Communications Inc. 2 * Copyright (c) 2004-2011 Atheros Communications Inc.
3 * Copyright (c) 2011 Qualcomm Atheros, Inc.
3 * 4 *
4 * Permission to use, copy, modify, and/or distribute this software for any 5 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above 6 * purpose with or without fee is hereby granted, provided that the above
diff --git a/drivers/net/wireless/ath/ath6kl/hif.c b/drivers/net/wireless/ath/ath6kl/hif.c
index e911737ab345..68ed6c2665b7 100644
--- a/drivers/net/wireless/ath/ath6kl/hif.c
+++ b/drivers/net/wireless/ath/ath6kl/hif.c
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (c) 2007-2011 Atheros Communications Inc. 2 * Copyright (c) 2007-2011 Atheros Communications Inc.
3 * Copyright (c) 2011-2012 Qualcomm Atheros, Inc.
3 * 4 *
4 * Permission to use, copy, modify, and/or distribute this software for any 5 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above 6 * purpose with or without fee is hereby granted, provided that the above
@@ -89,7 +90,7 @@ static void ath6kl_hif_dump_fw_crash(struct ath6kl *ar)
89 } 90 }
90 91
91 ath6kl_dbg(ATH6KL_DBG_IRQ, "register dump data address 0x%x\n", 92 ath6kl_dbg(ATH6KL_DBG_IRQ, "register dump data address 0x%x\n",
92 regdump_addr); 93 regdump_addr);
93 regdump_addr = TARG_VTOP(ar->target_type, regdump_addr); 94 regdump_addr = TARG_VTOP(ar->target_type, regdump_addr);
94 95
95 /* fetch register dump data */ 96 /* fetch register dump data */
@@ -106,9 +107,9 @@ static void ath6kl_hif_dump_fw_crash(struct ath6kl *ar)
106 107
107 BUILD_BUG_ON(REG_DUMP_COUNT_AR6003 % 4); 108 BUILD_BUG_ON(REG_DUMP_COUNT_AR6003 % 4);
108 109
109 for (i = 0; i < REG_DUMP_COUNT_AR6003 / 4; i++) { 110 for (i = 0; i < REG_DUMP_COUNT_AR6003; i += 4) {
110 ath6kl_info("%d: 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x\n", 111 ath6kl_info("%d: 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x\n",
111 4 * i, 112 i,
112 le32_to_cpu(regdump_val[i]), 113 le32_to_cpu(regdump_val[i]),
113 le32_to_cpu(regdump_val[i + 1]), 114 le32_to_cpu(regdump_val[i + 1]),
114 le32_to_cpu(regdump_val[i + 2]), 115 le32_to_cpu(regdump_val[i + 2]),
@@ -134,6 +135,7 @@ static int ath6kl_hif_proc_dbg_intr(struct ath6kl_device *dev)
134 ath6kl_warn("Failed to clear debug interrupt: %d\n", ret); 135 ath6kl_warn("Failed to clear debug interrupt: %d\n", ret);
135 136
136 ath6kl_hif_dump_fw_crash(dev->ar); 137 ath6kl_hif_dump_fw_crash(dev->ar);
138 ath6kl_read_fwlogs(dev->ar);
137 139
138 return ret; 140 return ret;
139} 141}
@@ -283,7 +285,7 @@ static int ath6kl_hif_proc_counter_intr(struct ath6kl_device *dev)
283 dev->irq_en_reg.cntr_int_status_en; 285 dev->irq_en_reg.cntr_int_status_en;
284 286
285 ath6kl_dbg(ATH6KL_DBG_IRQ, 287 ath6kl_dbg(ATH6KL_DBG_IRQ,
286 "valid interrupt source(s) in COUNTER_INT_STATUS: 0x%x\n", 288 "valid interrupt source(s) in COUNTER_INT_STATUS: 0x%x\n",
287 counter_int_status); 289 counter_int_status);
288 290
289 /* 291 /*
@@ -358,7 +360,7 @@ static int ath6kl_hif_proc_cpu_intr(struct ath6kl_device *dev)
358 } 360 }
359 361
360 ath6kl_dbg(ATH6KL_DBG_IRQ, 362 ath6kl_dbg(ATH6KL_DBG_IRQ,
361 "valid interrupt source(s) in CPU_INT_STATUS: 0x%x\n", 363 "valid interrupt source(s) in CPU_INT_STATUS: 0x%x\n",
362 cpu_int_status); 364 cpu_int_status);
363 365
364 /* Clear the interrupt */ 366 /* Clear the interrupt */
diff --git a/drivers/net/wireless/ath/ath6kl/hif.h b/drivers/net/wireless/ath/ath6kl/hif.h
index 699a036f3a44..20ed6b73517b 100644
--- a/drivers/net/wireless/ath/ath6kl/hif.h
+++ b/drivers/net/wireless/ath/ath6kl/hif.h
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (c) 2004-2011 Atheros Communications Inc. 2 * Copyright (c) 2004-2011 Atheros Communications Inc.
3 * Copyright (c) 2011 Qualcomm Atheros, Inc.
3 * 4 *
4 * Permission to use, copy, modify, and/or distribute this software for any 5 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above 6 * purpose with or without fee is hereby granted, provided that the above
@@ -197,6 +198,8 @@ struct hif_scatter_req {
197 u8 *virt_dma_buf; 198 u8 *virt_dma_buf;
198 199
199 struct hif_scatter_item scat_list[1]; 200 struct hif_scatter_item scat_list[1];
201
202 u32 scat_q_depth;
200}; 203};
201 204
202struct ath6kl_irq_proc_registers { 205struct ath6kl_irq_proc_registers {
@@ -220,6 +223,7 @@ struct ath6kl_irq_enable_reg {
220} __packed; 223} __packed;
221 224
222struct ath6kl_device { 225struct ath6kl_device {
226 /* protects irq_proc_reg and irq_en_reg below */
223 spinlock_t lock; 227 spinlock_t lock;
224 struct ath6kl_irq_proc_registers irq_proc_reg; 228 struct ath6kl_irq_proc_registers irq_proc_reg;
225 struct ath6kl_irq_enable_reg irq_en_reg; 229 struct ath6kl_irq_enable_reg irq_en_reg;
diff --git a/drivers/net/wireless/ath/ath6kl/htc.c b/drivers/net/wireless/ath/ath6kl/htc.c
index 2d721903640b..4849d99cce77 100644
--- a/drivers/net/wireless/ath/ath6kl/htc.c
+++ b/drivers/net/wireless/ath/ath6kl/htc.c
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (c) 2007-2011 Atheros Communications Inc. 2 * Copyright (c) 2007-2011 Atheros Communications Inc.
3 * Copyright (c) 2011-2012 Qualcomm Atheros, Inc.
3 * 4 *
4 * Permission to use, copy, modify, and/or distribute this software for any 5 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above 6 * purpose with or without fee is hereby granted, provided that the above
@@ -22,6 +23,9 @@
22 23
23#define CALC_TXRX_PADDED_LEN(dev, len) (__ALIGN_MASK((len), (dev)->block_mask)) 24#define CALC_TXRX_PADDED_LEN(dev, len) (__ALIGN_MASK((len), (dev)->block_mask))
24 25
26/* threshold to re-enable Tx bundling for an AC*/
27#define TX_RESUME_BUNDLE_THRESHOLD 1500
28
25/* Functions for Tx credit handling */ 29/* Functions for Tx credit handling */
26static void ath6kl_credit_deposit(struct ath6kl_htc_credit_info *cred_info, 30static void ath6kl_credit_deposit(struct ath6kl_htc_credit_info *cred_info,
27 struct htc_endpoint_credit_dist *ep_dist, 31 struct htc_endpoint_credit_dist *ep_dist,
@@ -168,31 +172,29 @@ static void ath6kl_credit_reduce(struct ath6kl_htc_credit_info *cred_info,
168static void ath6kl_credit_update(struct ath6kl_htc_credit_info *cred_info, 172static void ath6kl_credit_update(struct ath6kl_htc_credit_info *cred_info,
169 struct list_head *epdist_list) 173 struct list_head *epdist_list)
170{ 174{
171 struct htc_endpoint_credit_dist *cur_dist_list; 175 struct htc_endpoint_credit_dist *cur_list;
172 176
173 list_for_each_entry(cur_dist_list, epdist_list, list) { 177 list_for_each_entry(cur_list, epdist_list, list) {
174 if (cur_dist_list->endpoint == ENDPOINT_0) 178 if (cur_list->endpoint == ENDPOINT_0)
175 continue; 179 continue;
176 180
177 if (cur_dist_list->cred_to_dist > 0) { 181 if (cur_list->cred_to_dist > 0) {
178 cur_dist_list->credits += 182 cur_list->credits += cur_list->cred_to_dist;
179 cur_dist_list->cred_to_dist; 183 cur_list->cred_to_dist = 0;
180 cur_dist_list->cred_to_dist = 0; 184
181 if (cur_dist_list->credits > 185 if (cur_list->credits > cur_list->cred_assngd)
182 cur_dist_list->cred_assngd)
183 ath6kl_credit_reduce(cred_info, 186 ath6kl_credit_reduce(cred_info,
184 cur_dist_list, 187 cur_list,
185 cur_dist_list->cred_assngd); 188 cur_list->cred_assngd);
186 189
187 if (cur_dist_list->credits > 190 if (cur_list->credits > cur_list->cred_norm)
188 cur_dist_list->cred_norm) 191 ath6kl_credit_reduce(cred_info, cur_list,
189 ath6kl_credit_reduce(cred_info, cur_dist_list, 192 cur_list->cred_norm);
190 cur_dist_list->cred_norm);
191 193
192 if (!(cur_dist_list->dist_flags & HTC_EP_ACTIVE)) { 194 if (!(cur_list->dist_flags & HTC_EP_ACTIVE)) {
193 if (cur_dist_list->txq_depth == 0) 195 if (cur_list->txq_depth == 0)
194 ath6kl_credit_reduce(cred_info, 196 ath6kl_credit_reduce(cred_info,
195 cur_dist_list, 0); 197 cur_list, 0);
196 } 198 }
197 } 199 }
198 } 200 }
@@ -460,8 +462,8 @@ static void htc_async_tx_scat_complete(struct htc_target *target,
460 INIT_LIST_HEAD(&tx_compq); 462 INIT_LIST_HEAD(&tx_compq);
461 463
462 ath6kl_dbg(ATH6KL_DBG_HTC, 464 ath6kl_dbg(ATH6KL_DBG_HTC,
463 "htc tx scat complete len %d entries %d\n", 465 "htc tx scat complete len %d entries %d\n",
464 scat_req->len, scat_req->scat_entries); 466 scat_req->len, scat_req->scat_entries);
465 467
466 if (scat_req->status) 468 if (scat_req->status)
467 ath6kl_err("send scatter req failed: %d\n", scat_req->status); 469 ath6kl_err("send scatter req failed: %d\n", scat_req->status);
@@ -599,8 +601,8 @@ static void ath6kl_htc_tx_pkts_get(struct htc_target *target,
599 list); 601 list);
600 602
601 ath6kl_dbg(ATH6KL_DBG_HTC, 603 ath6kl_dbg(ATH6KL_DBG_HTC,
602 "htc tx got packet 0x%p queue depth %d\n", 604 "htc tx got packet 0x%p queue depth %d\n",
603 packet, get_queue_depth(&endpoint->txq)); 605 packet, get_queue_depth(&endpoint->txq));
604 606
605 len = CALC_TXRX_PADDED_LEN(target, 607 len = CALC_TXRX_PADDED_LEN(target,
606 packet->act_len + HTC_HDR_LENGTH); 608 packet->act_len + HTC_HDR_LENGTH);
@@ -670,6 +672,7 @@ static int ath6kl_htc_tx_setup_scat_list(struct htc_target *target,
670 struct htc_packet *packet; 672 struct htc_packet *packet;
671 int i, len, rem_scat, cred_pad; 673 int i, len, rem_scat, cred_pad;
672 int status = 0; 674 int status = 0;
675 u8 flags;
673 676
674 rem_scat = target->max_tx_bndl_sz; 677 rem_scat = target->max_tx_bndl_sz;
675 678
@@ -696,9 +699,9 @@ static int ath6kl_htc_tx_setup_scat_list(struct htc_target *target,
696 699
697 scat_req->scat_list[i].packet = packet; 700 scat_req->scat_list[i].packet = packet;
698 /* prepare packet and flag message as part of a send bundle */ 701 /* prepare packet and flag message as part of a send bundle */
699 ath6kl_htc_tx_prep_pkt(packet, 702 flags = packet->info.tx.flags | HTC_FLAGS_SEND_BUNDLE;
700 packet->info.tx.flags | HTC_FLAGS_SEND_BUNDLE, 703 ath6kl_htc_tx_prep_pkt(packet, flags,
701 cred_pad, packet->info.tx.seqno); 704 cred_pad, packet->info.tx.seqno);
702 /* Make sure the buffer is 4-byte aligned */ 705 /* Make sure the buffer is 4-byte aligned */
703 ath6kl_htc_tx_buf_align(&packet->buf, 706 ath6kl_htc_tx_buf_align(&packet->buf,
704 packet->act_len + HTC_HDR_LENGTH); 707 packet->act_len + HTC_HDR_LENGTH);
@@ -744,6 +747,12 @@ static void ath6kl_htc_tx_bundle(struct htc_endpoint *endpoint,
744 struct hif_scatter_req *scat_req = NULL; 747 struct hif_scatter_req *scat_req = NULL;
745 int n_scat, n_sent_bundle = 0, tot_pkts_bundle = 0; 748 int n_scat, n_sent_bundle = 0, tot_pkts_bundle = 0;
746 int status; 749 int status;
750 u32 txb_mask;
751 u8 ac = WMM_NUM_AC;
752
753 if ((HTC_CTRL_RSVD_SVC != endpoint->svc_id) ||
754 (WMI_CONTROL_SVC != endpoint->svc_id))
755 ac = target->dev->ar->ep2ac_map[endpoint->eid];
747 756
748 while (true) { 757 while (true) {
749 status = 0; 758 status = 0;
@@ -759,10 +768,35 @@ static void ath6kl_htc_tx_bundle(struct htc_endpoint *endpoint,
759 if (!scat_req) { 768 if (!scat_req) {
760 /* no scatter resources */ 769 /* no scatter resources */
761 ath6kl_dbg(ATH6KL_DBG_HTC, 770 ath6kl_dbg(ATH6KL_DBG_HTC,
762 "htc tx no more scatter resources\n"); 771 "htc tx no more scatter resources\n");
763 break; 772 break;
764 } 773 }
765 774
775 if ((ac < WMM_NUM_AC) && (ac != WMM_AC_BK)) {
776 if (WMM_AC_BE == ac)
777 /*
778 * BE, BK have priorities and bit
779 * positions reversed
780 */
781 txb_mask = (1 << WMM_AC_BK);
782 else
783 /*
784 * any AC with priority lower than
785 * itself
786 */
787 txb_mask = ((1 << ac) - 1);
788 /*
789 * when the scatter request resources drop below a
790 * certain threshold, disable Tx bundling for all
791 * AC's with priority lower than the current requesting
792 * AC. Otherwise re-enable Tx bundling for them
793 */
794 if (scat_req->scat_q_depth < ATH6KL_SCATTER_REQS)
795 target->tx_bndl_mask &= ~txb_mask;
796 else
797 target->tx_bndl_mask |= txb_mask;
798 }
799
766 ath6kl_dbg(ATH6KL_DBG_HTC, "htc tx pkts to scatter: %d\n", 800 ath6kl_dbg(ATH6KL_DBG_HTC, "htc tx pkts to scatter: %d\n",
767 n_scat); 801 n_scat);
768 802
@@ -806,6 +840,7 @@ static void ath6kl_htc_tx_from_queue(struct htc_target *target,
806 struct htc_packet *packet; 840 struct htc_packet *packet;
807 int bundle_sent; 841 int bundle_sent;
808 int n_pkts_bundle; 842 int n_pkts_bundle;
843 u8 ac = WMM_NUM_AC;
809 844
810 spin_lock_bh(&target->tx_lock); 845 spin_lock_bh(&target->tx_lock);
811 846
@@ -823,6 +858,10 @@ static void ath6kl_htc_tx_from_queue(struct htc_target *target,
823 */ 858 */
824 INIT_LIST_HEAD(&txq); 859 INIT_LIST_HEAD(&txq);
825 860
861 if ((HTC_CTRL_RSVD_SVC != endpoint->svc_id) ||
862 (WMI_CONTROL_SVC != endpoint->svc_id))
863 ac = target->dev->ar->ep2ac_map[endpoint->eid];
864
826 while (true) { 865 while (true) {
827 866
828 if (list_empty(&endpoint->txq)) 867 if (list_empty(&endpoint->txq))
@@ -840,15 +879,18 @@ static void ath6kl_htc_tx_from_queue(struct htc_target *target,
840 879
841 while (true) { 880 while (true) {
842 /* try to send a bundle on each pass */ 881 /* try to send a bundle on each pass */
843 if ((target->tx_bndl_enable) && 882 if ((target->tx_bndl_mask) &&
844 (get_queue_depth(&txq) >= 883 (get_queue_depth(&txq) >=
845 HTC_MIN_HTC_MSGS_TO_BUNDLE)) { 884 HTC_MIN_HTC_MSGS_TO_BUNDLE)) {
846 int temp1 = 0, temp2 = 0; 885 int temp1 = 0, temp2 = 0;
847 886
848 ath6kl_htc_tx_bundle(endpoint, &txq, 887 /* check if bundling is enabled for an AC */
849 &temp1, &temp2); 888 if (target->tx_bndl_mask & (1 << ac)) {
850 bundle_sent += temp1; 889 ath6kl_htc_tx_bundle(endpoint, &txq,
851 n_pkts_bundle += temp2; 890 &temp1, &temp2);
891 bundle_sent += temp1;
892 n_pkts_bundle += temp2;
893 }
852 } 894 }
853 895
854 if (list_empty(&txq)) 896 if (list_empty(&txq))
@@ -867,6 +909,26 @@ static void ath6kl_htc_tx_from_queue(struct htc_target *target,
867 909
868 endpoint->ep_st.tx_bundles += bundle_sent; 910 endpoint->ep_st.tx_bundles += bundle_sent;
869 endpoint->ep_st.tx_pkt_bundled += n_pkts_bundle; 911 endpoint->ep_st.tx_pkt_bundled += n_pkts_bundle;
912
913 /*
914 * if an AC has bundling disabled and no tx bundling
915 * has occured continously for a certain number of TX,
916 * enable tx bundling for this AC
917 */
918 if (!bundle_sent) {
919 if (!(target->tx_bndl_mask & (1 << ac)) &&
920 (ac < WMM_NUM_AC)) {
921 if (++target->ac_tx_count[ac] >=
922 TX_RESUME_BUNDLE_THRESHOLD) {
923 target->ac_tx_count[ac] = 0;
924 target->tx_bndl_mask |= (1 << ac);
925 }
926 }
927 } else {
928 /* tx bundling will reset the counter */
929 if (ac < WMM_NUM_AC)
930 target->ac_tx_count[ac] = 0;
931 }
870 } 932 }
871 933
872 endpoint->tx_proc_cnt = 0; 934 endpoint->tx_proc_cnt = 0;
@@ -979,8 +1041,8 @@ static int htc_setup_tx_complete(struct htc_target *target)
979 memcpy(&setup_comp_ext->flags, &flags, 1041 memcpy(&setup_comp_ext->flags, &flags,
980 sizeof(setup_comp_ext->flags)); 1042 sizeof(setup_comp_ext->flags));
981 set_htc_pkt_info(send_pkt, NULL, (u8 *) setup_comp_ext, 1043 set_htc_pkt_info(send_pkt, NULL, (u8 *) setup_comp_ext,
982 sizeof(struct htc_setup_comp_ext_msg), 1044 sizeof(struct htc_setup_comp_ext_msg),
983 ENDPOINT_0, HTC_SERVICE_TX_PACKET_TAG); 1045 ENDPOINT_0, HTC_SERVICE_TX_PACKET_TAG);
984 1046
985 } else { 1047 } else {
986 struct htc_setup_comp_msg *setup_comp; 1048 struct htc_setup_comp_msg *setup_comp;
@@ -988,8 +1050,8 @@ static int htc_setup_tx_complete(struct htc_target *target)
988 memset(setup_comp, 0, sizeof(struct htc_setup_comp_msg)); 1050 memset(setup_comp, 0, sizeof(struct htc_setup_comp_msg));
989 setup_comp->msg_id = cpu_to_le16(HTC_MSG_SETUP_COMPLETE_ID); 1051 setup_comp->msg_id = cpu_to_le16(HTC_MSG_SETUP_COMPLETE_ID);
990 set_htc_pkt_info(send_pkt, NULL, (u8 *) setup_comp, 1052 set_htc_pkt_info(send_pkt, NULL, (u8 *) setup_comp,
991 sizeof(struct htc_setup_comp_msg), 1053 sizeof(struct htc_setup_comp_msg),
992 ENDPOINT_0, HTC_SERVICE_TX_PACKET_TAG); 1054 ENDPOINT_0, HTC_SERVICE_TX_PACKET_TAG);
993 } 1055 }
994 1056
995 /* we want synchronous operation */ 1057 /* we want synchronous operation */
@@ -1088,9 +1150,9 @@ void ath6kl_htc_flush_txep(struct htc_target *target,
1088 packet->status = -ECANCELED; 1150 packet->status = -ECANCELED;
1089 list_del(&packet->list); 1151 list_del(&packet->list);
1090 ath6kl_dbg(ATH6KL_DBG_HTC, 1152 ath6kl_dbg(ATH6KL_DBG_HTC,
1091 "htc tx flushing pkt 0x%p len %d ep %d tag 0x%x\n", 1153 "htc tx flushing pkt 0x%p len %d ep %d tag 0x%x\n",
1092 packet, packet->act_len, 1154 packet, packet->act_len,
1093 packet->endpoint, packet->info.tx.tag); 1155 packet->endpoint, packet->info.tx.tag);
1094 1156
1095 INIT_LIST_HEAD(&container); 1157 INIT_LIST_HEAD(&container);
1096 list_add_tail(&packet->list, &container); 1158 list_add_tail(&packet->list, &container);
@@ -1490,7 +1552,7 @@ static void htc_ctrl_rx(struct htc_target *context, struct htc_packet *packets)
1490 1552
1491 if (packets->act_len > 0) { 1553 if (packets->act_len > 0) {
1492 ath6kl_err("htc_ctrl_rx, got message with len:%zu\n", 1554 ath6kl_err("htc_ctrl_rx, got message with len:%zu\n",
1493 packets->act_len + HTC_HDR_LENGTH); 1555 packets->act_len + HTC_HDR_LENGTH);
1494 1556
1495 ath6kl_dbg_dump(ATH6KL_DBG_HTC, 1557 ath6kl_dbg_dump(ATH6KL_DBG_HTC,
1496 "htc rx unexpected endpoint 0 message", "", 1558 "htc rx unexpected endpoint 0 message", "",
@@ -1609,8 +1671,8 @@ static int htc_parse_trailer(struct htc_target *target,
1609 } 1671 }
1610 1672
1611 lk_ahd = (struct htc_lookahead_report *) record_buf; 1673 lk_ahd = (struct htc_lookahead_report *) record_buf;
1612 if ((lk_ahd->pre_valid == ((~lk_ahd->post_valid) & 0xFF)) 1674 if ((lk_ahd->pre_valid == ((~lk_ahd->post_valid) & 0xFF)) &&
1613 && next_lk_ahds) { 1675 next_lk_ahds) {
1614 1676
1615 ath6kl_dbg(ATH6KL_DBG_HTC, 1677 ath6kl_dbg(ATH6KL_DBG_HTC,
1616 "htc rx lk_ahd found pre_valid 0x%x post_valid 0x%x\n", 1678 "htc rx lk_ahd found pre_valid 0x%x post_valid 0x%x\n",
@@ -2038,13 +2100,13 @@ fail_rx:
2038 list_for_each_entry_safe(packet, tmp_pkt, rx_pktq, list) { 2100 list_for_each_entry_safe(packet, tmp_pkt, rx_pktq, list) {
2039 list_del(&packet->list); 2101 list_del(&packet->list);
2040 htc_reclaim_rxbuf(target, packet, 2102 htc_reclaim_rxbuf(target, packet,
2041 &target->endpoint[packet->endpoint]); 2103 &target->endpoint[packet->endpoint]);
2042 } 2104 }
2043 2105
2044 list_for_each_entry_safe(packet, tmp_pkt, &tmp_rxq, list) { 2106 list_for_each_entry_safe(packet, tmp_pkt, &tmp_rxq, list) {
2045 list_del(&packet->list); 2107 list_del(&packet->list);
2046 htc_reclaim_rxbuf(target, packet, 2108 htc_reclaim_rxbuf(target, packet,
2047 &target->endpoint[packet->endpoint]); 2109 &target->endpoint[packet->endpoint]);
2048 } 2110 }
2049 2111
2050 return status; 2112 return status;
@@ -2176,11 +2238,11 @@ static struct htc_packet *htc_wait_for_ctrl_msg(struct htc_target *target)
2176 u32 look_ahead; 2238 u32 look_ahead;
2177 2239
2178 if (ath6kl_hif_poll_mboxmsg_rx(target->dev, &look_ahead, 2240 if (ath6kl_hif_poll_mboxmsg_rx(target->dev, &look_ahead,
2179 HTC_TARGET_RESPONSE_TIMEOUT)) 2241 HTC_TARGET_RESPONSE_TIMEOUT))
2180 return NULL; 2242 return NULL;
2181 2243
2182 ath6kl_dbg(ATH6KL_DBG_HTC, 2244 ath6kl_dbg(ATH6KL_DBG_HTC,
2183 "htc rx wait ctrl look_ahead 0x%X\n", look_ahead); 2245 "htc rx wait ctrl look_ahead 0x%X\n", look_ahead);
2184 2246
2185 htc_hdr = (struct htc_frame_hdr *)&look_ahead; 2247 htc_hdr = (struct htc_frame_hdr *)&look_ahead;
2186 2248
@@ -2245,7 +2307,7 @@ int ath6kl_htc_add_rxbuf_multiple(struct htc_target *target,
2245 depth = get_queue_depth(pkt_queue); 2307 depth = get_queue_depth(pkt_queue);
2246 2308
2247 ath6kl_dbg(ATH6KL_DBG_HTC, 2309 ath6kl_dbg(ATH6KL_DBG_HTC,
2248 "htc rx add multiple ep id %d cnt %d len %d\n", 2310 "htc rx add multiple ep id %d cnt %d len %d\n",
2249 first_pkt->endpoint, depth, first_pkt->buf_len); 2311 first_pkt->endpoint, depth, first_pkt->buf_len);
2250 2312
2251 endpoint = &target->endpoint[first_pkt->endpoint]; 2313 endpoint = &target->endpoint[first_pkt->endpoint];
@@ -2271,8 +2333,8 @@ int ath6kl_htc_add_rxbuf_multiple(struct htc_target *target,
2271 if (target->rx_st_flags & HTC_RECV_WAIT_BUFFERS) { 2333 if (target->rx_st_flags & HTC_RECV_WAIT_BUFFERS) {
2272 if (target->ep_waiting == first_pkt->endpoint) { 2334 if (target->ep_waiting == first_pkt->endpoint) {
2273 ath6kl_dbg(ATH6KL_DBG_HTC, 2335 ath6kl_dbg(ATH6KL_DBG_HTC,
2274 "htc rx blocked on ep %d, unblocking\n", 2336 "htc rx blocked on ep %d, unblocking\n",
2275 target->ep_waiting); 2337 target->ep_waiting);
2276 target->rx_st_flags &= ~HTC_RECV_WAIT_BUFFERS; 2338 target->rx_st_flags &= ~HTC_RECV_WAIT_BUFFERS;
2277 target->ep_waiting = ENDPOINT_MAX; 2339 target->ep_waiting = ENDPOINT_MAX;
2278 rx_unblock = true; 2340 rx_unblock = true;
@@ -2309,7 +2371,21 @@ void ath6kl_htc_flush_rx_buf(struct htc_target *target)
2309 "htc rx flush pkt 0x%p len %d ep %d\n", 2371 "htc rx flush pkt 0x%p len %d ep %d\n",
2310 packet, packet->buf_len, 2372 packet, packet->buf_len,
2311 packet->endpoint); 2373 packet->endpoint);
2312 dev_kfree_skb(packet->pkt_cntxt); 2374 /*
2375 * packets in rx_bufq of endpoint 0 have originally
2376 * been queued from target->free_ctrl_rxbuf where
2377 * packet and packet->buf_start are allocated
2378 * separately using kmalloc(). For other endpoint
2379 * rx_bufq, it is allocated as skb where packet is
2380 * skb->head. Take care of this difference while freeing
2381 * the memory.
2382 */
2383 if (packet->endpoint == ENDPOINT_0) {
2384 kfree(packet->buf_start);
2385 kfree(packet);
2386 } else {
2387 dev_kfree_skb(packet->pkt_cntxt);
2388 }
2313 spin_lock_bh(&target->rx_lock); 2389 spin_lock_bh(&target->rx_lock);
2314 } 2390 }
2315 spin_unlock_bh(&target->rx_lock); 2391 spin_unlock_bh(&target->rx_lock);
@@ -2328,6 +2404,7 @@ int ath6kl_htc_conn_service(struct htc_target *target,
2328 enum htc_endpoint_id assigned_ep = ENDPOINT_MAX; 2404 enum htc_endpoint_id assigned_ep = ENDPOINT_MAX;
2329 unsigned int max_msg_sz = 0; 2405 unsigned int max_msg_sz = 0;
2330 int status = 0; 2406 int status = 0;
2407 u16 msg_id;
2331 2408
2332 ath6kl_dbg(ATH6KL_DBG_HTC, 2409 ath6kl_dbg(ATH6KL_DBG_HTC,
2333 "htc connect service target 0x%p service id 0x%x\n", 2410 "htc connect service target 0x%p service id 0x%x\n",
@@ -2371,9 +2448,10 @@ int ath6kl_htc_conn_service(struct htc_target *target,
2371 } 2448 }
2372 2449
2373 resp_msg = (struct htc_conn_service_resp *)rx_pkt->buf; 2450 resp_msg = (struct htc_conn_service_resp *)rx_pkt->buf;
2451 msg_id = le16_to_cpu(resp_msg->msg_id);
2374 2452
2375 if ((le16_to_cpu(resp_msg->msg_id) != HTC_MSG_CONN_SVC_RESP_ID) 2453 if ((msg_id != HTC_MSG_CONN_SVC_RESP_ID) ||
2376 || (rx_pkt->act_len < sizeof(*resp_msg))) { 2454 (rx_pkt->act_len < sizeof(*resp_msg))) {
2377 status = -ENOMEM; 2455 status = -ENOMEM;
2378 goto fail_tx; 2456 goto fail_tx;
2379 } 2457 }
@@ -2420,6 +2498,15 @@ int ath6kl_htc_conn_service(struct htc_target *target,
2420 endpoint->cred_dist.endpoint = assigned_ep; 2498 endpoint->cred_dist.endpoint = assigned_ep;
2421 endpoint->cred_dist.cred_sz = target->tgt_cred_sz; 2499 endpoint->cred_dist.cred_sz = target->tgt_cred_sz;
2422 2500
2501 switch (endpoint->svc_id) {
2502 case WMI_DATA_BK_SVC:
2503 endpoint->tx_drop_packet_threshold = MAX_DEF_COOKIE_NUM / 3;
2504 break;
2505 default:
2506 endpoint->tx_drop_packet_threshold = MAX_HI_COOKIE_NUM;
2507 break;
2508 }
2509
2423 if (conn_req->max_rxmsg_sz) { 2510 if (conn_req->max_rxmsg_sz) {
2424 /* 2511 /*
2425 * Override cred_per_msg calculation, this optimizes 2512 * Override cred_per_msg calculation, this optimizes
@@ -2517,7 +2604,8 @@ static void htc_setup_msg_bndl(struct htc_target *target)
2517 target->max_rx_bndl_sz, target->max_tx_bndl_sz); 2604 target->max_rx_bndl_sz, target->max_tx_bndl_sz);
2518 2605
2519 if (target->max_tx_bndl_sz) 2606 if (target->max_tx_bndl_sz)
2520 target->tx_bndl_enable = true; 2607 /* tx_bndl_mask is enabled per AC, each has 1 bit */
2608 target->tx_bndl_mask = (1 << WMM_NUM_AC) - 1;
2521 2609
2522 if (target->max_rx_bndl_sz) 2610 if (target->max_rx_bndl_sz)
2523 target->rx_bndl_enable = true; 2611 target->rx_bndl_enable = true;
@@ -2532,7 +2620,7 @@ static void htc_setup_msg_bndl(struct htc_target *target)
2532 * padding will spill into the next credit buffer 2620 * padding will spill into the next credit buffer
2533 * which is fatal. 2621 * which is fatal.
2534 */ 2622 */
2535 target->tx_bndl_enable = false; 2623 target->tx_bndl_mask = 0;
2536 } 2624 }
2537} 2625}
2538 2626
@@ -2589,8 +2677,8 @@ int ath6kl_htc_wait_target(struct htc_target *target)
2589 } 2677 }
2590 2678
2591 ath6kl_dbg(ATH6KL_DBG_BOOT, "htc using protocol %s (%d)\n", 2679 ath6kl_dbg(ATH6KL_DBG_BOOT, "htc using protocol %s (%d)\n",
2592 (target->htc_tgt_ver == HTC_VERSION_2P0) ? "2.0" : ">= 2.1", 2680 (target->htc_tgt_ver == HTC_VERSION_2P0) ? "2.0" : ">= 2.1",
2593 target->htc_tgt_ver); 2681 target->htc_tgt_ver);
2594 2682
2595 if (target->msg_per_bndl_max > 0) 2683 if (target->msg_per_bndl_max > 0)
2596 htc_setup_msg_bndl(target); 2684 htc_setup_msg_bndl(target);
@@ -2784,14 +2872,14 @@ void ath6kl_htc_cleanup(struct htc_target *target)
2784 ath6kl_hif_cleanup_scatter(target->dev->ar); 2872 ath6kl_hif_cleanup_scatter(target->dev->ar);
2785 2873
2786 list_for_each_entry_safe(packet, tmp_packet, 2874 list_for_each_entry_safe(packet, tmp_packet,
2787 &target->free_ctrl_txbuf, list) { 2875 &target->free_ctrl_txbuf, list) {
2788 list_del(&packet->list); 2876 list_del(&packet->list);
2789 kfree(packet->buf_start); 2877 kfree(packet->buf_start);
2790 kfree(packet); 2878 kfree(packet);
2791 } 2879 }
2792 2880
2793 list_for_each_entry_safe(packet, tmp_packet, 2881 list_for_each_entry_safe(packet, tmp_packet,
2794 &target->free_ctrl_rxbuf, list) { 2882 &target->free_ctrl_rxbuf, list) {
2795 list_del(&packet->list); 2883 list_del(&packet->list);
2796 kfree(packet->buf_start); 2884 kfree(packet->buf_start);
2797 kfree(packet); 2885 kfree(packet);
diff --git a/drivers/net/wireless/ath/ath6kl/htc.h b/drivers/net/wireless/ath/ath6kl/htc.h
index 57672e1ed1a6..5027ccc36b62 100644
--- a/drivers/net/wireless/ath/ath6kl/htc.h
+++ b/drivers/net/wireless/ath/ath6kl/htc.h
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (c) 2004-2011 Atheros Communications Inc. 2 * Copyright (c) 2004-2011 Atheros Communications Inc.
3 * Copyright (c) 2011 Qualcomm Atheros, Inc.
3 * 4 *
4 * Permission to use, copy, modify, and/or distribute this software for any 5 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above 6 * purpose with or without fee is hereby granted, provided that the above
@@ -87,6 +88,8 @@
87#define WMI_DATA_VO_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 4) 88#define WMI_DATA_VO_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 4)
88#define WMI_MAX_SERVICES 5 89#define WMI_MAX_SERVICES 5
89 90
91#define WMM_NUM_AC 4
92
90/* reserved and used to flush ALL packets */ 93/* reserved and used to flush ALL packets */
91#define HTC_TX_PACKET_TAG_ALL 0 94#define HTC_TX_PACKET_TAG_ALL 0
92#define HTC_SERVICE_TX_PACKET_TAG 1 95#define HTC_SERVICE_TX_PACKET_TAG 1
@@ -498,6 +501,7 @@ struct htc_endpoint {
498 u8 seqno; 501 u8 seqno;
499 u32 conn_flags; 502 u32 conn_flags;
500 struct htc_endpoint_stats ep_st; 503 struct htc_endpoint_stats ep_st;
504 u16 tx_drop_packet_threshold;
501}; 505};
502 506
503struct htc_control_buffer { 507struct htc_control_buffer {
@@ -519,9 +523,16 @@ struct htc_target {
519 struct ath6kl_htc_credit_info *credit_info; 523 struct ath6kl_htc_credit_info *credit_info;
520 int tgt_creds; 524 int tgt_creds;
521 unsigned int tgt_cred_sz; 525 unsigned int tgt_cred_sz;
526
527 /* protects free_ctrl_txbuf and free_ctrl_rxbuf */
522 spinlock_t htc_lock; 528 spinlock_t htc_lock;
529
530 /* FIXME: does this protext rx_bufq and endpoint structures or what? */
523 spinlock_t rx_lock; 531 spinlock_t rx_lock;
532
533 /* protects endpoint->txq */
524 spinlock_t tx_lock; 534 spinlock_t tx_lock;
535
525 struct ath6kl_device *dev; 536 struct ath6kl_device *dev;
526 u32 htc_flags; 537 u32 htc_flags;
527 u32 rx_st_flags; 538 u32 rx_st_flags;
@@ -531,7 +542,7 @@ struct htc_target {
531 /* max messages per bundle for HTC */ 542 /* max messages per bundle for HTC */
532 int msg_per_bndl_max; 543 int msg_per_bndl_max;
533 544
534 bool tx_bndl_enable; 545 u32 tx_bndl_mask;
535 int rx_bndl_enable; 546 int rx_bndl_enable;
536 int max_rx_bndl_sz; 547 int max_rx_bndl_sz;
537 int max_tx_bndl_sz; 548 int max_tx_bndl_sz;
@@ -543,6 +554,9 @@ struct htc_target {
543 int max_xfer_szper_scatreq; 554 int max_xfer_szper_scatreq;
544 555
545 int chk_irq_status_cnt; 556 int chk_irq_status_cnt;
557
558 /* counts the number of Tx without bundling continously per AC */
559 u32 ac_tx_count[WMM_NUM_AC];
546}; 560};
547 561
548void *ath6kl_htc_create(struct ath6kl *ar); 562void *ath6kl_htc_create(struct ath6kl *ar);
diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c
index 0d76c3778106..03cae142f178 100644
--- a/drivers/net/wireless/ath/ath6kl/init.c
+++ b/drivers/net/wireless/ath/ath6kl/init.c
@@ -1,6 +1,7 @@
1 1
2/* 2/*
3 * Copyright (c) 2011 Atheros Communications Inc. 3 * Copyright (c) 2011 Atheros Communications Inc.
4 * Copyright (c) 2011-2012 Qualcomm Atheros, Inc.
4 * 5 *
5 * Permission to use, copy, modify, and/or distribute this software for any 6 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above 7 * purpose with or without fee is hereby granted, provided that the above
@@ -74,7 +75,7 @@ static const struct ath6kl_hw hw_list[] = {
74 }, 75 },
75 76
76 .fw_board = AR6003_HW_2_1_1_BOARD_DATA_FILE, 77 .fw_board = AR6003_HW_2_1_1_BOARD_DATA_FILE,
77 .fw_default_board = AR6003_HW_2_1_1_DEFAULT_BOARD_DATA_FILE, 78 .fw_default_board = AR6003_HW_2_1_1_DEFAULT_BOARD_DATA_FILE,
78 }, 79 },
79 { 80 {
80 .id = AR6004_HW_1_0_VERSION, 81 .id = AR6004_HW_1_0_VERSION,
@@ -351,11 +352,7 @@ static int ath6kl_set_htc_params(struct ath6kl *ar, u32 mbox_isr_yield_val,
351 blk_size |= ((u32)htc_ctrl_buf) << 16; 352 blk_size |= ((u32)htc_ctrl_buf) << 16;
352 353
353 /* set the host interest area for the block size */ 354 /* set the host interest area for the block size */
354 status = ath6kl_bmi_write(ar, 355 status = ath6kl_bmi_write_hi32(ar, hi_mbox_io_block_sz, blk_size);
355 ath6kl_get_hi_item_addr(ar,
356 HI_ITEM(hi_mbox_io_block_sz)),
357 (u8 *)&blk_size,
358 4);
359 if (status) { 356 if (status) {
360 ath6kl_err("bmi_write_memory for IO block size failed\n"); 357 ath6kl_err("bmi_write_memory for IO block size failed\n");
361 goto out; 358 goto out;
@@ -367,11 +364,8 @@ static int ath6kl_set_htc_params(struct ath6kl *ar, u32 mbox_isr_yield_val,
367 364
368 if (mbox_isr_yield_val) { 365 if (mbox_isr_yield_val) {
369 /* set the host interest area for the mbox ISR yield limit */ 366 /* set the host interest area for the mbox ISR yield limit */
370 status = ath6kl_bmi_write(ar, 367 status = ath6kl_bmi_write_hi32(ar, hi_mbox_isr_yield_limit,
371 ath6kl_get_hi_item_addr(ar, 368 mbox_isr_yield_val);
372 HI_ITEM(hi_mbox_isr_yield_limit)),
373 (u8 *)&mbox_isr_yield_val,
374 4);
375 if (status) { 369 if (status) {
376 ath6kl_err("bmi_write_memory for yield limit failed\n"); 370 ath6kl_err("bmi_write_memory for yield limit failed\n");
377 goto out; 371 goto out;
@@ -384,7 +378,6 @@ out:
384 378
385static int ath6kl_target_config_wlan_params(struct ath6kl *ar, int idx) 379static int ath6kl_target_config_wlan_params(struct ath6kl *ar, int idx)
386{ 380{
387 int status = 0;
388 int ret; 381 int ret;
389 382
390 /* 383 /*
@@ -392,43 +385,54 @@ static int ath6kl_target_config_wlan_params(struct ath6kl *ar, int idx)
392 * default values. Required if checksum offload is needed. Set 385 * default values. Required if checksum offload is needed. Set
393 * RxMetaVersion to 2. 386 * RxMetaVersion to 2.
394 */ 387 */
395 if (ath6kl_wmi_set_rx_frame_format_cmd(ar->wmi, idx, 388 ret = ath6kl_wmi_set_rx_frame_format_cmd(ar->wmi, idx,
396 ar->rx_meta_ver, 0, 0)) { 389 ar->rx_meta_ver, 0, 0);
397 ath6kl_err("unable to set the rx frame format\n"); 390 if (ret) {
398 status = -EIO; 391 ath6kl_err("unable to set the rx frame format: %d\n", ret);
392 return ret;
399 } 393 }
400 394
401 if (ar->conf_flags & ATH6KL_CONF_IGNORE_PS_FAIL_EVT_IN_SCAN) 395 if (ar->conf_flags & ATH6KL_CONF_IGNORE_PS_FAIL_EVT_IN_SCAN) {
402 if ((ath6kl_wmi_pmparams_cmd(ar->wmi, idx, 0, 1, 0, 0, 1, 396 ret = ath6kl_wmi_pmparams_cmd(ar->wmi, idx, 0, 1, 0, 0, 1,
403 IGNORE_POWER_SAVE_FAIL_EVENT_DURING_SCAN)) != 0) { 397 IGNORE_PS_FAIL_DURING_SCAN);
404 ath6kl_err("unable to set power save fail event policy\n"); 398 if (ret) {
405 status = -EIO; 399 ath6kl_err("unable to set power save fail event policy: %d\n",
400 ret);
401 return ret;
406 } 402 }
403 }
407 404
408 if (!(ar->conf_flags & ATH6KL_CONF_IGNORE_ERP_BARKER)) 405 if (!(ar->conf_flags & ATH6KL_CONF_IGNORE_ERP_BARKER)) {
409 if ((ath6kl_wmi_set_lpreamble_cmd(ar->wmi, idx, 0, 406 ret = ath6kl_wmi_set_lpreamble_cmd(ar->wmi, idx, 0,
410 WMI_DONOT_IGNORE_BARKER_IN_ERP)) != 0) { 407 WMI_FOLLOW_BARKER_IN_ERP);
411 ath6kl_err("unable to set barker preamble policy\n"); 408 if (ret) {
412 status = -EIO; 409 ath6kl_err("unable to set barker preamble policy: %d\n",
410 ret);
411 return ret;
413 } 412 }
413 }
414 414
415 if (ath6kl_wmi_set_keepalive_cmd(ar->wmi, idx, 415 ret = ath6kl_wmi_set_keepalive_cmd(ar->wmi, idx,
416 WLAN_CONFIG_KEEP_ALIVE_INTERVAL)) { 416 WLAN_CONFIG_KEEP_ALIVE_INTERVAL);
417 ath6kl_err("unable to set keep alive interval\n"); 417 if (ret) {
418 status = -EIO; 418 ath6kl_err("unable to set keep alive interval: %d\n", ret);
419 return ret;
419 } 420 }
420 421
421 if (ath6kl_wmi_disctimeout_cmd(ar->wmi, idx, 422 ret = ath6kl_wmi_disctimeout_cmd(ar->wmi, idx,
422 WLAN_CONFIG_DISCONNECT_TIMEOUT)) { 423 WLAN_CONFIG_DISCONNECT_TIMEOUT);
423 ath6kl_err("unable to set disconnect timeout\n"); 424 if (ret) {
424 status = -EIO; 425 ath6kl_err("unable to set disconnect timeout: %d\n", ret);
426 return ret;
425 } 427 }
426 428
427 if (!(ar->conf_flags & ATH6KL_CONF_ENABLE_TX_BURST)) 429 if (!(ar->conf_flags & ATH6KL_CONF_ENABLE_TX_BURST)) {
428 if (ath6kl_wmi_set_wmm_txop(ar->wmi, idx, WMI_TXOP_DISABLED)) { 430 ret = ath6kl_wmi_set_wmm_txop(ar->wmi, idx, WMI_TXOP_DISABLED);
429 ath6kl_err("unable to set txop bursting\n"); 431 if (ret) {
430 status = -EIO; 432 ath6kl_err("unable to set txop bursting: %d\n", ret);
433 return ret;
431 } 434 }
435 }
432 436
433 if (ar->p2p && (ar->vif_max == 1 || idx)) { 437 if (ar->p2p && (ar->vif_max == 1 || idx)) {
434 ret = ath6kl_wmi_info_req_cmd(ar->wmi, idx, 438 ret = ath6kl_wmi_info_req_cmd(ar->wmi, idx,
@@ -452,7 +456,7 @@ static int ath6kl_target_config_wlan_params(struct ath6kl *ar, int idx)
452 } 456 }
453 } 457 }
454 458
455 return status; 459 return ret;
456} 460}
457 461
458int ath6kl_configure_target(struct ath6kl *ar) 462int ath6kl_configure_target(struct ath6kl *ar)
@@ -462,8 +466,7 @@ int ath6kl_configure_target(struct ath6kl *ar)
462 int i, status; 466 int i, status;
463 467
464 param = !!(ar->conf_flags & ATH6KL_CONF_UART_DEBUG); 468 param = !!(ar->conf_flags & ATH6KL_CONF_UART_DEBUG);
465 if (ath6kl_bmi_write(ar, ath6kl_get_hi_item_addr(ar, 469 if (ath6kl_bmi_write_hi32(ar, hi_serial_enable, param)) {
466 HI_ITEM(hi_serial_enable)), (u8 *)&param, 4)) {
467 ath6kl_err("bmi_write_memory for uart debug failed\n"); 470 ath6kl_err("bmi_write_memory for uart debug failed\n");
468 return -EIO; 471 return -EIO;
469 } 472 }
@@ -499,11 +502,8 @@ int ath6kl_configure_target(struct ath6kl *ar)
499 if (ar->p2p && ar->vif_max == 1) 502 if (ar->p2p && ar->vif_max == 1)
500 fw_submode = HI_OPTION_FW_SUBMODE_P2PDEV; 503 fw_submode = HI_OPTION_FW_SUBMODE_P2PDEV;
501 504
502 param = HTC_PROTOCOL_VERSION; 505 if (ath6kl_bmi_write_hi32(ar, hi_app_host_interest,
503 if (ath6kl_bmi_write(ar, 506 HTC_PROTOCOL_VERSION) != 0) {
504 ath6kl_get_hi_item_addr(ar,
505 HI_ITEM(hi_app_host_interest)),
506 (u8 *)&param, 4) != 0) {
507 ath6kl_err("bmi_write_memory for htc version failed\n"); 507 ath6kl_err("bmi_write_memory for htc version failed\n");
508 return -EIO; 508 return -EIO;
509 } 509 }
@@ -511,10 +511,7 @@ int ath6kl_configure_target(struct ath6kl *ar)
511 /* set the firmware mode to STA/IBSS/AP */ 511 /* set the firmware mode to STA/IBSS/AP */
512 param = 0; 512 param = 0;
513 513
514 if (ath6kl_bmi_read(ar, 514 if (ath6kl_bmi_read_hi32(ar, hi_option_flag, &param) != 0) {
515 ath6kl_get_hi_item_addr(ar,
516 HI_ITEM(hi_option_flag)),
517 (u8 *)&param, 4) != 0) {
518 ath6kl_err("bmi_read_memory for setting fwmode failed\n"); 515 ath6kl_err("bmi_read_memory for setting fwmode failed\n");
519 return -EIO; 516 return -EIO;
520 } 517 }
@@ -526,11 +523,7 @@ int ath6kl_configure_target(struct ath6kl *ar)
526 param |= (0 << HI_OPTION_MAC_ADDR_METHOD_SHIFT); 523 param |= (0 << HI_OPTION_MAC_ADDR_METHOD_SHIFT);
527 param |= (0 << HI_OPTION_FW_BRIDGE_SHIFT); 524 param |= (0 << HI_OPTION_FW_BRIDGE_SHIFT);
528 525
529 if (ath6kl_bmi_write(ar, 526 if (ath6kl_bmi_write_hi32(ar, hi_option_flag, param) != 0) {
530 ath6kl_get_hi_item_addr(ar,
531 HI_ITEM(hi_option_flag)),
532 (u8 *)&param,
533 4) != 0) {
534 ath6kl_err("bmi_write_memory for setting fwmode failed\n"); 527 ath6kl_err("bmi_write_memory for setting fwmode failed\n");
535 return -EIO; 528 return -EIO;
536 } 529 }
@@ -549,16 +542,13 @@ int ath6kl_configure_target(struct ath6kl *ar)
549 param = ar->hw.board_ext_data_addr; 542 param = ar->hw.board_ext_data_addr;
550 ram_reserved_size = ar->hw.reserved_ram_size; 543 ram_reserved_size = ar->hw.reserved_ram_size;
551 544
552 if (ath6kl_bmi_write(ar, ath6kl_get_hi_item_addr(ar, 545 if (ath6kl_bmi_write_hi32(ar, hi_board_ext_data, param) != 0) {
553 HI_ITEM(hi_board_ext_data)),
554 (u8 *)&param, 4) != 0) {
555 ath6kl_err("bmi_write_memory for hi_board_ext_data failed\n"); 546 ath6kl_err("bmi_write_memory for hi_board_ext_data failed\n");
556 return -EIO; 547 return -EIO;
557 } 548 }
558 549
559 if (ath6kl_bmi_write(ar, ath6kl_get_hi_item_addr(ar, 550 if (ath6kl_bmi_write_hi32(ar, hi_end_ram_reserve_sz,
560 HI_ITEM(hi_end_ram_reserve_sz)), 551 ram_reserved_size) != 0) {
561 (u8 *)&ram_reserved_size, 4) != 0) {
562 ath6kl_err("bmi_write_memory for hi_end_ram_reserve_sz failed\n"); 552 ath6kl_err("bmi_write_memory for hi_end_ram_reserve_sz failed\n");
563 return -EIO; 553 return -EIO;
564 } 554 }
@@ -569,20 +559,13 @@ int ath6kl_configure_target(struct ath6kl *ar)
569 return -EIO; 559 return -EIO;
570 560
571 /* Configure GPIO AR600x UART */ 561 /* Configure GPIO AR600x UART */
572 param = ar->hw.uarttx_pin; 562 status = ath6kl_bmi_write_hi32(ar, hi_dbg_uart_txpin,
573 status = ath6kl_bmi_write(ar, 563 ar->hw.uarttx_pin);
574 ath6kl_get_hi_item_addr(ar,
575 HI_ITEM(hi_dbg_uart_txpin)),
576 (u8 *)&param, 4);
577 if (status) 564 if (status)
578 return status; 565 return status;
579 566
580 /* Configure target refclk_hz */ 567 /* Configure target refclk_hz */
581 param = ar->hw.refclk_hz; 568 status = ath6kl_bmi_write_hi32(ar, hi_refclk_hz, ar->hw.refclk_hz);
582 status = ath6kl_bmi_write(ar,
583 ath6kl_get_hi_item_addr(ar,
584 HI_ITEM(hi_refclk_hz)),
585 (u8 *)&param, 4);
586 if (status) 569 if (status)
587 return status; 570 return status;
588 571
@@ -832,13 +815,13 @@ static int ath6kl_fetch_testscript_file(struct ath6kl *ar)
832 return 0; 815 return 0;
833 816
834 snprintf(filename, sizeof(filename), "%s/%s", 817 snprintf(filename, sizeof(filename), "%s/%s",
835 ar->hw.fw.dir, ar->hw.fw.testscript); 818 ar->hw.fw.dir, ar->hw.fw.testscript);
836 819
837 ret = ath6kl_get_fw(ar, filename, &ar->fw_testscript, 820 ret = ath6kl_get_fw(ar, filename, &ar->fw_testscript,
838 &ar->fw_testscript_len); 821 &ar->fw_testscript_len);
839 if (ret) { 822 if (ret) {
840 ath6kl_err("Failed to get testscript file %s: %d\n", 823 ath6kl_err("Failed to get testscript file %s: %d\n",
841 filename, ret); 824 filename, ret);
842 return ret; 825 return ret;
843 } 826 }
844 827
@@ -922,7 +905,7 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name)
922 switch (ie_id) { 905 switch (ie_id) {
923 case ATH6KL_FW_IE_OTP_IMAGE: 906 case ATH6KL_FW_IE_OTP_IMAGE:
924 ath6kl_dbg(ATH6KL_DBG_BOOT, "found otp image ie (%zd B)\n", 907 ath6kl_dbg(ATH6KL_DBG_BOOT, "found otp image ie (%zd B)\n",
925 ie_len); 908 ie_len);
926 909
927 ar->fw_otp = kmemdup(data, ie_len, GFP_KERNEL); 910 ar->fw_otp = kmemdup(data, ie_len, GFP_KERNEL);
928 911
@@ -935,7 +918,7 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name)
935 break; 918 break;
936 case ATH6KL_FW_IE_FW_IMAGE: 919 case ATH6KL_FW_IE_FW_IMAGE:
937 ath6kl_dbg(ATH6KL_DBG_BOOT, "found fw image ie (%zd B)\n", 920 ath6kl_dbg(ATH6KL_DBG_BOOT, "found fw image ie (%zd B)\n",
938 ie_len); 921 ie_len);
939 922
940 /* in testmode we already might have a fw file */ 923 /* in testmode we already might have a fw file */
941 if (ar->fw != NULL) 924 if (ar->fw != NULL)
@@ -952,7 +935,7 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name)
952 break; 935 break;
953 case ATH6KL_FW_IE_PATCH_IMAGE: 936 case ATH6KL_FW_IE_PATCH_IMAGE:
954 ath6kl_dbg(ATH6KL_DBG_BOOT, "found patch image ie (%zd B)\n", 937 ath6kl_dbg(ATH6KL_DBG_BOOT, "found patch image ie (%zd B)\n",
955 ie_len); 938 ie_len);
956 939
957 ar->fw_patch = kmemdup(data, ie_len, GFP_KERNEL); 940 ar->fw_patch = kmemdup(data, ie_len, GFP_KERNEL);
958 941
@@ -1096,22 +1079,14 @@ static int ath6kl_upload_board_file(struct ath6kl *ar)
1096 */ 1079 */
1097 if (ar->hw.board_addr != 0) { 1080 if (ar->hw.board_addr != 0) {
1098 board_address = ar->hw.board_addr; 1081 board_address = ar->hw.board_addr;
1099 ath6kl_bmi_write(ar, 1082 ath6kl_bmi_write_hi32(ar, hi_board_data,
1100 ath6kl_get_hi_item_addr(ar, 1083 board_address);
1101 HI_ITEM(hi_board_data)),
1102 (u8 *) &board_address, 4);
1103 } else { 1084 } else {
1104 ath6kl_bmi_read(ar, 1085 ath6kl_bmi_read_hi32(ar, hi_board_data, &board_address);
1105 ath6kl_get_hi_item_addr(ar,
1106 HI_ITEM(hi_board_data)),
1107 (u8 *) &board_address, 4);
1108 } 1086 }
1109 1087
1110 /* determine where in target ram to write extended board data */ 1088 /* determine where in target ram to write extended board data */
1111 ath6kl_bmi_read(ar, 1089 ath6kl_bmi_read_hi32(ar, hi_board_ext_data, &board_ext_address);
1112 ath6kl_get_hi_item_addr(ar,
1113 HI_ITEM(hi_board_ext_data)),
1114 (u8 *) &board_ext_address, 4);
1115 1090
1116 if (ar->target_type == TARGET_TYPE_AR6003 && 1091 if (ar->target_type == TARGET_TYPE_AR6003 &&
1117 board_ext_address == 0) { 1092 board_ext_address == 0) {
@@ -1123,6 +1098,8 @@ static int ath6kl_upload_board_file(struct ath6kl *ar)
1123 case TARGET_TYPE_AR6003: 1098 case TARGET_TYPE_AR6003:
1124 board_data_size = AR6003_BOARD_DATA_SZ; 1099 board_data_size = AR6003_BOARD_DATA_SZ;
1125 board_ext_data_size = AR6003_BOARD_EXT_DATA_SZ; 1100 board_ext_data_size = AR6003_BOARD_EXT_DATA_SZ;
1101 if (ar->fw_board_len > (board_data_size + board_ext_data_size))
1102 board_ext_data_size = AR6003_BOARD_EXT_DATA_SZ_V2;
1126 break; 1103 break;
1127 case TARGET_TYPE_AR6004: 1104 case TARGET_TYPE_AR6004:
1128 board_data_size = AR6004_BOARD_DATA_SZ; 1105 board_data_size = AR6004_BOARD_DATA_SZ;
@@ -1154,10 +1131,7 @@ static int ath6kl_upload_board_file(struct ath6kl *ar)
1154 /* record that extended board data is initialized */ 1131 /* record that extended board data is initialized */
1155 param = (board_ext_data_size << 16) | 1; 1132 param = (board_ext_data_size << 16) | 1;
1156 1133
1157 ath6kl_bmi_write(ar, 1134 ath6kl_bmi_write_hi32(ar, hi_board_ext_data_config, param);
1158 ath6kl_get_hi_item_addr(ar,
1159 HI_ITEM(hi_board_ext_data_config)),
1160 (unsigned char *) &param, 4);
1161 } 1135 }
1162 1136
1163 if (ar->fw_board_len < board_data_size) { 1137 if (ar->fw_board_len < board_data_size) {
@@ -1178,11 +1152,7 @@ static int ath6kl_upload_board_file(struct ath6kl *ar)
1178 } 1152 }
1179 1153
1180 /* record the fact that Board Data IS initialized */ 1154 /* record the fact that Board Data IS initialized */
1181 param = 1; 1155 ath6kl_bmi_write_hi32(ar, hi_board_data_initialized, 1);
1182 ath6kl_bmi_write(ar,
1183 ath6kl_get_hi_item_addr(ar,
1184 HI_ITEM(hi_board_data_initialized)),
1185 (u8 *)&param, 4);
1186 1156
1187 return ret; 1157 return ret;
1188} 1158}
@@ -1209,10 +1179,7 @@ static int ath6kl_upload_otp(struct ath6kl *ar)
1209 } 1179 }
1210 1180
1211 /* read firmware start address */ 1181 /* read firmware start address */
1212 ret = ath6kl_bmi_read(ar, 1182 ret = ath6kl_bmi_read_hi32(ar, hi_app_start, &address);
1213 ath6kl_get_hi_item_addr(ar,
1214 HI_ITEM(hi_app_start)),
1215 (u8 *) &address, sizeof(address));
1216 1183
1217 if (ret) { 1184 if (ret) {
1218 ath6kl_err("Failed to read hi_app_start: %d\n", ret); 1185 ath6kl_err("Failed to read hi_app_start: %d\n", ret);
@@ -1270,7 +1237,7 @@ static int ath6kl_upload_firmware(struct ath6kl *ar)
1270 1237
1271static int ath6kl_upload_patch(struct ath6kl *ar) 1238static int ath6kl_upload_patch(struct ath6kl *ar)
1272{ 1239{
1273 u32 address, param; 1240 u32 address;
1274 int ret; 1241 int ret;
1275 1242
1276 if (ar->fw_patch == NULL) 1243 if (ar->fw_patch == NULL)
@@ -1287,18 +1254,14 @@ static int ath6kl_upload_patch(struct ath6kl *ar)
1287 return ret; 1254 return ret;
1288 } 1255 }
1289 1256
1290 param = address; 1257 ath6kl_bmi_write_hi32(ar, hi_dset_list_head, address);
1291 ath6kl_bmi_write(ar,
1292 ath6kl_get_hi_item_addr(ar,
1293 HI_ITEM(hi_dset_list_head)),
1294 (unsigned char *) &param, 4);
1295 1258
1296 return 0; 1259 return 0;
1297} 1260}
1298 1261
1299static int ath6kl_upload_testscript(struct ath6kl *ar) 1262static int ath6kl_upload_testscript(struct ath6kl *ar)
1300{ 1263{
1301 u32 address, param; 1264 u32 address;
1302 int ret; 1265 int ret;
1303 1266
1304 if (ar->testmode != 2) 1267 if (ar->testmode != 2)
@@ -1310,7 +1273,7 @@ static int ath6kl_upload_testscript(struct ath6kl *ar)
1310 address = ar->hw.testscript_addr; 1273 address = ar->hw.testscript_addr;
1311 1274
1312 ath6kl_dbg(ATH6KL_DBG_BOOT, "writing testscript to 0x%x (%zd B)\n", 1275 ath6kl_dbg(ATH6KL_DBG_BOOT, "writing testscript to 0x%x (%zd B)\n",
1313 address, ar->fw_testscript_len); 1276 address, ar->fw_testscript_len);
1314 1277
1315 ret = ath6kl_bmi_write(ar, address, ar->fw_testscript, 1278 ret = ath6kl_bmi_write(ar, address, ar->fw_testscript,
1316 ar->fw_testscript_len); 1279 ar->fw_testscript_len);
@@ -1319,23 +1282,9 @@ static int ath6kl_upload_testscript(struct ath6kl *ar)
1319 return ret; 1282 return ret;
1320 } 1283 }
1321 1284
1322 param = address; 1285 ath6kl_bmi_write_hi32(ar, hi_ota_testscript, address);
1323 ath6kl_bmi_write(ar, 1286 ath6kl_bmi_write_hi32(ar, hi_end_ram_reserve_sz, 4096);
1324 ath6kl_get_hi_item_addr(ar, 1287 ath6kl_bmi_write_hi32(ar, hi_test_apps_related, 1);
1325 HI_ITEM(hi_ota_testscript)),
1326 (unsigned char *) &param, 4);
1327
1328 param = 4096;
1329 ath6kl_bmi_write(ar,
1330 ath6kl_get_hi_item_addr(ar,
1331 HI_ITEM(hi_end_ram_reserve_sz)),
1332 (unsigned char *) &param, 4);
1333
1334 param = 1;
1335 ath6kl_bmi_write(ar,
1336 ath6kl_get_hi_item_addr(ar,
1337 HI_ITEM(hi_test_apps_related)),
1338 (unsigned char *) &param, 4);
1339 1288
1340 return 0; 1289 return 0;
1341} 1290}
@@ -1346,7 +1295,7 @@ static int ath6kl_init_upload(struct ath6kl *ar)
1346 int status = 0; 1295 int status = 0;
1347 1296
1348 if (ar->target_type != TARGET_TYPE_AR6003 && 1297 if (ar->target_type != TARGET_TYPE_AR6003 &&
1349 ar->target_type != TARGET_TYPE_AR6004) 1298 ar->target_type != TARGET_TYPE_AR6004)
1350 return -EINVAL; 1299 return -EINVAL;
1351 1300
1352 /* temporarily disable system sleep */ 1301 /* temporarily disable system sleep */
@@ -1403,7 +1352,8 @@ static int ath6kl_init_upload(struct ath6kl *ar)
1403 return status; 1352 return status;
1404 1353
1405 /* WAR to avoid SDIO CRC err */ 1354 /* WAR to avoid SDIO CRC err */
1406 if (ar->version.target_ver == AR6003_HW_2_0_VERSION) { 1355 if (ar->version.target_ver == AR6003_HW_2_0_VERSION ||
1356 ar->version.target_ver == AR6003_HW_2_1_1_VERSION) {
1407 ath6kl_err("temporary war to avoid sdio crc error\n"); 1357 ath6kl_err("temporary war to avoid sdio crc error\n");
1408 1358
1409 param = 0x20; 1359 param = 0x20;
@@ -1726,9 +1676,11 @@ void ath6kl_stop_txrx(struct ath6kl *ar)
1726 * configure NOT to reset the target during a debug session. 1676 * configure NOT to reset the target during a debug session.
1727 */ 1677 */
1728 ath6kl_dbg(ATH6KL_DBG_TRC, 1678 ath6kl_dbg(ATH6KL_DBG_TRC,
1729 "attempting to reset target on instance destroy\n"); 1679 "attempting to reset target on instance destroy\n");
1730 ath6kl_reset_device(ar, ar->target_type, true, true); 1680 ath6kl_reset_device(ar, ar->target_type, true, true);
1731 1681
1732 clear_bit(WLAN_ENABLED, &ar->flag); 1682 clear_bit(WLAN_ENABLED, &ar->flag);
1683
1684 up(&ar->sem);
1733} 1685}
1734EXPORT_SYMBOL(ath6kl_stop_txrx); 1686EXPORT_SYMBOL(ath6kl_stop_txrx);
diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c
index b96d01a7919b..229e1922ebe4 100644
--- a/drivers/net/wireless/ath/ath6kl/main.c
+++ b/drivers/net/wireless/ath/ath6kl/main.c
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (c) 2004-2011 Atheros Communications Inc. 2 * Copyright (c) 2004-2011 Atheros Communications Inc.
3 * Copyright (c) 2011-2012 Qualcomm Atheros, Inc.
3 * 4 *
4 * Permission to use, copy, modify, and/or distribute this software for any 5 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above 6 * purpose with or without fee is hereby granted, provided that the above
@@ -80,11 +81,21 @@ static void ath6kl_add_new_sta(struct ath6kl_vif *vif, u8 *mac, u16 aid,
80static void ath6kl_sta_cleanup(struct ath6kl *ar, u8 i) 81static void ath6kl_sta_cleanup(struct ath6kl *ar, u8 i)
81{ 82{
82 struct ath6kl_sta *sta = &ar->sta_list[i]; 83 struct ath6kl_sta *sta = &ar->sta_list[i];
84 struct ath6kl_mgmt_buff *entry, *tmp;
83 85
84 /* empty the queued pkts in the PS queue if any */ 86 /* empty the queued pkts in the PS queue if any */
85 spin_lock_bh(&sta->psq_lock); 87 spin_lock_bh(&sta->psq_lock);
86 skb_queue_purge(&sta->psq); 88 skb_queue_purge(&sta->psq);
87 skb_queue_purge(&sta->apsdq); 89 skb_queue_purge(&sta->apsdq);
90
91 if (sta->mgmt_psq_len != 0) {
92 list_for_each_entry_safe(entry, tmp, &sta->mgmt_psq, list) {
93 kfree(entry);
94 }
95 INIT_LIST_HEAD(&sta->mgmt_psq);
96 sta->mgmt_psq_len = 0;
97 }
98
88 spin_unlock_bh(&sta->psq_lock); 99 spin_unlock_bh(&sta->psq_lock);
89 100
90 memset(&ar->ap_stats.sta[sta->aid - 1], 0, 101 memset(&ar->ap_stats.sta[sta->aid - 1], 0,
@@ -339,7 +350,7 @@ void ath6kl_reset_device(struct ath6kl *ar, u32 target_type,
339 __le32 data; 350 __le32 data;
340 351
341 if (target_type != TARGET_TYPE_AR6003 && 352 if (target_type != TARGET_TYPE_AR6003 &&
342 target_type != TARGET_TYPE_AR6004) 353 target_type != TARGET_TYPE_AR6004)
343 return; 354 return;
344 355
345 data = cold_reset ? cpu_to_le32(RESET_CONTROL_COLD_RST) : 356 data = cold_reset ? cpu_to_le32(RESET_CONTROL_COLD_RST) :
@@ -588,11 +599,9 @@ void ath6kl_connect_event(struct ath6kl_vif *vif, u16 channel, u8 *bssid,
588 memcpy(vif->bssid, bssid, sizeof(vif->bssid)); 599 memcpy(vif->bssid, bssid, sizeof(vif->bssid));
589 vif->bss_ch = channel; 600 vif->bss_ch = channel;
590 601
591 if ((vif->nw_type == INFRA_NETWORK)) { 602 if ((vif->nw_type == INFRA_NETWORK))
592 ar->listen_intvl_b = listen_int;
593 ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx, 603 ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx,
594 0, ar->listen_intvl_b); 604 vif->listen_intvl_t, 0);
595 }
596 605
597 netif_wake_queue(vif->ndev); 606 netif_wake_queue(vif->ndev);
598 607
@@ -810,6 +819,7 @@ void ath6kl_pspoll_event(struct ath6kl_vif *vif, u8 aid)
810 struct sk_buff *skb; 819 struct sk_buff *skb;
811 bool psq_empty = false; 820 bool psq_empty = false;
812 struct ath6kl *ar = vif->ar; 821 struct ath6kl *ar = vif->ar;
822 struct ath6kl_mgmt_buff *mgmt_buf;
813 823
814 conn = ath6kl_find_sta_by_aid(ar, aid); 824 conn = ath6kl_find_sta_by_aid(ar, aid);
815 825
@@ -820,7 +830,7 @@ void ath6kl_pspoll_event(struct ath6kl_vif *vif, u8 aid)
820 * becomes empty update the PVB for this station. 830 * becomes empty update the PVB for this station.
821 */ 831 */
822 spin_lock_bh(&conn->psq_lock); 832 spin_lock_bh(&conn->psq_lock);
823 psq_empty = skb_queue_empty(&conn->psq); 833 psq_empty = skb_queue_empty(&conn->psq) && (conn->mgmt_psq_len == 0);
824 spin_unlock_bh(&conn->psq_lock); 834 spin_unlock_bh(&conn->psq_lock);
825 835
826 if (psq_empty) 836 if (psq_empty)
@@ -828,15 +838,31 @@ void ath6kl_pspoll_event(struct ath6kl_vif *vif, u8 aid)
828 return; 838 return;
829 839
830 spin_lock_bh(&conn->psq_lock); 840 spin_lock_bh(&conn->psq_lock);
831 skb = skb_dequeue(&conn->psq); 841 if (conn->mgmt_psq_len > 0) {
832 spin_unlock_bh(&conn->psq_lock); 842 mgmt_buf = list_first_entry(&conn->mgmt_psq,
843 struct ath6kl_mgmt_buff, list);
844 list_del(&mgmt_buf->list);
845 conn->mgmt_psq_len--;
846 spin_unlock_bh(&conn->psq_lock);
847
848 conn->sta_flags |= STA_PS_POLLED;
849 ath6kl_wmi_send_mgmt_cmd(ar->wmi, vif->fw_vif_idx,
850 mgmt_buf->id, mgmt_buf->freq,
851 mgmt_buf->wait, mgmt_buf->buf,
852 mgmt_buf->len, mgmt_buf->no_cck);
853 conn->sta_flags &= ~STA_PS_POLLED;
854 kfree(mgmt_buf);
855 } else {
856 skb = skb_dequeue(&conn->psq);
857 spin_unlock_bh(&conn->psq_lock);
833 858
834 conn->sta_flags |= STA_PS_POLLED; 859 conn->sta_flags |= STA_PS_POLLED;
835 ath6kl_data_tx(skb, vif->ndev); 860 ath6kl_data_tx(skb, vif->ndev);
836 conn->sta_flags &= ~STA_PS_POLLED; 861 conn->sta_flags &= ~STA_PS_POLLED;
862 }
837 863
838 spin_lock_bh(&conn->psq_lock); 864 spin_lock_bh(&conn->psq_lock);
839 psq_empty = skb_queue_empty(&conn->psq); 865 psq_empty = skb_queue_empty(&conn->psq) && (conn->mgmt_psq_len == 0);
840 spin_unlock_bh(&conn->psq_lock); 866 spin_unlock_bh(&conn->psq_lock);
841 867
842 if (psq_empty) 868 if (psq_empty)
@@ -922,8 +948,8 @@ void ath6kl_disconnect_event(struct ath6kl_vif *vif, u8 reason, u8 *bssid,
922 } 948 }
923 949
924 ath6kl_cfg80211_disconnect_event(vif, reason, bssid, 950 ath6kl_cfg80211_disconnect_event(vif, reason, bssid,
925 assoc_resp_len, assoc_info, 951 assoc_resp_len, assoc_info,
926 prot_reason_status); 952 prot_reason_status);
927 953
928 aggr_reset_state(vif->aggr_cntxt->aggr_conn); 954 aggr_reset_state(vif->aggr_cntxt->aggr_conn);
929 955
@@ -943,9 +969,9 @@ void ath6kl_disconnect_event(struct ath6kl_vif *vif, u8 reason, u8 *bssid,
943 } else { 969 } else {
944 set_bit(CONNECT_PEND, &vif->flags); 970 set_bit(CONNECT_PEND, &vif->flags);
945 if (((reason == ASSOC_FAILED) && 971 if (((reason == ASSOC_FAILED) &&
946 (prot_reason_status == 0x11)) || 972 (prot_reason_status == 0x11)) ||
947 ((reason == ASSOC_FAILED) && (prot_reason_status == 0x0) 973 ((reason == ASSOC_FAILED) && (prot_reason_status == 0x0) &&
948 && (vif->reconnect_flag == 1))) { 974 (vif->reconnect_flag == 1))) {
949 set_bit(CONNECTED, &vif->flags); 975 set_bit(CONNECTED, &vif->flags);
950 return; 976 return;
951 } 977 }
@@ -1079,7 +1105,7 @@ static void ath6kl_set_multicast_list(struct net_device *ndev)
1079 if (mc_all_on || mc_all_off) { 1105 if (mc_all_on || mc_all_off) {
1080 /* Enable/disable all multicast */ 1106 /* Enable/disable all multicast */
1081 ath6kl_dbg(ATH6KL_DBG_TRC, "%s multicast filter\n", 1107 ath6kl_dbg(ATH6KL_DBG_TRC, "%s multicast filter\n",
1082 mc_all_on ? "enabling" : "disabling"); 1108 mc_all_on ? "enabling" : "disabling");
1083 ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi, vif->fw_vif_idx, 1109 ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi, vif->fw_vif_idx,
1084 mc_all_on); 1110 mc_all_on);
1085 if (ret) 1111 if (ret)
@@ -1092,7 +1118,7 @@ static void ath6kl_set_multicast_list(struct net_device *ndev)
1092 found = false; 1118 found = false;
1093 netdev_for_each_mc_addr(ha, ndev) { 1119 netdev_for_each_mc_addr(ha, ndev) {
1094 if (memcmp(ha->addr, mc_filter->hw_addr, 1120 if (memcmp(ha->addr, mc_filter->hw_addr,
1095 ATH6KL_MCAST_FILTER_MAC_ADDR_SIZE) == 0) { 1121 ATH6KL_MCAST_FILTER_MAC_ADDR_SIZE) == 0) {
1096 found = true; 1122 found = true;
1097 break; 1123 break;
1098 } 1124 }
@@ -1111,7 +1137,7 @@ static void ath6kl_set_multicast_list(struct net_device *ndev)
1111 false); 1137 false);
1112 if (ret) { 1138 if (ret) {
1113 ath6kl_warn("Failed to remove multicast filter:%pM\n", 1139 ath6kl_warn("Failed to remove multicast filter:%pM\n",
1114 mc_filter->hw_addr); 1140 mc_filter->hw_addr);
1115 return; 1141 return;
1116 } 1142 }
1117 1143
@@ -1126,7 +1152,7 @@ static void ath6kl_set_multicast_list(struct net_device *ndev)
1126 found = false; 1152 found = false;
1127 list_for_each_entry(mc_filter, &vif->mc_filter, list) { 1153 list_for_each_entry(mc_filter, &vif->mc_filter, list) {
1128 if (memcmp(ha->addr, mc_filter->hw_addr, 1154 if (memcmp(ha->addr, mc_filter->hw_addr,
1129 ATH6KL_MCAST_FILTER_MAC_ADDR_SIZE) == 0) { 1155 ATH6KL_MCAST_FILTER_MAC_ADDR_SIZE) == 0) {
1130 found = true; 1156 found = true;
1131 break; 1157 break;
1132 } 1158 }
@@ -1151,7 +1177,7 @@ static void ath6kl_set_multicast_list(struct net_device *ndev)
1151 true); 1177 true);
1152 if (ret) { 1178 if (ret) {
1153 ath6kl_warn("Failed to add multicast filter :%pM\n", 1179 ath6kl_warn("Failed to add multicast filter :%pM\n",
1154 mc_filter->hw_addr); 1180 mc_filter->hw_addr);
1155 kfree(mc_filter); 1181 kfree(mc_filter);
1156 goto out; 1182 goto out;
1157 } 1183 }
@@ -1184,5 +1210,7 @@ void init_netdev(struct net_device *dev)
1184 sizeof(struct wmi_data_hdr) + HTC_HDR_LENGTH 1210 sizeof(struct wmi_data_hdr) + HTC_HDR_LENGTH
1185 + WMI_MAX_TX_META_SZ + ATH6KL_HTC_ALIGN_BYTES; 1211 + WMI_MAX_TX_META_SZ + ATH6KL_HTC_ALIGN_BYTES;
1186 1212
1213 dev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_RXCSUM;
1214
1187 return; 1215 return;
1188} 1216}
diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c
index 4febee723495..53528648b425 100644
--- a/drivers/net/wireless/ath/ath6kl/sdio.c
+++ b/drivers/net/wireless/ath/ath6kl/sdio.c
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (c) 2004-2011 Atheros Communications Inc. 2 * Copyright (c) 2004-2011 Atheros Communications Inc.
3 * Copyright (c) 2011-2012 Qualcomm Atheros, Inc.
3 * 4 *
4 * Permission to use, copy, modify, and/or distribute this software for any 5 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above 6 * purpose with or without fee is hereby granted, provided that the above
@@ -31,6 +32,7 @@
31struct ath6kl_sdio { 32struct ath6kl_sdio {
32 struct sdio_func *func; 33 struct sdio_func *func;
33 34
35 /* protects access to bus_req_freeq */
34 spinlock_t lock; 36 spinlock_t lock;
35 37
36 /* free list */ 38 /* free list */
@@ -49,16 +51,20 @@ struct ath6kl_sdio {
49 /* scatter request list head */ 51 /* scatter request list head */
50 struct list_head scat_req; 52 struct list_head scat_req;
51 53
52 /* Avoids disabling irq while the interrupts being handled */ 54 atomic_t irq_handling;
53 struct mutex mtx_irq; 55 wait_queue_head_t irq_wq;
54 56
57 /* protects access to scat_req */
55 spinlock_t scat_lock; 58 spinlock_t scat_lock;
59
56 bool scatter_enabled; 60 bool scatter_enabled;
57 61
58 bool is_disabled; 62 bool is_disabled;
59 const struct sdio_device_id *id; 63 const struct sdio_device_id *id;
60 struct work_struct wr_async_work; 64 struct work_struct wr_async_work;
61 struct list_head wr_asyncq; 65 struct list_head wr_asyncq;
66
67 /* protects access to wr_asyncq */
62 spinlock_t wr_async_lock; 68 spinlock_t wr_async_lock;
63}; 69};
64 70
@@ -404,7 +410,10 @@ static int ath6kl_sdio_read_write_sync(struct ath6kl *ar, u32 addr, u8 *buf,
404 return -ENOMEM; 410 return -ENOMEM;
405 mutex_lock(&ar_sdio->dma_buffer_mutex); 411 mutex_lock(&ar_sdio->dma_buffer_mutex);
406 tbuf = ar_sdio->dma_buffer; 412 tbuf = ar_sdio->dma_buffer;
407 memcpy(tbuf, buf, len); 413
414 if (request & HIF_WRITE)
415 memcpy(tbuf, buf, len);
416
408 bounced = true; 417 bounced = true;
409 } else 418 } else
410 tbuf = buf; 419 tbuf = buf;
@@ -462,7 +471,7 @@ static void ath6kl_sdio_irq_handler(struct sdio_func *func)
462 ath6kl_dbg(ATH6KL_DBG_SDIO, "irq\n"); 471 ath6kl_dbg(ATH6KL_DBG_SDIO, "irq\n");
463 472
464 ar_sdio = sdio_get_drvdata(func); 473 ar_sdio = sdio_get_drvdata(func);
465 mutex_lock(&ar_sdio->mtx_irq); 474 atomic_set(&ar_sdio->irq_handling, 1);
466 /* 475 /*
467 * Release the host during interrups so we can pick it back up when 476 * Release the host during interrups so we can pick it back up when
468 * we process commands. 477 * we process commands.
@@ -471,7 +480,10 @@ static void ath6kl_sdio_irq_handler(struct sdio_func *func)
471 480
472 status = ath6kl_hif_intr_bh_handler(ar_sdio->ar); 481 status = ath6kl_hif_intr_bh_handler(ar_sdio->ar);
473 sdio_claim_host(ar_sdio->func); 482 sdio_claim_host(ar_sdio->func);
474 mutex_unlock(&ar_sdio->mtx_irq); 483
484 atomic_set(&ar_sdio->irq_handling, 0);
485 wake_up(&ar_sdio->irq_wq);
486
475 WARN_ON(status && status != -ECANCELED); 487 WARN_ON(status && status != -ECANCELED);
476} 488}
477 489
@@ -572,6 +584,13 @@ static void ath6kl_sdio_irq_enable(struct ath6kl *ar)
572 sdio_release_host(ar_sdio->func); 584 sdio_release_host(ar_sdio->func);
573} 585}
574 586
587static bool ath6kl_sdio_is_on_irq(struct ath6kl *ar)
588{
589 struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar);
590
591 return !atomic_read(&ar_sdio->irq_handling);
592}
593
575static void ath6kl_sdio_irq_disable(struct ath6kl *ar) 594static void ath6kl_sdio_irq_disable(struct ath6kl *ar)
576{ 595{
577 struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar); 596 struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar);
@@ -579,14 +598,21 @@ static void ath6kl_sdio_irq_disable(struct ath6kl *ar)
579 598
580 sdio_claim_host(ar_sdio->func); 599 sdio_claim_host(ar_sdio->func);
581 600
582 mutex_lock(&ar_sdio->mtx_irq); 601 if (atomic_read(&ar_sdio->irq_handling)) {
602 sdio_release_host(ar_sdio->func);
603
604 ret = wait_event_interruptible(ar_sdio->irq_wq,
605 ath6kl_sdio_is_on_irq(ar));
606 if (ret)
607 return;
608
609 sdio_claim_host(ar_sdio->func);
610 }
583 611
584 ret = sdio_release_irq(ar_sdio->func); 612 ret = sdio_release_irq(ar_sdio->func);
585 if (ret) 613 if (ret)
586 ath6kl_err("Failed to release sdio irq: %d\n", ret); 614 ath6kl_err("Failed to release sdio irq: %d\n", ret);
587 615
588 mutex_unlock(&ar_sdio->mtx_irq);
589
590 sdio_release_host(ar_sdio->func); 616 sdio_release_host(ar_sdio->func);
591} 617}
592 618
@@ -601,6 +627,8 @@ static struct hif_scatter_req *ath6kl_sdio_scatter_req_get(struct ath6kl *ar)
601 node = list_first_entry(&ar_sdio->scat_req, 627 node = list_first_entry(&ar_sdio->scat_req,
602 struct hif_scatter_req, list); 628 struct hif_scatter_req, list);
603 list_del(&node->list); 629 list_del(&node->list);
630
631 node->scat_q_depth = get_queue_depth(&ar_sdio->scat_req);
604 } 632 }
605 633
606 spin_unlock_bh(&ar_sdio->scat_lock); 634 spin_unlock_bh(&ar_sdio->scat_lock);
@@ -633,8 +661,8 @@ static int ath6kl_sdio_async_rw_scatter(struct ath6kl *ar,
633 return -EINVAL; 661 return -EINVAL;
634 662
635 ath6kl_dbg(ATH6KL_DBG_SCATTER, 663 ath6kl_dbg(ATH6KL_DBG_SCATTER,
636 "hif-scatter: total len: %d scatter entries: %d\n", 664 "hif-scatter: total len: %d scatter entries: %d\n",
637 scat_req->len, scat_req->scat_entries); 665 scat_req->len, scat_req->scat_entries);
638 666
639 if (request & HIF_SYNCHRONOUS) 667 if (request & HIF_SYNCHRONOUS)
640 status = ath6kl_sdio_scat_rw(ar_sdio, scat_req->busrequest); 668 status = ath6kl_sdio_scat_rw(ar_sdio, scat_req->busrequest);
@@ -813,6 +841,7 @@ static int ath6kl_sdio_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
813 struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar); 841 struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar);
814 struct sdio_func *func = ar_sdio->func; 842 struct sdio_func *func = ar_sdio->func;
815 mmc_pm_flag_t flags; 843 mmc_pm_flag_t flags;
844 bool try_deepsleep = false;
816 int ret; 845 int ret;
817 846
818 if (ar->state == ATH6KL_STATE_SCHED_SCAN) { 847 if (ar->state == ATH6KL_STATE_SCHED_SCAN) {
@@ -839,14 +868,22 @@ static int ath6kl_sdio_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
839 goto cut_pwr; 868 goto cut_pwr;
840 869
841 ret = ath6kl_cfg80211_suspend(ar, ATH6KL_CFG_SUSPEND_WOW, wow); 870 ret = ath6kl_cfg80211_suspend(ar, ATH6KL_CFG_SUSPEND_WOW, wow);
842 if (ret) 871 if (ret && ret != -ENOTCONN)
872 ath6kl_err("wow suspend failed: %d\n", ret);
873
874 if (ret &&
875 (!ar->wow_suspend_mode ||
876 ar->wow_suspend_mode == WLAN_POWER_STATE_DEEP_SLEEP))
877 try_deepsleep = true;
878 else if (ret &&
879 ar->wow_suspend_mode == WLAN_POWER_STATE_CUT_PWR)
843 goto cut_pwr; 880 goto cut_pwr;
844 881 if (!ret)
845 return 0; 882 return 0;
846 } 883 }
847 884
848 if (ar->suspend_mode == WLAN_POWER_STATE_DEEP_SLEEP || 885 if (ar->suspend_mode == WLAN_POWER_STATE_DEEP_SLEEP ||
849 !ar->suspend_mode) { 886 !ar->suspend_mode || try_deepsleep) {
850 887
851 flags = sdio_get_host_pm_caps(func); 888 flags = sdio_get_host_pm_caps(func);
852 if (!(flags & MMC_PM_KEEP_POWER)) 889 if (!(flags & MMC_PM_KEEP_POWER))
@@ -901,8 +938,15 @@ static int ath6kl_sdio_resume(struct ath6kl *ar)
901 938
902 case ATH6KL_STATE_WOW: 939 case ATH6KL_STATE_WOW:
903 break; 940 break;
941
904 case ATH6KL_STATE_SCHED_SCAN: 942 case ATH6KL_STATE_SCHED_SCAN:
905 break; 943 break;
944
945 case ATH6KL_STATE_SUSPENDING:
946 break;
947
948 case ATH6KL_STATE_RESUMING:
949 break;
906 } 950 }
907 951
908 ath6kl_cfg80211_resume(ar); 952 ath6kl_cfg80211_resume(ar);
@@ -981,7 +1025,7 @@ static int ath6kl_sdio_diag_read32(struct ath6kl *ar, u32 address, u32 *data)
981 (u8 *)data, sizeof(u32), HIF_RD_SYNC_BYTE_INC); 1025 (u8 *)data, sizeof(u32), HIF_RD_SYNC_BYTE_INC);
982 if (status) { 1026 if (status) {
983 ath6kl_err("%s: failed to read from window data addr\n", 1027 ath6kl_err("%s: failed to read from window data addr\n",
984 __func__); 1028 __func__);
985 return status; 1029 return status;
986 } 1030 }
987 1031
@@ -1285,7 +1329,6 @@ static int ath6kl_sdio_probe(struct sdio_func *func,
1285 spin_lock_init(&ar_sdio->scat_lock); 1329 spin_lock_init(&ar_sdio->scat_lock);
1286 spin_lock_init(&ar_sdio->wr_async_lock); 1330 spin_lock_init(&ar_sdio->wr_async_lock);
1287 mutex_init(&ar_sdio->dma_buffer_mutex); 1331 mutex_init(&ar_sdio->dma_buffer_mutex);
1288 mutex_init(&ar_sdio->mtx_irq);
1289 1332
1290 INIT_LIST_HEAD(&ar_sdio->scat_req); 1333 INIT_LIST_HEAD(&ar_sdio->scat_req);
1291 INIT_LIST_HEAD(&ar_sdio->bus_req_freeq); 1334 INIT_LIST_HEAD(&ar_sdio->bus_req_freeq);
@@ -1293,6 +1336,8 @@ static int ath6kl_sdio_probe(struct sdio_func *func,
1293 1336
1294 INIT_WORK(&ar_sdio->wr_async_work, ath6kl_sdio_write_async_work); 1337 INIT_WORK(&ar_sdio->wr_async_work, ath6kl_sdio_write_async_work);
1295 1338
1339 init_waitqueue_head(&ar_sdio->irq_wq);
1340
1296 for (count = 0; count < BUS_REQUEST_MAX_NUM; count++) 1341 for (count = 0; count < BUS_REQUEST_MAX_NUM; count++)
1297 ath6kl_sdio_free_bus_req(ar_sdio, &ar_sdio->bus_req[count]); 1342 ath6kl_sdio_free_bus_req(ar_sdio, &ar_sdio->bus_req[count]);
1298 1343
diff --git a/drivers/net/wireless/ath/ath6kl/target.h b/drivers/net/wireless/ath/ath6kl/target.h
index 108a723a1085..78e0ef4567a5 100644
--- a/drivers/net/wireless/ath/ath6kl/target.h
+++ b/drivers/net/wireless/ath/ath6kl/target.h
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (c) 2004-2010 Atheros Communications Inc. 2 * Copyright (c) 2004-2010 Atheros Communications Inc.
3 * Copyright (c) 2011 Qualcomm Atheros, Inc.
3 * 4 *
4 * Permission to use, copy, modify, and/or distribute this software for any 5 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above 6 * purpose with or without fee is hereby granted, provided that the above
@@ -19,6 +20,7 @@
19 20
20#define AR6003_BOARD_DATA_SZ 1024 21#define AR6003_BOARD_DATA_SZ 1024
21#define AR6003_BOARD_EXT_DATA_SZ 768 22#define AR6003_BOARD_EXT_DATA_SZ 768
23#define AR6003_BOARD_EXT_DATA_SZ_V2 1024
22 24
23#define AR6004_BOARD_DATA_SZ 6144 25#define AR6004_BOARD_DATA_SZ 6144
24#define AR6004_BOARD_EXT_DATA_SZ 0 26#define AR6004_BOARD_EXT_DATA_SZ 0
diff --git a/drivers/net/wireless/ath/ath6kl/testmode.c b/drivers/net/wireless/ath/ath6kl/testmode.c
index f0cd61d6188a..6675c92b542b 100644
--- a/drivers/net/wireless/ath/ath6kl/testmode.c
+++ b/drivers/net/wireless/ath/ath6kl/testmode.c
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (c) 2010-2011 Atheros Communications Inc. 2 * Copyright (c) 2010-2011 Atheros Communications Inc.
3 * Copyright (c) 2011 Qualcomm Atheros, Inc.
3 * 4 *
4 * Permission to use, copy, modify, and/or distribute this software for any 5 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above 6 * purpose with or without fee is hereby granted, provided that the above
diff --git a/drivers/net/wireless/ath/ath6kl/testmode.h b/drivers/net/wireless/ath/ath6kl/testmode.h
index 7fd47a62d078..fe651d6707df 100644
--- a/drivers/net/wireless/ath/ath6kl/testmode.h
+++ b/drivers/net/wireless/ath/ath6kl/testmode.h
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (c) 2010-2011 Atheros Communications Inc. 2 * Copyright (c) 2010-2011 Atheros Communications Inc.
3 * Copyright (c) 2011 Qualcomm Atheros, Inc.
3 * 4 *
4 * Permission to use, copy, modify, and/or distribute this software for any 5 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above 6 * purpose with or without fee is hereby granted, provided that the above
diff --git a/drivers/net/wireless/ath/ath6kl/txrx.c b/drivers/net/wireless/ath/ath6kl/txrx.c
index a3dc6943c7f7..f85353fd1792 100644
--- a/drivers/net/wireless/ath/ath6kl/txrx.c
+++ b/drivers/net/wireless/ath/ath6kl/txrx.c
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (c) 2004-2011 Atheros Communications Inc. 2 * Copyright (c) 2004-2011 Atheros Communications Inc.
3 * Copyright (c) 2011-2012 Qualcomm Atheros, Inc.
3 * 4 *
4 * Permission to use, copy, modify, and/or distribute this software for any 5 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above 6 * purpose with or without fee is hereby granted, provided that the above
@@ -158,8 +159,8 @@ static bool ath6kl_process_uapsdq(struct ath6kl_sta *conn,
158 */ 159 */
159 if (is_apsdq_empty) { 160 if (is_apsdq_empty) {
160 ath6kl_wmi_set_apsd_bfrd_traf(ar->wmi, 161 ath6kl_wmi_set_apsd_bfrd_traf(ar->wmi,
161 vif->fw_vif_idx, 162 vif->fw_vif_idx,
162 conn->aid, 1, 0); 163 conn->aid, 1, 0);
163 } 164 }
164 *flags |= WMI_DATA_HDR_FLAGS_UAPSD; 165 *flags |= WMI_DATA_HDR_FLAGS_UAPSD;
165 166
@@ -284,6 +285,9 @@ int ath6kl_control_tx(void *devt, struct sk_buff *skb,
284 int status = 0; 285 int status = 0;
285 struct ath6kl_cookie *cookie = NULL; 286 struct ath6kl_cookie *cookie = NULL;
286 287
288 if (WARN_ON_ONCE(ar->state == ATH6KL_STATE_WOW))
289 return -EACCES;
290
287 spin_lock_bh(&ar->lock); 291 spin_lock_bh(&ar->lock);
288 292
289 ath6kl_dbg(ATH6KL_DBG_WLAN_TX, 293 ath6kl_dbg(ATH6KL_DBG_WLAN_TX,
@@ -359,6 +363,11 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev)
359 return 0; 363 return 0;
360 } 364 }
361 365
366 if (WARN_ON_ONCE(ar->state != ATH6KL_STATE_ON)) {
367 dev_kfree_skb(skb);
368 return 0;
369 }
370
362 if (!test_bit(WMI_READY, &ar->flag)) 371 if (!test_bit(WMI_READY, &ar->flag))
363 goto fail_tx; 372 goto fail_tx;
364 373
@@ -370,7 +379,7 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev)
370 379
371 if (test_bit(WMI_ENABLED, &ar->flag)) { 380 if (test_bit(WMI_ENABLED, &ar->flag)) {
372 if ((dev->features & NETIF_F_IP_CSUM) && 381 if ((dev->features & NETIF_F_IP_CSUM) &&
373 (csum == CHECKSUM_PARTIAL)) { 382 (csum == CHECKSUM_PARTIAL)) {
374 csum_start = skb->csum_start - 383 csum_start = skb->csum_start -
375 (skb_network_header(skb) - skb->head) + 384 (skb_network_header(skb) - skb->head) +
376 sizeof(struct ath6kl_llc_snap_hdr); 385 sizeof(struct ath6kl_llc_snap_hdr);
@@ -394,7 +403,7 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev)
394 } 403 }
395 404
396 if ((dev->features & NETIF_F_IP_CSUM) && 405 if ((dev->features & NETIF_F_IP_CSUM) &&
397 (csum == CHECKSUM_PARTIAL)) { 406 (csum == CHECKSUM_PARTIAL)) {
398 meta_v2.csum_start = csum_start; 407 meta_v2.csum_start = csum_start;
399 meta_v2.csum_dest = csum_dest; 408 meta_v2.csum_dest = csum_dest;
400 409
@@ -419,7 +428,7 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev)
419 } 428 }
420 429
421 if ((vif->nw_type == ADHOC_NETWORK) && 430 if ((vif->nw_type == ADHOC_NETWORK) &&
422 ar->ibss_ps_enable && test_bit(CONNECTED, &vif->flags)) 431 ar->ibss_ps_enable && test_bit(CONNECTED, &vif->flags))
423 chk_adhoc_ps_mapping = true; 432 chk_adhoc_ps_mapping = true;
424 else { 433 else {
425 /* get the stream mapping */ 434 /* get the stream mapping */
@@ -593,7 +602,8 @@ enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target,
593 */ 602 */
594 if (ar->ac_stream_pri_map[ar->ep2ac_map[endpoint]] < 603 if (ar->ac_stream_pri_map[ar->ep2ac_map[endpoint]] <
595 ar->hiac_stream_active_pri && 604 ar->hiac_stream_active_pri &&
596 ar->cookie_count <= MAX_HI_COOKIE_NUM) 605 ar->cookie_count <=
606 target->endpoint[endpoint].tx_drop_packet_threshold)
597 /* 607 /*
598 * Give preference to the highest priority stream by 608 * Give preference to the highest priority stream by
599 * dropping the packets which overflowed. 609 * dropping the packets which overflowed.
@@ -876,7 +886,7 @@ void ath6kl_rx_refill(struct htc_target *target, enum htc_endpoint_id endpoint)
876 if (!IS_ALIGNED((unsigned long) skb->data, 4)) 886 if (!IS_ALIGNED((unsigned long) skb->data, 4))
877 skb->data = PTR_ALIGN(skb->data - 4, 4); 887 skb->data = PTR_ALIGN(skb->data - 4, 4);
878 set_htc_rxpkt_info(packet, skb, skb->data, 888 set_htc_rxpkt_info(packet, skb, skb->data,
879 ATH6KL_BUFFER_SIZE, endpoint); 889 ATH6KL_BUFFER_SIZE, endpoint);
880 list_add_tail(&packet->list, &queue); 890 list_add_tail(&packet->list, &queue);
881 } 891 }
882 892
@@ -1256,8 +1266,8 @@ static void ath6kl_uapsd_trigger_frame_rx(struct ath6kl_vif *vif,
1256 flags = 0; 1266 flags = 0;
1257 1267
1258 ath6kl_wmi_set_apsd_bfrd_traf(ar->wmi, 1268 ath6kl_wmi_set_apsd_bfrd_traf(ar->wmi,
1259 vif->fw_vif_idx, 1269 vif->fw_vif_idx,
1260 conn->aid, 0, flags); 1270 conn->aid, 0, flags);
1261 } 1271 }
1262 1272
1263 return; 1273 return;
@@ -1296,7 +1306,15 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet)
1296 skb_put(skb, packet->act_len + HTC_HDR_LENGTH); 1306 skb_put(skb, packet->act_len + HTC_HDR_LENGTH);
1297 skb_pull(skb, HTC_HDR_LENGTH); 1307 skb_pull(skb, HTC_HDR_LENGTH);
1298 1308
1309 ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, __func__, "rx ",
1310 skb->data, skb->len);
1311
1299 if (ept == ar->ctrl_ep) { 1312 if (ept == ar->ctrl_ep) {
1313 if (test_bit(WMI_ENABLED, &ar->flag)) {
1314 ath6kl_check_wow_status(ar);
1315 ath6kl_wmi_control_rx(ar->wmi, skb);
1316 return;
1317 }
1300 if_idx = 1318 if_idx =
1301 wmi_cmd_hdr_get_if_idx((struct wmi_cmd_hdr *) skb->data); 1319 wmi_cmd_hdr_get_if_idx((struct wmi_cmd_hdr *) skb->data);
1302 } else { 1320 } else {
@@ -1321,10 +1339,6 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet)
1321 1339
1322 spin_unlock_bh(&vif->if_lock); 1340 spin_unlock_bh(&vif->if_lock);
1323 1341
1324
1325 ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, __func__, "rx ",
1326 skb->data, skb->len);
1327
1328 skb->dev = vif->ndev; 1342 skb->dev = vif->ndev;
1329 1343
1330 if (!test_bit(WMI_ENABLED, &ar->flag)) { 1344 if (!test_bit(WMI_ENABLED, &ar->flag)) {
@@ -1336,11 +1350,6 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet)
1336 1350
1337 ath6kl_check_wow_status(ar); 1351 ath6kl_check_wow_status(ar);
1338 1352
1339 if (ept == ar->ctrl_ep) {
1340 ath6kl_wmi_control_rx(ar->wmi, skb);
1341 return;
1342 }
1343
1344 min_hdr_len = sizeof(struct ethhdr) + sizeof(struct wmi_data_hdr) + 1353 min_hdr_len = sizeof(struct ethhdr) + sizeof(struct wmi_data_hdr) +
1345 sizeof(struct ath6kl_llc_snap_hdr); 1354 sizeof(struct ath6kl_llc_snap_hdr);
1346 1355
@@ -1416,8 +1425,33 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet)
1416 if (!(conn->sta_flags & STA_PS_SLEEP)) { 1425 if (!(conn->sta_flags & STA_PS_SLEEP)) {
1417 struct sk_buff *skbuff = NULL; 1426 struct sk_buff *skbuff = NULL;
1418 bool is_apsdq_empty; 1427 bool is_apsdq_empty;
1428 struct ath6kl_mgmt_buff *mgmt;
1429 u8 idx;
1419 1430
1420 spin_lock_bh(&conn->psq_lock); 1431 spin_lock_bh(&conn->psq_lock);
1432 while (conn->mgmt_psq_len > 0) {
1433 mgmt = list_first_entry(
1434 &conn->mgmt_psq,
1435 struct ath6kl_mgmt_buff,
1436 list);
1437 list_del(&mgmt->list);
1438 conn->mgmt_psq_len--;
1439 spin_unlock_bh(&conn->psq_lock);
1440 idx = vif->fw_vif_idx;
1441
1442 ath6kl_wmi_send_mgmt_cmd(ar->wmi,
1443 idx,
1444 mgmt->id,
1445 mgmt->freq,
1446 mgmt->wait,
1447 mgmt->buf,
1448 mgmt->len,
1449 mgmt->no_cck);
1450
1451 kfree(mgmt);
1452 spin_lock_bh(&conn->psq_lock);
1453 }
1454 conn->mgmt_psq_len = 0;
1421 while ((skbuff = skb_dequeue(&conn->psq))) { 1455 while ((skbuff = skb_dequeue(&conn->psq))) {
1422 spin_unlock_bh(&conn->psq_lock); 1456 spin_unlock_bh(&conn->psq_lock);
1423 ath6kl_data_tx(skbuff, vif->ndev); 1457 ath6kl_data_tx(skbuff, vif->ndev);
@@ -1541,7 +1575,7 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet)
1541 aggr_conn = vif->aggr_cntxt->aggr_conn; 1575 aggr_conn = vif->aggr_cntxt->aggr_conn;
1542 1576
1543 if (aggr_process_recv_frm(aggr_conn, tid, seq_no, 1577 if (aggr_process_recv_frm(aggr_conn, tid, seq_no,
1544 is_amsdu, skb)) { 1578 is_amsdu, skb)) {
1545 /* aggregation code will handle the skb */ 1579 /* aggregation code will handle the skb */
1546 return; 1580 return;
1547 } 1581 }
diff --git a/drivers/net/wireless/ath/ath6kl/usb.c b/drivers/net/wireless/ath/ath6kl/usb.c
index c72567c6d338..325b1224c2b1 100644
--- a/drivers/net/wireless/ath/ath6kl/usb.c
+++ b/drivers/net/wireless/ath/ath6kl/usb.c
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (c) 2007-2011 Atheros Communications Inc. 2 * Copyright (c) 2007-2011 Atheros Communications Inc.
3 * Copyright (c) 2011-2012 Qualcomm Atheros, Inc.
3 * 4 *
4 * Permission to use, copy, modify, and/or distribute this software for any 5 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above 6 * purpose with or without fee is hereby granted, provided that the above
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c
index 97abf4699b41..2b442332cd0f 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.c
+++ b/drivers/net/wireless/ath/ath6kl/wmi.c
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (c) 2004-2011 Atheros Communications Inc. 2 * Copyright (c) 2004-2011 Atheros Communications Inc.
3 * Copyright (c) 2011-2012 Qualcomm Atheros, Inc.
3 * 4 *
4 * Permission to use, copy, modify, and/or distribute this software for any 5 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above 6 * purpose with or without fee is hereby granted, provided that the above
@@ -126,7 +127,7 @@ int ath6kl_wmi_dix_2_dot3(struct wmi *wmi, struct sk_buff *skb)
126 127
127 if (!is_ethertype(be16_to_cpu(type))) { 128 if (!is_ethertype(be16_to_cpu(type))) {
128 ath6kl_dbg(ATH6KL_DBG_WMI, 129 ath6kl_dbg(ATH6KL_DBG_WMI,
129 "%s: pkt is already in 802.3 format\n", __func__); 130 "%s: pkt is already in 802.3 format\n", __func__);
130 return 0; 131 return 0;
131 } 132 }
132 133
@@ -827,8 +828,8 @@ static int ath6kl_wmi_connect_event_rx(struct wmi *wmi, u8 *datap, int len,
827 if (pie[1] > 3 && pie[2] == 0x00 && pie[3] == 0x50 && 828 if (pie[1] > 3 && pie[2] == 0x00 && pie[3] == 0x50 &&
828 pie[4] == 0xf2 && pie[5] == WMM_OUI_TYPE) { 829 pie[4] == 0xf2 && pie[5] == WMM_OUI_TYPE) {
829 /* WMM OUT (00:50:F2) */ 830 /* WMM OUT (00:50:F2) */
830 if (pie[1] > 5 831 if (pie[1] > 5 &&
831 && pie[6] == WMM_PARAM_OUI_SUBTYPE) 832 pie[6] == WMM_PARAM_OUI_SUBTYPE)
832 wmi->is_wmm_enabled = true; 833 wmi->is_wmm_enabled = true;
833 } 834 }
834 break; 835 break;
@@ -912,17 +913,17 @@ static void ath6kl_wmi_regdomain_event(struct wmi *wmi, u8 *datap, int len)
912 regpair = ath6kl_get_regpair((u16) reg_code); 913 regpair = ath6kl_get_regpair((u16) reg_code);
913 country = ath6kl_regd_find_country_by_rd((u16) reg_code); 914 country = ath6kl_regd_find_country_by_rd((u16) reg_code);
914 ath6kl_dbg(ATH6KL_DBG_WMI, "Regpair used: 0x%0x\n", 915 ath6kl_dbg(ATH6KL_DBG_WMI, "Regpair used: 0x%0x\n",
915 regpair->regDmnEnum); 916 regpair->regDmnEnum);
916 } 917 }
917 918
918 if (country) { 919 if (country && wmi->parent_dev->wiphy_registered) {
919 alpha2[0] = country->isoName[0]; 920 alpha2[0] = country->isoName[0];
920 alpha2[1] = country->isoName[1]; 921 alpha2[1] = country->isoName[1];
921 922
922 regulatory_hint(wmi->parent_dev->wiphy, alpha2); 923 regulatory_hint(wmi->parent_dev->wiphy, alpha2);
923 924
924 ath6kl_dbg(ATH6KL_DBG_WMI, "Country alpha2 being used: %c%c\n", 925 ath6kl_dbg(ATH6KL_DBG_WMI, "Country alpha2 being used: %c%c\n",
925 alpha2[0], alpha2[1]); 926 alpha2[0], alpha2[1]);
926 } 927 }
927} 928}
928 929
@@ -1033,8 +1034,9 @@ static int ath6kl_wmi_bssinfo_event_rx(struct wmi *wmi, u8 *datap, int len,
1033 if (len < 8 + 2 + 2) 1034 if (len < 8 + 2 + 2)
1034 return -EINVAL; 1035 return -EINVAL;
1035 1036
1036 if (bih->frame_type == BEACON_FTYPE && test_bit(CONNECTED, &vif->flags) 1037 if (bih->frame_type == BEACON_FTYPE &&
1037 && memcmp(bih->bssid, vif->bssid, ETH_ALEN) == 0) { 1038 test_bit(CONNECTED, &vif->flags) &&
1039 memcmp(bih->bssid, vif->bssid, ETH_ALEN) == 0) {
1038 const u8 *tim; 1040 const u8 *tim;
1039 tim = cfg80211_find_ie(WLAN_EID_TIM, buf + 8 + 2 + 2, 1041 tim = cfg80211_find_ie(WLAN_EID_TIM, buf + 8 + 2 + 2,
1040 len - 8 - 2 - 2); 1042 len - 8 - 2 - 2);
@@ -1366,8 +1368,8 @@ static int ath6kl_wmi_rssi_threshold_event_rx(struct wmi *wmi, u8 *datap,
1366 /* Upper threshold breached */ 1368 /* Upper threshold breached */
1367 if (rssi < sq_thresh->upper_threshold[0]) { 1369 if (rssi < sq_thresh->upper_threshold[0]) {
1368 ath6kl_dbg(ATH6KL_DBG_WMI, 1370 ath6kl_dbg(ATH6KL_DBG_WMI,
1369 "spurious upper rssi threshold event: %d\n", 1371 "spurious upper rssi threshold event: %d\n",
1370 rssi); 1372 rssi);
1371 } else if ((rssi < sq_thresh->upper_threshold[1]) && 1373 } else if ((rssi < sq_thresh->upper_threshold[1]) &&
1372 (rssi >= sq_thresh->upper_threshold[0])) { 1374 (rssi >= sq_thresh->upper_threshold[0])) {
1373 new_threshold = WMI_RSSI_THRESHOLD1_ABOVE; 1375 new_threshold = WMI_RSSI_THRESHOLD1_ABOVE;
@@ -1390,7 +1392,7 @@ static int ath6kl_wmi_rssi_threshold_event_rx(struct wmi *wmi, u8 *datap,
1390 /* Lower threshold breached */ 1392 /* Lower threshold breached */
1391 if (rssi > sq_thresh->lower_threshold[0]) { 1393 if (rssi > sq_thresh->lower_threshold[0]) {
1392 ath6kl_dbg(ATH6KL_DBG_WMI, 1394 ath6kl_dbg(ATH6KL_DBG_WMI,
1393 "spurious lower rssi threshold event: %d %d\n", 1395 "spurious lower rssi threshold event: %d %d\n",
1394 rssi, sq_thresh->lower_threshold[0]); 1396 rssi, sq_thresh->lower_threshold[0]);
1395 } else if ((rssi > sq_thresh->lower_threshold[1]) && 1397 } else if ((rssi > sq_thresh->lower_threshold[1]) &&
1396 (rssi <= sq_thresh->lower_threshold[0])) { 1398 (rssi <= sq_thresh->lower_threshold[0])) {
@@ -1551,8 +1553,8 @@ static int ath6kl_wmi_snr_threshold_event_rx(struct wmi *wmi, u8 *datap,
1551 /* Upper threshold breached */ 1553 /* Upper threshold breached */
1552 if (snr < sq_thresh->upper_threshold[0]) { 1554 if (snr < sq_thresh->upper_threshold[0]) {
1553 ath6kl_dbg(ATH6KL_DBG_WMI, 1555 ath6kl_dbg(ATH6KL_DBG_WMI,
1554 "spurious upper snr threshold event: %d\n", 1556 "spurious upper snr threshold event: %d\n",
1555 snr); 1557 snr);
1556 } else if ((snr < sq_thresh->upper_threshold[1]) && 1558 } else if ((snr < sq_thresh->upper_threshold[1]) &&
1557 (snr >= sq_thresh->upper_threshold[0])) { 1559 (snr >= sq_thresh->upper_threshold[0])) {
1558 new_threshold = WMI_SNR_THRESHOLD1_ABOVE; 1560 new_threshold = WMI_SNR_THRESHOLD1_ABOVE;
@@ -1569,8 +1571,8 @@ static int ath6kl_wmi_snr_threshold_event_rx(struct wmi *wmi, u8 *datap,
1569 /* Lower threshold breached */ 1571 /* Lower threshold breached */
1570 if (snr > sq_thresh->lower_threshold[0]) { 1572 if (snr > sq_thresh->lower_threshold[0]) {
1571 ath6kl_dbg(ATH6KL_DBG_WMI, 1573 ath6kl_dbg(ATH6KL_DBG_WMI,
1572 "spurious lower snr threshold event: %d\n", 1574 "spurious lower snr threshold event: %d\n",
1573 sq_thresh->lower_threshold[0]); 1575 sq_thresh->lower_threshold[0]);
1574 } else if ((snr > sq_thresh->lower_threshold[1]) && 1576 } else if ((snr > sq_thresh->lower_threshold[1]) &&
1575 (snr <= sq_thresh->lower_threshold[0])) { 1577 (snr <= sq_thresh->lower_threshold[0])) {
1576 new_threshold = WMI_SNR_THRESHOLD4_BELOW; 1578 new_threshold = WMI_SNR_THRESHOLD4_BELOW;
@@ -2028,6 +2030,26 @@ int ath6kl_wmi_listeninterval_cmd(struct wmi *wmi, u8 if_idx,
2028 return ret; 2030 return ret;
2029} 2031}
2030 2032
2033int ath6kl_wmi_bmisstime_cmd(struct wmi *wmi, u8 if_idx,
2034 u16 bmiss_time, u16 num_beacons)
2035{
2036 struct sk_buff *skb;
2037 struct wmi_bmiss_time_cmd *cmd;
2038 int ret;
2039
2040 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
2041 if (!skb)
2042 return -ENOMEM;
2043
2044 cmd = (struct wmi_bmiss_time_cmd *) skb->data;
2045 cmd->bmiss_time = cpu_to_le16(bmiss_time);
2046 cmd->num_beacons = cpu_to_le16(num_beacons);
2047
2048 ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_BMISS_TIME_CMDID,
2049 NO_SYNC_WMIFLAG);
2050 return ret;
2051}
2052
2031int ath6kl_wmi_powermode_cmd(struct wmi *wmi, u8 if_idx, u8 pwr_mode) 2053int ath6kl_wmi_powermode_cmd(struct wmi *wmi, u8 if_idx, u8 pwr_mode)
2032{ 2054{
2033 struct sk_buff *skb; 2055 struct sk_buff *skb;
@@ -2613,7 +2635,7 @@ int ath6kl_wmi_set_wow_mode_cmd(struct wmi *wmi, u8 if_idx,
2613 int ret; 2635 int ret;
2614 2636
2615 if ((wow_mode != ATH6KL_WOW_MODE_ENABLE) && 2637 if ((wow_mode != ATH6KL_WOW_MODE_ENABLE) &&
2616 wow_mode != ATH6KL_WOW_MODE_DISABLE) { 2638 wow_mode != ATH6KL_WOW_MODE_DISABLE) {
2617 ath6kl_err("invalid wow mode: %d\n", wow_mode); 2639 ath6kl_err("invalid wow mode: %d\n", wow_mode);
2618 return -EINVAL; 2640 return -EINVAL;
2619 } 2641 }
@@ -3014,6 +3036,22 @@ int ath6kl_wmi_ap_set_mlme(struct wmi *wmip, u8 if_idx, u8 cmd, const u8 *mac,
3014 NO_SYNC_WMIFLAG); 3036 NO_SYNC_WMIFLAG);
3015} 3037}
3016 3038
3039int ath6kl_wmi_ap_hidden_ssid(struct wmi *wmi, u8 if_idx, bool enable)
3040{
3041 struct sk_buff *skb;
3042 struct wmi_ap_hidden_ssid_cmd *cmd;
3043
3044 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
3045 if (!skb)
3046 return -ENOMEM;
3047
3048 cmd = (struct wmi_ap_hidden_ssid_cmd *) skb->data;
3049 cmd->hidden_ssid = enable ? 1 : 0;
3050
3051 return ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_AP_HIDDEN_SSID_CMDID,
3052 NO_SYNC_WMIFLAG);
3053}
3054
3017/* This command will be used to enable/disable AP uAPSD feature */ 3055/* This command will be used to enable/disable AP uAPSD feature */
3018int ath6kl_wmi_ap_set_apsd(struct wmi *wmi, u8 if_idx, u8 enable) 3056int ath6kl_wmi_ap_set_apsd(struct wmi *wmi, u8 if_idx, u8 enable)
3019{ 3057{
@@ -3183,8 +3221,9 @@ int ath6kl_wmi_remain_on_chnl_cmd(struct wmi *wmi, u8 if_idx, u32 freq, u32 dur)
3183 * ath6kl_wmi_send_mgmt_cmd instead. The new function supports P2P 3221 * ath6kl_wmi_send_mgmt_cmd instead. The new function supports P2P
3184 * mgmt operations using station interface. 3222 * mgmt operations using station interface.
3185 */ 3223 */
3186int ath6kl_wmi_send_action_cmd(struct wmi *wmi, u8 if_idx, u32 id, u32 freq, 3224static int ath6kl_wmi_send_action_cmd(struct wmi *wmi, u8 if_idx, u32 id,
3187 u32 wait, const u8 *data, u16 data_len) 3225 u32 freq, u32 wait, const u8 *data,
3226 u16 data_len)
3188{ 3227{
3189 struct sk_buff *skb; 3228 struct sk_buff *skb;
3190 struct wmi_send_action_cmd *p; 3229 struct wmi_send_action_cmd *p;
@@ -3220,9 +3259,9 @@ int ath6kl_wmi_send_action_cmd(struct wmi *wmi, u8 if_idx, u32 id, u32 freq,
3220 NO_SYNC_WMIFLAG); 3259 NO_SYNC_WMIFLAG);
3221} 3260}
3222 3261
3223int ath6kl_wmi_send_mgmt_cmd(struct wmi *wmi, u8 if_idx, u32 id, u32 freq, 3262static int __ath6kl_wmi_send_mgmt_cmd(struct wmi *wmi, u8 if_idx, u32 id,
3224 u32 wait, const u8 *data, u16 data_len, 3263 u32 freq, u32 wait, const u8 *data,
3225 u32 no_cck) 3264 u16 data_len, u32 no_cck)
3226{ 3265{
3227 struct sk_buff *skb; 3266 struct sk_buff *skb;
3228 struct wmi_send_mgmt_cmd *p; 3267 struct wmi_send_mgmt_cmd *p;
@@ -3259,6 +3298,32 @@ int ath6kl_wmi_send_mgmt_cmd(struct wmi *wmi, u8 if_idx, u32 id, u32 freq,
3259 NO_SYNC_WMIFLAG); 3298 NO_SYNC_WMIFLAG);
3260} 3299}
3261 3300
3301int ath6kl_wmi_send_mgmt_cmd(struct wmi *wmi, u8 if_idx, u32 id, u32 freq,
3302 u32 wait, const u8 *data, u16 data_len,
3303 u32 no_cck)
3304{
3305 int status;
3306 struct ath6kl *ar = wmi->parent_dev;
3307
3308 if (test_bit(ATH6KL_FW_CAPABILITY_STA_P2PDEV_DUPLEX,
3309 ar->fw_capabilities)) {
3310 /*
3311 * If capable of doing P2P mgmt operations using
3312 * station interface, send additional information like
3313 * supported rates to advertise and xmit rates for
3314 * probe requests
3315 */
3316 status = __ath6kl_wmi_send_mgmt_cmd(ar->wmi, if_idx, id, freq,
3317 wait, data, data_len,
3318 no_cck);
3319 } else {
3320 status = ath6kl_wmi_send_action_cmd(ar->wmi, if_idx, id, freq,
3321 wait, data, data_len);
3322 }
3323
3324 return status;
3325}
3326
3262int ath6kl_wmi_send_probe_response_cmd(struct wmi *wmi, u8 if_idx, u32 freq, 3327int ath6kl_wmi_send_probe_response_cmd(struct wmi *wmi, u8 if_idx, u32 freq,
3263 const u8 *dst, const u8 *data, 3328 const u8 *dst, const u8 *data,
3264 u16 data_len) 3329 u16 data_len)
@@ -3370,32 +3435,101 @@ static int ath6kl_wmi_roam_tbl_event_rx(struct wmi *wmi, u8 *datap, int len)
3370 return ath6kl_debug_roam_tbl_event(wmi->parent_dev, datap, len); 3435 return ath6kl_debug_roam_tbl_event(wmi->parent_dev, datap, len);
3371} 3436}
3372 3437
3373/* Control Path */ 3438/* Process interface specific wmi events, caller would free the datap */
3374int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb) 3439static int ath6kl_wmi_proc_events_vif(struct wmi *wmi, u16 if_idx, u16 cmd_id,
3440 u8 *datap, u32 len)
3375{ 3441{
3376 struct wmi_cmd_hdr *cmd;
3377 struct ath6kl_vif *vif; 3442 struct ath6kl_vif *vif;
3378 u32 len;
3379 u16 id;
3380 u8 if_idx;
3381 u8 *datap;
3382 int ret = 0;
3383 3443
3384 if (WARN_ON(skb == NULL)) 3444 vif = ath6kl_get_vif_by_index(wmi->parent_dev, if_idx);
3445 if (!vif) {
3446 ath6kl_dbg(ATH6KL_DBG_WMI,
3447 "Wmi event for unavailable vif, vif_index:%d\n",
3448 if_idx);
3385 return -EINVAL; 3449 return -EINVAL;
3450 }
3386 3451
3387 if (skb->len < sizeof(struct wmi_cmd_hdr)) { 3452 switch (cmd_id) {
3388 ath6kl_err("bad packet 1\n"); 3453 case WMI_CONNECT_EVENTID:
3389 dev_kfree_skb(skb); 3454 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_CONNECT_EVENTID\n");
3455 return ath6kl_wmi_connect_event_rx(wmi, datap, len, vif);
3456 case WMI_DISCONNECT_EVENTID:
3457 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_DISCONNECT_EVENTID\n");
3458 return ath6kl_wmi_disconnect_event_rx(wmi, datap, len, vif);
3459 case WMI_TKIP_MICERR_EVENTID:
3460 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TKIP_MICERR_EVENTID\n");
3461 return ath6kl_wmi_tkip_micerr_event_rx(wmi, datap, len, vif);
3462 case WMI_BSSINFO_EVENTID:
3463 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_BSSINFO_EVENTID\n");
3464 return ath6kl_wmi_bssinfo_event_rx(wmi, datap, len, vif);
3465 case WMI_NEIGHBOR_REPORT_EVENTID:
3466 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_NEIGHBOR_REPORT_EVENTID\n");
3467 return ath6kl_wmi_neighbor_report_event_rx(wmi, datap, len,
3468 vif);
3469 case WMI_SCAN_COMPLETE_EVENTID:
3470 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_SCAN_COMPLETE_EVENTID\n");
3471 return ath6kl_wmi_scan_complete_rx(wmi, datap, len, vif);
3472 case WMI_REPORT_STATISTICS_EVENTID:
3473 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REPORT_STATISTICS_EVENTID\n");
3474 return ath6kl_wmi_stats_event_rx(wmi, datap, len, vif);
3475 case WMI_CAC_EVENTID:
3476 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_CAC_EVENTID\n");
3477 return ath6kl_wmi_cac_event_rx(wmi, datap, len, vif);
3478 case WMI_PSPOLL_EVENTID:
3479 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_PSPOLL_EVENTID\n");
3480 return ath6kl_wmi_pspoll_event_rx(wmi, datap, len, vif);
3481 case WMI_DTIMEXPIRY_EVENTID:
3482 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_DTIMEXPIRY_EVENTID\n");
3483 return ath6kl_wmi_dtimexpiry_event_rx(wmi, datap, len, vif);
3484 case WMI_ADDBA_REQ_EVENTID:
3485 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_ADDBA_REQ_EVENTID\n");
3486 return ath6kl_wmi_addba_req_event_rx(wmi, datap, len, vif);
3487 case WMI_DELBA_REQ_EVENTID:
3488 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_DELBA_REQ_EVENTID\n");
3489 return ath6kl_wmi_delba_req_event_rx(wmi, datap, len, vif);
3490 case WMI_SET_HOST_SLEEP_MODE_CMD_PROCESSED_EVENTID:
3491 ath6kl_dbg(ATH6KL_DBG_WMI,
3492 "WMI_SET_HOST_SLEEP_MODE_CMD_PROCESSED_EVENTID");
3493 return ath6kl_wmi_host_sleep_mode_cmd_prcd_evt_rx(wmi, vif);
3494 case WMI_REMAIN_ON_CHNL_EVENTID:
3495 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REMAIN_ON_CHNL_EVENTID\n");
3496 return ath6kl_wmi_remain_on_chnl_event_rx(wmi, datap, len, vif);
3497 case WMI_CANCEL_REMAIN_ON_CHNL_EVENTID:
3498 ath6kl_dbg(ATH6KL_DBG_WMI,
3499 "WMI_CANCEL_REMAIN_ON_CHNL_EVENTID\n");
3500 return ath6kl_wmi_cancel_remain_on_chnl_event_rx(wmi, datap,
3501 len, vif);
3502 case WMI_TX_STATUS_EVENTID:
3503 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TX_STATUS_EVENTID\n");
3504 return ath6kl_wmi_tx_status_event_rx(wmi, datap, len, vif);
3505 case WMI_RX_PROBE_REQ_EVENTID:
3506 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_RX_PROBE_REQ_EVENTID\n");
3507 return ath6kl_wmi_rx_probe_req_event_rx(wmi, datap, len, vif);
3508 case WMI_RX_ACTION_EVENTID:
3509 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_RX_ACTION_EVENTID\n");
3510 return ath6kl_wmi_rx_action_event_rx(wmi, datap, len, vif);
3511 default:
3512 ath6kl_dbg(ATH6KL_DBG_WMI, "unknown cmd id 0x%x\n", cmd_id);
3390 return -EINVAL; 3513 return -EINVAL;
3391 } 3514 }
3392 3515
3516 return 0;
3517}
3518
3519static int ath6kl_wmi_proc_events(struct wmi *wmi, struct sk_buff *skb)
3520{
3521 struct wmi_cmd_hdr *cmd;
3522 int ret = 0;
3523 u32 len;
3524 u16 id;
3525 u8 if_idx;
3526 u8 *datap;
3527
3393 cmd = (struct wmi_cmd_hdr *) skb->data; 3528 cmd = (struct wmi_cmd_hdr *) skb->data;
3394 id = le16_to_cpu(cmd->cmd_id); 3529 id = le16_to_cpu(cmd->cmd_id);
3395 if_idx = le16_to_cpu(cmd->info1) & WMI_CMD_HDR_IF_ID_MASK; 3530 if_idx = le16_to_cpu(cmd->info1) & WMI_CMD_HDR_IF_ID_MASK;
3396 3531
3397 skb_pull(skb, sizeof(struct wmi_cmd_hdr)); 3532 skb_pull(skb, sizeof(struct wmi_cmd_hdr));
3398
3399 datap = skb->data; 3533 datap = skb->data;
3400 len = skb->len; 3534 len = skb->len;
3401 3535
@@ -3403,15 +3537,6 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
3403 ath6kl_dbg_dump(ATH6KL_DBG_WMI_DUMP, NULL, "wmi rx ", 3537 ath6kl_dbg_dump(ATH6KL_DBG_WMI_DUMP, NULL, "wmi rx ",
3404 datap, len); 3538 datap, len);
3405 3539
3406 vif = ath6kl_get_vif_by_index(wmi->parent_dev, if_idx);
3407 if (!vif) {
3408 ath6kl_dbg(ATH6KL_DBG_WMI,
3409 "Wmi event for unavailable vif, vif_index:%d\n",
3410 if_idx);
3411 dev_kfree_skb(skb);
3412 return -EINVAL;
3413 }
3414
3415 switch (id) { 3540 switch (id) {
3416 case WMI_GET_BITRATE_CMDID: 3541 case WMI_GET_BITRATE_CMDID:
3417 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_BITRATE_CMDID\n"); 3542 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_BITRATE_CMDID\n");
@@ -3429,26 +3554,10 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
3429 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_READY_EVENTID\n"); 3554 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_READY_EVENTID\n");
3430 ret = ath6kl_wmi_ready_event_rx(wmi, datap, len); 3555 ret = ath6kl_wmi_ready_event_rx(wmi, datap, len);
3431 break; 3556 break;
3432 case WMI_CONNECT_EVENTID:
3433 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_CONNECT_EVENTID\n");
3434 ret = ath6kl_wmi_connect_event_rx(wmi, datap, len, vif);
3435 break;
3436 case WMI_DISCONNECT_EVENTID:
3437 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_DISCONNECT_EVENTID\n");
3438 ret = ath6kl_wmi_disconnect_event_rx(wmi, datap, len, vif);
3439 break;
3440 case WMI_PEER_NODE_EVENTID: 3557 case WMI_PEER_NODE_EVENTID:
3441 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_PEER_NODE_EVENTID\n"); 3558 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_PEER_NODE_EVENTID\n");
3442 ret = ath6kl_wmi_peer_node_event_rx(wmi, datap, len); 3559 ret = ath6kl_wmi_peer_node_event_rx(wmi, datap, len);
3443 break; 3560 break;
3444 case WMI_TKIP_MICERR_EVENTID:
3445 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TKIP_MICERR_EVENTID\n");
3446 ret = ath6kl_wmi_tkip_micerr_event_rx(wmi, datap, len, vif);
3447 break;
3448 case WMI_BSSINFO_EVENTID:
3449 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_BSSINFO_EVENTID\n");
3450 ret = ath6kl_wmi_bssinfo_event_rx(wmi, datap, len, vif);
3451 break;
3452 case WMI_REGDOMAIN_EVENTID: 3561 case WMI_REGDOMAIN_EVENTID:
3453 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REGDOMAIN_EVENTID\n"); 3562 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REGDOMAIN_EVENTID\n");
3454 ath6kl_wmi_regdomain_event(wmi, datap, len); 3563 ath6kl_wmi_regdomain_event(wmi, datap, len);
@@ -3457,23 +3566,10 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
3457 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_PSTREAM_TIMEOUT_EVENTID\n"); 3566 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_PSTREAM_TIMEOUT_EVENTID\n");
3458 ret = ath6kl_wmi_pstream_timeout_event_rx(wmi, datap, len); 3567 ret = ath6kl_wmi_pstream_timeout_event_rx(wmi, datap, len);
3459 break; 3568 break;
3460 case WMI_NEIGHBOR_REPORT_EVENTID:
3461 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_NEIGHBOR_REPORT_EVENTID\n");
3462 ret = ath6kl_wmi_neighbor_report_event_rx(wmi, datap, len,
3463 vif);
3464 break;
3465 case WMI_SCAN_COMPLETE_EVENTID:
3466 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_SCAN_COMPLETE_EVENTID\n");
3467 ret = ath6kl_wmi_scan_complete_rx(wmi, datap, len, vif);
3468 break;
3469 case WMI_CMDERROR_EVENTID: 3569 case WMI_CMDERROR_EVENTID:
3470 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_CMDERROR_EVENTID\n"); 3570 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_CMDERROR_EVENTID\n");
3471 ret = ath6kl_wmi_error_event_rx(wmi, datap, len); 3571 ret = ath6kl_wmi_error_event_rx(wmi, datap, len);
3472 break; 3572 break;
3473 case WMI_REPORT_STATISTICS_EVENTID:
3474 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REPORT_STATISTICS_EVENTID\n");
3475 ret = ath6kl_wmi_stats_event_rx(wmi, datap, len, vif);
3476 break;
3477 case WMI_RSSI_THRESHOLD_EVENTID: 3573 case WMI_RSSI_THRESHOLD_EVENTID:
3478 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_RSSI_THRESHOLD_EVENTID\n"); 3574 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_RSSI_THRESHOLD_EVENTID\n");
3479 ret = ath6kl_wmi_rssi_threshold_event_rx(wmi, datap, len); 3575 ret = ath6kl_wmi_rssi_threshold_event_rx(wmi, datap, len);
@@ -3493,10 +3589,6 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
3493 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_EXTENSION_EVENTID\n"); 3589 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_EXTENSION_EVENTID\n");
3494 ret = ath6kl_wmi_control_rx_xtnd(wmi, skb); 3590 ret = ath6kl_wmi_control_rx_xtnd(wmi, skb);
3495 break; 3591 break;
3496 case WMI_CAC_EVENTID:
3497 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_CAC_EVENTID\n");
3498 ret = ath6kl_wmi_cac_event_rx(wmi, datap, len, vif);
3499 break;
3500 case WMI_CHANNEL_CHANGE_EVENTID: 3592 case WMI_CHANNEL_CHANGE_EVENTID:
3501 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_CHANNEL_CHANGE_EVENTID\n"); 3593 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_CHANNEL_CHANGE_EVENTID\n");
3502 break; 3594 break;
@@ -3536,28 +3628,12 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
3536 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_PMKID_LIST_EVENTID\n"); 3628 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_PMKID_LIST_EVENTID\n");
3537 ret = ath6kl_wmi_get_pmkid_list_event_rx(wmi, datap, len); 3629 ret = ath6kl_wmi_get_pmkid_list_event_rx(wmi, datap, len);
3538 break; 3630 break;
3539 case WMI_PSPOLL_EVENTID:
3540 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_PSPOLL_EVENTID\n");
3541 ret = ath6kl_wmi_pspoll_event_rx(wmi, datap, len, vif);
3542 break;
3543 case WMI_DTIMEXPIRY_EVENTID:
3544 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_DTIMEXPIRY_EVENTID\n");
3545 ret = ath6kl_wmi_dtimexpiry_event_rx(wmi, datap, len, vif);
3546 break;
3547 case WMI_SET_PARAMS_REPLY_EVENTID: 3631 case WMI_SET_PARAMS_REPLY_EVENTID:
3548 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_SET_PARAMS_REPLY_EVENTID\n"); 3632 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_SET_PARAMS_REPLY_EVENTID\n");
3549 break; 3633 break;
3550 case WMI_ADDBA_REQ_EVENTID:
3551 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_ADDBA_REQ_EVENTID\n");
3552 ret = ath6kl_wmi_addba_req_event_rx(wmi, datap, len, vif);
3553 break;
3554 case WMI_ADDBA_RESP_EVENTID: 3634 case WMI_ADDBA_RESP_EVENTID:
3555 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_ADDBA_RESP_EVENTID\n"); 3635 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_ADDBA_RESP_EVENTID\n");
3556 break; 3636 break;
3557 case WMI_DELBA_REQ_EVENTID:
3558 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_DELBA_REQ_EVENTID\n");
3559 ret = ath6kl_wmi_delba_req_event_rx(wmi, datap, len, vif);
3560 break;
3561 case WMI_REPORT_BTCOEX_CONFIG_EVENTID: 3637 case WMI_REPORT_BTCOEX_CONFIG_EVENTID:
3562 ath6kl_dbg(ATH6KL_DBG_WMI, 3638 ath6kl_dbg(ATH6KL_DBG_WMI,
3563 "WMI_REPORT_BTCOEX_CONFIG_EVENTID\n"); 3639 "WMI_REPORT_BTCOEX_CONFIG_EVENTID\n");
@@ -3570,52 +3646,39 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
3570 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TX_COMPLETE_EVENTID\n"); 3646 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TX_COMPLETE_EVENTID\n");
3571 ret = ath6kl_wmi_tx_complete_event_rx(datap, len); 3647 ret = ath6kl_wmi_tx_complete_event_rx(datap, len);
3572 break; 3648 break;
3573 case WMI_SET_HOST_SLEEP_MODE_CMD_PROCESSED_EVENTID:
3574 ath6kl_dbg(ATH6KL_DBG_WMI,
3575 "WMI_SET_HOST_SLEEP_MODE_CMD_PROCESSED_EVENTID");
3576 ret = ath6kl_wmi_host_sleep_mode_cmd_prcd_evt_rx(wmi, vif);
3577 break;
3578 case WMI_REMAIN_ON_CHNL_EVENTID:
3579 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REMAIN_ON_CHNL_EVENTID\n");
3580 ret = ath6kl_wmi_remain_on_chnl_event_rx(wmi, datap, len, vif);
3581 break;
3582 case WMI_CANCEL_REMAIN_ON_CHNL_EVENTID:
3583 ath6kl_dbg(ATH6KL_DBG_WMI,
3584 "WMI_CANCEL_REMAIN_ON_CHNL_EVENTID\n");
3585 ret = ath6kl_wmi_cancel_remain_on_chnl_event_rx(wmi, datap,
3586 len, vif);
3587 break;
3588 case WMI_TX_STATUS_EVENTID:
3589 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TX_STATUS_EVENTID\n");
3590 ret = ath6kl_wmi_tx_status_event_rx(wmi, datap, len, vif);
3591 break;
3592 case WMI_RX_PROBE_REQ_EVENTID:
3593 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_RX_PROBE_REQ_EVENTID\n");
3594 ret = ath6kl_wmi_rx_probe_req_event_rx(wmi, datap, len, vif);
3595 break;
3596 case WMI_P2P_CAPABILITIES_EVENTID: 3649 case WMI_P2P_CAPABILITIES_EVENTID:
3597 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_P2P_CAPABILITIES_EVENTID\n"); 3650 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_P2P_CAPABILITIES_EVENTID\n");
3598 ret = ath6kl_wmi_p2p_capabilities_event_rx(datap, len); 3651 ret = ath6kl_wmi_p2p_capabilities_event_rx(datap, len);
3599 break; 3652 break;
3600 case WMI_RX_ACTION_EVENTID:
3601 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_RX_ACTION_EVENTID\n");
3602 ret = ath6kl_wmi_rx_action_event_rx(wmi, datap, len, vif);
3603 break;
3604 case WMI_P2P_INFO_EVENTID: 3653 case WMI_P2P_INFO_EVENTID:
3605 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_P2P_INFO_EVENTID\n"); 3654 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_P2P_INFO_EVENTID\n");
3606 ret = ath6kl_wmi_p2p_info_event_rx(datap, len); 3655 ret = ath6kl_wmi_p2p_info_event_rx(datap, len);
3607 break; 3656 break;
3608 default: 3657 default:
3609 ath6kl_dbg(ATH6KL_DBG_WMI, "unknown cmd id 0x%x\n", id); 3658 /* may be the event is interface specific */
3610 ret = -EINVAL; 3659 ret = ath6kl_wmi_proc_events_vif(wmi, if_idx, id, datap, len);
3611 break; 3660 break;
3612 } 3661 }
3613 3662
3614 dev_kfree_skb(skb); 3663 dev_kfree_skb(skb);
3615
3616 return ret; 3664 return ret;
3617} 3665}
3618 3666
3667/* Control Path */
3668int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
3669{
3670 if (WARN_ON(skb == NULL))
3671 return -EINVAL;
3672
3673 if (skb->len < sizeof(struct wmi_cmd_hdr)) {
3674 ath6kl_err("bad packet 1\n");
3675 dev_kfree_skb(skb);
3676 return -EINVAL;
3677 }
3678
3679 return ath6kl_wmi_proc_events(wmi, skb);
3680}
3681
3619void ath6kl_wmi_reset(struct wmi *wmi) 3682void ath6kl_wmi_reset(struct wmi *wmi)
3620{ 3683{
3621 spin_lock_bh(&wmi->lock); 3684 spin_lock_bh(&wmi->lock);
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h
index e7919869725e..4092e3e80790 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.h
+++ b/drivers/net/wireless/ath/ath6kl/wmi.h
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (c) 2010-2011 Atheros Communications Inc. 2 * Copyright (c) 2010-2011 Atheros Communications Inc.
3 * Copyright (c) 2011-2012 Qualcomm Atheros, Inc.
3 * 4 *
4 * Permission to use, copy, modify, and/or distribute this software for any 5 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above 6 * purpose with or without fee is hereby granted, provided that the above
@@ -110,6 +111,8 @@ struct wmi {
110 u8 fat_pipe_exist; 111 u8 fat_pipe_exist;
111 struct ath6kl *parent_dev; 112 struct ath6kl *parent_dev;
112 u8 pwr_mode; 113 u8 pwr_mode;
114
115 /* protects fat_pipe_exist and stream_exist_for_ac */
113 spinlock_t lock; 116 spinlock_t lock;
114 enum htc_endpoint_id ep_id; 117 enum htc_endpoint_id ep_id;
115 struct sq_threshold_params 118 struct sq_threshold_params
@@ -997,6 +1000,12 @@ struct wmi_listen_int_cmd {
997 __le16 num_beacons; 1000 __le16 num_beacons;
998} __packed; 1001} __packed;
999 1002
1003/* WMI_SET_BMISS_TIME_CMDID */
1004struct wmi_bmiss_time_cmd {
1005 __le16 bmiss_time;
1006 __le16 num_beacons;
1007};
1008
1000/* WMI_SET_POWER_MODE_CMDID */ 1009/* WMI_SET_POWER_MODE_CMDID */
1001enum wmi_power_mode { 1010enum wmi_power_mode {
1002 REC_POWER = 0x01, 1011 REC_POWER = 0x01,
@@ -1014,7 +1023,7 @@ struct wmi_power_mode_cmd {
1014 */ 1023 */
1015enum power_save_fail_event_policy { 1024enum power_save_fail_event_policy {
1016 SEND_POWER_SAVE_FAIL_EVENT_ALWAYS = 1, 1025 SEND_POWER_SAVE_FAIL_EVENT_ALWAYS = 1,
1017 IGNORE_POWER_SAVE_FAIL_EVENT_DURING_SCAN = 2, 1026 IGNORE_PS_FAIL_DURING_SCAN = 2,
1018}; 1027};
1019 1028
1020struct wmi_power_params_cmd { 1029struct wmi_power_params_cmd {
@@ -1212,7 +1221,7 @@ struct wmi_snr_threshold_params_cmd {
1212 1221
1213enum wmi_preamble_policy { 1222enum wmi_preamble_policy {
1214 WMI_IGNORE_BARKER_IN_ERP = 0, 1223 WMI_IGNORE_BARKER_IN_ERP = 0,
1215 WMI_DONOT_IGNORE_BARKER_IN_ERP 1224 WMI_FOLLOW_BARKER_IN_ERP,
1216}; 1225};
1217 1226
1218struct wmi_set_lpreamble_cmd { 1227struct wmi_set_lpreamble_cmd {
@@ -2128,6 +2137,10 @@ struct wmi_rx_frame_format_cmd {
2128 u8 reserved[1]; 2137 u8 reserved[1];
2129} __packed; 2138} __packed;
2130 2139
2140struct wmi_ap_hidden_ssid_cmd {
2141 u8 hidden_ssid;
2142} __packed;
2143
2131/* AP mode events */ 2144/* AP mode events */
2132struct wmi_ap_set_apsd_cmd { 2145struct wmi_ap_set_apsd_cmd {
2133 u8 enable; 2146 u8 enable;
@@ -2413,6 +2426,8 @@ int ath6kl_wmi_probedssid_cmd(struct wmi *wmi, u8 if_idx, u8 index, u8 flag,
2413int ath6kl_wmi_listeninterval_cmd(struct wmi *wmi, u8 if_idx, 2426int ath6kl_wmi_listeninterval_cmd(struct wmi *wmi, u8 if_idx,
2414 u16 listen_interval, 2427 u16 listen_interval,
2415 u16 listen_beacons); 2428 u16 listen_beacons);
2429int ath6kl_wmi_bmisstime_cmd(struct wmi *wmi, u8 if_idx,
2430 u16 bmiss_time, u16 num_beacons);
2416int ath6kl_wmi_powermode_cmd(struct wmi *wmi, u8 if_idx, u8 pwr_mode); 2431int ath6kl_wmi_powermode_cmd(struct wmi *wmi, u8 if_idx, u8 pwr_mode);
2417int ath6kl_wmi_pmparams_cmd(struct wmi *wmi, u8 if_idx, u16 idle_period, 2432int ath6kl_wmi_pmparams_cmd(struct wmi *wmi, u8 if_idx, u16 idle_period,
2418 u16 ps_poll_num, u16 dtim_policy, 2433 u16 ps_poll_num, u16 dtim_policy,
@@ -2484,6 +2499,7 @@ u8 ath6kl_wmi_get_traffic_class(u8 user_priority);
2484 2499
2485u8 ath6kl_wmi_determine_user_priority(u8 *pkt, u32 layer2_pri); 2500u8 ath6kl_wmi_determine_user_priority(u8 *pkt, u32 layer2_pri);
2486/* AP mode */ 2501/* AP mode */
2502int ath6kl_wmi_ap_hidden_ssid(struct wmi *wmi, u8 if_idx, bool enable);
2487int ath6kl_wmi_ap_profile_commit(struct wmi *wmip, u8 if_idx, 2503int ath6kl_wmi_ap_profile_commit(struct wmi *wmip, u8 if_idx,
2488 struct wmi_connect_cmd *p); 2504 struct wmi_connect_cmd *p);
2489 2505
@@ -2505,9 +2521,6 @@ int ath6kl_wmi_disable_11b_rates_cmd(struct wmi *wmi, bool disable);
2505int ath6kl_wmi_remain_on_chnl_cmd(struct wmi *wmi, u8 if_idx, u32 freq, 2521int ath6kl_wmi_remain_on_chnl_cmd(struct wmi *wmi, u8 if_idx, u32 freq,
2506 u32 dur); 2522 u32 dur);
2507 2523
2508int ath6kl_wmi_send_action_cmd(struct wmi *wmi, u8 if_idx, u32 id, u32 freq,
2509 u32 wait, const u8 *data, u16 data_len);
2510
2511int ath6kl_wmi_send_mgmt_cmd(struct wmi *wmi, u8 if_idx, u32 id, u32 freq, 2524int ath6kl_wmi_send_mgmt_cmd(struct wmi *wmi, u8 if_idx, u32 id, u32 freq,
2512 u32 wait, const u8 *data, u16 data_len, 2525 u32 wait, const u8 *data, u16 data_len,
2513 u32 no_cck); 2526 u32 no_cck);