Skip to content

Commit

Permalink
mac80211: don't reconfigure sched scan in case of wowlan
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Emmanuel Grumbach <[email protected]>
Signed-off-by: Johannes Berg <[email protected]>
  • Loading branch information
elp authored and jmberg-intel committed Nov 3, 2015
1 parent 968a76c commit 0d440ea
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 35 deletions.
6 changes: 3 additions & 3 deletions net/mac80211/cfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -2010,12 +2010,12 @@ ieee80211_sched_scan_start(struct wiphy *wiphy,
static int
ieee80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_local *local = wiphy_priv(wiphy);

if (!sdata->local->ops->sched_scan_stop)
if (!local->ops->sched_scan_stop)
return -EOPNOTSUPP;

return ieee80211_request_sched_scan_stop(sdata);
return ieee80211_request_sched_scan_stop(local);
}

static int ieee80211_auth(struct wiphy *wiphy, struct net_device *dev,
Expand Down
2 changes: 1 addition & 1 deletion net/mac80211/ieee80211_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -1573,7 +1573,7 @@ __ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
struct cfg80211_sched_scan_request *req);
int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
struct cfg80211_sched_scan_request *req);
int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata);
int ieee80211_request_sched_scan_stop(struct ieee80211_local *local);
void ieee80211_sched_scan_end(struct ieee80211_local *local);
void ieee80211_sched_scan_stopped_work(struct work_struct *work);

Expand Down
11 changes: 11 additions & 0 deletions net/mac80211/pm.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@
#include "driver-ops.h"
#include "led.h"

static void ieee80211_sched_scan_cancel(struct ieee80211_local *local)
{
if (ieee80211_request_sched_scan_stop(local))
return;
cfg80211_sched_scan_stopped_rtnl(local->hw.wiphy);
}

int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
{
struct ieee80211_local *local = hw_to_local(hw);
Expand Down Expand Up @@ -34,6 +41,10 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
mutex_unlock(&local->sta_mtx);
}

/* keep sched_scan only in case of 'any' trigger */
if (!(wowlan && wowlan->any))
ieee80211_sched_scan_cancel(local);

ieee80211_stop_queues_by_reason(hw,
IEEE80211_MAX_QUEUE_MAP,
IEEE80211_QUEUE_STOP_REASON_SUSPEND,
Expand Down
12 changes: 7 additions & 5 deletions net/mac80211/scan.c
Original file line number Diff line number Diff line change
Expand Up @@ -1140,10 +1140,10 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
return ret;
}

int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata)
int ieee80211_request_sched_scan_stop(struct ieee80211_local *local)
{
struct ieee80211_local *local = sdata->local;
int ret = 0;
struct ieee80211_sub_if_data *sched_scan_sdata;
int ret = -ENOENT;

mutex_lock(&local->mtx);

Expand All @@ -1155,8 +1155,10 @@ int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata)
/* We don't want to restart sched scan anymore. */
RCU_INIT_POINTER(local->sched_scan_req, NULL);

if (rcu_access_pointer(local->sched_scan_sdata)) {
ret = drv_sched_scan_stop(local, sdata);
sched_scan_sdata = rcu_dereference_protected(local->sched_scan_sdata,
lockdep_is_held(&local->mtx));
if (sched_scan_sdata) {
ret = drv_sched_scan_stop(local, sched_scan_sdata);
if (!ret)
RCU_INIT_POINTER(local->sched_scan_sdata, NULL);
}
Expand Down
49 changes: 23 additions & 26 deletions net/mac80211/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -2008,6 +2008,29 @@ int ieee80211_reconfig(struct ieee80211_local *local)
if (ieee80211_sdata_running(sdata))
ieee80211_enable_keys(sdata);

/* Reconfigure sched scan if it was interrupted by FW restart */
mutex_lock(&local->mtx);
sched_scan_sdata = rcu_dereference_protected(local->sched_scan_sdata,
lockdep_is_held(&local->mtx));
sched_scan_req = rcu_dereference_protected(local->sched_scan_req,
lockdep_is_held(&local->mtx));
if (sched_scan_sdata && sched_scan_req)
/*
* Sched scan stopped, but we don't want to report it. Instead,
* we're trying to reschedule. However, if more than one scan
* plan was set, we cannot reschedule since we don't know which
* scan plan was currently running (and some scan plans may have
* already finished).
*/
if (sched_scan_req->n_scan_plans > 1 ||
__ieee80211_request_sched_scan_start(sched_scan_sdata,
sched_scan_req))
sched_scan_stopped = true;
mutex_unlock(&local->mtx);

if (sched_scan_stopped)
cfg80211_sched_scan_stopped_rtnl(local->hw.wiphy);

wake_up:
local->in_reconfig = false;
barrier();
Expand Down Expand Up @@ -2042,32 +2065,6 @@ int ieee80211_reconfig(struct ieee80211_local *local)
IEEE80211_QUEUE_STOP_REASON_SUSPEND,
false);

/*
* Reconfigure sched scan if it was interrupted by FW restart or
* suspend.
*/
mutex_lock(&local->mtx);
sched_scan_sdata = rcu_dereference_protected(local->sched_scan_sdata,
lockdep_is_held(&local->mtx));
sched_scan_req = rcu_dereference_protected(local->sched_scan_req,
lockdep_is_held(&local->mtx));
if (sched_scan_sdata && sched_scan_req)
/*
* Sched scan stopped, but we don't want to report it. Instead,
* we're trying to reschedule. However, if more than one scan
* plan was set, we cannot reschedule since we don't know which
* scan plan was currently running (and some scan plans may have
* already finished).
*/
if (sched_scan_req->n_scan_plans > 1 ||
__ieee80211_request_sched_scan_start(sched_scan_sdata,
sched_scan_req))
sched_scan_stopped = true;
mutex_unlock(&local->mtx);

if (sched_scan_stopped)
cfg80211_sched_scan_stopped_rtnl(local->hw.wiphy);

/*
* If this is for hw restart things are still running.
* We may want to change that later, however.
Expand Down

0 comments on commit 0d440ea

Please sign in to comment.