ACS: Extend the 320 MHz support
There are bandwidth 320 MHz-1 and 320 MHz-2 channelization in EHT mode. When using ACS, user might prefer one of the channelization or both, but original ACS was unable to take such preference. Another problem is that the original ACS returns only the ideal channel but no 320 MHz channelization. The function acs_get_bw_center_chan() also could not correctly return the center frequency of bandwidth 320 MHz that is decided by ACS. For example, if ACS decide the ideal channel is channel 37 with channelization 320 MHz-2 (center frequency 6265 MHz), acs_get_bw_center_chan() returns 6105 MHz, which is 320 MHz-1. Extend the support for 320 MHz so that ACS can choose the best channel according to the user's preference. Also, after calling acs_find_ideal_chan_mode(), the best channel and bandwidth can be derived. The changes are: - bw_type ACS_BW320 is divided into ACS_BW320_1 and ACS_BW320_2 - in bandwidth 320 MHz, find the best channel and bandwidth according to user's perference (320 MHz-1, 320 Mhz-2 or both are OK) - before acs_find_ideal_chan_mode() returns, update bw320_offset in iface->conf so that the best channel's channelization is recorded. - get the best center frequency from bw320_offset Co-developed-by: Money Wang <money.wang@mediatek.com> Signed-off-by: Michael-CY Lee <michael-cy.lee@mediatek.com>
This commit is contained in:
parent
e6f2494c3a
commit
98f3bd26de
1 changed files with 74 additions and 15 deletions
89
src/ap/acs.c
89
src/ap/acs.c
|
@ -245,7 +245,8 @@ enum bw_type {
|
||||||
ACS_BW40,
|
ACS_BW40,
|
||||||
ACS_BW80,
|
ACS_BW80,
|
||||||
ACS_BW160,
|
ACS_BW160,
|
||||||
ACS_BW320,
|
ACS_BW320_1,
|
||||||
|
ACS_BW320_2,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct bw_item {
|
struct bw_item {
|
||||||
|
@ -287,16 +288,20 @@ static const struct bw_item bw_160[] = {
|
||||||
{ 6435, 6575, 111 }, { 6595, 6735, 143 },
|
{ 6435, 6575, 111 }, { 6595, 6735, 143 },
|
||||||
{ 6755, 6895, 175 }, { 6915, 7055, 207 }, { -1, -1, -1 }
|
{ 6755, 6895, 175 }, { 6915, 7055, 207 }, { -1, -1, -1 }
|
||||||
};
|
};
|
||||||
static const struct bw_item bw_320[] = {
|
static const struct bw_item bw_320_1[] = {
|
||||||
{ 5955, 6255, 31 }, { 6115, 6415, 63 }, { 6275, 6575, 95 },
|
{ 5955, 6255, 31 }, { 6275, 6575, 95 }, { 6595, 6895, 159 },
|
||||||
{ 6435, 6735, 127 }, { 6595, 6895, 159}, { 6755, 7055, 191 },
|
{ -1, -1, -1 }
|
||||||
|
};
|
||||||
|
static const struct bw_item bw_320_2[] = {
|
||||||
|
{ 6115, 6415, 63 }, { 6435, 6735, 127 }, { 6755, 7055, 191 },
|
||||||
{ -1, -1, -1 }
|
{ -1, -1, -1 }
|
||||||
};
|
};
|
||||||
static const struct bw_item *bw_desc[] = {
|
static const struct bw_item *bw_desc[] = {
|
||||||
[ACS_BW40] = bw_40,
|
[ACS_BW40] = bw_40,
|
||||||
[ACS_BW80] = bw_80,
|
[ACS_BW80] = bw_80,
|
||||||
[ACS_BW160] = bw_160,
|
[ACS_BW160] = bw_160,
|
||||||
[ACS_BW320] = bw_320,
|
[ACS_BW320_1] = bw_320_1,
|
||||||
|
[ACS_BW320_2] = bw_320_2,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -775,6 +780,42 @@ static void acs_update_puncturing_bitmap(struct hostapd_iface *iface,
|
||||||
#endif /* CONFIG_IEEE80211BE */
|
#endif /* CONFIG_IEEE80211BE */
|
||||||
|
|
||||||
|
|
||||||
|
static bool
|
||||||
|
acs_usable_bw320_chan(struct hostapd_iface *iface,
|
||||||
|
struct hostapd_channel_data *chan, int *bw320_offset)
|
||||||
|
{
|
||||||
|
const char *bw320_str[] = { "320 MHz", "320 MHz-1", "320 MHz-2" };
|
||||||
|
int conf_bw320_offset = hostapd_get_bw320_offset(iface->conf);
|
||||||
|
|
||||||
|
*bw320_offset = 0;
|
||||||
|
switch (conf_bw320_offset) {
|
||||||
|
case 1:
|
||||||
|
if (acs_usable_bw_chan(chan, ACS_BW320_1))
|
||||||
|
*bw320_offset = 1;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if (acs_usable_bw_chan(chan, ACS_BW320_2))
|
||||||
|
*bw320_offset = 2;
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
default:
|
||||||
|
conf_bw320_offset = 0;
|
||||||
|
if (acs_usable_bw_chan(chan, ACS_BW320_1))
|
||||||
|
*bw320_offset = 1;
|
||||||
|
else if (acs_usable_bw_chan(chan, ACS_BW320_2))
|
||||||
|
*bw320_offset = 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!*bw320_offset)
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"ACS: Channel %d: not allowed as primary channel for %s bandwidth",
|
||||||
|
chan->chan, bw320_str[conf_bw320_offset]);
|
||||||
|
|
||||||
|
return *bw320_offset != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
acs_find_ideal_chan_mode(struct hostapd_iface *iface,
|
acs_find_ideal_chan_mode(struct hostapd_iface *iface,
|
||||||
struct hostapd_hw_modes *mode,
|
struct hostapd_hw_modes *mode,
|
||||||
|
@ -786,6 +827,7 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
|
||||||
struct hostapd_channel_data *chan, *adj_chan = NULL, *best;
|
struct hostapd_channel_data *chan, *adj_chan = NULL, *best;
|
||||||
long double factor;
|
long double factor;
|
||||||
int i, j;
|
int i, j;
|
||||||
|
int bw320_offset = 0, ideal_bw320_offset = 0;
|
||||||
unsigned int k;
|
unsigned int k;
|
||||||
int secondary_channel = 1, freq_offset;
|
int secondary_channel = 1, freq_offset;
|
||||||
|
|
||||||
|
@ -849,7 +891,8 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode->mode == HOSTAPD_MODE_IEEE80211A &&
|
if (mode->mode == HOSTAPD_MODE_IEEE80211A &&
|
||||||
(iface->conf->ieee80211ac || iface->conf->ieee80211ax)) {
|
(iface->conf->ieee80211ac || iface->conf->ieee80211ax ||
|
||||||
|
iface->conf->ieee80211be)) {
|
||||||
if (hostapd_get_oper_chwidth(iface->conf) ==
|
if (hostapd_get_oper_chwidth(iface->conf) ==
|
||||||
CONF_OPER_CHWIDTH_80MHZ &&
|
CONF_OPER_CHWIDTH_80MHZ &&
|
||||||
!acs_usable_bw_chan(chan, ACS_BW80)) {
|
!acs_usable_bw_chan(chan, ACS_BW80)) {
|
||||||
|
@ -873,12 +916,8 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
|
||||||
iface->conf->ieee80211be) {
|
iface->conf->ieee80211be) {
|
||||||
if (hostapd_get_oper_chwidth(iface->conf) ==
|
if (hostapd_get_oper_chwidth(iface->conf) ==
|
||||||
CONF_OPER_CHWIDTH_320MHZ &&
|
CONF_OPER_CHWIDTH_320MHZ &&
|
||||||
!acs_usable_bw_chan(chan, ACS_BW320)) {
|
!acs_usable_bw320_chan(iface, chan, &bw320_offset))
|
||||||
wpa_printf(MSG_DEBUG,
|
|
||||||
"ACS: Channel %d: not allowed as primary channel for 320 MHz bandwidth",
|
|
||||||
chan->chan);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
factor = 0;
|
factor = 0;
|
||||||
|
@ -1012,6 +1051,7 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
|
||||||
|
|
||||||
*ideal_factor = factor;
|
*ideal_factor = factor;
|
||||||
*ideal_chan = chan;
|
*ideal_chan = chan;
|
||||||
|
ideal_bw320_offset = bw320_offset;
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211BE
|
#ifdef CONFIG_IEEE80211BE
|
||||||
if (iface->conf->ieee80211be)
|
if (iface->conf->ieee80211be)
|
||||||
|
@ -1022,9 +1062,13 @@ acs_find_ideal_chan_mode(struct hostapd_iface *iface,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This channel would at least be usable */
|
/* This channel would at least be usable */
|
||||||
if (!(*rand_chan))
|
if (!(*rand_chan)) {
|
||||||
*rand_chan = chan;
|
*rand_chan = chan;
|
||||||
|
ideal_bw320_offset = bw320_offset;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hostapd_set_and_check_bw320_offset(iface->conf, ideal_bw320_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1116,7 +1160,8 @@ static void acs_adjust_secondary(struct hostapd_iface *iface)
|
||||||
acs_find_mode(iface, iface->freq) != HOSTAPD_MODE_IEEE80211A)
|
acs_find_mode(iface, iface->freq) != HOSTAPD_MODE_IEEE80211A)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "ACS: Adjusting HT/VHT/HE secondary frequency");
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"ACS: Adjusting HT/VHT/HE/EHT secondary frequency");
|
||||||
|
|
||||||
for (i = 0; bw_desc[ACS_BW40][i].first != -1; i++) {
|
for (i = 0; bw_desc[ACS_BW40][i].first != -1; i++) {
|
||||||
if (iface->freq == bw_desc[ACS_BW40][i].first)
|
if (iface->freq == bw_desc[ACS_BW40][i].first)
|
||||||
|
@ -1131,7 +1176,7 @@ static void acs_adjust_center_freq(struct hostapd_iface *iface)
|
||||||
{
|
{
|
||||||
int center;
|
int center;
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "ACS: Adjusting VHT center frequency");
|
wpa_printf(MSG_DEBUG, "ACS: Adjusting center frequency");
|
||||||
|
|
||||||
switch (hostapd_get_oper_chwidth(iface->conf)) {
|
switch (hostapd_get_oper_chwidth(iface->conf)) {
|
||||||
case CONF_OPER_CHWIDTH_USE_HT:
|
case CONF_OPER_CHWIDTH_USE_HT:
|
||||||
|
@ -1151,7 +1196,21 @@ static void acs_adjust_center_freq(struct hostapd_iface *iface)
|
||||||
center = acs_get_bw_center_chan(iface->freq, ACS_BW160);
|
center = acs_get_bw_center_chan(iface->freq, ACS_BW160);
|
||||||
break;
|
break;
|
||||||
case CONF_OPER_CHWIDTH_320MHZ:
|
case CONF_OPER_CHWIDTH_320MHZ:
|
||||||
center = acs_get_bw_center_chan(iface->freq, ACS_BW320);
|
switch (hostapd_get_bw320_offset(iface->conf)) {
|
||||||
|
case 1:
|
||||||
|
center = acs_get_bw_center_chan(iface->freq,
|
||||||
|
ACS_BW320_1);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
center = acs_get_bw_center_chan(iface->freq,
|
||||||
|
ACS_BW320_2);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
wpa_printf(MSG_INFO,
|
||||||
|
"ACS: BW320 offset is not selected");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* TODO: How can this be calculated? Adjust
|
/* TODO: How can this be calculated? Adjust
|
||||||
|
|
Loading…
Reference in a new issue