diff options
-rw-r--r-- | include/net/mac80211.h | 14 | ||||
-rw-r--r-- | net/mac80211/cfg.c | 36 | ||||
-rw-r--r-- | net/mac80211/chan.c | 33 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 14 | ||||
-rw-r--r-- | net/mac80211/iface.c | 12 | ||||
-rw-r--r-- | net/mac80211/main.c | 13 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 13 | ||||
-rw-r--r-- | net/mac80211/pm.c | 2 | ||||
-rw-r--r-- | net/mac80211/scan.c | 3 | ||||
-rw-r--r-- | net/mac80211/trace.h | 19 | ||||
-rw-r--r-- | net/mac80211/util.c | 46 |
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 | */ |
151 | enum ieee80211_chanctx_change { | 152 | enum 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 | */ | ||
3959 | void 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, ¶ms->chandef, | 933 | err = ieee80211_vif_use_channel(sdata, ¶ms->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 | ||
2650 | static 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 | |||
2648 | static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | 2681 | static 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 | ||
220 | void 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 | |||
219 | void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local, | 251 | void 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 | ||
1607 | void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local, | 1614 | void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local, |
1608 | struct ieee80211_chanctx *chanctx); | 1615 | struct ieee80211_chanctx *chanctx); |
1616 | void ieee80211_recalc_radar_chanctx(struct ieee80211_local *local, | ||
1617 | struct ieee80211_chanctx *chanctx); | ||
1618 | |||
1619 | void ieee80211_dfs_cac_timer(unsigned long data); | ||
1620 | void ieee80211_dfs_cac_timer_work(struct work_struct *work); | ||
1621 | void ieee80211_dfs_cac_cancel(struct ieee80211_local *local); | ||
1622 | void 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 | ||
1215 | void 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 */ |
1216 | static bool ieee80211_sta_wmm_params(struct ieee80211_local *local, | 1229 | static 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) | |||
351 | static bool ieee80211_can_scan(struct ieee80211_local *local, | 351 | static 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 | ||
1865 | TRACE_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 | |||
2137 | void 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 | |||
2155 | void 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 | |||
2173 | void 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 | } | ||
2181 | EXPORT_SYMBOL(ieee80211_radar_detected); | ||