aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDavid Spinadel <david.spinadel@intel.com>2013-12-08 14:48:57 -0500
committerJohannes Berg <johannes.berg@intel.com>2013-12-16 07:47:26 -0500
commitd43c6b6e6f2fcaebf198c499716e5e24d878fdd2 (patch)
treeef8cc16a17e5b0101d0fc138eb28e55ebd3363c9 /net
parent0ae07968f6de608ab02d98731747299a0cf274ea (diff)
mac80211: reschedule sched scan after HW restart
Keep the sched scan req when starting sched scan, and reschedule it in case of HW restart during sched scan. The upper layer don't have to know about the restart. Signed-off-by: David Spinadel <david.spinadel@intel.com> Reviewed-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/ieee80211_i.h4
-rw-r--r--net/mac80211/main.c8
-rw-r--r--net/mac80211/scan.c53
-rw-r--r--net/mac80211/util.c23
4 files changed, 68 insertions, 20 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 287462875857..ee13c6593b9a 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1113,6 +1113,7 @@ struct ieee80211_local {
1113 1113
1114 struct work_struct sched_scan_stopped_work; 1114 struct work_struct sched_scan_stopped_work;
1115 struct ieee80211_sub_if_data __rcu *sched_scan_sdata; 1115 struct ieee80211_sub_if_data __rcu *sched_scan_sdata;
1116 struct cfg80211_sched_scan_request *sched_scan_req;
1116 1117
1117 unsigned long leave_oper_channel_time; 1118 unsigned long leave_oper_channel_time;
1118 enum mac80211_scan_state next_scan_state; 1119 enum mac80211_scan_state next_scan_state;
@@ -1421,6 +1422,9 @@ void ieee80211_rx_bss_put(struct ieee80211_local *local,
1421 struct ieee80211_bss *bss); 1422 struct ieee80211_bss *bss);
1422 1423
1423/* scheduled scan handling */ 1424/* scheduled scan handling */
1425int
1426__ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
1427 struct cfg80211_sched_scan_request *req);
1424int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, 1428int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
1425 struct cfg80211_sched_scan_request *req); 1429 struct cfg80211_sched_scan_request *req);
1426int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata); 1430int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata);
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index fa34cd2344b9..2bd5b552b2f6 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -250,12 +250,8 @@ static void ieee80211_restart_work(struct work_struct *work)
250 /* wait for scan work complete */ 250 /* wait for scan work complete */
251 flush_workqueue(local->workqueue); 251 flush_workqueue(local->workqueue);
252 252
253 mutex_lock(&local->mtx); 253 WARN(test_bit(SCAN_HW_SCANNING, &local->scanning),
254 WARN(test_bit(SCAN_HW_SCANNING, &local->scanning) || 254 "%s called with hardware scan in progress\n", __func__);
255 rcu_dereference_protected(local->sched_scan_sdata,
256 lockdep_is_held(&local->mtx)),
257 "%s called with hardware scan in progress\n", __func__);
258 mutex_unlock(&local->mtx);
259 255
260 rtnl_lock(); 256 rtnl_lock();
261 ieee80211_scan_cancel(local); 257 ieee80211_scan_cancel(local);
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index ee6c8515f97b..88c81616f8f7 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -971,8 +971,8 @@ out:
971 mutex_unlock(&local->mtx); 971 mutex_unlock(&local->mtx);
972} 972}
973 973
974int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, 974int __ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
975 struct cfg80211_sched_scan_request *req) 975 struct cfg80211_sched_scan_request *req)
976{ 976{
977 struct ieee80211_local *local = sdata->local; 977 struct ieee80211_local *local = sdata->local;
978 struct ieee80211_sched_scan_ies sched_scan_ies = {}; 978 struct ieee80211_sched_scan_ies sched_scan_ies = {};
@@ -982,17 +982,10 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
982 iebufsz = 2 + IEEE80211_MAX_SSID_LEN + 982 iebufsz = 2 + IEEE80211_MAX_SSID_LEN +
983 local->scan_ies_len + req->ie_len; 983 local->scan_ies_len + req->ie_len;
984 984
985 mutex_lock(&local->mtx); 985 lockdep_assert_held(&local->mtx);
986 986
987 if (rcu_access_pointer(local->sched_scan_sdata)) { 987 if (!local->ops->sched_scan_start)
988 ret = -EBUSY; 988 return -ENOTSUPP;
989 goto out;
990 }
991
992 if (!local->ops->sched_scan_start) {
993 ret = -ENOTSUPP;
994 goto out;
995 }
996 989
997 for (i = 0; i < IEEE80211_NUM_BANDS; i++) { 990 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
998 if (!local->hw.wiphy->bands[i]) 991 if (!local->hw.wiphy->bands[i])
@@ -1013,13 +1006,39 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
1013 } 1006 }
1014 1007
1015 ret = drv_sched_scan_start(local, sdata, req, &sched_scan_ies); 1008 ret = drv_sched_scan_start(local, sdata, req, &sched_scan_ies);
1016 if (ret == 0) 1009 if (ret == 0) {
1017 rcu_assign_pointer(local->sched_scan_sdata, sdata); 1010 rcu_assign_pointer(local->sched_scan_sdata, sdata);
1011 local->sched_scan_req = req;
1012 }
1018 1013
1019out_free: 1014out_free:
1020 while (i > 0) 1015 while (i > 0)
1021 kfree(sched_scan_ies.ie[--i]); 1016 kfree(sched_scan_ies.ie[--i]);
1022out: 1017
1018 if (ret) {
1019 /* Clean in case of failure after HW restart or upon resume. */
1020 rcu_assign_pointer(local->sched_scan_sdata, NULL);
1021 local->sched_scan_req = NULL;
1022 }
1023
1024 return ret;
1025}
1026
1027int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
1028 struct cfg80211_sched_scan_request *req)
1029{
1030 struct ieee80211_local *local = sdata->local;
1031 int ret;
1032
1033 mutex_lock(&local->mtx);
1034
1035 if (rcu_access_pointer(local->sched_scan_sdata)) {
1036 mutex_unlock(&local->mtx);
1037 return -EBUSY;
1038 }
1039
1040 ret = __ieee80211_request_sched_scan_start(sdata, req);
1041
1023 mutex_unlock(&local->mtx); 1042 mutex_unlock(&local->mtx);
1024 return ret; 1043 return ret;
1025} 1044}
@@ -1036,6 +1055,9 @@ int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata)
1036 goto out; 1055 goto out;
1037 } 1056 }
1038 1057
1058 /* We don't want to restart sched scan anymore. */
1059 local->sched_scan_req = NULL;
1060
1039 if (rcu_access_pointer(local->sched_scan_sdata)) 1061 if (rcu_access_pointer(local->sched_scan_sdata))
1040 drv_sched_scan_stop(local, sdata); 1062 drv_sched_scan_stop(local, sdata);
1041 1063
@@ -1070,6 +1092,9 @@ void ieee80211_sched_scan_stopped_work(struct work_struct *work)
1070 1092
1071 rcu_assign_pointer(local->sched_scan_sdata, NULL); 1093 rcu_assign_pointer(local->sched_scan_sdata, NULL);
1072 1094
1095 /* If sched scan was aborted by the driver. */
1096 local->sched_scan_req = NULL;
1097
1073 mutex_unlock(&local->mtx); 1098 mutex_unlock(&local->mtx);
1074 1099
1075 cfg80211_sched_scan_stopped(local->hw.wiphy); 1100 cfg80211_sched_scan_stopped(local->hw.wiphy);
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index adf81f023681..591b46b72462 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1462,6 +1462,8 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1462 struct sta_info *sta; 1462 struct sta_info *sta;
1463 int res, i; 1463 int res, i;
1464 bool reconfig_due_to_wowlan = false; 1464 bool reconfig_due_to_wowlan = false;
1465 struct ieee80211_sub_if_data *sched_scan_sdata;
1466 bool sched_scan_stopped = false;
1465 1467
1466#ifdef CONFIG_PM 1468#ifdef CONFIG_PM
1467 if (local->suspended) 1469 if (local->suspended)
@@ -1765,6 +1767,27 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1765#else 1767#else
1766 WARN_ON(1); 1768 WARN_ON(1);
1767#endif 1769#endif
1770
1771 /*
1772 * Reconfigure sched scan if it was interrupted by FW restart or
1773 * suspend.
1774 */
1775 mutex_lock(&local->mtx);
1776 sched_scan_sdata = rcu_dereference_protected(local->sched_scan_sdata,
1777 lockdep_is_held(&local->mtx));
1778 if (sched_scan_sdata && local->sched_scan_req)
1779 /*
1780 * Sched scan stopped, but we don't want to report it. Instead,
1781 * we're trying to reschedule.
1782 */
1783 if (__ieee80211_request_sched_scan_start(sched_scan_sdata,
1784 local->sched_scan_req))
1785 sched_scan_stopped = true;
1786 mutex_unlock(&local->mtx);
1787
1788 if (sched_scan_stopped)
1789 cfg80211_sched_scan_stopped(local->hw.wiphy);
1790
1768 return 0; 1791 return 0;
1769} 1792}
1770 1793