developer | 3d5faf2 | 2022-11-29 18:07:22 +0800 | [diff] [blame] | 1 | From af85a4c0624897cb92ba6f543b322bb1fcbe9845 Mon Sep 17 00:00:00 2001 |
developer | 29344f1 | 2022-10-17 12:01:44 +0800 | [diff] [blame] | 2 | From: StanleyYP Wang <StanleyYP.Wang@mediatek.com> |
| 3 | Date: Wed, 5 Oct 2022 19:13:43 +0800 |
developer | 3d5faf2 | 2022-11-29 18:07:22 +0800 | [diff] [blame] | 4 | Subject: [PATCH 913/913] mac80211: mtk: fix the issue of AP and STA starting |
| 5 | on DFS channel concurrently |
developer | 29344f1 | 2022-10-17 12:01:44 +0800 | [diff] [blame] | 6 | |
| 7 | Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com> |
| 8 | --- |
developer | e126222 | 2022-10-25 12:20:54 +0800 | [diff] [blame] | 9 | include/net/cfg80211.h | 21 +++++++++++++++++ |
developer | 29344f1 | 2022-10-17 12:01:44 +0800 | [diff] [blame] | 10 | include/uapi/linux/nl80211.h | 2 +- |
developer | e126222 | 2022-10-25 12:20:54 +0800 | [diff] [blame] | 11 | net/mac80211/cfg.c | 44 ++++++++++++++++++++++++++++++++++++ |
developer | 29344f1 | 2022-10-17 12:01:44 +0800 | [diff] [blame] | 12 | net/mac80211/chan.c | 2 +- |
| 13 | net/wireless/chan.c | 6 ++--- |
developer | e126222 | 2022-10-25 12:20:54 +0800 | [diff] [blame] | 14 | net/wireless/nl80211.c | 8 +++++++ |
| 15 | net/wireless/rdev-ops.h | 16 +++++++++++++ |
| 16 | net/wireless/trace.h | 15 ++++++++++++ |
| 17 | 8 files changed, 109 insertions(+), 5 deletions(-) |
developer | 29344f1 | 2022-10-17 12:01:44 +0800 | [diff] [blame] | 18 | |
| 19 | diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h |
developer | 3d5faf2 | 2022-11-29 18:07:22 +0800 | [diff] [blame] | 20 | index b97ddbd..c4c0926 100644 |
developer | 29344f1 | 2022-10-17 12:01:44 +0800 | [diff] [blame] | 21 | --- a/include/net/cfg80211.h |
| 22 | +++ b/include/net/cfg80211.h |
| 23 | @@ -800,6 +800,24 @@ cfg80211_chandef_identical(const struct cfg80211_chan_def *chandef1, |
| 24 | chandef1->center_freq2 == chandef2->center_freq2); |
| 25 | } |
| 26 | |
| 27 | +/** |
| 28 | + * cfg80211_chan_fully_overlap - check if two channel are fully overlapped |
| 29 | + * @chandef1: first channel definition |
| 30 | + * @chandef2: second channel definition |
| 31 | + * |
| 32 | + * Return: %true if the channels are valid and fully overlapped, %false otherwise. |
| 33 | + */ |
| 34 | +static inline bool |
| 35 | +cfg80211_chan_fully_overlap(const struct cfg80211_chan_def *chandef1, |
| 36 | + const struct cfg80211_chan_def *chandef2) |
| 37 | +{ |
| 38 | + return (chandef1->center_freq1 != 0 && |
| 39 | + chandef1->center_freq1 == chandef2->center_freq1 && |
| 40 | + chandef1->width == chandef2->width && |
| 41 | + chandef1->freq1_offset == chandef2->freq1_offset && |
| 42 | + chandef1->center_freq2 == chandef2->center_freq2); |
| 43 | +} |
| 44 | + |
| 45 | /** |
| 46 | * cfg80211_chandef_is_edmg - check if chandef represents an EDMG channel |
| 47 | * |
developer | e126222 | 2022-10-25 12:20:54 +0800 | [diff] [blame] | 48 | @@ -4402,6 +4420,8 @@ struct cfg80211_ops { |
developer | 29344f1 | 2022-10-17 12:01:44 +0800 | [diff] [blame] | 49 | int (*set_radar_background)(struct wiphy *wiphy, |
| 50 | struct cfg80211_chan_def *chandef); |
developer | e126222 | 2022-10-25 12:20:54 +0800 | [diff] [blame] | 51 | void (*skip_cac)(struct wireless_dev *wdev); |
developer | 29344f1 | 2022-10-17 12:01:44 +0800 | [diff] [blame] | 52 | + void (*check_cac_skip)(struct wiphy *wiphy, |
| 53 | + struct cfg80211_chan_def *chandef); |
| 54 | }; |
| 55 | |
| 56 | /* |
developer | e126222 | 2022-10-25 12:20:54 +0800 | [diff] [blame] | 57 | @@ -5555,6 +5575,7 @@ struct wireless_dev { |
developer | 29344f1 | 2022-10-17 12:01:44 +0800 | [diff] [blame] | 58 | struct work_struct pmsr_free_wk; |
| 59 | |
| 60 | unsigned long unprot_beacon_reported; |
| 61 | + bool start_disabled; |
| 62 | }; |
| 63 | |
| 64 | static inline u8 *wdev_address(struct wireless_dev *wdev) |
| 65 | diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h |
| 66 | index e674aa7..ada8288 100644 |
| 67 | --- a/include/uapi/linux/nl80211.h |
| 68 | +++ b/include/uapi/linux/nl80211.h |
| 69 | @@ -3129,7 +3129,7 @@ enum nl80211_attrs { |
| 70 | NL80211_ATTR_WIPHY_ANTENNA_GAIN, |
| 71 | |
| 72 | /* add attributes here, update the policy in nl80211.c */ |
| 73 | - |
| 74 | + NL80211_ATTR_START_DISABLED = 999, |
| 75 | __NL80211_ATTR_AFTER_LAST, |
| 76 | NUM_NL80211_ATTR = __NL80211_ATTR_AFTER_LAST, |
| 77 | NL80211_ATTR_MAX = __NL80211_ATTR_AFTER_LAST - 1 |
| 78 | diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c |
developer | 3d5faf2 | 2022-11-29 18:07:22 +0800 | [diff] [blame] | 79 | index 97c5e5d..d726410 100644 |
developer | 29344f1 | 2022-10-17 12:01:44 +0800 | [diff] [blame] | 80 | --- a/net/mac80211/cfg.c |
| 81 | +++ b/net/mac80211/cfg.c |
developer | 3d5faf2 | 2022-11-29 18:07:22 +0800 | [diff] [blame] | 82 | @@ -4522,6 +4522,49 @@ ieee80211_skip_cac(struct wireless_dev *wdev) |
developer | e126222 | 2022-10-25 12:20:54 +0800 | [diff] [blame] | 83 | } |
developer | 29344f1 | 2022-10-17 12:01:44 +0800 | [diff] [blame] | 84 | } |
| 85 | |
| 86 | +static void |
| 87 | +ieee80211_check_cac_skip(struct wiphy *wiphy, |
| 88 | + struct cfg80211_chan_def *chandef) |
| 89 | +{ |
| 90 | + struct ieee80211_local *local = wiphy_priv(wiphy); |
| 91 | + struct ieee80211_sub_if_data *s1; |
| 92 | + struct ieee80211_sub_if_data *s2; |
| 93 | + struct ieee80211_sub_if_data *sdata_sta; |
| 94 | + struct ieee80211_if_managed *ifmgd; |
| 95 | + struct ieee80211_channel *chan; |
| 96 | + struct wireless_dev *wdev; |
| 97 | + unsigned int cac_time_ms; |
| 98 | + |
| 99 | + mutex_lock(&local->mtx); |
| 100 | + /* Bypass AP's cac if there is a STA associated to the same DFS channel */ |
| 101 | + list_for_each_entry(s1, &local->interfaces, list) { |
| 102 | + ifmgd = &s1->u.mgd; |
| 103 | + |
| 104 | + if (s1->vif.type == NL80211_IFTYPE_STATION && ifmgd->associated) |
| 105 | + sdata_sta = s1; |
| 106 | + else |
| 107 | + continue; |
| 108 | + |
| 109 | + list_for_each_entry(s2, &local->interfaces, list) { |
| 110 | + wdev = &s2->wdev; |
| 111 | + chan = wdev->chandef.chan; |
| 112 | + if (chan) { |
| 113 | + if (!(chan->flags & IEEE80211_CHAN_RADAR)) |
| 114 | + continue; |
| 115 | + |
| 116 | + if (wdev->identifier != sdata_sta->wdev.identifier && |
| 117 | + chan->dfs_state == NL80211_DFS_USABLE && wdev->cac_started && |
| 118 | + cfg80211_chan_fully_overlap(&sdata_sta->vif.bss_conf.chandef, |
| 119 | + &s2->vif.bss_conf.chandef)) { |
developer | e126222 | 2022-10-25 12:20:54 +0800 | [diff] [blame] | 120 | + ieee80211_skip_cac(wdev); |
developer | 29344f1 | 2022-10-17 12:01:44 +0800 | [diff] [blame] | 121 | + sdata_info(s2, "Skip CAC on the associated STA's chan\n"); |
| 122 | + } |
| 123 | + } |
| 124 | + } |
| 125 | + } |
| 126 | + mutex_unlock(&local->mtx); |
| 127 | +} |
| 128 | + |
| 129 | const struct cfg80211_ops mac80211_config_ops = { |
| 130 | .add_virtual_intf = ieee80211_add_iface, |
| 131 | .del_virtual_intf = ieee80211_del_iface, |
developer | 3d5faf2 | 2022-11-29 18:07:22 +0800 | [diff] [blame] | 132 | @@ -4629,4 +4672,5 @@ const struct cfg80211_ops mac80211_config_ops = { |
developer | 29344f1 | 2022-10-17 12:01:44 +0800 | [diff] [blame] | 133 | .color_change = ieee80211_color_change, |
| 134 | .set_radar_background = ieee80211_set_radar_background, |
developer | e126222 | 2022-10-25 12:20:54 +0800 | [diff] [blame] | 135 | .skip_cac = ieee80211_skip_cac, |
developer | 29344f1 | 2022-10-17 12:01:44 +0800 | [diff] [blame] | 136 | + .check_cac_skip = ieee80211_check_cac_skip, |
| 137 | }; |
| 138 | diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c |
| 139 | index 63e15f5..5e57e4a 100644 |
| 140 | --- a/net/mac80211/chan.c |
| 141 | +++ b/net/mac80211/chan.c |
| 142 | @@ -505,7 +505,7 @@ bool ieee80211_is_radar_required(struct ieee80211_local *local) |
| 143 | |
| 144 | rcu_read_lock(); |
| 145 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
| 146 | - if (sdata->radar_required) { |
| 147 | + if (sdata->radar_required && sdata->wdev.cac_started) { |
| 148 | rcu_read_unlock(); |
| 149 | return true; |
| 150 | } |
| 151 | diff --git a/net/wireless/chan.c b/net/wireless/chan.c |
| 152 | index 5f50ac4..067ed79 100644 |
| 153 | --- a/net/wireless/chan.c |
| 154 | +++ b/net/wireless/chan.c |
| 155 | @@ -664,13 +664,13 @@ bool cfg80211_beaconing_iface_active(struct wireless_dev *wdev) |
| 156 | switch (wdev->iftype) { |
| 157 | case NL80211_IFTYPE_AP: |
| 158 | case NL80211_IFTYPE_P2P_GO: |
| 159 | - active = wdev->beacon_interval != 0; |
| 160 | + active = wdev->beacon_interval != 0 || wdev->start_disabled; |
| 161 | break; |
| 162 | case NL80211_IFTYPE_ADHOC: |
| 163 | - active = wdev->ssid_len != 0; |
| 164 | + active = wdev->ssid_len != 0 || wdev->start_disabled; |
| 165 | break; |
| 166 | case NL80211_IFTYPE_MESH_POINT: |
| 167 | - active = wdev->mesh_id_len != 0; |
| 168 | + active = wdev->mesh_id_len != 0 || wdev->start_disabled; |
| 169 | break; |
| 170 | case NL80211_IFTYPE_STATION: |
| 171 | case NL80211_IFTYPE_OCB: |
| 172 | diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c |
| 173 | index a20aba5..8dc928d 100644 |
| 174 | --- a/net/wireless/nl80211.c |
| 175 | +++ b/net/wireless/nl80211.c |
| 176 | @@ -803,6 +803,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { |
| 177 | NLA_POLICY_NESTED(nl80211_mbssid_config_policy), |
| 178 | [NL80211_ATTR_MBSSID_ELEMS] = { .type = NLA_NESTED }, |
| 179 | [NL80211_ATTR_RADAR_BACKGROUND] = { .type = NLA_FLAG }, |
| 180 | + [NL80211_ATTR_START_DISABLED] = { .type = NLA_FLAG }, |
| 181 | [NL80211_ATTR_WIPHY_ANTENNA_GAIN] = { .type = NLA_U32 }, |
| 182 | }; |
| 183 | |
| 184 | @@ -5547,6 +5548,12 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) |
| 185 | |
| 186 | memset(¶ms, 0, sizeof(params)); |
| 187 | |
| 188 | + if (info->attrs[NL80211_ATTR_START_DISABLED]) { |
| 189 | + wdev->start_disabled = nla_get_flag(info->attrs[NL80211_ATTR_START_DISABLED]); |
| 190 | + err = 0; |
| 191 | + goto out; |
| 192 | + } |
| 193 | + |
| 194 | /* these are required for START_AP */ |
| 195 | if (!info->attrs[NL80211_ATTR_BEACON_INTERVAL] || |
| 196 | !info->attrs[NL80211_ATTR_DTIM_PERIOD] || |
| 197 | @@ -9393,6 +9400,7 @@ static int nl80211_start_radar_detection(struct sk_buff *skb, |
| 198 | wdev->cac_started = true; |
| 199 | wdev->cac_start_time = jiffies; |
| 200 | wdev->cac_time_ms = cac_time_ms; |
| 201 | + err = rdev_check_cac_skip(rdev, &wdev->chandef); |
| 202 | } |
| 203 | unlock: |
| 204 | wiphy_unlock(wiphy); |
| 205 | diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h |
developer | e126222 | 2022-10-25 12:20:54 +0800 | [diff] [blame] | 206 | index 26f4604..c38aea1 100644 |
developer | 29344f1 | 2022-10-17 12:01:44 +0800 | [diff] [blame] | 207 | --- a/net/wireless/rdev-ops.h |
| 208 | +++ b/net/wireless/rdev-ops.h |
developer | e126222 | 2022-10-25 12:20:54 +0800 | [diff] [blame] | 209 | @@ -1412,4 +1412,20 @@ rdev_skip_cac(struct cfg80211_registered_device *rdev, |
| 210 | return 0; |
developer | 29344f1 | 2022-10-17 12:01:44 +0800 | [diff] [blame] | 211 | } |
| 212 | |
| 213 | +static inline int |
| 214 | +rdev_check_cac_skip(struct cfg80211_registered_device *rdev, |
| 215 | + struct cfg80211_chan_def *chandef) |
| 216 | +{ |
| 217 | + struct wiphy *wiphy = &rdev->wiphy; |
| 218 | + |
| 219 | + if (!rdev->ops->check_cac_skip) |
| 220 | + return -EOPNOTSUPP; |
| 221 | + |
| 222 | + trace_rdev_check_cac_skip(wiphy, chandef); |
| 223 | + rdev->ops->check_cac_skip(wiphy, chandef); |
| 224 | + trace_rdev_return_void(wiphy); |
| 225 | + |
| 226 | + return 0; |
| 227 | +} |
| 228 | + |
| 229 | #endif /* __CFG80211_RDEV_OPS */ |
| 230 | diff --git a/net/wireless/trace.h b/net/wireless/trace.h |
developer | e126222 | 2022-10-25 12:20:54 +0800 | [diff] [blame] | 231 | index eadabfa..a7b0c82 100644 |
developer | 29344f1 | 2022-10-17 12:01:44 +0800 | [diff] [blame] | 232 | --- a/net/wireless/trace.h |
| 233 | +++ b/net/wireless/trace.h |
developer | e126222 | 2022-10-25 12:20:54 +0800 | [diff] [blame] | 234 | @@ -3677,6 +3677,21 @@ TRACE_EVENT(rdev_skip_cac, |
| 235 | TP_printk(WDEV_PR_FMT, WDEV_PR_ARG) |
developer | 29344f1 | 2022-10-17 12:01:44 +0800 | [diff] [blame] | 236 | ); |
| 237 | |
| 238 | +TRACE_EVENT(rdev_check_cac_skip, |
| 239 | + TP_PROTO(struct wiphy *wiphy, struct cfg80211_chan_def *chandef), |
| 240 | + |
| 241 | + TP_ARGS(wiphy, chandef), |
| 242 | + |
| 243 | + TP_STRUCT__entry(WIPHY_ENTRY |
| 244 | + CHAN_DEF_ENTRY), |
| 245 | + |
| 246 | + TP_fast_assign(WIPHY_ASSIGN; |
| 247 | + CHAN_DEF_ASSIGN(chandef)), |
| 248 | + |
| 249 | + TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT, |
| 250 | + WIPHY_PR_ARG, CHAN_DEF_PR_ARG) |
| 251 | +); |
| 252 | + |
| 253 | #endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */ |
| 254 | |
| 255 | #undef TRACE_INCLUDE_PATH |
| 256 | -- |
developer | 3d5faf2 | 2022-11-29 18:07:22 +0800 | [diff] [blame] | 257 | 2.36.1 |
developer | 29344f1 | 2022-10-17 12:01:44 +0800 | [diff] [blame] | 258 | |