aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEliad Peller <eliad@wizery.com>2015-10-25 04:59:33 -0400
committerJohannes Berg <johannes.berg@intel.com>2015-11-03 04:42:05 -0500
commit0d440ea294a00b60ced66c0bc5cb5caa42fd4fbd (patch)
tree0f8e7a81bc3843836a4557cb8adbe5d9a34ff34f
parent968a76cef3d1bb9a3b4d135cd788056e742859f3 (diff)
mac80211: don't reconfigure sched scan in case of wowlan
Scheduled scan has to be reconfigured only if wowlan wasn't configured, since otherwise it should continue to run (with the 'any' trigger) or be aborted. The current code will end up asking the driver to start a new scheduled scan without stopping the previous one, and leaking some memory (from the previous request.) Fix this by doing the abort/restart under the proper conditions. Signed-off-by: Eliad Peller <eliadx.peller@intel.com> Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--net/mac80211/cfg.c6
-rw-r--r--net/mac80211/ieee80211_i.h2
-rw-r--r--net/mac80211/pm.c11
-rw-r--r--net/mac80211/scan.c12
-rw-r--r--net/mac80211/util.c49
5 files changed, 45 insertions, 35 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 713cdbf6fb3c..c2bd1b6a6922 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2010,12 +2010,12 @@ ieee80211_sched_scan_start(struct wiphy *wiphy,
2010static int 2010static int
2011ieee80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev) 2011ieee80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev)
2012{ 2012{
2013 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 2013 struct ieee80211_local *local = wiphy_priv(wiphy);
2014 2014
2015 if (!sdata->local->ops->sched_scan_stop) 2015 if (!local->ops->sched_scan_stop)
2016 return -EOPNOTSUPP; 2016 return -EOPNOTSUPP;
2017 2017
2018 return ieee80211_request_sched_scan_stop(sdata); 2018 return ieee80211_request_sched_scan_stop(local);
2019} 2019}
2020 2020
2021static int ieee80211_auth(struct wiphy *wiphy, struct net_device *dev, 2021static int ieee80211_auth(struct wiphy *wiphy, struct net_device *dev,
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 62f2a97cd2a6..68680ad04cef 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1573,7 +1573,7 @@ __ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
1573 struct cfg80211_sched_scan_request *req); 1573 struct cfg80211_sched_scan_request *req);
1574int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, 1574int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
1575 struct cfg80211_sched_scan_request *req); 1575 struct cfg80211_sched_scan_request *req);
1576int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata); 1576int ieee80211_request_sched_scan_stop(struct ieee80211_local *local);
1577void ieee80211_sched_scan_end(struct ieee80211_local *local); 1577void ieee80211_sched_scan_end(struct ieee80211_local *local);
1578void ieee80211_sched_scan_stopped_work(struct work_struct *work); 1578void ieee80211_sched_scan_stopped_work(struct work_struct *work);
1579 1579
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
index ad88ad4e8eb1..00a43a70e1fc 100644
--- a/net/mac80211/pm.c
+++ b/net/mac80211/pm.c
@@ -6,6 +6,13 @@
6#include "driver-ops.h" 6#include "driver-ops.h"
7#include "led.h" 7#include "led.h"
8 8
9static void ieee80211_sched_scan_cancel(struct ieee80211_local *local)
10{
11 if (ieee80211_request_sched_scan_stop(local))
12 return;
13 cfg80211_sched_scan_stopped_rtnl(local->hw.wiphy);
14}
15
9int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) 16int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
10{ 17{
11 struct ieee80211_local *local = hw_to_local(hw); 18 struct ieee80211_local *local = hw_to_local(hw);
@@ -34,6 +41,10 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
34 mutex_unlock(&local->sta_mtx); 41 mutex_unlock(&local->sta_mtx);
35 } 42 }
36 43
44 /* keep sched_scan only in case of 'any' trigger */
45 if (!(wowlan && wowlan->any))
46 ieee80211_sched_scan_cancel(local);
47
37 ieee80211_stop_queues_by_reason(hw, 48 ieee80211_stop_queues_by_reason(hw,
38 IEEE80211_MAX_QUEUE_MAP, 49 IEEE80211_MAX_QUEUE_MAP,
39 IEEE80211_QUEUE_STOP_REASON_SUSPEND, 50 IEEE80211_QUEUE_STOP_REASON_SUSPEND,
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index b64fd2b2d95a..4aeca4b0c3cb 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -1140,10 +1140,10 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
1140 return ret; 1140 return ret;
1141} 1141}
1142 1142
1143int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata) 1143int ieee80211_request_sched_scan_stop(struct ieee80211_local *local)
1144{ 1144{
1145 struct ieee80211_local *local = sdata->local; 1145 struct ieee80211_sub_if_data *sched_scan_sdata;
1146 int ret = 0; 1146 int ret = -ENOENT;
1147 1147
1148 mutex_lock(&local->mtx); 1148 mutex_lock(&local->mtx);
1149 1149
@@ -1155,8 +1155,10 @@ int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata)
1155 /* We don't want to restart sched scan anymore. */ 1155 /* We don't want to restart sched scan anymore. */
1156 RCU_INIT_POINTER(local->sched_scan_req, NULL); 1156 RCU_INIT_POINTER(local->sched_scan_req, NULL);
1157 1157
1158 if (rcu_access_pointer(local->sched_scan_sdata)) { 1158 sched_scan_sdata = rcu_dereference_protected(local->sched_scan_sdata,
1159 ret = drv_sched_scan_stop(local, sdata); 1159 lockdep_is_held(&local->mtx));
1160 if (sched_scan_sdata) {
1161 ret = drv_sched_scan_stop(local, sched_scan_sdata);
1160 if (!ret) 1162 if (!ret)
1161 RCU_INIT_POINTER(local->sched_scan_sdata, NULL); 1163 RCU_INIT_POINTER(local->sched_scan_sdata, NULL);
1162 } 1164 }
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 551164dabbaf..d38daf0181e8 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -2008,6 +2008,29 @@ int ieee80211_reconfig(struct ieee80211_local *local)
2008 if (ieee80211_sdata_running(sdata)) 2008 if (ieee80211_sdata_running(sdata))
2009 ieee80211_enable_keys(sdata); 2009 ieee80211_enable_keys(sdata);
2010 2010
2011 /* Reconfigure sched scan if it was interrupted by FW restart */
2012 mutex_lock(&local->mtx);
2013 sched_scan_sdata = rcu_dereference_protected(local->sched_scan_sdata,
2014 lockdep_is_held(&local->mtx));
2015 sched_scan_req = rcu_dereference_protected(local->sched_scan_req,
2016 lockdep_is_held(&local->mtx));
2017 if (sched_scan_sdata && sched_scan_req)
2018 /*
2019 * Sched scan stopped, but we don't want to report it. Instead,
2020 * we're trying to reschedule. However, if more than one scan
2021 * plan was set, we cannot reschedule since we don't know which
2022 * scan plan was currently running (and some scan plans may have
2023 * already finished).
2024 */
2025 if (sched_scan_req->n_scan_plans > 1 ||
2026 __ieee80211_request_sched_scan_start(sched_scan_sdata,
2027 sched_scan_req))
2028 sched_scan_stopped = true;
2029 mutex_unlock(&local->mtx);
2030
2031 if (sched_scan_stopped)
2032 cfg80211_sched_scan_stopped_rtnl(local->hw.wiphy);
2033
2011 wake_up: 2034 wake_up:
2012 local->in_reconfig = false; 2035 local->in_reconfig = false;
2013 barrier(); 2036 barrier();
@@ -2043,32 +2066,6 @@ int ieee80211_reconfig(struct ieee80211_local *local)
2043 false); 2066 false);
2044 2067
2045 /* 2068 /*
2046 * Reconfigure sched scan if it was interrupted by FW restart or
2047 * suspend.
2048 */
2049 mutex_lock(&local->mtx);
2050 sched_scan_sdata = rcu_dereference_protected(local->sched_scan_sdata,
2051 lockdep_is_held(&local->mtx));
2052 sched_scan_req = rcu_dereference_protected(local->sched_scan_req,
2053 lockdep_is_held(&local->mtx));
2054 if (sched_scan_sdata && sched_scan_req)
2055 /*
2056 * Sched scan stopped, but we don't want to report it. Instead,
2057 * we're trying to reschedule. However, if more than one scan
2058 * plan was set, we cannot reschedule since we don't know which
2059 * scan plan was currently running (and some scan plans may have
2060 * already finished).
2061 */
2062 if (sched_scan_req->n_scan_plans > 1 ||
2063 __ieee80211_request_sched_scan_start(sched_scan_sdata,
2064 sched_scan_req))
2065 sched_scan_stopped = true;
2066 mutex_unlock(&local->mtx);
2067
2068 if (sched_scan_stopped)
2069 cfg80211_sched_scan_stopped_rtnl(local->hw.wiphy);
2070
2071 /*
2072 * If this is for hw restart things are still running. 2069 * If this is for hw restart things are still running.
2073 * We may want to change that later, however. 2070 * We may want to change that later, however.
2074 */ 2071 */