[rdkb][common][bsp][Refactor and sync wifi from openwrt]
[Description]
16b7683 [mac80211][mt76][Fix wtbl CR and fix memory leak]
787e2c4 [MAC80211][core][remove duplicated patches]
f2532a8 [MAC80211][core][refine backports patches]
4827f0a [MAC80211][wed][fix fe reset hang issue]
472b001 [MAC80211][hostapd][refine hostapd patches]
[Release-log]
Change-Id: I1c2669521173b1977eed191945f505792fb6cca6
diff --git a/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0010-hostapd-mtk-Add-DFS-and-ZWDFS-support.patch b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0010-hostapd-mtk-Add-DFS-and-ZWDFS-support.patch
new file mode 100644
index 0000000..8a387a7
--- /dev/null
+++ b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0010-hostapd-mtk-Add-DFS-and-ZWDFS-support.patch
@@ -0,0 +1,376 @@
+From 4e7c861c971ca49ea162bd908fef6021a62b9018 Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Fri, 7 Oct 2022 10:46:29 +0800
+Subject: [PATCH 10/15] hostapd: mtk: Add DFS and ZWDFS support
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ hostapd/config_file.c | 4 ++
+ hostapd/ctrl_iface.c | 95 ++++++++++++++++++++++++++++++++++++
+ src/ap/ap_config.h | 13 +++++
+ src/ap/dfs.c | 35 +++++++------
+ src/ap/dfs.h | 15 ++++++
+ src/ap/hostapd.c | 4 +-
+ src/drivers/driver.h | 7 +++
+ src/drivers/driver_nl80211.c | 29 +++++++++++
+ src/drivers/nl80211_copy.h | 1 +
+ 9 files changed, 186 insertions(+), 17 deletions(-)
+
+diff --git a/hostapd/config_file.c b/hostapd/config_file.c
+index 63c9d40be..cd1534952 100644
+--- a/hostapd/config_file.c
++++ b/hostapd/config_file.c
+@@ -4803,6 +4803,10 @@ static int hostapd_config_fill(struct hostapd_config *conf,
+ } else if (os_strcmp(buf, "ibf_enable") == 0) { /*ibf setting is per device*/
+ int val = atoi(pos);
+ conf->ibf_enable = !!val;
++ } else if (os_strcmp(buf, "dfs_detect_mode") == 0) { /*bypass channel switch*/
++ u8 en = strtol(pos, NULL, 10);
++
++ conf->dfs_detect_mode = en;
+ } else {
+ wpa_printf(MSG_ERROR,
+ "Line %d: unknown configuration item '%s'",
+diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
+index c881d3717..6ea1573b8 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -3522,6 +3522,96 @@ hostapd_ctrl_iface_get_ibf(struct hostapd_data *hapd, char *buf,
+ }
+
+
++static int
++hostapd_ctrl_iface_set_dfs_detect_mode(struct hostapd_data *hapd, char *value,
++ char *buf, size_t buflen)
++{
++ u8 dfs_detect_mode;
++
++ if (!value)
++ return -1;
++
++ dfs_detect_mode = strtol(value, NULL, 10);
++ if (dfs_detect_mode > DFS_DETECT_MODE_MAX) {
++ wpa_printf(MSG_ERROR, "Invalid value for dfs detect mode");
++ return -1;
++ }
++ hapd->iconf->dfs_detect_mode = dfs_detect_mode;
++
++ return os_snprintf(buf, buflen, "OK\n");
++}
++
++
++static int
++hostapd_ctrl_iface_set_offchan_ctrl(struct hostapd_data *hapd, char *cmd,
++ char *buf, size_t buflen)
++{
++ struct hostapd_iface *iface = hapd->iface;
++ char *pos, *param;
++ enum hostapd_hw_mode hw_mode;
++ bool chan_found = false;
++ int i, num_available_chandefs, channel, chan_width, sec = 0;
++ int sec_chan_idx_80p80 = -1;
++ u8 oper_centr_freq_seg0_idx, oper_centr_freq_seg1_idx;
++ struct hostapd_channel_data *chan;
++ enum dfs_channel_type type = DFS_NO_CAC_YET;
++
++ param = os_strchr(cmd, ' ');
++ if (!param)
++ return -1;
++ *param++ = '\0';
++
++ pos = os_strstr(param, "chan=");
++ if (pos)
++ channel = strtol(pos + 5, NULL, 10);
++ else
++ return -1;
++
++ num_available_chandefs = dfs_find_channel(iface, NULL, 0, type);
++ for (i = 0; i < num_available_chandefs; i++) {
++ dfs_find_channel(iface, &chan, i, type);
++ if (chan->chan == channel) {
++ chan_found = true;
++ break;
++ }
++ }
++
++ if (!chan_found)
++ return -1;
++
++ if (iface->conf->secondary_channel)
++ sec = 1;
++
++ dfs_adjust_center_freq(iface, chan,
++ sec,
++ sec_chan_idx_80p80,
++ &oper_centr_freq_seg0_idx,
++ &oper_centr_freq_seg1_idx);
++
++ if (hostapd_start_dfs_cac(iface, iface->conf->hw_mode,
++ chan->freq, chan->chan,
++ iface->conf->ieee80211n,
++ iface->conf->ieee80211ac,
++ iface->conf->ieee80211ax,
++ iface->conf->ieee80211be,
++ sec, hostapd_get_oper_chwidth(iface->conf),
++ oper_centr_freq_seg0_idx,
++ oper_centr_freq_seg1_idx, true)) {
++ wpa_printf(MSG_ERROR, "DFS failed to start CAC offchannel");
++ iface->radar_background.channel = -1;
++ return -1;
++ }
++
++ iface->radar_background.channel = chan->chan;
++ iface->radar_background.freq = chan->freq;
++ iface->radar_background.secondary_channel = sec;
++ iface->radar_background.centr_freq_seg0_idx = oper_centr_freq_seg0_idx;
++ iface->radar_background.centr_freq_seg1_idx = oper_centr_freq_seg1_idx;
++
++ return os_snprintf(buf, buflen, "OK\n");
++}
++
++
+ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
+ char *buf, char *reply,
+ int reply_size,
+@@ -4081,6 +4171,11 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
+ reply_len = hostapd_ctrl_iface_get_hemu(hapd, reply, reply_size);
+ } else if (os_strncmp(buf, "GET_IBF", 7) == 0) {
+ reply_len = hostapd_ctrl_iface_get_ibf(hapd, reply, reply_size);
++ } else if (os_strncmp(buf, "DFS_DETECT_MODE ", 16) == 0) {
++ reply_len = hostapd_ctrl_iface_set_dfs_detect_mode(hapd, buf + 16,
++ reply, reply_size);
++ } else if (os_strncmp(buf, "SET_OFFCHAN_CTRL", 16) == 0) {
++ reply_len = hostapd_ctrl_iface_set_offchan_ctrl(hapd, buf + 16, reply, reply_size);
+ } else {
+ os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
+ reply_len = 16;
+diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
+index a9e3d2aeb..77f6169d2 100644
+--- a/src/ap/ap_config.h
++++ b/src/ap/ap_config.h
+@@ -1160,6 +1160,7 @@ struct hostapd_config {
+ int *edcca_threshold;
+ u8 three_wire_enable;
+ u8 ibf_enable;
++ u8 dfs_detect_mode;
+ };
+
+ enum three_wire_mode {
+@@ -1174,6 +1175,18 @@ enum three_wire_mode {
+ NUM_THREE_WIRE_MODE - 1
+ };
+
++enum dfs_mode {
++ DFS_DETECT_MODE_DISABLE,
++ DFS_DETECT_MODE_AP_ENABLE,
++ DFS_DETECT_MODE_BACKGROUND_ENABLE,
++ DFS_DETECT_MODE_ALL_ENABLE,
++
++ /* keep last */
++ NUM_DFS_DETECT_MODE,
++ DFS_DETECT_MODE_MAX =
++ NUM_DFS_DETECT_MODE - 1
++};
++
+ enum edcca_mode {
+ EDCCA_MODE_FORCE_DISABLE = 0,
+ EDCCA_MODE_AUTO = 1,
+diff --git a/src/ap/dfs.c b/src/ap/dfs.c
+index b5d105d6a..1c3f6785b 100644
+--- a/src/ap/dfs.c
++++ b/src/ap/dfs.c
+@@ -19,13 +19,6 @@
+ #include "dfs.h"
+ #include "crypto/crypto.h"
+
+-
+-enum dfs_channel_type {
+- DFS_ANY_CHANNEL,
+- DFS_AVAILABLE, /* non-radar or radar-available */
+- DFS_NO_CAC_YET, /* radar-not-yet-available */
+-};
+-
+ static struct hostapd_channel_data *
+ dfs_downgrade_bandwidth(struct hostapd_iface *iface, int *secondary_channel,
+ u8 *oper_centr_freq_seg0_idx,
+@@ -238,9 +231,9 @@ static int is_in_chanlist(struct hostapd_iface *iface,
+ * - hapd->vht/he_oper_centr_freq_seg0_idx
+ * - hapd->vht/he_oper_centr_freq_seg1_idx
+ */
+-static int dfs_find_channel(struct hostapd_iface *iface,
+- struct hostapd_channel_data **ret_chan,
+- int idx, enum dfs_channel_type type)
++int dfs_find_channel(struct hostapd_iface *iface,
++ struct hostapd_channel_data **ret_chan,
++ int idx, enum dfs_channel_type type)
+ {
+ struct hostapd_hw_modes *mode;
+ struct hostapd_channel_data *chan;
+@@ -299,12 +292,12 @@ static int dfs_find_channel(struct hostapd_iface *iface,
+ }
+
+
+-static void dfs_adjust_center_freq(struct hostapd_iface *iface,
+- struct hostapd_channel_data *chan,
+- int secondary_channel,
+- int sec_chan_idx_80p80,
+- u8 *oper_centr_freq_seg0_idx,
+- u8 *oper_centr_freq_seg1_idx)
++void dfs_adjust_center_freq(struct hostapd_iface *iface,
++ struct hostapd_channel_data *chan,
++ int secondary_channel,
++ int sec_chan_idx_80p80,
++ u8 *oper_centr_freq_seg0_idx,
++ u8 *oper_centr_freq_seg1_idx)
+ {
+ if (!iface->conf->ieee80211ac && !iface->conf->ieee80211ax)
+ return;
+@@ -1317,6 +1310,11 @@ hostapd_dfs_background_start_channel_switch(struct hostapd_iface *iface,
+ __func__, iface->radar_background.cac_started ? "yes" : "no",
+ hostapd_csa_in_progress(iface) ? "yes" : "no");
+
++ /* Skip channel switch when background dfs detect mode is on */
++ if (iface->conf->dfs_detect_mode == DFS_DETECT_MODE_BACKGROUND_ENABLE ||
++ iface->conf->dfs_detect_mode == DFS_DETECT_MODE_ALL_ENABLE)
++ return 0;
++
+ /* Check if CSA in progress */
+ if (hostapd_csa_in_progress(iface))
+ return 0;
+@@ -1365,6 +1363,11 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface)
+ __func__, iface->cac_started ? "yes" : "no",
+ hostapd_csa_in_progress(iface) ? "yes" : "no");
+
++ /* Skip channel switch when dfs detect mode is on */
++ if (iface->conf->dfs_detect_mode == DFS_DETECT_MODE_AP_ENABLE ||
++ iface->conf->dfs_detect_mode == DFS_DETECT_MODE_ALL_ENABLE)
++ return 0;
++
+ /* Check if CSA in progress */
+ if (hostapd_csa_in_progress(iface))
+ return 0;
+diff --git a/src/ap/dfs.h b/src/ap/dfs.h
+index 606c1b393..c2556d2d9 100644
+--- a/src/ap/dfs.h
++++ b/src/ap/dfs.h
+@@ -9,6 +9,12 @@
+ #ifndef DFS_H
+ #define DFS_H
+
++enum dfs_channel_type {
++ DFS_ANY_CHANNEL,
++ DFS_AVAILABLE, /* non-radar or radar-available */
++ DFS_NO_CAC_YET, /* radar-not-yet-available */
++};
++
+ int hostapd_handle_dfs(struct hostapd_iface *iface);
+
+ int hostapd_dfs_complete_cac(struct hostapd_iface *iface, int success, int freq,
+@@ -32,5 +38,14 @@ int hostapd_dfs_start_cac(struct hostapd_iface *iface, int freq,
+ int hostapd_handle_dfs_offload(struct hostapd_iface *iface);
+ int hostapd_is_dfs_overlap(struct hostapd_iface *iface, enum chan_width width,
+ int center_freq);
++int dfs_find_channel(struct hostapd_iface *iface,
++ struct hostapd_channel_data **ret_chan,
++ int idx, enum dfs_channel_type type);
++void dfs_adjust_center_freq(struct hostapd_iface *iface,
++ struct hostapd_channel_data *chan,
++ int secondary_channel,
++ int sec_chan_idx_80p80,
++ u8 *oper_centr_freq_seg0_idx,
++ u8 *oper_centr_freq_seg1_idx);
+
+ #endif /* DFS_H */
+diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
+index da7f7d87b..a0229c9ca 100644
+--- a/src/ap/hostapd.c
++++ b/src/ap/hostapd.c
+@@ -1464,7 +1464,9 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
+ return -1;
+ }
+
+- if (!conf->start_disabled && ieee802_11_set_beacon(hapd) < 0)
++ if (conf->start_disabled)
++ hapd->driver->start_disabled(hapd->drv_priv);
++ else if (ieee802_11_set_beacon(hapd) < 0)
+ return -1;
+
+ if (flush_old_stations && !conf->start_disabled &&
+diff --git a/src/drivers/driver.h b/src/drivers/driver.h
+index 71ded617f..aa23fbdb3 100644
+--- a/src/drivers/driver.h
++++ b/src/drivers/driver.h
+@@ -4720,6 +4720,13 @@ struct wpa_driver_ops {
+ *
+ */
+ int (*ibf_dump)(void *priv, u8 *ibf_enable);
++
++ /**
++ * start_disabled - set start_disabled to cfg80211
++ * @priv: Private driver interface data
++ *
++ */
++ int (*start_disabled)(void *priv);
+ };
+
+ /**
+diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
+index 5c2a291ca..7472542cc 100644
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -12776,6 +12776,34 @@ fail:
+ return -ENOBUFS;
+ }
+
++static int nl80211_start_disabled(void *priv)
++{
++ struct i802_bss *bss = priv;
++ struct wpa_driver_nl80211_data *drv = bss->drv;
++ struct nl_msg *msg;
++ struct nlattr *data;
++ int ret;
++
++ msg = nl80211_bss_msg(bss, 0, NL80211_CMD_NEW_BEACON);
++ if (!msg)
++ goto fail;
++
++ if (nla_put_flag(msg, NL80211_ATTR_START_DISABLED))
++ goto fail;
++
++ ret = send_and_recv_msgs_connect_handle(drv, msg, bss, 1);
++
++ if (ret)
++ wpa_printf(MSG_ERROR, "Failed to set start_disabled. ret=%d (%s)",
++ ret, strerror(-ret));
++
++ return ret;
++
++fail:
++ nlmsg_free(msg);
++ return ret;
++}
++
+ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
+ .name = "nl80211",
+ .desc = "Linux nl80211/cfg80211",
+@@ -12930,4 +12958,5 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
+ .three_wire_ctrl = nl80211_enable_three_wire,
+ .ibf_ctrl = nl80211_ibf_enable,
+ .ibf_dump = nl80211_ibf_dump,
++ .start_disabled = nl80211_start_disabled,
+ };
+diff --git a/src/drivers/nl80211_copy.h b/src/drivers/nl80211_copy.h
+index c4bf3ad35..79bc76c57 100644
+--- a/src/drivers/nl80211_copy.h
++++ b/src/drivers/nl80211_copy.h
+@@ -3176,6 +3176,7 @@ enum nl80211_attrs {
+ NL80211_ATTR_EHT_CAPABILITY,
+
+ /* add attributes here, update the policy in nl80211.c */
++ NL80211_ATTR_START_DISABLED = 999,
+
+ __NL80211_ATTR_AFTER_LAST,
+ NUM_NL80211_ATTR = __NL80211_ATTR_AFTER_LAST,
+--
+2.25.1
+