aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/ath/ath6kl/cfg80211.c206
-rw-r--r--drivers/net/wireless/ath/ath6kl/common.h3
-rw-r--r--drivers/net/wireless/ath/ath6kl/core.h2
-rw-r--r--drivers/net/wireless/ath/ath6kl/debug.c6
-rw-r--r--drivers/net/wireless/ath/ath6kl/htc.c4
-rw-r--r--drivers/net/wireless/ath/ath6kl/main.c4
-rw-r--r--drivers/net/wireless/ath/ath6kl/wmi.c3
7 files changed, 174 insertions, 54 deletions
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index 00d38952b5fb..80910286d1b8 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -1924,12 +1924,61 @@ static int ath6kl_wow_sta(struct ath6kl *ar, struct ath6kl_vif *vif)
1924 return 0; 1924 return 0;
1925} 1925}
1926 1926
1927static int is_hsleep_mode_procsed(struct ath6kl_vif *vif)
1928{
1929 return test_bit(HOST_SLEEP_MODE_CMD_PROCESSED, &vif->flags);
1930}
1931
1932static bool is_ctrl_ep_empty(struct ath6kl *ar)
1933{
1934 return !ar->tx_pending[ar->ctrl_ep];
1935}
1936
1937static int ath6kl_cfg80211_host_sleep(struct ath6kl *ar, struct ath6kl_vif *vif)
1938{
1939 int ret, left;
1940
1941 clear_bit(HOST_SLEEP_MODE_CMD_PROCESSED, &vif->flags);
1942
1943 ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx,
1944 ATH6KL_HOST_MODE_ASLEEP);
1945 if (ret)
1946 return ret;
1947
1948 left = wait_event_interruptible_timeout(ar->event_wq,
1949 is_hsleep_mode_procsed(vif),
1950 WMI_TIMEOUT);
1951 if (left == 0) {
1952 ath6kl_warn("timeout, didn't get host sleep cmd processed event\n");
1953 ret = -ETIMEDOUT;
1954 } else if (left < 0) {
1955 ath6kl_warn("error while waiting for host sleep cmd processed event %d\n",
1956 left);
1957 ret = left;
1958 }
1959
1960 if (ar->tx_pending[ar->ctrl_ep]) {
1961 left = wait_event_interruptible_timeout(ar->event_wq,
1962 is_ctrl_ep_empty(ar),
1963 WMI_TIMEOUT);
1964 if (left == 0) {
1965 ath6kl_warn("clear wmi ctrl data timeout\n");
1966 ret = -ETIMEDOUT;
1967 } else if (left < 0) {
1968 ath6kl_warn("clear wmi ctrl data failed: %d\n", left);
1969 ret = left;
1970 }
1971 }
1972
1973 return ret;
1974}
1975
1927static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow) 1976static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
1928{ 1977{
1929 struct in_device *in_dev; 1978 struct in_device *in_dev;
1930 struct in_ifaddr *ifa; 1979 struct in_ifaddr *ifa;
1931 struct ath6kl_vif *vif; 1980 struct ath6kl_vif *vif;
1932 int ret, left; 1981 int ret;
1933 u32 filter = 0; 1982 u32 filter = 0;
1934 u16 i, bmiss_time; 1983 u16 i, bmiss_time;
1935 u8 index = 0; 1984 u8 index = 0;
@@ -2030,39 +2079,11 @@ skip_arp:
2030 if (ret) 2079 if (ret)
2031 return ret; 2080 return ret;
2032 2081
2033 clear_bit(HOST_SLEEP_MODE_CMD_PROCESSED, &vif->flags); 2082 ret = ath6kl_cfg80211_host_sleep(ar, vif);
2034
2035 ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx,
2036 ATH6KL_HOST_MODE_ASLEEP);
2037 if (ret) 2083 if (ret)
2038 return ret; 2084 return ret;
2039 2085
2040 left = wait_event_interruptible_timeout(ar->event_wq, 2086 return 0;
2041 test_bit(HOST_SLEEP_MODE_CMD_PROCESSED, &vif->flags),
2042 WMI_TIMEOUT);
2043 if (left == 0) {
2044 ath6kl_warn("timeout, didn't get host sleep cmd "
2045 "processed event\n");
2046 ret = -ETIMEDOUT;
2047 } else if (left < 0) {
2048 ath6kl_warn("error while waiting for host sleep cmd "
2049 "processed event %d\n", left);
2050 ret = left;
2051 }
2052
2053 if (ar->tx_pending[ar->ctrl_ep]) {
2054 left = wait_event_interruptible_timeout(ar->event_wq,
2055 ar->tx_pending[ar->ctrl_ep] == 0, WMI_TIMEOUT);
2056 if (left == 0) {
2057 ath6kl_warn("clear wmi ctrl data timeout\n");
2058 ret = -ETIMEDOUT;
2059 } else if (left < 0) {
2060 ath6kl_warn("clear wmi ctrl data failed: %d\n", left);
2061 ret = left;
2062 }
2063 }
2064
2065 return ret;
2066} 2087}
2067 2088
2068static int ath6kl_wow_resume(struct ath6kl *ar) 2089static int ath6kl_wow_resume(struct ath6kl *ar)
@@ -2109,6 +2130,77 @@ static int ath6kl_wow_resume(struct ath6kl *ar)
2109 return 0; 2130 return 0;
2110} 2131}
2111 2132
2133static int ath6kl_cfg80211_deepsleep_suspend(struct ath6kl *ar)
2134{
2135 struct ath6kl_vif *vif;
2136 int ret;
2137
2138 vif = ath6kl_vif_first(ar);
2139 if (!vif)
2140 return -EIO;
2141
2142 if (!ath6kl_cfg80211_ready(vif))
2143 return -EIO;
2144
2145 ath6kl_cfg80211_stop_all(ar);
2146
2147 /* Save the current power mode before enabling power save */
2148 ar->wmi->saved_pwr_mode = ar->wmi->pwr_mode;
2149
2150 ret = ath6kl_wmi_powermode_cmd(ar->wmi, 0, REC_POWER);
2151 if (ret)
2152 return ret;
2153
2154 /* Disable WOW mode */
2155 ret = ath6kl_wmi_set_wow_mode_cmd(ar->wmi, vif->fw_vif_idx,
2156 ATH6KL_WOW_MODE_DISABLE,
2157 0, 0);
2158 if (ret)
2159 return ret;
2160
2161 /* Flush all non control pkts in TX path */
2162 ath6kl_tx_data_cleanup(ar);
2163
2164 ret = ath6kl_cfg80211_host_sleep(ar, vif);
2165 if (ret)
2166 return ret;
2167
2168 return 0;
2169}
2170
2171static int ath6kl_cfg80211_deepsleep_resume(struct ath6kl *ar)
2172{
2173 struct ath6kl_vif *vif;
2174 int ret;
2175
2176 vif = ath6kl_vif_first(ar);
2177
2178 if (!vif)
2179 return -EIO;
2180
2181 if (ar->wmi->pwr_mode != ar->wmi->saved_pwr_mode) {
2182 ret = ath6kl_wmi_powermode_cmd(ar->wmi, 0,
2183 ar->wmi->saved_pwr_mode);
2184 if (ret)
2185 return ret;
2186 }
2187
2188 ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx,
2189 ATH6KL_HOST_MODE_AWAKE);
2190 if (ret)
2191 return ret;
2192
2193 ar->state = ATH6KL_STATE_ON;
2194
2195 /* Reset scan parameter to default values */
2196 ret = ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx,
2197 0, 0, 0, 0, 0, 0, 3, 0, 0, 0);
2198 if (ret)
2199 return ret;
2200
2201 return 0;
2202}
2203
2112int ath6kl_cfg80211_suspend(struct ath6kl *ar, 2204int ath6kl_cfg80211_suspend(struct ath6kl *ar,
2113 enum ath6kl_cfg_suspend_mode mode, 2205 enum ath6kl_cfg_suspend_mode mode,
2114 struct cfg80211_wowlan *wow) 2206 struct cfg80211_wowlan *wow)
@@ -2137,15 +2229,12 @@ int ath6kl_cfg80211_suspend(struct ath6kl *ar,
2137 2229
2138 case ATH6KL_CFG_SUSPEND_DEEPSLEEP: 2230 case ATH6KL_CFG_SUSPEND_DEEPSLEEP:
2139 2231
2140 ath6kl_cfg80211_stop_all(ar); 2232 ath6kl_dbg(ATH6KL_DBG_SUSPEND, "deep sleep suspend\n");
2141 2233
2142 /* save the current power mode before enabling power save */ 2234 ret = ath6kl_cfg80211_deepsleep_suspend(ar);
2143 ar->wmi->saved_pwr_mode = ar->wmi->pwr_mode;
2144
2145 ret = ath6kl_wmi_powermode_cmd(ar->wmi, 0, REC_POWER);
2146 if (ret) { 2235 if (ret) {
2147 ath6kl_warn("wmi powermode command failed during suspend: %d\n", 2236 ath6kl_err("deepsleep suspend failed: %d\n", ret);
2148 ret); 2237 return ret;
2149 } 2238 }
2150 2239
2151 ar->state = ATH6KL_STATE_DEEPSLEEP; 2240 ar->state = ATH6KL_STATE_DEEPSLEEP;
@@ -2206,17 +2295,13 @@ int ath6kl_cfg80211_resume(struct ath6kl *ar)
2206 break; 2295 break;
2207 2296
2208 case ATH6KL_STATE_DEEPSLEEP: 2297 case ATH6KL_STATE_DEEPSLEEP:
2209 if (ar->wmi->pwr_mode != ar->wmi->saved_pwr_mode) { 2298 ath6kl_dbg(ATH6KL_DBG_SUSPEND, "deep sleep resume\n");
2210 ret = ath6kl_wmi_powermode_cmd(ar->wmi, 0,
2211 ar->wmi->saved_pwr_mode);
2212 if (ret) {
2213 ath6kl_warn("wmi powermode command failed during resume: %d\n",
2214 ret);
2215 }
2216 }
2217
2218 ar->state = ATH6KL_STATE_ON;
2219 2299
2300 ret = ath6kl_cfg80211_deepsleep_resume(ar);
2301 if (ret) {
2302 ath6kl_warn("deep sleep resume failed: %d\n", ret);
2303 return ret;
2304 }
2220 break; 2305 break;
2221 2306
2222 case ATH6KL_STATE_CUTPOWER: 2307 case ATH6KL_STATE_CUTPOWER:
@@ -2747,6 +2832,21 @@ static bool ath6kl_mgmt_powersave_ap(struct ath6kl_vif *vif,
2747 return false; 2832 return false;
2748} 2833}
2749 2834
2835/* Check if SSID length is greater than DIRECT- */
2836static bool ath6kl_is_p2p_go_ssid(const u8 *buf, size_t len)
2837{
2838 const struct ieee80211_mgmt *mgmt;
2839 mgmt = (const struct ieee80211_mgmt *) buf;
2840
2841 /* variable[1] contains the SSID tag length */
2842 if (buf + len >= &mgmt->u.probe_resp.variable[1] &&
2843 (mgmt->u.probe_resp.variable[1] > P2P_WILDCARD_SSID_LEN)) {
2844 return true;
2845 }
2846
2847 return false;
2848}
2849
2750static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, 2850static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
2751 struct ieee80211_channel *chan, bool offchan, 2851 struct ieee80211_channel *chan, bool offchan,
2752 enum nl80211_channel_type channel_type, 2852 enum nl80211_channel_type channel_type,
@@ -2761,11 +2861,11 @@ static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
2761 bool more_data, queued; 2861 bool more_data, queued;
2762 2862
2763 mgmt = (const struct ieee80211_mgmt *) buf; 2863 mgmt = (const struct ieee80211_mgmt *) buf;
2764 if (buf + len >= mgmt->u.probe_resp.variable && 2864 if (vif->nw_type == AP_NETWORK && test_bit(CONNECTED, &vif->flags) &&
2765 vif->nw_type == AP_NETWORK && test_bit(CONNECTED, &vif->flags) && 2865 ieee80211_is_probe_resp(mgmt->frame_control) &&
2766 ieee80211_is_probe_resp(mgmt->frame_control)) { 2866 ath6kl_is_p2p_go_ssid(buf, len)) {
2767 /* 2867 /*
2768 * Send Probe Response frame in AP mode using a separate WMI 2868 * Send Probe Response frame in GO mode using a separate WMI
2769 * command to allow the target to fill in the generic IEs. 2869 * command to allow the target to fill in the generic IEs.
2770 */ 2870 */
2771 *cookie = 0; /* TX status not supported */ 2871 *cookie = 0; /* TX status not supported */
@@ -2833,6 +2933,8 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
2833 if (vif->sme_state != SME_DISCONNECTED) 2933 if (vif->sme_state != SME_DISCONNECTED)
2834 return -EBUSY; 2934 return -EBUSY;
2835 2935
2936 ath6kl_cfg80211_scan_complete_event(vif, true);
2937
2836 for (i = 0; i < ar->wiphy->max_sched_scan_ssids; i++) { 2938 for (i = 0; i < ar->wiphy->max_sched_scan_ssids; i++) {
2837 ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, 2939 ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx,
2838 i, DISABLE_SSID_FLAG, 2940 i, DISABLE_SSID_FLAG,
diff --git a/drivers/net/wireless/ath/ath6kl/common.h b/drivers/net/wireless/ath/ath6kl/common.h
index a60e78c0472f..71f54501464a 100644
--- a/drivers/net/wireless/ath/ath6kl/common.h
+++ b/drivers/net/wireless/ath/ath6kl/common.h
@@ -22,7 +22,8 @@
22 22
23#define ATH6KL_MAX_IE 256 23#define ATH6KL_MAX_IE 256
24 24
25extern int ath6kl_printk(const char *level, const char *fmt, ...); 25extern __printf(2, 3)
26int ath6kl_printk(const char *level, const char *fmt, ...);
26 27
27/* 28/*
28 * Reflects the version of binary interface exposed by ATH6KL target 29 * Reflects the version of binary interface exposed by ATH6KL target
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h
index f1dd8906be45..17697eb054fa 100644
--- a/drivers/net/wireless/ath/ath6kl/core.h
+++ b/drivers/net/wireless/ath/ath6kl/core.h
@@ -205,6 +205,8 @@ struct ath6kl_fw_ie {
205#define ATH6KL_CONF_ENABLE_TX_BURST BIT(3) 205#define ATH6KL_CONF_ENABLE_TX_BURST BIT(3)
206#define ATH6KL_CONF_UART_DEBUG BIT(4) 206#define ATH6KL_CONF_UART_DEBUG BIT(4)
207 207
208#define P2P_WILDCARD_SSID_LEN 7 /* DIRECT- */
209
208enum wlan_low_pwr_state { 210enum wlan_low_pwr_state {
209 WLAN_POWER_STATE_ON, 211 WLAN_POWER_STATE_ON,
210 WLAN_POWER_STATE_CUT_PWR, 212 WLAN_POWER_STATE_CUT_PWR,
diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c
index 552adb3f80d0..2bcd45095eb9 100644
--- a/drivers/net/wireless/ath/ath6kl/debug.c
+++ b/drivers/net/wireless/ath/ath6kl/debug.c
@@ -622,6 +622,12 @@ static ssize_t read_file_tgt_stats(struct file *file, char __user *user_buf,
622 "Num disconnects", tgt_stats->cs_discon_cnt); 622 "Num disconnects", tgt_stats->cs_discon_cnt);
623 len += scnprintf(buf + len, buf_len - len, "%20s %10d\n", 623 len += scnprintf(buf + len, buf_len - len, "%20s %10d\n",
624 "Beacon avg rssi", tgt_stats->cs_ave_beacon_rssi); 624 "Beacon avg rssi", tgt_stats->cs_ave_beacon_rssi);
625 len += scnprintf(buf + len, buf_len - len, "%20s %10d\n",
626 "ARP pkt received", tgt_stats->arp_received);
627 len += scnprintf(buf + len, buf_len - len, "%20s %10d\n",
628 "ARP pkt matched", tgt_stats->arp_matched);
629 len += scnprintf(buf + len, buf_len - len, "%20s %10d\n",
630 "ARP pkt replied", tgt_stats->arp_replied);
625 631
626 if (len > buf_len) 632 if (len > buf_len)
627 len = buf_len; 633 len = buf_len;
diff --git a/drivers/net/wireless/ath/ath6kl/htc.c b/drivers/net/wireless/ath/ath6kl/htc.c
index 4849d99cce77..5dfb7cc27aa3 100644
--- a/drivers/net/wireless/ath/ath6kl/htc.c
+++ b/drivers/net/wireless/ath/ath6kl/htc.c
@@ -1353,7 +1353,9 @@ static int ath6kl_htc_rx_setup(struct htc_target *target,
1353 sizeof(*htc_hdr)); 1353 sizeof(*htc_hdr));
1354 1354
1355 if (!htc_valid_rx_frame_len(target, ep->eid, full_len)) { 1355 if (!htc_valid_rx_frame_len(target, ep->eid, full_len)) {
1356 ath6kl_warn("Rx buffer requested with invalid length\n"); 1356 ath6kl_warn("Rx buffer requested with invalid length htc_hdr:eid %d, flags 0x%x, len %d\n",
1357 htc_hdr->eid, htc_hdr->flags,
1358 le16_to_cpu(htc_hdr->payld_len));
1357 return -EINVAL; 1359 return -EINVAL;
1358 } 1360 }
1359 1361
diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c
index 229e1922ebe4..7f3addd6c944 100644
--- a/drivers/net/wireless/ath/ath6kl/main.c
+++ b/drivers/net/wireless/ath/ath6kl/main.c
@@ -756,6 +756,10 @@ static void ath6kl_update_target_stats(struct ath6kl_vif *vif, u8 *ptr, u32 len)
756 stats->wow_evt_discarded += 756 stats->wow_evt_discarded +=
757 le16_to_cpu(tgt_stats->wow_stats.wow_evt_discarded); 757 le16_to_cpu(tgt_stats->wow_stats.wow_evt_discarded);
758 758
759 stats->arp_received = le32_to_cpu(tgt_stats->arp_stats.arp_received);
760 stats->arp_replied = le32_to_cpu(tgt_stats->arp_stats.arp_replied);
761 stats->arp_matched = le32_to_cpu(tgt_stats->arp_stats.arp_matched);
762
759 if (test_bit(STATS_UPDATE_PEND, &vif->flags)) { 763 if (test_bit(STATS_UPDATE_PEND, &vif->flags)) {
760 clear_bit(STATS_UPDATE_PEND, &vif->flags); 764 clear_bit(STATS_UPDATE_PEND, &vif->flags);
761 wake_up(&ar->event_wq); 765 wake_up(&ar->event_wq);
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c
index 2b442332cd0f..7654e8e286d3 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.c
+++ b/drivers/net/wireless/ath/ath6kl/wmi.c
@@ -3032,6 +3032,9 @@ int ath6kl_wmi_ap_set_mlme(struct wmi *wmip, u8 if_idx, u8 cmd, const u8 *mac,
3032 cm->reason = cpu_to_le16(reason); 3032 cm->reason = cpu_to_le16(reason);
3033 cm->cmd = cmd; 3033 cm->cmd = cmd;
3034 3034
3035 ath6kl_dbg(ATH6KL_DBG_WMI, "ap_set_mlme: cmd=%d reason=%d\n", cm->cmd,
3036 cm->reason);
3037
3035 return ath6kl_wmi_cmd_send(wmip, if_idx, skb, WMI_AP_SET_MLME_CMDID, 3038 return ath6kl_wmi_cmd_send(wmip, if_idx, skb, WMI_AP_SET_MLME_CMDID,
3036 NO_SYNC_WMIFLAG); 3039 NO_SYNC_WMIFLAG);
3037} 3040}