cfg80211: Fix radar event during another phy CAC
In case a radar event of CAC_FINISHED or RADAR_DETECTED happens during another phy is during CAC we might need to cancel that CAC. If we got a radar in a channel that another phy is now doing CAC on then the CAC should be canceled there. If, for example, 2 phys doing CAC on the same channels, or on comptable channels, once on of them will finish his CAC the other might need to cancel his CAC, since it is no longer relevant. To fix that the commit adds an callback and implement it in mac80211 to end CAC. This commit also adds a call to said callback if after a radar event we see the CAC is no longer relevant Signed-off-by: Orr Mazor <Orr.Mazor@tandemg.com> Reviewed-by: Sergey Matyukevich <sergey.matyukevich.os@quantenna.com> Link: https://lore.kernel.org/r/20191222145449.15792-1-Orr.Mazor@tandemg.com [slightly reformat/reword commit message] Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
c4b9d655e4
commit
26ec17a1dc
|
@ -3548,6 +3548,9 @@ struct cfg80211_update_owe_info {
|
||||||
*
|
*
|
||||||
* @start_radar_detection: Start radar detection in the driver.
|
* @start_radar_detection: Start radar detection in the driver.
|
||||||
*
|
*
|
||||||
|
* @end_cac: End running CAC, probably because a related CAC
|
||||||
|
* was finished on another phy.
|
||||||
|
*
|
||||||
* @update_ft_ies: Provide updated Fast BSS Transition information to the
|
* @update_ft_ies: Provide updated Fast BSS Transition information to the
|
||||||
* driver. If the SME is in the driver/firmware, this information can be
|
* driver. If the SME is in the driver/firmware, this information can be
|
||||||
* used in building Authentication and Reassociation Request frames.
|
* used in building Authentication and Reassociation Request frames.
|
||||||
|
@ -3874,6 +3877,8 @@ struct cfg80211_ops {
|
||||||
struct net_device *dev,
|
struct net_device *dev,
|
||||||
struct cfg80211_chan_def *chandef,
|
struct cfg80211_chan_def *chandef,
|
||||||
u32 cac_time_ms);
|
u32 cac_time_ms);
|
||||||
|
void (*end_cac)(struct wiphy *wiphy,
|
||||||
|
struct net_device *dev);
|
||||||
int (*update_ft_ies)(struct wiphy *wiphy, struct net_device *dev,
|
int (*update_ft_ies)(struct wiphy *wiphy, struct net_device *dev,
|
||||||
struct cfg80211_update_ft_ies_params *ftie);
|
struct cfg80211_update_ft_ies_params *ftie);
|
||||||
int (*crit_proto_start)(struct wiphy *wiphy,
|
int (*crit_proto_start)(struct wiphy *wiphy,
|
||||||
|
|
|
@ -2954,6 +2954,28 @@ static int ieee80211_start_radar_detection(struct wiphy *wiphy,
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ieee80211_end_cac(struct wiphy *wiphy,
|
||||||
|
struct net_device *dev)
|
||||||
|
{
|
||||||
|
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||||
|
struct ieee80211_local *local = sdata->local;
|
||||||
|
|
||||||
|
mutex_lock(&local->mtx);
|
||||||
|
list_for_each_entry(sdata, &local->interfaces, list) {
|
||||||
|
/* it might be waiting for the local->mtx, but then
|
||||||
|
* by the time it gets it, sdata->wdev.cac_started
|
||||||
|
* will no longer be true
|
||||||
|
*/
|
||||||
|
cancel_delayed_work(&sdata->dfs_cac_timer_work);
|
||||||
|
|
||||||
|
if (sdata->wdev.cac_started) {
|
||||||
|
ieee80211_vif_release_channel(sdata);
|
||||||
|
sdata->wdev.cac_started = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mutex_unlock(&local->mtx);
|
||||||
|
}
|
||||||
|
|
||||||
static struct cfg80211_beacon_data *
|
static struct cfg80211_beacon_data *
|
||||||
cfg80211_beacon_dup(struct cfg80211_beacon_data *beacon)
|
cfg80211_beacon_dup(struct cfg80211_beacon_data *beacon)
|
||||||
{
|
{
|
||||||
|
@ -4023,6 +4045,7 @@ const struct cfg80211_ops mac80211_config_ops = {
|
||||||
#endif
|
#endif
|
||||||
.get_channel = ieee80211_cfg_get_channel,
|
.get_channel = ieee80211_cfg_get_channel,
|
||||||
.start_radar_detection = ieee80211_start_radar_detection,
|
.start_radar_detection = ieee80211_start_radar_detection,
|
||||||
|
.end_cac = ieee80211_end_cac,
|
||||||
.channel_switch = ieee80211_channel_switch,
|
.channel_switch = ieee80211_channel_switch,
|
||||||
.set_qos_map = ieee80211_set_qos_map,
|
.set_qos_map = ieee80211_set_qos_map,
|
||||||
.set_ap_chanwidth = ieee80211_set_ap_chanwidth,
|
.set_ap_chanwidth = ieee80211_set_ap_chanwidth,
|
||||||
|
|
|
@ -1167,6 +1167,16 @@ rdev_start_radar_detection(struct cfg80211_registered_device *rdev,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
rdev_end_cac(struct cfg80211_registered_device *rdev,
|
||||||
|
struct net_device *dev)
|
||||||
|
{
|
||||||
|
trace_rdev_end_cac(&rdev->wiphy, dev);
|
||||||
|
if (rdev->ops->end_cac)
|
||||||
|
rdev->ops->end_cac(&rdev->wiphy, dev);
|
||||||
|
trace_rdev_return_void(&rdev->wiphy);
|
||||||
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
rdev_set_mcast_rate(struct cfg80211_registered_device *rdev,
|
rdev_set_mcast_rate(struct cfg80211_registered_device *rdev,
|
||||||
struct net_device *dev,
|
struct net_device *dev,
|
||||||
|
|
|
@ -3892,6 +3892,25 @@ bool regulatory_pre_cac_allowed(struct wiphy *wiphy)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(regulatory_pre_cac_allowed);
|
EXPORT_SYMBOL(regulatory_pre_cac_allowed);
|
||||||
|
|
||||||
|
static void cfg80211_check_and_end_cac(struct cfg80211_registered_device *rdev)
|
||||||
|
{
|
||||||
|
struct wireless_dev *wdev;
|
||||||
|
/* If we finished CAC or received radar, we should end any
|
||||||
|
* CAC running on the same channels.
|
||||||
|
* the check !cfg80211_chandef_dfs_usable contain 2 options:
|
||||||
|
* either all channels are available - those the CAC_FINISHED
|
||||||
|
* event has effected another wdev state, or there is a channel
|
||||||
|
* in unavailable state in wdev chandef - those the RADAR_DETECTED
|
||||||
|
* event has effected another wdev state.
|
||||||
|
* In both cases we should end the CAC on the wdev.
|
||||||
|
*/
|
||||||
|
list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
|
||||||
|
if (wdev->cac_started &&
|
||||||
|
!cfg80211_chandef_dfs_usable(&rdev->wiphy, &wdev->chandef))
|
||||||
|
rdev_end_cac(rdev, wdev->netdev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void regulatory_propagate_dfs_state(struct wiphy *wiphy,
|
void regulatory_propagate_dfs_state(struct wiphy *wiphy,
|
||||||
struct cfg80211_chan_def *chandef,
|
struct cfg80211_chan_def *chandef,
|
||||||
enum nl80211_dfs_state dfs_state,
|
enum nl80211_dfs_state dfs_state,
|
||||||
|
@ -3918,8 +3937,10 @@ void regulatory_propagate_dfs_state(struct wiphy *wiphy,
|
||||||
cfg80211_set_dfs_state(&rdev->wiphy, chandef, dfs_state);
|
cfg80211_set_dfs_state(&rdev->wiphy, chandef, dfs_state);
|
||||||
|
|
||||||
if (event == NL80211_RADAR_DETECTED ||
|
if (event == NL80211_RADAR_DETECTED ||
|
||||||
event == NL80211_RADAR_CAC_FINISHED)
|
event == NL80211_RADAR_CAC_FINISHED) {
|
||||||
cfg80211_sched_dfs_chan_update(rdev);
|
cfg80211_sched_dfs_chan_update(rdev);
|
||||||
|
cfg80211_check_and_end_cac(rdev);
|
||||||
|
}
|
||||||
|
|
||||||
nl80211_radar_notify(rdev, chandef, event, NULL, GFP_KERNEL);
|
nl80211_radar_notify(rdev, chandef, event, NULL, GFP_KERNEL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -646,6 +646,11 @@ DEFINE_EVENT(wiphy_netdev_evt, rdev_flush_pmksa,
|
||||||
TP_ARGS(wiphy, netdev)
|
TP_ARGS(wiphy, netdev)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
DEFINE_EVENT(wiphy_netdev_evt, rdev_end_cac,
|
||||||
|
TP_PROTO(struct wiphy *wiphy, struct net_device *netdev),
|
||||||
|
TP_ARGS(wiphy, netdev)
|
||||||
|
);
|
||||||
|
|
||||||
DECLARE_EVENT_CLASS(station_add_change,
|
DECLARE_EVENT_CLASS(station_add_change,
|
||||||
TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 *mac,
|
TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 *mac,
|
||||||
struct station_parameters *params),
|
struct station_parameters *params),
|
||||||
|
|
Loading…
Reference in New Issue