aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/mlme.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless/mlme.c')
-rw-r--r--net/wireless/mlme.c120
1 files changed, 120 insertions, 0 deletions
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 8e6920728c43..caddca35d686 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -987,3 +987,123 @@ void cfg80211_pmksa_candidate_notify(struct net_device *dev, int index,
987 nl80211_pmksa_candidate_notify(rdev, dev, index, bssid, preauth, gfp); 987 nl80211_pmksa_candidate_notify(rdev, dev, index, bssid, preauth, gfp);
988} 988}
989EXPORT_SYMBOL(cfg80211_pmksa_candidate_notify); 989EXPORT_SYMBOL(cfg80211_pmksa_candidate_notify);
990
991void cfg80211_dfs_channels_update_work(struct work_struct *work)
992{
993 struct delayed_work *delayed_work;
994 struct cfg80211_registered_device *rdev;
995 struct cfg80211_chan_def chandef;
996 struct ieee80211_supported_band *sband;
997 struct ieee80211_channel *c;
998 struct wiphy *wiphy;
999 bool check_again = false;
1000 unsigned long timeout, next_time = 0;
1001 int bandid, i;
1002
1003 delayed_work = container_of(work, struct delayed_work, work);
1004 rdev = container_of(delayed_work, struct cfg80211_registered_device,
1005 dfs_update_channels_wk);
1006 wiphy = &rdev->wiphy;
1007
1008 mutex_lock(&cfg80211_mutex);
1009 for (bandid = 0; bandid < IEEE80211_NUM_BANDS; bandid++) {
1010 sband = wiphy->bands[bandid];
1011 if (!sband)
1012 continue;
1013
1014 for (i = 0; i < sband->n_channels; i++) {
1015 c = &sband->channels[i];
1016
1017 if (c->dfs_state != NL80211_DFS_UNAVAILABLE)
1018 continue;
1019
1020 timeout = c->dfs_state_entered +
1021 IEEE80211_DFS_MIN_NOP_TIME_MS;
1022
1023 if (time_after_eq(jiffies, timeout)) {
1024 c->dfs_state = NL80211_DFS_USABLE;
1025 cfg80211_chandef_create(&chandef, c,
1026 NL80211_CHAN_NO_HT);
1027
1028 nl80211_radar_notify(rdev, &chandef,
1029 NL80211_RADAR_NOP_FINISHED,
1030 NULL, GFP_ATOMIC);
1031 continue;
1032 }
1033
1034 if (!check_again)
1035 next_time = timeout - jiffies;
1036 else
1037 next_time = min(next_time, timeout - jiffies);
1038 check_again = true;
1039 }
1040 }
1041 mutex_unlock(&cfg80211_mutex);
1042
1043 /* reschedule if there are other channels waiting to be cleared again */
1044 if (check_again)
1045 queue_delayed_work(cfg80211_wq, &rdev->dfs_update_channels_wk,
1046 next_time);
1047}
1048
1049
1050void cfg80211_radar_event(struct wiphy *wiphy,
1051 struct cfg80211_chan_def *chandef,
1052 gfp_t gfp)
1053{
1054 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
1055 unsigned long timeout;
1056
1057 trace_cfg80211_radar_event(wiphy, chandef);
1058
1059 /* only set the chandef supplied channel to unavailable, in
1060 * case the radar is detected on only one of multiple channels
1061 * spanned by the chandef.
1062 */
1063 cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_UNAVAILABLE);
1064
1065 timeout = msecs_to_jiffies(IEEE80211_DFS_MIN_NOP_TIME_MS);
1066 queue_delayed_work(cfg80211_wq, &rdev->dfs_update_channels_wk,
1067 timeout);
1068
1069 nl80211_radar_notify(rdev, chandef, NL80211_RADAR_DETECTED, NULL, gfp);
1070}
1071EXPORT_SYMBOL(cfg80211_radar_event);
1072
1073void cfg80211_cac_event(struct net_device *netdev,
1074 enum nl80211_radar_event event, gfp_t gfp)
1075{
1076 struct wireless_dev *wdev = netdev->ieee80211_ptr;
1077 struct wiphy *wiphy = wdev->wiphy;
1078 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
1079 struct cfg80211_chan_def chandef;
1080 unsigned long timeout;
1081
1082 trace_cfg80211_cac_event(netdev, event);
1083
1084 if (WARN_ON(!wdev->cac_started))
1085 return;
1086
1087 if (WARN_ON(!wdev->channel))
1088 return;
1089
1090 cfg80211_chandef_create(&chandef, wdev->channel, NL80211_CHAN_NO_HT);
1091
1092 switch (event) {
1093 case NL80211_RADAR_CAC_FINISHED:
1094 timeout = wdev->cac_start_time +
1095 msecs_to_jiffies(IEEE80211_DFS_MIN_CAC_TIME_MS);
1096 WARN_ON(!time_after_eq(jiffies, timeout));
1097 cfg80211_set_dfs_state(wiphy, &chandef, NL80211_DFS_AVAILABLE);
1098 break;
1099 case NL80211_RADAR_CAC_ABORTED:
1100 break;
1101 default:
1102 WARN_ON(1);
1103 return;
1104 }
1105 wdev->cac_started = false;
1106
1107 nl80211_radar_notify(rdev, &chandef, event, netdev, gfp);
1108}
1109EXPORT_SYMBOL(cfg80211_cac_event);