1 From: Felix Fietkau <nbd@nbd.name>
2 Date: Tue, 4 Jun 2024 21:01:50 +0200
3 Subject: [PATCH] wifi: cfg80211: extend interface combination check for
6 Add a field in struct iface_combination_params to check per-radio
7 interface combinations instead of per-wiphy ones.
9 Signed-off-by: Felix Fietkau <nbd@nbd.name>
12 --- a/include/net/cfg80211.h
13 +++ b/include/net/cfg80211.h
14 @@ -1598,6 +1598,7 @@ struct cfg80211_color_change_settings {
16 * Used to pass interface combination parameters
18 + * @radio_idx: wiphy radio index or -1 for global
19 * @num_different_channels: the number of different channels we want
20 * to use for verification
21 * @radar_detect: a bitmap where each bit corresponds to a channel
22 @@ -1611,6 +1612,7 @@ struct cfg80211_color_change_settings {
25 struct iface_combination_params {
27 int num_different_channels;
29 int iftype_num[NUM_NL80211_IFTYPES];
30 @@ -4579,6 +4581,8 @@ struct mgmt_frame_regs {
32 * @set_hw_timestamp: Enable/disable HW timestamping of TM/FTM frames.
33 * @set_ttlm: set the TID to link mapping.
34 + * @get_radio_mask: get bitmask of radios in use.
35 + * (invoked with the wiphy mutex held)
38 int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
39 @@ -4940,6 +4944,7 @@ struct cfg80211_ops {
40 struct cfg80211_set_hw_timestamp *hwts);
41 int (*set_ttlm)(struct wiphy *wiphy, struct net_device *dev,
42 struct cfg80211_ttlm_params *params);
43 + u32 (*get_radio_mask)(struct wiphy *wiphy, struct net_device *dev);
47 --- a/net/mac80211/util.c
48 +++ b/net/mac80211/util.c
49 @@ -3930,6 +3930,7 @@ int ieee80211_check_combinations(struct
51 struct iface_combination_params params = {
52 .radar_detect = radar_detect,
56 lockdep_assert_wiphy(local->hw.wiphy);
57 @@ -4020,7 +4021,9 @@ int ieee80211_max_num_channels(struct ie
58 struct ieee80211_chanctx *ctx;
59 u32 max_num_different_channels = 1;
61 - struct iface_combination_params params = {0};
62 + struct iface_combination_params params = {
66 lockdep_assert_wiphy(local->hw.wiphy);
68 --- a/net/wireless/rdev-ops.h
69 +++ b/net/wireless/rdev-ops.h
70 @@ -1542,4 +1542,16 @@ rdev_set_ttlm(struct cfg80211_registered
76 +rdev_get_radio_mask(struct cfg80211_registered_device *rdev,
77 + struct net_device *dev)
79 + struct wiphy *wiphy = &rdev->wiphy;
81 + if (!rdev->ops->get_radio_mask)
84 + return rdev->ops->get_radio_mask(wiphy, dev);
86 #endif /* __CFG80211_RDEV_OPS */
87 --- a/net/wireless/util.c
88 +++ b/net/wireless/util.c
89 @@ -2305,13 +2305,16 @@ static int cfg80211_wdev_bi(struct wirel
91 static void cfg80211_calculate_bi_data(struct wiphy *wiphy, u32 new_beacon_int,
93 - bool *beacon_int_different)
94 + bool *beacon_int_different,
97 + struct cfg80211_registered_device *rdev;
98 struct wireless_dev *wdev;
101 *beacon_int_different = false;
103 + rdev = wiphy_to_rdev(wiphy);
104 list_for_each_entry(wdev, &wiphy->wdev_list, list) {
107 @@ -2319,6 +2322,11 @@ static void cfg80211_calculate_bi_data(s
108 if (wdev->valid_links)
111 + /* skip wdevs not active on the given wiphy radio */
112 + if (radio_idx >= 0 &&
113 + !(rdev_get_radio_mask(rdev, wdev->netdev) & BIT(radio_idx)))
116 wdev_bi = cfg80211_wdev_bi(wdev);
119 @@ -2366,14 +2374,19 @@ int cfg80211_iter_combinations(struct wi
123 + const struct wiphy_radio *radio = NULL;
124 + const struct ieee80211_iface_combination *c, *cs;
125 const struct ieee80211_regdomain *regdom;
126 enum nl80211_dfs_regions region = 0;
128 + int i, j, n, iftype;
129 int num_interfaces = 0;
130 u32 used_iftypes = 0;
132 bool beacon_int_different;
134 + if (params->radio_idx >= 0)
135 + radio = &wiphy->radio[params->radio_idx];
138 * This is a bit strange, since the iteration used to rely only on
139 * the data given by the driver, but here it now relies on context,
140 @@ -2385,7 +2398,8 @@ int cfg80211_iter_combinations(struct wi
141 * interfaces (while being brought up) and channel/radar data.
143 cfg80211_calculate_bi_data(wiphy, params->new_beacon_int,
144 - &beacon_int_gcd, &beacon_int_different);
145 + &beacon_int_gcd, &beacon_int_different,
146 + params->radio_idx);
148 if (params->radar_detect) {
150 @@ -2402,13 +2416,18 @@ int cfg80211_iter_combinations(struct wi
151 used_iftypes |= BIT(iftype);
154 - for (i = 0; i < wiphy->n_iface_combinations; i++) {
155 - const struct ieee80211_iface_combination *c;
157 + cs = radio->iface_combinations;
158 + n = radio->n_iface_combinations;
160 + cs = wiphy->iface_combinations;
161 + n = wiphy->n_iface_combinations;
163 + for (i = 0; i < n; i++) {
164 struct ieee80211_iface_limit *limits;
167 - c = &wiphy->iface_combinations[i];
170 if (num_interfaces > c->max_interfaces)
172 if (params->num_different_channels > c->num_different_channels)