diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index fbd0923aff8e26d2def1279813ba2798c59d735d..dae041d19a613c56052ca5b5dabfeae565785502 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -2970,6 +2970,8 @@ struct cfg80211_ops { int (*set_ap_chanwidth)(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_chan_def *chandef); + bool (*is_all_iface_idle)(struct wiphy *wiphy); + int (*add_tx_ts)(struct wiphy *wiphy, struct net_device *dev, u8 tsid, const u8 *peer, u8 user_prio, u16 admitted_time); diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 3deba85dde3779a365bd6d523091afae5075bfaa..91ff69b57d9d18148d4156ee798e4b8791b91000 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -3690,6 +3690,8 @@ struct ieee80211_ops { int (*get_connection_alive)(struct ieee80211_hw *hw, struct ieee80211_vif *vif); + bool (*is_all_iface_idle)(struct ieee80211_hw *hw); + #if IS_ENABLED(CONFIG_IPV6) void (*ipv6_addr_change)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 5e27811a409b5cb58f3435d9b60ec90c530a9b44..91cfd1b20e32a07c77aba015bc2e26eebd3cc8c4 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -3183,6 +3183,13 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, return err; } +static bool ieee80211_is_all_iface_idle(struct wiphy *wiphy) +{ + struct ieee80211_local *local = wiphy_priv(wiphy); + + return drv_is_all_iface_idle(local); +} + u64 ieee80211_mgmt_tx_cookie(struct ieee80211_local *local) { lockdep_assert_held(&local->mtx); @@ -3669,6 +3676,7 @@ const struct cfg80211_ops mac80211_config_ops = { .get_channel = ieee80211_cfg_get_channel, .start_radar_detection = ieee80211_start_radar_detection, .channel_switch = ieee80211_channel_switch, + .is_all_iface_idle = ieee80211_is_all_iface_idle, .set_qos_map = ieee80211_set_qos_map, .set_ap_chanwidth = ieee80211_set_ap_chanwidth, .add_tx_ts = ieee80211_add_tx_ts, diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 3be8346ef51e18a252861078cf627d491098830b..f53f9c22d492e0c903d0ea6c7a7e2c5c2e6daa55 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h @@ -655,6 +655,14 @@ static inline int drv_set_antenna(struct ieee80211_local *local, return ret; } +static inline bool drv_is_all_iface_idle(struct ieee80211_local *local) +{ + if (!local->ops->is_all_iface_idle) + return true; + + return local->ops->is_all_iface_idle(&local->hw); +} + static inline int drv_get_antenna(struct ieee80211_local *local, u32 *tx_ant, u32 *rx_ant) { diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index c48e158c6ceca0cdcb7788ee45c803d2d7b3a127..acec3a8dc7d11af7d54af02a6b318b75de716c48 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c @@ -802,7 +802,7 @@ static void cfg80211_set_chans_dfs_state_bit_map (struct wiphy *wiphy, u32 cente if (radar_bit_map & (1 << *bit_idx)) { c = ieee80211_get_channel(wiphy, freq); if (!c || !(c->flags & IEEE80211_CHAN_RADAR)) { - *bit_idx++; + (*bit_idx)++; continue; } diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index eb3250b085a93b8bec85d3627dae413cec6a1737..bfdfed3a18448af3f75071b9eaf7ac0a89dcf203 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -7431,7 +7431,7 @@ skip_beacons: if (info->attrs[NL80211_ATTR_SB_DFS_BW]) params.sb_dfs_bw = nla_get_u8(info->attrs[NL80211_ATTR_SB_DFS_BW]); - if (NL80211_SB_DFS_BW_FULL == params.sb_dfs_bw) + if (params.sb_dfs_bw) cfg80211_set_dfs_state(&rdev->wiphy, ¶ms.chandef, NL80211_DFS_AVAILABLE); if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, ¶ms.chandef, diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h index 11cf83c8ad4f5008abb3f1cf8f59058027f2bb2d..669bca63c33f2b67b9176ec98b0e5ae1dad616b3 100644 --- a/net/wireless/rdev-ops.h +++ b/net/wireless/rdev-ops.h @@ -758,6 +758,14 @@ static inline int rdev_set_antenna(struct cfg80211_registered_device *rdev, return ret; } +static inline bool rdev_is_all_iface_idle(struct cfg80211_registered_device *rdev) +{ + if (!rdev->ops->is_all_iface_idle) + return true; + + return rdev->ops->is_all_iface_idle(&rdev->wiphy); +} + static inline int rdev_get_antenna(struct cfg80211_registered_device *rdev, u32 *tx_ant, u32 *rx_ant) { diff --git a/net/wireless/sme.c b/net/wireless/sme.c index ece8a0ab7b1a9d8de99f68d9476912abe8e9060c..dca8b57ff4b394ed1aaf7c888d9cb656ac970105 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c @@ -640,10 +640,24 @@ static bool cfg80211_is_all_idle(void) return is_all_idle; } +static bool cfg80211_drv_is_all_idle(void) +{ + struct cfg80211_registered_device *rdev; + bool is_all_idle = true; + + list_for_each_entry(rdev, &cfg80211_rdev_list, list) { + if (!rdev_is_all_iface_idle(rdev)) + is_all_idle = false; + } + + return is_all_idle; +} + + static void disconnect_work(struct work_struct *work) { rtnl_lock(); - if (cfg80211_is_all_idle()) + if (cfg80211_is_all_idle() && cfg80211_drv_is_all_idle()) regulatory_hint_disconnect(); rtnl_unlock(); }