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>
case 160:
bandwidth = CHAN_WIDTH_160;
break;
+ case 320:
+ bandwidth = CHAN_WIDTH_320;
+ break;
default:
bandwidth = CHAN_WIDTH_20;
break;
#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)
#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)
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)
case CHAN_WIDTH_160:
txt = "160";
break;
+ case CHAN_WIDTH_320:
+ txt = "320";
+ break;
default:
txt = NULL;
break;
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:
}
}
+#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) {
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;
}
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);
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;
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)
else
seg0 += 16;
break;
-#endif
case CONF_OPER_CHWIDTH_160MHZ:
oper->oper_info.control |= EHT_OPER_CHANNEL_WIDTH_160MHZ;
seg1 = seg0;
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;
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;
CHAN_WIDTH_4320,
CHAN_WIDTH_6480,
CHAN_WIDTH_8640,
+ CHAN_WIDTH_320,
CHAN_WIDTH_UNKNOWN
};
CONF_OPER_CHWIDTH_6480MHZ,
CONF_OPER_CHWIDTH_8640MHZ,
CONF_OPER_CHWIDTH_40MHZ_6GHZ,
+ CONF_OPER_CHWIDTH_320MHZ,
};
enum key_flag {
{
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;
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
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,
return -1;
}
break;
+ default:
+ break;
}
-#endif
if (data->he_enabled || data->eht_enabled) switch (oper_chwidth) {
case CONF_OPER_CHWIDTH_USE_HT:
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;
}
case 2:
case 4:
case 8:
+ case 16:
return num_chans * 20;
default:
return 20;
case 160:
bw_mask = HOSTAPD_CHAN_WIDTH_160;
break;
+ case 320:
+ bw_mask = HOSTAPD_CHAN_WIDTH_320;
+ break;
default:
bw_mask = 0;
break;
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;
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,
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;
/* 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;
}
bool is_6ghz_op_class(u8 op_class)
{
- return op_class >= 131 && op_class <= 136;
+ return op_class >= 131 && op_class <= 137;
}
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 */
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 */
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 */
return "80+80 MHz";
case CHAN_WIDTH_160:
return "160 MHz";
+ case CHAN_WIDTH_320:
+ return "320 MHz";
default:
return "unknown";
}
case CHAN_WIDTH_80P80:
case CHAN_WIDTH_160:
return 160;
+ case CHAN_WIDTH_320:
+ return 320;
default:
return 0;
}
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;
}
case 160:
cw = NL80211_CHAN_WIDTH_160;
break;
+ case 320:
+ cw = NL80211_CHAN_WIDTH_320;
+ break;
default:
return -EINVAL;
}
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:
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;
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);