wlan-ap-Telecominfraproject/feeds/ipq95xx/hostapd/patches/q02-051-hostapd-add-awgn-support-for-320MHz-bw-in-6GHz-band.patch
John Crispin b9b03a6e38 ipq95xx: add Qualcomm wifi-7 support
Signed-off-by: John Crispin <john@phrozen.org>
2023-04-10 14:25:48 +02:00

264 lines
8.2 KiB
Diff

From 856937cfab895f6a20e1fd9d919ad5710077745c Mon Sep 17 00:00:00 2001
From: Hari Chandrakanthan <quic_haric@quicinc.com>
Date: Wed, 28 Sep 2022 17:48:40 +0530
Subject: [PATCH] hostapd : add awgn support for 320MHz bw in 6GHz band
Add support for awgn handling of 320MHz bw in 6GHz band.
Signed-off-by: Hari Chandrakanthan <quic_haric@quicinc.com>
---
src/ap/interference.c | 147 ++++++++++++++++++++++++++++++++++----------------
1 file changed, 100 insertions(+), 47 deletions(-)
diff --git a/src/ap/interference.c b/src/ap/interference.c
index c51a4bf..4148489 100644
--- a/src/ap/interference.c
+++ b/src/ap/interference.c
@@ -62,6 +62,7 @@ static int intf_awgn_chan_range_available(struct hostapd_hw_modes *mode,
int allowed_80_6g[] = {1, 17, 33, 49, 65, 81, 97, 113, 129, 145, 161, 177,
193, 209};
int allowed_160_6g[] = {1, 33, 65, 97, 129, 161, 193};
+ int allowed_320_6g[] = {1, 65, 129, 33, 97, 161};
int chan_idx_match = 0;
int i;
@@ -97,6 +98,13 @@ static int intf_awgn_chan_range_available(struct hostapd_hw_modes *mode,
break;
}
}
+ } else if (num_chans == 16) { /* 320Mhz channel */
+ for (i = 0; i < ARRAY_SIZE(allowed_320_6g); i++) {
+ if (first_chan->chan == allowed_320_6g[i]) {
+ chan_idx_match = 1;
+ break;
+ }
+ }
}
if (chan_idx_match == 1)
@@ -114,6 +122,42 @@ static int is_in_chanlist(struct hostapd_iface *iface,
return freq_range_list_includes(&iface->conf->acs_ch_list, chan->chan);
}
+#define BASE_6G_FREQ 5950
+
+int get_centre_freq_6g(int chan_idx, int chan_width, int *centre_freq)
+{
+ if (!centre_freq)
+ return -1;
+
+ *centre_freq = 0;
+
+ switch (chan_width) {
+ case CHAN_WIDTH_40:
+ if (chan_idx >= 1 && chan_idx <= 229)
+ *centre_freq = ((chan_idx / 8) * 8 + 3) * 5 + BASE_6G_FREQ;
+ break;
+ case CHAN_WIDTH_80:
+ if (chan_idx >= 1 && chan_idx <= 221)
+ *centre_freq = ((chan_idx / 16) * 16 + 7) * 5 + BASE_6G_FREQ;
+ break;
+ case CHAN_WIDTH_160:
+ if (chan_idx >= 1 && chan_idx <= 221)
+ *centre_freq = ((chan_idx / 32) * 32 + 15) * 5 + BASE_6G_FREQ;
+ break;
+ case CHAN_WIDTH_320:
+ if (chan_idx >= 1 && chan_idx <= 221)
+ *centre_freq = ((chan_idx /64) * 64 + 31) * 5 + BASE_6G_FREQ;
+ default:
+ break;
+ }
+
+ if (*centre_freq == 0)
+ return -1;
+
+ return 0;
+}
+
+
/*
*intf_awgn_find_channel - find the channel that can operate with bandwidth chan_width.
If idx doesn't match with index of any of the existing channel, then the api
@@ -123,11 +167,13 @@ static int is_in_chanlist(struct hostapd_iface *iface,
*/
static int intf_awgn_find_channel(struct hostapd_iface *iface,
struct hostapd_channel_data **ret_chan,
- int idx, int chan_width)
+ int idx, int chan_width, int cs1)
{
struct hostapd_hw_modes *mode = iface->current_mode;
struct hostapd_channel_data *chan;
int i, channel_idx = 0, n_chans;
+ int temp_centre_freq;
+ int ret;
switch (chan_width) {
case CHAN_WIDTH_20_NOHT:
@@ -144,6 +190,9 @@ static int intf_awgn_find_channel(struct hostapd_iface *iface,
case CHAN_WIDTH_160:
n_chans = 8;
break;
+ case CHAN_WIDTH_320:
+ n_chans = 16;
+ break;
default:
n_chans = 1;
break;
@@ -167,6 +216,24 @@ static int intf_awgn_find_channel(struct hostapd_iface *iface,
continue;
}
+ if (chan_width == CHAN_WIDTH_320) {
+ ret = get_centre_freq_6g(chan->chan, CHAN_WIDTH_320,
+ &temp_centre_freq);
+ if (ret) {
+ wpa_printf(MSG_ERROR,
+ "AWGN : couldn't find centre freq for chan : %d"
+ " chan_width : %d", chan->chan, CHAN_WIDTH_320);
+ return 0;
+ }
+
+ if (abs(temp_centre_freq - cs1) < 320) {
+ wpa_printf(MSG_DEBUG,
+ "AWGN: channel %d is a overlapping channel so skipping",
+ chan->freq);
+ continue;
+ }
+ }
+
if (ret_chan && idx == channel_idx) {
wpa_printf(MSG_DEBUG, "AWGN: Selected channel %d (%d)",
chan->freq, chan->chan);
@@ -182,50 +249,27 @@ static int intf_awgn_find_channel(struct hostapd_iface *iface,
}
enum chan_seg {
- SEG_PRI20 = 0x1,
- SEG_SEC20 = 0x2,
- SEG_SEC40_LOWER = 0x4,
- SEG_SEC40_UPPER = 0x8,
- SEG_SEC40 = 0xC,
- SEG_SEC80_LOWER = 0x10,
- SEG_SEC80_LOWER_UPPER = 0x20,
- SEG_SEC80_UPPER_LOWER = 0x40,
- SEG_SEC80_UPPER = 0x80,
- SEG_SEC80 = 0xF0,
+ SEG_PRI20 = 0x1,
+ SEG_SEC20 = 0x2,
+ SEG_SEC40_LOW = 0x4,
+ SEG_SEC40_UP = 0x8,
+ SEG_SEC40 = 0xC,
+ SEG_SEC80_LOW = 0x10,
+ SEG_SEC80_LOW_UP = 0x20,
+ SEG_SEC80_UP_LOW = 0x40,
+ SEG_SEC80_UP = 0x80,
+ SEG_SEC80 = 0xF0,
+ SEG_SEC160_LOW = 0x0100,
+ SEG_SEC160_LOW_UP = 0x0200,
+ SEG_SEC160_LOW_UP_UP = 0x0400,
+ SEG_SEC160_LOW_UP_UP_UP = 0x0800,
+ SEG_SEC160_UP_LOW_LOW_LOW = 0x1000,
+ SEG_SEC160_UP_LOW_LOW = 0x2000,
+ SEG_SEC160_UP_LOW = 0x4000,
+ SEG_SEC160_UP = 0x8000,
+ SEG_SEC160 = 0xFF00,
};
-#define BASE_6G_FREQ 5950
-
-int get_centre_freq_6g(int chan_idx, int chan_width, int *centre_freq)
-{
- if (!centre_freq)
- return -1;
-
- *centre_freq = 0;
-
- switch (chan_width) {
- case CHAN_WIDTH_40:
- if (chan_idx >= 1 && chan_idx <= 229)
- *centre_freq = ((chan_idx / 8) * 8 + 3) * 5 + BASE_6G_FREQ;
- break;
- case CHAN_WIDTH_80:
- if (chan_idx >= 1 && chan_idx <= 221)
- *centre_freq = ((chan_idx / 16) * 16 + 7) * 5 + BASE_6G_FREQ;
- break;
- case CHAN_WIDTH_160:
- if (chan_idx >= 1 && chan_idx <= 221)
- *centre_freq = ((chan_idx / 32) * 32 + 15) * 5 + BASE_6G_FREQ;
- break;
- default:
- break;
- }
-
- if (*centre_freq == 0)
- return -1;
-
- return 0;
-}
-
/*
* hostapd_intf_awgn_detected - awgn interference is detected in the operating channel.
* The interference channel information is available as a
@@ -269,7 +313,7 @@ int hostapd_intf_awgn_detected(struct hostapd_iface *iface, int freq, int chan_w
if (channel_switch) {
/* Find a random channel to be switched */
num_available_chandefs = intf_awgn_find_channel(iface, NULL, 0,
- chan_width);
+ chan_width, cf1);
if (num_available_chandefs == 0) {
wpa_printf(MSG_ERROR, "AWGN: no available_chandefs");
return 0;
@@ -281,7 +325,7 @@ int hostapd_intf_awgn_detected(struct hostapd_iface *iface, int freq, int chan_w
}
chan_idx = _rand % num_available_chandefs;
- intf_awgn_find_channel(iface, &chan_data, chan_idx, chan_width);
+ intf_awgn_find_channel(iface, &chan_data, chan_idx, chan_width, cf1);
if (!chan_data) {
wpa_printf(MSG_ERROR, "AWGN: no random channel found, chan idx : %d",
@@ -295,7 +339,7 @@ int hostapd_intf_awgn_detected(struct hostapd_iface *iface, int freq, int chan_w
*/
chan_data = NULL;
chan_idx = (chan_idx + 1) % num_available_chandefs;
- intf_awgn_find_channel(iface, &chan_data, chan_idx, chan_width);
+ intf_awgn_find_channel(iface, &chan_data, chan_idx, chan_width, cf1);
if (!chan_data) {
wpa_printf(MSG_ERROR,
"AWGN: random channel not found, chan idx : %d",
@@ -319,7 +363,12 @@ int hostapd_intf_awgn_detected(struct hostapd_iface *iface, int freq, int chan_w
return 0;
}
- if ((chan_width > CHAN_WIDTH_80) &&
+ if ((chan_width > CHAN_WIDTH_160) &&
+ !(chan_bw_interference_bitmap & SEG_SEC80) &&
+ !(chan_bw_interference_bitmap & SEG_SEC40) &&
+ !(chan_bw_interference_bitmap & SEG_SEC20))
+ new_chan_width = CHAN_WIDTH_160;
+ else if ((chan_width > CHAN_WIDTH_80) &&
!(chan_bw_interference_bitmap & SEG_SEC40) &&
!(chan_bw_interference_bitmap & SEG_SEC20))
new_chan_width = CHAN_WIDTH_80;
@@ -358,6 +407,9 @@ int hostapd_intf_awgn_detected(struct hostapd_iface *iface, int freq, int chan_w
case CHAN_WIDTH_160:
settings.freq_params.bandwidth = 160;
break;
+ case CHAN_WIDTH_320:
+ settings.freq_params.bandwidth = 320;
+ break;
default:
settings.freq_params.bandwidth = 20;
break;
@@ -367,6 +419,7 @@ int hostapd_intf_awgn_detected(struct hostapd_iface *iface, int freq, int chan_w
settings.freq_params.ht_enabled = iface->conf->ieee80211n;
settings.freq_params.vht_enabled = iface->conf->ieee80211ac;
settings.freq_params.he_enabled = iface->conf->ieee80211ax;
+ settings.freq_params.eht_enabled= iface->conf->ieee80211be;
for (i = 0; i < iface->num_bss; i++) {
/* Save CHAN_SWITCH VHT and HE config */
--
2.7.4