aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorEliad Peller <eliadx.peller@intel.com>2014-06-22 11:15:59 -0400
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>2014-07-22 12:21:08 -0400
commit4660dfbbe04cc5777cd7a68916e2c8c5b3b07674 (patch)
tree75dc3a30ce3a50ff37c5e4a428fbd17cfe3daa39 /drivers/net/wireless
parent45bbb2ca1e27c79bd3cbdcec040e7daceceeabbb (diff)
iwlwifi: mvm: wait for handlers when stopping scans
The recent unified scan api change introduced issues when stopping ongoing scans, since both regular and sched scan now use same stopped notification. When issuing a new scan right after a running one, we get the "old" notification and handle it wrongly as notification for the current scan. Fix it by introducing a new function that make sure we consume the pending notifications before issuing a new scan. Signed-off-by: Eliad Peller <eliad@wizery.com> Reviewed-by: ArikX Nemtsov <arik@wizery.com> Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mac80211.c86
1 files changed, 51 insertions, 35 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
index 5219b3a5689d..46ff7cd52d92 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
@@ -1718,6 +1718,47 @@ static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw,
1718 iwl_mvm_unref(mvm, IWL_MVM_REF_BSS_CHANGED); 1718 iwl_mvm_unref(mvm, IWL_MVM_REF_BSS_CHANGED);
1719} 1719}
1720 1720
1721static int iwl_mvm_cancel_scan_wait_notif(struct iwl_mvm *mvm,
1722 enum iwl_scan_status scan_type)
1723{
1724 int ret;
1725 bool wait_for_handlers = false;
1726
1727 mutex_lock(&mvm->mutex);
1728
1729 if (mvm->scan_status != scan_type) {
1730 ret = 0;
1731 /* make sure there are no pending notifications */
1732 wait_for_handlers = true;
1733 goto out;
1734 }
1735
1736 switch (scan_type) {
1737 case IWL_MVM_SCAN_SCHED:
1738 ret = iwl_mvm_scan_offload_stop(mvm, true);
1739 break;
1740 case IWL_MVM_SCAN_OS:
1741 ret = iwl_mvm_cancel_scan(mvm);
1742 break;
1743 case IWL_MVM_SCAN_NONE:
1744 default:
1745 WARN_ON_ONCE(1);
1746 ret = -EINVAL;
1747 break;
1748 }
1749 if (ret)
1750 goto out;
1751
1752 wait_for_handlers = true;
1753out:
1754 mutex_unlock(&mvm->mutex);
1755
1756 /* make sure we consume the completion notification */
1757 if (wait_for_handlers)
1758 iwl_mvm_wait_for_async_handlers(mvm);
1759
1760 return ret;
1761}
1721static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw, 1762static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw,
1722 struct ieee80211_vif *vif, 1763 struct ieee80211_vif *vif,
1723 struct ieee80211_scan_request *hw_req) 1764 struct ieee80211_scan_request *hw_req)
@@ -1730,19 +1771,13 @@ static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw,
1730 req->n_channels > mvm->fw->ucode_capa.n_scan_channels) 1771 req->n_channels > mvm->fw->ucode_capa.n_scan_channels)
1731 return -EINVAL; 1772 return -EINVAL;
1732 1773
1774 ret = iwl_mvm_cancel_scan_wait_notif(mvm, IWL_MVM_SCAN_SCHED);
1775 if (ret)
1776 return ret;
1777
1733 mutex_lock(&mvm->mutex); 1778 mutex_lock(&mvm->mutex);
1734 1779
1735 switch (mvm->scan_status) { 1780 if (mvm->scan_status != IWL_MVM_SCAN_NONE) {
1736 case IWL_MVM_SCAN_SCHED:
1737 ret = iwl_mvm_scan_offload_stop(mvm, true);
1738 if (ret) {
1739 ret = -EBUSY;
1740 goto out;
1741 }
1742 break;
1743 case IWL_MVM_SCAN_NONE:
1744 break;
1745 default:
1746 ret = -EBUSY; 1781 ret = -EBUSY;
1747 goto out; 1782 goto out;
1748 } 1783 }
@@ -1758,8 +1793,6 @@ static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw,
1758 iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); 1793 iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
1759out: 1794out:
1760 mutex_unlock(&mvm->mutex); 1795 mutex_unlock(&mvm->mutex);
1761 /* make sure to flush the Rx handler before the next scan arrives */
1762 iwl_mvm_wait_for_async_handlers(mvm);
1763 return ret; 1796 return ret;
1764} 1797}
1765 1798
@@ -2135,6 +2168,10 @@ static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw,
2135 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); 2168 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
2136 int ret; 2169 int ret;
2137 2170
2171 ret = iwl_mvm_cancel_scan_wait_notif(mvm, IWL_MVM_SCAN_OS);
2172 if (ret)
2173 return ret;
2174
2138 mutex_lock(&mvm->mutex); 2175 mutex_lock(&mvm->mutex);
2139 2176
2140 if (!iwl_mvm_is_idle(mvm)) { 2177 if (!iwl_mvm_is_idle(mvm)) {
@@ -2142,26 +2179,7 @@ static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw,
2142 goto out; 2179 goto out;
2143 } 2180 }
2144 2181
2145 switch (mvm->scan_status) { 2182 if (mvm->scan_status != IWL_MVM_SCAN_NONE) {
2146 case IWL_MVM_SCAN_OS:
2147 IWL_DEBUG_SCAN(mvm, "Stopping previous scan for sched_scan\n");
2148 ret = iwl_mvm_cancel_scan(mvm);
2149 if (ret) {
2150 ret = -EBUSY;
2151 goto out;
2152 }
2153
2154 /*
2155 * iwl_mvm_rx_scan_complete() will be called soon but will
2156 * not reset the scan status as it won't be IWL_MVM_SCAN_OS
2157 * any more since we queue the next scan immediately (below).
2158 * We make sure it is called before the next scan starts by
2159 * flushing the async-handlers work.
2160 */
2161 break;
2162 case IWL_MVM_SCAN_NONE:
2163 break;
2164 default:
2165 ret = -EBUSY; 2183 ret = -EBUSY;
2166 goto out; 2184 goto out;
2167 } 2185 }
@@ -2189,8 +2207,6 @@ err:
2189 mvm->scan_status = IWL_MVM_SCAN_NONE; 2207 mvm->scan_status = IWL_MVM_SCAN_NONE;
2190out: 2208out:
2191 mutex_unlock(&mvm->mutex); 2209 mutex_unlock(&mvm->mutex);
2192 /* make sure to flush the Rx handler before the next scan arrives */
2193 iwl_mvm_wait_for_async_handlers(mvm);
2194 return ret; 2210 return ret;
2195} 2211}
2196 2212