aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Spinadel <david.spinadel@intel.com>2014-05-20 05:46:37 -0400
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>2014-11-23 13:02:43 -0500
commitd24962214dd5930aa713213654721fe1fd7ed844 (patch)
treecd5fd7f8ddcd49aac5f5ee1cfcf487a4efe0c0e7
parent5387b348b7af299c2aa8e0318498fa7d889da4fd (diff)
iwlwifi: mvm: implement UMAC scan API
This API uses second CPU scan commands, and can support multiple simultaneous scans. Adding the new API, and adding new mechanisms to deal with up to 8 simultaneous scans instead of the old scan status. New scan API requires scan configuration for default scan parameters, adding it in _up flow. Also updating scan configuration after updating valid scan antennas via debugfs. Signed-off-by: David Spinadel <david.spinadel@intel.com> Reviewed-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-fw.h2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/debugfs.c6
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h253
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api.h6
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw.c6
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mac80211.c25
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mvm.h16
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/ops.c17
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/scan.c669
9 files changed, 942 insertions, 58 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw.h b/drivers/net/wireless/iwlwifi/iwl-fw.h
index 598065b053de..133022a7bf6f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-fw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fw.h
@@ -145,6 +145,7 @@ enum iwl_ucode_tlv_api {
145/** 145/**
146 * enum iwl_ucode_tlv_capa - ucode capabilities 146 * enum iwl_ucode_tlv_capa - ucode capabilities
147 * @IWL_UCODE_TLV_CAPA_D0I3_SUPPORT: supports D0i3 147 * @IWL_UCODE_TLV_CAPA_D0I3_SUPPORT: supports D0i3
148 * @IWL_UCODE_TLV_CAPA_UMAC_SCAN: supports UMAC scan.
148 * @IWL_UCODE_TLV_CAPA_TXPOWER_INSERTION_SUPPORT: supports insertion of current 149 * @IWL_UCODE_TLV_CAPA_TXPOWER_INSERTION_SUPPORT: supports insertion of current
149 * tx power value into TPC Report action frame and Link Measurement Report 150 * tx power value into TPC Report action frame and Link Measurement Report
150 * action frame 151 * action frame
@@ -158,6 +159,7 @@ enum iwl_ucode_tlv_api {
158 */ 159 */
159enum iwl_ucode_tlv_capa { 160enum iwl_ucode_tlv_capa {
160 IWL_UCODE_TLV_CAPA_D0I3_SUPPORT = BIT(0), 161 IWL_UCODE_TLV_CAPA_D0I3_SUPPORT = BIT(0),
162 IWL_UCODE_TLV_CAPA_UMAC_SCAN = BIT(2),
161 IWL_UCODE_TLV_CAPA_TXPOWER_INSERTION_SUPPORT = BIT(8), 163 IWL_UCODE_TLV_CAPA_TXPOWER_INSERTION_SUPPORT = BIT(8),
162 IWL_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT = BIT(9), 164 IWL_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT = BIT(9),
163 IWL_UCODE_TLV_CAPA_WFA_TPC_REP_IE_SUPPORT = BIT(10), 165 IWL_UCODE_TLV_CAPA_WFA_TPC_REP_IE_SUPPORT = BIT(10),
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
index 51b7116965ed..8212b00096f9 100644
--- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
@@ -936,7 +936,11 @@ iwl_dbgfs_scan_ant_rxchain_write(struct iwl_mvm *mvm, char *buf,
936 if (scan_rx_ant & ~mvm->fw->valid_rx_ant) 936 if (scan_rx_ant & ~mvm->fw->valid_rx_ant)
937 return -EINVAL; 937 return -EINVAL;
938 938
939 mvm->scan_rx_ant = scan_rx_ant; 939 if (mvm->scan_rx_ant != scan_rx_ant) {
940 mvm->scan_rx_ant = scan_rx_ant;
941 if (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN)
942 iwl_mvm_config_scan(mvm);
943 }
940 944
941 return count; 945 return count;
942} 946}
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h
index 1354c68f6468..7163eb391826 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h
@@ -794,4 +794,257 @@ struct iwl_periodic_scan_complete {
794 __le32 reserved; 794 __le32 reserved;
795} __packed; 795} __packed;
796 796
797/* UMAC Scan API */
798
799/**
800 * struct iwl_mvm_umac_cmd_hdr - Command header for UMAC commands
801 * @size: size of the command (not including header)
802 * @reserved0: for future use and alignment
803 * @ver: API version number
804 */
805struct iwl_mvm_umac_cmd_hdr {
806 __le16 size;
807 u8 reserved0;
808 u8 ver;
809} __packed;
810
811#define IWL_MVM_MAX_SIMULTANEOUS_SCANS 8
812
813enum scan_config_flags {
814 SCAN_CONFIG_FLAG_ACTIVATE = BIT(0),
815 SCAN_CONFIG_FLAG_DEACTIVATE = BIT(1),
816 SCAN_CONFIG_FLAG_FORBID_CHUB_REQS = BIT(2),
817 SCAN_CONFIG_FLAG_ALLOW_CHUB_REQS = BIT(3),
818 SCAN_CONFIG_FLAG_SET_TX_CHAINS = BIT(8),
819 SCAN_CONFIG_FLAG_SET_RX_CHAINS = BIT(9),
820 SCAN_CONFIG_FLAG_SET_AUX_STA_ID = BIT(10),
821 SCAN_CONFIG_FLAG_SET_ALL_TIMES = BIT(11),
822 SCAN_CONFIG_FLAG_SET_EFFECTIVE_TIMES = BIT(12),
823 SCAN_CONFIG_FLAG_SET_CHANNEL_FLAGS = BIT(13),
824 SCAN_CONFIG_FLAG_SET_LEGACY_RATES = BIT(14),
825 SCAN_CONFIG_FLAG_SET_MAC_ADDR = BIT(15),
826 SCAN_CONFIG_FLAG_SET_FRAGMENTED = BIT(16),
827 SCAN_CONFIG_FLAG_CLEAR_FRAGMENTED = BIT(17),
828 SCAN_CONFIG_FLAG_SET_CAM_MODE = BIT(18),
829 SCAN_CONFIG_FLAG_CLEAR_CAM_MODE = BIT(19),
830 SCAN_CONFIG_FLAG_SET_PROMISC_MODE = BIT(20),
831 SCAN_CONFIG_FLAG_CLEAR_PROMISC_MODE = BIT(21),
832
833 /* Bits 26-31 are for num of channels in channel_array */
834#define SCAN_CONFIG_N_CHANNELS(n) ((n) << 26)
835};
836
837enum scan_config_rates {
838 /* OFDM basic rates */
839 SCAN_CONFIG_RATE_6M = BIT(0),
840 SCAN_CONFIG_RATE_9M = BIT(1),
841 SCAN_CONFIG_RATE_12M = BIT(2),
842 SCAN_CONFIG_RATE_18M = BIT(3),
843 SCAN_CONFIG_RATE_24M = BIT(4),
844 SCAN_CONFIG_RATE_36M = BIT(5),
845 SCAN_CONFIG_RATE_48M = BIT(6),
846 SCAN_CONFIG_RATE_54M = BIT(7),
847 /* CCK basic rates */
848 SCAN_CONFIG_RATE_1M = BIT(8),
849 SCAN_CONFIG_RATE_2M = BIT(9),
850 SCAN_CONFIG_RATE_5M = BIT(10),
851 SCAN_CONFIG_RATE_11M = BIT(11),
852
853 /* Bits 16-27 are for supported rates */
854#define SCAN_CONFIG_SUPPORTED_RATE(rate) ((rate) << 16)
855};
856
857enum iwl_channel_flags {
858 IWL_CHANNEL_FLAG_EBS = BIT(0),
859 IWL_CHANNEL_FLAG_ACCURATE_EBS = BIT(1),
860 IWL_CHANNEL_FLAG_EBS_ADD = BIT(2),
861 IWL_CHANNEL_FLAG_PRE_SCAN_PASSIVE2ACTIVE = BIT(3),
862};
863
864/**
865 * struct iwl_scan_config
866 * @hdr: umac command header
867 * @flags: enum scan_config_flags
868 * @tx_chains: valid_tx antenna - ANT_* definitions
869 * @rx_chains: valid_rx antenna - ANT_* definitions
870 * @legacy_rates: default legacy rates - enum scan_config_rates
871 * @out_of_channel_time: default max out of serving channel time
872 * @suspend_time: default max suspend time
873 * @dwell_active: default dwell time for active scan
874 * @dwell_passive: default dwell time for passive scan
875 * @dwell_fragmented: default dwell time for fragmented scan
876 * @reserved: for future use and alignment
877 * @mac_addr: default mac address to be used in probes
878 * @bcast_sta_id: the index of the station in the fw
879 * @channel_flags: default channel flags - enum iwl_channel_flags
880 * scan_config_channel_flag
881 * @channel_array: default supported channels
882 */
883struct iwl_scan_config {
884 struct iwl_mvm_umac_cmd_hdr hdr;
885 __le32 flags;
886 __le32 tx_chains;
887 __le32 rx_chains;
888 __le32 legacy_rates;
889 __le32 out_of_channel_time;
890 __le32 suspend_time;
891 u8 dwell_active;
892 u8 dwell_passive;
893 u8 dwell_fragmented;
894 u8 reserved;
895 u8 mac_addr[ETH_ALEN];
896 u8 bcast_sta_id;
897 u8 channel_flags;
898 u8 channel_array[];
899} __packed; /* SCAN_CONFIG_DB_CMD_API_S */
900
901/**
902 * iwl_umac_scan_flags
903 *@IWL_UMAC_SCAN_FLAG_PREEMPTIVE: scan process triggered by this scan request
904 * can be preempted by other scan requests with higher priority.
905 * The low priority scan is aborted.
906 *@IWL_UMAC_SCAN_FLAG_START_NOTIF: notification will be sent to the driver
907 * when scan starts.
908 */
909enum iwl_umac_scan_flags {
910 IWL_UMAC_SCAN_FLAG_PREEMPTIVE = BIT(0),
911 IWL_UMAC_SCAN_FLAG_START_NOTIF = BIT(1),
912};
913
914enum iwl_umac_scan_uid_offsets {
915 IWL_UMAC_SCAN_UID_TYPE_OFFSET = 0,
916 IWL_UMAC_SCAN_UID_SEQ_OFFSET = 8,
917};
918
919enum iwl_umac_scan_general_flags {
920 IWL_UMAC_SCAN_GEN_FLAGS_PERIODIC = BIT(0),
921 IWL_UMAC_SCAN_GEN_FLAGS_OVER_BT = BIT(1),
922 IWL_UMAC_SCAN_GEN_FLAGS_PASS_ALL = BIT(2),
923 IWL_UMAC_SCAN_GEN_FLAGS_PASSIVE = BIT(3),
924 IWL_UMAC_SCAN_GEN_FLAGS_PRE_CONNECT = BIT(4),
925 IWL_UMAC_SCAN_GEN_FLAGS_ITER_COMPLETE = BIT(5),
926 IWL_UMAC_SCAN_GEN_FLAGS_MULTIPLE_SSID = BIT(6),
927 IWL_UMAC_SCAN_GEN_FLAGS_FRAGMENTED = BIT(7),
928 IWL_UMAC_SCAN_GEN_FLAGS_RRM_ENABLED = BIT(8),
929 IWL_UMAC_SCAN_GEN_FLAGS_MATCH = BIT(9)
930};
931
932/**
933 * struct iwl_scan_channel_cfg_umac
934 * @flags: bitmap - 0-19: directed scan to i'th ssid.
935 * @channel_num: channel number 1-13 etc.
936 * @iter_count: repetition count for the channel.
937 * @iter_interval: interval between two scan interations on one channel.
938 */
939struct iwl_scan_channel_cfg_umac {
940 __le32 flags;
941 u8 channel_num;
942 u8 iter_count;
943 __le16 iter_interval;
944} __packed; /* SCAN_CHANNEL_CFG_S_VER2 */
945
946/**
947 * struct iwl_scan_umac_schedule
948 * @interval: interval in seconds between scan iterations
949 * @iter_count: num of scan iterations for schedule plan, 0xff for infinite loop
950 * @reserved: for alignment and future use
951 */
952struct iwl_scan_umac_schedule {
953 __le16 interval;
954 u8 iter_count;
955 u8 reserved;
956} __packed; /* SCAN_SCHED_PARAM_API_S_VER_1 */
957
958/**
959 * struct iwl_scan_req_umac_tail - the rest of the UMAC scan request command
960 * parameters following channels configuration array.
961 * @schedule: two scheduling plans.
962 * @delay: delay in TUs before starting the first scan iteration
963 * @reserved: for future use and alignment
964 * @preq: probe request with IEs blocks
965 * @direct_scan: list of SSIDs for directed active scan
966 */
967struct iwl_scan_req_umac_tail {
968 /* SCAN_PERIODIC_PARAMS_API_S_VER_1 */
969 struct iwl_scan_umac_schedule schedule[2];
970 __le16 delay;
971 __le16 reserved;
972 /* SCAN_PROBE_PARAMS_API_S_VER_1 */
973 struct iwl_scan_probe_req preq;
974 struct iwl_ssid_ie direct_scan[PROBE_OPTION_MAX];
975} __packed;
976
977/**
978 * struct iwl_scan_req_umac
979 * @hdr: umac command header
980 * @flags: &enum iwl_umac_scan_flags
981 * @uid: scan id, &enum iwl_umac_scan_uid_offsets
982 * @ooc_priority: out of channel priority - &enum iwl_scan_priority
983 * @general_flags: &enum iwl_umac_scan_general_flags
984 * @reserved1: for future use and alignment
985 * @active_dwell: dwell time for active scan
986 * @passive_dwell: dwell time for passive scan
987 * @fragmented_dwell: dwell time for fragmented passive scan
988 * @max_out_time: max out of serving channel time
989 * @suspend_time: max suspend time
990 * @scan_priority: scan internal prioritization &enum iwl_scan_priority
991 * @channel_flags: &enum iwl_scan_channel_flags
992 * @n_channels: num of channels in scan request
993 * @reserved2: for future use and alignment
994 * @data: &struct iwl_scan_channel_cfg_umac and
995 * &struct iwl_scan_req_umac_tail
996 */
997struct iwl_scan_req_umac {
998 struct iwl_mvm_umac_cmd_hdr hdr;
999 __le32 flags;
1000 __le32 uid;
1001 __le32 ooc_priority;
1002 /* SCAN_GENERAL_PARAMS_API_S_VER_1 */
1003 __le32 general_flags;
1004 u8 reserved1;
1005 u8 active_dwell;
1006 u8 passive_dwell;
1007 u8 fragmented_dwell;
1008 __le32 max_out_time;
1009 __le32 suspend_time;
1010 __le32 scan_priority;
1011 /* SCAN_CHANNEL_PARAMS_API_S_VER_1 */
1012 u8 channel_flags;
1013 u8 n_channels;
1014 __le16 reserved2;
1015 u8 data[];
1016} __packed; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_1 */
1017
1018/**
1019 * struct iwl_umac_scan_abort
1020 * @hdr: umac command header
1021 * @uid: scan id, &enum iwl_umac_scan_uid_offsets
1022 * @flags: reserved
1023 */
1024struct iwl_umac_scan_abort {
1025 struct iwl_mvm_umac_cmd_hdr hdr;
1026 __le32 uid;
1027 __le32 flags;
1028} __packed; /* SCAN_ABORT_CMD_UMAC_API_S_VER_1 */
1029
1030/**
1031 * struct iwl_umac_scan_complete
1032 * @uid: scan id, &enum iwl_umac_scan_uid_offsets
1033 * @last_schedule: last scheduling line
1034 * @last_iter: last scan iteration number
1035 * @scan status: &enum iwl_scan_offload_complete_status
1036 * @ebs_status: &enum iwl_scan_ebs_status
1037 * @time_from_last_iter: time elapsed from last iteration
1038 * @reserved: for future use
1039 */
1040struct iwl_umac_scan_complete {
1041 __le32 uid;
1042 u8 last_schedule;
1043 u8 last_iter;
1044 u8 status;
1045 u8 ebs_status;
1046 __le32 time_from_last_iter;
1047 __le32 reserved;
1048} __packed; /* SCAN_COMPLETE_NTF_UMAC_API_S_VER_1 */
1049
797#endif 1050#endif
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h
index c62575d86bcd..1a67788e55f5 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h
@@ -106,6 +106,12 @@ enum {
106 DBG_CFG = 0x9, 106 DBG_CFG = 0x9,
107 ANTENNA_COUPLING_NOTIFICATION = 0xa, 107 ANTENNA_COUPLING_NOTIFICATION = 0xa,
108 108
109 /* UMAC scan commands */
110 SCAN_CFG_CMD = 0xc,
111 SCAN_REQ_UMAC = 0xd,
112 SCAN_ABORT_UMAC = 0xe,
113 SCAN_COMPLETE_UMAC = 0xf,
114
109 /* station table */ 115 /* station table */
110 ADD_STA_KEY = 0x17, 116 ADD_STA_KEY = 0x17,
111 ADD_STA = 0x18, 117 ADD_STA = 0x18,
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c
index f12b43d65f66..b4f244f510ed 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/iwlwifi/mvm/fw.c
@@ -505,6 +505,12 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
505 if (ret) 505 if (ret)
506 goto error; 506 goto error;
507 507
508 if (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN) {
509 ret = iwl_mvm_config_scan(mvm);
510 if (ret)
511 goto error;
512 }
513
508 /* allow FW/transport low power modes if not during restart */ 514 /* allow FW/transport low power modes if not during restart */
509 if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) 515 if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
510 iwl_mvm_unref(mvm, IWL_MVM_REF_UCODE_DOWN); 516 iwl_mvm_unref(mvm, IWL_MVM_REF_UCODE_DOWN);
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
index e3259b61b9e8..79ad6958255c 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
@@ -343,7 +343,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
343 hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP; 343 hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP;
344 } 344 }
345 345
346 if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN) 346 if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN ||
347 mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN)
347 hw->flags |= IEEE80211_SINGLE_HW_SCAN_ON_ALL_BANDS; 348 hw->flags |= IEEE80211_SINGLE_HW_SCAN_ON_ALL_BANDS;
348 349
349 hw->sta_data_size = sizeof(struct iwl_mvm_sta); 350 hw->sta_data_size = sizeof(struct iwl_mvm_sta);
@@ -1935,9 +1936,11 @@ static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw,
1935 req->n_channels > mvm->fw->ucode_capa.n_scan_channels) 1936 req->n_channels > mvm->fw->ucode_capa.n_scan_channels)
1936 return -EINVAL; 1937 return -EINVAL;
1937 1938
1938 ret = iwl_mvm_cancel_scan_wait_notif(mvm, IWL_MVM_SCAN_SCHED); 1939 if (!(mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN)) {
1939 if (ret) 1940 ret = iwl_mvm_cancel_scan_wait_notif(mvm, IWL_MVM_SCAN_SCHED);
1940 return ret; 1941 if (ret)
1942 return ret;
1943 }
1941 1944
1942 mutex_lock(&mvm->mutex); 1945 mutex_lock(&mvm->mutex);
1943 1946
@@ -1950,6 +1953,8 @@ static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw,
1950 1953
1951 if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN) 1954 if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)
1952 ret = iwl_mvm_unified_scan_lmac(mvm, vif, hw_req); 1955 ret = iwl_mvm_unified_scan_lmac(mvm, vif, hw_req);
1956 else if (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN)
1957 ret = iwl_mvm_scan_umac(mvm, vif, hw_req);
1953 else 1958 else
1954 ret = iwl_mvm_scan_request(mvm, vif, req); 1959 ret = iwl_mvm_scan_request(mvm, vif, req);
1955 1960
@@ -2247,9 +2252,11 @@ static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw,
2247 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); 2252 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
2248 int ret; 2253 int ret;
2249 2254
2250 ret = iwl_mvm_cancel_scan_wait_notif(mvm, IWL_MVM_SCAN_OS); 2255 if (!(mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN)) {
2251 if (ret) 2256 ret = iwl_mvm_cancel_scan_wait_notif(mvm, IWL_MVM_SCAN_OS);
2252 return ret; 2257 if (ret)
2258 return ret;
2259 }
2253 2260
2254 mutex_lock(&mvm->mutex); 2261 mutex_lock(&mvm->mutex);
2255 2262
@@ -2269,11 +2276,10 @@ static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw,
2269 goto out; 2276 goto out;
2270 } 2277 }
2271 2278
2272 mvm->scan_status = IWL_MVM_SCAN_SCHED;
2273
2274 ret = iwl_mvm_scan_offload_start(mvm, vif, req, ies); 2279 ret = iwl_mvm_scan_offload_start(mvm, vif, req, ies);
2275 if (ret) 2280 if (ret)
2276 mvm->scan_status = IWL_MVM_SCAN_NONE; 2281 mvm->scan_status = IWL_MVM_SCAN_NONE;
2282
2277out: 2283out:
2278 mutex_unlock(&mvm->mutex); 2284 mutex_unlock(&mvm->mutex);
2279 return ret; 2285 return ret;
@@ -2291,6 +2297,7 @@ static int iwl_mvm_mac_sched_scan_stop(struct ieee80211_hw *hw,
2291 iwl_mvm_wait_for_async_handlers(mvm); 2297 iwl_mvm_wait_for_async_handlers(mvm);
2292 2298
2293 return ret; 2299 return ret;
2300
2294} 2301}
2295 2302
2296static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw, 2303static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h
index 09b49b407a5b..cbfba80a0e2f 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h
@@ -588,6 +588,10 @@ struct iwl_mvm {
588 void *scan_cmd; 588 void *scan_cmd;
589 struct iwl_mcast_filter_cmd *mcast_filter_cmd; 589 struct iwl_mcast_filter_cmd *mcast_filter_cmd;
590 590
591 /* UMAC scan tracking */
592 u32 scan_uid[IWL_MVM_MAX_SIMULTANEOUS_SCANS];
593 u8 scan_seq_num, sched_scan_seq_num;
594
591 /* rx chain antennas set through debugfs for the scan command */ 595 /* rx chain antennas set through debugfs for the scan command */
592 u8 scan_rx_ant; 596 u8 scan_rx_ant;
593 597
@@ -943,6 +947,7 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm,
943 struct ieee80211_vif *disabled_vif); 947 struct ieee80211_vif *disabled_vif);
944 948
945/* Scanning */ 949/* Scanning */
950int iwl_mvm_scan_size(struct iwl_mvm *mvm);
946int iwl_mvm_scan_request(struct iwl_mvm *mvm, 951int iwl_mvm_scan_request(struct iwl_mvm *mvm,
947 struct ieee80211_vif *vif, 952 struct ieee80211_vif *vif,
948 struct cfg80211_scan_request *req); 953 struct cfg80211_scan_request *req);
@@ -983,6 +988,17 @@ int iwl_mvm_unified_sched_scan_lmac(struct iwl_mvm *mvm,
983 struct cfg80211_sched_scan_request *req, 988 struct cfg80211_sched_scan_request *req,
984 struct ieee80211_scan_ies *ies); 989 struct ieee80211_scan_ies *ies);
985 990
991/* UMAC scan */
992int iwl_mvm_config_scan(struct iwl_mvm *mvm);
993int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
994 struct ieee80211_scan_request *req);
995int iwl_mvm_sched_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
996 struct cfg80211_sched_scan_request *req,
997 struct ieee80211_scan_ies *ies);
998int iwl_mvm_rx_umac_scan_complete_notif(struct iwl_mvm *mvm,
999 struct iwl_rx_cmd_buffer *rxb,
1000 struct iwl_device_cmd *cmd);
1001
986/* MVM debugfs */ 1002/* MVM debugfs */
987#ifdef CONFIG_IWLWIFI_DEBUGFS 1003#ifdef CONFIG_IWLWIFI_DEBUGFS
988int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir); 1004int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir);
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c
index 53a5a29897b4..5ab10fb9d672 100644
--- a/drivers/net/wireless/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/iwlwifi/mvm/ops.c
@@ -244,6 +244,8 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
244 iwl_mvm_rx_scan_offload_complete_notif, true), 244 iwl_mvm_rx_scan_offload_complete_notif, true),
245 RX_HANDLER(MATCH_FOUND_NOTIFICATION, iwl_mvm_rx_scan_offload_results, 245 RX_HANDLER(MATCH_FOUND_NOTIFICATION, iwl_mvm_rx_scan_offload_results,
246 false), 246 false),
247 RX_HANDLER(SCAN_COMPLETE_UMAC, iwl_mvm_rx_umac_scan_complete_notif,
248 true),
247 249
248 RX_HANDLER(RADIO_VERSION_NOTIFICATION, iwl_mvm_rx_radio_ver, false), 250 RX_HANDLER(RADIO_VERSION_NOTIFICATION, iwl_mvm_rx_radio_ver, false),
249 RX_HANDLER(CARD_STATE_NOTIFICATION, iwl_mvm_rx_card_state_notif, false), 251 RX_HANDLER(CARD_STATE_NOTIFICATION, iwl_mvm_rx_card_state_notif, false),
@@ -346,6 +348,10 @@ static const char *const iwl_mvm_cmd_strings[REPLY_MAX] = {
346 CMD(PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION), 348 CMD(PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION),
347 CMD(ANTENNA_COUPLING_NOTIFICATION), 349 CMD(ANTENNA_COUPLING_NOTIFICATION),
348 CMD(SCD_QUEUE_CFG), 350 CMD(SCD_QUEUE_CFG),
351 CMD(SCAN_CFG_CMD),
352 CMD(SCAN_REQ_UMAC),
353 CMD(SCAN_ABORT_UMAC),
354 CMD(SCAN_COMPLETE_UMAC),
349}; 355};
350#undef CMD 356#undef CMD
351 357
@@ -537,16 +543,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
537 } 543 }
538 } 544 }
539 545
540 if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN) 546 scan_size = iwl_mvm_scan_size(mvm);
541 scan_size = sizeof(struct iwl_scan_req_unified_lmac) +
542 sizeof(struct iwl_scan_channel_cfg_lmac) *
543 mvm->fw->ucode_capa.n_scan_channels +
544 sizeof(struct iwl_scan_probe_req);
545 else
546 scan_size = sizeof(struct iwl_scan_cmd) +
547 mvm->fw->ucode_capa.max_probe_length +
548 mvm->fw->ucode_capa.n_scan_channels *
549 sizeof(struct iwl_scan_channel);
550 547
551 mvm->scan_cmd = kmalloc(scan_size, GFP_KERNEL); 548 mvm->scan_cmd = kmalloc(scan_size, GFP_KERNEL);
552 if (!mvm->scan_cmd) 549 if (!mvm->scan_cmd)
diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c
index 8a1f4a8e80e7..c440b7b3ea4f 100644
--- a/drivers/net/wireless/iwlwifi/mvm/scan.c
+++ b/drivers/net/wireless/iwlwifi/mvm/scan.c
@@ -83,15 +83,29 @@ struct iwl_mvm_scan_params {
83 } dwell[IEEE80211_NUM_BANDS]; 83 } dwell[IEEE80211_NUM_BANDS];
84}; 84};
85 85
86enum iwl_umac_scan_uid_type {
87 IWL_UMAC_SCAN_UID_REG_SCAN = BIT(0),
88 IWL_UMAC_SCAN_UID_SCHED_SCAN = BIT(1),
89 IWL_UMAC_SCAN_UID_ALL = IWL_UMAC_SCAN_UID_REG_SCAN |
90 IWL_UMAC_SCAN_UID_SCHED_SCAN,
91};
92
93static int iwl_umac_scan_stop(struct iwl_mvm *mvm,
94 enum iwl_umac_scan_uid_type type, bool notify);
95
96static u8 iwl_mvm_scan_rx_ant(struct iwl_mvm *mvm)
97{
98 if (mvm->scan_rx_ant != ANT_NONE)
99 return mvm->scan_rx_ant;
100 return mvm->fw->valid_rx_ant;
101}
102
86static inline __le16 iwl_mvm_scan_rx_chain(struct iwl_mvm *mvm) 103static inline __le16 iwl_mvm_scan_rx_chain(struct iwl_mvm *mvm)
87{ 104{
88 u16 rx_chain; 105 u16 rx_chain;
89 u8 rx_ant; 106 u8 rx_ant;
90 107
91 if (mvm->scan_rx_ant != ANT_NONE) 108 rx_ant = iwl_mvm_scan_rx_ant(mvm);
92 rx_ant = mvm->scan_rx_ant;
93 else
94 rx_ant = mvm->fw->valid_rx_ant;
95 rx_chain = rx_ant << PHY_RX_CHAIN_VALID_POS; 109 rx_chain = rx_ant << PHY_RX_CHAIN_VALID_POS;
96 rx_chain |= rx_ant << PHY_RX_CHAIN_FORCE_MIMO_SEL_POS; 110 rx_chain |= rx_ant << PHY_RX_CHAIN_FORCE_MIMO_SEL_POS;
97 rx_chain |= rx_ant << PHY_RX_CHAIN_FORCE_SEL_POS; 111 rx_chain |= rx_ant << PHY_RX_CHAIN_FORCE_SEL_POS;
@@ -541,23 +555,17 @@ int iwl_mvm_rx_scan_offload_results(struct iwl_mvm *mvm,
541 struct iwl_device_cmd *cmd) 555 struct iwl_device_cmd *cmd)
542{ 556{
543 struct iwl_rx_packet *pkt = rxb_addr(rxb); 557 struct iwl_rx_packet *pkt = rxb_addr(rxb);
544 u8 client_bitmap = 0;
545 558
546 if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)) { 559 if (!(mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN) &&
560 !(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)) {
547 struct iwl_sched_scan_results *notif = (void *)pkt->data; 561 struct iwl_sched_scan_results *notif = (void *)pkt->data;
548 562
549 client_bitmap = notif->client_bitmap; 563 if (!(notif->client_bitmap & SCAN_CLIENT_SCHED_SCAN))
564 return 0;
550 } 565 }
551 566
552 if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN || 567 IWL_DEBUG_SCAN(mvm, "Scheduled scan results\n");
553 client_bitmap & SCAN_CLIENT_SCHED_SCAN) { 568 ieee80211_sched_scan_results(mvm->hw);
554 if (mvm->scan_status == IWL_MVM_SCAN_SCHED) {
555 IWL_DEBUG_SCAN(mvm, "Scheduled scan results\n");
556 ieee80211_sched_scan_results(mvm->hw);
557 } else {
558 IWL_DEBUG_SCAN(mvm, "Scan results\n");
559 }
560 }
561 569
562 return 0; 570 return 0;
563} 571}
@@ -969,6 +977,20 @@ free_blacklist:
969 return ret; 977 return ret;
970} 978}
971 979
980static bool iwl_mvm_scan_pass_all(struct iwl_mvm *mvm,
981 struct cfg80211_sched_scan_request *req)
982{
983 if (req->n_match_sets && req->match_sets[0].ssid.ssid_len) {
984 IWL_DEBUG_SCAN(mvm,
985 "Sending scheduled scan with filtering, n_match_sets %d\n",
986 req->n_match_sets);
987 return false;
988 }
989
990 IWL_DEBUG_SCAN(mvm, "Sending Scheduled scan without filtering\n");
991 return true;
992}
993
972int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm, 994int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm,
973 struct cfg80211_sched_scan_request *req) 995 struct cfg80211_sched_scan_request *req)
974{ 996{
@@ -984,15 +1006,8 @@ int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm,
984 .schedule_line[1].full_scan_mul = IWL_FULL_SCAN_MULTIPLIER, 1006 .schedule_line[1].full_scan_mul = IWL_FULL_SCAN_MULTIPLIER,
985 }; 1007 };
986 1008
987 if (req->n_match_sets && req->match_sets[0].ssid.ssid_len) { 1009 if (iwl_mvm_scan_pass_all(mvm, req))
988 IWL_DEBUG_SCAN(mvm,
989 "Sending scheduled scan with filtering, filter len %d\n",
990 req->n_match_sets);
991 } else {
992 IWL_DEBUG_SCAN(mvm,
993 "Sending Scheduled scan without filtering\n");
994 scan_req.flags |= cpu_to_le16(IWL_SCAN_OFFLOAD_FLAG_PASS_ALL); 1010 scan_req.flags |= cpu_to_le16(IWL_SCAN_OFFLOAD_FLAG_PASS_ALL);
995 }
996 1011
997 if (mvm->last_ebs_successful && 1012 if (mvm->last_ebs_successful &&
998 mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_EBS_SUPPORT) 1013 mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_EBS_SUPPORT)
@@ -1011,11 +1026,18 @@ int iwl_mvm_scan_offload_start(struct iwl_mvm *mvm,
1011 int ret; 1026 int ret;
1012 1027
1013 if ((mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)) { 1028 if ((mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)) {
1029 mvm->scan_status = IWL_MVM_SCAN_SCHED;
1014 ret = iwl_mvm_config_sched_scan_profiles(mvm, req); 1030 ret = iwl_mvm_config_sched_scan_profiles(mvm, req);
1015 if (ret) 1031 if (ret)
1016 return ret; 1032 return ret;
1017 ret = iwl_mvm_unified_sched_scan_lmac(mvm, vif, req, ies); 1033 ret = iwl_mvm_unified_sched_scan_lmac(mvm, vif, req, ies);
1034 } else if (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN) {
1035 ret = iwl_mvm_config_sched_scan_profiles(mvm, req);
1036 if (ret)
1037 return ret;
1038 ret = iwl_mvm_sched_scan_umac(mvm, vif, req, ies);
1018 } else { 1039 } else {
1040 mvm->scan_status = IWL_MVM_SCAN_SCHED;
1019 ret = iwl_mvm_config_sched_scan(mvm, vif, req, ies); 1041 ret = iwl_mvm_config_sched_scan(mvm, vif, req, ies);
1020 if (ret) 1042 if (ret)
1021 return ret; 1043 return ret;
@@ -1072,6 +1094,10 @@ int iwl_mvm_scan_offload_stop(struct iwl_mvm *mvm, bool notify)
1072 1094
1073 lockdep_assert_held(&mvm->mutex); 1095 lockdep_assert_held(&mvm->mutex);
1074 1096
1097 if (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN)
1098 return iwl_umac_scan_stop(mvm, IWL_UMAC_SCAN_UID_SCHED_SCAN,
1099 notify);
1100
1075 if (mvm->scan_status != IWL_MVM_SCAN_SCHED && 1101 if (mvm->scan_status != IWL_MVM_SCAN_SCHED &&
1076 (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN) || 1102 (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN) ||
1077 mvm->scan_status != IWL_MVM_SCAN_OS)) { 1103 mvm->scan_status != IWL_MVM_SCAN_OS)) {
@@ -1198,11 +1224,8 @@ static u8 *iwl_mvm_copy_and_insert_ds_elem(struct iwl_mvm *mvm, const u8 *ies,
1198static void 1224static void
1199iwl_mvm_build_unified_scan_probe(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 1225iwl_mvm_build_unified_scan_probe(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
1200 struct ieee80211_scan_ies *ies, 1226 struct ieee80211_scan_ies *ies,
1201 struct iwl_scan_req_unified_lmac *cmd) 1227 struct iwl_scan_probe_req *preq)
1202{ 1228{
1203 struct iwl_scan_probe_req *preq = (void *)(cmd->data +
1204 sizeof(struct iwl_scan_channel_cfg_lmac) *
1205 mvm->fw->ucode_capa.n_scan_channels);
1206 struct ieee80211_mgmt *frame = (struct ieee80211_mgmt *)preq->buf; 1229 struct ieee80211_mgmt *frame = (struct ieee80211_mgmt *)preq->buf;
1207 u8 *pos, *newpos; 1230 u8 *pos, *newpos;
1208 1231
@@ -1287,6 +1310,7 @@ int iwl_mvm_unified_scan_lmac(struct iwl_mvm *mvm,
1287 .dataflags = { IWL_HCMD_DFL_NOCOPY, }, 1310 .dataflags = { IWL_HCMD_DFL_NOCOPY, },
1288 }; 1311 };
1289 struct iwl_scan_req_unified_lmac *cmd = mvm->scan_cmd; 1312 struct iwl_scan_req_unified_lmac *cmd = mvm->scan_cmd;
1313 struct iwl_scan_probe_req *preq;
1290 struct iwl_mvm_scan_params params = {}; 1314 struct iwl_mvm_scan_params params = {};
1291 u32 flags; 1315 u32 flags;
1292 int ssid_bitmap = 0; 1316 int ssid_bitmap = 0;
@@ -1348,7 +1372,10 @@ int iwl_mvm_unified_scan_lmac(struct iwl_mvm *mvm,
1348 req->req.n_channels, ssid_bitmap, 1372 req->req.n_channels, ssid_bitmap,
1349 cmd); 1373 cmd);
1350 1374
1351 iwl_mvm_build_unified_scan_probe(mvm, vif, &req->ies, cmd); 1375 preq = (void *)(cmd->data + sizeof(struct iwl_scan_channel_cfg_lmac) *
1376 mvm->fw->ucode_capa.n_scan_channels);
1377
1378 iwl_mvm_build_unified_scan_probe(mvm, vif, &req->ies, preq);
1352 1379
1353 ret = iwl_mvm_send_cmd(mvm, &hcmd); 1380 ret = iwl_mvm_send_cmd(mvm, &hcmd);
1354 if (!ret) { 1381 if (!ret) {
@@ -1381,6 +1408,7 @@ int iwl_mvm_unified_sched_scan_lmac(struct iwl_mvm *mvm,
1381 .dataflags = { IWL_HCMD_DFL_NOCOPY, }, 1408 .dataflags = { IWL_HCMD_DFL_NOCOPY, },
1382 }; 1409 };
1383 struct iwl_scan_req_unified_lmac *cmd = mvm->scan_cmd; 1410 struct iwl_scan_req_unified_lmac *cmd = mvm->scan_cmd;
1411 struct iwl_scan_probe_req *preq;
1384 struct iwl_mvm_scan_params params = {}; 1412 struct iwl_mvm_scan_params params = {};
1385 int ret; 1413 int ret;
1386 u32 flags = 0, ssid_bitmap = 0; 1414 u32 flags = 0, ssid_bitmap = 0;
@@ -1404,15 +1432,8 @@ int iwl_mvm_unified_sched_scan_lmac(struct iwl_mvm *mvm,
1404 1432
1405 cmd->n_channels = (u8)req->n_channels; 1433 cmd->n_channels = (u8)req->n_channels;
1406 1434
1407 if (req->n_match_sets && req->match_sets[0].ssid.ssid_len) { 1435 if (iwl_mvm_scan_pass_all(mvm, req))
1408 IWL_DEBUG_SCAN(mvm,
1409 "Sending scheduled scan with filtering, n_match_sets %d\n",
1410 req->n_match_sets);
1411 } else {
1412 IWL_DEBUG_SCAN(mvm,
1413 "Sending Scheduled scan without filtering\n");
1414 flags |= IWL_MVM_LMAC_SCAN_FLAG_PASS_ALL; 1436 flags |= IWL_MVM_LMAC_SCAN_FLAG_PASS_ALL;
1415 }
1416 1437
1417 if (req->n_ssids == 1 && req->ssids[0].ssid_len != 0) 1438 if (req->n_ssids == 1 && req->ssids[0].ssid_len != 0)
1418 flags |= IWL_MVM_LMAC_SCAN_FLAG_PRE_CONNECTION; 1439 flags |= IWL_MVM_LMAC_SCAN_FLAG_PRE_CONNECTION;
@@ -1442,7 +1463,10 @@ int iwl_mvm_unified_sched_scan_lmac(struct iwl_mvm *mvm,
1442 iwl_mvm_lmac_scan_cfg_channels(mvm, req->channels, req->n_channels, 1463 iwl_mvm_lmac_scan_cfg_channels(mvm, req->channels, req->n_channels,
1443 ssid_bitmap, cmd); 1464 ssid_bitmap, cmd);
1444 1465
1445 iwl_mvm_build_unified_scan_probe(mvm, vif, ies, cmd); 1466 preq = (void *)(cmd->data + sizeof(struct iwl_scan_channel_cfg_lmac) *
1467 mvm->fw->ucode_capa.n_scan_channels);
1468
1469 iwl_mvm_build_unified_scan_probe(mvm, vif, ies, preq);
1446 1470
1447 ret = iwl_mvm_send_cmd(mvm, &hcmd); 1471 ret = iwl_mvm_send_cmd(mvm, &hcmd);
1448 if (!ret) { 1472 if (!ret) {
@@ -1464,6 +1488,10 @@ int iwl_mvm_unified_sched_scan_lmac(struct iwl_mvm *mvm,
1464 1488
1465int iwl_mvm_cancel_scan(struct iwl_mvm *mvm) 1489int iwl_mvm_cancel_scan(struct iwl_mvm *mvm)
1466{ 1490{
1491 if (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN)
1492 return iwl_umac_scan_stop(mvm, IWL_UMAC_SCAN_UID_REG_SCAN,
1493 true);
1494
1467 if (mvm->scan_status == IWL_MVM_SCAN_NONE) 1495 if (mvm->scan_status == IWL_MVM_SCAN_NONE)
1468 return 0; 1496 return 0;
1469 1497
@@ -1478,3 +1506,568 @@ int iwl_mvm_cancel_scan(struct iwl_mvm *mvm)
1478 return iwl_mvm_scan_offload_stop(mvm, true); 1506 return iwl_mvm_scan_offload_stop(mvm, true);
1479 return iwl_mvm_cancel_regular_scan(mvm); 1507 return iwl_mvm_cancel_regular_scan(mvm);
1480} 1508}
1509
1510/* UMAC scan API */
1511
1512struct iwl_umac_scan_done {
1513 struct iwl_mvm *mvm;
1514 enum iwl_umac_scan_uid_type type;
1515};
1516
1517static int rate_to_scan_rate_flag(unsigned int rate)
1518{
1519 static const int rate_to_scan_rate[IWL_RATE_COUNT] = {
1520 [IWL_RATE_1M_INDEX] = SCAN_CONFIG_RATE_1M,
1521 [IWL_RATE_2M_INDEX] = SCAN_CONFIG_RATE_2M,
1522 [IWL_RATE_5M_INDEX] = SCAN_CONFIG_RATE_5M,
1523 [IWL_RATE_11M_INDEX] = SCAN_CONFIG_RATE_11M,
1524 [IWL_RATE_6M_INDEX] = SCAN_CONFIG_RATE_6M,
1525 [IWL_RATE_9M_INDEX] = SCAN_CONFIG_RATE_9M,
1526 [IWL_RATE_12M_INDEX] = SCAN_CONFIG_RATE_12M,
1527 [IWL_RATE_18M_INDEX] = SCAN_CONFIG_RATE_18M,
1528 [IWL_RATE_24M_INDEX] = SCAN_CONFIG_RATE_24M,
1529 [IWL_RATE_36M_INDEX] = SCAN_CONFIG_RATE_36M,
1530 [IWL_RATE_48M_INDEX] = SCAN_CONFIG_RATE_48M,
1531 [IWL_RATE_54M_INDEX] = SCAN_CONFIG_RATE_54M,
1532 };
1533
1534 return rate_to_scan_rate[rate];
1535}
1536
1537static __le32 iwl_mvm_scan_config_rates(struct iwl_mvm *mvm)
1538{
1539 struct ieee80211_supported_band *band;
1540 unsigned int rates = 0;
1541 int i;
1542
1543 band = &mvm->nvm_data->bands[IEEE80211_BAND_2GHZ];
1544 for (i = 0; i < band->n_bitrates; i++)
1545 rates |= rate_to_scan_rate_flag(band->bitrates[i].hw_value);
1546 band = &mvm->nvm_data->bands[IEEE80211_BAND_5GHZ];
1547 for (i = 0; i < band->n_bitrates; i++)
1548 rates |= rate_to_scan_rate_flag(band->bitrates[i].hw_value);
1549
1550 /* Set both basic rates and supported rates */
1551 rates |= SCAN_CONFIG_SUPPORTED_RATE(rates);
1552
1553 return cpu_to_le32(rates);
1554}
1555
1556int iwl_mvm_config_scan(struct iwl_mvm *mvm)
1557{
1558
1559 struct iwl_scan_config *scan_config;
1560 struct ieee80211_supported_band *band;
1561 int num_channels =
1562 mvm->nvm_data->bands[IEEE80211_BAND_2GHZ].n_channels +
1563 mvm->nvm_data->bands[IEEE80211_BAND_5GHZ].n_channels;
1564 int ret, i, j = 0, cmd_size, data_size;
1565 struct iwl_host_cmd cmd = {
1566 .id = SCAN_CFG_CMD,
1567 };
1568
1569 if (WARN_ON(num_channels > mvm->fw->ucode_capa.n_scan_channels))
1570 return -ENOBUFS;
1571
1572 cmd_size = sizeof(*scan_config) + mvm->fw->ucode_capa.n_scan_channels;
1573
1574 scan_config = kzalloc(cmd_size, GFP_KERNEL);
1575 if (!scan_config)
1576 return -ENOMEM;
1577
1578 data_size = cmd_size - sizeof(struct iwl_mvm_umac_cmd_hdr);
1579 scan_config->hdr.size = cpu_to_le16(data_size);
1580 scan_config->flags = cpu_to_le32(SCAN_CONFIG_FLAG_ACTIVATE |
1581 SCAN_CONFIG_FLAG_ALLOW_CHUB_REQS |
1582 SCAN_CONFIG_FLAG_SET_TX_CHAINS |
1583 SCAN_CONFIG_FLAG_SET_RX_CHAINS |
1584 SCAN_CONFIG_FLAG_SET_ALL_TIMES |
1585 SCAN_CONFIG_FLAG_SET_LEGACY_RATES |
1586 SCAN_CONFIG_FLAG_SET_MAC_ADDR |
1587 SCAN_CONFIG_FLAG_SET_CHANNEL_FLAGS|
1588 SCAN_CONFIG_N_CHANNELS(num_channels));
1589 scan_config->tx_chains = cpu_to_le32(mvm->fw->valid_tx_ant);
1590 scan_config->rx_chains = cpu_to_le32(iwl_mvm_scan_rx_ant(mvm));
1591 scan_config->legacy_rates = iwl_mvm_scan_config_rates(mvm);
1592 scan_config->out_of_channel_time = cpu_to_le32(170);
1593 scan_config->suspend_time = cpu_to_le32(30);
1594 scan_config->dwell_active = 20;
1595 scan_config->dwell_passive = 110;
1596 scan_config->dwell_fragmented = 20;
1597
1598 memcpy(&scan_config->mac_addr, &mvm->addresses[0].addr, ETH_ALEN);
1599
1600 scan_config->bcast_sta_id = mvm->aux_sta.sta_id;
1601 scan_config->channel_flags = IWL_CHANNEL_FLAG_EBS |
1602 IWL_CHANNEL_FLAG_ACCURATE_EBS |
1603 IWL_CHANNEL_FLAG_EBS_ADD |
1604 IWL_CHANNEL_FLAG_PRE_SCAN_PASSIVE2ACTIVE;
1605
1606 band = &mvm->nvm_data->bands[IEEE80211_BAND_2GHZ];
1607 for (i = 0; i < band->n_channels; i++, j++)
1608 scan_config->channel_array[j] = band->channels[i].center_freq;
1609 band = &mvm->nvm_data->bands[IEEE80211_BAND_5GHZ];
1610 for (i = 0; i < band->n_channels; i++, j++)
1611 scan_config->channel_array[j] = band->channels[i].center_freq;
1612
1613 cmd.data[0] = scan_config;
1614 cmd.len[0] = cmd_size;
1615 cmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY;
1616
1617 IWL_DEBUG_SCAN(mvm, "Sending UMAC scan config\n");
1618
1619 ret = iwl_mvm_send_cmd(mvm, &cmd);
1620
1621 kfree(scan_config);
1622 return ret;
1623}
1624
1625static int iwl_mvm_find_scan_uid(struct iwl_mvm *mvm, u32 uid)
1626{
1627 int i;
1628
1629 for (i = 0; i < IWL_MVM_MAX_SIMULTANEOUS_SCANS; i++)
1630 if (mvm->scan_uid[i] == uid)
1631 return i;
1632
1633 return i;
1634}
1635
1636static int iwl_mvm_find_free_scan_uid(struct iwl_mvm *mvm)
1637{
1638 return iwl_mvm_find_scan_uid(mvm, 0);
1639}
1640
1641static bool iwl_mvm_find_scan_type(struct iwl_mvm *mvm,
1642 enum iwl_umac_scan_uid_type type)
1643{
1644 int i;
1645
1646 for (i = 0; i < IWL_MVM_MAX_SIMULTANEOUS_SCANS; i++)
1647 if (mvm->scan_uid[i] & type)
1648 return true;
1649
1650 return false;
1651}
1652
1653static u32 iwl_generate_scan_uid(struct iwl_mvm *mvm,
1654 enum iwl_umac_scan_uid_type type)
1655{
1656 u32 uid;
1657
1658 /* make sure exactly one bit is on in scan type */
1659 WARN_ON(hweight8(type) != 1);
1660
1661 /*
1662 * Make sure scan uids are unique. If one scan lasts long time while
1663 * others are completing frequently, the seq number will wrap up and
1664 * we may have more than one scan with the same uid.
1665 */
1666 do {
1667 uid = type | (mvm->scan_seq_num <<
1668 IWL_UMAC_SCAN_UID_SEQ_OFFSET);
1669 mvm->scan_seq_num++;
1670 } while (iwl_mvm_find_scan_uid(mvm, uid) <
1671 IWL_MVM_MAX_SIMULTANEOUS_SCANS);
1672
1673 IWL_DEBUG_SCAN(mvm, "Generated scan UID %u\n", uid);
1674
1675 return uid;
1676}
1677
1678static void
1679iwl_mvm_build_generic_umac_scan_cmd(struct iwl_mvm *mvm,
1680 struct iwl_scan_req_umac *cmd,
1681 struct iwl_mvm_scan_params *params)
1682{
1683 memset(cmd, 0, ksize(cmd));
1684 cmd->hdr.size = cpu_to_le16(iwl_mvm_scan_size(mvm) -
1685 sizeof(struct iwl_mvm_umac_cmd_hdr));
1686 cmd->active_dwell = params->dwell[IEEE80211_BAND_2GHZ].active;
1687 cmd->passive_dwell = params->dwell[IEEE80211_BAND_2GHZ].passive;
1688 if (params->passive_fragmented)
1689 cmd->fragmented_dwell =
1690 params->dwell[IEEE80211_BAND_2GHZ].passive;
1691 cmd->max_out_time = cpu_to_le32(params->max_out_time);
1692 cmd->suspend_time = cpu_to_le32(params->suspend_time);
1693 cmd->scan_priority = cpu_to_le32(IWL_SCAN_PRIORITY_HIGH);
1694}
1695
1696static void
1697iwl_mvm_umac_scan_cfg_channels(struct iwl_mvm *mvm,
1698 struct ieee80211_channel **channels,
1699 int n_channels, u32 ssid_bitmap,
1700 struct iwl_scan_req_umac *cmd)
1701{
1702 struct iwl_scan_channel_cfg_umac *channel_cfg = (void *)&cmd->data;
1703 int i;
1704
1705 for (i = 0; i < n_channels; i++) {
1706 channel_cfg[i].flags = cpu_to_le32(ssid_bitmap);
1707 channel_cfg[i].channel_num = channels[i]->hw_value;
1708 channel_cfg[i].iter_count = 1;
1709 channel_cfg[i].iter_interval = 0;
1710 }
1711}
1712
1713static u32 iwl_mvm_scan_umac_common_flags(struct iwl_mvm *mvm, int n_ssids,
1714 struct cfg80211_ssid *ssids,
1715 int fragmented)
1716{
1717 int flags = 0;
1718
1719 if (n_ssids == 0)
1720 flags = IWL_UMAC_SCAN_GEN_FLAGS_PASSIVE;
1721
1722 if (n_ssids == 1 && ssids[0].ssid_len != 0)
1723 flags |= IWL_UMAC_SCAN_GEN_FLAGS_PRE_CONNECT;
1724
1725 if (fragmented)
1726 flags |= IWL_UMAC_SCAN_GEN_FLAGS_FRAGMENTED;
1727
1728 if (iwl_mvm_rrm_scan_needed(mvm))
1729 flags |= IWL_UMAC_SCAN_GEN_FLAGS_RRM_ENABLED;
1730
1731 return flags;
1732}
1733
1734int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
1735 struct ieee80211_scan_request *req)
1736{
1737 struct iwl_host_cmd hcmd = {
1738 .id = SCAN_REQ_UMAC,
1739 .len = { iwl_mvm_scan_size(mvm), },
1740 .data = { mvm->scan_cmd, },
1741 .dataflags = { IWL_HCMD_DFL_NOCOPY, },
1742 };
1743 struct iwl_scan_req_umac *cmd = mvm->scan_cmd;
1744 struct iwl_scan_req_umac_tail *sec_part = (void *)&cmd->data +
1745 sizeof(struct iwl_scan_channel_cfg_umac) *
1746 mvm->fw->ucode_capa.n_scan_channels;
1747 struct iwl_mvm_scan_params params = {};
1748 u32 uid, flags;
1749 int ssid_bitmap = 0;
1750 int ret, i, uid_idx;
1751
1752 lockdep_assert_held(&mvm->mutex);
1753
1754 uid_idx = iwl_mvm_find_free_scan_uid(mvm);
1755 if (uid_idx >= IWL_MVM_MAX_SIMULTANEOUS_SCANS)
1756 return -EBUSY;
1757
1758 /* we should have failed registration if scan_cmd was NULL */
1759 if (WARN_ON(mvm->scan_cmd == NULL))
1760 return -ENOMEM;
1761
1762 if (WARN_ON(req->req.n_ssids > PROBE_OPTION_MAX ||
1763 req->ies.common_ie_len +
1764 req->ies.len[NL80211_BAND_2GHZ] +
1765 req->ies.len[NL80211_BAND_5GHZ] + 24 + 2 >
1766 SCAN_OFFLOAD_PROBE_REQ_SIZE || req->req.n_channels >
1767 mvm->fw->ucode_capa.n_scan_channels))
1768 return -ENOBUFS;
1769
1770 iwl_mvm_scan_calc_params(mvm, vif, req->req.n_ssids, req->req.flags,
1771 &params);
1772
1773 iwl_mvm_build_generic_umac_scan_cmd(mvm, cmd, &params);
1774
1775 uid = iwl_generate_scan_uid(mvm, IWL_UMAC_SCAN_UID_REG_SCAN);
1776 mvm->scan_uid[uid_idx] = uid;
1777 cmd->uid = cpu_to_le32(uid);
1778
1779 cmd->ooc_priority = cpu_to_le32(IWL_SCAN_PRIORITY_HIGH);
1780
1781 flags = iwl_mvm_scan_umac_common_flags(mvm, req->req.n_ssids,
1782 req->req.ssids,
1783 params.passive_fragmented);
1784
1785 flags |= IWL_UMAC_SCAN_GEN_FLAGS_PASS_ALL;
1786
1787 cmd->general_flags = cpu_to_le32(flags);
1788 cmd->n_channels = req->req.n_channels;
1789
1790 for (i = 0; i < req->req.n_ssids; i++)
1791 ssid_bitmap |= BIT(i);
1792
1793 iwl_mvm_umac_scan_cfg_channels(mvm, req->req.channels,
1794 req->req.n_channels, ssid_bitmap, cmd);
1795
1796 sec_part->schedule[0].iter_count = 1;
1797 sec_part->delay = 0;
1798
1799 iwl_mvm_build_unified_scan_probe(mvm, vif, &req->ies, &sec_part->preq);
1800
1801 iwl_mvm_scan_fill_ssids(sec_part->direct_scan, req->req.ssids,
1802 req->req.n_ssids, 0);
1803
1804 ret = iwl_mvm_send_cmd(mvm, &hcmd);
1805 if (!ret) {
1806 IWL_DEBUG_SCAN(mvm,
1807 "Scan request was sent successfully\n");
1808 } else {
1809 /*
1810 * If the scan failed, it usually means that the FW was unable
1811 * to allocate the time events. Warn on it, but maybe we
1812 * should try to send the command again with different params.
1813 */
1814 IWL_ERR(mvm, "Scan failed! ret %d\n", ret);
1815 }
1816 return ret;
1817}
1818
1819int iwl_mvm_sched_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
1820 struct cfg80211_sched_scan_request *req,
1821 struct ieee80211_scan_ies *ies)
1822{
1823
1824 struct iwl_host_cmd hcmd = {
1825 .id = SCAN_REQ_UMAC,
1826 .len = { iwl_mvm_scan_size(mvm), },
1827 .data = { mvm->scan_cmd, },
1828 .dataflags = { IWL_HCMD_DFL_NOCOPY, },
1829 };
1830 struct iwl_scan_req_umac *cmd = mvm->scan_cmd;
1831 struct iwl_scan_req_umac_tail *sec_part = (void *)&cmd->data +
1832 sizeof(struct iwl_scan_channel_cfg_umac) *
1833 mvm->fw->ucode_capa.n_scan_channels;
1834 struct iwl_mvm_scan_params params = {};
1835 u32 uid, flags;
1836 int ssid_bitmap = 0;
1837 int ret, uid_idx;
1838
1839 lockdep_assert_held(&mvm->mutex);
1840
1841 uid_idx = iwl_mvm_find_free_scan_uid(mvm);
1842 if (uid_idx >= IWL_MVM_MAX_SIMULTANEOUS_SCANS)
1843 return -EBUSY;
1844
1845 /* we should have failed registration if scan_cmd was NULL */
1846 if (WARN_ON(mvm->scan_cmd == NULL))
1847 return -ENOMEM;
1848
1849 if (WARN_ON(req->n_ssids > PROBE_OPTION_MAX ||
1850 ies->common_ie_len + ies->len[NL80211_BAND_2GHZ] +
1851 ies->len[NL80211_BAND_5GHZ] + 24 + 2 >
1852 SCAN_OFFLOAD_PROBE_REQ_SIZE || req->n_channels >
1853 mvm->fw->ucode_capa.n_scan_channels))
1854 return -ENOBUFS;
1855
1856 iwl_mvm_scan_calc_params(mvm, vif, req->n_ssids, req->flags,
1857 &params);
1858
1859 iwl_mvm_build_generic_umac_scan_cmd(mvm, cmd, &params);
1860
1861 cmd->flags = cpu_to_le32(IWL_UMAC_SCAN_FLAG_PREEMPTIVE);
1862
1863 uid = iwl_generate_scan_uid(mvm, IWL_UMAC_SCAN_UID_SCHED_SCAN);
1864 mvm->scan_uid[uid_idx] = uid;
1865 cmd->uid = cpu_to_le32(uid);
1866
1867 cmd->ooc_priority = cpu_to_le32(IWL_SCAN_PRIORITY_LOW);
1868
1869 flags = iwl_mvm_scan_umac_common_flags(mvm, req->n_ssids, req->ssids,
1870 params.passive_fragmented);
1871
1872 flags |= IWL_UMAC_SCAN_GEN_FLAGS_PERIODIC;
1873
1874 if (iwl_mvm_scan_pass_all(mvm, req))
1875 flags |= IWL_UMAC_SCAN_GEN_FLAGS_PASS_ALL;
1876 else
1877 flags |= IWL_UMAC_SCAN_GEN_FLAGS_MATCH;
1878
1879 cmd->general_flags = cpu_to_le32(flags);
1880
1881 if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_EBS_SUPPORT &&
1882 mvm->last_ebs_successful)
1883 cmd->channel_flags = IWL_SCAN_CHANNEL_FLAG_EBS |
1884 IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE |
1885 IWL_SCAN_CHANNEL_FLAG_CACHE_ADD;
1886
1887 cmd->n_channels = req->n_channels;
1888
1889 iwl_scan_offload_build_ssid(req, sec_part->direct_scan, &ssid_bitmap,
1890 false);
1891
1892 /* This API uses bits 0-19 instead of 1-20. */
1893 ssid_bitmap = ssid_bitmap >> 1;
1894
1895 iwl_mvm_umac_scan_cfg_channels(mvm, req->channels, req->n_channels,
1896 ssid_bitmap, cmd);
1897
1898 sec_part->schedule[0].interval =
1899 cpu_to_le16(req->interval / MSEC_PER_SEC);
1900 sec_part->schedule[0].iter_count = 0xff;
1901
1902 sec_part->delay = 0;
1903
1904 iwl_mvm_build_unified_scan_probe(mvm, vif, ies, &sec_part->preq);
1905
1906 ret = iwl_mvm_send_cmd(mvm, &hcmd);
1907 if (!ret) {
1908 IWL_DEBUG_SCAN(mvm,
1909 "Sched scan request was sent successfully\n");
1910 } else {
1911 /*
1912 * If the scan failed, it usually means that the FW was unable
1913 * to allocate the time events. Warn on it, but maybe we
1914 * should try to send the command again with different params.
1915 */
1916 IWL_ERR(mvm, "Sched scan failed! ret %d\n", ret);
1917 }
1918 return ret;
1919}
1920
1921int iwl_mvm_rx_umac_scan_complete_notif(struct iwl_mvm *mvm,
1922 struct iwl_rx_cmd_buffer *rxb,
1923 struct iwl_device_cmd *cmd)
1924{
1925 struct iwl_rx_packet *pkt = rxb_addr(rxb);
1926 struct iwl_umac_scan_complete *notif = (void *)pkt->data;
1927 u32 uid = __le32_to_cpu(notif->uid);
1928 bool sched = !!(uid & IWL_UMAC_SCAN_UID_SCHED_SCAN);
1929 int uid_idx = iwl_mvm_find_scan_uid(mvm, uid);
1930
1931 if (WARN(uid_idx >= IWL_MVM_MAX_SIMULTANEOUS_SCANS,
1932 "Scan notification for uknown scan ID\n"))
1933 return 0;
1934
1935 IWL_DEBUG_SCAN(mvm,
1936 "Scan completed, uid %u type %s, status %s, EBS status %s\n",
1937 uid, sched ? "sched" : "regular",
1938 notif->status == IWL_SCAN_OFFLOAD_COMPLETED ?
1939 "completed" : "aborted",
1940 notif->ebs_status == IWL_SCAN_EBS_SUCCESS ?
1941 "success" : "failed");
1942
1943 mvm->last_ebs_successful = !notif->ebs_status;
1944 mvm->scan_uid[uid_idx] = 0;
1945
1946 if (!sched) {
1947 ieee80211_scan_completed(mvm->hw,
1948 notif->status ==
1949 IWL_SCAN_OFFLOAD_ABORTED);
1950 iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
1951 } else if (!iwl_mvm_find_scan_type(mvm, IWL_UMAC_SCAN_UID_SCHED_SCAN)) {
1952 ieee80211_sched_scan_stopped(mvm->hw);
1953 } else {
1954 IWL_DEBUG_SCAN(mvm, "Another sched scan is running\n");
1955 }
1956
1957 return 0;
1958}
1959
1960static bool iwl_scan_umac_done_check(struct iwl_notif_wait_data *notif_wait,
1961 struct iwl_rx_packet *pkt, void *data)
1962{
1963 struct iwl_umac_scan_done *scan_done = data;
1964 struct iwl_umac_scan_complete *notif = (void *)pkt->data;
1965 u32 uid = __le32_to_cpu(notif->uid);
1966 int uid_idx = iwl_mvm_find_scan_uid(scan_done->mvm, uid);
1967
1968 if (WARN_ON(pkt->hdr.cmd != SCAN_COMPLETE_UMAC))
1969 return false;
1970
1971 if (uid_idx >= IWL_MVM_MAX_SIMULTANEOUS_SCANS)
1972 return false;
1973
1974 /*
1975 * Clear scan uid of scans that was aborted from above and completed
1976 * in FW so the RX handler does nothing.
1977 */
1978 scan_done->mvm->scan_uid[uid_idx] = 0;
1979
1980 return !iwl_mvm_find_scan_type(scan_done->mvm, scan_done->type);
1981}
1982
1983static int iwl_umac_scan_abort_one(struct iwl_mvm *mvm, u32 uid)
1984{
1985 struct iwl_umac_scan_abort cmd = {
1986 .hdr.size = cpu_to_le16(sizeof(struct iwl_umac_scan_abort) -
1987 sizeof(struct iwl_mvm_umac_cmd_hdr)),
1988 .uid = cpu_to_le32(uid),
1989 };
1990
1991 lockdep_assert_held(&mvm->mutex);
1992
1993 IWL_DEBUG_SCAN(mvm, "Sending scan abort, uid %u\n", uid);
1994
1995 return iwl_mvm_send_cmd_pdu(mvm, SCAN_ABORT_UMAC, 0, sizeof(cmd), &cmd);
1996}
1997
1998static int iwl_umac_scan_stop(struct iwl_mvm *mvm,
1999 enum iwl_umac_scan_uid_type type, bool notify)
2000{
2001 struct iwl_notification_wait wait_scan_done;
2002 static const u8 scan_done_notif[] = { SCAN_COMPLETE_UMAC, };
2003 struct iwl_umac_scan_done scan_done = {
2004 .mvm = mvm,
2005 .type = type,
2006 };
2007 int i, ret = -EIO;
2008
2009 iwl_init_notification_wait(&mvm->notif_wait, &wait_scan_done,
2010 scan_done_notif,
2011 ARRAY_SIZE(scan_done_notif),
2012 iwl_scan_umac_done_check, &scan_done);
2013
2014 IWL_DEBUG_SCAN(mvm, "Preparing to stop scan, type %x\n", type);
2015
2016 for (i = 0; i < IWL_MVM_MAX_SIMULTANEOUS_SCANS; i++) {
2017 if (mvm->scan_uid[i] & type) {
2018 int err;
2019
2020 if (iwl_mvm_is_radio_killed(mvm) &&
2021 (type & IWL_UMAC_SCAN_UID_REG_SCAN)) {
2022 ieee80211_scan_completed(mvm->hw, true);
2023 iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
2024 break;
2025 }
2026
2027 err = iwl_umac_scan_abort_one(mvm, mvm->scan_uid[i]);
2028 if (!err)
2029 ret = 0;
2030 }
2031 }
2032
2033 if (ret) {
2034 IWL_DEBUG_SCAN(mvm, "Couldn't stop scan\n");
2035 iwl_remove_notification(&mvm->notif_wait, &wait_scan_done);
2036 return ret;
2037 }
2038
2039 ret = iwl_wait_notification(&mvm->notif_wait, &wait_scan_done, 1 * HZ);
2040 if (ret)
2041 return ret;
2042
2043 if (notify) {
2044 if (type & IWL_UMAC_SCAN_UID_SCHED_SCAN)
2045 ieee80211_sched_scan_stopped(mvm->hw);
2046 if (type & IWL_UMAC_SCAN_UID_REG_SCAN) {
2047 ieee80211_scan_completed(mvm->hw, true);
2048 iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
2049 }
2050 }
2051
2052 return ret;
2053}
2054
2055int iwl_mvm_scan_size(struct iwl_mvm *mvm)
2056{
2057 if (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN)
2058 return sizeof(struct iwl_scan_req_umac) +
2059 sizeof(struct iwl_scan_channel_cfg_umac) *
2060 mvm->fw->ucode_capa.n_scan_channels +
2061 sizeof(struct iwl_scan_req_umac_tail);
2062
2063 if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)
2064 return sizeof(struct iwl_scan_req_unified_lmac) +
2065 sizeof(struct iwl_scan_channel_cfg_lmac) *
2066 mvm->fw->ucode_capa.n_scan_channels +
2067 sizeof(struct iwl_scan_probe_req);
2068
2069 return sizeof(struct iwl_scan_cmd) +
2070 mvm->fw->ucode_capa.max_probe_length +
2071 mvm->fw->ucode_capa.n_scan_channels *
2072 sizeof(struct iwl_scan_channel);
2073}