@@ -1227,7 +1227,7 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
iwl_trans_stop_device(mvm->trans);
- mvm->scan_status = IWL_MVM_SCAN_NONE;
+ mvm->scan_status = 0;
mvm->ps_disabled = false;
mvm->calibrating = false;
@@ -2374,28 +2374,30 @@ static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw,
}
static int iwl_mvm_cancel_scan_wait_notif(struct iwl_mvm *mvm,
- enum iwl_scan_status scan_type)
+ unsigned int scan_type)
{
int ret;
bool wait_for_handlers = false;
mutex_lock(&mvm->mutex);
- if (mvm->scan_status != scan_type) {
+ if (!(mvm->scan_status & scan_type)) {
ret = 0;
/* make sure there are no pending notifications */
wait_for_handlers = true;
goto out;
}
+ /* It's okay to switch on bitmask values here, because we can
+ * only stop one scan type at a time.
+ */
switch (scan_type) {
case IWL_MVM_SCAN_SCHED:
ret = iwl_mvm_scan_offload_stop(mvm, true);
break;
- case IWL_MVM_SCAN_OS:
+ case IWL_MVM_SCAN_REGULAR:
ret = iwl_mvm_cancel_scan(mvm);
break;
- case IWL_MVM_SCAN_NONE:
default:
WARN_ON_ONCE(1);
ret = -EINVAL;
@@ -2440,7 +2442,7 @@ static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw,
goto out;
}
- if (mvm->scan_status != IWL_MVM_SCAN_NONE) {
+ if (mvm->scan_status & IWL_MVM_SCAN_REGULAR) {
ret = -EBUSY;
goto out;
}
@@ -2476,7 +2478,7 @@ static void iwl_mvm_mac_cancel_hw_scan(struct ieee80211_hw *hw,
/* FIXME: for now, we ignore this race for UMAC scans, since
* they don't set the scan_status.
*/
- if ((mvm->scan_status == IWL_MVM_SCAN_OS) ||
+ if ((mvm->scan_status & IWL_MVM_SCAN_REGULAR) ||
(mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN))
iwl_mvm_cancel_scan(mvm);
@@ -2797,7 +2799,7 @@ static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw,
int ret;
if (!(mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN)) {
- ret = iwl_mvm_cancel_scan_wait_notif(mvm, IWL_MVM_SCAN_OS);
+ ret = iwl_mvm_cancel_scan_wait_notif(mvm, IWL_MVM_SCAN_REGULAR);
if (ret)
return ret;
}
@@ -2815,14 +2817,14 @@ static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw,
goto out;
}
- if (mvm->scan_status != IWL_MVM_SCAN_NONE) {
+ if (mvm->scan_status & IWL_MVM_SCAN_SCHED) {
ret = -EBUSY;
goto out;
}
ret = iwl_mvm_scan_offload_start(mvm, vif, req, ies);
if (ret)
- mvm->scan_status = IWL_MVM_SCAN_NONE;
+ mvm->scan_status &= ~IWL_MVM_SCAN_SCHED;
out:
mutex_unlock(&mvm->mutex);
@@ -2848,7 +2850,7 @@ static int iwl_mvm_mac_sched_scan_stop(struct ieee80211_hw *hw,
/* FIXME: for now, we ignore this race for UMAC scans, since
* they don't set the scan_status.
*/
- if (mvm->scan_status != IWL_MVM_SCAN_SCHED &&
+ if (!(mvm->scan_status & IWL_MVM_SCAN_SCHED) &&
!(mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN)) {
mutex_unlock(&mvm->mutex);
return 0;
@@ -6,7 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
*
* 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
@@ -32,7 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -446,9 +446,19 @@ iwl_mvm_vif_from_mac80211(struct ieee80211_vif *vif)
extern const u8 tid_to_mac80211_ac[];
enum iwl_scan_status {
- IWL_MVM_SCAN_NONE,
- IWL_MVM_SCAN_OS,
- IWL_MVM_SCAN_SCHED,
+ IWL_MVM_SCAN_REGULAR = BIT(0),
+ IWL_MVM_SCAN_SCHED = BIT(1),
+
+ IWL_MVM_SCAN_STOPPING_REGULAR = BIT(8),
+ IWL_MVM_SCAN_STOPPING_SCHED = BIT(9),
+
+ IWL_MVM_SCAN_REGULAR_MASK = IWL_MVM_SCAN_REGULAR |
+ IWL_MVM_SCAN_STOPPING_REGULAR,
+ IWL_MVM_SCAN_SCHED_MASK = IWL_MVM_SCAN_SCHED |
+ IWL_MVM_SCAN_STOPPING_SCHED,
+
+ IWL_MVM_SCAN_STOPPING_MASK = 0xff00,
+ IWL_MVM_SCAN_MASK = 0x00ff,
};
/**
@@ -647,7 +657,7 @@ struct iwl_mvm {
u32 rts_threshold;
/* Scan status, cmd (pre-allocated) and auxiliary station */
- enum iwl_scan_status scan_status;
+ unsigned int scan_status;
void *scan_cmd;
struct iwl_mcast_filter_cmd *mcast_filter_cmd;
@@ -6,7 +6,7 @@
* GPL LICENSE SUMMARY
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
*
* 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
@@ -32,7 +32,7 @@
* BSD LICENSE
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -358,36 +358,58 @@ int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm,
struct iwl_device_cmd *cmd)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
- struct iwl_periodic_scan_complete *scan_notif;
-
- scan_notif = (void *)pkt->data;
+ struct iwl_periodic_scan_complete *scan_notif = (void *)pkt->data;
+ bool aborted = (scan_notif->status == IWL_SCAN_OFFLOAD_ABORTED);
+ bool ebs_successful = (scan_notif->ebs_status == IWL_SCAN_EBS_SUCCESS);
/* scan status must be locked for proper checking */
lockdep_assert_held(&mvm->mutex);
- IWL_DEBUG_SCAN(mvm,
- "%s completed, status %s, EBS status %s\n",
- mvm->scan_status == IWL_MVM_SCAN_SCHED ?
- "Scheduled scan" : "Scan",
- scan_notif->status == IWL_SCAN_OFFLOAD_COMPLETED ?
- "completed" : "aborted",
- scan_notif->ebs_status == IWL_SCAN_EBS_SUCCESS ?
- "success" : "failed");
+ /* We first check if we were stopping a scan, in which case we
+ * just clear the stopping flag. Then we check if it was a
+ * firmware initiated stop, in which case we need to inform
+ * mac80211.
+ * Note that we can have a stopping and a running scan
+ * simultaneously, but we can't have two different types of
+ * scans stopping or running at the same time (since LMAC
+ * doesn't support it).
+ */
+
+ if (mvm->scan_status & IWL_MVM_SCAN_STOPPING_SCHED) {
+ WARN_ON_ONCE(mvm->scan_status & IWL_MVM_SCAN_STOPPING_REGULAR);
+
+ IWL_DEBUG_SCAN(mvm, "Scheduled scan %s, EBS status %s\n",
+ aborted ? "aborted" : "completed",
+ ebs_successful ? "successful" : "failed");
+ mvm->scan_status &= ~IWL_MVM_SCAN_STOPPING_SCHED;
+ } else if (mvm->scan_status & IWL_MVM_SCAN_STOPPING_REGULAR) {
+ IWL_DEBUG_SCAN(mvm, "Regular scan %s, EBS status %s\n",
+ aborted ? "aborted" : "completed",
+ ebs_successful ? "successful" : "failed");
- /* only call mac80211 completion if the stop was initiated by FW */
- if (mvm->scan_status == IWL_MVM_SCAN_SCHED) {
- mvm->scan_status = IWL_MVM_SCAN_NONE;
+ mvm->scan_status &= ~IWL_MVM_SCAN_STOPPING_REGULAR;
+ } else if (mvm->scan_status & IWL_MVM_SCAN_SCHED) {
+ WARN_ON_ONCE(mvm->scan_status & IWL_MVM_SCAN_REGULAR);
+
+ IWL_DEBUG_SCAN(mvm, "Scheduled scan %s, EBS status %s (FW)\n",
+ aborted ? "aborted" : "completed",
+ ebs_successful ? "successful" : "failed");
+
+ mvm->scan_status &= ~IWL_MVM_SCAN_SCHED;
ieee80211_sched_scan_stopped(mvm->hw);
- } else if (mvm->scan_status == IWL_MVM_SCAN_OS) {
- mvm->scan_status = IWL_MVM_SCAN_NONE;
+ } else if (mvm->scan_status & IWL_MVM_SCAN_REGULAR) {
+ IWL_DEBUG_SCAN(mvm, "Regular scan %s, EBS status %s (FW)\n",
+ aborted ? "aborted" : "completed",
+ ebs_successful ? "successful" : "failed");
+
+ mvm->scan_status &= ~IWL_MVM_SCAN_REGULAR;
ieee80211_scan_completed(mvm->hw,
scan_notif->status == IWL_SCAN_OFFLOAD_ABORTED);
iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
}
- if (scan_notif->ebs_status)
- mvm->last_ebs_successful = false;
+ mvm->last_ebs_successful = ebs_successful;
return 0;
}
@@ -544,7 +566,7 @@ int iwl_mvm_scan_offload_start(struct iwl_mvm *mvm,
return ret;
ret = iwl_mvm_sched_scan_umac(mvm, vif, req, ies);
} else {
- mvm->scan_status = IWL_MVM_SCAN_SCHED;
+ mvm->scan_status |= IWL_MVM_SCAN_SCHED;
ret = iwl_mvm_config_sched_scan_profiles(mvm, req);
if (ret)
return ret;
@@ -565,7 +587,7 @@ static int iwl_mvm_send_scan_offload_abort(struct iwl_mvm *mvm)
/* Exit instantly with error when device is not ready
* to receive scan abort command or it does not perform
* scheduled scan currently */
- if (mvm->scan_status == IWL_MVM_SCAN_NONE)
+ if (!mvm->scan_status)
return -EIO;
ret = iwl_mvm_send_cmd_status(mvm, &cmd, &status);
@@ -592,7 +614,7 @@ int iwl_mvm_scan_offload_stop(struct iwl_mvm *mvm, bool notify)
int ret;
struct iwl_notification_wait wait_scan_done;
static const u8 scan_done_notif[] = { SCAN_OFFLOAD_COMPLETE, };
- bool sched = mvm->scan_status == IWL_MVM_SCAN_SCHED;
+ bool sched = !!(mvm->scan_status & IWL_MVM_SCAN_SCHED);
lockdep_assert_held(&mvm->mutex);
@@ -600,7 +622,11 @@ int iwl_mvm_scan_offload_stop(struct iwl_mvm *mvm, bool notify)
return iwl_umac_scan_stop(mvm, IWL_UMAC_SCAN_UID_SCHED_SCAN,
notify);
- if (mvm->scan_status == IWL_MVM_SCAN_NONE)
+ /* FIXME: For now we only check if no scan is set here, since
+ * we only support LMAC in this flow and it doesn't support
+ * multiple scans.
+ */
+ if (!mvm->scan_status)
return 0;
if (iwl_mvm_is_radio_killed(mvm)) {
@@ -622,25 +648,28 @@ int iwl_mvm_scan_offload_stop(struct iwl_mvm *mvm, bool notify)
}
IWL_DEBUG_SCAN(mvm, "Successfully sent stop %sscan\n",
- sched ? "offloaded " : "");
+ sched ? "scheduled " : "");
ret = iwl_wait_notification(&mvm->notif_wait, &wait_scan_done, 1 * HZ);
out:
- /*
- * Clear the scan status so the next scan requests will succeed. This
- * also ensures the Rx handler doesn't do anything, as the scan was
- * stopped from above. Since the rx handler won't do anything now,
- * we have to release the scan reference here.
+ /* Clear the scan status so the next scan requests will
+ * succeed and mark the scan as stopping, so that the Rx
+ * handler doesn't do anything, as the scan was stopped from
+ * above. Since the rx handler won't do anything now, we have
+ * to release the scan reference here.
*/
- if (mvm->scan_status == IWL_MVM_SCAN_OS)
+ if (mvm->scan_status == IWL_MVM_SCAN_REGULAR)
iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
- mvm->scan_status = IWL_MVM_SCAN_NONE;
-
- if (notify) {
- if (sched)
+ if (sched) {
+ mvm->scan_status &= ~IWL_MVM_SCAN_SCHED;
+ mvm->scan_status |= IWL_MVM_SCAN_STOPPING_SCHED;
+ if (notify)
ieee80211_sched_scan_stopped(mvm->hw);
- else
+ } else {
+ mvm->scan_status &= ~IWL_MVM_SCAN_REGULAR;
+ mvm->scan_status |= IWL_MVM_SCAN_STOPPING_REGULAR;
+ if (notify)
ieee80211_scan_completed(mvm->hw, true);
}
@@ -829,7 +858,7 @@ int iwl_mvm_unified_scan_lmac(struct iwl_mvm *mvm,
req->req.n_channels > mvm->fw->ucode_capa.n_scan_channels)
return -ENOBUFS;
- mvm->scan_status = IWL_MVM_SCAN_OS;
+ mvm->scan_status |= IWL_MVM_SCAN_REGULAR;
iwl_mvm_scan_calc_params(mvm, vif, req->req.n_ssids, req->req.flags,
¶ms);
@@ -906,7 +935,7 @@ int iwl_mvm_unified_scan_lmac(struct iwl_mvm *mvm,
* should try to send the command again with different params.
*/
IWL_ERR(mvm, "Scan failed! ret %d\n", ret);
- mvm->scan_status = IWL_MVM_SCAN_NONE;
+ mvm->scan_status &= ~IWL_MVM_SCAN_REGULAR;
ret = -EIO;
}
return ret;
@@ -1026,7 +1055,7 @@ int iwl_mvm_unified_sched_scan_lmac(struct iwl_mvm *mvm,
* should try to send the command again with different params.
*/
IWL_ERR(mvm, "Sched scan failed! ret %d\n", ret);
- mvm->scan_status = IWL_MVM_SCAN_NONE;
+ mvm->scan_status &= ~IWL_MVM_SCAN_SCHED;
ret = -EIO;
}
return ret;
@@ -1039,13 +1068,13 @@ int iwl_mvm_cancel_scan(struct iwl_mvm *mvm)
return iwl_umac_scan_stop(mvm, IWL_UMAC_SCAN_UID_REG_SCAN,
true);
- if (mvm->scan_status == IWL_MVM_SCAN_NONE)
+ if (!(mvm->scan_status & IWL_MVM_SCAN_REGULAR))
return 0;
if (iwl_mvm_is_radio_killed(mvm)) {
ieee80211_scan_completed(mvm->hw, true);
iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
- mvm->scan_status = IWL_MVM_SCAN_NONE;
+ mvm->scan_status &= ~IWL_MVM_SCAN_REGULAR;
return 0;
}
@@ -1682,21 +1711,14 @@ void iwl_mvm_report_scan_aborted(struct iwl_mvm *mvm)
mvm->scan_uid[i] = 0;
}
} else {
- switch (mvm->scan_status) {
- case IWL_MVM_SCAN_NONE:
- break;
- case IWL_MVM_SCAN_OS:
+ if (mvm->scan_status & IWL_MVM_SCAN_REGULAR)
ieee80211_scan_completed(mvm->hw, true);
- break;
- case IWL_MVM_SCAN_SCHED:
- /*
- * Sched scan will be restarted by mac80211 in
- * restart_hw, so do not report if FW is about to be
- * restarted.
- */
- if (!mvm->restart_fw)
- ieee80211_sched_scan_stopped(mvm->hw);
- break;
- }
+
+ /* Sched scan will be restarted by mac80211 in
+ * restart_hw, so do not report if FW is about to be
+ * restarted.
+ */
+ if ((mvm->scan_status & IWL_MVM_SCAN_SCHED) && !mvm->restart_fw)
+ ieee80211_sched_scan_stopped(mvm->hw);
}
}