Commit a339e918 authored by Luca Coelho's avatar Luca Coelho Committed by Emmanuel Grumbach

iwlwifi: mvm: handle pass all scan reporting

The firmware doesn't send match found notifications when no matchsets
are passed.  This makes sense because if there are no matchsets,
nothing can be matched.  But the nl80211 API should report when there
are results available, even if no matchsets were passed.

To handle this, we can use the firmware's ITERATION_COMPLETE
reporting, which will send us notifications every time it completed a
scheduled scan iteration.  Then we can set a flag when we received
beacons and use that to report that results are available.
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
Signed-off-by: default avatarEmmanuel Grumbach <emmanuel.grumbach@intel.com>
parent 3cce9bb0
...@@ -493,6 +493,12 @@ enum iwl_mvm_scan_type { ...@@ -493,6 +493,12 @@ enum iwl_mvm_scan_type {
IWL_SCAN_TYPE_FRAGMENTED, IWL_SCAN_TYPE_FRAGMENTED,
}; };
enum iwl_mvm_sched_scan_pass_all_states {
SCHED_SCAN_PASS_ALL_DISABLED,
SCHED_SCAN_PASS_ALL_ENABLED,
SCHED_SCAN_PASS_ALL_FOUND,
};
/** /**
* struct iwl_nvm_section - describes an NVM section in memory. * struct iwl_nvm_section - describes an NVM section in memory.
* *
...@@ -687,6 +693,7 @@ struct iwl_mvm { ...@@ -687,6 +693,7 @@ struct iwl_mvm {
void *scan_cmd; void *scan_cmd;
struct iwl_mcast_filter_cmd *mcast_filter_cmd; struct iwl_mcast_filter_cmd *mcast_filter_cmd;
enum iwl_mvm_scan_type scan_type; enum iwl_mvm_scan_type scan_type;
enum iwl_mvm_sched_scan_pass_all_states sched_scan_pass_all;
/* max number of simultaneous scans the FW supports */ /* max number of simultaneous scans the FW supports */
unsigned int max_scans; unsigned int max_scans;
......
...@@ -448,6 +448,12 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi, ...@@ -448,6 +448,12 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi,
iwl_mvm_update_frame_stats(mvm, rate_n_flags, iwl_mvm_update_frame_stats(mvm, rate_n_flags,
rx_status->flag & RX_FLAG_AMPDU_DETAILS); rx_status->flag & RX_FLAG_AMPDU_DETAILS);
#endif #endif
if (unlikely((ieee80211_is_beacon(hdr->frame_control) ||
ieee80211_is_probe_resp(hdr->frame_control)) &&
mvm->sched_scan_pass_all == SCHED_SCAN_PASS_ALL_ENABLED))
mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_FOUND;
iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb, hdr, len, ampdu_status, iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb, hdr, len, ampdu_status,
crypt_len, rxb); crypt_len, rxb);
} }
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
* *
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 Intel Deutschland GmbH
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
...@@ -33,6 +34,7 @@ ...@@ -33,6 +34,7 @@
* *
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 Intel Deutschland GmbH
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
...@@ -297,6 +299,12 @@ void iwl_mvm_rx_lmac_scan_iter_complete_notif(struct iwl_mvm *mvm, ...@@ -297,6 +299,12 @@ void iwl_mvm_rx_lmac_scan_iter_complete_notif(struct iwl_mvm *mvm,
iwl_mvm_dump_channel_list(notif->results, iwl_mvm_dump_channel_list(notif->results,
notif->scanned_channels, buf, notif->scanned_channels, buf,
sizeof(buf))); sizeof(buf)));
if (mvm->sched_scan_pass_all == SCHED_SCAN_PASS_ALL_FOUND) {
IWL_DEBUG_SCAN(mvm, "Pass all scheduled scan results found\n");
ieee80211_sched_scan_results(mvm->hw);
mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_ENABLED;
}
} }
void iwl_mvm_rx_scan_match_found(struct iwl_mvm *mvm, void iwl_mvm_rx_scan_match_found(struct iwl_mvm *mvm,
...@@ -380,6 +388,7 @@ void iwl_mvm_rx_lmac_scan_complete_notif(struct iwl_mvm *mvm, ...@@ -380,6 +388,7 @@ void iwl_mvm_rx_lmac_scan_complete_notif(struct iwl_mvm *mvm,
mvm->scan_status &= ~IWL_MVM_SCAN_SCHED; mvm->scan_status &= ~IWL_MVM_SCAN_SCHED;
ieee80211_sched_scan_stopped(mvm->hw); ieee80211_sched_scan_stopped(mvm->hw);
mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_DISABLED;
} else if (mvm->scan_status & IWL_MVM_SCAN_REGULAR) { } else if (mvm->scan_status & IWL_MVM_SCAN_REGULAR) {
IWL_DEBUG_SCAN(mvm, "Regular scan %s, EBS status %s (FW)\n", IWL_DEBUG_SCAN(mvm, "Regular scan %s, EBS status %s (FW)\n",
aborted ? "aborted" : "completed", aborted ? "aborted" : "completed",
...@@ -533,10 +542,13 @@ static bool iwl_mvm_scan_pass_all(struct iwl_mvm *mvm, ...@@ -533,10 +542,13 @@ static bool iwl_mvm_scan_pass_all(struct iwl_mvm *mvm,
IWL_DEBUG_SCAN(mvm, IWL_DEBUG_SCAN(mvm,
"Sending scheduled scan with filtering, n_match_sets %d\n", "Sending scheduled scan with filtering, n_match_sets %d\n",
req->n_match_sets); req->n_match_sets);
mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_DISABLED;
return false; return false;
} }
IWL_DEBUG_SCAN(mvm, "Sending Scheduled scan without filtering\n"); IWL_DEBUG_SCAN(mvm, "Sending Scheduled scan without filtering\n");
mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_ENABLED;
return true; return true;
} }
...@@ -788,6 +800,9 @@ static int iwl_mvm_scan_lmac_flags(struct iwl_mvm *mvm, ...@@ -788,6 +800,9 @@ static int iwl_mvm_scan_lmac_flags(struct iwl_mvm *mvm,
flags |= IWL_MVM_LMAC_SCAN_FLAG_ITER_COMPLETE; flags |= IWL_MVM_LMAC_SCAN_FLAG_ITER_COMPLETE;
#endif #endif
if (mvm->sched_scan_pass_all == SCHED_SCAN_PASS_ALL_ENABLED)
flags |= IWL_MVM_LMAC_SCAN_FLAG_ITER_COMPLETE;
if (iwl_mvm_is_regular_scan(params) && if (iwl_mvm_is_regular_scan(params) &&
vif->type != NL80211_IFTYPE_P2P_DEVICE && vif->type != NL80211_IFTYPE_P2P_DEVICE &&
params->type != IWL_SCAN_TYPE_FRAGMENTED) params->type != IWL_SCAN_TYPE_FRAGMENTED)
...@@ -1074,6 +1089,9 @@ static u32 iwl_mvm_scan_umac_flags(struct iwl_mvm *mvm, ...@@ -1074,6 +1089,9 @@ static u32 iwl_mvm_scan_umac_flags(struct iwl_mvm *mvm,
flags |= IWL_UMAC_SCAN_GEN_FLAGS_ITER_COMPLETE; flags |= IWL_UMAC_SCAN_GEN_FLAGS_ITER_COMPLETE;
#endif #endif
if (mvm->sched_scan_pass_all == SCHED_SCAN_PASS_ALL_ENABLED)
flags |= IWL_UMAC_SCAN_GEN_FLAGS_ITER_COMPLETE;
if (iwl_mvm_is_regular_scan(params) && if (iwl_mvm_is_regular_scan(params) &&
vif->type != NL80211_IFTYPE_P2P_DEVICE && vif->type != NL80211_IFTYPE_P2P_DEVICE &&
params->type != IWL_SCAN_TYPE_FRAGMENTED) params->type != IWL_SCAN_TYPE_FRAGMENTED)
...@@ -1301,10 +1319,6 @@ int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm, ...@@ -1301,10 +1319,6 @@ int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm,
return -EBUSY; return -EBUSY;
} }
/* we don't support "match all" in the firmware */
if (!req->n_match_sets)
return -EOPNOTSUPP;
ret = iwl_mvm_check_running_scans(mvm, type); ret = iwl_mvm_check_running_scans(mvm, type);
if (ret) if (ret)
return ret; return ret;
...@@ -1400,6 +1414,7 @@ void iwl_mvm_rx_umac_scan_complete_notif(struct iwl_mvm *mvm, ...@@ -1400,6 +1414,7 @@ void iwl_mvm_rx_umac_scan_complete_notif(struct iwl_mvm *mvm,
iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
} else if (mvm->scan_uid_status[uid] == IWL_MVM_SCAN_SCHED) { } else if (mvm->scan_uid_status[uid] == IWL_MVM_SCAN_SCHED) {
ieee80211_sched_scan_stopped(mvm->hw); ieee80211_sched_scan_stopped(mvm->hw);
mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_DISABLED;
} }
mvm->scan_status &= ~mvm->scan_uid_status[uid]; mvm->scan_status &= ~mvm->scan_uid_status[uid];
...@@ -1434,6 +1449,12 @@ void iwl_mvm_rx_umac_scan_iter_complete_notif(struct iwl_mvm *mvm, ...@@ -1434,6 +1449,12 @@ void iwl_mvm_rx_umac_scan_iter_complete_notif(struct iwl_mvm *mvm,
iwl_mvm_dump_channel_list(notif->results, iwl_mvm_dump_channel_list(notif->results,
notif->scanned_channels, buf, notif->scanned_channels, buf,
sizeof(buf))); sizeof(buf)));
if (mvm->sched_scan_pass_all == SCHED_SCAN_PASS_ALL_FOUND) {
IWL_DEBUG_SCAN(mvm, "Pass all scheduled scan results found\n");
ieee80211_sched_scan_results(mvm->hw);
mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_ENABLED;
}
} }
static int iwl_mvm_umac_scan_abort(struct iwl_mvm *mvm, int type) static int iwl_mvm_umac_scan_abort(struct iwl_mvm *mvm, int type)
...@@ -1528,6 +1549,7 @@ void iwl_mvm_report_scan_aborted(struct iwl_mvm *mvm) ...@@ -1528,6 +1549,7 @@ void iwl_mvm_report_scan_aborted(struct iwl_mvm *mvm)
uid = iwl_mvm_scan_uid_by_status(mvm, IWL_MVM_SCAN_SCHED); uid = iwl_mvm_scan_uid_by_status(mvm, IWL_MVM_SCAN_SCHED);
if (uid >= 0 && !mvm->restart_fw) { if (uid >= 0 && !mvm->restart_fw) {
ieee80211_sched_scan_stopped(mvm->hw); ieee80211_sched_scan_stopped(mvm->hw);
mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_DISABLED;
mvm->scan_uid_status[uid] = 0; mvm->scan_uid_status[uid] = 0;
} }
...@@ -1549,8 +1571,11 @@ void iwl_mvm_report_scan_aborted(struct iwl_mvm *mvm) ...@@ -1549,8 +1571,11 @@ void iwl_mvm_report_scan_aborted(struct iwl_mvm *mvm)
* restart_hw, so do not report if FW is about to be * restart_hw, so do not report if FW is about to be
* restarted. * restarted.
*/ */
if ((mvm->scan_status & IWL_MVM_SCAN_SCHED) && !mvm->restart_fw) if ((mvm->scan_status & IWL_MVM_SCAN_SCHED) &&
!mvm->restart_fw) {
ieee80211_sched_scan_stopped(mvm->hw); ieee80211_sched_scan_stopped(mvm->hw);
mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_DISABLED;
}
} }
} }
...@@ -1586,6 +1611,7 @@ int iwl_mvm_scan_stop(struct iwl_mvm *mvm, int type, bool notify) ...@@ -1586,6 +1611,7 @@ int iwl_mvm_scan_stop(struct iwl_mvm *mvm, int type, bool notify)
ieee80211_scan_completed(mvm->hw, true); ieee80211_scan_completed(mvm->hw, true);
} else if (notify) { } else if (notify) {
ieee80211_sched_scan_stopped(mvm->hw); ieee80211_sched_scan_stopped(mvm->hw);
mvm->sched_scan_pass_all = SCHED_SCAN_PASS_ALL_DISABLED;
} }
return ret; return ret;
......
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