iwlwifi: mvm: Add support for Energy based scan (EBS)
authorHaim Dreyfuss <haim.dreyfuss@intel.com>
Sun, 6 Apr 2014 08:19:09 +0000 (11:19 +0300)
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Sun, 13 Apr 2014 19:23:17 +0000 (22:23 +0300)
This patch enables Energy Based Scan (EBS) - intended to detect energy
on 5 GHz band channels. Passive scan on this band takes up to 2.64 sec
assuming 110mSec per-channel * 24 channels. EBS is designed to detect
energy on channels with intensive Wifi activity as well as those where
only beacons are transmitted. EBS completes sampling all channels within
shortest beacon frame transmission time. Total EBS duration is about 100
msec (typical beacon interval).
Detecting Wifi activity on 5 GHz band channels can significantly reduce
scan duration thus saving time and power. EBS failure reported by FW
disables EBS for current connection. It is re-enabled upon new
connection attempt on any WLAN interface.

Signed-off-by: Haim Dreyfuss <haim.dreyfuss@intel.com>
Signed-off-by: Alexander Bondar <alexander.bondar@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
drivers/net/wireless/iwlwifi/iwl-fw.h
drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h
drivers/net/wireless/iwlwifi/mvm/fw-api.h
drivers/net/wireless/iwlwifi/mvm/mac80211.c
drivers/net/wireless/iwlwifi/mvm/mvm.h
drivers/net/wireless/iwlwifi/mvm/scan.c

index 265d6f194f2edd674e62e33405a1dc605a4f09d9..f5927d0cf9b66dca59c13ede6e3a6627a368fecf 100644 (file)
@@ -91,6 +91,7 @@
  * @IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD: P2P client supports uAPSD power save
  * @IWL_UCODE_TLV_FLAGS_BCAST_FILTERING: uCode supports broadcast filtering.
  * @IWL_UCODE_TLV_FLAGS_GO_UAPSD: AP/GO interfaces support uAPSD clients
