|
|
@@ -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;
|