blob: 5a632795d00700b5fbefee8daf8fb67b1d16d438 [file] [log] [blame]
developere35b8e42023-10-16 11:04:00 +08001From 804f9b03e7f143d3a80741cb67721810e27ed2d8 Mon Sep 17 00:00:00 2001
developerdfb50982023-09-11 13:34:36 +08002From: Michael-CY Lee <michael-cy.lee@mediatek.com>
developere35b8e42023-10-16 11:04:00 +08003Date: Mon, 11 Sep 2023 10:16:35 +0800
developerdfb50982023-09-11 13:34:36 +08004Subject: [PATCH] hostapd: mtk: synchronize bandwidth in AP/STA support
5
6Signed-off-by: Michael Lee <michael-cy.lee@mediatek.com>
7---
developere35b8e42023-10-16 11:04:00 +08008 src/ap/ucode.c | 41 +++++++++++++++++++--
9 src/utils/ucode.c | 12 +++++--
10 wpa_supplicant/ucode.c | 82 ++++++++++++++++++++++++++++++++++--------
11 3 files changed, 117 insertions(+), 18 deletions(-)
developerdfb50982023-09-11 13:34:36 +080012
developere35b8e42023-10-16 11:04:00 +080013diff --git a/src/ap/ucode.c b/src/ap/ucode.c
14index af97091..79d568f 100644
15--- a/src/ap/ucode.c
16+++ b/src/ap/ucode.c
17@@ -489,6 +489,9 @@ uc_hostapd_iface_stop(uc_vm_t *vm, size_t nargs)
18 struct hostapd_iface *iface = uc_fn_thisval("hostapd.iface");
19 int i;
20
21+ wpa_printf(MSG_INFO, "ucode: mtk: stop iface for %s in state %s\n",
22+ iface->phy, hostapd_state_text(iface->state));
23+
24 if (!iface)
25 return NULL;
26
27@@ -515,6 +518,9 @@ uc_hostapd_iface_start(uc_vm_t *vm, size_t nargs)
28 uint64_t intval;
29 int i;
30
31+ wpa_printf(MSG_INFO, "ucode: mtk: start iface for %s in state %s\n",
32+ iface->phy, hostapd_state_text(iface->state));
33+
34 if (!iface)
35 return NULL;
36
37@@ -537,7 +543,13 @@ uc_hostapd_iface_start(uc_vm_t *vm, size_t nargs)
38 UPDATE_VAL(op_class, "op_class");
39 UPDATE_VAL(hw_mode, "hw_mode");
40 UPDATE_VAL(channel, "channel");
41- UPDATE_VAL(secondary_channel, "sec_channel");
42+
43+ intval = ucv_int64_get(ucv_object_get(info, "sec_channel", NULL));
44+ if (!errno) {
45+ conf->secondary_channel = intval;
46+ changed = true;
47+ }
48+
49 if (!changed &&
50 (iface->bss[0]->beacon_set_done ||
51 iface->state == HAPD_IFACE_DFS))
52@@ -583,6 +595,18 @@ out:
53 return ucv_boolean_new(true);
54 }
55
56+ wpa_printf(MSG_INFO, "ucode: mtk: updated channel information:\n");
57+ wpa_printf(MSG_INFO, " * channel: %d\n", conf->channel);
58+ wpa_printf(MSG_INFO, " * op_class: %d\n", conf->op_class);
59+ wpa_printf(MSG_INFO, " * secondary channel: %d\n",
60+ conf->secondary_channel);
61+ wpa_printf(MSG_INFO, " * seg0: %d\n",
62+ hostapd_get_oper_centr_freq_seg0_idx(conf));
63+ wpa_printf(MSG_INFO, " * seg1: %d\n",
64+ hostapd_get_oper_centr_freq_seg0_idx(conf));
65+ wpa_printf(MSG_INFO, " * oper_chwidth: %d\n",
66+ hostapd_get_oper_chwidth(conf));
67+
68 for (i = 0; i < iface->num_bss; i++) {
69 struct hostapd_data *hapd = iface->bss[i];
70 int ret;
71@@ -617,6 +641,7 @@ uc_hostapd_iface_switch_channel(uc_vm_t *vm, size_t nargs)
72 uint64_t intval;
73 int i, ret = 0;
74
75+ wpa_printf(MSG_INFO, "ucode: mtk: channel switch for %s\n", iface->phy);
76 if (!iface || ucv_type(info) != UC_OBJECT)
77 return NULL;
78
79@@ -636,7 +661,8 @@ uc_hostapd_iface_switch_channel(uc_vm_t *vm, size_t nargs)
80 if (errno)
81 intval = hostapd_get_oper_chwidth(conf);
82 if (intval)
83- csa.freq_params.bandwidth = 40 << intval;
84+ csa.freq_params.bandwidth = 40 <<
85+ (intval == CONF_OPER_CHWIDTH_320MHZ ? 3 : intval);
86 else
87 csa.freq_params.bandwidth = csa.freq_params.sec_channel_offset ? 40 : 20;
88
89@@ -647,6 +673,17 @@ uc_hostapd_iface_switch_channel(uc_vm_t *vm, size_t nargs)
90 if ((intval = ucv_int64_get(ucv_object_get(info, "center_freq2", NULL))) && !errno)
91 csa.freq_params.center_freq2 = intval;
92
93+ wpa_printf(MSG_INFO, "ucode: mtk: switch channel information:\n");
94+ wpa_printf(MSG_INFO, " * freq is %d\n", csa.freq_params.freq);
95+ wpa_printf(MSG_INFO, " * bandwidth is %d\n",
96+ csa.freq_params.bandwidth);
97+ wpa_printf(MSG_INFO, " * sec_chan_offset is %d\n",
98+ csa.freq_params.sec_channel_offset);
99+ wpa_printf(MSG_INFO, " * center_freq1 is %d\n",
100+ csa.freq_params.center_freq1);
101+ wpa_printf(MSG_INFO, " * center_freq2 is %d\n",
102+ csa.freq_params.center_freq2);
103+
104 for (i = 0; i < iface->num_bss; i++)
105 ret = hostapd_switch_channel(iface->bss[i], &csa);
106
developerdfb50982023-09-11 13:34:36 +0800107diff --git a/src/utils/ucode.c b/src/utils/ucode.c
developere35b8e42023-10-16 11:04:00 +0800108index 122c619..0990e7b 100644
developerdfb50982023-09-11 13:34:36 +0800109--- a/src/utils/ucode.c
110+++ b/src/utils/ucode.c
developere35b8e42023-10-16 11:04:00 +0800111@@ -51,6 +51,7 @@ uc_value_t *uc_wpa_freq_info(uc_vm_t *vm, size_t nargs)
112 uc_value_t *freq = uc_fn_arg(0);
113 uc_value_t *sec = uc_fn_arg(1);
114 int width = ucv_uint64_get(uc_fn_arg(2));
115+ int bw320_offset = 1;
116 int freq_val, center_idx, center_ofs;
117 enum oper_chan_width chanwidth;
118 enum hostapd_hw_mode hw_mode;
119@@ -88,6 +89,9 @@ uc_value_t *uc_wpa_freq_info(uc_vm_t *vm, size_t nargs)
120 case 9:
121 width = 3;
122 chanwidth = CONF_OPER_CHWIDTH_320MHZ;
123+
124+ /* bw320_offset is 1 for 320 MHz-1, and 2 for 320 MHz-2 */
125+ bw320_offset = ucv_uint64_get(uc_fn_arg(3));
126 break;
127 default:
128 return NULL;
129@@ -119,12 +123,16 @@ uc_value_t *uc_wpa_freq_info(uc_vm_t *vm, size_t nargs)
developerdfb50982023-09-11 13:34:36 +0800130 ucv_object_add(ret, "hw_mode_str", ucv_get(ucv_string_new(modestr)));
131 ucv_object_add(ret, "sec_channel", ucv_int64_new(sec_channel));
132 ucv_object_add(ret, "frequency", ucv_int64_new(freq_val));
133+ ucv_object_add(ret, "oper_chwidth", ucv_int64_new(chanwidth));
134
developere35b8e42023-10-16 11:04:00 +0800135- if (!sec_channel)
136+ if (chanwidth == CONF_OPER_CHWIDTH_USE_HT && !sec_channel) {
137+ ucv_object_add(ret, "center_seg0_idx", ucv_int64_new(channel));
138+ ucv_object_add(ret, "center_freq1", ucv_int64_new(freq_val));
developerdfb50982023-09-11 13:34:36 +0800139 return ret;
developere35b8e42023-10-16 11:04:00 +0800140+ }
141
142 if (freq_val >= 5900)
143- center_ofs = 0;
144+ center_ofs = 32 * (1 - bw320_offset);
145 else if (freq_val >= 5745)
146 center_ofs = 20;
147 else
developerdfb50982023-09-11 13:34:36 +0800148diff --git a/wpa_supplicant/ucode.c b/wpa_supplicant/ucode.c
developere35b8e42023-10-16 11:04:00 +0800149index 6cba73d..d5489ea 100644
developerdfb50982023-09-11 13:34:36 +0800150--- a/wpa_supplicant/ucode.c
151+++ b/wpa_supplicant/ucode.c
developere35b8e42023-10-16 11:04:00 +0800152@@ -7,6 +7,8 @@
developerdfb50982023-09-11 13:34:36 +0800153 #include "wps_supplicant.h"
154 #include "bss.h"
155 #include "ucode.h"
156+#include "driver_i.h"
developere35b8e42023-10-16 11:04:00 +0800157+#include "common/ieee802_11_common.h"
developerdfb50982023-09-11 13:34:36 +0800158
159 static struct wpa_global *wpa_global;
160 static uc_resource_type_t *global_type, *iface_type;
developere35b8e42023-10-16 11:04:00 +0800161@@ -96,6 +98,8 @@ void wpas_ucode_event(struct wpa_supplicant *wpa_s, int event, union wpa_event_d
162 {
163 const char *state;
164 uc_value_t *val;
165+ enum oper_chan_width ch_width;
166+ int center_freq1, bw320_offset = 1;
167
168 if (event != EVENT_CH_SWITCH_STARTED)
169 return;
170@@ -114,11 +118,42 @@ void wpas_ucode_event(struct wpa_supplicant *wpa_s, int event, union wpa_event_d
171 uc_value_push(ucv_get(val));
172
173 if (event == EVENT_CH_SWITCH_STARTED) {
174+ center_freq1 = data->ch_switch.cf1;
175+
176+ switch (data->ch_switch.ch_width) {
177+ case CHAN_WIDTH_80:
178+ ch_width = CONF_OPER_CHWIDTH_80MHZ;
179+ break;
180+ case CHAN_WIDTH_80P80:
181+ ch_width = CONF_OPER_CHWIDTH_80P80MHZ;
182+ break;
183+ case CHAN_WIDTH_160:
184+ ch_width = CONF_OPER_CHWIDTH_160MHZ;
185+ break;
186+ case CHAN_WIDTH_320:
187+ ch_width = CONF_OPER_CHWIDTH_320MHZ;
188+ break;
189+ case CHAN_WIDTH_20_NOHT:
190+ case CHAN_WIDTH_20:
191+ case CHAN_WIDTH_40:
192+ default:
193+ ch_width = CONF_OPER_CHWIDTH_USE_HT;
194+ break;
195+ }
196+
197+ /* Check bandwidth 320 MHz-2 */
198+ if (ch_width == CONF_OPER_CHWIDTH_320MHZ &&
199+ (center_freq1 == 6265) || center_freq1 == 6585 ||
200+ center_freq1 == 6905)
201+ bw320_offset = 2;
202+
203 ucv_object_add(val, "csa_count", ucv_int64_new(data->ch_switch.count));
204 ucv_object_add(val, "frequency", ucv_int64_new(data->ch_switch.freq));
205 ucv_object_add(val, "sec_chan_offset", ucv_int64_new(data->ch_switch.ch_offset));
206- ucv_object_add(val, "center_freq1", ucv_int64_new(data->ch_switch.cf1));
207+ ucv_object_add(val, "center_freq1", ucv_int64_new(center_freq1));
208 ucv_object_add(val, "center_freq2", ucv_int64_new(data->ch_switch.cf2));
209+ ucv_object_add(val, "ch_width", ucv_int64_new(ch_width));
210+ ucv_object_add(val, "bw320_offset", ucv_int64_new(bw320_offset));
211 }
212
213 ucv_put(wpa_ucode_call(4));
214@@ -212,6 +247,11 @@ uc_wpas_iface_status(uc_vm_t *vm, size_t nargs)
developerdfb50982023-09-11 13:34:36 +0800215 struct wpa_supplicant *wpa_s = uc_fn_thisval("wpas.iface");
216 struct wpa_bss *bss;
217 uc_value_t *ret, *val;
218+ struct wpa_channel_info ci;
219+ u8 op_class, channel;
220+ enum oper_chan_width ch_width;
developere35b8e42023-10-16 11:04:00 +0800221+ int center_freq1, bw320_offset = 1, is_24ghz;
222+ enum hostapd_hw_mode hw_mode;
developerdfb50982023-09-11 13:34:36 +0800223
224 if (!wpa_s)
225 return NULL;
developere35b8e42023-10-16 11:04:00 +0800226@@ -224,23 +264,37 @@ uc_wpas_iface_status(uc_vm_t *vm, size_t nargs)
227 bss = wpa_s->current_bss;
228 if (bss) {
229 int sec_chan = 0;
230- const u8 *ie;
231-
232- ie = wpa_bss_get_ie(bss, WLAN_EID_HT_OPERATION);
233- if (ie && ie[1] >= 2) {
234- const struct ieee80211_ht_operation *ht_oper;
235- int sec;
236-
237- ht_oper = (const void *) (ie + 2);
238- sec = ht_oper->ht_param & HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK;
239- if (sec == HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE)
240- sec_chan = 1;
241- else if (sec == HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW)
242- sec_chan = -1;
243+
244+ hw_mode = ieee80211_freq_to_chan(bss->freq, &channel);
245+ is_24ghz = hw_mode == HOSTAPD_MODE_IEEE80211G ||
246+ hw_mode == HOSTAPD_MODE_IEEE80211B;
developer36fe7092023-09-27 12:24:47 +0800247+
248+ wpa_drv_channel_info(wpa_s, &ci);
developere35b8e42023-10-16 11:04:00 +0800249+ center_freq1 = ci.center_frq1;
250+
251+ if (bss->freq != center_freq1) {
252+ if (is_24ghz)
253+ sec_chan = (bss->freq < center_freq1) ? 1 : -1;
254+ else
255+ sec_chan = (bss->freq / 20) & 1 ? 1 : -1;
256+ }
257+
258+ if (ieee80211_chaninfo_to_channel(ci.frequency, ci.chanwidth,
259+ sec_chan, &op_class, &channel))
260+ return NULL;
261+
developer36fe7092023-09-27 12:24:47 +0800262+ ch_width = op_class_to_ch_width(op_class);
developere35b8e42023-10-16 11:04:00 +0800263+ if (ch_width == CONF_OPER_CHWIDTH_320MHZ &&
264+ (center_freq1 == 6265) || center_freq1 == 6585 ||
265+ center_freq1 == 6905) {
266+ /* Bandwidth 320 MHz-2 */
267+ bw320_offset = 2;
268 }
269
270 ucv_object_add(ret, "sec_chan_offset", ucv_int64_new(sec_chan));
271 ucv_object_add(ret, "frequency", ucv_int64_new(bss->freq));
developerdfb50982023-09-11 13:34:36 +0800272+ ucv_object_add(ret, "ch_width", ucv_int64_new(ch_width));
developere35b8e42023-10-16 11:04:00 +0800273+ ucv_object_add(ret, "bw320_offset", ucv_int64_new(bw320_offset));
developerdfb50982023-09-11 13:34:36 +0800274 }
275
developere35b8e42023-10-16 11:04:00 +0800276 #ifdef CONFIG_MESH
developerdfb50982023-09-11 13:34:36 +0800277--
2782.25.1
279