+ * @IWL_UCODE_TLV_FLAGS_EBS_SUPPORT: this uCode image supports EBS.
  */
 enum iwl_ucode_tlv_flag {
        IWL_UCODE_TLV_FLAGS_PAN                 = BIT(0),
@@ -106,6 +107,7 @@ enum iwl_ucode_tlv_flag {
        IWL_UCODE_TLV_FLAGS_P2P_PM              = BIT(21),
        IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM      = BIT(22),
        IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_SCM      = BIT(23),
+       IWL_UCODE_TLV_FLAGS_EBS_SUPPORT         = BIT(25),
        IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD        = BIT(26),
        IWL_UCODE_TLV_FLAGS_BCAST_FILTERING     = BIT(29),
        IWL_UCODE_TLV_FLAGS_GO_UAPSD            = BIT(30),
index 02856e061115e496a832a8d410af7c612ae5a24d..6174c027ff594e30c29c5c263c1efa33e6a5f5e8 100644 (file)
@@ -538,13 +538,16 @@ struct iwl_scan_offload_schedule {
  *
  * IWL_SCAN_OFFLOAD_FLAG_PASS_ALL: pass all results - no filtering.
  * IWL_SCAN_OFFLOAD_FLAG_CACHED_CHANNEL: add cached channels to partial scan.
- * IWL_SCAN_OFFLOAD_FLAG_ENERGY_SCAN: use energy based scan before partial scan
- *     on A band.
+ * IWL_SCAN_OFFLOAD_FLAG_EBS_QUICK_MODE: EBS duration is 100mSec - typical
+ *     beacon period. Finding channel activity in this mode is not guaranteed.
+ * IWL_SCAN_OFFLOAD_FLAG_EBS_ACCURATE_MODE: EBS duration is 200mSec.
+ *     Assuming beacon period is 100ms finding channel activity is guaranteed.
  */
 enum iwl_scan_offload_flags {
        IWL_SCAN_OFFLOAD_FLAG_PASS_ALL          = BIT(0),
        IWL_SCAN_OFFLOAD_FLAG_CACHED_CHANNEL    = BIT(2),
-       IWL_SCAN_OFFLOAD_FLAG_ENERGY_SCAN       = BIT(3),
+       IWL_SCAN_OFFLOAD_FLAG_EBS_QUICK_MODE    = BIT(5),
+       IWL_SCAN_OFFLOAD_FLAG_EBS_ACCURATE_MODE = BIT(6),
 };
 
 /**
@@ -567,17 +570,24 @@ enum iwl_scan_offload_compleate_status {
        IWL_SCAN_OFFLOAD_ABORTED        = 2,
 };
 
+enum iwl_scan_ebs_status {
+       IWL_SCAN_EBS_SUCCESS,
+       IWL_SCAN_EBS_FAILED,
+       IWL_SCAN_EBS_CHAN_NOT_FOUND,
+};
+
 /**
  * iwl_scan_offload_complete - SCAN_OFFLOAD_COMPLETE_NTF_API_S_VER_1
  * @last_schedule_line:                last schedule line executed (fast or regular)
  * @last_schedule_iteration:   last scan iteration executed before scan abort
  * @status:                    enum iwl_scan_offload_compleate_status
+ * @ebs_status: last EBS status, see IWL_SCAN_EBS_*
  */
 struct iwl_scan_offload_complete {
        u8 last_schedule_line;
        u8 last_schedule_iteration;
        u8 status;
-       u8 reserved;
+       u8 ebs_status;
 } __packed;
 
 /**
index 48554da7a11c8eb9b9fdbec162480786448c9306..309a9b9a94fecc26918f967e7b9e7a01374d43b3 100644 (file)
@@ -71,6 +71,7 @@
 #include "fw-api-power.h"
 #include "fw-api-d3.h"
 #include "fw-api-coex.h"
+#include "fw-api-scan.h"
 
 /* maximal number of Tx queues in any platform */
 #define IWL_MVM_MAX_QUEUES     20
index dc9069b2f48c32f4650286736427d156a477682a..374ecd4593793765d1baeb2ee898bf028c229c6f 100644 (file)
@@ -1694,6 +1694,11 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
                ret = iwl_mvm_add_sta(mvm, vif, sta);
        } else if (old_state == IEEE80211_STA_NONE &&
                   new_state == IEEE80211_STA_AUTH) {
+               /*
+                * EBS may be disabled due to previous failures reported by FW.
+                * Reset EBS status here assuming environment has been changed.
+                */
+               mvm->last_ebs_successful = true;
                ret = 0;
        } else if (old_state == IEEE80211_STA_AUTH &&
                   new_state == IEEE80211_STA_ASSOC) {
index ed2220136c0e93588523fba008944cfac14c4ecc..41184a4ec9a4fe0faf15399a17025df0b67c5925 100644 (file)
@@ -535,6 +535,8 @@ struct iwl_mvm {
        /* Internal station */
        struct iwl_mvm_int_sta aux_sta;
 
+       bool last_ebs_successful;
+
        u8 scan_last_antenna_idx; /* to toggle TX between antennas */
        u8 mgmt_last_antenna_idx;
 
index 9e760d0c5985c820550db3ad3a7deabe53dc8de7..63e7b16edb552be4b626fca9d0b64b064adc6fd2 100644 (file)
@@ -570,9 +570,13 @@ int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm,
        /* scan status must be locked for proper checking */
        lockdep_assert_held(&mvm->mutex);
 
-       IWL_DEBUG_SCAN(mvm, "Scheduled scan completed, status %s\n",
+       IWL_DEBUG_SCAN(mvm,
+                      "Scheduled scan completed, status %s EBS status %s:%d\n",
                       scan_notif->status == IWL_SCAN_OFFLOAD_COMPLETED ?
-                      "completed" : "aborted");
+                      "completed" : "aborted", scan_notif->ebs_status ==
+                      IWL_SCAN_EBS_SUCCESS ? "success" : "failed",
+                      scan_notif->ebs_status);
+
 
        /* only call mac80211 completion if the stop was initiated by FW */
        if (mvm->scan_status == IWL_MVM_SCAN_SCHED) {
@@ -580,6 +584,8 @@ int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm,
                ieee80211_sched_scan_stopped(mvm->hw);
        }
 
+       mvm->last_ebs_successful = !scan_notif->ebs_status;
+
        return 0;
 }
 
@@ -916,6 +922,11 @@ int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm,
                scan_req.flags |= cpu_to_le16(IWL_SCAN_OFFLOAD_FLAG_PASS_ALL);
        }
 
+       if (mvm->last_ebs_successful &&
+           mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_EBS_SUPPORT)
+               scan_req.flags |=
+                       cpu_to_le16(IWL_SCAN_OFFLOAD_FLAG_EBS_ACCURATE_MODE);
+
        return iwl_mvm_send_cmd_pdu(mvm, SCAN_OFFLOAD_REQUEST_CMD, CMD_SYNC,
                                    sizeof(scan_req), &scan_req);
 }