ath6kl: support rssi threshold for sched scan
authorThomas Pedersen <c_tpeder@qca.qualcomm.com>
Thu, 21 Jun 2012 19:50:08 +0000 (12:50 -0700)
committerKalle Valo <kvalo@qca.qualcomm.com>
Wed, 24 Oct 2012 08:49:31 +0000 (11:49 +0300)
The ath6kl firmware can filter scan results based on rssi. This is
useful to limit hosts wakeups on scheduled scans.

Signed-off-by: Thomas Pedersen <c_tpeder@qca.qualcomm.com>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
drivers/net/wireless/ath/ath6kl/cfg80211.c
drivers/net/wireless/ath/ath6kl/core.h
drivers/net/wireless/ath/ath6kl/wmi.c
drivers/net/wireless/ath/ath6kl/wmi.h

index 2770899..a5f3d6e 100644 (file)
@@ -3211,7 +3211,7 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
        struct ath6kl *ar = ath6kl_priv(dev);
        struct ath6kl_vif *vif = netdev_priv(dev);
        u16 interval;
-       int ret;
+       int ret, rssi_thold;
 
        if (ar->state != ATH6KL_STATE_ON)
                return -EIO;
@@ -3244,6 +3244,23 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
                        return ret;
        }
 
+       if (test_bit(ATH6KL_FW_CAPABILITY_RSSI_SCAN_THOLD,
+                    ar->fw_capabilities)) {
+               if (request->rssi_thold <= NL80211_SCAN_RSSI_THOLD_OFF)
+                       rssi_thold = 0;
+               else if (request->rssi_thold < -127)
+                       rssi_thold = -127;
+               else
+                       rssi_thold = request->rssi_thold;
+
+               ret = ath6kl_wmi_set_rssi_filter_cmd(ar->wmi, vif->fw_vif_idx,
+                                                    rssi_thold);
+               if (ret) {
+                       ath6kl_err("failed to set RSSI threshold for scan\n");
+                       return ret;
+               }
+       }
+
        /* fw uses seconds, also make sure that it's >0 */
        interval = max_t(u16, 1, request->interval / 1000);
 
index cec49a3..a6f0d2c 100644 (file)
@@ -115,6 +115,9 @@ enum ath6kl_fw_capability {
         */
        ATH6KL_FW_CAPABILITY_SCHED_SCAN_MATCH_LIST,
 
+       /* Firmware supports filtering BSS results by RSSI */
+       ATH6KL_FW_CAPABILITY_RSSI_SCAN_THOLD,
+
        /* this needs to be last */
        ATH6KL_FW_CAPABILITY_MAX,
 };
index c30ab4b..9673f27 100644 (file)
@@ -1531,6 +1531,24 @@ static int ath6kl_wmi_cac_event_rx(struct wmi *wmi, u8 *datap, int len,
        return 0;
 }
 
+int ath6kl_wmi_set_rssi_filter_cmd(struct wmi *wmi, u8 if_idx, s8 rssi)
+{
+       struct sk_buff *skb;
+       struct wmi_set_rssi_filter_cmd *cmd;
+       int ret;
+
+       skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
+       if (!skb)
+               return -ENOMEM;
+
+       cmd = (struct wmi_set_rssi_filter_cmd *) skb->data;
+       cmd->rssi = rssi;
+
+       ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_RSSI_FILTER_CMDID,
+                                 NO_SYNC_WMIFLAG);
+       return ret;
+}
+
 static int ath6kl_wmi_send_snr_threshold_params(struct wmi *wmi,
                        struct wmi_snr_threshold_params_cmd *snr_cmd)
 {
index 43339ac..b5deaff 100644 (file)
@@ -628,6 +628,10 @@ enum wmi_cmd_id {
        WMI_SET_MCASTRATE,
 
        WMI_STA_BMISS_ENHANCE_CMDID,
+
+       WMI_SET_REGDOMAIN_CMDID,
+
+       WMI_SET_RSSI_FILTER_CMDID,
 };
 
 enum wmi_mgmt_frame_type {
@@ -1276,6 +1280,11 @@ struct wmi_snr_threshold_params_cmd {
        u8 reserved[3];
 } __packed;
 
+/* Don't report BSSs with signal (RSSI) below this threshold */
+struct wmi_set_rssi_filter_cmd {
+       s8 rssi;
+} __packed;
+
 enum wmi_preamble_policy {
        WMI_IGNORE_BARKER_IN_ERP = 0,
        WMI_FOLLOW_BARKER_IN_ERP,
@@ -2592,6 +2601,7 @@ int ath6kl_wmi_add_wow_pattern_cmd(struct wmi *wmi, u8 if_idx,
                                   const u8 *mask);
 int ath6kl_wmi_del_wow_pattern_cmd(struct wmi *wmi, u8 if_idx,
                                   u16 list_id, u16 filter_id);
+int ath6kl_wmi_set_rssi_filter_cmd(struct wmi *wmi, u8 if_idx, s8 rssi);
 int ath6kl_wmi_set_roam_lrssi_cmd(struct wmi *wmi, u8 lrssi);
 int ath6kl_wmi_ap_set_dtim_cmd(struct wmi *wmi, u8 if_idx, u32 dtim_period);
 int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid);