EHT: Add 320 channel width support
Add initial changes to support 320 MHz channel width. Signed-off-by: Veerendranath Jakkam <quic_vjakkam@quicinc.com> Signed-off-by: Karthikeyan Periyasamy <quic_periyasa@quicinc.com>
This commit is contained in:
parent
bafe35df03
commit
085a3fc76e
16 changed files with 121 additions and 13 deletions
|
@ -2527,6 +2527,9 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
|
|||
case 160:
|
||||
bandwidth = CHAN_WIDTH_160;
|
||||
break;
|
||||
case 320:
|
||||
bandwidth = CHAN_WIDTH_320;
|
||||
break;
|
||||
default:
|
||||
bandwidth = CHAN_WIDTH_20;
|
||||
break;
|
||||
|
|
|
@ -1163,6 +1163,8 @@ hostapd_set_oper_chwidth(struct hostapd_config *conf,
|
|||
#ifdef CONFIG_IEEE80211BE
|
||||
if (conf->ieee80211be)
|
||||
conf->eht_oper_chwidth = oper_chwidth;
|
||||
if (oper_chwidth == CONF_OPER_CHWIDTH_320MHZ)
|
||||
oper_chwidth = CONF_OPER_CHWIDTH_160MHZ;
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
#ifdef CONFIG_IEEE80211AX
|
||||
if (conf->ieee80211ax)
|
||||
|
@ -1192,6 +1194,9 @@ hostapd_set_oper_centr_freq_seg0_idx(struct hostapd_config *conf,
|
|||
#ifdef CONFIG_IEEE80211BE
|
||||
if (conf->ieee80211be)
|
||||
conf->eht_oper_centr_freq_seg0_idx = oper_centr_freq_seg0_idx;
|
||||
if (center_idx_to_bw_6ghz(oper_centr_freq_seg0_idx) == 4)
|
||||
oper_centr_freq_seg0_idx +=
|
||||
conf->channel > oper_centr_freq_seg0_idx ? 16 : -16;
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
#ifdef CONFIG_IEEE80211AX
|
||||
if (conf->ieee80211ax)
|
||||
|
|
|
@ -986,6 +986,8 @@ int hostapd_drv_do_acs(struct hostapd_data *hapd)
|
|||
else if (oper_chwidth == CONF_OPER_CHWIDTH_160MHZ ||
|
||||
oper_chwidth == CONF_OPER_CHWIDTH_80P80MHZ)
|
||||
params.ch_width = 160;
|
||||
else if (oper_chwidth == CONF_OPER_CHWIDTH_320MHZ)
|
||||
params.ch_width = 320;
|
||||
}
|
||||
|
||||
if (hapd->iface->conf->op_class)
|
||||
|
|
|
@ -838,6 +838,9 @@ void hostapd_event_sta_opmode_changed(struct hostapd_data *hapd, const u8 *addr,
|
|||
case CHAN_WIDTH_160:
|
||||
txt = "160";
|
||||
break;
|
||||
case CHAN_WIDTH_320:
|
||||
txt = "320";
|
||||
break;
|
||||
default:
|
||||
txt = NULL;
|
||||
break;
|
||||
|
@ -899,6 +902,9 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
|
|||
case CHAN_WIDTH_160:
|
||||
chwidth = CONF_OPER_CHWIDTH_160MHZ;
|
||||
break;
|
||||
case CHAN_WIDTH_320:
|
||||
chwidth = CONF_OPER_CHWIDTH_320MHZ;
|
||||
break;
|
||||
case CHAN_WIDTH_20_NOHT:
|
||||
case CHAN_WIDTH_20:
|
||||
case CHAN_WIDTH_40:
|
||||
|
@ -1173,6 +1179,15 @@ void hostapd_acs_channel_selected(struct hostapd_data *hapd,
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IEEE80211BE
|
||||
if (hapd->iface->conf->ieee80211be && acs_res->ch_width == 320) {
|
||||
hostapd_set_oper_chwidth(hapd->iconf, CONF_OPER_CHWIDTH_320MHZ);
|
||||
hostapd_set_oper_centr_freq_seg0_idx(
|
||||
hapd->iconf, acs_res->vht_seg1_center_ch);
|
||||
hostapd_set_oper_centr_freq_seg1_idx(hapd->iconf, 0);
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211BE */
|
||||
|
||||
out:
|
||||
ret = hostapd_acs_completed(hapd->iface, err);
|
||||
if (ret) {
|
||||
|
|
|
@ -3516,6 +3516,9 @@ static int hostapd_change_config_freq(struct hostapd_data *hapd,
|
|||
case 160:
|
||||
hostapd_set_oper_chwidth(conf, CONF_OPER_CHWIDTH_160MHZ);
|
||||
break;
|
||||
case 320:
|
||||
hostapd_set_oper_chwidth(conf, CONF_OPER_CHWIDTH_320MHZ);
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
@ -3715,6 +3718,9 @@ hostapd_switch_channel_fallback(struct hostapd_iface *iface,
|
|||
case 160:
|
||||
bw = CONF_OPER_CHWIDTH_160MHZ;
|
||||
break;
|
||||
case 320:
|
||||
bw = CONF_OPER_CHWIDTH_320MHZ;
|
||||
break;
|
||||
default:
|
||||
wpa_printf(MSG_WARNING, "Unknown CSA bandwidth: %d",
|
||||
freq_params->bandwidth);
|
||||
|
|
|
@ -1087,13 +1087,14 @@ int hostapd_select_hw_mode(struct hostapd_iface *iface)
|
|||
|
||||
if ((iface->conf->hw_mode == HOSTAPD_MODE_IEEE80211G ||
|
||||
iface->conf->ieee80211n || iface->conf->ieee80211ac ||
|
||||
iface->conf->ieee80211ax) &&
|
||||
iface->conf->ieee80211ax || iface->conf->ieee80211be) &&
|
||||
iface->conf->channel == 14) {
|
||||
wpa_printf(MSG_INFO, "Disable OFDM/HT/VHT/HE on channel 14");
|
||||
wpa_printf(MSG_INFO, "Disable OFDM/HT/VHT/HE/EHT on channel 14");
|
||||
iface->conf->hw_mode = HOSTAPD_MODE_IEEE80211B;
|
||||
iface->conf->ieee80211n = 0;
|
||||
iface->conf->ieee80211ac = 0;
|
||||
iface->conf->ieee80211ax = 0;
|
||||
iface->conf->ieee80211be = 0;
|
||||
}
|
||||
|
||||
iface->current_mode = NULL;
|
||||
|
|
|
@ -197,9 +197,7 @@ u8 * hostapd_eid_eht_operation(struct hostapd_data *hapd, u8 *eid)
|
|||
seg0 = hostapd_get_oper_centr_freq_seg0_idx(conf);
|
||||
|
||||
switch (chwidth) {
|
||||
#if 0 /* FIX: Need to clean up CHANWIDTH_* use for protocol vs. internal
|
||||
* needs to be able to define this. */
|
||||
case CHANWIDTH_320MHZ:
|
||||
case CONF_OPER_CHWIDTH_320MHZ:
|
||||
oper->oper_info.control |= EHT_OPER_CHANNEL_WIDTH_320MHZ;
|
||||
seg1 = seg0;
|
||||
if (hapd->iconf->channel < seg0)
|
||||
|
@ -207,7 +205,6 @@ u8 * hostapd_eid_eht_operation(struct hostapd_data *hapd, u8 *eid)
|
|||
else
|
||||
seg0 += 16;
|
||||
break;
|
||||
#endif
|
||||
case CONF_OPER_CHWIDTH_160MHZ:
|
||||
oper->oper_info.control |= EHT_OPER_CHANNEL_WIDTH_160MHZ;
|
||||
seg1 = seg0;
|
||||
|
@ -286,10 +283,12 @@ static bool check_valid_eht_mcs(struct hostapd_data *hapd,
|
|||
EHT_PHYCAP_MCS_NSS_LEN_20MHZ_ONLY);
|
||||
|
||||
switch (hapd->iface->conf->eht_oper_chwidth) {
|
||||
/* TODO: CHANWIDTH_320MHZ */
|
||||
case CONF_OPER_CHWIDTH_320MHZ:
|
||||
mcs_count++;
|
||||
/* fall through */
|
||||
case CONF_OPER_CHWIDTH_80P80MHZ:
|
||||
case CONF_OPER_CHWIDTH_160MHZ:
|
||||
mcs_count = 2;
|
||||
mcs_count++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -219,7 +219,7 @@ u8 * hostapd_eid_he_operation(struct hostapd_data *hapd, u8 *eid)
|
|||
pos += 6; /* skip the fixed part */
|
||||
|
||||
if (is_6ghz_op_class(hapd->iconf->op_class)) {
|
||||
u8 seg0 = hostapd_get_oper_centr_freq_seg0_idx(hapd->iconf);
|
||||
u8 seg0 = hapd->iconf->he_oper_centr_freq_seg0_idx;
|
||||
u8 seg1 = hostapd_get_oper_centr_freq_seg1_idx(hapd->iconf);
|
||||
u8 control;
|
||||
|
||||
|
|
|
@ -429,6 +429,7 @@ enum chan_width {
|
|||
CHAN_WIDTH_4320,
|
||||
CHAN_WIDTH_6480,
|
||||
CHAN_WIDTH_8640,
|
||||
CHAN_WIDTH_320,
|
||||
CHAN_WIDTH_UNKNOWN
|
||||
};
|
||||
|
||||
|
@ -445,6 +446,7 @@ enum oper_chan_width {
|
|||
CONF_OPER_CHWIDTH_6480MHZ,
|
||||
CONF_OPER_CHWIDTH_8640MHZ,
|
||||
CONF_OPER_CHWIDTH_40MHZ_6GHZ,
|
||||
CONF_OPER_CHWIDTH_320MHZ,
|
||||
};
|
||||
|
||||
enum key_flag {
|
||||
|
|
|
@ -392,6 +392,8 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
|
|||
{
|
||||
if (!he_cap || !he_cap->he_supported)
|
||||
he_enabled = 0;
|
||||
if (!eht_cap || !eht_cap->eht_supported)
|
||||
eht_enabled = 0;
|
||||
os_memset(data, 0, sizeof(*data));
|
||||
data->mode = mode;
|
||||
data->freq = freq;
|
||||
|
@ -408,6 +410,8 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
|
|||
else if (oper_chwidth == CONF_OPER_CHWIDTH_160MHZ ||
|
||||
oper_chwidth == CONF_OPER_CHWIDTH_80P80MHZ)
|
||||
data->bandwidth = 160;
|
||||
else if (oper_chwidth == CONF_OPER_CHWIDTH_320MHZ)
|
||||
data->bandwidth = 320;
|
||||
else if (sec_channel_offset)
|
||||
data->bandwidth = 40;
|
||||
else
|
||||
|
@ -483,9 +487,8 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if 0 /* FIX: Figure out how to handle CHANWIDTH_320MHZ */
|
||||
if (data->eht_enabled) switch (oper_chwidth) {
|
||||
case CHANWIDTH_320MHZ:
|
||||
case CONF_OPER_CHWIDTH_320MHZ:
|
||||
if (!(eht_cap->phy_cap[EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_IDX] &
|
||||
EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_MASK)) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
|
@ -493,8 +496,9 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
|
|||
return -1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (data->he_enabled || data->eht_enabled) switch (oper_chwidth) {
|
||||
case CONF_OPER_CHWIDTH_USE_HT:
|
||||
|
@ -673,6 +677,41 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
|
|||
return -1;
|
||||
}
|
||||
break;
|
||||
case CONF_OPER_CHWIDTH_320MHZ:
|
||||
data->bandwidth = 320;
|
||||
if (!data->eht_enabled || !is_6ghz_freq(freq)) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"320 MHz: EHT not enabled or not a 6 GHz channel");
|
||||
return -1;
|
||||
}
|
||||
if (center_segment1) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"320 MHz: center segment 1 should not be set");
|
||||
return -1;
|
||||
}
|
||||
if (center_segment0 == channel + 30 ||
|
||||
center_segment0 == channel + 26 ||
|
||||
center_segment0 == channel + 22 ||
|
||||
center_segment0 == channel + 18 ||
|
||||
center_segment0 == channel + 14 ||
|
||||
center_segment0 == channel + 10 ||
|
||||
center_segment0 == channel + 6 ||
|
||||
center_segment0 == channel + 2 ||
|
||||
center_segment0 == channel - 2 ||
|
||||
center_segment0 == channel - 6 ||
|
||||
center_segment0 == channel - 10 ||
|
||||
center_segment0 == channel - 14 ||
|
||||
center_segment0 == channel - 18 ||
|
||||
center_segment0 == channel - 22 ||
|
||||
center_segment0 == channel - 26 ||
|
||||
center_segment0 == channel - 30)
|
||||
data->center_freq1 = 5000 + center_segment0 * 5;
|
||||
else {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"320 MHz: wrong center segment 0");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -785,6 +824,7 @@ u32 num_chan_to_bw(int num_chans)
|
|||
case 2:
|
||||
case 4:
|
||||
case 8:
|
||||
case 16:
|
||||
return num_chans * 20;
|
||||
default:
|
||||
return 20;
|
||||
|
@ -818,6 +858,9 @@ int chan_bw_allowed(const struct hostapd_channel_data *chan, u32 bw,
|
|||
case 160:
|
||||
bw_mask = HOSTAPD_CHAN_WIDTH_160;
|
||||
break;
|
||||
case 320:
|
||||
bw_mask = HOSTAPD_CHAN_WIDTH_320;
|
||||
break;
|
||||
default:
|
||||
bw_mask = 0;
|
||||
break;
|
||||
|
|
|
@ -1060,6 +1060,9 @@ ieee80211_freq_to_channel_ext(unsigned int freq, int sec_channel,
|
|||
case CONF_OPER_CHWIDTH_80P80MHZ:
|
||||
*op_class = 135;
|
||||
break;
|
||||
case CONF_OPER_CHWIDTH_320MHZ:
|
||||
*op_class = 137;
|
||||
break;
|
||||
default:
|
||||
if (sec_channel)
|
||||
*op_class = 132;
|
||||
|
@ -1157,6 +1160,9 @@ int ieee80211_chaninfo_to_channel(unsigned int freq, enum chan_width chanwidth,
|
|||
case CHAN_WIDTH_8640:
|
||||
cw = CONF_OPER_CHWIDTH_8640MHZ;
|
||||
break;
|
||||
case CHAN_WIDTH_320:
|
||||
cw = CONF_OPER_CHWIDTH_320MHZ;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ieee80211_freq_to_channel_ext(freq, sec_channel, cw, op_class,
|
||||
|
@ -1452,6 +1458,7 @@ static int ieee80211_chan_to_freq_global(u8 op_class, u8 chan)
|
|||
case 133: /* UHB channels, 80 MHz: 7, 23, 39.. */
|
||||
case 134: /* UHB channels, 160 MHz: 15, 47, 79.. */
|
||||
case 135: /* UHB channels, 80+80 MHz: 7, 23, 39.. */
|
||||
case 137: /* UHB channels, 320 MHz: 31, 63, 95, 127, 159, 191 */
|
||||
if (chan < 1 || chan > 233)
|
||||
return -1;
|
||||
return 5950 + chan * 5;
|
||||
|
@ -2265,6 +2272,9 @@ int center_idx_to_bw_6ghz(u8 idx)
|
|||
/* channels 15, 47, 79...*/
|
||||
if ((idx & 0x1f) == 0xf)
|
||||
return 3; /* 160 MHz */
|
||||
/* channels 31, 63, 95, 127, 159, 191 */
|
||||
if ((idx & 0x1f) == 0x1f && idx < 192)
|
||||
return 4; /* 320 MHz */
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
@ -2287,7 +2297,7 @@ bool is_6ghz_freq(int freq)
|
|||
|
||||
bool is_6ghz_op_class(u8 op_class)
|
||||
{
|
||||
return op_class >= 131 && op_class <= 136;
|
||||
return op_class >= 131 && op_class <= 137;
|
||||
}
|
||||
|
||||
|
||||
|
@ -2593,6 +2603,8 @@ int op_class_to_bandwidth(u8 op_class)
|
|||
return 160;
|
||||
case 136: /* UHB channels, 20 MHz: 2 */
|
||||
return 20;
|
||||
case 137: /* UHB channels, 320 MHz: 31, 63, 95, 127, 159, 191 */
|
||||
return 320;
|
||||
case 180: /* 60 GHz band, channels 1..8 */
|
||||
return 2160;
|
||||
case 181: /* 60 GHz band, EDMG CB2, channels 9..15 */
|
||||
|
@ -2655,6 +2667,8 @@ enum oper_chan_width op_class_to_ch_width(u8 op_class)
|
|||
return CONF_OPER_CHWIDTH_80P80MHZ;
|
||||
case 136: /* UHB channels, 20 MHz: 2 */
|
||||
return CONF_OPER_CHWIDTH_USE_HT;
|
||||
case 137: /* UHB channels, 320 MHz: 31, 63, 95, 127, 159, 191 */
|
||||
return CONF_OPER_CHWIDTH_320MHZ;
|
||||
case 180: /* 60 GHz band, channels 1..8 */
|
||||
return CONF_OPER_CHWIDTH_2160MHZ;
|
||||
case 181: /* 60 GHz band, EDMG CB2, channels 9..15 */
|
||||
|
|
|
@ -66,6 +66,7 @@ enum hostapd_chan_width_attr {
|
|||
HOSTAPD_CHAN_WIDTH_40M = BIT(3),
|
||||
HOSTAPD_CHAN_WIDTH_80 = BIT(4),
|
||||
HOSTAPD_CHAN_WIDTH_160 = BIT(5),
|
||||
HOSTAPD_CHAN_WIDTH_320 = BIT(6),
|
||||
};
|
||||
|
||||
/* Filter gratuitous ARP */
|
||||
|
|
|
@ -117,6 +117,8 @@ const char * channel_width_to_string(enum chan_width width)
|
|||
return "80+80 MHz";
|
||||
case CHAN_WIDTH_160:
|
||||
return "160 MHz";
|
||||
case CHAN_WIDTH_320:
|
||||
return "320 MHz";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
|
@ -136,6 +138,8 @@ int channel_width_to_int(enum chan_width width)
|
|||
case CHAN_WIDTH_80P80:
|
||||
case CHAN_WIDTH_160:
|
||||
return 160;
|
||||
case CHAN_WIDTH_320:
|
||||
return 320;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -215,6 +215,8 @@ enum chan_width convert2width(int width)
|
|||
return CHAN_WIDTH_80P80;
|
||||
case NL80211_CHAN_WIDTH_160:
|
||||
return CHAN_WIDTH_160;
|
||||
case NL80211_CHAN_WIDTH_320:
|
||||
return CHAN_WIDTH_320;
|
||||
}
|
||||
return CHAN_WIDTH_UNKNOWN;
|
||||
}
|
||||
|
@ -4941,6 +4943,9 @@ static int nl80211_put_freq_params(struct nl_msg *msg,
|
|||
case 160:
|
||||
cw = NL80211_CHAN_WIDTH_160;
|
||||
break;
|
||||
case 320:
|
||||
cw = NL80211_CHAN_WIDTH_320;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
|
@ -674,6 +674,9 @@ static int calculate_chan_offset(int width, int freq, int cf1, int cf2)
|
|||
case CHAN_WIDTH_80P80:
|
||||
freq1 = cf1 - 30;
|
||||
break;
|
||||
case CHAN_WIDTH_320:
|
||||
freq1 = cf1 - 150;
|
||||
break;
|
||||
case CHAN_WIDTH_UNKNOWN:
|
||||
case CHAN_WIDTH_2160:
|
||||
case CHAN_WIDTH_4320:
|
||||
|
@ -2791,6 +2794,9 @@ static void nl80211_sta_opmode_change_event(struct wpa_driver_nl80211_data *drv,
|
|||
case NL80211_CHAN_WIDTH_160:
|
||||
ed.sta_opmode.chan_width = CHAN_WIDTH_160;
|
||||
break;
|
||||
case NL80211_CHAN_WIDTH_320:
|
||||
ed.sta_opmode.chan_width = CHAN_WIDTH_320;
|
||||
break;
|
||||
default:
|
||||
ed.sta_opmode.chan_width = CHAN_WIDTH_UNKNOWN;
|
||||
break;
|
||||
|
|
|
@ -5989,6 +5989,8 @@ static int parse_freq(int chwidth, int freq2)
|
|||
return CONF_OPER_CHWIDTH_80MHZ;
|
||||
case 160:
|
||||
return CONF_OPER_CHWIDTH_160MHZ;
|
||||
case 320:
|
||||
return CONF_OPER_CHWIDTH_320MHZ;
|
||||
default:
|
||||
wpa_printf(MSG_DEBUG, "Unknown max oper bandwidth: %d",
|
||||
chwidth);
|
||||
|
|
Loading…
Reference in a new issue