diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index a46adb7a91b7..e1f1b41f7b13 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1515,8 +1515,7 @@ struct cfg80211_ops { int (*sched_scan_start)(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_sched_scan_request *request); - int (*sched_scan_stop)(struct wiphy *wiphy, struct net_device *dev, - bool driver_initiated); + int (*sched_scan_stop)(struct wiphy *wiphy, struct net_device *dev); }; /* diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 303f33fcb844..2d1c1a5f3c51 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1372,15 +1372,14 @@ ieee80211_sched_scan_start(struct wiphy *wiphy, } static int -ieee80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev, - bool driver_initiated) +ieee80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev) { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); if (!sdata->local->ops->sched_scan_stop) return -EOPNOTSUPP; - return ieee80211_request_sched_scan_stop(sdata, driver_initiated); + return ieee80211_request_sched_scan_stop(sdata); } static 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 6f55a789c099..82f90ff8bb18 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -849,6 +849,7 @@ struct ieee80211_local { bool sched_scanning; struct ieee80211_sched_scan_ies sched_scan_ies; + struct work_struct sched_scan_stopped_work; unsigned long leave_oper_channel_time; enum mac80211_scan_state next_scan_state; @@ -1160,8 +1161,8 @@ void ieee80211_rx_bss_put(struct ieee80211_local *local, /* scheduled scan handling */ 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, - bool driver_initiated); +int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata); +void ieee80211_sched_scan_stopped_work(struct work_struct *work); /* off-channel helpers */ bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local); diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 30e6a682a047..7f89011fa22d 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -652,6 +652,9 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, setup_timer(&local->dynamic_ps_timer, ieee80211_dynamic_ps_timer, (unsigned long) local); + INIT_WORK(&local->sched_scan_stopped_work, + ieee80211_sched_scan_stopped_work); + sta_info_init(local); for (i = 0; i < IEEE80211_MAX_QUEUES; i++) { diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index ea44a8e941ec..d20046b5d8f4 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -902,8 +902,7 @@ out: return ret; } -int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata, - bool driver_initiated) +int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata) { struct ieee80211_local *local = sdata->local; int ret = 0, i; @@ -919,11 +918,9 @@ int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata, for (i = 0; i < IEEE80211_NUM_BANDS; i++) kfree(local->sched_scan_ies.ie[i]); - if (!driver_initiated) - drv_sched_scan_stop(local, sdata); + drv_sched_scan_stop(local, sdata); local->sched_scanning = false; } - out: mutex_unlock(&sdata->local->mtx); @@ -940,12 +937,36 @@ void ieee80211_sched_scan_results(struct ieee80211_hw *hw) } EXPORT_SYMBOL(ieee80211_sched_scan_results); +void ieee80211_sched_scan_stopped_work(struct work_struct *work) +{ + struct ieee80211_local *local = + container_of(work, struct ieee80211_local, + sched_scan_stopped_work); + int i; + + mutex_lock(&local->mtx); + + if (!local->sched_scanning) { + mutex_unlock(&local->mtx); + return; + } + + for (i = 0; i < IEEE80211_NUM_BANDS; i++) + kfree(local->sched_scan_ies.ie[i]); + + local->sched_scanning = false; + + mutex_unlock(&local->mtx); + + cfg80211_sched_scan_stopped(local->hw.wiphy); +} + void ieee80211_sched_scan_stopped(struct ieee80211_hw *hw) { struct ieee80211_local *local = hw_to_local(hw); trace_api_sched_scan_stopped(local); - cfg80211_sched_scan_stopped(hw->wiphy); + ieee80211_queue_work(&local->hw, &local->sched_scan_stopped_work); } EXPORT_SYMBOL(ieee80211_sched_scan_stopped); diff --git a/net/wireless/core.c b/net/wireless/core.c index e2ab65d7c86d..18b002f16860 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -371,7 +371,6 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv) INIT_LIST_HEAD(&rdev->bss_list); INIT_WORK(&rdev->scan_done_wk, __cfg80211_scan_done); INIT_WORK(&rdev->sched_scan_results_wk, __cfg80211_sched_scan_results); - INIT_WORK(&rdev->sched_scan_stopped_wk, __cfg80211_sched_scan_stopped); #ifdef CONFIG_CFG80211_WEXT rdev->wiphy.wext = &cfg80211_wext_handler; #endif diff --git a/net/wireless/core.h b/net/wireless/core.h index fd9135f9b5be..d4b8f4c0bbbb 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -64,7 +64,6 @@ struct cfg80211_registered_device { unsigned long suspend_at; struct work_struct scan_done_wk; struct work_struct sched_scan_results_wk; - struct work_struct sched_scan_stopped_wk; #ifdef CONFIG_NL80211_TESTMODE struct genl_info *testmode_info; @@ -417,7 +416,6 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak); void __cfg80211_sched_scan_results(struct work_struct *wk); int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev, bool driver_initiated); -void __cfg80211_sched_scan_stopped(struct work_struct *wk); void cfg80211_upload_connect_keys(struct wireless_dev *wdev); int cfg80211_change_iface(struct cfg80211_registered_device *rdev, struct net_device *dev, enum nl80211_iftype ntype, diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 65dfae3b9d41..73a441d237b5 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -119,22 +119,14 @@ void cfg80211_sched_scan_results(struct wiphy *wiphy) } EXPORT_SYMBOL(cfg80211_sched_scan_results); -void __cfg80211_sched_scan_stopped(struct work_struct *wk) +void cfg80211_sched_scan_stopped(struct wiphy *wiphy) { - struct cfg80211_registered_device *rdev; - - rdev = container_of(wk, struct cfg80211_registered_device, - sched_scan_stopped_wk); + struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); cfg80211_lock_rdev(rdev); __cfg80211_stop_sched_scan(rdev, true); cfg80211_unlock_rdev(rdev); } - -void cfg80211_sched_scan_stopped(struct wiphy *wiphy) -{ - queue_work(cfg80211_wq, &wiphy_to_dev(wiphy)->sched_scan_stopped_wk); -} EXPORT_SYMBOL(cfg80211_sched_scan_stopped); int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev, @@ -150,10 +142,11 @@ int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev, dev = rdev->sched_scan_req->dev; - err = rdev->ops->sched_scan_stop(&rdev->wiphy, dev, - driver_initiated); - if (err) - return err; + if (!driver_initiated) { + err = rdev->ops->sched_scan_stop(&rdev->wiphy, dev); + if (err) + return err; + } nl80211_send_sched_scan(rdev, dev, NL80211_CMD_SCHED_SCAN_STOPPED);