Merge remote branch 'wireless-next/master' into ath6kl-next
authorKalle Valo <kvalo@qca.qualcomm.com>
Mon, 26 Mar 2012 13:26:56 +0000 (16:26 +0300)
committerKalle Valo <kvalo@qca.qualcomm.com>
Mon, 26 Mar 2012 13:26:56 +0000 (16:26 +0300)
drivers/net/wireless/ath/ath6kl/cfg80211.c
drivers/net/wireless/ath/ath6kl/common.h
drivers/net/wireless/ath/ath6kl/core.h
drivers/net/wireless/ath/ath6kl/debug.c
drivers/net/wireless/ath/ath6kl/htc.c
drivers/net/wireless/ath/ath6kl/main.c
drivers/net/wireless/ath/ath6kl/wmi.c

index 00d3895..8091028 100644 (file)
@@ -1924,12 +1924,61 @@ static int ath6kl_wow_sta(struct ath6kl *ar, struct ath6kl_vif *vif)
        return 0;
 }
 
+static int is_hsleep_mode_procsed(struct ath6kl_vif *vif)
+{
+       return test_bit(HOST_SLEEP_MODE_CMD_PROCESSED, &vif->flags);
+}
+
+static bool is_ctrl_ep_empty(struct ath6kl *ar)
+{
+       return !ar->tx_pending[ar->ctrl_ep];
+}
+
+static int ath6kl_cfg80211_host_sleep(struct ath6kl *ar, struct ath6kl_vif *vif)
+{
+       int ret, left;
+
+       clear_bit(HOST_SLEEP_MODE_CMD_PROCESSED, &vif->flags);
+
+       ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx,
+                                                ATH6KL_HOST_MODE_ASLEEP);
+       if (ret)
+               return ret;
+
+       left = wait_event_interruptible_timeout(ar->event_wq,
+                                               is_hsleep_mode_procsed(vif),
+                                               WMI_TIMEOUT);
+       if (left == 0) {
+               ath6kl_warn("timeout, didn't get host sleep cmd processed event\n");
+               ret = -ETIMEDOUT;
+       } else if (left < 0) {
+               ath6kl_warn("error while waiting for host sleep cmd processed event %d\n",
+                           left);
+               ret = left;
+       }
+
+       if (ar->tx_pending[ar->ctrl_ep]) {
+               left = wait_event_interruptible_timeout(ar->event_wq,
+                                                       is_ctrl_ep_empty(ar),
+                                                       WMI_TIMEOUT);
+               if (left == 0) {
+                       ath6kl_warn("clear wmi ctrl data timeout\n");
+                       ret = -ETIMEDOUT;
+               } else if (left < 0) {
+                       ath6kl_warn("clear wmi ctrl data failed: %d\n", left);
+                       ret = left;
+               }
+       }
+
+       return ret;
+}
+
 static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
 {
        struct in_device *in_dev;
        struct in_ifaddr *ifa;
        struct ath6kl_vif *vif;
-       int ret, left;
+       int ret;
        u32 filter = 0;
        u16 i, bmiss_time;
        u8 index = 0;
@@ -2030,39 +2079,11 @@ skip_arp:
        if (ret)
                return ret;
 
-       clear_bit(HOST_SLEEP_MODE_CMD_PROCESSED, &vif->flags);
-
-       ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx,
-                                                ATH6KL_HOST_MODE_ASLEEP);
+       ret = ath6kl_cfg80211_host_sleep(ar, vif);
        if (ret)
                return ret;
 
-       left = wait_event_interruptible_timeout(ar->event_wq,
-                       test_bit(HOST_SLEEP_MODE_CMD_PROCESSED, &vif->flags),
-                       WMI_TIMEOUT);
-       if (left == 0) {
-               ath6kl_warn("timeout, didn't get host sleep cmd "
-                           "processed event\n");
-               ret = -ETIMEDOUT;
-       } else if (left < 0) {
-               ath6kl_warn("error while waiting for host sleep cmd "
-                           "processed event %d\n", left);
-               ret = left;
-       }
-
-       if (ar->tx_pending[ar->ctrl_ep]) {
-               left = wait_event_interruptible_timeout(ar->event_wq,
-                               ar->tx_pending[ar->ctrl_ep] == 0, WMI_TIMEOUT);
-               if (left == 0) {
-                       ath6kl_warn("clear wmi ctrl data timeout\n");
-                       ret = -ETIMEDOUT;
-               } else if (left < 0) {
-                       ath6kl_warn("clear wmi ctrl data failed: %d\n", left);
-                       ret = left;
-               }
-       }
-
-       return ret;
+       return 0;
 }
 
 static int ath6kl_wow_resume(struct ath6kl *ar)
@@ -2109,6 +2130,77 @@ static int ath6kl_wow_resume(struct ath6kl *ar)
        return 0;
 }
 
