blob: 0f8af3e141defb244d64c83fbe91fb15bb7cfc35 [file] [log] [blame]
developer05f3b2b2024-08-19 19:17:34 +08001From d45a052e2c7efe295705ad2185f36b38058ede83 Mon Sep 17 00:00:00 2001
2From: Allen Ye <allen.ye@mediatek.com>
3Date: Tue, 28 May 2024 17:46:26 +0800
4Subject: [PATCH 112/126] mtk: hostapd: support enable/disable preamble
5 puncture from mtk vendor command
6
7Add mtk vendor event to update punct bitmap and trigger channel switch.
8Change to pp user mode when use hostapd_cli to channel switch.
9Change pp vendor cmd use link_id instead of band_idx.
10Remove band_ind in hostapd_cli get/set pp cmd.
11
12Change pp default enable firmware mode.
13
14Signed-off-by: Allen Ye <allen.ye@mediatek.com>
15---
16 hostapd/config_file.c | 1 -
17 hostapd/ctrl_iface.c | 45 ++++++++--------
18 hostapd/hostapd_cli.c | 4 +-
19 src/ap/ap_config.c | 2 +-
20 src/ap/ap_drv_ops.c | 10 +++-
21 src/ap/drv_callbacks.c | 82 ++++++++++++++++++++++++++++++
22 src/common/mtk_vendor.h | 8 ++-
23 src/drivers/driver.h | 11 +++-
24 src/drivers/driver_nl80211.c | 10 ++--
25 src/drivers/driver_nl80211_event.c | 48 +++++++++++++++++
26 10 files changed, 185 insertions(+), 36 deletions(-)
27
28diff --git a/hostapd/config_file.c b/hostapd/config_file.c
29index 38273a4f2..f7bfc357a 100644
30--- a/hostapd/config_file.c
31+++ b/hostapd/config_file.c
32@@ -5452,7 +5452,6 @@ static int hostapd_config_fill(struct hostapd_config *conf,
33 if (get_u16(pos, line, &conf->punct_bitmap))
34 return 1;
35 conf->punct_bitmap = atoi(pos);
36- conf->pp_mode = PP_USR_MODE;
37 } else if (os_strcmp(buf, "punct_acs_threshold") == 0) {
38 int val = atoi(pos);
39
40diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
41index 988bc90de..337261f8f 100644
42--- a/hostapd/ctrl_iface.c
43+++ b/hostapd/ctrl_iface.c
44@@ -2818,6 +2818,7 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
45 #ifdef NEED_AP_MLME
46 struct hostapd_hw_modes *mode = iface->current_mode;
47 struct csa_settings settings, background_settings;
48+ struct hostapd_data *hapd;
49 int ret;
50 int freq, state;
51 int bandwidth, oper_chwidth;
52@@ -2914,6 +2915,17 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
53 break;
54 }
55
56+#ifdef CONFIG_IEEE80211BE
57+ hapd = iface->bss[0];
58+ if (hapd->iconf->punct_bitmap != settings.punct_bitmap &&
59+ hapd->iconf->pp_mode != PP_USR_MODE) {
60+ hapd->iconf->pp_mode = PP_USR_MODE;
61+ ret = hostapd_drv_pp_mode_set(hapd);
62+ if (ret)
63+ return ret;
64+ }
65+#endif /* CONFIG_IEEE80211BE */
66+
67 for (i = 0; i < iface->num_bss; i++) {
68
69 /* Save CHAN_SWITCH VHT, HE, and EHT config */
70@@ -5172,8 +5184,7 @@ static int
71 hostapd_ctrl_iface_set_pp(struct hostapd_data *hapd, char *cmd, char *buf,
72 size_t buflen)
73 {
74- char *band, *config, *value;
75- u8 band_idx;
76+ char *config, *value;
77
78 config = cmd;
79
80@@ -5182,31 +5193,26 @@ hostapd_ctrl_iface_set_pp(struct hostapd_data *hapd, char *cmd, char *buf,
81 return -1;
82 *value++ = '\0';
83
84- band = os_strchr(value, ' ');
85- if (band == NULL)
86- return -1;
87- *band++ = '\0';
88- band_idx = strtol(band, NULL, 10);
89-
90- hapd = hostapd_get_hapd_by_band_idx(hapd, band_idx);
91-
92- if (!hapd)
93- return -1;
94-
95 if (os_strcmp(config, "mode") == 0) {
96 int val = strtol(value, NULL, 10);
97
98- if (val < PP_DISABLE || val > PP_FW_MODE) {
99+ switch(val) {
100+ case PP_DISABLE:
101+ case PP_FW_MODE:
102+ break;
103+ case PP_USR_MODE:
104+ default:
105 wpa_printf(MSG_ERROR, "Invalid value for SET_PP");
106 return -1;
107 }
108 hapd->iconf->pp_mode = (u8) val;
109+ hapd->iconf->punct_bitmap = 0;
110 if (hostapd_drv_pp_mode_set(hapd) != 0)
111 return -1;
112 } else {
113 wpa_printf(MSG_ERROR,
114 "Unsupported parameter %s for SET_PP"
115- "Usage: set_pp mode <value> <band_idx>", config);
116+ "Usage: set_pp mode <value>", config);
117 return -1;
118 }
119 return os_snprintf(buf, buflen, "OK\n");
120@@ -5216,15 +5222,6 @@ static int
121 hostapd_ctrl_iface_get_pp(struct hostapd_data *hapd, char *cmd, char *buf,
122 size_t buflen)
123 {
124- u8 band_idx;
125-
126- band_idx = strtol(cmd, NULL, 10);
127-
128- hapd = hostapd_get_hapd_by_band_idx(hapd, band_idx);
129-
130- if (!hapd)
131- return -1;
132-
133 return os_snprintf(buf, buflen, "pp_mode: %d, punct_bitmap: 0x%04x\n",
134 hapd->iconf->pp_mode, hapd->iconf->punct_bitmap);
135 }
136diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
137index bfa912dff..12ee0a18f 100644
138--- a/hostapd/hostapd_cli.c
139+++ b/hostapd/hostapd_cli.c
140@@ -1764,13 +1764,13 @@ static int hostapd_cli_cmd_dump_csi(struct wpa_ctrl *ctrl, int argc,
141 static int hostapd_cli_cmd_set_pp(struct wpa_ctrl *ctrl, int argc,
142 char *argv[])
143 {
144- return hostapd_cli_cmd(ctrl, "set_pp", 3, argc, argv);
145+ return hostapd_cli_cmd(ctrl, "set_pp", 2, argc, argv);
146 }
147
148 static int hostapd_cli_cmd_get_pp(struct wpa_ctrl *ctrl, int argc,
149 char *argv[])
150 {
151- return hostapd_cli_cmd(ctrl, "get_pp", 1, argc, argv);
152+ return hostapd_cli_cmd(ctrl, "get_pp", 0, argc, argv);
153 }
154
155 static int hostapd_cli_cmd_wmm(struct wpa_ctrl *ctrl, int argc,
156diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
157index 95100b25c..4528df823 100644
158--- a/src/ap/ap_config.c
159+++ b/src/ap/ap_config.c
160@@ -312,7 +312,7 @@ struct hostapd_config * hostapd_config_defaults(void)
161 conf->three_wire_enable = THREE_WIRE_MODE_DISABLE;
162 conf->ibf_enable = IBF_DEFAULT_ENABLE;
163 conf->amsdu = 1;
164- conf->pp_mode = PP_DISABLE;
165+ conf->pp_mode = PP_FW_MODE;
166 conf->band_idx = 255;
167
168 hostapd_set_and_check_bw320_offset(conf, 0);
169diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
170index 8631bf960..f9ec9a689 100644
171--- a/src/ap/ap_drv_ops.c
172+++ b/src/ap/ap_drv_ops.c
173@@ -1447,14 +1447,20 @@ int hostapd_drv_background_radar_mode(struct hostapd_data *hapd)
174
175 int hostapd_drv_pp_mode_set(struct hostapd_data *hapd)
176 {
177+ s8 link_id = -1;
178+
179 if (!hapd->driver || !hapd->driver->pp_mode_set ||
180- hapd->iconf->pp_mode >= PP_USR_MODE ||
181+ hapd->iconf->pp_mode > PP_USR_MODE ||
182 hapd->iface->current_mode->mode != HOSTAPD_MODE_IEEE80211A)
183 return 0;
184
185+ if (hapd->conf->mld_ap)
186+ link_id = hapd->mld_link_id;
187+
188 return hapd->driver->pp_mode_set(hapd->drv_priv,
189 hapd->iconf->pp_mode,
190- hapd->iconf->band_idx);
191+ link_id,
192+ hapd->iconf->punct_bitmap);
193 }
194
195 int hostapd_drv_beacon_ctrl(struct hostapd_data *hapd, u8 beacon_mode)
196diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
197index 0e7cfd285..420d156c8 100644
198--- a/src/ap/drv_callbacks.c
199+++ b/src/ap/drv_callbacks.c
200@@ -43,6 +43,7 @@
201 #include "fils_hlp.h"
202 #include "neighbor_db.h"
203 #include "nan_usd_ap.h"
204+#include "ap/beacon.h"
205
206
207 #ifdef CONFIG_FILS
208@@ -2456,6 +2457,81 @@ static void hostapd_event_color_change(struct hostapd_data *hapd, bool success)
209 #endif /* CONFIG_IEEE80211AX */
210
211
212+static void hostapd_event_pp_bitmap_update(struct hostapd_data *hapd,
213+ struct ch_switch *ch_switch)
214+{
215+ struct hostapd_iface *iface = hapd->iface;
216+ struct hostapd_hw_modes *cmode = iface->current_mode;
217+ int err, freq;
218+ struct csa_settings csa_settings;
219+ unsigned int i;
220+
221+ /* Check if CSA in progress */
222+ if (hostapd_csa_in_progress(iface))
223+ return;
224+
225+ if (!hw_get_channel_chan(cmode, iface->conf->channel, &freq))
226+ return;
227+
228+ if (iface->conf->punct_bitmap == ch_switch->punct_bitmap ||
229+ freq != ch_switch->freq)
230+ return;
231+
232+ /* Setup CSA request */
233+ os_memset(&csa_settings, 0, sizeof(csa_settings));
234+ csa_settings.cs_count = 5;
235+ csa_settings.block_tx = 0;
236+ csa_settings.punct_bitmap = ch_switch->punct_bitmap;
237+ csa_settings.link_id = ch_switch->link_id;
238+
239+ err = hostapd_set_freq_params(&csa_settings.freq_params,
240+ iface->conf->hw_mode,
241+ freq,
242+ iface->conf->channel,
243+ iface->conf->enable_edmg,
244+ iface->conf->edmg_channel,
245+ iface->conf->ieee80211n,
246+ iface->conf->ieee80211ac,
247+ iface->conf->ieee80211ax,
248+ iface->conf->ieee80211be,
249+ iface->conf->secondary_channel,
250+ hostapd_get_oper_chwidth(iface->conf),
251+ hostapd_get_oper_centr_freq_seg0_idx(iface->conf),
252+ hostapd_get_oper_centr_freq_seg1_idx(iface->conf),
253+ cmode->vht_capab,
254+ &cmode->he_capab[IEEE80211_MODE_AP],
255+ &cmode->eht_capab[IEEE80211_MODE_AP],
256+ ch_switch->punct_bitmap);
257+
258+ if (err) {
259+ wpa_printf(MSG_ERROR,
260+ "Failed to calculate CSA freq params");
261+ hostapd_disable_iface(iface);
262+ return;
263+ }
264+
265+ for (i = 0; i < iface->num_bss; i++) {
266+ ieee802_11_set_bss_critical_update(iface->bss[i],
267+ BSS_CRIT_UPDATE_EVENT_CSA);
268+
269+ err = hostapd_switch_channel(iface->bss[i], &csa_settings);
270+ if (err)
271+ break;
272+
273+#ifdef CONFIG_IEEE80211BE
274+ if (iface->bss[i]->conf->mld_ap)
275+ hostapd_update_aff_link_beacon(iface->bss[i],
276+ csa_settings.cs_count);
277+
278+ /* FIXME:
279+ * CU flag should be cleared when receiving DTIM event from FW
280+ */
281+ iface->bss[i]->eht_mld_bss_critical_update = 0;
282+#endif /* CONFIG_IEEE80211BE */
283+ }
284+}
285+
286+
287 void hostapd_wpa_event(void *ctx, enum wpa_event_type event,
288 union wpa_event_data *data)
289 {
290@@ -2759,6 +2835,12 @@ void hostapd_wpa_event(void *ctx, enum wpa_event_type event,
291 hostapd_event_dfs_cac_started(hapd, &data->dfs_event);
292 break;
293 #endif /* NEED_AP_MLME */
294+ case EVENT_PP_BITMAP_UPDATE:
295+ if (!data)
296+ break;
297+ hapd = switch_link_hapd(hapd, data->ch_switch.link_id);
298+ hostapd_event_pp_bitmap_update(hapd, &data->ch_switch);
299+ break;
300 case EVENT_INTERFACE_ENABLED:
301 wpa_msg(hapd->msg_ctx, MSG_INFO, INTERFACE_ENABLED);
302 if (hapd->disabled && hapd->started) {
303diff --git a/src/common/mtk_vendor.h b/src/common/mtk_vendor.h
304index 937b968d5..933f0099d 100644
305--- a/src/common/mtk_vendor.h
306+++ b/src/common/mtk_vendor.h
307@@ -22,6 +22,10 @@ enum mtk_nl80211_vendor_subcmds {
308 MTK_NL80211_VENDOR_SUBCMD_EML_CTRL = 0xd3,
309 };
310
311+enum mtk_nl80211_vendor_subevents {
312+ MTK_NL80211_VENDOR_EVENT_PP_BMP_UPDATE = 0x5,
313+};
314+
315 enum mtk_vendor_attr_edcca_ctrl {
316 MTK_VENDOR_ATTR_EDCCA_THRESHOLD_INVALID = 0,
317
318@@ -271,7 +275,9 @@ enum mtk_vendor_attr_pp_ctrl {
319 MTK_VENDOR_ATTR_PP_CTRL_UNSPEC,
320
321 MTK_VENDOR_ATTR_PP_MODE,
322- MTK_VENDOR_ATTR_PP_BAND_IDX,
323+ MTK_VENDOR_ATTR_PP_LINK_ID,
324+ MTK_VENDOR_ATTR_PP_BITMAP,
325+ MTK_VENDOR_ATTR_PP_CURR_FREQ,
326
327 /* keep last */
328 NUM_MTK_VENDOR_ATTRS_PP_CTRL,
329diff --git a/src/drivers/driver.h b/src/drivers/driver.h
330index dacf0a98d..5e65d9e0b 100644
331--- a/src/drivers/driver.h
332+++ b/src/drivers/driver.h
333@@ -5381,9 +5381,10 @@ struct wpa_driver_ops {
334 * pp_mode_set - Set preamble puncture operation mode
335 * @priv: Private driver interface data
336 * @pp_mode: Value is defined in enum pp_mode
337- * @band_idx: chip band index
338+ * @link_id: MLD link id. -1 if this is an non-MLD AP
339+ * @punct_bitmap: current puncture bitmap
340 */
341- int (*pp_mode_set)(void *priv, const u8 pp_mode, u8 band_idx);
342+ int (*pp_mode_set)(void *priv, const u8 pp_mode, s8 link_id, u16 punct_bitmap);
343 #ifdef CONFIG_IEEE80211BE
344 int (*get_mld_addr)(void *priv, u8 *addr);
345 #endif
346@@ -6058,6 +6059,12 @@ enum wpa_event_type {
347 * channel has been updated and operating channel should expand its width.
348 */
349 EVENT_DFS_BACKGROUND_CHAN_EXPAND,
350+
351+ /**
352+ * EVENT_PP_BITMAP_UPDATE - Notification that the new puncture bitmap
353+ * has been applied and a channel switch should be triggered.
354+ */
355+ EVENT_PP_BITMAP_UPDATE,
356 };
357
358
359diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
360index 80fe2e591..5d97317f7 100644
361--- a/src/drivers/driver_nl80211.c
362+++ b/src/drivers/driver_nl80211.c
363@@ -160,7 +160,9 @@ amnt_dump_policy[NUM_MTK_VENDOR_ATTRS_AMNT_DUMP] = {
364 static struct nla_policy
365 pp_ctrl_policy[NUM_MTK_VENDOR_ATTRS_PP_CTRL] = {
366 [MTK_VENDOR_ATTR_PP_MODE] = { .type = NLA_U8 },
367- [MTK_VENDOR_ATTR_PP_BAND_IDX] = { .type = NLA_U8 },
368+ [MTK_VENDOR_ATTR_PP_LINK_ID] = { .type = NLA_U8 },
369+ [MTK_VENDOR_ATTR_PP_BITMAP] = { .type = NLA_U16 },
370+ [MTK_VENDOR_ATTR_PP_CURR_FREQ] = { .type = NLA_U32 },
371 };
372
373 static struct nla_policy csi_ctrl_policy[NUM_MTK_VENDOR_ATTRS_CSI_CTRL] = {
374@@ -15248,7 +15250,7 @@ static int nl80211_background_radar_mode(void *priv, const u8 background_radar_m
375 return ret;
376 }
377
378-static int nl80211_pp_mode_set(void *priv, const u8 pp_mode, u8 band_idx)
379+static int nl80211_pp_mode_set(void *priv, const u8 pp_mode, s8 link_id, u16 punct_bitmap)
380 {
381 struct i802_bss *bss = priv;
382 struct wpa_driver_nl80211_data *drv = bss->drv;
383@@ -15275,8 +15277,10 @@ static int nl80211_pp_mode_set(void *priv, const u8 pp_mode, u8 band_idx)
384 if (!data)
385 goto fail;
386
387- nla_put_u8(msg, MTK_VENDOR_ATTR_PP_BAND_IDX, band_idx);
388+ if (link_id > -1)
389+ nla_put_u8(msg, MTK_VENDOR_ATTR_PP_LINK_ID, link_id);
390 nla_put_u8(msg, MTK_VENDOR_ATTR_PP_MODE, pp_mode);
391+ nla_put_u16(msg, MTK_VENDOR_ATTR_PP_BITMAP, punct_bitmap);
392
393 nla_nest_end(msg, data);
394 ret = send_and_recv_cmd(drv, msg);
395diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c
396index e95593a5b..efdb8ef7f 100644
397--- a/src/drivers/driver_nl80211_event.c
398+++ b/src/drivers/driver_nl80211_event.c
399@@ -19,6 +19,7 @@
400 #include "common/ieee802_11_defs.h"
401 #include "common/ieee802_11_common.h"
402 #include "driver_nl80211.h"
403+#include "common/mtk_vendor.h"
404
405
406 static void
407@@ -3332,6 +3333,50 @@ static void nl80211_vendor_event_brcm(struct wpa_driver_nl80211_data *drv,
408
409 #endif /* CONFIG_DRIVER_NL80211_BRCM */
410
411+static void mtk_nl80211_pp_bitmap_update(struct wpa_driver_nl80211_data *drv,
412+ const u8 *data, size_t len)
413+{
414+ struct nlattr *tb[MTK_VENDOR_ATTR_PP_CTRL_MAX + 1];
415+ union wpa_event_data event;
416+
417+ wpa_printf(MSG_DEBUG,
418+ "nl80211: MTK pp bitmap update vendor event received");
419+
420+ if (nla_parse(tb, MTK_VENDOR_ATTR_PP_CTRL_MAX,
421+ (struct nlattr *) data, len, NULL) ||
422+ !tb[MTK_VENDOR_ATTR_PP_CURR_FREQ] ||
423+ !tb[MTK_VENDOR_ATTR_PP_BITMAP])
424+ return;
425+
426+ os_memset(&event, 0, sizeof(event));
427+ event.ch_switch.freq = nla_get_u32(tb[MTK_VENDOR_ATTR_PP_CURR_FREQ]);
428+
429+ event.ch_switch.link_id =
430+ nl80211_get_link_id_by_freq(drv->first_bss, event.ch_switch.freq);
431+ event.ch_switch.punct_bitmap =
432+ nla_get_u16(tb[MTK_VENDOR_ATTR_PP_BITMAP]);
433+
434+ wpa_printf(MSG_DEBUG,
435+ "nl80211: puncture bitmap: 0x%04x, link_id: %d",
436+ event.ch_switch.punct_bitmap, event.ch_switch.link_id);
437+ wpa_supplicant_event(drv->ctx, EVENT_PP_BITMAP_UPDATE, &event);
438+}
439+
440+static void nl80211_vendor_event_mtk(struct wpa_driver_nl80211_data *drv,
441+ u32 subcmd, u8 *data, size_t len)
442+{
443+ wpa_printf(MSG_DEBUG, "nl80211: Got MTK vendor event %u", subcmd);
444+ switch (subcmd) {
445+ case MTK_NL80211_VENDOR_EVENT_PP_BMP_UPDATE:
446+ mtk_nl80211_pp_bitmap_update(drv, data, len);
447+ break;
448+ default:
449+ wpa_printf(MSG_DEBUG,
450+ "%s: Ignore unsupported MTK vendor event %u",
451+ __func__, subcmd);
452+ break;
453+ }
454+}
455
456 static void nl80211_vendor_event(struct wpa_driver_nl80211_data *drv,
457 struct nlattr **tb)
458@@ -3388,6 +3433,9 @@ static void nl80211_vendor_event(struct wpa_driver_nl80211_data *drv,
459 nl80211_vendor_event_brcm(drv, subcmd, data, len);
460 break;
461 #endif /* CONFIG_DRIVER_NL80211_BRCM */
462+ case OUI_MTK:
463+ nl80211_vendor_event_mtk(drv, subcmd, data, len);
464+ break;
465 default:
466 wpa_printf(MSG_DEBUG, "nl80211: Ignore unsupported vendor event");
467 break;
468--
4692.18.0
470