aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/mac80211.h14
-rw-r--r--net/mac80211/cfg.c36
-rw-r--r--net/mac80211/chan.c33
-rw-r--r--net/mac80211/ieee80211_i.h14
-rw-r--r--net/mac80211/iface.c12
-rw-r--r--net/mac80211/main.c13
-rw-r--r--net/mac80211/mlme.c13
-rw-r--r--net/mac80211/pm.c2
-rw-r--r--net/mac80211/scan.c3
-rw-r--r--net/mac80211/trace.h19
-rw-r--r--net/mac80211/util.c46
11 files changed, 204 insertions, 1 deletions
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 0eaa9092364b..7241962f9f13 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -147,10 +147,12 @@ struct ieee80211_low_level_stats {
147 * enum ieee80211_chanctx_change - change flag for channel context 147 * enum ieee80211_chanctx_change - change flag for channel context
148 * @IEEE80211_CHANCTX_CHANGE_WIDTH: The channel width changed 148 * @IEEE80211_CHANCTX_CHANGE_WIDTH: The channel width changed
149 * @IEEE80211_CHANCTX_CHANGE_RX_CHAINS: The number of RX chains changed 149 * @IEEE80211_CHANCTX_CHANGE_RX_CHAINS: The number of RX chains changed
150 * @IEEE80211_CHANCTX_CHANGE_RADAR: radar detection flag changed
150 */ 151 */
151enum ieee80211_chanctx_change { 152enum ieee80211_chanctx_change {
152 IEEE80211_CHANCTX_CHANGE_WIDTH = BIT(0), 153 IEEE80211_CHANCTX_CHANGE_WIDTH = BIT(0),
153 IEEE80211_CHANCTX_CHANGE_RX_CHAINS = BIT(1), 154 IEEE80211_CHANCTX_CHANGE_RX_CHAINS = BIT(1),
155 IEEE80211_CHANCTX_CHANGE_RADAR = BIT(2),
154}; 156};
155 157
156/** 158/**
@@ -165,6 +167,7 @@ enum ieee80211_chanctx_change {
165 * @rx_chains_dynamic: The number of RX chains that must be enabled 167 * @rx_chains_dynamic: The number of RX chains that must be enabled
166 * after RTS/CTS handshake to receive SMPS MIMO transmissions; 168 * after RTS/CTS handshake to receive SMPS MIMO transmissions;
167 * this will always be >= @rx_chains_static. 169 * this will always be >= @rx_chains_static.
170 * @radar_enabled: whether radar detection is enabled on this channel.
168 * @drv_priv: data area for driver use, will always be aligned to 171 * @drv_priv: data area for driver use, will always be aligned to
169 * sizeof(void *), size is determined in hw information. 172 * sizeof(void *), size is determined in hw information.
170 */ 173 */
@@ -173,6 +176,8 @@ struct ieee80211_chanctx_conf {
173 176
174 u8 rx_chains_static, rx_chains_dynamic; 177 u8 rx_chains_static, rx_chains_dynamic;
175 178
179 bool radar_enabled;
180
176 u8 drv_priv[0] __aligned(sizeof(void *)); 181 u8 drv_priv[0] __aligned(sizeof(void *));
177}; 182};
178 183
@@ -967,6 +972,7 @@ enum ieee80211_smps_mode {
967 * 972 *
968 * @channel: the channel to tune to 973 * @channel: the channel to tune to
969 * @channel_type: the channel (HT) type 974 * @channel_type: the channel (HT) type
975 * @radar_enabled: whether radar detection is enabled
970 * 976 *
971 * @long_frame_max_tx_count: Maximum number of transmissions for a "long" frame 977 * @long_frame_max_tx_count: Maximum number of transmissions for a "long" frame
972 * (a frame not RTS protected), called "dot11LongRetryLimit" in 802.11, 978 * (a frame not RTS protected), called "dot11LongRetryLimit" in 802.11,
@@ -993,6 +999,7 @@ struct ieee80211_conf {
993 999
994 struct ieee80211_channel *channel; 1000 struct ieee80211_channel *channel;
995 enum nl80211_channel_type channel_type; 1001 enum nl80211_channel_type channel_type;
1002 bool radar_enabled;
996 enum ieee80211_smps_mode smps_mode; 1003 enum ieee80211_smps_mode smps_mode;
997}; 1004};
998 1005
@@ -3945,6 +3952,13 @@ void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif,
3945 gfp_t gfp); 3952 gfp_t gfp);
3946 3953
3947/** 3954/**
3955 * ieee80211_radar_detected - inform that a radar was detected
3956 *
3957 * @hw: pointer as obtained from ieee80211_alloc_hw()
3958 */
3959void ieee80211_radar_detected(struct ieee80211_hw *hw);
3960
3961/**
3948 * ieee80211_chswitch_done - Complete channel switch process 3962 * ieee80211_chswitch_done - Complete channel switch process
3949 * @vif: &struct ieee80211_vif pointer from the add_interface callback. 3963 * @vif: &struct ieee80211_vif pointer from the add_interface callback.
3950 * @success: make the channel switch successful or not 3964 * @success: make the channel switch successful or not
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index e3dec80cf617..0969978c2d92 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -928,6 +928,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
928 /* TODO: make hostapd tell us what it wants */ 928 /* TODO: make hostapd tell us what it wants */
929 sdata->smps_mode = IEEE80211_SMPS_OFF; 929 sdata->smps_mode = IEEE80211_SMPS_OFF;
930 sdata->needed_rx_chains = sdata->local->rx_chains; 930 sdata->needed_rx_chains = sdata->local->rx_chains;
931 sdata->radar_required = params->radar_required;
931 932
932 err = ieee80211_vif_use_channel(sdata, &params->chandef, 933 err = ieee80211_vif_use_channel(sdata, &params->chandef,
933 IEEE80211_CHANCTX_SHARED); 934 IEEE80211_CHANCTX_SHARED);
@@ -2395,7 +2396,8 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local,
2395 INIT_LIST_HEAD(&roc->dependents); 2396 INIT_LIST_HEAD(&roc->dependents);
2396 2397
2397 /* if there's one pending or we're scanning, queue this one */ 2398 /* if there's one pending or we're scanning, queue this one */
2398 if (!list_empty(&local->roc_list) || local->scanning) 2399 if (!list_empty(&local->roc_list) ||
2400 local->scanning || local->radar_detect_enabled)
2399 goto out_check_combine; 2401 goto out_check_combine;
2400 2402
2401 /* if not HW assist, just queue & schedule work */ 2403 /* if not HW assist, just queue & schedule work */
@@ -2645,6 +2647,37 @@ static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy,
2645 return ieee80211_cancel_roc(local, cookie, false); 2647 return ieee80211_cancel_roc(local, cookie, false);
2646} 2648}
2647 2649
2650static int ieee80211_start_radar_detection(struct wiphy *wiphy,
2651 struct net_device *dev,
2652 struct cfg80211_chan_def *chandef)
2653{
2654 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
2655 struct ieee80211_local *local = sdata->local;
2656 unsigned long timeout;
2657 int err;
2658
2659 if (!list_empty(&local->roc_list) || local->scanning)
2660 return -EBUSY;
2661
2662 /* whatever, but channel contexts should not complain about that one */
2663 sdata->smps_mode = IEEE80211_SMPS_OFF;
2664 sdata->needed_rx_chains = local->rx_chains;
2665 sdata->radar_required = true;
2666
2667 mutex_lock(&local->iflist_mtx);
2668 err = ieee80211_vif_use_channel(sdata, chandef,
2669 IEEE80211_CHANCTX_SHARED);
2670 mutex_unlock(&local->iflist_mtx);
2671 if (err)
2672 return err;
2673
2674 timeout = msecs_to_jiffies(IEEE80211_DFS_MIN_CAC_TIME_MS);
2675 ieee80211_queue_delayed_work(&sdata->local->hw,
2676 &sdata->dfs_cac_timer_work, timeout);
2677
2678 return 0;
2679}
2680
2648static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, 2681static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
2649 struct ieee80211_channel *chan, bool offchan, 2682 struct ieee80211_channel *chan, bool offchan,
2650 unsigned int wait, const u8 *buf, size_t len, 2683 unsigned int wait, const u8 *buf, size_t len,
@@ -3350,4 +3383,5 @@ struct cfg80211_ops mac80211_config_ops = {
3350 .get_et_stats = ieee80211_get_et_stats, 3383 .get_et_stats = ieee80211_get_et_stats,
3351 .get_et_strings = ieee80211_get_et_strings, 3384 .get_et_strings = ieee80211_get_et_strings,
3352 .get_channel = ieee80211_cfg_get_channel, 3385 .get_channel = ieee80211_cfg_get_channel,
3386 .start_radar_detection = ieee80211_start_radar_detection,
3353}; 3387};
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
index 038f249966d6..2e6faeda22ad 100644
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -193,6 +193,7 @@ static void ieee80211_unassign_vif_chanctx(struct ieee80211_sub_if_data *sdata,
193 if (ctx->refcount > 0) { 193 if (ctx->refcount > 0) {
194 ieee80211_recalc_chanctx_chantype(sdata->local, ctx); 194 ieee80211_recalc_chanctx_chantype(sdata->local, ctx);
195 ieee80211_recalc_smps_chanctx(local, ctx); 195 ieee80211_recalc_smps_chanctx(local, ctx);
196 ieee80211_recalc_radar_chanctx(local, ctx);
196 } 197 }
197} 198}
198 199
@@ -216,6 +217,37 @@ static void __ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata)
216 ieee80211_free_chanctx(local, ctx); 217 ieee80211_free_chanctx(local, ctx);
217} 218}
218 219
220void ieee80211_recalc_radar_chanctx(struct ieee80211_local *local,
221 struct ieee80211_chanctx *chanctx)
222{
223 struct ieee80211_sub_if_data *sdata;
224 bool radar_enabled = false;
225
226 lockdep_assert_held(&local->chanctx_mtx);
227
228 rcu_read_lock();
229 list_for_each_entry_rcu(sdata, &local->interfaces, list) {
230 if (sdata->radar_required) {
231 radar_enabled = true;
232 break;
233 }
234 }
235 rcu_read_unlock();
236
237 if (radar_enabled == chanctx->conf.radar_enabled)
238 return;
239
240 chanctx->conf.radar_enabled = radar_enabled;
241 local->radar_detect_enabled = chanctx->conf.radar_enabled;
242
243 if (!local->use_chanctx) {
244 local->hw.conf.radar_enabled = chanctx->conf.radar_enabled;
245 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
246 }
247
248 drv_change_chanctx(local, chanctx, IEEE80211_CHANCTX_CHANGE_RADAR);
249}
250
219void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local, 251void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local,
220 struct ieee80211_chanctx *chanctx) 252 struct ieee80211_chanctx *chanctx)
221{ 253{
@@ -331,6 +363,7 @@ int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
331 } 363 }
332 364
333 ieee80211_recalc_smps_chanctx(local, ctx); 365 ieee80211_recalc_smps_chanctx(local, ctx);
366 ieee80211_recalc_radar_chanctx(local, ctx);
334 out: 367 out:
335 mutex_unlock(&local->chanctx_mtx); 368 mutex_unlock(&local->chanctx_mtx);
336 return ret; 369 return ret;
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 76cdcfcd614c..0e0a9776be39 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -722,6 +722,9 @@ struct ieee80211_sub_if_data {
722 int user_power_level; /* in dBm */ 722 int user_power_level; /* in dBm */
723 int ap_power_level; /* in dBm */ 723 int ap_power_level; /* in dBm */
724 724
725 bool radar_required;
726 struct delayed_work dfs_cac_timer_work;
727
725 /* 728 /*
726 * AP this belongs to: self in AP mode and 729 * AP this belongs to: self in AP mode and
727 * corresponding AP in VLAN mode, NULL for 730 * corresponding AP in VLAN mode, NULL for
@@ -942,6 +945,10 @@ struct ieee80211_local {
942 /* wowlan is enabled -- don't reconfig on resume */ 945 /* wowlan is enabled -- don't reconfig on resume */
943 bool wowlan; 946 bool wowlan;
944 947
948 /* DFS/radar detection is enabled */
949 bool radar_detect_enabled;
950 struct work_struct radar_detected_work;
951
945 /* number of RX chains the hardware has */ 952 /* number of RX chains the hardware has */
946 u8 rx_chains; 953 u8 rx_chains;
947 954
@@ -1606,6 +1613,13 @@ void ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data *sdata,
1606 1613
1607void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local, 1614void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local,
1608 struct ieee80211_chanctx *chanctx); 1615 struct ieee80211_chanctx *chanctx);
1616void ieee80211_recalc_radar_chanctx(struct ieee80211_local *local,
1617 struct ieee80211_chanctx *chanctx);
1618
1619void ieee80211_dfs_cac_timer(unsigned long data);
1620void ieee80211_dfs_cac_timer_work(struct work_struct *work);
1621void ieee80211_dfs_cac_cancel(struct ieee80211_local *local);
1622void ieee80211_dfs_radar_detected_work(struct work_struct *work);
1609 1623
1610#ifdef CONFIG_MAC80211_NOINLINE 1624#ifdef CONFIG_MAC80211_NOINLINE
1611#define debug_noinline noinline 1625#define debug_noinline noinline
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 40ff0307d089..e9223ce2bf99 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -749,6 +749,16 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
749 749
750 cancel_work_sync(&sdata->recalc_smps); 750 cancel_work_sync(&sdata->recalc_smps);
751 751
752 cancel_delayed_work_sync(&sdata->dfs_cac_timer_work);
753
754 if (sdata->wdev.cac_started) {
755 mutex_lock(&local->iflist_mtx);
756 ieee80211_vif_release_channel(sdata);
757 mutex_unlock(&local->iflist_mtx);
758 cfg80211_cac_event(sdata->dev, NL80211_RADAR_CAC_ABORTED,
759 GFP_KERNEL);
760 }
761
752 /* APs need special treatment */ 762 /* APs need special treatment */
753 if (sdata->vif.type == NL80211_IFTYPE_AP) { 763 if (sdata->vif.type == NL80211_IFTYPE_AP) {
754 struct ieee80211_sub_if_data *vlan, *tmpsdata; 764 struct ieee80211_sub_if_data *vlan, *tmpsdata;
@@ -1513,6 +1523,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
1513 spin_lock_init(&sdata->cleanup_stations_lock); 1523 spin_lock_init(&sdata->cleanup_stations_lock);
1514 INIT_LIST_HEAD(&sdata->cleanup_stations); 1524 INIT_LIST_HEAD(&sdata->cleanup_stations);
1515 INIT_WORK(&sdata->cleanup_stations_wk, ieee80211_cleanup_sdata_stas_wk); 1525 INIT_WORK(&sdata->cleanup_stations_wk, ieee80211_cleanup_sdata_stas_wk);
1526 INIT_DELAYED_WORK(&sdata->dfs_cac_timer_work,
1527 ieee80211_dfs_cac_timer_work);
1516 1528
1517 for (i = 0; i < IEEE80211_NUM_BANDS; i++) { 1529 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
1518 struct ieee80211_supported_band *sband; 1530 struct ieee80211_supported_band *sband;
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 38b3468bc515..9cdbc774cfd7 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -621,6 +621,9 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
621 621
622 INIT_WORK(&local->restart_work, ieee80211_restart_work); 622 INIT_WORK(&local->restart_work, ieee80211_restart_work);
623 623
624 INIT_WORK(&local->radar_detected_work,
625 ieee80211_dfs_radar_detected_work);
626
624 INIT_WORK(&local->reconfig_filter, ieee80211_reconfig_filter); 627 INIT_WORK(&local->reconfig_filter, ieee80211_reconfig_filter);
625 local->smps_mode = IEEE80211_SMPS_OFF; 628 local->smps_mode = IEEE80211_SMPS_OFF;
626 629
@@ -713,6 +716,16 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
713 */ 716 */
714 if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_WDS)) 717 if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_WDS))
715 return -EINVAL; 718 return -EINVAL;
719
720 /* DFS currently not supported with channel context drivers */
721 for (i = 0; i < local->hw.wiphy->n_iface_combinations; i++) {
722 const struct ieee80211_iface_combination *comb;
723
724 comb = &local->hw.wiphy->iface_combinations[i];
725
726 if (comb->radar_detect_widths)
727 return -EINVAL;
728 }
716 } 729 }
717 730
718 /* Only HW csum features are currently compatible with mac80211 */ 731 /* Only HW csum features are currently compatible with mac80211 */
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index efb22763d56d..7d4cde7af98e 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1212,6 +1212,19 @@ void ieee80211_dynamic_ps_timer(unsigned long data)
1212 ieee80211_queue_work(&local->hw, &local->dynamic_ps_enable_work); 1212 ieee80211_queue_work(&local->hw, &local->dynamic_ps_enable_work);
1213} 1213}
1214 1214
1215void ieee80211_dfs_cac_timer_work(struct work_struct *work)
1216{
1217 struct delayed_work *delayed_work =
1218 container_of(work, struct delayed_work, work);
1219 struct ieee80211_sub_if_data *sdata =
1220 container_of(delayed_work, struct ieee80211_sub_if_data,
1221 dfs_cac_timer_work);
1222
1223 ieee80211_vif_release_channel(sdata);
1224
1225 cfg80211_cac_event(sdata->dev, NL80211_RADAR_CAC_FINISHED, GFP_KERNEL);
1226}
1227
1215/* MLME */ 1228/* MLME */
1216static bool ieee80211_sta_wmm_params(struct ieee80211_local *local, 1229static bool ieee80211_sta_wmm_params(struct ieee80211_local *local,
1217 struct ieee80211_sub_if_data *sdata, 1230 struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
index 53801d20176d..d0275f34bf70 100644
--- a/net/mac80211/pm.c
+++ b/net/mac80211/pm.c
@@ -38,6 +38,8 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
38 38
39 ieee80211_scan_cancel(local); 39 ieee80211_scan_cancel(local);
40 40
41 ieee80211_dfs_cac_cancel(local);
42
41 if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { 43 if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) {
42 mutex_lock(&local->sta_mtx); 44 mutex_lock(&local->sta_mtx);
43 list_for_each_entry(sta, &local->sta_list, list) { 45 list_for_each_entry(sta, &local->sta_list, list) {
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 6d0b89e4aa31..43a45cf00e06 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -351,6 +351,9 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local)
351static bool ieee80211_can_scan(struct ieee80211_local *local, 351static bool ieee80211_can_scan(struct ieee80211_local *local,
352 struct ieee80211_sub_if_data *sdata) 352 struct ieee80211_sub_if_data *sdata)
353{ 353{
354 if (local->radar_detect_enabled)
355 return false;
356
354 if (!list_empty(&local->roc_list)) 357 if (!list_empty(&local->roc_list))
355 return false; 358 return false;
356 359
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index 0bdd7aeb8958..1183c4a4fee5 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -1862,6 +1862,25 @@ TRACE_EVENT(drv_set_default_unicast_key,
1862 LOCAL_PR_ARG, VIF_PR_ARG, __entry->key_idx) 1862 LOCAL_PR_ARG, VIF_PR_ARG, __entry->key_idx)
1863); 1863);
1864 1864
1865TRACE_EVENT(api_radar_detected,
1866 TP_PROTO(struct ieee80211_local *local),
1867
1868 TP_ARGS(local),
1869
1870 TP_STRUCT__entry(
1871 LOCAL_ENTRY
1872 ),
1873
1874 TP_fast_assign(
1875 LOCAL_ASSIGN;
1876 ),
1877
1878 TP_printk(
1879 LOCAL_PR_FMT " radar detected",
1880 LOCAL_PR_ARG
1881 )
1882);
1883
1865#ifdef CONFIG_MAC80211_MESSAGE_TRACING 1884#ifdef CONFIG_MAC80211_MESSAGE_TRACING
1866#undef TRACE_SYSTEM 1885#undef TRACE_SYSTEM
1867#define TRACE_SYSTEM mac80211_msg 1886#define TRACE_SYSTEM mac80211_msg
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 6cb71a350edd..218cb52f2b59 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -2133,3 +2133,49 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local,
2133 2133
2134 return ts; 2134 return ts;
2135} 2135}
2136
2137void ieee80211_dfs_cac_cancel(struct ieee80211_local *local)
2138{
2139 struct ieee80211_sub_if_data *sdata;
2140
2141 mutex_lock(&local->iflist_mtx);
2142 list_for_each_entry(sdata, &local->interfaces, list) {
2143 cancel_delayed_work_sync(&sdata->dfs_cac_timer_work);
2144
2145 if (sdata->wdev.cac_started) {
2146 ieee80211_vif_release_channel(sdata);
2147 cfg80211_cac_event(sdata->dev,
2148 NL80211_RADAR_CAC_ABORTED,
2149 GFP_KERNEL);
2150 }
2151 }
2152 mutex_unlock(&local->iflist_mtx);
2153}
2154
2155void ieee80211_dfs_radar_detected_work(struct work_struct *work)
2156{
2157 struct ieee80211_local *local =
2158 container_of(work, struct ieee80211_local, radar_detected_work);
2159 struct cfg80211_chan_def chandef;
2160
2161 ieee80211_dfs_cac_cancel(local);
2162
2163 if (local->use_chanctx)
2164 /* currently not handled */
2165 WARN_ON(1);
2166 else {
2167 cfg80211_chandef_create(&chandef, local->hw.conf.channel,
2168 local->hw.conf.channel_type);
2169 cfg80211_radar_event(local->hw.wiphy, &chandef, GFP_KERNEL);
2170 }
2171}
2172
2173void ieee80211_radar_detected(struct ieee80211_hw *hw)
2174{
2175 struct ieee80211_local *local = hw_to_local(hw);
2176
2177 trace_api_radar_detected(local);
2178
2179 ieee80211_queue_work(hw, &local->radar_detected_work);
2180}
2181EXPORT_SYMBOL(ieee80211_radar_detected);