+static int ath6kl_cfg80211_deepsleep_suspend(struct ath6kl *ar)
+{
+       struct ath6kl_vif *vif;
+       int ret;
+
+       vif = ath6kl_vif_first(ar);
+       if (!vif)
+               return -EIO;
+
+       if (!ath6kl_cfg80211_ready(vif))
+               return -EIO;
+
+       ath6kl_cfg80211_stop_all(ar);
+
+       /* Save the current power mode before enabling power save */
+       ar->wmi->saved_pwr_mode = ar->wmi->pwr_mode;
+
+       ret = ath6kl_wmi_powermode_cmd(ar->wmi, 0, REC_POWER);
+       if (ret)
+               return ret;
+
+       /* Disable WOW mode */
+       ret = ath6kl_wmi_set_wow_mode_cmd(ar->wmi, vif->fw_vif_idx,
+                                         ATH6KL_WOW_MODE_DISABLE,
+                                         0, 0);
+       if (ret)
+               return ret;
+
+       /* Flush all non control pkts in TX path */
+       ath6kl_tx_data_cleanup(ar);
+
+       ret = ath6kl_cfg80211_host_sleep(ar, vif);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static int ath6kl_cfg80211_deepsleep_resume(struct ath6kl *ar)
+{
+       struct ath6kl_vif *vif;
+       int ret;
+
+       vif = ath6kl_vif_first(ar);
+
+       if (!vif)
+               return -EIO;
+
+       if (ar->wmi->pwr_mode != ar->wmi->saved_pwr_mode) {
+               ret = ath6kl_wmi_powermode_cmd(ar->wmi, 0,
+                                              ar->wmi->saved_pwr_mode);
+               if (ret)
+                       return ret;
+       }
+
+       ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx,
+                                                ATH6KL_HOST_MODE_AWAKE);
+       if (ret)
+               return ret;
+
+       ar->state = ATH6KL_STATE_ON;
+
+       /* Reset scan parameter to default values */
+       ret = ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx,
+                                       0, 0, 0, 0, 0, 0, 3, 0, 0, 0);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
 int ath6kl_cfg80211_suspend(struct ath6kl *ar,
                            enum ath6kl_cfg_suspend_mode mode,
                            struct cfg80211_wowlan *wow)
