Commit d2601e34 authored by Felix Fietkau's avatar Felix Fietkau Committed by Johannes Berg

wifi: mac80211_hwsim: add support for multi-radio wiphy

This registers one wiphy radio per supported band. Number of different
channels is set per radio.
Signed-off-by: default avatarFelix Fietkau <nbd@nbd.name>
Link: https://patch.msgid.link/3a16838bb7a7d1a072bd7c9d586d17f70fcd8a60.1720514221.git-series.nbd@nbd.nameSigned-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 27d4c034
...@@ -69,6 +69,10 @@ static bool mlo; ...@@ -69,6 +69,10 @@ static bool mlo;
module_param(mlo, bool, 0444); module_param(mlo, bool, 0444);
MODULE_PARM_DESC(mlo, "Support MLO"); MODULE_PARM_DESC(mlo, "Support MLO");
static bool multi_radio;
module_param(multi_radio, bool, 0444);
MODULE_PARM_DESC(mlo, "Support Multiple Radios per wiphy");
/** /**
* enum hwsim_regtest - the type of regulatory tests we offer * enum hwsim_regtest - the type of regulatory tests we offer
* *
...@@ -669,6 +673,10 @@ struct mac80211_hwsim_data { ...@@ -669,6 +673,10 @@ struct mac80211_hwsim_data {
struct ieee80211_iface_limit if_limits[3]; struct ieee80211_iface_limit if_limits[3];
int n_if_limits; int n_if_limits;
struct ieee80211_iface_combination if_combination_radio;
struct wiphy_radio_freq_range radio_range[NUM_NL80211_BANDS];
struct wiphy_radio radio[NUM_NL80211_BANDS];
u32 ciphers[ARRAY_SIZE(hwsim_ciphers)]; u32 ciphers[ARRAY_SIZE(hwsim_ciphers)];
struct mac_address addresses[2]; struct mac_address addresses[2];
...@@ -917,6 +925,7 @@ static const struct nla_policy hwsim_genl_policy[HWSIM_ATTR_MAX + 1] = { ...@@ -917,6 +925,7 @@ static const struct nla_policy hwsim_genl_policy[HWSIM_ATTR_MAX + 1] = {
[HWSIM_ATTR_MLO_SUPPORT] = { .type = NLA_FLAG }, [HWSIM_ATTR_MLO_SUPPORT] = { .type = NLA_FLAG },
[HWSIM_ATTR_PMSR_SUPPORT] = NLA_POLICY_NESTED(hwsim_pmsr_capa_policy), [HWSIM_ATTR_PMSR_SUPPORT] = NLA_POLICY_NESTED(hwsim_pmsr_capa_policy),
[HWSIM_ATTR_PMSR_RESULT] = NLA_POLICY_NESTED(hwsim_pmsr_peers_result_policy), [HWSIM_ATTR_PMSR_RESULT] = NLA_POLICY_NESTED(hwsim_pmsr_peers_result_policy),
[HWSIM_ATTR_MULTI_RADIO] = { .type = NLA_FLAG },
}; };
#if IS_REACHABLE(CONFIG_VIRTIO) #if IS_REACHABLE(CONFIG_VIRTIO)
...@@ -4018,6 +4027,7 @@ struct hwsim_new_radio_params { ...@@ -4018,6 +4027,7 @@ struct hwsim_new_radio_params {
bool reg_strict; bool reg_strict;
bool p2p_device; bool p2p_device;
bool use_chanctx; bool use_chanctx;
bool multi_radio;
bool destroy_on_close; bool destroy_on_close;
const char *hwname; const char *hwname;
bool no_vif; bool no_vif;
...@@ -4094,6 +4104,12 @@ static int append_radio_msg(struct sk_buff *skb, int id, ...@@ -4094,6 +4104,12 @@ static int append_radio_msg(struct sk_buff *skb, int id,
return ret; return ret;
} }
if (param->multi_radio) {
ret = nla_put_flag(skb, HWSIM_ATTR_MULTI_RADIO);
if (ret < 0)
return ret;
}
if (param->hwname) { if (param->hwname) {
ret = nla_put(skb, HWSIM_ATTR_RADIO_NAME, ret = nla_put(skb, HWSIM_ATTR_RADIO_NAME,
strlen(param->hwname), param->hwname); strlen(param->hwname), param->hwname);
...@@ -5114,6 +5130,7 @@ static int mac80211_hwsim_new_radio(struct genl_info *info, ...@@ -5114,6 +5130,7 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
struct net *net; struct net *net;
int idx, i; int idx, i;
int n_limits = 0; int n_limits = 0;
int n_bands = 0;
if (WARN_ON(param->channels > 1 && !param->use_chanctx)) if (WARN_ON(param->channels > 1 && !param->use_chanctx))
return -EINVAL; return -EINVAL;
...@@ -5217,22 +5234,22 @@ static int mac80211_hwsim_new_radio(struct genl_info *info, ...@@ -5217,22 +5234,22 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
n_limits++; n_limits++;
} }
data->if_combination.radar_detect_widths =
BIT(NL80211_CHAN_WIDTH_5) |
BIT(NL80211_CHAN_WIDTH_10) |
BIT(NL80211_CHAN_WIDTH_20_NOHT) |
BIT(NL80211_CHAN_WIDTH_20) |
BIT(NL80211_CHAN_WIDTH_40) |
BIT(NL80211_CHAN_WIDTH_80) |
BIT(NL80211_CHAN_WIDTH_160);
if (data->use_chanctx) { if (data->use_chanctx) {
hw->wiphy->max_scan_ssids = 255; hw->wiphy->max_scan_ssids = 255;
hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN; hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
hw->wiphy->max_remain_on_channel_duration = 1000; hw->wiphy->max_remain_on_channel_duration = 1000;
data->if_combination.radar_detect_widths = 0;
data->if_combination.num_different_channels = data->channels; data->if_combination.num_different_channels = data->channels;
} else { } else {
data->if_combination.num_different_channels = 1; data->if_combination.num_different_channels = 1;
data->if_combination.radar_detect_widths =
BIT(NL80211_CHAN_WIDTH_5) |
BIT(NL80211_CHAN_WIDTH_10) |
BIT(NL80211_CHAN_WIDTH_20_NOHT) |
BIT(NL80211_CHAN_WIDTH_20) |
BIT(NL80211_CHAN_WIDTH_40) |
BIT(NL80211_CHAN_WIDTH_80) |
BIT(NL80211_CHAN_WIDTH_160);
} }
if (!n_limits) { if (!n_limits) {
...@@ -5350,6 +5367,9 @@ static int mac80211_hwsim_new_radio(struct genl_info *info, ...@@ -5350,6 +5367,9 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
for (band = NL80211_BAND_2GHZ; band < NUM_NL80211_BANDS; band++) { for (band = NL80211_BAND_2GHZ; band < NUM_NL80211_BANDS; band++) {
struct ieee80211_supported_band *sband = &data->bands[band]; struct ieee80211_supported_band *sband = &data->bands[band];
struct wiphy_radio_freq_range *radio_range;
const struct ieee80211_channel *c;
struct wiphy_radio *radio;
sband->band = band; sband->band = band;
...@@ -5423,8 +5443,36 @@ static int mac80211_hwsim_new_radio(struct genl_info *info, ...@@ -5423,8 +5443,36 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
mac80211_hwsim_sband_capab(sband); mac80211_hwsim_sband_capab(sband);
hw->wiphy->bands[band] = sband; hw->wiphy->bands[band] = sband;
if (!param->multi_radio)
continue;
c = sband->channels;
radio_range = &data->radio_range[n_bands];
radio_range->start_freq = ieee80211_channel_to_khz(c) - 10000;
c += sband->n_channels - 1;
radio_range->end_freq = ieee80211_channel_to_khz(c) + 10000;
radio = &data->radio[n_bands++];
radio->freq_range = radio_range;
radio->n_freq_range = 1;
radio->iface_combinations = &data->if_combination_radio;
radio->n_iface_combinations = 1;
} }
if (param->multi_radio) {
hw->wiphy->radio = data->radio;
hw->wiphy->n_radio = n_bands;
memcpy(&data->if_combination_radio, &data->if_combination,
sizeof(data->if_combination));
data->if_combination.num_different_channels *= n_bands;
}
if (data->use_chanctx)
data->if_combination.radar_detect_widths = 0;
/* By default all radios belong to the first group */ /* By default all radios belong to the first group */
data->group = 1; data->group = 1;
mutex_init(&data->mutex); mutex_init(&data->mutex);
...@@ -6042,6 +6090,9 @@ static int hwsim_new_radio_nl(struct sk_buff *msg, struct genl_info *info) ...@@ -6042,6 +6090,9 @@ static int hwsim_new_radio_nl(struct sk_buff *msg, struct genl_info *info)
else else
param.use_chanctx = (param.channels > 1); param.use_chanctx = (param.channels > 1);
if (info->attrs[HWSIM_ATTR_MULTI_RADIO])
param.multi_radio = true;
if (info->attrs[HWSIM_ATTR_REG_HINT_ALPHA2]) if (info->attrs[HWSIM_ATTR_REG_HINT_ALPHA2])
param.reg_alpha2 = param.reg_alpha2 =
nla_data(info->attrs[HWSIM_ATTR_REG_HINT_ALPHA2]); nla_data(info->attrs[HWSIM_ATTR_REG_HINT_ALPHA2]);
...@@ -6122,7 +6173,7 @@ static int hwsim_new_radio_nl(struct sk_buff *msg, struct genl_info *info) ...@@ -6122,7 +6173,7 @@ static int hwsim_new_radio_nl(struct sk_buff *msg, struct genl_info *info)
param.mlo = info->attrs[HWSIM_ATTR_MLO_SUPPORT]; param.mlo = info->attrs[HWSIM_ATTR_MLO_SUPPORT];
if (param.mlo) if (param.mlo || param.multi_radio)
param.use_chanctx = true; param.use_chanctx = true;
if (info->attrs[HWSIM_ATTR_RADIO_NAME]) { if (info->attrs[HWSIM_ATTR_RADIO_NAME]) {
...@@ -6815,7 +6866,8 @@ static int __init init_mac80211_hwsim(void) ...@@ -6815,7 +6866,8 @@ static int __init init_mac80211_hwsim(void)
param.p2p_device = support_p2p_device; param.p2p_device = support_p2p_device;
param.mlo = mlo; param.mlo = mlo;
param.use_chanctx = channels > 1 || mlo; param.multi_radio = multi_radio;
param.use_chanctx = channels > 1 || mlo || multi_radio;
param.iftypes = HWSIM_IFTYPE_SUPPORT_MASK; param.iftypes = HWSIM_IFTYPE_SUPPORT_MASK;
if (param.p2p_device) if (param.p2p_device)
param.iftypes |= BIT(NL80211_IFTYPE_P2P_DEVICE); param.iftypes |= BIT(NL80211_IFTYPE_P2P_DEVICE);
......
...@@ -157,6 +157,9 @@ enum hwsim_commands { ...@@ -157,6 +157,9 @@ enum hwsim_commands {
* to provide details about peer measurement request (nl80211_peer_measurement_attrs) * to provide details about peer measurement request (nl80211_peer_measurement_attrs)
* @HWSIM_ATTR_PMSR_RESULT: nested attributed used with %HWSIM_CMD_REPORT_PMSR * @HWSIM_ATTR_PMSR_RESULT: nested attributed used with %HWSIM_CMD_REPORT_PMSR
* to provide peer measurement result (nl80211_peer_measurement_attrs) * to provide peer measurement result (nl80211_peer_measurement_attrs)
* @HWSIM_ATTR_MULTI_RADIO: Register multiple wiphy radios (flag).
* Adds one radio for each band. Number of supported channels will be set for
* each radio instead of for the wiphy.
* @__HWSIM_ATTR_MAX: enum limit * @__HWSIM_ATTR_MAX: enum limit
*/ */
enum hwsim_attrs { enum hwsim_attrs {
...@@ -189,6 +192,7 @@ enum hwsim_attrs { ...@@ -189,6 +192,7 @@ enum hwsim_attrs {
HWSIM_ATTR_PMSR_SUPPORT, HWSIM_ATTR_PMSR_SUPPORT,
HWSIM_ATTR_PMSR_REQUEST, HWSIM_ATTR_PMSR_REQUEST,
HWSIM_ATTR_PMSR_RESULT, HWSIM_ATTR_PMSR_RESULT,
HWSIM_ATTR_MULTI_RADIO,
__HWSIM_ATTR_MAX, __HWSIM_ATTR_MAX,
}; };
#define HWSIM_ATTR_MAX (__HWSIM_ATTR_MAX - 1) #define HWSIM_ATTR_MAX (__HWSIM_ATTR_MAX - 1)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment