diff options
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/mac80211.c | 86 |
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 | ||
1721 | static 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; | ||
1753 | out: | ||
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 | } | ||
1721 | static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw, | 1762 | static 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); |
1759 | out: | 1794 | out: |
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; |
2190 | out: | 2208 | out: |
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 | ||