Commit 35a000b7 authored by David Spinadel's avatar David Spinadel Committed by Johannes Berg

iwlwifi: mvm: support sched scan if supported by the fw

Add support for scheduled scan according to firmware support.
Signed-off-by: default avatarDavid Spinadel <david.spinadel@intel.com>
Reviewed-by: default avatarEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 20f1a5de
...@@ -75,6 +75,8 @@ ...@@ -75,6 +75,8 @@
* @IWL_UCODE_TLV_FLAGS_P2P: This uCode image supports P2P. * @IWL_UCODE_TLV_FLAGS_P2P: This uCode image supports P2P.
* @IWL_UCODE_TLV_FLAGS_DW_BC_TABLE: The SCD byte count table is in DWORDS * @IWL_UCODE_TLV_FLAGS_DW_BC_TABLE: The SCD byte count table is in DWORDS
* @IWL_UCODE_TLV_FLAGS_UAPSD: This uCode image supports uAPSD * @IWL_UCODE_TLV_FLAGS_UAPSD: This uCode image supports uAPSD
* @IWL_UCODE_TLV_FLAGS_SHORT_BL: 16 entries of black list instead of 64 in scan
* offload profile config command.
* @IWL_UCODE_TLV_FLAGS_RX_ENERGY_API: supports rx signal strength api * @IWL_UCODE_TLV_FLAGS_RX_ENERGY_API: supports rx signal strength api
* @IWL_UCODE_TLV_FLAGS_TIME_EVENT_API_V2: using the new time event API. * @IWL_UCODE_TLV_FLAGS_TIME_EVENT_API_V2: using the new time event API.
* @IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS: D3 image supports up to six * @IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS: D3 image supports up to six
...@@ -82,6 +84,7 @@ ...@@ -82,6 +84,7 @@
* @IWL_UCODE_TLV_FLAGS_BF_UPDATED: new beacon filtering API * @IWL_UCODE_TLV_FLAGS_BF_UPDATED: new beacon filtering API
* @IWL_UCODE_TLV_FLAGS_NO_BASIC_SSID: not sending a probe with the SSID element * @IWL_UCODE_TLV_FLAGS_NO_BASIC_SSID: not sending a probe with the SSID element
* from the probe request template. * from the probe request template.
* @IWL_UCODE_TLV_FLAGS_SCHED_SCAN: this uCode image supports scheduled scan.
* @IWL_UCODE_TLV_FLAGS_STA_KEY_CMD: new ADD_STA and ADD_STA_KEY command API * @IWL_UCODE_TLV_FLAGS_STA_KEY_CMD: new ADD_STA and ADD_STA_KEY command API
*/ */
enum iwl_ucode_tlv_flag { enum iwl_ucode_tlv_flag {
...@@ -91,11 +94,13 @@ enum iwl_ucode_tlv_flag { ...@@ -91,11 +94,13 @@ enum iwl_ucode_tlv_flag {
IWL_UCODE_TLV_FLAGS_P2P = BIT(3), IWL_UCODE_TLV_FLAGS_P2P = BIT(3),
IWL_UCODE_TLV_FLAGS_DW_BC_TABLE = BIT(4), IWL_UCODE_TLV_FLAGS_DW_BC_TABLE = BIT(4),
IWL_UCODE_TLV_FLAGS_UAPSD = BIT(6), IWL_UCODE_TLV_FLAGS_UAPSD = BIT(6),
IWL_UCODE_TLV_FLAGS_SHORT_BL = BIT(7),
IWL_UCODE_TLV_FLAGS_RX_ENERGY_API = BIT(8), IWL_UCODE_TLV_FLAGS_RX_ENERGY_API = BIT(8),
IWL_UCODE_TLV_FLAGS_TIME_EVENT_API_V2 = BIT(9), IWL_UCODE_TLV_FLAGS_TIME_EVENT_API_V2 = BIT(9),
IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS = BIT(10), IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS = BIT(10),
IWL_UCODE_TLV_FLAGS_BF_UPDATED = BIT(11), IWL_UCODE_TLV_FLAGS_BF_UPDATED = BIT(11),
IWL_UCODE_TLV_FLAGS_NO_BASIC_SSID = BIT(12), IWL_UCODE_TLV_FLAGS_NO_BASIC_SSID = BIT(12),
IWL_UCODE_TLV_FLAGS_SCHED_SCAN = BIT(17),
IWL_UCODE_TLV_FLAGS_STA_KEY_CMD = BIT(19), IWL_UCODE_TLV_FLAGS_STA_KEY_CMD = BIT(19),
}; };
......
...@@ -356,6 +356,7 @@ struct iwl_scan_complete_notif { ...@@ -356,6 +356,7 @@ struct iwl_scan_complete_notif {
/* scan offload */ /* scan offload */
#define IWL_MAX_SCAN_CHANNELS 40 #define IWL_MAX_SCAN_CHANNELS 40
#define IWL_SCAN_MAX_BLACKLIST_LEN 64 #define IWL_SCAN_MAX_BLACKLIST_LEN 64
#define IWL_SCAN_SHORT_BLACKLIST_LEN 16
#define IWL_SCAN_MAX_PROFILES 11 #define IWL_SCAN_MAX_PROFILES 11
#define SCAN_OFFLOAD_PROBE_REQ_SIZE 512 #define SCAN_OFFLOAD_PROBE_REQ_SIZE 512
...@@ -368,6 +369,12 @@ struct iwl_scan_complete_notif { ...@@ -368,6 +369,12 @@ struct iwl_scan_complete_notif {
#define IWL_FULL_SCAN_MULTIPLIER 5 #define IWL_FULL_SCAN_MULTIPLIER 5
#define IWL_FAST_SCHED_SCAN_ITERATIONS 3 #define IWL_FAST_SCHED_SCAN_ITERATIONS 3
enum scan_framework_client {
SCAN_CLIENT_SCHED_SCAN = BIT(0),
SCAN_CLIENT_NETDETECT = BIT(1),
SCAN_CLIENT_ASSET_TRACKING = BIT(2),
};
/** /**
* struct iwl_scan_offload_cmd - SCAN_REQUEST_FIXED_PART_API_S_VER_6 * struct iwl_scan_offload_cmd - SCAN_REQUEST_FIXED_PART_API_S_VER_6
* @scan_flags: see enum iwl_scan_flags * @scan_flags: see enum iwl_scan_flags
...@@ -449,11 +456,12 @@ struct iwl_scan_offload_cfg { ...@@ -449,11 +456,12 @@ struct iwl_scan_offload_cfg {
* iwl_scan_offload_blacklist - SCAN_OFFLOAD_BLACKLIST_S * iwl_scan_offload_blacklist - SCAN_OFFLOAD_BLACKLIST_S
* @ssid: MAC address to filter out * @ssid: MAC address to filter out
* @reported_rssi: AP rssi reported to the host * @reported_rssi: AP rssi reported to the host
* @client_bitmap: clients ignore this entry - enum scan_framework_client
*/ */
struct iwl_scan_offload_blacklist { struct iwl_scan_offload_blacklist {
u8 ssid[ETH_ALEN]; u8 ssid[ETH_ALEN];
u8 reported_rssi; u8 reported_rssi;
u8 reserved; u8 client_bitmap;
} __packed; } __packed;
enum iwl_scan_offload_network_type { enum iwl_scan_offload_network_type {
...@@ -475,6 +483,7 @@ enum iwl_scan_offload_band_selection { ...@@ -475,6 +483,7 @@ enum iwl_scan_offload_band_selection {
* @aut_alg: authentication olgorithm to match - bitmap * @aut_alg: authentication olgorithm to match - bitmap
* @network_type: enum iwl_scan_offload_network_type * @network_type: enum iwl_scan_offload_network_type
* @band_selection: enum iwl_scan_offload_band_selection * @band_selection: enum iwl_scan_offload_band_selection
* @client_bitmap: clients waiting for match - enum scan_framework_client
*/ */
struct iwl_scan_offload_profile { struct iwl_scan_offload_profile {
u8 ssid_index; u8 ssid_index;
...@@ -482,7 +491,8 @@ struct iwl_scan_offload_profile { ...@@ -482,7 +491,8 @@ struct iwl_scan_offload_profile {
u8 auth_alg; u8 auth_alg;
u8 network_type; u8 network_type;
u8 band_selection; u8 band_selection;
u8 reserved[3]; u8 client_bitmap;
u8 reserved[2];
} __packed; } __packed;
/** /**
...@@ -491,13 +501,18 @@ struct iwl_scan_offload_profile { ...@@ -491,13 +501,18 @@ struct iwl_scan_offload_profile {
* @profiles: profiles to search for match * @profiles: profiles to search for match
* @blacklist_len: length of blacklist * @blacklist_len: length of blacklist
* @num_profiles: num of profiles in the list * @num_profiles: num of profiles in the list
* @match_notify: clients waiting for match found notification
* @pass_match: clients waiting for the results
* @active_clients: active clients bitmap - enum scan_framework_client
*/ */
struct iwl_scan_offload_profile_cfg { struct iwl_scan_offload_profile_cfg {
struct iwl_scan_offload_blacklist blacklist[IWL_SCAN_MAX_BLACKLIST_LEN];
struct iwl_scan_offload_profile profiles[IWL_SCAN_MAX_PROFILES]; struct iwl_scan_offload_profile profiles[IWL_SCAN_MAX_PROFILES];
u8 blacklist_len; u8 blacklist_len;
u8 num_profiles; u8 num_profiles;
u8 reserved[2]; u8 match_notify;
u8 pass_match;
u8 active_clients;
u8 reserved[3];
} __packed; } __packed;
/** /**
...@@ -560,4 +575,15 @@ struct iwl_scan_offload_complete { ...@@ -560,4 +575,15 @@ struct iwl_scan_offload_complete {
u8 reserved; u8 reserved;
} __packed; } __packed;
/**
* iwl_sched_scan_results - SCAN_OFFLOAD_MATCH_FOUND_NTF_API_S_VER_1
* @ssid_bitmap: SSIDs indexes found in this iteration
* @client_bitmap: clients that are active and wait for this notification
*/
struct iwl_sched_scan_results {
__le16 ssid_bitmap;
u8 client_bitmap;
u8 reserved;
};
#endif #endif
...@@ -132,6 +132,7 @@ enum { ...@@ -132,6 +132,7 @@ enum {
SCAN_OFFLOAD_COMPLETE = 0x6D, SCAN_OFFLOAD_COMPLETE = 0x6D,
SCAN_OFFLOAD_UPDATE_PROFILES_CMD = 0x6E, SCAN_OFFLOAD_UPDATE_PROFILES_CMD = 0x6E,
SCAN_OFFLOAD_CONFIG_CMD = 0x6f, SCAN_OFFLOAD_CONFIG_CMD = 0x6f,
MATCH_FOUND_NOTIFICATION = 0xd9,
/* Phy */ /* Phy */
PHY_CONFIGURATION_CMD = 0x6a, PHY_CONFIGURATION_CMD = 0x6a,
......
...@@ -239,6 +239,15 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) ...@@ -239,6 +239,15 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
else else
hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_SCHED_SCAN) {
hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
hw->wiphy->max_sched_scan_ssids = PROBE_OPTION_MAX;
hw->wiphy->max_match_sets = IWL_SCAN_MAX_PROFILES;
/* we create the 802.11 header and zero length SSID IE. */
hw->wiphy->max_sched_scan_ie_len =
SCAN_OFFLOAD_PROBE_REQ_SIZE - 24 - 2;
}
hw->wiphy->features |= NL80211_FEATURE_P2P_GO_CTWIN | hw->wiphy->features |= NL80211_FEATURE_P2P_GO_CTWIN |
NL80211_FEATURE_P2P_GO_OPPPS; NL80211_FEATURE_P2P_GO_OPPPS;
...@@ -1202,6 +1211,53 @@ static void iwl_mvm_mac_mgd_prepare_tx(struct ieee80211_hw *hw, ...@@ -1202,6 +1211,53 @@ static void iwl_mvm_mac_mgd_prepare_tx(struct ieee80211_hw *hw,
mutex_unlock(&mvm->mutex); mutex_unlock(&mvm->mutex);
} }
static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct cfg80211_sched_scan_request *req,
struct ieee80211_sched_scan_ies *ies)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
int ret;
mutex_lock(&mvm->mutex);
if (mvm->scan_status != IWL_MVM_SCAN_NONE) {
IWL_DEBUG_SCAN(mvm,
"SCHED SCAN request during internal scan - abort\n");
ret = -EBUSY;
goto out;
}
mvm->scan_status = IWL_MVM_SCAN_SCHED;
ret = iwl_mvm_config_sched_scan(mvm, vif, req, ies);
if (ret)
goto err;
ret = iwl_mvm_config_sched_scan_profiles(mvm, req);
if (ret)
goto err;
ret = iwl_mvm_sched_scan_start(mvm, req);
if (!ret)
goto out;
err:
mvm->scan_status = IWL_MVM_SCAN_NONE;
out:
mutex_unlock(&mvm->mutex);
return ret;
}
static void iwl_mvm_mac_sched_scan_stop(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
mutex_lock(&mvm->mutex);
iwl_mvm_sched_scan_stop(mvm);
mutex_unlock(&mvm->mutex);
}
static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw, static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
enum set_key_cmd cmd, enum set_key_cmd cmd,
struct ieee80211_vif *vif, struct ieee80211_vif *vif,
...@@ -1671,6 +1727,8 @@ struct ieee80211_ops iwl_mvm_hw_ops = { ...@@ -1671,6 +1727,8 @@ struct ieee80211_ops iwl_mvm_hw_ops = {
.set_rts_threshold = iwl_mvm_mac_set_rts_threshold, .set_rts_threshold = iwl_mvm_mac_set_rts_threshold,
.conf_tx = iwl_mvm_mac_conf_tx, .conf_tx = iwl_mvm_mac_conf_tx,
.mgd_prepare_tx = iwl_mvm_mac_mgd_prepare_tx, .mgd_prepare_tx = iwl_mvm_mac_mgd_prepare_tx,
.sched_scan_start = iwl_mvm_mac_sched_scan_start,
.sched_scan_stop = iwl_mvm_mac_sched_scan_stop,
.set_key = iwl_mvm_mac_set_key, .set_key = iwl_mvm_mac_set_key,
.update_tkip_key = iwl_mvm_mac_update_tkip_key, .update_tkip_key = iwl_mvm_mac_update_tkip_key,
.remain_on_channel = iwl_mvm_roc, .remain_on_channel = iwl_mvm_roc,
......
...@@ -339,6 +339,7 @@ iwl_mvm_vif_from_mac80211(struct ieee80211_vif *vif) ...@@ -339,6 +339,7 @@ iwl_mvm_vif_from_mac80211(struct ieee80211_vif *vif)
enum iwl_scan_status { enum iwl_scan_status {
IWL_MVM_SCAN_NONE, IWL_MVM_SCAN_NONE,
IWL_MVM_SCAN_OS, IWL_MVM_SCAN_OS,
IWL_MVM_SCAN_SCHED,
}; };
/** /**
...@@ -696,6 +697,23 @@ int iwl_mvm_rx_scan_complete(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, ...@@ -696,6 +697,23 @@ int iwl_mvm_rx_scan_complete(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd); struct iwl_device_cmd *cmd);
void iwl_mvm_cancel_scan(struct iwl_mvm *mvm); void iwl_mvm_cancel_scan(struct iwl_mvm *mvm);
/* Scheduled scan */
int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd);
int iwl_mvm_config_sched_scan(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct cfg80211_sched_scan_request *req,
struct ieee80211_sched_scan_ies *ies);
int iwl_mvm_config_sched_scan_profiles(struct iwl_mvm *mvm,
struct cfg80211_sched_scan_request *req);
int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm,
struct cfg80211_sched_scan_request *req);
void iwl_mvm_sched_scan_stop(struct iwl_mvm *mvm);
int iwl_mvm_rx_sched_scan_results(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd);
/* MVM debugfs */ /* MVM debugfs */
#ifdef CONFIG_IWLWIFI_DEBUGFS #ifdef CONFIG_IWLWIFI_DEBUGFS
int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir); int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir);
......
...@@ -224,6 +224,10 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = { ...@@ -224,6 +224,10 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
RX_HANDLER(SCAN_REQUEST_CMD, iwl_mvm_rx_scan_response, false), RX_HANDLER(SCAN_REQUEST_CMD, iwl_mvm_rx_scan_response, false),
RX_HANDLER(SCAN_COMPLETE_NOTIFICATION, iwl_mvm_rx_scan_complete, false), RX_HANDLER(SCAN_COMPLETE_NOTIFICATION, iwl_mvm_rx_scan_complete, false),
RX_HANDLER(SCAN_OFFLOAD_COMPLETE,
iwl_mvm_rx_scan_offload_complete_notif, false),
RX_HANDLER(MATCH_FOUND_NOTIFICATION, iwl_mvm_rx_sched_scan_results,
false),
RX_HANDLER(RADIO_VERSION_NOTIFICATION, iwl_mvm_rx_radio_ver, false), RX_HANDLER(RADIO_VERSION_NOTIFICATION, iwl_mvm_rx_radio_ver, false),
RX_HANDLER(CARD_STATE_NOTIFICATION, iwl_mvm_rx_card_state_notif, false), RX_HANDLER(CARD_STATE_NOTIFICATION, iwl_mvm_rx_card_state_notif, false),
...@@ -266,6 +270,7 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = { ...@@ -266,6 +270,7 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = {
CMD(REMOVE_STA), CMD(REMOVE_STA),
CMD(LQ_CMD), CMD(LQ_CMD),
CMD(SCAN_OFFLOAD_CONFIG_CMD), CMD(SCAN_OFFLOAD_CONFIG_CMD),
CMD(MATCH_FOUND_NOTIFICATION),
CMD(SCAN_OFFLOAD_REQUEST_CMD), CMD(SCAN_OFFLOAD_REQUEST_CMD),
CMD(SCAN_OFFLOAD_ABORT_CMD), CMD(SCAN_OFFLOAD_ABORT_CMD),
CMD(SCAN_OFFLOAD_COMPLETE), CMD(SCAN_OFFLOAD_COMPLETE),
...@@ -717,6 +722,9 @@ static void iwl_mvm_nic_restart(struct iwl_mvm *mvm) ...@@ -717,6 +722,9 @@ static void iwl_mvm_nic_restart(struct iwl_mvm *mvm)
case IWL_MVM_SCAN_OS: case IWL_MVM_SCAN_OS:
ieee80211_scan_completed(mvm->hw, true); ieee80211_scan_completed(mvm->hw, true);
break; break;
case IWL_MVM_SCAN_SCHED:
ieee80211_sched_scan_stopped(mvm->hw);
break;
} }
if (mvm->restart_fw > 0) if (mvm->restart_fw > 0)
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment