]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - net/wireless/mlme.c
cfg80211: Make pre-CAC results valid only for ETSI domain
[mirror_ubuntu-bionic-kernel.git] / net / wireless / mlme.c
index 22b3d999006559d7572287c2b8e6f4fad286766d..cd29366a520682b695b5189943a5fdd331dceda5 100644 (file)
@@ -745,6 +745,12 @@ bool cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, int sig_mbm,
 }
 EXPORT_SYMBOL(cfg80211_rx_mgmt);
 
+void cfg80211_sched_dfs_chan_update(struct cfg80211_registered_device *rdev)
+{
+       cancel_delayed_work(&rdev->dfs_update_channels_wk);
+       queue_delayed_work(cfg80211_wq, &rdev->dfs_update_channels_wk, 0);
+}
+
 void cfg80211_dfs_channels_update_work(struct work_struct *work)
 {
        struct delayed_work *delayed_work = to_delayed_work(work);
@@ -755,6 +761,8 @@ void cfg80211_dfs_channels_update_work(struct work_struct *work)
        struct wiphy *wiphy;
        bool check_again = false;
        unsigned long timeout, next_time = 0;
+       unsigned long time_dfs_update;
+       enum nl80211_radar_event radar_event;
        int bandid, i;
 
        rdev = container_of(delayed_work, struct cfg80211_registered_device,
@@ -770,11 +778,27 @@ void cfg80211_dfs_channels_update_work(struct work_struct *work)
                for (i = 0; i < sband->n_channels; i++) {
                        c = &sband->channels[i];
 
-                       if (c->dfs_state != NL80211_DFS_UNAVAILABLE)
+                       if (!(c->flags & IEEE80211_CHAN_RADAR))
+                               continue;
+
+                       if (c->dfs_state != NL80211_DFS_UNAVAILABLE &&
+                           c->dfs_state != NL80211_DFS_AVAILABLE)
                                continue;
 
-                       timeout = c->dfs_state_entered + msecs_to_jiffies(
-                                       IEEE80211_DFS_MIN_NOP_TIME_MS);
+                       if (c->dfs_state == NL80211_DFS_UNAVAILABLE) {
+                               time_dfs_update = IEEE80211_DFS_MIN_NOP_TIME_MS;
+                               radar_event = NL80211_RADAR_NOP_FINISHED;
+                       } else {
+                               if (regulatory_pre_cac_allowed(wiphy) ||
+                                   cfg80211_any_wiphy_oper_chan(wiphy, c))
+                                       continue;
+
+                               time_dfs_update = REG_PRE_CAC_EXPIRY_GRACE_MS;
+                               radar_event = NL80211_RADAR_PRE_CAC_EXPIRED;
+                       }
+
+                       timeout = c->dfs_state_entered +
+                                 msecs_to_jiffies(time_dfs_update);
 
                        if (time_after_eq(jiffies, timeout)) {
                                c->dfs_state = NL80211_DFS_USABLE;
@@ -784,8 +808,8 @@ void cfg80211_dfs_channels_update_work(struct work_struct *work)
                                                        NL80211_CHAN_NO_HT);
 
                                nl80211_radar_notify(rdev, &chandef,
-                                                    NL80211_RADAR_NOP_FINISHED,
-                                                    NULL, GFP_ATOMIC);
+                                                    radar_event, NULL,
+                                                    GFP_ATOMIC);
                                continue;
                        }
 
@@ -810,7 +834,6 @@ void cfg80211_radar_event(struct wiphy *wiphy,
                          gfp_t gfp)
 {
        struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
-       unsigned long timeout;
 
        trace_cfg80211_radar_event(wiphy, chandef);
 
@@ -820,9 +843,7 @@ void cfg80211_radar_event(struct wiphy *wiphy,
         */
        cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_UNAVAILABLE);
 
-       timeout = msecs_to_jiffies(IEEE80211_DFS_MIN_NOP_TIME_MS);
-       queue_delayed_work(cfg80211_wq, &rdev->dfs_update_channels_wk,
-                          timeout);
+       cfg80211_sched_dfs_chan_update(rdev);
 
        nl80211_radar_notify(rdev, chandef, NL80211_RADAR_DETECTED, NULL, gfp);
 }
@@ -851,6 +872,7 @@ void cfg80211_cac_event(struct net_device *netdev,
                          msecs_to_jiffies(wdev->cac_time_ms);
                WARN_ON(!time_after_eq(jiffies, timeout));
                cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_AVAILABLE);
+               cfg80211_sched_dfs_chan_update(rdev);
                break;
        case NL80211_RADAR_CAC_ABORTED:
                break;