@@ -2137,15 +2229,12 @@ int ath6kl_cfg80211_suspend(struct ath6kl *ar,
 
        case ATH6KL_CFG_SUSPEND_DEEPSLEEP:
 
-               ath6kl_cfg80211_stop_all(ar);
+               ath6kl_dbg(ATH6KL_DBG_SUSPEND, "deep sleep suspend\n");
 
-               /* save the current power mode before enabling power save */
-               ar->wmi->saved_pwr_mode = ar->wmi->pwr_mode;
-
-               ret = ath6kl_wmi_powermode_cmd(ar->wmi, 0, REC_POWER);
+               ret = ath6kl_cfg80211_deepsleep_suspend(ar);
                if (ret) {
-                       ath6kl_warn("wmi powermode command failed during suspend: %d\n",
-                                   ret);
+                       ath6kl_err("deepsleep suspend failed: %d\n", ret);
+                       return ret;
                }
 
                ar->state = ATH6KL_STATE_DEEPSLEEP;
@@ -2206,17 +2295,13 @@ int ath6kl_cfg80211_resume(struct ath6kl *ar)
                break;
 
        case ATH6KL_STATE_DEEPSLEEP:
-               if (ar->wmi->pwr_mode != ar->wmi->saved_pwr_mode) {
-                       ret = ath6kl_wmi_powermode_cmd(ar->wmi, 0,
-                                                      ar->wmi->saved_pwr_mode);
-                       if (ret) {
-                               ath6kl_warn("wmi powermode command failed during resume: %d\n",
-                                           ret);
-                       }
-               }
-
-               ar->state = ATH6KL_STATE_ON;
+               ath6kl_dbg(ATH6KL_DBG_SUSPEND, "deep sleep resume\n");
 
+               ret = ath6kl_cfg80211_deepsleep_resume(ar);
+               if (ret) {
+                       ath6kl_warn("deep sleep resume failed: %d\n", ret);
+                       return ret;
+               }
                break;
 
        case ATH6KL_STATE_CUTPOWER:
@@ -2747,6 +2832,21 @@ static bool ath6kl_mgmt_powersave_ap(struct ath6kl_vif *vif,
        return false;
 }
 
+/* Check if SSID length is greater than DIRECT- */
+static bool ath6kl_is_p2p_go_ssid(const u8 *buf, size_t len)
+{
+       const struct ieee80211_mgmt *mgmt;
+       mgmt = (const struct ieee80211_mgmt *) buf;
+
+       /* variable[1] contains the SSID tag length */
+       if (buf + len >= &mgmt->u.probe_resp.variable[1] &&
+           (mgmt->u.probe_resp.variable[1] > P2P_WILDCARD_SSID_LEN)) {
+               return true;
+       }
+
+       return false;
+}
+
 static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
                          struct ieee80211_channel *chan, bool offchan,
                          enum nl80211_channel_type channel_type,
@@ -2761,11 +2861,11 @@ static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
        bool more_data, queued;
 
        mgmt = (const struct ieee80211_mgmt *) buf;
-       if (buf + len >= mgmt->u.probe_resp.variable &&
-           vif->nw_type == AP_NETWORK && test_bit(CONNECTED, &vif->flags) &&
-           ieee80211_is_probe_resp(mgmt->frame_control)) {
+       if (vif->nw_type == AP_NETWORK && test_bit(CONNECTED, &vif->flags) &&
+           ieee80211_is_probe_resp(mgmt->frame_control) &&
+           ath6kl_is_p2p_go_ssid(buf, len)) {
                /*
-                * Send Probe Response frame in AP mode using a separate WMI
+                * Send Probe Response frame in GO mode using a separate WMI
                 * command to allow the target to fill in the generic IEs.
                 */
                *cookie = 0; /* TX status not supported */
@@ -2833,6 +2933,8 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
        if (vif->sme_state != SME_DISCONNECTED)
                return -EBUSY;
 
+       ath6kl_cfg80211_scan_complete_event(vif, true);
+
        for (i = 0; i < ar->wiphy->max_sched_scan_ssids; i++) {
                ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx,
                                          i, DISABLE_SSID_FLAG,
index a60e78c..71f5450 100644 (file)
@@ -22,7 +22,8 @@
 
 #define ATH6KL_MAX_IE                  256
 
-extern int ath6kl_printk(const char *level, const char *fmt, ...);
+extern __printf(2, 3)
+int ath6kl_printk(const char *level, const char *fmt, ...);
 
 /*
  * Reflects the version of binary interface exposed by ATH6KL target
index f1dd890..17697eb 100644 (file)
@@ -205,6 +205,8 @@ struct ath6kl_fw_ie {
 #define ATH6KL_CONF_ENABLE_TX_BURST            BIT(3)
 #define ATH6KL_CONF_UART_DEBUG                 BIT(4)
 
+#define P2P_WILDCARD_SSID_LEN                  7 /* DIRECT- */
+
 enum wlan_low_pwr_state {
        WLAN_POWER_STATE_ON,
        WLAN_POWER_STATE_CUT_PWR,
index 552adb3..2bcd450 100644 (file)
@@ -622,6 +622,12 @@ static ssize_t read_file_tgt_stats(struct file *file, char __user *user_buf,
                         "Num disconnects", tgt_stats->cs_discon_cnt);
        len += scnprintf(buf + len, buf_len - len, "%20s %10d\n",
                         "Beacon avg rssi", tgt_stats->cs_ave_beacon_rssi);
+       len += scnprintf(buf + len, buf_len - len, "%20s %10d\n",
+                        "ARP pkt received", tgt_stats->arp_received);
+       len += scnprintf(buf + len, buf_len - len, "%20s %10d\n",
+                        "ARP pkt matched", tgt_stats->arp_matched);
+       len += scnprintf(buf + len, buf_len - len, "%20s %10d\n",
+                        "ARP pkt replied", tgt_stats->arp_replied);
 
        if (len > buf_len)
                len = buf_len;
index 4849d99..5dfb7cc 100644 (file)
@@ -1353,7 +1353,9 @@ static int ath6kl_htc_rx_setup(struct htc_target *target,
                                        sizeof(*htc_hdr));
 
        if (!htc_valid_rx_frame_len(target, ep->eid, full_len)) {
-               ath6kl_warn("Rx buffer requested with invalid length\n");
+               ath6kl_warn("Rx buffer requested with invalid length htc_hdr:eid %d, flags 0x%x, len %d\n",
+                           htc_hdr->eid, htc_hdr->flags,
+                           le16_to_cpu(htc_hdr->payld_len));
                return -EINVAL;
        }
 
index 229e192..7f3addd 100644 (file)
@@ -756,6 +756,10 @@ static void ath6kl_update_target_stats(struct ath6kl_vif *vif, u8 *ptr, u32 len)
        stats->wow_evt_discarded +=
                le16_to_cpu(tgt_stats->wow_stats.wow_evt_discarded);
 
+       stats->arp_received = le32_to_cpu(tgt_stats->arp_stats.arp_received);
+       stats->arp_replied = le32_to_cpu(tgt_stats->arp_stats.arp_replied);
+       stats->arp_matched = le32_to_cpu(tgt_stats->arp_stats.arp_matched);
+
        if (test_bit(STATS_UPDATE_PEND, &vif->flags)) {
                clear_bit(STATS_UPDATE_PEND, &vif->flags);
                wake_up(&ar->event_wq);
index 2b44233..7654e8e 100644 (file)
@@ -3032,6 +3032,9 @@ int ath6kl_wmi_ap_set_mlme(struct wmi *wmip, u8 if_idx, u8 cmd, const u8 *mac,
        cm->reason = cpu_to_le16(reason);
        cm->cmd = cmd;
 
+       ath6kl_dbg(ATH6KL_DBG_WMI, "ap_set_mlme: cmd=%d reason=%d\n", cm->cmd,
+                  cm->reason);
+
        return ath6kl_wmi_cmd_send(wmip, if_idx, skb, WMI_AP_SET_MLME_CMDID,
                                   NO_SYNC_WMIFLAG);
 }