Merge "[AUTO00217168] [[Colgin][RDKB][WiFi][MT76] modify uci cmd for deny acl mode]"
diff --git a/recipes-devtools/flowtable/files/COPYING b/recipes-devtools/flowtable/files/COPYING
new file mode 100644
index 0000000..d511905
--- /dev/null
+++ b/recipes-devtools/flowtable/files/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/recipes-devtools/flowtable/files/src/Makefile b/recipes-devtools/flowtable/files/src/Makefile
new file mode 100644
index 0000000..3f450ad
--- /dev/null
+++ b/recipes-devtools/flowtable/files/src/Makefile
@@ -0,0 +1,9 @@
+EXEC = ftnl
+SRC = api.c ftnl.c
+
+all:$(EXEC)
+$(EXEC):$(SRC)
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(SRC) $(LDLIBS) $(LIBS)
+
+clean:
+ -rm -f $(EXEC) *.elf *.gdb *.o
diff --git a/recipes-devtools/flowtable/files/src/api.c b/recipes-devtools/flowtable/files/src/api.c
new file mode 100644
index 0000000..17b88b4
--- /dev/null
+++ b/recipes-devtools/flowtable/files/src/api.c
@@ -0,0 +1,106 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "netfilter_flowtable.h"
+
+static void attr_dump(struct nfattr *attr)
+{
+ char *data = nla_data(attr);
+ int i = 0;
+
+ while (i < nal_len(attr)) {
+ printf("%x ", *(data + i));
+ i++;
+ if (i % 16 == 0)
+ printf("\n");
+ }
+ printf("\n");
+}
+
+struct ftnl_handle* ftnl_open(void)
+{
+ struct ftnl_handle *h = NULL;
+
+ h = malloc(sizeof(struct ftnl_handle));
+ if (!h)
+ return NULL;
+
+ h->nfnlh = nfnl_open();
+ if (!h->nfnlh) {
+ printf("nfnl open fail\n");
+ free(h);
+ return NULL;
+ }
+
+ h->ftnlssh = nfnl_subsys_open(h->nfnlh, NFNL_SUBSYS_FLOWTABLE, 1, 0);
+ if (!h->ftnlssh) {
+ nfnl_close(h->nfnlh);
+ printf("subsys open fail\n");
+ free(h);
+ return NULL;
+ }
+
+ return h;
+}
+
+void ftnl_close(struct ftnl_handle *h)
+{
+ nfnl_subsys_close(h->ftnlssh);
+ nfnl_close(h->nfnlh);
+ free(h);
+}
+
+static void build_tuple(struct nlmsghdr *nlh,size_t size, struct flow_tuple *tuple)
+{
+ struct nfattr *nest_tuple, *nest_ip, *nest_proto;
+
+ nest_tuple = nfnl_nest(nlh, size, FTA_TUPLE);
+
+ nest_ip = nfnl_nest(nlh, size, FTA_TUPLE_IP);
+ nfnl_addattr_l(nlh, size, FTA_IP_V4_SRC, &tuple->sip4, sizeof(uint32_t));
+ nfnl_addattr_l(nlh, size, FTA_IP_V4_DST, &tuple->dip4, sizeof(uint32_t));
+ nfnl_nest_end(nlh, nest_ip);
+
+ nest_proto = nfnl_nest(nlh, size, FTA_TUPLE_PROTO);
+ nfnl_addattr_l(nlh, size, FTA_PROTO_NUM, &tuple->proto, sizeof(uint8_t));
+ nfnl_addattr_l(nlh, size, FTA_PROTO_SPORT, &tuple->sport, sizeof(uint16_t));
+ nfnl_addattr_l(nlh, size, FTA_PROTO_DPORT, &tuple->dport, sizeof(uint16_t));
+ nfnl_nest_end(nlh, nest_proto);
+
+ nfnl_nest_end(nlh,nest_tuple);
+// attr_dump(nest_tuple);
+}
+
+int ftnl_flush_table(struct ftnl_handle *h)
+{
+ struct nlmsghdr nlh;
+ int ret;
+
+ /* construct msg */
+ nfnl_fill_hdr(h->ftnlssh, &nlh, 0, AF_INET, 0,
+ FT_MSG_FLUSH, NLM_F_REQUEST | NLM_F_ACK);
+
+ /* send msg */
+ ret = nfnl_send(h->nfnlh, &nlh);
+ return ret;
+}
+
+int ftnl_del_flow(struct ftnl_handle *h, struct flow_tuple *tuple)
+{
+ const int size = 256;
+ union {
+ char buffer[size];
+ struct nlmsghdr nlh;
+ } u;
+ int ret;
+
+ /* construct msg */
+ nfnl_fill_hdr(h->ftnlssh, &u.nlh, 0, AF_INET, 0,
+ FT_MSG_DEL, NLM_F_REQUEST|NLM_F_ACK);
+ build_tuple(&u.nlh, size, tuple);
+
+ /* send msg */
+ ret = nfnl_send(h->nfnlh, &u.nlh);
+
+ return ret;
+}
diff --git a/recipes-devtools/flowtable/files/src/ftnl.c b/recipes-devtools/flowtable/files/src/ftnl.c
new file mode 100644
index 0000000..30352b2
--- /dev/null
+++ b/recipes-devtools/flowtable/files/src/ftnl.c
@@ -0,0 +1,92 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <getopt.h>
+
+#include "netfilter_flowtable.h"
+
+void usage(void)
+{
+ printf("#########flush flow table\n");
+ printf("ftnl -F\n");
+ printf("#########del flow from offload table\n");
+ printf("ftnl -D [sip] [dip] [proto] [sport] [dport]\n");
+}
+
+int main (int argc, char *argv[])
+{
+ struct ftnl_handle *h;
+ struct flow_tuple tuple = {0};
+ int msg = -1;
+ int c;
+ int ret = -1;
+ const char* optstring = "FD";
+ struct option opts[] = {
+ {"sip", required_argument, NULL, 's'},
+ {"dip", required_argument, NULL, 'd'},
+ {"proto", required_argument, NULL, 'p'},
+ {"sport", required_argument, NULL, 'm'},
+ {"dport", required_argument, NULL, 'n'}
+ };
+
+ /* open netlink socket */
+ h = ftnl_open();
+ if (!h)
+ return ret;
+
+ /* parse arg */
+ while ((c = getopt_long(argc, argv, optstring, opts, NULL)) != -1) {
+ switch (c) {
+ case 'F':
+ msg = FT_MSG_FLUSH;
+ break;
+ case 'D':
+ msg = FT_MSG_DEL;
+ break;
+ case 's':
+ inet_aton(optarg, &tuple.sip4);
+ break;
+ case 'd':
+ inet_aton(optarg, &tuple.dip4);
+ break;
+ case 'p':
+ if (!strcmp(optarg, "tcp"))
+ tuple.proto = IPPROTO_TCP;
+ else if (!strcmp(optarg, "udp"))
+ tuple.proto = IPPROTO_UDP;
+ else {
+ printf("proto bad value "
+ "pls set proto to udp or tcp "
+ "arg : %s\n", optarg);
+ goto out;
+ }
+ break;
+ case 'm':
+ tuple.sport = htons(atoi(optarg));
+ break;
+ case 'n':
+ tuple.dport = htons(atoi(optarg));
+ break;
+ default:
+ usage();
+ goto out;
+ }
+ }
+
+ switch (msg) {
+ case FT_MSG_FLUSH:
+ ftnl_flush_table(h);
+ break;
+ case FT_MSG_DEL:
+ ftnl_del_flow(h, &tuple);
+ break;
+ default:
+ break;
+ }
+
+out:
+ ftnl_close(h);
+ return ret;
+}
diff --git a/recipes-devtools/flowtable/files/src/netfilter_flowtable.h b/recipes-devtools/flowtable/files/src/netfilter_flowtable.h
new file mode 100644
index 0000000..3ea8916
--- /dev/null
+++ b/recipes-devtools/flowtable/files/src/netfilter_flowtable.h
@@ -0,0 +1,63 @@
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <libnfnetlink/libnfnetlink.h>
+
+struct ftnl_handle {
+ struct nfnl_handle *nfnlh;
+ struct nfnl_subsys_handle *ftnlssh;
+};
+
+struct flow_tuple {
+ struct in_addr sip4;
+ struct in_addr dip4;
+ unsigned char proto;
+ unsigned short int sport;
+ unsigned short int dport;
+};
+
+enum ft_msg_types{
+ FT_MSG_DEL,
+ FT_MSG_ADD, //not support now
+ FT_MSG_FLUSH,
+ FT_MSG_MAX
+};
+
+enum ftattr_type {
+ FTA_UNSPEC,
+ FTA_TUPLE,
+ __FTA_MAX
+};
+#define FTA_MAX (__FTA_MAX - 1)
+
+enum ftattr_tuple {
+ FTA_TUPLE_UNSPEC,
+ FTA_TUPLE_IP,
+ FTA_TUPLE_PROTO,
+ FTA_TUPLE_ZONE,
+ __FTA_TUPLE_MAX
+};
+#define FTA_TUPLE_MAX (__FTA_TUPLE_MAX - 1)
+
+enum ftattr_ip {
+ FTA_IP_UNSPEC,
+ FTA_IP_V4_SRC,
+ FTA_IP_V4_DST,
+ FTA_IP_V6_SRC,
+ FTA_IP_V6_DST,
+ __FTA_IP_MAX
+};
+#define FTA_IP_MAX (__FTA_IP_MAX - 1)
+
+enum ftattr_l4proto {
+ FTA_PROTO_UNSPEC,
+ FTA_PROTO_NUM,
+ FTA_PROTO_SPORT,
+ FTA_PROTO_DPORT,
+ __FTA_PROTO_MAX
+};
+#define FTA_PROTO_MAX (__FTA_PROTO_MAX - 1)
+
+struct ftnl_handle* ftnl_open(void);
+void ftnl_close(struct ftnl_handle *h);
+int ftnl_flush_table(struct ftnl_handle *h);
+int ftnl_del_flow(struct ftnl_handle *h, struct flow_tuple *tuple);
diff --git a/recipes-devtools/flowtable/flowtable.bb b/recipes-devtools/flowtable/flowtable.bb
new file mode 100644
index 0000000..007bece
--- /dev/null
+++ b/recipes-devtools/flowtable/flowtable.bb
@@ -0,0 +1,28 @@
+SUMMARY = "netfilter_flowtable tools"
+SECTION = "applications"
+LICENSE = "GPLv2"
+LIC_FILES_CHKSUM = "file://COPYING;md5=751419260aa954499f7abaabaa882bbe"
+
+
+DEPENDS = "libnfnetlink libmnl"
+
+SRC_URI = " \
+ file://COPYING;subdir=git/src \
+ file://src;subdir=git \
+ "
+
+S = "${WORKDIR}/git/src"
+
+CFLAGS_prepend = " \
+ -fPIC -D_GNU_SOURCE \
+ -I${S} \
+ "
+
+do_compile() {
+ oe_runmake -C ${S} "LIBS=-L${STAGING_LIBDIR} -lnfnetlink -lm"
+}
+
+do_install() {
+ install -d ${D}/usr/bin
+ install -m 0755 ${S}/ftnl ${D}/usr/bin
+}
diff --git a/recipes-devtools/smp/files/smp-mt76.sh b/recipes-devtools/smp/files/smp-mt76.sh
index b71c90a..c76e2f8 100644
--- a/recipes-devtools/smp/files/smp-mt76.sh
+++ b/recipes-devtools/smp/files/smp-mt76.sh
@@ -149,7 +149,7 @@
CPU0_RPS="$WIFI_IF_LIST"
CPU1_RPS="$WIFI_IF_LIST"
- CPU2_RPS="$WIFI_IF_LIST"
+ CPU2_RPS=""
CPU3_RPS=""
fi
dbg2 "CPU0_AFFINITY = $CPU0_AFFINITY"
diff --git a/recipes-filter/libnfnetlink/files/0001-rdkb-support-netfilter-netlink-ftnl-tools.patch b/recipes-filter/libnfnetlink/files/0001-rdkb-support-netfilter-netlink-ftnl-tools.patch
new file mode 100644
index 0000000..e2e837e
--- /dev/null
+++ b/recipes-filter/libnfnetlink/files/0001-rdkb-support-netfilter-netlink-ftnl-tools.patch
@@ -0,0 +1,9 @@
+--- a/include/libnfnetlink/linux_nfnetlink.h.bak 2023-03-07 17:16:35.972965700 +0800
++++ b/include/libnfnetlink/linux_nfnetlink.h 2023-03-07 17:50:33.115953207 +0800
+@@ -49,5 +49,6 @@
+ #define NFNL_SUBSYS_OSF 5
+ #define NFNL_SUBSYS_IPSET 6
+ #define NFNL_SUBSYS_COUNT 7
++#define NFNL_SUBSYS_FLOWTABLE 12
+
+ #endif /* _NFNETLINK_H */
diff --git a/recipes-filter/libnfnetlink/libnfnetlink_1.0.1.bbappend b/recipes-filter/libnfnetlink/libnfnetlink_1.0.1.bbappend
new file mode 100644
index 0000000..d93c9b5
--- /dev/null
+++ b/recipes-filter/libnfnetlink/libnfnetlink_1.0.1.bbappend
@@ -0,0 +1,3 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/files:"
+
+SRC_URI_append += "file://0001-rdkb-support-netfilter-netlink-ftnl-tools.patch"
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/hack-5.4/800-leds-leds-bcm63138-read-default-trigger-from-OF.patch b/recipes-kernel/linux/linux-mediatek-5.4/generic/hack-5.4/800-leds-leds-bcm63138-read-default-trigger-from-OF.patch
new file mode 100644
index 0000000..684bb9f
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/generic/hack-5.4/800-leds-leds-bcm63138-read-default-trigger-from-OF.patch
@@ -0,0 +1,26 @@
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+Date: Tue, 28 Feb 2023 23:38:30 +0100
+Subject: [PATCH] leds: leds-bcm63138: read default trigger from OF
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+It's needed in kernels older than 5.10 due to the missing commit
+c49d6cab0d7f ("leds: parse linux,default-trigger DT property in LED
+core").
+
+Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
+---
+ drivers/leds/blink/leds-bcm63138.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/leds/blink/leds-bcm63138.c
++++ b/drivers/leds/blink/leds-bcm63138.c
+@@ -228,6 +228,7 @@ static void bcm63138_leds_create_led(str
+ led->cdev.max_brightness = BCM63138_MAX_BRIGHTNESS;
+ led->cdev.brightness_set = bcm63138_leds_brightness_set;
+ led->cdev.blink_set = bcm63138_leds_blink_set;
++ led->cdev.default_trigger = of_get_property(np, "linux,default-trigger", NULL);
+
+ err = devm_led_classdev_register_ext(dev, &led->cdev, &init_data);
+ if (err) {
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/generic/hack-5.4/hack-5.4.inc b/recipes-kernel/linux/linux-mediatek-5.4/generic/hack-5.4/hack-5.4.inc
index 8597603..431e127 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/generic/hack-5.4/hack-5.4.inc
+++ b/recipes-kernel/linux/linux-mediatek-5.4/generic/hack-5.4/hack-5.4.inc
@@ -34,6 +34,7 @@
file://711-net-dsa-mv88e6xxx-disable-ATU-violation.patch \
file://721-phy_packets.patch \
file://773-bgmac-add-srab-switch.patch \
+ file://800-leds-leds-bcm63138-read-default-trigger-from-OF.patch \
file://901-debloat_sock_diag.patch \
file://902-debloat_proc.patch \
file://904-debloat_dma_buf.patch \
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988.dtsi b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988.dtsi
index 46f0708..1f881ea 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988.dtsi
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988.dtsi
@@ -286,9 +286,17 @@
#size-cells = <2>;
ranges;
- /* 192 KiB reserved for ARM Trusted Firmware (BL31) */
+ ramoops: ramoops@42ff0000{
+ compatible = "ramoops";
+ reg = <0x0 0x42ff0000 0x0 0x10000>;
+ record-size = <0x2000>;
+ console-size = <0x2000>;
+ pmsg-size = <0x2000>;
+ };
+
+ /* 256 KiB reserved for ARM Trusted Firmware (BL31) */
secmon_reserved: secmon@43000000 {
- reg = <0 0x43000000 0 0x30000>;
+ reg = <0 0x43000000 0 0x40000>;
no-map;
};
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-emmc.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-emmc.dts
index e9566d6..428d3d2 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-emmc.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-emmc.dts
@@ -207,16 +207,16 @@
reg = <0>;
compatible = "ethernet-phy-ieee802.3-c45";
reset-gpios = <&pio 72 1>;
- reset-assert-us = <1000000>;
- reset-deassert-us = <1000000>;
+ reset-assert-us = <100000>;
+ reset-deassert-us = <221000>;
};
phy1: ethernet-phy@8 {
reg = <8>;
compatible = "ethernet-phy-ieee802.3-c45";
reset-gpios = <&pio 71 1>;
- reset-assert-us = <1000000>;
- reset-deassert-us = <1000000>;
+ reset-assert-us = <100000>;
+ reset-deassert-us = <221000>;
};
switch@0 {
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-sd.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-sd.dts
index e043757..4805f15 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-sd.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-sd.dts
@@ -198,16 +198,16 @@
reg = <0>;
compatible = "ethernet-phy-ieee802.3-c45";
reset-gpios = <&pio 72 1>;
- reset-assert-us = <1000000>;
- reset-deassert-us = <1000000>;
+ reset-assert-us = <100000>;
+ reset-deassert-us = <221000>;
};
phy1: ethernet-phy@8 {
reg = <8>;
compatible = "ethernet-phy-ieee802.3-c45";
reset-gpios = <&pio 71 1>;
- reset-assert-us = <1000000>;
- reset-deassert-us = <1000000>;
+ reset-assert-us = <100000>;
+ reset-deassert-us = <221000>;
};
switch@0 {
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-snfi-nand.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-snfi-nand.dts
index 111e43f..d2ce655 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-snfi-nand.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-snfi-nand.dts
@@ -233,16 +233,16 @@
reg = <0>;
compatible = "ethernet-phy-ieee802.3-c45";
reset-gpios = <&pio 72 1>;
- reset-assert-us = <1000000>;
- reset-deassert-us = <1000000>;
+ reset-assert-us = <100000>;
+ reset-deassert-us = <221000>;
};
phy1: ethernet-phy@8 {
reg = <8>;
compatible = "ethernet-phy-ieee802.3-c45";
reset-gpios = <&pio 71 1>;
- reset-assert-us = <1000000>;
- reset-deassert-us = <1000000>;
+ reset-assert-us = <100000>;
+ reset-deassert-us = <221000>;
};
switch@0 {
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nand.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nand.dts
index 0352d83..fc9d17c 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nand.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nand.dts
@@ -171,6 +171,11 @@
compatible = "wlf,wm8960";
reg = <0x1a>;
};
+
+ dps368: dps368@77 {
+ compatible = "infineon,dps310";
+ reg = <0x77>;
+ };
};
&spi0 {
@@ -373,16 +378,16 @@
reg = <0>;
compatible = "ethernet-phy-ieee802.3-c45";
reset-gpios = <&pio 72 1>;
- reset-assert-us = <1000000>;
- reset-deassert-us = <1000000>;
+ reset-assert-us = <100000>;
+ reset-deassert-us = <221000>;
};
phy1: ethernet-phy@8 {
reg = <8>;
compatible = "ethernet-phy-ieee802.3-c45";
reset-gpios = <&pio 71 1>;
- reset-assert-us = <1000000>;
- reset-deassert-us = <1000000>;
+ reset-assert-us = <100000>;
+ reset-deassert-us = <221000>;
};
switch@0 {
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nor.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nor.dts
index 99677f6..093a55d 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nor.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nor.dts
@@ -223,16 +223,16 @@
reg = <0>;
compatible = "ethernet-phy-ieee802.3-c45";
reset-gpios = <&pio 72 1>;
- reset-assert-us = <1000000>;
- reset-deassert-us = <1000000>;
+ reset-assert-us = <100000>;
+ reset-deassert-us = <221000>;
};
phy1: ethernet-phy@8 {
reg = <8>;
compatible = "ethernet-phy-ieee802.3-c45";
reset-gpios = <&pio 71 1>;
- reset-assert-us = <1000000>;
- reset-deassert-us = <1000000>;
+ reset-assert-us = <100000>;
+ reset-deassert-us = <221000>;
};
switch@0 {
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-e2p5g-spim-nand.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-e2p5g-spim-nand.dts
index fee356d..74fa426 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-e2p5g-spim-nand.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-dsa-e2p5g-spim-nand.dts
@@ -134,6 +134,11 @@
pinctrl-names = "default";
pinctrl-0 = <&i2c1_pins>;
status = "okay";
+
+ dps368: dps368@77 {
+ compatible = "infineon,dps310";
+ reg = <0x77>;
+ };
};
&pwm {
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-spim-nand-4pcie.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-spim-nand-4pcie.dts
index e674902..3e61896 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-spim-nand-4pcie.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-spim-nand-4pcie.dts
@@ -329,16 +329,16 @@
reg = <0>;
compatible = "ethernet-phy-ieee802.3-c45";
reset-gpios = <&pio 72 1>;
- reset-assert-us = <1000000>;
- reset-deassert-us = <1000000>;
+ reset-assert-us = <100000>;
+ reset-deassert-us = <221000>;
};
phy1: ethernet-phy@8 {
reg = <8>;
compatible = "ethernet-phy-ieee802.3-c45";
reset-gpios = <&pio 71 1>;
- reset-assert-us = <1000000>;
- reset-deassert-us = <1000000>;
+ reset-assert-us = <100000>;
+ reset-deassert-us = <221000>;
};
};
};
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-spim-nand.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-spim-nand.dts
index 6c50c0c..53d0b93 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-spim-nand.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988a-gsw-10g-spim-nand.dts
@@ -349,16 +349,16 @@
reg = <0>;
compatible = "ethernet-phy-ieee802.3-c45";
reset-gpios = <&pio 72 1>;
- reset-assert-us = <1000000>;
- reset-deassert-us = <1000000>;
+ reset-assert-us = <100000>;
+ reset-deassert-us = <221000>;
};
phy1: ethernet-phy@8 {
reg = <8>;
compatible = "ethernet-phy-ieee802.3-c45";
reset-gpios = <&pio 71 1>;
- reset-assert-us = <1000000>;
- reset-deassert-us = <1000000>;
+ reset-assert-us = <100000>;
+ reset-deassert-us = <221000>;
};
};
};
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988c-dsa-10g-emmc.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988c-dsa-10g-emmc.dts
index 02f6e38..4cd6054 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988c-dsa-10g-emmc.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988c-dsa-10g-emmc.dts
@@ -199,8 +199,8 @@
reg = <0>;
compatible = "ethernet-phy-ieee802.3-c45";
reset-gpios = <&pio 72 1>;
- reset-assert-us = <1000000>;
- reset-deassert-us = <1000000>;
+ reset-assert-us = <100000>;
+ reset-deassert-us = <221000>;
};
switch@0 {
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988c-dsa-10g-sd.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988c-dsa-10g-sd.dts
index 2c69653..e8743bf 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988c-dsa-10g-sd.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988c-dsa-10g-sd.dts
@@ -190,8 +190,8 @@
reg = <0>;
compatible = "ethernet-phy-ieee802.3-c45";
reset-gpios = <&pio 72 1>;
- reset-assert-us = <1000000>;
- reset-deassert-us = <1000000>;
+ reset-assert-us = <100000>;
+ reset-deassert-us = <221000>;
};
switch@0 {
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988c-dsa-10g-snfi-nand.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988c-dsa-10g-snfi-nand.dts
index ada514a..fc3f58d 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988c-dsa-10g-snfi-nand.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988c-dsa-10g-snfi-nand.dts
@@ -225,8 +225,8 @@
reg = <0>;
compatible = "ethernet-phy-ieee802.3-c45";
reset-gpios = <&pio 72 1>;
- reset-assert-us = <1000000>;
- reset-deassert-us = <1000000>;
+ reset-assert-us = <100000>;
+ reset-deassert-us = <221000>;
};
switch@0 {
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988c-dsa-10g-spim-nand.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988c-dsa-10g-spim-nand.dts
index f4729f9..22ec0a1 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988c-dsa-10g-spim-nand.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988c-dsa-10g-spim-nand.dts
@@ -365,8 +365,8 @@
reg = <0>;
compatible = "ethernet-phy-ieee802.3-c45";
reset-gpios = <&pio 3 1>;
- reset-assert-us = <1000000>;
- reset-deassert-us = <1000000>;
+ reset-assert-us = <100000>;
+ reset-deassert-us = <221000>;
};
switch@0 {
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988c-dsa-10g-spim-nor.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988c-dsa-10g-spim-nor.dts
index 9ebf02c..26fd171 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988c-dsa-10g-spim-nor.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988c-dsa-10g-spim-nor.dts
@@ -215,8 +215,8 @@
reg = <0>;
compatible = "ethernet-phy-ieee802.3-c45";
reset-gpios = <&pio 72 1>;
- reset-assert-us = <1000000>;
- reset-deassert-us = <1000000>;
+ reset-assert-us = <100000>;
+ reset-deassert-us = <221000>;
};
switch@0 {
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988c-gsw-10g-spim-nand.dts b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988c-gsw-10g-spim-nand.dts
index 65e747a..473ea27 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988c-gsw-10g-spim-nand.dts
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7988c-gsw-10g-spim-nand.dts
@@ -341,8 +341,8 @@
reg = <0>;
compatible = "ethernet-phy-ieee802.3-c45";
reset-gpios = <&pio 72 1>;
- reset-assert-us = <1000000>;
- reset-deassert-us = <1000000>;
+ reset-assert-us = <100000>;
+ reset-deassert-us = <221000>;
};
};
};
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/clk/mediatek/clk-mt7988.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/clk/mediatek/clk-mt7988.c
index f3bb72d..93585ce 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/clk/mediatek/clk-mt7988.c
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/clk/mediatek/clk-mt7988.c
@@ -772,7 +772,8 @@
"infra_66m_mck", 17),
GATE_INFRA2(CK_INFRA_66M_FLASHIF_AXI, "infra_hf_66m_flashif_axi",
"infra_66m_mck", 18),
- GATE_INFRA2(CK_INFRA_RTC, "infra_f_frtc", "infra_lb_mux_frtc", 19),
+ GATE_CRITICAL(CK_INFRA_RTC, "infra_f_frtc", "infra_lb_mux_frtc",
+ &infra2_cg_regs, 19),
GATE_INFRA2(CK_INFRA_26M_ADC_BCK, "infra_f_26m_adc_bck",
"infra_f26m_o1", 20),
GATE_INFRA2(CK_INFRA_RC_ADC, "infra_f_frc_adc", "infra_f_26m_adc_bck",
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/iio/pressure/dps310.c b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/iio/pressure/dps310.c
new file mode 100644
index 0000000..72640cb
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/files-5.4/drivers/iio/pressure/dps310.c
@@ -0,0 +1,848 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright IBM Corp 2019
+/*
+ * The DPS310 is a barometric pressure and temperature sensor.
+ * Currently only reading a single temperature is supported by
+ * this driver.
+ *
+ * https://www.infineon.com/dgdl/?fileId=5546d462576f34750157750826c42242
+ *
+ * Temperature calculation:
+ * c0 * 0.5 + c1 * T_raw / kT °C
+ *
+ * TODO:
+ * - Optionally support the FIFO
+ */
+
+#include <linux/i2c.h>
+#include <linux/limits.h>
+#include <linux/math64.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+
+#define DPS310_DEV_NAME "dps310"
+
+#define DPS310_PRS_B0 0x00
+#define DPS310_PRS_B1 0x01
+#define DPS310_PRS_B2 0x02
+#define DPS310_TMP_B0 0x03
+#define DPS310_TMP_B1 0x04
+#define DPS310_TMP_B2 0x05
+#define DPS310_PRS_CFG 0x06
+#define DPS310_PRS_RATE_BITS GENMASK(6, 4)
+#define DPS310_PRS_PRC_BITS GENMASK(3, 0)
+#define DPS310_TMP_CFG 0x07
+#define DPS310_TMP_RATE_BITS GENMASK(6, 4)
+#define DPS310_TMP_PRC_BITS GENMASK(3, 0)
+#define DPS310_TMP_EXT BIT(7)
+#define DPS310_MEAS_CFG 0x08
+#define DPS310_MEAS_CTRL_BITS GENMASK(2, 0)
+#define DPS310_PRS_EN BIT(0)
+#define DPS310_TEMP_EN BIT(1)
+#define DPS310_BACKGROUND BIT(2)
+#define DPS310_PRS_RDY BIT(4)
+#define DPS310_TMP_RDY BIT(5)
+#define DPS310_SENSOR_RDY BIT(6)
+#define DPS310_COEF_RDY BIT(7)
+#define DPS310_CFG_REG 0x09
+#define DPS310_INT_HL BIT(7)
+#define DPS310_TMP_SHIFT_EN BIT(3)
+#define DPS310_PRS_SHIFT_EN BIT(4)
+#define DPS310_FIFO_EN BIT(5)
+#define DPS310_SPI_EN BIT(6)
+#define DPS310_RESET 0x0c
+#define DPS310_RESET_MAGIC 0x09
+#define DPS310_COEF_BASE 0x10
+
+/* Make sure sleep time is <= 20ms for usleep_range */
+#define DPS310_POLL_SLEEP_US(t) min(20000, (t) / 8)
+/* Silently handle error in rate value here */
+#define DPS310_POLL_TIMEOUT_US(rc) ((rc) <= 0 ? 1000000 : 1000000 / (rc))
+
+#define DPS310_PRS_BASE DPS310_PRS_B0
+#define DPS310_TMP_BASE DPS310_TMP_B0
+
+/*
+ * These values (defined in the spec) indicate how to scale the raw register
+ * values for each level of precision available.
+ */
+static const int scale_factors[] = {
+ 524288,
+ 1572864,
+ 3670016,
+ 7864320,
+ 253952,
+ 516096,
+ 1040384,
+ 2088960,
+};
+
+struct dps310_data {
+ struct i2c_client *client;
+ struct regmap *regmap;
+ struct mutex lock; /* Lock for sequential HW access functions */
+
+ s32 c0, c1;
+ s32 c00, c10, c20, c30, c01, c11, c21;
+ s32 pressure_raw;
+ s32 temp_raw;
+};
+
+static const struct iio_chan_spec dps310_channels[] = {
+ {
+ .type = IIO_TEMP,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO) |
+ BIT(IIO_CHAN_INFO_SAMP_FREQ) |
+ BIT(IIO_CHAN_INFO_PROCESSED),
+ },
+ {
+ .type = IIO_PRESSURE,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO) |
+ BIT(IIO_CHAN_INFO_SAMP_FREQ) |
+ BIT(IIO_CHAN_INFO_PROCESSED),
+ },
+};
+
+/* To be called after checking the COEF_RDY bit in MEAS_CFG */
+static int dps310_get_coefs(struct dps310_data *data)
+{
+ int rc;
+ u8 coef[18];
+ u32 c0, c1;
+ u32 c00, c10, c20, c30, c01, c11, c21;
+
+ /* Read all sensor calibration coefficients from the COEF registers. */
+ rc = regmap_bulk_read(data->regmap, DPS310_COEF_BASE, coef,
+ sizeof(coef));
+ if (rc < 0)
+ return rc;
+
+ /*
+ * Calculate temperature calibration coefficients c0 and c1. The
+ * numbers are 12-bit 2's complement numbers.
+ */
+ c0 = (coef[0] << 4) | (coef[1] >> 4);
+ data->c0 = sign_extend32(c0, 11);
+
+ c1 = ((coef[1] & GENMASK(3, 0)) << 8) | coef[2];
+ data->c1 = sign_extend32(c1, 11);
+
+ /*
+ * Calculate pressure calibration coefficients. c00 and c10 are 20 bit
+ * 2's complement numbers, while the rest are 16 bit 2's complement
+ * numbers.
+ */
+ c00 = (coef[3] << 12) | (coef[4] << 4) | (coef[5] >> 4);
+ data->c00 = sign_extend32(c00, 19);
+
+ c10 = ((coef[5] & GENMASK(3, 0)) << 16) | (coef[6] << 8) | coef[7];
+ data->c10 = sign_extend32(c10, 19);
+
+ c01 = (coef[8] << 8) | coef[9];
+ data->c01 = sign_extend32(c01, 15);
+
+ c11 = (coef[10] << 8) | coef[11];
+ data->c11 = sign_extend32(c11, 15);
+
+ c20 = (coef[12] << 8) | coef[13];
+ data->c20 = sign_extend32(c20, 15);
+
+ c21 = (coef[14] << 8) | coef[15];
+ data->c21 = sign_extend32(c21, 15);
+
+ c30 = (coef[16] << 8) | coef[17];
+ data->c30 = sign_extend32(c30, 15);
+
+ return 0;
+}
+
+static int dps310_get_pres_precision(struct dps310_data *data)
+{
+ int rc;
+ int val;
+
+ rc = regmap_read(data->regmap, DPS310_PRS_CFG, &val);
+ if (rc < 0)
+ return rc;
+
+ return BIT(val & GENMASK(2, 0));
+}
+
+static int dps310_get_temp_precision(struct dps310_data *data)
+{
+ int rc;
+ int val;
+
+ rc = regmap_read(data->regmap, DPS310_TMP_CFG, &val);
+ if (rc < 0)
+ return rc;
+
+ /*
+ * Scale factor is bottom 4 bits of the register, but 1111 is
+ * reserved so just grab bottom three
+ */
+ return BIT(val & GENMASK(2, 0));
+}
+
+/* Called with lock held */
+static int dps310_set_pres_precision(struct dps310_data *data, int val)
+{
+ int rc;
+ u8 shift_en;
+
+ if (val < 0 || val > 128)
+ return -EINVAL;
+
+ shift_en = val >= 16 ? DPS310_PRS_SHIFT_EN : 0;
+ rc = regmap_write_bits(data->regmap, DPS310_CFG_REG,
+ DPS310_PRS_SHIFT_EN, shift_en);
+ if (rc)
+ return rc;
+
+ return regmap_update_bits(data->regmap, DPS310_PRS_CFG,
+ DPS310_PRS_PRC_BITS, ilog2(val));
+}
+
+/* Called with lock held */
+static int dps310_set_temp_precision(struct dps310_data *data, int val)
+{
+ int rc;
+ u8 shift_en;
+
+ if (val < 0 || val > 128)
+ return -EINVAL;
+
+ shift_en = val >= 16 ? DPS310_TMP_SHIFT_EN : 0;
+ rc = regmap_write_bits(data->regmap, DPS310_CFG_REG,
+ DPS310_TMP_SHIFT_EN, shift_en);
+ if (rc)
+ return rc;
+
+ return regmap_update_bits(data->regmap, DPS310_TMP_CFG,
+ DPS310_TMP_PRC_BITS, ilog2(val));
+}
+
+/* Called with lock held */
+static int dps310_set_pres_samp_freq(struct dps310_data *data, int freq)
+{
+ u8 val;
+
+ if (freq < 0 || freq > 128)
+ return -EINVAL;
+
+ val = ilog2(freq) << 4;
+
+ return regmap_update_bits(data->regmap, DPS310_PRS_CFG,
+ DPS310_PRS_RATE_BITS, val);
+}
+
+/* Called with lock held */
+static int dps310_set_temp_samp_freq(struct dps310_data *data, int freq)
+{
+ u8 val;
+
+ if (freq < 0 || freq > 128)
+ return -EINVAL;
+
+ val = ilog2(freq) << 4;
+
+ return regmap_update_bits(data->regmap, DPS310_TMP_CFG,
+ DPS310_TMP_RATE_BITS, val);
+}
+
+static int dps310_get_pres_samp_freq(struct dps310_data *data)
+{
+ int rc;
+ int val;
+
+ rc = regmap_read(data->regmap, DPS310_PRS_CFG, &val);
+ if (rc < 0)
+ return rc;
+
+ return BIT((val & DPS310_PRS_RATE_BITS) >> 4);
+}
+
+static int dps310_get_temp_samp_freq(struct dps310_data *data)
+{
+ int rc;
+ int val;
+
+ rc = regmap_read(data->regmap, DPS310_TMP_CFG, &val);
+ if (rc < 0)
+ return rc;
+
+ return BIT((val & DPS310_TMP_RATE_BITS) >> 4);
+}
+
+static int dps310_get_pres_k(struct dps310_data *data)
+{
+ int rc = dps310_get_pres_precision(data);
+
+ if (rc < 0)
+ return rc;
+
+ return scale_factors[ilog2(rc)];
+}
+
+static int dps310_get_temp_k(struct dps310_data *data)
+{
+ int rc = dps310_get_temp_precision(data);
+
+ if (rc < 0)
+ return rc;
+
+ return scale_factors[ilog2(rc)];
+}
+
+static int dps310_read_pres_raw(struct dps310_data *data)
+{
+ int rc;
+ int rate;
+ int ready;
+ int timeout;
+ s32 raw;
+ u8 val[3];
+
+ if (mutex_lock_interruptible(&data->lock))
+ return -EINTR;
+
+ rate = dps310_get_pres_samp_freq(data);
+ timeout = DPS310_POLL_TIMEOUT_US(rate);
+
+ /* Poll for sensor readiness; base the timeout upon the sample rate. */
+ rc = regmap_read_poll_timeout(data->regmap, DPS310_MEAS_CFG, ready,
+ ready & DPS310_PRS_RDY,
+ DPS310_POLL_SLEEP_US(timeout), timeout);
+ if (rc)
+ goto done;
+
+ rc = regmap_bulk_read(data->regmap, DPS310_PRS_BASE, val, sizeof(val));
+ if (rc < 0)
+ goto done;
+
+ raw = (val[0] << 16) | (val[1] << 8) | val[2];
+ data->pressure_raw = sign_extend32(raw, 23);
+
+done:
+ mutex_unlock(&data->lock);
+ return rc;
+}
+
+/* Called with lock held */
+static int dps310_read_temp_ready(struct dps310_data *data)
+{
+ int rc;
+ u8 val[3];
+ s32 raw;
+
+ rc = regmap_bulk_read(data->regmap, DPS310_TMP_BASE, val, sizeof(val));
+ if (rc < 0)
+ return rc;
+
+ raw = (val[0] << 16) | (val[1] << 8) | val[2];
+ data->temp_raw = sign_extend32(raw, 23);
+
+ return 0;
+}
+
+static int dps310_read_temp_raw(struct dps310_data *data)
+{
+ int rc;
+ int rate;
+ int ready;
+ int timeout;
+
+ if (mutex_lock_interruptible(&data->lock))
+ return -EINTR;
+
+ rate = dps310_get_temp_samp_freq(data);
+ timeout = DPS310_POLL_TIMEOUT_US(rate);
+
+ /* Poll for sensor readiness; base the timeout upon the sample rate. */
+ rc = regmap_read_poll_timeout(data->regmap, DPS310_MEAS_CFG, ready,
+ ready & DPS310_TMP_RDY,
+ DPS310_POLL_SLEEP_US(timeout), timeout);
+ if (rc < 0)
+ goto done;
+
+ rc = dps310_read_temp_ready(data);
+
+done:
+ mutex_unlock(&data->lock);
+ return rc;
+}
+
+static bool dps310_is_writeable_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case DPS310_PRS_CFG:
+ case DPS310_TMP_CFG:
+ case DPS310_MEAS_CFG:
+ case DPS310_CFG_REG:
+ case DPS310_RESET:
+ /* No documentation available on the registers below */
+ case 0x0e:
+ case 0x0f:
+ case 0x62:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool dps310_is_volatile_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case DPS310_PRS_B0:
+ case DPS310_PRS_B1:
+ case DPS310_PRS_B2:
+ case DPS310_TMP_B0:
+ case DPS310_TMP_B1:
+ case DPS310_TMP_B2:
+ case DPS310_MEAS_CFG:
+ case 0x32: /* No documentation available on this register */
+ return true;
+ default:
+ return false;
+ }
+}
+
+static int dps310_write_raw(struct iio_dev *iio,
+ struct iio_chan_spec const *chan, int val,
+ int val2, long mask)
+{
+ int rc;
+ struct dps310_data *data = iio_priv(iio);
+
+ if (mutex_lock_interruptible(&data->lock))
+ return -EINTR;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ switch (chan->type) {
+ case IIO_PRESSURE:
+ rc = dps310_set_pres_samp_freq(data, val);
+ break;
+
+ case IIO_TEMP:
+ rc = dps310_set_temp_samp_freq(data, val);
+ break;
+
+ default:
+ rc = -EINVAL;
+ break;
+ }
+ break;
+
+ case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
+ switch (chan->type) {
+ case IIO_PRESSURE:
+ rc = dps310_set_pres_precision(data, val);
+ break;
+
+ case IIO_TEMP:
+ rc = dps310_set_temp_precision(data, val);
+ break;
+
+ default:
+ rc = -EINVAL;
+ break;
+ }
+ break;
+
+ default:
+ rc = -EINVAL;
+ break;
+ }
+
+ mutex_unlock(&data->lock);
+ return rc;
+}
+
+static int dps310_calculate_pressure(struct dps310_data *data)
+{
+ int i;
+ int rc;
+ int t_ready;
+ int kpi = dps310_get_pres_k(data);
+ int kti = dps310_get_temp_k(data);
+ s64 rem = 0ULL;
+ s64 pressure = 0ULL;
+ s64 p;
+ s64 t;
+ s64 denoms[7];
+ s64 nums[7];
+ s64 rems[7];
+ s64 kp;
+ s64 kt;
+
+ if (kpi < 0)
+ return kpi;
+
+ if (kti < 0)
+ return kti;
+
+ kp = (s64)kpi;
+ kt = (s64)kti;
+
+ /* Refresh temp if it's ready, otherwise just use the latest value */
+ if (mutex_trylock(&data->lock)) {
+ rc = regmap_read(data->regmap, DPS310_MEAS_CFG, &t_ready);
+ if (rc >= 0 && t_ready & DPS310_TMP_RDY)
+ dps310_read_temp_ready(data);
+
+ mutex_unlock(&data->lock);
+ }
+
+ p = (s64)data->pressure_raw;
+ t = (s64)data->temp_raw;
+
+ /* Section 4.9.1 of the DPS310 spec; algebra'd to avoid underflow */
+ nums[0] = (s64)data->c00;
+ denoms[0] = 1LL;
+ nums[1] = p * (s64)data->c10;
+ denoms[1] = kp;
+ nums[2] = p * p * (s64)data->c20;
+ denoms[2] = kp * kp;
+ nums[3] = p * p * p * (s64)data->c30;
+ denoms[3] = kp * kp * kp;
+ nums[4] = t * (s64)data->c01;
+ denoms[4] = kt;
+ nums[5] = t * p * (s64)data->c11;
+ denoms[5] = kp * kt;
+ nums[6] = t * p * p * (s64)data->c21;
+ denoms[6] = kp * kp * kt;
+
+ /* Kernel lacks a div64_s64_rem function; denoms are all positive */
+ for (i = 0; i < 7; ++i) {
+ u64 irem;
+
+ if (nums[i] < 0LL) {
+ pressure -= div64_u64_rem(-nums[i], denoms[i], &irem);
+ rems[i] = -irem;
+ } else {
+ pressure += div64_u64_rem(nums[i], denoms[i], &irem);
+ rems[i] = (s64)irem;
+ }
+ }
+
+ /* Increase precision and calculate the remainder sum */
+ for (i = 0; i < 7; ++i)
+ rem += div64_s64((s64)rems[i] * 1000000000LL, denoms[i]);
+
+ pressure += div_s64(rem, 1000000000LL);
+ if (pressure < 0LL)
+ return -ERANGE;
+
+ return (int)min_t(s64, pressure, INT_MAX);
+}
+
+static int dps310_read_pressure(struct dps310_data *data, int *val, int *val2,
+ long mask)
+{
+ int rc;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ rc = dps310_get_pres_samp_freq(data);
+ if (rc < 0)
+ return rc;
+
+ *val = rc;
+ return IIO_VAL_INT;
+
+ case IIO_CHAN_INFO_PROCESSED:
+ rc = dps310_read_pres_raw(data);
+ if (rc)
+ return rc;
+
+ rc = dps310_calculate_pressure(data);
+ if (rc < 0)
+ return rc;
+
+ *val = rc;
+ *val2 = 1000; /* Convert Pa to KPa per IIO ABI */
+ return IIO_VAL_FRACTIONAL;
+
+ case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
+ rc = dps310_get_pres_precision(data);
+ if (rc < 0)
+ return rc;
+
+ *val = rc;
+ return IIO_VAL_INT;
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static int dps310_calculate_temp(struct dps310_data *data)
+{
+ s64 c0;
+ s64 t;
+ int kt = dps310_get_temp_k(data);
+
+ if (kt < 0)
+ return kt;
+
+ /* Obtain inverse-scaled offset */
+ c0 = div_s64((s64)kt * (s64)data->c0, 2);
+
+ /* Add the offset to the unscaled temperature */
+ t = c0 + ((s64)data->temp_raw * (s64)data->c1);
+
+ /* Convert to milliCelsius and scale the temperature */
+ return (int)div_s64(t * 1000LL, kt);
+}
+
+static int dps310_read_temp(struct dps310_data *data, int *val, int *val2,
+ long mask)
+{
+ int rc;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ rc = dps310_get_temp_samp_freq(data);
+ if (rc < 0)
+ return rc;
+
+ *val = rc;
+ return IIO_VAL_INT;
+
+ case IIO_CHAN_INFO_PROCESSED:
+ rc = dps310_read_temp_raw(data);
+ if (rc)
+ return rc;
+
+ rc = dps310_calculate_temp(data);
+ if (rc < 0)
+ return rc;
+
+ *val = rc;
+ return IIO_VAL_INT;
+
+ case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
+ rc = dps310_get_temp_precision(data);
+ if (rc < 0)
+ return rc;
+
+ *val = rc;
+ return IIO_VAL_INT;
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static int dps310_read_raw(struct iio_dev *iio,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ struct dps310_data *data = iio_priv(iio);
+
+ switch (chan->type) {
+ case IIO_PRESSURE:
+ return dps310_read_pressure(data, val, val2, mask);
+
+ case IIO_TEMP:
+ return dps310_read_temp(data, val, val2, mask);
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static void dps310_reset(void *action_data)
+{
+ struct dps310_data *data = action_data;
+
+ regmap_write(data->regmap, DPS310_RESET, DPS310_RESET_MAGIC);
+}
+
+static const struct regmap_config dps310_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .writeable_reg = dps310_is_writeable_reg,
+ .volatile_reg = dps310_is_volatile_reg,
+ .cache_type = REGCACHE_RBTREE,
+ .max_register = 0x62, /* No documentation available on this register */
+};
+
+static const struct iio_info dps310_info = {
+ .read_raw = dps310_read_raw,
+ .write_raw = dps310_write_raw,
+};
+
+/*
+ * Some verions of chip will read temperatures in the ~60C range when
+ * its actually ~20C. This is the manufacturer recommended workaround
+ * to correct the issue. The registers used below are undocumented.
+ */
+static int dps310_temp_workaround(struct dps310_data *data)
+{
+ int rc;
+ int reg;
+
+ rc = regmap_read(data->regmap, 0x32, ®);
+ if (rc < 0)
+ return rc;
+
+ /*
+ * If bit 1 is set then the device is okay, and the workaround does not
+ * need to be applied
+ */
+ if (reg & BIT(1))
+ return 0;
+
+ rc = regmap_write(data->regmap, 0x0e, 0xA5);
+ if (rc < 0)
+ return rc;
+
+ rc = regmap_write(data->regmap, 0x0f, 0x96);
+ if (rc < 0)
+ return rc;
+
+ rc = regmap_write(data->regmap, 0x62, 0x02);
+ if (rc < 0)
+ return rc;
+
+ rc = regmap_write(data->regmap, 0x0e, 0x00);
+ if (rc < 0)
+ return rc;
+
+ return regmap_write(data->regmap, 0x0f, 0x00);
+}
+
+static int dps310_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct dps310_data *data;
+ struct iio_dev *iio;
+ int rc, ready;
+
+ iio = devm_iio_device_alloc(&client->dev, sizeof(*data));
+ if (!iio)
+ return -ENOMEM;
+
+ data = iio_priv(iio);
+ data->client = client;
+ mutex_init(&data->lock);
+
+ iio->name = id->name;
+ iio->channels = dps310_channels;
+ iio->num_channels = ARRAY_SIZE(dps310_channels);
+ iio->info = &dps310_info;
+ iio->modes = INDIO_DIRECT_MODE;
+
+ data->regmap = devm_regmap_init_i2c(client, &dps310_regmap_config);
+ if (IS_ERR(data->regmap))
+ return PTR_ERR(data->regmap);
+
+ /* Register to run the device reset when the device is removed */
+ rc = devm_add_action_or_reset(&client->dev, dps310_reset, data);
+ if (rc)
+ return rc;
+
+ /*
+ * Set up pressure sensor in single sample, one measurement per second
+ * mode
+ */
+ rc = regmap_write(data->regmap, DPS310_PRS_CFG, 0);
+
+ /*
+ * Set up external (MEMS) temperature sensor in single sample, one
+ * measurement per second mode
+ */
+ rc = regmap_write(data->regmap, DPS310_TMP_CFG, DPS310_TMP_EXT);
+ if (rc < 0)
+ return rc;
+
+ /* Temp and pressure shifts are disabled when PRC <= 8 */
+ rc = regmap_write_bits(data->regmap, DPS310_CFG_REG,
+ DPS310_PRS_SHIFT_EN | DPS310_TMP_SHIFT_EN, 0);
+ if (rc < 0)
+ return rc;
+
+ /* MEAS_CFG doesn't update correctly unless first written with 0 */
+ rc = regmap_write_bits(data->regmap, DPS310_MEAS_CFG,
+ DPS310_MEAS_CTRL_BITS, 0);
+ if (rc < 0)
+ return rc;
+
+ /* Turn on temperature and pressure measurement in the background */
+ rc = regmap_write_bits(data->regmap, DPS310_MEAS_CFG,
+ DPS310_MEAS_CTRL_BITS, DPS310_PRS_EN |
+ DPS310_TEMP_EN | DPS310_BACKGROUND);
+ if (rc < 0)
+ return rc;
+
+ /*
+ * Calibration coefficients required for reporting temperature.
+ * They are available 40ms after the device has started
+ */
+ rc = regmap_read_poll_timeout(data->regmap, DPS310_MEAS_CFG, ready,
+ ready & DPS310_COEF_RDY, 10000, 40000);
+ if (rc < 0)
+ return rc;
+
+ rc = dps310_get_coefs(data);
+ if (rc < 0)
+ return rc;
+
+ rc = dps310_temp_workaround(data);
+ if (rc < 0)
+ return rc;
+
+ rc = devm_iio_device_register(&client->dev, iio);
+ if (rc)
+ return rc;
+
+ i2c_set_clientdata(client, iio);
+
+ return 0;
+}
+
+static int dps310_remove(struct i2c_client *client)
+{
+ return 0;
+}
+
+static const struct i2c_device_id dps310_id[] = {
+ { DPS310_DEV_NAME, 0 },
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, dps310_id);
+
+static const struct acpi_device_id dps310_acpi_match[] = {
+ { "IFX3100" },
+ {}
+};
+MODULE_DEVICE_TABLE(acpi, dps310_acpi_match);
+
+static const struct of_device_id dps310_of_match[] = {
+ { .compatible = "infineon,dps310", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, dps310_of_match);
+
+static struct i2c_driver dps310_driver = {
+ .driver = {
+ .name = DPS310_DEV_NAME,
+ .acpi_match_table = dps310_acpi_match,
+ .of_match_table = dps310_of_match,
+ },
+ .probe = dps310_probe,
+ .remove = dps310_remove,
+ .id_table = dps310_id,
+};
+module_i2c_driver(dps310_driver);
+
+MODULE_AUTHOR("Joel Stanley <joel@jms.id.au>");
+MODULE_DESCRIPTION("Infineon DPS310 pressure and temperature sensor");
+MODULE_LICENSE("GPL v2");
+
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9993-add-wed.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9993-add-wed.patch
index baa88ef..b4f8e4e 100755
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9993-add-wed.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9993-add-wed.patch
@@ -654,7 +654,7 @@
entry->ipv6.ib2 = val;
l2 = &entry->ipv6.l2;
} else {
-@@ -329,32 +351,167 @@ int mtk_foe_entry_set_pppoe(struct mtk_foe_entry *entry, int sid)
+@@ -329,32 +351,168 @@ int mtk_foe_entry_set_pppoe(struct mtk_foe_entry *entry, int sid)
return 0;
}
@@ -723,6 +723,7 @@
+ ppe->foe_table[entry->hash].ib1 |= FIELD_PREP(MTK_FOE_IB1_STATE,
+ MTK_FOE_STATE_INVALID);
+ dma_wmb();
++ mtk_ppe_cache_clear(ppe);
+ }
+ entry->hash = 0xffff;
+
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9999-2-flow-offload-add-mtkhnat-flow-accounting.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9999-2-flow-offload-add-mtkhnat-flow-accounting.patch
index f6243d0..5b6253f 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9999-2-flow-offload-add-mtkhnat-flow-accounting.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9999-2-flow-offload-add-mtkhnat-flow-accounting.patch
@@ -139,9 +139,10 @@
static void mtk_ppe_cache_clear(struct mtk_ppe *ppe)
{
ppe_set(ppe, MTK_PPE_CACHE_CTL, MTK_PPE_CACHE_CTL_CLEAR);
-@@ -412,6 +452,18 @@ __mtk_foe_entry_clear(struct mtk_ppe *ppe, struct mtk_flow_entry *entry)
+@@ -412,7 +452,19 @@ __mtk_foe_entry_clear(struct mtk_ppe *ppe, struct mtk_flow_entry *entry)
MTK_FOE_STATE_INVALID);
dma_wmb();
+ mtk_ppe_cache_clear(ppe);
+
+ if (ppe->accounting) {
+ struct mtk_foe_accounting *acct, *acct_updated;
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9999-8-flow-offload-add-mtkhnat-dscp.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9999-8-flow-offload-add-mtkhnat-dscp.patch
new file mode 100644
index 0000000..fe278a7
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9999-8-flow-offload-add-mtkhnat-dscp.patch
@@ -0,0 +1,169 @@
+diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c
+index c2416b1..bc13a9b 100755
+--- a/drivers/net/ethernet/mediatek/mtk_ppe.c
++++ b/drivers/net/ethernet/mediatek/mtk_ppe.c
+@@ -435,6 +435,17 @@ int mtk_foe_entry_set_qid(struct mtk_foe_entry *entry, int qid)
+
+ return 0;
+ }
++
++int mtk_foe_entry_set_dscp(struct mtk_foe_entry *entry, int dscp)
++{
++ u32 *ib2 = mtk_foe_entry_ib2(entry);
++
++ *ib2 &= ~MTK_FOE_IB2_DSCP;
++ *ib2 |= FIELD_PREP(MTK_FOE_IB2_DSCP, dscp);
++
++ return 0;
++}
++
+ static inline bool mtk_foe_entry_usable(struct mtk_foe_entry *entry)
+ {
+ return !(entry->ib1 & MTK_FOE_IB1_STATIC) &&
+diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.h b/drivers/net/ethernet/mediatek/mtk_ppe.h
+index e7ecbf7..df10040 100644
+--- a/drivers/net/ethernet/mediatek/mtk_ppe.h
++++ b/drivers/net/ethernet/mediatek/mtk_ppe.h
+@@ -430,6 +430,7 @@ int mtk_foe_entry_set_pppoe(struct mtk_foe_entry *entry, int sid);
+ int mtk_foe_entry_set_wdma(struct mtk_foe_entry *entry, int wdma_idx, int txq,
+ int bss, int wcid);
+ int mtk_foe_entry_set_qid(struct mtk_foe_entry *entry, int qid);
++int mtk_foe_entry_set_dscp(struct mtk_foe_entry *entry, int dscp);
+ int mtk_foe_entry_commit(struct mtk_ppe *ppe, struct mtk_flow_entry *entry);
+ void mtk_foe_entry_clear(struct mtk_ppe *ppe, struct mtk_flow_entry *entry);
+ int mtk_foe_entry_idle_time(struct mtk_ppe *ppe, struct mtk_flow_entry *entry);
+diff --git a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
+index 23d2048..9bc0857 100644
+--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
++++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
+@@ -246,6 +246,7 @@ mtk_flow_offload_replace(struct mtk_eth *eth, struct flow_cls_offload *f)
+ int wed_index = -1;
+ u16 addr_type = 0;
+ u8 l4proto = 0;
++ u8 dscp = 0;
+ int err = 0;
+ int i;
+
+@@ -282,6 +283,15 @@ mtk_flow_offload_replace(struct mtk_eth *eth, struct flow_cls_offload *f)
+ return -EOPNOTSUPP;
+ }
+
++ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IP)) {
++ struct flow_match_ip match;
++
++ flow_rule_match_ip(rule, &match);
++ dscp = match.key->tos;
++ } else {
++ return -EOPNOTSUPP;
++ }
++
+ switch (addr_type) {
+ case 0:
+ offload_type = MTK_PPE_PKT_TYPE_BRIDGE;
+@@ -441,6 +451,8 @@ mtk_flow_offload_replace(struct mtk_eth *eth, struct flow_cls_offload *f)
+ if (data.pppoe.num == 1)
+ mtk_foe_entry_set_pppoe(&foe, data.pppoe.sid);
+
++ mtk_foe_entry_set_dscp(&foe, dscp);
++
+ err = mtk_flow_set_output_device(eth, &foe, odev, f->flow->ct, data.eth.h_dest,
+ &wed_index);
+ if (err)
+diff --git a/include/net/netfilter/nf_flow_table.h b/include/net/netfilter/nf_flow_table.h
+index 55359dd..1a23c03 100644
+--- a/include/net/netfilter/nf_flow_table.h
++++ b/include/net/netfilter/nf_flow_table.h
+@@ -36,6 +36,7 @@ struct nf_flow_key {
+ };
+ struct flow_dissector_key_tcp tcp;
+ struct flow_dissector_key_ports tp;
++ struct flow_dissector_key_ip ip;
+ } __aligned(BITS_PER_LONG / 8); /* Ensure that we can do comparisons as longs. */
+
+ struct nf_flow_match {
+@@ -145,6 +146,7 @@ struct flow_offload_tuple {
+ u8 h_dest[ETH_ALEN];
+ } out;
+ };
++ u8 tos;
+ };
+
+ struct flow_offload_tuple_rhash {
+diff --git a/net/netfilter/nf_flow_table_offload.c b/net/netfilter/nf_flow_table_offload.c
+index 61cc518..c1a5f64 100644
+--- a/net/netfilter/nf_flow_table_offload.c
++++ b/net/netfilter/nf_flow_table_offload.c
+@@ -104,6 +104,7 @@ static int nf_flow_rule_match(struct nf_flow_match *match,
+ NF_FLOW_DISSECTOR(match, FLOW_DISSECTOR_KEY_IPV6_ADDRS, ipv6);
+ NF_FLOW_DISSECTOR(match, FLOW_DISSECTOR_KEY_TCP, tcp);
+ NF_FLOW_DISSECTOR(match, FLOW_DISSECTOR_KEY_PORTS, tp);
++ NF_FLOW_DISSECTOR(match, FLOW_DISSECTOR_KEY_IP, ip);
+
+ if (other_dst && other_dst->lwtstate) {
+ tun_info = lwt_tun_info(other_dst->lwtstate);
+@@ -183,10 +184,14 @@ static int nf_flow_rule_match(struct nf_flow_match *match,
+ key->tp.dst = tuple->dst_port;
+ mask->tp.dst = 0xffff;
+
++ key->ip.tos = tuple->tos;
++ mask->ip.tos = 0xff;
++
+ match->dissector.used_keys |= BIT(FLOW_DISSECTOR_KEY_META) |
+ BIT(FLOW_DISSECTOR_KEY_CONTROL) |
+ BIT(FLOW_DISSECTOR_KEY_BASIC) |
+- BIT(FLOW_DISSECTOR_KEY_PORTS);
++ BIT(FLOW_DISSECTOR_KEY_PORTS) |
++ BIT(FLOW_DISSECTOR_KEY_IP);
+ return 0;
+ }
+
+diff --git a/net/netfilter/xt_FLOWOFFLOAD.c b/net/netfilter/xt_FLOWOFFLOAD.c
+index 2d5c3cc..b231dd7 100644
+--- a/net/netfilter/xt_FLOWOFFLOAD.c
++++ b/net/netfilter/xt_FLOWOFFLOAD.c
+@@ -49,6 +49,35 @@ static DEFINE_SPINLOCK(hooks_lock);
+
+ struct xt_flowoffload_table flowtable[2];
+
++static int
++xt_flowoffload_dscp_init(struct sk_buff *skb, struct flow_offload *flow,
++ enum ip_conntrack_dir dir)
++{
++ const struct flow_offload_tuple *flow_tuple = &flow->tuplehash[dir].tuple;
++ struct iphdr *iph;
++ struct ipv6hdr *ip6h;
++ u32 offset = 0;
++ u8 tos = 0;
++
++ switch (flow_tuple->l3proto) {
++ case NFPROTO_IPV4:
++ iph = (struct iphdr *)(skb_network_header(skb) + offset);
++ tos = iph->tos;
++ break;
++ case NFPROTO_IPV6:
++ ip6h = (struct ipv6hdr *)(skb_network_header(skb) + offset);
++ tos = ipv6_get_dsfield(ip6h);
++ break;
++ default:
++ return -1;
++ };
++
++ flow->tuplehash[dir].tuple.tos = tos;
++ flow->tuplehash[!dir].tuple.tos = tos;
++
++ return 0;
++}
++
+ static unsigned int
+ xt_flowoffload_net_hook(void *priv, struct sk_buff *skb,
+ const struct nf_hook_state *state)
+@@ -599,6 +628,9 @@ flowoffload_tg(struct sk_buff *skb, const struct xt_action_param *par)
+ if (flow_offload_route_init(flow, &route) < 0)
+ goto err_flow_add;
+
++ if (xt_flowoffload_dscp_init(skb, flow, dir) < 0)
++ goto err_flow_add;
++
+ if (tcph) {
+ ct->proto.tcp.seen[0].flags |= IP_CT_TCP_FLAG_BE_LIBERAL;
+ ct->proto.tcp.seen[1].flags |= IP_CT_TCP_FLAG_BE_LIBERAL;
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9999-9-flow-offload-add-mtkhnat-netlink.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9999-9-flow-offload-add-mtkhnat-netlink.patch
new file mode 100644
index 0000000..3b9e863
--- /dev/null
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/flow_patch/9999-9-flow-offload-add-mtkhnat-netlink.patch
@@ -0,0 +1,337 @@
+diff --git a/include/net/netfilter/nf_flow_table.h b/include/net/netfilter/nf_flow_table.h
+index 8a84de3..1a23c03 100644
+--- a/include/net/netfilter/nf_flow_table.h
++++ b/include/net/netfilter/nf_flow_table.h
+@@ -276,6 +276,7 @@ int nf_flow_table_init(struct nf_flowtable *flow_table);
+ void nf_flow_table_free(struct nf_flowtable *flow_table);
+
+ void flow_offload_teardown(struct flow_offload *flow);
++void flow_offload_teardown_by_tuple(struct flow_offload_tuple *tuple);
+
+ int nf_flow_table_iterate(struct nf_flowtable *flow_table,
+ void (*iter)(struct flow_offload *flow, void *data),
+diff --git a/include/uapi/linux/netfilter/nfnetlink.h b/include/uapi/linux/netfilter/nfnetlink.h
+index 5bc960f..603d9c0 100644
+--- a/include/uapi/linux/netfilter/nfnetlink.h
++++ b/include/uapi/linux/netfilter/nfnetlink.h
+@@ -60,7 +60,8 @@ struct nfgenmsg {
+ #define NFNL_SUBSYS_CTHELPER 9
+ #define NFNL_SUBSYS_NFTABLES 10
+ #define NFNL_SUBSYS_NFT_COMPAT 11
+-#define NFNL_SUBSYS_COUNT 12
++#define NFNL_SUBSYS_FLOWTABLE 12
++#define NFNL_SUBSYS_COUNT 13
+
+ /* Reserved control nfnetlink messages */
+ #define NFNL_MSG_BATCH_BEGIN NLMSG_MIN_TYPE
+diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
+index 5d690ab..8ec87aa 100644
+--- a/net/netfilter/Kconfig
++++ b/net/netfilter/Kconfig
+@@ -708,6 +708,15 @@ config NF_FLOW_TABLE
+
+ To compile it as a module, choose M here.
+
++config NF_FLOW_TABLE_NETLINK
++ tristate "Netfilter flow table netlink module"
++ depends on NETFILTER_INGRESS
++ depends on NF_CONNTRACK
++ help
++ This option adds the flow table core infrastructure.
++
++ To compile it as a module, choose M here.
++
+ config NETFILTER_XTABLES
+ tristate "Netfilter Xtables support (required for ip_tables)"
+ default m if NETFILTER_ADVANCED=n
+diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
+index d93a121..fa6ffb1 100644
+--- a/net/netfilter/Makefile
++++ b/net/netfilter/Makefile
+@@ -124,6 +124,7 @@ nf_flow_table-objs := nf_flow_table_core.o nf_flow_table_ip.o \
+ nf_flow_table_offload.o
+
+ obj-$(CONFIG_NF_FLOW_TABLE_INET) += nf_flow_table_inet.o
++obj-$(CONFIG_NF_FLOW_TABLE_NETLINK) += nf_flow_table_netlink.o
+
+ # generic X tables
+ obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o
+diff --git a/net/netfilter/nf_flow_table_core.c b/net/netfilter/nf_flow_table_core.c
+index 1036558..a0f52f6 100644
+--- a/net/netfilter/nf_flow_table_core.c
++++ b/net/netfilter/nf_flow_table_core.c
+@@ -373,6 +373,29 @@ void flow_offload_teardown(struct flow_offload *flow)
+ }
+ EXPORT_SYMBOL_GPL(flow_offload_teardown);
+
++void flow_offload_teardown_by_tuple(struct flow_offload_tuple *tuple)
++{
++ struct net_device *netdev;
++ struct nf_flowtable *flowtable;
++ struct flow_offload_tuple_rhash *tuplehash;
++ struct flow_offload *flow;
++ int dir;
++
++ list_for_each_entry(flowtable, &flowtables, list) {
++ for_each_netdev(&init_net, netdev) {
++ tuple->iifidx = netdev->ifindex;
++ tuplehash = flow_offload_lookup(flowtable, tuple);
++ if (!tuplehash)
++ continue;
++
++ dir = tuplehash->tuple.dir;
++ flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]);
++ flow_offload_teardown(flow);
++ }
++ };
++}
++EXPORT_SYMBOL_GPL(flow_offload_teardown_by_tuple);
++
+ struct flow_offload_tuple_rhash *
+ flow_offload_lookup(struct nf_flowtable *flow_table,
+ struct flow_offload_tuple *tuple)
+diff --git a/net/netfilter/nf_flow_table_netlink.c b/net/netfilter/nf_flow_table_netlink.c
+new file mode 100644
+index 0000000..f05f29e
+--- /dev/null
++++ b/net/netfilter/nf_flow_table_netlink.c
+@@ -0,0 +1,239 @@
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/netfilter.h>
++#include <linux/netlink.h>
++#include <net/netlink.h>
++#include <net/ip.h>
++#include <linux/netfilter/nfnetlink.h>
++#include <net/netfilter/nf_flow_table.h>
++
++enum ft_netlink_msg_types {
++ FT_MSG_DEL,
++ FT_MSG_ADD,
++ FT_MSG_FLUSH,
++ FT_MSG_MAX
++};
++
++enum ftattr_type {
++ FTA_UNSPEC,
++ FTA_TUPLE,
++ __FTA_MAX
++};
++#define FTA_MAX (__FTA_MAX - 1)
++
++enum ftattr_tuple {
++ FTA_TUPLE_UNSPEC,
++ FTA_TUPLE_IP,
++ FTA_TUPLE_PROTO,
++ FTA_TUPLE_ZONE,
++ __FTA_TUPLE_MAX
++};
++#define FTA_TUPLE_MAX (__FTA_TUPLE_MAX - 1)
++
++enum ftattr_ip {
++ FTA_IP_UNSPEC,
++ FTA_IP_V4_SRC,
++ FTA_IP_V4_DST,
++ __FTA_IP_MAX
++};
++#define FTA_IP_MAX (__FTA_IP_MAX - 1)
++
++enum ftattr_l4proto {
++ FTA_PROTO_UNSPEC,
++ FTA_PROTO_NUM,
++ FTA_PROTO_SPORT,
++ FTA_PROTO_DPORT,
++ __FTA_PROTO_MAX
++};
++#define FTA_PROTO_MAX (__FTA_PROTO_MAX - 1)
++
++static const struct nla_policy tuple_nla_policy[FTA_TUPLE_MAX + 1] = {
++ [FTA_TUPLE_IP] = { .type = NLA_NESTED },
++ [FTA_TUPLE_PROTO] = { .type = NLA_NESTED },
++ [FTA_TUPLE_ZONE] = { .type = NLA_U16 },
++};
++
++static const struct nla_policy ip_nla_policy[FTA_IP_MAX + 1] = {
++ [FTA_IP_V4_SRC] = { .type = NLA_U32 },
++ [FTA_IP_V4_DST] = { .type = NLA_U32 },
++};
++
++static const struct nla_policy l4proto_nla_policy[FTA_PROTO_MAX + 1] = {
++ [FTA_PROTO_NUM] = { .type = NLA_U8 },
++ [FTA_PROTO_SPORT] = {.type = NLA_U16},
++ [FTA_PROTO_DPORT] = {.type = NLA_U16},
++};
++
++static inline int ftnetlink_parse_tuple_ip(struct nlattr *attr,
++ struct flow_offload_tuple *tuple)
++{
++ struct nlattr *tb[FTA_IP_MAX+1];
++ int err;
++
++ err = nla_parse_nested_deprecated(tb, FTA_IP_MAX, attr, ip_nla_policy, NULL);
++
++ if (err < 0)
++ return err;
++
++ switch (tuple->l3proto) {
++ case NFPROTO_IPV4:
++ if (!tb[FTA_IP_V4_SRC] || !tb[FTA_IP_V4_DST])
++ return -EINVAL;
++
++ tuple->src_v4.s_addr = nla_get_in_addr(tb[FTA_IP_V4_SRC]);
++ tuple->dst_v4.s_addr = nla_get_in_addr(tb[FTA_IP_V4_DST]);
++ }
++
++ return err;
++}
++
++static inline int ftnetlink_parse_tuple_proto(struct nlattr *attr,
++ struct flow_offload_tuple *tuple)
++{
++ struct nlattr *tb[FTA_PROTO_MAX+1];
++ int err;
++
++ err = nla_parse_nested_deprecated(tb, FTA_PROTO_MAX, attr, l4proto_nla_policy, NULL);
++
++ if(err < 0)
++ return err;
++
++ if (!tb[FTA_PROTO_NUM] || !tb[FTA_PROTO_SPORT] || !tb[FTA_PROTO_DPORT])
++ return -EINVAL;
++
++ tuple->l4proto = nla_get_u8(tb[FTA_PROTO_NUM]);
++ tuple->src_port = nla_get_u16(tb[FTA_PROTO_SPORT]);
++ tuple->dst_port = nla_get_u16(tb[FTA_PROTO_DPORT]);
++
++ return err;
++}
++
++static int ftnetlink_parse_tuple(const struct nlattr * const cda[],
++ struct flow_offload_tuple *tuple,
++ int attrtype, int l3proto)
++{
++ struct nlattr *tb[FTA_TUPLE_MAX+1];
++ int err;
++
++ memset(tuple, 0, sizeof(*tuple));
++
++ err = nla_parse_nested_deprecated(tb, FTA_TUPLE_MAX, cda[attrtype], tuple_nla_policy, NULL);
++ if (err < 0)
++ return err;
++
++ if (!tb[FTA_TUPLE_IP])
++ return -EINVAL;
++
++ /* parse IP */
++ tuple->l3proto = l3proto;
++ err = ftnetlink_parse_tuple_ip(tb[FTA_TUPLE_IP], tuple);
++ if (err < 0)
++ return err;
++
++ /* parse proto */
++ if (!tb[FTA_TUPLE_PROTO])
++ return -EINVAL;
++ err = ftnetlink_parse_tuple_proto(tb[FTA_TUPLE_PROTO], tuple);
++
++ if (err >= 0)
++ printk("tuple info:sip=%pI4,dip=%pI4 proto=%d "
++ "sport=%d dport=%d\n",
++ &tuple->src_v4, &tuple->dst_v4, tuple->l4proto,
++ ntohs(tuple->src_port), ntohs(tuple->dst_port));
++
++ return err;
++}
++
++static int ftnetlink_del_nf_flow(struct net *net, struct sock *ftnl, struct sk_buff *skb,
++ const struct nlmsghdr *nlh,
++ const struct nlattr * const cda[],
++ struct netlink_ext_ack *extack)
++{
++ struct net_device *dev = skb->dev;
++ struct flow_offload_tuple tuple;
++ int err = -1;
++ struct nfgenmsg *nfmsg = nlmsg_data(nlh);
++ u_int8_t u3 = nfmsg->nfgen_family;
++
++ /* parse tuple */
++ if(!cda[FTA_TUPLE])
++ return -EINVAL;
++
++ err = ftnetlink_parse_tuple(cda, &tuple, FTA_TUPLE, u3);
++ if (err < 0)
++ return err;
++
++ /* teardown the flow */
++ flow_offload_teardown_by_tuple(&tuple);
++
++ return 0;
++}
++
++static int ftnetlink_add_nf_flow(struct net *net, struct sock *ftnl, struct sk_buff *skb,
++ const struct nlmsghdr *nlh,
++ const struct nlattr * const cda[],
++ struct netlink_ext_ack *extack)
++{
++ return 0;
++}
++
++static int ftnetlink_flush_table(struct net *net, struct sock *ftnl, struct sk_buff *skb,
++ const struct nlmsghdr *nlh,
++ const struct nlattr * const cda[],
++ struct netlink_ext_ack *extack)
++{
++ struct net_device *dev = skb->dev;
++
++ nf_flow_table_cleanup(dev);
++
++ return 0;
++}
++
++static const struct nla_policy ft_nla_policy[FTA_MAX + 1] = {
++ [FTA_TUPLE] = { .type = NLA_NESTED },
++};
++
++static const struct nfnl_callback flow_table_cb[FT_MSG_MAX] = {
++ [FT_MSG_DEL] = {
++ .call = ftnetlink_del_nf_flow,
++ .attr_count = FTA_MAX,
++ .policy = ft_nla_policy
++ },
++ [FT_MSG_ADD] = {
++ .call = ftnetlink_add_nf_flow,
++ .attr_count = FTA_MAX,
++ .policy = ft_nla_policy
++ },
++ [FT_MSG_FLUSH] = {
++ .call = ftnetlink_flush_table,
++ .attr_count = FTA_MAX,
++ .policy = ft_nla_policy
++ },
++};
++
++static const struct nfnetlink_subsystem ftnl_subsys = {
++ .name = "flowtable",
++ .subsys_id = NFNL_SUBSYS_FLOWTABLE,
++ .cb_count = FT_MSG_MAX,
++ .cb = flow_table_cb,
++};
++
++static int __init ftnetlink_init(void)
++{
++ int ret;
++
++ ret = nfnetlink_subsys_register(&ftnl_subsys);
++
++ return ret;
++}
++
++static void ftnetlink_exit(void)
++{
++ nfnetlink_subsys_unregister(&ftnl_subsys);
++}
++
++MODULE_LICENSE("GPL");
++module_init(ftnetlink_init);
++module_exit(ftnetlink_exit);
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7988.cfg b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7988.cfg
index 14a6468..2675268 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7988.cfg
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/mt7988.cfg
@@ -3,11 +3,11 @@
# CONFIG_AIROHA_EN8801SC_PHY is not set
# CONFIG_AIROHA_EN8811H_PHY is not set
CONFIG_AQUANTIA_PHY=y
-# CONFIG_AQUANTIA_PHY_MDI_SWAP is not set
CONFIG_AQUANTIA_PHY_FW_DOWNLOAD=y
CONFIG_AQUANTIA_PHY_FW_DOWNLOAD_GANG=y
# CONFIG_AQUANTIA_PHY_FW_DOWNLOAD_SINGLE is not set
CONFIG_AQUANTIA_PHY_FW_FILE="Rhe-05.06-Candidate7-AQR_Mediatek_23B_StartOff_ID45623_VER36657.cld"
+# CONFIG_AQUANTIA_PHY_MDI_SWAP is not set
CONFIG_ARCH_CLOCKSOURCE_DATA=y
CONFIG_ARCH_DMA_ADDR_T_64BIT=y
CONFIG_ARCH_KEEP_MEMBLOCK=y
@@ -56,6 +56,7 @@
CONFIG_ARM_MEDIATEK_CPUFREQ=y
CONFIG_ARM_PMU=y
CONFIG_ARM_PSCI_FW=y
+# CONFIG_ASN1 is not set
CONFIG_ATA=y
CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y
CONFIG_BLK_DEV_DM=y
@@ -118,7 +119,6 @@
# CONFIG_CPUFREQ_DT is not set
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
-# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
CONFIG_CPU_FREQ_GOV_ATTR_SET=y
CONFIG_CPU_FREQ_GOV_COMMON=y
CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
@@ -179,6 +179,7 @@
CONFIG_DM_VERITY=y
# CONFIG_DM_VERITY_FEC is not set
# CONFIG_DM_VERITY_VERIFY_ROOTHASH_SIG is not set
+CONFIG_DPS310=y
CONFIG_DRM_RCAR_WRITEBACK=y
CONFIG_DTC=y
CONFIG_DYNAMIC_DEBUG=y
@@ -203,6 +204,7 @@
CONFIG_GENERIC_GETTIMEOFDAY=y
CONFIG_GENERIC_IDLE_POLL_SETUP=y
CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y
+CONFIG_GENERIC_IRQ_MIGRATION=y
CONFIG_GENERIC_IRQ_MULTI_HANDLER=y
CONFIG_GENERIC_IRQ_SHOW=y
CONFIG_GENERIC_IRQ_SHOW_LEVEL=y
@@ -238,6 +240,7 @@
CONFIG_HZ_250=y
CONFIG_I2C=y
CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
CONFIG_I2C_MT65XX=y
CONFIG_ICPLUS_PHY=y
CONFIG_IIO=y
@@ -289,7 +292,6 @@
CONFIG_MTD_NAND_MTK=y
CONFIG_MTD_RAW_NAND=y
CONFIG_MTD_SPI_NAND=y
-# CONFIG_MTD_SPI_NAND_W25N01KV is not set
CONFIG_MTD_SPI_NOR=y
CONFIG_MTD_SPLIT_FIRMWARE=y
CONFIG_MTD_SPLIT_FIT_FW=y
@@ -305,9 +307,9 @@
CONFIG_MTK_INFRACFG=y
CONFIG_MTK_PMIC_WRAP=y
CONFIG_MTK_SCPSYS=y
+CONFIG_MTK_SOC_THERMAL_LVTS=y
CONFIG_MTK_SPI_NAND=y
# CONFIG_MTK_THERMAL is not set
-CONFIG_MTK_SOC_THERMAL_LVTS=y
CONFIG_MTK_TIMER=y
# CONFIG_MTK_UART_APDMA is not set
CONFIG_MUTEX_SPIN_ON_OWNER=y
@@ -360,12 +362,8 @@
CONFIG_PHYLIB=y
CONFIG_PHYLINK=y
CONFIG_PHYS_ADDR_T_64BIT=y
-# CONFIG_PHY_MTK_A60810 is not set
-# CONFIG_PHY_MTK_A60931 is not set
-# CONFIG_PHY_MTK_A60XXX is not set
CONFIG_PHY_MTK_TPHY=y
# CONFIG_PHY_MTK_UFS is not set
-# CONFIG_PHY_MTK_USB3_I2C_FPGA is not set
CONFIG_PHY_MTK_XSPHY=y
CONFIG_PINCTRL=y
# CONFIG_PINCTRL_MT2712 is not set
@@ -389,6 +387,16 @@
CONFIG_POWER_RESET_SYSCON=y
CONFIG_POWER_SUPPLY=y
CONFIG_PRINTK_TIME=y
+CONFIG_PSTORE=y
+# CONFIG_PSTORE_842_COMPRESS is not set
+CONFIG_PSTORE_CONSOLE=y
+# CONFIG_PSTORE_DEFLATE_COMPRESS is not set
+# CONFIG_PSTORE_LZ4HC_COMPRESS is not set
+# CONFIG_PSTORE_LZ4_COMPRESS is not set
+# CONFIG_PSTORE_LZO_COMPRESS is not set
+CONFIG_PSTORE_PMSG=y
+CONFIG_PSTORE_RAM=y
+# CONFIG_PSTORE_ZSTD_COMPRESS is not set
CONFIG_PWM=y
CONFIG_PWM_MEDIATEK=y
# CONFIG_PWM_MTK_DISP is not set
@@ -496,5 +504,3 @@
CONFIG_ZLIB_DEFLATE=y
CONFIG_ZLIB_INFLATE=y
CONFIG_ZONE_DMA32=y
-# CONFIG_BPF_KPROBE_OVERRIDE is not set
-# CONFIG_HIST_TRIGGERS is not set
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/747-net-phy-aquantia-add-AQR113C.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/747-net-phy-aquantia-add-AQR113C.patch
index 8d01cab..d99d75f 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/747-net-phy-aquantia-add-AQR113C.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/747-net-phy-aquantia-add-AQR113C.patch
@@ -10,20 +10,59 @@
#define MDIO_PHYXS_VEND_IF_STATUS 0xe812
#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK GENMASK(7, 3)
-@@ -352,6 +352,13 @@ static int aqr107_read_status(struct phy_device *phydev)
+@@ -268,17 +268,6 @@ static int aqr_read_status(struct phy_device *phydev)
+ return genphy_c45_read_status(phydev);
+ }
+
+-static int aqr107_read_downshift_event(struct phy_device *phydev)
+-{
+- int val;
+-
+- val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_TX_VEND_INT_STATUS1);
+- if (val < 0)
+- return val;
+-
+- return !!(val & MDIO_AN_TX_VEND_INT_STATUS1_DOWNSHIFT);
+-}
+-
+ static int aqr107_read_rate(struct phy_device *phydev)
+ {
+ int val;
+@@ -353,13 +342,7 @@ static int aqr107_read_status(struct phy_device *phydev)
break;
}
+- val = aqr107_read_downshift_event(phydev);
+- if (val <= 0)
+- return val;
+-
+- phydev_warn(phydev, "Downshift occurred! Cabling may be defective.\n");
+-
+- /* Read downshifted rate from vendor register */
++ /* Read possibly downshifted rate from vendor register */
+ return aqr107_read_rate(phydev);
+ }
+
+@@ -500,9 +483,6 @@ static int aqr107_config_init(struct phy_device *phydev)
+ if (!ret)
+ aqr107_chip_info(phydev);
+
+- /* ensure that a latched downshift event is cleared */
+- aqr107_read_downshift_event(phydev);
+-
+ return aqr107_set_downshift(phydev, MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT);
+ }
+
+@@ -527,9 +507,6 @@ static int aqcs109_config_init(struct phy_device *phydev)
+ if (ret)
+ return ret;
+
+- /* ensure that a latched downshift event is cleared */
+- aqr107_read_downshift_event(phydev);
+-
+ return aqr107_set_downshift(phydev, MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT);
+ }
+
-+ /* Handle the case when the link speed is unknown */
-+ if (phydev->speed == SPEED_UNKNOWN) {
-+ val = aqr107_read_rate(phydev);
-+ if (val < 0)
-+ return val;
-+ }
-+
- val = aqr107_read_downshift_event(phydev);
- if (val <= 0)
- return val;
@@ -695,6 +696,24 @@ static struct phy_driver aqr_driver[] = {
.ack_interrupt = aqr_ack_interrupt,
.read_status = aqr_read_status,
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/751-net-phy-aquantia-add-firmware-download.patch b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/751-net-phy-aquantia-add-firmware-download.patch
index 6eb5bf4..2fe3132 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/751-net-phy-aquantia-add-firmware-download.patch
+++ b/recipes-kernel/linux/linux-mediatek-5.4/mediatek/patches-5.4/751-net-phy-aquantia-add-firmware-download.patch
@@ -1338,8 +1338,8 @@
+ aqr_firmware_download(phydev);
+#endif
+
- /* ensure that a latched downshift event is cleared */
- aqr107_read_downshift_event(phydev);
+ return aqr107_set_downshift(phydev, MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT);
+ }
@@ -605,6 +609,15 @@ static int aqr107_resume(struct phy_device *phydev)
MDIO_CTRL1_LPOWER);
diff --git a/recipes-kernel/linux/linux-mediatek-5.4/rdkb_cfg/mac80211.cfg b/recipes-kernel/linux/linux-mediatek-5.4/rdkb_cfg/mac80211.cfg
index 9bc3ae6..9410623 100644
--- a/recipes-kernel/linux/linux-mediatek-5.4/rdkb_cfg/mac80211.cfg
+++ b/recipes-kernel/linux/linux-mediatek-5.4/rdkb_cfg/mac80211.cfg
@@ -12,4 +12,5 @@
CONFIG_TRACING=y
CONFIG_GENERIC_TRACER=y
CONFIG_TRACING_SUPPORT=y
-CONFIG_STACK_TRACER=y
\ No newline at end of file
+CONFIG_STACK_TRACER=y
+CONFIG_NF_FLOW_TABLE_NETLINK=y
\ No newline at end of file
diff --git a/recipes-wifi/atenl/atenl.bb b/recipes-wifi/atenl/atenl.bb
index e1cf94f..50229f8 100644
--- a/recipes-wifi/atenl/atenl.bb
+++ b/recipes-wifi/atenl/atenl.bb
@@ -4,7 +4,7 @@
LIC_FILES_CHKSUM = "file://COPYING;md5=751419260aa954499f7abaabaa882bbe"
DEPENDS += "libnl-tiny"
-RDEPENDS_${PN} += "busybox"
+RDEPENDS_${PN} += "bash"
inherit pkgconfig cmake
SRC_URI = " \
@@ -12,12 +12,22 @@
file://src;subdir=git \
file://ated.sh;subdir=git \
file://iwpriv.sh;subdir=git \
+ file://001-RDKB-ash-to-bash.patch;apply=no \
"
S = "${WORKDIR}/git/src"
CFLAGS_append = " -I=${includedir}/libnl-tiny "
+do_mtk_patches() {
+ cd ${S}/../
+
+ if [ ! -e mtk_wifi_patch_applied ]; then
+ patch -p1 < ${WORKDIR}/001-RDKB-ash-to-bash.patch
+ fi
+ touch mtk_wifi_patch_applied
+}
+addtask mtk_patches after do_patch before do_configure
do_install_append() {
install -d ${D}${sbindir}
diff --git a/recipes-wifi/atenl/files/001-RDKB-ash-to-bash.patch b/recipes-wifi/atenl/files/001-RDKB-ash-to-bash.patch
new file mode 100644
index 0000000..9b1f22b
--- /dev/null
+++ b/recipes-wifi/atenl/files/001-RDKB-ash-to-bash.patch
@@ -0,0 +1,20 @@
+diff --git a/ated.sh b/ated.sh
+index e989e446..c15867a8 100644
+--- a/ated.sh
++++ b/ated.sh
+@@ -1,4 +1,4 @@
+-#!/bin/ash
++#!/bin/bash
+ # This script is used for wrapping atenl daemon to ated
+ # 0 is normal mode, 1 is used for doing specific commands such as "sync eeprom all"
+
+diff --git a/iwpriv.sh b/iwpriv.sh
+index 8b0d76fd..9f75bae9 100644
+--- a/iwpriv.sh
++++ b/iwpriv.sh
+@@ -1,4 +1,4 @@
+-#!/bin/ash
++#!/bin/bash
+
+ interface=$1 # phy0/phy1/ra0
+ cmd_type=$2 # set/show/e2p/mac/dump
diff --git a/recipes-wifi/atenl/files/iwpriv.sh b/recipes-wifi/atenl/files/iwpriv.sh
index 8b0d76f..de74190 100644
--- a/recipes-wifi/atenl/files/iwpriv.sh
+++ b/recipes-wifi/atenl/files/iwpriv.sh
@@ -269,6 +269,12 @@
echo "he_tb"
elif [ "$tx_mode" = "11" ]; then
echo "he_mu"
+ elif [ "$tx_mode" = "13" ]; then
+ echo "eht_su"
+ elif [ "$tx_mode" = "14" ]; then
+ echo "eht_tb"
+ elif [ "$tx_mode" = "15" ]; then
+ echo "eht_mu"
else
echo "undefined"
fi
@@ -496,7 +502,27 @@
local base_freq=5180
local base_chan=36
else
+ local base_freq=5955
case ${bw} in
+ "12")
+ local bw_str="320"
+ if [ ${ch} == "31" ]; then
+ local control_freq="5955"
+ elif [ ${ch} == "63" ]; then
+ local control_freq="6115"
+ elif [ ${ch} == "95" ]; then
+ local control_freq="6275"
+ elif [ ${ch} == "127" ]; then
+ local control_freq="6435"
+ elif [ ${ch} == "159" ]; then
+ local control_freq="6595"
+ elif [ ${ch} == "191" ]; then
+ local control_freq="6755"
+ fi
+ local center_freq=$(((ch - base_chan) * 5 + base_freq))
+ do_cmd "iw dev mon${phy_idx} set freq ${control_freq} ${bw_str} ${center_freq}"
+ return
+ ;;
"5")
bw_str="160MHz"
if [ ${ch} -lt "33" ]; then
@@ -644,7 +670,6 @@
local bw_str="HT20"
;;
esac
- local base_freq=5955
fi
local control_freq=$(((ch - base_chan) * 5 + base_freq))
@@ -826,15 +851,22 @@
if [ "${cmd}" = "ATETxPacketWithBf" ]; then
do_cmd "mt76-test phy${phy_idx} set state=tx_frames"
elif [ "${cmd}" = "ATEConTxETxBfInitProc" ]; then
+ local wlan_idx="1"
+ if [ ${is_eagle} == "1" ]; then
+ local wlan_idx=$((phy_idx+1))
+ fi
do_cmd "mt76-test phy${phy_idx} set aid=1"
do_cmd "mt76-test phy${phy_idx} set txbf_act=stop_sounding txbf_param=1"
do_cmd "mt76-test phy${phy_idx} set txbf_act=update_ch txbf_param=1"
do_cmd "mt76-test phy${phy_idx} set txbf_act=ebf_prof_update txbf_param=0,0,0"
- do_cmd "mt76-test phy${phy_idx} set txbf_act=apply_tx txbf_param=1,1,0,0,0"
+ do_cmd "mt76-test phy${phy_idx} set txbf_act=apply_tx txbf_param=${wlan_idx},1,0,0,0"
+ if [ ${is_eagle} == "1" ]; then
+ do_cmd "mt76-test phy${phy_idx} set txbf_act=txcmd txbf_param=1,1,1"
+ fi
do_cmd "mt76-test phy${phy_idx} set txbf_act=pfmu_tag_read txbf_param=0,1"
- do_cmd "mt76-test phy${phy_idx} set txbf_act=sta_rec_read txbf_param=1"
- do_cmd "mt76-test phy${phy_idx} set txbf_act=trigger_sounding txbf_param=0,1,0,1,0,0,0"
- do_cmd "mt76-test phy${phy_idx} set txbf_act=trigger_sounding txbf_param=2,1,ff,1,0,0,0"
+ do_cmd "mt76-test phy${phy_idx} set txbf_act=sta_rec_read txbf_param=${wlan_idx}"
+ do_cmd "mt76-test phy${phy_idx} set txbf_act=trigger_sounding txbf_param=0,1,0,${wlan_idx},0,0,0"
+ do_cmd "mt76-test phy${phy_idx} set txbf_act=trigger_sounding txbf_param=2,1,ff,${wlan_idx},0,0,0"
do_cmd "mt76-test phy${phy_idx} set state=rx_frames"
elif [ "${cmd}" = "ATEConTxETxBfGdProc" ]; then
do_cmd "mt76-test phy${phy_idx} set aid=1"
@@ -1104,6 +1136,11 @@
exit
elif [[ ${interface} == "ra"* ]]; then
convert_interface $interface
+elif [[ ${interface} == "phy" ]]; then
+ # handle mwctl phy phy0 e2p ... case
+ interface=$2
+ cmd_type=$3
+ full_cmd=$4
fi
tmp_work_mode=$(get_config "WORKMODE" ${iwpriv_file})
@@ -1122,12 +1159,12 @@
## Therefore this wrapper would translate it to either mt76-test or mt76-vendor based on the attribute of the command
## Translate to mt76-vendor command
"csi"|"amnt"|"ap_rfeatures"|"ap_wireless"|"mu")
- if [ ${is_eagle} == "1" ]; then
+ if [ ${is_eagle} == "1" ]; then
do_cmd "hostapd_cli -i $*"
- skip=1
- else
+ else
do_cmd "mt76-vendor $*"
- skip=1
+ fi
+ skip=1
;;
"ATE")
do_ate_work ${param}
@@ -1151,9 +1188,14 @@
param_new=${param}
;;
"ATETXGI")
- tx_mode=$(convert_tx_mode $(get_config "ATETXMODE" ${iwpriv_file}))
- convert_gi ${tx_mode} ${param}
- skip=1
+ if [ ${is_eagle} == "0" ]; then
+ tx_mode=$(convert_tx_mode $(get_config "ATETXMODE" ${iwpriv_file}))
+ convert_gi ${tx_mode} ${param}
+ skip=1
+ else
+ cmd_new="tx_rate_sgi"
+ param_new=${param}
+ fi
;;
"ATETXMODE")
cmd_new="tx_rate_mode"
@@ -1166,10 +1208,18 @@
record_config ${cmd} ${param} ${iwpriv_file}
fi
;;
- "ATETXPOW0"|"ATETXPOW1"|"ATETXPOW2"|"ATETXPOW3")
+ "ATETXPOW0"|"ATETXPOW1"|"ATETXPOW2"|"ATETXPOW3"|"ATETXPOW")
cmd_new="tx_power"
+ if [ "${param}" == "127" ]; then
+ # for iTest verification
+ exit
+ fi
param_new="${param},0,0,0"
;;
+ "ATEMUAID")
+ cmd_new="aid"
+ param_new=${param}
+ ;;
"ATETXBW")
record_config ${cmd} ${param} ${iwpriv_file}
skip=1
@@ -1232,6 +1282,8 @@
do_cmd "echo ${param} > ${wlan_idx}"
do_cmd "cat ${wtbl_info}"
+ elif [ "${cmd}" = "ATERXSTAT" ]; then
+ convert_rxstat
else
do_cmd "mt76-test ${interface} dump"
do_cmd "mt76-test ${interface} dump stats"
diff --git a/recipes-wifi/hal/files/0002-Add-EHT-support.patch b/recipes-wifi/hal/files/0002-Add-EHT-support.patch
new file mode 100644
index 0000000..50b6495
--- /dev/null
+++ b/recipes-wifi/hal/files/0002-Add-EHT-support.patch
@@ -0,0 +1,37 @@
+From 6a3fa092965c3b19f09592b8608dd9ded6089157 Mon Sep 17 00:00:00 2001
+From: "Allen.Ye" <allen.ye@mediatek.com>
+Date: Wed, 1 Mar 2023 18:05:49 +0800
+Subject: [PATCH] Add EHT support
+
+---
+ wifi_hal_generic.h | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/wifi_hal_generic.h b/wifi_hal_generic.h
+index 01417bf..8d731c4 100644
+--- a/wifi_hal_generic.h
++++ b/wifi_hal_generic.h
+@@ -282,7 +282,9 @@ typedef enum{
+ WIFI_CHANNELBANDWIDTH_40MHZ = 0x2,
+ WIFI_CHANNELBANDWIDTH_80MHZ = 0x4,
+ WIFI_CHANNELBANDWIDTH_160MHZ = 0x8,
+- WIFI_CHANNELBANDWIDTH_80_80MHZ = 0x10
++ WIFI_CHANNELBANDWIDTH_80_80MHZ = 0x10,
++ WIFI_CHANNELBANDWIDTH_320_1MHZ = 0x20,
++ WIFI_CHANNELBANDWIDTH_320_2MHZ = 0x40
+ } wifi_channelBandwidth_t;
+
+ typedef struct {
+@@ -311,7 +313,8 @@ typedef enum {
+ WIFI_80211_VARIANT_H = 0x10,
+ WIFI_80211_VARIANT_AC = 0x20,
+ WIFI_80211_VARIANT_AD = 0x40,
+- WIFI_80211_VARIANT_AX = 0x80
++ WIFI_80211_VARIANT_AX = 0x80,
++ WIFI_80211_VARIANT_BE = 0x100
+ } wifi_ieee80211Variant_t;
+
+ #define MAXNUMBEROFTRANSMIPOWERSUPPORTED 21
+--
+2.18.0
+
diff --git a/recipes-wifi/hal/halinterface.bbappend b/recipes-wifi/hal/halinterface.bbappend
index 3a26d71..4523aa9 100644
--- a/recipes-wifi/hal/halinterface.bbappend
+++ b/recipes-wifi/hal/halinterface.bbappend
@@ -1,6 +1,6 @@
FILESEXTRAPATHS_prepend := "${THISDIR}/files:"
-SRC_URI += "file://*.patch;apply=no \
- "
+SRC_URI_append = " file://*.patch;apply=no \
+ "
#This is workaround for missing do_patch when RDK uses external sources
do_filogic_patches() {
@@ -9,6 +9,7 @@
patch -p1 < ${WORKDIR}/sta-network.patch
patch -p1 < ${WORKDIR}/add_undefined_dfs_function.patch
patch -p1 < ${WORKDIR}/0001-Add-owe-mode.patch
+ patch -p1 < ${WORKDIR}/0002-Add-EHT-support.patch
touch patch_applied
fi
}
diff --git a/recipes-wifi/hostapd/files/hostapd-full.config b/recipes-wifi/hostapd/files/hostapd-full.config
index b92f9a2..9076ebc 100644
--- a/recipes-wifi/hostapd/files/hostapd-full.config
+++ b/recipes-wifi/hostapd/files/hostapd-full.config
@@ -142,7 +142,7 @@
# RADIUS authentication server. This provides access to the integrated EAP
# server from external hosts using RADIUS.
-#CONFIG_RADIUS_SERVER=y
+CONFIG_RADIUS_SERVER=y
# Build IPv6 support for RADIUS operations
CONFIG_IPV6=y
diff --git a/recipes-wifi/hostapd/files/mac80211-EHT.sh b/recipes-wifi/hostapd/files/mac80211-EHT.sh
new file mode 100644
index 0000000..c8de5bd
--- /dev/null
+++ b/recipes-wifi/hostapd/files/mac80211-EHT.sh
@@ -0,0 +1,245 @@
+#!/bin/sh
+
+#append DRIVERS "mac80211"
+
+lookup_phy() {
+ [ -n "$phy" ] && {
+ [ -d /sys/class/ieee80211/$phy ] && return
+ }
+
+ local devpath
+ config_get devpath "$device" path
+ [ -n "$devpath" ] && {
+ phy="$(iwinfo nl80211 phyname "path=$devpath")"
+ [ -n "$phy" ] && return
+ }
+
+ local macaddr="$(config_get "$device" macaddr | tr 'A-Z' 'a-z')"
+ [ -n "$macaddr" ] && {
+ for _phy in /sys/class/ieee80211/*; do
+ [ -e "$_phy" ] || continue
+
+ [ "$macaddr" = "$(cat ${_phy}/macaddress)" ] || continue
+ phy="${_phy##*/}"
+ return
+ done
+ }
+ phy=
+ return
+}
+
+find_mac80211_phy() {
+ local device="$1"
+
+ config_get phy "$device" phy
+ lookup_phy
+ [ -n "$phy" -a -d "/sys/class/ieee80211/$phy" ] || {
+ echo "PHY for wifi device $1 not found"
+ return 1
+ }
+ config_set "$device" phy "$phy"
+
+ config_get macaddr "$device" macaddr
+ [ -z "$macaddr" ] && {
+ config_set "$device" macaddr "$(cat /sys/class/ieee80211/${phy}/macaddress)"
+ }
+
+ return 0
+}
+
+check_mac80211_device() {
+ config_get phy "$1" phy
+ [ -z "$phy" ] && {
+ find_mac80211_phy "$1" >/dev/null || return 0
+ config_get phy "$1" phy
+ }
+ [ "$phy" = "$dev" ] && found=1
+}
+
+
+__get_band_defaults() {
+ local phy="$1"
+
+ ( iw phy "$phy" info; echo ) | awk '
+BEGIN {
+ bands = ""
+}
+
+($1 == "Band" || $1 == "") && band {
+ if (channel) {
+ mode="NOHT"
+ if (ht) mode="HT20"
+ if (vht && band != "1:") mode="VHT80"
+ if (he) mode="HE80"
+ if (he && band == "1:") mode="HE20"
+ if (eht) mode="EHT80"
+ if (eht && band == "1:") mode="EHT20"
+ sub("\\[", "", channel)
+ sub("\\]", "", channel)
+ bands = bands band channel ":" mode " "
+ }
+ band=""
+}
+
+$1 == "Band" {
+ band = $2
+ channel = ""
+ vht = ""
+ ht = ""
+ he = ""
+ eht = ""
+}
+
+$0 ~ "Capabilities:" {
+ ht=1
+}
+
+$0 ~ "VHT Capabilities" {
+ vht=1
+}
+
+$0 ~ "HE Iftypes" {
+ he=1
+}
+
+$0 ~ "EHT Iftypes" {
+ eht=1
+}
+
+$1 == "*" && $3 == "MHz" && $0 !~ /disabled/ && band && !channel {
+ channel = $4
+}
+
+END {
+ print bands
+}'
+}
+
+get_band_defaults() {
+ local phy="$1"
+
+ for c in $(__get_band_defaults "$phy"); do
+ local band="${c%%:*}"
+ c="${c#*:}"
+ local chan="${c%%:*}"
+ c="${c#*:}"
+ local mode="${c%%:*}"
+
+ case "$band" in
+ 1) band=2g;;
+ 2) band=5g;;
+ 3) band=60g;;
+ 4) band=6g;;
+ *) band="";;
+ esac
+
+ [ -n "$band" ] || continue
+ [ -n "$mode_band" -a "$band" = "6g" ] && return
+
+ mode_band="$band"
+ channel="$chan"
+ htmode="$mode"
+ if [ "$band" = "6g" ]
+ then
+ encryption=sae
+ key=12345678
+ else
+ encryption=none
+ fi
+ done
+}
+
+detect_mac80211() {
+ devidx=0
+ #config_load wireless
+ while :; do
+ #config_get type "radio$devidx" type
+ [ -n "$type" ] || break
+ devidx=$(($devidx + 1))
+ done
+
+ if [ ! -f /etc/config/wireless ]; then
+ mkdir -p /etc/config
+ echo -n > /etc/config/wireless
+ fi
+
+ pcieCheck="$(uci get wireless.radio1.path)"
+ checkpath="$(realpath /sys/class/ieee80211/phy1/device | cut -d/ -f4-)"
+
+ if [[ "$pcieCheck"* != "$checkpath"* ]]; then
+ echo -n > /etc/config/wireless
+ rm /nvram/hostapd*
+ fi
+
+ old_path=""
+ for _dev in /sys/class/ieee80211/*; do
+ [ -e "$_dev" ] || continue
+
+ dev="${_dev##*/}"
+
+ found="$(uci get wireless.radio${devidx})"
+
+
+ if [ "$found" == "wifi-device" ]; then
+ devidx=$(($devidx + 1))
+ continue
+ fi
+
+ mode_band=""
+ channel=""
+ htmode=""
+ ht_capab=""
+
+
+ get_band_defaults "$dev"
+
+ path="$(realpath /sys/class/ieee80211/"$dev"/device | cut -d/ -f4-)"
+ if [ -n "$path" ]; then
+ if [ "$path" == "$old_path" ]; then
+ dev_id="set wireless.radio${devidx}.path='$path'+1"
+ else
+ dev_id="set wireless.radio${devidx}.path='$path'"
+ fi
+ else
+ dev_id="set wireless.radio${devidx}.macaddr=$(cat /sys/class/ieee80211/${dev}/macaddress)"
+ fi
+
+ if [ "$(cat /sys/class/ieee80211/"$dev"/device/device)" == "0x7906" ]; then
+ isMerlin=1
+ fi
+
+ if [ "$mode_band" = "6g" ]; then
+ channel="37"
+ fi
+ setdisable="set wireless.radio${devidx}.disabled=0"
+
+
+ if [ "$isMerlin" == "1" ] && [ "$devidx" == "2" ] && [ "$mode_band" == "2g" ]; then
+ setdisable="set wireless.radio${devidx}.disabled=1"
+ fi
+
+ uci -q batch <<-EOF
+ set wireless.radio${devidx}=wifi-device
+ set wireless.radio${devidx}.type=mac80211
+ ${dev_id}
+ set wireless.radio${devidx}.channel=${channel}
+ set wireless.radio${devidx}.band=${mode_band}
+ set wireless.radio${devidx}.htmode=$htmode
+ ${setdisable}
+ set wireless.default_radio${devidx}=wifi-iface
+ set wireless.default_radio${devidx}.device=radio${devidx}
+ set wireless.default_radio${devidx}.network=lan
+ set wireless.default_radio${devidx}.mode=ap
+ set wireless.default_radio${devidx}.ssid=Filogic_${mode_band}
+ set wireless.default_radio${devidx}.encryption=${encryption}
+EOF
+ [ -n "$key" ] && {
+ uci -q set wireless.default_radio${devidx}.key=${key}
+ }
+ uci -q commit wireless
+
+ devidx=$(($devidx + 1))
+ old_path=$path
+ done
+}
+detect_mac80211
\ No newline at end of file
diff --git a/recipes-wifi/hostapd/files/mac80211.sh b/recipes-wifi/hostapd/files/mac80211.sh
index b83e7aa..6449516 100644
--- a/recipes-wifi/hostapd/files/mac80211.sh
+++ b/recipes-wifi/hostapd/files/mac80211.sh
@@ -132,6 +132,13 @@
mode_band="$band"
channel="$chan"
htmode="$mode"
+ if [ "$band" = "6g" ]
+ then
+ encryption=sae
+ key=12345678
+ else
+ encryption=none
+ fi
done
}
@@ -217,8 +224,11 @@
set wireless.default_radio${devidx}.network=lan
set wireless.default_radio${devidx}.mode=ap
set wireless.default_radio${devidx}.ssid=Filogic_${mode_band}
- set wireless.default_radio${devidx}.encryption=none
+ set wireless.default_radio${devidx}.encryption=${encryption}
EOF
+ [ -n "$key" ] && {
+ uci -q set wireless.default_radio${devidx}.key=${key}
+ }
uci -q commit wireless
devidx=$(($devidx + 1))
diff --git a/recipes-wifi/hostapd/files/openwrt_script/hostapd.sh b/recipes-wifi/hostapd/files/openwrt_script/hostapd.sh
index 8c233a4..28bd210 100644
--- a/recipes-wifi/hostapd/files/openwrt_script/hostapd.sh
+++ b/recipes-wifi/hostapd/files/openwrt_script/hostapd.sh
@@ -265,11 +265,11 @@
config_add_int ieee80211w
config_add_int eapol_version
- config_add_string 'auth_server:host' 'server:host'
+ config_add_array auth_server acct_server
+ config_add_string 'server:host'
config_add_string auth_secret key
config_add_int 'auth_port:port' 'port:port'
- config_add_string acct_server
config_add_string acct_secret
config_add_int acct_port
config_add_int acct_interval
@@ -524,6 +524,20 @@
[ -n "$1" ] && append bss_conf "airtime_sta_weight=$1" "$N"
}
+append_auth_server() {
+ [ -n "$1" ] || return
+ append bss_conf "auth_server_addr=$1" "$N"
+ append bss_conf "auth_server_port=$auth_port" "$N"
+ [ -n "$auth_secret" ] && append bss_conf "auth_server_shared_secret=$auth_secret" "$N"
+}
+
+append_acct_server() {
+ [ -n "$1" ] || return
+ append bss_conf "acct_server_addr=$1" "$N"
+ append bss_conf "acct_server_port=$acct_port" "$N"
+ [ -n "$acct_secret" ] && append bss_conf "acct_server_shared_secret=$acct_secret" "$N"
+}
+
hostapd_set_bss_options() {
local var="$1"
local phy="$2"
@@ -542,7 +556,7 @@
wps_independent wps_device_type wps_device_name wps_manufacturer wps_pin \
macfilter ssid utf8_ssid wmm uapsd hidden short_preamble rsn_preauth \
iapp_interface eapol_version dynamic_vlan ieee80211w nasid \
- acct_server acct_secret acct_port acct_interval \
+ acct_secret acct_port acct_interval \
bss_load_update_period chan_util_avg_period sae_require_mfp sae_pwe \
multi_ap multi_ap_backhaul_ssid multi_ap_backhaul_key skip_inactivity_poll \
ppsk airtime_bss_weight airtime_bss_limit airtime_sta_weight \
@@ -614,15 +628,10 @@
set_default nasid "${macaddr//\:}"
append bss_conf "nas_identifier=$nasid" "$N"
- [ -n "$acct_server" ] && {
- append bss_conf "acct_server_addr=$acct_server" "$N"
- append bss_conf "acct_server_port=$acct_port" "$N"
- [ -n "$acct_secret" ] && \
- append bss_conf "acct_server_shared_secret=$acct_secret" "$N"
- [ -n "$acct_interval" ] && \
- append bss_conf "radius_acct_interim_interval=$acct_interval" "$N"
- json_for_each_item append_radius_acct_req_attr radius_acct_req_attr
- }
+ [ -n "$acct_interval" ] && \
+ append bss_conf "radius_acct_interim_interval=$acct_interval" "$N"
+ json_for_each_item append_acct_server acct_server
+ json_for_each_item append_radius_acct_req_attr radius_acct_req_attr
[ -n "$ocv" ] && append bss_conf "ocv=$ocv" "$N"
@@ -659,11 +668,9 @@
psk|sae|psk-sae)
json_get_vars key wpa_psk_file
if [ "$auth_type" = "psk" ] && [ "$ppsk" -ne 0 ] ; then
- json_get_vars auth_server auth_secret auth_port
+ json_get_vars auth_secret auth_port
set_default auth_port 1812
- append bss_conf "auth_server_addr=$auth_server" "$N"
- append bss_conf "auth_server_port=$auth_port" "$N"
- append bss_conf "auth_server_shared_secret=$auth_secret" "$N"
+ json_for_each_item append_auth_server auth_server
append bss_conf "macaddr_acl=2" "$N"
append bss_conf "wpa_psk_radius=2" "$N"
elif [ ${#key} -eq 64 ]; then
@@ -732,12 +739,7 @@
set_default dae_port 3799
set_default request_cui 0
- [ "$eap_server" -eq 0 ] && {
- append bss_conf "auth_server_addr=$auth_server" "$N"
- append bss_conf "auth_server_port=$auth_port" "$N"
- append bss_conf "auth_server_shared_secret=$auth_secret" "$N"
- }
-
+ [ "$eap_server" -eq 0 ] && json_for_each_item append_auth_server auth_server
[ "$request_cui" -gt 0 ] && append bss_conf "radius_request_cui=$request_cui" "$N"
[ -n "$eap_reauth_period" ] && append bss_conf "eap_reauth_period=$eap_reauth_period" "$N"
@@ -777,9 +779,7 @@
[ -n "$auth_server" ] && {
set_default auth_port 1812
- append bss_conf "auth_server_addr=$auth_server" "$N"
- append bss_conf "auth_server_port=$auth_port" "$N"
- [ -n "$auth_secret" ] && append bss_conf "auth_server_shared_secret=$auth_secret" "$N"
+ json_for_each_item append_auth_server auth_server
[ -n "$ownip" ] && append bss_conf "own_ip_addr=$ownip" "$N"
[ -n "$radius_client_addr" ] && append bss_conf "radius_client_addr=$radius_client_addr" "$N"
append bss_conf "macaddr_acl=2" "$N"
diff --git a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0010-hostapd-mtk-Add-DFS-and-ZWDFS-support.patch b/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0010-hostapd-mtk-Add-DFS-and-ZWDFS-support.patch
deleted file mode 100644
index 3237aa3..0000000
--- a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0010-hostapd-mtk-Add-DFS-and-ZWDFS-support.patch
+++ /dev/null
@@ -1,376 +0,0 @@
-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_mu(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
-
diff --git a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0010-hostapd-mtk-Add-DFS-detection-mode.patch b/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0010-hostapd-mtk-Add-DFS-detection-mode.patch
new file mode 100644
index 0000000..7ec986a
--- /dev/null
+++ b/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0010-hostapd-mtk-Add-DFS-detection-mode.patch
@@ -0,0 +1,136 @@
+From 6828156c206701f5a0e5d30afcc514f452ce0ada Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Mon, 20 Feb 2023 14:55:49 +0800
+Subject: [PATCH 10/16] hostapd: mtk: Add DFS detection mode
+
+Add DFS detection mode for testing radar detection rate.
+If DFS detection mode is on, AP will not switch channels when receiving
+a radar signal.
+This detection mode also supports background chain.
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ hostapd/config_file.c | 4 ++++
+ hostapd/ctrl_iface.c | 23 +++++++++++++++++++++++
+ src/ap/ap_config.h | 13 +++++++++++++
+ src/ap/dfs.c | 10 ++++++++++
+ 4 files changed, 50 insertions(+)
+
+diff --git a/hostapd/config_file.c b/hostapd/config_file.c
+index 63c9d40..cd15349 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 c881d37..0b4c234 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -3522,6 +3522,26 @@ 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_receive_process(struct hostapd_data *hapd,
+ char *buf, char *reply,
+ int reply_size,
+@@ -4081,6 +4101,9 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
+ reply_len = hostapd_ctrl_iface_get_mu(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 {
+ 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 a9e3d2a..77f6169 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 b5d105d..5cb7799 100644
+--- a/src/ap/dfs.c
++++ b/src/ap/dfs.c
+@@ -1317,6 +1317,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 +1370,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;
+--
+2.18.0
+
diff --git a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0011-hostapd-mtk-Add-DFS-offchan-channel-switch.patch b/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0011-hostapd-mtk-Add-DFS-offchan-channel-switch.patch
new file mode 100644
index 0000000..1d8baf8
--- /dev/null
+++ b/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0011-hostapd-mtk-Add-DFS-offchan-channel-switch.patch
@@ -0,0 +1,192 @@
+From 88dd3df28e3736af4cca0daf4f7d19ab888ea6c4 Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Mon, 20 Feb 2023 14:56:55 +0800
+Subject: [PATCH 11/16] hostapd: mtk: Add DFS offchan channel switch
+
+Add DFS background chain channel switch command for testing purpose.
+This feature is implemented via hostapd_cli command.
+Command format:
+hostapd_cli -i <interface> raw SET_OFFCHAN_CTRL chan=<dfs_channel>
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ hostapd/ctrl_iface.c | 72 ++++++++++++++++++++++++++++++++++++++++++++
+ src/ap/dfs.c | 25 ++++++---------
+ src/ap/dfs.h | 15 +++++++++
+ 3 files changed, 96 insertions(+), 16 deletions(-)
+
+diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
+index 0b4c234..6ea1573 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -3542,6 +3542,76 @@ hostapd_ctrl_iface_set_dfs_detect_mode(struct hostapd_data *hapd, char *value,
+ }
+
+
++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,
+@@ -4104,6 +4174,8 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
+ } 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/dfs.c b/src/ap/dfs.c
+index 5cb7799..1c3f678 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;
+diff --git a/src/ap/dfs.h b/src/ap/dfs.h
+index 606c1b3..c2556d2 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 */
+--
+2.18.0
+
diff --git a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0011-hostapd-mtk-Add-amsdu-set-get-ctrl.patch b/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0012-hostapd-mtk-Add-amsdu-set-get-ctrl.patch
similarity index 92%
rename from recipes-wifi/hostapd/files/patches-2.10.3/mtk-0011-hostapd-mtk-Add-amsdu-set-get-ctrl.patch
rename to recipes-wifi/hostapd/files/patches-2.10.3/mtk-0012-hostapd-mtk-Add-amsdu-set-get-ctrl.patch
index dba90d1..7db3ae2 100644
--- a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0011-hostapd-mtk-Add-amsdu-set-get-ctrl.patch
+++ b/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0012-hostapd-mtk-Add-amsdu-set-get-ctrl.patch
@@ -1,7 +1,7 @@
-From bc0722ebc1cc08be6239879fddaef37e0db2d9e0 Mon Sep 17 00:00:00 2001
+From d0128fc60d38ce4f20f8368bdc5ea9ed19a329b7 Mon Sep 17 00:00:00 2001
From: Evelyn Tsai <evelyn.tsai@mediatek.com>
Date: Fri, 16 Dec 2022 03:57:11 +0800
-Subject: [PATCH 11/15] hostapd: mtk: Add amsdu set get ctrl
+Subject: [PATCH 12/16] hostapd: mtk: Add amsdu set get ctrl
---
hostapd/config_file.c | 9 +++
@@ -20,7 +20,7 @@
13 files changed, 207 insertions(+), 1 deletion(-)
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
-index cd1534952..10ea52518 100644
+index cd15349..10ea525 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -4807,6 +4807,15 @@ static int hostapd_config_fill(struct hostapd_config *conf,
@@ -40,7 +40,7 @@
wpa_printf(MSG_ERROR,
"Line %d: unknown configuration item '%s'",
diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
-index 6ea1573b8..0ad8451aa 100644
+index 6ea1573..0ad8451 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -3612,6 +3612,30 @@ hostapd_ctrl_iface_set_offchan_ctrl(struct hostapd_data *hapd, char *cmd,
@@ -84,7 +84,7 @@
os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
reply_len = 16;
diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
-index c2a123a8c..30b3392e6 100644
+index c2a123a..30b3392 100644
--- a/hostapd/hostapd_cli.c
+++ b/hostapd/hostapd_cli.c
@@ -1593,6 +1593,13 @@ static int hostapd_cli_cmd_get_ibf(struct wpa_ctrl *ctrl, int argc,
@@ -111,7 +111,7 @@
};
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
-index 7a96cb8b2..85ad5e444 100644
+index 7a96cb8..85ad5e4 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -299,6 +299,7 @@ struct hostapd_config * hostapd_config_defaults(void)
@@ -123,7 +123,7 @@
return conf;
}
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
-index 77f6169d2..a9ac39619 100644
+index 77f6169..a9ac396 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -1161,6 +1161,7 @@ struct hostapd_config {
@@ -135,7 +135,7 @@
enum three_wire_mode {
diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
-index 60ae8253b..1a82f234c 100644
+index 60ae825..1a82f23 100644
--- a/src/ap/ap_drv_ops.c
+++ b/src/ap/ap_drv_ops.c
@@ -1077,4 +1077,18 @@ int hostapd_drv_ibf_dump(struct hostapd_data *hapd, u8 *ibf_enable)
@@ -159,7 +159,7 @@
}
\ No newline at end of file
diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
-index ab9aedcee..4406666fd 100644
+index ab9aedc..4406666 100644
--- a/src/ap/ap_drv_ops.h
+++ b/src/ap/ap_drv_ops.h
@@ -147,6 +147,8 @@ int hostapd_drv_mu_dump(struct hostapd_data *hapd, u8 *mu_onoff);
@@ -172,10 +172,10 @@
#include "drivers/driver.h"
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
-index a0229c9ca..152060db4 100644
+index da7f7d8..a18e744 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
-@@ -2310,6 +2310,8 @@ dfs_offload:
+@@ -2308,6 +2308,8 @@ dfs_offload:
goto fail;
if (hostapd_drv_ibf_ctrl(hapd) < 0)
goto fail;
@@ -185,7 +185,7 @@
wpa_printf(MSG_DEBUG, "%s: Setup of interface done.",
iface->bss[0]->conf->iface);
diff --git a/src/common/mtk_vendor.h b/src/common/mtk_vendor.h
-index 4050cf886..0999ea9e2 100644
+index 4050cf8..0999ea9 100644
--- a/src/common/mtk_vendor.h
+++ b/src/common/mtk_vendor.h
@@ -167,7 +167,6 @@ enum mtk_vendor_attr_wireless_ctrl {
@@ -220,13 +220,13 @@
MTK_VENDOR_ATTR_RFEATURE_CTRL_UNSPEC,
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
-index aa23fbdb3..b07aaf3fe 100644
+index 71ded61..265d86d 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
-@@ -4727,6 +4727,15 @@ struct wpa_driver_ops {
+@@ -4720,6 +4720,15 @@ struct wpa_driver_ops {
*
*/
- int (*start_disabled)(void *priv);
+ int (*ibf_dump)(void *priv, u8 *ibf_enable);
+
+ /**
+ * amsdu_ctrl - enable/disable amsdu
@@ -240,11 +240,11 @@
/**
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
-index 7472542cc..6702384ef 100644
+index 5c2a291..d91b29c 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
-@@ -12804,6 +12804,118 @@ fail:
- return ret;
+@@ -12776,6 +12776,118 @@ fail:
+ return -ENOBUFS;
}
+static int nl80211_enable_amsdu(void *priv, u8 amsdu)
@@ -362,15 +362,15 @@
const struct wpa_driver_ops wpa_driver_nl80211_ops = {
.name = "nl80211",
.desc = "Linux nl80211/cfg80211",
-@@ -12959,4 +13071,6 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
+@@ -12930,4 +13042,6 @@ 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,
+ .amsdu_ctrl = nl80211_enable_amsdu,
+ .amsdu_dump = nl80211_dump_amsdu,
};
diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h
-index 607592ceb..e57022409 100644
+index 607592c..e570224 100644
--- a/src/drivers/driver_nl80211.h
+++ b/src/drivers/driver_nl80211.h
@@ -185,6 +185,7 @@ struct wpa_driver_nl80211_data {
@@ -382,7 +382,7 @@
u64 vendor_scan_cookie;
u64 remain_on_chan_cookie;
diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
-index 9ecc0ff9a..fcfa68bf7 100644
+index 9ecc0ff..fcfa68b 100644
--- a/src/drivers/driver_nl80211_capa.c
+++ b/src/drivers/driver_nl80211_capa.c
@@ -1065,6 +1065,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
@@ -396,5 +396,5 @@
}
--
-2.25.1
+2.18.0
diff --git a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0012-hostapd-mtk-Add-he_ldpc-configuration.patch b/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0013-hostapd-mtk-Add-he_ldpc-configuration.patch
similarity index 90%
rename from recipes-wifi/hostapd/files/patches-2.10.3/mtk-0012-hostapd-mtk-Add-he_ldpc-configuration.patch
rename to recipes-wifi/hostapd/files/patches-2.10.3/mtk-0013-hostapd-mtk-Add-he_ldpc-configuration.patch
index 63101e0..4df0ba6 100644
--- a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0012-hostapd-mtk-Add-he_ldpc-configuration.patch
+++ b/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0013-hostapd-mtk-Add-he_ldpc-configuration.patch
@@ -1,7 +1,7 @@
-From b49ce922afa13fe8ea5d847753dfb7641b70c9a4 Mon Sep 17 00:00:00 2001
+From ebbf23ac8c19224b34523e8b9820e32f0789fe11 Mon Sep 17 00:00:00 2001
From: MeiChia Chiu <meichia.chiu@mediatek.com>
Date: Thu, 12 Jan 2023 15:18:19 +0800
-Subject: [PATCH 12/15] hostapd: mtk: Add he_ldpc configuration
+Subject: [PATCH 13/16] hostapd: mtk: Add he_ldpc configuration
---
hostapd/config_file.c | 2 ++
@@ -13,7 +13,7 @@
6 files changed, 19 insertions(+)
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
-index 10ea52518..4237a5cca 100644
+index 10ea525..4237a5c 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -3508,6 +3508,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
@@ -26,7 +26,7 @@
conf->he_op.he_bss_color = atoi(pos) & 0x3f;
conf->he_op.he_bss_color_disabled = 0;
diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
-index ea67aa100..e3a5eb365 100644
+index ea67aa1..e3a5eb3 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -830,6 +830,11 @@ wmm_ac_vo_acm=0
@@ -42,7 +42,7 @@
#he_bss_color=1
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
-index 85ad5e444..b283de624 100644
+index 85ad5e4..b283de6 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -268,6 +268,7 @@ struct hostapd_config * hostapd_config_defaults(void)
@@ -54,7 +54,7 @@
HE_OPERATION_RTS_THRESHOLD_OFFSET;
/* Set default basic MCS/NSS set to single stream MCS 0-7 */
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
-index a9ac39619..b8b20a7aa 100644
+index a9ac396..b8b20a7 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -929,6 +929,7 @@ struct hostapd_bss_config {
@@ -66,7 +66,7 @@
bool he_su_beamformee;
bool he_mu_beamformer;
diff --git a/src/ap/ieee802_11_he.c b/src/ap/ieee802_11_he.c
-index b5b7e5d46..f27aeb196 100644
+index b5b7e5d..f27aeb1 100644
--- a/src/ap/ieee802_11_he.c
+++ b/src/ap/ieee802_11_he.c
@@ -138,6 +138,13 @@ u8 * hostapd_eid_he_capab(struct hostapd_data *hapd, u8 *eid,
@@ -84,7 +84,7 @@
cap->he_phy_capab_info[HE_PHYCAP_SU_BEAMFORMER_CAPAB_IDX] |=
HE_PHYCAP_SU_BEAMFORMER_CAPAB;
diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
-index 65e125e83..62088bda6 100644
+index 65e125e..62088bd 100644
--- a/src/common/ieee802_11_defs.h
+++ b/src/common/ieee802_11_defs.h
@@ -2298,6 +2298,9 @@ struct ieee80211_spatial_reuse {
@@ -98,5 +98,5 @@
#define HE_PHYCAP_SU_BEAMFORMER_CAPAB ((u8) BIT(7))
#define HE_PHYCAP_SU_BEAMFORMEE_CAPAB_IDX 4
--
-2.25.1
+2.18.0
diff --git a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0013-hostapd-mtk-Add-the-broadcast-destination-address-of.patch b/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0014-hostapd-mtk-Add-the-broadcast-destination-address-of.patch
similarity index 89%
rename from recipes-wifi/hostapd/files/patches-2.10.3/mtk-0013-hostapd-mtk-Add-the-broadcast-destination-address-of.patch
rename to recipes-wifi/hostapd/files/patches-2.10.3/mtk-0014-hostapd-mtk-Add-the-broadcast-destination-address-of.patch
index 1222510..f0d25c6 100644
--- a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0013-hostapd-mtk-Add-the-broadcast-destination-address-of.patch
+++ b/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0014-hostapd-mtk-Add-the-broadcast-destination-address-of.patch
@@ -1,7 +1,7 @@
-From 52a1775318c9926a1dbf4f7c563e95b5be3c9bd6 Mon Sep 17 00:00:00 2001
+From bb5cb086162828392a04820063ad7997d8ae26d7 Mon Sep 17 00:00:00 2001
From: MeiChia Chiu <meichia.chiu@mediatek.com>
Date: Tue, 17 Jan 2023 13:25:18 +0800
-Subject: [PATCH 13/15] hostapd: mtk: Add the broadcast destination address of
+Subject: [PATCH 14/16] hostapd: mtk: Add the broadcast destination address of
Probe Response frame on 6 GHz
According to IEEE 802.11ax 26.17.2.3.2,
@@ -19,7 +19,7 @@
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/src/ap/beacon.c b/src/ap/beacon.c
-index 1a26f11ff..f3ea5c277 100644
+index 1a26f11..f3ea5c2 100644
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -1156,8 +1156,13 @@ void handle_probe_req(struct hostapd_data *hapd,
@@ -39,5 +39,5 @@
return;
--
-2.25.1
+2.18.0
diff --git a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0014-hostapd-mtk-Add-vendor-command-attribute-for-RTS-BW-.patch b/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0015-hostapd-mtk-Add-vendor-command-attribute-for-RTS-BW-.patch
similarity index 79%
rename from recipes-wifi/hostapd/files/patches-2.10.3/mtk-0014-hostapd-mtk-Add-vendor-command-attribute-for-RTS-BW-.patch
rename to recipes-wifi/hostapd/files/patches-2.10.3/mtk-0015-hostapd-mtk-Add-vendor-command-attribute-for-RTS-BW-.patch
index 3689f74..5fcd0c5 100644
--- a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0014-hostapd-mtk-Add-vendor-command-attribute-for-RTS-BW-.patch
+++ b/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0015-hostapd-mtk-Add-vendor-command-attribute-for-RTS-BW-.patch
@@ -1,7 +1,7 @@
-From 7d741c99f2e211abe70593ff6e8265633bed0d8a Mon Sep 17 00:00:00 2001
+From 1db373190399a907b27141c199841aeafd4643da Mon Sep 17 00:00:00 2001
From: "himanshu.goyal" <himanshu.goyal@mediatek.com>
Date: Tue, 24 Jan 2023 19:06:44 +0800
-Subject: [PATCH 14/15] hostapd: mtk: Add vendor command attribute for RTS BW
+Subject: [PATCH 15/16] hostapd: mtk: Add vendor command attribute for RTS BW
signaling.
Signed-off-by: himanshu.goyal <himanshu.goyal@mediatek.com>
@@ -10,7 +10,7 @@
1 file changed, 1 insertion(+)
diff --git a/src/common/mtk_vendor.h b/src/common/mtk_vendor.h
-index 0999ea9e2..fb12895ce 100644
+index 0999ea9..fb12895 100644
--- a/src/common/mtk_vendor.h
+++ b/src/common/mtk_vendor.h
@@ -169,6 +169,7 @@ enum mtk_vendor_attr_wireless_ctrl {
@@ -22,5 +22,5 @@
/* keep last */
NUM_MTK_VENDOR_ATTRS_WIRELESS_CTRL,
--
-2.25.1
+2.18.0
diff --git a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0015-hostapd-mtk-6G-band-does-not-require-DFS.patch b/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0016-hostapd-mtk-6G-band-does-not-require-DFS.patch
similarity index 76%
rename from recipes-wifi/hostapd/files/patches-2.10.3/mtk-0015-hostapd-mtk-6G-band-does-not-require-DFS.patch
rename to recipes-wifi/hostapd/files/patches-2.10.3/mtk-0016-hostapd-mtk-6G-band-does-not-require-DFS.patch
index 642c625..33fea78 100644
--- a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0015-hostapd-mtk-6G-band-does-not-require-DFS.patch
+++ b/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0016-hostapd-mtk-6G-band-does-not-require-DFS.patch
@@ -1,14 +1,14 @@
-From 619075bb430c908c61a818c45e36f1ca76020741 Mon Sep 17 00:00:00 2001
+From efa1d271d28c84b8ca77ffc3ca7cb75e727088a0 Mon Sep 17 00:00:00 2001
From: Peter Chiu <chui-hao.chiu@mediatek.com>
Date: Mon, 13 Feb 2023 11:03:53 +0800
-Subject: [PATCH 15/15] hostapd: mtk: 6G band does not require DFS
+Subject: [PATCH 16/16] hostapd: mtk: 6G band does not require DFS
---
src/ap/dfs.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/ap/dfs.c b/src/ap/dfs.c
-index 1c3f6785b..4b1e64246 100644
+index 1c3f678..4b1e642 100644
--- a/src/ap/dfs.c
+++ b/src/ap/dfs.c
@@ -1506,6 +1506,7 @@ int hostapd_is_dfs_required(struct hostapd_iface *iface)
@@ -20,5 +20,5 @@
return 0;
--
-2.25.1
+2.18.0
diff --git a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0016-hostapd-mtk-Add-available-color-bitmap.patch b/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0016-hostapd-mtk-Add-available-color-bitmap.patch
new file mode 100644
index 0000000..9bbbf87
--- /dev/null
+++ b/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0016-hostapd-mtk-Add-available-color-bitmap.patch
@@ -0,0 +1,337 @@
+From e7790a1bceca6b7612f29b00c429cf23f5dd9e3a Mon Sep 17 00:00:00 2001
+From: Yi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
+Date: Thu, 26 Jan 2023 09:16:00 +0800
+Subject: [PATCH] hostapd: mtk: Add available color bitmap
+
+Signed-off-by: Yi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
+---
+ hostapd/ctrl_iface.c | 74 +++++++++++++++++++++++++++++++
+ hostapd/hostapd_cli.c | 18 ++++++++
+ src/ap/ap_drv_ops.c | 10 ++++-
+ src/ap/ap_drv_ops.h | 2 +
+ src/common/mtk_vendor.h | 11 +++++
+ src/drivers/driver.h | 8 ++++
+ src/drivers/driver_nl80211.c | 66 +++++++++++++++++++++++++++
+ src/drivers/driver_nl80211.h | 1 +
+ src/drivers/driver_nl80211_capa.c | 3 ++
+ 9 files changed, 192 insertions(+), 1 deletion(-)
+
+diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
+index 0ad8451..b0d5ded 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -3635,6 +3635,76 @@ hostapd_ctrl_iface_get_amsdu(struct hostapd_data *hapd, char *buf,
+ return ret;
+ }
+
++static int
++hostapd_ctrl_iface_get_bss_color(struct hostapd_data *hapd, char *buf,
++ size_t buflen)
++{
++ int ret;
++ char *pos, *end;
++ int i;
++
++ pos = buf;
++ end = buf + buflen;
++
++ if (hapd->iface->conf->he_op.he_bss_color_disabled)
++ ret = os_snprintf(buf, buflen, "BSS Color disabled\n");
++ else
++ ret = os_snprintf(buf, buflen, "BSS Color=%u\n",
++ hapd->iface->conf->he_op.he_bss_color);
++
++ pos += ret;
++
++ return pos - buf;
++}
++
++
++static int
++hostapd_ctrl_iface_get_aval_color_bmp(struct hostapd_data *hapd, char *buf,
++ size_t buflen)
++{
++ int ret;
++ char *pos, *end;
++ int i;
++ u64 aval_color_bmp = 0;
++
++ hostapd_drv_get_aval_bss_color_bmp(hapd, &aval_color_bmp);
++ hapd->color_collision_bitmap = ~aval_color_bmp;
++
++ pos = buf;
++ end = buf + buflen;
++
++ ret = os_snprintf(buf, buflen,
++ "available color bitmap=0x%llx\n",
++ aval_color_bmp);
++ if (os_snprintf_error(end - pos, ret))
++ return pos - buf;
++ pos += ret;
++
++ for (i = 0; i < HE_OPERATION_BSS_COLOR_MAX; i++) {
++ int bit = !!((aval_color_bmp >> i) & 1LLU);
++
++ if (i % 8 == 0) {
++ ret = os_snprintf(pos, end - pos, "%2d: ", i);
++ if (os_snprintf_error(end - pos, ret))
++ return pos - buf;
++ pos += ret;
++ }
++
++ ret = os_snprintf(pos, end - pos, "%d ", bit);
++ if (os_snprintf_error(end - pos, ret))
++ return pos - buf;
++ pos += ret;
++
++ if (i % 8 == 7) {
++ ret = os_snprintf(pos, end - pos, "\n");
++ if (os_snprintf_error(end - pos, ret))
++ return pos - buf;
++ pos += ret;
++ }
++ }
++ return pos - buf;
++}
++
+
+ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
+ char *buf, char *reply,
+@@ -4202,6 +4272,10 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
+ reply_len = hostapd_ctrl_iface_set_offchan_ctrl(hapd, buf + 16, reply, reply_size);
+ } else if (os_strncmp(buf, "GET_AMSDU", 9) == 0) {
+ reply_len = hostapd_ctrl_iface_get_amsdu(hapd, reply, reply_size);
++ } else if (os_strncmp(buf, "GET_BSS_COLOR", 13) == 0) {
++ reply_len = hostapd_ctrl_iface_get_bss_color(hapd, reply, reply_size);
++ } else if (os_strncmp(buf, "AVAL_COLOR_BMP", 14) == 0) {
++ reply_len = hostapd_ctrl_iface_get_aval_color_bmp(hapd, reply, reply_size);
+ } else {
+ os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
+ reply_len = 16;
+diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
+index 30b3392..b6cf52e 100644
+--- a/hostapd/hostapd_cli.c
++++ b/hostapd/hostapd_cli.c
+@@ -1578,6 +1578,20 @@ static int hostapd_cli_cmd_reload_wpa_psk(struct wpa_ctrl *ctrl, int argc,
+ }
+
+
++static int hostapd_cli_cmd_get_bss_color(struct wpa_ctrl *ctrl, int argc,
++ char *argv[])
++{
++ return wpa_ctrl_command(ctrl, "GET_BSS_COLOR");
++}
++
++
++static int hostapd_cli_cmd_get_aval_color_bmp(struct wpa_ctrl *ctrl, int argc,
++ char *argv[])
++{
++ return wpa_ctrl_command(ctrl, "AVAL_COLOR_BMP");
++}
++
++
+ #ifdef ANDROID
+ static int hostapd_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[])
+ {
+@@ -1795,6 +1809,10 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
+ "<addr> [req_mode=] <measurement request hexdump> = send a Beacon report request to a station" },
+ { "reload_wpa_psk", hostapd_cli_cmd_reload_wpa_psk, NULL,
+ "= reload wpa_psk_file only" },
++ { "get_bss_color", hostapd_cli_cmd_get_bss_color, NULL,
++ "= get current BSS color" },
++ { "get_color_bmp", hostapd_cli_cmd_get_aval_color_bmp, NULL,
++ "= get available BSS color bitmap" },
+ #ifdef ANDROID
+ { "driver", hostapd_cli_cmd_driver, NULL,
+ "<driver sub command> [<hex formatted data>] = send driver command data" },
+diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
+index 1a82f23..decffdd 100644
+--- a/src/ap/ap_drv_ops.c
++++ b/src/ap/ap_drv_ops.c
+@@ -1091,4 +1091,12 @@ int hostapd_drv_amsdu_dump(struct hostapd_data *hapd, u8 *amsdu)
+ if (!hapd->driver || !hapd->driver->amsdu_dump)
+ return 0;
+ return hapd->driver->amsdu_dump(hapd->drv_priv, amsdu);
+-}
+\ No newline at end of file
++}
++
++int hostapd_drv_get_aval_bss_color_bmp(struct hostapd_data *hapd, u64 *aval_color_bmp)
++{
++ if (!hapd->driver || !hapd->driver->get_aval_color_bmp ||
++ hapd->iface->conf->he_op.he_bss_color_disabled)
++ return 0;
++ return hapd->driver->get_aval_color_bmp(hapd->drv_priv, aval_color_bmp);
++}
+diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
+index 4406666..61c1360 100644
+--- a/src/ap/ap_drv_ops.h
++++ b/src/ap/ap_drv_ops.h
+@@ -149,6 +149,8 @@ int hostapd_drv_ibf_ctrl(struct hostapd_data *hapd);
+ int hostapd_drv_ibf_dump(struct hostapd_data *hapd, u8 *ibf_enable);
+ int hostapd_drv_amsdu_ctrl(struct hostapd_data *hapd);
+ int hostapd_drv_amsdu_dump(struct hostapd_data *hapd, u8 *amsdu);
++int hostapd_drv_get_aval_bss_color_bmp(struct hostapd_data *hapd,
++ u64 *aval_color_bmp);
+
+ #include "drivers/driver.h"
+
+diff --git a/src/common/mtk_vendor.h b/src/common/mtk_vendor.h
+index 0999ea9..f2afb2e 100644
+--- a/src/common/mtk_vendor.h
++++ b/src/common/mtk_vendor.h
+@@ -15,6 +15,7 @@ enum mtk_nl80211_vendor_subcmds {
+ MTK_NL80211_VENDOR_SUBCMD_EDCCA_CTRL = 0xc7,
+ MTK_NL80211_VENDOR_SUBCMD_3WIRE_CTRL = 0xc8,
+ MTK_NL80211_VENDOR_SUBCMD_IBF_CTRL = 0xc9,
++ MTK_NL80211_VENDOR_SUBCMD_BSS_COLOR_CTRL = 0xca,
+ };
+
+ enum mtk_vendor_attr_edcca_ctrl {
+@@ -252,6 +253,16 @@ ibf_dump_policy[NUM_MTK_VENDOR_ATTRS_IBF_DUMP] = {
+ [MTK_VENDOR_ATTR_IBF_DUMP_ENABLE] = { .type = NLA_U8 },
+ };
+
++enum mtk_vendor_attr_bss_color_ctrl {
++ MTK_VENDOR_ATTR_BSS_COLOR_CTRL_UNSPEC,
++
++ MTK_VENDOR_ATTR_AVAL_BSS_COLOR_BMP,
++
++ /* keep last */
++ NUM_MTK_VENDOR_ATTRS_BSS_COLOR_CTRL,
++ MTK_VENDOR_ATTR_BSS_COLOR_CTRL_MAX =
++ NUM_MTK_VENDOR_ATTRS_BSS_COLOR_CTRL - 1
++};
+
+ #define CSI_MAX_COUNT 256
+ #define ETH_ALEN 6
+diff --git a/src/drivers/driver.h b/src/drivers/driver.h
+index b07aaf3..266c630 100644
+--- a/src/drivers/driver.h
++++ b/src/drivers/driver.h
+@@ -4736,6 +4736,14 @@ struct wpa_driver_ops {
+ */
+ int (*amsdu_ctrl)(void *priv, u8 amsdu);
+ int (*amsdu_dump)(void *priv, u8 *amsdu);
++
++ /**
++ * get_aval_color_bmp - get available BSS color bitmap
++ * @priv: Private driver interface data
++ * @aval_color_bmp: available bss color bitmap
++ *
++ */
++ int (*get_aval_color_bmp)(void *priv, u64 *aval_color_bmp);
+ };
+
+ /**
+diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
+index 6702384..c8771f7 100644
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -12433,6 +12433,71 @@ static int nl80211_dpp_listen(void *priv, bool enable)
+ }
+ #endif /* CONFIG_DPP */
+
++static int nl80211_get_aval_color_bmp_handler(struct nl_msg *msg, void *arg)
++{
++ u64 *aval_color_bmp = arg;
++ struct nlattr *tb[NL80211_ATTR_MAX + 1];
++ struct nlattr *tb_vendor[MTK_VENDOR_ATTR_BSS_COLOR_CTRL_MAX + 1];
++ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
++ struct nlattr *nl_vend, *attr;
++
++ static const struct nla_policy
++ bss_color_ctrl_policy[NUM_MTK_VENDOR_ATTRS_BSS_COLOR_CTRL + 1] = {
++ [MTK_VENDOR_ATTR_AVAL_BSS_COLOR_BMP] = { .type = NLA_U64 },
++ };
++
++ nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
++ genlmsg_attrlen(gnlh, 0), NULL);
++
++ nl_vend = tb[NL80211_ATTR_VENDOR_DATA];
++ if (!nl_vend)
++ return NL_SKIP;
++
++ nla_parse(tb_vendor, MTK_VENDOR_ATTR_BSS_COLOR_CTRL_MAX,
++ nla_data(nl_vend), nla_len(nl_vend), NULL);
++
++ *aval_color_bmp = nla_get_u64(tb_vendor[MTK_VENDOR_ATTR_AVAL_BSS_COLOR_BMP]);
++
++ return 0;
++}
++
++static int nl80211_get_aval_color_bmp(void *priv, u64 *aval_color_bmp)
++{
++ struct i802_bss *bss = priv;
++ struct wpa_driver_nl80211_data *drv = bss->drv;
++ struct nl_msg *msg;
++ struct nlattr *attr;
++ int ret;
++
++ if (!drv->mtk_bss_color_vendor_cmd_avail) {
++ wpa_printf(MSG_INFO,
++ "nl80211: Driver does not support BSS COLOR vendor cmd");
++ return 0;
++ }
++
++ if (!(msg = nl80211_drv_msg(drv, NLM_F_DUMP, NL80211_CMD_VENDOR)) ||
++ nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_MTK) ||
++ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
++ MTK_NL80211_VENDOR_SUBCMD_BSS_COLOR_CTRL))
++ return -ENOBUFS;
++
++ attr = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
++ if (!attr) {
++ nlmsg_free(msg);
++ return -1;
++ }
++
++ nla_nest_end(msg, attr);
++
++ ret = send_and_recv_msgs(drv, msg,
++ nl80211_get_aval_color_bmp_handler, aval_color_bmp, NULL, NULL);
++
++ if (ret) {
++ wpa_printf(MSG_ERROR, "Failed to send BSS COLOR vendor cmd. ret=%d (%s) ",
++ ret, strerror(-ret));
++ }
++ return ret;
++}
+
+ #ifdef CONFIG_TESTING_OPTIONS
+
+@@ -13073,4 +13138,5 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
+ .start_disabled = nl80211_start_disabled,
+ .amsdu_ctrl = nl80211_enable_amsdu,
+ .amsdu_dump = nl80211_dump_amsdu,
++ .get_aval_color_bmp = nl80211_get_aval_color_bmp,
+ };
+diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h
+index e570224..b90c8fa 100644
+--- a/src/drivers/driver_nl80211.h
++++ b/src/drivers/driver_nl80211.h
+@@ -186,6 +186,7 @@ struct wpa_driver_nl80211_data {
+ unsigned int mtk_3wire_vendor_cmd_avail:1;
+ unsigned int mtk_ibf_vendor_cmd_avail:1;
+ unsigned int mtk_wireless_vendor_cmd_avail:1;
++ unsigned int mtk_bss_color_vendor_cmd_avail:1;
+
+ u64 vendor_scan_cookie;
+ u64 remain_on_chan_cookie;
+diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
+index fcfa68b..c3c7b41 100644
+--- a/src/drivers/driver_nl80211_capa.c
++++ b/src/drivers/driver_nl80211_capa.c
+@@ -1068,6 +1068,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
+ case MTK_NL80211_VENDOR_SUBCMD_WIRELESS_CTRL:
+ drv->mtk_wireless_vendor_cmd_avail = 1;
+ break;
++ case MTK_NL80211_VENDOR_SUBCMD_BSS_COLOR_CTRL :
++ drv->mtk_bss_color_vendor_cmd_avail = 1;
++ break;
+ }
+ }
+
+--
+2.39.0
+
diff --git a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0017-hostapd-mtk-Fix-sending-wrong-VHT-operation-IE-in-CS.patch b/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0017-hostapd-mtk-Fix-sending-wrong-VHT-operation-IE-in-CS.patch
new file mode 100644
index 0000000..265c37a
--- /dev/null
+++ b/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0017-hostapd-mtk-Fix-sending-wrong-VHT-operation-IE-in-CS.patch
@@ -0,0 +1,46 @@
+From f6bfd9a4a6c0d08e0dec9311873c9e863a07c9a8 Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Mon, 20 Feb 2023 11:01:18 +0800
+Subject: [PATCH] hostapd: mtk: Fix sending wrong VHT operation IE in CSA while
+ using ZWDFS
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ src/ap/dfs.c | 14 +++++++++-----
+ 1 file changed, 9 insertions(+), 5 deletions(-)
+
+diff --git a/src/ap/dfs.c b/src/ap/dfs.c
+index 4b1e642..307a4e1 100644
+--- a/src/ap/dfs.c
++++ b/src/ap/dfs.c
+@@ -1110,6 +1110,14 @@ static int
+ hostapd_dfs_start_channel_switch_background(struct hostapd_iface *iface)
+ {
+ u8 current_vht_oper_chwidth = hostapd_get_oper_chwidth(iface->conf);
++ int ret;
++
++ ret = hostapd_dfs_request_channel_switch(iface, iface->radar_background.channel,
++ iface->radar_background.freq,
++ iface->radar_background.secondary_channel,
++ current_vht_oper_chwidth,
++ iface->radar_background.centr_freq_seg0_idx,
++ iface->radar_background.centr_freq_seg1_idx);
+
+ iface->conf->channel = iface->radar_background.channel;
+ iface->freq = iface->radar_background.freq;
+@@ -1122,11 +1130,7 @@ hostapd_dfs_start_channel_switch_background(struct hostapd_iface *iface)
+
+ hostpad_dfs_update_background_chain(iface);
+
+- return hostapd_dfs_request_channel_switch(
+- iface, iface->conf->channel, iface->freq,
+- iface->conf->secondary_channel, current_vht_oper_chwidth,
+- hostapd_get_oper_centr_freq_seg0_idx(iface->conf),
+- hostapd_get_oper_centr_freq_seg1_idx(iface->conf));
++ return ret;
+ }
+
+
+--
+2.18.0
+
diff --git a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0018-hostapd-mtk-Add-sta-assisted-DFS-state-update-mechan.patch b/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0018-hostapd-mtk-Add-sta-assisted-DFS-state-update-mechan.patch
new file mode 100644
index 0000000..db3c813
--- /dev/null
+++ b/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0018-hostapd-mtk-Add-sta-assisted-DFS-state-update-mechan.patch
@@ -0,0 +1,189 @@
+From 3337e7b4f75a66e53e1320e49deba2b58a8a80b0 Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Mon, 20 Feb 2023 10:51:47 +0800
+Subject: [PATCH 18/19] hostapd: mtk: Add sta-assisted DFS state update
+ mechanism
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ src/ap/dfs.c | 20 ++++++++++++++++++++
+ src/ap/dfs.h | 3 +++
+ src/ap/drv_callbacks.c | 28 ++++++++++++++++++++++++++++
+ src/common/wpa_ctrl.h | 1 +
+ src/drivers/driver.h | 14 ++++++++++++++
+ src/drivers/driver_nl80211_event.c | 6 ++++++
+ src/drivers/nl80211_copy.h | 6 ++++++
+ 7 files changed, 78 insertions(+)
+
+diff --git a/src/ap/dfs.c b/src/ap/dfs.c
+index 307a4e1..d082fe0 100644
+--- a/src/ap/dfs.c
++++ b/src/ap/dfs.c
+@@ -1503,6 +1503,26 @@ int hostapd_dfs_nop_finished(struct hostapd_iface *iface, int freq,
+ }
+
+
++int hostapd_dfs_sta_update_state(struct hostapd_iface *iface, int freq,
++ int ht_enabled, int chan_offset, int chan_width,
++ int cf1, int cf2, u32 state)
++{
++ wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_STA_UPDATE
++ "freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d state=%s",
++ freq, ht_enabled, chan_offset, chan_width, cf1, cf2,
++ (state == HOSTAPD_CHAN_DFS_AVAILABLE) ? "available" : "usable");
++
++ /* Proceed only if DFS is not offloaded to the driver */
++ if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD)
++ return 0;
++
++ set_dfs_state(iface, freq, ht_enabled, chan_offset, chan_width,
++ cf1, cf2, state);
++
++ return 0;
++}
++
++
+ int hostapd_is_dfs_required(struct hostapd_iface *iface)
+ {
+ int n_chans, n_chans1, start_chan_idx, start_chan_idx1, res;
+diff --git a/src/ap/dfs.h b/src/ap/dfs.h
+index c2556d2..25ba29c 100644
+--- a/src/ap/dfs.h
++++ b/src/ap/dfs.h
+@@ -30,6 +30,9 @@ int hostapd_dfs_radar_detected(struct hostapd_iface *iface, int freq,
+ int hostapd_dfs_nop_finished(struct hostapd_iface *iface, int freq,
+ int ht_enabled,
+ int chan_offset, int chan_width, int cf1, int cf2);
++int hostapd_dfs_sta_update_state(struct hostapd_iface *iface, int freq,
++ int ht_enabled, int chan_offset, int chan_width,
++ int cf1, int cf2, u32 state);
+ int hostapd_is_dfs_required(struct hostapd_iface *iface);
+ int hostapd_is_dfs_chan_available(struct hostapd_iface *iface);
+ int hostapd_dfs_start_cac(struct hostapd_iface *iface, int freq,
+diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
+index 09783cb..275f6b3 100644
+--- a/src/ap/drv_callbacks.c
++++ b/src/ap/drv_callbacks.c
+@@ -1790,6 +1790,24 @@ static void hostapd_event_dfs_cac_started(struct hostapd_data *hapd,
+ radar->cf1, radar->cf2);
+ }
+
++static void hostapd_event_dfs_sta_cac_skipped(struct hostapd_data *hapd,
++ struct dfs_event *radar)
++{
++ wpa_printf(MSG_DEBUG, "DFS CAC skipped (by STA) on %d MHz", radar->freq);
++ hostapd_dfs_sta_update_state(hapd->iface, radar->freq, radar->ht_enabled,
++ radar->chan_offset, radar->chan_width,
++ radar->cf1, radar->cf2, HOSTAPD_CHAN_DFS_AVAILABLE);
++}
++
++static void hostapd_event_dfs_sta_cac_expired(struct hostapd_data *hapd,
++ struct dfs_event *radar)
++{
++ wpa_printf(MSG_DEBUG, "DFS CAC expired (by STA) on %d MHz", radar->freq);
++ hostapd_dfs_sta_update_state(hapd->iface, radar->freq, radar->ht_enabled,
++ radar->chan_offset, radar->chan_width,
++ radar->cf1, radar->cf2, HOSTAPD_CHAN_DFS_USABLE);
++}
++
+ #endif /* NEED_AP_MLME */
+
+
+@@ -2064,6 +2082,16 @@ void hostapd_wpa_event(void *ctx, enum wpa_event_type event,
+ break;
+ hostapd_event_dfs_nop_finished(hapd, &data->dfs_event);
+ break;
++ case EVENT_DFS_STA_CAC_SKIPPED:
++ if (!data)
++ break;
++ hostapd_event_dfs_sta_cac_skipped(hapd, &data->dfs_event);
++ break;
++ case EVENT_DFS_STA_CAC_EXPIRED:
++ if (!data)
++ break;
++ hostapd_event_dfs_sta_cac_expired(hapd, &data->dfs_event);
++ break;
+ case EVENT_CHANNEL_LIST_CHANGED:
+ /* channel list changed (regulatory?), update channel list */
+ /* TODO: check this. hostapd_get_hw_features() initializes
+diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h
+index 3435084..79c8a82 100644
+--- a/src/common/wpa_ctrl.h
++++ b/src/common/wpa_ctrl.h
+@@ -360,6 +360,7 @@ extern "C" {
+ #define DFS_EVENT_CAC_COMPLETED "DFS-CAC-COMPLETED "
+ #define DFS_EVENT_NOP_FINISHED "DFS-NOP-FINISHED "
+ #define DFS_EVENT_PRE_CAC_EXPIRED "DFS-PRE-CAC-EXPIRED "
++#define DFS_EVENT_STA_UPDATE "DFS-STA-UPDATE "
+
+ #define AP_CSA_FINISHED "AP-CSA-FINISHED "
+
+diff --git a/src/drivers/driver.h b/src/drivers/driver.h
+index 265d86d..b5de0e6 100644
+--- a/src/drivers/driver.h
++++ b/src/drivers/driver.h
+@@ -5317,6 +5317,20 @@ enum wpa_event_type {
+ * EVENT_CCA_NOTIFY - Notification that CCA has completed
+ */
+ EVENT_CCA_NOTIFY,
++
++ /**
++ * EVENT_DFS_STA_CAC_SKIPPED - Notification that CAC has been skipped
++ *
++ * The channel in the notification is now marked as available.
++ */
++ EVENT_DFS_STA_CAC_SKIPPED,
++
++ /**
++ * EVENT_DFS_STA_CAC_EXPIRED - Notification that CAC has expired
++ *
++ * The channel in the notification is now marked as usable.
++ */
++ EVENT_DFS_STA_CAC_EXPIRED,
+ };
+
+
+diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c
+index 73bb7a4..ee922ac 100644
+--- a/src/drivers/driver_nl80211_event.c
++++ b/src/drivers/driver_nl80211_event.c
+@@ -1854,6 +1854,12 @@ static void nl80211_radar_event(struct wpa_driver_nl80211_data *drv,
+ case NL80211_RADAR_CAC_STARTED:
+ wpa_supplicant_event(drv->ctx, EVENT_DFS_CAC_STARTED, &data);
+ break;
++ case NL80211_RADAR_STA_CAC_SKIPPED:
++ wpa_supplicant_event(drv->ctx, EVENT_DFS_STA_CAC_SKIPPED, &data);
++ break;
++ case NL80211_RADAR_STA_CAC_EXPIRED:
++ wpa_supplicant_event(drv->ctx, EVENT_DFS_STA_CAC_EXPIRED, &data);
++ break;
+ default:
+ wpa_printf(MSG_DEBUG, "nl80211: Unknown radar event %d "
+ "received", event_type);
+diff --git a/src/drivers/nl80211_copy.h b/src/drivers/nl80211_copy.h
+index c4bf3ad..0937752 100644
+--- a/src/drivers/nl80211_copy.h
++++ b/src/drivers/nl80211_copy.h
+@@ -6431,6 +6431,10 @@ enum nl80211_smps_mode {
+ * applicable for ETSI dfs domain where pre-CAC is valid for ever.
+ * @NL80211_RADAR_CAC_STARTED: Channel Availability Check has been started,
+ * should be generated by HW if NL80211_EXT_FEATURE_DFS_OFFLOAD is enabled.
++ * @NL80211_RADAR_STA_CAC_SKIPPED: STA set the DFS state to available
++ * when receiving CSA/assoc resp
++ * @NL80211_RADAR_STA_CAC_EXPIRED: STA set the DFS state to usable
++ * when STA is disconnected or leaving the channel
+ */
+ enum nl80211_radar_event {
+ NL80211_RADAR_DETECTED,
+@@ -6439,6 +6443,8 @@ enum nl80211_radar_event {
+ NL80211_RADAR_NOP_FINISHED,
+ NL80211_RADAR_PRE_CAC_EXPIRED,
+ NL80211_RADAR_CAC_STARTED,
++ NL80211_RADAR_STA_CAC_SKIPPED,
++ NL80211_RADAR_STA_CAC_EXPIRED,
+ };
+
+ /**
+--
+2.18.0
+
diff --git a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0019-hostapd-mtk-Fix-auto-ht-issue-when-switching-to-DFS-.patch b/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0019-hostapd-mtk-Fix-auto-ht-issue-when-switching-to-DFS-.patch
new file mode 100644
index 0000000..8340fd9
--- /dev/null
+++ b/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0019-hostapd-mtk-Fix-auto-ht-issue-when-switching-to-DFS-.patch
@@ -0,0 +1,43 @@
+From 83ab1a9cc51225095842d3c62bf75cf4efe63075 Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Mon, 20 Feb 2023 16:58:20 +0800
+Subject: [PATCH] hostapd: mtk: Fix auto ht issue when switching to DFS channel
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ hostapd/ctrl_iface.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
+index 0ad8451..407790f 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -2698,6 +2698,12 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
+ break;
+ }
+
++ if (os_strstr(pos, " auto-ht")) {
++ settings.freq_params.ht_enabled = iface->conf->ieee80211n;
++ settings.freq_params.vht_enabled = iface->conf->ieee80211ac;
++ settings.freq_params.he_enabled = iface->conf->ieee80211ax;
++ }
++
+ if (settings.freq_params.center_freq1)
+ dfs_range += hostapd_is_dfs_overlap(
+ iface, bandwidth, settings.freq_params.center_freq1);
+@@ -2735,12 +2741,6 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
+ return 0;
+ }
+
+- if (os_strstr(pos, " auto-ht")) {
+- settings.freq_params.ht_enabled = iface->conf->ieee80211n;
+- settings.freq_params.vht_enabled = iface->conf->ieee80211ac;
+- settings.freq_params.he_enabled = iface->conf->ieee80211ax;
+- }
+-
+ for (i = 0; i < iface->num_bss; i++) {
+
+ /* Save CHAN_SWITCH VHT, HE, and EHT config */
+--
+2.18.0
+
diff --git a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0020-hostapd-mtk-Mark-DFS-channel-as-available-for-CSA.patch b/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0020-hostapd-mtk-Mark-DFS-channel-as-available-for-CSA.patch
new file mode 100644
index 0000000..1fe5c88
--- /dev/null
+++ b/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0020-hostapd-mtk-Mark-DFS-channel-as-available-for-CSA.patch
@@ -0,0 +1,60 @@
+From 3e9500a42a41e8cd7c2d7bc20aba96e1e17161fb Mon Sep 17 00:00:00 2001
+From: "himanshu.goyal" <himanshu.goyal@mediatek.com>
+Date: Fri, 3 Mar 2023 12:45:42 +0800
+Subject: [PATCH] hostapd: mtk: Mark DFS channel as available for CSA.
+
+---
+ hostapd/ctrl_iface.c | 10 ++++++++++
+ hostapd/hostapd_cli.c | 2 +-
+ src/ap/ctrl_iface_ap.c | 1 +
+ 3 files changed, 12 insertions(+), 1 deletion(-)
+
+diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
+index c33b7a4..9ba6992 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -2704,6 +2704,16 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
+ settings.freq_params.he_enabled = iface->conf->ieee80211ax;
+ }
+
++ if (settings.freq_params.radar_background) {
++ hostapd_dfs_sta_update_state(iface,
++ settings.freq_params.freq,
++ settings.freq_params.ht_enabled,
++ settings.freq_params.sec_channel_offset,
++ bandwidth, settings.freq_params.center_freq1,
++ settings.freq_params.center_freq2,
++ HOSTAPD_CHAN_DFS_AVAILABLE);
++ }
++
+ if (settings.freq_params.center_freq1)
+ dfs_range += hostapd_is_dfs_overlap(
+ iface, bandwidth, settings.freq_params.center_freq1);
+diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
+index 0da18e2..6231e51 100644
+--- a/hostapd/hostapd_cli.c
++++ b/hostapd/hostapd_cli.c
+@@ -1693,7 +1693,7 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
+ "<addr> = send QoS Map Configure frame" },
+ { "chan_switch", hostapd_cli_cmd_chan_switch, NULL,
+ "<cs_count> <freq> [sec_channel_offset=] [center_freq1=]\n"
+- " [center_freq2=] [bandwidth=] [blocktx] [ht|vht]\n"
++ " [center_freq2=] [bandwidth=] [blocktx] [ht|vht] [skip_cac]\n"
+ " = initiate channel switch announcement" },
+ { "hs20_wnm_notif", hostapd_cli_cmd_hs20_wnm_notif, NULL,
+ "<addr> <url>\n"
+diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c
+index 18bae5c..2fae590 100644
+--- a/src/ap/ctrl_iface_ap.c
++++ b/src/ap/ctrl_iface_ap.c
+@@ -938,6 +938,7 @@ int hostapd_parse_csa_settings(const char *pos,
+ settings->freq_params.vht_enabled = !!os_strstr(pos, " vht");
+ settings->freq_params.he_enabled = !!os_strstr(pos, " he");
+ settings->freq_params.eht_enabled = !!os_strstr(pos, " eht");
++ settings->freq_params.radar_background = !!os_strstr(pos, " skip_cac");
+ settings->block_tx = !!os_strstr(pos, " blocktx");
+ #undef SET_CSA_SETTING
+
+--
+2.18.0
+
diff --git a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0020-hostapd-mtk-add-11v_mbss-and-ema-support.patch b/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0020-hostapd-mtk-add-11v_mbss-and-ema-support.patch
new file mode 100644
index 0000000..8d59a0f
--- /dev/null
+++ b/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0020-hostapd-mtk-add-11v_mbss-and-ema-support.patch
@@ -0,0 +1,1175 @@
+From 8cbdb9a59e3bbe8804f909b13ce6df6e2777c3da Mon Sep 17 00:00:00 2001
+From: mtk20656 <chank.chen@mediatek.com>
+Date: Thu, 2 Mar 2023 10:51:43 +0800
+Subject: [PATCH] hostapd: mtk: add 11v_mbss and ema support for hostapd
+
+Signed-off-by: mtk20656 <chank.chen@mediatek.com>
+---
+ hostapd/config_file.c | 9 +
+ hostapd/hostapd.conf | 58 +++++++
+ hostapd/main.c | 3 +
+ src/ap/ap_config.c | 12 ++
+ src/ap/ap_config.h | 6 +
+ src/ap/beacon.c | 124 ++++++++++++--
+ src/ap/hostapd.c | 72 +++++++-
+ src/ap/hostapd.h | 7 +
+ src/ap/ieee802_11.c | 276 +++++++++++++++++++++++++++++-
+ src/ap/ieee802_11.h | 7 +-
+ src/ap/ieee802_11_shared.c | 11 ++
+ src/common/ieee802_11_common.c | 4 +
+ src/common/ieee802_11_common.h | 3 +
+ src/common/ieee802_11_defs.h | 5 +
+ src/drivers/driver.h | 42 +++++
+ src/drivers/driver_nl80211.c | 52 ++++++
+ src/drivers/driver_nl80211_capa.c | 27 +++
+ 17 files changed, 698 insertions(+), 20 deletions(-)
+
+diff --git a/hostapd/config_file.c b/hostapd/config_file.c
+index 649618b..3f26191 100644
+--- a/hostapd/config_file.c
++++ b/hostapd/config_file.c
+@@ -3663,6 +3663,15 @@ static int hostapd_config_fill(struct hostapd_config *conf,
+ return 1;
+ }
+ bss->unsol_bcast_probe_resp_interval = val;
++ } else if (os_strcmp(buf, "mbssid") == 0) {
++ int mbssid = atoi(pos);
++ if (mbssid < 0 || mbssid > ENHANCED_MBSSID_ENABLED) {
++ wpa_printf(MSG_ERROR,
++ "Line %d: invalid mbssid (%d): '%s'.",
++ line, mbssid, pos);
++ return 1;
++ }
++ conf->mbssid = mbssid;
+ } else if (os_strcmp(buf, "mu_onoff") == 0) {
+ int val = atoi(pos);
+ if (val < 0 || val > 15) {
+diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
+index e3a5eb3..f926029 100644
+--- a/hostapd/hostapd.conf
++++ b/hostapd/hostapd.conf
+@@ -3123,3 +3123,61 @@ own_ip_addr=127.0.0.1
+ #bss=wlan0_1
+ #bssid=00:13:10:95:fe:0b
+ # ...
++#
++# Multiple BSSID Advertisement in 802.11ax
++# IEEE Std 802.11ax-2021 added a feature where instead of multiple interfaces
++# on a common radio transmitting individual beacons, those can form a set with
++# a common beacon is transmitted for all. The interface which is brought up
++# first is called as the transmitting profile of the MBSSID set which transmits
++# the beacons. The remaining interfaces are called as the non-transmitting
++# profiles and these are advertised inside the multiple BSSID element in the
++# beacons and probe response frames.
++# The transmitting interface is visible to all clients in the vicinity, however
++# the clients which do not support parsing of the multiple BSSID element will
++# not be able to connect to the non-transmitting interfaces.
++#
++# Enhanced Multiple BSSID Advertisements (EMA)
++# When enabled, the non-transmitting interfaces are split into multiple
++# beacons. The number of beacons required to cover all the non-transmitting
++# profiles is called as the profile periodicity.
++#
++# Refer to IEEE Std 802.11-2020 for details regarding the procedure and
++# required MAC address assignment.
++#
++# Following configuration is per radio.
++# 0 = Disabled (Default)
++# 1 = Multiple BSSID advertisements enabled.
++# 2 = Enhanced multiple BSSID advertisements enabled.
++#mbssid=0
++#
++# The transmitting interface should be added with 'interface' option while
++# the non-transmitting interfaces should be added using 'bss' option.
++# Security configuration should be added separately per interface, if required.
++#
++# Example:
++#mbssid=2
++#interface=wlan2
++#ctrl_interface=/var/run/hostapd
++#wpa_passphrase=0123456789
++#ieee80211w=2
++#sae_pwe=1
++#auth_algs=1
++#wpa=2
++#wpa_pairwise=CCMP
++#ssid=<SSID-0>
++#bridge=br-lan
++#wpa_key_mgmt=SAE
++#bssid=00:03:7f:12:84:84
++#
++#bss=wlan2-1
++#ctrl_interface=/var/run/hostapd
++#wpa_passphrase=0123456789
++#ieee80211w=2
++#sae_pwe=1
++#auth_algs=1
++#wpa=2
++#wpa_pairwise=CCMP
++#ssid=<SSID-1>
++#bridge=br-lan
++#wpa_key_mgmt=SAE
++#bssid=00:03:7f:12:84:85
+diff --git a/hostapd/main.c b/hostapd/main.c
+index 70a4b32..1b6474a 100644
+--- a/hostapd/main.c
++++ b/hostapd/main.c
+@@ -253,6 +253,9 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
+ wpa_printf(MSG_ERROR, "set_wowlan failed");
+ }
+ os_free(triggs);
++
++ iface->mbssid_max_interfaces = capa.mbssid_max_interfaces;
++ iface->ema_max_periodicity = capa.ema_max_periodicity;
+ }
+
+ return 0;
+diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
+index 4e46a62..7d9d5cb 100644
+--- a/src/ap/ap_config.c
++++ b/src/ap/ap_config.c
+@@ -1462,6 +1462,12 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
+ }
+ #endif /* CONFIG_IEEE80211BE */
+
++ if (full_config && bss->ignore_broadcast_ssid && conf->mbssid) {
++ wpa_printf(MSG_ERROR,
++ "Hidden SSID is not suppored when MBSSID is enabled");
++ return -1;
++ }
++
+ return 0;
+ }
+
+@@ -1545,6 +1551,12 @@ int hostapd_config_check(struct hostapd_config *conf, int full_config)
+ }
+ #endif /* CONFIG_IEEE80211BE */
+
++ if (full_config && conf->mbssid && !conf->ieee80211ax) {
++ wpa_printf(MSG_ERROR,
++ "Cannot enable multiple BSSID support without ieee80211ax");
++ return -1;
++ }
++
+ for (i = 0; i < conf->num_bss; i++) {
+ if (hostapd_config_check_bss(conf->bss[i], conf, full_config))
+ return -1;
+diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
+index 7aeb176..51476b8 100644
+--- a/src/ap/ap_config.h
++++ b/src/ap/ap_config.h
+@@ -923,6 +923,8 @@ struct hostapd_bss_config {
+ u8 ext_capa[EXT_CAPA_MAX_LEN];
+
+ u8 rnr;
++
++ bool xrates_supported;
+ };
+
+ /**
+@@ -1163,6 +1165,10 @@ struct hostapd_config {
+ u8 ibf_enable;
+ u8 dfs_detect_mode;
+ u8 amsdu;
++
++#define MBSSID_ENABLED 1
++#define ENHANCED_MBSSID_ENABLED 2
++ u8 mbssid;
+ };
+
+ enum three_wire_mode {
+diff --git a/src/ap/beacon.c b/src/ap/beacon.c
+index f3ea5c2..51db23a 100644
+--- a/src/ap/beacon.c
++++ b/src/ap/beacon.c
+@@ -462,15 +462,77 @@ static u8 * hostapd_eid_supported_op_classes(struct hostapd_data *hapd, u8 *eid)
+ }
+
+
++static int ieee802_11_build_ap_params_mbssid(struct hostapd_data *hapd,
++ struct wpa_driver_ap_params *params,
++ u8 **eid)
++{
++ struct hostapd_iface *iface = hapd->iface;
++ struct hostapd_data *tx_bss;
++ size_t len;
++ u8 elem_count = 0, *elem = NULL, **elem_offset = NULL, *end;
++ u8 *tailpos = *eid;
++
++ if (!iface->mbssid_max_interfaces ||
++ iface->num_bss > iface->mbssid_max_interfaces ||
++ (iface->conf->mbssid == ENHANCED_MBSSID_ENABLED &&
++ !iface->ema_max_periodicity))
++ goto fail;
++
++ tx_bss = hostapd_mbssid_get_tx_bss(hapd);
++ len = hostapd_eid_mbssid_len(tx_bss, WLAN_FC_STYPE_BEACON, &elem_count,
++ NULL, 0);
++ if (!len || (iface->conf->mbssid == ENHANCED_MBSSID_ENABLED &&
++ elem_count > iface->ema_max_periodicity))
++ goto fail;
++
++ elem = os_zalloc(len);
++ if (!elem)
++ goto fail;
++
++ elem_offset = os_zalloc(elem_count * sizeof(u8 *));
++ if (!elem_offset)
++ goto fail;
++
++ end = hostapd_eid_mbssid(tx_bss, elem, elem + len, WLAN_FC_STYPE_BEACON,
++ elem_count, elem_offset, NULL, 0);
++
++ params->mbssid_tx_iface = tx_bss->conf->iface;
++ params->mbssid_index = hostapd_mbssid_get_bss_index(hapd);
++ params->mbssid_elem = elem;
++ params->mbssid_elem_len = end - elem;
++ params->mbssid_elem_count = elem_count;
++ params->mbssid_elem_offset = elem_offset;
++ if (iface->conf->mbssid == ENHANCED_MBSSID_ENABLED) {
++ params->ema = true;
++ *tailpos++ = WLAN_EID_EXTENSION;
++ *tailpos++ = 3;
++ *tailpos++ = WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION;
++ *tailpos++ = iface->num_bss;
++ *tailpos++ = params->mbssid_elem_count;
++ *eid = tailpos;
++ }
++
++ return 0;
++
++fail:
++ os_free(elem);
++ wpa_printf(MSG_ERROR, "MBSSID: Configuration failed");
++ return -1;
++}
++
++
+ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
+ const struct ieee80211_mgmt *req,
+ int is_p2p, size_t *resp_len,
+- bool bcast_probe_resp)
++ bool bcast_probe_resp, const u8 *known_bss,
++ u8 known_bss_len)
+ {
+ struct ieee80211_mgmt *resp;
+- u8 *pos, *epos, *csa_pos;
++ u8 *pos, *epos, *csa_pos, *ext_cap_pos;
+ size_t buflen;
+
++ hapd = hostapd_mbssid_get_tx_bss(hapd);
++
+ #define MAX_PROBERESP_LEN 768
+ buflen = MAX_PROBERESP_LEN;
+ #ifdef CONFIG_WPS
+@@ -517,6 +579,8 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
+ }
+ #endif /* CONFIG_IEEE80211BE */
+
++ buflen += hostapd_eid_mbssid_len(hapd, WLAN_FC_STYPE_PROBE_RESP, NULL,
++ known_bss, known_bss_len);
+ buflen += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_PROBE_RESP);
+ buflen += hostapd_mbo_ie_len(hapd);
+ buflen += hostapd_eid_owe_trans_len(hapd);
+@@ -588,8 +652,16 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
+ pos = hostapd_eid_supported_op_classes(hapd, pos);
+ pos = hostapd_eid_ht_capabilities(hapd, pos);
+ pos = hostapd_eid_ht_operation(hapd, pos);
++ pos = hostapd_eid_mbssid(hapd, pos, epos, WLAN_FC_STYPE_PROBE_RESP, 0,
++ NULL, known_bss, known_bss_len);
+
++ ext_cap_pos = pos;
+ pos = hostapd_eid_ext_capab(hapd, pos);
++ if (hapd->iconf->mbssid >= MBSSID_ENABLED && !known_bss_len)
++ ext_cap_pos[12] |= 0x01; /* Probe responses always include all
++ * non-tx profiles except when a list
++ * of known BSSes is included in the
++ * probe request. */
+
+ pos = hostapd_eid_time_adv(hapd, pos);
+ pos = hostapd_eid_time_zone(hapd, pos);
+@@ -1153,16 +1225,23 @@ void handle_probe_req(struct hostapd_data *hapd,
+ }
+ #endif /* CONFIG_TESTING_OPTIONS */
+
++ /* Do not send probe response from a non-transmitting multiple BSSID
++ * profile unless the probe request is directed at that paticular BSS */
++ if (hapd != hostapd_mbssid_get_tx_bss(hapd) && res != EXACT_SSID_MATCH)
++ return;
++
+ wpa_msg_ctrl(hapd->msg_ctx, MSG_INFO, RX_PROBE_REQUEST "sa=" MACSTR
+ " signal=%d", MAC2STR(mgmt->sa), ssi_signal);
+
+ if (is_6ghz_op_class(hapd->iconf->op_class) &&
+ is_broadcast_ether_addr(mgmt->da))
+ resp = hostapd_gen_probe_resp(hapd, NULL, elems.p2p != NULL,
+- &resp_len, true);
++ &resp_len, false, elems.mbssid_known_bss,
++ elems.mbssid_known_bss_len);
+ else
+ resp = hostapd_gen_probe_resp(hapd, mgmt, elems.p2p != NULL,
+- &resp_len, false);
++ &resp_len, false, elems.mbssid_known_bss,
++ elems.mbssid_known_bss_len);
+ if (resp == NULL)
+ return;
+
+@@ -1184,7 +1263,8 @@ void handle_probe_req(struct hostapd_data *hapd,
+ hapd->cs_c_off_ecsa_proberesp;
+ }
+
+- ret = hostapd_drv_send_mlme(hapd, resp, resp_len, noack,
++ ret = hostapd_drv_send_mlme(hostapd_mbssid_get_tx_bss(hapd), resp,
++ resp_len, noack,
+ csa_offs_len ? csa_offs : NULL,
+ csa_offs_len, 0);
+
+@@ -1231,7 +1311,7 @@ static u8 * hostapd_probe_resp_offloads(struct hostapd_data *hapd,
+ "this");
+
+ /* Generate a Probe Response template for the non-P2P case */
+- return hostapd_gen_probe_resp(hapd, NULL, 0, resp_len, false);
++ return hostapd_gen_probe_resp(hapd, NULL, 0, resp_len, false, NULL, 0);
+ }
+
+ #endif /* NEED_AP_MLME */
+@@ -1250,7 +1330,7 @@ static u8 * hostapd_unsol_bcast_probe_resp(struct hostapd_data *hapd,
+
+ return hostapd_gen_probe_resp(hapd, NULL, 0,
+ ¶ms->unsol_bcast_probe_resp_tmpl_len,
+- true);
++ true, NULL, 0);
+ }
+ #endif /* CONFIG_IEEE80211AX */
+
+@@ -1533,8 +1613,12 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
+ size_t resp_len = 0;
+ #ifdef NEED_AP_MLME
+ u16 capab_info;
+- u8 *pos, *tailpos, *tailend, *csa_pos;
++ u8 *pos, *tailpos, *tailend, *csa_pos, *ext_cap_pos;
++#endif /* NEED_AP_MLME */
+
++ os_memset(params, 0, sizeof(*params));
++
++#ifdef NEED_AP_MLME
+ #define BEACON_HEAD_BUF_SIZE 256
+ #define BEACON_TAIL_BUF_SIZE 512
+ head = os_zalloc(BEACON_HEAD_BUF_SIZE);
+@@ -1586,6 +1670,9 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
+ }
+ #endif /* CONFIG_IEEE80211BE */
+
++ if (hapd->iconf->mbssid == ENHANCED_MBSSID_ENABLED &&
++ hapd == hostapd_mbssid_get_tx_bss(hapd))
++ tail_len += 5; /* Multiple BSSID Configuration element */
+ tail_len += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_BEACON);
+ tail_len += hostapd_mbo_ie_len(hapd);
+ tail_len += hostapd_eid_owe_trans_len(hapd);
+@@ -1671,9 +1758,23 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
+ tailpos = hostapd_eid_supported_op_classes(hapd, tailpos);
+ tailpos = hostapd_eid_ht_capabilities(hapd, tailpos);
+ tailpos = hostapd_eid_ht_operation(hapd, tailpos);
+-
++ ext_cap_pos = tailpos;
+ tailpos = hostapd_eid_ext_capab(hapd, tailpos);
+
++ if (hapd->iconf->mbssid && hapd->iconf->num_bss > 1) {
++ if (ieee802_11_build_ap_params_mbssid(hapd, params, &tailpos)) {
++ os_free(head);
++ os_free(tail);
++ wpa_printf(MSG_ERROR, "Failed to set beacon data");
++ return -1;
++ } else if (hapd->iconf->mbssid == MBSSID_ENABLED ||
++ (hapd->iconf->mbssid == ENHANCED_MBSSID_ENABLED &&
++ params->mbssid_elem_count == 1)) {
++ /* Set the extended capability bit for "complete list
++ * of non-tx profiles" */
++ ext_cap_pos[12] |= 0x01;
++ }
++ }
+ /*
+ * TODO: Time Advertisement element should only be included in some
+ * DTIM Beacon frames.
+@@ -1794,7 +1895,6 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
+ resp = hostapd_probe_resp_offloads(hapd, &resp_len);
+ #endif /* NEED_AP_MLME */
+
+- os_memset(params, 0, sizeof(*params));
+ params->head = (u8 *) head;
+ params->head_len = head_len;
+ params->tail = tail;
+@@ -1897,6 +1997,10 @@ void ieee802_11_free_ap_params(struct wpa_driver_ap_params *params)
+ params->head = NULL;
+ os_free(params->proberesp);
+ params->proberesp = NULL;
++ os_free(params->mbssid_elem);
++ params->mbssid_elem = NULL;
++ os_free(params->mbssid_elem_offset);
++ params->mbssid_elem_offset = NULL;
+ #ifdef CONFIG_FILS
+ os_free(params->fd_frame_tmpl);
+ params->fd_frame_tmpl = NULL;
+diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
+index 42e8ed7..82cc155 100644
+--- a/src/ap/hostapd.c
++++ b/src/ap/hostapd.c
+@@ -91,6 +91,29 @@ int hostapd_for_each_interface(struct hapd_interfaces *interfaces,
+ }
+
+
++struct hostapd_data * hostapd_mbssid_get_tx_bss(struct hostapd_data *hapd)
++{
++ if (hapd->iconf->mbssid)
++ return hapd->iface->bss[0];
++
++ return hapd;
++}
++
++
++int hostapd_mbssid_get_bss_index(struct hostapd_data *hapd)
++{
++ if (hapd->iconf->mbssid) {
++ size_t i;
++
++ for (i = 1; i < hapd->iface->num_bss; i++)
++ if (hapd->iface->bss[i] == hapd)
++ return i;
++ }
++
++ return 0;
++}
++
++
+ void hostapd_reconfig_encryption(struct hostapd_data *hapd)
+ {
+ if (hapd->wpa_auth)
+@@ -1179,19 +1202,37 @@ static int db_table_create_radius_attributes(sqlite3 *db)
+
+ #endif /* CONFIG_NO_RADIUS */
+
++static int hostapd_start_beacon(struct hostapd_data *hapd)
++{
++ struct hostapd_bss_config *conf = hapd->conf;
++
++ if (!conf->start_disabled && ieee802_11_set_beacon(hapd) < 0)
++ return -1;
++
++ if (hapd->driver && hapd->driver->set_operstate)
++ hapd->driver->set_operstate(hapd->drv_priv, 1);
++
++ return 0;
++}
+
+ /**
+ * hostapd_setup_bss - Per-BSS setup (initialization)
+ * @hapd: Pointer to BSS data
+ * @first: Whether this BSS is the first BSS of an interface; -1 = not first,
+ * but interface may exist
++ * @start_beacon: Whether beacons should be configured and transmission started
++ * at this time. This is used when MBSSID IE is enabled where the
++ * information regarding all BSSes should be retrieved before configuring
++ * the beacons. The calling functions are responsible to configure the
++ * beacon explicitly if this is set to 'false'.
+ *
+ * This function is used to initialize all per-BSS data structures and
+ * resources. This gets called in a loop for each BSS when an interface is
+ * initialized. Most of the modules that are initialized here will be
+ * deinitialized in hostapd_cleanup().
+ */
+-static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
++static int hostapd_setup_bss(struct hostapd_data *hapd, int first,
++ bool start_beacon)
+ {
+ struct hostapd_bss_config *conf = hapd->conf;
+ u8 ssid[SSID_MAX_LEN + 1];
+@@ -1464,9 +1505,6 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
+ return -1;
+ }
+
+- if (!conf->start_disabled && ieee802_11_set_beacon(hapd) < 0)
+- return -1;
+-
+ if (flush_old_stations && !conf->start_disabled &&
+ conf->broadcast_deauth) {
+ u8 addr[ETH_ALEN];
+@@ -1485,8 +1523,8 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
+ if (hapd->wpa_auth && wpa_init_keys(hapd->wpa_auth) < 0)
+ return -1;
+
+- if (hapd->driver && hapd->driver->set_operstate)
+- hapd->driver->set_operstate(hapd->drv_priv, 1);
++ if (start_beacon)
++ return hostapd_start_beacon(hapd);
+
+ hostapd_ubus_add_bss(hapd);
+
+@@ -2214,7 +2252,7 @@ static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface,
+ hapd = iface->bss[j];
+ if (j)
+ os_memcpy(hapd->own_addr, prev_addr, ETH_ALEN);
+- if (hostapd_setup_bss(hapd, j == 0)) {
++ if (hostapd_setup_bss(hapd, j == 0, !iface->conf->mbssid)) {
+ for (;;) {
+ hapd = iface->bss[j];
+ hostapd_bss_deinit_no_free(hapd);
+@@ -2228,6 +2266,24 @@ static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface,
+ if (is_zero_ether_addr(hapd->conf->bssid))
+ prev_addr = hapd->own_addr;
+ }
++
++ if (hapd->iconf->mbssid) {
++ for (j = 0; j < iface->num_bss; j++) {
++ hapd = iface->bss[j];
++ if (hostapd_start_beacon(hapd)) {
++ for (;;) {
++ hapd = iface->bss[j];
++ hostapd_bss_deinit_no_free(hapd);
++ hostapd_free_hapd_data(hapd);
++ if (j == 0)
++ break;
++ j--;
++ }
++ goto fail;
++ }
++ }
++ }
++
+ hapd = iface->bss[0];
+
+ hostapd_tx_queue_params(iface);
+@@ -3130,7 +3186,7 @@ int hostapd_add_iface(struct hapd_interfaces *interfaces, char *buf)
+
+ if (start_ctrl_iface_bss(hapd) < 0 ||
+ (hapd_iface->state == HAPD_IFACE_ENABLED &&
+- hostapd_setup_bss(hapd, -1))) {
++ hostapd_setup_bss(hapd, -1, true))) {
+ hostapd_cleanup(hapd);
+ hapd_iface->bss[hapd_iface->num_bss - 1] = NULL;
+ hapd_iface->conf->num_bss--;
+diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
+index 56d96a5..093c28a 100644
+--- a/src/ap/hostapd.h
++++ b/src/ap/hostapd.h
+@@ -660,6 +660,11 @@ struct hostapd_iface {
+ /* Previous WMM element information */
+ struct hostapd_wmm_ac_params prev_wmm[WMM_AC_NUM];
+
++ /* Maximum number of interfaces supported for MBSSID advertisements */
++ u8 mbssid_max_interfaces;
++ /* Maximum profile periodicity for enhanced MBSSID advertisements */
++ u8 ema_max_periodicity;
++
+ int (*enable_iface_cb)(struct hostapd_iface *iface);
+ int (*disable_iface_cb)(struct hostapd_iface *iface);
+ };
+@@ -762,5 +767,7 @@ void fst_hostapd_fill_iface_obj(struct hostapd_data *hapd,
+ #endif /* CONFIG_FST */
+
+ int hostapd_set_acl(struct hostapd_data *hapd);
++struct hostapd_data * hostapd_mbssid_get_tx_bss(struct hostapd_data *hapd);
++int hostapd_mbssid_get_bss_index(struct hostapd_data *hapd);
+
+ #endif /* HOSTAPD_H */
+diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
+index 098793e..30bfa30 100644
+--- a/src/ap/ieee802_11.c
++++ b/src/ap/ieee802_11.c
+@@ -165,6 +165,7 @@ u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid)
+ int i, num, count;
+ int h2e_required;
+
++ hapd->conf->xrates_supported = 0;
+ if (hapd->iface->current_rates == NULL)
+ return eid;
+
+@@ -214,6 +215,7 @@ u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid)
+ *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_SAE_H2E_ONLY;
+ }
+
++ hapd->conf->xrates_supported = 1;
+ return pos;
+ }
+
+@@ -3979,6 +3981,23 @@ static void handle_auth(struct hostapd_data *hapd,
+ }
+
+
++static u8 hostapd_max_bssid_indicator(struct hostapd_data *hapd)
++{
++ size_t num_bss_nontx;
++ u8 max_bssid_ind = 0;
++
++ if (!hapd->iconf->mbssid || hapd->iface->num_bss <= 1)
++ return 0;
++
++ num_bss_nontx = hapd->iface->num_bss - 1;
++ while (num_bss_nontx > 0) {
++ max_bssid_ind++;
++ num_bss_nontx >>= 1;
++ }
++ return max_bssid_ind;
++}
++
++
+ int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta)
+ {
+ int i, j = 32, aid;
+@@ -4004,7 +4023,10 @@ int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta)
+ }
+ if (j == 32)
+ return -1;
+- aid = i * 32 + j + 1;
++ aid = i * 32 + j;
++
++ aid += (1 << hostapd_max_bssid_indicator(hapd));
++
+ if (aid > 2007)
+ return -1;
+
+@@ -7579,4 +7601,256 @@ u8 * hostapd_eid_rnr(struct hostapd_data *hapd, u8 *eid, u32 type)
+ return eid;
+ }
+
++
++static size_t hostapd_eid_mbssid_elem_len(struct hostapd_data *hapd,
++ u32 frame_type, size_t *bss_index,
++ const u8 *known_bss,
++ size_t known_bss_len)
++{
++ struct hostapd_data *tx_bss = hostapd_mbssid_get_tx_bss(hapd);
++ size_t len = 3, i;
++
++ for (i = *bss_index; i < hapd->iface->num_bss; i++) {
++ struct hostapd_data *bss = hapd->iface->bss[i];
++ const u8 *auth, *rsn = NULL, *rsnx = NULL;
++ size_t nontx_profile_len, auth_len;
++ u8 ie_count = 0;
++
++ if (known_bss && (known_bss_len > (i / 8))) {
++ known_bss = &known_bss[i / 8];
++ if (*known_bss & (u8)(BIT(i % 8)))
++ continue;
++ }
++
++ if (!bss || !bss->conf || !bss->started)
++ continue;
++
++ /*
++ * Sublement ID: 1 byte
++ * Length: 1 byte
++ * Nontransmitted capabilities: 4 bytes
++ * SSID element: 2 + variable
++ * Multiple BSSID Index Element: 3 bytes (+2 bytes in beacons)
++ * Fixed length = 1 + 1 + 4 + 2 + 3 = 11
++ */
++ nontx_profile_len = 11 + bss->conf->ssid.ssid_len;
++
++ if (frame_type == WLAN_FC_STYPE_BEACON)
++ nontx_profile_len += 2;
++
++ auth = wpa_auth_get_wpa_ie(bss->wpa_auth, &auth_len);
++ if (auth) {
++ rsn = get_ie(auth, auth_len, WLAN_EID_RSN);
++ if (rsn)
++ nontx_profile_len += (2 + rsn[1]);
++
++ rsnx = get_ie(auth, auth_len, WLAN_EID_RSNX);
++ if (rsnx)
++ nontx_profile_len += (2 + rsnx[1]);
++ }
++ if (!rsn && hostapd_wpa_ie(tx_bss, WLAN_EID_RSN))
++ ie_count++;
++ if (!rsnx && hostapd_wpa_ie(tx_bss, WLAN_EID_RSNX))
++ ie_count++;
++ if (bss->conf->xrates_supported)
++ nontx_profile_len += 8;
++ else if (hapd->conf->xrates_supported)
++ ie_count++;
++ if (ie_count)
++ nontx_profile_len += (4 + ie_count);
++
++ if ((len + nontx_profile_len) > 255)
++ goto mbssid_too_big;
++
++ len += nontx_profile_len;
++ }
++
++mbssid_too_big:
++ *bss_index = i;
++ return len;
++}
++
++
++size_t hostapd_eid_mbssid_len(struct hostapd_data *hapd, u32 frame_type,
++ u8 *elem_count, const u8 *known_bss,
++ size_t known_bss_len)
++{
++ size_t len = 0, bss_index = 1;
++
++ if (!hapd->iconf->mbssid || hapd->iface->num_bss <= 1 ||
++ (frame_type != WLAN_FC_STYPE_BEACON &&
++ frame_type != WLAN_FC_STYPE_PROBE_RESP))
++ return 0;
++
++ if (frame_type == WLAN_FC_STYPE_BEACON) {
++ if (!elem_count) {
++ wpa_printf(MSG_ERROR,
++ "MBSSID: Insufficient data for beacons");
++ return 0;
++ }
++ *elem_count = 0;
++ }
++
++ while (bss_index < hapd->iface->num_bss) {
++ len += hostapd_eid_mbssid_elem_len(hapd, frame_type,
++ &bss_index, known_bss,
++ known_bss_len);
++
++ if (frame_type == WLAN_FC_STYPE_BEACON)
++ *elem_count += 1;
++ }
++ return len;
++}
++
++
++static u8 * hostapd_eid_mbssid_elem(struct hostapd_data *hapd, u8 *eid, u8 *end,
++ u32 frame_type, u8 max_bssid_indicator,
++ size_t *bss_index, u8 elem_count,
++ const u8 *known_bss, size_t known_bss_len)
++{
++ struct hostapd_data *tx_bss = hostapd_mbssid_get_tx_bss(hapd);
++ size_t i;
++ u8 *eid_len_offset, *max_bssid_indicator_offset;
++
++ *eid++ = WLAN_EID_MULTIPLE_BSSID;
++ eid_len_offset = eid++;
++ max_bssid_indicator_offset = eid++;
++
++ for (i = *bss_index; i < hapd->iface->num_bss; i++) {
++ struct hostapd_data *bss = hapd->iface->bss[i];
++ struct hostapd_bss_config *conf;
++ u8 *eid_len_pos, *nontx_bss_start = eid;
++ const u8 *auth, *rsn = NULL, *rsnx = NULL;
++ u8 ie_count = 0, non_inherit_ie[3];
++ size_t auth_len = 0;
++ u16 capab_info;
++
++ if (known_bss && (known_bss_len > (i / 8))) {
++ known_bss = &known_bss[i / 8];
++ if (*known_bss & (u8)(BIT(i % 8)))
++ continue;
++ }
++
++ if (!bss || !bss->conf || !bss->started)
++ continue;
++ conf = bss->conf;
++
++ *eid++ = WLAN_EID_SUBELEMENT_NONTRANSMITTED_BSSID_PROFILE;
++ eid_len_pos = eid++;
++
++ *eid++ = WLAN_EID_NONTRANSMITTED_BSSID_CAPA;
++ *eid++ = sizeof(capab_info);
++ capab_info = host_to_le16(hostapd_own_capab_info(bss));
++ os_memcpy(eid, (const void *)&capab_info, sizeof(capab_info));
++ eid += sizeof(capab_info);
++
++ *eid++ = WLAN_EID_SSID;
++ *eid++ = conf->ssid.ssid_len;
++ os_memcpy(eid, conf->ssid.ssid, conf->ssid.ssid_len);
++ eid += conf->ssid.ssid_len;
++
++ *eid++ = WLAN_EID_MULTIPLE_BSSID_INDEX;
++ if (frame_type == WLAN_FC_STYPE_BEACON) {
++ *eid++ = 3;
++ *eid++ = i;
++ if (hapd->iconf->mbssid == ENHANCED_MBSSID_ENABLED &&
++ (conf->dtim_period % elem_count))
++ conf->dtim_period = elem_count;
++ *eid++ = conf->dtim_period;
++ *eid++ = 0xFF;
++ } else {
++ *eid++ = 1;
++ *eid++ = i;
++ }
++
++ auth = wpa_auth_get_wpa_ie(bss->wpa_auth, &auth_len);
++ if (auth) {
++ rsn = get_ie(auth, auth_len, WLAN_EID_RSN);
++ if (rsn) {
++ os_memcpy(eid, rsn, 2 + rsn[1]);
++ eid += (2 + rsn[1]);
++ }
++
++ rsnx = get_ie(auth, auth_len, WLAN_EID_RSNX);
++ if (rsnx) {
++ os_memcpy(eid, rsnx, 2 + rsnx[1]);
++ eid += (2 + rsnx[1]);
++ }
++ }
++ if (!rsn && hostapd_wpa_ie(tx_bss, WLAN_EID_RSN)) {
++ non_inherit_ie[ie_count] = WLAN_EID_RSN;
++ ie_count++;
++ }
++ if (!rsnx && hostapd_wpa_ie(tx_bss, WLAN_EID_RSNX)) {
++ non_inherit_ie[ie_count] = WLAN_EID_RSNX;
++ ie_count++;
++ }
++ if (hapd->conf->xrates_supported &&
++ !bss->conf->xrates_supported) {
++ non_inherit_ie[ie_count] = WLAN_EID_EXT_SUPP_RATES;
++ ie_count++;
++ }
++ if (ie_count) {
++ *eid++ = WLAN_EID_EXTENSION;
++ *eid++ = 2 + ie_count;
++ *eid++ = WLAN_EID_EXT_NON_INHERITANCE;
++ *eid++ = ie_count;
++ os_memcpy(eid, non_inherit_ie, ie_count);
++ eid += ie_count;
++ }
++
++ *eid_len_pos = (eid - eid_len_pos) - 1;
++
++ if (((eid - eid_len_offset) - 1) > 255) {
++ eid = nontx_bss_start;
++ goto mbssid_too_big;
++ }
++ }
++
++mbssid_too_big:
++ *bss_index = i;
++ *max_bssid_indicator_offset = max_bssid_indicator;
++ if (*max_bssid_indicator_offset < 1)
++ *max_bssid_indicator_offset = 1;
++ *eid_len_offset = (eid - eid_len_offset) - 1;
++ return eid;
++}
++
++
++u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end,
++ u32 frame_type, u8 elem_count, u8 **elem_offset,
++ const u8 *known_bss, size_t known_bss_len)
++{
++ size_t bss_index = 1;
++ u8 elem_index = 0;
++
++ if (!hapd->iconf->mbssid || hapd->iface->num_bss <= 1 ||
++ (frame_type != WLAN_FC_STYPE_BEACON &&
++ frame_type != WLAN_FC_STYPE_PROBE_RESP))
++ return eid;
++
++ if (frame_type == WLAN_FC_STYPE_BEACON && !elem_offset) {
++ wpa_printf(MSG_ERROR, "MBSSID: Insufficient data for beacons");
++ return eid;
++ }
++
++ while (bss_index < hapd->iface->num_bss) {
++ if (frame_type == WLAN_FC_STYPE_BEACON) {
++ if (elem_index == elem_count) {
++ wpa_printf(MSG_WARNING,
++ "MBSSID: More number of elements than provided array");
++ break;
++ }
++
++ elem_offset[elem_index] = eid;
++ elem_index = elem_index + 1;
++ }
++ eid = hostapd_eid_mbssid_elem(hapd, eid, end, frame_type,
++ hostapd_max_bssid_indicator(hapd),
++ &bss_index, elem_count,
++ known_bss, known_bss_len);
++ }
++ return eid;
++}
++
+ #endif /* CONFIG_NATIVE_WINDOWS */
+diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h
+index fa1f47b..bb454bb 100644
+--- a/src/ap/ieee802_11.h
++++ b/src/ap/ieee802_11.h
+@@ -214,5 +214,10 @@ u16 copy_sta_eht_capab(struct hostapd_data *hapd, struct sta_info *sta,
+ enum ieee80211_op_mode opmode,
+ const u8 *he_capab, size_t he_capab_len,
+ const u8 *eht_capab, size_t eht_capab_len);
+-
++size_t hostapd_eid_mbssid_len(struct hostapd_data *hapd, u32 frame_type,
++ u8 *elem_count, const u8 *known_bss,
++ size_t known_bss_len);
++u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end,
++ u32 frame_type, u8 elem_count, u8 **elem_offset,
++ const u8 *known_bss, size_t known_bss_len);
+ #endif /* IEEE802_11_H */
+diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c
+index 4f85d78..7f5b475 100644
+--- a/src/ap/ieee802_11_shared.c
++++ b/src/ap/ieee802_11_shared.c
+@@ -364,6 +364,8 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx)
+ *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
+ if (hapd->conf->bss_transition)
+ *pos |= 0x08; /* Bit 19 - BSS Transition */
++ if (hapd->iconf->mbssid)
++ *pos |= 0x40; /* Bit 22 - Multiple BSSID */
+ break;
+ case 3: /* Bits 24-31 */
+ #ifdef CONFIG_WNM_AP
+@@ -436,6 +438,8 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx)
+ (hapd->iface->drv_flags &
+ WPA_DRIVER_FLAGS_BEACON_PROTECTION))
+ *pos |= 0x10; /* Bit 84 - Beacon Protection Enabled */
++ if (hapd->iconf->mbssid == ENHANCED_MBSSID_ENABLED)
++ *pos |= 0x08; /* Bit 83 - Enhanced multiple BSSID */
+ break;
+ case 11: /* Bits 88-95 */
+ #ifdef CONFIG_SAE_PK
+@@ -471,6 +475,13 @@ u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid)
+ *pos &= ~hapd->conf->ext_capa_mask[i];
+ *pos |= hapd->conf->ext_capa[i];
+ }
++
++ /* Clear bits 83 and 22 if EMA and MBSSID are not enabled
++ * otherwise association fails with some clients */
++ if (i == 10 && hapd->iconf->mbssid < ENHANCED_MBSSID_ENABLED)
++ *pos &= ~0x08;
++ if (i == 2 && !hapd->iconf->mbssid)
++ *pos &= ~0x40;
+ }
+
+ while (len > 0 && eid[1 + len] == 0) {
+diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c
+index c8ee90c..2fab7c3 100644
+--- a/src/common/ieee802_11_common.c
++++ b/src/common/ieee802_11_common.c
+@@ -315,6 +315,10 @@ static int ieee802_11_parse_extension(const u8 *pos, size_t elen,
+ elems->eht_operation = pos;
+ elems->eht_operation_len = elen;
+ break;
++ case WLAN_EID_EXT_KNOWN_BSSID:
++ elems->mbssid_known_bss = pos;
++ elems->mbssid_known_bss_len = elen;
++ break;
+ default:
+ if (show_errors) {
+ wpa_printf(MSG_MSGDUMP,
+diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h
+index 94e1d7b..1e4e27d 100644
+--- a/src/common/ieee802_11_common.h
++++ b/src/common/ieee802_11_common.h
+@@ -119,6 +119,7 @@ struct ieee802_11_elems {
+ const u8 *pasn_params;
+ const u8 *eht_capabilities;
+ const u8 *eht_operation;
++ const u8 *mbssid_known_bss;
+
+ u8 ssid_len;
+ u8 supp_rates_len;
+@@ -176,6 +177,8 @@ struct ieee802_11_elems {
+ u8 eht_capabilities_len;
+ u8 eht_operation_len;
+
++ u8 mbssid_known_bss_len;
++
+ struct mb_ies_info mb_ies;
+ struct frag_ies_info frag_ies;
+ };
+diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
+index 62088bd..0bbbca9 100644
+--- a/src/common/ieee802_11_defs.h
++++ b/src/common/ieee802_11_defs.h
+@@ -481,6 +481,9 @@
+ #define WLAN_EID_EXT_SPATIAL_REUSE 39
+ #define WLAN_EID_EXT_COLOR_CHANGE_ANNOUNCEMENT 42
+ #define WLAN_EID_EXT_OCV_OCI 54
++#define WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION 55
++#define WLAN_EID_EXT_NON_INHERITANCE 56
++#define WLAN_EID_EXT_KNOWN_BSSID 57
+ #define WLAN_EID_EXT_SHORT_SSID_LIST 58
+ #define WLAN_EID_EXT_HE_6GHZ_BAND_CAP 59
+ #define WLAN_EID_EXT_EDMG_CAPABILITIES 61
+@@ -497,6 +500,8 @@
+ #define WLAN_EID_EXT_MULTI_LINK_TRAFFIC_INDICATION 110
+ #define WLAN_EID_EXT_AKM_SUITE_SELECTOR 114
+
++#define WLAN_EID_SUBELEMENT_NONTRANSMITTED_BSSID_PROFILE 0
++
+ /* Extended Capabilities field */
+ #define WLAN_EXT_CAPAB_20_40_COEX 0
+ #define WLAN_EXT_CAPAB_GLK 1
+diff --git a/src/drivers/driver.h b/src/drivers/driver.h
+index 82daef0..36f465c 100644
+--- a/src/drivers/driver.h
++++ b/src/drivers/driver.h
+@@ -1633,6 +1633,43 @@ struct wpa_driver_ap_params {
+ * ibf_enable=<val>
+ */
+ u8 ibf_enable;
++
++ /**
++ * mbssid_tx_iface - Transmitting interface of the MBSSID set
++ */
++ const char *mbssid_tx_iface;
++
++ /**
++ * mbssid_index - The index of this BSS in the MBSSID set
++ */
++ unsigned int mbssid_index;
++
++ /**
++ * mbssid_elem - Buffer containing all MBSSID elements
++ */
++ u8 *mbssid_elem;
++
++ /**
++ * mbssid_elem_len - Total length of all MBSSID elements
++ */
++ size_t mbssid_elem_len;
++
++ /**
++ * mbssid_elem_count - The number of MBSSID elements
++ */
++ u8 mbssid_elem_count;
++
++ /**
++ * mbssid_elem_offset - Offsets to elements in mbssid_elem.
++ * Kernel will use these offsets to generate multiple BSSID beacons.
++ */
++ u8 **mbssid_elem_offset;
++
++ /**
++ * ema - Enhanced MBSSID advertisements support.
++ */
++ bool ema;
++
+ };
+
+ struct wpa_driver_mesh_bss_params {
+@@ -2197,6 +2234,11 @@ struct wpa_driver_capa {
+
+ /* Maximum number of supported CSA counters */
+ u16 max_csa_counters;
++
++ /* Maximum number of interfaces supported for MBSSID advertisements */
++ u8 mbssid_max_interfaces;
++ /* Maximum profile periodicity for enhanced MBSSID advertisements */
++ u8 ema_max_periodicity;
+ };
+
+
+diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
+index 6c65901..3753409 100644
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -4540,6 +4540,55 @@ static int nl80211_unsol_bcast_probe_resp(struct i802_bss *bss,
+ nla_nest_end(msg, attr);
+ return 0;
+ }
++
++
++static int nl80211_mbssid(struct nl_msg *msg,
++ struct wpa_driver_ap_params *params)
++{
++ struct nlattr *config, *elems;
++ int ifidx;
++
++ if (!params->mbssid_tx_iface)
++ return 0;
++
++ config = nla_nest_start(msg, NL80211_ATTR_MBSSID_CONFIG);
++ if (!config)
++ return -1;
++
++ nla_put_u8(msg, NL80211_MBSSID_CONFIG_ATTR_INDEX, params->mbssid_index);
++ if (params->mbssid_tx_iface) {
++ ifidx = if_nametoindex(params->mbssid_tx_iface);
++ if (ifidx <= 0)
++ return -1;
++ nla_put_u32(msg,
++ NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX,
++ ifidx);
++ }
++
++ if (params->ema)
++ nla_put_flag(msg, NL80211_MBSSID_CONFIG_ATTR_EMA);
++
++ nla_nest_end(msg, config);
++
++ if (params->mbssid_elem_count && params->mbssid_elem_len &&
++ params->mbssid_elem_offset && *params->mbssid_elem_offset) {
++ u8 i, **offs = params->mbssid_elem_offset;
++
++ elems = nla_nest_start(msg, NL80211_ATTR_MBSSID_ELEMS);
++ if (!elems)
++ return -1;
++
++ for (i = 0; i < params->mbssid_elem_count - 1; i++)
++ nla_put(msg, i + 1, offs[i + 1] - offs[i], offs[i]);
++
++ nla_put(msg, i + 1,
++ *offs + params->mbssid_elem_len - offs[i],
++ offs[i]);
++
++ nla_nest_end(msg, elems);
++ }
++ return 0;
++}
+ #endif /* CONFIG_IEEE80211AX */
+
+
+@@ -4838,6 +4887,9 @@ static int wpa_driver_nl80211_set_ap(void *priv,
+ if (params->unsol_bcast_probe_resp_interval &&
+ nl80211_unsol_bcast_probe_resp(bss, msg, params) < 0)
+ goto fail;
++
++ if (nl80211_mbssid(msg, params) < 0)
++ goto fail;
+ #endif /* CONFIG_IEEE80211AX */
+
+ #ifdef CONFIG_SAE
+diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
+index 06a52db..d8078bc 100644
+--- a/src/drivers/driver_nl80211_capa.c
++++ b/src/drivers/driver_nl80211_capa.c
+@@ -857,6 +857,30 @@ err:
+ }
+
+
++static void wiphy_info_mbssid(struct wpa_driver_capa *cap, struct nlattr *attr)
++{
++ struct nlattr *config[NL80211_MBSSID_CONFIG_ATTR_MAX + 1];
++
++ if (nla_parse_nested(config, NL80211_MBSSID_CONFIG_ATTR_MAX, attr,
++ NULL))
++ return;
++
++ if (!config[NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES])
++ return;
++
++ cap->mbssid_max_interfaces =
++ nla_get_u8(config[NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES]);
++
++ if (config[NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY])
++ cap->ema_max_periodicity =
++ nla_get_u8(config[NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY]);
++
++ wpa_printf(MSG_DEBUG,
++ "multiple_bssid: max interfaces %u, max profile periodicity %u\n",
++ cap->mbssid_max_interfaces, cap->ema_max_periodicity);
++}
++
++
+ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
+ {
+ struct nlattr *tb[NL80211_ATTR_MAX + 1];
+@@ -1106,6 +1130,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
+ if (tb[NL80211_ATTR_WIPHY_SELF_MANAGED_REG])
+ capa->flags |= WPA_DRIVER_FLAGS_SELF_MANAGED_REGULATORY;
+
++ if (tb[NL80211_ATTR_MBSSID_CONFIG])
++ wiphy_info_mbssid(capa, tb[NL80211_ATTR_MBSSID_CONFIG]);
++
+ return NL_SKIP;
+ }
+
+--
+2.18.0
+
diff --git a/recipes-wifi/hostapd/files/patches-2.10.3/patches.inc b/recipes-wifi/hostapd/files/patches-2.10.3/patches.inc
index 4a42f53..5e6bf88 100644
--- a/recipes-wifi/hostapd/files/patches-2.10.3/patches.inc
+++ b/recipes-wifi/hostapd/files/patches-2.10.3/patches.inc
@@ -71,11 +71,18 @@
file://mtk-0007-hostapd-mtk-Add-three-wire-PTA-ctrl-hostapd-vendor-c.patch \
file://mtk-0008-hostapd-mtk-Add-hostapd-iBF-control.patch \
file://mtk-0009-hostapd-mtk-Do-not-include-HE-capab-IE-if-associated.patch \
- file://mtk-0010-hostapd-mtk-Add-DFS-and-ZWDFS-support.patch \
- file://mtk-0011-hostapd-mtk-Add-amsdu-set-get-ctrl.patch \
- file://mtk-0012-hostapd-mtk-Add-he_ldpc-configuration.patch \
- file://mtk-0013-hostapd-mtk-Add-the-broadcast-destination-address-of.patch \
- file://mtk-0014-hostapd-mtk-Add-vendor-command-attribute-for-RTS-BW-.patch \
- file://mtk-0015-hostapd-mtk-6G-band-does-not-require-DFS.patch \
+ file://mtk-0010-hostapd-mtk-Add-DFS-detection-mode.patch \
+ file://mtk-0011-hostapd-mtk-Add-DFS-offchan-channel-switch.patch \
+ file://mtk-0012-hostapd-mtk-Add-amsdu-set-get-ctrl.patch \
+ file://mtk-0013-hostapd-mtk-Add-he_ldpc-configuration.patch \
+ file://mtk-0014-hostapd-mtk-Add-the-broadcast-destination-address-of.patch \
+ file://mtk-0015-hostapd-mtk-Add-vendor-command-attribute-for-RTS-BW-.patch \
+ file://mtk-0016-hostapd-mtk-6G-band-does-not-require-DFS.patch \
+ file://mtk-0016-hostapd-mtk-Add-available-color-bitmap.patch \
+ file://mtk-0017-hostapd-mtk-Fix-sending-wrong-VHT-operation-IE-in-CS.patch \
+ file://mtk-0018-hostapd-mtk-Add-sta-assisted-DFS-state-update-mechan.patch \
+ file://mtk-0019-hostapd-mtk-Fix-auto-ht-issue-when-switching-to-DFS-.patch \
+ file://mtk-0020-hostapd-mtk-Mark-DFS-channel-as-available-for-CSA.patch \
+ file://mtk-0020-hostapd-mtk-add-11v_mbss-and-ema-support.patch \
file://mtk-0100-hostapd-mtk-update-eht-operation-elem.patch \
"
diff --git a/recipes-wifi/hostapd/files/patches/mtk-0010-hostapd-mtk-Add-DFS-and-ZWDFS-support.patch b/recipes-wifi/hostapd/files/patches/mtk-0010-hostapd-mtk-Add-DFS-and-ZWDFS-support.patch
deleted file mode 100644
index 3237aa3..0000000
--- a/recipes-wifi/hostapd/files/patches/mtk-0010-hostapd-mtk-Add-DFS-and-ZWDFS-support.patch
+++ /dev/null
@@ -1,376 +0,0 @@
-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_mu(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
-
diff --git a/recipes-wifi/hostapd/files/patches/mtk-0010-hostapd-mtk-Add-DFS-detection-mode.patch b/recipes-wifi/hostapd/files/patches/mtk-0010-hostapd-mtk-Add-DFS-detection-mode.patch
new file mode 100644
index 0000000..7ec986a
--- /dev/null
+++ b/recipes-wifi/hostapd/files/patches/mtk-0010-hostapd-mtk-Add-DFS-detection-mode.patch
@@ -0,0 +1,136 @@
+From 6828156c206701f5a0e5d30afcc514f452ce0ada Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Mon, 20 Feb 2023 14:55:49 +0800
+Subject: [PATCH 10/16] hostapd: mtk: Add DFS detection mode
+
+Add DFS detection mode for testing radar detection rate.
+If DFS detection mode is on, AP will not switch channels when receiving
+a radar signal.
+This detection mode also supports background chain.
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ hostapd/config_file.c | 4 ++++
+ hostapd/ctrl_iface.c | 23 +++++++++++++++++++++++
+ src/ap/ap_config.h | 13 +++++++++++++
+ src/ap/dfs.c | 10 ++++++++++
+ 4 files changed, 50 insertions(+)
+
+diff --git a/hostapd/config_file.c b/hostapd/config_file.c
+index 63c9d40..cd15349 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 c881d37..0b4c234 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -3522,6 +3522,26 @@ 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_receive_process(struct hostapd_data *hapd,
+ char *buf, char *reply,
+ int reply_size,
+@@ -4081,6 +4101,9 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
+ reply_len = hostapd_ctrl_iface_get_mu(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 {
+ 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 a9e3d2a..77f6169 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 b5d105d..5cb7799 100644
+--- a/src/ap/dfs.c
++++ b/src/ap/dfs.c
+@@ -1317,6 +1317,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 +1370,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;
+--
+2.18.0
+
diff --git a/recipes-wifi/hostapd/files/patches/mtk-0011-hostapd-mtk-Add-DFS-offchan-channel-switch.patch b/recipes-wifi/hostapd/files/patches/mtk-0011-hostapd-mtk-Add-DFS-offchan-channel-switch.patch
new file mode 100644
index 0000000..1d8baf8
--- /dev/null
+++ b/recipes-wifi/hostapd/files/patches/mtk-0011-hostapd-mtk-Add-DFS-offchan-channel-switch.patch
@@ -0,0 +1,192 @@
+From 88dd3df28e3736af4cca0daf4f7d19ab888ea6c4 Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Mon, 20 Feb 2023 14:56:55 +0800
+Subject: [PATCH 11/16] hostapd: mtk: Add DFS offchan channel switch
+
+Add DFS background chain channel switch command for testing purpose.
+This feature is implemented via hostapd_cli command.
+Command format:
+hostapd_cli -i <interface> raw SET_OFFCHAN_CTRL chan=<dfs_channel>
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ hostapd/ctrl_iface.c | 72 ++++++++++++++++++++++++++++++++++++++++++++
+ src/ap/dfs.c | 25 ++++++---------
+ src/ap/dfs.h | 15 +++++++++
+ 3 files changed, 96 insertions(+), 16 deletions(-)
+
+diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
+index 0b4c234..6ea1573 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -3542,6 +3542,76 @@ hostapd_ctrl_iface_set_dfs_detect_mode(struct hostapd_data *hapd, char *value,
+ }
+
+
++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,
+@@ -4104,6 +4174,8 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
+ } 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/dfs.c b/src/ap/dfs.c
+index 5cb7799..1c3f678 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;
+diff --git a/src/ap/dfs.h b/src/ap/dfs.h
+index 606c1b3..c2556d2 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 */
+--
+2.18.0
+
diff --git a/recipes-wifi/hostapd/files/patches/mtk-0011-hostapd-mtk-Add-amsdu-set-get-ctrl.patch b/recipes-wifi/hostapd/files/patches/mtk-0011-hostapd-mtk-Add-amsdu-set-get-ctrl.patch
deleted file mode 100644
index dba90d1..0000000
--- a/recipes-wifi/hostapd/files/patches/mtk-0011-hostapd-mtk-Add-amsdu-set-get-ctrl.patch
+++ /dev/null
@@ -1,400 +0,0 @@
-From bc0722ebc1cc08be6239879fddaef37e0db2d9e0 Mon Sep 17 00:00:00 2001
-From: Evelyn Tsai <evelyn.tsai@mediatek.com>
-Date: Fri, 16 Dec 2022 03:57:11 +0800
-Subject: [PATCH 11/15] hostapd: mtk: Add amsdu set get ctrl
-
----
- hostapd/config_file.c | 9 +++
- hostapd/ctrl_iface.c | 26 +++++++
- hostapd/hostapd_cli.c | 9 +++
- src/ap/ap_config.c | 1 +
- src/ap/ap_config.h | 1 +
- src/ap/ap_drv_ops.c | 14 ++++
- src/ap/ap_drv_ops.h | 2 +
- src/ap/hostapd.c | 2 +
- src/common/mtk_vendor.h | 17 ++++-
- src/drivers/driver.h | 9 +++
- src/drivers/driver_nl80211.c | 114 ++++++++++++++++++++++++++++++
- src/drivers/driver_nl80211.h | 1 +
- src/drivers/driver_nl80211_capa.c | 3 +
- 13 files changed, 207 insertions(+), 1 deletion(-)
-
-diff --git a/hostapd/config_file.c b/hostapd/config_file.c
-index cd1534952..10ea52518 100644
---- a/hostapd/config_file.c
-+++ b/hostapd/config_file.c
-@@ -4807,6 +4807,15 @@ static int hostapd_config_fill(struct hostapd_config *conf,
- u8 en = strtol(pos, NULL, 10);
-
- conf->dfs_detect_mode = en;
-+ } else if (os_strcmp(buf, "amsdu") == 0) {
-+ int val = atoi(pos);
-+ if (val < 0 || val > 1) {
-+ wpa_printf(MSG_ERROR,
-+ "Line %d: invalid amsdu value",
-+ line);
-+ return 1;
-+ }
-+ conf->amsdu = val;
- } else {
- wpa_printf(MSG_ERROR,
- "Line %d: unknown configuration item '%s'",
-diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
-index 6ea1573b8..0ad8451aa 100644
---- a/hostapd/ctrl_iface.c
-+++ b/hostapd/ctrl_iface.c
-@@ -3612,6 +3612,30 @@ hostapd_ctrl_iface_set_offchan_ctrl(struct hostapd_data *hapd, char *cmd,
- }
-
-
-+static int
-+hostapd_ctrl_iface_get_amsdu(struct hostapd_data *hapd, char *buf,
-+ size_t buflen)
-+{
-+ u8 amsdu;
-+ int ret;
-+ char *pos, *end;
-+
-+ pos = buf;
-+ end = buf + buflen;
-+
-+ if (hostapd_drv_amsdu_dump(hapd, &amsdu) == 0) {
-+ hapd->iconf->amsdu = amsdu;
-+ ret = os_snprintf(pos, end - pos, "[hostapd_cli] AMSDU: %u\n",
-+ hapd->iconf->amsdu);
-+ }
-+
-+ if (os_snprintf_error(end - pos, ret))
-+ return 0;
-+
-+ return ret;
-+}
-+
-+
- static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
- char *buf, char *reply,
- int reply_size,
-@@ -4176,6 +4200,8 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
- 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 if (os_strncmp(buf, "GET_AMSDU", 9) == 0) {
-+ reply_len = hostapd_ctrl_iface_get_amsdu(hapd, reply, reply_size);
- } else {
- os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
- reply_len = 16;
-diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
-index c2a123a8c..30b3392e6 100644
---- a/hostapd/hostapd_cli.c
-+++ b/hostapd/hostapd_cli.c
-@@ -1593,6 +1593,13 @@ static int hostapd_cli_cmd_get_ibf(struct wpa_ctrl *ctrl, int argc,
- }
-
-
-+static int hostapd_cli_cmd_get_amsdu(struct wpa_ctrl *ctrl, int argc,
-+ char *argv[])
-+{
-+ return hostapd_cli_cmd(ctrl, "GET_AMSDU", 0, NULL, NULL);
-+}
-+
-+
- struct hostapd_cli_cmd {
- const char *cmd;
- int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
-@@ -1796,6 +1803,8 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
- "<tx type(0/1/2)> <interval> = runtime set inband discovery" },
- { "get_ibf", hostapd_cli_cmd_get_ibf, NULL,
- " = show iBF state (enabled/disabled)"},
-+ { "get_amsdu", hostapd_cli_cmd_get_amsdu, NULL,
-+ " = show AMSDU state"},
- { NULL, NULL, NULL, NULL }
- };
-
-diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
-index 7a96cb8b2..85ad5e444 100644
---- a/src/ap/ap_config.c
-+++ b/src/ap/ap_config.c
-@@ -299,6 +299,7 @@ struct hostapd_config * hostapd_config_defaults(void)
- conf->edcca_compensation = EDCCA_DEFAULT_COMPENSATION;
- conf->three_wire_enable = THREE_WIRE_MODE_DISABLE;
- conf->ibf_enable = IBF_DEFAULT_ENABLE;
-+ conf->amsdu = 1;
-
- return conf;
- }
-diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
-index 77f6169d2..a9ac39619 100644
---- a/src/ap/ap_config.h
-+++ b/src/ap/ap_config.h
-@@ -1161,6 +1161,7 @@ struct hostapd_config {
- u8 three_wire_enable;
- u8 ibf_enable;
- u8 dfs_detect_mode;
-+ u8 amsdu;
- };
-
- enum three_wire_mode {
-diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
-index 60ae8253b..1a82f234c 100644
---- a/src/ap/ap_drv_ops.c
-+++ b/src/ap/ap_drv_ops.c
-@@ -1077,4 +1077,18 @@ int hostapd_drv_ibf_dump(struct hostapd_data *hapd, u8 *ibf_enable)
- if (!hapd->driver || !hapd->driver->ibf_dump)
- return 0;
- return hapd->driver->ibf_dump(hapd->drv_priv, ibf_enable);
-+}
-+
-+int hostapd_drv_amsdu_ctrl(struct hostapd_data *hapd)
-+{
-+ if (!hapd->driver || !hapd->driver->amsdu_ctrl)
-+ return 0;
-+ return hapd->driver->amsdu_ctrl(hapd->drv_priv, hapd->iconf->amsdu);
-+}
-+
-+int hostapd_drv_amsdu_dump(struct hostapd_data *hapd, u8 *amsdu)
-+{
-+ if (!hapd->driver || !hapd->driver->amsdu_dump)
-+ return 0;
-+ return hapd->driver->amsdu_dump(hapd->drv_priv, amsdu);
- }
-\ No newline at end of file
-diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
-index ab9aedcee..4406666fd 100644
---- a/src/ap/ap_drv_ops.h
-+++ b/src/ap/ap_drv_ops.h
-@@ -147,6 +147,8 @@ int hostapd_drv_mu_dump(struct hostapd_data *hapd, u8 *mu_onoff);
- int hostapd_drv_three_wire_ctrl(struct hostapd_data *hapd);
- int hostapd_drv_ibf_ctrl(struct hostapd_data *hapd);
- int hostapd_drv_ibf_dump(struct hostapd_data *hapd, u8 *ibf_enable);
-+int hostapd_drv_amsdu_ctrl(struct hostapd_data *hapd);
-+int hostapd_drv_amsdu_dump(struct hostapd_data *hapd, u8 *amsdu);
-
- #include "drivers/driver.h"
-
-diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
-index a0229c9ca..152060db4 100644
---- a/src/ap/hostapd.c
-+++ b/src/ap/hostapd.c
-@@ -2310,6 +2310,8 @@ dfs_offload:
- goto fail;
- if (hostapd_drv_ibf_ctrl(hapd) < 0)
- goto fail;
-+ if (hostapd_drv_amsdu_ctrl(hapd) < 0)
-+ goto fail;
-
- wpa_printf(MSG_DEBUG, "%s: Setup of interface done.",
- iface->bss[0]->conf->iface);
-diff --git a/src/common/mtk_vendor.h b/src/common/mtk_vendor.h
-index 4050cf886..0999ea9e2 100644
---- a/src/common/mtk_vendor.h
-+++ b/src/common/mtk_vendor.h
-@@ -167,7 +167,6 @@ enum mtk_vendor_attr_wireless_ctrl {
- MTK_VENDOR_ATTR_WIRELESS_CTRL_NUSERS_OFDMA,
- MTK_VENDOR_ATTR_WIRELESS_CTRL_BA_BUFFER_SIZE,
- MTK_VENDOR_ATTR_WIRELESS_CTRL_MIMO,
-- MTK_VENDOR_ATTR_WIRELESS_CTRL_AMPDU,
- MTK_VENDOR_ATTR_WIRELESS_CTRL_AMSDU,
- MTK_VENDOR_ATTR_WIRELESS_CTRL_CERT,
-
-@@ -177,6 +176,22 @@ enum mtk_vendor_attr_wireless_ctrl {
- NUM_MTK_VENDOR_ATTRS_WIRELESS_CTRL - 1
- };
-
-+enum mtk_vendor_attr_wireless_dump {
-+ MTK_VENDOR_ATTR_WIRELESS_DUMP_UNSPEC,
-+
-+ MTK_VENDOR_ATTR_WIRELESS_DUMP_AMSDU,
-+
-+ /* keep last */
-+ NUM_MTK_VENDOR_ATTRS_WIRELESS_DUMP,
-+ MTK_VENDOR_ATTR_WIRELESS_DUMP_MAX =
-+ NUM_MTK_VENDOR_ATTRS_WIRELESS_DUMP - 1
-+};
-+
-+static const struct nla_policy
-+wireless_dump_policy[NUM_MTK_VENDOR_ATTRS_WIRELESS_DUMP] = {
-+ [MTK_VENDOR_ATTR_WIRELESS_DUMP_AMSDU] = { .type = NLA_U8 },
-+};
-+
- enum mtk_vendor_attr_rfeature_ctrl {
- MTK_VENDOR_ATTR_RFEATURE_CTRL_UNSPEC,
-
-diff --git a/src/drivers/driver.h b/src/drivers/driver.h
-index aa23fbdb3..b07aaf3fe 100644
---- a/src/drivers/driver.h
-+++ b/src/drivers/driver.h
-@@ -4727,6 +4727,15 @@ struct wpa_driver_ops {
- *
- */
- int (*start_disabled)(void *priv);
-+
-+ /**
-+ * amsdu_ctrl - enable/disable amsdu
-+ * amsdu_dump - get current amsdu status
-+ * @priv: Private driver interface data
-+ *
-+ */
-+ int (*amsdu_ctrl)(void *priv, u8 amsdu);
-+ int (*amsdu_dump)(void *priv, u8 *amsdu);
- };
-
- /**
-diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
-index 7472542cc..6702384ef 100644
---- a/src/drivers/driver_nl80211.c
-+++ b/src/drivers/driver_nl80211.c
-@@ -12804,6 +12804,118 @@ fail:
- return ret;
- }
-
-+static int nl80211_enable_amsdu(void *priv, u8 amsdu)
-+{
-+ struct i802_bss *bss = priv;
-+ struct wpa_driver_nl80211_data *drv = bss->drv;
-+ struct nl_msg *msg;
-+ struct nlattr *data;
-+ int ret;
-+
-+ if (!drv->mtk_wireless_vendor_cmd_avail) {
-+ wpa_printf(MSG_INFO,
-+ "nl80211: Driver does not support setting ap wireless control");
-+ return 0;
-+ }
-+
-+ msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR);
-+ if (!msg)
-+ goto fail;
-+
-+ if (nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_MTK) ||
-+ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, MTK_NL80211_VENDOR_SUBCMD_WIRELESS_CTRL))
-+ goto fail;
-+
-+ data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
-+ if (!data)
-+ goto fail;
-+
-+ nla_put_u8(msg, MTK_VENDOR_ATTR_WIRELESS_CTRL_AMSDU, amsdu);
-+
-+ nla_nest_end(msg, data);
-+ ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
-+ if (ret) {
-+ wpa_printf(MSG_ERROR, "Failed to set amsdu. ret=%d (%s)", ret, strerror(-ret));
-+ }
-+
-+ return ret;
-+
-+fail:
-+ nlmsg_free(msg);
-+ return -ENOBUFS;
-+}
-+
-+static int dump_amsdu_handler(struct nl_msg *msg, void *arg)
-+{
-+ u8 *amsdu = (u8 *) arg;
-+ struct nlattr *tb[NL80211_ATTR_MAX + 1];
-+ struct nlattr *tb_vendor[MTK_VENDOR_ATTR_WIRELESS_DUMP_MAX + 1];
-+ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
-+ struct nlattr *nl_vend, *attr_amsdu;
-+
-+ nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
-+ genlmsg_attrlen(gnlh, 0), NULL);
-+
-+ nl_vend = tb[NL80211_ATTR_VENDOR_DATA];
-+ if (!nl_vend)
-+ return NL_SKIP;
-+
-+ nla_parse(tb_vendor, MTK_VENDOR_ATTR_WIRELESS_DUMP_MAX,
-+ nla_data(nl_vend), nla_len(nl_vend), NULL);
-+
-+ attr_amsdu = tb_vendor[MTK_VENDOR_ATTR_WIRELESS_DUMP_AMSDU];
-+ if (!attr_amsdu ){
-+ wpa_printf(MSG_ERROR, "nl80211: cannot find vendor attributes");
-+ return NL_SKIP;
-+ }
-+
-+ *amsdu = nla_get_u8(attr_amsdu);
-+
-+ return NL_SKIP;
-+}
-+
-+static int
-+nl80211_dump_amsdu(void *priv, u8 *amsdu)
-+{
-+ struct i802_bss *bss = priv;
-+ struct wpa_driver_nl80211_data *drv = bss->drv;
-+ struct nl_msg *msg;
-+ struct nlattr *data;
-+ int ret;
-+
-+ if (!drv->mtk_wireless_vendor_cmd_avail) {
-+ wpa_printf(MSG_INFO,
-+ "nl80211: Driver does not support ap_wireless control");
-+ return 0;
-+ }
-+
-+ msg = nl80211_drv_msg(drv, NLM_F_DUMP, NL80211_CMD_VENDOR);
-+ if (!msg)
-+ goto fail;
-+
-+ if (nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_MTK) ||
-+ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, MTK_NL80211_VENDOR_SUBCMD_WIRELESS_CTRL))
-+ goto fail;
-+
-+ data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
-+ if (!data)
-+ goto fail;
-+
-+ nla_nest_end(msg, data);
-+
-+ ret = send_and_recv_msgs(drv, msg, dump_amsdu_handler, amsdu, NULL, NULL);
-+
-+ if (ret) {
-+ wpa_printf(MSG_ERROR, "Failed to dump amsdu. ret=%d (%s)", ret, strerror(-ret));
-+ }
-+
-+ return ret;
-+
-+fail:
-+ nlmsg_free(msg);
-+ return -ENOBUFS;
-+}
-+
- const struct wpa_driver_ops wpa_driver_nl80211_ops = {
- .name = "nl80211",
- .desc = "Linux nl80211/cfg80211",
-@@ -12959,4 +13071,6 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
- .ibf_ctrl = nl80211_ibf_enable,
- .ibf_dump = nl80211_ibf_dump,
- .start_disabled = nl80211_start_disabled,
-+ .amsdu_ctrl = nl80211_enable_amsdu,
-+ .amsdu_dump = nl80211_dump_amsdu,
- };
-diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h
-index 607592ceb..e57022409 100644
---- a/src/drivers/driver_nl80211.h
-+++ b/src/drivers/driver_nl80211.h
-@@ -185,6 +185,7 @@ struct wpa_driver_nl80211_data {
- unsigned int mtk_mu_vendor_cmd_avail:1;
- unsigned int mtk_3wire_vendor_cmd_avail:1;
- unsigned int mtk_ibf_vendor_cmd_avail:1;
-+ unsigned int mtk_wireless_vendor_cmd_avail:1;
-
- u64 vendor_scan_cookie;
- u64 remain_on_chan_cookie;
-diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
-index 9ecc0ff9a..fcfa68bf7 100644
---- a/src/drivers/driver_nl80211_capa.c
-+++ b/src/drivers/driver_nl80211_capa.c
-@@ -1065,6 +1065,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
- case MTK_NL80211_VENDOR_SUBCMD_IBF_CTRL:
- drv->mtk_ibf_vendor_cmd_avail = 1;
- break;
-+ case MTK_NL80211_VENDOR_SUBCMD_WIRELESS_CTRL:
-+ drv->mtk_wireless_vendor_cmd_avail = 1;
-+ break;
- }
- }
-
---
-2.25.1
-
diff --git a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0011-hostapd-mtk-Add-amsdu-set-get-ctrl.patch b/recipes-wifi/hostapd/files/patches/mtk-0012-hostapd-mtk-Add-amsdu-set-get-ctrl.patch
similarity index 92%
copy from recipes-wifi/hostapd/files/patches-2.10.3/mtk-0011-hostapd-mtk-Add-amsdu-set-get-ctrl.patch
copy to recipes-wifi/hostapd/files/patches/mtk-0012-hostapd-mtk-Add-amsdu-set-get-ctrl.patch
index dba90d1..7db3ae2 100644
--- a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0011-hostapd-mtk-Add-amsdu-set-get-ctrl.patch
+++ b/recipes-wifi/hostapd/files/patches/mtk-0012-hostapd-mtk-Add-amsdu-set-get-ctrl.patch
@@ -1,7 +1,7 @@
-From bc0722ebc1cc08be6239879fddaef37e0db2d9e0 Mon Sep 17 00:00:00 2001
+From d0128fc60d38ce4f20f8368bdc5ea9ed19a329b7 Mon Sep 17 00:00:00 2001
From: Evelyn Tsai <evelyn.tsai@mediatek.com>
Date: Fri, 16 Dec 2022 03:57:11 +0800
-Subject: [PATCH 11/15] hostapd: mtk: Add amsdu set get ctrl
+Subject: [PATCH 12/16] hostapd: mtk: Add amsdu set get ctrl
---
hostapd/config_file.c | 9 +++
@@ -20,7 +20,7 @@
13 files changed, 207 insertions(+), 1 deletion(-)
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
-index cd1534952..10ea52518 100644
+index cd15349..10ea525 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -4807,6 +4807,15 @@ static int hostapd_config_fill(struct hostapd_config *conf,
@@ -40,7 +40,7 @@
wpa_printf(MSG_ERROR,
"Line %d: unknown configuration item '%s'",
diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
-index 6ea1573b8..0ad8451aa 100644
+index 6ea1573..0ad8451 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -3612,6 +3612,30 @@ hostapd_ctrl_iface_set_offchan_ctrl(struct hostapd_data *hapd, char *cmd,
@@ -84,7 +84,7 @@
os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
reply_len = 16;
diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
-index c2a123a8c..30b3392e6 100644
+index c2a123a..30b3392 100644
--- a/hostapd/hostapd_cli.c
+++ b/hostapd/hostapd_cli.c
@@ -1593,6 +1593,13 @@ static int hostapd_cli_cmd_get_ibf(struct wpa_ctrl *ctrl, int argc,
@@ -111,7 +111,7 @@
};
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
-index 7a96cb8b2..85ad5e444 100644
+index 7a96cb8..85ad5e4 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -299,6 +299,7 @@ struct hostapd_config * hostapd_config_defaults(void)
@@ -123,7 +123,7 @@
return conf;
}
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
-index 77f6169d2..a9ac39619 100644
+index 77f6169..a9ac396 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -1161,6 +1161,7 @@ struct hostapd_config {
@@ -135,7 +135,7 @@
enum three_wire_mode {
diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
-index 60ae8253b..1a82f234c 100644
+index 60ae825..1a82f23 100644
--- a/src/ap/ap_drv_ops.c
+++ b/src/ap/ap_drv_ops.c
@@ -1077,4 +1077,18 @@ int hostapd_drv_ibf_dump(struct hostapd_data *hapd, u8 *ibf_enable)
@@ -159,7 +159,7 @@
}
\ No newline at end of file
diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
-index ab9aedcee..4406666fd 100644
+index ab9aedc..4406666 100644
--- a/src/ap/ap_drv_ops.h
+++ b/src/ap/ap_drv_ops.h
@@ -147,6 +147,8 @@ int hostapd_drv_mu_dump(struct hostapd_data *hapd, u8 *mu_onoff);
@@ -172,10 +172,10 @@
#include "drivers/driver.h"
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
-index a0229c9ca..152060db4 100644
+index da7f7d8..a18e744 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
-@@ -2310,6 +2310,8 @@ dfs_offload:
+@@ -2308,6 +2308,8 @@ dfs_offload:
goto fail;
if (hostapd_drv_ibf_ctrl(hapd) < 0)
goto fail;
@@ -185,7 +185,7 @@
wpa_printf(MSG_DEBUG, "%s: Setup of interface done.",
iface->bss[0]->conf->iface);
diff --git a/src/common/mtk_vendor.h b/src/common/mtk_vendor.h
-index 4050cf886..0999ea9e2 100644
+index 4050cf8..0999ea9 100644
--- a/src/common/mtk_vendor.h
+++ b/src/common/mtk_vendor.h
@@ -167,7 +167,6 @@ enum mtk_vendor_attr_wireless_ctrl {
@@ -220,13 +220,13 @@
MTK_VENDOR_ATTR_RFEATURE_CTRL_UNSPEC,
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
-index aa23fbdb3..b07aaf3fe 100644
+index 71ded61..265d86d 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
-@@ -4727,6 +4727,15 @@ struct wpa_driver_ops {
+@@ -4720,6 +4720,15 @@ struct wpa_driver_ops {
*
*/
- int (*start_disabled)(void *priv);
+ int (*ibf_dump)(void *priv, u8 *ibf_enable);
+
+ /**
+ * amsdu_ctrl - enable/disable amsdu
@@ -240,11 +240,11 @@
/**
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
-index 7472542cc..6702384ef 100644
+index 5c2a291..d91b29c 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
-@@ -12804,6 +12804,118 @@ fail:
- return ret;
+@@ -12776,6 +12776,118 @@ fail:
+ return -ENOBUFS;
}
+static int nl80211_enable_amsdu(void *priv, u8 amsdu)
@@ -362,15 +362,15 @@
const struct wpa_driver_ops wpa_driver_nl80211_ops = {
.name = "nl80211",
.desc = "Linux nl80211/cfg80211",
-@@ -12959,4 +13071,6 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
+@@ -12930,4 +13042,6 @@ 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,
+ .amsdu_ctrl = nl80211_enable_amsdu,
+ .amsdu_dump = nl80211_dump_amsdu,
};
diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h
-index 607592ceb..e57022409 100644
+index 607592c..e570224 100644
--- a/src/drivers/driver_nl80211.h
+++ b/src/drivers/driver_nl80211.h
@@ -185,6 +185,7 @@ struct wpa_driver_nl80211_data {
@@ -382,7 +382,7 @@
u64 vendor_scan_cookie;
u64 remain_on_chan_cookie;
diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
-index 9ecc0ff9a..fcfa68bf7 100644
+index 9ecc0ff..fcfa68b 100644
--- a/src/drivers/driver_nl80211_capa.c
+++ b/src/drivers/driver_nl80211_capa.c
@@ -1065,6 +1065,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
@@ -396,5 +396,5 @@
}
--
-2.25.1
+2.18.0
diff --git a/recipes-wifi/hostapd/files/patches/mtk-0012-hostapd-mtk-Add-he_ldpc-configuration.patch b/recipes-wifi/hostapd/files/patches/mtk-0012-hostapd-mtk-Add-he_ldpc-configuration.patch
deleted file mode 100644
index 63101e0..0000000
--- a/recipes-wifi/hostapd/files/patches/mtk-0012-hostapd-mtk-Add-he_ldpc-configuration.patch
+++ /dev/null
@@ -1,102 +0,0 @@
-From b49ce922afa13fe8ea5d847753dfb7641b70c9a4 Mon Sep 17 00:00:00 2001
-From: MeiChia Chiu <meichia.chiu@mediatek.com>
-Date: Thu, 12 Jan 2023 15:18:19 +0800
-Subject: [PATCH 12/15] hostapd: mtk: Add he_ldpc configuration
-
----
- hostapd/config_file.c | 2 ++
- hostapd/hostapd.conf | 5 +++++
- src/ap/ap_config.c | 1 +
- src/ap/ap_config.h | 1 +
- src/ap/ieee802_11_he.c | 7 +++++++
- src/common/ieee802_11_defs.h | 3 +++
- 6 files changed, 19 insertions(+)
-
-diff --git a/hostapd/config_file.c b/hostapd/config_file.c
-index 10ea52518..4237a5cca 100644
---- a/hostapd/config_file.c
-+++ b/hostapd/config_file.c
-@@ -3508,6 +3508,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
- conf->he_phy_capab.he_su_beamformee = atoi(pos);
- } else if (os_strcmp(buf, "he_mu_beamformer") == 0) {
- conf->he_phy_capab.he_mu_beamformer = atoi(pos);
-+ } else if (os_strcmp(buf, "he_ldpc") == 0) {
-+ conf->he_phy_capab.he_ldpc = atoi(pos);
- } else if (os_strcmp(buf, "he_bss_color") == 0) {
- conf->he_op.he_bss_color = atoi(pos) & 0x3f;
- conf->he_op.he_bss_color_disabled = 0;
-diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
-index ea67aa100..e3a5eb365 100644
---- a/hostapd/hostapd.conf
-+++ b/hostapd/hostapd.conf
-@@ -830,6 +830,11 @@ wmm_ac_vo_acm=0
- # 1 = supported
- #he_mu_beamformer=1
-
-+#he_ldpc: HE LDPC support
-+# 0 = not supported
-+# 1 = supported (default)
-+#he_ldpc=1
-+
- # he_bss_color: BSS color (1-63)
- #he_bss_color=1
-
-diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
-index 85ad5e444..b283de624 100644
---- a/src/ap/ap_config.c
-+++ b/src/ap/ap_config.c
-@@ -268,6 +268,7 @@ struct hostapd_config * hostapd_config_defaults(void)
- #endif /* CONFIG_ACS */
-
- #ifdef CONFIG_IEEE80211AX
-+ conf->he_phy_capab.he_ldpc = 1;
- conf->he_op.he_rts_threshold = HE_OPERATION_RTS_THRESHOLD_MASK >>
- HE_OPERATION_RTS_THRESHOLD_OFFSET;
- /* Set default basic MCS/NSS set to single stream MCS 0-7 */
-diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
-index a9ac39619..b8b20a7aa 100644
---- a/src/ap/ap_config.h
-+++ b/src/ap/ap_config.h
-@@ -929,6 +929,7 @@ struct hostapd_bss_config {
- * struct he_phy_capabilities_info - HE PHY capabilities
- */
- struct he_phy_capabilities_info {
-+ bool he_ldpc;
- bool he_su_beamformer;
- bool he_su_beamformee;
- bool he_mu_beamformer;
-diff --git a/src/ap/ieee802_11_he.c b/src/ap/ieee802_11_he.c
-index b5b7e5d46..f27aeb196 100644
---- a/src/ap/ieee802_11_he.c
-+++ b/src/ap/ieee802_11_he.c
-@@ -138,6 +138,13 @@ u8 * hostapd_eid_he_capab(struct hostapd_data *hapd, u8 *eid,
- os_memcpy(&cap->optional[mcs_nss_size],
- mode->he_capab[opmode].ppet, ppet_size);
-
-+ if (hapd->iface->conf->he_phy_capab.he_ldpc)
-+ cap->he_phy_capab_info[HE_PHYCAP_LDPC_CODING_IN_PAYLOAD_IDX] |=
-+ HE_PHYCAP_LDPC_CODING_IN_PAYLOAD;
-+ else
-+ cap->he_phy_capab_info[HE_PHYCAP_LDPC_CODING_IN_PAYLOAD_IDX] &=
-+ ~HE_PHYCAP_LDPC_CODING_IN_PAYLOAD;
-+
- if (hapd->iface->conf->he_phy_capab.he_su_beamformer)
- cap->he_phy_capab_info[HE_PHYCAP_SU_BEAMFORMER_CAPAB_IDX] |=
- HE_PHYCAP_SU_BEAMFORMER_CAPAB;
-diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
-index 65e125e83..62088bda6 100644
---- a/src/common/ieee802_11_defs.h
-+++ b/src/common/ieee802_11_defs.h
-@@ -2298,6 +2298,9 @@ struct ieee80211_spatial_reuse {
- #define HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G ((u8) BIT(3))
- #define HE_PHYCAP_CHANNEL_WIDTH_SET_80PLUS80MHZ_IN_5G ((u8) BIT(4))
-
-+#define HE_PHYCAP_LDPC_CODING_IN_PAYLOAD_IDX 1
-+#define HE_PHYCAP_LDPC_CODING_IN_PAYLOAD ((u8) BIT(5))
-+
- #define HE_PHYCAP_SU_BEAMFORMER_CAPAB_IDX 3
- #define HE_PHYCAP_SU_BEAMFORMER_CAPAB ((u8) BIT(7))
- #define HE_PHYCAP_SU_BEAMFORMEE_CAPAB_IDX 4
---
-2.25.1
-
diff --git a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0012-hostapd-mtk-Add-he_ldpc-configuration.patch b/recipes-wifi/hostapd/files/patches/mtk-0013-hostapd-mtk-Add-he_ldpc-configuration.patch
similarity index 90%
copy from recipes-wifi/hostapd/files/patches-2.10.3/mtk-0012-hostapd-mtk-Add-he_ldpc-configuration.patch
copy to recipes-wifi/hostapd/files/patches/mtk-0013-hostapd-mtk-Add-he_ldpc-configuration.patch
index 63101e0..4df0ba6 100644
--- a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0012-hostapd-mtk-Add-he_ldpc-configuration.patch
+++ b/recipes-wifi/hostapd/files/patches/mtk-0013-hostapd-mtk-Add-he_ldpc-configuration.patch
@@ -1,7 +1,7 @@
-From b49ce922afa13fe8ea5d847753dfb7641b70c9a4 Mon Sep 17 00:00:00 2001
+From ebbf23ac8c19224b34523e8b9820e32f0789fe11 Mon Sep 17 00:00:00 2001
From: MeiChia Chiu <meichia.chiu@mediatek.com>
Date: Thu, 12 Jan 2023 15:18:19 +0800
-Subject: [PATCH 12/15] hostapd: mtk: Add he_ldpc configuration
+Subject: [PATCH 13/16] hostapd: mtk: Add he_ldpc configuration
---
hostapd/config_file.c | 2 ++
@@ -13,7 +13,7 @@
6 files changed, 19 insertions(+)
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
-index 10ea52518..4237a5cca 100644
+index 10ea525..4237a5c 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -3508,6 +3508,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
@@ -26,7 +26,7 @@
conf->he_op.he_bss_color = atoi(pos) & 0x3f;
conf->he_op.he_bss_color_disabled = 0;
diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
-index ea67aa100..e3a5eb365 100644
+index ea67aa1..e3a5eb3 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -830,6 +830,11 @@ wmm_ac_vo_acm=0
@@ -42,7 +42,7 @@
#he_bss_color=1
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
-index 85ad5e444..b283de624 100644
+index 85ad5e4..b283de6 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -268,6 +268,7 @@ struct hostapd_config * hostapd_config_defaults(void)
@@ -54,7 +54,7 @@
HE_OPERATION_RTS_THRESHOLD_OFFSET;
/* Set default basic MCS/NSS set to single stream MCS 0-7 */
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
-index a9ac39619..b8b20a7aa 100644
+index a9ac396..b8b20a7 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -929,6 +929,7 @@ struct hostapd_bss_config {
@@ -66,7 +66,7 @@
bool he_su_beamformee;
bool he_mu_beamformer;
diff --git a/src/ap/ieee802_11_he.c b/src/ap/ieee802_11_he.c
-index b5b7e5d46..f27aeb196 100644
+index b5b7e5d..f27aeb1 100644
--- a/src/ap/ieee802_11_he.c
+++ b/src/ap/ieee802_11_he.c
@@ -138,6 +138,13 @@ u8 * hostapd_eid_he_capab(struct hostapd_data *hapd, u8 *eid,
@@ -84,7 +84,7 @@
cap->he_phy_capab_info[HE_PHYCAP_SU_BEAMFORMER_CAPAB_IDX] |=
HE_PHYCAP_SU_BEAMFORMER_CAPAB;
diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
-index 65e125e83..62088bda6 100644
+index 65e125e..62088bd 100644
--- a/src/common/ieee802_11_defs.h
+++ b/src/common/ieee802_11_defs.h
@@ -2298,6 +2298,9 @@ struct ieee80211_spatial_reuse {
@@ -98,5 +98,5 @@
#define HE_PHYCAP_SU_BEAMFORMER_CAPAB ((u8) BIT(7))
#define HE_PHYCAP_SU_BEAMFORMEE_CAPAB_IDX 4
--
-2.25.1
+2.18.0
diff --git a/recipes-wifi/hostapd/files/patches/mtk-0013-hostapd-mtk-Add-the-broadcast-destination-address-of.patch b/recipes-wifi/hostapd/files/patches/mtk-0013-hostapd-mtk-Add-the-broadcast-destination-address-of.patch
deleted file mode 100644
index 1222510..0000000
--- a/recipes-wifi/hostapd/files/patches/mtk-0013-hostapd-mtk-Add-the-broadcast-destination-address-of.patch
+++ /dev/null
@@ -1,43 +0,0 @@
-From 52a1775318c9926a1dbf4f7c563e95b5be3c9bd6 Mon Sep 17 00:00:00 2001
-From: MeiChia Chiu <meichia.chiu@mediatek.com>
-Date: Tue, 17 Jan 2023 13:25:18 +0800
-Subject: [PATCH 13/15] hostapd: mtk: Add the broadcast destination address of
- Probe Response frame on 6 GHz
-
-According to IEEE 802.11ax 26.17.2.3.2,
-if a 6 GHz AP receives a Probe Request frame and responds with a Probe Response frame,
-the Address 1 field of the Probe Response frame shall be set to the broadcast address,
-unless the AP is not indicating its actual SSID in the SSID element of its Beacon frames.
-
-Without this, hostapd fill the Address 1 feild of the Probe Response frame
-with the source address from Probe Request frame on 6 GHz.
-Fix this to use broadcast address instead.
-
-Signed-off-by: MeiChia Chiu <meichia.chiu@mediatek.com>
----
- src/ap/beacon.c | 9 +++++++--
- 1 file changed, 7 insertions(+), 2 deletions(-)
-
-diff --git a/src/ap/beacon.c b/src/ap/beacon.c
-index 1a26f11ff..f3ea5c277 100644
---- a/src/ap/beacon.c
-+++ b/src/ap/beacon.c
-@@ -1156,8 +1156,13 @@ void handle_probe_req(struct hostapd_data *hapd,
- wpa_msg_ctrl(hapd->msg_ctx, MSG_INFO, RX_PROBE_REQUEST "sa=" MACSTR
- " signal=%d", MAC2STR(mgmt->sa), ssi_signal);
-
-- resp = hostapd_gen_probe_resp(hapd, mgmt, elems.p2p != NULL,
-- &resp_len, false);
-+ if (is_6ghz_op_class(hapd->iconf->op_class) &&
-+ is_broadcast_ether_addr(mgmt->da))
-+ resp = hostapd_gen_probe_resp(hapd, NULL, elems.p2p != NULL,
-+ &resp_len, true);
-+ else
-+ resp = hostapd_gen_probe_resp(hapd, mgmt, elems.p2p != NULL,
-+ &resp_len, false);
- if (resp == NULL)
- return;
-
---
-2.25.1
-
diff --git a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0013-hostapd-mtk-Add-the-broadcast-destination-address-of.patch b/recipes-wifi/hostapd/files/patches/mtk-0014-hostapd-mtk-Add-the-broadcast-destination-address-of.patch
similarity index 89%
copy from recipes-wifi/hostapd/files/patches-2.10.3/mtk-0013-hostapd-mtk-Add-the-broadcast-destination-address-of.patch
copy to recipes-wifi/hostapd/files/patches/mtk-0014-hostapd-mtk-Add-the-broadcast-destination-address-of.patch
index 1222510..f0d25c6 100644
--- a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0013-hostapd-mtk-Add-the-broadcast-destination-address-of.patch
+++ b/recipes-wifi/hostapd/files/patches/mtk-0014-hostapd-mtk-Add-the-broadcast-destination-address-of.patch
@@ -1,7 +1,7 @@
-From 52a1775318c9926a1dbf4f7c563e95b5be3c9bd6 Mon Sep 17 00:00:00 2001
+From bb5cb086162828392a04820063ad7997d8ae26d7 Mon Sep 17 00:00:00 2001
From: MeiChia Chiu <meichia.chiu@mediatek.com>
Date: Tue, 17 Jan 2023 13:25:18 +0800
-Subject: [PATCH 13/15] hostapd: mtk: Add the broadcast destination address of
+Subject: [PATCH 14/16] hostapd: mtk: Add the broadcast destination address of
Probe Response frame on 6 GHz
According to IEEE 802.11ax 26.17.2.3.2,
@@ -19,7 +19,7 @@
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/src/ap/beacon.c b/src/ap/beacon.c
-index 1a26f11ff..f3ea5c277 100644
+index 1a26f11..f3ea5c2 100644
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -1156,8 +1156,13 @@ void handle_probe_req(struct hostapd_data *hapd,
@@ -39,5 +39,5 @@
return;
--
-2.25.1
+2.18.0
diff --git a/recipes-wifi/hostapd/files/patches/mtk-0014-hostapd-mtk-Add-vendor-command-attribute-for-RTS-BW-.patch b/recipes-wifi/hostapd/files/patches/mtk-0014-hostapd-mtk-Add-vendor-command-attribute-for-RTS-BW-.patch
deleted file mode 100644
index 3689f74..0000000
--- a/recipes-wifi/hostapd/files/patches/mtk-0014-hostapd-mtk-Add-vendor-command-attribute-for-RTS-BW-.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-From 7d741c99f2e211abe70593ff6e8265633bed0d8a Mon Sep 17 00:00:00 2001
-From: "himanshu.goyal" <himanshu.goyal@mediatek.com>
-Date: Tue, 24 Jan 2023 19:06:44 +0800
-Subject: [PATCH 14/15] hostapd: mtk: Add vendor command attribute for RTS BW
- signaling.
-
-Signed-off-by: himanshu.goyal <himanshu.goyal@mediatek.com>
----
- src/common/mtk_vendor.h | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/src/common/mtk_vendor.h b/src/common/mtk_vendor.h
-index 0999ea9e2..fb12895ce 100644
---- a/src/common/mtk_vendor.h
-+++ b/src/common/mtk_vendor.h
-@@ -169,6 +169,7 @@ enum mtk_vendor_attr_wireless_ctrl {
- MTK_VENDOR_ATTR_WIRELESS_CTRL_MIMO,
- MTK_VENDOR_ATTR_WIRELESS_CTRL_AMSDU,
- MTK_VENDOR_ATTR_WIRELESS_CTRL_CERT,
-+ MTK_VENDOR_ATTR_WIRELESS_CTRL_RTS_SIGTA,
-
- /* keep last */
- NUM_MTK_VENDOR_ATTRS_WIRELESS_CTRL,
---
-2.25.1
-
diff --git a/recipes-wifi/hostapd/files/patches/mtk-0015-hostapd-mtk-6G-band-does-not-require-DFS.patch b/recipes-wifi/hostapd/files/patches/mtk-0015-hostapd-mtk-6G-band-does-not-require-DFS.patch
deleted file mode 100644
index 642c625..0000000
--- a/recipes-wifi/hostapd/files/patches/mtk-0015-hostapd-mtk-6G-band-does-not-require-DFS.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-From 619075bb430c908c61a818c45e36f1ca76020741 Mon Sep 17 00:00:00 2001
-From: Peter Chiu <chui-hao.chiu@mediatek.com>
-Date: Mon, 13 Feb 2023 11:03:53 +0800
-Subject: [PATCH 15/15] hostapd: mtk: 6G band does not require DFS
-
----
- src/ap/dfs.c | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/src/ap/dfs.c b/src/ap/dfs.c
-index 1c3f6785b..4b1e64246 100644
---- a/src/ap/dfs.c
-+++ b/src/ap/dfs.c
-@@ -1506,6 +1506,7 @@ int hostapd_is_dfs_required(struct hostapd_iface *iface)
- if ((!(iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) &&
- !iface->conf->ieee80211h) ||
- !iface->current_mode ||
-+ is_6ghz_freq(iface->freq) ||
- iface->current_mode->mode != HOSTAPD_MODE_IEEE80211A)
- return 0;
-
---
-2.25.1
-
diff --git a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0014-hostapd-mtk-Add-vendor-command-attribute-for-RTS-BW-.patch b/recipes-wifi/hostapd/files/patches/mtk-0015-hostapd-mtk-Add-vendor-command-attribute-for-RTS-BW-.patch
similarity index 79%
copy from recipes-wifi/hostapd/files/patches-2.10.3/mtk-0014-hostapd-mtk-Add-vendor-command-attribute-for-RTS-BW-.patch
copy to recipes-wifi/hostapd/files/patches/mtk-0015-hostapd-mtk-Add-vendor-command-attribute-for-RTS-BW-.patch
index 3689f74..5fcd0c5 100644
--- a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0014-hostapd-mtk-Add-vendor-command-attribute-for-RTS-BW-.patch
+++ b/recipes-wifi/hostapd/files/patches/mtk-0015-hostapd-mtk-Add-vendor-command-attribute-for-RTS-BW-.patch
@@ -1,7 +1,7 @@
-From 7d741c99f2e211abe70593ff6e8265633bed0d8a Mon Sep 17 00:00:00 2001
+From 1db373190399a907b27141c199841aeafd4643da Mon Sep 17 00:00:00 2001
From: "himanshu.goyal" <himanshu.goyal@mediatek.com>
Date: Tue, 24 Jan 2023 19:06:44 +0800
-Subject: [PATCH 14/15] hostapd: mtk: Add vendor command attribute for RTS BW
+Subject: [PATCH 15/16] hostapd: mtk: Add vendor command attribute for RTS BW
signaling.
Signed-off-by: himanshu.goyal <himanshu.goyal@mediatek.com>
@@ -10,7 +10,7 @@
1 file changed, 1 insertion(+)
diff --git a/src/common/mtk_vendor.h b/src/common/mtk_vendor.h
-index 0999ea9e2..fb12895ce 100644
+index 0999ea9..fb12895 100644
--- a/src/common/mtk_vendor.h
+++ b/src/common/mtk_vendor.h
@@ -169,6 +169,7 @@ enum mtk_vendor_attr_wireless_ctrl {
@@ -22,5 +22,5 @@
/* keep last */
NUM_MTK_VENDOR_ATTRS_WIRELESS_CTRL,
--
-2.25.1
+2.18.0
diff --git a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0015-hostapd-mtk-6G-band-does-not-require-DFS.patch b/recipes-wifi/hostapd/files/patches/mtk-0016-hostapd-mtk-6G-band-does-not-require-DFS.patch
similarity index 76%
copy from recipes-wifi/hostapd/files/patches-2.10.3/mtk-0015-hostapd-mtk-6G-band-does-not-require-DFS.patch
copy to recipes-wifi/hostapd/files/patches/mtk-0016-hostapd-mtk-6G-band-does-not-require-DFS.patch
index 642c625..33fea78 100644
--- a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0015-hostapd-mtk-6G-band-does-not-require-DFS.patch
+++ b/recipes-wifi/hostapd/files/patches/mtk-0016-hostapd-mtk-6G-band-does-not-require-DFS.patch
@@ -1,14 +1,14 @@
-From 619075bb430c908c61a818c45e36f1ca76020741 Mon Sep 17 00:00:00 2001
+From efa1d271d28c84b8ca77ffc3ca7cb75e727088a0 Mon Sep 17 00:00:00 2001
From: Peter Chiu <chui-hao.chiu@mediatek.com>
Date: Mon, 13 Feb 2023 11:03:53 +0800
-Subject: [PATCH 15/15] hostapd: mtk: 6G band does not require DFS
+Subject: [PATCH 16/16] hostapd: mtk: 6G band does not require DFS
---
src/ap/dfs.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/ap/dfs.c b/src/ap/dfs.c
-index 1c3f6785b..4b1e64246 100644
+index 1c3f678..4b1e642 100644
--- a/src/ap/dfs.c
+++ b/src/ap/dfs.c
@@ -1506,6 +1506,7 @@ int hostapd_is_dfs_required(struct hostapd_iface *iface)
@@ -20,5 +20,5 @@
return 0;
--
-2.25.1
+2.18.0
diff --git a/recipes-wifi/hostapd/files/patches/mtk-0016-hostapd-mtk-Add-available-color-bitmap.patch b/recipes-wifi/hostapd/files/patches/mtk-0016-hostapd-mtk-Add-available-color-bitmap.patch
new file mode 100644
index 0000000..9bbbf87
--- /dev/null
+++ b/recipes-wifi/hostapd/files/patches/mtk-0016-hostapd-mtk-Add-available-color-bitmap.patch
@@ -0,0 +1,337 @@
+From e7790a1bceca6b7612f29b00c429cf23f5dd9e3a Mon Sep 17 00:00:00 2001
+From: Yi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
+Date: Thu, 26 Jan 2023 09:16:00 +0800
+Subject: [PATCH] hostapd: mtk: Add available color bitmap
+
+Signed-off-by: Yi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
+---
+ hostapd/ctrl_iface.c | 74 +++++++++++++++++++++++++++++++
+ hostapd/hostapd_cli.c | 18 ++++++++
+ src/ap/ap_drv_ops.c | 10 ++++-
+ src/ap/ap_drv_ops.h | 2 +
+ src/common/mtk_vendor.h | 11 +++++
+ src/drivers/driver.h | 8 ++++
+ src/drivers/driver_nl80211.c | 66 +++++++++++++++++++++++++++
+ src/drivers/driver_nl80211.h | 1 +
+ src/drivers/driver_nl80211_capa.c | 3 ++
+ 9 files changed, 192 insertions(+), 1 deletion(-)
+
+diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
+index 0ad8451..b0d5ded 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -3635,6 +3635,76 @@ hostapd_ctrl_iface_get_amsdu(struct hostapd_data *hapd, char *buf,
+ return ret;
+ }
+
++static int
++hostapd_ctrl_iface_get_bss_color(struct hostapd_data *hapd, char *buf,
++ size_t buflen)
++{
++ int ret;
++ char *pos, *end;
++ int i;
++
++ pos = buf;
++ end = buf + buflen;
++
++ if (hapd->iface->conf->he_op.he_bss_color_disabled)
++ ret = os_snprintf(buf, buflen, "BSS Color disabled\n");
++ else
++ ret = os_snprintf(buf, buflen, "BSS Color=%u\n",
++ hapd->iface->conf->he_op.he_bss_color);
++
++ pos += ret;
++
++ return pos - buf;
++}
++
++
++static int
++hostapd_ctrl_iface_get_aval_color_bmp(struct hostapd_data *hapd, char *buf,
++ size_t buflen)
++{
++ int ret;
++ char *pos, *end;
++ int i;
++ u64 aval_color_bmp = 0;
++
++ hostapd_drv_get_aval_bss_color_bmp(hapd, &aval_color_bmp);
++ hapd->color_collision_bitmap = ~aval_color_bmp;
++
++ pos = buf;
++ end = buf + buflen;
++
++ ret = os_snprintf(buf, buflen,
++ "available color bitmap=0x%llx\n",
++ aval_color_bmp);
++ if (os_snprintf_error(end - pos, ret))
++ return pos - buf;
++ pos += ret;
++
++ for (i = 0; i < HE_OPERATION_BSS_COLOR_MAX; i++) {
++ int bit = !!((aval_color_bmp >> i) & 1LLU);
++
++ if (i % 8 == 0) {
++ ret = os_snprintf(pos, end - pos, "%2d: ", i);
++ if (os_snprintf_error(end - pos, ret))
++ return pos - buf;
++ pos += ret;
++ }
++
++ ret = os_snprintf(pos, end - pos, "%d ", bit);
++ if (os_snprintf_error(end - pos, ret))
++ return pos - buf;
++ pos += ret;
++
++ if (i % 8 == 7) {
++ ret = os_snprintf(pos, end - pos, "\n");
++ if (os_snprintf_error(end - pos, ret))
++ return pos - buf;
++ pos += ret;
++ }
++ }
++ return pos - buf;
++}
++
+
+ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
+ char *buf, char *reply,
+@@ -4202,6 +4272,10 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
+ reply_len = hostapd_ctrl_iface_set_offchan_ctrl(hapd, buf + 16, reply, reply_size);
+ } else if (os_strncmp(buf, "GET_AMSDU", 9) == 0) {
+ reply_len = hostapd_ctrl_iface_get_amsdu(hapd, reply, reply_size);
++ } else if (os_strncmp(buf, "GET_BSS_COLOR", 13) == 0) {
++ reply_len = hostapd_ctrl_iface_get_bss_color(hapd, reply, reply_size);
++ } else if (os_strncmp(buf, "AVAL_COLOR_BMP", 14) == 0) {
++ reply_len = hostapd_ctrl_iface_get_aval_color_bmp(hapd, reply, reply_size);
+ } else {
+ os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
+ reply_len = 16;
+diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
+index 30b3392..b6cf52e 100644
+--- a/hostapd/hostapd_cli.c
++++ b/hostapd/hostapd_cli.c
+@@ -1578,6 +1578,20 @@ static int hostapd_cli_cmd_reload_wpa_psk(struct wpa_ctrl *ctrl, int argc,
+ }
+
+
++static int hostapd_cli_cmd_get_bss_color(struct wpa_ctrl *ctrl, int argc,
++ char *argv[])
++{
++ return wpa_ctrl_command(ctrl, "GET_BSS_COLOR");
++}
++
++
++static int hostapd_cli_cmd_get_aval_color_bmp(struct wpa_ctrl *ctrl, int argc,
++ char *argv[])
++{
++ return wpa_ctrl_command(ctrl, "AVAL_COLOR_BMP");
++}
++
++
+ #ifdef ANDROID
+ static int hostapd_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[])
+ {
+@@ -1795,6 +1809,10 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
+ "<addr> [req_mode=] <measurement request hexdump> = send a Beacon report request to a station" },
+ { "reload_wpa_psk", hostapd_cli_cmd_reload_wpa_psk, NULL,
+ "= reload wpa_psk_file only" },
++ { "get_bss_color", hostapd_cli_cmd_get_bss_color, NULL,
++ "= get current BSS color" },
++ { "get_color_bmp", hostapd_cli_cmd_get_aval_color_bmp, NULL,
++ "= get available BSS color bitmap" },
+ #ifdef ANDROID
+ { "driver", hostapd_cli_cmd_driver, NULL,
+ "<driver sub command> [<hex formatted data>] = send driver command data" },
+diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
+index 1a82f23..decffdd 100644
+--- a/src/ap/ap_drv_ops.c
++++ b/src/ap/ap_drv_ops.c
+@@ -1091,4 +1091,12 @@ int hostapd_drv_amsdu_dump(struct hostapd_data *hapd, u8 *amsdu)
+ if (!hapd->driver || !hapd->driver->amsdu_dump)
+ return 0;
+ return hapd->driver->amsdu_dump(hapd->drv_priv, amsdu);
+-}
+\ No newline at end of file
++}
++
++int hostapd_drv_get_aval_bss_color_bmp(struct hostapd_data *hapd, u64 *aval_color_bmp)
++{
++ if (!hapd->driver || !hapd->driver->get_aval_color_bmp ||
++ hapd->iface->conf->he_op.he_bss_color_disabled)
++ return 0;
++ return hapd->driver->get_aval_color_bmp(hapd->drv_priv, aval_color_bmp);
++}
+diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
+index 4406666..61c1360 100644
+--- a/src/ap/ap_drv_ops.h
++++ b/src/ap/ap_drv_ops.h
+@@ -149,6 +149,8 @@ int hostapd_drv_ibf_ctrl(struct hostapd_data *hapd);
+ int hostapd_drv_ibf_dump(struct hostapd_data *hapd, u8 *ibf_enable);
+ int hostapd_drv_amsdu_ctrl(struct hostapd_data *hapd);
+ int hostapd_drv_amsdu_dump(struct hostapd_data *hapd, u8 *amsdu);
++int hostapd_drv_get_aval_bss_color_bmp(struct hostapd_data *hapd,
++ u64 *aval_color_bmp);
+
+ #include "drivers/driver.h"
+
+diff --git a/src/common/mtk_vendor.h b/src/common/mtk_vendor.h
+index 0999ea9..f2afb2e 100644
+--- a/src/common/mtk_vendor.h
++++ b/src/common/mtk_vendor.h
+@@ -15,6 +15,7 @@ enum mtk_nl80211_vendor_subcmds {
+ MTK_NL80211_VENDOR_SUBCMD_EDCCA_CTRL = 0xc7,
+ MTK_NL80211_VENDOR_SUBCMD_3WIRE_CTRL = 0xc8,
+ MTK_NL80211_VENDOR_SUBCMD_IBF_CTRL = 0xc9,
++ MTK_NL80211_VENDOR_SUBCMD_BSS_COLOR_CTRL = 0xca,
+ };
+
+ enum mtk_vendor_attr_edcca_ctrl {
+@@ -252,6 +253,16 @@ ibf_dump_policy[NUM_MTK_VENDOR_ATTRS_IBF_DUMP] = {
+ [MTK_VENDOR_ATTR_IBF_DUMP_ENABLE] = { .type = NLA_U8 },
+ };
+
++enum mtk_vendor_attr_bss_color_ctrl {
++ MTK_VENDOR_ATTR_BSS_COLOR_CTRL_UNSPEC,
++
++ MTK_VENDOR_ATTR_AVAL_BSS_COLOR_BMP,
++
++ /* keep last */
++ NUM_MTK_VENDOR_ATTRS_BSS_COLOR_CTRL,
++ MTK_VENDOR_ATTR_BSS_COLOR_CTRL_MAX =
++ NUM_MTK_VENDOR_ATTRS_BSS_COLOR_CTRL - 1
++};
+
+ #define CSI_MAX_COUNT 256
+ #define ETH_ALEN 6
+diff --git a/src/drivers/driver.h b/src/drivers/driver.h
+index b07aaf3..266c630 100644
+--- a/src/drivers/driver.h
++++ b/src/drivers/driver.h
+@@ -4736,6 +4736,14 @@ struct wpa_driver_ops {
+ */
+ int (*amsdu_ctrl)(void *priv, u8 amsdu);
+ int (*amsdu_dump)(void *priv, u8 *amsdu);
++
++ /**
++ * get_aval_color_bmp - get available BSS color bitmap
++ * @priv: Private driver interface data
++ * @aval_color_bmp: available bss color bitmap
++ *
++ */
++ int (*get_aval_color_bmp)(void *priv, u64 *aval_color_bmp);
+ };
+
+ /**
+diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
+index 6702384..c8771f7 100644
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -12433,6 +12433,71 @@ static int nl80211_dpp_listen(void *priv, bool enable)
+ }
+ #endif /* CONFIG_DPP */
+
++static int nl80211_get_aval_color_bmp_handler(struct nl_msg *msg, void *arg)
++{
++ u64 *aval_color_bmp = arg;
++ struct nlattr *tb[NL80211_ATTR_MAX + 1];
++ struct nlattr *tb_vendor[MTK_VENDOR_ATTR_BSS_COLOR_CTRL_MAX + 1];
++ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
++ struct nlattr *nl_vend, *attr;
++
++ static const struct nla_policy
++ bss_color_ctrl_policy[NUM_MTK_VENDOR_ATTRS_BSS_COLOR_CTRL + 1] = {
++ [MTK_VENDOR_ATTR_AVAL_BSS_COLOR_BMP] = { .type = NLA_U64 },
++ };
++
++ nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
++ genlmsg_attrlen(gnlh, 0), NULL);
++
++ nl_vend = tb[NL80211_ATTR_VENDOR_DATA];
++ if (!nl_vend)
++ return NL_SKIP;
++
++ nla_parse(tb_vendor, MTK_VENDOR_ATTR_BSS_COLOR_CTRL_MAX,
++ nla_data(nl_vend), nla_len(nl_vend), NULL);
++
++ *aval_color_bmp = nla_get_u64(tb_vendor[MTK_VENDOR_ATTR_AVAL_BSS_COLOR_BMP]);
++
++ return 0;
++}
++
++static int nl80211_get_aval_color_bmp(void *priv, u64 *aval_color_bmp)
++{
++ struct i802_bss *bss = priv;
++ struct wpa_driver_nl80211_data *drv = bss->drv;
++ struct nl_msg *msg;
++ struct nlattr *attr;
++ int ret;
++
++ if (!drv->mtk_bss_color_vendor_cmd_avail) {
++ wpa_printf(MSG_INFO,
++ "nl80211: Driver does not support BSS COLOR vendor cmd");
++ return 0;
++ }
++
++ if (!(msg = nl80211_drv_msg(drv, NLM_F_DUMP, NL80211_CMD_VENDOR)) ||
++ nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_MTK) ||
++ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
++ MTK_NL80211_VENDOR_SUBCMD_BSS_COLOR_CTRL))
++ return -ENOBUFS;
++
++ attr = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
++ if (!attr) {
++ nlmsg_free(msg);
++ return -1;
++ }
++
++ nla_nest_end(msg, attr);
++
++ ret = send_and_recv_msgs(drv, msg,
++ nl80211_get_aval_color_bmp_handler, aval_color_bmp, NULL, NULL);
++
++ if (ret) {
++ wpa_printf(MSG_ERROR, "Failed to send BSS COLOR vendor cmd. ret=%d (%s) ",
++ ret, strerror(-ret));
++ }
++ return ret;
++}
+
+ #ifdef CONFIG_TESTING_OPTIONS
+
+@@ -13073,4 +13138,5 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
+ .start_disabled = nl80211_start_disabled,
+ .amsdu_ctrl = nl80211_enable_amsdu,
+ .amsdu_dump = nl80211_dump_amsdu,
++ .get_aval_color_bmp = nl80211_get_aval_color_bmp,
+ };
+diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h
+index e570224..b90c8fa 100644
+--- a/src/drivers/driver_nl80211.h
++++ b/src/drivers/driver_nl80211.h
+@@ -186,6 +186,7 @@ struct wpa_driver_nl80211_data {
+ unsigned int mtk_3wire_vendor_cmd_avail:1;
+ unsigned int mtk_ibf_vendor_cmd_avail:1;
+ unsigned int mtk_wireless_vendor_cmd_avail:1;
++ unsigned int mtk_bss_color_vendor_cmd_avail:1;
+
+ u64 vendor_scan_cookie;
+ u64 remain_on_chan_cookie;
+diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
+index fcfa68b..c3c7b41 100644
+--- a/src/drivers/driver_nl80211_capa.c
++++ b/src/drivers/driver_nl80211_capa.c
+@@ -1068,6 +1068,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
+ case MTK_NL80211_VENDOR_SUBCMD_WIRELESS_CTRL:
+ drv->mtk_wireless_vendor_cmd_avail = 1;
+ break;
++ case MTK_NL80211_VENDOR_SUBCMD_BSS_COLOR_CTRL :
++ drv->mtk_bss_color_vendor_cmd_avail = 1;
++ break;
+ }
+ }
+
+--
+2.39.0
+
diff --git a/recipes-wifi/hostapd/files/patches/mtk-0017-hostapd-mtk-Fix-sending-wrong-VHT-operation-IE-in-CS.patch b/recipes-wifi/hostapd/files/patches/mtk-0017-hostapd-mtk-Fix-sending-wrong-VHT-operation-IE-in-CS.patch
new file mode 100644
index 0000000..265c37a
--- /dev/null
+++ b/recipes-wifi/hostapd/files/patches/mtk-0017-hostapd-mtk-Fix-sending-wrong-VHT-operation-IE-in-CS.patch
@@ -0,0 +1,46 @@
+From f6bfd9a4a6c0d08e0dec9311873c9e863a07c9a8 Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Mon, 20 Feb 2023 11:01:18 +0800
+Subject: [PATCH] hostapd: mtk: Fix sending wrong VHT operation IE in CSA while
+ using ZWDFS
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ src/ap/dfs.c | 14 +++++++++-----
+ 1 file changed, 9 insertions(+), 5 deletions(-)
+
+diff --git a/src/ap/dfs.c b/src/ap/dfs.c
+index 4b1e642..307a4e1 100644
+--- a/src/ap/dfs.c
++++ b/src/ap/dfs.c
+@@ -1110,6 +1110,14 @@ static int
+ hostapd_dfs_start_channel_switch_background(struct hostapd_iface *iface)
+ {
+ u8 current_vht_oper_chwidth = hostapd_get_oper_chwidth(iface->conf);
++ int ret;
++
++ ret = hostapd_dfs_request_channel_switch(iface, iface->radar_background.channel,
++ iface->radar_background.freq,
++ iface->radar_background.secondary_channel,
++ current_vht_oper_chwidth,
++ iface->radar_background.centr_freq_seg0_idx,
++ iface->radar_background.centr_freq_seg1_idx);
+
+ iface->conf->channel = iface->radar_background.channel;
+ iface->freq = iface->radar_background.freq;
+@@ -1122,11 +1130,7 @@ hostapd_dfs_start_channel_switch_background(struct hostapd_iface *iface)
+
+ hostpad_dfs_update_background_chain(iface);
+
+- return hostapd_dfs_request_channel_switch(
+- iface, iface->conf->channel, iface->freq,
+- iface->conf->secondary_channel, current_vht_oper_chwidth,
+- hostapd_get_oper_centr_freq_seg0_idx(iface->conf),
+- hostapd_get_oper_centr_freq_seg1_idx(iface->conf));
++ return ret;
+ }
+
+
+--
+2.18.0
+
diff --git a/recipes-wifi/hostapd/files/patches/mtk-0018-hostapd-mtk-Add-sta-assisted-DFS-state-update-mechan.patch b/recipes-wifi/hostapd/files/patches/mtk-0018-hostapd-mtk-Add-sta-assisted-DFS-state-update-mechan.patch
new file mode 100644
index 0000000..db3c813
--- /dev/null
+++ b/recipes-wifi/hostapd/files/patches/mtk-0018-hostapd-mtk-Add-sta-assisted-DFS-state-update-mechan.patch
@@ -0,0 +1,189 @@
+From 3337e7b4f75a66e53e1320e49deba2b58a8a80b0 Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Mon, 20 Feb 2023 10:51:47 +0800
+Subject: [PATCH 18/19] hostapd: mtk: Add sta-assisted DFS state update
+ mechanism
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ src/ap/dfs.c | 20 ++++++++++++++++++++
+ src/ap/dfs.h | 3 +++
+ src/ap/drv_callbacks.c | 28 ++++++++++++++++++++++++++++
+ src/common/wpa_ctrl.h | 1 +
+ src/drivers/driver.h | 14 ++++++++++++++
+ src/drivers/driver_nl80211_event.c | 6 ++++++
+ src/drivers/nl80211_copy.h | 6 ++++++
+ 7 files changed, 78 insertions(+)
+
+diff --git a/src/ap/dfs.c b/src/ap/dfs.c
+index 307a4e1..d082fe0 100644
+--- a/src/ap/dfs.c
++++ b/src/ap/dfs.c
+@@ -1503,6 +1503,26 @@ int hostapd_dfs_nop_finished(struct hostapd_iface *iface, int freq,
+ }
+
+
++int hostapd_dfs_sta_update_state(struct hostapd_iface *iface, int freq,
++ int ht_enabled, int chan_offset, int chan_width,
++ int cf1, int cf2, u32 state)
++{
++ wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_STA_UPDATE
++ "freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d state=%s",
++ freq, ht_enabled, chan_offset, chan_width, cf1, cf2,
++ (state == HOSTAPD_CHAN_DFS_AVAILABLE) ? "available" : "usable");
++
++ /* Proceed only if DFS is not offloaded to the driver */
++ if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD)
++ return 0;
++
++ set_dfs_state(iface, freq, ht_enabled, chan_offset, chan_width,
++ cf1, cf2, state);
++
++ return 0;
++}
++
++
+ int hostapd_is_dfs_required(struct hostapd_iface *iface)
+ {
+ int n_chans, n_chans1, start_chan_idx, start_chan_idx1, res;
+diff --git a/src/ap/dfs.h b/src/ap/dfs.h
+index c2556d2..25ba29c 100644
+--- a/src/ap/dfs.h
++++ b/src/ap/dfs.h
+@@ -30,6 +30,9 @@ int hostapd_dfs_radar_detected(struct hostapd_iface *iface, int freq,
+ int hostapd_dfs_nop_finished(struct hostapd_iface *iface, int freq,
+ int ht_enabled,
+ int chan_offset, int chan_width, int cf1, int cf2);
++int hostapd_dfs_sta_update_state(struct hostapd_iface *iface, int freq,
++ int ht_enabled, int chan_offset, int chan_width,
++ int cf1, int cf2, u32 state);
+ int hostapd_is_dfs_required(struct hostapd_iface *iface);
+ int hostapd_is_dfs_chan_available(struct hostapd_iface *iface);
+ int hostapd_dfs_start_cac(struct hostapd_iface *iface, int freq,
+diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
+index 09783cb..275f6b3 100644
+--- a/src/ap/drv_callbacks.c
++++ b/src/ap/drv_callbacks.c
+@@ -1790,6 +1790,24 @@ static void hostapd_event_dfs_cac_started(struct hostapd_data *hapd,
+ radar->cf1, radar->cf2);
+ }
+
++static void hostapd_event_dfs_sta_cac_skipped(struct hostapd_data *hapd,
++ struct dfs_event *radar)
++{
++ wpa_printf(MSG_DEBUG, "DFS CAC skipped (by STA) on %d MHz", radar->freq);
++ hostapd_dfs_sta_update_state(hapd->iface, radar->freq, radar->ht_enabled,
++ radar->chan_offset, radar->chan_width,
++ radar->cf1, radar->cf2, HOSTAPD_CHAN_DFS_AVAILABLE);
++}
++
++static void hostapd_event_dfs_sta_cac_expired(struct hostapd_data *hapd,
++ struct dfs_event *radar)
++{
++ wpa_printf(MSG_DEBUG, "DFS CAC expired (by STA) on %d MHz", radar->freq);
++ hostapd_dfs_sta_update_state(hapd->iface, radar->freq, radar->ht_enabled,
++ radar->chan_offset, radar->chan_width,
++ radar->cf1, radar->cf2, HOSTAPD_CHAN_DFS_USABLE);
++}
++
+ #endif /* NEED_AP_MLME */
+
+
+@@ -2064,6 +2082,16 @@ void hostapd_wpa_event(void *ctx, enum wpa_event_type event,
+ break;
+ hostapd_event_dfs_nop_finished(hapd, &data->dfs_event);
+ break;
++ case EVENT_DFS_STA_CAC_SKIPPED:
++ if (!data)
++ break;
++ hostapd_event_dfs_sta_cac_skipped(hapd, &data->dfs_event);
++ break;
++ case EVENT_DFS_STA_CAC_EXPIRED:
++ if (!data)
++ break;
++ hostapd_event_dfs_sta_cac_expired(hapd, &data->dfs_event);
++ break;
+ case EVENT_CHANNEL_LIST_CHANGED:
+ /* channel list changed (regulatory?), update channel list */
+ /* TODO: check this. hostapd_get_hw_features() initializes
+diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h
+index 3435084..79c8a82 100644
+--- a/src/common/wpa_ctrl.h
++++ b/src/common/wpa_ctrl.h
+@@ -360,6 +360,7 @@ extern "C" {
+ #define DFS_EVENT_CAC_COMPLETED "DFS-CAC-COMPLETED "
+ #define DFS_EVENT_NOP_FINISHED "DFS-NOP-FINISHED "
+ #define DFS_EVENT_PRE_CAC_EXPIRED "DFS-PRE-CAC-EXPIRED "
++#define DFS_EVENT_STA_UPDATE "DFS-STA-UPDATE "
+
+ #define AP_CSA_FINISHED "AP-CSA-FINISHED "
+
+diff --git a/src/drivers/driver.h b/src/drivers/driver.h
+index 265d86d..b5de0e6 100644
+--- a/src/drivers/driver.h
++++ b/src/drivers/driver.h
+@@ -5317,6 +5317,20 @@ enum wpa_event_type {
+ * EVENT_CCA_NOTIFY - Notification that CCA has completed
+ */
+ EVENT_CCA_NOTIFY,
++
++ /**
++ * EVENT_DFS_STA_CAC_SKIPPED - Notification that CAC has been skipped
++ *
++ * The channel in the notification is now marked as available.
++ */
++ EVENT_DFS_STA_CAC_SKIPPED,
++
++ /**
++ * EVENT_DFS_STA_CAC_EXPIRED - Notification that CAC has expired
++ *
++ * The channel in the notification is now marked as usable.
++ */
++ EVENT_DFS_STA_CAC_EXPIRED,
+ };
+
+
+diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c
+index 73bb7a4..ee922ac 100644
+--- a/src/drivers/driver_nl80211_event.c
++++ b/src/drivers/driver_nl80211_event.c
+@@ -1854,6 +1854,12 @@ static void nl80211_radar_event(struct wpa_driver_nl80211_data *drv,
+ case NL80211_RADAR_CAC_STARTED:
+ wpa_supplicant_event(drv->ctx, EVENT_DFS_CAC_STARTED, &data);
+ break;
++ case NL80211_RADAR_STA_CAC_SKIPPED:
++ wpa_supplicant_event(drv->ctx, EVENT_DFS_STA_CAC_SKIPPED, &data);
++ break;
++ case NL80211_RADAR_STA_CAC_EXPIRED:
++ wpa_supplicant_event(drv->ctx, EVENT_DFS_STA_CAC_EXPIRED, &data);
++ break;
+ default:
+ wpa_printf(MSG_DEBUG, "nl80211: Unknown radar event %d "
+ "received", event_type);
+diff --git a/src/drivers/nl80211_copy.h b/src/drivers/nl80211_copy.h
+index c4bf3ad..0937752 100644
+--- a/src/drivers/nl80211_copy.h
++++ b/src/drivers/nl80211_copy.h
+@@ -6431,6 +6431,10 @@ enum nl80211_smps_mode {
+ * applicable for ETSI dfs domain where pre-CAC is valid for ever.
+ * @NL80211_RADAR_CAC_STARTED: Channel Availability Check has been started,
+ * should be generated by HW if NL80211_EXT_FEATURE_DFS_OFFLOAD is enabled.
++ * @NL80211_RADAR_STA_CAC_SKIPPED: STA set the DFS state to available
++ * when receiving CSA/assoc resp
++ * @NL80211_RADAR_STA_CAC_EXPIRED: STA set the DFS state to usable
++ * when STA is disconnected or leaving the channel
+ */
+ enum nl80211_radar_event {
+ NL80211_RADAR_DETECTED,
+@@ -6439,6 +6443,8 @@ enum nl80211_radar_event {
+ NL80211_RADAR_NOP_FINISHED,
+ NL80211_RADAR_PRE_CAC_EXPIRED,
+ NL80211_RADAR_CAC_STARTED,
++ NL80211_RADAR_STA_CAC_SKIPPED,
++ NL80211_RADAR_STA_CAC_EXPIRED,
+ };
+
+ /**
+--
+2.18.0
+
diff --git a/recipes-wifi/hostapd/files/patches/mtk-0019-hostapd-mtk-Fix-auto-ht-issue-when-switching-to-DFS-.patch b/recipes-wifi/hostapd/files/patches/mtk-0019-hostapd-mtk-Fix-auto-ht-issue-when-switching-to-DFS-.patch
new file mode 100644
index 0000000..8340fd9
--- /dev/null
+++ b/recipes-wifi/hostapd/files/patches/mtk-0019-hostapd-mtk-Fix-auto-ht-issue-when-switching-to-DFS-.patch
@@ -0,0 +1,43 @@
+From 83ab1a9cc51225095842d3c62bf75cf4efe63075 Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Mon, 20 Feb 2023 16:58:20 +0800
+Subject: [PATCH] hostapd: mtk: Fix auto ht issue when switching to DFS channel
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ hostapd/ctrl_iface.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
+index 0ad8451..407790f 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -2698,6 +2698,12 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
+ break;
+ }
+
++ if (os_strstr(pos, " auto-ht")) {
++ settings.freq_params.ht_enabled = iface->conf->ieee80211n;
++ settings.freq_params.vht_enabled = iface->conf->ieee80211ac;
++ settings.freq_params.he_enabled = iface->conf->ieee80211ax;
++ }
++
+ if (settings.freq_params.center_freq1)
+ dfs_range += hostapd_is_dfs_overlap(
+ iface, bandwidth, settings.freq_params.center_freq1);
+@@ -2735,12 +2741,6 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
+ return 0;
+ }
+
+- if (os_strstr(pos, " auto-ht")) {
+- settings.freq_params.ht_enabled = iface->conf->ieee80211n;
+- settings.freq_params.vht_enabled = iface->conf->ieee80211ac;
+- settings.freq_params.he_enabled = iface->conf->ieee80211ax;
+- }
+-
+ for (i = 0; i < iface->num_bss; i++) {
+
+ /* Save CHAN_SWITCH VHT, HE, and EHT config */
+--
+2.18.0
+
diff --git a/recipes-wifi/hostapd/files/patches/mtk-0020-hostapd-mtk-Mark-DFS-channel-as-available-for-CSA.patch b/recipes-wifi/hostapd/files/patches/mtk-0020-hostapd-mtk-Mark-DFS-channel-as-available-for-CSA.patch
new file mode 100644
index 0000000..1fe5c88
--- /dev/null
+++ b/recipes-wifi/hostapd/files/patches/mtk-0020-hostapd-mtk-Mark-DFS-channel-as-available-for-CSA.patch
@@ -0,0 +1,60 @@
+From 3e9500a42a41e8cd7c2d7bc20aba96e1e17161fb Mon Sep 17 00:00:00 2001
+From: "himanshu.goyal" <himanshu.goyal@mediatek.com>
+Date: Fri, 3 Mar 2023 12:45:42 +0800
+Subject: [PATCH] hostapd: mtk: Mark DFS channel as available for CSA.
+
+---
+ hostapd/ctrl_iface.c | 10 ++++++++++
+ hostapd/hostapd_cli.c | 2 +-
+ src/ap/ctrl_iface_ap.c | 1 +
+ 3 files changed, 12 insertions(+), 1 deletion(-)
+
+diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
+index c33b7a4..9ba6992 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -2704,6 +2704,16 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
+ settings.freq_params.he_enabled = iface->conf->ieee80211ax;
+ }
+
++ if (settings.freq_params.radar_background) {
++ hostapd_dfs_sta_update_state(iface,
++ settings.freq_params.freq,
++ settings.freq_params.ht_enabled,
++ settings.freq_params.sec_channel_offset,
++ bandwidth, settings.freq_params.center_freq1,
++ settings.freq_params.center_freq2,
++ HOSTAPD_CHAN_DFS_AVAILABLE);
++ }
++
+ if (settings.freq_params.center_freq1)
+ dfs_range += hostapd_is_dfs_overlap(
+ iface, bandwidth, settings.freq_params.center_freq1);
+diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
+index 0da18e2..6231e51 100644
+--- a/hostapd/hostapd_cli.c
++++ b/hostapd/hostapd_cli.c
+@@ -1693,7 +1693,7 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
+ "<addr> = send QoS Map Configure frame" },
+ { "chan_switch", hostapd_cli_cmd_chan_switch, NULL,
+ "<cs_count> <freq> [sec_channel_offset=] [center_freq1=]\n"
+- " [center_freq2=] [bandwidth=] [blocktx] [ht|vht]\n"
++ " [center_freq2=] [bandwidth=] [blocktx] [ht|vht] [skip_cac]\n"
+ " = initiate channel switch announcement" },
+ { "hs20_wnm_notif", hostapd_cli_cmd_hs20_wnm_notif, NULL,
+ "<addr> <url>\n"
+diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c
+index 18bae5c..2fae590 100644
+--- a/src/ap/ctrl_iface_ap.c
++++ b/src/ap/ctrl_iface_ap.c
+@@ -938,6 +938,7 @@ int hostapd_parse_csa_settings(const char *pos,
+ settings->freq_params.vht_enabled = !!os_strstr(pos, " vht");
+ settings->freq_params.he_enabled = !!os_strstr(pos, " he");
+ settings->freq_params.eht_enabled = !!os_strstr(pos, " eht");
++ settings->freq_params.radar_background = !!os_strstr(pos, " skip_cac");
+ settings->block_tx = !!os_strstr(pos, " blocktx");
+ #undef SET_CSA_SETTING
+
+--
+2.18.0
+
diff --git a/recipes-wifi/hostapd/files/patches/mtk-0020-hostapd-mtk-add-11v_mbss-and-ema-support.patch b/recipes-wifi/hostapd/files/patches/mtk-0020-hostapd-mtk-add-11v_mbss-and-ema-support.patch
new file mode 100644
index 0000000..8d59a0f
--- /dev/null
+++ b/recipes-wifi/hostapd/files/patches/mtk-0020-hostapd-mtk-add-11v_mbss-and-ema-support.patch
@@ -0,0 +1,1175 @@
+From 8cbdb9a59e3bbe8804f909b13ce6df6e2777c3da Mon Sep 17 00:00:00 2001
+From: mtk20656 <chank.chen@mediatek.com>
+Date: Thu, 2 Mar 2023 10:51:43 +0800
+Subject: [PATCH] hostapd: mtk: add 11v_mbss and ema support for hostapd
+
+Signed-off-by: mtk20656 <chank.chen@mediatek.com>
+---
+ hostapd/config_file.c | 9 +
+ hostapd/hostapd.conf | 58 +++++++
+ hostapd/main.c | 3 +
+ src/ap/ap_config.c | 12 ++
+ src/ap/ap_config.h | 6 +
+ src/ap/beacon.c | 124 ++++++++++++--
+ src/ap/hostapd.c | 72 +++++++-
+ src/ap/hostapd.h | 7 +
+ src/ap/ieee802_11.c | 276 +++++++++++++++++++++++++++++-
+ src/ap/ieee802_11.h | 7 +-
+ src/ap/ieee802_11_shared.c | 11 ++
+ src/common/ieee802_11_common.c | 4 +
+ src/common/ieee802_11_common.h | 3 +
+ src/common/ieee802_11_defs.h | 5 +
+ src/drivers/driver.h | 42 +++++
+ src/drivers/driver_nl80211.c | 52 ++++++
+ src/drivers/driver_nl80211_capa.c | 27 +++
+ 17 files changed, 698 insertions(+), 20 deletions(-)
+
+diff --git a/hostapd/config_file.c b/hostapd/config_file.c
+index 649618b..3f26191 100644
+--- a/hostapd/config_file.c
++++ b/hostapd/config_file.c
+@@ -3663,6 +3663,15 @@ static int hostapd_config_fill(struct hostapd_config *conf,
+ return 1;
+ }
+ bss->unsol_bcast_probe_resp_interval = val;
++ } else if (os_strcmp(buf, "mbssid") == 0) {
++ int mbssid = atoi(pos);
++ if (mbssid < 0 || mbssid > ENHANCED_MBSSID_ENABLED) {
++ wpa_printf(MSG_ERROR,
++ "Line %d: invalid mbssid (%d): '%s'.",
++ line, mbssid, pos);
++ return 1;
++ }
++ conf->mbssid = mbssid;
+ } else if (os_strcmp(buf, "mu_onoff") == 0) {
+ int val = atoi(pos);
+ if (val < 0 || val > 15) {
+diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
+index e3a5eb3..f926029 100644
+--- a/hostapd/hostapd.conf
++++ b/hostapd/hostapd.conf
+@@ -3123,3 +3123,61 @@ own_ip_addr=127.0.0.1
+ #bss=wlan0_1
+ #bssid=00:13:10:95:fe:0b
+ # ...
++#
++# Multiple BSSID Advertisement in 802.11ax
++# IEEE Std 802.11ax-2021 added a feature where instead of multiple interfaces
++# on a common radio transmitting individual beacons, those can form a set with
++# a common beacon is transmitted for all. The interface which is brought up
++# first is called as the transmitting profile of the MBSSID set which transmits
++# the beacons. The remaining interfaces are called as the non-transmitting
++# profiles and these are advertised inside the multiple BSSID element in the
++# beacons and probe response frames.
++# The transmitting interface is visible to all clients in the vicinity, however
++# the clients which do not support parsing of the multiple BSSID element will
++# not be able to connect to the non-transmitting interfaces.
++#
++# Enhanced Multiple BSSID Advertisements (EMA)
++# When enabled, the non-transmitting interfaces are split into multiple
++# beacons. The number of beacons required to cover all the non-transmitting
++# profiles is called as the profile periodicity.
++#
++# Refer to IEEE Std 802.11-2020 for details regarding the procedure and
++# required MAC address assignment.
++#
++# Following configuration is per radio.
++# 0 = Disabled (Default)
++# 1 = Multiple BSSID advertisements enabled.
++# 2 = Enhanced multiple BSSID advertisements enabled.
++#mbssid=0
++#
++# The transmitting interface should be added with 'interface' option while
++# the non-transmitting interfaces should be added using 'bss' option.
++# Security configuration should be added separately per interface, if required.
++#
++# Example:
++#mbssid=2
++#interface=wlan2
++#ctrl_interface=/var/run/hostapd
++#wpa_passphrase=0123456789
++#ieee80211w=2
++#sae_pwe=1
++#auth_algs=1
++#wpa=2
++#wpa_pairwise=CCMP
++#ssid=<SSID-0>
++#bridge=br-lan
++#wpa_key_mgmt=SAE
++#bssid=00:03:7f:12:84:84
++#
++#bss=wlan2-1
++#ctrl_interface=/var/run/hostapd
++#wpa_passphrase=0123456789
++#ieee80211w=2
++#sae_pwe=1
++#auth_algs=1
++#wpa=2
++#wpa_pairwise=CCMP
++#ssid=<SSID-1>
++#bridge=br-lan
++#wpa_key_mgmt=SAE
++#bssid=00:03:7f:12:84:85
+diff --git a/hostapd/main.c b/hostapd/main.c
+index 70a4b32..1b6474a 100644
+--- a/hostapd/main.c
++++ b/hostapd/main.c
+@@ -253,6 +253,9 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
+ wpa_printf(MSG_ERROR, "set_wowlan failed");
+ }
+ os_free(triggs);
++
++ iface->mbssid_max_interfaces = capa.mbssid_max_interfaces;
++ iface->ema_max_periodicity = capa.ema_max_periodicity;
+ }
+
+ return 0;
+diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
+index 4e46a62..7d9d5cb 100644
+--- a/src/ap/ap_config.c
++++ b/src/ap/ap_config.c
+@@ -1462,6 +1462,12 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
+ }
+ #endif /* CONFIG_IEEE80211BE */
+
++ if (full_config && bss->ignore_broadcast_ssid && conf->mbssid) {
++ wpa_printf(MSG_ERROR,
++ "Hidden SSID is not suppored when MBSSID is enabled");
++ return -1;
++ }
++
+ return 0;
+ }
+
+@@ -1545,6 +1551,12 @@ int hostapd_config_check(struct hostapd_config *conf, int full_config)
+ }
+ #endif /* CONFIG_IEEE80211BE */
+
++ if (full_config && conf->mbssid && !conf->ieee80211ax) {
++ wpa_printf(MSG_ERROR,
++ "Cannot enable multiple BSSID support without ieee80211ax");
++ return -1;
++ }
++
+ for (i = 0; i < conf->num_bss; i++) {
+ if (hostapd_config_check_bss(conf->bss[i], conf, full_config))
+ return -1;
+diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
+index 7aeb176..51476b8 100644
+--- a/src/ap/ap_config.h
++++ b/src/ap/ap_config.h
+@@ -923,6 +923,8 @@ struct hostapd_bss_config {
+ u8 ext_capa[EXT_CAPA_MAX_LEN];
+
+ u8 rnr;
++
++ bool xrates_supported;
+ };
+
+ /**
+@@ -1163,6 +1165,10 @@ struct hostapd_config {
+ u8 ibf_enable;
+ u8 dfs_detect_mode;
+ u8 amsdu;
++
++#define MBSSID_ENABLED 1
++#define ENHANCED_MBSSID_ENABLED 2
++ u8 mbssid;
+ };
+
+ enum three_wire_mode {
+diff --git a/src/ap/beacon.c b/src/ap/beacon.c
+index f3ea5c2..51db23a 100644
+--- a/src/ap/beacon.c
++++ b/src/ap/beacon.c
+@@ -462,15 +462,77 @@ static u8 * hostapd_eid_supported_op_classes(struct hostapd_data *hapd, u8 *eid)
+ }
+
+
++static int ieee802_11_build_ap_params_mbssid(struct hostapd_data *hapd,
++ struct wpa_driver_ap_params *params,
++ u8 **eid)
++{
++ struct hostapd_iface *iface = hapd->iface;
++ struct hostapd_data *tx_bss;
++ size_t len;
++ u8 elem_count = 0, *elem = NULL, **elem_offset = NULL, *end;
++ u8 *tailpos = *eid;
++
++ if (!iface->mbssid_max_interfaces ||
++ iface->num_bss > iface->mbssid_max_interfaces ||
++ (iface->conf->mbssid == ENHANCED_MBSSID_ENABLED &&
++ !iface->ema_max_periodicity))
++ goto fail;
++
++ tx_bss = hostapd_mbssid_get_tx_bss(hapd);
++ len = hostapd_eid_mbssid_len(tx_bss, WLAN_FC_STYPE_BEACON, &elem_count,
++ NULL, 0);
++ if (!len || (iface->conf->mbssid == ENHANCED_MBSSID_ENABLED &&
++ elem_count > iface->ema_max_periodicity))
++ goto fail;
++
++ elem = os_zalloc(len);
++ if (!elem)
++ goto fail;
++
++ elem_offset = os_zalloc(elem_count * sizeof(u8 *));
++ if (!elem_offset)
++ goto fail;
++
++ end = hostapd_eid_mbssid(tx_bss, elem, elem + len, WLAN_FC_STYPE_BEACON,
++ elem_count, elem_offset, NULL, 0);
++
++ params->mbssid_tx_iface = tx_bss->conf->iface;
++ params->mbssid_index = hostapd_mbssid_get_bss_index(hapd);
++ params->mbssid_elem = elem;
++ params->mbssid_elem_len = end - elem;
++ params->mbssid_elem_count = elem_count;
++ params->mbssid_elem_offset = elem_offset;
++ if (iface->conf->mbssid == ENHANCED_MBSSID_ENABLED) {
++ params->ema = true;
++ *tailpos++ = WLAN_EID_EXTENSION;
++ *tailpos++ = 3;
++ *tailpos++ = WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION;
++ *tailpos++ = iface->num_bss;
++ *tailpos++ = params->mbssid_elem_count;
++ *eid = tailpos;
++ }
++
++ return 0;
++
++fail:
++ os_free(elem);
++ wpa_printf(MSG_ERROR, "MBSSID: Configuration failed");
++ return -1;
++}
++
++
+ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
+ const struct ieee80211_mgmt *req,
+ int is_p2p, size_t *resp_len,
+- bool bcast_probe_resp)
++ bool bcast_probe_resp, const u8 *known_bss,
++ u8 known_bss_len)
+ {
+ struct ieee80211_mgmt *resp;
+- u8 *pos, *epos, *csa_pos;
++ u8 *pos, *epos, *csa_pos, *ext_cap_pos;
+ size_t buflen;
+
++ hapd = hostapd_mbssid_get_tx_bss(hapd);
++
+ #define MAX_PROBERESP_LEN 768
+ buflen = MAX_PROBERESP_LEN;
+ #ifdef CONFIG_WPS
+@@ -517,6 +579,8 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
+ }
+ #endif /* CONFIG_IEEE80211BE */
+
++ buflen += hostapd_eid_mbssid_len(hapd, WLAN_FC_STYPE_PROBE_RESP, NULL,
++ known_bss, known_bss_len);
+ buflen += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_PROBE_RESP);
+ buflen += hostapd_mbo_ie_len(hapd);
+ buflen += hostapd_eid_owe_trans_len(hapd);
+@@ -588,8 +652,16 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
+ pos = hostapd_eid_supported_op_classes(hapd, pos);
+ pos = hostapd_eid_ht_capabilities(hapd, pos);
+ pos = hostapd_eid_ht_operation(hapd, pos);
++ pos = hostapd_eid_mbssid(hapd, pos, epos, WLAN_FC_STYPE_PROBE_RESP, 0,
++ NULL, known_bss, known_bss_len);
+
++ ext_cap_pos = pos;
+ pos = hostapd_eid_ext_capab(hapd, pos);
++ if (hapd->iconf->mbssid >= MBSSID_ENABLED && !known_bss_len)
++ ext_cap_pos[12] |= 0x01; /* Probe responses always include all
++ * non-tx profiles except when a list
++ * of known BSSes is included in the
++ * probe request. */
+
+ pos = hostapd_eid_time_adv(hapd, pos);
+ pos = hostapd_eid_time_zone(hapd, pos);
+@@ -1153,16 +1225,23 @@ void handle_probe_req(struct hostapd_data *hapd,
+ }
+ #endif /* CONFIG_TESTING_OPTIONS */
+
++ /* Do not send probe response from a non-transmitting multiple BSSID
++ * profile unless the probe request is directed at that paticular BSS */
++ if (hapd != hostapd_mbssid_get_tx_bss(hapd) && res != EXACT_SSID_MATCH)
++ return;
++
+ wpa_msg_ctrl(hapd->msg_ctx, MSG_INFO, RX_PROBE_REQUEST "sa=" MACSTR
+ " signal=%d", MAC2STR(mgmt->sa), ssi_signal);
+
+ if (is_6ghz_op_class(hapd->iconf->op_class) &&
+ is_broadcast_ether_addr(mgmt->da))
+ resp = hostapd_gen_probe_resp(hapd, NULL, elems.p2p != NULL,
+- &resp_len, true);
++ &resp_len, false, elems.mbssid_known_bss,
++ elems.mbssid_known_bss_len);
+ else
+ resp = hostapd_gen_probe_resp(hapd, mgmt, elems.p2p != NULL,
+- &resp_len, false);
++ &resp_len, false, elems.mbssid_known_bss,
++ elems.mbssid_known_bss_len);
+ if (resp == NULL)
+ return;
+
+@@ -1184,7 +1263,8 @@ void handle_probe_req(struct hostapd_data *hapd,
+ hapd->cs_c_off_ecsa_proberesp;
+ }
+
+- ret = hostapd_drv_send_mlme(hapd, resp, resp_len, noack,
++ ret = hostapd_drv_send_mlme(hostapd_mbssid_get_tx_bss(hapd), resp,
++ resp_len, noack,
+ csa_offs_len ? csa_offs : NULL,
+ csa_offs_len, 0);
+
+@@ -1231,7 +1311,7 @@ static u8 * hostapd_probe_resp_offloads(struct hostapd_data *hapd,
+ "this");
+
+ /* Generate a Probe Response template for the non-P2P case */
+- return hostapd_gen_probe_resp(hapd, NULL, 0, resp_len, false);
++ return hostapd_gen_probe_resp(hapd, NULL, 0, resp_len, false, NULL, 0);
+ }
+
+ #endif /* NEED_AP_MLME */
+@@ -1250,7 +1330,7 @@ static u8 * hostapd_unsol_bcast_probe_resp(struct hostapd_data *hapd,
+
+ return hostapd_gen_probe_resp(hapd, NULL, 0,
+ ¶ms->unsol_bcast_probe_resp_tmpl_len,
+- true);
++ true, NULL, 0);
+ }
+ #endif /* CONFIG_IEEE80211AX */
+
+@@ -1533,8 +1613,12 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
+ size_t resp_len = 0;
+ #ifdef NEED_AP_MLME
+ u16 capab_info;
+- u8 *pos, *tailpos, *tailend, *csa_pos;
++ u8 *pos, *tailpos, *tailend, *csa_pos, *ext_cap_pos;
++#endif /* NEED_AP_MLME */
+
++ os_memset(params, 0, sizeof(*params));
++
++#ifdef NEED_AP_MLME
+ #define BEACON_HEAD_BUF_SIZE 256
+ #define BEACON_TAIL_BUF_SIZE 512
+ head = os_zalloc(BEACON_HEAD_BUF_SIZE);
+@@ -1586,6 +1670,9 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
+ }
+ #endif /* CONFIG_IEEE80211BE */
+
++ if (hapd->iconf->mbssid == ENHANCED_MBSSID_ENABLED &&
++ hapd == hostapd_mbssid_get_tx_bss(hapd))
++ tail_len += 5; /* Multiple BSSID Configuration element */
+ tail_len += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_BEACON);
+ tail_len += hostapd_mbo_ie_len(hapd);
+ tail_len += hostapd_eid_owe_trans_len(hapd);
+@@ -1671,9 +1758,23 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
+ tailpos = hostapd_eid_supported_op_classes(hapd, tailpos);
+ tailpos = hostapd_eid_ht_capabilities(hapd, tailpos);
+ tailpos = hostapd_eid_ht_operation(hapd, tailpos);
+-
++ ext_cap_pos = tailpos;
+ tailpos = hostapd_eid_ext_capab(hapd, tailpos);
+
++ if (hapd->iconf->mbssid && hapd->iconf->num_bss > 1) {
++ if (ieee802_11_build_ap_params_mbssid(hapd, params, &tailpos)) {
++ os_free(head);
++ os_free(tail);
++ wpa_printf(MSG_ERROR, "Failed to set beacon data");
++ return -1;
++ } else if (hapd->iconf->mbssid == MBSSID_ENABLED ||
++ (hapd->iconf->mbssid == ENHANCED_MBSSID_ENABLED &&
++ params->mbssid_elem_count == 1)) {
++ /* Set the extended capability bit for "complete list
++ * of non-tx profiles" */
++ ext_cap_pos[12] |= 0x01;
++ }
++ }
+ /*
+ * TODO: Time Advertisement element should only be included in some
+ * DTIM Beacon frames.
+@@ -1794,7 +1895,6 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
+ resp = hostapd_probe_resp_offloads(hapd, &resp_len);
+ #endif /* NEED_AP_MLME */
+
+- os_memset(params, 0, sizeof(*params));
+ params->head = (u8 *) head;
+ params->head_len = head_len;
+ params->tail = tail;
+@@ -1897,6 +1997,10 @@ void ieee802_11_free_ap_params(struct wpa_driver_ap_params *params)
+ params->head = NULL;
+ os_free(params->proberesp);
+ params->proberesp = NULL;
++ os_free(params->mbssid_elem);
++ params->mbssid_elem = NULL;
++ os_free(params->mbssid_elem_offset);
++ params->mbssid_elem_offset = NULL;
+ #ifdef CONFIG_FILS
+ os_free(params->fd_frame_tmpl);
+ params->fd_frame_tmpl = NULL;
+diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
+index 42e8ed7..82cc155 100644
+--- a/src/ap/hostapd.c
++++ b/src/ap/hostapd.c
+@@ -91,6 +91,29 @@ int hostapd_for_each_interface(struct hapd_interfaces *interfaces,
+ }
+
+
++struct hostapd_data * hostapd_mbssid_get_tx_bss(struct hostapd_data *hapd)
++{
++ if (hapd->iconf->mbssid)
++ return hapd->iface->bss[0];
++
++ return hapd;
++}
++
++
++int hostapd_mbssid_get_bss_index(struct hostapd_data *hapd)
++{
++ if (hapd->iconf->mbssid) {
++ size_t i;
++
++ for (i = 1; i < hapd->iface->num_bss; i++)
++ if (hapd->iface->bss[i] == hapd)
++ return i;
++ }
++
++ return 0;
++}
++
++
+ void hostapd_reconfig_encryption(struct hostapd_data *hapd)
+ {
+ if (hapd->wpa_auth)
+@@ -1179,19 +1202,37 @@ static int db_table_create_radius_attributes(sqlite3 *db)
+
+ #endif /* CONFIG_NO_RADIUS */
+
++static int hostapd_start_beacon(struct hostapd_data *hapd)
++{
++ struct hostapd_bss_config *conf = hapd->conf;
++
++ if (!conf->start_disabled && ieee802_11_set_beacon(hapd) < 0)
++ return -1;
++
++ if (hapd->driver && hapd->driver->set_operstate)
++ hapd->driver->set_operstate(hapd->drv_priv, 1);
++
++ return 0;
++}
+
+ /**
+ * hostapd_setup_bss - Per-BSS setup (initialization)
+ * @hapd: Pointer to BSS data
+ * @first: Whether this BSS is the first BSS of an interface; -1 = not first,
+ * but interface may exist
++ * @start_beacon: Whether beacons should be configured and transmission started
++ * at this time. This is used when MBSSID IE is enabled where the
++ * information regarding all BSSes should be retrieved before configuring
++ * the beacons. The calling functions are responsible to configure the
++ * beacon explicitly if this is set to 'false'.
+ *
+ * This function is used to initialize all per-BSS data structures and
+ * resources. This gets called in a loop for each BSS when an interface is
+ * initialized. Most of the modules that are initialized here will be
+ * deinitialized in hostapd_cleanup().
+ */
+-static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
++static int hostapd_setup_bss(struct hostapd_data *hapd, int first,
++ bool start_beacon)
+ {
+ struct hostapd_bss_config *conf = hapd->conf;
+ u8 ssid[SSID_MAX_LEN + 1];
+@@ -1464,9 +1505,6 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
+ return -1;
+ }
+
+- if (!conf->start_disabled && ieee802_11_set_beacon(hapd) < 0)
+- return -1;
+-
+ if (flush_old_stations && !conf->start_disabled &&
+ conf->broadcast_deauth) {
+ u8 addr[ETH_ALEN];
+@@ -1485,8 +1523,8 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
+ if (hapd->wpa_auth && wpa_init_keys(hapd->wpa_auth) < 0)
+ return -1;
+
+- if (hapd->driver && hapd->driver->set_operstate)
+- hapd->driver->set_operstate(hapd->drv_priv, 1);
++ if (start_beacon)
++ return hostapd_start_beacon(hapd);
+
+ hostapd_ubus_add_bss(hapd);
+
+@@ -2214,7 +2252,7 @@ static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface,
+ hapd = iface->bss[j];
+ if (j)
+ os_memcpy(hapd->own_addr, prev_addr, ETH_ALEN);
+- if (hostapd_setup_bss(hapd, j == 0)) {
++ if (hostapd_setup_bss(hapd, j == 0, !iface->conf->mbssid)) {
+ for (;;) {
+ hapd = iface->bss[j];
+ hostapd_bss_deinit_no_free(hapd);
+@@ -2228,6 +2266,24 @@ static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface,
+ if (is_zero_ether_addr(hapd->conf->bssid))
+ prev_addr = hapd->own_addr;
+ }
++
++ if (hapd->iconf->mbssid) {
++ for (j = 0; j < iface->num_bss; j++) {
++ hapd = iface->bss[j];
++ if (hostapd_start_beacon(hapd)) {
++ for (;;) {
++ hapd = iface->bss[j];
++ hostapd_bss_deinit_no_free(hapd);
++ hostapd_free_hapd_data(hapd);
++ if (j == 0)
++ break;
++ j--;
++ }
++ goto fail;
++ }
++ }
++ }
++
+ hapd = iface->bss[0];
+
+ hostapd_tx_queue_params(iface);
+@@ -3130,7 +3186,7 @@ int hostapd_add_iface(struct hapd_interfaces *interfaces, char *buf)
+
+ if (start_ctrl_iface_bss(hapd) < 0 ||
+ (hapd_iface->state == HAPD_IFACE_ENABLED &&
+- hostapd_setup_bss(hapd, -1))) {
++ hostapd_setup_bss(hapd, -1, true))) {
+ hostapd_cleanup(hapd);
+ hapd_iface->bss[hapd_iface->num_bss - 1] = NULL;
+ hapd_iface->conf->num_bss--;
+diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
+index 56d96a5..093c28a 100644
+--- a/src/ap/hostapd.h
++++ b/src/ap/hostapd.h
+@@ -660,6 +660,11 @@ struct hostapd_iface {
+ /* Previous WMM element information */
+ struct hostapd_wmm_ac_params prev_wmm[WMM_AC_NUM];
+
++ /* Maximum number of interfaces supported for MBSSID advertisements */
++ u8 mbssid_max_interfaces;
++ /* Maximum profile periodicity for enhanced MBSSID advertisements */
++ u8 ema_max_periodicity;
++
+ int (*enable_iface_cb)(struct hostapd_iface *iface);
+ int (*disable_iface_cb)(struct hostapd_iface *iface);
+ };
+@@ -762,5 +767,7 @@ void fst_hostapd_fill_iface_obj(struct hostapd_data *hapd,
+ #endif /* CONFIG_FST */
+
+ int hostapd_set_acl(struct hostapd_data *hapd);
++struct hostapd_data * hostapd_mbssid_get_tx_bss(struct hostapd_data *hapd);
++int hostapd_mbssid_get_bss_index(struct hostapd_data *hapd);
+
+ #endif /* HOSTAPD_H */
+diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
+index 098793e..30bfa30 100644
+--- a/src/ap/ieee802_11.c
++++ b/src/ap/ieee802_11.c
+@@ -165,6 +165,7 @@ u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid)
+ int i, num, count;
+ int h2e_required;
+
++ hapd->conf->xrates_supported = 0;
+ if (hapd->iface->current_rates == NULL)
+ return eid;
+
+@@ -214,6 +215,7 @@ u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid)
+ *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_SAE_H2E_ONLY;
+ }
+
++ hapd->conf->xrates_supported = 1;
+ return pos;
+ }
+
+@@ -3979,6 +3981,23 @@ static void handle_auth(struct hostapd_data *hapd,
+ }
+
+
++static u8 hostapd_max_bssid_indicator(struct hostapd_data *hapd)
++{
++ size_t num_bss_nontx;
++ u8 max_bssid_ind = 0;
++
++ if (!hapd->iconf->mbssid || hapd->iface->num_bss <= 1)
++ return 0;
++
++ num_bss_nontx = hapd->iface->num_bss - 1;
++ while (num_bss_nontx > 0) {
++ max_bssid_ind++;
++ num_bss_nontx >>= 1;
++ }
++ return max_bssid_ind;
++}
++
++
+ int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta)
+ {
+ int i, j = 32, aid;
+@@ -4004,7 +4023,10 @@ int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta)
+ }
+ if (j == 32)
+ return -1;
+- aid = i * 32 + j + 1;
++ aid = i * 32 + j;
++
++ aid += (1 << hostapd_max_bssid_indicator(hapd));
++
+ if (aid > 2007)
+ return -1;
+
+@@ -7579,4 +7601,256 @@ u8 * hostapd_eid_rnr(struct hostapd_data *hapd, u8 *eid, u32 type)
+ return eid;
+ }
+
++
++static size_t hostapd_eid_mbssid_elem_len(struct hostapd_data *hapd,
++ u32 frame_type, size_t *bss_index,
++ const u8 *known_bss,
++ size_t known_bss_len)
++{
++ struct hostapd_data *tx_bss = hostapd_mbssid_get_tx_bss(hapd);
++ size_t len = 3, i;
++
++ for (i = *bss_index; i < hapd->iface->num_bss; i++) {
++ struct hostapd_data *bss = hapd->iface->bss[i];
++ const u8 *auth, *rsn = NULL, *rsnx = NULL;
++ size_t nontx_profile_len, auth_len;
++ u8 ie_count = 0;
++
++ if (known_bss && (known_bss_len > (i / 8))) {
++ known_bss = &known_bss[i / 8];
++ if (*known_bss & (u8)(BIT(i % 8)))
++ continue;
++ }
++
++ if (!bss || !bss->conf || !bss->started)
++ continue;
++
++ /*
++ * Sublement ID: 1 byte
++ * Length: 1 byte
++ * Nontransmitted capabilities: 4 bytes
++ * SSID element: 2 + variable
++ * Multiple BSSID Index Element: 3 bytes (+2 bytes in beacons)
++ * Fixed length = 1 + 1 + 4 + 2 + 3 = 11
++ */
++ nontx_profile_len = 11 + bss->conf->ssid.ssid_len;
++
++ if (frame_type == WLAN_FC_STYPE_BEACON)
++ nontx_profile_len += 2;
++
++ auth = wpa_auth_get_wpa_ie(bss->wpa_auth, &auth_len);
++ if (auth) {
++ rsn = get_ie(auth, auth_len, WLAN_EID_RSN);
++ if (rsn)
++ nontx_profile_len += (2 + rsn[1]);
++
++ rsnx = get_ie(auth, auth_len, WLAN_EID_RSNX);
++ if (rsnx)
++ nontx_profile_len += (2 + rsnx[1]);
++ }
++ if (!rsn && hostapd_wpa_ie(tx_bss, WLAN_EID_RSN))
++ ie_count++;
++ if (!rsnx && hostapd_wpa_ie(tx_bss, WLAN_EID_RSNX))
++ ie_count++;
++ if (bss->conf->xrates_supported)
++ nontx_profile_len += 8;
++ else if (hapd->conf->xrates_supported)
++ ie_count++;
++ if (ie_count)
++ nontx_profile_len += (4 + ie_count);
++
++ if ((len + nontx_profile_len) > 255)
++ goto mbssid_too_big;
++
++ len += nontx_profile_len;
++ }
++
++mbssid_too_big:
++ *bss_index = i;
++ return len;
++}
++
++
++size_t hostapd_eid_mbssid_len(struct hostapd_data *hapd, u32 frame_type,
++ u8 *elem_count, const u8 *known_bss,
++ size_t known_bss_len)
++{
++ size_t len = 0, bss_index = 1;
++
++ if (!hapd->iconf->mbssid || hapd->iface->num_bss <= 1 ||
++ (frame_type != WLAN_FC_STYPE_BEACON &&
++ frame_type != WLAN_FC_STYPE_PROBE_RESP))
++ return 0;
++
++ if (frame_type == WLAN_FC_STYPE_BEACON) {
++ if (!elem_count) {
++ wpa_printf(MSG_ERROR,
++ "MBSSID: Insufficient data for beacons");
++ return 0;
++ }
++ *elem_count = 0;
++ }
++
++ while (bss_index < hapd->iface->num_bss) {
++ len += hostapd_eid_mbssid_elem_len(hapd, frame_type,
++ &bss_index, known_bss,
++ known_bss_len);
++
++ if (frame_type == WLAN_FC_STYPE_BEACON)
++ *elem_count += 1;
++ }
++ return len;
++}
++
++
++static u8 * hostapd_eid_mbssid_elem(struct hostapd_data *hapd, u8 *eid, u8 *end,
++ u32 frame_type, u8 max_bssid_indicator,
++ size_t *bss_index, u8 elem_count,
++ const u8 *known_bss, size_t known_bss_len)
++{
++ struct hostapd_data *tx_bss = hostapd_mbssid_get_tx_bss(hapd);
++ size_t i;
++ u8 *eid_len_offset, *max_bssid_indicator_offset;
++
++ *eid++ = WLAN_EID_MULTIPLE_BSSID;
++ eid_len_offset = eid++;
++ max_bssid_indicator_offset = eid++;
++
++ for (i = *bss_index; i < hapd->iface->num_bss; i++) {
++ struct hostapd_data *bss = hapd->iface->bss[i];
++ struct hostapd_bss_config *conf;
++ u8 *eid_len_pos, *nontx_bss_start = eid;
++ const u8 *auth, *rsn = NULL, *rsnx = NULL;
++ u8 ie_count = 0, non_inherit_ie[3];
++ size_t auth_len = 0;
++ u16 capab_info;
++
++ if (known_bss && (known_bss_len > (i / 8))) {
++ known_bss = &known_bss[i / 8];
++ if (*known_bss & (u8)(BIT(i % 8)))
++ continue;
++ }
++
++ if (!bss || !bss->conf || !bss->started)
++ continue;
++ conf = bss->conf;
++
++ *eid++ = WLAN_EID_SUBELEMENT_NONTRANSMITTED_BSSID_PROFILE;
++ eid_len_pos = eid++;
++
++ *eid++ = WLAN_EID_NONTRANSMITTED_BSSID_CAPA;
++ *eid++ = sizeof(capab_info);
++ capab_info = host_to_le16(hostapd_own_capab_info(bss));
++ os_memcpy(eid, (const void *)&capab_info, sizeof(capab_info));
++ eid += sizeof(capab_info);
++
++ *eid++ = WLAN_EID_SSID;
++ *eid++ = conf->ssid.ssid_len;
++ os_memcpy(eid, conf->ssid.ssid, conf->ssid.ssid_len);
++ eid += conf->ssid.ssid_len;
++
++ *eid++ = WLAN_EID_MULTIPLE_BSSID_INDEX;
++ if (frame_type == WLAN_FC_STYPE_BEACON) {
++ *eid++ = 3;
++ *eid++ = i;
++ if (hapd->iconf->mbssid == ENHANCED_MBSSID_ENABLED &&
++ (conf->dtim_period % elem_count))
++ conf->dtim_period = elem_count;
++ *eid++ = conf->dtim_period;
++ *eid++ = 0xFF;
++ } else {
++ *eid++ = 1;
++ *eid++ = i;
++ }
++
++ auth = wpa_auth_get_wpa_ie(bss->wpa_auth, &auth_len);
++ if (auth) {
++ rsn = get_ie(auth, auth_len, WLAN_EID_RSN);
++ if (rsn) {
++ os_memcpy(eid, rsn, 2 + rsn[1]);
++ eid += (2 + rsn[1]);
++ }
++
++ rsnx = get_ie(auth, auth_len, WLAN_EID_RSNX);
++ if (rsnx) {
++ os_memcpy(eid, rsnx, 2 + rsnx[1]);
++ eid += (2 + rsnx[1]);
++ }
++ }
++ if (!rsn && hostapd_wpa_ie(tx_bss, WLAN_EID_RSN)) {
++ non_inherit_ie[ie_count] = WLAN_EID_RSN;
++ ie_count++;
++ }
++ if (!rsnx && hostapd_wpa_ie(tx_bss, WLAN_EID_RSNX)) {
++ non_inherit_ie[ie_count] = WLAN_EID_RSNX;
++ ie_count++;
++ }
++ if (hapd->conf->xrates_supported &&
++ !bss->conf->xrates_supported) {
++ non_inherit_ie[ie_count] = WLAN_EID_EXT_SUPP_RATES;
++ ie_count++;
++ }
++ if (ie_count) {
++ *eid++ = WLAN_EID_EXTENSION;
++ *eid++ = 2 + ie_count;
++ *eid++ = WLAN_EID_EXT_NON_INHERITANCE;
++ *eid++ = ie_count;
++ os_memcpy(eid, non_inherit_ie, ie_count);
++ eid += ie_count;
++ }
++
++ *eid_len_pos = (eid - eid_len_pos) - 1;
++
++ if (((eid - eid_len_offset) - 1) > 255) {
++ eid = nontx_bss_start;
++ goto mbssid_too_big;
++ }
++ }
++
++mbssid_too_big:
++ *bss_index = i;
++ *max_bssid_indicator_offset = max_bssid_indicator;
++ if (*max_bssid_indicator_offset < 1)
++ *max_bssid_indicator_offset = 1;
++ *eid_len_offset = (eid - eid_len_offset) - 1;
++ return eid;
++}
++
++
++u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end,
++ u32 frame_type, u8 elem_count, u8 **elem_offset,
++ const u8 *known_bss, size_t known_bss_len)
++{
++ size_t bss_index = 1;
++ u8 elem_index = 0;
++
++ if (!hapd->iconf->mbssid || hapd->iface->num_bss <= 1 ||
++ (frame_type != WLAN_FC_STYPE_BEACON &&
++ frame_type != WLAN_FC_STYPE_PROBE_RESP))
++ return eid;
++
++ if (frame_type == WLAN_FC_STYPE_BEACON && !elem_offset) {
++ wpa_printf(MSG_ERROR, "MBSSID: Insufficient data for beacons");
++ return eid;
++ }
++
++ while (bss_index < hapd->iface->num_bss) {
++ if (frame_type == WLAN_FC_STYPE_BEACON) {
++ if (elem_index == elem_count) {
++ wpa_printf(MSG_WARNING,
++ "MBSSID: More number of elements than provided array");
++ break;
++ }
++
++ elem_offset[elem_index] = eid;
++ elem_index = elem_index + 1;
++ }
++ eid = hostapd_eid_mbssid_elem(hapd, eid, end, frame_type,
++ hostapd_max_bssid_indicator(hapd),
++ &bss_index, elem_count,
++ known_bss, known_bss_len);
++ }
++ return eid;
++}
++
+ #endif /* CONFIG_NATIVE_WINDOWS */
+diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h
+index fa1f47b..bb454bb 100644
+--- a/src/ap/ieee802_11.h
++++ b/src/ap/ieee802_11.h
+@@ -214,5 +214,10 @@ u16 copy_sta_eht_capab(struct hostapd_data *hapd, struct sta_info *sta,
+ enum ieee80211_op_mode opmode,
+ const u8 *he_capab, size_t he_capab_len,
+ const u8 *eht_capab, size_t eht_capab_len);
+-
++size_t hostapd_eid_mbssid_len(struct hostapd_data *hapd, u32 frame_type,
++ u8 *elem_count, const u8 *known_bss,
++ size_t known_bss_len);
++u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end,
++ u32 frame_type, u8 elem_count, u8 **elem_offset,
++ const u8 *known_bss, size_t known_bss_len);
+ #endif /* IEEE802_11_H */
+diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c
+index 4f85d78..7f5b475 100644
+--- a/src/ap/ieee802_11_shared.c
++++ b/src/ap/ieee802_11_shared.c
+@@ -364,6 +364,8 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx)
+ *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
+ if (hapd->conf->bss_transition)
+ *pos |= 0x08; /* Bit 19 - BSS Transition */
++ if (hapd->iconf->mbssid)
++ *pos |= 0x40; /* Bit 22 - Multiple BSSID */
+ break;
+ case 3: /* Bits 24-31 */
+ #ifdef CONFIG_WNM_AP
+@@ -436,6 +438,8 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx)
+ (hapd->iface->drv_flags &
+ WPA_DRIVER_FLAGS_BEACON_PROTECTION))
+ *pos |= 0x10; /* Bit 84 - Beacon Protection Enabled */
++ if (hapd->iconf->mbssid == ENHANCED_MBSSID_ENABLED)
++ *pos |= 0x08; /* Bit 83 - Enhanced multiple BSSID */
+ break;
+ case 11: /* Bits 88-95 */
+ #ifdef CONFIG_SAE_PK
+@@ -471,6 +475,13 @@ u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid)
+ *pos &= ~hapd->conf->ext_capa_mask[i];
+ *pos |= hapd->conf->ext_capa[i];
+ }
++
++ /* Clear bits 83 and 22 if EMA and MBSSID are not enabled
++ * otherwise association fails with some clients */
++ if (i == 10 && hapd->iconf->mbssid < ENHANCED_MBSSID_ENABLED)
++ *pos &= ~0x08;
++ if (i == 2 && !hapd->iconf->mbssid)
++ *pos &= ~0x40;
+ }
+
+ while (len > 0 && eid[1 + len] == 0) {
+diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c
+index c8ee90c..2fab7c3 100644
+--- a/src/common/ieee802_11_common.c
++++ b/src/common/ieee802_11_common.c
+@@ -315,6 +315,10 @@ static int ieee802_11_parse_extension(const u8 *pos, size_t elen,
+ elems->eht_operation = pos;
+ elems->eht_operation_len = elen;
+ break;
++ case WLAN_EID_EXT_KNOWN_BSSID:
++ elems->mbssid_known_bss = pos;
++ elems->mbssid_known_bss_len = elen;
++ break;
+ default:
+ if (show_errors) {
+ wpa_printf(MSG_MSGDUMP,
+diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h
+index 94e1d7b..1e4e27d 100644
+--- a/src/common/ieee802_11_common.h
++++ b/src/common/ieee802_11_common.h
+@@ -119,6 +119,7 @@ struct ieee802_11_elems {
+ const u8 *pasn_params;
+ const u8 *eht_capabilities;
+ const u8 *eht_operation;
++ const u8 *mbssid_known_bss;
+
+ u8 ssid_len;
+ u8 supp_rates_len;
+@@ -176,6 +177,8 @@ struct ieee802_11_elems {
+ u8 eht_capabilities_len;
+ u8 eht_operation_len;
+
++ u8 mbssid_known_bss_len;
++
+ struct mb_ies_info mb_ies;
+ struct frag_ies_info frag_ies;
+ };
+diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
+index 62088bd..0bbbca9 100644
+--- a/src/common/ieee802_11_defs.h
++++ b/src/common/ieee802_11_defs.h
+@@ -481,6 +481,9 @@
+ #define WLAN_EID_EXT_SPATIAL_REUSE 39
+ #define WLAN_EID_EXT_COLOR_CHANGE_ANNOUNCEMENT 42
+ #define WLAN_EID_EXT_OCV_OCI 54
++#define WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION 55
++#define WLAN_EID_EXT_NON_INHERITANCE 56
++#define WLAN_EID_EXT_KNOWN_BSSID 57
+ #define WLAN_EID_EXT_SHORT_SSID_LIST 58
+ #define WLAN_EID_EXT_HE_6GHZ_BAND_CAP 59
+ #define WLAN_EID_EXT_EDMG_CAPABILITIES 61
+@@ -497,6 +500,8 @@
+ #define WLAN_EID_EXT_MULTI_LINK_TRAFFIC_INDICATION 110
+ #define WLAN_EID_EXT_AKM_SUITE_SELECTOR 114
+
++#define WLAN_EID_SUBELEMENT_NONTRANSMITTED_BSSID_PROFILE 0
++
+ /* Extended Capabilities field */
+ #define WLAN_EXT_CAPAB_20_40_COEX 0
+ #define WLAN_EXT_CAPAB_GLK 1
+diff --git a/src/drivers/driver.h b/src/drivers/driver.h
+index 82daef0..36f465c 100644
+--- a/src/drivers/driver.h
++++ b/src/drivers/driver.h
+@@ -1633,6 +1633,43 @@ struct wpa_driver_ap_params {
+ * ibf_enable=<val>
+ */
+ u8 ibf_enable;
++
++ /**
++ * mbssid_tx_iface - Transmitting interface of the MBSSID set
++ */
++ const char *mbssid_tx_iface;
++
++ /**
++ * mbssid_index - The index of this BSS in the MBSSID set
++ */
++ unsigned int mbssid_index;
++
++ /**
++ * mbssid_elem - Buffer containing all MBSSID elements
++ */
++ u8 *mbssid_elem;
++
++ /**
++ * mbssid_elem_len - Total length of all MBSSID elements
++ */
++ size_t mbssid_elem_len;
++
++ /**
++ * mbssid_elem_count - The number of MBSSID elements
++ */
++ u8 mbssid_elem_count;
++
++ /**
++ * mbssid_elem_offset - Offsets to elements in mbssid_elem.
++ * Kernel will use these offsets to generate multiple BSSID beacons.
++ */
++ u8 **mbssid_elem_offset;
++
++ /**
++ * ema - Enhanced MBSSID advertisements support.
++ */
++ bool ema;
++
+ };
+
+ struct wpa_driver_mesh_bss_params {
+@@ -2197,6 +2234,11 @@ struct wpa_driver_capa {
+
+ /* Maximum number of supported CSA counters */
+ u16 max_csa_counters;
++
++ /* Maximum number of interfaces supported for MBSSID advertisements */
++ u8 mbssid_max_interfaces;
++ /* Maximum profile periodicity for enhanced MBSSID advertisements */
++ u8 ema_max_periodicity;
+ };
+
+
+diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
+index 6c65901..3753409 100644
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -4540,6 +4540,55 @@ static int nl80211_unsol_bcast_probe_resp(struct i802_bss *bss,
+ nla_nest_end(msg, attr);
+ return 0;
+ }
++
++
++static int nl80211_mbssid(struct nl_msg *msg,
++ struct wpa_driver_ap_params *params)
++{
++ struct nlattr *config, *elems;
++ int ifidx;
++
++ if (!params->mbssid_tx_iface)
++ return 0;
++
++ config = nla_nest_start(msg, NL80211_ATTR_MBSSID_CONFIG);
++ if (!config)
++ return -1;
++
++ nla_put_u8(msg, NL80211_MBSSID_CONFIG_ATTR_INDEX, params->mbssid_index);
++ if (params->mbssid_tx_iface) {
++ ifidx = if_nametoindex(params->mbssid_tx_iface);
++ if (ifidx <= 0)
++ return -1;
++ nla_put_u32(msg,
++ NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX,
++ ifidx);
++ }
++
++ if (params->ema)
++ nla_put_flag(msg, NL80211_MBSSID_CONFIG_ATTR_EMA);
++
++ nla_nest_end(msg, config);
++
++ if (params->mbssid_elem_count && params->mbssid_elem_len &&
++ params->mbssid_elem_offset && *params->mbssid_elem_offset) {
++ u8 i, **offs = params->mbssid_elem_offset;
++
++ elems = nla_nest_start(msg, NL80211_ATTR_MBSSID_ELEMS);
++ if (!elems)
++ return -1;
++
++ for (i = 0; i < params->mbssid_elem_count - 1; i++)
++ nla_put(msg, i + 1, offs[i + 1] - offs[i], offs[i]);
++
++ nla_put(msg, i + 1,
++ *offs + params->mbssid_elem_len - offs[i],
++ offs[i]);
++
++ nla_nest_end(msg, elems);
++ }
++ return 0;
++}
+ #endif /* CONFIG_IEEE80211AX */
+
+
+@@ -4838,6 +4887,9 @@ static int wpa_driver_nl80211_set_ap(void *priv,
+ if (params->unsol_bcast_probe_resp_interval &&
+ nl80211_unsol_bcast_probe_resp(bss, msg, params) < 0)
+ goto fail;
++
++ if (nl80211_mbssid(msg, params) < 0)
++ goto fail;
+ #endif /* CONFIG_IEEE80211AX */
+
+ #ifdef CONFIG_SAE
+diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
+index 06a52db..d8078bc 100644
+--- a/src/drivers/driver_nl80211_capa.c
++++ b/src/drivers/driver_nl80211_capa.c
+@@ -857,6 +857,30 @@ err:
+ }
+
+
++static void wiphy_info_mbssid(struct wpa_driver_capa *cap, struct nlattr *attr)
++{
++ struct nlattr *config[NL80211_MBSSID_CONFIG_ATTR_MAX + 1];
++
++ if (nla_parse_nested(config, NL80211_MBSSID_CONFIG_ATTR_MAX, attr,
++ NULL))
++ return;
++
++ if (!config[NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES])
++ return;
++
++ cap->mbssid_max_interfaces =
++ nla_get_u8(config[NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES]);
++
++ if (config[NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY])
++ cap->ema_max_periodicity =
++ nla_get_u8(config[NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY]);
++
++ wpa_printf(MSG_DEBUG,
++ "multiple_bssid: max interfaces %u, max profile periodicity %u\n",
++ cap->mbssid_max_interfaces, cap->ema_max_periodicity);
++}
++
++
+ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
+ {
+ struct nlattr *tb[NL80211_ATTR_MAX + 1];
+@@ -1106,6 +1130,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
+ if (tb[NL80211_ATTR_WIPHY_SELF_MANAGED_REG])
+ capa->flags |= WPA_DRIVER_FLAGS_SELF_MANAGED_REGULATORY;
+
++ if (tb[NL80211_ATTR_MBSSID_CONFIG])
++ wiphy_info_mbssid(capa, tb[NL80211_ATTR_MBSSID_CONFIG]);
++
+ return NL_SKIP;
+ }
+
+--
+2.18.0
+
diff --git a/recipes-wifi/hostapd/files/patches/patches.inc b/recipes-wifi/hostapd/files/patches/patches.inc
index b2f59b9..48bd493 100644
--- a/recipes-wifi/hostapd/files/patches/patches.inc
+++ b/recipes-wifi/hostapd/files/patches/patches.inc
@@ -71,10 +71,17 @@
file://mtk-0007-hostapd-mtk-Add-three-wire-PTA-ctrl-hostapd-vendor-c.patch \
file://mtk-0008-hostapd-mtk-Add-hostapd-iBF-control.patch \
file://mtk-0009-hostapd-mtk-Do-not-include-HE-capab-IE-if-associated.patch \
- file://mtk-0010-hostapd-mtk-Add-DFS-and-ZWDFS-support.patch \
- file://mtk-0011-hostapd-mtk-Add-amsdu-set-get-ctrl.patch \
- file://mtk-0012-hostapd-mtk-Add-he_ldpc-configuration.patch \
- file://mtk-0013-hostapd-mtk-Add-the-broadcast-destination-address-of.patch \
- file://mtk-0014-hostapd-mtk-Add-vendor-command-attribute-for-RTS-BW-.patch \
- file://mtk-0015-hostapd-mtk-6G-band-does-not-require-DFS.patch \
+ file://mtk-0010-hostapd-mtk-Add-DFS-detection-mode.patch \
+ file://mtk-0011-hostapd-mtk-Add-DFS-offchan-channel-switch.patch \
+ file://mtk-0012-hostapd-mtk-Add-amsdu-set-get-ctrl.patch \
+ file://mtk-0013-hostapd-mtk-Add-he_ldpc-configuration.patch \
+ file://mtk-0014-hostapd-mtk-Add-the-broadcast-destination-address-of.patch \
+ file://mtk-0015-hostapd-mtk-Add-vendor-command-attribute-for-RTS-BW-.patch \
+ file://mtk-0016-hostapd-mtk-6G-band-does-not-require-DFS.patch \
+ file://mtk-0016-hostapd-mtk-Add-available-color-bitmap.patch \
+ file://mtk-0017-hostapd-mtk-Fix-sending-wrong-VHT-operation-IE-in-CS.patch \
+ file://mtk-0018-hostapd-mtk-Add-sta-assisted-DFS-state-update-mechan.patch \
+ file://mtk-0019-hostapd-mtk-Fix-auto-ht-issue-when-switching-to-DFS-.patch \
+ file://mtk-0020-hostapd-mtk-Mark-DFS-channel-as-available-for-CSA.patch \
+ file://mtk-0020-hostapd-mtk-add-11v_mbss-and-ema-support.patch \
"
diff --git a/recipes-wifi/hostapd/files/src/src/ap/ubus.c b/recipes-wifi/hostapd/files/src/src/ap/ubus.c
index 5001225..ddd8644 100644
--- a/recipes-wifi/hostapd/files/src/src/ap/ubus.c
+++ b/recipes-wifi/hostapd/files/src/src/ap/ubus.c
@@ -1084,6 +1084,8 @@
}
__hostapd_bss_mgmt_enable(hapd, flags);
+
+ return 0;
}
diff --git a/recipes-wifi/hostapd/hostapd_2.10.3.bb b/recipes-wifi/hostapd/hostapd_2.10.3.bb
index df99b78..5f9d72f 100644
--- a/recipes-wifi/hostapd/hostapd_2.10.3.bb
+++ b/recipes-wifi/hostapd/hostapd_2.10.3.bb
@@ -23,7 +23,7 @@
file://hostapd-5G-7916.conf \
file://hostapd.service \
file://hostapd-init.sh \
- file://mac80211.sh \
+ file://mac80211-EHT.sh \
file://init-uci-config.service \
file://src \
file://001-rdkb-remove-ubus-support.patch;apply=no \
@@ -98,7 +98,7 @@
install -m 0644 ${WORKDIR}/hostapd.service ${D}${systemd_unitdir}/system
install -m 0755 ${WORKDIR}/hostapd-init.sh ${D}${base_libdir}/rdk
install -m 0644 ${WORKDIR}/init-uci-config.service ${D}${systemd_unitdir}/system
- install -m 0755 ${WORKDIR}/mac80211.sh ${D}${sbindir}
+ install -m 0755 ${WORKDIR}/mac80211-EHT.sh ${D}${sbindir}/mac80211.sh
}
FILES_${PN} += " \
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/319-wifi-mac80211-mesh-fast-xmit-support.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/319-wifi-mac80211-mesh-fast-xmit-support.patch
index 4bd3d4c..12e9cf5 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/319-wifi-mac80211-mesh-fast-xmit-support.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/319-wifi-mac80211-mesh-fast-xmit-support.patch
@@ -1,33 +1,32 @@
-From: Sriram R <quic_srirrama@quicinc.com>
-Date: Thu, 18 Aug 2022 12:35:42 +0530
+From: Felix Fietkau <nbd@nbd.name>
+Date: Sun, 26 Feb 2023 13:53:08 +0100
Subject: [PATCH] wifi: mac80211: mesh fast xmit support
-Currently fast xmit is supported in AP, STA and other device types where
-the destination doesn't change for the lifetime of its association by
-caching the static parts of the header that can be reused directly for
-every Tx such as addresses and updates only mutable header fields such as
-PN.
-This technique is not directly applicable for a Mesh device type due
-to the dynamic nature of the topology and protocol. The header is built
-based on the destination mesh device which is proxying a certain external
-device and based on the Mesh destination the next hop changes.
-And the RA/A1 which is the next hop for reaching the destination can
-vary during runtime as per the best route based on airtime. To accommodate
-these changes and to come up with a solution to avoid overhead during header
-generation, the headers comprising the MAC, Mesh and LLC part are cached
-whenever data for a certain external destination is sent.
-This cached header is reused every time a data is sent to that external
-destination.
+Previously, fast xmit only worked on interface types where initially a
+sta lookup is performed, and a cached header can be attached to the sta,
+requiring only some fields to be updated at runtime.
+
+This technique is not directly applicable for a mesh device type due
+to the dynamic nature of the topology and protocol. There are more
+addresses that need to be filled, and there is an extra header with a
+dynamic length based on the addressing mode.
+
+Change the code to cache entries contain a copy of the mesh subframe header +
+bridge tunnel header, as well as an embedded struct ieee80211_fast_tx, which
+contains the information for building the 802.11 header.
+
+Add a mesh specific early fast xmit call, which looks up a cached entry and
+adds only the mesh subframe header, before passing it over to the generic
+fast xmit code.
To ensure the changes in network are reflected in these cached headers,
flush affected cached entries on path changes, as well as other conditions
that currently trigger a fast xmit check in other modes (key changes etc.)
-In order to keep the cache small, use a short timeout for expiring cache
-entries.
+This code is loosely based on a previous implementation by:
+Sriram R <quic_srirrama@quicinc.com>
-Co-developed-by: Felix Fietkau <nbd@nbd.name>
-Signed-off-by: Sriram R <quic_srirrama@quicinc.com>
+Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
@@ -37,24 +36,23 @@
extern const struct cfg80211_ops mac80211_config_ops;
struct ieee80211_local;
-+struct mhdr_cache_entry;
++struct ieee80211_mesh_fast_tx;
/* Maximum number of broadcast/multicast frames to buffer when some of the
* associated stations are using power saving. */
-@@ -655,6 +656,20 @@ struct mesh_table {
+@@ -655,6 +656,19 @@ struct mesh_table {
atomic_t entries; /* Up to MAX_MESH_NEIGHBOURS */
};
+/**
-+ * struct mesh_hdr_cache - mesh fast xmit header cache
++ * struct mesh_tx_cache - mesh fast xmit header cache
+ *
-+ * @rhead: hash table containing struct mhdr_cache_entry, using skb DA as key
-+ * @walk_head: linked list containing all mhdr_cache_entry objects
-+ * @walk_lock: lock protecting walk_head and rhead
-+ * @enabled: indicates if header cache is initialized
++ * @rht: hash table containing struct ieee80211_mesh_fast_tx, using skb DA as key
++ * @walk_head: linked list containing all ieee80211_mesh_fast_tx objects
++ * @walk_lock: lock protecting walk_head and rht
+ */
-+struct mesh_hdr_cache {
-+ struct rhashtable rhead;
++struct mesh_tx_cache {
++ struct rhashtable rht;
+ struct hlist_head walk_head;
+ spinlock_t walk_lock;
+};
@@ -62,145 +60,263 @@
struct ieee80211_if_mesh {
struct timer_list housekeeping_timer;
struct timer_list mesh_path_timer;
-@@ -733,6 +748,7 @@ struct ieee80211_if_mesh {
+@@ -733,6 +747,7 @@ struct ieee80211_if_mesh {
struct mesh_table mpp_paths; /* Store paths for MPP&MAP */
int mesh_paths_generation;
int mpp_paths_generation;
-+ struct mesh_hdr_cache hdr_cache;
++ struct mesh_tx_cache tx_cache;
};
#ifdef CPTCFG_MAC80211_MESH
-@@ -1998,6 +2014,9 @@ int ieee80211_tx_control_port(struct wip
+@@ -1998,6 +2013,11 @@ int ieee80211_tx_control_port(struct wip
int link_id, u64 *cookie);
int ieee80211_probe_mesh_link(struct wiphy *wiphy, struct net_device *dev,
const u8 *buf, size_t len);
-+void __ieee80211_mesh_xmit_fast(struct ieee80211_sub_if_data *sdata,
-+ struct mhdr_cache_entry *entry,
-+ struct sk_buff *skb);
++void __ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata,
++ struct sta_info *sta,
++ struct ieee80211_fast_tx *fast_tx,
++ struct sk_buff *skb, bool ampdu,
++ const u8 *da, const u8 *sa);
/* HT */
void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata,
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
-@@ -780,6 +780,8 @@ static void ieee80211_mesh_housekeeping(
+@@ -10,6 +10,7 @@
+ #include <asm/unaligned.h>
+ #include "ieee80211_i.h"
+ #include "mesh.h"
++#include "wme.h"
+ #include "driver-ops.h"
+
+ static int mesh_allocated;
+@@ -698,6 +699,95 @@ ieee80211_mesh_update_bss_params(struct
+ __le32_to_cpu(he_oper->he_oper_params);
+ }
+
++bool ieee80211_mesh_xmit_fast(struct ieee80211_sub_if_data *sdata,
++ struct sk_buff *skb, u32 ctrl_flags)
++{
++ struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
++ struct ieee80211_mesh_fast_tx *entry;
++ struct ieee80211s_hdr *meshhdr;
++ u8 sa[ETH_ALEN] __aligned(2);
++ struct tid_ampdu_tx *tid_tx;
++ struct sta_info *sta;
++ bool copy_sa = false;
++ u16 ethertype;
++ u8 tid;
++
++ if (ctrl_flags & IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP)
++ return false;
++
++ if (ifmsh->mshcfg.dot11MeshNolearn)
++ return false;
++
++ /* Add support for these cases later */
++ if (ifmsh->ps_peers_light_sleep || ifmsh->ps_peers_deep_sleep)
++ return false;
++
++ if (is_multicast_ether_addr(skb->data))
++ return false;
++
++ ethertype = (skb->data[12] << 8) | skb->data[13];
++ if (ethertype < ETH_P_802_3_MIN)
++ return false;
++
++ if (skb->sk && skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS)
++ return false;
++
++ if (skb->ip_summed == CHECKSUM_PARTIAL) {
++ skb_set_transport_header(skb, skb_checksum_start_offset(skb));
++ if (skb_checksum_help(skb))
++ return false;
++ }
++
++ entry = mesh_fast_tx_get(sdata, skb->data);
++ if (!entry)
++ return false;
++
++ if (skb_headroom(skb) < entry->hdrlen + entry->fast_tx.hdr_len)
++ return false;
++
++ sta = rcu_dereference(entry->mpath->next_hop);
++ if (!sta)
++ return false;
++
++ tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
++ tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]);
++ if (tid_tx) {
++ if (!test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state))
++ return false;
++ if (tid_tx->timeout)
++ tid_tx->last_tx = jiffies;
++ }
++
++ skb = skb_share_check(skb, GFP_ATOMIC);
++ if (!skb)
++ return true;
++
++ skb_set_queue_mapping(skb, ieee80211_select_queue(sdata, sta, skb));
++
++ meshhdr = (struct ieee80211s_hdr *)entry->hdr;
++ if ((meshhdr->flags & MESH_FLAGS_AE) == MESH_FLAGS_AE_A5_A6) {
++ /* preserve SA from eth header for 6-addr frames */
++ ether_addr_copy(sa, skb->data + ETH_ALEN);
++ copy_sa = true;
++ }
++
++ memcpy(skb_push(skb, entry->hdrlen - 2 * ETH_ALEN), entry->hdr,
++ entry->hdrlen);
++
++ meshhdr = (struct ieee80211s_hdr *)skb->data;
++ put_unaligned_le32(atomic_inc_return(&sdata->u.mesh.mesh_seqnum),
++ &meshhdr->seqnum);
++ meshhdr->ttl = sdata->u.mesh.mshcfg.dot11MeshTTL;
++ if (copy_sa)
++ ether_addr_copy(meshhdr->eaddr2, sa);
++
++ skb_push(skb, 2 * ETH_ALEN);
++ __ieee80211_xmit_fast(sdata, sta, &entry->fast_tx, skb, tid_tx,
++ entry->mpath->dst, sdata->vif.addr);
++
++ return true;
++}
++
+ /**
+ * ieee80211_fill_mesh_addresses - fill addresses of a locally originated mesh frame
+ * @hdr: 802.11 frame header
+@@ -780,6 +870,8 @@ static void ieee80211_mesh_housekeeping(
changed = mesh_accept_plinks_update(sdata);
ieee80211_mbss_info_change_notify(sdata, changed);
-+ mesh_hdr_cache_gc(sdata);
++ mesh_fast_tx_gc(sdata);
+
mod_timer(&ifmsh->housekeeping_timer,
round_jiffies(jiffies +
IEEE80211_MESH_HOUSEKEEPING_INTERVAL));
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
-@@ -122,11 +122,49 @@ struct mesh_path {
+@@ -122,11 +122,41 @@ struct mesh_path {
u8 rann_snd_addr[ETH_ALEN];
u32 rann_metric;
unsigned long last_preq_to_root;
-+ unsigned long fast_xmit_check;
++ unsigned long fast_tx_check;
bool is_root;
bool is_gate;
u32 path_change_count;
};
-+#define MESH_HEADER_CACHE_MAX_SIZE 512
-+#define MESH_HEADER_CACHE_THRESHOLD_SIZE 384
-+#define MESH_HEADER_CACHE_TIMEOUT 8000 /* msecs */
-+#define MESH_HEADER_MAX_LEN 68 /* mac+mesh+rfc1042 hdr */
++#define MESH_FAST_TX_CACHE_MAX_SIZE 512
++#define MESH_FAST_TX_CACHE_THRESHOLD_SIZE 384
++#define MESH_FAST_TX_CACHE_TIMEOUT 8000 /* msecs */
+
+/**
-+ * struct mhdr_cache_entry - Cached Mesh header entry
-+ * @addr_key: The Ethernet DA which is the key for this entry
-+ * @hdr: The cached header
-+ * @machdr_len: Total length of the mac header
-+ * @hdrlen: Length of this header entry
-+ * @key: Key corresponding to the nexthop stored in the header
-+ * @pn_offs: Offset to PN which is updated for every xmit
-+ * @band: band used for tx
-+ * @walk_list: list containing all the cached header entries
++ * struct ieee80211_mesh_fast_tx - cached mesh fast tx entry
+ * @rhash: rhashtable pointer
-+ * @mpath: The Mesh path corresponding to the Mesh DA
-+ * @mppath: The MPP entry corresponding to this DA
++ * @addr_key: The Ethernet DA which is the key for this entry
++ * @fast_tx: base fast_tx data
++ * @hdr: cached mesh and rfc1042 headers
++ * @hdrlen: length of mesh + rfc1042
++ * @walk_list: list containing all the fast tx entries
++ * @mpath: mesh path corresponding to the Mesh DA
++ * @mppath: MPP entry corresponding to this DA
+ * @timestamp: Last used time of this entry
-+ * @rcu: rcu to free this entry
-+ * @path_change_count: Stored path change value corresponding to the mpath
+ */
-+struct mhdr_cache_entry {
++struct ieee80211_mesh_fast_tx {
++ struct rhash_head rhash;
+ u8 addr_key[ETH_ALEN] __aligned(2);
-+ u8 hdr[MESH_HEADER_MAX_LEN];
-+ u16 machdr_len;
++
++ struct ieee80211_fast_tx fast_tx;
++ u8 hdr[sizeof(struct ieee80211s_hdr) + sizeof(rfc1042_header)];
+ u16 hdrlen;
-+ u8 pn_offs;
-+ u8 band;
-+ struct ieee80211_key __rcu *key;
-+ struct hlist_node walk_list;
-+ struct rhash_head rhash;
++
+ struct mesh_path *mpath, *mppath;
++ struct hlist_node walk_list;
+ unsigned long timestamp;
-+ struct rcu_head rcu;
+};
+
/* Recent multicast cache */
/* RMC_BUCKETS must be a power of 2, maximum 256 */
#define RMC_BUCKETS 256
-@@ -298,6 +336,15 @@ void mesh_path_discard_frame(struct ieee
+@@ -298,6 +328,20 @@ void mesh_path_discard_frame(struct ieee
void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata);
bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt);
-+struct mhdr_cache_entry *
-+mesh_get_cached_hdr(struct ieee80211_sub_if_data *sdata, const u8 *addr);
-+void mesh_cache_hdr(struct ieee80211_sub_if_data *sdata,
-+ struct sk_buff *skb, struct mesh_path *mpath);
-+void mesh_hdr_cache_gc(struct ieee80211_sub_if_data *sdata);
-+void mesh_hdr_cache_flush(struct ieee80211_sub_if_data *sdata, const u8 *addr,
-+ bool is_mpp);
-+void mesh_refresh_path(struct ieee80211_sub_if_data *sdata,
++struct ieee80211_mesh_fast_tx *
++mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata, const u8 *addr);
++bool ieee80211_mesh_xmit_fast(struct ieee80211_sub_if_data *sdata,
++ struct sk_buff *skb, u32 ctrl_flags);
++void mesh_fast_tx_cache(struct ieee80211_sub_if_data *sdata,
++ struct sk_buff *skb, struct mesh_path *mpath);
++void mesh_fast_tx_gc(struct ieee80211_sub_if_data *sdata);
++void mesh_fast_tx_flush_addr(struct ieee80211_sub_if_data *sdata,
++ const u8 *addr);
++void mesh_fast_tx_flush_mpath(struct mesh_path *mpath);
++void mesh_fast_tx_flush_sta(struct ieee80211_sub_if_data *sdata,
++ struct sta_info *sta);
++void mesh_path_refresh(struct ieee80211_sub_if_data *sdata,
+ struct mesh_path *mpath, const u8 *addr);
#ifdef CPTCFG_MAC80211_MESH
static inline
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
-@@ -491,8 +491,11 @@ static u32 hwmp_route_info_get(struct ie
+@@ -394,6 +394,7 @@ static u32 hwmp_route_info_get(struct ie
+ u32 orig_sn, orig_metric;
+ unsigned long orig_lifetime, exp_time;
+ u32 last_hop_metric, new_metric;
++ bool flush_mpath = false;
+ bool process = true;
+ u8 hopcount;
+
+@@ -491,8 +492,10 @@ static u32 hwmp_route_info_get(struct ie
}
if (fresh_info) {
- if (rcu_access_pointer(mpath->next_hop) != sta)
+ if (rcu_access_pointer(mpath->next_hop) != sta) {
mpath->path_change_count++;
-+ mesh_hdr_cache_flush(mpath->sdata, mpath->dst,
-+ false);
++ flush_mpath = true;
+ }
mesh_path_assign_nexthop(mpath, sta);
mpath->flags |= MESH_PATH_SN_VALID;
mpath->metric = new_metric;
-@@ -539,8 +542,11 @@ static u32 hwmp_route_info_get(struct ie
+@@ -502,6 +505,8 @@ static u32 hwmp_route_info_get(struct ie
+ mpath->hop_count = hopcount;
+ mesh_path_activate(mpath);
+ spin_unlock_bh(&mpath->state_lock);
++ if (flush_mpath)
++ mesh_fast_tx_flush_mpath(mpath);
+ ewma_mesh_fail_avg_init(&sta->mesh->fail_avg);
+ /* init it at a low value - 0 start is tricky */
+ ewma_mesh_fail_avg_add(&sta->mesh->fail_avg, 1);
+@@ -539,8 +544,10 @@ static u32 hwmp_route_info_get(struct ie
}
if (fresh_info) {
- if (rcu_access_pointer(mpath->next_hop) != sta)
+ if (rcu_access_pointer(mpath->next_hop) != sta) {
mpath->path_change_count++;
-+ mesh_hdr_cache_flush(mpath->sdata, mpath->dst,
-+ false);
++ flush_mpath = true;
+ }
mesh_path_assign_nexthop(mpath, sta);
mpath->metric = last_hop_metric;
mpath->exp_time = time_after(mpath->exp_time, exp_time)
-@@ -977,7 +983,7 @@ free:
- * Locking: the function must be called from within a rcu read lock block.
- *
- */
--static void mesh_queue_preq(struct mesh_path *mpath, u8 flags)
-+void mesh_queue_preq(struct mesh_path *mpath, u8 flags)
- {
- struct ieee80211_sub_if_data *sdata = mpath->sdata;
- struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
-@@ -1215,6 +1221,20 @@ static int mesh_nexthop_lookup_nolearn(s
+@@ -548,6 +555,8 @@ static u32 hwmp_route_info_get(struct ie
+ mpath->hop_count = 1;
+ mesh_path_activate(mpath);
+ spin_unlock_bh(&mpath->state_lock);
++ if (flush_mpath)
++ mesh_fast_tx_flush_mpath(mpath);
+ ewma_mesh_fail_avg_init(&sta->mesh->fail_avg);
+ /* init it at a low value - 0 start is tricky */
+ ewma_mesh_fail_avg_add(&sta->mesh->fail_avg, 1);
+@@ -1215,6 +1224,20 @@ static int mesh_nexthop_lookup_nolearn(s
return 0;
}
-+void mesh_refresh_path(struct ieee80211_sub_if_data *sdata,
++void mesh_path_refresh(struct ieee80211_sub_if_data *sdata,
+ struct mesh_path *mpath, const u8 *addr)
+{
+ if (mpath->flags & (MESH_PATH_REQ_QUEUED | MESH_PATH_FIXED |
@@ -217,7 +333,7 @@
/**
* mesh_nexthop_lookup - put the appropriate next hop on a mesh frame. Calling
* this function is considered "using" the associated mpath, so preempt a path
-@@ -1242,19 +1262,18 @@ int mesh_nexthop_lookup(struct ieee80211
+@@ -1242,19 +1265,15 @@ int mesh_nexthop_lookup(struct ieee80211
if (!mpath || !(mpath->flags & MESH_PATH_ACTIVE))
return -ENOENT;
@@ -228,18 +344,15 @@
- !(mpath->flags & MESH_PATH_RESOLVING) &&
- !(mpath->flags & MESH_PATH_FIXED))
- mesh_queue_preq(mpath, PREQ_Q_F_START | PREQ_Q_F_REFRESH);
-+ mesh_refresh_path(sdata, mpath, hdr->addr4);
++ mesh_path_refresh(sdata, mpath, hdr->addr4);
next_hop = rcu_dereference(mpath->next_hop);
if (next_hop) {
memcpy(hdr->addr1, next_hop->sta.addr, ETH_ALEN);
memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN);
ieee80211_mps_set_frame_flags(sdata, next_hop, hdr);
-+ /* Cache the whole header so as to use next time rather than resolving
-+ * and building it every time
-+ */
+ if (ieee80211_hw_check(&sdata->local->hw, SUPPORT_FAST_XMIT))
-+ mesh_cache_hdr(sdata, skb, mpath);
++ mesh_fast_tx_cache(sdata, skb, mpath);
return 0;
}
@@ -257,37 +370,37 @@
.hashfn = mesh_table_hash,
};
-+static const struct rhashtable_params mesh_hdr_rht_params = {
++static const struct rhashtable_params fast_tx_rht_params = {
+ .nelem_hint = 10,
+ .automatic_shrinking = true,
-+ .key_len = ETH_ALEN,
-+ .key_offset = offsetof(struct mhdr_cache_entry, addr_key),
-+ .head_offset = offsetof(struct mhdr_cache_entry, rhash),
++ .key_len = ETH_ALEN,
++ .key_offset = offsetof(struct ieee80211_mesh_fast_tx, addr_key),
++ .head_offset = offsetof(struct ieee80211_mesh_fast_tx, rhash),
+ .hashfn = mesh_table_hash,
+};
+
-+static void __mesh_hdr_cache_entry_free(void *ptr, void *tblptr)
++static void __mesh_fast_tx_entry_free(void *ptr, void *tblptr)
+{
-+ struct mhdr_cache_entry *mhdr = ptr;
++ struct ieee80211_mesh_fast_tx *entry = ptr;
+
-+ kfree_rcu(mhdr, rcu);
++ kfree_rcu(entry, fast_tx.rcu_head);
+}
+
-+static void mesh_hdr_cache_deinit(struct ieee80211_sub_if_data *sdata)
++static void mesh_fast_tx_deinit(struct ieee80211_sub_if_data *sdata)
+{
-+ struct mesh_hdr_cache *cache;
++ struct mesh_tx_cache *cache;
+
-+ cache = &sdata->u.mesh.hdr_cache;
-+ rhashtable_free_and_destroy(&cache->rhead,
-+ __mesh_hdr_cache_entry_free, NULL);
++ cache = &sdata->u.mesh.tx_cache;
++ rhashtable_free_and_destroy(&cache->rht,
++ __mesh_fast_tx_entry_free, NULL);
+}
+
-+static void mesh_hdr_cache_init(struct ieee80211_sub_if_data *sdata)
++static void mesh_fast_tx_init(struct ieee80211_sub_if_data *sdata)
+{
-+ struct mesh_hdr_cache *cache;
++ struct mesh_tx_cache *cache;
+
-+ cache = &sdata->u.mesh.hdr_cache;
-+ rhashtable_init(&cache->rhead, &mesh_hdr_rht_params);
++ cache = &sdata->u.mesh.tx_cache;
++ rhashtable_init(&cache->rht, &fast_tx_rht_params);
+ INIT_HLIST_HEAD(&cache->walk_head);
+ spin_lock_init(&cache->walk_lock);
+}
@@ -295,66 +408,75 @@
static inline bool mpath_expired(struct mesh_path *mpath)
{
return (mpath->flags & MESH_PATH_ACTIVE) &&
-@@ -381,6 +417,211 @@ struct mesh_path *mesh_path_new(struct i
+@@ -381,6 +417,243 @@ struct mesh_path *mesh_path_new(struct i
return new_mpath;
}
-+struct mhdr_cache_entry *
-+mesh_get_cached_hdr(struct ieee80211_sub_if_data *sdata, const u8 *addr)
++static void mesh_fast_tx_entry_free(struct mesh_tx_cache *cache,
++ struct ieee80211_mesh_fast_tx *entry)
+{
-+ struct mesh_path *mpath, *mppath;
-+ struct mhdr_cache_entry *entry;
-+ struct mesh_hdr_cache *cache;
++ hlist_del_rcu(&entry->walk_list);
++ rhashtable_remove_fast(&cache->rht, &entry->rhash, fast_tx_rht_params);
++ kfree_rcu(entry, fast_tx.rcu_head);
++}
+
-+ cache = &sdata->u.mesh.hdr_cache;
-+ entry = rhashtable_lookup(&cache->rhead, addr, mesh_hdr_rht_params);
++struct ieee80211_mesh_fast_tx *
++mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata, const u8 *addr)
++{
++ struct ieee80211_mesh_fast_tx *entry;
++ struct mesh_tx_cache *cache;
++
++ cache = &sdata->u.mesh.tx_cache;
++ entry = rhashtable_lookup(&cache->rht, addr, fast_tx_rht_params);
+ if (!entry)
+ return NULL;
+
-+ mpath = rcu_dereference(entry->mpath);
-+ mppath = rcu_dereference(entry->mppath);
-+ if (!(mpath->flags & MESH_PATH_ACTIVE) || mpath_expired(mpath))
++ if (!(entry->mpath->flags & MESH_PATH_ACTIVE) ||
++ mpath_expired(entry->mpath)) {
++ spin_lock_bh(&cache->walk_lock);
++ entry = rhashtable_lookup(&cache->rht, addr, fast_tx_rht_params);
++ if (entry)
++ mesh_fast_tx_entry_free(cache, entry);
++ spin_unlock_bh(&cache->walk_lock);
+ return NULL;
++ }
+
-+ mesh_refresh_path(sdata, mpath, NULL);
-+ if (mppath)
-+ mppath->exp_time = jiffies;
++ mesh_path_refresh(sdata, entry->mpath, NULL);
++ if (entry->mppath)
++ entry->mppath->exp_time = jiffies;
+ entry->timestamp = jiffies;
+
+ return entry;
+}
+
-+void mesh_cache_hdr(struct ieee80211_sub_if_data *sdata,
-+ struct sk_buff *skb, struct mesh_path *mpath)
++void mesh_fast_tx_cache(struct ieee80211_sub_if_data *sdata,
++ struct sk_buff *skb, struct mesh_path *mpath)
+{
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-+ struct mesh_hdr_cache *cache;
-+ struct mhdr_cache_entry *mhdr, *old_mhdr;
++ struct ieee80211_mesh_fast_tx *entry, *prev;
++ struct ieee80211_mesh_fast_tx build = {};
+ struct ieee80211s_hdr *meshhdr;
-+ struct sta_info *next_hop;
++ struct mesh_tx_cache *cache;
+ struct ieee80211_key *key;
+ struct mesh_path *mppath;
-+ u16 meshhdr_len;
-+ u8 pn_offs = 0;
-+ int hdrlen;
-+
-+ if (sdata->noack_map)
-+ return;
++ struct sta_info *sta;
++ u8 *qc;
+
-+ if (!ieee80211_is_data_qos(hdr->frame_control))
++ if (sdata->noack_map ||
++ !ieee80211_is_data_qos(hdr->frame_control))
+ return;
+
-+ hdrlen = ieee80211_hdrlen(hdr->frame_control);
-+ meshhdr = (struct ieee80211s_hdr *)(skb->data + hdrlen);
-+ meshhdr_len = ieee80211_get_mesh_hdrlen(meshhdr);
++ build.fast_tx.hdr_len = ieee80211_hdrlen(hdr->frame_control);
++ meshhdr = (struct ieee80211s_hdr *)(skb->data + build.fast_tx.hdr_len);
++ build.hdrlen = ieee80211_get_mesh_hdrlen(meshhdr);
+
-+ cache = &sdata->u.mesh.hdr_cache;
-+ if (atomic_read(&cache->rhead.nelems) >= MESH_HEADER_CACHE_MAX_SIZE)
++ cache = &sdata->u.mesh.tx_cache;
++ if (atomic_read(&cache->rht.nelems) >= MESH_FAST_TX_CACHE_MAX_SIZE)
+ return;
+
-+ next_hop = rcu_dereference(mpath->next_hop);
-+ if (!next_hop)
++ sta = rcu_dereference(mpath->next_hop);
++ if (!sta)
+ return;
+
+ if ((meshhdr->flags & MESH_FLAGS_AE) == MESH_FLAGS_AE_A5_A6) {
@@ -362,6 +484,7 @@
+ mppath = mpp_path_lookup(sdata, meshhdr->eaddr1);
+ if (!mppath)
+ return;
++ build.mppath = mppath;
+ } else if (ieee80211_has_a4(hdr->frame_control)) {
+ mppath = mpath;
+ } else {
@@ -369,14 +492,20 @@
+ }
+
+ /* rate limit, in case fast xmit can't be enabled */
-+ if (mppath->fast_xmit_check == jiffies)
++ if (mppath->fast_tx_check == jiffies)
+ return;
+
-+ mppath->fast_xmit_check = jiffies;
++ mppath->fast_tx_check = jiffies;
+
-+ key = rcu_access_pointer(next_hop->ptk[next_hop->ptk_idx]);
++ /*
++ * Same use of the sta lock as in ieee80211_check_fast_xmit, in order
++ * to protect against concurrent sta key updates.
++ */
++ spin_lock_bh(&sta->lock);
++ key = rcu_access_pointer(sta->ptk[sta->ptk_idx]);
+ if (!key)
+ key = rcu_access_pointer(sdata->default_unicast_key);
++ build.fast_tx.key = key;
+
+ if (key) {
+ bool gen_iv, iv_spc;
@@ -386,157 +515,184 @@
+
+ if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) ||
+ (key->flags & KEY_FLAG_TAINTED))
-+ return;
++ goto unlock_sta;
+
+ switch (key->conf.cipher) {
+ case WLAN_CIPHER_SUITE_CCMP:
+ case WLAN_CIPHER_SUITE_CCMP_256:
+ if (gen_iv)
-+ pn_offs = hdrlen;
++ build.fast_tx.pn_offs = build.fast_tx.hdr_len;
+ if (gen_iv || iv_spc)
-+ hdrlen += IEEE80211_CCMP_HDR_LEN;
++ build.fast_tx.hdr_len += IEEE80211_CCMP_HDR_LEN;
+ break;
+ case WLAN_CIPHER_SUITE_GCMP:
+ case WLAN_CIPHER_SUITE_GCMP_256:
+ if (gen_iv)
-+ pn_offs = hdrlen;
++ build.fast_tx.pn_offs = build.fast_tx.hdr_len;
+ if (gen_iv || iv_spc)
-+ hdrlen += IEEE80211_GCMP_HDR_LEN;
++ build.fast_tx.hdr_len += IEEE80211_GCMP_HDR_LEN;
+ break;
+ default:
-+ return;
++ goto unlock_sta;
+ }
+ }
+
-+ if (WARN_ON_ONCE(hdrlen + meshhdr_len + sizeof(rfc1042_header) >
-+ MESH_HEADER_MAX_LEN))
-+ return;
++ memcpy(build.addr_key, mppath->dst, ETH_ALEN);
++ build.timestamp = jiffies;
++ build.fast_tx.band = info->band;
++ build.fast_tx.da_offs = offsetof(struct ieee80211_hdr, addr3);
++ build.fast_tx.sa_offs = offsetof(struct ieee80211_hdr, addr4);
++ build.mpath = mpath;
++ memcpy(build.hdr, meshhdr, build.hdrlen);
++ memcpy(build.hdr + build.hdrlen, rfc1042_header, sizeof(rfc1042_header));
++ build.hdrlen += sizeof(rfc1042_header);
++ memcpy(build.fast_tx.hdr, hdr, build.fast_tx.hdr_len);
+
-+ mhdr = kzalloc(sizeof(*mhdr), GFP_ATOMIC);
-+ if (!mhdr)
-+ return;
++ hdr = (struct ieee80211_hdr *)build.fast_tx.hdr;
++ if (build.fast_tx.key)
++ hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
+
-+ memcpy(mhdr->addr_key, mppath->dst, ETH_ALEN);
-+ mhdr->machdr_len = hdrlen;
-+ mhdr->hdrlen = mhdr->machdr_len + meshhdr_len + sizeof(rfc1042_header);
-+ rcu_assign_pointer(mhdr->mpath, mpath);
-+ if (meshhdr->flags & MESH_FLAGS_AE)
-+ rcu_assign_pointer(mhdr->mppath, mppath);
-+ rcu_assign_pointer(mhdr->key, key);
-+ mhdr->timestamp = jiffies;
-+ mhdr->band = info->band;
-+ mhdr->pn_offs = pn_offs;
++ qc = ieee80211_get_qos_ctl(hdr);
++ qc[1] |= IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT >> 8;
+
-+ if (pn_offs) {
-+ memcpy(mhdr->hdr, skb->data, pn_offs);
-+ memcpy(mhdr->hdr + mhdr->machdr_len, skb->data + pn_offs,
-+ mhdr->hdrlen - mhdr->machdr_len);
-+ } else {
-+ memcpy(mhdr->hdr, skb->data, mhdr->hdrlen);
++ entry = kmemdup(&build, sizeof(build), GFP_ATOMIC);
++ if (!entry)
++ goto unlock_sta;
++
++ spin_lock(&cache->walk_lock);
++ prev = rhashtable_lookup_get_insert_fast(&cache->rht,
++ &entry->rhash,
++ fast_tx_rht_params);
++ if (unlikely(IS_ERR(prev))) {
++ kfree(entry);
++ goto unlock_cache;
+ }
+
-+ if (key) {
-+ hdr = (struct ieee80211_hdr *)mhdr->hdr;
-+ hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
++ /*
++ * replace any previous entry in the hash table, in case we're
++ * replacing it with a different type (e.g. mpath -> mpp)
++ */
++ if (unlikely(prev)) {
++ rhashtable_replace_fast(&cache->rht, &prev->rhash,
++ &entry->rhash, fast_tx_rht_params);
++ hlist_del_rcu(&prev->walk_list);
++ kfree_rcu(prev, fast_tx.rcu_head);
+ }
+
-+ spin_lock_bh(&cache->walk_lock);
-+ old_mhdr = rhashtable_lookup_get_insert_fast(&cache->rhead,
-+ &mhdr->rhash,
-+ mesh_hdr_rht_params);
-+ if (likely(!old_mhdr))
-+ hlist_add_head(&mhdr->walk_list, &cache->walk_head);
-+ else
-+ kfree(mhdr);
-+ spin_unlock_bh(&cache->walk_lock);
-+}
++ hlist_add_head(&entry->walk_list, &cache->walk_head);
+
-+static void mesh_hdr_cache_entry_free(struct mesh_hdr_cache *cache,
-+ struct mhdr_cache_entry *entry)
-+{
-+ hlist_del_rcu(&entry->walk_list);
-+ rhashtable_remove_fast(&cache->rhead, &entry->rhash, mesh_hdr_rht_params);
-+ kfree_rcu(entry, rcu);
++unlock_cache:
++ spin_unlock(&cache->walk_lock);
++unlock_sta:
++ spin_unlock_bh(&sta->lock);
+}
+
-+void mesh_hdr_cache_gc(struct ieee80211_sub_if_data *sdata)
++void mesh_fast_tx_gc(struct ieee80211_sub_if_data *sdata)
+{
-+ unsigned long timeout = msecs_to_jiffies(MESH_HEADER_CACHE_TIMEOUT);
-+ struct mesh_hdr_cache *cache;
-+ struct mhdr_cache_entry *entry;
++ unsigned long timeout = msecs_to_jiffies(MESH_FAST_TX_CACHE_TIMEOUT);
++ struct mesh_tx_cache *cache;
++ struct ieee80211_mesh_fast_tx *entry;
+ struct hlist_node *n;
+
-+ cache = &sdata->u.mesh.hdr_cache;
-+ if (atomic_read(&cache->rhead.nelems) < MESH_HEADER_CACHE_THRESHOLD_SIZE)
++ cache = &sdata->u.mesh.tx_cache;
++ if (atomic_read(&cache->rht.nelems) < MESH_FAST_TX_CACHE_THRESHOLD_SIZE)
+ return;
+
+ spin_lock_bh(&cache->walk_lock);
+ hlist_for_each_entry_safe(entry, n, &cache->walk_head, walk_list)
+ if (!time_is_after_jiffies(entry->timestamp + timeout))
-+ mesh_hdr_cache_entry_free(cache, entry);
++ mesh_fast_tx_entry_free(cache, entry);
+ spin_unlock_bh(&cache->walk_lock);
+}
+
-+void mesh_hdr_cache_flush(struct ieee80211_sub_if_data *sdata, const u8 *addr,
-+ bool is_mpp)
++void mesh_fast_tx_flush_mpath(struct mesh_path *mpath)
+{
-+ struct mesh_hdr_cache *cache = &sdata->u.mesh.hdr_cache;
-+ struct mhdr_cache_entry *entry;
++ struct ieee80211_sub_if_data *sdata = mpath->sdata;
++ struct mesh_tx_cache *cache = &sdata->u.mesh.tx_cache;
++ struct ieee80211_mesh_fast_tx *entry;
+ struct hlist_node *n;
+
-+ cache = &sdata->u.mesh.hdr_cache;
++ cache = &sdata->u.mesh.tx_cache;
+ spin_lock_bh(&cache->walk_lock);
++ hlist_for_each_entry_safe(entry, n, &cache->walk_head, walk_list)
++ if (entry->mpath == mpath)
++ mesh_fast_tx_entry_free(cache, entry);
++ spin_unlock_bh(&cache->walk_lock);
++}
+
-+ /* Only one header per mpp address is expected in the header cache */
-+ if (is_mpp) {
-+ entry = rhashtable_lookup(&cache->rhead, addr,
-+ mesh_hdr_rht_params);
-+ if (entry)
-+ mesh_hdr_cache_entry_free(cache, entry);
-+ goto out;
-+ }
++void mesh_fast_tx_flush_sta(struct ieee80211_sub_if_data *sdata,
++ struct sta_info *sta)
++{
++ struct mesh_tx_cache *cache = &sdata->u.mesh.tx_cache;
++ struct ieee80211_mesh_fast_tx *entry;
++ struct hlist_node *n;
+
++ cache = &sdata->u.mesh.tx_cache;
++ spin_lock_bh(&cache->walk_lock);
+ hlist_for_each_entry_safe(entry, n, &cache->walk_head, walk_list)
-+ if (ether_addr_equal(entry->mpath->dst, addr))
-+ mesh_hdr_cache_entry_free(cache, entry);
++ if (rcu_access_pointer(entry->mpath->next_hop) == sta)
++ mesh_fast_tx_entry_free(cache, entry);
++ spin_unlock_bh(&cache->walk_lock);
++}
++
++void mesh_fast_tx_flush_addr(struct ieee80211_sub_if_data *sdata,
++ const u8 *addr)
++{
++ struct mesh_tx_cache *cache = &sdata->u.mesh.tx_cache;
++ struct ieee80211_mesh_fast_tx *entry;
+
-+out:
++ cache = &sdata->u.mesh.tx_cache;
++ spin_lock_bh(&cache->walk_lock);
++ entry = rhashtable_lookup(&cache->rht, addr, fast_tx_rht_params);
++ if (entry)
++ mesh_fast_tx_entry_free(cache, entry);
+ spin_unlock_bh(&cache->walk_lock);
+}
+
/**
* mesh_path_add - allocate and add a new path to the mesh path table
* @dst: destination address of the path (ETH_ALEN length)
-@@ -521,6 +762,8 @@ static void mesh_path_free_rcu(struct me
+@@ -464,6 +737,8 @@ int mpp_path_add(struct ieee80211_sub_if
- static void __mesh_path_del(struct mesh_table *tbl, struct mesh_path *mpath)
+ if (ret)
+ kfree(new_mpath);
++ else
++ mesh_fast_tx_flush_addr(sdata, dst);
+
+ sdata->u.mesh.mpp_paths_generation++;
+ return ret;
+@@ -523,6 +798,10 @@ static void __mesh_path_del(struct mesh_
{
-+ mesh_hdr_cache_flush(mpath->sdata, mpath->dst,
-+ tbl == &mpath->sdata->u.mesh.mpp_paths);
hlist_del_rcu(&mpath->walk_list);
rhashtable_remove_fast(&tbl->rhead, &mpath->rhash, mesh_rht_params);
++ if (tbl == &mpath->sdata->u.mesh.mpp_paths)
++ mesh_fast_tx_flush_addr(mpath->sdata, mpath->dst);
++ else
++ mesh_fast_tx_flush_mpath(mpath);
mesh_path_free_rcu(tbl, mpath);
-@@ -747,6 +990,7 @@ void mesh_path_fix_nexthop(struct mesh_p
+ }
+
+@@ -747,6 +1026,7 @@ void mesh_path_fix_nexthop(struct mesh_p
mpath->exp_time = 0;
mpath->flags = MESH_PATH_FIXED | MESH_PATH_SN_VALID;
mesh_path_activate(mpath);
-+ mesh_hdr_cache_flush(mpath->sdata, mpath->dst, false);
++ mesh_fast_tx_flush_mpath(mpath);
spin_unlock_bh(&mpath->state_lock);
ewma_mesh_fail_avg_init(&next_hop->mesh->fail_avg);
/* init it at a low value - 0 start is tricky */
-@@ -758,6 +1002,7 @@ void mesh_pathtbl_init(struct ieee80211_
+@@ -758,6 +1038,7 @@ void mesh_pathtbl_init(struct ieee80211_
{
mesh_table_init(&sdata->u.mesh.mesh_paths);
mesh_table_init(&sdata->u.mesh.mpp_paths);
-+ mesh_hdr_cache_init(sdata);
++ mesh_fast_tx_init(sdata);
}
static
-@@ -785,6 +1030,7 @@ void mesh_path_expire(struct ieee80211_s
+@@ -785,6 +1066,7 @@ void mesh_path_expire(struct ieee80211_s
void mesh_pathtbl_unregister(struct ieee80211_sub_if_data *sdata)
{
-+ mesh_hdr_cache_deinit(sdata);
++ mesh_fast_tx_deinit(sdata);
mesh_table_free(&sdata->u.mesh.mesh_paths);
mesh_table_free(&sdata->u.mesh.mpp_paths);
}
@@ -565,7 +721,7 @@
+
+ /* flush fast xmit cache if the address path changed */
+ if (update)
-+ mesh_hdr_cache_flush(sdata, proxied_addr, true);
++ mesh_fast_tx_flush_addr(sdata, proxied_addr);
+
rcu_read_unlock();
}
@@ -577,168 +733,97 @@
return;
+ if (ieee80211_vif_is_mesh(&sdata->vif))
-+ mesh_hdr_cache_flush(sdata, sta->addr, false);
++ mesh_fast_tx_flush_sta(sdata, sta);
+
/* Locking here protects both the pointer itself, and against concurrent
* invocations winning data access races to, e.g., the key pointer that
* is used.
-@@ -3723,6 +3726,155 @@ free:
- kfree_skb(skb);
- }
+@@ -3402,6 +3405,9 @@ static bool ieee80211_amsdu_aggregate(st
+ if (sdata->vif.offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED)
+ return false;
-+void __ieee80211_mesh_xmit_fast(struct ieee80211_sub_if_data *sdata,
-+ struct mhdr_cache_entry *entry,
-+ struct sk_buff *skb)
-+{
-+ struct ieee80211_local *local = sdata->local;
-+ struct ieee80211_tx_data tx = {};
-+ struct ieee80211_tx_info *info;
-+ struct ieee80211_key *key;
-+ struct ieee80211_hdr *hdr;
-+ struct mesh_path *mpath;
-+ ieee80211_tx_result r;
-+ struct sta_info *sta;
-+ u8 tid;
-+
-+ if (!IS_ENABLED(CPTCFG_MAC80211_MESH))
-+ return;
-+
-+ info = IEEE80211_SKB_CB(skb);
-+ memset(info, 0, sizeof(*info));
-+ info->band = entry->band;
-+ info->control.vif = &sdata->vif;
-+ info->flags = IEEE80211_TX_CTL_FIRST_FRAGMENT |
-+ IEEE80211_TX_CTL_DONTFRAG;
-+
-+ info->control.flags = IEEE80211_TX_CTRL_FAST_XMIT;
-+
-+#ifdef CONFIG_MAC80211_DEBUGFS
-+ if (local->force_tx_status)
-+ info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
-+#endif
-+
-+ mpath = entry->mpath;
-+ key = entry->key;
-+ sta = rcu_dereference(mpath->next_hop);
-+
-+ __skb_queue_head_init(&tx.skbs);
-+
-+ tx.flags = IEEE80211_TX_UNICAST;
-+ tx.local = local;
-+ tx.sdata = sdata;
-+ tx.sta = sta;
-+ tx.key = key;
-+ tx.skb = skb;
-+
-+ hdr = (struct ieee80211_hdr *)skb->data;
-+ tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
-+ *ieee80211_get_qos_ctl(hdr) = tid;
-+
-+ ieee80211_aggr_check(sdata, sta, skb);
-+
-+ if (ieee80211_queue_skb(local, sdata, sta, skb))
-+ return;
-+
-+ r = ieee80211_xmit_fast_finish(sdata, sta, entry->pn_offs, key, &tx);
-+ if (r == TX_DROP) {
-+ kfree_skb(skb);
-+ return;
-+ }
-+
-+ __skb_queue_tail(&tx.skbs, skb);
-+ ieee80211_tx_frags(local, &sdata->vif, sta, &tx.skbs, false);
-+}
-+
-+
-+static bool ieee80211_mesh_xmit_fast(struct ieee80211_sub_if_data *sdata,
-+ struct sk_buff *skb, u32 ctrl_flags)
-+{
-+ struct ieee80211_local *local = sdata->local;
-+ struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
-+ struct mhdr_cache_entry *entry;
-+ struct ieee80211s_hdr *meshhdr;
-+ u8 sa[ETH_ALEN] __aligned(2);
-+ struct sta_info *sta;
-+ bool copy_sa = false;
-+ u16 ethertype;
-+
-+ if (ctrl_flags & IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP)
-+ return false;
-+
-+ if (ifmsh->mshcfg.dot11MeshNolearn)
-+ return false;
-+
-+ if (!ieee80211_hw_check(&local->hw, SUPPORT_FAST_XMIT))
-+ return false;
-+
-+ /* Add support for these cases later */
-+ if (ifmsh->ps_peers_light_sleep || ifmsh->ps_peers_deep_sleep)
-+ return false;
-+
-+ if (is_multicast_ether_addr(skb->data))
-+ return false;
-+
-+ ethertype = (skb->data[12] << 8) | skb->data[13];
-+ if (ethertype < ETH_P_802_3_MIN)
-+ return false;
-+
-+ if (skb->sk && skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS)
-+ return false;
-+
-+ if (skb->ip_summed == CHECKSUM_PARTIAL) {
-+ skb_set_transport_header(skb, skb_checksum_start_offset(skb));
-+ if (skb_checksum_help(skb))
-+ return false;
-+ }
-+
-+ entry = mesh_get_cached_hdr(sdata, skb->data);
-+ if (!entry)
-+ return false;
-+
-+ /* Avoid extra work in this path */
-+ if (skb_headroom(skb) < (entry->hdrlen - ETH_HLEN + 2))
++ if (ieee80211_vif_is_mesh(&sdata->vif))
+ return false;
+
-+ /* If the skb is shared we need to obtain our own copy */
-+ if (skb_shared(skb)) {
-+ struct sk_buff *oskb = skb;
-+
-+ skb = skb_clone(skb, GFP_ATOMIC);
-+ if (!skb)
-+ return false;
-+
-+ kfree_skb(oskb);
-+ }
-+
-+ sta = rcu_dereference(entry->mpath->next_hop);
-+ skb_set_queue_mapping(skb, ieee80211_select_queue(sdata, sta, skb));
-+
-+ meshhdr = (struct ieee80211s_hdr *)(entry->hdr + entry->machdr_len);
-+ if ((meshhdr->flags & MESH_FLAGS_AE) == MESH_FLAGS_AE_A5_A6) {
-+ /* preserve SA from eth header for 6-addr frames */
-+ ether_addr_copy(sa, skb->data + ETH_ALEN);
-+ copy_sa = true;
-+ }
-+
-+ memcpy(skb_push(skb, entry->hdrlen - 2 * ETH_ALEN), entry->hdr,
-+ entry->hdrlen);
-+
-+ meshhdr = (struct ieee80211s_hdr *)(skb->data + entry->machdr_len);
-+ put_unaligned_le32(atomic_inc_return(&sdata->u.mesh.mesh_seqnum),
-+ &meshhdr->seqnum);
-+ meshhdr->ttl = sdata->u.mesh.mshcfg.dot11MeshTTL;
-+ if (copy_sa)
-+ ether_addr_copy(meshhdr->eaddr2, sa);
-+
-+ __ieee80211_mesh_xmit_fast(sdata, entry, skb);
+ if (skb_is_gso(skb))
+ return false;
+
+@@ -3634,10 +3640,11 @@ free:
+ return NULL;
+ }
+
+-static void __ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata,
+- struct sta_info *sta,
+- struct ieee80211_fast_tx *fast_tx,
+- struct sk_buff *skb, u8 tid, bool ampdu)
++void __ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata,
++ struct sta_info *sta,
++ struct ieee80211_fast_tx *fast_tx,
++ struct sk_buff *skb, bool ampdu,
++ const u8 *da, const u8 *sa)
+ {
+ struct ieee80211_local *local = sdata->local;
+ struct ieee80211_hdr *hdr = (void *)fast_tx->hdr;
+@@ -3646,7 +3653,6 @@ static void __ieee80211_xmit_fast(struct
+ ieee80211_tx_result r;
+ int hw_headroom = sdata->local->hw.extra_tx_headroom;
+ int extra_head = fast_tx->hdr_len - (ETH_HLEN - 2);
+- struct ethhdr eth;
+
+ skb = skb_share_check(skb, GFP_ATOMIC);
+ if (unlikely(!skb))
+@@ -3666,11 +3672,10 @@ static void __ieee80211_xmit_fast(struct
+ ENCRYPT_NO)))
+ goto free;
+
+- memcpy(ð, skb->data, ETH_HLEN - 2);
+ hdr = skb_push(skb, extra_head);
+ memcpy(skb->data, fast_tx->hdr, fast_tx->hdr_len);
+- memcpy(skb->data + fast_tx->da_offs, eth.h_dest, ETH_ALEN);
+- memcpy(skb->data + fast_tx->sa_offs, eth.h_source, ETH_ALEN);
++ memcpy(skb->data + fast_tx->da_offs, da, ETH_ALEN);
++ memcpy(skb->data + fast_tx->sa_offs, sa, ETH_ALEN);
+
+ info = IEEE80211_SKB_CB(skb);
+ memset(info, 0, sizeof(*info));
+@@ -3689,7 +3694,8 @@ static void __ieee80211_xmit_fast(struct
+ #endif
+
+ if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) {
+- tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
++ u8 tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
+
-+ return true;
-+}
+ *ieee80211_get_qos_ctl(hdr) = tid;
+ }
+
+@@ -3732,6 +3738,7 @@ static bool ieee80211_xmit_fast(struct i
+ struct ieee80211_hdr *hdr = (void *)fast_tx->hdr;
+ struct tid_ampdu_tx *tid_tx = NULL;
+ struct sk_buff *next;
++ struct ethhdr eth;
+ u8 tid = IEEE80211_NUM_TIDS;
+
+ /* control port protocol needs a lot of special handling */
+@@ -3757,6 +3764,8 @@ static bool ieee80211_xmit_fast(struct i
+ }
+ }
+
++ memcpy(ð, skb->data, ETH_HLEN - 2);
+
- static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata,
- struct sta_info *sta,
- struct ieee80211_fast_tx *fast_tx,
-@@ -4244,8 +4396,14 @@ void __ieee80211_subif_start_xmit(struct
+ /* after this point (skb is modified) we cannot return false */
+ skb = ieee80211_tx_skb_fixup(skb, ieee80211_sdata_netdev_features(sdata));
+ if (!skb)
+@@ -3764,7 +3773,8 @@ static bool ieee80211_xmit_fast(struct i
+
+ skb_list_walk_safe(skb, skb, next) {
+ skb_mark_not_on_list(skb);
+- __ieee80211_xmit_fast(sdata, sta, fast_tx, skb, tid, tid_tx);
++ __ieee80211_xmit_fast(sdata, sta, fast_tx, skb, tid_tx,
++ eth.h_dest, eth.h_source);
+ }
+
+ return true;
+@@ -4244,8 +4254,15 @@ void __ieee80211_subif_start_xmit(struct
return;
}
@@ -747,13 +832,14 @@
rcu_read_lock();
+ if (ieee80211_vif_is_mesh(&sdata->vif) &&
++ ieee80211_hw_check(&local->hw, SUPPORT_FAST_XMIT) &&
+ ieee80211_mesh_xmit_fast(sdata, skb, ctrl_flags))
+ goto out;
+
if (ieee80211_lookup_ra_sta(sdata, skb, &sta))
goto out_free;
-@@ -4255,8 +4413,6 @@ void __ieee80211_subif_start_xmit(struct
+@@ -4255,8 +4272,6 @@ void __ieee80211_subif_start_xmit(struct
skb_set_queue_mapping(skb, ieee80211_select_queue(sdata, sta, skb));
ieee80211_aggr_check(sdata, sta, skb);
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/320-wifi-mac80211-use-mesh-header-cache-to-speed-up-mesh.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/320-wifi-mac80211-use-mesh-header-cache-to-speed-up-mesh.patch
index e0d4e60..7ec8f3d 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/320-wifi-mac80211-use-mesh-header-cache-to-speed-up-mesh.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/320-wifi-mac80211-use-mesh-header-cache-to-speed-up-mesh.patch
@@ -3,40 +3,92 @@
Subject: [PATCH] wifi: mac80211: use mesh header cache to speed up mesh
forwarding
-Use it to look up the next hop address + sta pointer + key and call
-__ieee80211_mesh_xmit_fast to queue the tx frame.
-
Significantly reduces mesh forwarding path CPU usage and enables the
-use of iTXQ.
+direct use of iTXQ.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
-@@ -2731,6 +2731,7 @@ ieee80211_rx_mesh_data(struct ieee80211_
- struct ieee80211_hdr hdr = {
- .frame_control = cpu_to_le16(fc)
- };
-+ struct mhdr_cache_entry *entry = NULL;
- struct ieee80211_hdr *fwd_hdr;
- struct ieee80211s_hdr *mesh_hdr;
- struct ieee80211_tx_info *info;
-@@ -2788,7 +2789,12 @@ ieee80211_rx_mesh_data(struct ieee80211_
- return RX_DROP_MONITOR;
+@@ -2720,6 +2720,65 @@ ieee80211_deliver_skb(struct ieee80211_r
}
+ }
-- if (mesh_hdr->flags & MESH_FLAGS_AE) {
++#ifdef CPTCFG_MAC80211_MESH
++static bool
++ieee80211_rx_mesh_fast_forward(struct ieee80211_sub_if_data *sdata,
++ struct sk_buff *skb, int hdrlen)
++{
++ struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
++ struct ieee80211_mesh_fast_tx *entry = NULL;
++ struct ieee80211s_hdr *mesh_hdr;
++ struct tid_ampdu_tx *tid_tx;
++ struct sta_info *sta;
++ struct ethhdr eth;
++ u8 tid;
++
++ mesh_hdr = (struct ieee80211s_hdr *)(skb->data + sizeof(eth));
+ if ((mesh_hdr->flags & MESH_FLAGS_AE) == MESH_FLAGS_AE_A5_A6)
-+ entry = mesh_get_cached_hdr(sdata, mesh_hdr->eaddr1);
++ entry = mesh_fast_tx_get(sdata, mesh_hdr->eaddr1);
+ else if (!(mesh_hdr->flags & MESH_FLAGS_AE))
-+ entry = mesh_get_cached_hdr(sdata, eth->h_dest);
++ entry = mesh_fast_tx_get(sdata, skb->data);
++ if (!entry)
++ return false;
++
++ sta = rcu_dereference(entry->mpath->next_hop);
++ if (!sta)
++ return false;
++
++ if (skb_linearize(skb))
++ return false;
++
++ tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
++ tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]);
++ if (tid_tx) {
++ if (!test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state))
++ return false;
++
++ if (tid_tx->timeout)
++ tid_tx->last_tx = jiffies;
++ }
++
++ ieee80211_aggr_check(sdata, sta, skb);
++
++ if (ieee80211_get_8023_tunnel_proto(skb->data + hdrlen,
++ &skb->protocol))
++ hdrlen += ETH_ALEN;
++ else
++ skb->protocol = htons(skb->len - hdrlen);
++ skb_set_network_header(skb, hdrlen + 2);
++
++ skb->dev = sdata->dev;
++ memcpy(ð, skb->data, ETH_HLEN - 2);
++ skb_pull(skb, 2);
++ __ieee80211_xmit_fast(sdata, sta, &entry->fast_tx, skb, tid_tx,
++ eth.h_dest, eth.h_source);
++ IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_unicast);
++ IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_frames);
+
-+ if (!entry && (mesh_hdr->flags & MESH_FLAGS_AE)) {
- struct mesh_path *mppath;
- char *proxied_addr;
- bool update = false;
-@@ -2862,11 +2868,23 @@ ieee80211_rx_mesh_data(struct ieee80211_
++ return true;
++}
++#endif
++
+ static ieee80211_rx_result
+ ieee80211_rx_mesh_data(struct ieee80211_sub_if_data *sdata, struct sta_info *sta,
+ struct sk_buff *skb)
+@@ -2824,6 +2883,10 @@ ieee80211_rx_mesh_data(struct ieee80211_
+
+ skb_set_queue_mapping(skb, ieee802_1d_to_ac[skb->priority]);
+
++ if (!multicast &&
++ ieee80211_rx_mesh_fast_forward(sdata, skb, mesh_hdrlen))
++ return RX_QUEUED;
++
+ ieee80211_fill_mesh_addresses(&hdr, &hdr.frame_control,
+ eth->h_dest, eth->h_source);
+ hdrlen = ieee80211_hdrlen(hdr.frame_control);
+@@ -2862,6 +2925,7 @@ ieee80211_rx_mesh_data(struct ieee80211_
info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
info->control.vif = &sdata->vif;
info->control.jiffies = jiffies;
@@ -44,23 +96,7 @@
if (multicast) {
IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_mcast);
memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN);
- /* update power mode indication when forwarding */
- ieee80211_mps_set_frame_flags(sdata, NULL, fwd_hdr);
-+ } else if (entry) {
-+ struct ieee80211_hdr *ehdr = (struct ieee80211_hdr *)entry->hdr;
-+
-+ ether_addr_copy(fwd_hdr->addr1, ehdr->addr1);
-+ ether_addr_copy(fwd_hdr->addr2, sdata->vif.addr);
-+ IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_unicast);
-+ IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_frames);
-+ qos[0] = fwd_skb->priority;
-+ qos[1] = ieee80211_get_qos_ctl(ehdr)[1];
-+ __ieee80211_mesh_xmit_fast(sdata, entry, fwd_skb);
-+ return RX_QUEUED;
- } else if (!mesh_nexthop_lookup(sdata, fwd_skb)) {
- /* mesh power mode flags updated in mesh_nexthop_lookup */
- IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_unicast);
-@@ -2883,7 +2901,6 @@ ieee80211_rx_mesh_data(struct ieee80211_
+@@ -2883,7 +2947,6 @@ ieee80211_rx_mesh_data(struct ieee80211_
}
IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_frames);
@@ -68,3 +104,29 @@
ieee80211_add_pending_skb(local, fwd_skb);
rx_accept:
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -2018,6 +2018,8 @@ void __ieee80211_xmit_fast(struct ieee80
+ struct ieee80211_fast_tx *fast_tx,
+ struct sk_buff *skb, bool ampdu,
+ const u8 *da, const u8 *sa);
++void ieee80211_aggr_check(struct ieee80211_sub_if_data *sdata,
++ struct sta_info *sta, struct sk_buff *skb);
+
+ /* HT */
+ void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata,
+--- a/net/mac80211/tx.c
++++ b/net/mac80211/tx.c
+@@ -1191,10 +1191,8 @@ static bool ieee80211_tx_prep_agg(struct
+ return queued;
+ }
+
+-static void
+-ieee80211_aggr_check(struct ieee80211_sub_if_data *sdata,
+- struct sta_info *sta,
+- struct sk_buff *skb)
++void ieee80211_aggr_check(struct ieee80211_sub_if_data *sdata,
++ struct sta_info *sta, struct sk_buff *skb)
+ {
+ struct rate_control_ref *ref = sdata->local->rate_ctrl;
+ u16 tid;
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/321-mac80211-fix-mesh-forwarding.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/321-mac80211-fix-mesh-forwarding.patch
index d9af8c7..e2b268a 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/321-mac80211-fix-mesh-forwarding.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/321-mac80211-fix-mesh-forwarding.patch
@@ -11,7 +11,7 @@
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
-@@ -2847,6 +2847,9 @@ ieee80211_rx_mesh_data(struct ieee80211_
+@@ -2904,6 +2904,9 @@ ieee80211_rx_mesh_data(struct ieee80211_
if (skb_cow_head(fwd_skb, hdrlen - sizeof(struct ethhdr)))
return RX_DROP_UNUSABLE;
@@ -21,7 +21,7 @@
}
fwd_hdr = skb_push(fwd_skb, hdrlen - sizeof(struct ethhdr));
-@@ -2861,7 +2864,7 @@ ieee80211_rx_mesh_data(struct ieee80211_
+@@ -2918,7 +2921,7 @@ ieee80211_rx_mesh_data(struct ieee80211_
hdrlen += ETH_ALEN;
else
fwd_skb->protocol = htons(fwd_skb->len - hdrlen);
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/322-wifi-mac80211-fix-mesh-path-discovery-based-on-unica.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/322-wifi-mac80211-fix-mesh-path-discovery-based-on-unica.patch
new file mode 100644
index 0000000..292a89e
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/322-wifi-mac80211-fix-mesh-path-discovery-based-on-unica.patch
@@ -0,0 +1,52 @@
+From: Felix Fietkau <nbd@nbd.name>
+Date: Sun, 26 Feb 2023 20:30:20 +0100
+Subject: [PATCH] wifi: mac80211: fix mesh path discovery based on unicast
+ packets
+
+If a packet has reached its intended destination, it was bumped to the code
+that accepts it, without first checking if a mesh_path needs to be created
+based on the discovered source.
+Fix this by moving the destination address check further down
+
+Fixes: 986e43b19ae9 ("wifi: mac80211: fix receiving A-MSDU frames on mesh interfaces")
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -2824,17 +2824,6 @@ ieee80211_rx_mesh_data(struct ieee80211_
+ mesh_rmc_check(sdata, eth->h_source, mesh_hdr))
+ return RX_DROP_MONITOR;
+
+- /* Frame has reached destination. Don't forward */
+- if (ether_addr_equal(sdata->vif.addr, eth->h_dest))
+- goto rx_accept;
+-
+- if (!ifmsh->mshcfg.dot11MeshForwarding) {
+- if (is_multicast_ether_addr(eth->h_dest))
+- goto rx_accept;
+-
+- return RX_DROP_MONITOR;
+- }
+-
+ /* forward packet */
+ if (sdata->crypto_tx_tailroom_needed_cnt)
+ tailroom = IEEE80211_ENCRYPT_TAILROOM;
+@@ -2881,6 +2870,17 @@ ieee80211_rx_mesh_data(struct ieee80211_
+ rcu_read_unlock();
+ }
+
++ /* Frame has reached destination. Don't forward */
++ if (ether_addr_equal(sdata->vif.addr, eth->h_dest))
++ goto rx_accept;
++
++ if (!ifmsh->mshcfg.dot11MeshForwarding) {
++ if (is_multicast_ether_addr(eth->h_dest))
++ goto rx_accept;
++
++ return RX_DROP_MONITOR;
++ }
++
+ skb_set_queue_mapping(skb, ieee802_1d_to_ac[skb->priority]);
+
+ if (!multicast &&
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/323-wifi-mac80211-Add-VHT-MU-MIMO-related-flags-in-ieee8.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/323-wifi-mac80211-Add-VHT-MU-MIMO-related-flags-in-ieee8.patch
new file mode 100644
index 0000000..2310593
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/323-wifi-mac80211-Add-VHT-MU-MIMO-related-flags-in-ieee8.patch
@@ -0,0 +1,68 @@
+From: Muna Sinada <quic_msinada@quicinc.com>
+Date: Wed, 5 Oct 2022 14:54:45 -0700
+Subject: [PATCH] wifi: mac80211: Add VHT MU-MIMO related flags in
+ ieee80211_bss_conf
+
+Adding flags for SU Beamformer, SU Beamformee, MU Beamformer and
+MU Beamformee for VHT. This is utilized to pass MU-MIMO
+configurations from user space to driver in AP mode.
+
+Signed-off-by: Muna Sinada <quic_msinada@quicinc.com>
+Link: https://lore.kernel.org/r/1665006886-23874-1-git-send-email-quic_msinada@quicinc.com
+[fixed indentation, removed redundant !!]
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+---
+
+--- a/include/net/mac80211.h
++++ b/include/net/mac80211.h
+@@ -653,6 +653,14 @@ struct ieee80211_fils_discovery {
+ * write-protected by sdata_lock and local->mtx so holding either is fine
+ * for read access.
+ * @color_change_color: the bss color that will be used after the change.
++ * @vht_su_beamformer: in AP mode, does this BSS support operation as an VHT SU
++ * beamformer
++ * @vht_su_beamformee: in AP mode, does this BSS support operation as an VHT SU
++ * beamformee
++ * @vht_mu_beamformer: in AP mode, does this BSS support operation as an VHT MU
++ * beamformer
++ * @vht_mu_beamformee: in AP mode, does this BSS support operation as an VHT MU
++ * beamformee
+ */
+ struct ieee80211_bss_conf {
+ const u8 *bssid;
+@@ -726,6 +734,11 @@ struct ieee80211_bss_conf {
+
+ bool color_change_active;
+ u8 color_change_color;
++
++ bool vht_su_beamformer;
++ bool vht_su_beamformee;
++ bool vht_mu_beamformer;
++ bool vht_mu_beamformee;
+ };
+
+ /**
+--- a/net/mac80211/cfg.c
++++ b/net/mac80211/cfg.c
+@@ -1251,6 +1251,21 @@ static int ieee80211_start_ap(struct wip
+ prev_beacon_int = link_conf->beacon_int;
+ link_conf->beacon_int = params->beacon_interval;
+
++ if (params->vht_cap) {
++ link_conf->vht_su_beamformer =
++ params->vht_cap->vht_cap_info &
++ cpu_to_le32(IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE);
++ link_conf->vht_su_beamformee =
++ params->vht_cap->vht_cap_info &
++ cpu_to_le32(IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE);
++ link_conf->vht_mu_beamformer =
++ params->vht_cap->vht_cap_info &
++ cpu_to_le32(IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE);
++ link_conf->vht_mu_beamformee =
++ params->vht_cap->vht_cap_info &
++ cpu_to_le32(IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE);
++ }
++
+ if (params->he_cap && params->he_oper) {
+ link_conf->he_support = true;
+ link_conf->htc_trig_based_pkt_ext =
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/324-wifi-mac80211-Add-HE-MU-MIMO-related-flags-in-ieee80.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/324-wifi-mac80211-Add-HE-MU-MIMO-related-flags-in-ieee80.patch
new file mode 100644
index 0000000..a3c4453
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/324-wifi-mac80211-Add-HE-MU-MIMO-related-flags-in-ieee80.patch
@@ -0,0 +1,68 @@
+From: Muna Sinada <quic_msinada@quicinc.com>
+Date: Wed, 5 Oct 2022 14:54:46 -0700
+Subject: [PATCH] wifi: mac80211: Add HE MU-MIMO related flags in
+ ieee80211_bss_conf
+
+Adding flags for SU Beamformer, SU Beamformee, MU Beamformer and Full
+Bandwidth UL MU-MIMO for HE. This is utilized to pass MU-MIMO
+configurations from user space to driver in AP mode.
+
+Signed-off-by: Muna Sinada <quic_msinada@quicinc.com>
+Link: https://lore.kernel.org/r/1665006886-23874-2-git-send-email-quic_msinada@quicinc.com
+[fixed indentation, removed redundant !!]
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+---
+
+--- a/include/net/mac80211.h
++++ b/include/net/mac80211.h
+@@ -661,6 +661,15 @@ struct ieee80211_fils_discovery {
+ * beamformer
+ * @vht_mu_beamformee: in AP mode, does this BSS support operation as an VHT MU
+ * beamformee
++ * @he_su_beamformer: in AP-mode, does this BSS support operation as an HE SU
++ * beamformer
++ * @he_su_beamformee: in AP-mode, does this BSS support operation as an HE SU
++ * beamformee
++ * @he_mu_beamformer: in AP-mode, does this BSS support operation as an HE MU
++ * beamformer
++ * @he_full_ul_mumimo: does this BSS support the reception (AP) or transmission
++ * (non-AP STA) of an HE TB PPDU on an RU that spans the entire PPDU
++ * bandwidth
+ */
+ struct ieee80211_bss_conf {
+ const u8 *bssid;
+@@ -739,6 +748,10 @@ struct ieee80211_bss_conf {
+ bool vht_su_beamformee;
+ bool vht_mu_beamformer;
+ bool vht_mu_beamformee;
++ bool he_su_beamformer;
++ bool he_su_beamformee;
++ bool he_mu_beamformer;
++ bool he_full_ul_mumimo;
+ };
+
+ /**
+--- a/net/mac80211/cfg.c
++++ b/net/mac80211/cfg.c
+@@ -1280,6 +1280,21 @@ static int ieee80211_start_ap(struct wip
+ changed |= BSS_CHANGED_HE_BSS_COLOR;
+ }
+
++ if (params->he_cap) {
++ link_conf->he_su_beamformer =
++ params->he_cap->phy_cap_info[3] &
++ IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER;
++ link_conf->he_su_beamformee =
++ params->he_cap->phy_cap_info[4] &
++ IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE;
++ link_conf->he_mu_beamformer =
++ params->he_cap->phy_cap_info[4] &
++ IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER;
++ link_conf->he_full_ul_mumimo =
++ params->he_cap->phy_cap_info[2] &
++ IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO;
++ }
++
+ if (sdata->vif.type == NL80211_IFTYPE_AP &&
+ params->mbssid_config.tx_wdev) {
+ err = ieee80211_set_ap_mbssid_options(sdata,
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/325-wifi-mac80211-introduce-ieee80211_refresh_tx_agg_ses.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/325-wifi-mac80211-introduce-ieee80211_refresh_tx_agg_ses.patch
new file mode 100644
index 0000000..f6d3d78
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/325-wifi-mac80211-introduce-ieee80211_refresh_tx_agg_ses.patch
@@ -0,0 +1,60 @@
+From: Ryder Lee <ryder.lee@mediatek.com>
+Date: Sat, 18 Feb 2023 01:50:05 +0800
+Subject: [PATCH] wifi: mac80211: introduce
+ ieee80211_refresh_tx_agg_session_timer()
+
+This allows low level drivers to refresh the tx agg session timer, based on
+querying stats from the firmware usually. Especially for some mt76 devices
+support .net_fill_forward_path would bypass mac80211, which leads to tx BA
+session timeout for certain clients.
+
+Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
+---
+
+--- a/include/net/mac80211.h
++++ b/include/net/mac80211.h
+@@ -5968,6 +5968,18 @@ void ieee80211_queue_delayed_work(struct
+ unsigned long delay);
+
+ /**
++ * ieee80211_refresh_tx_agg_session_timer - Refresh a tx agg session timer.
++ * @sta: the station for which to start a BA session
++ * @tid: the TID to BA on.
++ *
++ * This function allows low level driver to refresh tx agg session timer
++ * to maintain BA session, the session level will still be managed by the
++ * mac80211.
++ */
++void ieee80211_refresh_tx_agg_session_timer(struct ieee80211_sta *sta,
++ u16 tid);
++
++/**
+ * ieee80211_start_tx_ba_session - Start a tx Block Ack session.
+ * @sta: the station for which to start a BA session
+ * @tid: the TID to BA on.
+--- a/net/mac80211/agg-tx.c
++++ b/net/mac80211/agg-tx.c
+@@ -552,6 +552,23 @@ void ieee80211_tx_ba_session_handle_star
+ ieee80211_send_addba_with_timeout(sta, tid_tx);
+ }
+
++void ieee80211_refresh_tx_agg_session_timer(struct ieee80211_sta *pubsta,
++ u16 tid)
++{
++ struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
++ struct tid_ampdu_tx *tid_tx;
++
++ if (WARN_ON_ONCE(tid >= IEEE80211_NUM_TIDS))
++ return;
++
++ tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]);
++ if (!tid_tx)
++ return;
++
++ tid_tx->last_tx = jiffies;
++}
++EXPORT_SYMBOL(ieee80211_refresh_tx_agg_session_timer);
++
+ /*
+ * After accepting the AddBA Response we activated a timer,
+ * resetting it after each frame that we send.
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/326-wifi-mac80211-add-mesh-fast-rx-support.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/326-wifi-mac80211-add-mesh-fast-rx-support.patch
new file mode 100644
index 0000000..b2b94d0
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/326-wifi-mac80211-add-mesh-fast-rx-support.patch
@@ -0,0 +1,77 @@
+From: Felix Fietkau <nbd@nbd.name>
+Date: Thu, 2 Mar 2023 13:52:29 +0100
+Subject: [PATCH] wifi: mac80211: add mesh fast-rx support
+
+This helps bring down rx CPU usage by avoiding calls to the rx handlers in
+the slow path. Supports forwarding and local rx, including A-MSDU.
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -4572,6 +4572,12 @@ void ieee80211_check_fast_rx(struct sta_
+ }
+
+ break;
++ case NL80211_IFTYPE_MESH_POINT:
++ fastrx.expected_ds_bits = cpu_to_le16(IEEE80211_FCTL_FROMDS |
++ IEEE80211_FCTL_TODS);
++ fastrx.da_offs = offsetof(struct ieee80211_hdr, addr3);
++ fastrx.sa_offs = offsetof(struct ieee80211_hdr, addr4);
++ break;
+ default:
+ goto clear;
+ }
+@@ -4780,6 +4786,7 @@ static bool ieee80211_invoke_fast_rx(str
+ struct sk_buff *skb = rx->skb;
+ struct ieee80211_hdr *hdr = (void *)skb->data;
+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
++ static ieee80211_rx_result res;
+ int orig_len = skb->len;
+ int hdrlen = ieee80211_hdrlen(hdr->frame_control);
+ int snap_offs = hdrlen;
+@@ -4841,7 +4848,8 @@ static bool ieee80211_invoke_fast_rx(str
+ snap_offs += IEEE80211_CCMP_HDR_LEN;
+ }
+
+- if (!(status->rx_flags & IEEE80211_RX_AMSDU)) {
++ if (!ieee80211_vif_is_mesh(&rx->sdata->vif) &&
++ !(status->rx_flags & IEEE80211_RX_AMSDU)) {
+ if (!pskb_may_pull(skb, snap_offs + sizeof(*payload)))
+ return false;
+
+@@ -4880,13 +4888,29 @@ static bool ieee80211_invoke_fast_rx(str
+ /* do the header conversion - first grab the addresses */
+ ether_addr_copy(addrs.da, skb->data + fast_rx->da_offs);
+ ether_addr_copy(addrs.sa, skb->data + fast_rx->sa_offs);
+- skb_postpull_rcsum(skb, skb->data + snap_offs,
+- sizeof(rfc1042_header) + 2);
+- /* remove the SNAP but leave the ethertype */
+- skb_pull(skb, snap_offs + sizeof(rfc1042_header));
++ if (ieee80211_vif_is_mesh(&rx->sdata->vif)) {
++ skb_pull(skb, snap_offs - 2);
++ put_unaligned_be16(skb->len - 2, skb->data);
++ } else {
++ skb_postpull_rcsum(skb, skb->data + snap_offs,
++ sizeof(rfc1042_header) + 2);
++
++ /* remove the SNAP but leave the ethertype */
++ skb_pull(skb, snap_offs + sizeof(rfc1042_header));
++ }
+ /* push the addresses in front */
+ memcpy(skb_push(skb, sizeof(addrs)), &addrs, sizeof(addrs));
+
++ res = ieee80211_rx_mesh_data(rx->sdata, rx->sta, rx->skb);
++ switch (res) {
++ case RX_QUEUED:
++ return true;
++ case RX_CONTINUE:
++ break;
++ default:
++ goto drop;
++ }
++
+ ieee80211_rx_8023(rx, fast_rx, orig_len);
+
+ return true;
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/500-mac80211_configure_antenna_gain.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/500-mac80211_configure_antenna_gain.patch
index 817be9e..80ffb49 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/500-mac80211_configure_antenna_gain.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/500-mac80211_configure_antenna_gain.patch
@@ -87,7 +87,7 @@
CFG80211_TESTMODE_DUMP(ieee80211_testmode_dump)
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
-@@ -1536,6 +1536,7 @@ struct ieee80211_local {
+@@ -1535,6 +1535,7 @@ struct ieee80211_local {
int dynamic_ps_forced_timeout;
int user_power_level; /* in dBm, for all interfaces */
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0008-mac80211-mtk-remove-timerout-handle-for-ax210-iot-is.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0008-mac80211-mtk-remove-timerout-handle-for-ax210-iot-is.patch
deleted file mode 100644
index bf8111a..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0008-mac80211-mtk-remove-timerout-handle-for-ax210-iot-is.patch
+++ /dev/null
@@ -1,35 +0,0 @@
-From 41ef202d35486326d8fc52466ef4ad6f7aa98e34 Mon Sep 17 00:00:00 2001
-From: Evelyn Tsai <evelyn.tsai@mediatek.com>
-Date: Wed, 19 Oct 2022 13:49:21 +0800
-Subject: [PATCH 08/16] mac80211: mtk: remove timerout handle for ax210 iot
- issue
-
-Signed-off-by: Evelyn Tsai <evelyn.tsai@mediatek.com>
----
- net/mac80211/agg-tx.c | 7 +++----
- 1 file changed, 3 insertions(+), 4 deletions(-)
- mode change 100644 => 100755 net/mac80211/agg-tx.c
-
-diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
-old mode 100644
-new mode 100755
-index 07c892a..1f46561
---- a/net/mac80211/agg-tx.c
-+++ b/net/mac80211/agg-tx.c
-@@ -568,10 +568,9 @@ static void sta_tx_agg_session_timer_expired(struct timer_list *t)
- }
-
- timeout = tid_tx->last_tx + TU_TO_JIFFIES(tid_tx->timeout);
-- if (time_is_after_jiffies(timeout)) {
-- mod_timer(&tid_tx->session_timer, timeout);
-- return;
-- }
-+ /* remove timerout handle for ax210 iot issue */
-+ mod_timer(&tid_tx->session_timer, timeout);
-+ return;
-
- ht_dbg(sta->sdata, "tx session timer expired on %pM tid %d\n",
- sta->sta.addr, tid);
---
-2.25.1
-
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0012-mac80211-mtk-check-the-control-channel-before-downgr.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0011-mac80211-mtk-check-the-control-channel-before-downgr.patch
similarity index 92%
rename from recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0012-mac80211-mtk-check-the-control-channel-before-downgr.patch
rename to recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0011-mac80211-mtk-check-the-control-channel-before-downgr.patch
index 23b9ccb..18f434f 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0012-mac80211-mtk-check-the-control-channel-before-downgr.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0011-mac80211-mtk-check-the-control-channel-before-downgr.patch
@@ -1,7 +1,7 @@
-From cc6f40e49bfdee7c824d4b158a060c2dc42ded4c Mon Sep 17 00:00:00 2001
+From 0ed0a8f524a3288603f9eb298dcdeff7ae745e39 Mon Sep 17 00:00:00 2001
From: Evelyn Tsai <evelyn.tsai@mediatek.com>
Date: Fri, 16 Dec 2022 03:31:06 +0800
-Subject: [PATCH 12/16] mac80211: mtk: check the control channel before
+Subject: [PATCH 11/19] mac80211: mtk: check the control channel before
downgrading the bandwidth
---
@@ -50,5 +50,5 @@
*conn_flags |=
ieee80211_chandef_downgrade(&chandef);
--
-2.25.1
+2.18.0
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0011-mac80211-mtk-fix-the-issue-of-AP-and-STA-starting-on.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0011-mac80211-mtk-fix-the-issue-of-AP-and-STA-starting-on.patch
deleted file mode 100644
index c42a00f..0000000
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0011-mac80211-mtk-fix-the-issue-of-AP-and-STA-starting-on.patch
+++ /dev/null
@@ -1,261 +0,0 @@
-From 7dd3aacd15e5678a617001dc329cf942ed7f4298 Mon Sep 17 00:00:00 2001
-From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
-Date: Wed, 5 Oct 2022 19:13:43 +0800
-Subject: [PATCH 11/16] mac80211: mtk: fix the issue of AP and STA starting on
- DFS channel concurrently
-
-Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
----
- include/net/cfg80211.h | 22 ++++++++++++++++++
- include/uapi/linux/nl80211.h | 2 +-
- net/mac80211/cfg.c | 44 ++++++++++++++++++++++++++++++++++++
- net/mac80211/chan.c | 2 +-
- net/wireless/chan.c | 6 ++---
- net/wireless/nl80211.c | 7 ++++++
- net/wireless/rdev-ops.h | 16 +++++++++++++
- net/wireless/trace.h | 15 ++++++++++++
- 8 files changed, 109 insertions(+), 5 deletions(-)
-
-diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
-index f9c2cc3..84e769b 100644
---- a/include/net/cfg80211.h
-+++ b/include/net/cfg80211.h
-@@ -888,6 +888,24 @@ cfg80211_chandef_identical(const struct cfg80211_chan_def *chandef1,
- chandef1->center_freq2 == chandef2->center_freq2);
- }
-
-+/**
-+ * cfg80211_chan_fully_overlap - check if two channel are fully overlapped
-+ * @chandef1: first channel definition
-+ * @chandef2: second channel definition
-+ *
-+ * Return: %true if the channels are valid and fully overlapped, %false otherwise.
-+ */
-+static inline bool
-+cfg80211_chan_fully_overlap(const struct cfg80211_chan_def *chandef1,
-+ const struct cfg80211_chan_def *chandef2)
-+{
-+ return (chandef1->center_freq1 != 0 &&
-+ chandef1->center_freq1 == chandef2->center_freq1 &&
-+ chandef1->width == chandef2->width &&
-+ chandef1->freq1_offset == chandef2->freq1_offset &&
-+ chandef1->center_freq2 == chandef2->center_freq2);
-+}
-+
- /**
- * cfg80211_chandef_is_edmg - check if chandef represents an EDMG channel
- *
-@@ -4642,6 +4660,8 @@ struct cfg80211_ops {
- int (*del_link_station)(struct wiphy *wiphy, struct net_device *dev,
- struct link_station_del_parameters *params);
- void (*skip_cac)(struct wireless_dev *wdev);
-+ void (*check_cac_skip)(struct wiphy *wiphy,
-+ struct cfg80211_chan_def *chandef);
- };
-
- /*
-@@ -5847,6 +5867,8 @@ struct wireless_dev {
- };
- } links[IEEE80211_MLD_MAX_NUM_LINKS];
- u16 valid_links;
-+
-+ bool start_disabled;
- };
-
- static inline const u8 *wdev_address(struct wireless_dev *wdev)
-diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
-index 1293d30..db9d0a8 100644
---- a/include/uapi/linux/nl80211.h
-+++ b/include/uapi/linux/nl80211.h
-@@ -3283,7 +3283,7 @@ enum nl80211_attrs {
- NL80211_ATTR_WIPHY_ANTENNA_GAIN,
-
- /* 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,
- NL80211_ATTR_MAX = __NL80211_ATTR_AFTER_LAST - 1
-diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
-index 5718c56..9da02d9 100644
---- a/net/mac80211/cfg.c
-+++ b/net/mac80211/cfg.c
-@@ -4889,6 +4889,49 @@ ieee80211_skip_cac(struct wireless_dev *wdev)
- }
- }
-
-+static void
-+ieee80211_check_cac_skip(struct wiphy *wiphy,
-+ struct cfg80211_chan_def *chandef)
-+{
-+ struct ieee80211_local *local = wiphy_priv(wiphy);
-+ struct ieee80211_sub_if_data *s1;
-+ struct ieee80211_sub_if_data *s2;
-+ struct ieee80211_sub_if_data *sdata_sta;
-+ struct ieee80211_if_managed *ifmgd;
-+ struct ieee80211_channel *chan;
-+ struct wireless_dev *wdev;
-+ unsigned int cac_time_ms;
-+
-+ mutex_lock(&local->mtx);
-+ /* Bypass AP's cac if there is a STA associated to the same DFS channel */
-+ list_for_each_entry(s1, &local->interfaces, list) {
-+ ifmgd = &s1->u.mgd;
-+
-+ if (s1->vif.type == NL80211_IFTYPE_STATION && ifmgd->associated)
-+ sdata_sta = s1;
-+ else
-+ continue;
-+
-+ list_for_each_entry(s2, &local->interfaces, list) {
-+ wdev = &s2->wdev;
-+ chan = wdev->links[0].ap.chandef.chan;
-+ if (chan) {
-+ if (!(chan->flags & IEEE80211_CHAN_RADAR))
-+ continue;
-+
-+ if (wdev->identifier != sdata_sta->wdev.identifier &&
-+ chan->dfs_state == NL80211_DFS_USABLE && wdev->cac_started &&
-+ cfg80211_chan_fully_overlap(&sdata_sta->vif.bss_conf.chandef,
-+ &s2->vif.bss_conf.chandef)) {
-+ ieee80211_skip_cac(wdev);
-+ sdata_info(s2, "Skip CAC on the associated STA's chan\n");
-+ }
-+ }
-+ }
-+ }
-+ mutex_unlock(&local->mtx);
-+}
-+
- const struct cfg80211_ops mac80211_config_ops = {
- .add_virtual_intf = ieee80211_add_iface,
- .del_virtual_intf = ieee80211_del_iface,
-@@ -5001,4 +5044,5 @@ const struct cfg80211_ops mac80211_config_ops = {
- .mod_link_station = ieee80211_mod_link_station,
- .del_link_station = ieee80211_del_link_station,
- .skip_cac = ieee80211_skip_cac,
-+ .check_cac_skip = ieee80211_check_cac_skip,
- };
-diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
-index e72cf07..94496d7 100644
---- a/net/mac80211/chan.c
-+++ b/net/mac80211/chan.c
-@@ -567,7 +567,7 @@ bool ieee80211_is_radar_required(struct ieee80211_local *local)
-
- link = rcu_dereference(sdata->link[link_id]);
-
-- if (link && link->radar_required) {
-+ if (link && link->radar_required && sdata->wdev.cac_started) {
- rcu_read_unlock();
- return true;
- }
-diff --git a/net/wireless/chan.c b/net/wireless/chan.c
-index 29b5c2f..bf21f99 100644
---- a/net/wireless/chan.c
-+++ b/net/wireless/chan.c
-@@ -719,16 +719,16 @@ bool cfg80211_beaconing_iface_active(struct wireless_dev *wdev)
- case NL80211_IFTYPE_AP:
- case NL80211_IFTYPE_P2P_GO:
- for_each_valid_link(wdev, link) {
-- if (wdev->links[link].ap.beacon_interval)
-+ if (wdev->links[link].ap.beacon_interval || wdev->start_disabled)
- return true;
- }
- break;
- case NL80211_IFTYPE_ADHOC:
-- if (wdev->u.ibss.ssid_len)
-+ if (wdev->u.ibss.ssid_len || wdev->start_disabled)
- return true;
- break;
- case NL80211_IFTYPE_MESH_POINT:
-- if (wdev->u.mesh.id_len)
-+ if (wdev->u.mesh.id_len || wdev->start_disabled)
- return true;
- break;
- case NL80211_IFTYPE_STATION:
-diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
-index 202f802..cc8d4b2 100644
---- a/net/wireless/nl80211.c
-+++ b/net/wireless/nl80211.c
-@@ -789,6 +789,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
- NLA_POLICY_NESTED(nl80211_mbssid_config_policy),
- [NL80211_ATTR_MBSSID_ELEMS] = { .type = NLA_NESTED },
- [NL80211_ATTR_RADAR_BACKGROUND] = { .type = NLA_FLAG },
-+ [NL80211_ATTR_START_DISABLED] = { .type = NLA_FLAG },
- [NL80211_ATTR_AP_SETTINGS_FLAGS] = { .type = NLA_U32 },
- [NL80211_ATTR_EHT_CAPABILITY] =
- NLA_POLICY_BINARY_RANGE(NL80211_EHT_MIN_CAPABILITY_LEN, NL80211_EHT_MAX_CAPABILITY_LEN),
-@@ -5803,6 +5804,11 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
- if (wdev->links[link_id].ap.beacon_interval)
- return -EALREADY;
-
-+ if (info->attrs[NL80211_ATTR_START_DISABLED]) {
-+ wdev->start_disabled = nla_get_flag(info->attrs[NL80211_ATTR_START_DISABLED]);
-+ return 0;
-+ }
-+
- /* these are required for START_AP */
- if (!info->attrs[NL80211_ATTR_BEACON_INTERVAL] ||
- !info->attrs[NL80211_ATTR_DTIM_PERIOD] ||
-@@ -9846,6 +9852,7 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
- wdev->cac_started = true;
- wdev->cac_start_time = jiffies;
- wdev->cac_time_ms = cac_time_ms;
-+ err = rdev_check_cac_skip(rdev, &wdev->links[0].ap.chandef);
- }
- unlock:
- wiphy_unlock(wiphy);
-diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
-index ce83152..ffa504a 100644
---- a/net/wireless/rdev-ops.h
-+++ b/net/wireless/rdev-ops.h
-@@ -1508,4 +1508,20 @@ rdev_skip_cac(struct cfg80211_registered_device *rdev,
- return 0;
- }
-
-+static inline int
-+rdev_check_cac_skip(struct cfg80211_registered_device *rdev,
-+ struct cfg80211_chan_def *chandef)
-+{
-+ struct wiphy *wiphy = &rdev->wiphy;
-+
-+ if (!rdev->ops->check_cac_skip)
-+ return -EOPNOTSUPP;
-+
-+ trace_rdev_check_cac_skip(wiphy, chandef);
-+ rdev->ops->check_cac_skip(wiphy, chandef);
-+ trace_rdev_return_void(wiphy);
-+
-+ return 0;
-+}
-+
- #endif /* __CFG80211_RDEV_OPS */
-diff --git a/net/wireless/trace.h b/net/wireless/trace.h
-index d3a98e8..72c8f0e 100644
---- a/net/wireless/trace.h
-+++ b/net/wireless/trace.h
-@@ -3913,6 +3913,21 @@ TRACE_EVENT(rdev_skip_cac,
- TP_printk(WDEV_PR_FMT, WDEV_PR_ARG)
- );
-
-+TRACE_EVENT(rdev_check_cac_skip,
-+ TP_PROTO(struct wiphy *wiphy, struct cfg80211_chan_def *chandef),
-+
-+ TP_ARGS(wiphy, chandef),
-+
-+ TP_STRUCT__entry(WIPHY_ENTRY
-+ CHAN_DEF_ENTRY),
-+
-+ TP_fast_assign(WIPHY_ASSIGN;
-+ CHAN_DEF_ASSIGN(chandef)),
-+
-+ TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT,
-+ WIPHY_PR_ARG, CHAN_DEF_PR_ARG)
-+);
-+
- #endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */
-
- #undef TRACE_INCLUDE_PATH
---
-2.25.1
-
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0013-mac80211-mtk-fix-tx-amsdu-aggregation.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0012-mac80211-mtk-fix-tx-amsdu-aggregation.patch
similarity index 87%
rename from recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0013-mac80211-mtk-fix-tx-amsdu-aggregation.patch
rename to recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0012-mac80211-mtk-fix-tx-amsdu-aggregation.patch
index da3eede..6b5dab9 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0013-mac80211-mtk-fix-tx-amsdu-aggregation.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0012-mac80211-mtk-fix-tx-amsdu-aggregation.patch
@@ -1,7 +1,7 @@
-From e07d5401accc96f8380bf42ec454c9ea42255196 Mon Sep 17 00:00:00 2001
+From bb385f098e5f12c7ec0cc5032ac32a27f6713af6 Mon Sep 17 00:00:00 2001
From: TomLiu <tomml.liu@mediatek.com>
Date: Wed, 14 Dec 2022 00:26:50 -0800
-Subject: [PATCH 13/16] mac80211: mtk: fix tx amsdu aggregation
+Subject: [PATCH 12/19] mac80211: mtk: fix tx amsdu aggregation
---
include/net/mac80211.h | 7 +++++++
@@ -9,10 +9,10 @@
2 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
-index dc4faea..286810b 100644
+index 5908ba3..ad5f217 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
-@@ -2864,6 +2864,13 @@ static inline void _ieee80211_hw_set(struct ieee80211_hw *hw,
+@@ -2890,6 +2890,13 @@ static inline void _ieee80211_hw_set(struct ieee80211_hw *hw,
}
#define ieee80211_hw_set(hw, flg) _ieee80211_hw_set(hw, IEEE80211_HW_##flg)
@@ -27,7 +27,7 @@
* struct ieee80211_scan_request - hw scan request
*
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
-index 1f46561..318c71e 100755
+index 65c35e4..6b7ec6e 100755
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
@@ -66,7 +66,8 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata,
@@ -51,5 +51,5 @@
capab |= u16_encode_bits(tid, IEEE80211_ADDBA_PARAM_TID_MASK);
capab |= u16_encode_bits(agg_size, IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK);
--
-2.25.1
+2.18.0
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0014-mac80211-mtk-add-fill-receive-path-ops-to-get-wed-id.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0013-mac80211-mtk-add-fill-receive-path-ops-to-get-wed-id.patch
similarity index 91%
rename from recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0014-mac80211-mtk-add-fill-receive-path-ops-to-get-wed-id.patch
rename to recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0013-mac80211-mtk-add-fill-receive-path-ops-to-get-wed-id.patch
index 277e231..8d2067f 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0014-mac80211-mtk-add-fill-receive-path-ops-to-get-wed-id.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0013-mac80211-mtk-add-fill-receive-path-ops-to-get-wed-id.patch
@@ -1,7 +1,7 @@
-From b36c1fd5e967880b025a8301aadbeb832a364639 Mon Sep 17 00:00:00 2001
+From 2a801c07d58b8c9b9d5e9049856c7ef7b504d841 Mon Sep 17 00:00:00 2001
From: Sujuan Chen <sujuan.chen@mediatek.com>
Date: Wed, 18 May 2022 15:10:22 +0800
-Subject: [PATCH 14/16] mac80211: mtk: add fill receive path ops to get wed idx
+Subject: [PATCH 13/19] mac80211: mtk: add fill receive path ops to get wed idx
Signed-off-by: Sujuan Chen <sujuan.chen@mediatek.com>
---
@@ -13,10 +13,10 @@
mode change 100644 => 100755 net/mac80211/util.c
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
-index 286810b..f68eb7d 100644
+index ad5f217..d1d7fc3 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
-@@ -1354,7 +1354,7 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)
+@@ -1380,7 +1380,7 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)
* @RX_FLAG_AMPDU_EOF_BIT_KNOWN: The EOF value is known
* @RX_FLAG_RADIOTAP_HE: HE radiotap data is present
* (&struct ieee80211_radiotap_he, mac80211 will fill in
@@ -25,7 +25,7 @@
* - DATA3_DATA_MCS
* - DATA3_DATA_DCM
* - DATA3_CODING
-@@ -1362,7 +1362,7 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)
+@@ -1388,7 +1388,7 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)
* - DATA5_DATA_BW_RU_ALLOC
* - DATA6_NSTS
* - DATA3_STBC
@@ -34,7 +34,7 @@
* from the RX info data, so leave those zeroed when building this data)
* @RX_FLAG_RADIOTAP_HE_MU: HE MU radiotap data is present
* (&struct ieee80211_radiotap_he_mu)
-@@ -1924,6 +1924,12 @@ struct ieee80211_vif *wdev_to_ieee80211_vif(struct wireless_dev *wdev);
+@@ -1950,6 +1950,12 @@ struct ieee80211_vif *wdev_to_ieee80211_vif(struct wireless_dev *wdev);
*/
struct wireless_dev *ieee80211_vif_to_wdev(struct ieee80211_vif *vif);
@@ -47,7 +47,7 @@
/**
* lockdep_vif_mutex_held - for lockdep checks on link poiners
* @vif: the interface to check
-@@ -4193,6 +4199,8 @@ struct ieee80211_prep_tx_info {
+@@ -4219,6 +4225,8 @@ struct ieee80211_prep_tx_info {
* Note that a sta can also be inserted or removed with valid links,
* i.e. passed to @sta_add/@sta_state with sta->valid_links not zero.
* In fact, cannot change from having valid_links and not having them.
@@ -56,7 +56,7 @@
*/
struct ieee80211_ops {
void (*tx)(struct ieee80211_hw *hw,
-@@ -4548,6 +4556,9 @@ struct ieee80211_ops {
+@@ -4574,6 +4582,9 @@ struct ieee80211_ops {
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
u16 old_links, u16 new_links);
@@ -153,5 +153,5 @@
* Nothing should have been stuffed into the workqueue during
* the suspend->resume cycle. Since we can't check each caller
--
-2.25.1
+2.18.0
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0015-mac80211-mtk-register-.ndo_setup_tc-to-support-wifi2.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0014-mac80211-mtk-register-.ndo_setup_tc-to-support-wifi2.patch
similarity index 90%
rename from recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0015-mac80211-mtk-register-.ndo_setup_tc-to-support-wifi2.patch
rename to recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0014-mac80211-mtk-register-.ndo_setup_tc-to-support-wifi2.patch
index 60ab368..c32e2a0 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0015-mac80211-mtk-register-.ndo_setup_tc-to-support-wifi2.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0014-mac80211-mtk-register-.ndo_setup_tc-to-support-wifi2.patch
@@ -1,7 +1,7 @@
-From d0bf320b53011bf418e32991f899683280da184f Mon Sep 17 00:00:00 2001
+From a4cd8f81a63827647e88021cbcfc479f024221cb Mon Sep 17 00:00:00 2001
From: Sujuan Chen <sujuan.chen@mediatek.com>
Date: Fri, 23 Dec 2022 18:12:41 +0800
-Subject: [PATCH 15/16] mac80211: mtk: register .ndo_setup_tc to support
+Subject: [PATCH 14/19] mac80211: mtk: register .ndo_setup_tc to support
wifi2wifi offload
Signed-off-by: Sujuan Chen <sujuan.chen@mediatek.com>
@@ -11,10 +11,10 @@
2 files changed, 31 insertions(+)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
-index f68eb7d..c453b19 100644
+index d1d7fc3..1de9fad 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
-@@ -4201,6 +4201,8 @@ struct ieee80211_prep_tx_info {
+@@ -4227,6 +4227,8 @@ struct ieee80211_prep_tx_info {
* In fact, cannot change from having valid_links and not having them.
* @net_fill_receive_path: Called from .ndo_fill_receive_path in order to
* get a path for hardware flow offloading
@@ -23,7 +23,7 @@
*/
struct ieee80211_ops {
void (*tx)(struct ieee80211_hw *hw,
-@@ -4559,6 +4561,9 @@ struct ieee80211_ops {
+@@ -4585,6 +4587,9 @@ struct ieee80211_ops {
int (*net_fill_receive_path)(struct ieee80211_hw *hw,
struct net_device_path_ctx *ctx,
struct net_device_path *path);
@@ -85,5 +85,5 @@
dev->needs_free_netdev = true;
dev->priv_destructor = ieee80211_if_free;
--
-2.25.1
+2.18.0
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0016-mac80211-mtk-fix-build-error-on-Linux-Kernel-5.4.patch b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0015-mac80211-mtk-fix-build-error-on-Linux-Kernel-5.4.patch
similarity index 90%
rename from recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0016-mac80211-mtk-fix-build-error-on-Linux-Kernel-5.4.patch
rename to recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0015-mac80211-mtk-fix-build-error-on-Linux-Kernel-5.4.patch
index bb53403..3b2b718 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0016-mac80211-mtk-fix-build-error-on-Linux-Kernel-5.4.patch
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/mtk-0015-mac80211-mtk-fix-build-error-on-Linux-Kernel-5.4.patch
@@ -1,7 +1,7 @@
-From 12d2196bb600818a9fc9081037c509f2624b2d25 Mon Sep 17 00:00:00 2001
+From 83f826c468a145fb205cffe0f5fcc8d69143bb78 Mon Sep 17 00:00:00 2001
From: Evelyn Tsai <evelyn.tsai@mediatek.com>
Date: Tue, 13 Dec 2022 09:04:49 +0800
-Subject: [PATCH 16/16] mac80211: mtk: fix build error on Linux Kernel 5.4
+Subject: [PATCH 15/19] mac80211: mtk: fix build error on Linux Kernel 5.4
---
include/linux/ieee80211.h | 8 +++-----
@@ -66,10 +66,10 @@
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
-index cc8d4b2..8928a26 100644
+index 202f802..1035f74 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
-@@ -16448,9 +16448,11 @@ static const struct genl_ops nl80211_ops[] = {
+@@ -16441,9 +16441,11 @@ static const struct genl_ops nl80211_ops[] = {
/* can be retrieved by unprivileged users */
.internal_flags = IFLAGS(NL80211_FLAG_NEED_WIPHY),
},
@@ -81,7 +81,7 @@
{
.cmd = NL80211_CMD_SET_WIPHY,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
-@@ -17287,8 +17289,10 @@ static struct genl_family nl80211_fam __genl_ro_after_init = {
+@@ -17280,8 +17282,10 @@ static struct genl_family nl80211_fam __genl_ro_after_init = {
.module = THIS_MODULE,
.ops = nl80211_ops,
.n_ops = ARRAY_SIZE(nl80211_ops),
@@ -93,5 +93,5 @@
.resv_start_op = NL80211_CMD_REMOVE_LINK_STA + 1,
#endif
--
-2.25.1
+2.18.0
diff --git a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/subsys.inc b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/subsys.inc
index 45bcf93..a2d8984 100644
--- a/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/subsys.inc
+++ b/recipes-wifi/linux-mac80211/files/patches-6.x/subsys/subsys.inc
@@ -26,6 +26,11 @@
file://319-wifi-mac80211-mesh-fast-xmit-support.patch \
file://320-wifi-mac80211-use-mesh-header-cache-to-speed-up-mesh.patch \
file://321-mac80211-fix-mesh-forwarding.patch \
+ file://322-wifi-mac80211-fix-mesh-path-discovery-based-on-unica.patch \
+ file://323-wifi-mac80211-Add-VHT-MU-MIMO-related-flags-in-ieee8.patch \
+ file://324-wifi-mac80211-Add-HE-MU-MIMO-related-flags-in-ieee80.patch \
+ file://325-wifi-mac80211-introduce-ieee80211_refresh_tx_agg_ses.patch \
+ file://326-wifi-mac80211-add-mesh-fast-rx-support.patch \
file://400-allow-ibss-mixed.patch \
file://500-mac80211_configure_antenna_gain.patch \
file://782-net-next-1-of-net-pass-the-dst-buffer-to-of_get_mac_address.patch \
@@ -36,15 +41,13 @@
file://mtk-0005-mac80211-mtk-it-s-invalid-case-when-frag_threshold-i.patch \
file://mtk-0006-mac80211-mtk-airtime_flags-depends-on-NL80211_EXT_FE.patch \
file://mtk-0007-mac80211-mtk-add-support-for-runtime-set-inband-disc.patch \
- file://mtk-0008-mac80211-mtk-remove-timerout-handle-for-ax210-iot-is.patch \
file://mtk-0009-cfg80211-mtk-implement-DFS-status-show-cac-and-nop-s.patch \
file://mtk-0010-mac80211-mtk-Set-TWT-Information-Frame-Disabled-bit-.patch \
- file://mtk-0011-mac80211-mtk-fix-the-issue-of-AP-and-STA-starting-on.patch \
- file://mtk-0012-mac80211-mtk-check-the-control-channel-before-downgr.patch \
- file://mtk-0013-mac80211-mtk-fix-tx-amsdu-aggregation.patch \
- file://mtk-0014-mac80211-mtk-add-fill-receive-path-ops-to-get-wed-id.patch \
- file://mtk-0015-mac80211-mtk-register-.ndo_setup_tc-to-support-wifi2.patch \
- file://mtk-0016-mac80211-mtk-fix-build-error-on-Linux-Kernel-5.4.patch \
+ file://mtk-0011-mac80211-mtk-check-the-control-channel-before-downgr.patch \
+ file://mtk-0012-mac80211-mtk-fix-tx-amsdu-aggregation.patch \
+ file://mtk-0013-mac80211-mtk-add-fill-receive-path-ops-to-get-wed-id.patch \
+ file://mtk-0014-mac80211-mtk-register-.ndo_setup_tc-to-support-wifi2.patch \
+ file://mtk-0015-mac80211-mtk-fix-build-error-on-Linux-Kernel-5.4.patch \
file://mtk-0100-mac80211-mtk-add-EHT-BA1024-support.patch \
file://mtk-0101-mac80211-mtk-add-rate-duration-for-EHT-rate.patch \
"
diff --git a/recipes-wifi/linux-mac80211/files/patches/subsys/347-wifi-mac80211-introduce-ieee80211_refresh_tx_agg_ses.patch b/recipes-wifi/linux-mac80211/files/patches/subsys/347-wifi-mac80211-introduce-ieee80211_refresh_tx_agg_ses.patch
new file mode 100644
index 0000000..acd6c12
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches/subsys/347-wifi-mac80211-introduce-ieee80211_refresh_tx_agg_ses.patch
@@ -0,0 +1,60 @@
+From: Ryder Lee <ryder.lee@mediatek.com>
+Date: Sat, 18 Feb 2023 01:50:05 +0800
+Subject: [PATCH] wifi: mac80211: introduce
+ ieee80211_refresh_tx_agg_session_timer()
+
+This allows low level drivers to refresh the tx agg session timer, based on
+querying stats from the firmware usually. Especially for some mt76 devices
+support .net_fill_forward_path would bypass mac80211, which leads to tx BA
+session timeout for certain clients.
+
+Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
+---
+
+--- a/include/net/mac80211.h
++++ b/include/net/mac80211.h
+@@ -5970,6 +5970,18 @@ void ieee80211_queue_delayed_work(struct
+ unsigned long delay);
+
+ /**
++ * ieee80211_refresh_tx_agg_session_timer - Refresh a tx agg session timer.
++ * @sta: the station for which to start a BA session
++ * @tid: the TID to BA on.
++ *
++ * This function allows low level driver to refresh tx agg session timer
++ * to maintain BA session, the session level will still be managed by the
++ * mac80211.
++ */
++void ieee80211_refresh_tx_agg_session_timer(struct ieee80211_sta *sta,
++ u16 tid);
++
++/**
+ * ieee80211_start_tx_ba_session - Start a tx Block Ack session.
+ * @sta: the station for which to start a BA session
+ * @tid: the TID to BA on.
+--- a/net/mac80211/agg-tx.c
++++ b/net/mac80211/agg-tx.c
+@@ -552,6 +552,23 @@ void ieee80211_tx_ba_session_handle_star
+ ieee80211_send_addba_with_timeout(sta, tid_tx);
+ }
+
++void ieee80211_refresh_tx_agg_session_timer(struct ieee80211_sta *pubsta,
++ u16 tid)
++{
++ struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
++ struct tid_ampdu_tx *tid_tx;
++
++ if (WARN_ON_ONCE(tid >= IEEE80211_NUM_TIDS))
++ return;
++
++ tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]);
++ if (!tid_tx)
++ return;
++
++ tid_tx->last_tx = jiffies;
++}
++EXPORT_SYMBOL(ieee80211_refresh_tx_agg_session_timer);
++
+ /*
+ * After accepting the AddBA Response we activated a timer,
+ * resetting it after each frame that we send.
diff --git a/recipes-wifi/linux-mac80211/files/patches/subsys/mtk-0009-mac80211-mtk-remove-timerout-handle-for-ax210-iot-is.patch b/recipes-wifi/linux-mac80211/files/patches/subsys/mtk-0009-mac80211-mtk-remove-timerout-handle-for-ax210-iot-is.patch
deleted file mode 100644
index 50f2684..0000000
--- a/recipes-wifi/linux-mac80211/files/patches/subsys/mtk-0009-mac80211-mtk-remove-timerout-handle-for-ax210-iot-is.patch
+++ /dev/null
@@ -1,35 +0,0 @@
-From 733277b58ef0b13581c4c22231003f1910d60a5b Mon Sep 17 00:00:00 2001
-From: Evelyn Tsai <evelyn.tsai@mediatek.com>
-Date: Wed, 19 Oct 2022 13:49:21 +0800
-Subject: [PATCH 908/915] mac80211: mtk: remove timerout handle for ax210 iot
- issue
-
-Signed-off-by: Evelyn Tsai <evelyn.tsai@mediatek.com>
----
- net/mac80211/agg-tx.c | 7 +++----
- 1 file changed, 3 insertions(+), 4 deletions(-)
- mode change 100644 => 100755 net/mac80211/agg-tx.c
-
-diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
-old mode 100644
-new mode 100755
-index 1deb3d8..c30f02d
---- a/net/mac80211/agg-tx.c
-+++ b/net/mac80211/agg-tx.c
-@@ -568,10 +568,9 @@ static void sta_tx_agg_session_timer_expired(struct timer_list *t)
- }
-
- timeout = tid_tx->last_tx + TU_TO_JIFFIES(tid_tx->timeout);
-- if (time_is_after_jiffies(timeout)) {
-- mod_timer(&tid_tx->session_timer, timeout);
-- return;
-- }
-+ /* remove timerout handle for ax210 iot issue */
-+ mod_timer(&tid_tx->session_timer, timeout);
-+ return;
-
- ht_dbg(sta->sdata, "tx session timer expired on %pM tid %d\n",
- sta->sta.addr, tid);
---
-2.36.1
-
diff --git a/recipes-wifi/linux-mac80211/files/patches/subsys/mtk-0013-mac80211-mtk-check-the-control-channel-before-downgr.patch b/recipes-wifi/linux-mac80211/files/patches/subsys/mtk-0012-mac80211-mtk-check-the-control-channel-before-downgr.patch
similarity index 91%
rename from recipes-wifi/linux-mac80211/files/patches/subsys/mtk-0013-mac80211-mtk-check-the-control-channel-before-downgr.patch
rename to recipes-wifi/linux-mac80211/files/patches/subsys/mtk-0012-mac80211-mtk-check-the-control-channel-before-downgr.patch
index cf2f1b5..f5903f0 100644
--- a/recipes-wifi/linux-mac80211/files/patches/subsys/mtk-0013-mac80211-mtk-check-the-control-channel-before-downgr.patch
+++ b/recipes-wifi/linux-mac80211/files/patches/subsys/mtk-0012-mac80211-mtk-check-the-control-channel-before-downgr.patch
@@ -1,7 +1,7 @@
-From 0d87b80d522117ea4c074ff3f7767f76fdd3df2d Mon Sep 17 00:00:00 2001
+From 750e991ce9cf04af982bb11e6058c133d205d879 Mon Sep 17 00:00:00 2001
From: mtk31095 <michael-cy.lee@mediatek.com>
Date: Fri, 16 Dec 2022 10:37:53 +0800
-Subject: [PATCH 912/915] mac80211: mtk: check the control channel before
+Subject: [PATCH 12/14] mac80211: mtk: check the control channel before
downgrading the bandwidth
Signed-off-by: mtk31095 <michael-cy.lee@mediatek.com>
@@ -51,5 +51,5 @@
ifmgd->flags |= ieee80211_chandef_downgrade(&chandef);
ret = ieee80211_vif_use_channel(sdata, &chandef,
--
-2.36.1
+2.18.0
diff --git a/recipes-wifi/linux-mac80211/files/patches/subsys/mtk-0012-mac80211-mtk-fix-the-issue-of-AP-and-STA-starting-on.patch b/recipes-wifi/linux-mac80211/files/patches/subsys/mtk-0012-mac80211-mtk-fix-the-issue-of-AP-and-STA-starting-on.patch
deleted file mode 100644
index b089f6a..0000000
--- a/recipes-wifi/linux-mac80211/files/patches/subsys/mtk-0012-mac80211-mtk-fix-the-issue-of-AP-and-STA-starting-on.patch
+++ /dev/null
@@ -1,258 +0,0 @@
-From 7aebd936d9c3b2f1d1bbd2d9e9996b67fde989a1 Mon Sep 17 00:00:00 2001
-From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
-Date: Wed, 5 Oct 2022 19:13:43 +0800
-Subject: [PATCH 911/915] mac80211: mtk: fix the issue of AP and STA starting
- on DFS channel concurrently
-
-Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
----
- include/net/cfg80211.h | 21 +++++++++++++++++
- include/uapi/linux/nl80211.h | 2 +-
- net/mac80211/cfg.c | 44 ++++++++++++++++++++++++++++++++++++
- net/mac80211/chan.c | 2 +-
- net/wireless/chan.c | 6 ++---
- net/wireless/nl80211.c | 8 +++++++
- net/wireless/rdev-ops.h | 16 +++++++++++++
- net/wireless/trace.h | 15 ++++++++++++
- 8 files changed, 109 insertions(+), 5 deletions(-)
-
-diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
-index b97ddbd..c4c0926 100644
---- a/include/net/cfg80211.h
-+++ b/include/net/cfg80211.h
-@@ -800,6 +800,24 @@ cfg80211_chandef_identical(const struct cfg80211_chan_def *chandef1,
- chandef1->center_freq2 == chandef2->center_freq2);
- }
-
-+/**
-+ * cfg80211_chan_fully_overlap - check if two channel are fully overlapped
-+ * @chandef1: first channel definition
-+ * @chandef2: second channel definition
-+ *
-+ * Return: %true if the channels are valid and fully overlapped, %false otherwise.
-+ */
-+static inline bool
-+cfg80211_chan_fully_overlap(const struct cfg80211_chan_def *chandef1,
-+ const struct cfg80211_chan_def *chandef2)
-+{
-+ return (chandef1->center_freq1 != 0 &&
-+ chandef1->center_freq1 == chandef2->center_freq1 &&
-+ chandef1->width == chandef2->width &&
-+ chandef1->freq1_offset == chandef2->freq1_offset &&
-+ chandef1->center_freq2 == chandef2->center_freq2);
-+}
-+
- /**
- * cfg80211_chandef_is_edmg - check if chandef represents an EDMG channel
- *
-@@ -4402,6 +4420,8 @@ struct cfg80211_ops {
- int (*set_radar_background)(struct wiphy *wiphy,
- struct cfg80211_chan_def *chandef);
- void (*skip_cac)(struct wireless_dev *wdev);
-+ void (*check_cac_skip)(struct wiphy *wiphy,
-+ struct cfg80211_chan_def *chandef);
- };
-
- /*
-@@ -5555,6 +5575,7 @@ struct wireless_dev {
- struct work_struct pmsr_free_wk;
-
- unsigned long unprot_beacon_reported;
-+ bool start_disabled;
- };
-
- static inline u8 *wdev_address(struct wireless_dev *wdev)
-diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
-index e674aa7..ada8288 100644
---- a/include/uapi/linux/nl80211.h
-+++ b/include/uapi/linux/nl80211.h
-@@ -3129,7 +3129,7 @@ enum nl80211_attrs {
- NL80211_ATTR_WIPHY_ANTENNA_GAIN,
-
- /* 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,
- NL80211_ATTR_MAX = __NL80211_ATTR_AFTER_LAST - 1
-diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
-index 0a6257d..a7b6284 100644
---- a/net/mac80211/cfg.c
-+++ b/net/mac80211/cfg.c
-@@ -4519,6 +4519,49 @@ ieee80211_skip_cac(struct wireless_dev *wdev)
- }
- }
-
-+static void
-+ieee80211_check_cac_skip(struct wiphy *wiphy,
-+ struct cfg80211_chan_def *chandef)
-+{
-+ struct ieee80211_local *local = wiphy_priv(wiphy);
-+ struct ieee80211_sub_if_data *s1;
-+ struct ieee80211_sub_if_data *s2;
-+ struct ieee80211_sub_if_data *sdata_sta;
-+ struct ieee80211_if_managed *ifmgd;
-+ struct ieee80211_channel *chan;
-+ struct wireless_dev *wdev;
-+ unsigned int cac_time_ms;
-+
-+ mutex_lock(&local->mtx);
-+ /* Bypass AP's cac if there is a STA associated to the same DFS channel */
-+ list_for_each_entry(s1, &local->interfaces, list) {
-+ ifmgd = &s1->u.mgd;
-+
-+ if (s1->vif.type == NL80211_IFTYPE_STATION && ifmgd->associated)
-+ sdata_sta = s1;
-+ else
-+ continue;
-+
-+ list_for_each_entry(s2, &local->interfaces, list) {
-+ wdev = &s2->wdev;
-+ chan = wdev->chandef.chan;
-+ if (chan) {
-+ if (!(chan->flags & IEEE80211_CHAN_RADAR))
-+ continue;
-+
-+ if (wdev->identifier != sdata_sta->wdev.identifier &&
-+ chan->dfs_state == NL80211_DFS_USABLE && wdev->cac_started &&
-+ cfg80211_chan_fully_overlap(&sdata_sta->vif.bss_conf.chandef,
-+ &s2->vif.bss_conf.chandef)) {
-+ ieee80211_skip_cac(wdev);
-+ sdata_info(s2, "Skip CAC on the associated STA's chan\n");
-+ }
-+ }
-+ }
-+ }
-+ mutex_unlock(&local->mtx);
-+}
-+
- const struct cfg80211_ops mac80211_config_ops = {
- .add_virtual_intf = ieee80211_add_iface,
- .del_virtual_intf = ieee80211_del_iface,
-@@ -4626,4 +4669,5 @@ const struct cfg80211_ops mac80211_config_ops = {
- .color_change = ieee80211_color_change,
- .set_radar_background = ieee80211_set_radar_background,
- .skip_cac = ieee80211_skip_cac,
-+ .check_cac_skip = ieee80211_check_cac_skip,
- };
-diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
-index 63e15f5..5e57e4a 100644
---- a/net/mac80211/chan.c
-+++ b/net/mac80211/chan.c
-@@ -505,7 +505,7 @@ bool ieee80211_is_radar_required(struct ieee80211_local *local)
-
- rcu_read_lock();
- list_for_each_entry_rcu(sdata, &local->interfaces, list) {
-- if (sdata->radar_required) {
-+ if (sdata->radar_required && sdata->wdev.cac_started) {
- rcu_read_unlock();
- return true;
- }
-diff --git a/net/wireless/chan.c b/net/wireless/chan.c
-index 5f50ac4..067ed79 100644
---- a/net/wireless/chan.c
-+++ b/net/wireless/chan.c
-@@ -664,13 +664,13 @@ bool cfg80211_beaconing_iface_active(struct wireless_dev *wdev)
- switch (wdev->iftype) {
- case NL80211_IFTYPE_AP:
- case NL80211_IFTYPE_P2P_GO:
-- active = wdev->beacon_interval != 0;
-+ active = wdev->beacon_interval != 0 || wdev->start_disabled;
- break;
- case NL80211_IFTYPE_ADHOC:
-- active = wdev->ssid_len != 0;
-+ active = wdev->ssid_len != 0 || wdev->start_disabled;
- break;
- case NL80211_IFTYPE_MESH_POINT:
-- active = wdev->mesh_id_len != 0;
-+ active = wdev->mesh_id_len != 0 || wdev->start_disabled;
- break;
- case NL80211_IFTYPE_STATION:
- case NL80211_IFTYPE_OCB:
-diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
-index a20aba5..8dc928d 100644
---- a/net/wireless/nl80211.c
-+++ b/net/wireless/nl80211.c
-@@ -803,6 +803,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
- NLA_POLICY_NESTED(nl80211_mbssid_config_policy),
- [NL80211_ATTR_MBSSID_ELEMS] = { .type = NLA_NESTED },
- [NL80211_ATTR_RADAR_BACKGROUND] = { .type = NLA_FLAG },
-+ [NL80211_ATTR_START_DISABLED] = { .type = NLA_FLAG },
- [NL80211_ATTR_WIPHY_ANTENNA_GAIN] = { .type = NLA_U32 },
- };
-
-@@ -5547,6 +5548,12 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
-
- memset(¶ms, 0, sizeof(params));
-
-+ if (info->attrs[NL80211_ATTR_START_DISABLED]) {
-+ wdev->start_disabled = nla_get_flag(info->attrs[NL80211_ATTR_START_DISABLED]);
-+ err = 0;
-+ goto out;
-+ }
-+
- /* these are required for START_AP */
- if (!info->attrs[NL80211_ATTR_BEACON_INTERVAL] ||
- !info->attrs[NL80211_ATTR_DTIM_PERIOD] ||
-@@ -9393,6 +9400,7 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
- wdev->cac_started = true;
- wdev->cac_start_time = jiffies;
- wdev->cac_time_ms = cac_time_ms;
-+ err = rdev_check_cac_skip(rdev, &wdev->chandef);
- }
- unlock:
- wiphy_unlock(wiphy);
-diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
-index 26f4604..c38aea1 100644
---- a/net/wireless/rdev-ops.h
-+++ b/net/wireless/rdev-ops.h
-@@ -1412,4 +1412,20 @@ rdev_skip_cac(struct cfg80211_registered_device *rdev,
- return 0;
- }
-
-+static inline int
-+rdev_check_cac_skip(struct cfg80211_registered_device *rdev,
-+ struct cfg80211_chan_def *chandef)
-+{
-+ struct wiphy *wiphy = &rdev->wiphy;
-+
-+ if (!rdev->ops->check_cac_skip)
-+ return -EOPNOTSUPP;
-+
-+ trace_rdev_check_cac_skip(wiphy, chandef);
-+ rdev->ops->check_cac_skip(wiphy, chandef);
-+ trace_rdev_return_void(wiphy);
-+
-+ return 0;
-+}
-+
- #endif /* __CFG80211_RDEV_OPS */
-diff --git a/net/wireless/trace.h b/net/wireless/trace.h
-index eadabfa..a7b0c82 100644
---- a/net/wireless/trace.h
-+++ b/net/wireless/trace.h
-@@ -3677,6 +3677,21 @@ TRACE_EVENT(rdev_skip_cac,
- TP_printk(WDEV_PR_FMT, WDEV_PR_ARG)
- );
-
-+TRACE_EVENT(rdev_check_cac_skip,
-+ TP_PROTO(struct wiphy *wiphy, struct cfg80211_chan_def *chandef),
-+
-+ TP_ARGS(wiphy, chandef),
-+
-+ TP_STRUCT__entry(WIPHY_ENTRY
-+ CHAN_DEF_ENTRY),
-+
-+ TP_fast_assign(WIPHY_ASSIGN;
-+ CHAN_DEF_ASSIGN(chandef)),
-+
-+ TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT,
-+ WIPHY_PR_ARG, CHAN_DEF_PR_ARG)
-+);
-+
- #endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */
-
- #undef TRACE_INCLUDE_PATH
---
-2.36.1
-
diff --git a/recipes-wifi/linux-mac80211/files/patches/subsys/mtk-0014-mac80211-mtk-fix-tx-amsdu-aggregation.patch b/recipes-wifi/linux-mac80211/files/patches/subsys/mtk-0013-mac80211-mtk-fix-tx-amsdu-aggregation.patch
similarity index 93%
rename from recipes-wifi/linux-mac80211/files/patches/subsys/mtk-0014-mac80211-mtk-fix-tx-amsdu-aggregation.patch
rename to recipes-wifi/linux-mac80211/files/patches/subsys/mtk-0013-mac80211-mtk-fix-tx-amsdu-aggregation.patch
index 371958d..da8632a 100644
--- a/recipes-wifi/linux-mac80211/files/patches/subsys/mtk-0014-mac80211-mtk-fix-tx-amsdu-aggregation.patch
+++ b/recipes-wifi/linux-mac80211/files/patches/subsys/mtk-0013-mac80211-mtk-fix-tx-amsdu-aggregation.patch
@@ -1,7 +1,7 @@
-From 491811bea8080d41f28438947d51c712ccf91d0e Mon Sep 17 00:00:00 2001
+From b4f6a720d5a0aeaeb2772ce99cf89f7bede959bf Mon Sep 17 00:00:00 2001
From: TomLiu <tomml.liu@mediatek.com>
Date: Wed, 14 Dec 2022 00:26:50 -0800
-Subject: [PATCH 913/915] mac80211: mtk: fix tx amsdu aggregation
+Subject: [PATCH 13/14] mac80211: mtk: fix tx amsdu aggregation
---
include/net/mac80211.h | 7 +++++++
@@ -51,5 +51,5 @@
capab |= u16_encode_bits(tid, IEEE80211_ADDBA_PARAM_TID_MASK);
capab |= u16_encode_bits(agg_size, IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK);
--
-2.36.1
+2.18.0
diff --git a/recipes-wifi/linux-mac80211/files/patches/subsys/mtk-0014--mac80211-mtk-track-obss-color-bitmap.patch b/recipes-wifi/linux-mac80211/files/patches/subsys/mtk-0014--mac80211-mtk-track-obss-color-bitmap.patch
new file mode 100644
index 0000000..18d8aab
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches/subsys/mtk-0014--mac80211-mtk-track-obss-color-bitmap.patch
@@ -0,0 +1,102 @@
+From 40ceb2dcc486ddefb5e4cb69e4cd86906242872c Mon Sep 17 00:00:00 2001
+From: Yi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
+Date: Tue, 15 Nov 2022 06:35:48 +0800
+Subject: [PATCH] mac80211: mtk: track obss color bitmap
+
+Track OBSS BSS color when receive their beacon.
+
+Adding 2 tracepoint for debug, usage:
+echo 1 > /sys/kernel/debug/tracing/events/mac80211/bss_color_bitmap/enable
+echo 1 > /sys/kernel/debug/tracing/events/mac80211/bss_color_collision/enable
+---
+ include/net/cfg80211.h | 1 +
+ net/mac80211/rx.c | 14 ++++++++++++--
+ net/mac80211/trace.h | 35 +++++++++++++++++++++++++++++++++++
+ 3 files changed, 48 insertions(+), 2 deletions(-)
+
+diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
+index c4c0926..e5175c2 100644
+--- a/include/net/cfg80211.h
++++ b/include/net/cfg80211.h
+@@ -307,6 +307,7 @@ struct cfg80211_he_bss_color {
+ u8 color;
+ bool enabled;
+ bool partial;
++ u64 used_color_bitmap;
+ };
+
+ /**
+diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
+index eb16838..4a6491c 100644
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -3219,9 +3219,18 @@ ieee80211_rx_check_bss_color_collision(struct ieee80211_rx_data *rx)
+
+ color = le32_get_bits(he_oper->he_oper_params,
+ IEEE80211_HE_OPERATION_BSS_COLOR_MASK);
+- if (color == bss_conf->he_bss_color.color)
++
++ bss_conf->he_bss_color.used_color_bitmap |= BIT_ULL(color);
++
++ trace_bss_color_bitmap(color,
++ bss_conf->he_bss_color.used_color_bitmap);
++
++ if (color == bss_conf->he_bss_color.color) {
++ trace_bss_color_collision(color);
++
+ ieeee80211_obss_color_collision_notify(&rx->sdata->vif,
+- BIT_ULL(color));
++ bss_conf->he_bss_color.used_color_bitmap);
++ }
+ }
+ }
+
+diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
+index d91498f..013f5e4 100644
+--- a/net/mac80211/trace.h
++++ b/net/mac80211/trace.h
+@@ -2899,6 +2899,41 @@ DEFINE_EVENT(sta_event, drv_net_fill_forward_path,
+ TP_ARGS(local, sdata, sta)
+ );
+
++TRACE_EVENT(bss_color_bitmap,
++ TP_PROTO(u8 color,
++ u64 color_bitmap),
++
++ TP_ARGS(color, color_bitmap),
++
++ TP_STRUCT__entry(
++ __field(u8, color)
++ __field(u64, color_bitmap)
++ ),
++
++ TP_fast_assign(
++ __entry->color = color;
++ __entry->color_bitmap = color_bitmap;
++ ),
++
++ TP_printk(
++ "color=%u color_bitmap=0x%llx", __entry->color, __entry->color_bitmap
++ )
++);
++
++TRACE_EVENT(bss_color_collision,
++ TP_PROTO(u8 color),
++
++ TP_ARGS(color),
++
++ TP_STRUCT__entry(__field(u8, color)),
++
++ TP_fast_assign(
++ __entry->color = color;
++ ),
++
++ TP_printk("collision detected on color %u", __entry->color)
++);
++
+ #endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */
+
+ #undef TRACE_INCLUDE_PATH
+--
+2.36.1
+
diff --git a/recipes-wifi/linux-mac80211/files/patches/subsys/mtk-0014-mac80211-mtk-add-sta-assisted-DFS-state-update-mecha.patch b/recipes-wifi/linux-mac80211/files/patches/subsys/mtk-0014-mac80211-mtk-add-sta-assisted-DFS-state-update-mecha.patch
new file mode 100644
index 0000000..2006b27
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches/subsys/mtk-0014-mac80211-mtk-add-sta-assisted-DFS-state-update-mecha.patch
@@ -0,0 +1,176 @@
+From 8fdded8b5d47f1ab5fb7ab1fd2a4247cd81edad0 Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Mon, 20 Feb 2023 14:25:24 +0800
+Subject: [PATCH] mac80211: mtk: add sta-assisted DFS state update mechanism
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ include/net/cfg80211.h | 14 +++++++++
+ include/uapi/linux/nl80211.h | 6 ++++
+ net/mac80211/mlme.c | 11 +++++++
+ net/wireless/chan.c | 60 ++++++++++++++++++++++++++++++++++++
+ 4 files changed, 91 insertions(+)
+
+diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
+index b97ddbd..02ad2b2 100644
+--- a/include/net/cfg80211.h
++++ b/include/net/cfg80211.h
+@@ -7641,6 +7641,20 @@ void cfg80211_cac_event(struct net_device *netdev,
+ const struct cfg80211_chan_def *chandef,
+ enum nl80211_radar_event event, gfp_t gfp);
+
++/**
++ * cfg80211_sta_update_dfs_state - Update channel's DFS state during STA channel switch,
++ * association, and disassociation
++ * @wdev: the wireless device
++ * @bss_chandef: the current BSS channel definition
++ * @csa_chandef: the CSA channel definition
++ * @associated: whether STA is during association or disassociation process
++ *
++ */
++void cfg80211_sta_update_dfs_state(struct wireless_dev *wdev,
++ const struct cfg80211_chan_def *bss_chandef,
++ const struct cfg80211_chan_def *csa_chandef,
++ bool associated);
++
+ /**
+ * cfg80211_background_cac_abort - Channel Availability Check offchan abort event
+ * @wiphy: the wiphy
+diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
+index e674aa7..3e348a5 100644
+--- a/include/uapi/linux/nl80211.h
++++ b/include/uapi/linux/nl80211.h
+@@ -6294,6 +6294,10 @@ enum nl80211_smps_mode {
+ * applicable for ETSI dfs domain where pre-CAC is valid for ever.
+ * @NL80211_RADAR_CAC_STARTED: Channel Availability Check has been started,
+ * should be generated by HW if NL80211_EXT_FEATURE_DFS_OFFLOAD is enabled.
++ * @NL80211_RADAR_STA_CAC_SKIPPED: STA set the DFS state to available
++ * when receiving CSA/assoc resp
++ * @NL80211_RADAR_STA_CAC_EXPIRED: STA set the DFS state to usable
++ * when STA is disconnected or leaving the channel
+ */
+ enum nl80211_radar_event {
+ NL80211_RADAR_DETECTED,
+@@ -6302,6 +6306,8 @@ enum nl80211_radar_event {
+ NL80211_RADAR_NOP_FINISHED,
+ NL80211_RADAR_PRE_CAC_EXPIRED,
+ NL80211_RADAR_CAC_STARTED,
++ NL80211_RADAR_STA_CAC_SKIPPED,
++ NL80211_RADAR_STA_CAC_EXPIRED,
+ };
+
+ /**
+diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
+index 8ee325a..48053e4 100644
+--- a/net/mac80211/mlme.c
++++ b/net/mac80211/mlme.c
+@@ -1442,6 +1442,10 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
+ IEEE80211_QUEUE_STOP_REASON_CSA);
+ mutex_unlock(&local->mtx);
+
++ cfg80211_sta_update_dfs_state(&sdata->wdev,
++ &sdata->vif.bss_conf.chandef,
++ &sdata->csa_chandef,
++ sdata->vif.bss_conf.assoc);
+ cfg80211_ch_switch_started_notify(sdata->dev, &csa_ie.chandef,
+ csa_ie.count, csa_ie.mode);
+
+@@ -2420,6 +2424,10 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
+ cancel_delayed_work_sync(&ifmgd->tx_tspec_wk);
+
+ sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
++
++ cfg80211_sta_update_dfs_state(&sdata->wdev,
++ &sdata->vif.bss_conf.chandef,
++ NULL, sdata->vif.bss_conf.assoc);
+ }
+
+ static void ieee80211_reset_ap_probe(struct ieee80211_sub_if_data *sdata)
+@@ -3782,6 +3790,9 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
+ event.u.mlme.status = MLME_SUCCESS;
+ drv_event_callback(sdata->local, sdata, &event);
+ sdata_info(sdata, "associated\n");
++ cfg80211_sta_update_dfs_state(&sdata->wdev,
++ &sdata->vif.bss_conf.chandef,
++ NULL, sdata->vif.bss_conf.assoc);
+
+ /*
+ * destroy assoc_data afterwards, as otherwise an idle
+diff --git a/net/wireless/chan.c b/net/wireless/chan.c
+index 5f50ac4..0309758 100644
+--- a/net/wireless/chan.c
++++ b/net/wireless/chan.c
+@@ -14,6 +14,7 @@
+ #include <net/cfg80211.h>
+ #include "core.h"
+ #include "rdev-ops.h"
++#include "nl80211.h"
+
+ static bool cfg80211_valid_60g_freq(u32 freq)
+ {
+@@ -1386,3 +1387,62 @@ bool cfg80211_any_usable_channels(struct wiphy *wiphy,
+ return false;
+ }
+ EXPORT_SYMBOL(cfg80211_any_usable_channels);
++
++static void cfg80211_sta_radar_notify(struct wiphy *wiphy,
++ const struct cfg80211_chan_def *chandef,
++ enum nl80211_radar_event event)
++{
++ struct wireless_dev *wdev;
++
++ list_for_each_entry(wdev, &wiphy->wdev_list, list) {
++ if (cfg80211_chandef_dfs_required(wiphy, chandef, wdev->iftype) > 0) {
++ nl80211_radar_notify(wiphy_to_rdev(wiphy), chandef,
++ event, wdev->netdev, GFP_KERNEL);
++ return;
++ }
++ }
++}
++
++void cfg80211_sta_update_dfs_state(struct wireless_dev *wdev,
++ const struct cfg80211_chan_def *bss_chandef,
++ const struct cfg80211_chan_def *csa_chandef,
++ bool associated)
++{
++ bool csa_active = !!csa_chandef;
++ enum nl80211_dfs_state dfs_state = NL80211_DFS_USABLE;
++ enum nl80211_radar_event event = NL80211_RADAR_STA_CAC_EXPIRED;
++
++ if (!bss_chandef)
++ return;
++
++ /* assume csa channel is cac completed */
++ if (csa_active &&
++ (cfg80211_chandef_dfs_usable(wdev->wiphy, csa_chandef) ||
++ cfg80211_chandef_dfs_available(wdev->wiphy, csa_chandef))) {
++ cfg80211_set_dfs_state(wdev->wiphy, csa_chandef, NL80211_DFS_AVAILABLE);
++ cfg80211_sta_radar_notify(wdev->wiphy, csa_chandef,
++ NL80211_RADAR_STA_CAC_SKIPPED);
++ netdev_info(wdev->netdev, "Set CSA channel's DFS state to available\n");
++ }
++
++ /* avoid updating the dfs state during nop */
++ if (!cfg80211_chandef_dfs_usable(wdev->wiphy, bss_chandef) &&
++ !cfg80211_chandef_dfs_available(wdev->wiphy, bss_chandef))
++ return;
++
++ if (associated && !csa_active) {
++ dfs_state = NL80211_DFS_AVAILABLE;
++ event = NL80211_RADAR_STA_CAC_SKIPPED;
++ }
++
++ cfg80211_set_dfs_state(wdev->wiphy, bss_chandef, dfs_state);
++ cfg80211_sta_radar_notify(wdev->wiphy, bss_chandef, event);
++
++ if (csa_active)
++ netdev_info(wdev->netdev, "Set origin channel's DFS state to usable\n");
++ else
++ netdev_info(wdev->netdev, "Set BSS channel's DFS state to %s due to %s\n",
++ (dfs_state == NL80211_DFS_USABLE) ? "usable" : "available",
++ associated ? "association" : "disassociation");
++}
++EXPORT_SYMBOL(cfg80211_sta_update_dfs_state);
+--
+2.18.0
+
diff --git a/recipes-wifi/linux-mac80211/files/patches/subsys/mtk-0015-mac80211-mtk-aging-color-bitmap.patch b/recipes-wifi/linux-mac80211/files/patches/subsys/mtk-0015-mac80211-mtk-aging-color-bitmap.patch
new file mode 100644
index 0000000..4ed9142
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches/subsys/mtk-0015-mac80211-mtk-aging-color-bitmap.patch
@@ -0,0 +1,126 @@
+From f6cd955e1c042a00691fa80d231495024cfcf7a5 Mon Sep 17 00:00:00 2001
+From: Yi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
+Date: Tue, 15 Nov 2022 11:03:22 +0800
+Subject: [PATCH] mac80211: mtk: ageout color bitmap
+
+Adding a periodic work which runs once per second to check BSS color.
+OBSS BSS Color will be ageout if not seen for 10 seconds.
+---
+ include/net/cfg80211.h | 1 +
+ net/mac80211/cfg.c | 25 +++++++++++++++++++++++++
+ net/mac80211/ieee80211_i.h | 4 ++++
+ net/mac80211/iface.c | 5 +++++
+ net/mac80211/rx.c | 1 +
+ 5 files changed, 36 insertions(+)
+
+diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
+index e5175c2..3e826f0 100644
+--- a/include/net/cfg80211.h
++++ b/include/net/cfg80211.h
+@@ -308,6 +308,7 @@ struct cfg80211_he_bss_color {
+ bool enabled;
+ bool partial;
+ u64 used_color_bitmap;
++ u64 color_last_seen[64];
+ };
+
+ /**
+diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
+index a7b6284..f084912 100644
+--- a/net/mac80211/cfg.c
++++ b/net/mac80211/cfg.c
+@@ -4425,6 +4425,31 @@ unlock:
+ sdata_unlock(sdata);
+ }
+
++void ieee80211_color_aging_work(struct work_struct *work)
++{
++ struct ieee80211_sub_if_data *sdata =
++ container_of(work, struct ieee80211_sub_if_data,
++ color_aging_work.work);
++ struct cfg80211_he_bss_color *he_bss_color = &sdata->vif.bss_conf.he_bss_color;
++ int i = 0;
++
++ sdata_lock(sdata);
++
++ for (i = 0; i < IEEE80211_BSS_COLOR_MAX; i++) {
++ /* ageout if not seen for a period */
++ if ((he_bss_color->used_color_bitmap & BIT_ULL(i)) &&
++ time_before(he_bss_color->color_last_seen[i],
++ jiffies - IEEE80211_BSS_COLOR_AGEOUT_TIME * HZ)) {
++ he_bss_color->used_color_bitmap &= ~BIT_ULL(i);
++ }
++ }
++
++ ieee80211_queue_delayed_work(&sdata->local->hw,
++ &sdata->color_aging_work, HZ);
++
++ sdata_unlock(sdata);
++}
++
+ void ieee80211_color_change_finish(struct ieee80211_vif *vif)
+ {
+ struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
+index 6edabd8..415f202 100644
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -1033,6 +1033,8 @@ struct ieee80211_sub_if_data {
+ } debugfs;
+ #endif
+
++ struct delayed_work color_aging_work;
++
+ /* must be last, dynamically sized area in this! */
+ struct ieee80211_vif vif;
+ };
+@@ -1811,8 +1813,11 @@ void ieee80211_csa_finalize_work(struct work_struct *work);
+ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_csa_settings *params);
+
++#define IEEE80211_BSS_COLOR_AGEOUT_TIME 10
++#define IEEE80211_BSS_COLOR_MAX 64
+ /* color change handling */
+ void ieee80211_color_change_finalize_work(struct work_struct *work);
++void ieee80211_color_aging_work(struct work_struct *work);
+
+ /* interface handling */
+ #define MAC80211_SUPPORTED_FEATURES_TX (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | \
+diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
+index 43f6cb0..7f26828 100644
+--- a/net/mac80211/iface.c
++++ b/net/mac80211/iface.c
+@@ -466,6 +466,8 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do
+ cancel_work_sync(&sdata->color_change_finalize_work);
+
+ cancel_delayed_work_sync(&sdata->dfs_cac_timer_work);
++ if (sdata->vif.type == NL80211_IFTYPE_AP)
++ cancel_delayed_work_sync(&sdata->color_aging_work);
+
+ if (sdata->wdev.cac_started) {
+ chandef = sdata->vif.bss_conf.chandef;
+@@ -1804,6 +1806,9 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
+ skb_queue_head_init(&sdata->u.ap.ps.bc_buf);
+ INIT_LIST_HEAD(&sdata->u.ap.vlans);
+ sdata->vif.bss_conf.bssid = sdata->vif.addr;
++ INIT_DELAYED_WORK(&sdata->color_aging_work, ieee80211_color_aging_work);
++ ieee80211_queue_delayed_work(&sdata->local->hw,
++ &sdata->color_aging_work, 0);
+ break;
+ case NL80211_IFTYPE_P2P_CLIENT:
+ type = NL80211_IFTYPE_STATION;
+diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
+index 789a41b..4a6491c 100644
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -3221,6 +3221,7 @@ ieee80211_rx_check_bss_color_collision(struct ieee80211_rx_data *rx)
+ IEEE80211_HE_OPERATION_BSS_COLOR_MASK);
+
+ bss_conf->he_bss_color.used_color_bitmap |= BIT_ULL(color);
++ bss_conf->he_bss_color.color_last_seen[color] = jiffies;
+
+ trace_bss_color_bitmap(color,
+ bss_conf->he_bss_color.used_color_bitmap);
+--
+2.39.0
+
diff --git a/recipes-wifi/linux-mac80211/files/patches/subsys/mtk-0015-nl80211-mtk-Mark-DFS-channel-as-available-for-CSA.patch b/recipes-wifi/linux-mac80211/files/patches/subsys/mtk-0015-nl80211-mtk-Mark-DFS-channel-as-available-for-CSA.patch
new file mode 100644
index 0000000..eff574e
--- /dev/null
+++ b/recipes-wifi/linux-mac80211/files/patches/subsys/mtk-0015-nl80211-mtk-Mark-DFS-channel-as-available-for-CSA.patch
@@ -0,0 +1,28 @@
+From 20d6ed31c0e6c15cfbc120bea6a8729121560371 Mon Sep 17 00:00:00 2001
+From: "himanshu.goyal" <himanshu.goyal@mediatek.com>
+Date: Tue, 21 Feb 2023 15:24:09 +0800
+Subject: [PATCH] nl80211: mtk: Mark DFS channel as available for CSA.
+
+---
+ net/wireless/nl80211.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
+index 8dc928d..a02aacb 100644
+--- a/net/wireless/nl80211.c
++++ b/net/wireless/nl80211.c
+@@ -3193,6 +3193,11 @@ int nl80211_parse_chandef(struct cfg80211_registered_device *rdev,
+ return -EINVAL;
+ }
+
++ /* Use RADAR_BACKGROUND attribute here for skipping CAC */
++ if (info->attrs[NL80211_ATTR_RADAR_BACKGROUND]) {
++ cfg80211_set_dfs_state(&rdev->wiphy, chandef, NL80211_DFS_AVAILABLE);
++ }
++
+ if (!cfg80211_chandef_usable(&rdev->wiphy, chandef,
+ IEEE80211_CHAN_DISABLED)) {
+ NL_SET_ERR_MSG(extack, "(extension) channel is disabled");
+--
+2.18.0
+
diff --git a/recipes-wifi/linux-mac80211/files/patches/subsys/subsys.inc b/recipes-wifi/linux-mac80211/files/patches/subsys/subsys.inc
index 86e3ccb..dcebb38 100644
--- a/recipes-wifi/linux-mac80211/files/patches/subsys/subsys.inc
+++ b/recipes-wifi/linux-mac80211/files/patches/subsys/subsys.inc
@@ -42,6 +42,7 @@
file://344-v6.1-wifi-cfg80211-fix-ieee80211_data_to_8023_exthdr-hand.patch \
file://345-v6.1-wifi-mac80211-do-not-drop-packets-smaller-than-the-L.patch \
file://346-v6.0-wifi-mac80211-fix-mesh-airtime-link-metric-estimatin.patch \
+ file://347-wifi-mac80211-introduce-ieee80211_refresh_tx_agg_ses.patch \
file://363-v5.19-bss-color-collision.patch \
file://364-mac80211-add-support-for-restricting-netdev-features.patch \
file://400-allow-ibss-mixed.patch \
@@ -57,12 +58,14 @@
file://mtk-0006-mac80211-mtk-add-support-for-runtime-set-inband-disc.patch \
file://mtk-0007-mac80211-mtk-add-s1g-category-to-_ieee80211_is_robus.patch \
file://mtk-0008-mac80211-mtk-make-4addr-null-frames-using-min_rate-f.patch \
- file://mtk-0009-mac80211-mtk-remove-timerout-handle-for-ax210-iot-is.patch \
file://mtk-0010-cfg80211-mtk-implement-DFS-status-show-cac-and-nop-s.patch \
file://mtk-0011-mac80211-mtk-Set-TWT-Information-Frame-Disabled-bit-.patch \
- file://mtk-0012-mac80211-mtk-fix-the-issue-of-AP-and-STA-starting-on.patch \
- file://mtk-0013-mac80211-mtk-check-the-control-channel-before-downgr.patch \
- file://mtk-0014-mac80211-mtk-fix-tx-amsdu-aggregation.patch \
+ file://mtk-0012-mac80211-mtk-check-the-control-channel-before-downgr.patch \
+ file://mtk-0013-mac80211-mtk-fix-tx-amsdu-aggregation.patch \
+ file://mtk-0014--mac80211-mtk-track-obss-color-bitmap.patch \
+ file://mtk-0014-mac80211-mtk-add-sta-assisted-DFS-state-update-mecha.patch \
+ file://mtk-0015-mac80211-mtk-aging-color-bitmap.patch \
+ file://mtk-0015-nl80211-mtk-Mark-DFS-channel-as-available-for-CSA.patch \
file://mtk-9900-mac80211-mtk-mask-kernel-version-limitation-and-fil.patch \
file://mtk-9901-mac80211-mtk-add-fill-receive-path-ops-to-get-wed-i.patch \
file://mtk-9902-mac80211-mtk-register-.ndo_setup_tc-to-support-wifi2.patch \
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0000-sync-to-master.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0000-sync-to-master.patch
deleted file mode 100644
index 44a01ec..0000000
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0000-sync-to-master.patch
+++ /dev/null
@@ -1,249 +0,0 @@
-diff --git a/eeprom.c b/eeprom.c
-index 0a88048b..ea54b7af 100644
---- a/eeprom.c
-+++ b/eeprom.c
-@@ -138,6 +138,7 @@ mt76_find_power_limits_node(struct mt76_dev *dev)
- {
- struct device_node *np = dev->dev->of_node;
- const char *const region_names[] = {
-+ [NL80211_DFS_UNSET] = "ww",
- [NL80211_DFS_ETSI] = "etsi",
- [NL80211_DFS_FCC] = "fcc",
- [NL80211_DFS_JP] = "jp",
-diff --git a/mt76_connac_mac.c b/mt76_connac_mac.c
-index 614df85e..aed4ee95 100644
---- a/mt76_connac_mac.c
-+++ b/mt76_connac_mac.c
-@@ -823,7 +823,6 @@ void mt76_connac2_mac_decode_he_radiotap(struct mt76_dev *dev,
- HE_BITS(DATA2_TXOP_KNOWN),
- };
- u32 ltf_size = le32_get_bits(rxv[2], MT_CRXV_HE_LTF_SIZE) + 1;
-- u32 txbf_mask = is_mt7996(dev) ? BIT(11) : BIT(10);
- struct ieee80211_radiotap_he *he;
-
- status->flag |= RX_FLAG_RADIOTAP_HE;
-@@ -837,7 +836,7 @@ void mt76_connac2_mac_decode_he_radiotap(struct mt76_dev *dev,
- he->data5 = HE_PREP(DATA5_PE_DISAMBIG, PE_DISAMBIG, rxv[2]) |
- le16_encode_bits(ltf_size,
- IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE);
-- if (le32_to_cpu(rxv[0]) & txbf_mask)
-+ if (le32_to_cpu(rxv[0]) & MT_PRXV_TXBF)
- he->data5 |= HE_BITS(DATA5_TXBF);
- he->data6 = HE_PREP(DATA6_TXOP, TXOP_DUR, rxv[14]) |
- HE_PREP(DATA6_DOPPLER, DOPPLER, rxv[14]);
-diff --git a/mt76x0/usb_mcu.c b/mt76x0/usb_mcu.c
-index 45502fd4..6dc1f51f 100644
---- a/mt76x0/usb_mcu.c
-+++ b/mt76x0/usb_mcu.c
-@@ -148,6 +148,7 @@ static int mt76x0u_load_firmware(struct mt76x02_dev *dev)
- mt76_wr(dev, MT_USB_DMA_CFG, val);
-
- ret = mt76x0u_upload_firmware(dev, hdr);
-+ mt76x02_set_ethtool_fwver(dev, hdr);
- release_firmware(fw);
-
- mt76_wr(dev, MT_FCE_PSE_CTRL, 1);
-diff --git a/mt7996/mac.c b/mt7996/mac.c
-index 674cea1a..c9a9f0e3 100644
---- a/mt7996/mac.c
-+++ b/mt7996/mac.c
-@@ -12,6 +12,10 @@
-
- #define to_rssi(field, rcpi) ((FIELD_GET(field, rcpi) - 220) / 2)
-
-+#define HE_BITS(f) cpu_to_le16(IEEE80211_RADIOTAP_HE_##f)
-+#define HE_PREP(f, m, v) le16_encode_bits(le32_get_bits(v, MT_CRXV_HE_##m),\
-+ IEEE80211_RADIOTAP_HE_##f)
-+
- static const struct mt7996_dfs_radar_spec etsi_radar_specs = {
- .pulse_th = { 110, -10, -80, 40, 5200, 128, 5200 },
- .radar_pattern = {
-@@ -251,6 +255,178 @@ void mt7996_mac_enable_rtscts(struct mt7996_dev *dev,
- mt76_clear(dev, addr, BIT(5));
- }
-
-+static void
-+mt7996_mac_decode_he_radiotap_ru(struct mt76_rx_status *status,
-+ struct ieee80211_radiotap_he *he,
-+ __le32 *rxv)
-+{
-+ u32 ru_h, ru_l;
-+ u8 ru, offs = 0;
-+
-+ ru_l = le32_get_bits(rxv[0], MT_PRXV_HE_RU_ALLOC_L);
-+ ru_h = le32_get_bits(rxv[1], MT_PRXV_HE_RU_ALLOC_H);
-+ ru = (u8)(ru_l | ru_h << 4);
-+
-+ status->bw = RATE_INFO_BW_HE_RU;
-+
-+ switch (ru) {
-+ case 0 ... 36:
-+ status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_26;
-+ offs = ru;
-+ break;
-+ case 37 ... 52:
-+ status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_52;
-+ offs = ru - 37;
-+ break;
-+ case 53 ... 60:
-+ status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_106;
-+ offs = ru - 53;
-+ break;
-+ case 61 ... 64:
-+ status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_242;
-+ offs = ru - 61;
-+ break;
-+ case 65 ... 66:
-+ status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_484;
-+ offs = ru - 65;
-+ break;
-+ case 67:
-+ status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_996;
-+ break;
-+ case 68:
-+ status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_2x996;
-+ break;
-+ }
-+
-+ he->data1 |= HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
-+ he->data2 |= HE_BITS(DATA2_RU_OFFSET_KNOWN) |
-+ le16_encode_bits(offs,
-+ IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET);
-+}
-+
-+static void
-+mt7996_mac_decode_he_mu_radiotap(struct sk_buff *skb, __le32 *rxv)
-+{
-+ struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
-+ static const struct ieee80211_radiotap_he_mu mu_known = {
-+ .flags1 = HE_BITS(MU_FLAGS1_SIG_B_MCS_KNOWN) |
-+ HE_BITS(MU_FLAGS1_SIG_B_DCM_KNOWN) |
-+ HE_BITS(MU_FLAGS1_CH1_RU_KNOWN) |
-+ HE_BITS(MU_FLAGS1_SIG_B_SYMS_USERS_KNOWN),
-+ .flags2 = HE_BITS(MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN),
-+ };
-+ struct ieee80211_radiotap_he_mu *he_mu = NULL;
-+
-+ status->flag |= RX_FLAG_RADIOTAP_HE_MU;
-+
-+ he_mu = skb_push(skb, sizeof(mu_known));
-+ memcpy(he_mu, &mu_known, sizeof(mu_known));
-+
-+#define MU_PREP(f, v) le16_encode_bits(v, IEEE80211_RADIOTAP_HE_MU_##f)
-+
-+ he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_MCS, status->rate_idx);
-+ if (status->he_dcm)
-+ he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_DCM, status->he_dcm);
-+
-+ he_mu->flags2 |= MU_PREP(FLAGS2_BW_FROM_SIG_A_BW, status->bw) |
-+ MU_PREP(FLAGS2_SIG_B_SYMS_USERS,
-+ le32_get_bits(rxv[2], MT_CRXV_HE_NUM_USER));
-+
-+ he_mu->ru_ch1[0] = le32_get_bits(rxv[3], MT_CRXV_HE_RU0);
-+
-+ if (status->bw >= RATE_INFO_BW_40) {
-+ he_mu->flags1 |= HE_BITS(MU_FLAGS1_CH2_RU_KNOWN);
-+ he_mu->ru_ch2[0] = le32_get_bits(rxv[3], MT_CRXV_HE_RU1);
-+ }
-+
-+ if (status->bw >= RATE_INFO_BW_80) {
-+ he_mu->ru_ch1[1] = le32_get_bits(rxv[3], MT_CRXV_HE_RU2);
-+ he_mu->ru_ch2[1] = le32_get_bits(rxv[3], MT_CRXV_HE_RU3);
-+ }
-+}
-+
-+static void
-+mt7996_mac_decode_he_radiotap(struct sk_buff *skb, __le32 *rxv, u8 mode)
-+{
-+ struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
-+ static const struct ieee80211_radiotap_he known = {
-+ .data1 = HE_BITS(DATA1_DATA_MCS_KNOWN) |
-+ HE_BITS(DATA1_DATA_DCM_KNOWN) |
-+ HE_BITS(DATA1_STBC_KNOWN) |
-+ HE_BITS(DATA1_CODING_KNOWN) |
-+ HE_BITS(DATA1_LDPC_XSYMSEG_KNOWN) |
-+ HE_BITS(DATA1_DOPPLER_KNOWN) |
-+ HE_BITS(DATA1_SPTL_REUSE_KNOWN) |
-+ HE_BITS(DATA1_BSS_COLOR_KNOWN),
-+ .data2 = HE_BITS(DATA2_GI_KNOWN) |
-+ HE_BITS(DATA2_TXBF_KNOWN) |
-+ HE_BITS(DATA2_PE_DISAMBIG_KNOWN) |
-+ HE_BITS(DATA2_TXOP_KNOWN),
-+ };
-+ struct ieee80211_radiotap_he *he = NULL;
-+ u32 ltf_size = le32_get_bits(rxv[2], MT_CRXV_HE_LTF_SIZE) + 1;
-+
-+ status->flag |= RX_FLAG_RADIOTAP_HE;
-+
-+ he = skb_push(skb, sizeof(known));
-+ memcpy(he, &known, sizeof(known));
-+
-+ he->data3 = HE_PREP(DATA3_BSS_COLOR, BSS_COLOR, rxv[14]) |
-+ HE_PREP(DATA3_LDPC_XSYMSEG, LDPC_EXT_SYM, rxv[2]);
-+ he->data4 = HE_PREP(DATA4_SU_MU_SPTL_REUSE, SR_MASK, rxv[11]);
-+ he->data5 = HE_PREP(DATA5_PE_DISAMBIG, PE_DISAMBIG, rxv[2]) |
-+ le16_encode_bits(ltf_size,
-+ IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE);
-+ if (le32_to_cpu(rxv[0]) & MT_PRXV_TXBF)
-+ he->data5 |= HE_BITS(DATA5_TXBF);
-+ he->data6 = HE_PREP(DATA6_TXOP, TXOP_DUR, rxv[14]) |
-+ HE_PREP(DATA6_DOPPLER, DOPPLER, rxv[14]);
-+
-+ switch (mode) {
-+ case MT_PHY_TYPE_HE_SU:
-+ he->data1 |= HE_BITS(DATA1_FORMAT_SU) |
-+ HE_BITS(DATA1_UL_DL_KNOWN) |
-+ HE_BITS(DATA1_BEAM_CHANGE_KNOWN) |
-+ HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
-+
-+ he->data3 |= HE_PREP(DATA3_BEAM_CHANGE, BEAM_CHNG, rxv[14]) |
-+ HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]);
-+ break;
-+ case MT_PHY_TYPE_HE_EXT_SU:
-+ he->data1 |= HE_BITS(DATA1_FORMAT_EXT_SU) |
-+ HE_BITS(DATA1_UL_DL_KNOWN) |
-+ HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
-+
-+ he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]);
-+ break;
-+ case MT_PHY_TYPE_HE_MU:
-+ he->data1 |= HE_BITS(DATA1_FORMAT_MU) |
-+ HE_BITS(DATA1_UL_DL_KNOWN);
-+
-+ he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[2]);
-+ he->data4 |= HE_PREP(DATA4_MU_STA_ID, MU_AID, rxv[7]);
-+
-+ mt7996_mac_decode_he_radiotap_ru(status, he, rxv);
-+ mt7996_mac_decode_he_mu_radiotap(skb, rxv);
-+ break;
-+ case MT_PHY_TYPE_HE_TB:
-+ he->data1 |= HE_BITS(DATA1_FORMAT_TRIG) |
-+ HE_BITS(DATA1_SPTL_REUSE2_KNOWN) |
-+ HE_BITS(DATA1_SPTL_REUSE3_KNOWN) |
-+ HE_BITS(DATA1_SPTL_REUSE4_KNOWN);
-+
-+ he->data4 |= HE_PREP(DATA4_TB_SPTL_REUSE1, SR_MASK, rxv[11]) |
-+ HE_PREP(DATA4_TB_SPTL_REUSE2, SR1_MASK, rxv[11]) |
-+ HE_PREP(DATA4_TB_SPTL_REUSE3, SR2_MASK, rxv[11]) |
-+ HE_PREP(DATA4_TB_SPTL_REUSE4, SR3_MASK, rxv[11]);
-+
-+ mt7996_mac_decode_he_radiotap_ru(status, he, rxv);
-+ break;
-+ default:
-+ break;
-+ }
-+}
-+
- /* The HW does not translate the mac header to 802.3 for mesh point */
- static int mt7996_reverse_frag0_hdr_trans(struct sk_buff *skb, u16 hdr_gap)
- {
-@@ -686,8 +862,7 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
- }
-
- if (rxv && mode >= MT_PHY_TYPE_HE_SU && !(status->flag & RX_FLAG_8023))
-- mt76_connac2_mac_decode_he_radiotap(&dev->mt76, skb, rxv,
-- mode);
-+ mt7996_mac_decode_he_radiotap(skb, rxv, mode);
-
- if (!status->wcid || !ieee80211_is_data_qos(fc))
- return 0;
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0001-Revert-wifi-mt76-mt7996-rely-on-mt76_connac_tx_compl.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0001-Revert-wifi-mt76-mt7996-rely-on-mt76_connac_tx_compl.patch
deleted file mode 100644
index 1022535..0000000
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0001-Revert-wifi-mt76-mt7996-rely-on-mt76_connac_tx_compl.patch
+++ /dev/null
@@ -1,96 +0,0 @@
-From 6767bcfec5f48f14fdf63c9699c63e6bc741ad74 Mon Sep 17 00:00:00 2001
-From: Shayne Chen <shayne.chen@mediatek.com>
-Date: Fri, 3 Feb 2023 11:00:59 +0800
-Subject: [PATCH 1/7] Revert "wifi: mt76: mt7996: rely on
- mt76_connac_tx_complete_skb"
-
-This reverts commit 8688756305c643b8a296c16d0626732aaae1d02a.
----
- mt7996/mac.c | 21 +++++++++++++++++++++
- mt7996/mac.h | 13 +++++++++++++
- mt7996/mmio.c | 2 +-
- mt7996/mt7996.h | 1 +
- 4 files changed, 36 insertions(+), 1 deletion(-)
-
-diff --git a/mt7996/mac.c b/mt7996/mac.c
-index c9a9f0e3..0d718598 100644
---- a/mt7996/mac.c
-+++ b/mt7996/mac.c
-@@ -1565,6 +1565,27 @@ void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
- }
- }
-
-+void mt7996_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e)
-+{
-+ if (!e->txwi) {
-+ dev_kfree_skb_any(e->skb);
-+ return;
-+ }
-+
-+ /* error path */
-+ if (e->skb == DMA_DUMMY_DATA) {
-+ struct mt76_connac_txp_common *txp;
-+ struct mt76_txwi_cache *t;
-+
-+ txp = mt7996_txwi_to_txp(mdev, e->txwi);
-+ t = mt76_token_put(mdev, le16_to_cpu(txp->fw.token));
-+ e->skb = t ? t->skb : NULL;
-+ }
-+
-+ if (e->skb)
-+ mt76_tx_complete_skb(mdev, e->wcid, e->skb);
-+}
-+
- void mt7996_mac_cca_stats_reset(struct mt7996_phy *phy)
- {
- struct mt7996_dev *dev = phy->dev;
-diff --git a/mt7996/mac.h b/mt7996/mac.h
-index 27184cba..10e08d66 100644
---- a/mt7996/mac.h
-+++ b/mt7996/mac.h
-@@ -371,4 +371,17 @@ struct mt7996_dfs_radar_spec {
- struct mt7996_dfs_pattern radar_pattern[16];
- };
-
-+static inline struct mt76_connac_txp_common *
-+mt7996_txwi_to_txp(struct mt76_dev *dev, struct mt76_txwi_cache *t)
-+{
-+ u8 *txwi;
-+
-+ if (!t)
-+ return NULL;
-+
-+ txwi = mt76_get_txwi_ptr(dev, t);
-+
-+ return (struct mt76_connac_txp_common *)(txwi + MT_TXD_SIZE);
-+}
-+
- #endif
-diff --git a/mt7996/mmio.c b/mt7996/mmio.c
-index 902370a2..2237f50a 100644
---- a/mt7996/mmio.c
-+++ b/mt7996/mmio.c
-@@ -326,7 +326,7 @@ struct mt7996_dev *mt7996_mmio_probe(struct device *pdev,
- SURVEY_INFO_TIME_BSS_RX,
- .token_size = MT7996_TOKEN_SIZE,
- .tx_prepare_skb = mt7996_tx_prepare_skb,
-- .tx_complete_skb = mt76_connac_tx_complete_skb,
-+ .tx_complete_skb = mt7996_tx_complete_skb,
- .rx_skb = mt7996_queue_rx_skb,
- .rx_check = mt7996_rx_check,
- .rx_poll_complete = mt7996_rx_poll_complete,
-diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index 018dfd2b..13f22432 100644
---- a/mt7996/mt7996.h
-+++ b/mt7996/mt7996.h
-@@ -508,6 +508,7 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
- enum mt76_txq_id qid, struct mt76_wcid *wcid,
- struct ieee80211_sta *sta,
- struct mt76_tx_info *tx_info);
-+void mt7996_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e);
- void mt7996_tx_token_put(struct mt7996_dev *dev);
- void mt7996_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
- struct sk_buff *skb, u32 *info);
---
-2.25.1
-
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0001-wifi-mt76-mt7996-add-eht-rx-rate-support.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0001-wifi-mt76-mt7996-add-eht-rx-rate-support.patch
new file mode 100644
index 0000000..66ab9ce
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0001-wifi-mt76-mt7996-add-eht-rx-rate-support.patch
@@ -0,0 +1,92 @@
+From 995b09b6a62700568b36cc2e4ae6b6063456942b Mon Sep 17 00:00:00 2001
+From: Shayne Chen <shayne.chen@mediatek.com>
+Date: Fri, 10 Feb 2023 17:39:23 +0800
+Subject: [PATCH 01/19] wifi: mt76: mt7996: add eht rx rate support
+
+Add support to report eht rx rate.
+
+Change-Id: Iee067d891bd634a918c942c2ba90ae72cd40c538
+Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
+---
+ mac80211.c | 11 ++++++++---
+ mt76.h | 18 ++++++++++++++----
+ mt7996/mac.c | 9 +++++----
+ 3 files changed, 27 insertions(+), 11 deletions(-)
+
+diff --git a/mac80211.c b/mac80211.c
+index 87902f4b..e53166fc 100644
+--- a/mac80211.c
++++ b/mac80211.c
+@@ -1067,9 +1067,14 @@ mt76_rx_convert(struct mt76_dev *dev, struct sk_buff *skb,
+ status->enc_flags = mstat.enc_flags;
+ status->encoding = mstat.encoding;
+ status->bw = mstat.bw;
+- status->he_ru = mstat.he_ru;
+- status->he_gi = mstat.he_gi;
+- status->he_dcm = mstat.he_dcm;
++ if (status->encoding == RX_ENC_EHT) {
++ status->eht.ru = mstat.eht.ru;
++ status->eht.gi = mstat.eht.gi;
++ } else {
++ status->he_ru = mstat.he_ru;
++ status->he_gi = mstat.he_gi;
++ status->he_dcm = mstat.he_dcm;
++ }
+ status->rate_idx = mstat.rate_idx;
+ status->nss = mstat.nss;
+ status->band = mstat.band;
+diff --git a/mt76.h b/mt76.h
+index 183b0fc5..c3d1313e 100644
+--- a/mt76.h
++++ b/mt76.h
+@@ -621,12 +621,22 @@ struct mt76_rx_status {
+ u16 freq;
+ u32 flag;
+ u8 enc_flags;
+- u8 encoding:2, bw:3, he_ru:3;
+- u8 he_gi:2, he_dcm:1;
++ u8 encoding:3, bw:4;
++ union {
++ struct {
++ u8 he_ru:3;
++ u8 he_gi:2;
++ u8 he_dcm:1;
++ };
++ struct {
++ u8 ru:4;
++ u8 gi:2;
++ } eht;
++ };
++
+ u8 amsdu:1, first_amsdu:1, last_amsdu:1;
+ u8 rate_idx;
+- u8 nss;
+- u8 band;
++ u8 nss:5, band:3;
+ s8 signal;
+ u8 chains;
+ s8 chain_signal[IEEE80211_MAX_CHAINS];
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index 3c3506c7..d811b4e0 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -572,11 +572,12 @@ mt7996_mac_fill_rx_rate(struct mt7996_dev *dev,
+ case MT_PHY_TYPE_EHT_SU:
+ case MT_PHY_TYPE_EHT_TRIG:
+ case MT_PHY_TYPE_EHT_MU:
+- /* TODO: currently report rx rate with HE rate */
+ status->nss = nss;
+- status->encoding = RX_ENC_HE;
+- bw = min_t(int, bw, IEEE80211_STA_RX_BW_160);
+- i = min_t(int, i & 0xf, 11);
++ status->encoding = RX_ENC_EHT;
++ i &= GENMASK(3, 0);
++
++ if (gi <= NL80211_RATE_INFO_EHT_GI_3_2)
++ status->eht.gi = gi;
+ break;
+ default:
+ return -EINVAL;
+--
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0002-Revert-wifi-mt76-mt7996-rely-on-mt76_connac_txp_skb_.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0002-Revert-wifi-mt76-mt7996-rely-on-mt76_connac_txp_skb_.patch
deleted file mode 100644
index fb6581a..0000000
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0002-Revert-wifi-mt76-mt7996-rely-on-mt76_connac_txp_skb_.patch
+++ /dev/null
@@ -1,46 +0,0 @@
-From 9c2313ddded0179ae1a9e6112e2762a1a3e958d7 Mon Sep 17 00:00:00 2001
-From: Shayne Chen <shayne.chen@mediatek.com>
-Date: Fri, 3 Feb 2023 11:01:11 +0800
-Subject: [PATCH 2/7] Revert "wifi: mt76: mt7996: rely on
- mt76_connac_txp_skb_unmap"
-
-This reverts commit bdb7dc38a6d150b5aa4b09b82a8954c6bb49ba4a.
----
- mt7996/mac.c | 14 +++++++++++++-
- 1 file changed, 13 insertions(+), 1 deletion(-)
-
-diff --git a/mt7996/mac.c b/mt7996/mac.c
-index 0d718598..df97d7cf 100644
---- a/mt7996/mac.c
-+++ b/mt7996/mac.c
-@@ -1187,6 +1187,18 @@ mt7996_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)
- ieee80211_start_tx_ba_session(sta, tid, 0);
- }
-
-+static void
-+mt7996_txp_skb_unmap(struct mt76_dev *dev, struct mt76_txwi_cache *t)
-+{
-+ struct mt76_connac_txp_common *txp;
-+ int i;
-+
-+ txp = mt7996_txwi_to_txp(dev, t);
-+ for (i = 0; i < txp->fw.nbuf; i++)
-+ dma_unmap_single(dev->dev, le32_to_cpu(txp->fw.buf[i]),
-+ le16_to_cpu(txp->fw.len[i]), DMA_TO_DEVICE);
-+}
-+
- static void
- mt7996_txwi_free(struct mt7996_dev *dev, struct mt76_txwi_cache *t,
- struct ieee80211_sta *sta, struct list_head *free_list)
-@@ -1196,7 +1208,7 @@ mt7996_txwi_free(struct mt7996_dev *dev, struct mt76_txwi_cache *t,
- __le32 *txwi;
- u16 wcid_idx;
-
-- mt76_connac_txp_skb_unmap(mdev, t);
-+ mt7996_txp_skb_unmap(mdev, t);
- if (!t->skb)
- goto out;
-
---
-2.25.1
-
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0002-wifi-mt76-mt7996-let-non-bufferable-MMPDUs-use-corre.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0002-wifi-mt76-mt7996-let-non-bufferable-MMPDUs-use-corre.patch
new file mode 100644
index 0000000..872ef03
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0002-wifi-mt76-mt7996-let-non-bufferable-MMPDUs-use-corre.patch
@@ -0,0 +1,92 @@
+From 5b858f7f944144d99fb0ca1ef26d6b8c6719890c Mon Sep 17 00:00:00 2001
+From: Shayne Chen <shayne.chen@mediatek.com>
+Date: Thu, 16 Feb 2023 10:52:22 +0800
+Subject: [PATCH 02/19] wifi: mt76: mt7996: let non-bufferable MMPDUs use
+ correct hw queue
+
+non-bufferable MMPDUs are expected to use ALTX hw queue, but current
+condition in mt7996_mac_write_txwi() won't let their tx descriptor
+be filled with correct q_idx. Fix this by passing qid parameter into
+the funciton.
+
+Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
+Change-Id: I18bd1a5ea698912c7aa8f4d4317d4a428d4ac440
+---
+ mt7996/mac.c | 9 +++++----
+ mt7996/mcu.c | 4 ++--
+ mt7996/mt7996.h | 3 ++-
+ 3 files changed, 9 insertions(+), 7 deletions(-)
+
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index d811b4e0..198eb711 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -982,7 +982,8 @@ mt7996_mac_write_txwi_80211(struct mt7996_dev *dev, __le32 *txwi,
+ }
+
+ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
+- struct sk_buff *skb, struct mt76_wcid *wcid, int pid,
++ struct sk_buff *skb, struct mt76_wcid *wcid,
++ enum mt76_txq_id qid, int pid,
+ struct ieee80211_key_conf *key, u32 changed)
+ {
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+@@ -1014,7 +1015,7 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
+ } else if (beacon) {
+ p_fmt = MT_TX_TYPE_FW;
+ q_idx = MT_LMAC_BCN0;
+- } else if (skb_get_queue_mapping(skb) >= MT_TXQ_PSD) {
++ } else if (qid >= MT_TXQ_PSD) {
+ p_fmt = MT_TX_TYPE_CT;
+ q_idx = MT_LMAC_ALTX0;
+ } else {
+@@ -1123,8 +1124,8 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
+ memset(txwi_ptr, 0, MT_TXD_SIZE);
+ /* Transmit non qos data by 802.11 header and need to fill txd by host*/
+ if (!is_8023 || pid >= MT_PACKET_ID_FIRST)
+- mt7996_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, pid,
+- key, 0);
++ mt7996_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, qid,
++ pid, key, 0);
+
+ txp = (struct mt76_connac_txp_common *)(txwi + MT_TXD_SIZE);
+ for (i = 0; i < nbuf; i++) {
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 8ad51cbf..dbe10576 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -1906,7 +1906,7 @@ mt7996_mcu_beacon_cont(struct mt7996_dev *dev, struct ieee80211_vif *vif,
+ }
+
+ buf = (u8 *)bcn + sizeof(*bcn) - MAX_BEACON_SIZE;
+- mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, 0, NULL,
++ mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, 0, 0, NULL,
+ BSS_CHANGED_BEACON);
+ memcpy(buf + MT_TXD_SIZE, skb->data, skb->len);
+ }
+@@ -2115,7 +2115,7 @@ int mt7996_mcu_beacon_inband_discov(struct mt7996_dev *dev,
+
+ buf = (u8 *)tlv + sizeof(*discov) - MAX_INBAND_FRAME_SIZE;
+
+- mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, 0, NULL,
++ mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, 0, 0, NULL,
+ changed);
+
+ memcpy(buf + MT_TXD_SIZE, skb->data, skb->len);
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index 018dfd2b..d20aa5f2 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -487,7 +487,8 @@ void mt7996_mac_enable_nf(struct mt7996_dev *dev, u8 band);
+ void mt7996_mac_enable_rtscts(struct mt7996_dev *dev,
+ struct ieee80211_vif *vif, bool enable);
+ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
+- struct sk_buff *skb, struct mt76_wcid *wcid, int pid,
++ struct sk_buff *skb, struct mt76_wcid *wcid,
++ enum mt76_txq_id qid, int pid,
+ struct ieee80211_key_conf *key, u32 changed);
+ void mt7996_mac_set_timing(struct mt7996_phy *phy);
+ int mt7996_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
+--
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0003-Revert-wifi-mt76-mt7996-rely-on-mt76_connac_txp_comm.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0003-Revert-wifi-mt76-mt7996-rely-on-mt76_connac_txp_comm.patch
deleted file mode 100644
index 43ea6c9..0000000
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0003-Revert-wifi-mt76-mt7996-rely-on-mt76_connac_txp_comm.patch
+++ /dev/null
@@ -1,163 +0,0 @@
-From 8ba17e7cdbb5e921edd03102476cd8fb4f4e1b31 Mon Sep 17 00:00:00 2001
-From: Shayne Chen <shayne.chen@mediatek.com>
-Date: Fri, 3 Feb 2023 11:12:46 +0800
-Subject: [PATCH 3/7] Revert "wifi: mt76: mt7996: rely on
- mt76_connac_txp_common structure"
-
-This reverts commit 321edbb414dcc03d349bddd08916b7cc531802e8.
----
- mt7996/mac.c | 38 +++++++++++++++++++-------------------
- mt7996/mac.h | 15 +++++++++++++--
- mt7996/mmio.c | 2 +-
- 3 files changed, 33 insertions(+), 22 deletions(-)
-
-diff --git a/mt7996/mac.c b/mt7996/mac.c
-index df97d7cf..e5b5fed6 100644
---- a/mt7996/mac.c
-+++ b/mt7996/mac.c
-@@ -1088,8 +1088,8 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb);
- struct ieee80211_key_conf *key = info->control.hw_key;
- struct ieee80211_vif *vif = info->control.vif;
-- struct mt76_connac_txp_common *txp;
- struct mt76_txwi_cache *t;
-+ struct mt7996_txp *txp;
- int id, i, pid, nbuf = tx_info->nbuf - 1;
- bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP;
- u8 *txwi = (u8 *)txwi_ptr;
-@@ -1123,35 +1123,35 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
- mt7996_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, pid,
- key, 0);
-
-- txp = (struct mt76_connac_txp_common *)(txwi + MT_TXD_SIZE);
-+ txp = (struct mt7996_txp *)(txwi + MT_TXD_SIZE);
- for (i = 0; i < nbuf; i++) {
-- txp->fw.buf[i] = cpu_to_le32(tx_info->buf[i + 1].addr);
-- txp->fw.len[i] = cpu_to_le16(tx_info->buf[i + 1].len);
-+ txp->buf[i] = cpu_to_le32(tx_info->buf[i + 1].addr);
-+ txp->len[i] = cpu_to_le16(tx_info->buf[i + 1].len);
- }
-- txp->fw.nbuf = nbuf;
-+ txp->nbuf = nbuf;
-
-- txp->fw.flags = cpu_to_le16(MT_CT_INFO_FROM_HOST);
-+ txp->flags = cpu_to_le16(MT_CT_INFO_FROM_HOST);
-
- if (!is_8023 || pid >= MT_PACKET_ID_FIRST)
-- txp->fw.flags |= cpu_to_le16(MT_CT_INFO_APPLY_TXD);
-+ txp->flags |= cpu_to_le16(MT_CT_INFO_APPLY_TXD);
-
- if (!key)
-- txp->fw.flags |= cpu_to_le16(MT_CT_INFO_NONE_CIPHER_FRAME);
-+ txp->flags |= cpu_to_le16(MT_CT_INFO_NONE_CIPHER_FRAME);
-
- if (!is_8023 && ieee80211_is_mgmt(hdr->frame_control))
-- txp->fw.flags |= cpu_to_le16(MT_CT_INFO_MGMT_FRAME);
-+ txp->flags |= cpu_to_le16(MT_CT_INFO_MGMT_FRAME);
-
- if (vif) {
- struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
-
-- txp->fw.bss_idx = mvif->mt76.idx;
-+ txp->bss_idx = mvif->mt76.idx;
- }
-
-- txp->fw.token = cpu_to_le16(id);
-+ txp->token = cpu_to_le16(id);
- if (test_bit(MT_WCID_FLAG_4ADDR, &wcid->flags))
-- txp->fw.rept_wds_wcid = cpu_to_le16(wcid->idx);
-+ txp->rept_wds_wcid = cpu_to_le16(wcid->idx);
- else
-- txp->fw.rept_wds_wcid = cpu_to_le16(0xfff);
-+ txp->rept_wds_wcid = cpu_to_le16(0xfff);
- tx_info->skb = DMA_DUMMY_DATA;
-
- /* pass partial skb header to fw */
-@@ -1190,13 +1190,13 @@ mt7996_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)
- static void
- mt7996_txp_skb_unmap(struct mt76_dev *dev, struct mt76_txwi_cache *t)
- {
-- struct mt76_connac_txp_common *txp;
-+ struct mt7996_txp *txp;
- int i;
-
- txp = mt7996_txwi_to_txp(dev, t);
-- for (i = 0; i < txp->fw.nbuf; i++)
-- dma_unmap_single(dev->dev, le32_to_cpu(txp->fw.buf[i]),
-- le16_to_cpu(txp->fw.len[i]), DMA_TO_DEVICE);
-+ for (i = 0; i < txp->nbuf; i++)
-+ dma_unmap_single(dev->dev, le32_to_cpu(txp->buf[i]),
-+ le16_to_cpu(txp->len[i]), DMA_TO_DEVICE);
- }
-
- static void
-@@ -1586,11 +1586,11 @@ void mt7996_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e)
-
- /* error path */
- if (e->skb == DMA_DUMMY_DATA) {
-- struct mt76_connac_txp_common *txp;
- struct mt76_txwi_cache *t;
-+ struct mt7996_txp *txp;
-
- txp = mt7996_txwi_to_txp(mdev, e->txwi);
-- t = mt76_token_put(mdev, le16_to_cpu(txp->fw.token));
-+ t = mt76_token_put(mdev, le16_to_cpu(txp->token));
- e->skb = t ? t->skb : NULL;
- }
-
-diff --git a/mt7996/mac.h b/mt7996/mac.h
-index 10e08d66..9f688520 100644
---- a/mt7996/mac.h
-+++ b/mt7996/mac.h
-@@ -268,6 +268,17 @@ enum tx_mgnt_type {
- /* VHT/HE only use bits 0-3 */
- #define MT_TX_RATE_IDX GENMASK(5, 0)
-
-+struct mt7996_txp {
-+ __le16 flags;
-+ __le16 token;
-+ u8 bss_idx;
-+ __le16 rept_wds_wcid;
-+ u8 nbuf;
-+#define MT_TXP_MAX_BUF_NUM 6
-+ __le32 buf[MT_TXP_MAX_BUF_NUM];
-+ __le16 len[MT_TXP_MAX_BUF_NUM];
-+} __packed __aligned(4);
-+
- #define MT_TXFREE0_PKT_TYPE GENMASK(31, 27)
- #define MT_TXFREE0_MSDU_CNT GENMASK(25, 16)
- #define MT_TXFREE0_RX_BYTE GENMASK(15, 0)
-@@ -371,7 +382,7 @@ struct mt7996_dfs_radar_spec {
- struct mt7996_dfs_pattern radar_pattern[16];
- };
-
--static inline struct mt76_connac_txp_common *
-+static inline struct mt7996_txp *
- mt7996_txwi_to_txp(struct mt76_dev *dev, struct mt76_txwi_cache *t)
- {
- u8 *txwi;
-@@ -381,7 +392,7 @@ mt7996_txwi_to_txp(struct mt76_dev *dev, struct mt76_txwi_cache *t)
-
- txwi = mt76_get_txwi_ptr(dev, t);
-
-- return (struct mt76_connac_txp_common *)(txwi + MT_TXD_SIZE);
-+ return (struct mt7996_txp *)(txwi + MT_TXD_SIZE);
- }
-
- #endif
-diff --git a/mt7996/mmio.c b/mt7996/mmio.c
-index 2237f50a..d8a2c1a7 100644
---- a/mt7996/mmio.c
-+++ b/mt7996/mmio.c
-@@ -318,7 +318,7 @@ struct mt7996_dev *mt7996_mmio_probe(struct device *pdev,
- {
- static const struct mt76_driver_ops drv_ops = {
- /* txwi_size = txd size + txp size */
-- .txwi_size = MT_TXD_SIZE + sizeof(struct mt76_connac_fw_txp),
-+ .txwi_size = MT_TXD_SIZE + sizeof(struct mt7996_txp),
- .drv_flags = MT_DRV_TXWI_NO_FREE |
- MT_DRV_HW_MGMT_TXQ,
- .survey_flags = SURVEY_INFO_TIME_TX |
---
-2.25.1
-
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0003-wifi-mt76-mt7996-reduce-repeated-bss_info-and-sta_re.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0003-wifi-mt76-mt7996-reduce-repeated-bss_info-and-sta_re.patch
new file mode 100644
index 0000000..c91eb62
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0003-wifi-mt76-mt7996-reduce-repeated-bss_info-and-sta_re.patch
@@ -0,0 +1,67 @@
+From 09ef1c1248c8b38c5f2c6e624397e64e8938349f Mon Sep 17 00:00:00 2001
+From: Shayne Chen <shayne.chen@mediatek.com>
+Date: Thu, 16 Feb 2023 00:39:01 +0800
+Subject: [PATCH 03/19] wifi: mt76: mt7996: reduce repeated bss_info and
+ sta_rec commands
+
+Refine the flow of setting bss_info and sta_rec commands to prevent from
+sending duplicated commands, especially for station mode.
+
+Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
+Change-Id: Iffd2c81f9ec98284793e75f4b7d39e9618977024
+---
+ mt7996/main.c | 21 ++++++---------------
+ 1 file changed, 6 insertions(+), 15 deletions(-)
+
+diff --git a/mt7996/main.c b/mt7996/main.c
+index 3e4da035..e80ee19e 100644
+--- a/mt7996/main.c
++++ b/mt7996/main.c
+@@ -241,8 +241,8 @@ static void mt7996_remove_interface(struct ieee80211_hw *hw,
+ struct mt7996_phy *phy = mt7996_hw_phy(hw);
+ int idx = msta->wcid.idx;
+
+- mt7996_mcu_add_bss_info(phy, vif, false);
+ mt7996_mcu_add_sta(dev, vif, NULL, false);
++ mt7996_mcu_add_bss_info(phy, vif, false);
+
+ if (vif == phy->monitor_vif)
+ phy->monitor_vif = NULL;
+@@ -510,17 +510,13 @@ static void mt7996_bss_info_changed(struct ieee80211_hw *hw,
+ /* station mode uses BSSID to map the wlan entry to a peer,
+ * and then peer references bss_info_rfch to set bandwidth cap.
+ */
+- if (changed & BSS_CHANGED_BSSID &&
+- vif->type == NL80211_IFTYPE_STATION) {
+- bool join = !is_zero_ether_addr(info->bssid);
+-
+- mt7996_mcu_add_bss_info(phy, vif, join);
+- mt7996_mcu_add_sta(dev, vif, NULL, join);
++ if ((changed & BSS_CHANGED_BSSID && !is_zero_ether_addr(info->bssid)) ||
++ (changed & BSS_CHANGED_ASSOC && vif->cfg.assoc) ||
++ (changed & BSS_CHANGED_BEACON_ENABLED && info->enable_beacon)) {
++ mt7996_mcu_add_bss_info(phy, vif, true);
++ mt7996_mcu_add_sta(dev, vif, NULL, true);
+ }
+
+- if (changed & BSS_CHANGED_ASSOC)
+- mt7996_mcu_add_bss_info(phy, vif, vif->cfg.assoc);
+-
+ if (changed & BSS_CHANGED_ERP_CTS_PROT)
+ mt7996_mac_enable_rtscts(dev, vif, info->use_cts_prot);
+
+@@ -533,11 +529,6 @@ static void mt7996_bss_info_changed(struct ieee80211_hw *hw,
+ }
+ }
+
+- if (changed & BSS_CHANGED_BEACON_ENABLED && info->enable_beacon) {
+- mt7996_mcu_add_bss_info(phy, vif, true);
+- mt7996_mcu_add_sta(dev, vif, NULL, true);
+- }
+-
+ /* ensure that enable txcmd_mode after bss_info */
+ if (changed & (BSS_CHANGED_QOS | BSS_CHANGED_BEACON_ENABLED))
+ mt7996_mcu_set_tx(dev, vif);
+--
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0004-wifi-mt76-mt7996-move-radio-enable-command-to-mt7996.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0004-wifi-mt76-mt7996-move-radio-enable-command-to-mt7996.patch
new file mode 100644
index 0000000..cc366e3
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0004-wifi-mt76-mt7996-move-radio-enable-command-to-mt7996.patch
@@ -0,0 +1,61 @@
+From c86f2243472f00fd2011cc44b89a87f7f6e2066a Mon Sep 17 00:00:00 2001
+From: Shayne Chen <shayne.chen@mediatek.com>
+Date: Wed, 15 Feb 2023 18:38:04 +0800
+Subject: [PATCH 04/19] wifi: mt76: mt7996: move radio enable command to
+ mt7996_start()
+
+The radio enable and disable commands are used for per-phy radio, so
+move them into mt7996_start() and mt7996_stop(), respectively.
+
+Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
+Change-Id: I610b170f5198e085eb86dbd371ee0745ac6ff50f
+---
+ mt7996/main.c | 11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+diff --git a/mt7996/main.c b/mt7996/main.c
+index e80ee19e..a4fd9e24 100644
+--- a/mt7996/main.c
++++ b/mt7996/main.c
+@@ -46,6 +46,10 @@ static int mt7996_start(struct ieee80211_hw *hw)
+ if (ret)
+ goto out;
+
++ ret = mt7996_mcu_set_radio_en(phy, true);
++ if (ret)
++ goto out;
++
+ ret = mt7996_mcu_set_chan_info(phy, UNI_CHANNEL_RX_PATH);
+ if (ret)
+ goto out;
+@@ -77,6 +81,8 @@ static void mt7996_stop(struct ieee80211_hw *hw)
+
+ mutex_lock(&dev->mt76.mutex);
+
++ mt7996_mcu_set_radio_en(phy, false);
++
+ clear_bit(MT76_STATE_RUNNING, &phy->mt76->state);
+
+ ieee80211_iterate_interfaces(dev->mt76.hw,
+@@ -189,10 +195,6 @@ static int mt7996_add_interface(struct ieee80211_hw *hw,
+ if (ret)
+ goto out;
+
+- ret = mt7996_mcu_set_radio_en(phy, true);
+- if (ret)
+- goto out;
+-
+ dev->mt76.vif_mask |= BIT_ULL(mvif->mt76.idx);
+ phy->omac_mask |= BIT_ULL(mvif->mt76.omac_idx);
+
+@@ -248,7 +250,6 @@ static void mt7996_remove_interface(struct ieee80211_hw *hw,
+ phy->monitor_vif = NULL;
+
+ mt7996_mcu_add_dev_info(phy, vif, false);
+- mt7996_mcu_set_radio_en(phy, false);
+
+ rcu_assign_pointer(dev->mt76.wcid[idx], NULL);
+
+--
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0005-wifi-mt76-connac-set-correct-muar_idx-for-connac3-ch.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0005-wifi-mt76-connac-set-correct-muar_idx-for-connac3-ch.patch
new file mode 100644
index 0000000..07dffec
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0005-wifi-mt76-connac-set-correct-muar_idx-for-connac3-ch.patch
@@ -0,0 +1,49 @@
+From 5d4c7f88b2066f4a8ec1769cf6c067d0e88abfa3 Mon Sep 17 00:00:00 2001
+From: Shayne Chen <shayne.chen@mediatek.com>
+Date: Thu, 16 Feb 2023 13:53:14 +0800
+Subject: [PATCH 05/19] wifi: mt76: connac: set correct muar_idx for connac3
+ chipset
+
+Set the muar_idx to 0xe for the hw bcast/mcast station entry of connac3
+chipset.
+
+Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
+Change-Id: I7054c3b3c64ec447cc280ea810f4958afdfa9e02
+---
+ mt76_connac.h | 5 +++++
+ mt76_connac_mcu.c | 3 +++
+ 2 files changed, 8 insertions(+)
+
+diff --git a/mt76_connac.h b/mt76_connac.h
+index b339c50b..c8b91e86 100644
+--- a/mt76_connac.h
++++ b/mt76_connac.h
+@@ -216,6 +216,11 @@ static inline bool is_connac_v1(struct mt76_dev *dev)
+ return is_mt7615(dev) || is_mt7663(dev) || is_mt7622(dev);
+ }
+
++static inline bool is_connac_v3(struct mt76_dev *dev)
++{
++ return is_mt7996(dev);
++}
++
+ static inline bool is_mt76_fw_txp(struct mt76_dev *dev)
+ {
+ switch (mt76_chip(dev)) {
+diff --git a/mt76_connac_mcu.c b/mt76_connac_mcu.c
+index efb9bfaa..4e4f6b35 100644
+--- a/mt76_connac_mcu.c
++++ b/mt76_connac_mcu.c
+@@ -281,6 +281,9 @@ __mt76_connac_mcu_alloc_sta_req(struct mt76_dev *dev, struct mt76_vif *mvif,
+ };
+ struct sk_buff *skb;
+
++ if (is_connac_v3(dev) && !wcid->sta)
++ hdr.muar_idx = 0xe;
++
+ mt76_connac_mcu_get_wlan_idx(dev, wcid, &hdr.wlan_idx_lo,
+ &hdr.wlan_idx_hi);
+ skb = mt76_mcu_msg_alloc(dev, NULL, len);
+--
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0005-wifi-mt76-mt7996-set-txd-v1.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0005-wifi-mt76-mt7996-set-txd-v1.patch
deleted file mode 100644
index 8fddb93..0000000
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0005-wifi-mt76-mt7996-set-txd-v1.patch
+++ /dev/null
@@ -1,48 +0,0 @@
-From d8bef73f22f88bf857698f4018db3aed6a2fca2d Mon Sep 17 00:00:00 2001
-From: Peter Chiu <chui-hao.chiu@mediatek.com>
-Date: Tue, 29 Nov 2022 09:13:32 +0800
-Subject: [PATCH 5/7] wifi: mt76: mt7996: set txd v1
-
----
- mt7996/mac.c | 3 +++
- mt7996/mac.h | 3 ++-
- 2 files changed, 5 insertions(+), 1 deletion(-)
-
-diff --git a/mt7996/mac.c b/mt7996/mac.c
-index e5b5fed6..51337dde 100644
---- a/mt7996/mac.c
-+++ b/mt7996/mac.c
-@@ -1092,6 +1092,7 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
- struct mt7996_txp *txp;
- int id, i, pid, nbuf = tx_info->nbuf - 1;
- bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP;
-+ __le32 *txd = (__le32 *)txwi_ptr;
- u8 *txwi = (u8 *)txwi_ptr;
-
- if (unlikely(tx_info->skb->len <= ETH_HLEN))
-@@ -1123,6 +1124,8 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
- mt7996_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, pid,
- key, 0);
-
-+ txd[0] |= le32_encode_bits(1, MT_TXD0_VER);
-+
- txp = (struct mt7996_txp *)(txwi + MT_TXD_SIZE);
- for (i = 0; i < nbuf; i++) {
- txp->buf[i] = cpu_to_le32(tx_info->buf[i + 1].addr);
-diff --git a/mt7996/mac.h b/mt7996/mac.h
-index 9f688520..470b701a 100644
---- a/mt7996/mac.h
-+++ b/mt7996/mac.h
-@@ -186,7 +186,8 @@ enum tx_mgnt_type {
-
- #define MT_TXD0_Q_IDX GENMASK(31, 25)
- #define MT_TXD0_PKT_FMT GENMASK(24, 23)
--#define MT_TXD0_ETH_TYPE_OFFSET GENMASK(22, 16)
-+#define MT_TXD0_VER GENMASK(22, 19)
-+#define MT_TXD0_ETH_TYPE_OFFSET GENMASK(18, 16)
- #define MT_TXD0_TX_BYTES GENMASK(15, 0)
-
- #define MT_TXD1_FIXED_RATE BIT(31)
---
-2.25.1
-
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0006-wifi-mt76-mt7996-fix-pointer-calculation-in-ie-count.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0006-wifi-mt76-mt7996-fix-pointer-calculation-in-ie-count.patch
new file mode 100644
index 0000000..65596f4
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0006-wifi-mt76-mt7996-fix-pointer-calculation-in-ie-count.patch
@@ -0,0 +1,34 @@
+From 00d76d4dc3cdb719b5fc234d9cf3bbef39f448ce Mon Sep 17 00:00:00 2001
+From: Peter Chiu <chui-hao.chiu@mediatek.com>
+Date: Mon, 13 Feb 2023 14:48:10 +0800
+Subject: [PATCH 06/19] wifi: mt76: mt7996: fix pointer calculation in ie
+ countdown event
+
+Fix the tail and data pointers. The rxd->len in mt7996_mcu_rxd does not
+include the length of general rxd. It only includes the length of
+firmware event rxd. Use the skb->length to get the correct length.
+
+Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
+Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
+Change-Id: I832194559e63e6b49b7ee00dc9c606b6106d8669
+---
+ mt7996/mcu.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index dbe10576..2e25572a 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -422,7 +422,8 @@ mt7996_mcu_ie_countdown(struct mt7996_dev *dev, struct sk_buff *skb)
+ if (hdr->band && dev->mt76.phys[hdr->band])
+ mphy = dev->mt76.phys[hdr->band];
+
+- tail = skb->data + le16_to_cpu(rxd->len);
++ tail = skb->data + skb->len;
++ data += sizeof(struct header);
+ while (data + sizeof(struct tlv) < tail && le16_to_cpu(tlv->len)) {
+ switch (le16_to_cpu(tlv->tag)) {
+ case UNI_EVENT_IE_COUNTDOWN_CSA:
+--
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0007-wifi-mt76-mt7996-remove-mt7996_mcu_set_pm.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0007-wifi-mt76-mt7996-remove-mt7996_mcu_set_pm.patch
new file mode 100644
index 0000000..7988196
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0007-wifi-mt76-mt7996-remove-mt7996_mcu_set_pm.patch
@@ -0,0 +1,96 @@
+From c2dafe57df1726acb80e30987bc8d678b86af14a Mon Sep 17 00:00:00 2001
+From: Peter Chiu <chui-hao.chiu@mediatek.com>
+Date: Tue, 14 Feb 2023 18:35:43 +0800
+Subject: [PATCH 07/19] wifi: mt76: mt7996: remove mt7996_mcu_set_pm()
+
+Currently using BSS_INFO_PS command will sometimes cause packet drop in
+hw rx queue.
+Temporarily remove this function until finding the cause.
+
+Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
+Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
+Change-Id: I863fc1edb18e4d7b5dac20140dd0904875e1323c
+---
+ mt7996/main.c | 8 --------
+ mt7996/mcu.c | 26 --------------------------
+ mt7996/mt7996.h | 1 -
+ 3 files changed, 35 deletions(-)
+
+diff --git a/mt7996/main.c b/mt7996/main.c
+index a4fd9e24..44d23e1d 100644
+--- a/mt7996/main.c
++++ b/mt7996/main.c
+@@ -56,10 +56,6 @@ static int mt7996_start(struct ieee80211_hw *hw)
+
+ set_bit(MT76_STATE_RUNNING, &phy->mt76->state);
+
+- ieee80211_iterate_interfaces(dev->mt76.hw,
+- IEEE80211_IFACE_ITER_RESUME_ALL,
+- mt7996_mcu_set_pm, dev->mt76.hw);
+-
+ ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work,
+ MT7996_WATCHDOG_TIME);
+
+@@ -85,10 +81,6 @@ static void mt7996_stop(struct ieee80211_hw *hw)
+
+ clear_bit(MT76_STATE_RUNNING, &phy->mt76->state);
+
+- ieee80211_iterate_interfaces(dev->mt76.hw,
+- IEEE80211_IFACE_ITER_RESUME_ALL,
+- mt7996_mcu_set_pm, dev->mt76.hw);
+-
+ mutex_unlock(&dev->mt76.mutex);
+ }
+
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 2e25572a..f6947438 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -3577,32 +3577,6 @@ int mt7996_mcu_twt_agrt_update(struct mt7996_dev *dev,
+ &req, sizeof(req), true);
+ }
+
+-void mt7996_mcu_set_pm(void *priv, u8 *mac, struct ieee80211_vif *vif)
+-{
+-#define EXIT_PM_STATE 0
+-#define ENTER_PM_STATE 1
+- struct ieee80211_hw *hw = priv;
+- struct mt7996_dev *dev = mt7996_hw_dev(hw);
+- struct mt7996_phy *phy = mt7996_hw_phy(hw);
+- struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
+- struct bss_power_save *ps;
+- struct sk_buff *skb;
+- struct tlv *tlv;
+- bool running = test_bit(MT76_STATE_RUNNING, &phy->mt76->state);
+-
+- skb = __mt7996_mcu_alloc_bss_req(&dev->mt76, &mvif->mt76,
+- MT7996_BSS_UPDATE_MAX_SIZE);
+- if (IS_ERR(skb))
+- return;
+-
+- tlv = mt7996_mcu_add_uni_tlv(skb, UNI_BSS_INFO_PS, sizeof(*ps));
+- ps = (struct bss_power_save *)tlv;
+- ps->profile = running ? EXIT_PM_STATE : ENTER_PM_STATE;
+-
+- mt76_mcu_skb_send_msg(&dev->mt76, skb,
+- MCU_WMWA_UNI_CMD(BSS_INFO_UPDATE), true);
+-}
+-
+ int mt7996_mcu_set_rts_thresh(struct mt7996_phy *phy, u32 val)
+ {
+ struct {
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index d20aa5f2..f9d8fbfd 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -432,7 +432,6 @@ int mt7996_mcu_set_pulse_th(struct mt7996_dev *dev,
+ int mt7996_mcu_set_radar_th(struct mt7996_dev *dev, int index,
+ const struct mt7996_dfs_pattern *pattern);
+ int mt7996_mcu_set_radio_en(struct mt7996_phy *phy, bool enable);
+-void mt7996_mcu_set_pm(void *priv, u8 *mac, struct ieee80211_vif *vif);
+ int mt7996_mcu_set_rts_thresh(struct mt7996_phy *phy, u32 val);
+ int mt7996_mcu_get_chan_mib_info(struct mt7996_phy *phy, bool chan_switch);
+ int mt7996_mcu_rdd_cmd(struct mt7996_dev *dev, int cmd, u8 index,
+--
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0004-wifi-mt76-mt7996-add-muru-support.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0008-wifi-mt76-mt7996-add-muru-support.patch
similarity index 91%
rename from recipes-wifi/linux-mt76/files/patches-3.x/0004-wifi-mt76-mt7996-add-muru-support.patch
rename to recipes-wifi/linux-mt76/files/patches-3.x/0008-wifi-mt76-mt7996-add-muru-support.patch
index dab5182..20d7f48 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0004-wifi-mt76-mt7996-add-muru-support.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0008-wifi-mt76-mt7996-add-muru-support.patch
@@ -1,7 +1,7 @@
-From 7c8b8c77489ef907f2122c5d0edb7ff5e0fed177 Mon Sep 17 00:00:00 2001
+From b587a9f1615585f8db0fa98cc46791a3253ddac7 Mon Sep 17 00:00:00 2001
From: MeiChia Chiu <MeiChia.Chiu@mediatek.com>
Date: Mon, 28 Nov 2022 14:36:09 +0800
-Subject: [PATCH 4/7] wifi: mt76: mt7996: add muru support
+Subject: [PATCH 08/19] wifi: mt76: mt7996: add muru support
Add sta_rec_muru() and related phy cap for MU and RU support.
@@ -15,7 +15,7 @@
3 files changed, 73 insertions(+), 2 deletions(-)
diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index a5e6ee4d..39667840 100644
+index 40a99e0c..6f30a0fb 100644
--- a/mt76_connac_mcu.h
+++ b/mt76_connac_mcu.h
@@ -518,7 +518,8 @@ struct sta_rec_muru {
@@ -29,10 +29,10 @@
struct {
diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index dbe30832..394dd15c 100644
+index f6947438..b6bd36c2 100644
--- a/mt7996/mcu.c
+++ b/mt7996/mcu.c
-@@ -1049,6 +1049,63 @@ mt7996_mcu_sta_amsdu_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
+@@ -1050,6 +1050,63 @@ mt7996_mcu_sta_amsdu_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
}
}
@@ -96,7 +96,7 @@
static inline bool
mt7996_is_ebf_supported(struct mt7996_phy *phy, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, bool bfee)
-@@ -1721,7 +1778,8 @@ int mt7996_mcu_add_sta(struct mt7996_dev *dev, struct ieee80211_vif *vif,
+@@ -1722,7 +1779,8 @@ int mt7996_mcu_add_sta(struct mt7996_dev *dev, struct ieee80211_vif *vif,
mt7996_mcu_sta_he_6g_tlv(skb, sta);
/* starec eht */
mt7996_mcu_sta_eht_tlv(skb, sta);
@@ -106,7 +106,7 @@
/* starec bfee */
mt7996_mcu_sta_bfee_tlv(dev, skb, vif, sta);
/* starec hdr trans */
-@@ -2004,6 +2062,15 @@ mt7996_mcu_beacon_check_caps(struct mt7996_phy *phy, struct ieee80211_vif *vif,
+@@ -2005,6 +2063,15 @@ mt7996_mcu_beacon_check_caps(struct mt7996_phy *phy, struct ieee80211_vif *vif,
vc->eht_su_ebfee =
EHT_PHY(CAP0_SU_BEAMFORMEE, eht->phy_cap_info[0]) &&
EHT_PHY(CAP0_SU_BEAMFORMEE, pe->phy_cap_info[0]);
@@ -123,7 +123,7 @@
}
diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
-index 13f22432..64a804a4 100644
+index f9d8fbfd..997a0bf0 100644
--- a/mt7996/mt7996.h
+++ b/mt7996/mt7996.h
@@ -125,6 +125,9 @@ struct mt7996_vif_cap {
@@ -137,5 +137,5 @@
struct mt7996_vif {
--
-2.25.1
+2.39.2
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0009-wifi-mt76-mt7996-set-txd-v1.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0009-wifi-mt76-mt7996-set-txd-v1.patch
new file mode 100644
index 0000000..cc7548a
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0009-wifi-mt76-mt7996-set-txd-v1.patch
@@ -0,0 +1,48 @@
+From 9a1a54c7df9babadd8f6ae066deb2b5e49715cb0 Mon Sep 17 00:00:00 2001
+From: Bo Jiao <Bo.Jiao@mediatek.com>
+Date: Mon, 6 Feb 2023 10:40:33 +0800
+Subject: [PATCH 09/19] wifi: mt76: mt7996: set txd v1
+
+---
+ mt7996/mac.c | 3 +++
+ mt7996/mac.h | 3 ++-
+ 2 files changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index 198eb711..40ef5e4b 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -1096,6 +1096,7 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
+ struct mt76_txwi_cache *t;
+ int id, i, pid, nbuf = tx_info->nbuf - 1;
+ bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP;
++ __le32 *txd = (__le32 *)txwi_ptr;
+ u8 *txwi = (u8 *)txwi_ptr;
+
+ if (unlikely(tx_info->skb->len <= ETH_HLEN))
+@@ -1127,6 +1128,8 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
+ mt7996_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, qid,
+ pid, key, 0);
+
++ txd[0] |= le32_encode_bits(1, MT_TXD0_VER);
++
+ txp = (struct mt76_connac_txp_common *)(txwi + MT_TXD_SIZE);
+ for (i = 0; i < nbuf; i++) {
+ txp->fw.buf[i] = cpu_to_le32(tx_info->buf[i + 1].addr);
+diff --git a/mt7996/mac.h b/mt7996/mac.h
+index 2cc218f7..4914d3e5 100644
+--- a/mt7996/mac.h
++++ b/mt7996/mac.h
+@@ -183,7 +183,8 @@ enum tx_mgnt_type {
+
+ #define MT_TXD0_Q_IDX GENMASK(31, 25)
+ #define MT_TXD0_PKT_FMT GENMASK(24, 23)
+-#define MT_TXD0_ETH_TYPE_OFFSET GENMASK(22, 16)
++#define MT_TXD0_VER GENMASK(22, 19)
++#define MT_TXD0_ETH_TYPE_OFFSET GENMASK(18, 16)
+ #define MT_TXD0_TX_BYTES GENMASK(15, 0)
+
+ #define MT_TXD1_FIXED_RATE BIT(31)
+--
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0010-wifi-mt76-mt7996-add-thermal-protection-support.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0010-wifi-mt76-mt7996-add-thermal-protection-support.patch
new file mode 100644
index 0000000..319eb1f
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0010-wifi-mt76-mt7996-add-thermal-protection-support.patch
@@ -0,0 +1,437 @@
+From 1744b5397ad4240ce41bf88bfff2eef34d76d587 Mon Sep 17 00:00:00 2001
+From: Howard Hsu <howard-yh.hsu@mediatek.com>
+Date: Thu, 2 Feb 2023 21:20:31 +0800
+Subject: [PATCH 10/19] wifi: mt76: mt7996: add thermal protection support
+
+This commit includes the following changes:
+1. implement MTK thermal protection driver API
+2. support Linux cooling device control
+
+Change-Id: I8fecc28f5b17ee50ae4644d1dd17d188dd694731
+---
+ mt76_connac_mcu.h | 1 +
+ mt7996/init.c | 105 +++++++++++++++++++++++++++++++++++++++++++++
+ mt7996/main.c | 8 ++++
+ mt7996/mcu.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++
+ mt7996/mcu.h | 44 +++++++++++++++++++
+ mt7996/mt7996.h | 15 +++++++
+ 6 files changed, 279 insertions(+)
+
+diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
+index 6f30a0fb..fa10d823 100644
+--- a/mt76_connac_mcu.h
++++ b/mt76_connac_mcu.h
+@@ -1009,6 +1009,7 @@ enum {
+ MCU_UNI_EVENT_FW_LOG_2_HOST = 0x04,
+ MCU_UNI_EVENT_IE_COUNTDOWN = 0x09,
+ MCU_UNI_EVENT_RDD_REPORT = 0x11,
++ MCU_UNI_EVENT_THERMAL = 0x35,
+ };
+
+ #define MCU_UNI_CMD_EVENT BIT(1)
+diff --git a/mt7996/init.c b/mt7996/init.c
+index 946da93e..5a22cd81 100644
+--- a/mt7996/init.c
++++ b/mt7996/init.c
+@@ -41,6 +41,98 @@ static const struct ieee80211_iface_combination if_comb[] = {
+ }
+ };
+
++static int
++mt7996_thermal_get_max_throttle_state(struct thermal_cooling_device *cdev,
++ unsigned long *state)
++{
++ *state = MT7996_CDEV_THROTTLE_MAX;
++
++ return 0;
++}
++
++static int
++mt7996_thermal_get_cur_throttle_state(struct thermal_cooling_device *cdev,
++ unsigned long *state)
++{
++ struct mt7996_phy *phy = cdev->devdata;
++
++ *state = phy->cdev_state;
++
++ return 0;
++}
++
++static int
++mt7996_thermal_set_cur_throttle_state(struct thermal_cooling_device *cdev,
++ unsigned long state)
++{
++ struct mt7996_phy *phy = cdev->devdata;
++ u8 throttling = MT7996_THERMAL_THROTTLE_MAX - state;
++ int ret;
++
++ if (state > MT7996_CDEV_THROTTLE_MAX) {
++ dev_err(phy->dev->mt76.dev,
++ "please specify a valid throttling state\n");
++ return -EINVAL;
++ }
++
++ if (state == phy->cdev_state)
++ return 0;
++
++ /*
++ * cooling_device convention: 0 = no cooling, more = more cooling
++ * mcu convention: 1 = max cooling, more = less cooling
++ */
++ ret = mt7996_mcu_set_thermal_throttling(phy, throttling);
++ if (ret)
++ return ret;
++
++ phy->cdev_state = state;
++
++ return 0;
++}
++
++static const struct thermal_cooling_device_ops mt7996_thermal_ops = {
++ .get_max_state = mt7996_thermal_get_max_throttle_state,
++ .get_cur_state = mt7996_thermal_get_cur_throttle_state,
++ .set_cur_state = mt7996_thermal_set_cur_throttle_state,
++};
++
++static void mt7996_unregister_thermal(struct mt7996_phy *phy)
++{
++ struct wiphy *wiphy = phy->mt76->hw->wiphy;
++
++ if (!phy->cdev)
++ return;
++
++ sysfs_remove_link(&wiphy->dev.kobj, "cooling_device");
++ thermal_cooling_device_unregister(phy->cdev);
++}
++
++static int mt7996_thermal_init(struct mt7996_phy *phy)
++{
++ struct wiphy *wiphy = phy->mt76->hw->wiphy;
++ struct thermal_cooling_device *cdev;
++ const char *name;
++
++ name = devm_kasprintf(&wiphy->dev, GFP_KERNEL, "mt7996_%s",
++ wiphy_name(wiphy));
++
++ cdev = thermal_cooling_device_register(name, phy, &mt7996_thermal_ops);
++ if (!IS_ERR(cdev)) {
++ if (sysfs_create_link(&wiphy->dev.kobj, &cdev->device.kobj,
++ "cooling_device") < 0)
++ thermal_cooling_device_unregister(cdev);
++ else
++ phy->cdev = cdev;
++ }
++
++ /* initialize critical/maximum high temperature */
++ phy->throttle_temp[MT7996_CRIT_TEMP_IDX] = MT7996_CRIT_TEMP;
++ phy->throttle_temp[MT7996_MAX_TEMP_IDX] = MT7996_MAX_TEMP;
++
++ return 0;
++}
++
+ static void mt7996_led_set_config(struct led_classdev *led_cdev,
+ u8 delay_on, u8 delay_off)
+ {
+@@ -367,6 +459,10 @@ static int mt7996_register_phy(struct mt7996_dev *dev, struct mt7996_phy *phy,
+ if (ret)
+ goto error;
+
++ ret = mt7996_thermal_init(phy);
++ if (ret)
++ goto error;
++
+ ret = mt7996_init_debugfs(phy);
+ if (ret)
+ goto error;
+@@ -387,6 +483,8 @@ mt7996_unregister_phy(struct mt7996_phy *phy, enum mt76_band_id band)
+ if (!phy)
+ return;
+
++ mt7996_unregister_thermal(phy);
++
+ mphy = phy->dev->mt76.phys[band];
+ mt76_unregister_phy(mphy);
+ ieee80211_free_hw(mphy->hw);
+@@ -876,6 +974,10 @@ int mt7996_register_device(struct mt7996_dev *dev)
+ if (ret)
+ return ret;
+
++ ret = mt7996_thermal_init(&dev->phy);
++ if (ret)
++ return ret;
++
+ ieee80211_queue_work(mt76_hw(dev), &dev->init_work);
+
+ ret = mt7996_register_phy(dev, mt7996_phy2(dev), MT_BAND1);
+@@ -893,6 +995,9 @@ void mt7996_unregister_device(struct mt7996_dev *dev)
+ {
+ mt7996_unregister_phy(mt7996_phy3(dev), MT_BAND2);
+ mt7996_unregister_phy(mt7996_phy2(dev), MT_BAND1);
++
++ mt7996_unregister_thermal(&dev->phy);
++
+ mt76_unregister_device(&dev->mt76);
+ mt7996_mcu_exit(dev);
+ mt7996_tx_token_put(dev);
+diff --git a/mt7996/main.c b/mt7996/main.c
+index 44d23e1d..d8d578c0 100644
+--- a/mt7996/main.c
++++ b/mt7996/main.c
+@@ -54,6 +54,14 @@ static int mt7996_start(struct ieee80211_hw *hw)
+ if (ret)
+ goto out;
+
++ ret = mt7996_mcu_set_thermal_throttling(phy, MT7996_THERMAL_THROTTLE_MAX);
++ if (ret)
++ goto out;
++
++ ret = mt7996_mcu_set_thermal_protect(phy);
++ if (ret)
++ goto out;
++
+ set_bit(MT76_STATE_RUNNING, &phy->mt76->state);
+
+ ieee80211_queue_delayed_work(hw, &phy->mt76->mac_work,
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index b6bd36c2..3820a63e 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -443,6 +443,34 @@ mt7996_mcu_ie_countdown(struct mt7996_dev *dev, struct sk_buff *skb)
+ }
+ }
+
++static void
++mt7996_mcu_rx_thermal_notify(struct mt7996_dev *dev, struct sk_buff *skb)
++{
++#define THERMAL_NOTIFY_TAG 0x4
++#define THERMAL_NOTIFY 0x2
++ struct mt76_phy *mphy = &dev->mt76.phy;
++ struct mt7996_mcu_thermal_notify *n;
++ struct mt7996_phy *phy;
++
++ n = (struct mt7996_mcu_thermal_notify *)skb->data;
++
++ if (n->tag != THERMAL_NOTIFY_TAG)
++ return;
++
++ if (n->event_id != THERMAL_NOTIFY)
++ return;
++
++ if (n->band_idx > MT_BAND2)
++ return;
++
++ mphy = dev->mt76.phys[n->band_idx];
++ if (!mphy)
++ return;
++
++ phy = (struct mt7996_phy *)mphy->priv;
++ phy->throttle_state = n->duty_percent;
++}
++
+ static void
+ mt7996_mcu_rx_ext_event(struct mt7996_dev *dev, struct sk_buff *skb)
+ {
+@@ -487,6 +515,9 @@ mt7996_mcu_uni_rx_unsolicited_event(struct mt7996_dev *dev, struct sk_buff *skb)
+ case MCU_UNI_EVENT_RDD_REPORT:
+ mt7996_mcu_rx_radar_detected(dev, skb);
+ break;
++ case MCU_UNI_EVENT_THERMAL:
++ mt7996_mcu_rx_thermal_notify(dev, skb);
++ break;
+ default:
+ break;
+ }
+@@ -3277,6 +3308,81 @@ out:
+ return 0;
+ }
+
++
++int mt7996_mcu_set_thermal_throttling(struct mt7996_phy *phy, u8 state)
++{
++ struct {
++ u8 _rsv[4];
++
++ __le16 tag;
++ __le16 len;
++
++ struct mt7996_mcu_thermal_ctrl ctrl;
++ } __packed req = {
++ .tag = cpu_to_le16(UNI_CMD_THERMAL_PROTECT_DUTY_CONFIG),
++ .len = cpu_to_le16(sizeof(req) - 4),
++ .ctrl = {
++ .band_idx = phy->mt76->band_idx,
++ },
++ };
++ int level, ret;
++
++ /* set duty cycle and level */
++ for (level = 0; level < 4; level++) {
++ req.ctrl.duty.duty_level = level;
++ req.ctrl.duty.duty_cycle = state;
++ state /= 2;
++
++ ret = mt76_mcu_send_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(THERMAL),
++ &req, sizeof(req), false);
++ if (ret)
++ return ret;
++ }
++
++ return 0;
++}
++
++int mt7996_mcu_set_thermal_protect(struct mt7996_phy *phy)
++{
++#define SUSTAIN_PERIOD 10
++ struct {
++ u8 _rsv[4];
++
++ __le16 tag;
++ __le16 len;
++
++ struct mt7996_mcu_thermal_ctrl ctrl;
++ struct mt7996_mcu_thermal_enable enable;
++ } __packed req = {
++ .len = cpu_to_le16(sizeof(req) - 4 - sizeof(req.enable)),
++ .ctrl = {
++ .band_idx = phy->mt76->band_idx,
++ .type.protect_type = 1,
++ .type.trigger_type = 1,
++ },
++ };
++ int ret;
++
++ req.tag = cpu_to_le16(UNI_CMD_THERMAL_PROTECT_DISABLE);
++
++ ret = mt76_mcu_send_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(THERMAL),
++ &req, sizeof(req) - sizeof(req.enable), false);
++ if (ret)
++ return ret;
++
++ /* set high-temperature trigger threshold */
++ req.tag = cpu_to_le16(UNI_CMD_THERMAL_PROTECT_ENABLE);
++ /* add a safety margin ~10 */
++ req.enable.restore_temp = cpu_to_le32(phy->throttle_temp[0] - 10);
++ req.enable.trigger_temp = cpu_to_le32(phy->throttle_temp[1]);
++ req.enable.sustain_time = cpu_to_le16(SUSTAIN_PERIOD);
++
++ req.len = cpu_to_le16(sizeof(req) - 4);
++
++ return mt76_mcu_send_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(THERMAL),
++ &req, sizeof(req), false);
++}
++
+ int mt7996_mcu_set_ser(struct mt7996_dev *dev, u8 action, u8 val, u8 band)
+ {
+ struct {
+diff --git a/mt7996/mcu.h b/mt7996/mcu.h
+index dd0c5ac5..7fefc28f 100644
+--- a/mt7996/mcu.h
++++ b/mt7996/mcu.h
+@@ -30,6 +30,28 @@ struct mt7996_mcu_uni_event {
+ __le32 status; /* 0: success, others: fail */
+ } __packed;
+
++struct mt7996_mcu_thermal_ctrl {
++ u8 ctrl_id;
++ u8 band_idx;
++ union {
++ struct {
++ u8 protect_type; /* 1: duty admit, 2: radio off */
++ u8 trigger_type; /* 0: low, 1: high */
++ } __packed type;
++ struct {
++ u8 duty_level; /* level 0~3 */
++ u8 duty_cycle;
++ } __packed duty;
++ };
++} __packed;
++
++struct mt7996_mcu_thermal_enable {
++ __le32 trigger_temp;
++ __le32 restore_temp;
++ __le16 sustain_time;
++ u8 rsv[2];
++} __packed;
++
+ struct mt7996_mcu_csa_notify {
+ struct mt7996_mcu_rxd rxd;
+
+@@ -153,6 +175,22 @@ struct mt7996_mcu_mib {
+ __le64 data;
+ } __packed;
+
++struct mt7996_mcu_thermal_notify {
++ struct mt7996_mcu_rxd rxd;
++
++ u8 __rsv1[4];
++
++ __le16 tag;
++ __le16 len;
++
++ u8 event_id;
++ u8 band_idx;
++ u8 level_idx;
++ u8 duty_percent;
++ __le32 restore_temp;
++ u8 __rsv2[4];
++} __packed;
++
+ enum mt7996_chan_mib_offs {
+ UNI_MIB_OBSS_AIRTIME = 26,
+ UNI_MIB_NON_WIFI_TIME = 27,
+@@ -642,6 +680,12 @@ enum{
+ UNI_CMD_SR_SET_SIGA = 0xd0,
+ };
+
++enum {
++ UNI_CMD_THERMAL_PROTECT_ENABLE = 0x6,
++ UNI_CMD_THERMAL_PROTECT_DISABLE,
++ UNI_CMD_THERMAL_PROTECT_DUTY_CONFIG,
++};
++
+ enum {
+ UNI_CMD_ACCESS_REG_BASIC = 0x0,
+ UNI_CMD_ACCESS_RF_REG_BASIC,
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index 997a0bf0..25b20fa6 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -43,6 +43,13 @@
+ #define MT7996_MAX_STA_TWT_AGRT 8
+ #define MT7996_MAX_QUEUE (__MT_RXQ_MAX + __MT_MCUQ_MAX + 3)
+
++#define MT7996_THERMAL_THROTTLE_MAX 100
++#define MT7996_CDEV_THROTTLE_MAX 99
++#define MT7996_CRIT_TEMP_IDX 0
++#define MT7996_MAX_TEMP_IDX 1
++#define MT7996_CRIT_TEMP 110
++#define MT7996_MAX_TEMP 120
++
+ struct mt7996_vif;
+ struct mt7996_sta;
+ struct mt7996_dfs_pulse;
+@@ -211,6 +218,11 @@ struct mt7996_phy {
+
+ struct ieee80211_vif *monitor_vif;
+
++ struct thermal_cooling_device *cdev;
++ u8 cdev_state;
++ u8 throttle_state;
++ u32 throttle_temp[2]; /* 0: critical high, 1: maximum */
++
+ u32 rxfilter;
+ u64 omac_mask;
+
+@@ -437,6 +449,9 @@ int mt7996_mcu_set_radar_th(struct mt7996_dev *dev, int index,
+ int mt7996_mcu_set_radio_en(struct mt7996_phy *phy, bool enable);
+ int mt7996_mcu_set_rts_thresh(struct mt7996_phy *phy, u32 val);
+ int mt7996_mcu_get_chan_mib_info(struct mt7996_phy *phy, bool chan_switch);
++int mt7996_mcu_get_temperature(struct mt7996_phy *phy);
++int mt7996_mcu_set_thermal_throttling(struct mt7996_phy *phy, u8 state);
++int mt7996_mcu_set_thermal_protect(struct mt7996_phy *phy);
+ int mt7996_mcu_rdd_cmd(struct mt7996_dev *dev, int cmd, u8 index,
+ u8 rx_sel, u8 val);
+ int mt7996_mcu_rdd_background_enable(struct mt7996_phy *phy,
+--
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0011-wifi-mt76-mt7996-add-thermal-sensor-device-support.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0011-wifi-mt76-mt7996-add-thermal-sensor-device-support.patch
new file mode 100644
index 0000000..3de5b90
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0011-wifi-mt76-mt7996-add-thermal-sensor-device-support.patch
@@ -0,0 +1,184 @@
+From afdb511f0febad0e0cc5572461ab04794cf86852 Mon Sep 17 00:00:00 2001
+From: Howard Hsu <howard-yh.hsu@mediatek.com>
+Date: Thu, 2 Feb 2023 20:53:42 +0800
+Subject: [PATCH 11/19] wifi: mt76: mt7996: add thermal sensor device support
+
+---
+ mt7996/init.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++
+ mt7996/mcu.c | 41 ++++++++++++++++++++++++
+ 2 files changed, 128 insertions(+)
+
+diff --git a/mt7996/init.c b/mt7996/init.c
+index 5a22cd81..631ada15 100644
+--- a/mt7996/init.c
++++ b/mt7996/init.c
+@@ -4,6 +4,8 @@
+ */
+
+ #include <linux/etherdevice.h>
++#include <linux/hwmon.h>
++#include <linux/hwmon-sysfs.h>
+ #include <linux/thermal.h>
+ #include "mt7996.h"
+ #include "mac.h"
+@@ -41,6 +43,81 @@ static const struct ieee80211_iface_combination if_comb[] = {
+ }
+ };
+
++static ssize_t mt7996_thermal_temp_show(struct device *dev,
++ struct device_attribute *attr,
++ char *buf)
++{
++ struct mt7996_phy *phy = dev_get_drvdata(dev);
++ int i = to_sensor_dev_attr(attr)->index;
++ int temperature;
++
++ switch (i) {
++ case 0:
++ temperature = mt7996_mcu_get_temperature(phy);
++ if (temperature < 0)
++ return temperature;
++ /* display in millidegree celcius */
++ return sprintf(buf, "%u\n", temperature * 1000);
++ case 1:
++ case 2:
++ return sprintf(buf, "%u\n",
++ phy->throttle_temp[i - 1] * 1000);
++ case 3:
++ return sprintf(buf, "%hhu\n", phy->throttle_state);
++ default:
++ return -EINVAL;
++ }
++}
++
++static ssize_t mt7996_thermal_temp_store(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct mt7996_phy *phy = dev_get_drvdata(dev);
++ int ret, i = to_sensor_dev_attr(attr)->index;
++ long val;
++
++ ret = kstrtol(buf, 10, &val);
++ if (ret < 0)
++ return ret;
++
++ mutex_lock(&phy->dev->mt76.mutex);
++ val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 40, 130);
++
++ if ((i - 1 == MT7996_CRIT_TEMP_IDX &&
++ val > phy->throttle_temp[MT7996_MAX_TEMP_IDX]) ||
++ (i - 1 == MT7996_MAX_TEMP_IDX &&
++ val < phy->throttle_temp[MT7996_CRIT_TEMP_IDX])) {
++ dev_err(phy->dev->mt76.dev,
++ "temp1_max shall be greater than temp1_crit.");
++ mutex_unlock(&phy->dev->mt76.mutex);
++ return -EINVAL;
++ }
++
++ phy->throttle_temp[i - 1] = val;
++ mutex_unlock(&phy->dev->mt76.mutex);
++
++ ret = mt7996_mcu_set_thermal_protect(phy);
++ if (ret)
++ return ret;
++
++ return count;
++}
++
++static SENSOR_DEVICE_ATTR_RO(temp1_input, mt7996_thermal_temp, 0);
++static SENSOR_DEVICE_ATTR_RW(temp1_crit, mt7996_thermal_temp, 1);
++static SENSOR_DEVICE_ATTR_RW(temp1_max, mt7996_thermal_temp, 2);
++static SENSOR_DEVICE_ATTR_RO(throttle1, mt7996_thermal_temp, 3);
++
++static struct attribute *mt7996_hwmon_attrs[] = {
++ &sensor_dev_attr_temp1_input.dev_attr.attr,
++ &sensor_dev_attr_temp1_crit.dev_attr.attr,
++ &sensor_dev_attr_temp1_max.dev_attr.attr,
++ &sensor_dev_attr_throttle1.dev_attr.attr,
++ NULL,
++};
++ATTRIBUTE_GROUPS(mt7996_hwmon);
++
+ static int
+ mt7996_thermal_get_max_throttle_state(struct thermal_cooling_device *cdev,
+ unsigned long *state)
+@@ -112,6 +189,7 @@ static int mt7996_thermal_init(struct mt7996_phy *phy)
+ {
+ struct wiphy *wiphy = phy->mt76->hw->wiphy;
+ struct thermal_cooling_device *cdev;
++ struct device *hwmon;
+ const char *name;
+
+ name = devm_kasprintf(&wiphy->dev, GFP_KERNEL, "mt7996_%s",
+@@ -130,6 +208,15 @@ static int mt7996_thermal_init(struct mt7996_phy *phy)
+ phy->throttle_temp[MT7996_CRIT_TEMP_IDX] = MT7996_CRIT_TEMP;
+ phy->throttle_temp[MT7996_MAX_TEMP_IDX] = MT7996_MAX_TEMP;
+
++ if (!IS_REACHABLE(CONFIG_HWMON))
++ return 0;
++
++ hwmon = devm_hwmon_device_register_with_groups(&wiphy->dev, name, phy,
++ mt7996_hwmon_groups);
++
++ if (IS_ERR(hwmon))
++ return PTR_ERR(hwmon);
++
+ return 0;
+ }
+
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 3820a63e..b3326586 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -3308,6 +3308,47 @@ out:
+ return 0;
+ }
+
++int mt7996_mcu_get_temperature(struct mt7996_phy *phy)
++{
++#define TEMPERATURE_QUERY 0
++#define GET_TEMPERATURE 0
++ struct {
++ u8 _rsv[4];
++
++ __le16 tag;
++ __le16 len;
++
++ u8 rsv1;
++ u8 action;
++ u8 band_idx;
++ u8 rsv2;
++ } req = {
++ .tag = cpu_to_le16(TEMPERATURE_QUERY),
++ .len = cpu_to_le16(sizeof(req) - 4),
++ .action = GET_TEMPERATURE,
++ .band_idx = phy->mt76->band_idx,
++ };
++ struct mt7996_mcu_thermal {
++ u8 _rsv[4];
++
++ __le16 tag;
++ __le16 len;
++
++ __le32 rsv;
++ __le32 temperature;
++ } __packed *res;
++ struct sk_buff *skb;
++ int ret;
++
++ ret = mt76_mcu_send_and_get_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(THERMAL),
++ &req, sizeof(req), true, &skb);
++ if (ret)
++ return ret;
++
++ res = (void *)skb->data;
++
++ return le32_to_cpu(res->temperature);
++}
+
+ int mt7996_mcu_set_thermal_throttling(struct mt7996_phy *phy, u8 state)
+ {
+--
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0006-wifi-mt76-mt7996-add-802.11s-mesh-amsdu-de-amsdu-sup.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0012-wifi-mt76-mt7996-add-802.11s-mesh-amsdu-de-amsdu-sup.patch
similarity index 78%
rename from recipes-wifi/linux-mt76/files/patches-3.x/0006-wifi-mt76-mt7996-add-802.11s-mesh-amsdu-de-amsdu-sup.patch
rename to recipes-wifi/linux-mt76/files/patches-3.x/0012-wifi-mt76-mt7996-add-802.11s-mesh-amsdu-de-amsdu-sup.patch
index 70867df..728b4e0 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0006-wifi-mt76-mt7996-add-802.11s-mesh-amsdu-de-amsdu-sup.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0012-wifi-mt76-mt7996-add-802.11s-mesh-amsdu-de-amsdu-sup.patch
@@ -1,7 +1,7 @@
-From 6298046de15b190139552d74aeb668e8cb873b1d Mon Sep 17 00:00:00 2001
+From f78111386b1ac57a459687b9d58e1804a80d4970 Mon Sep 17 00:00:00 2001
From: Bo Jiao <Bo.Jiao@mediatek.com>
-Date: Thu, 15 Dec 2022 18:22:37 +0800
-Subject: [PATCH 6/7] wifi: mt76: mt7996: add 802.11s mesh amsdu/de-amsdu
+Date: Mon, 6 Feb 2023 11:34:51 +0800
+Subject: [PATCH 12/19] wifi: mt76: mt7996: add 802.11s mesh amsdu/de-amsdu
support
Signed-off-by: Bo Jiao <Bo.Jiao@mediatek.com>
@@ -12,16 +12,12 @@
mt7996/mcu.h | 2 +-
mt7996/mmio.c | 3 ++-
5 files changed, 27 insertions(+), 4 deletions(-)
- mode change 100644 => 100755 mt7996/mac.c
- mode change 100644 => 100755 mt7996/mmio.c
diff --git a/mt7996/mac.c b/mt7996/mac.c
-old mode 100644
-new mode 100755
-index 51337dde..d17b5478
+index 40ef5e4b..8dc3a621 100644
--- a/mt7996/mac.c
+++ b/mt7996/mac.c
-@@ -630,6 +630,7 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
+@@ -633,6 +633,7 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
u32 rxd4 = le32_to_cpu(rxd[4]);
u32 csum_mask = MT_RXD0_NORMAL_IP_SUM | MT_RXD0_NORMAL_UDP_TCP_SUM;
u32 csum_status = *(u32 *)skb->cb;
@@ -29,7 +25,7 @@
bool unicast, insert_ccmp_hdr = false;
u8 remove_pad, amsdu_info, band_idx;
u8 mode = 0, qos_ctl = 0;
-@@ -822,6 +823,9 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
+@@ -825,6 +826,9 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
skb_pull(skb, hdr_gap);
if (!hdr_trans && status->amsdu) {
@@ -39,7 +35,7 @@
pad_start = ieee80211_get_hdrlen_from_skb(skb);
} else if (hdr_trans && (rxd2 & MT_RXD2_NORMAL_HDR_TRANS_ERROR)) {
/* When header translation failure is indicated,
-@@ -854,8 +858,17 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
+@@ -857,8 +861,17 @@ mt7996_mac_fill_rx(struct mt7996_dev *dev, struct sk_buff *skb)
hdr = mt76_skb_get_hdr(skb);
fc = hdr->frame_control;
if (ieee80211_is_data_qos(fc)) {
@@ -59,7 +55,7 @@
} else {
status->flag |= RX_FLAG_8023;
diff --git a/mt7996/mac.h b/mt7996/mac.h
-index 470b701a..fd0e5d1c 100644
+index 4914d3e5..e48cc68b 100644
--- a/mt7996/mac.h
+++ b/mt7996/mac.h
@@ -12,6 +12,8 @@
@@ -72,10 +68,10 @@
#define MT_RXD0_NORMAL_IP_SUM BIT(23)
#define MT_RXD0_NORMAL_UDP_TCP_SUM BIT(24)
diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index 394dd15c..1e47b0ae 100644
+index b3326586..0dbe2e01 100644
--- a/mt7996/mcu.c
+++ b/mt7996/mcu.c
-@@ -1022,7 +1022,8 @@ mt7996_mcu_sta_amsdu_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
+@@ -1054,7 +1054,8 @@ mt7996_mcu_sta_amsdu_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
struct tlv *tlv;
if (vif->type != NL80211_IFTYPE_STATION &&
@@ -85,7 +81,7 @@
return;
if (!sta->deflink.agg.max_amsdu_len)
-@@ -1528,6 +1529,12 @@ mt7996_mcu_sta_hdr_trans_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
+@@ -1560,6 +1561,12 @@ mt7996_mcu_sta_hdr_trans_tlv(struct mt7996_dev *dev, struct sk_buff *skb,
hdr_trans->to_ds = true;
hdr_trans->from_ds = true;
}
@@ -99,10 +95,10 @@
static enum mcu_mmps_mode
diff --git a/mt7996/mcu.h b/mt7996/mcu.h
-index dd0c5ac5..009f5f06 100644
+index 7fefc28f..ad66a1f8 100644
--- a/mt7996/mcu.h
+++ b/mt7996/mcu.h
-@@ -396,7 +396,7 @@ struct sta_rec_hdr_trans {
+@@ -434,7 +434,7 @@ struct sta_rec_hdr_trans {
u8 from_ds;
u8 to_ds;
u8 dis_rx_hdr_tran;
@@ -112,14 +108,12 @@
struct hdr_trans_en {
diff --git a/mt7996/mmio.c b/mt7996/mmio.c
-old mode 100644
-new mode 100755
-index d8a2c1a7..08164b1a
+index 902370a2..6610cc45 100644
--- a/mt7996/mmio.c
+++ b/mt7996/mmio.c
@@ -320,7 +320,8 @@ struct mt7996_dev *mt7996_mmio_probe(struct device *pdev,
/* txwi_size = txd size + txp size */
- .txwi_size = MT_TXD_SIZE + sizeof(struct mt7996_txp),
+ .txwi_size = MT_TXD_SIZE + sizeof(struct mt76_connac_fw_txp),
.drv_flags = MT_DRV_TXWI_NO_FREE |
- MT_DRV_HW_MGMT_TXQ,
+ MT_DRV_HW_MGMT_TXQ |
@@ -128,5 +122,5 @@
SURVEY_INFO_TIME_RX |
SURVEY_INFO_TIME_BSS_RX,
--
-2.25.1
+2.39.2
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0013-wifi-mt76-mt7996-add-L0.5-system-error-recovery-supp.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0013-wifi-mt76-mt7996-add-L0.5-system-error-recovery-supp.patch
new file mode 100644
index 0000000..93ec12d
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0013-wifi-mt76-mt7996-add-L0.5-system-error-recovery-supp.patch
@@ -0,0 +1,948 @@
+From 6b8dfe2580a782be754be7bcd44da6ad79dc4231 Mon Sep 17 00:00:00 2001
+From: Bo Jiao <Bo.Jiao@mediatek.com>
+Date: Mon, 13 Feb 2023 18:00:25 +0800
+Subject: [PATCH 13/19] wifi: mt76: mt7996: add L0.5 system error recovery
+ support
+
+Signed-off-by: Bo Jiao <Bo.Jiao@mediatek.com>
+---
+ mt7996/debugfs.c | 155 +++++++++++++++++++++++---
+ mt7996/dma.c | 65 +++++++++++
+ mt7996/init.c | 9 +-
+ mt7996/mac.c | 285 +++++++++++++++++++++++++++++++++++++++--------
+ mt7996/main.c | 18 ++-
+ mt7996/mcu.c | 22 ++--
+ mt7996/mcu.h | 28 +++--
+ mt7996/mmio.c | 7 +-
+ mt7996/mt7996.h | 17 ++-
+ mt7996/regs.h | 36 +++++-
+ 10 files changed, 542 insertions(+), 100 deletions(-)
+
+diff --git a/mt7996/debugfs.c b/mt7996/debugfs.c
+index 9c5e9ac1..f2c46a50 100644
+--- a/mt7996/debugfs.c
++++ b/mt7996/debugfs.c
+@@ -48,12 +48,12 @@ DEFINE_DEBUGFS_ATTRIBUTE(fops_implicit_txbf, mt7996_implicit_txbf_get,
+
+ /* test knob of system error recovery */
+ static ssize_t
+-mt7996_fw_ser_set(struct file *file, const char __user *user_buf,
+- size_t count, loff_t *ppos)
++mt7996_sys_recovery_set(struct file *file, const char __user *user_buf,
++ size_t count, loff_t *ppos)
+ {
+ struct mt7996_phy *phy = file->private_data;
+ struct mt7996_dev *dev = phy->dev;
+- u8 band_idx = phy->mt76->band_idx;
++ bool band = phy->mt76->band_idx;
+ char buf[16];
+ int ret = 0;
+ u16 val;
+@@ -73,17 +73,49 @@ mt7996_fw_ser_set(struct file *file, const char __user *user_buf,
+ return -EINVAL;
+
+ switch (val) {
+- case SER_SET_RECOVER_L1:
+- case SER_SET_RECOVER_L2:
+- case SER_SET_RECOVER_L3_RX_ABORT:
+- case SER_SET_RECOVER_L3_TX_ABORT:
+- case SER_SET_RECOVER_L3_TX_DISABLE:
+- case SER_SET_RECOVER_L3_BF:
+- ret = mt7996_mcu_set_ser(dev, SER_ENABLE, BIT(val), band_idx);
++ /*
++ * 0: grab firmware current SER state.
++ * 1: trigger & enable system error L1 recovery.
++ * 2: trigger & enable system error L2 recovery.
++ * 3: trigger & enable system error L3 rx abort.
++ * 4: trigger & enable system error L3 tx abort.
++ * 5: trigger & enable system error L3 tx disable.
++ * 6: trigger & enable system error L3 bf recovery.
++ * 7: trigger & enable system error L4 MDP recovery.
++ * 8: trigger & enable system error full recovery.
++ * 9: trigger firmware crash.
++ */
++ case UNI_CMD_SER_QUERY:
++ ret = mt7996_mcu_set_ser(dev, UNI_CMD_SER_QUERY, 0, band);
++ break;
++ case UNI_CMD_SER_SET_RECOVER_L1:
++ case UNI_CMD_SER_SET_RECOVER_L2:
++ case UNI_CMD_SER_SET_RECOVER_L3_RX_ABORT:
++ case UNI_CMD_SER_SET_RECOVER_L3_TX_ABORT:
++ case UNI_CMD_SER_SET_RECOVER_L3_TX_DISABLE:
++ case UNI_CMD_SER_SET_RECOVER_L3_BF:
++ case UNI_CMD_SER_SET_RECOVER_L4_MDP:
++ ret = mt7996_mcu_set_ser(dev, UNI_CMD_SER_SET, BIT(val), band);
++ if (ret)
++ return ret;
++
++ ret = mt7996_mcu_set_ser(dev, UNI_CMD_SER_TRIGGER, val, band);
++ break;
++
++ /* enable full chip reset */
++ case UNI_CMD_SER_SET_RECOVER_FULL:
++ mt76_set(dev, MT_WFDMA0_MCU_HOST_INT_ENA, MT_MCU_CMD_WDT_MASK);
+ if (ret)
+ return ret;
+
+- ret = mt7996_mcu_set_ser(dev, SER_RECOVER, val, band_idx);
++ dev->recovery.state |= MT_MCU_CMD_WDT_MASK;
++ mt7996_reset(dev);
++ break;
++
++ /* WARNING: trigger firmware crash */
++ case UNI_CMD_SER_SET_SYSTEM_ASSERT:
++ mt76_wr(dev, MT_MCU_WM_CIRQ_EINT_MASK_CLR_ADDR, BIT(18));
++ mt76_wr(dev, MT_MCU_WM_CIRQ_EINT_SOFT_ADDR, BIT(18));
+ break;
+ default:
+ break;
+@@ -92,9 +124,101 @@ mt7996_fw_ser_set(struct file *file, const char __user *user_buf,
+ return ret ? ret : count;
+ }
+
+-static const struct file_operations mt7996_fw_ser_ops = {
+- .write = mt7996_fw_ser_set,
+- /* TODO: ser read */
++static ssize_t
++mt7996_sys_recovery_get(struct file *file, char __user *user_buf,
++ size_t count, loff_t *ppos)
++{
++ struct mt7996_phy *phy = file->private_data;
++ struct mt7996_dev *dev = phy->dev;
++ char *buff;
++ int desc = 0;
++ ssize_t ret;
++ static const size_t bufsz = 1024;
++
++ buff = kmalloc(bufsz, GFP_KERNEL);
++ if (!buff)
++ return -ENOMEM;
++
++ /* HELP */
++ desc += scnprintf(buff + desc, bufsz - desc,
++ "Please echo the correct value ...\n");
++ desc += scnprintf(buff + desc, bufsz - desc,
++ "0: grab firmware transient SER state\n");
++ desc += scnprintf(buff + desc, bufsz - desc,
++ "1: trigger system error L1 recovery\n");
++ desc += scnprintf(buff + desc, bufsz - desc,
++ "2: trigger system error L2 recovery\n");
++ desc += scnprintf(buff + desc, bufsz - desc,
++ "3: trigger system error L3 rx abort\n");
++ desc += scnprintf(buff + desc, bufsz - desc,
++ "4: trigger system error L3 tx abort\n");
++ desc += scnprintf(buff + desc, bufsz - desc,
++ "5: trigger system error L3 tx disable\n");
++ desc += scnprintf(buff + desc, bufsz - desc,
++ "6: trigger system error L3 bf recovery\n");
++ desc += scnprintf(buff + desc, bufsz - desc,
++ "7: trigger system error L4 MDP recovery\n");
++ desc += scnprintf(buff + desc, bufsz - desc,
++ "8: trigger system error full recovery\n");
++ desc += scnprintf(buff + desc, bufsz - desc,
++ "9: trigger firmware crash\n");
++
++ /* SER statistics */
++ desc += scnprintf(buff + desc, bufsz - desc,
++ "\nlet's dump firmware SER statistics...\n");
++ desc += scnprintf(buff + desc, bufsz - desc,
++ "::E R , SER_STATUS = 0x%08x\n",
++ mt76_rr(dev, MT_SWDEF_SER_STATS));
++ desc += scnprintf(buff + desc, bufsz - desc,
++ "::E R , SER_PLE_ERR = 0x%08x\n",
++ mt76_rr(dev, MT_SWDEF_PLE_STATS));
++ desc += scnprintf(buff + desc, bufsz - desc,
++ "::E R , SER_PLE_ERR_1 = 0x%08x\n",
++ mt76_rr(dev, MT_SWDEF_PLE1_STATS));
++ desc += scnprintf(buff + desc, bufsz - desc,
++ "::E R , SER_PLE_ERR_AMSDU = 0x%08x\n",
++ mt76_rr(dev, MT_SWDEF_PLE_AMSDU_STATS));
++ desc += scnprintf(buff + desc, bufsz - desc,
++ "::E R , SER_PSE_ERR = 0x%08x\n",
++ mt76_rr(dev, MT_SWDEF_PSE_STATS));
++ desc += scnprintf(buff + desc, bufsz - desc,
++ "::E R , SER_PSE_ERR_1 = 0x%08x\n",
++ mt76_rr(dev, MT_SWDEF_PSE1_STATS));
++ desc += scnprintf(buff + desc, bufsz - desc,
++ "::E R , SER_LMAC_WISR6_B0 = 0x%08x\n",
++ mt76_rr(dev, MT_SWDEF_LAMC_WISR6_BN0_STATS));
++ desc += scnprintf(buff + desc, bufsz - desc,
++ "::E R , SER_LMAC_WISR6_B1 = 0x%08x\n",
++ mt76_rr(dev, MT_SWDEF_LAMC_WISR6_BN1_STATS));
++ desc += scnprintf(buff + desc, bufsz - desc,
++ "::E R , SER_LMAC_WISR6_B2 = 0x%08x\n",
++ mt76_rr(dev, MT_SWDEF_LAMC_WISR6_BN2_STATS));
++ desc += scnprintf(buff + desc, bufsz - desc,
++ "::E R , SER_LMAC_WISR7_B0 = 0x%08x\n",
++ mt76_rr(dev, MT_SWDEF_LAMC_WISR7_BN0_STATS));
++ desc += scnprintf(buff + desc, bufsz - desc,
++ "::E R , SER_LMAC_WISR7_B1 = 0x%08x\n",
++ mt76_rr(dev, MT_SWDEF_LAMC_WISR7_BN1_STATS));
++ desc += scnprintf(buff + desc, bufsz - desc,
++ "::E R , SER_LMAC_WISR7_B2 = 0x%08x\n",
++ mt76_rr(dev, MT_SWDEF_LAMC_WISR7_BN2_STATS));
++ desc += scnprintf(buff + desc, bufsz - desc,
++ "::E R , SER_WFDMA_ERR = 0x%08x\n",
++ mt76_rr(dev, WF_SWDEF_WFDMA_STATUS_ADDR));
++
++ desc += scnprintf(buff + desc, bufsz - desc,
++ "\nSYS_RESET_COUNT: WM %d, WA %d\n",
++ dev->recovery.wm_reset_count,
++ dev->recovery.wa_reset_count);
++
++ ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc);
++ kfree(buff);
++ return ret;
++}
++
++static const struct file_operations mt7996_sys_recovery_ops = {
++ .write = mt7996_sys_recovery_set,
++ .read = mt7996_sys_recovery_get,
+ .open = simple_open,
+ .llseek = default_llseek,
+ };
+@@ -674,6 +798,8 @@ int mt7996_init_debugfs(struct mt7996_phy *phy)
+ debugfs_create_file("xmit-queues", 0400, dir, phy,
+ &mt7996_xmit_queues_fops);
+ debugfs_create_file("tx_stats", 0400, dir, phy, &mt7996_tx_stats_fops);
++ debugfs_create_file("sys_recovery", 0600, dir, phy,
++ &mt7996_sys_recovery_ops);
+ debugfs_create_file("fw_debug_wm", 0600, dir, dev, &fops_fw_debug_wm);
+ debugfs_create_file("fw_debug_wa", 0600, dir, dev, &fops_fw_debug_wa);
+ debugfs_create_file("fw_debug_bin", 0600, dir, dev, &fops_fw_debug_bin);
+@@ -684,7 +810,6 @@ int mt7996_init_debugfs(struct mt7996_phy *phy)
+ &fops_implicit_txbf);
+ debugfs_create_devm_seqfile(dev->mt76.dev, "twt_stats", dir,
+ mt7996_twt_stats);
+- debugfs_create_file("fw_ser", 0600, dir, phy, &mt7996_fw_ser_ops);
+ debugfs_create_file("rf_regval", 0600, dir, dev, &fops_rf_regval);
+
+ if (phy->mt76->cap.has_5ghz) {
+diff --git a/mt7996/dma.c b/mt7996/dma.c
+index c09fe427..18ea758c 100644
+--- a/mt7996/dma.c
++++ b/mt7996/dma.c
+@@ -352,6 +352,71 @@ int mt7996_dma_init(struct mt7996_dev *dev)
+ return 0;
+ }
+
++void mt7996_dma_reset(struct mt7996_dev *dev, bool force)
++{
++ struct mt76_phy *phy2 = dev->mt76.phys[MT_BAND1];
++ struct mt76_phy *phy3 = dev->mt76.phys[MT_BAND2];
++ u32 hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0);
++ int i;
++
++ mt76_clear(dev, MT_WFDMA0_GLO_CFG,
++ MT_WFDMA0_GLO_CFG_TX_DMA_EN |
++ MT_WFDMA0_GLO_CFG_RX_DMA_EN);
++
++ if (dev->hif2)
++ mt76_clear(dev, MT_WFDMA0_GLO_CFG + hif1_ofs,
++ MT_WFDMA0_GLO_CFG_TX_DMA_EN |
++ MT_WFDMA0_GLO_CFG_RX_DMA_EN);
++
++ usleep_range(1000, 2000);
++
++ for (i = 0; i < __MT_TXQ_MAX; i++) {
++ mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], true);
++ if (phy2)
++ mt76_queue_tx_cleanup(dev, phy2->q_tx[i], true);
++ if (phy3)
++ mt76_queue_tx_cleanup(dev, phy3->q_tx[i], true);
++ }
++
++ for (i = 0; i < __MT_MCUQ_MAX; i++)
++ mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[i], true);
++
++ mt76_for_each_q_rx(&dev->mt76, i)
++ //mt76_queue_rx_reset(dev, i);
++ mt76_queue_rx_cleanup(dev, &dev->mt76.q_rx[i]);
++
++ mt76_tx_status_check(&dev->mt76, true);
++
++ /* reset wfsys */
++ if (force)
++ mt7996_wfsys_reset(dev);
++
++ mt7996_dma_disable(dev, force);
++
++ /* reset hw queues */
++ for (i = 0; i < __MT_TXQ_MAX; i++) {
++ mt76_queue_reset(dev, dev->mphy.q_tx[i]);
++ if (phy2)
++ mt76_queue_reset(dev, phy2->q_tx[i]);
++ if (phy3)
++ mt76_queue_reset(dev, phy3->q_tx[i]);
++ }
++
++ for (i = 0; i < __MT_MCUQ_MAX; i++)
++ mt76_queue_reset(dev, dev->mt76.q_mcu[i]);
++
++ mt76_for_each_q_rx(&dev->mt76, i) {
++ mt76_queue_reset(dev, &dev->mt76.q_rx[i]);
++ }
++
++ mt76_tx_status_check(&dev->mt76, true);
++
++ mt76_for_each_q_rx(&dev->mt76, i)
++ mt76_queue_rx_reset(dev, i);
++
++ mt7996_dma_enable(dev);
++}
++
+ void mt7996_dma_cleanup(struct mt7996_dev *dev)
+ {
+ mt7996_dma_disable(dev, true);
+diff --git a/mt7996/init.c b/mt7996/init.c
+index 631ada15..ced38ac8 100644
+--- a/mt7996/init.c
++++ b/mt7996/init.c
+@@ -278,8 +278,7 @@ static void mt7996_led_set_brightness(struct led_classdev *led_cdev,
+ mt7996_led_set_config(led_cdev, 0xff, 0);
+ }
+
+-static void
+-mt7996_init_txpower(struct mt7996_dev *dev,
++void mt7996_init_txpower(struct mt7996_dev *dev,
+ struct ieee80211_supported_band *sband)
+ {
+ int i, nss = hweight8(dev->mphy.antenna_mask);
+@@ -429,7 +428,7 @@ mt7996_mac_init_band(struct mt7996_dev *dev, u8 band)
+ mt76_rmw(dev, MT_WTBLOFF_RSCR(band), mask, set);
+ }
+
+-static void mt7996_mac_init(struct mt7996_dev *dev)
++void mt7996_mac_init(struct mt7996_dev *dev)
+ {
+ #define HIF_TXD_V2_1 4
+ int i;
+@@ -463,7 +462,7 @@ static void mt7996_mac_init(struct mt7996_dev *dev)
+ mt7996_mac_init_band(dev, i);
+ }
+
+-static int mt7996_txbf_init(struct mt7996_dev *dev)
++int mt7996_txbf_init(struct mt7996_dev *dev)
+ {
+ int ret;
+
+@@ -1075,6 +1074,8 @@ int mt7996_register_device(struct mt7996_dev *dev)
+ if (ret)
+ return ret;
+
++ dev->recovery.hw_init_done = true;
++
+ return mt7996_init_debugfs(&dev->phy);
+ }
+
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index 8dc3a621..4c0c8f1e 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -1724,7 +1724,7 @@ mt7996_wait_reset_state(struct mt7996_dev *dev, u32 state)
+ bool ret;
+
+ ret = wait_event_timeout(dev->reset_wait,
+- (READ_ONCE(dev->reset_state) & state),
++ (READ_ONCE(dev->recovery.state) & state),
+ MT7996_RESET_TIMEOUT);
+
+ WARN(!ret, "Timeout waiting for MCU reset state %x\n", state);
+@@ -1773,68 +1773,208 @@ mt7996_update_beacons(struct mt7996_dev *dev)
+ mt7996_update_vif_beacon, phy3->hw);
+ }
+
+-static void
+-mt7996_dma_reset(struct mt7996_dev *dev)
++void mt7996_tx_token_put(struct mt7996_dev *dev)
+ {
+- struct mt76_phy *phy2 = dev->mt76.phys[MT_BAND1];
+- struct mt76_phy *phy3 = dev->mt76.phys[MT_BAND2];
+- u32 hif1_ofs = MT_WFDMA0_PCIE1(0) - MT_WFDMA0(0);
+- int i;
++ struct mt76_txwi_cache *txwi;
++ int id;
+
+- mt76_clear(dev, MT_WFDMA0_GLO_CFG,
+- MT_WFDMA0_GLO_CFG_TX_DMA_EN |
+- MT_WFDMA0_GLO_CFG_RX_DMA_EN);
++ spin_lock_bh(&dev->mt76.token_lock);
++ idr_for_each_entry(&dev->mt76.token, txwi, id) {
++ mt7996_txwi_free(dev, txwi, NULL, NULL);
++ dev->mt76.token_count--;
++ }
++ spin_unlock_bh(&dev->mt76.token_lock);
++ idr_destroy(&dev->mt76.token);
++}
+
+- if (dev->hif2)
+- mt76_clear(dev, MT_WFDMA0_GLO_CFG + hif1_ofs,
+- MT_WFDMA0_GLO_CFG_TX_DMA_EN |
+- MT_WFDMA0_GLO_CFG_RX_DMA_EN);
+
+- usleep_range(1000, 2000);
++static int
++mt7996_mac_restart(struct mt7996_dev *dev)
++{
++ struct mt7996_phy *phy2, *phy3;
++ struct mt76_dev *mdev = &dev->mt76;
++ int i, ret;
+
+- for (i = 0; i < __MT_TXQ_MAX; i++) {
+- mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], true);
+- if (phy2)
+- mt76_queue_tx_cleanup(dev, phy2->q_tx[i], true);
+- if (phy3)
+- mt76_queue_tx_cleanup(dev, phy3->q_tx[i], true);
++ phy2 = mt7996_phy2(dev);
++ phy3 = mt7996_phy3(dev);
++
++ if (dev->hif2) {
++ mt76_wr(dev, MT_INT1_MASK_CSR, 0x0);
++ mt76_wr(dev, MT_INT1_SOURCE_CSR, ~0);
+ }
+
+- for (i = 0; i < __MT_MCUQ_MAX; i++)
+- mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[i], true);
++ if (dev_is_pci(mdev->dev)) {
++ mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0x0);
++ if (dev->hif2)
++ mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0x0);
++ }
+
+- mt76_for_each_q_rx(&dev->mt76, i)
+- mt76_queue_rx_reset(dev, i);
++ set_bit(MT76_RESET, &dev->mphy.state);
++ set_bit(MT76_MCU_RESET, &dev->mphy.state);
++ wake_up(&dev->mt76.mcu.wait);
++ if (phy2) {
++ set_bit(MT76_RESET, &phy2->mt76->state);
++ set_bit(MT76_MCU_RESET, &phy2->mt76->state);
++ }
++ if (phy3) {
++ set_bit(MT76_RESET, &phy3->mt76->state);
++ set_bit(MT76_MCU_RESET, &phy3->mt76->state);
++ }
+
+- mt76_tx_status_check(&dev->mt76, true);
++ /* lock/unlock all queues to ensure that no tx is pending */
++ mt76_txq_schedule_all(&dev->mphy);
++ if (phy2)
++ mt76_txq_schedule_all(phy2->mt76);
++ if (phy3)
++ mt76_txq_schedule_all(phy3->mt76);
++
++ /* disable all tx/rx napi */
++ mt76_worker_disable(&dev->mt76.tx_worker);
++ mt76_for_each_q_rx(mdev, i) {
++ if (mdev->q_rx[i].ndesc)
++ napi_disable(&dev->mt76.napi[i]);
++ }
++ napi_disable(&dev->mt76.tx_napi);
+
+- /* re-init prefetch settings after reset */
+- mt7996_dma_prefetch(dev);
++ /* token reinit */
++ mt7996_tx_token_put(dev);
++ idr_init(&dev->mt76.token);
+
+- mt76_set(dev, MT_WFDMA0_GLO_CFG,
+- MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN);
++ mt7996_dma_reset(dev, true);
+
+- if (dev->hif2)
+- mt76_set(dev, MT_WFDMA0_GLO_CFG + hif1_ofs,
+- MT_WFDMA0_GLO_CFG_TX_DMA_EN |
+- MT_WFDMA0_GLO_CFG_RX_DMA_EN);
++ local_bh_disable();
++ mt76_for_each_q_rx(mdev, i) {
++ if (mdev->q_rx[i].ndesc) {
++ napi_enable(&dev->mt76.napi[i]);
++ napi_schedule(&dev->mt76.napi[i]);
++ }
++ }
++ local_bh_enable();
++ clear_bit(MT76_MCU_RESET, &dev->mphy.state);
++ clear_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);
++
++ mt76_wr(dev, MT_INT_MASK_CSR, dev->mt76.mmio.irqmask);
++ mt76_wr(dev, MT_INT_SOURCE_CSR, ~0);
++ if (dev->hif2) {
++ mt76_wr(dev, MT_INT1_MASK_CSR, dev->mt76.mmio.irqmask);
++ mt76_wr(dev, MT_INT1_SOURCE_CSR, ~0);
++ }
++ if (dev_is_pci(mdev->dev)) {
++ mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
++ if (dev->hif2)
++ mt76_wr(dev, MT_PCIE1_MAC_INT_ENABLE, 0xff);
++ }
++
++ /* load firmware */
++ ret = mt7996_mcu_init_firmware(dev);
++ if (ret)
++ goto out;
++
++ /* set the necessary init items */
++ ret = mt7996_mcu_set_eeprom(dev);
++ if (ret)
++ goto out;
++
++ mt7996_mac_init(dev);
++ mt7996_init_txpower(dev, &dev->mphy.sband_2g.sband);
++ mt7996_init_txpower(dev, &dev->mphy.sband_5g.sband);
++ mt7996_init_txpower(dev, &dev->mphy.sband_6g.sband);
++ ret = mt7996_txbf_init(dev);
++
++ if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state)) {
++ ret = mt7996_run(dev->mphy.hw);
++ if (ret)
++ goto out;
++ }
++
++ if (phy2 && test_bit(MT76_STATE_RUNNING, &phy2->mt76->state)) {
++ ret = mt7996_run(phy2->mt76->hw);
++ if (ret)
++ goto out;
++ }
++
++ if (phy3 && test_bit(MT76_STATE_RUNNING, &phy3->mt76->state)) {
++ ret = mt7996_run(phy3->mt76->hw);
++ if (ret)
++ goto out;
++ }
++
++out:
++ /* reset done */
++ clear_bit(MT76_RESET, &dev->mphy.state);
++ if (phy2)
++ clear_bit(MT76_RESET, &phy2->mt76->state);
++ if (phy3)
++ clear_bit(MT76_RESET, &phy3->mt76->state);
++
++ local_bh_disable();
++ napi_enable(&dev->mt76.tx_napi);
++ napi_schedule(&dev->mt76.tx_napi);
++ local_bh_enable();
++
++ mt76_worker_enable(&dev->mt76.tx_worker);
++ return ret;
+ }
+
+-void mt7996_tx_token_put(struct mt7996_dev *dev)
++static void
++mt7996_mac_full_reset(struct mt7996_dev *dev)
+ {
+- struct mt76_txwi_cache *txwi;
+- int id;
++ struct mt7996_phy *phy2, *phy3;
++ int i;
+
+- spin_lock_bh(&dev->mt76.token_lock);
+- idr_for_each_entry(&dev->mt76.token, txwi, id) {
+- mt7996_txwi_free(dev, txwi, NULL, NULL);
+- dev->mt76.token_count--;
++ phy2 = mt7996_phy2(dev);
++ phy3 = mt7996_phy3(dev);
++ dev->recovery.hw_full_reset = true;
++
++ wake_up(&dev->mt76.mcu.wait);
++ ieee80211_stop_queues(mt76_hw(dev));
++ if (phy2)
++ ieee80211_stop_queues(phy2->mt76->hw);
++ if (phy3)
++ ieee80211_stop_queues(phy3->mt76->hw);
++
++ cancel_delayed_work_sync(&dev->mphy.mac_work);
++ if (phy2)
++ cancel_delayed_work_sync(&phy2->mt76->mac_work);
++ if (phy3)
++ cancel_delayed_work_sync(&phy3->mt76->mac_work);
++
++ mutex_lock(&dev->mt76.mutex);
++ for (i = 0; i < 10; i++) {
++ if (!mt7996_mac_restart(dev))
++ break;
+ }
+- spin_unlock_bh(&dev->mt76.token_lock);
+- idr_destroy(&dev->mt76.token);
++ mutex_unlock(&dev->mt76.mutex);
++
++ if (i == 10)
++ dev_err(dev->mt76.dev, "chip full reset failed\n");
++
++ ieee80211_restart_hw(mt76_hw(dev));
++ if (phy2)
++ ieee80211_restart_hw(phy2->mt76->hw);
++ if (phy3)
++ ieee80211_restart_hw(phy3->mt76->hw);
++
++ ieee80211_wake_queues(mt76_hw(dev));
++ if (phy2)
++ ieee80211_wake_queues(phy2->mt76->hw);
++ if (phy3)
++ ieee80211_wake_queues(phy3->mt76->hw);
++
++ dev->recovery.hw_full_reset = false;
++ ieee80211_queue_delayed_work(mt76_hw(dev),
++ &dev->mphy.mac_work,
++ MT7996_WATCHDOG_TIME);
++ if (phy2)
++ ieee80211_queue_delayed_work(phy2->mt76->hw,
++ &phy2->mt76->mac_work,
++ MT7996_WATCHDOG_TIME);
++ if (phy3)
++ ieee80211_queue_delayed_work(phy3->mt76->hw,
++ &phy3->mt76->mac_work,
++ MT7996_WATCHDOG_TIME);
+ }
+
+-/* system error recovery */
+ void mt7996_mac_reset_work(struct work_struct *work)
+ {
+ struct mt7996_phy *phy2, *phy3;
+@@ -1845,9 +1985,36 @@ void mt7996_mac_reset_work(struct work_struct *work)
+ phy2 = mt7996_phy2(dev);
+ phy3 = mt7996_phy3(dev);
+
+- if (!(READ_ONCE(dev->reset_state) & MT_MCU_CMD_STOP_DMA))
++ /* chip full reset */
++ if (dev->recovery.restart) {
++ /* disable WA/WM WDT */
++ mt76_clear(dev, MT_WFDMA0_MCU_HOST_INT_ENA,
++ MT_MCU_CMD_WDT_MASK);
++
++ if (READ_ONCE(dev->recovery.state) & MT_MCU_CMD_WA_WDT)
++ dev->recovery.wa_reset_count++;
++ else
++ dev->recovery.wm_reset_count++;
++
++ mt7996_mac_full_reset(dev);
++
++ /* enable mcu irq */
++ mt7996_irq_enable(dev, MT_INT_MCU_CMD);
++ mt7996_irq_disable(dev, 0);
++
++ /* enable WA/WM WDT */
++ mt76_set(dev, MT_WFDMA0_MCU_HOST_INT_ENA, MT_MCU_CMD_WDT_MASK);
++
++ dev->recovery.state = MT_MCU_CMD_NORMAL_STATE;
++ dev->recovery.restart = false;
+ return;
++ }
+
++ if (!(READ_ONCE(dev->recovery.state) & MT_MCU_CMD_STOP_DMA))
++ return;
++
++ dev_info(dev->mt76.dev,"\n%s L1 SER recovery start.",
++ wiphy_name(dev->mt76.hw->wiphy));
+ ieee80211_stop_queues(mt76_hw(dev));
+ if (phy2)
+ ieee80211_stop_queues(phy2->mt76->hw);
+@@ -1876,7 +2043,7 @@ void mt7996_mac_reset_work(struct work_struct *work)
+ mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_STOPPED);
+
+ if (mt7996_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) {
+- mt7996_dma_reset(dev);
++ mt7996_dma_reset(dev, false);
+
+ mt7996_tx_token_put(dev);
+ idr_init(&dev->mt76.token);
+@@ -1931,6 +2098,32 @@ void mt7996_mac_reset_work(struct work_struct *work)
+ ieee80211_queue_delayed_work(phy3->mt76->hw,
+ &phy3->mt76->mac_work,
+ MT7996_WATCHDOG_TIME);
++ dev_info(dev->mt76.dev,"\n%s L1 SER recovery completed.",
++ wiphy_name(dev->mt76.hw->wiphy));
++}
++
++void mt7996_reset(struct mt7996_dev *dev)
++{
++ if (!dev->recovery.hw_init_done)
++ return;
++
++ if (dev->recovery.hw_full_reset)
++ return;
++
++ /* wm/wa exception: do full recovery */
++ if (READ_ONCE(dev->recovery.state) & MT_MCU_CMD_WDT_MASK) {
++ dev->recovery.restart = true;
++ dev_info(dev->mt76.dev,
++ "%s indicated firmware crash, attempting recovery\n",
++ wiphy_name(dev->mt76.hw->wiphy));
++
++ mt7996_irq_disable(dev, MT_INT_MCU_CMD);
++ queue_work(dev->mt76.wq, &dev->reset_work);
++ return;
++ }
++
++ queue_work(dev->mt76.wq, &dev->reset_work);
++ wake_up(&dev->reset_wait);
+ }
+
+ void mt7996_mac_update_stats(struct mt7996_phy *phy)
+diff --git a/mt7996/main.c b/mt7996/main.c
+index d8d578c0..cb0e0d31 100644
+--- a/mt7996/main.c
++++ b/mt7996/main.c
+@@ -22,17 +22,13 @@ static bool mt7996_dev_running(struct mt7996_dev *dev)
+ return phy && test_bit(MT76_STATE_RUNNING, &phy->mt76->state);
+ }
+
+-static int mt7996_start(struct ieee80211_hw *hw)
++int mt7996_run(struct ieee80211_hw *hw)
+ {
+ struct mt7996_dev *dev = mt7996_hw_dev(hw);
+ struct mt7996_phy *phy = mt7996_hw_phy(hw);
+ bool running;
+ int ret;
+
+- flush_work(&dev->init_work);
+-
+- mutex_lock(&dev->mt76.mutex);
+-
+ running = mt7996_dev_running(dev);
+ if (!running) {
+ ret = mt7996_mcu_set_hdr_trans(dev, true);
+@@ -71,6 +67,18 @@ static int mt7996_start(struct ieee80211_hw *hw)
+ mt7996_mac_reset_counters(phy);
+
+ out:
++ return ret;
++}
++
++static int mt7996_start(struct ieee80211_hw *hw)
++{
++ struct mt7996_dev *dev = mt7996_hw_dev(hw);
++ int ret;
++
++ flush_work(&dev->init_work);
++
++ mutex_lock(&dev->mt76.mutex);
++ ret = mt7996_run(hw);
+ mutex_unlock(&dev->mt76.mutex);
+
+ return ret;
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 0dbe2e01..a949ff76 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -2629,17 +2629,10 @@ mt7996_mcu_init_rx_airtime(struct mt7996_dev *dev)
+ MCU_WM_UNI_CMD(VOW), true);
+ }
+
+-int mt7996_mcu_init(struct mt7996_dev *dev)
++int mt7996_mcu_init_firmware(struct mt7996_dev *dev)
+ {
+- static const struct mt76_mcu_ops mt7996_mcu_ops = {
+- .headroom = sizeof(struct mt76_connac2_mcu_txd), /* reuse */
+- .mcu_skb_send_msg = mt7996_mcu_send_message,
+- .mcu_parse_response = mt7996_mcu_parse_response,
+- };
+ int ret;
+
+- dev->mt76.mcu_ops = &mt7996_mcu_ops;
+-
+ /* force firmware operation mode into normal state,
+ * which should be set before firmware download stage.
+ */
+@@ -2680,6 +2673,19 @@ int mt7996_mcu_init(struct mt7996_dev *dev)
+ MCU_WA_PARAM_RED, 0, 0);
+ }
+
++int mt7996_mcu_init(struct mt7996_dev *dev)
++{
++ static const struct mt76_mcu_ops mt7996_mcu_ops = {
++ .headroom = sizeof(struct mt76_connac2_mcu_txd), /* reuse */
++ .mcu_skb_send_msg = mt7996_mcu_send_message,
++ .mcu_parse_response = mt7996_mcu_parse_response,
++ };
++
++ dev->mt76.mcu_ops = &mt7996_mcu_ops;
++
++ return mt7996_mcu_init_firmware(dev);
++}
++
+ void mt7996_mcu_exit(struct mt7996_dev *dev)
+ {
+ mt7996_mcu_restart(&dev->mt76);
+diff --git a/mt7996/mcu.h b/mt7996/mcu.h
+index ad66a1f8..778deedf 100644
+--- a/mt7996/mcu.h
++++ b/mt7996/mcu.h
+@@ -692,23 +692,21 @@ enum {
+ };
+
+ enum {
+- UNI_CMD_SER_QUERY = 0x0,
+- UNI_CMD_SER_SET = 0x2,
+- UNI_CMD_SER_TRIGGER = 0x3,
+-};
+-
+-enum {
+- SER_QUERY,
++ UNI_CMD_SER_QUERY,
+ /* recovery */
+- SER_SET_RECOVER_L1,
+- SER_SET_RECOVER_L2,
+- SER_SET_RECOVER_L3_RX_ABORT,
+- SER_SET_RECOVER_L3_TX_ABORT,
+- SER_SET_RECOVER_L3_TX_DISABLE,
+- SER_SET_RECOVER_L3_BF,
++ UNI_CMD_SER_SET_RECOVER_L1,
++ UNI_CMD_SER_SET_RECOVER_L2,
++ UNI_CMD_SER_SET_RECOVER_L3_RX_ABORT,
++ UNI_CMD_SER_SET_RECOVER_L3_TX_ABORT,
++ UNI_CMD_SER_SET_RECOVER_L3_TX_DISABLE,
++ UNI_CMD_SER_SET_RECOVER_L3_BF,
++ UNI_CMD_SER_SET_RECOVER_L4_MDP,
++ UNI_CMD_SER_SET_RECOVER_FULL,
++ UNI_CMD_SER_SET_SYSTEM_ASSERT,
+ /* action */
+- SER_ENABLE = 2,
+- SER_RECOVER
++ UNI_CMD_SER_ENABLE = 1,
++ UNI_CMD_SER_SET,
++ UNI_CMD_SER_TRIGGER
+ };
+
+ enum {
+diff --git a/mt7996/mmio.c b/mt7996/mmio.c
+index 6610cc45..0e11f398 100644
+--- a/mt7996/mmio.c
++++ b/mt7996/mmio.c
+@@ -289,10 +289,9 @@ static void mt7996_irq_tasklet(struct tasklet_struct *t)
+ u32 val = mt76_rr(dev, MT_MCU_CMD);
+
+ mt76_wr(dev, MT_MCU_CMD, val);
+- if (val & MT_MCU_CMD_ERROR_MASK) {
+- dev->reset_state = val;
+- ieee80211_queue_work(mt76_hw(dev), &dev->reset_work);
+- wake_up(&dev->reset_wait);
++ if (val & (MT_MCU_CMD_ERROR_MASK | MT_MCU_CMD_WDT_MASK)) {
++ dev->recovery.state = val;
++ mt7996_reset(dev);
+ }
+ }
+ }
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index 25b20fa6..923e6fc9 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -268,7 +268,14 @@ struct mt7996_dev {
+ struct work_struct rc_work;
+ struct work_struct reset_work;
+ wait_queue_head_t reset_wait;
+- u32 reset_state;
++ struct {
++ u32 state;
++ u32 wa_reset_count;
++ u32 wm_reset_count;
++ bool hw_full_reset:1;
++ bool hw_init_done:1;
++ bool restart:1;
++ } recovery;
+
+ struct list_head sta_rc_list;
+ struct list_head sta_poll_list;
+@@ -401,9 +408,16 @@ int mt7996_eeprom_get_target_power(struct mt7996_dev *dev,
+ struct ieee80211_channel *chan);
+ s8 mt7996_eeprom_get_power_delta(struct mt7996_dev *dev, int band);
+ int mt7996_dma_init(struct mt7996_dev *dev);
++void mt7996_dma_reset(struct mt7996_dev *dev, bool force);
+ void mt7996_dma_prefetch(struct mt7996_dev *dev);
+ void mt7996_dma_cleanup(struct mt7996_dev *dev);
++void mt7996_init_txpower(struct mt7996_dev *dev,
++ struct ieee80211_supported_band *sband);
++int mt7996_txbf_init(struct mt7996_dev *dev);
++void mt7996_reset(struct mt7996_dev *dev);
++int mt7996_run(struct ieee80211_hw *hw);
+ int mt7996_mcu_init(struct mt7996_dev *dev);
++int mt7996_mcu_init_firmware(struct mt7996_dev *dev);
+ int mt7996_mcu_twt_agrt_update(struct mt7996_dev *dev,
+ struct mt7996_vif *mvif,
+ struct mt7996_twt_flow *flow,
+@@ -496,6 +510,7 @@ static inline void mt7996_irq_disable(struct mt7996_dev *dev, u32 mask)
+ mt76_set_irq_mask(&dev->mt76, MT_INT_MASK_CSR, mask, 0);
+ }
+
++void mt7996_mac_init(struct mt7996_dev *dev);
+ u32 mt7996_mac_wtbl_lmac_addr(struct mt7996_dev *dev, u16 wcid, u8 dw);
+ bool mt7996_mac_wtbl_update(struct mt7996_dev *dev, int idx, u32 mask);
+ void mt7996_mac_reset_counters(struct mt7996_phy *phy);
+diff --git a/mt7996/regs.h b/mt7996/regs.h
+index 7a28cae3..0775ca58 100644
+--- a/mt7996/regs.h
++++ b/mt7996/regs.h
+@@ -317,6 +317,8 @@ enum base_rev {
+ #define MT_WFDMA0_RX_INT_PCIE_SEL MT_WFDMA0(0x154)
+ #define MT_WFDMA0_RX_INT_SEL_RING3 BIT(3)
+
++#define MT_WFDMA0_MCU_HOST_INT_ENA MT_WFDMA0(0x1f4)
++
+ #define MT_WFDMA0_GLO_CFG MT_WFDMA0(0x208)
+ #define MT_WFDMA0_GLO_CFG_TX_DMA_EN BIT(0)
+ #define MT_WFDMA0_GLO_CFG_RX_DMA_EN BIT(2)
+@@ -444,6 +446,10 @@ enum base_rev {
+ #define MT_MCU_CMD_NORMAL_STATE BIT(5)
+ #define MT_MCU_CMD_ERROR_MASK GENMASK(5, 1)
+
++#define MT_MCU_CMD_WA_WDT BIT(31)
++#define MT_MCU_CMD_WM_WDT BIT(30)
++#define MT_MCU_CMD_WDT_MASK GENMASK(31, 30)
++
+ /* l1/l2 remap */
+ #define MT_HIF_REMAP_L1 0x155024
+ #define MT_HIF_REMAP_L1_MASK GENMASK(31, 16)
+@@ -468,8 +474,27 @@ enum base_rev {
+ #define MT_INFRA_MCU_END 0x7c3fffff
+
+ /* FW MODE SYNC */
+-#define MT_SWDEF_MODE 0x9143c
++#define MT_SWDEF_BASE 0x00401400
++
++#define MT_SWDEF(ofs) (MT_SWDEF_BASE + (ofs))
++#define MT_SWDEF_MODE MT_SWDEF(0x3c)
+ #define MT_SWDEF_NORMAL_MODE 0
++#define MT_SWDEF_ICAP_MODE 1
++#define MT_SWDEF_SPECTRUM_MODE 2
++
++#define MT_SWDEF_SER_STATS MT_SWDEF(0x040)
++#define MT_SWDEF_PLE_STATS MT_SWDEF(0x044)
++#define MT_SWDEF_PLE1_STATS MT_SWDEF(0x048)
++#define MT_SWDEF_PLE_AMSDU_STATS MT_SWDEF(0x04C)
++#define MT_SWDEF_PSE_STATS MT_SWDEF(0x050)
++#define MT_SWDEF_PSE1_STATS MT_SWDEF(0x054)
++#define MT_SWDEF_LAMC_WISR6_BN0_STATS MT_SWDEF(0x058)
++#define MT_SWDEF_LAMC_WISR6_BN1_STATS MT_SWDEF(0x05C)
++#define MT_SWDEF_LAMC_WISR6_BN2_STATS MT_SWDEF(0x060)
++#define MT_SWDEF_LAMC_WISR7_BN0_STATS MT_SWDEF(0x064)
++#define MT_SWDEF_LAMC_WISR7_BN1_STATS MT_SWDEF(0x068)
++#define MT_SWDEF_LAMC_WISR7_BN2_STATS MT_SWDEF(0x06C)
++#define WF_SWDEF_WFDMA_STATUS_ADDR MT_SWDEF(0x090)
+
+ /* LED */
+ #define MT_LED_TOP_BASE 0x18013000
+@@ -506,7 +531,7 @@ enum base_rev {
+ #define MT_TOP_MISC_FW_STATE GENMASK(2, 0)
+
+ #define MT_HW_REV 0x70010204
+-#define MT_WF_SUBSYS_RST 0x70002600
++#define MT_WF_SUBSYS_RST 0x70028600
+
+ /* PCIE MAC */
+ #define MT_PCIE_MAC_BASE 0x74030000
+@@ -539,4 +564,11 @@ enum base_rev {
+ #define MT_WF_PHYRX_CSD_BAND_RXTD12_IRPI_SW_CLR_ONLY BIT(18)
+ #define MT_WF_PHYRX_CSD_BAND_RXTD12_IRPI_SW_CLR BIT(29)
+
++#define MT_MCU_WM_CIRQ_BASE 0x89010000
++#define MT_MCU_WM_CIRQ(ofs) (MT_MCU_WM_CIRQ_BASE + (ofs))
++#define MT_MCU_WM_CIRQ_IRQ_MASK_CLR_ADDR MT_MCU_WM_CIRQ(0x80)
++#define MT_MCU_WM_CIRQ_IRQ_SOFT_ADDR MT_MCU_WM_CIRQ(0xc0)
++#define MT_MCU_WM_CIRQ_EINT_MASK_CLR_ADDR MT_MCU_WM_CIRQ(0x108)
++#define MT_MCU_WM_CIRQ_EINT_SOFT_ADDR MT_MCU_WM_CIRQ(0x118)
++
+ #endif
+--
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0014-wifi-mt76-mt7996-add-dsp-firmware-download.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0014-wifi-mt76-mt7996-add-dsp-firmware-download.patch
new file mode 100644
index 0000000..8193a5a
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0014-wifi-mt76-mt7996-add-dsp-firmware-download.patch
@@ -0,0 +1,194 @@
+From 2d6ca0f6974ad4f6dcf110ccbbcbbc7185aa7655 Mon Sep 17 00:00:00 2001
+From: Peter Chiu <chui-hao.chiu@mediatek.com>
+Date: Fri, 17 Feb 2023 14:13:38 +0800
+Subject: [PATCH 14/19] wifi: mt76: mt7996: add dsp firmware download
+
+Add DSP firmware for phy related control. Without this patch,the
+firmware state would not be ready.
+
+Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
+---
+ mt76_connac_mcu.h | 1 +
+ mt7996/mcu.c | 94 +++++++++++++++++++++--------------------------
+ mt7996/mt7996.h | 7 ++++
+ mt7996/pci.c | 1 +
+ 4 files changed, 50 insertions(+), 53 deletions(-)
+
+diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
+index fa10d823..79dde31a 100644
+--- a/mt76_connac_mcu.h
++++ b/mt76_connac_mcu.h
+@@ -22,6 +22,7 @@
+
+ #define FW_START_OVERRIDE BIT(0)
+ #define FW_START_WORKING_PDA_CR4 BIT(2)
++#define FW_START_WORKING_PDA_DSP BIT(3)
+
+ #define PATCH_SEC_NOT_SUPPORT GENMASK(31, 0)
+ #define PATCH_SEC_TYPE_MASK GENMASK(15, 0)
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index a949ff76..09800ff2 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -2353,7 +2353,7 @@ out:
+ static int
+ mt7996_mcu_send_ram_firmware(struct mt7996_dev *dev,
+ const struct mt7996_fw_trailer *hdr,
+- const u8 *data, bool is_wa)
++ const u8 *data, enum mt7996_ram_type type)
+ {
+ int i, offset = 0;
+ u32 override = 0, option = 0;
+@@ -2365,8 +2365,10 @@ mt7996_mcu_send_ram_firmware(struct mt7996_dev *dev,
+
+ region = (const struct mt7996_fw_region *)((const u8 *)hdr -
+ (hdr->n_region - i) * sizeof(*region));
++ /* DSP and WA use same mode */
+ mode = mt76_connac_mcu_gen_dl_mode(&dev->mt76,
+- region->feature_set, is_wa);
++ region->feature_set,
++ type != MT7996_RAM_TYPE_WM);
+ len = le32_to_cpu(region->len);
+ addr = le32_to_cpu(region->addr);
+
+@@ -2393,8 +2395,10 @@ mt7996_mcu_send_ram_firmware(struct mt7996_dev *dev,
+ if (override)
+ option |= FW_START_OVERRIDE;
+
+- if (is_wa)
++ if (type == MT7996_RAM_TYPE_WA)
+ option |= FW_START_WORKING_PDA_CR4;
++ else if (type == MT7996_RAM_TYPE_DSP)
++ option |= FW_START_WORKING_PDA_DSP;
+
+ return mt76_connac_mcu_start_firmware(&dev->mt76, override, option);
+ }
+@@ -2405,56 +2409,40 @@ static int mt7996_load_ram(struct mt7996_dev *dev)
+ const struct firmware *fw;
+ int ret;
+
+- ret = request_firmware(&fw, MT7996_FIRMWARE_WM, dev->mt76.dev);
+- if (ret)
+- return ret;
+-
+- if (!fw || !fw->data || fw->size < sizeof(*hdr)) {
+- dev_err(dev->mt76.dev, "Invalid firmware\n");
+- ret = -EINVAL;
+- goto out;
+- }
+-
+- hdr = (const struct mt7996_fw_trailer *)(fw->data + fw->size - sizeof(*hdr));
+-
+- dev_info(dev->mt76.dev, "WM Firmware Version: %.10s, Build Time: %.15s\n",
+- hdr->fw_ver, hdr->build_date);
+-
+- ret = mt7996_mcu_send_ram_firmware(dev, hdr, fw->data, false);
+- if (ret) {
+- dev_err(dev->mt76.dev, "Failed to start WM firmware\n");
+- goto out;
+- }
+-
+- release_firmware(fw);
+-
+- ret = request_firmware(&fw, MT7996_FIRMWARE_WA, dev->mt76.dev);
+- if (ret)
+- return ret;
+-
+- if (!fw || !fw->data || fw->size < sizeof(*hdr)) {
+- dev_err(dev->mt76.dev, "Invalid firmware\n");
+- ret = -EINVAL;
+- goto out;
+- }
+-
+- hdr = (const struct mt7996_fw_trailer *)(fw->data + fw->size - sizeof(*hdr));
+-
+- dev_info(dev->mt76.dev, "WA Firmware Version: %.10s, Build Time: %.15s\n",
+- hdr->fw_ver, hdr->build_date);
+-
+- ret = mt7996_mcu_send_ram_firmware(dev, hdr, fw->data, true);
+- if (ret) {
+- dev_err(dev->mt76.dev, "Failed to start WA firmware\n");
+- goto out;
+- }
+-
+- snprintf(dev->mt76.hw->wiphy->fw_version,
+- sizeof(dev->mt76.hw->wiphy->fw_version),
+- "%.10s-%.15s", hdr->fw_ver, hdr->build_date);
+-
+-out:
+- release_firmware(fw);
++#define LOAD_RAM(_type) \
++ do { \
++ ret = request_firmware(&fw, MT7996_FIRMWARE_##_type, dev->mt76.dev); \
++ if (ret) \
++ return ret; \
++ \
++ if (!fw || !fw->data || fw->size < sizeof(*hdr)) { \
++ dev_err(dev->mt76.dev, "Invalid firmware\n"); \
++ release_firmware(fw); \
++ return -EINVAL; \
++ } \
++ \
++ hdr = (const struct mt7996_fw_trailer *) \
++ (fw->data + fw->size - sizeof(*hdr)); \
++ \
++ dev_info(dev->mt76.dev, \
++ "%s Firmware Version: %.10s, Build Time: %.15s\n", \
++ #_type, hdr->fw_ver, hdr->build_date); \
++ \
++ ret = mt7996_mcu_send_ram_firmware(dev, hdr, fw->data, \
++ MT7996_RAM_TYPE_##_type); \
++ if (ret) { \
++ dev_err(dev->mt76.dev, "Failed to start %s firmware\n", #_type);\
++ release_firmware(fw); \
++ return ret; \
++ } \
++ \
++ release_firmware(fw); \
++ } while (0)
++
++ LOAD_RAM(WM);
++ LOAD_RAM(DSP);
++ LOAD_RAM(WA);
++#undef LOAD_RAM
+
+ return ret;
+ }
+diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
+index 923e6fc9..c2f8900c 100644
+--- a/mt7996/mt7996.h
++++ b/mt7996/mt7996.h
+@@ -29,6 +29,7 @@
+
+ #define MT7996_FIRMWARE_WA "mediatek/mt7996/mt7996_wa.bin"
+ #define MT7996_FIRMWARE_WM "mediatek/mt7996/mt7996_wm.bin"
++#define MT7996_FIRMWARE_DSP "mediatek/mt7996/mt7996_dsp.bin"
+ #define MT7996_ROM_PATCH "mediatek/mt7996/mt7996_rom_patch.bin"
+
+ #define MT7996_EEPROM_DEFAULT "mediatek/mt7996/mt7996_eeprom.bin"
+@@ -55,6 +56,12 @@ struct mt7996_sta;
+ struct mt7996_dfs_pulse;
+ struct mt7996_dfs_pattern;
+
++enum mt7996_ram_type {
++ MT7996_RAM_TYPE_WM = 0,
++ MT7996_RAM_TYPE_WA,
++ MT7996_RAM_TYPE_DSP,
++};
++
+ enum mt7996_txq_id {
+ MT7996_TXQ_FWDL = 16,
+ MT7996_TXQ_MCU_WM,
+diff --git a/mt7996/pci.c b/mt7996/pci.c
+index 64aee3fb..c5301050 100644
+--- a/mt7996/pci.c
++++ b/mt7996/pci.c
+@@ -219,4 +219,5 @@ MODULE_DEVICE_TABLE(pci, mt7996_pci_device_table);
+ MODULE_DEVICE_TABLE(pci, mt7996_hif_device_table);
+ MODULE_FIRMWARE(MT7996_FIRMWARE_WA);
+ MODULE_FIRMWARE(MT7996_FIRMWARE_WM);
++MODULE_FIRMWARE(MT7996_FIRMWARE_DSP);
+ MODULE_FIRMWARE(MT7996_ROM_PATCH);
+--
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0015-wifi-mt76-mt7996-fix-eeprom-antenna-bitfield-mask.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0015-wifi-mt76-mt7996-fix-eeprom-antenna-bitfield-mask.patch
new file mode 100644
index 0000000..236cada
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0015-wifi-mt76-mt7996-fix-eeprom-antenna-bitfield-mask.patch
@@ -0,0 +1,33 @@
+From 763303e5fb846c92c22dd19ffec95d844103e425 Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Thu, 23 Feb 2023 19:18:45 +0800
+Subject: [PATCH 15/19] wifi: mt76: mt7996: fix eeprom antenna bitfield mask
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ mt7996/eeprom.h | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/mt7996/eeprom.h b/mt7996/eeprom.h
+index 8da599e0..cfc48698 100644
+--- a/mt7996/eeprom.h
++++ b/mt7996/eeprom.h
+@@ -31,11 +31,11 @@ enum mt7996_eeprom_field {
+ #define MT_EE_WIFI_CONF2_BAND_SEL GENMASK(2, 0)
+
+ #define MT_EE_WIFI_CONF1_TX_PATH_BAND0 GENMASK(5, 3)
+-#define MT_EE_WIFI_CONF2_TX_PATH_BAND1 GENMASK(5, 3)
+-#define MT_EE_WIFI_CONF2_TX_PATH_BAND2 GENMASK(2, 0)
++#define MT_EE_WIFI_CONF2_TX_PATH_BAND1 GENMASK(2, 0)
++#define MT_EE_WIFI_CONF2_TX_PATH_BAND2 GENMASK(5, 3)
+ #define MT_EE_WIFI_CONF4_STREAM_NUM_BAND0 GENMASK(5, 3)
+-#define MT_EE_WIFI_CONF5_STREAM_NUM_BAND1 GENMASK(5, 3)
+-#define MT_EE_WIFI_CONF5_STREAM_NUM_BAND2 GENMASK(2, 0)
++#define MT_EE_WIFI_CONF5_STREAM_NUM_BAND1 GENMASK(2, 0)
++#define MT_EE_WIFI_CONF5_STREAM_NUM_BAND2 GENMASK(5, 3)
+
+ #define MT_EE_RATE_DELTA_MASK GENMASK(5, 0)
+ #define MT_EE_RATE_DELTA_SIGN BIT(6)
+--
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0016-wifi-mt76-mt7996-init-mpdu-density.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0016-wifi-mt76-mt7996-init-mpdu-density.patch
new file mode 100644
index 0000000..74992ab
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0016-wifi-mt76-mt7996-init-mpdu-density.patch
@@ -0,0 +1,53 @@
+From 322307272a4c4ccb627d6596220b0ab5bd4aed45 Mon Sep 17 00:00:00 2001
+From: Peter Chiu <chui-hao.chiu@mediatek.com>
+Date: Mon, 13 Feb 2023 09:46:40 +0800
+Subject: [PATCH 16/19] wifi: mt76: mt7996: init mpdu density
+
+Init mpdu density based on the hardware capability to
+prevent hardware drop.
+
+Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
+---
+ mt7996/init.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/mt7996/init.c b/mt7996/init.c
+index ced38ac8..479b2cee 100644
+--- a/mt7996/init.c
++++ b/mt7996/init.c
+@@ -374,10 +374,13 @@ mt7996_init_wiphy(struct ieee80211_hw *hw)
+
+ hw->max_tx_fragments = 4;
+
+- if (phy->mt76->cap.has_2ghz)
++ if (phy->mt76->cap.has_2ghz) {
+ phy->mt76->sband_2g.sband.ht_cap.cap |=
+ IEEE80211_HT_CAP_LDPC_CODING |
+ IEEE80211_HT_CAP_MAX_AMSDU;
++ phy->mt76->sband_2g.sband.ht_cap.ampdu_density =
++ IEEE80211_HT_MPDU_DENSITY_2;
++ }
+
+ if (phy->mt76->cap.has_5ghz) {
+ phy->mt76->sband_5g.sband.ht_cap.cap |=
+@@ -389,6 +392,8 @@ mt7996_init_wiphy(struct ieee80211_hw *hw)
+ IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK |
+ IEEE80211_VHT_CAP_SHORT_GI_160 |
+ IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
++ phy->mt76->sband_5g.sband.ht_cap.ampdu_density =
++ IEEE80211_HT_MPDU_DENSITY_1;
+ }
+
+ mt76_set_stream_caps(phy->mt76, true);
+@@ -873,7 +878,7 @@ mt7996_init_he_caps(struct mt7996_phy *phy, enum nl80211_band band,
+ u16 cap = IEEE80211_HE_6GHZ_CAP_TX_ANTPAT_CONS |
+ IEEE80211_HE_6GHZ_CAP_RX_ANTPAT_CONS;
+
+- cap |= u16_encode_bits(IEEE80211_HT_MPDU_DENSITY_2,
++ cap |= u16_encode_bits(IEEE80211_HT_MPDU_DENSITY_0_5,
+ IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START) |
+ u16_encode_bits(IEEE80211_VHT_MAX_AMPDU_1024K,
+ IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP) |
+--
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0017-wifi-mt76-mt7996-fix-icv-error-when-enable-AP-and-ST.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0017-wifi-mt76-mt7996-fix-icv-error-when-enable-AP-and-ST.patch
new file mode 100644
index 0000000..0b179f4
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0017-wifi-mt76-mt7996-fix-icv-error-when-enable-AP-and-ST.patch
@@ -0,0 +1,71 @@
+From b4af2c843368e7a787fc02ebde5a8ff41edf0a76 Mon Sep 17 00:00:00 2001
+From: Peter Chiu <chui-hao.chiu@mediatek.com>
+Date: Thu, 2 Mar 2023 15:44:52 +0800
+Subject: [PATCH 17/19] wifi: mt76: mt7996: fix icv error when enable AP and
+ STA simultaneously
+
+Fix mcu command content to prevent ICV error
+1. The legacy mld index needs to start from 16.
+2. The bmc_tx_wlan_idx needs to be the vif index rather
+than peer AP's index.
+
+Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
+---
+ mt7996/mcu.c | 12 +++++++++---
+ 1 file changed, 9 insertions(+), 3 deletions(-)
+
+diff --git a/mt7996/mcu.c b/mt7996/mcu.c
+index 09800ff2..829f7be6 100644
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -664,6 +664,7 @@ mt7996_mcu_bss_txcmd_tlv(struct sk_buff *skb, bool en)
+ static void
+ mt7996_mcu_bss_mld_tlv(struct sk_buff *skb, struct ieee80211_vif *vif)
+ {
++#define MT7996_LEGACY_MLD_IDX_START 16
+ struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv;
+ struct bss_mld_tlv *mld;
+ struct tlv *tlv;
+@@ -672,8 +673,12 @@ mt7996_mcu_bss_mld_tlv(struct sk_buff *skb, struct ieee80211_vif *vif)
+
+ mld = (struct bss_mld_tlv *)tlv;
+ mld->group_mld_id = 0xff;
+- mld->own_mld_id = mvif->mt76.idx;
++ mld->own_mld_id = MT7996_LEGACY_MLD_IDX_START + mvif->mt76.idx;
+ mld->remap_idx = 0xff;
++ if (vif->type == NL80211_IFTYPE_AP) {
++ mld->group_mld_id = MT7996_LEGACY_MLD_IDX_START + mvif->mt76.idx;
++ memcpy(mld->mac_addr, vif->bss_conf.bssid, ETH_ALEN);
++ }
+ }
+
+ static void
+@@ -744,6 +749,7 @@ mt7996_mcu_bss_basic_tlv(struct sk_buff *skb,
+ struct cfg80211_chan_def *chandef = &phy->chandef;
+ struct mt76_connac_bss_basic_tlv *bss;
+ u32 type = CONNECTION_INFRA_AP;
++ u16 sta_wlan_idx = wlan_idx;
+ struct tlv *tlv;
+ int idx;
+
+@@ -763,7 +769,7 @@ mt7996_mcu_bss_basic_tlv(struct sk_buff *skb,
+ struct mt76_wcid *wcid;
+
+ wcid = (struct mt76_wcid *)sta->drv_priv;
+- wlan_idx = wcid->idx;
++ sta_wlan_idx = wcid->idx;
+ }
+ rcu_read_unlock();
+ }
+@@ -783,7 +789,7 @@ mt7996_mcu_bss_basic_tlv(struct sk_buff *skb,
+ bss->bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int);
+ bss->dtim_period = vif->bss_conf.dtim_period;
+ bss->bmc_tx_wlan_idx = cpu_to_le16(wlan_idx);
+- bss->sta_idx = cpu_to_le16(wlan_idx);
++ bss->sta_idx = cpu_to_le16(sta_wlan_idx);
+ bss->conn_type = cpu_to_le32(type);
+ bss->omac_idx = mvif->omac_idx;
+ bss->band_idx = mvif->band_idx;
+--
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0018-wifi-mt76-mt7996-set-wcid-in-txp.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0018-wifi-mt76-mt7996-set-wcid-in-txp.patch
new file mode 100644
index 0000000..74f4e9e
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0018-wifi-mt76-mt7996-set-wcid-in-txp.patch
@@ -0,0 +1,35 @@
+From 68649746f1862d6c9b3e06492789aadde8c4d2e5 Mon Sep 17 00:00:00 2001
+From: Peter Chiu <chui-hao.chiu@mediatek.com>
+Date: Mon, 6 Mar 2023 15:52:26 +0800
+Subject: [PATCH 18/19] wifi: mt76: mt7996: set wcid in txp
+
+Set correct wcid in txp for SDO to get wtbl.
+
+Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
+---
+ mt7996/mac.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/mt7996/mac.c b/mt7996/mac.c
+index 4c0c8f1e..bb23f531 100644
+--- a/mt7996/mac.c
++++ b/mt7996/mac.c
+@@ -1168,10 +1168,12 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
+ }
+
+ txp->fw.token = cpu_to_le16(id);
+- if (test_bit(MT_WCID_FLAG_4ADDR, &wcid->flags))
+- txp->fw.rept_wds_wcid = cpu_to_le16(wcid->idx);
+- else
++ if ((is_8023 && is_multicast_ether_addr(tx_info->skb->data)) ||
++ is_multicast_ether_addr(hdr->addr1))
+ txp->fw.rept_wds_wcid = cpu_to_le16(0xfff);
++ else
++ txp->fw.rept_wds_wcid = cpu_to_le16(wcid->idx);
++
+ tx_info->skb = DMA_DUMMY_DATA;
+
+ /* pass partial skb header to fw */
+--
+2.39.2
+
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0007-mt76-revert-page-pool-changes.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0019-mt76-revert-page-pool-changes.patch
similarity index 92%
rename from recipes-wifi/linux-mt76/files/patches-3.x/0007-mt76-revert-page-pool-changes.patch
rename to recipes-wifi/linux-mt76/files/patches-3.x/0019-mt76-revert-page-pool-changes.patch
index ab1161f..20feead 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0007-mt76-revert-page-pool-changes.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0019-mt76-revert-page-pool-changes.patch
@@ -1,7 +1,7 @@
-From 60c4e64c0198c828fafd5e7b96027ad5fd633213 Mon Sep 17 00:00:00 2001
+From 175bf122ac5790e7e28dadecd9410370364bc16a Mon Sep 17 00:00:00 2001
From: Shayne Chen <shayne.chen@mediatek.com>
Date: Mon, 6 Feb 2023 15:34:43 +0800
-Subject: [PATCH 7/7] mt76: revert page pool changes
+Subject: [PATCH 19/19] mt76: revert page pool changes
---
dma.c | 72 ++++++++++++++++++++++++++-------------------------
@@ -10,11 +10,11 @@
mt7915/main.c | 26 +++++++------------
mt7915/mmio.c | 55 ++++++++++++++++++++++++---------------
mt7921/main.c | 31 +++-------------------
- usb.c | 42 ++++++++++++++++--------------
- 7 files changed, 108 insertions(+), 197 deletions(-)
+ usb.c | 43 +++++++++++++++---------------
+ 7 files changed, 108 insertions(+), 198 deletions(-)
diff --git a/dma.c b/dma.c
-index e3fa4f39..50a7a689 100644
+index df2ca73f..7357b398 100644
--- a/dma.c
+++ b/dma.c
@@ -173,7 +173,7 @@ mt76_free_pending_rxwi(struct mt76_dev *dev)
@@ -39,7 +39,7 @@
buf = t->ptr;
t->dma_addr = 0;
-@@ -428,9 +428,9 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
+@@ -430,9 +430,9 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
} else {
buf = e->buf;
e->buf = NULL;
@@ -52,7 +52,7 @@
}
return buf;
-@@ -582,11 +582,11 @@ free_skb:
+@@ -584,11 +584,11 @@ free_skb:
}
static int
@@ -67,7 +67,7 @@
if (!q->ndesc)
return 0;
-@@ -594,25 +594,26 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q,
+@@ -596,25 +596,26 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q,
spin_lock_bh(&q->lock);
while (q->queued < q->ndesc - 1) {
@@ -105,7 +105,7 @@
break;
}
frames++;
-@@ -656,7 +657,7 @@ int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset)
+@@ -658,7 +659,7 @@ int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset)
/* WED txfree queue needs ring to be initialized before setup */
q->flags = 0;
mt76_dma_queue_reset(dev, q);
@@ -114,7 +114,7 @@
q->flags = flags;
ret = mtk_wed_device_txfree_ring_setup(wed, q->regs);
-@@ -704,10 +705,6 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
+@@ -706,10 +707,6 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
if (!q->entry)
return -ENOMEM;
@@ -125,7 +125,7 @@
ret = mt76_dma_wed_setup(dev, q, false);
if (ret)
return ret;
-@@ -721,6 +718,7 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
+@@ -723,6 +720,7 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
static void
mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
{
@@ -133,7 +133,7 @@
void *buf;
bool more;
-@@ -734,7 +732,7 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
+@@ -736,7 +734,7 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
if (!buf)
break;
@@ -142,7 +142,7 @@
} while (1);
if (q->rx_head) {
-@@ -743,6 +741,13 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
+@@ -745,6 +743,13 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
}
spin_unlock_bh(&q->lock);
@@ -156,7 +156,7 @@
}
static void
-@@ -763,7 +768,7 @@ mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid)
+@@ -765,7 +770,7 @@ mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid)
mt76_dma_wed_setup(dev, q, true);
if (q->flags != MT_WED_Q_TXFREE) {
mt76_dma_sync_idx(dev, q);
@@ -165,7 +165,7 @@
}
}
-@@ -781,7 +786,7 @@ mt76_add_fragment(struct mt76_dev *dev, struct mt76_queue *q, void *data,
+@@ -783,7 +788,7 @@ mt76_add_fragment(struct mt76_dev *dev, struct mt76_queue *q, void *data,
skb_add_rx_frag(skb, nr_frags, page, offset, len, q->buf_size);
} else {
@@ -174,7 +174,7 @@
}
if (more)
-@@ -854,7 +859,6 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
+@@ -856,7 +861,6 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
goto free_frag;
skb_reserve(skb, q->buf_offset);
@@ -182,7 +182,7 @@
*(u32 *)skb->cb = info;
-@@ -870,10 +874,10 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
+@@ -872,10 +876,10 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
continue;
free_frag:
@@ -195,7 +195,7 @@
return done;
}
-@@ -918,7 +922,7 @@ mt76_dma_init(struct mt76_dev *dev,
+@@ -920,7 +924,7 @@ mt76_dma_init(struct mt76_dev *dev,
mt76_for_each_q_rx(dev, i) {
netif_napi_add(&dev->napi_dev, &dev->napi[i], poll);
@@ -204,7 +204,7 @@
napi_enable(&dev->napi[i]);
}
-@@ -969,8 +973,6 @@ void mt76_dma_cleanup(struct mt76_dev *dev)
+@@ -971,8 +975,6 @@ void mt76_dma_cleanup(struct mt76_dev *dev)
netif_napi_del(&dev->napi[i]);
mt76_dma_rx_cleanup(dev, q);
@@ -214,7 +214,7 @@
mt76_free_pending_txwi(dev);
diff --git a/mac80211.c b/mac80211.c
-index b117e446..8a5f21e8 100644
+index e53166fc..d69e7214 100644
--- a/mac80211.c
+++ b/mac80211.c
@@ -4,7 +4,6 @@
@@ -225,7 +225,7 @@
#include "mt76.h"
#define CHAN2G(_idx, _freq) { \
-@@ -557,47 +556,6 @@ void mt76_unregister_phy(struct mt76_phy *phy)
+@@ -562,47 +561,6 @@ void mt76_unregister_phy(struct mt76_phy *phy)
}
EXPORT_SYMBOL_GPL(mt76_unregister_phy);
@@ -273,7 +273,7 @@
struct mt76_dev *
mt76_alloc_device(struct device *pdev, unsigned int size,
const struct ieee80211_ops *ops,
-@@ -1732,21 +1690,6 @@ void mt76_ethtool_worker(struct mt76_ethtool_worker_info *wi,
+@@ -1746,21 +1704,6 @@ void mt76_ethtool_worker(struct mt76_ethtool_worker_info *wi,
}
EXPORT_SYMBOL_GPL(mt76_ethtool_worker);
@@ -296,7 +296,7 @@
{
struct ieee80211_hw *hw = phy->hw;
diff --git a/mt76.h b/mt76.h
-index ccca0162..f6a32fe3 100644
+index c3d1313e..49da2caa 100644
--- a/mt76.h
+++ b/mt76.h
@@ -202,7 +202,7 @@ struct mt76_queue {
@@ -308,7 +308,7 @@
};
struct mt76_mcu_ops {
-@@ -1318,7 +1318,6 @@ mt76u_bulk_msg(struct mt76_dev *dev, void *data, int len, int *actual_len,
+@@ -1329,7 +1329,6 @@ mt76u_bulk_msg(struct mt76_dev *dev, void *data, int len, int *actual_len,
return usb_bulk_msg(udev, pipe, data, len, actual_len, timeout);
}
@@ -316,7 +316,7 @@
void mt76_ethtool_worker(struct mt76_ethtool_worker_info *wi,
struct mt76_sta_stats *stats, bool eht);
int mt76_skb_adjust_pad(struct sk_buff *skb, int pad);
-@@ -1430,25 +1429,6 @@ void __mt76_set_tx_blocked(struct mt76_dev *dev, bool blocked);
+@@ -1441,25 +1440,6 @@ void __mt76_set_tx_blocked(struct mt76_dev *dev, bool blocked);
struct mt76_txwi_cache *mt76_rx_token_release(struct mt76_dev *dev, int token);
int mt76_rx_token_consume(struct mt76_dev *dev, void *ptr,
struct mt76_txwi_cache *r, dma_addr_t phys);
@@ -401,7 +401,7 @@
static void
diff --git a/mt7915/mmio.c b/mt7915/mmio.c
-index 225a1960..cbe6e2cd 100644
+index 6f0c0e2a..5ef43c44 100644
--- a/mt7915/mmio.c
+++ b/mt7915/mmio.c
@@ -596,9 +596,13 @@ static void mt7915_mmio_wed_offload_disable(struct mtk_wed_device *wed)
@@ -505,7 +505,7 @@
return -ENOMEM;
}
diff --git a/mt7921/main.c b/mt7921/main.c
-index 75eaf86c..1434ca79 100644
+index a72964e7..4c400223 100644
--- a/mt7921/main.c
+++ b/mt7921/main.c
@@ -1090,34 +1090,17 @@ static void
@@ -571,7 +571,7 @@
static u64
diff --git a/usb.c b/usb.c
-index b88959ef..3e281715 100644
+index 5e5c7bf5..3e281715 100644
--- a/usb.c
+++ b/usb.c
@@ -319,27 +319,29 @@ mt76u_set_endpoints(struct usb_interface *intf,
@@ -688,11 +688,12 @@
int i;
for (i = 0; i < q->ndesc; i++) {
-@@ -705,7 +701,13 @@ mt76u_free_rx_queue(struct mt76_dev *dev, struct mt76_queue *q)
+@@ -705,8 +701,13 @@ mt76u_free_rx_queue(struct mt76_dev *dev, struct mt76_queue *q)
mt76u_urb_free(q->entry[i].urb);
q->entry[i].urb = NULL;
}
- page_pool_destroy(q->page_pool);
+- q->page_pool = NULL;
+
+ if (!q->rx_page.va)
+ return;
@@ -704,5 +705,5 @@
static void mt76u_free_rx(struct mt76_dev *dev)
--
-2.25.1
+2.39.2
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/0999-mt76-mt7996-for-build-pass.patch b/recipes-wifi/linux-mt76/files/patches-3.x/0999-mt76-mt7996-for-build-pass.patch
index dd28dc9..2f9a0c3 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/0999-mt76-mt7996-for-build-pass.patch
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/0999-mt76-mt7996-for-build-pass.patch
@@ -1,4 +1,4 @@
-From e66fbcb72e09e9e6a88fcedc84f4eda0d53ef65d Mon Sep 17 00:00:00 2001
+From a126ad08af718c71b4b05261caefb68996044330 Mon Sep 17 00:00:00 2001
From: Shayne Chen <shayne.chen@mediatek.com>
Date: Thu, 3 Nov 2022 00:27:17 +0800
Subject: [PATCH] mt76: mt7996: for build pass
@@ -6,16 +6,15 @@
Change-Id: Ieb44c33ee6e6a2e6058c1ef528404c1a1cbcfdaf
---
debugfs.c | 3 +++
- dma.c | 2 +-
eeprom.c | 8 +++++++-
mcu.c | 1 +
mt7615/mcu.c | 1 +
mt76_connac_mcu.c | 1 +
mt7915/mcu.c | 1 +
mt7996/dma.c | 4 ++--
- mt7996/eeprom.c | 1 +
+ mt7996/eeprom.c | 2 ++
mt7996/mcu.c | 1 +
- 10 files changed, 19 insertions(+), 4 deletions(-)
+ 9 files changed, 19 insertions(+), 3 deletions(-)
diff --git a/debugfs.c b/debugfs.c
index 79064a4d..e10d4cbc 100644
@@ -33,19 +32,6 @@
return 0;
}
-diff --git a/dma.c b/dma.c
-index 50a7a689..beb9f4a4 100644
---- a/dma.c
-+++ b/dma.c
-@@ -854,7 +854,7 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
- !(dev->drv->rx_check(dev, data, len)))
- goto free_frag;
-
-- skb = napi_build_skb(data, q->buf_size);
-+ skb = build_skb(data, q->buf_size);
- if (!skb)
- goto free_frag;
-
diff --git a/eeprom.c b/eeprom.c
index ea54b7af..90d36c8d 100644
--- a/eeprom.c
@@ -92,7 +78,7 @@
static bool prefer_offload_fw = true;
module_param(prefer_offload_fw, bool, 0644);
diff --git a/mt76_connac_mcu.c b/mt76_connac_mcu.c
-index efb9bfaa..4a650721 100644
+index 4e4f6b35..e5815227 100644
--- a/mt76_connac_mcu.c
+++ b/mt76_connac_mcu.c
@@ -4,6 +4,7 @@
@@ -104,7 +90,7 @@
int mt76_connac_mcu_start_firmware(struct mt76_dev *dev, u32 addr, u32 option)
{
diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index f151ce86..20d81f05 100644
+index d08907f5..99ef8c9c 100644
--- a/mt7915/mcu.c
+++ b/mt7915/mcu.c
@@ -6,6 +6,7 @@
@@ -116,7 +102,7 @@
#define fw_name(_dev, name, ...) ({ \
char *_fw; \
diff --git a/mt7996/dma.c b/mt7996/dma.c
-index c09fe427..8c2e060d 100644
+index 18ea758c..3e2967f7 100644
--- a/mt7996/dma.c
+++ b/mt7996/dma.c
@@ -343,8 +343,8 @@ int mt7996_dma_init(struct mt7996_dev *dev)
@@ -131,19 +117,20 @@
mt7996_dma_enable(dev);
diff --git a/mt7996/eeprom.c b/mt7996/eeprom.c
-index 2e48c5a4..dd322f62 100644
+index 2e48c5a4..e747cb9f 100644
--- a/mt7996/eeprom.c
+++ b/mt7996/eeprom.c
-@@ -98,6 +98,7 @@ static int mt7996_eeprom_parse_efuse_hw_cap(struct mt7996_dev *dev)
+@@ -98,6 +98,8 @@ static int mt7996_eeprom_parse_efuse_hw_cap(struct mt7996_dev *dev)
if (ret)
return ret;
-+ cap = 0x4b249248; /* internal hardcode */
++ /* for internal testing */
++ cap = 0x4b249248;
if (cap) {
dev->has_eht = !(cap & MODE_HE_ONLY);
dev->wtbl_size_group = u32_get_bits(cap, WTBL_SIZE_GROUP);
diff --git a/mt7996/mcu.c b/mt7996/mcu.c
-index 1e47b0ae..db715195 100644
+index 829f7be6..0d9d309f 100644
--- a/mt7996/mcu.c
+++ b/mt7996/mcu.c
@@ -5,6 +5,7 @@
@@ -155,5 +142,5 @@
#include "mcu.h"
#include "mac.h"
--
-2.25.1
+2.39.2
diff --git a/recipes-wifi/linux-mt76/files/patches-3.x/patches.inc b/recipes-wifi/linux-mt76/files/patches-3.x/patches.inc
index cf59945..51df096 100644
--- a/recipes-wifi/linux-mt76/files/patches-3.x/patches.inc
+++ b/recipes-wifi/linux-mt76/files/patches-3.x/patches.inc
@@ -1,12 +1,23 @@
#patch patches (come from openwrt/lede/target/linux/mediatek)
SRC_URI_append = " \
- file://0000-sync-to-master.patch \
- file://0001-Revert-wifi-mt76-mt7996-rely-on-mt76_connac_tx_compl.patch \
- file://0002-Revert-wifi-mt76-mt7996-rely-on-mt76_connac_txp_skb_.patch \
- file://0003-Revert-wifi-mt76-mt7996-rely-on-mt76_connac_txp_comm.patch \
- file://0004-wifi-mt76-mt7996-add-muru-support.patch \
- file://0005-wifi-mt76-mt7996-set-txd-v1.patch \
- file://0006-wifi-mt76-mt7996-add-802.11s-mesh-amsdu-de-amsdu-sup.patch \
- file://0007-mt76-revert-page-pool-changes.patch \
+ file://0001-wifi-mt76-mt7996-add-eht-rx-rate-support.patch \
+ file://0002-wifi-mt76-mt7996-let-non-bufferable-MMPDUs-use-corre.patch \
+ file://0003-wifi-mt76-mt7996-reduce-repeated-bss_info-and-sta_re.patch \
+ file://0004-wifi-mt76-mt7996-move-radio-enable-command-to-mt7996.patch \
+ file://0005-wifi-mt76-connac-set-correct-muar_idx-for-connac3-ch.patch \
+ file://0006-wifi-mt76-mt7996-fix-pointer-calculation-in-ie-count.patch \
+ file://0007-wifi-mt76-mt7996-remove-mt7996_mcu_set_pm.patch \
+ file://0008-wifi-mt76-mt7996-add-muru-support.patch \
+ file://0009-wifi-mt76-mt7996-set-txd-v1.patch \
+ file://0010-wifi-mt76-mt7996-add-thermal-protection-support.patch \
+ file://0011-wifi-mt76-mt7996-add-thermal-sensor-device-support.patch \
+ file://0012-wifi-mt76-mt7996-add-802.11s-mesh-amsdu-de-amsdu-sup.patch \
+ file://0013-wifi-mt76-mt7996-add-L0.5-system-error-recovery-supp.patch \
+ file://0014-wifi-mt76-mt7996-add-dsp-firmware-download.patch \
+ file://0015-wifi-mt76-mt7996-fix-eeprom-antenna-bitfield-mask.patch \
+ file://0016-wifi-mt76-mt7996-init-mpdu-density.patch \
+ file://0017-wifi-mt76-mt7996-fix-icv-error-when-enable-AP-and-ST.patch \
+ file://0018-wifi-mt76-mt7996-set-wcid-in-txp.patch \
+ file://0019-mt76-revert-page-pool-changes.patch \
file://0999-mt76-mt7996-for-build-pass.patch \
"
diff --git a/recipes-wifi/linux-mt76/files/patches/0001-wifi-mt76-mt7915-rework-mt7915_thermal_init.patch b/recipes-wifi/linux-mt76/files/patches/0001-wifi-mt76-mt7915-rework-mt7915_thermal_init.patch
deleted file mode 100644
index 0494b40..0000000
--- a/recipes-wifi/linux-mt76/files/patches/0001-wifi-mt76-mt7915-rework-mt7915_thermal_init.patch
+++ /dev/null
@@ -1,41 +0,0 @@
-From e4a095d551a5d2252887b88d064dee43fcb4149d Mon Sep 17 00:00:00 2001
-From: Howard Hsu <howard-yh.hsu@mediatek.com>
-Date: Thu, 19 Jan 2023 11:03:44 +0800
-Subject: [PATCH] wifi: mt76: mt7915: rework mt7915_thermal_init()
-
-If the kernel configuration "CONFIG_HWMON" is not set to Y, the
-critial/maximum high temperature will not be initialised to the correct
-setting. Rework mt7915_thermal_init to fix this.
----
- mt7915/init.c | 8 ++++----
- 1 file changed, 4 insertions(+), 4 deletions(-)
-
-diff --git a/mt7915/init.c b/mt7915/init.c
-index ec297e04..8485a154 100644
---- a/mt7915/init.c
-+++ b/mt7915/init.c
-@@ -202,6 +202,10 @@ static int mt7915_thermal_init(struct mt7915_phy *phy)
- phy->cdev = cdev;
- }
-
-+ /* initialize critical/maximum high temperature */
-+ phy->throttle_temp[MT7915_CRIT_TEMP_IDX] = MT7915_CRIT_TEMP;
-+ phy->throttle_temp[MT7915_MAX_TEMP_IDX] = MT7915_MAX_TEMP;
-+
- if (!IS_REACHABLE(CONFIG_HWMON))
- return 0;
-
-@@ -210,10 +214,6 @@ static int mt7915_thermal_init(struct mt7915_phy *phy)
- if (IS_ERR(hwmon))
- return PTR_ERR(hwmon);
-
-- /* initialize critical/maximum high temperature */
-- phy->throttle_temp[MT7915_CRIT_TEMP_IDX] = MT7915_CRIT_TEMP;
-- phy->throttle_temp[MT7915_MAX_TEMP_IDX] = MT7915_MAX_TEMP;
--
- return 0;
- }
-
---
-2.18.0
-
diff --git a/recipes-wifi/linux-mt76/files/patches/1001-mt76-mt7915-add-mtk-internal-debug-tools-for-mt76.patch b/recipes-wifi/linux-mt76/files/patches/1001-mt76-mt7915-add-mtk-internal-debug-tools-for-mt76.patch
index 492a5de..ef37684 100644
--- a/recipes-wifi/linux-mt76/files/patches/1001-mt76-mt7915-add-mtk-internal-debug-tools-for-mt76.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1001-mt76-mt7915-add-mtk-internal-debug-tools-for-mt76.patch
@@ -1,7 +1,7 @@
-From 0585e668ca5e848c1b30f6f492ba0897ddb4071b Mon Sep 17 00:00:00 2001
+From 764731bb9676e58e8819bdbe48719b1076625032 Mon Sep 17 00:00:00 2001
From: Shayne Chen <shayne.chen@mediatek.com>
Date: Wed, 22 Jun 2022 10:39:47 +0800
-Subject: [PATCH] mt76: mt7915: add mtk internal debug tools for mt76
+Subject: [PATCH 1001/1009] mt76: mt7915: add mtk internal debug tools for mt76
---
mt76_connac_mcu.h | 6 +
@@ -22,10 +22,10 @@
create mode 100644 mt7915/mtk_mcu.c
diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index a5e6ee4d..cbe0c52a 100644
+index 40a99e0c..312e7b3c 100644
--- a/mt76_connac_mcu.h
+++ b/mt76_connac_mcu.h
-@@ -1151,6 +1151,7 @@ enum {
+@@ -1148,6 +1148,7 @@ enum {
MCU_EXT_CMD_SET_TX_POWER_CTRL = 0x11,
MCU_EXT_CMD_FW_LOG_2_HOST = 0x13,
MCU_EXT_CMD_TXBF_ACTION = 0x1e,
@@ -33,7 +33,7 @@
MCU_EXT_CMD_EFUSE_BUFFER_MODE = 0x21,
MCU_EXT_CMD_THERMAL_PROT = 0x23,
MCU_EXT_CMD_STA_REC_UPDATE = 0x25,
-@@ -1174,6 +1175,11 @@ enum {
+@@ -1171,6 +1172,11 @@ enum {
MCU_EXT_CMD_TX_POWER_FEATURE_CTRL = 0x58,
MCU_EXT_CMD_RXDCOC_CAL = 0x59,
MCU_EXT_CMD_GET_MIB_INFO = 0x5a,
@@ -258,7 +258,7 @@
goto out;
diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index f151ce86..ff718f78 100644
+index d08907f5..1fecd4b1 100644
--- a/mt7915/mcu.c
+++ b/mt7915/mcu.c
@@ -199,6 +199,11 @@ mt7915_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
@@ -285,7 +285,7 @@
{
#define RED_DISABLE 0
#define RED_BY_WA_ENABLE 2
-@@ -3377,6 +3385,8 @@ int mt7915_mcu_set_sku_en(struct mt7915_phy *phy, bool enable)
+@@ -3379,6 +3387,8 @@ int mt7915_mcu_set_sku_en(struct mt7915_phy *phy, bool enable)
.sku_enable = enable,
};
@@ -294,7 +294,7 @@
return mt76_mcu_send_msg(&dev->mt76,
MCU_EXT_CMD(TX_POWER_FEATURE_CTRL), &req,
sizeof(req), true);
-@@ -3814,6 +3824,23 @@ int mt7915_mcu_twt_agrt_update(struct mt7915_dev *dev,
+@@ -3816,6 +3826,23 @@ int mt7915_mcu_twt_agrt_update(struct mt7915_dev *dev,
&req, sizeof(req), true);
}
@@ -318,7 +318,7 @@
int mt7915_mcu_rf_regval(struct mt7915_dev *dev, u32 regidx, u32 *val, bool set)
{
struct {
-@@ -3842,3 +3869,22 @@ int mt7915_mcu_rf_regval(struct mt7915_dev *dev, u32 regidx, u32 *val, bool set)
+@@ -3844,3 +3871,22 @@ int mt7915_mcu_rf_regval(struct mt7915_dev *dev, u32 regidx, u32 *val, bool set)
return 0;
}
diff --git a/recipes-wifi/linux-mt76/files/patches/1002-mt76-mt7915-csi-implement-csi-support.patch b/recipes-wifi/linux-mt76/files/patches/1002-mt76-mt7915-csi-implement-csi-support.patch
index bde66c3..125a023 100644
--- a/recipes-wifi/linux-mt76/files/patches/1002-mt76-mt7915-csi-implement-csi-support.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1002-mt76-mt7915-csi-implement-csi-support.patch
@@ -1,4 +1,4 @@
-From f7a36f2ff5ca5cdf4a5fca215b14622da6257016 Mon Sep 17 00:00:00 2001
+From 41752b5e4ac73781e070aabff226904ab9efb5e4 Mon Sep 17 00:00:00 2001
From: Bo Jiao <Bo.Jiao@mediatek.com>
Date: Mon, 6 Jun 2022 20:13:02 +0800
Subject: [PATCH 1002/1009] mt76: mt7915: csi: implement csi support
@@ -17,10 +17,10 @@
create mode 100644 mt7915/vendor.h
diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index cbe0c52a..32156d35 100644
+index 312e7b3c..39a7f691 100644
--- a/mt76_connac_mcu.h
+++ b/mt76_connac_mcu.h
-@@ -1003,6 +1003,7 @@ enum {
+@@ -1000,6 +1000,7 @@ enum {
MCU_EXT_EVENT_CSA_NOTIFY = 0x4f,
MCU_EXT_EVENT_BCC_NOTIFY = 0x75,
MCU_EXT_EVENT_MURU_CTRL = 0x9f,
@@ -28,7 +28,7 @@
};
/* unified event table */
-@@ -1196,6 +1197,7 @@ enum {
+@@ -1193,6 +1194,7 @@ enum {
MCU_EXT_CMD_GROUP_PRE_CAL_INFO = 0xab,
MCU_EXT_CMD_DPD_PRE_CAL_INFO = 0xac,
MCU_EXT_CMD_PHY_STAT_INFO = 0xad,
@@ -54,10 +54,10 @@
mt7915e-$(CONFIG_NL80211_TESTMODE) += testmode.o
mt7915e-$(CONFIG_MT7986_WMAC) += soc.o
diff --git a/mt7915/init.c b/mt7915/init.c
-index 8485a154..06ac261f 100644
+index b88c3827..c27469e4 100644
--- a/mt7915/init.c
+++ b/mt7915/init.c
-@@ -652,6 +652,12 @@ mt7915_register_ext_phy(struct mt7915_dev *dev, struct mt7915_phy *phy)
+@@ -664,6 +664,12 @@ mt7915_register_ext_phy(struct mt7915_dev *dev, struct mt7915_phy *phy)
/* init wiphy according to mphy and phy */
mt7915_init_wiphy(phy);
@@ -70,7 +70,7 @@
ret = mt76_register_phy(mphy, true, mt76_rates,
ARRAY_SIZE(mt76_rates));
if (ret)
-@@ -1144,6 +1150,25 @@ void mt7915_set_stream_he_caps(struct mt7915_phy *phy)
+@@ -1165,6 +1171,25 @@ void mt7915_set_stream_he_caps(struct mt7915_phy *phy)
}
}
@@ -96,7 +96,7 @@
static void mt7915_unregister_ext_phy(struct mt7915_dev *dev)
{
struct mt7915_phy *phy = mt7915_ext_phy(dev);
-@@ -1152,6 +1177,10 @@ static void mt7915_unregister_ext_phy(struct mt7915_dev *dev)
+@@ -1173,6 +1198,10 @@ static void mt7915_unregister_ext_phy(struct mt7915_dev *dev)
if (!phy)
return;
@@ -107,7 +107,7 @@
mt7915_unregister_thermal(phy);
mt76_unregister_phy(mphy);
ieee80211_free_hw(mphy->hw);
-@@ -1164,6 +1193,10 @@ static void mt7915_stop_hardware(struct mt7915_dev *dev)
+@@ -1185,6 +1214,10 @@ static void mt7915_stop_hardware(struct mt7915_dev *dev)
mt7915_dma_cleanup(dev);
tasklet_disable(&dev->irq_tasklet);
@@ -118,7 +118,7 @@
if (is_mt7986(&dev->mt76))
mt7986_wmac_disable(dev);
}
-@@ -1204,6 +1237,12 @@ int mt7915_register_device(struct mt7915_dev *dev)
+@@ -1225,6 +1258,12 @@ int mt7915_register_device(struct mt7915_dev *dev)
dev->mt76.test_ops = &mt7915_testmode_ops;
#endif
@@ -132,7 +132,7 @@
ARRAY_SIZE(mt76_rates));
if (ret)
diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index ff718f78..59cce553 100644
+index 1fecd4b1..40f77428 100644
--- a/mt7915/mcu.c
+++ b/mt7915/mcu.c
@@ -36,6 +36,10 @@ static bool sr_scene_detect = true;
@@ -158,7 +158,7 @@
case MCU_EXT_EVENT_BCC_NOTIFY:
mt7915_mcu_rx_bcc_notify(dev, skb);
break;
-@@ -3824,6 +3833,108 @@ int mt7915_mcu_twt_agrt_update(struct mt7915_dev *dev,
+@@ -3826,6 +3835,108 @@ int mt7915_mcu_twt_agrt_update(struct mt7915_dev *dev,
&req, sizeof(req), true);
}
@@ -353,7 +353,7 @@
+
#endif
diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
-index 19880099..bd2ca6cc 100644
+index 5fcc8ace..e0133b13 100644
--- a/mt7915/mt7915.h
+++ b/mt7915/mt7915.h
@@ -294,6 +294,20 @@ struct mt7915_phy {
@@ -377,7 +377,7 @@
};
struct mt7915_dev {
-@@ -675,6 +689,12 @@ void mt7915_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+@@ -674,6 +688,12 @@ void mt7915_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
int mt7915_mmio_wed_init(struct mt7915_dev *dev, void *pdev_ptr,
bool pci, int *irq);
diff --git a/recipes-wifi/linux-mt76/files/patches/1003-mt76-mt7915-air-monitor-support.patch b/recipes-wifi/linux-mt76/files/patches/1003-mt76-mt7915-air-monitor-support.patch
index c59c63d..b3388ce 100644
--- a/recipes-wifi/linux-mt76/files/patches/1003-mt76-mt7915-air-monitor-support.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1003-mt76-mt7915-air-monitor-support.patch
@@ -1,4 +1,4 @@
-From a97766c58f1dc2a25421f1bc527a06b59cd5f0dc Mon Sep 17 00:00:00 2001
+From f6b5a16ecd5e9cc986a3dde75a84a447aa729449 Mon Sep 17 00:00:00 2001
From: Bo Jiao <Bo.Jiao@mediatek.com>
Date: Tue, 11 Jan 2022 12:03:23 +0800
Subject: [PATCH 1003/1009] mt76: mt7915: air monitor support
@@ -13,10 +13,10 @@
6 files changed, 440 insertions(+)
diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index 32156d35..60161c9e 100644
+index 39a7f691..d35f9e92 100644
--- a/mt76_connac_mcu.h
+++ b/mt76_connac_mcu.h
-@@ -1197,6 +1197,8 @@ enum {
+@@ -1194,6 +1194,8 @@ enum {
MCU_EXT_CMD_GROUP_PRE_CAL_INFO = 0xab,
MCU_EXT_CMD_DPD_PRE_CAL_INFO = 0xac,
MCU_EXT_CMD_PHY_STAT_INFO = 0xad,
@@ -55,7 +55,7 @@
}
diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
-index bd2ca6cc..9a9d7f55 100644
+index e0133b13..df0d7a1e 100644
--- a/mt7915/mt7915.h
+++ b/mt7915/mt7915.h
@@ -250,6 +250,35 @@ struct mt7915_hif {
@@ -103,7 +103,7 @@
#endif
};
-@@ -693,6 +724,9 @@ int mt7915_mmio_wed_init(struct mt7915_dev *dev, void *pdev_ptr,
+@@ -692,6 +723,9 @@ int mt7915_mmio_wed_init(struct mt7915_dev *dev, void *pdev_ptr,
void mt7915_vendor_register(struct mt7915_phy *phy);
int mt7915_mcu_set_csi(struct mt7915_phy *phy, u8 mode,
u8 cfg, u8 v1, u32 v2, u8 *mac_addr);
diff --git a/recipes-wifi/linux-mt76/files/patches/1004-mt76-mt7915-add-support-for-muru_onoff-via-debugfs.patch b/recipes-wifi/linux-mt76/files/patches/1004-mt76-mt7915-add-support-for-muru_onoff-via-debugfs.patch
index 30c30f1..b2739d3 100644
--- a/recipes-wifi/linux-mt76/files/patches/1004-mt76-mt7915-add-support-for-muru_onoff-via-debugfs.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1004-mt76-mt7915-add-support-for-muru_onoff-via-debugfs.patch
@@ -1,4 +1,4 @@
-From f45e6908cbe43d1dd02f92569ed2549e021822e1 Mon Sep 17 00:00:00 2001
+From 7a1f0d570d96e8e23b771976da052e94def589b9 Mon Sep 17 00:00:00 2001
From: MeiChia Chiu <meichia.chiu@mediatek.com>
Date: Wed, 22 Jun 2022 10:45:53 +0800
Subject: [PATCH 1004/1009] mt76: mt7915: add support for muru_onoff via
@@ -13,10 +13,10 @@
5 files changed, 52 insertions(+), 3 deletions(-)
diff --git a/mt7915/init.c b/mt7915/init.c
-index 06ac261..3897ac4 100644
+index c27469e4..1177e4e7 100644
--- a/mt7915/init.c
+++ b/mt7915/init.c
-@@ -433,6 +433,8 @@ mt7915_init_wiphy(struct mt7915_phy *phy)
+@@ -445,6 +445,8 @@ mt7915_init_wiphy(struct mt7915_phy *phy)
mphy->leds.cdev.brightness_set = mt7915_led_set_brightness;
mphy->leds.cdev.blink_set = mt7915_led_set_blink;
}
@@ -26,7 +26,7 @@
static void
diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index 59cce55..cf9a3e2 100644
+index 40f77428..b507f14f 100644
--- a/mt7915/mcu.c
+++ b/mt7915/mcu.c
@@ -864,6 +864,7 @@ mt7915_mcu_sta_muru_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
@@ -60,7 +60,7 @@
muru->mimo_dl.vht_mu_bfee =
!!(sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE);
diff --git a/mt7915/mcu.h b/mt7915/mcu.h
-index c776417..275a0ec 100644
+index c776417b..275a0ece 100644
--- a/mt7915/mcu.h
+++ b/mt7915/mcu.h
@@ -609,4 +609,10 @@ struct csi_data {
@@ -75,7 +75,7 @@
+
#endif
diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
-index df0d7a1..e94970b 100644
+index df0d7a1e..e94970ba 100644
--- a/mt7915/mt7915.h
+++ b/mt7915/mt7915.h
@@ -307,6 +307,8 @@ struct mt7915_phy {
@@ -88,7 +88,7 @@
struct mt76_channel_state state_ts;
diff --git a/mt7915/mtk_debugfs.c b/mt7915/mtk_debugfs.c
-index 4fb845b..1aafe04 100644
+index 530bde1a..824ddeda 100644
--- a/mt7915/mtk_debugfs.c
+++ b/mt7915/mtk_debugfs.c
@@ -2558,6 +2558,38 @@ static int mt7915_token_txd_read(struct seq_file *s, void *data)
@@ -139,5 +139,5 @@
&fops_fw_debug_module);
debugfs_create_file("fw_debug_level", 0600, dir, dev,
--
-2.39.0
+2.18.0
diff --git a/recipes-wifi/linux-mt76/files/patches/1005-mt76-mt7915-certification-patches.patch b/recipes-wifi/linux-mt76/files/patches/1005-mt76-mt7915-certification-patches.patch
index 1c216ec..8bb1195 100644
--- a/recipes-wifi/linux-mt76/files/patches/1005-mt76-mt7915-certification-patches.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1005-mt76-mt7915-certification-patches.patch
@@ -1,4 +1,4 @@
-From a3246b4d0ebb9b123c552f05226b0dc612c70788 Mon Sep 17 00:00:00 2001
+From a3b277ab5965fc3ea056d9d4f2f9a9dedd4fef51 Mon Sep 17 00:00:00 2001
From: MeiChia Chiu <meichia.chiu@mediatek.com>
Date: Mon, 6 Jun 2022 20:15:51 +0800
Subject: [PATCH 1005/1009] mt76: mt7915: certification patches
@@ -6,20 +6,20 @@
---
mt76_connac_mcu.h | 1 +
mt7915/mac.c | 23 +++
- mt7915/main.c | 15 +-
+ mt7915/main.c | 13 +-
mt7915/mcu.c | 466 +++++++++++++++++++++++++++++++++++++++++++
mt7915/mcu.h | 207 ++++++++++++++++++-
mt7915/mt7915.h | 13 ++
- mt7915/mtk_debugfs.c | 25 +--
+ mt7915/mtk_debugfs.c | 7 +-
mt7915/vendor.c | 187 +++++++++++++++++
mt7915/vendor.h | 42 ++++
- 9 files changed, 965 insertions(+), 14 deletions(-)
+ 9 files changed, 954 insertions(+), 5 deletions(-)
diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index 60161c9..ff114cb 100644
+index d35f9e92..68e9c7e1 100644
--- a/mt76_connac_mcu.h
+++ b/mt76_connac_mcu.h
-@@ -1199,6 +1199,7 @@ enum {
+@@ -1196,6 +1196,7 @@ enum {
MCU_EXT_CMD_PHY_STAT_INFO = 0xad,
/* for vendor csi and air monitor */
MCU_EXT_CMD_SMESH_CTRL = 0xae,
@@ -28,7 +28,7 @@
};
diff --git a/mt7915/mac.c b/mt7915/mac.c
-index 547519c..599d328 100644
+index 547519cc..599d328d 100644
--- a/mt7915/mac.c
+++ b/mt7915/mac.c
@@ -8,6 +8,7 @@
@@ -76,7 +76,7 @@
IEEE80211_RC_NSS_CHANGED |
IEEE80211_RC_BW_CHANGED))
diff --git a/mt7915/main.c b/mt7915/main.c
-index 3ded65d..05a5fbc 100644
+index 3ded65de..f0cbfbef 100644
--- a/mt7915/main.c
+++ b/mt7915/main.c
@@ -678,6 +678,9 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
@@ -107,10 +107,10 @@
void mt7915_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index cf9a3e2..c15dce3 100644
+index b507f14f..057ea6ee 100644
--- a/mt7915/mcu.c
+++ b/mt7915/mcu.c
-@@ -3939,6 +3939,472 @@ mt7915_mcu_report_csi(struct mt7915_dev *dev, struct sk_buff *skb)
+@@ -3941,6 +3941,472 @@ mt7915_mcu_report_csi(struct mt7915_dev *dev, struct sk_buff *skb)
return 0;
}
@@ -584,7 +584,7 @@
#ifdef MTK_DEBUG
diff --git a/mt7915/mcu.h b/mt7915/mcu.h
-index 275a0ec..714bc44 100644
+index 275a0ece..714bc44d 100644
--- a/mt7915/mcu.h
+++ b/mt7915/mcu.h
@@ -416,10 +416,14 @@ enum {
@@ -818,7 +818,7 @@
#endif
diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
-index e94970b..8b292c3 100644
+index e94970ba..8b292c3c 100644
--- a/mt7915/mt7915.h
+++ b/mt7915/mt7915.h
@@ -722,6 +722,19 @@ int mt7915_mmio_wed_init(struct mt7915_dev *dev, void *pdev_ptr,
@@ -842,10 +842,10 @@
int mt7915_mcu_set_csi(struct mt7915_phy *phy, u8 mode,
u8 cfg, u8 v1, u32 v2, u8 *mac_addr);
diff --git a/mt7915/mtk_debugfs.c b/mt7915/mtk_debugfs.c
-index 1aafe04..e0af645 100644
+index 824ddeda..4662f46f 100644
--- a/mt7915/mtk_debugfs.c
+++ b/mt7915/mtk_debugfs.c
-@@ -2564,7 +2564,8 @@ static int mt7915_muru_onoff_get(void *d
+@@ -2564,7 +2564,8 @@ static int mt7915_muru_onoff_get(void *data, u64 *val)
*val = phy->muru_onoff;
@@ -855,7 +855,7 @@
!!(phy->muru_onoff & MUMIMO_UL),
!!(phy->muru_onoff & MUMIMO_DL),
!!(phy->muru_onoff & OFDMA_UL),
-@@ -2577,8 +2578,8 @@ static int mt7915_muru_onoff_set(void *d
+@@ -2577,8 +2578,8 @@ static int mt7915_muru_onoff_set(void *data, u64 val)
{
struct mt7915_phy *phy = data;
@@ -867,7 +867,7 @@
}
diff --git a/mt7915/vendor.c b/mt7915/vendor.c
-index b94d787..beb0583 100644
+index b94d787e..beb0583a 100644
--- a/mt7915/vendor.c
+++ b/mt7915/vendor.c
@@ -22,6 +22,29 @@ csi_ctrl_policy[NUM_MTK_VENDOR_ATTRS_CSI_CTRL] = {
@@ -1079,7 +1079,7 @@
};
diff --git a/mt7915/vendor.h b/mt7915/vendor.h
-index 976817f..1b08321 100644
+index 976817f3..1b08321c 100644
--- a/mt7915/vendor.h
+++ b/mt7915/vendor.h
@@ -6,6 +6,48 @@
@@ -1132,5 +1132,5 @@
enum mtk_vendor_attr_csi_ctrl {
--
-2.39.0
+2.18.0
diff --git a/recipes-wifi/linux-mt76/files/patches/1006-mt76-mt7915-add-support-for-runtime-set-in-band-disc.patch b/recipes-wifi/linux-mt76/files/patches/1006-mt76-mt7915-add-support-for-runtime-set-in-band-disc.patch
index 8ed42b3..b1db4b7 100644
--- a/recipes-wifi/linux-mt76/files/patches/1006-mt76-mt7915-add-support-for-runtime-set-in-band-disc.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1006-mt76-mt7915-add-support-for-runtime-set-in-band-disc.patch
@@ -1,4 +1,4 @@
-From 1a60e2ba1ae97e6109e1e27dc48ae074b46043ff Mon Sep 17 00:00:00 2001
+From 8999d582213c666073a3bf3c855b66b16be16a52 Mon Sep 17 00:00:00 2001
From: MeiChia Chiu <meichia.chiu@mediatek.com>
Date: Fri, 27 May 2022 15:51:48 +0800
Subject: [PATCH 1006/1009] mt76: mt7915: add support for runtime set in-band
@@ -10,10 +10,10 @@
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index 40b17b5f..f7ed1049 100644
+index 057ea6ee..03c94349 100644
--- a/mt7915/mcu.c
+++ b/mt7915/mcu.c
-@@ -1993,8 +1993,7 @@ mt7915_mcu_beacon_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vi
+@@ -1994,8 +1994,7 @@ mt7915_mcu_beacon_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vi
u8 *buf, interval;
int len;
@@ -23,7 +23,7 @@
interval = vif->bss_conf.fils_discovery.max_interval;
skb = ieee80211_get_fils_discovery_tmpl(hw, vif);
} else if (changed & BSS_CHANGED_UNSOL_BCAST_PROBE_RESP &&
-@@ -2029,7 +2028,7 @@ mt7915_mcu_beacon_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vi
+@@ -2030,7 +2029,7 @@ mt7915_mcu_beacon_inband_discov(struct mt7915_dev *dev, struct ieee80211_vif *vi
discov->tx_type = !!(changed & BSS_CHANGED_FILS_DISCOVERY);
discov->tx_interval = interval;
discov->prob_rsp_len = cpu_to_le16(MT_TXD_SIZE + skb->len);
diff --git a/recipes-wifi/linux-mt76/files/patches/1007-mt76-mt7915-add-mt76-vendor-muru-onoff-command.patch b/recipes-wifi/linux-mt76/files/patches/1007-mt76-mt7915-add-mt76-vendor-muru-onoff-command.patch
index 050a40b..39d4df8 100644
--- a/recipes-wifi/linux-mt76/files/patches/1007-mt76-mt7915-add-mt76-vendor-muru-onoff-command.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1007-mt76-mt7915-add-mt76-vendor-muru-onoff-command.patch
@@ -1,4 +1,4 @@
-From 7197b9ba537a486c3ba398d2e0a806f093b682a3 Mon Sep 17 00:00:00 2001
+From b789f416faea7dc90e4c83119274c773d417069c Mon Sep 17 00:00:00 2001
From: MeiChia Chiu <meichia.chiu@mediatek.com>
Date: Wed, 22 Jun 2022 10:53:43 +0800
Subject: [PATCH 1007/1009] mt76: mt7915: add mt76 vendor muru onoff command
@@ -11,10 +11,10 @@
4 files changed, 63 insertions(+)
diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index 3a0e87a..62d83bf 100644
+index 03c94349..70349a75 100644
--- a/mt7915/mcu.c
+++ b/mt7915/mcu.c
-@@ -3958,6 +3958,13 @@ void mt7915_set_wireless_vif(void *data, u8 *mac, struct ieee80211_vif *vif)
+@@ -3960,6 +3960,13 @@ void mt7915_set_wireless_vif(void *data, u8 *mac, struct ieee80211_vif *vif)
if (val == 0)
phy->muru_onoff = MUMIMO_DL_CERT | MUMIMO_DL;
break;
@@ -29,7 +29,7 @@
}
diff --git a/mt7915/mcu.h b/mt7915/mcu.h
-index 714bc44..aaea323 100644
+index 714bc44d..ac4e6c8b 100644
--- a/mt7915/mcu.h
+++ b/mt7915/mcu.h
@@ -423,6 +423,7 @@ enum {
@@ -41,7 +41,7 @@
};
diff --git a/mt7915/vendor.c b/mt7915/vendor.c
-index beb0583..5acbd2d 100644
+index beb0583a..8d864c86 100644
--- a/mt7915/vendor.c
+++ b/mt7915/vendor.c
@@ -34,6 +34,11 @@ wireless_ctrl_policy[NUM_MTK_VENDOR_ATTRS_WIRELESS_CTRL] = {
@@ -109,7 +109,7 @@
};
diff --git a/mt7915/vendor.h b/mt7915/vendor.h
-index 1b08321..a8e4ebf 100644
+index 1b08321c..2be5fc89 100644
--- a/mt7915/vendor.h
+++ b/mt7915/vendor.h
@@ -8,6 +8,7 @@ enum mtk_nl80211_vendor_subcmds {
@@ -139,5 +139,5 @@
MTK_VENDOR_ATTR_RFEATURE_CTRL_UNSPEC,
--
-2.39.0
+2.18.0
diff --git a/recipes-wifi/linux-mt76/files/patches/1008-mt76-mt7915-drop-undefined-action-frame.patch b/recipes-wifi/linux-mt76/files/patches/1008-mt76-mt7915-drop-undefined-action-frame.patch
index eea5003..a48e596 100644
--- a/recipes-wifi/linux-mt76/files/patches/1008-mt76-mt7915-drop-undefined-action-frame.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1008-mt76-mt7915-drop-undefined-action-frame.patch
@@ -1,4 +1,4 @@
-From d23718033b7a128a1bcffc203b38609116428374 Mon Sep 17 00:00:00 2001
+From d88b52321783cfb7cb51bc383d13ed270ccced43 Mon Sep 17 00:00:00 2001
From: Peter Chiu <chui-hao.chiu@mediatek.com>
Date: Thu, 14 Apr 2022 15:18:02 +0800
Subject: [PATCH 1008/1009] mt76: mt7915: drop undefined action frame
diff --git a/recipes-wifi/linux-mt76/files/patches/1009-mt76-mt7915-add-fw_version-dump.patch b/recipes-wifi/linux-mt76/files/patches/1009-mt76-mt7915-add-fw_version-dump.patch
index 89c073a..f405a43 100644
--- a/recipes-wifi/linux-mt76/files/patches/1009-mt76-mt7915-add-fw_version-dump.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1009-mt76-mt7915-add-fw_version-dump.patch
@@ -1,4 +1,4 @@
-From e64af60e5c5642dec30e8605967b74dff53ada80 Mon Sep 17 00:00:00 2001
+From 5034a64c8d1905c639f2bb26f538f4d2d7703a21 Mon Sep 17 00:00:00 2001
From: Evelyn Tsai <evelyn.tsai@mediatek.com>
Date: Wed, 17 Aug 2022 13:40:24 +0800
Subject: [PATCH 1009/1009] mt76: mt7915: add fw_version dump
@@ -10,10 +10,10 @@
3 files changed, 32 insertions(+)
diff --git a/mt76.h b/mt76.h
-index ccca0162..00f1cd0d 100644
+index 183b0fc5..55751e8f 100644
--- a/mt76.h
+++ b/mt76.h
-@@ -843,6 +843,10 @@ struct mt76_dev {
+@@ -844,6 +844,10 @@ struct mt76_dev {
struct mt76_usb usb;
struct mt76_sdio sdio;
};
@@ -59,7 +59,7 @@
struct mt76_connac2_patch_sec *sec;
u32 len, addr, mode;
diff --git a/mt7915/mtk_debugfs.c b/mt7915/mtk_debugfs.c
-index f8d2cbbb..cba38513 100644
+index 4662f46f..05dc7d5a 100644
--- a/mt7915/mtk_debugfs.c
+++ b/mt7915/mtk_debugfs.c
@@ -2799,6 +2799,22 @@ static int mt7915_agginfo_read_band1(struct seq_file *s, void *data)
diff --git a/recipes-wifi/linux-mt76/files/patches/1111-mt76-testmode-rework-testmode-init-registers.patch b/recipes-wifi/linux-mt76/files/patches/1111-mt76-testmode-rework-testmode-init-registers.patch
index 54c27fb..d8bcf4c 100644
--- a/recipes-wifi/linux-mt76/files/patches/1111-mt76-testmode-rework-testmode-init-registers.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1111-mt76-testmode-rework-testmode-init-registers.patch
@@ -1,7 +1,7 @@
-From 6517389a3eb0ee290151240c1639a94405fdfbd8 Mon Sep 17 00:00:00 2001
+From 67a19923b1e9f0491531d7f641725310b5152f87 Mon Sep 17 00:00:00 2001
From: Shayne Chen <shayne.chen@mediatek.com>
Date: Mon, 6 Jun 2022 19:46:26 +0800
-Subject: [PATCH 1111/1133] mt76: testmode: rework testmode init registers
+Subject: [PATCH 1111/1132] mt76: testmode: rework testmode init registers
---
mac80211.c | 3 +-
@@ -17,10 +17,10 @@
10 files changed, 164 insertions(+), 35 deletions(-)
diff --git a/mac80211.c b/mac80211.c
-index b117e446..00e7b4f3 100644
+index 87902f4b..ad5d6f8b 100644
--- a/mac80211.c
+++ b/mac80211.c
-@@ -817,7 +817,8 @@ void mt76_rx(struct mt76_dev *dev, enum mt76_rxq_id q, struct sk_buff *skb)
+@@ -826,7 +826,8 @@ void mt76_rx(struct mt76_dev *dev, enum mt76_rxq_id q, struct sk_buff *skb)
}
#ifdef CONFIG_NL80211_TESTMODE
@@ -31,10 +31,10 @@
if (status->flag & RX_FLAG_FAILED_FCS_CRC)
phy->test.rx_stats.fcs_error[q]++;
diff --git a/mt76.h b/mt76.h
-index 00f1cd0d..25ad0f6b 100644
+index 55751e8f..ca664489 100644
--- a/mt76.h
+++ b/mt76.h
-@@ -643,6 +643,8 @@ struct mt76_testmode_ops {
+@@ -644,6 +644,8 @@ struct mt76_testmode_ops {
int (*dump_stats)(struct mt76_phy *phy, struct sk_buff *msg);
};
@@ -43,7 +43,7 @@
struct mt76_testmode_data {
enum mt76_testmode_state state;
-@@ -674,6 +676,8 @@ struct mt76_testmode_data {
+@@ -675,6 +677,8 @@ struct mt76_testmode_data {
u8 addr[3][ETH_ALEN];
@@ -52,7 +52,7 @@
u32 tx_pending;
u32 tx_queued;
u16 tx_queued_limit;
-@@ -681,6 +685,7 @@ struct mt76_testmode_data {
+@@ -682,6 +686,7 @@ struct mt76_testmode_data {
struct {
u64 packets[__MT_RXQ_MAX];
u64 fcs_error[__MT_RXQ_MAX];
@@ -61,10 +61,10 @@
};
diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index ff114cb9..1a146563 100644
+index 68e9c7e1..8ba8ebfe 100644
--- a/mt76_connac_mcu.h
+++ b/mt76_connac_mcu.h
-@@ -1193,6 +1193,7 @@ enum {
+@@ -1190,6 +1190,7 @@ enum {
MCU_EXT_CMD_OFFCH_SCAN_CTRL = 0x9a,
MCU_EXT_CMD_SET_RDD_TH = 0x9d,
MCU_EXT_CMD_MURU_CTRL = 0x9f,
@@ -73,7 +73,7 @@
MCU_EXT_CMD_GROUP_PRE_CAL_INFO = 0xab,
MCU_EXT_CMD_DPD_PRE_CAL_INFO = 0xac,
diff --git a/mt7915/mcu.h b/mt7915/mcu.h
-index aaea3230..a4b7ef82 100644
+index ac4e6c8b..3c16d214 100644
--- a/mt7915/mcu.h
+++ b/mt7915/mcu.h
@@ -9,6 +9,7 @@
@@ -85,7 +85,7 @@
MCU_ATE_CLEAN_TXQUEUE = 0x1c,
};
diff --git a/mt7915/mmio.c b/mt7915/mmio.c
-index 225a1960..6d8455d5 100644
+index 6f0c0e2a..dbafb5ff 100644
--- a/mt7915/mmio.c
+++ b/mt7915/mmio.c
@@ -120,6 +120,7 @@ static const u32 mt7986_reg[] = {
diff --git a/recipes-wifi/linux-mt76/files/patches/1112-mt76-testmode-additional-supports.patch b/recipes-wifi/linux-mt76/files/patches/1112-mt76-testmode-additional-supports.patch
index 1430ef9..e5beb49 100644
--- a/recipes-wifi/linux-mt76/files/patches/1112-mt76-testmode-additional-supports.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1112-mt76-testmode-additional-supports.patch
@@ -1,9 +1,10 @@
-From 947b0a84d32ca9fbdfc5befc133da50c1349694e Mon Sep 17 00:00:00 2001
+From ec2f469639d9c5119fb6f1592df8407f3f45a8fe Mon Sep 17 00:00:00 2001
From: Shayne Chen <shayne.chen@mediatek.com>
Date: Thu, 21 Apr 2022 15:43:19 +0800
-Subject: [PATCH 1112/1133] mt76: testmode: additional supports
+Subject: [PATCH 1112/1116] mt76: testmode: additional supports
Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
---
dma.c | 3 +-
mac80211.c | 12 +
@@ -18,16 +19,16 @@
mt7915/mmio.c | 2 +
mt7915/mt7915.h | 14 +-
mt7915/regs.h | 3 +
- mt7915/testmode.c | 1172 ++++++++++++++++++++++++++++++++++++++++++---
+ mt7915/testmode.c | 1177 ++++++++++++++++++++++++++++++++++++++++++---
mt7915/testmode.h | 278 +++++++++++
testmode.c | 275 +++++++++--
testmode.h | 75 +++
- tools/fields.c | 80 ++++
+ tools/fields.c | 80 +++
tx.c | 3 +-
- 19 files changed, 1964 insertions(+), 148 deletions(-)
+ 19 files changed, 1969 insertions(+), 148 deletions(-)
diff --git a/dma.c b/dma.c
-index e3fa4f39..a6bb3730 100644
+index e3fa4f3..a6bb373 100644
--- a/dma.c
+++ b/dma.c
@@ -566,8 +566,7 @@ free:
@@ -41,7 +42,7 @@
#endif
diff --git a/mac80211.c b/mac80211.c
-index 00e7b4f3..2a66b1dd 100644
+index 00e7b4f..2a66b1d 100644
--- a/mac80211.c
+++ b/mac80211.c
@@ -56,6 +56,13 @@ static const struct ieee80211_channel mt76_channels_5ghz[] = {
@@ -71,7 +72,7 @@
static const struct ieee80211_channel mt76_channels_6ghz[] = {
diff --git a/mt76.h b/mt76.h
-index 25ad0f6b..cde52268 100644
+index 25ad0f6..cde5226 100644
--- a/mt76.h
+++ b/mt76.h
@@ -641,6 +641,21 @@ struct mt76_testmode_ops {
@@ -233,7 +234,7 @@
static inline void mt76_testmode_reset(struct mt76_phy *phy, bool disable)
{
diff --git a/mt76_connac_mcu.c b/mt76_connac_mcu.c
-index 2fefac68..b6c2ccf0 100644
+index 2fefac6..b6c2ccf 100644
--- a/mt76_connac_mcu.c
+++ b/mt76_connac_mcu.c
@@ -394,6 +394,7 @@ void mt76_connac_mcu_sta_basic_tlv(struct sk_buff *skb,
@@ -255,7 +256,7 @@
return;
diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index 1a146563..f616bcea 100644
+index 1a14656..f616bce 100644
--- a/mt76_connac_mcu.h
+++ b/mt76_connac_mcu.h
@@ -999,6 +999,7 @@ enum {
@@ -275,10 +276,10 @@
MCU_EXT_CMD_CSI_CTRL = 0xc2,
};
diff --git a/mt7915/init.c b/mt7915/init.c
-index f73d34a9..19447ad1 100644
+index 3897ac4..0a13a83 100644
--- a/mt7915/init.c
+++ b/mt7915/init.c
-@@ -681,7 +681,7 @@ static void mt7915_init_work(struct work_struct *work)
+@@ -683,7 +683,7 @@ static void mt7915_init_work(struct work_struct *work)
struct mt7915_dev *dev = container_of(work, struct mt7915_dev,
init_work);
@@ -288,7 +289,7 @@
mt7915_init_txpower(dev, &dev->mphy.sband_2g.sband);
mt7915_init_txpower(dev, &dev->mphy.sband_5g.sband);
diff --git a/mt7915/mac.c b/mt7915/mac.c
-index de2bdba5..1460a32b 100644
+index de2bdba..1460a32 100644
--- a/mt7915/mac.c
+++ b/mt7915/mac.c
@@ -627,16 +627,38 @@ mt7915_mac_write_txwi_tm(struct mt7915_phy *phy, __le32 *txwi,
@@ -370,7 +371,7 @@
goto out;
diff --git a/mt7915/main.c b/mt7915/main.c
-index e4d1c27b..ea0d22fe 100644
+index f0cbfbe..651887c 100644
--- a/mt7915/main.c
+++ b/mt7915/main.c
@@ -238,7 +238,7 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,
@@ -383,7 +384,7 @@
mvif->mt76.wmm_idx += 2;
diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index 6ec12fd2..4d878665 100644
+index 62d83bf..0e5ed14 100644
--- a/mt7915/mcu.c
+++ b/mt7915/mcu.c
@@ -383,6 +383,11 @@ mt7915_mcu_rx_ext_event(struct mt7915_dev *dev, struct sk_buff *skb)
@@ -406,7 +407,7 @@
!rxd->seq)
mt7915_mcu_rx_unsolicited_event(dev, skb);
else
-@@ -2847,14 +2853,14 @@ static int mt7915_mcu_set_eeprom_flash(struct mt7915_dev *dev)
+@@ -2848,14 +2854,14 @@ static int mt7915_mcu_set_eeprom_flash(struct mt7915_dev *dev)
return 0;
}
@@ -424,7 +425,7 @@
return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(EFUSE_BUFFER_MODE),
diff --git a/mt7915/mcu.h b/mt7915/mcu.h
-index a4b7ef82..1671d563 100644
+index a4b7ef8..1671d56 100644
--- a/mt7915/mcu.h
+++ b/mt7915/mcu.h
@@ -8,10 +8,15 @@
@@ -481,7 +482,7 @@
enum {
diff --git a/mt7915/mmio.c b/mt7915/mmio.c
-index 6d8455d5..9a666d0f 100644
+index 6d8455d..9a666d0 100644
--- a/mt7915/mmio.c
+++ b/mt7915/mmio.c
@@ -134,6 +134,7 @@ static const u32 mt7915_offs[] = {
@@ -501,10 +502,10 @@
[AGG_PCR0] = 0x040,
[AGG_ACR0] = 0x054,
diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
-index 018fd23e..c45e42c5 100644
+index 8b292c3..9d9c5fc 100644
--- a/mt7915/mt7915.h
+++ b/mt7915/mt7915.h
-@@ -321,6 +321,9 @@ struct mt7915_phy {
+@@ -323,6 +323,9 @@ struct mt7915_phy {
u8 last_snr;
u8 spe_idx;
@@ -514,7 +515,7 @@
} test;
#endif
-@@ -420,6 +423,14 @@ struct mt7915_dev {
+@@ -422,6 +425,14 @@ struct mt7915_dev {
void __iomem *dcm;
void __iomem *sku;
@@ -529,7 +530,7 @@
#ifdef MTK_DEBUG
u16 wlan_idx;
struct {
-@@ -591,7 +602,7 @@ int mt7915_mcu_set_fixed_rate_ctrl(struct mt7915_dev *dev,
+@@ -592,7 +603,7 @@ int mt7915_mcu_set_fixed_rate_ctrl(struct mt7915_dev *dev,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
void *data, u32 field);
@@ -538,7 +539,7 @@
int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset);
int mt7915_mcu_get_eeprom_free_block(struct mt7915_dev *dev, u8 *block_num);
int mt7915_mcu_set_mac(struct mt7915_dev *dev, int band, bool enable,
-@@ -629,6 +640,7 @@ int mt7915_mcu_fw_log_2_host(struct mt7915_dev *dev, u8 type, u8 ctrl);
+@@ -630,6 +641,7 @@ int mt7915_mcu_fw_log_2_host(struct mt7915_dev *dev, u8 type, u8 ctrl);
int mt7915_mcu_fw_dbg_ctrl(struct mt7915_dev *dev, u32 module, u8 level);
void mt7915_mcu_rx_event(struct mt7915_dev *dev, struct sk_buff *skb);
void mt7915_mcu_exit(struct mt7915_dev *dev);
@@ -547,7 +548,7 @@
static inline u16 mt7915_wtbl_size(struct mt7915_dev *dev)
{
diff --git a/mt7915/regs.h b/mt7915/regs.h
-index d6a05f13..e8768488 100644
+index d6a05f1..e876848 100644
--- a/mt7915/regs.h
+++ b/mt7915/regs.h
@@ -62,6 +62,7 @@ enum offs_rev {
@@ -568,7 +569,7 @@
(_n) * 4))
#define MT_AGG_PCR0(_band, _n) MT_WF_AGG(_band, (__OFFS(AGG_PCR0) + \
diff --git a/mt7915/testmode.c b/mt7915/testmode.c
-index 46939191..e0ba088f 100644
+index 4693919..9317a8e 100644
--- a/mt7915/testmode.c
+++ b/mt7915/testmode.c
@@ -9,6 +9,9 @@
@@ -1829,7 +1830,19 @@
}
static int
-@@ -807,6 +1771,7 @@ static int
+@@ -737,6 +1701,11 @@ mt7915_tm_set_state(struct mt76_phy *mphy, enum mt76_testmode_state state)
+ struct mt7915_phy *phy = mphy->priv;
+ enum mt76_testmode_state prev_state = td->state;
+
++ if (!phy->monitor_vif) {
++ dev_err(phy->dev->mt76.dev, "Please make sure monitor interface is up\n");
++ return -ENOTCONN;
++ }
++
+ mphy->test.state = state;
+
+ if (prev_state == MT76_TM_STATE_TX_FRAMES ||
+@@ -807,6 +1776,7 @@ static int
mt7915_tm_dump_stats(struct mt76_phy *mphy, struct sk_buff *msg)
{
struct mt7915_phy *phy = mphy->priv;
@@ -1837,7 +1850,7 @@
void *rx, *rssi;
int i;
-@@ -852,11 +1817,68 @@ mt7915_tm_dump_stats(struct mt76_phy *mphy, struct sk_buff *msg)
+@@ -852,11 +1822,68 @@ mt7915_tm_dump_stats(struct mt76_phy *mphy, struct sk_buff *msg)
nla_nest_end(msg, rx);
@@ -1907,7 +1920,7 @@
+ .set_eeprom = mt7915_tm_set_eeprom,
};
diff --git a/mt7915/testmode.h b/mt7915/testmode.h
-index a1c54c89..01b08e9e 100644
+index a1c54c8..01b08e9 100644
--- a/mt7915/testmode.h
+++ b/mt7915/testmode.h
@@ -4,6 +4,8 @@
@@ -2222,7 +2235,7 @@
+
#endif
diff --git a/testmode.c b/testmode.c
-index 1d0d5d30..7a9ed543 100644
+index 1d0d5d3..7a9ed54 100644
--- a/testmode.c
+++ b/testmode.c
@@ -27,28 +27,16 @@ const struct nla_policy mt76_tm_policy[NUM_MT76_TM_ATTRS] = {
@@ -2689,7 +2702,7 @@
a = nla_nest_start(msg, MT76_TM_ATTR_TX_POWER);
if (!a)
diff --git a/testmode.h b/testmode.h
-index 89613266..57949f2b 100644
+index 8961326..57949f2 100644
--- a/testmode.h
+++ b/testmode.h
@@ -6,6 +6,8 @@
@@ -2794,7 +2807,7 @@
+
#endif
diff --git a/tools/fields.c b/tools/fields.c
-index e3f69089..6e36ab27 100644
+index e3f6908..6e36ab2 100644
--- a/tools/fields.c
+++ b/tools/fields.c
@@ -10,6 +10,7 @@ static const char * const testmode_state[] = {
@@ -2920,7 +2933,7 @@
};
diff --git a/tx.c b/tx.c
-index 1f309d05..6d55566f 100644
+index 1f309d0..6d55566 100644
--- a/tx.c
+++ b/tx.c
@@ -250,8 +250,7 @@ void __mt76_tx_complete_skb(struct mt76_dev *dev, u16 wcid_idx, struct sk_buff *
diff --git a/recipes-wifi/linux-mt76/files/patches/1113-mt76-testmode-add-pre-cal-support.patch b/recipes-wifi/linux-mt76/files/patches/1113-mt76-testmode-add-pre-cal-support.patch
index 496d3a6..137b15a 100644
--- a/recipes-wifi/linux-mt76/files/patches/1113-mt76-testmode-add-pre-cal-support.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1113-mt76-testmode-add-pre-cal-support.patch
@@ -1,7 +1,7 @@
-From 7e220c97e2010f5a36f5d86928bb0bb7f3f5aa16 Mon Sep 17 00:00:00 2001
+From 52d97d39f652d9b7441bbbe52de72b25796df4a0 Mon Sep 17 00:00:00 2001
From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
Date: Wed, 31 Aug 2022 20:06:52 +0800
-Subject: [PATCH 1113/1133] mt76: testmode: add pre-cal support
+Subject: [PATCH 1113/1116] mt76: testmode: add pre-cal support
Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
Change-Id: Ibfbbc3443de994eeb4daa5e364b0a90f5d7d3bcd
@@ -20,7 +20,7 @@
11 files changed, 562 insertions(+), 13 deletions(-)
diff --git a/eeprom.c b/eeprom.c
-index 0a88048b..cb6ff17a 100644
+index 0a88048..cb6ff17 100644
--- a/eeprom.c
+++ b/eeprom.c
@@ -89,8 +89,10 @@ int mt76_get_of_eeprom(struct mt76_dev *dev, void *eep, int offset, int len)
@@ -37,7 +37,7 @@
out_put_node:
diff --git a/mt76.h b/mt76.h
-index cde52268..e22f82c7 100644
+index cde5226..e22f82c 100644
--- a/mt76.h
+++ b/mt76.h
@@ -642,6 +642,7 @@ struct mt76_testmode_ops {
@@ -49,7 +49,7 @@
struct mt76_testmode_entry_data {
diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index f616bcea..89411ba6 100644
+index f616bce..89411ba 100644
--- a/mt76_connac_mcu.h
+++ b/mt76_connac_mcu.h
@@ -995,6 +995,7 @@ enum {
@@ -61,7 +61,7 @@
MCU_EXT_EVENT_FW_LOG_2_HOST = 0x13,
MCU_EXT_EVENT_THERMAL_PROTECT = 0x22,
diff --git a/mt7915/eeprom.h b/mt7915/eeprom.h
-index f3e56817..88aaa16a 100644
+index f3e5681..88aaa16 100644
--- a/mt7915/eeprom.h
+++ b/mt7915/eeprom.h
@@ -39,10 +39,18 @@ enum mt7915_eeprom_field {
@@ -114,7 +114,7 @@
#endif
diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index 4d878665..fb89686b 100644
+index 0e5ed14..4922e73 100644
--- a/mt7915/mcu.c
+++ b/mt7915/mcu.c
@@ -387,6 +387,9 @@ mt7915_mcu_rx_ext_event(struct mt7915_dev *dev, struct sk_buff *skb)
@@ -127,7 +127,7 @@
#endif
default:
break;
-@@ -2950,7 +2953,7 @@ int mt7915_mcu_apply_group_cal(struct mt7915_dev *dev)
+@@ -2951,7 +2954,7 @@ int mt7915_mcu_apply_group_cal(struct mt7915_dev *dev)
u8 idx = 0, *cal = dev->cal, *eep = dev->mt76.eeprom.data;
u32 total = MT_EE_CAL_GROUP_SIZE;
@@ -136,7 +136,7 @@
return 0;
/*
-@@ -3030,11 +3033,29 @@ int mt7915_mcu_apply_tx_dpd(struct mt7915_phy *phy)
+@@ -3031,11 +3034,29 @@ int mt7915_mcu_apply_tx_dpd(struct mt7915_phy *phy)
{
struct mt7915_dev *dev = phy->dev;
struct cfg80211_chan_def *chandef = &phy->mt76->chandef;
@@ -169,10 +169,10 @@
idx = mt7915_dpd_freq_idx(center_freq, chandef->width);
diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
-index c45e42c5..5d12cbbc 100644
+index 9d9c5fc..d6fe9e7 100644
--- a/mt7915/mt7915.h
+++ b/mt7915/mt7915.h
-@@ -407,6 +407,10 @@ struct mt7915_dev {
+@@ -409,6 +409,10 @@ struct mt7915_dev {
struct rchan *relay_fwlog;
void *cal;
@@ -183,7 +183,7 @@
struct {
u8 debug_wm;
-@@ -641,6 +645,7 @@ int mt7915_mcu_fw_dbg_ctrl(struct mt7915_dev *dev, u32 module, u8 level);
+@@ -642,6 +646,7 @@ int mt7915_mcu_fw_dbg_ctrl(struct mt7915_dev *dev, u32 module, u8 level);
void mt7915_mcu_rx_event(struct mt7915_dev *dev, struct sk_buff *skb);
void mt7915_mcu_exit(struct mt7915_dev *dev);
int mt7915_tm_txbf_status_read(struct mt7915_dev *dev, struct sk_buff *skb);
@@ -192,7 +192,7 @@
static inline u16 mt7915_wtbl_size(struct mt7915_dev *dev)
{
diff --git a/mt7915/testmode.c b/mt7915/testmode.c
-index e0ba088f..a9e57e4b 100644
+index 9317a8e..a7c185f 100644
--- a/mt7915/testmode.c
+++ b/mt7915/testmode.c
@@ -5,6 +5,7 @@
@@ -541,7 +541,7 @@
static void
mt7915_tm_update_params(struct mt7915_phy *phy, u32 changed)
{
-@@ -1715,6 +2024,10 @@ mt7915_tm_set_state(struct mt76_phy *mphy, enum mt76_testmode_state state)
+@@ -1720,6 +2029,10 @@ mt7915_tm_set_state(struct mt76_phy *mphy, enum mt76_testmode_state state)
else if (prev_state == MT76_TM_STATE_OFF ||
state == MT76_TM_STATE_OFF)
mt7915_tm_init(phy, !(state == MT76_TM_STATE_OFF));
@@ -552,7 +552,7 @@
if ((state == MT76_TM_STATE_IDLE &&
prev_state == MT76_TM_STATE_OFF) ||
-@@ -1876,9 +2189,113 @@ mt7915_tm_set_eeprom(struct mt76_phy *mphy, u32 offset, u8 *val, u8 action)
+@@ -1881,9 +2194,113 @@ mt7915_tm_set_eeprom(struct mt76_phy *mphy, u32 offset, u8 *val, u8 action)
return ret;
}
@@ -667,7 +667,7 @@
+ .dump_precal = mt7915_tm_dump_precal,
};
diff --git a/mt7915/testmode.h b/mt7915/testmode.h
-index 01b08e9e..d500987d 100644
+index 01b08e9..d500987 100644
--- a/mt7915/testmode.h
+++ b/mt7915/testmode.h
@@ -81,6 +81,11 @@ struct tm_tx_cont {
@@ -735,7 +735,7 @@
TAM_ARB_OP_MODE_NORMAL = 1,
TAM_ARB_OP_MODE_TEST,
diff --git a/testmode.c b/testmode.c
-index 7a9ed543..42da6f08 100644
+index 7a9ed54..42da6f0 100644
--- a/testmode.c
+++ b/testmode.c
@@ -763,6 +763,18 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
@@ -768,7 +768,7 @@
if (nla_put_u32(msg, MT76_TM_ATTR_TX_COUNT, td->tx_count) ||
diff --git a/testmode.h b/testmode.h
-index 57949f2b..34936e5f 100644
+index 57949f2..34936e5 100644
--- a/testmode.h
+++ b/testmode.h
@@ -19,6 +19,7 @@
@@ -824,7 +824,7 @@
/* keep last */
diff --git a/tools/fields.c b/tools/fields.c
-index 6e36ab27..1be1ffd6 100644
+index 6e36ab2..1be1ffd 100644
--- a/tools/fields.c
+++ b/tools/fields.c
@@ -11,6 +11,14 @@ static const char * const testmode_state[] = {
diff --git a/recipes-wifi/linux-mt76/files/patches/1114-mt76-testmode-add-iBF-command-mode-support.patch b/recipes-wifi/linux-mt76/files/patches/1114-mt76-testmode-add-iBF-command-mode-support.patch
index 8f8b4dc..ff74c33 100644
--- a/recipes-wifi/linux-mt76/files/patches/1114-mt76-testmode-add-iBF-command-mode-support.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1114-mt76-testmode-add-iBF-command-mode-support.patch
@@ -1,7 +1,7 @@
-From 0f8a11a93fd25593e5e778e0d0abda8d61127117 Mon Sep 17 00:00:00 2001
+From 074ca69eba297963caa63b79a20d2cdf962045d2 Mon Sep 17 00:00:00 2001
From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
Date: Mon, 12 Sep 2022 18:16:54 +0800
-Subject: [PATCH 1114/1133] mt76: testmode: add iBF command mode support
+Subject: [PATCH 1114/1116] mt76: testmode: add iBF command mode support
Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
Change-Id: I7eea1d6412563f889e5774e787e58ce9eba001bd
@@ -13,7 +13,7 @@
4 files changed, 85 insertions(+), 7 deletions(-)
diff --git a/mt7915/testmode.c b/mt7915/testmode.c
-index a9e57e4b..99582d9c 100644
+index a7c185f..668f483 100644
--- a/mt7915/testmode.c
+++ b/mt7915/testmode.c
@@ -701,6 +701,7 @@ mt7915_tm_txbf_profile_update(struct mt7915_phy *phy, u16 *val, bool ebf)
@@ -105,7 +105,7 @@
mt7915_tm_set_tx_len(phy, tx_time);
diff --git a/testmode.c b/testmode.c
-index 42da6f08..b605a4bc 100644
+index 42da6f0..b605a4b 100644
--- a/testmode.c
+++ b/testmode.c
@@ -530,6 +530,42 @@ out:
@@ -164,7 +164,7 @@
nla_for_each_nested(cur, tb[MT76_TM_ATTR_TXBF_PARAM], rem) {
if (nla_len(cur) != 2 ||
diff --git a/testmode.h b/testmode.h
-index 34936e5f..bbfb313f 100644
+index 34936e5..bbfb313 100644
--- a/testmode.h
+++ b/testmode.h
@@ -281,8 +281,10 @@ enum mt76_testmode_txbf_act {
@@ -179,7 +179,7 @@
/* keep last */
diff --git a/tools/fields.c b/tools/fields.c
-index 1be1ffd6..47fc69f9 100644
+index 1be1ffd..47fc69f 100644
--- a/tools/fields.c
+++ b/tools/fields.c
@@ -32,6 +32,20 @@ static const char * const testmode_tx_mode[] = {
diff --git a/recipes-wifi/linux-mt76/files/patches/1115-mt76-testmode-add-ZWDFS-test-mode-support.patch b/recipes-wifi/linux-mt76/files/patches/1115-mt76-testmode-add-ZWDFS-test-mode-support.patch
index 10a8119..1128a92 100644
--- a/recipes-wifi/linux-mt76/files/patches/1115-mt76-testmode-add-ZWDFS-test-mode-support.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1115-mt76-testmode-add-ZWDFS-test-mode-support.patch
@@ -1,7 +1,7 @@
-From b269297b9cb95ea651d363ba49fff3d25d06f99b Mon Sep 17 00:00:00 2001
+From 34ccd9ebdfd36f8e6e7b554446eaeb022141307d Mon Sep 17 00:00:00 2001
From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
Date: Thu, 27 Oct 2022 17:42:07 +0800
-Subject: [PATCH 1115/1133] mt76: testmode: add ZWDFS test mode support
+Subject: [PATCH 1115/1116] mt76: testmode: add ZWDFS test mode support
Change-Id: I14d104b7158a35acf6b0595357d07fb87f5a9d94
Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
@@ -19,7 +19,7 @@
10 files changed, 452 insertions(+), 1 deletion(-)
diff --git a/mt76.h b/mt76.h
-index e22f82c7..d5f5054f 100644
+index e22f82c..d5f5054 100644
--- a/mt76.h
+++ b/mt76.h
@@ -725,6 +725,15 @@ struct mt76_testmode_data {
@@ -39,7 +39,7 @@
struct mt76_vif {
diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index 89411ba6..5cef308a 100644
+index 89411ba..5cef308 100644
--- a/mt76_connac_mcu.h
+++ b/mt76_connac_mcu.h
@@ -1195,6 +1195,7 @@ enum {
@@ -59,10 +59,10 @@
enum {
diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index fb89686b..988c55c6 100644
+index 4922e73..cce622d 100644
--- a/mt7915/mcu.c
+++ b/mt7915/mcu.c
-@@ -2685,6 +2685,7 @@ mt7915_mcu_background_chain_ctrl(struct mt7915_phy *phy,
+@@ -2686,6 +2686,7 @@ mt7915_mcu_background_chain_ctrl(struct mt7915_phy *phy,
req.monitor_chan = chandef->chan->hw_value;
req.monitor_central_chan =
ieee80211_frequency_to_channel(chandef->center_freq1);
@@ -70,7 +70,7 @@
req.band_idx = phy->mt76->band_idx;
req.scan_mode = 2;
break;
-@@ -4503,3 +4504,68 @@ int mt7915_mcu_set_amsdu_algo(struct mt7915_dev *dev, u16 wcid, u8 enable)
+@@ -4504,3 +4505,68 @@ int mt7915_mcu_set_amsdu_algo(struct mt7915_dev *dev, u16 wcid, u8 enable)
return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(MEC_CTRL), &req, sizeof(req), true);
}
#endif
@@ -140,7 +140,7 @@
+ return 0;
+}
diff --git a/mt7915/mcu.h b/mt7915/mcu.h
-index 1671d563..d780415c 100644
+index 1671d56..d780415 100644
--- a/mt7915/mcu.h
+++ b/mt7915/mcu.h
@@ -629,6 +629,52 @@ struct csi_data {
@@ -197,10 +197,10 @@
#define OFDMA_DL BIT(0)
#define OFDMA_UL BIT(1)
diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
-index 5d12cbbc..2b42fb11 100644
+index d6fe9e7..e99b586 100644
--- a/mt7915/mt7915.h
+++ b/mt7915/mt7915.h
-@@ -309,6 +309,7 @@ struct mt7915_phy {
+@@ -311,6 +311,7 @@ struct mt7915_phy {
struct mib_stats mib;
struct mt76_channel_state state_ts;
@@ -208,7 +208,7 @@
#ifdef CONFIG_NL80211_TESTMODE
struct {
-@@ -759,6 +760,9 @@ int mt7915_vendor_amnt_sta_remove(struct mt7915_phy *phy,
+@@ -760,6 +761,9 @@ int mt7915_vendor_amnt_sta_remove(struct mt7915_phy *phy,
struct ieee80211_sta *sta);
#endif
@@ -219,7 +219,7 @@
int mt7915_mtk_init_debugfs(struct mt7915_phy *phy, struct dentry *dir);
int mt7915_dbg_mcu_wa_cmd(struct mt7915_dev *dev, int cmd, u32 a1, u32 a2, u32 a3, bool wait_resp);
diff --git a/mt7915/regs.h b/mt7915/regs.h
-index e8768488..f4b57099 100644
+index e876848..f4b5709 100644
--- a/mt7915/regs.h
+++ b/mt7915/regs.h
@@ -1194,6 +1194,8 @@ enum offs_rev {
@@ -232,7 +232,7 @@
#define MT_WF_PHY_BASE 0x83080000
#define MT_WF_PHY(ofs) (MT_WF_PHY_BASE + (ofs))
diff --git a/mt7915/testmode.c b/mt7915/testmode.c
-index 99582d9c..2ae6c07f 100644
+index 668f483..23dcabd 100644
--- a/mt7915/testmode.c
+++ b/mt7915/testmode.c
@@ -13,6 +13,12 @@ enum {
@@ -503,7 +503,7 @@
static int
diff --git a/testmode.c b/testmode.c
-index b605a4bc..58280a40 100644
+index b605a4b..58280a4 100644
--- a/testmode.c
+++ b/testmode.c
@@ -24,6 +24,13 @@ const struct nla_policy mt76_tm_policy[NUM_MT76_TM_ATTRS] = {
@@ -567,7 +567,7 @@
nla_put_u8(msg, MT76_TM_ATTR_TX_LTF, td->tx_ltf)) ||
(mt76_testmode_param_present(td, MT76_TM_ATTR_TX_ANTENNA) &&
diff --git a/testmode.h b/testmode.h
-index bbfb313f..e03fa6df 100644
+index bbfb313..e03fa6d 100644
--- a/testmode.h
+++ b/testmode.h
@@ -63,6 +63,20 @@
@@ -635,7 +635,7 @@
+
#endif
diff --git a/tools/fields.c b/tools/fields.c
-index 47fc69f9..6f07eed0 100644
+index 47fc69f..6f07eed 100644
--- a/tools/fields.c
+++ b/tools/fields.c
@@ -46,6 +46,14 @@ static const char * const testmode_txbf_act[] = {
diff --git a/recipes-wifi/linux-mt76/files/patches/1116-mt76-testmode-add-iBF-eBF-cal-and-cert-commands-with.patch b/recipes-wifi/linux-mt76/files/patches/1116-mt76-testmode-add-iBF-eBF-cal-and-cert-commands-with.patch
index 8e9b2aa..fb5bb23 100644
--- a/recipes-wifi/linux-mt76/files/patches/1116-mt76-testmode-add-iBF-eBF-cal-and-cert-commands-with.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1116-mt76-testmode-add-iBF-eBF-cal-and-cert-commands-with.patch
@@ -1,7 +1,7 @@
-From e6da252b1895b1aebdfe737dcd57572d877cd1f1 Mon Sep 17 00:00:00 2001
+From a00620522ddc62d8070077e4d4a1ec18a8402bf9 Mon Sep 17 00:00:00 2001
From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
Date: Thu, 15 Dec 2022 19:45:18 +0800
-Subject: [PATCH 1116/1133] mt76: testmode: add iBF/eBF cal and cert commands
+Subject: [PATCH 1116/1116] mt76: testmode: add iBF/eBF cal and cert commands
with golden
Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
@@ -25,7 +25,7 @@
16 files changed, 856 insertions(+), 324 deletions(-)
diff --git a/mt76.h b/mt76.h
-index d5f5054f..6ab689af 100644
+index d5f5054..6ab689a 100644
--- a/mt76.h
+++ b/mt76.h
@@ -687,6 +687,7 @@ struct mt76_testmode_data {
@@ -47,7 +47,7 @@
u32 tx_pending;
u32 tx_queued;
diff --git a/mt76_connac_mcu.c b/mt76_connac_mcu.c
-index b6c2ccf0..6f5c81ce 100644
+index b6c2ccf..6f5c81c 100644
--- a/mt76_connac_mcu.c
+++ b/mt76_connac_mcu.c
@@ -2802,6 +2802,7 @@ int mt76_connac_mcu_bss_basic_tlv(struct sk_buff *skb,
@@ -68,7 +68,7 @@
memcpy(bss->bssid, phy->macaddr, ETH_ALEN);
}
diff --git a/mt7915/mac.c b/mt7915/mac.c
-index 1460a32b..35b85843 100644
+index 1460a32..35b8584 100644
--- a/mt7915/mac.c
+++ b/mt7915/mac.c
@@ -752,8 +752,10 @@ mt7915_mac_write_txwi_tm(struct mt7915_phy *phy, __le32 *txwi,
@@ -84,7 +84,7 @@
txwi[6] |= cpu_to_le32(val);
#endif
diff --git a/mt7915/main.c b/mt7915/main.c
-index ea0d22fe..ecd023f6 100644
+index 651887c..21ad3b0 100644
--- a/mt7915/main.c
+++ b/mt7915/main.c
@@ -205,46 +205,37 @@ static void mt7915_init_bitrate_mask(struct ieee80211_vif *vif)
@@ -175,7 +175,7 @@
return ret;
diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index 988c55c6..e82b7e14 100644
+index cce622d..d8a1b00 100644
--- a/mt7915/mcu.c
+++ b/mt7915/mcu.c
@@ -193,6 +193,7 @@ mt7915_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
@@ -227,7 +227,7 @@
if (enable) {
mt7915_mcu_bss_rfch_tlv(skb, vif, phy);
-@@ -3452,6 +3466,7 @@ int mt7915_mcu_set_ser(struct mt7915_dev *dev, u8 action, u8 set, u8 band)
+@@ -3453,6 +3467,7 @@ int mt7915_mcu_set_ser(struct mt7915_dev *dev, u8 action, u8 set, u8 band)
int mt7915_mcu_set_txbf(struct mt7915_dev *dev, u8 action)
{
@@ -235,7 +235,7 @@
struct {
u8 action;
union {
-@@ -3478,7 +3493,6 @@ int mt7915_mcu_set_txbf(struct mt7915_dev *dev, u8 action)
+@@ -3479,7 +3494,6 @@ int mt7915_mcu_set_txbf(struct mt7915_dev *dev, u8 action)
.action = action,
};
@@ -243,7 +243,7 @@
switch (action) {
case MT_BF_SOUNDING_ON:
req.snd.snd_mode = MT_BF_PROCESSING;
-@@ -4396,6 +4410,9 @@ int mt7915_mcu_set_txbf_sound_info(struct mt7915_phy *phy, u8 action,
+@@ -4397,6 +4411,9 @@ int mt7915_mcu_set_txbf_sound_info(struct mt7915_phy *phy, u8 action,
req.he_opt = v2;
req.glo_opt = v3;
break;
@@ -254,7 +254,7 @@
return -EINVAL;
}
diff --git a/mt7915/mcu.h b/mt7915/mcu.h
-index d780415c..5c5c92fc 100644
+index d780415..5c5c92f 100644
--- a/mt7915/mcu.h
+++ b/mt7915/mcu.h
@@ -476,10 +476,12 @@ enum {
@@ -448,7 +448,7 @@
MURU_SET_ARB_OP_MODE = 14,
MURU_SET_PLATFORM_TYPE = 25,
diff --git a/mt7915/mmio.c b/mt7915/mmio.c
-index 9a666d0f..95ded131 100644
+index 9a666d0..95ded13 100644
--- a/mt7915/mmio.c
+++ b/mt7915/mmio.c
@@ -133,6 +133,7 @@ static const u32 mt7915_offs[] = {
@@ -468,10 +468,10 @@
[AGG_AALCR0] = 0x028,
[AGG_AWSCR0] = 0x030,
diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
-index 2b42fb11..ae06a7c6 100644
+index e99b586..bb9c374 100644
--- a/mt7915/mt7915.h
+++ b/mt7915/mt7915.h
-@@ -323,7 +323,6 @@ struct mt7915_phy {
+@@ -325,7 +325,6 @@ struct mt7915_phy {
u8 spe_idx;
@@ -479,7 +479,7 @@
bool bf_ever_en;
} test;
#endif
-@@ -428,7 +427,7 @@ struct mt7915_dev {
+@@ -430,7 +429,7 @@ struct mt7915_dev {
void __iomem *dcm;
void __iomem *sku;
@@ -488,7 +488,7 @@
struct {
void *txbf_phase_cal;
void *txbf_pfmu_data;
-@@ -567,6 +566,7 @@ void mt7915_dma_prefetch(struct mt7915_dev *dev);
+@@ -568,6 +567,7 @@ void mt7915_dma_prefetch(struct mt7915_dev *dev);
void mt7915_dma_cleanup(struct mt7915_dev *dev);
int mt7915_dma_reset(struct mt7915_dev *dev, bool force);
int mt7915_txbf_init(struct mt7915_dev *dev);
@@ -496,7 +496,7 @@
void mt7915_init_txpower(struct mt7915_dev *dev,
struct ieee80211_supported_band *sband);
void mt7915_reset(struct mt7915_dev *dev);
-@@ -645,8 +645,10 @@ int mt7915_mcu_fw_log_2_host(struct mt7915_dev *dev, u8 type, u8 ctrl);
+@@ -646,8 +646,10 @@ int mt7915_mcu_fw_log_2_host(struct mt7915_dev *dev, u8 type, u8 ctrl);
int mt7915_mcu_fw_dbg_ctrl(struct mt7915_dev *dev, u32 module, u8 level);
void mt7915_mcu_rx_event(struct mt7915_dev *dev, struct sk_buff *skb);
void mt7915_mcu_exit(struct mt7915_dev *dev);
@@ -508,7 +508,7 @@
static inline u16 mt7915_wtbl_size(struct mt7915_dev *dev)
{
-@@ -783,4 +785,10 @@ enum {
+@@ -784,4 +786,10 @@ enum {
#endif
@@ -520,7 +520,7 @@
+
#endif
diff --git a/mt7915/mtk_debugfs.c b/mt7915/mtk_debugfs.c
-index cba38513..867d52d1 100644
+index 05dc7d5..a130f56 100644
--- a/mt7915/mtk_debugfs.c
+++ b/mt7915/mtk_debugfs.c
@@ -2908,6 +2908,36 @@ mt7915_txpower_level_set(void *data, u64 val)
@@ -573,7 +573,7 @@
debugfs_create_devm_seqfile(dev->mt76.dev, "fw_version", dir,
diff --git a/mt7915/mtk_mcu.c b/mt7915/mtk_mcu.c
-index 143dae26..906c8725 100644
+index 143dae2..906c872 100644
--- a/mt7915/mtk_mcu.c
+++ b/mt7915/mtk_mcu.c
@@ -1,9 +1,10 @@
@@ -836,7 +836,7 @@
+}
+#endif
diff --git a/mt7915/regs.h b/mt7915/regs.h
-index f4b57099..007fd4d2 100644
+index f4b5709..007fd4d 100644
--- a/mt7915/regs.h
+++ b/mt7915/regs.h
@@ -61,6 +61,7 @@ enum offs_rev {
@@ -858,7 +858,7 @@
#define MT_WF_RMAC_BASE(_band) ((_band) ? 0x820f5000 : 0x820e5000)
#define MT_WF_RMAC(_band, ofs) (MT_WF_RMAC_BASE(_band) + (ofs))
diff --git a/mt7915/testmode.c b/mt7915/testmode.c
-index 2ae6c07f..e4af5e1c 100644
+index 23dcabd..ad1865e 100644
--- a/mt7915/testmode.c
+++ b/mt7915/testmode.c
@@ -53,6 +53,8 @@ struct reg_band {
@@ -1701,7 +1701,7 @@
rateval = mode << 6 | rate_idx;
tx_cont->rateval = cpu_to_le16(rateval);
diff --git a/mt7915/testmode.h b/mt7915/testmode.h
-index d500987d..19823694 100644
+index d500987..1982369 100644
--- a/mt7915/testmode.h
+++ b/mt7915/testmode.h
@@ -311,137 +311,7 @@ struct mt7915_tm_muru {
@@ -1845,7 +1845,7 @@
#endif
diff --git a/testmode.c b/testmode.c
-index 58280a40..a6b0c160 100644
+index 58280a4..a6b0c16 100644
--- a/testmode.c
+++ b/testmode.c
@@ -191,6 +191,7 @@ mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len,
@@ -1857,7 +1857,7 @@
memcpy(hdr->addr2, addr[1], ETH_ALEN);
memcpy(hdr->addr3, addr[2], ETH_ALEN);
diff --git a/testmode.h b/testmode.h
-index e03fa6df..0e96173b 100644
+index e03fa6d..0e96173 100644
--- a/testmode.h
+++ b/testmode.h
@@ -299,7 +299,10 @@ enum mt76_testmode_cfg {
@@ -1885,7 +1885,7 @@
/* keep last */
NUM_MT76_TM_TXBF_ACT,
diff --git a/tools/fields.c b/tools/fields.c
-index 6f07eed0..7211ec52 100644
+index 6f07eed..7211ec5 100644
--- a/tools/fields.c
+++ b/tools/fields.c
@@ -33,7 +33,10 @@ static const char * const testmode_tx_mode[] = {
diff --git a/recipes-wifi/linux-mt76/files/patches/1117-mt76-mt7915-init-rssi-in-WTBL-when-add-station.patch b/recipes-wifi/linux-mt76/files/patches/1117-mt76-mt7915-init-rssi-in-WTBL-when-add-station.patch
index 04e2217..43a0ae7 100644
--- a/recipes-wifi/linux-mt76/files/patches/1117-mt76-mt7915-init-rssi-in-WTBL-when-add-station.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1117-mt76-mt7915-init-rssi-in-WTBL-when-add-station.patch
@@ -1,14 +1,14 @@
-From 57e604539560994584444115d893df77a24fafe0 Mon Sep 17 00:00:00 2001
+From 55254f381217a874a2bb20c288107bb3d2f3811d Mon Sep 17 00:00:00 2001
From: Peter Chiu <chui-hao.chiu@mediatek.com>
Date: Sun, 24 Apr 2022 10:07:00 +0800
-Subject: [PATCH 1117/1133] mt76: mt7915: init rssi in WTBL when add station
+Subject: [PATCH 1117/1132] mt76: mt7915: init rssi in WTBL when add station
---
mt7915/main.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/mt7915/main.c b/mt7915/main.c
-index ecd023f6..c32df9b1 100644
+index 21ad3b07..d1135d9f 100644
--- a/mt7915/main.c
+++ b/mt7915/main.c
@@ -692,6 +692,7 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
diff --git a/recipes-wifi/linux-mt76/files/patches/1118-mt76-connac-airtime-fairness-feature-off-in-mac80211.patch b/recipes-wifi/linux-mt76/files/patches/1118-mt76-connac-airtime-fairness-feature-off-in-mac80211.patch
index 27f8787..df0677d 100644
--- a/recipes-wifi/linux-mt76/files/patches/1118-mt76-connac-airtime-fairness-feature-off-in-mac80211.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1118-mt76-connac-airtime-fairness-feature-off-in-mac80211.patch
@@ -1,7 +1,7 @@
-From d0a0b51c3aea4e3a948e70aef7d137a5c4b235f3 Mon Sep 17 00:00:00 2001
+From 8ede062234d043820c188e0d25e68a9f71cb0e28 Mon Sep 17 00:00:00 2001
From: Evelyn Tsai <evelyn.tsai@mediatek.com>
Date: Fri, 6 May 2022 15:58:42 +0800
-Subject: [PATCH 1118/1133] mt76: connac: airtime fairness feature off in
+Subject: [PATCH 1118/1132] mt76: connac: airtime fairness feature off in
mac80211
---
@@ -9,10 +9,10 @@
1 file changed, 1 deletion(-)
diff --git a/mac80211.c b/mac80211.c
-index 2a66b1dd..e79568d1 100644
+index 9107c0c1..e2122c78 100644
--- a/mac80211.c
+++ b/mac80211.c
-@@ -436,7 +436,6 @@ mt76_phy_init(struct mt76_phy *phy, struct ieee80211_hw *hw)
+@@ -437,7 +437,6 @@ mt76_phy_init(struct mt76_phy *phy, struct ieee80211_hw *hw)
WIPHY_FLAG_AP_UAPSD;
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST);
diff --git a/recipes-wifi/linux-mt76/files/patches/1119-mt76-mt7915-add-mt7986-and-mt7916-pre-calibration.patch b/recipes-wifi/linux-mt76/files/patches/1119-mt76-mt7915-add-mt7986-and-mt7916-pre-calibration.patch
index c754c64..026f079 100644
--- a/recipes-wifi/linux-mt76/files/patches/1119-mt76-mt7915-add-mt7986-and-mt7916-pre-calibration.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1119-mt76-mt7915-add-mt7986-and-mt7916-pre-calibration.patch
@@ -1,7 +1,7 @@
-From 1d8b96957fe7ad695caf20a1525118bd48cf34f3 Mon Sep 17 00:00:00 2001
+From 166c44f4a9dfde91ac01c1cd04f79a3b9c8fe23e Mon Sep 17 00:00:00 2001
From: Peter Chiu <chui-hao.chiu@mediatek.com>
Date: Fri, 20 May 2022 19:19:25 +0800
-Subject: [PATCH 1119/1133] mt76: mt7915: add mt7986 and mt7916 pre-calibration
+Subject: [PATCH 1119/1132] mt76: mt7915: add mt7986 and mt7916 pre-calibration
Add pre-calibration for mt7986 and mt7916. It has different data size
with mt7915. Group cal needs 54k and 94k for 2G + 5G and 2G + 6G,
@@ -62,10 +62,10 @@
MT_EE_RATE_DELTA_5G = 0x29d,
MT_EE_TX0_POWER_2G = 0x2fc,
diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index d8a1b00e..185b6495 100644
+index e5cb9317..7da5bdfb 100644
--- a/mt7915/mcu.c
+++ b/mt7915/mcu.c
-@@ -2967,7 +2967,8 @@ static int mt7915_mcu_set_pre_cal(struct mt7915_dev *dev, u8 idx,
+@@ -2969,7 +2969,8 @@ static int mt7915_mcu_set_pre_cal(struct mt7915_dev *dev, u8 idx,
int mt7915_mcu_apply_group_cal(struct mt7915_dev *dev)
{
u8 idx = 0, *cal = dev->cal, *eep = dev->mt76.eeprom.data;
@@ -75,7 +75,7 @@
if (!(eep[offs] & MT_EE_WIFI_CAL_GROUP))
return 0;
-@@ -3005,9 +3006,9 @@ static int mt7915_find_freq_idx(const u16 *freqs, int n_freqs, u16 cur)
+@@ -3007,9 +3008,9 @@ static int mt7915_find_freq_idx(const u16 *freqs, int n_freqs, u16 cur)
return -1;
}
@@ -87,7 +87,7 @@
5180, 5200, 5220, 5240,
5260, 5280, 5300, 5320,
5500, 5520, 5540, 5560,
-@@ -3015,34 +3016,69 @@ static int mt7915_dpd_freq_idx(u16 freq, u8 bw)
+@@ -3017,34 +3018,69 @@ static int mt7915_dpd_freq_idx(u16 freq, u8 bw)
5660, 5680, 5700, 5745,
5765, 5785, 5805, 5825
};
@@ -167,7 +167,7 @@
}
int mt7915_mcu_apply_tx_dpd(struct mt7915_phy *phy)
-@@ -3074,24 +3110,24 @@ int mt7915_mcu_apply_tx_dpd(struct mt7915_phy *phy)
+@@ -3076,24 +3112,24 @@ int mt7915_mcu_apply_tx_dpd(struct mt7915_phy *phy)
if (!(eep[offs] & dpd_mask))
return 0;
diff --git a/recipes-wifi/linux-mt76/files/patches/1120-mt76-mt7915-add-phy-capability-vendor-command.patch b/recipes-wifi/linux-mt76/files/patches/1120-mt76-mt7915-add-phy-capability-vendor-command.patch
index 302d0ab..de77b3a 100644
--- a/recipes-wifi/linux-mt76/files/patches/1120-mt76-mt7915-add-phy-capability-vendor-command.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1120-mt76-mt7915-add-phy-capability-vendor-command.patch
@@ -1,7 +1,7 @@
-From 99d36c925c886a383d62fb3e9d009265161cf62a Mon Sep 17 00:00:00 2001
+From d181881aaeb24db4a51c75ac607eaeacc252e050 Mon Sep 17 00:00:00 2001
From: Yi-Chia Hsieh <Yi-Chia.Hsieh@mediatek.com>
Date: Tue, 12 Jul 2022 10:04:35 -0700
-Subject: [PATCH 1120/1133] mt76: mt7915: add phy capability vendor command
+Subject: [PATCH 1120/1132] mt76: mt7915: add phy capability vendor command
---
mt7915/mt7915.h | 1 +
@@ -22,7 +22,7 @@
#define MT7916_WTBL_SIZE 544
#define MT7915_WTBL_RESERVED (mt7915_wtbl_size(dev) - 1)
diff --git a/mt7915/vendor.c b/mt7915/vendor.c
-index 5acbd2d7..526eb6b2 100644
+index 8d864c86..607e66bb 100644
--- a/mt7915/vendor.c
+++ b/mt7915/vendor.c
@@ -50,6 +50,18 @@ rfeature_ctrl_policy[NUM_MTK_VENDOR_ATTRS_RFEATURE_CTRL] = {
@@ -99,7 +99,7 @@
};
diff --git a/mt7915/vendor.h b/mt7915/vendor.h
-index a8e4ebf9..719b851f 100644
+index 2be5fc89..ffdb466b 100644
--- a/mt7915/vendor.h
+++ b/mt7915/vendor.h
@@ -9,6 +9,7 @@ enum mtk_nl80211_vendor_subcmds {
diff --git a/recipes-wifi/linux-mt76/files/patches/1121-mt76-mt7915-add-vendor-subcmd-EDCCA-ctrl-enable-thre.patch b/recipes-wifi/linux-mt76/files/patches/1121-mt76-mt7915-add-vendor-subcmd-EDCCA-ctrl-enable-thre.patch
index ca559be..fc68b4d 100644
--- a/recipes-wifi/linux-mt76/files/patches/1121-mt76-mt7915-add-vendor-subcmd-EDCCA-ctrl-enable-thre.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1121-mt76-mt7915-add-vendor-subcmd-EDCCA-ctrl-enable-thre.patch
@@ -1,7 +1,7 @@
-From 9f4ef5f8637f597acf5fc876d40f9159e051e512 Mon Sep 17 00:00:00 2001
+From 0519381004e17ba76e11bda6d806bc5a4aedd013 Mon Sep 17 00:00:00 2001
From: Howard Hsu <howard-yh.hsu@mediatek.com>
Date: Fri, 24 Jun 2022 11:15:45 +0800
-Subject: [PATCH] mt76: mt7915: add vendor subcmd EDCCA ctrl
+Subject: [PATCH 1121/1132] mt76: mt7915: add vendor subcmd EDCCA ctrl
enable/threshold/compensation
Change-Id: I06a3f94d5e444be894200e2b6588d76ed38d09d0
@@ -16,10 +16,10 @@
7 files changed, 265 insertions(+), 1 deletion(-)
diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index 5cef308a..65863a0d 100644
+index f4a329e8..e04500f5 100644
--- a/mt76_connac_mcu.h
+++ b/mt76_connac_mcu.h
-@@ -1205,6 +1205,7 @@ enum {
+@@ -1202,6 +1202,7 @@ enum {
MCU_EXT_CMD_SMESH_CTRL = 0xae,
MCU_EXT_CMD_RX_STAT_USER_CTRL = 0xb3,
MCU_EXT_CMD_CERT_CFG = 0xb7,
@@ -42,10 +42,10 @@
ret = mt7915_set_channel(phy);
if (ret)
diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index 185b6495..85bb60c9 100644
+index 7da5bdfb..28b2a624 100644
--- a/mt7915/mcu.c
+++ b/mt7915/mcu.c
-@@ -4623,3 +4623,76 @@ int mt7915_mcu_ipi_hist_scan(struct mt7915_phy *phy, void *data, u8 mode, bool w
+@@ -4625,3 +4625,76 @@ int mt7915_mcu_ipi_hist_scan(struct mt7915_phy *phy, void *data, u8 mode, bool w
return 0;
}
@@ -123,7 +123,7 @@
+ return 0;
+}
diff --git a/mt7915/mcu.h b/mt7915/mcu.h
-index 5c5c92fc..c87fe8e8 100644
+index 7d1dc500..7558726c 100644
--- a/mt7915/mcu.h
+++ b/mt7915/mcu.h
@@ -1058,6 +1058,27 @@ enum {
@@ -169,7 +169,7 @@
int mt7915_mcu_ipi_hist_scan(struct mt7915_phy *phy, void *data, u8 mode, bool wait_resp);
diff --git a/mt7915/vendor.c b/mt7915/vendor.c
-index 526eb6b2..f712d67c 100644
+index 607e66bb..e748ab16 100644
--- a/mt7915/vendor.c
+++ b/mt7915/vendor.c
@@ -62,6 +62,24 @@ phy_capa_dump_policy[NUM_MTK_VENDOR_ATTRS_PHY_CAPA_DUMP] = {
@@ -326,7 +326,7 @@
};
diff --git a/mt7915/vendor.h b/mt7915/vendor.h
-index 719b851f..72319717 100644
+index ffdb466b..0c96377f 100644
--- a/mt7915/vendor.h
+++ b/mt7915/vendor.h
@@ -2,6 +2,7 @@
diff --git a/recipes-wifi/linux-mt76/files/patches/1122-mt76-mt7915-implement-bin-file-mode.patch b/recipes-wifi/linux-mt76/files/patches/1122-mt76-mt7915-implement-bin-file-mode.patch
index fdd6c4d..c9c4ad9 100644
--- a/recipes-wifi/linux-mt76/files/patches/1122-mt76-mt7915-implement-bin-file-mode.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1122-mt76-mt7915-implement-bin-file-mode.patch
@@ -1,7 +1,7 @@
-From 8a6c47c698f273485f749c8aa2c3fd2b6a946c86 Mon Sep 17 00:00:00 2001
+From 5650267fdb5d7e237e58908b5f11c9bd12170c3a Mon Sep 17 00:00:00 2001
From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
Date: Thu, 7 Jul 2022 11:09:59 +0800
-Subject: [PATCH 1122/1133] mt76: mt7915: implement bin file mode
+Subject: [PATCH 1122/1132] mt76: mt7915: implement bin file mode
Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
@@ -46,10 +46,10 @@
mt76_eeprom_override(struct mt76_phy *phy)
{
diff --git a/mt76.h b/mt76.h
-index 6ab689af..1638ef63 100644
+index 4cbe3670..675c12a4 100644
--- a/mt76.h
+++ b/mt76.h
-@@ -900,9 +900,11 @@ struct mt76_dev {
+@@ -901,9 +901,11 @@ struct mt76_dev {
struct mt76_sdio sdio;
};
@@ -61,7 +61,7 @@
};
struct mt76_power_limits {
-@@ -1039,6 +1041,7 @@ void mt76_seq_puts_array(struct seq_file *file, const char *str,
+@@ -1040,6 +1042,7 @@ void mt76_seq_puts_array(struct seq_file *file, const char *str,
int mt76_eeprom_init(struct mt76_dev *dev, int len);
void mt76_eeprom_override(struct mt76_phy *phy);
int mt76_get_of_eeprom(struct mt76_dev *dev, void *data, int offset, int len);
@@ -203,7 +203,7 @@
#define PKT_BIN_DEBUG_MAGIC 0xc8763123
enum {
diff --git a/mt7915/mtk_debugfs.c b/mt7915/mtk_debugfs.c
-index da444f38..5f34afc7 100644
+index a130f564..1f347efe 100644
--- a/mt7915/mtk_debugfs.c
+++ b/mt7915/mtk_debugfs.c
@@ -3,6 +3,7 @@
diff --git a/recipes-wifi/linux-mt76/files/patches/1123-mt76-mt7915-initialize-wcid.patch b/recipes-wifi/linux-mt76/files/patches/1123-mt76-mt7915-initialize-wcid.patch
index 066630e..8c0393c 100644
--- a/recipes-wifi/linux-mt76/files/patches/1123-mt76-mt7915-initialize-wcid.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1123-mt76-mt7915-initialize-wcid.patch
@@ -1,7 +1,7 @@
-From 9758ae301b7a08ace837a88d9534c7f22e4fef7f Mon Sep 17 00:00:00 2001
+From 76dcae6805d85864d5ebea700fcc488f80fbd75d Mon Sep 17 00:00:00 2001
From: Sujuan Chen <sujuan.chen@mediatek.com>
Date: Tue, 12 Jul 2022 13:56:07 +0800
-Subject: [PATCH 1123/1133] mt76: mt7915: initialize wcid
+Subject: [PATCH 1123/1132] mt76: mt7915: initialize wcid
Signed-off-by: Sujuan Chen <sujuan.chen@mediatek.com>
---
diff --git a/recipes-wifi/linux-mt76/files/patches/1124-mt76-mt7915-Add-mu-dump-support.patch b/recipes-wifi/linux-mt76/files/patches/1124-mt76-mt7915-Add-mu-dump-support.patch
index b3789c3..bac5e25 100644
--- a/recipes-wifi/linux-mt76/files/patches/1124-mt76-mt7915-Add-mu-dump-support.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1124-mt76-mt7915-Add-mu-dump-support.patch
@@ -1,7 +1,7 @@
-From dc1ea53db698073c61765925cdb17d28043c6f2d Mon Sep 17 00:00:00 2001
+From 0dbdca6f8f719929258c851bccd3dacbe78c4ad5 Mon Sep 17 00:00:00 2001
From: TomLiu <tomml.liu@mediatek.com>
Date: Thu, 11 Aug 2022 18:09:45 -0700
-Subject: [PATCH 1124/1133] mt76: mt7915: Add mu dump support
+Subject: [PATCH 1124/1132] mt76: mt7915: Add mu dump support
Change-Id: I521214f3feb6f0d528a9f550255050ffd1ec96d2
---
@@ -10,7 +10,7 @@
2 files changed, 25 insertions(+)
diff --git a/mt7915/vendor.c b/mt7915/vendor.c
-index f712d67c..83f38e07 100644
+index e748ab16..6915ac8d 100644
--- a/mt7915/vendor.c
+++ b/mt7915/vendor.c
@@ -37,6 +37,7 @@ wireless_ctrl_policy[NUM_MTK_VENDOR_ATTRS_WIRELESS_CTRL] = {
@@ -59,7 +59,7 @@
.maxattr = MTK_VENDOR_ATTR_MU_CTRL_MAX,
},
diff --git a/mt7915/vendor.h b/mt7915/vendor.h
-index 72319717..c19ffe72 100644
+index 0c96377f..d8e23d34 100644
--- a/mt7915/vendor.h
+++ b/mt7915/vendor.h
@@ -72,6 +72,7 @@ enum mtk_vendor_attr_mu_ctrl {
diff --git a/recipes-wifi/linux-mt76/files/patches/1125-mt76-mt7915-add-vendor-subcmd-three-wire-PTA-ctrl.patch b/recipes-wifi/linux-mt76/files/patches/1125-mt76-mt7915-add-vendor-subcmd-three-wire-PTA-ctrl.patch
index cd5fd8f..066ae83 100644
--- a/recipes-wifi/linux-mt76/files/patches/1125-mt76-mt7915-add-vendor-subcmd-three-wire-PTA-ctrl.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1125-mt76-mt7915-add-vendor-subcmd-three-wire-PTA-ctrl.patch
@@ -1,7 +1,7 @@
-From 6d68ed1f6ead694289dc9d2a98ef3d49dcb778dd Mon Sep 17 00:00:00 2001
+From 305cf303e1ab242784019ff78a2b534f7c9df707 Mon Sep 17 00:00:00 2001
From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
Date: Fri, 28 Oct 2022 10:15:56 +0800
-Subject: [PATCH 1125/1133] mt76: mt7915: add vendor subcmd three wire (PTA)
+Subject: [PATCH 1125/1132] mt76: mt7915: add vendor subcmd three wire (PTA)
ctrl
Change-Id: Ic1044698f294455594a0c6254f55326fdab90580
@@ -16,10 +16,10 @@
6 files changed, 111 insertions(+), 29 deletions(-)
diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index 65863a0d..41859dc3 100644
+index e04500f5..1ff517f0 100644
--- a/mt76_connac_mcu.h
+++ b/mt76_connac_mcu.h
-@@ -1204,7 +1204,7 @@ enum {
+@@ -1201,7 +1201,7 @@ enum {
/* for vendor csi and air monitor */
MCU_EXT_CMD_SMESH_CTRL = 0xae,
MCU_EXT_CMD_RX_STAT_USER_CTRL = 0xb3,
@@ -29,10 +29,10 @@
MCU_EXT_CMD_CSI_CTRL = 0xc2,
MCU_EXT_CMD_IPI_HIST_SCAN = 0xc5,
diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index 3408555e..ebe00300 100644
+index 28b2a624..baf74440 100644
--- a/mt7915/mcu.c
+++ b/mt7915/mcu.c
-@@ -4322,37 +4322,33 @@ void mt7915_mcu_set_dynalgo(struct mt7915_phy *phy, u8 enable)
+@@ -4324,37 +4324,33 @@ void mt7915_mcu_set_dynalgo(struct mt7915_phy *phy, u8 enable)
&req, sizeof(req), false);
}
@@ -94,7 +94,7 @@
void mt7915_mcu_set_bypass_smthint(struct mt7915_phy *phy, u8 val)
diff --git a/mt7915/mcu.h b/mt7915/mcu.h
-index c87fe8e8..16517099 100644
+index 7558726c..0aee6948 100644
--- a/mt7915/mcu.h
+++ b/mt7915/mcu.h
@@ -847,6 +847,35 @@ struct mt7915_mcu_rdd_ipi_scan {
@@ -146,7 +146,7 @@
void mt7915_vendor_register(struct mt7915_phy *phy);
int mt7915_mcu_set_csi(struct mt7915_phy *phy, u8 mode,
diff --git a/mt7915/vendor.c b/mt7915/vendor.c
-index 83f38e07..48d124e0 100644
+index 6915ac8d..b26b1cc6 100644
--- a/mt7915/vendor.c
+++ b/mt7915/vendor.c
@@ -40,6 +40,11 @@ mu_ctrl_policy[NUM_MTK_VENDOR_ATTRS_MU_CTRL] = {
@@ -229,7 +229,7 @@
};
diff --git a/mt7915/vendor.h b/mt7915/vendor.h
-index c19ffe72..d96e5c23 100644
+index d8e23d34..de3cbe2c 100644
--- a/mt7915/vendor.h
+++ b/mt7915/vendor.h
@@ -12,6 +12,7 @@ enum mtk_nl80211_vendor_subcmds {
diff --git a/recipes-wifi/linux-mt76/files/patches/1126-mt76-mt7915-add-ibf-control-vendor-cmd.patch b/recipes-wifi/linux-mt76/files/patches/1126-mt76-mt7915-add-ibf-control-vendor-cmd.patch
index 1fa6a9a..72672ac 100644
--- a/recipes-wifi/linux-mt76/files/patches/1126-mt76-mt7915-add-ibf-control-vendor-cmd.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1126-mt76-mt7915-add-ibf-control-vendor-cmd.patch
@@ -1,7 +1,7 @@
-From 169a6fe9914e6480b9981f5cd6a3911e8700e46c Mon Sep 17 00:00:00 2001
+From 2557e2878455ac38e0458a34d8e9fa4c0fcabe7e Mon Sep 17 00:00:00 2001
From: mtk27835 <shurong.wen@mediatek.com>
Date: Wed, 7 Sep 2022 14:01:29 -0700
-Subject: [PATCH 1126/1133] mt76: mt7915: add ibf control vendor cmd
+Subject: [PATCH 1126/1132] mt76: mt7915: add ibf control vendor cmd
Signed-off-by: mtk27835 <shurong.wen@mediatek.com>
---
@@ -10,7 +10,7 @@
2 files changed, 89 insertions(+), 1 deletion(-)
diff --git a/mt7915/vendor.c b/mt7915/vendor.c
-index 48d124e0..9cd6e811 100644
+index b26b1cc6..3e5c479e 100644
--- a/mt7915/vendor.c
+++ b/mt7915/vendor.c
@@ -86,6 +86,11 @@ edcca_dump_policy[NUM_MTK_VENDOR_ATTRS_EDCCA_DUMP] = {
@@ -100,7 +100,7 @@
};
diff --git a/mt7915/vendor.h b/mt7915/vendor.h
-index d96e5c23..949c8853 100644
+index de3cbe2c..a6309a32 100644
--- a/mt7915/vendor.h
+++ b/mt7915/vendor.h
@@ -12,7 +12,8 @@ enum mtk_nl80211_vendor_subcmds {
diff --git a/recipes-wifi/linux-mt76/files/patches/1127-mt76-mt7915-add-E3-re-bonding-for-low-yield-rate-iss.patch b/recipes-wifi/linux-mt76/files/patches/1127-mt76-mt7915-add-E3-re-bonding-for-low-yield-rate-iss.patch
index b06c540..1669e0c 100644
--- a/recipes-wifi/linux-mt76/files/patches/1127-mt76-mt7915-add-E3-re-bonding-for-low-yield-rate-iss.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1127-mt76-mt7915-add-E3-re-bonding-for-low-yield-rate-iss.patch
@@ -1,7 +1,7 @@
-From 2cd8e8385970f43311305c6849b31cd86cc40f5a Mon Sep 17 00:00:00 2001
+From 8f2a166a0af3f1c6b1f77335685beb56b9d908f3 Mon Sep 17 00:00:00 2001
From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
Date: Thu, 13 Oct 2022 13:22:05 +0800
-Subject: [PATCH 1127/1133] mt76: mt7915: add E3 re-bonding for low yield rate
+Subject: [PATCH 1127/1132] mt76: mt7915: add E3 re-bonding for low yield rate
issue
Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
@@ -64,10 +64,10 @@
if (ret)
return ret;
diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index ebe00300..292351fb 100644
+index baf74440..9d934748 100644
--- a/mt7915/mcu.c
+++ b/mt7915/mcu.c
-@@ -2886,7 +2886,7 @@ int mt7915_mcu_set_eeprom(struct mt7915_dev *dev, bool flash_mode)
+@@ -2888,7 +2888,7 @@ int mt7915_mcu_set_eeprom(struct mt7915_dev *dev, bool flash_mode)
&req, sizeof(req), true);
}
@@ -76,7 +76,7 @@
{
struct mt7915_mcu_eeprom_info req = {
.addr = cpu_to_le32(round_down(offset,
-@@ -2904,8 +2904,15 @@ int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset)
+@@ -2906,8 +2906,15 @@ int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset)
return ret;
res = (struct mt7915_mcu_eeprom_info *)skb->data;
diff --git a/recipes-wifi/linux-mt76/files/patches/1128-mt76-mt7915-support-on-off-SW-ACI-through-debugfs.patch b/recipes-wifi/linux-mt76/files/patches/1128-mt76-mt7915-support-on-off-SW-ACI-through-debugfs.patch
index 3fc342b..998228b 100644
--- a/recipes-wifi/linux-mt76/files/patches/1128-mt76-mt7915-support-on-off-SW-ACI-through-debugfs.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1128-mt76-mt7915-support-on-off-SW-ACI-through-debugfs.patch
@@ -1,7 +1,7 @@
-From 7cc147efe8e493d163b9670b8b737fd3bf8d59e0 Mon Sep 17 00:00:00 2001
+From 19ed70a278de504a58054906f9b25b4f5c3cf3d0 Mon Sep 17 00:00:00 2001
From: Evelyn Tsai <evelyn.tsai@mediatek.com>
Date: Fri, 14 Oct 2022 11:15:13 +0800
-Subject: [PATCH 1128/1133] mt76: mt7915: support on off SW ACI through debugfs
+Subject: [PATCH 1128/1132] mt76: mt7915: support on off SW ACI through debugfs
Signed-off-by: Evelyn Tsai <evelyn.tsai@mediatek.com>
Change-Id: I8a9c277c41d1ba76f9737d8af6f42e5e8f00ba64
@@ -11,10 +11,10 @@
2 files changed, 22 insertions(+)
diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index 41859dc3..73a5509a 100644
+index 1ff517f0..1a13cee0 100644
--- a/mt76_connac_mcu.h
+++ b/mt76_connac_mcu.h
-@@ -1206,6 +1206,7 @@ enum {
+@@ -1203,6 +1203,7 @@ enum {
MCU_EXT_CMD_RX_STAT_USER_CTRL = 0xb3,
MCU_EXT_CMD_SET_CFG = 0xb7,
MCU_EXT_CMD_EDCCA = 0xba,
@@ -23,7 +23,7 @@
MCU_EXT_CMD_IPI_HIST_SCAN = 0xc5,
};
diff --git a/mt7915/mtk_debugfs.c b/mt7915/mtk_debugfs.c
-index 5f34afc7..b99519dd 100644
+index 1f347efe..224d9960 100644
--- a/mt7915/mtk_debugfs.c
+++ b/mt7915/mtk_debugfs.c
@@ -3040,6 +3040,25 @@ static int mt7915_show_eeprom_mode(struct seq_file *s, void *data)
diff --git a/recipes-wifi/linux-mt76/files/patches/1129-mt76-mt7915-add-bf-backoff-limit-table-support.patch b/recipes-wifi/linux-mt76/files/patches/1129-mt76-mt7915-add-bf-backoff-limit-table-support.patch
index c916131..213e390 100644
--- a/recipes-wifi/linux-mt76/files/patches/1129-mt76-mt7915-add-bf-backoff-limit-table-support.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1129-mt76-mt7915-add-bf-backoff-limit-table-support.patch
@@ -1,7 +1,7 @@
-From cd6e64e5bdea2ee410c1cc8e83f78322bf9f3982 Mon Sep 17 00:00:00 2001
+From 82351f298ec49641998232fb648606996b3c5a37 Mon Sep 17 00:00:00 2001
From: Shayne Chen <shayne.chen@mediatek.com>
Date: Mon, 5 Dec 2022 18:21:51 +0800
-Subject: [PATCH 1129/1133] mt76: mt7915: add bf backoff limit table support
+Subject: [PATCH 1129/1132] mt76: mt7915: add bf backoff limit table support
Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
---
@@ -57,10 +57,10 @@
}
EXPORT_SYMBOL_GPL(mt76_get_rate_power_limits);
diff --git a/mt76.h b/mt76.h
-index 1638ef63..5e24d03c 100644
+index 675c12a4..dbb120cc 100644
--- a/mt76.h
+++ b/mt76.h
-@@ -912,6 +912,14 @@ struct mt76_power_limits {
+@@ -913,6 +913,14 @@ struct mt76_power_limits {
s8 ofdm[8];
s8 mcs[4][10];
s8 ru[7][12];
@@ -188,10 +188,10 @@
mt7915_twt_stats);
debugfs_create_file("rf_regval", 0600, dir, dev, &fops_rf_regval);
diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index 292351fb..ff309294 100644
+index 9d934748..5e74ed6e 100644
--- a/mt7915/mcu.c
+++ b/mt7915/mcu.c
-@@ -3331,7 +3331,8 @@ int mt7915_mcu_set_txpower_frame(struct mt7915_phy *phy,
+@@ -3333,7 +3333,8 @@ int mt7915_mcu_set_txpower_frame(struct mt7915_phy *phy,
int ret;
s8 txpower_sku[MT7915_SKU_RATE_NUM];
@@ -201,7 +201,7 @@
if (ret)
return ret;
-@@ -3373,51 +3374,98 @@ int mt7915_mcu_set_txpower_frame(struct mt7915_phy *phy,
+@@ -3375,51 +3376,98 @@ int mt7915_mcu_set_txpower_frame(struct mt7915_phy *phy,
int mt7915_mcu_set_txpower_sku(struct mt7915_phy *phy)
{
@@ -325,7 +325,7 @@
struct mt7915_dev *dev = phy->dev;
struct {
u8 format_id;
-@@ -3426,10 +3474,9 @@ int mt7915_mcu_get_txpower_sku(struct mt7915_phy *phy, s8 *txpower, int len)
+@@ -3428,10 +3476,9 @@ int mt7915_mcu_get_txpower_sku(struct mt7915_phy *phy, s8 *txpower, int len)
u8 _rsv;
} __packed req = {
.format_id = TX_POWER_LIMIT_INFO,
@@ -337,7 +337,7 @@
struct sk_buff *skb;
int ret, i;
-@@ -3439,9 +3486,15 @@ int mt7915_mcu_get_txpower_sku(struct mt7915_phy *phy, s8 *txpower, int len)
+@@ -3441,9 +3488,15 @@ int mt7915_mcu_get_txpower_sku(struct mt7915_phy *phy, s8 *txpower, int len)
if (ret)
return ret;
@@ -356,7 +356,7 @@
dev_kfree_skb(skb);
-@@ -3483,9 +3536,18 @@ int mt7915_mcu_set_sku_en(struct mt7915_phy *phy, bool enable)
+@@ -3485,9 +3538,18 @@ int mt7915_mcu_set_sku_en(struct mt7915_phy *phy, bool enable)
.band_idx = phy->mt76->band_idx,
.sku_enable = enable,
};
@@ -376,7 +376,7 @@
MCU_EXT_CMD(TX_POWER_FEATURE_CTRL), &req,
sizeof(req), true);
diff --git a/mt7915/mcu.h b/mt7915/mcu.h
-index 16517099..e869a9f5 100644
+index 0aee6948..a07bb9ac 100644
--- a/mt7915/mcu.h
+++ b/mt7915/mcu.h
@@ -447,12 +447,18 @@ enum {
diff --git a/recipes-wifi/linux-mt76/files/patches/1130-mt76-mt7915-amsdu-set-and-get-control.patch b/recipes-wifi/linux-mt76/files/patches/1130-mt76-mt7915-amsdu-set-and-get-control.patch
index 54ca9d2..be8c506 100644
--- a/recipes-wifi/linux-mt76/files/patches/1130-mt76-mt7915-amsdu-set-and-get-control.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1130-mt76-mt7915-amsdu-set-and-get-control.patch
@@ -1,7 +1,7 @@
-From 3991eb6b59ffaf4f30815206fb451bc32e2e2af6 Mon Sep 17 00:00:00 2001
+From dc16e6198fe467ca6db8701ba98f5dbdfecc1211 Mon Sep 17 00:00:00 2001
From: TomLiu <tomml.liu@mediatek.com>
Date: Wed, 14 Dec 2022 00:44:07 -0800
-Subject: [PATCH 1130/1133] mt76: mt7915: amsdu set and get control
+Subject: [PATCH 1130/1132] mt76: mt7915: amsdu set and get control
---
mt7915/mac.c | 10 ++++++++++
@@ -44,7 +44,7 @@
void mt7915_set_wireless_vif(void *data, u8 *mac, struct ieee80211_vif *vif);
void mt7915_mcu_set_rfeature_starec(void *data, struct mt7915_dev *dev,
diff --git a/mt7915/vendor.c b/mt7915/vendor.c
-index 9cd6e811..766fa595 100644
+index 3e5c479e..2e5f07c3 100644
--- a/mt7915/vendor.c
+++ b/mt7915/vendor.c
@@ -30,10 +30,16 @@ wireless_ctrl_policy[NUM_MTK_VENDOR_ATTRS_WIRELESS_CTRL] = {
@@ -109,7 +109,7 @@
.maxattr = MTK_VENDOR_ATTR_WIRELESS_CTRL_MAX,
},
diff --git a/mt7915/vendor.h b/mt7915/vendor.h
-index 949c8853..cbff910b 100644
+index a6309a32..33c75dc9 100644
--- a/mt7915/vendor.h
+++ b/mt7915/vendor.h
@@ -74,6 +74,7 @@ enum mtk_vendor_attr_wireless_ctrl {
diff --git a/recipes-wifi/linux-mt76/files/patches/1131-wifi-mt76-mt7915-add-support-for-he-ldpc-control-fro.patch b/recipes-wifi/linux-mt76/files/patches/1131-wifi-mt76-mt7915-add-support-for-he-ldpc-control-fro.patch
index ef0375b..6da2c9f 100644
--- a/recipes-wifi/linux-mt76/files/patches/1131-wifi-mt76-mt7915-add-support-for-he-ldpc-control-fro.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1131-wifi-mt76-mt7915-add-support-for-he-ldpc-control-fro.patch
@@ -1,7 +1,7 @@
-From 1fb0932ca2be712c94a8f57be5a7069541266201 Mon Sep 17 00:00:00 2001
+From 60271e19265ab37376b428decece440458156aa2 Mon Sep 17 00:00:00 2001
From: MeiChia Chiu <meichia.chiu@mediatek.com>
Date: Thu, 12 Jan 2023 15:15:42 +0800
-Subject: [PATCH 1131/1133] wifi: mt76: mt7915: add support for he ldpc control
+Subject: [PATCH 1131/1132] wifi: mt76: mt7915: add support for he ldpc control
from hostapd
---
@@ -9,7 +9,7 @@
1 file changed, 1 insertion(+)
diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index ff309294..2cfad0a3 100644
+index 5e74ed6e..dffd1761 100644
--- a/mt7915/mcu.c
+++ b/mt7915/mcu.c
@@ -1983,6 +1983,7 @@ mt7915_mcu_beacon_check_caps(struct mt7915_phy *phy, struct ieee80211_vif *vif,
diff --git a/recipes-wifi/linux-mt76/files/patches/1132-mt76-mt7915-Add-vendor-command-attribute-for-RTS-BW-.patch b/recipes-wifi/linux-mt76/files/patches/1132-mt76-mt7915-Add-vendor-command-attribute-for-RTS-BW-.patch
index 6a891bf..dea4ae5 100644
--- a/recipes-wifi/linux-mt76/files/patches/1132-mt76-mt7915-Add-vendor-command-attribute-for-RTS-BW-.patch
+++ b/recipes-wifi/linux-mt76/files/patches/1132-mt76-mt7915-Add-vendor-command-attribute-for-RTS-BW-.patch
@@ -1,7 +1,7 @@
-From 610518420411975d6d4cb88c722a8abf645c88f2 Mon Sep 17 00:00:00 2001
+From 81f9124f106441a6ac2f9c43efb9de9f5cc60cb4 Mon Sep 17 00:00:00 2001
From: "himanshu.goyal" <himanshu.goyal@mediatek.com>
Date: Tue, 24 Jan 2023 14:32:08 +0800
-Subject: [PATCH 1132/1133] mt76: mt7915: Add vendor command attribute for RTS
+Subject: [PATCH 1132/1132] mt76: mt7915: Add vendor command attribute for RTS
BW signaling.
Signed-off-by: himanshu.goyal <himanshu.goyal@mediatek.com>
@@ -13,10 +13,10 @@
4 files changed, 20 insertions(+)
diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index 2cfad0a3..4f1d2fe6 100644
+index dffd1761..e07197d0 100644
--- a/mt7915/mcu.c
+++ b/mt7915/mcu.c
-@@ -4408,6 +4408,12 @@ int mt7915_mcu_set_cfg(struct mt7915_phy *phy, u8 cfg_info, u8 type)
+@@ -4410,6 +4410,12 @@ int mt7915_mcu_set_cfg(struct mt7915_phy *phy, u8 cfg_info, u8 type)
req.cert.length = cpu_to_le16(tlv_len);
req.cert.cert_program = type;
break;
@@ -30,7 +30,7 @@
tlv_len = sizeof(struct three_wire_cfg);
req.three_wire.tag = cpu_to_le16(cfg_info);
diff --git a/mt7915/mcu.h b/mt7915/mcu.h
-index e869a9f5..03ee600a 100644
+index a07bb9ac..8cbd37ca 100644
--- a/mt7915/mcu.h
+++ b/mt7915/mcu.h
@@ -867,6 +867,13 @@ struct three_wire_cfg {
@@ -62,7 +62,7 @@
};
diff --git a/mt7915/vendor.c b/mt7915/vendor.c
-index 766fa595..7fbf67d6 100644
+index 2e5f07c3..3b7ac098 100644
--- a/mt7915/vendor.c
+++ b/mt7915/vendor.c
@@ -33,6 +33,7 @@ wireless_ctrl_policy[NUM_MTK_VENDOR_ATTRS_WIRELESS_CTRL] = {
@@ -84,7 +84,7 @@
return 0;
diff --git a/mt7915/vendor.h b/mt7915/vendor.h
-index cbff910b..41d6ff26 100644
+index 33c75dc9..6001ce4a 100644
--- a/mt7915/vendor.h
+++ b/mt7915/vendor.h
@@ -76,6 +76,7 @@ enum mtk_vendor_attr_wireless_ctrl {
diff --git a/recipes-wifi/linux-mt76/files/patches/1133-mt76-mt7915-Allow-AP-to-change-channel-width-for-40M.patch b/recipes-wifi/linux-mt76/files/patches/1133-mt76-mt7915-Allow-AP-to-change-channel-width-for-40M.patch
deleted file mode 100644
index 5f558ea..0000000
--- a/recipes-wifi/linux-mt76/files/patches/1133-mt76-mt7915-Allow-AP-to-change-channel-width-for-40M.patch
+++ /dev/null
@@ -1,30 +0,0 @@
-From 48e04e1209ec16bdb258c13a2939ad48f29deec1 Mon Sep 17 00:00:00 2001
-From: "himanshu.goyal" <himanshu.goyal@mediatek.com>
-Date: Mon, 30 Jan 2023 17:47:06 +0800
-Subject: [PATCH 1133/1133] mt76: mt7915: Allow AP to change channel width for
- 40Mhz Intolerant STA
-
-Ref: WFA 11n Test Case: 4.2.41 AP 20/40 MHz Coexistence
-
-Signed-off-by: himanshu.goyal <himanshu.goyal@mediatek.com>
----
- mac80211.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/mac80211.c b/mac80211.c
-index e79568d1..35fd0347 100644
---- a/mac80211.c
-+++ b/mac80211.c
-@@ -430,7 +430,8 @@ mt76_phy_init(struct mt76_phy *phy, struct ieee80211_hw *hw)
- SET_IEEE80211_DEV(hw, dev->dev);
- SET_IEEE80211_PERM_ADDR(hw, phy->macaddr);
-
-- wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR;
-+ wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR |
-+ NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
- wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH |
- WIPHY_FLAG_SUPPORTS_TDLS |
- WIPHY_FLAG_AP_UAPSD;
---
-2.18.0
-
diff --git a/recipes-wifi/linux-mt76/files/patches/1134-mt76-mt7915-add-vendor-cmd-to-get-available-color-bi.patch b/recipes-wifi/linux-mt76/files/patches/1134-mt76-mt7915-add-vendor-cmd-to-get-available-color-bi.patch
new file mode 100644
index 0000000..ec25241
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/patches/1134-mt76-mt7915-add-vendor-cmd-to-get-available-color-bi.patch
@@ -0,0 +1,106 @@
+From 1ecc90eee785504c9671985cabd6631ff1640f64 Mon Sep 17 00:00:00 2001
+From: Yi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
+Date: Thu, 26 Jan 2023 08:50:47 +0800
+Subject: [PATCH] mt76: mt7915: add vendor cmd to get available color bitmap
+
+Add a vendor cmd to notify user space available color bitmap.
+The OBSS BSS color bitmap is maintained in mac80211, so mt76 will make use of that.
+
+Signed-off-by: Yi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
+---
+ mt7915/vendor.c | 37 +++++++++++++++++++++++++++++++++++++
+ mt7915/vendor.h | 11 +++++++++++
+ 2 files changed, 48 insertions(+)
+
+diff --git a/mt7915/vendor.c b/mt7915/vendor.c
+index a1f526c..5cbe856 100644
+--- a/mt7915/vendor.c
++++ b/mt7915/vendor.c
+@@ -97,6 +97,11 @@ ibf_ctrl_policy[NUM_MTK_VENDOR_ATTRS_IBF_CTRL] = {
+ [MTK_VENDOR_ATTR_IBF_CTRL_ENABLE] = { .type = NLA_U8 },
+ };
+
++static struct nla_policy
++bss_color_ctrl_policy[NUM_MTK_VENDOR_ATTRS_BSS_COLOR_CTRL] = {
++ [MTK_VENDOR_ATTR_AVAL_BSS_COLOR_BMP] = { .type = NLA_U64 },
++};
++
+ struct csi_null_tone {
+ u8 start;
+ u8 end;
+@@ -1272,6 +1277,27 @@ mt7915_vendor_ibf_ctrl_dump(struct wiphy *wiphy, struct wireless_dev *wdev,
+ return 1;
+ }
+
++static int
++mt7915_vendor_bss_color_ctrl_dump(struct wiphy *wiphy, struct wireless_dev *wdev,
++ struct sk_buff *skb, const void *data, int data_len,
++ unsigned long *storage)
++{
++ struct ieee80211_vif *vif = wdev_to_ieee80211_vif(wdev);
++ struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
++ int len = 0;
++
++ if (*storage == 1)
++ return -ENOENT;
++ *storage = 1;
++
++ if (nla_put_u64_64bit(skb,
++ MTK_VENDOR_ATTR_AVAL_BSS_COLOR_BMP,
++ ~bss_conf->he_bss_color.used_color_bitmap, NL80211_ATTR_PAD))
++ return -ENOMEM;
++ len += 1;
++
++ return len;
++}
+
+ static const struct wiphy_vendor_command mt7915_vendor_commands[] = {
+ {
+@@ -1378,6 +1404,17 @@ static const struct wiphy_vendor_command mt7915_vendor_commands[] = {
+ .dumpit = mt7915_vendor_ibf_ctrl_dump,
+ .policy = ibf_ctrl_policy,
+ .maxattr = MTK_VENDOR_ATTR_IBF_CTRL_MAX,
++ },
++ {
++ .info = {
++ .vendor_id = MTK_NL80211_VENDOR_ID,
++ .subcmd = MTK_NL80211_VENDOR_SUBCMD_BSS_COLOR_CTRL,
++ },
++ .flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
++ WIPHY_VENDOR_CMD_NEED_RUNNING,
++ .dumpit = mt7915_vendor_bss_color_ctrl_dump,
++ .policy = bss_color_ctrl_policy,
++ .maxattr = MTK_VENDOR_ATTR_BSS_COLOR_CTRL_MAX,
+ }
+ };
+
+diff --git a/mt7915/vendor.h b/mt7915/vendor.h
+index cbff910..dda1447 100644
+--- a/mt7915/vendor.h
++++ b/mt7915/vendor.h
+@@ -14,6 +14,7 @@ enum mtk_nl80211_vendor_subcmds {
+ MTK_NL80211_VENDOR_SUBCMD_EDCCA_CTRL = 0xc7,
+ MTK_NL80211_VENDOR_SUBCMD_3WIRE_CTRL = 0xc8,
+ MTK_NL80211_VENDOR_SUBCMD_IBF_CTRL = 0xc9,
++ MTK_NL80211_VENDOR_SUBCMD_BSS_COLOR_CTRL = 0xca,
+ };
+
+
+@@ -257,4 +258,14 @@ enum mtk_vendor_attr_ibf_dump {
+ NUM_MTK_VENDOR_ATTRS_IBF_DUMP - 1
+ };
+
++enum mtk_vendor_attr_bss_color_ctrl {
++ MTK_VENDOR_ATTR_BSS_COLOR_CTRL_UNSPEC,
++
++ MTK_VENDOR_ATTR_AVAL_BSS_COLOR_BMP,
++
++ /* keep last */
++ NUM_MTK_VENDOR_ATTRS_BSS_COLOR_CTRL,
++ MTK_VENDOR_ATTR_BSS_COLOR_CTRL_MAX =
++ NUM_MTK_VENDOR_ATTRS_BSS_COLOR_CTRL - 1
++};
+ #endif
+--
+2.39.0
+
diff --git a/recipes-wifi/linux-mt76/files/patches/3001-mt76-mt7915-wed-add-wed-tx-support.patch b/recipes-wifi/linux-mt76/files/patches/3001-mt76-mt7915-wed-add-wed-tx-support.patch
index 500ec0f..deab403 100644
--- a/recipes-wifi/linux-mt76/files/patches/3001-mt76-mt7915-wed-add-wed-tx-support.patch
+++ b/recipes-wifi/linux-mt76/files/patches/3001-mt76-mt7915-wed-add-wed-tx-support.patch
@@ -1,7 +1,7 @@
-From 783c715b2271209d23b965517d97e5a834fcfa76 Mon Sep 17 00:00:00 2001
+From af605bd8d821cc9cd9dd4f3928c4632113574dc4 Mon Sep 17 00:00:00 2001
From: Sujuan Chen <sujuan.chen@mediatek.com>
Date: Fri, 25 Nov 2022 10:38:53 +0800
-Subject: [PATCH 3001/3015] mt76: mt7915: wed: add wed tx support
+Subject: [PATCH 3001/3013] mt76: mt7915: wed: add wed tx support
Signed-off-by: Sujuan Chen <sujuan.chen@mediatek.com>
---
@@ -86,7 +86,7 @@
ctx->dev = NULL;
diff --git a/mt7915/mmio.c b/mt7915/mmio.c
-index 95ded131..6ebb969f 100644
+index 568b5feb..890af388 100644
--- a/mt7915/mmio.c
+++ b/mt7915/mmio.c
@@ -13,7 +13,7 @@
diff --git a/recipes-wifi/linux-mt76/files/patches/3002-mt76-mt7915-wed-add-wds-support-when-wed-is-enabled.patch b/recipes-wifi/linux-mt76/files/patches/3002-mt76-mt7915-wed-add-wds-support-when-wed-is-enabled.patch
index 46fbf0c..46a68b5 100644
--- a/recipes-wifi/linux-mt76/files/patches/3002-mt76-mt7915-wed-add-wds-support-when-wed-is-enabled.patch
+++ b/recipes-wifi/linux-mt76/files/patches/3002-mt76-mt7915-wed-add-wds-support-when-wed-is-enabled.patch
@@ -1,21 +1,21 @@
-From 443b9ce1fa3d69fbfdbb6051c4ed46029556083d Mon Sep 17 00:00:00 2001
+From e7caf441138764cd701c00bf8c3bd6b7747ed323 Mon Sep 17 00:00:00 2001
From: Sujuan Chen <sujuan.chen@mediatek.com>
Date: Tue, 13 Dec 2022 17:51:26 +0800
-Subject: [PATCH 3002/3015] mt76: mt7915: wed: add wds support when wed is
+Subject: [PATCH 3002/3013] mt76: mt7915: wed: add wds support when wed is
enabled
Signed-off-by: Sujuan Chen <sujuan.chen@mediatek.com>
---
mt76.h | 6 ++++++
mt7915/main.c | 22 ++++++++++++++++++++--
- mt7915/mcu.c | 13 +++++++++++--
+ mt7915/mcu.c | 16 ++++++++++++----
mt7915/mcu.h | 1 +
util.c | 40 +++++++++++++++++++++++++++++++++++++---
util.h | 7 ++++++-
- 6 files changed, 81 insertions(+), 8 deletions(-)
+ 6 files changed, 82 insertions(+), 10 deletions(-)
diff --git a/mt76.h b/mt76.h
-index 5e24d03c..cb34391a 100644
+index dbb120cc..d8438953 100644
--- a/mt76.h
+++ b/mt76.h
@@ -60,6 +60,12 @@ enum mt76_wed_type {
@@ -81,17 +81,20 @@
ctx->dev = NULL;
diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index 4f1d2fe6..d046ce0f 100644
+index e07197d0..6b90f338 100644
--- a/mt7915/mcu.c
+++ b/mt7915/mcu.c
-@@ -2416,8 +2416,17 @@ int mt7915_mcu_init_firmware(struct mt7915_dev *dev)
+@@ -2416,10 +2416,18 @@ int mt7915_mcu_init_firmware(struct mt7915_dev *dev)
if (ret)
return ret;
-- if (mtk_wed_device_active(&dev->mt76.mmio.wed) && is_mt7915(&dev->mt76))
+- if ((mtk_wed_device_active(&dev->mt76.mmio.wed) &&
+- is_mt7915(&dev->mt76)) ||
+- !mtk_wed_get_rx_capa(&dev->mt76.mmio.wed))
- mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY), 0, 0, 0);
+ if (mtk_wed_device_active(&dev->mt76.mmio.wed)) {
-+ if (is_mt7915(&dev->mt76))
++ if (is_mt7915(&dev->mt76) ||
++ !mtk_wed_get_rx_capa(&dev->mt76.mmio.wed))
+ ret = mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY),
+ 0, 0, 0);
+ else
@@ -105,7 +108,7 @@
ret = mt7915_mcu_set_mwds(dev, 1);
if (ret)
diff --git a/mt7915/mcu.h b/mt7915/mcu.h
-index 03ee600a..24d0efd3 100644
+index 8cbd37ca..0f845075 100644
--- a/mt7915/mcu.h
+++ b/mt7915/mcu.h
@@ -284,6 +284,7 @@ enum {
diff --git a/recipes-wifi/linux-mt76/files/patches/3003-mt76-mt7915-wed-add-fill-receive-path-to-report-wed-.patch b/recipes-wifi/linux-mt76/files/patches/3003-mt76-mt7915-wed-add-fill-receive-path-to-report-wed-.patch
index 528c44c..5d3affc 100644
--- a/recipes-wifi/linux-mt76/files/patches/3003-mt76-mt7915-wed-add-fill-receive-path-to-report-wed-.patch
+++ b/recipes-wifi/linux-mt76/files/patches/3003-mt76-mt7915-wed-add-fill-receive-path-to-report-wed-.patch
@@ -1,7 +1,7 @@
-From b52fb2adf7b44ed323983b10721612347b86b569 Mon Sep 17 00:00:00 2001
+From 3cdc91efeb0dcb344b79c832373a62c09c4ceee9 Mon Sep 17 00:00:00 2001
From: Sujuan Chen <sujuan.chen@mediatek.com>
Date: Thu, 19 May 2022 13:44:42 +0800
-Subject: [PATCH 3003/3015] mt76: mt7915: wed: add fill receive path to report
+Subject: [PATCH 3003/3013] mt76: mt7915: wed: add fill receive path to report
wed idx
Signed-off-by: Sujuan Chen <sujuan.chen@mediatek.com>
diff --git a/recipes-wifi/linux-mt76/files/patches/3004-mt76-mt7915-wed-find-rx-token-by-physical-address.patch b/recipes-wifi/linux-mt76/files/patches/3004-mt76-mt7915-wed-find-rx-token-by-physical-address.patch
index 21367e9..a958a8f 100644
--- a/recipes-wifi/linux-mt76/files/patches/3004-mt76-mt7915-wed-find-rx-token-by-physical-address.patch
+++ b/recipes-wifi/linux-mt76/files/patches/3004-mt76-mt7915-wed-find-rx-token-by-physical-address.patch
@@ -1,7 +1,7 @@
-From fc10309ea47b4d34ace30e6f4e7ff0c0ffa71db2 Mon Sep 17 00:00:00 2001
+From b454d9a320895e76b3211a3c176dbf3ab24c1a8a Mon Sep 17 00:00:00 2001
From: Sujuan Chen <sujuan.chen@mediatek.com>
Date: Fri, 25 Nov 2022 14:32:35 +0800
-Subject: [PATCH 3004/3015] mt76: mt7915: wed: find rx token by physical
+Subject: [PATCH 3004/3013] mt76: mt7915: wed: find rx token by physical
address
The token id in RxDMAD may be incorrect when it is not the last frame due to
@@ -9,21 +9,19 @@
Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
---
- dma.c | 27 ++++++++++++++++++++++++++-
- 1 file changed, 26 insertions(+), 1 deletion(-)
+ dma.c | 25 ++++++++++++++++++++++++-
+ 1 file changed, 24 insertions(+), 1 deletion(-)
diff --git a/dma.c b/dma.c
-index a6bb3730..b58579c5 100644
+index fe65e0f3..14553b24 100644
--- a/dma.c
+++ b/dma.c
-@@ -402,10 +402,35 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
- *info = le32_to_cpu(desc->info);
+@@ -403,9 +403,32 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
if (mt76_queue_is_wed_rx(q)) {
-+ __le32 buf1;
+ u32 buf1 = le32_to_cpu(desc->buf1);
+ u32 id, find = 0;
- u32 token = FIELD_GET(MT_DMA_CTL_TOKEN,
- le32_to_cpu(desc->buf1));
+ u32 token = FIELD_GET(MT_DMA_CTL_TOKEN, buf1);
- struct mt76_txwi_cache *t = mt76_rx_token_release(dev, token);
+ struct mt76_txwi_cache *t;
+
@@ -36,10 +34,9 @@
+ token = id;
+
+ /* Write correct id back to DMA*/
-+ buf1 = desc->buf1;
-+ buf1 = le32_replace_bits(buf1, id,
-+ MT_DMA_CTL_TOKEN);
-+ WRITE_ONCE(desc->buf1, buf1);
++ u32p_replace_bits(&buf1, id,
++ MT_DMA_CTL_TOKEN);
++ WRITE_ONCE(desc->buf1, cpu_to_le32(buf1));
+ break;
+ }
+ }
diff --git a/recipes-wifi/linux-mt76/files/patches/3006-mt76-mt7915-wed-HW-ATF-support-for-mt7986.patch b/recipes-wifi/linux-mt76/files/patches/3005-mt76-mt7915-wed-HW-ATF-support-for-mt7986.patch
similarity index 98%
rename from recipes-wifi/linux-mt76/files/patches/3006-mt76-mt7915-wed-HW-ATF-support-for-mt7986.patch
rename to recipes-wifi/linux-mt76/files/patches/3005-mt76-mt7915-wed-HW-ATF-support-for-mt7986.patch
index c22106c..c163906 100644
--- a/recipes-wifi/linux-mt76/files/patches/3006-mt76-mt7915-wed-HW-ATF-support-for-mt7986.patch
+++ b/recipes-wifi/linux-mt76/files/patches/3005-mt76-mt7915-wed-HW-ATF-support-for-mt7986.patch
@@ -1,7 +1,7 @@
-From b2b4b6a891b1c9e4232addc929a0dac8cd548a06 Mon Sep 17 00:00:00 2001
+From c040b9a6ac177c22283388bff0b7a8c72271b45c Mon Sep 17 00:00:00 2001
From: Lian Chen <lian.chen@mediatek.com>
Date: Mon, 7 Nov 2022 14:47:44 +0800
-Subject: [PATCH 3006/3010] mt76: mt7915: wed: HW ATF support for mt7986
+Subject: [PATCH 3005/3013] mt76: mt7915: wed: HW ATF support for mt7986
Signed-off-by: Lian Chen <lian.chen@mediatek.com>
---
@@ -15,10 +15,10 @@
7 files changed, 826 insertions(+), 1 deletion(-)
diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index 73a5509a..130a8d25 100644
+index 1a13cee0..ad6f845b 100644
--- a/mt76_connac_mcu.h
+++ b/mt76_connac_mcu.h
-@@ -1164,6 +1164,7 @@ enum {
+@@ -1161,6 +1161,7 @@ enum {
MCU_EXT_CMD_THERMAL_CTRL = 0x2c,
MCU_EXT_CMD_WTBL_UPDATE = 0x32,
MCU_EXT_CMD_SET_DRR_CTRL = 0x36,
@@ -26,7 +26,7 @@
MCU_EXT_CMD_SET_RDD_CTRL = 0x3a,
MCU_EXT_CMD_ATE_CTRL = 0x3d,
MCU_EXT_CMD_PROTECT_CTRL = 0x3e,
-@@ -1173,6 +1174,7 @@ enum {
+@@ -1170,6 +1171,7 @@ enum {
MCU_EXT_CMD_MUAR_UPDATE = 0x48,
MCU_EXT_CMD_BCN_OFFLOAD = 0x49,
MCU_EXT_CMD_RX_AIRTIME_CTRL = 0x4a,
@@ -465,10 +465,10 @@
if (!dev->dbdc_support || phy->mt76->band_idx) {
debugfs_create_u32("dfs_hw_pattern", 0400, dir,
diff --git a/mt7915/init.c b/mt7915/init.c
-index 19447ad1..92977b98 100644
+index f40d09c3..27395316 100644
--- a/mt7915/init.c
+++ b/mt7915/init.c
-@@ -559,10 +559,46 @@ mt7915_init_led_mux(struct mt7915_dev *dev)
+@@ -571,10 +571,46 @@ mt7915_init_led_mux(struct mt7915_dev *dev)
}
}
@@ -515,7 +515,7 @@
/* config pse qid6 wfdma port selection */
if (!is_mt7915(&dev->mt76) && dev->hif2)
-@@ -584,6 +620,9 @@ void mt7915_mac_init(struct mt7915_dev *dev)
+@@ -596,6 +632,9 @@ void mt7915_mac_init(struct mt7915_dev *dev)
mt7915_mac_init_band(dev, i);
mt7915_init_led_mux(dev);
@@ -526,7 +526,7 @@
int mt7915_txbf_init(struct mt7915_dev *dev)
diff --git a/mt7915/main.c b/mt7915/main.c
-index 9a5dac91..a9980e70 100644
+index 7d25a93f..c549a183 100644
--- a/mt7915/main.c
+++ b/mt7915/main.c
@@ -209,6 +209,7 @@ int mt7915_init_vif(struct mt7915_phy *phy, struct ieee80211_vif *vif, bool bf_e
@@ -573,10 +573,10 @@
}
diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index 64789b80..e3b7d824 100644
+index 6b90f338..da10895c 100644
--- a/mt7915/mcu.c
+++ b/mt7915/mcu.c
-@@ -3580,6 +3580,171 @@ int mt7915_mcu_set_ser(struct mt7915_dev *dev, u8 action, u8 set, u8 band)
+@@ -3581,6 +3581,171 @@ int mt7915_mcu_set_ser(struct mt7915_dev *dev, u8 action, u8 set, u8 band)
&req, sizeof(req), false);
}
@@ -749,7 +749,7 @@
{
#define MT_BF_PROCESSING 4
diff --git a/mt7915/mt7915.h b/mt7915/mt7915.h
-index eb24b45f..a1ef8359 100644
+index c14d13ae..0fbc1047 100644
--- a/mt7915/mt7915.h
+++ b/mt7915/mt7915.h
@@ -127,6 +127,58 @@ struct mt7915_twt_flow {
@@ -856,7 +856,7 @@
int mt7915_mcu_set_txpower_sku(struct mt7915_phy *phy);
int mt7915_mcu_get_txpower_sku(struct mt7915_phy *phy, s8 *txpower, int len,
diff --git a/mt7915/mtk_debugfs.c b/mt7915/mtk_debugfs.c
-index 576995dc..5e64fe91 100644
+index 224d9960..2dc4cb87 100644
--- a/mt7915/mtk_debugfs.c
+++ b/mt7915/mtk_debugfs.c
@@ -1368,7 +1368,6 @@ static EMPTY_QUEUE_INFO_T ple_txcmd_queue_empty_info[] = {
diff --git a/recipes-wifi/linux-mt76/files/patches/3005-mt76-mt7915-wed-drop-scatter-and-gather-frame.patch b/recipes-wifi/linux-mt76/files/patches/3005-mt76-mt7915-wed-drop-scatter-and-gather-frame.patch
deleted file mode 100644
index 4f5d2c6..0000000
--- a/recipes-wifi/linux-mt76/files/patches/3005-mt76-mt7915-wed-drop-scatter-and-gather-frame.patch
+++ /dev/null
@@ -1,62 +0,0 @@
-From d99756a5e6b4b3d1d520aba763fddeadff53a529 Mon Sep 17 00:00:00 2001
-From: Peter Chiu <chui-hao.chiu@mediatek.com>
-Date: Fri, 25 Nov 2022 14:37:58 +0800
-Subject: [PATCH 3005/3015] mt76: mt7915: wed: drop scatter and gather frame
-
-The scatter and gather frame may be incorrect because WED and WO may
-send frames to host driver interleaved.
-
-Signed-off-by: Peter Chiu <chui-hao.chiu@mediatek.com>
----
- dma.c | 9 +++++++++
- dma.h | 1 +
- mt76.h | 1 +
- 3 files changed, 11 insertions(+)
-
-diff --git a/dma.c b/dma.c
-index b58579c5..86b0bf84 100644
---- a/dma.c
-+++ b/dma.c
-@@ -449,6 +449,15 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
-
- *drop = !!(ctrl & (MT_DMA_CTL_TO_HOST_A |
- MT_DMA_CTL_DROP));
-+
-+ if (*more || (q->flags & MT_QFLAG_WED_FRAG)) {
-+ *drop = true;
-+
-+ if (!(*more) && FIELD_GET(MT_DMA_CTL_WO, desc->buf1))
-+ q->flags &= ~MT_QFLAG_WED_FRAG;
-+ else
-+ q->flags |= MT_QFLAG_WED_FRAG;
-+ }
- }
- } else {
- buf = e->buf;
-diff --git a/dma.h b/dma.h
-index 4b9bc7f4..ce8ac426 100644
---- a/dma.h
-+++ b/dma.h
-@@ -19,6 +19,7 @@
- #define MT_DMA_CTL_TO_HOST_A BIT(12)
- #define MT_DMA_CTL_DROP BIT(14)
- #define MT_DMA_CTL_TOKEN GENMASK(31, 16)
-+#define MT_DMA_CTL_WO BIT(8)
-
- #define MT_DMA_PPE_CPU_REASON GENMASK(15, 11)
- #define MT_DMA_PPE_ENTRY GENMASK(30, 16)
-diff --git a/mt76.h b/mt76.h
-index cb34391a..982d0bbf 100644
---- a/mt76.h
-+++ b/mt76.h
-@@ -30,6 +30,7 @@
- #define MT_QFLAG_WED_RING GENMASK(1, 0)
- #define MT_QFLAG_WED_TYPE GENMASK(3, 2)
- #define MT_QFLAG_WED BIT(4)
-+#define MT_QFLAG_WED_FRAG BIT(5)
-
- #define __MT_WED_Q(_type, _n) (MT_QFLAG_WED | \
- FIELD_PREP(MT_QFLAG_WED_TYPE, _type) | \
---
-2.18.0
-
diff --git a/recipes-wifi/linux-mt76/files/patches/3008-mt76-mt7915-wed-add-rxwi-for-further-in-chip-rro.patch b/recipes-wifi/linux-mt76/files/patches/3006-mt76-mt7915-wed-add-rxwi-for-further-in-chip-rro.patch
similarity index 93%
rename from recipes-wifi/linux-mt76/files/patches/3008-mt76-mt7915-wed-add-rxwi-for-further-in-chip-rro.patch
rename to recipes-wifi/linux-mt76/files/patches/3006-mt76-mt7915-wed-add-rxwi-for-further-in-chip-rro.patch
index 78e257d..4e22353 100644
--- a/recipes-wifi/linux-mt76/files/patches/3008-mt76-mt7915-wed-add-rxwi-for-further-in-chip-rro.patch
+++ b/recipes-wifi/linux-mt76/files/patches/3006-mt76-mt7915-wed-add-rxwi-for-further-in-chip-rro.patch
@@ -1,7 +1,7 @@
-From 8d7faa4d207c13487196d09de0c1c452703f1b84 Mon Sep 17 00:00:00 2001
+From 72dda83ffb5d48393da817757f537770aeca4e40 Mon Sep 17 00:00:00 2001
From: Sujuan Chen <sujuan.chen@mediatek.com>
Date: Fri, 6 Jan 2023 18:18:50 +0800
-Subject: [PATCH 3008/3015] mt76: mt7915: wed: add rxwi for further in chip rro
+Subject: [PATCH 3006/3013] mt76: mt7915: wed: add rxwi for further in chip rro
Signed-off-by: Sujuan Chen <sujuan.chen@mediatek.com>
---
@@ -15,7 +15,7 @@
7 files changed, 86 insertions(+), 79 deletions(-)
diff --git a/dma.c b/dma.c
-index 86b0bf84..76af6506 100644
+index 14553b24..d1a1dae4 100644
--- a/dma.c
+++ b/dma.c
@@ -59,17 +59,17 @@ mt76_alloc_txwi(struct mt76_dev *dev)
@@ -180,10 +180,10 @@
q->entry[idx].skb = skb;
q->entry[idx].wcid = 0xffff;
-@@ -406,13 +407,13 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
+@@ -405,13 +406,13 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
+ u32 buf1 = le32_to_cpu(desc->buf1);
u32 id, find = 0;
- u32 token = FIELD_GET(MT_DMA_CTL_TOKEN,
- le32_to_cpu(desc->buf1));
+ u32 token = FIELD_GET(MT_DMA_CTL_TOKEN, buf1);
- struct mt76_txwi_cache *t;
+ struct mt76_rxwi_cache *r;
@@ -197,7 +197,7 @@
find = 1;
token = id;
-@@ -430,19 +431,19 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
+@@ -428,19 +429,19 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
return NULL;
}
@@ -224,7 +224,7 @@
if (drop) {
u32 ctrl = le32_to_cpu(READ_ONCE(desc->ctrl));
-@@ -510,7 +511,7 @@ mt76_dma_tx_queue_skb_raw(struct mt76_dev *dev, struct mt76_queue *q,
+@@ -501,7 +502,7 @@ mt76_dma_tx_queue_skb_raw(struct mt76_dev *dev, struct mt76_queue *q,
buf.len = skb->len;
spin_lock_bh(&q->lock);
@@ -233,7 +233,7 @@
mt76_dma_kick_queue(dev, q);
spin_unlock_bh(&q->lock);
-@@ -587,7 +588,7 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
+@@ -578,7 +579,7 @@ mt76_dma_tx_queue_skb(struct mt76_dev *dev, struct mt76_queue *q,
goto unmap;
return mt76_dma_add_buf(dev, q, tx_info.buf, tx_info.nbuf,
@@ -243,10 +243,10 @@
unmap:
for (n--; n > 0; n--)
diff --git a/mac80211.c b/mac80211.c
-index 35fd0347..95861d47 100644
+index e2122c78..4655f814 100644
--- a/mac80211.c
+++ b/mac80211.c
-@@ -640,7 +640,6 @@ mt76_alloc_device(struct device *pdev, unsigned int size,
+@@ -644,7 +644,6 @@ mt76_alloc_device(struct device *pdev, unsigned int size,
spin_lock_init(&dev->lock);
spin_lock_init(&dev->cc_lock);
spin_lock_init(&dev->status_lock);
@@ -254,7 +254,7 @@
mutex_init(&dev->mutex);
init_waitqueue_head(&dev->tx_wait);
-@@ -671,6 +670,7 @@ mt76_alloc_device(struct device *pdev, unsigned int size,
+@@ -675,6 +674,7 @@ mt76_alloc_device(struct device *pdev, unsigned int size,
INIT_LIST_HEAD(&dev->txwi_cache);
INIT_LIST_HEAD(&dev->rxwi_cache);
dev->token_size = dev->drv->token_size;
@@ -263,10 +263,10 @@
for (i = 0; i < ARRAY_SIZE(dev->q_rx); i++)
skb_queue_head_init(&dev->rx_skb[i]);
diff --git a/mt76.h b/mt76.h
-index 982d0bbf..a36a978b 100644
+index d8438953..7919cda8 100644
--- a/mt76.h
+++ b/mt76.h
-@@ -166,6 +166,7 @@ struct mt76_queue_entry {
+@@ -165,6 +165,7 @@ struct mt76_queue_entry {
};
union {
struct mt76_txwi_cache *txwi;
@@ -274,7 +274,7 @@
struct urb *urb;
int buf_sz;
};
-@@ -357,10 +358,15 @@ struct mt76_txwi_cache {
+@@ -356,10 +357,15 @@ struct mt76_txwi_cache {
struct list_head list;
dma_addr_t dma_addr;
@@ -334,10 +334,10 @@
static inline void mt76_put_page_pool_buf(void *buf, bool allow_direct)
{
diff --git a/mt7915/dma.c b/mt7915/dma.c
-index 52fabde0..4dd321ee 100644
+index 43a5456d..6d9b2d15 100644
--- a/mt7915/dma.c
+++ b/mt7915/dma.c
-@@ -491,7 +491,6 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
+@@ -493,7 +493,6 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
mtk_wed_get_rx_capa(&mdev->mmio.wed)) {
dev->mt76.q_rx[MT_RXQ_MAIN].flags =
MT_WED_Q_RX(MT7915_RXQ_BAND0);
@@ -345,7 +345,7 @@
}
ret = mt76_queue_alloc(dev, &dev->mt76.q_rx[MT_RXQ_MAIN],
-@@ -528,7 +527,6 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
+@@ -530,7 +529,6 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
mtk_wed_get_rx_capa(&mdev->mmio.wed)) {
dev->mt76.q_rx[MT_RXQ_BAND1].flags =
MT_WED_Q_RX(MT7915_RXQ_BAND1);
diff --git a/recipes-wifi/linux-mt76/files/patches/3009-mt76-mt7915-add-mt7915_net_setup_tc-to-support-wifi2.patch b/recipes-wifi/linux-mt76/files/patches/3007-mt76-mt7915-add-mt7915_net_setup_tc-to-support-wifi2.patch
similarity index 90%
rename from recipes-wifi/linux-mt76/files/patches/3009-mt76-mt7915-add-mt7915_net_setup_tc-to-support-wifi2.patch
rename to recipes-wifi/linux-mt76/files/patches/3007-mt76-mt7915-add-mt7915_net_setup_tc-to-support-wifi2.patch
index d5bbee7..bce65e6 100644
--- a/recipes-wifi/linux-mt76/files/patches/3009-mt76-mt7915-add-mt7915_net_setup_tc-to-support-wifi2.patch
+++ b/recipes-wifi/linux-mt76/files/patches/3007-mt76-mt7915-add-mt7915_net_setup_tc-to-support-wifi2.patch
@@ -1,7 +1,7 @@
-From b3a12a2a257355951c1f1a5902eb793a982bc23c Mon Sep 17 00:00:00 2001
+From 38e99f5b8641c3b1c054244d3c74229a9c0a470e Mon Sep 17 00:00:00 2001
From: Sujuan Chen <sujuan.chen@mediatek.com>
Date: Tue, 27 Dec 2022 09:45:14 +0800
-Subject: [PATCH 3009/3015] mt76: mt7915: add mt7915_net_setup_tc to support
+Subject: [PATCH 3007/3013] mt76: mt7915: add mt7915_net_setup_tc to support
wifi2wifi offload
Signed-off-by: Sujuan Chen <sujuan.chen@mediatek.com>
diff --git a/recipes-wifi/linux-mt76/files/patches/3007-mt76-mt7915-wed-add-mt7916-2-pcie-support-when-wed-o.patch b/recipes-wifi/linux-mt76/files/patches/3007-mt76-mt7915-wed-add-mt7916-2-pcie-support-when-wed-o.patch
deleted file mode 100644
index 4917bae..0000000
--- a/recipes-wifi/linux-mt76/files/patches/3007-mt76-mt7915-wed-add-mt7916-2-pcie-support-when-wed-o.patch
+++ /dev/null
@@ -1,75 +0,0 @@
-From 76a6c0fd812fa4682abca05d94594f063808d815 Mon Sep 17 00:00:00 2001
-From: Sujuan Chen <sujuan.chen@mediatek.com>
-Date: Fri, 2 Dec 2022 17:17:06 +0800
-Subject: [PATCH 3007/3015] mt76: mt7915: wed: add mt7916 2 pcie support when
- wed on
-
-It should use bit 23 in interrupt mask for wfdma band1 data
-for 2 pcie mt7916, and use bit 19 for band1 data for 1 pcie.
-
-Signed-off-by: Sujuan Chen <sujuan.chen@mediatek.com>
----
- mt7915/dma.c | 8 ++++++--
- mt7915/mcu.c | 3 ++-
- mt7915/mmio.c | 10 +++++-----
- 3 files changed, 13 insertions(+), 8 deletions(-)
-
-diff --git a/mt7915/dma.c b/mt7915/dma.c
-index abe17dac..52fabde0 100644
---- a/mt7915/dma.c
-+++ b/mt7915/dma.c
-@@ -87,8 +87,12 @@ static void mt7915_dma_config(struct mt7915_dev *dev)
- MT7916_RXQ_BAND0);
- RXQ_CONFIG(MT_RXQ_MCU_WA, WFDMA0, MT_INT_WED_RX_DONE_WA_MT7916,
- MT7916_RXQ_MCU_WA);
-- RXQ_CONFIG(MT_RXQ_BAND1, WFDMA0, MT_INT_WED_RX_DONE_BAND1_MT7916,
-- MT7916_RXQ_BAND1);
-+ if (dev->hif2)
-+ RXQ_CONFIG(MT_RXQ_BAND1, WFDMA0, MT_INT_RX_DONE_BAND1_MT7916,
-+ MT7916_RXQ_BAND1);
-+ else
-+ RXQ_CONFIG(MT_RXQ_BAND1, WFDMA0, MT_INT_WED_RX_DONE_BAND1_MT7916,
-+ MT7916_RXQ_BAND1);
- RXQ_CONFIG(MT_RXQ_MAIN_WA, WFDMA0, MT_INT_WED_RX_DONE_WA_MAIN_MT7916,
- MT7916_RXQ_MCU_WA_MAIN);
- TXQ_CONFIG(0, WFDMA0, MT_INT_WED_TX_DONE_BAND0,
-diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index 134dc5cb..7301ec1d 100644
---- a/mt7915/mcu.c
-+++ b/mt7915/mcu.c
-@@ -2417,7 +2417,8 @@ int mt7915_mcu_init_firmware(struct mt7915_dev *dev)
- return ret;
-
- if (mtk_wed_device_active(&dev->mt76.mmio.wed)) {
-- if (is_mt7915(&dev->mt76))
-+ if (is_mt7915(&dev->mt76) ||
-+ !mtk_wed_get_rx_capa(&dev->mt76.mmio.wed))
- ret = mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(CAPABILITY),
- 0, 0, 0);
- else
-diff --git a/mt7915/mmio.c b/mt7915/mmio.c
-index 6ebb969f..890af388 100644
---- a/mt7915/mmio.c
-+++ b/mt7915/mmio.c
-@@ -996,13 +996,13 @@ irqreturn_t mt7915_irq_handler(int irq, void *dev_instance)
- struct mt7915_dev *dev = dev_instance;
- struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
-
-- if (mtk_wed_device_active(wed)) {
-+ if (mtk_wed_device_active(wed))
- mtk_wed_device_irq_set_mask(wed, 0);
-- } else {
-+ else
- mt76_wr(dev, MT_INT_MASK_CSR, 0);
-- if (dev->hif2)
-- mt76_wr(dev, MT_INT1_MASK_CSR, 0);
-- }
-+
-+ if (dev->hif2)
-+ mt76_wr(dev, MT_INT1_MASK_CSR, 0);
-
- if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state))
- return IRQ_NONE;
---
-2.18.0
-
diff --git a/recipes-wifi/linux-mt76/files/patches/3010-wifi-mt76-mt7915-add-wa-command-to-get-tx-msdu-count.patch b/recipes-wifi/linux-mt76/files/patches/3008-wifi-mt76-mt7915-add-wa-command-to-get-tx-msdu-count.patch
similarity index 94%
rename from recipes-wifi/linux-mt76/files/patches/3010-wifi-mt76-mt7915-add-wa-command-to-get-tx-msdu-count.patch
rename to recipes-wifi/linux-mt76/files/patches/3008-wifi-mt76-mt7915-add-wa-command-to-get-tx-msdu-count.patch
index 85d97b1..9f30456 100644
--- a/recipes-wifi/linux-mt76/files/patches/3010-wifi-mt76-mt7915-add-wa-command-to-get-tx-msdu-count.patch
+++ b/recipes-wifi/linux-mt76/files/patches/3008-wifi-mt76-mt7915-add-wa-command-to-get-tx-msdu-count.patch
@@ -1,7 +1,7 @@
-From dbd25fa4a361f77c713e2f95e11c3806c490877e Mon Sep 17 00:00:00 2001
+From 101ab7022c500ad4adacb5faf90bef25d897c70a Mon Sep 17 00:00:00 2001
From: Peter Chiu <chui-hao.chiu@mediatek.com>
Date: Wed, 18 Jan 2023 16:37:22 +0800
-Subject: [PATCH 3010/3015] wifi: mt76: mt7915: add wa command to get tx msdu
+Subject: [PATCH 3008/3013] wifi: mt76: mt7915: add wa command to get tx msdu
count
---
@@ -16,10 +16,10 @@
8 files changed, 78 insertions(+), 11 deletions(-)
diff --git a/mt76.h b/mt76.h
-index a36a978b..0d1f3cbf 100644
+index 7919cda8..08945d66 100644
--- a/mt76.h
+++ b/mt76.h
-@@ -285,7 +285,7 @@ struct mt76_sta_stats {
+@@ -284,7 +284,7 @@ struct mt76_sta_stats {
u64 tx_mcs[16]; /* mcs idx */
u64 tx_bytes;
/* WED TX */
@@ -41,7 +41,7 @@
/* RXD DW1 */
diff --git a/mt76_connac_mac.c b/mt76_connac_mac.c
-index aed4ee95..2643f5aa 100644
+index 8d316d3a..1816bcbc 100644
--- a/mt76_connac_mac.c
+++ b/mt76_connac_mac.c
@@ -491,7 +491,9 @@ void mt76_connac2_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi,
@@ -68,10 +68,10 @@
le32_get_bits(txs_data[6], MT_TXS6_MPDU_FAIL_CNT);
stats->tx_retries +=
diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index 130a8d25..34df625a 100644
+index ad6f845b..7afd9d09 100644
--- a/mt76_connac_mcu.h
+++ b/mt76_connac_mcu.h
-@@ -1003,6 +1003,7 @@ enum {
+@@ -1000,6 +1000,7 @@ enum {
MCU_EXT_EVENT_BF_STATUS_READ = 0x35,
MCU_EXT_EVENT_RDD_REPORT = 0x3a,
MCU_EXT_EVENT_CSA_NOTIFY = 0x4f,
@@ -106,7 +106,7 @@
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL);
diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index 7301ec1d..3e0c3ab1 100644
+index da10895c..076480ba 100644
--- a/mt7915/mcu.c
+++ b/mt7915/mcu.c
@@ -168,7 +168,9 @@ mt7915_mcu_parse_response(struct mt76_dev *mdev, int cmd,
@@ -192,7 +192,7 @@
struct cfg80211_he_bss_color *he_bss_color)
{
diff --git a/mt7915/mcu.h b/mt7915/mcu.h
-index 24d0efd3..5f6c7c80 100644
+index 0f845075..d761fa59 100644
--- a/mt7915/mcu.h
+++ b/mt7915/mcu.h
@@ -292,6 +292,17 @@ enum {
diff --git a/recipes-wifi/linux-mt76/files/patches/3011-wifi-mt76-get-tx-count-and-tx-failed-from-mcu-comman.patch b/recipes-wifi/linux-mt76/files/patches/3009-wifi-mt76-get-tx-count-and-tx-failed-from-mcu-comman.patch
similarity index 94%
rename from recipes-wifi/linux-mt76/files/patches/3011-wifi-mt76-get-tx-count-and-tx-failed-from-mcu-comman.patch
rename to recipes-wifi/linux-mt76/files/patches/3009-wifi-mt76-get-tx-count-and-tx-failed-from-mcu-comman.patch
index 617ee6c..f1d5c88 100644
--- a/recipes-wifi/linux-mt76/files/patches/3011-wifi-mt76-get-tx-count-and-tx-failed-from-mcu-comman.patch
+++ b/recipes-wifi/linux-mt76/files/patches/3009-wifi-mt76-get-tx-count-and-tx-failed-from-mcu-comman.patch
@@ -1,7 +1,7 @@
-From 2a8cadb17c7c31806a41c5af0e97d76aed47fd94 Mon Sep 17 00:00:00 2001
+From 8fa8a22a16c04d8f18e27af2c02b960f0c02c91b Mon Sep 17 00:00:00 2001
From: Peter Chiu <chui-hao.chiu@mediatek.com>
Date: Wed, 11 Jan 2023 10:56:27 +0800
-Subject: [PATCH 3011/3015] wifi: mt76: get tx count and tx failed from mcu
+Subject: [PATCH 3009/3013] wifi: mt76: get tx count and tx failed from mcu
command
---
@@ -15,10 +15,10 @@
7 files changed, 138 insertions(+), 5 deletions(-)
diff --git a/mt76.h b/mt76.h
-index 0d1f3cbf..22c6531a 100644
+index 08945d66..bc0c9ae7 100644
--- a/mt76.h
+++ b/mt76.h
-@@ -286,6 +286,7 @@ struct mt76_sta_stats {
+@@ -285,6 +285,7 @@ struct mt76_sta_stats {
u64 tx_bytes;
/* WED TX */
u32 tx_packets; /* unit: MSDU */
@@ -27,7 +27,7 @@
u32 tx_failed;
/* WED RX */
diff --git a/mt76_connac_mac.c b/mt76_connac_mac.c
-index 2643f5aa..05ba5f26 100644
+index 1816bcbc..abcb9a27 100644
--- a/mt76_connac_mac.c
+++ b/mt76_connac_mac.c
@@ -579,8 +579,6 @@ bool mt76_connac2_mac_fill_txs(struct mt76_dev *dev, struct mt76_wcid *wcid,
@@ -38,12 +38,12 @@
- le32_get_bits(txs_data[6], MT_TXS6_MPDU_FAIL_CNT);
stats->tx_retries +=
le32_get_bits(txs_data[7], MT_TXS7_MPDU_RETRY_CNT);
- }
+
diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index 34df625a..747ae7e9 100644
+index 7afd9d09..287cffcc 100644
--- a/mt76_connac_mcu.h
+++ b/mt76_connac_mcu.h
-@@ -1163,6 +1163,7 @@ enum {
+@@ -1160,6 +1160,7 @@ enum {
MCU_EXT_CMD_EDCA_UPDATE = 0x27,
MCU_EXT_CMD_DEV_INFO_UPDATE = 0x2A,
MCU_EXT_CMD_THERMAL_CTRL = 0x2c,
@@ -78,7 +78,7 @@
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL);
diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index 3e0c3ab1..16a82e92 100644
+index 076480ba..e1c08178 100644
--- a/mt7915/mcu.c
+++ b/mt7915/mcu.c
@@ -4137,6 +4137,114 @@ out:
@@ -197,7 +197,7 @@
struct cfg80211_he_bss_color *he_bss_color)
{
diff --git a/mt7915/mcu.h b/mt7915/mcu.h
-index 5f6c7c80..7b611fb7 100644
+index d761fa59..41d5ea19 100644
--- a/mt7915/mcu.h
+++ b/mt7915/mcu.h
@@ -1018,6 +1018,28 @@ struct mt7915_muru {
diff --git a/recipes-wifi/linux-mt76/files/patches/3012-wifi-mt76-mt7915-enable-PPDU-TxS-to-host-when-wed-en.patch b/recipes-wifi/linux-mt76/files/patches/3010-wifi-mt76-mt7915-enable-PPDU-TxS-to-host-when-wed-en.patch
similarity index 93%
rename from recipes-wifi/linux-mt76/files/patches/3012-wifi-mt76-mt7915-enable-PPDU-TxS-to-host-when-wed-en.patch
rename to recipes-wifi/linux-mt76/files/patches/3010-wifi-mt76-mt7915-enable-PPDU-TxS-to-host-when-wed-en.patch
index 4dcba32..d7af854 100644
--- a/recipes-wifi/linux-mt76/files/patches/3012-wifi-mt76-mt7915-enable-PPDU-TxS-to-host-when-wed-en.patch
+++ b/recipes-wifi/linux-mt76/files/patches/3010-wifi-mt76-mt7915-enable-PPDU-TxS-to-host-when-wed-en.patch
@@ -1,7 +1,7 @@
-From 3c70695fbf551ae8eaf90fa92f08ab45199f69e4 Mon Sep 17 00:00:00 2001
+From 5c346af2c8a9352b9303d1e7f9e6f424417dfc98 Mon Sep 17 00:00:00 2001
From: Peter Chiu <chui-hao.chiu@mediatek.com>
Date: Wed, 18 Jan 2023 11:50:38 +0800
-Subject: [PATCH 3012/3015] wifi: mt76: mt7915: enable PPDU-TxS to host when
+Subject: [PATCH 3010/3013] wifi: mt76: mt7915: enable PPDU-TxS to host when
wed enable
Calculate tx bytes and tx retries from PPDU-TxS
@@ -13,7 +13,7 @@
4 files changed, 12 insertions(+), 23 deletions(-)
diff --git a/mt76_connac_mac.c b/mt76_connac_mac.c
-index 05ba5f26..4e24c492 100644
+index abcb9a27..5a5861a8 100644
--- a/mt76_connac_mac.c
+++ b/mt76_connac_mac.c
@@ -490,8 +490,6 @@ void mt76_connac2_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi,
@@ -26,10 +26,10 @@
wcid->stats.tx_packets++;
}
diff --git a/mt7915/init.c b/mt7915/init.c
-index c3b186c8..a1be5b7d 100644
+index 27395316..70563c9d 100644
--- a/mt7915/init.c
+++ b/mt7915/init.c
-@@ -491,6 +491,12 @@ mt7915_mac_init_band(struct mt7915_dev *dev, u8 band)
+@@ -503,6 +503,12 @@ mt7915_mac_init_band(struct mt7915_dev *dev, u8 band)
set = FIELD_PREP(MT_WTBLOFF_TOP_RSCR_RCPI_MODE, 0) |
FIELD_PREP(MT_WTBLOFF_TOP_RSCR_RCPI_PARAM, 0x3);
mt76_rmw(dev, MT_WTBLOFF_TOP_RSCR(band), mask, set);
diff --git a/recipes-wifi/linux-mt76/files/patches/3013-wifi-mt76-mt7915-get-tx-retries-from-tx-free-done-ev.patch b/recipes-wifi/linux-mt76/files/patches/3011-wifi-mt76-mt7915-get-tx-retries-from-tx-free-done-ev.patch
similarity index 95%
rename from recipes-wifi/linux-mt76/files/patches/3013-wifi-mt76-mt7915-get-tx-retries-from-tx-free-done-ev.patch
rename to recipes-wifi/linux-mt76/files/patches/3011-wifi-mt76-mt7915-get-tx-retries-from-tx-free-done-ev.patch
index e596240..6904bea 100644
--- a/recipes-wifi/linux-mt76/files/patches/3013-wifi-mt76-mt7915-get-tx-retries-from-tx-free-done-ev.patch
+++ b/recipes-wifi/linux-mt76/files/patches/3011-wifi-mt76-mt7915-get-tx-retries-from-tx-free-done-ev.patch
@@ -1,8 +1,8 @@
-From be812eb6a9ceafc732c518070458fed74a09cd2e Mon Sep 17 00:00:00 2001
+From 47c0c3360a84cb4f8d5500ef1190a1eea394e2e8 Mon Sep 17 00:00:00 2001
From: Peter Chiu <chui-hao.chiu@mediatek.com>
Date: Tue, 17 Jan 2023 21:15:00 +0800
-Subject: [PATCH] wifi: mt76: mt7915: get tx retries from tx free done event
- for sw path
+Subject: [PATCH 3011/3013] wifi: mt76: mt7915: get tx retries from tx free
+ done event for sw path
---
mt7915/mac.c | 14 +++++++++++---
diff --git a/recipes-wifi/linux-mt76/files/patches/3014-wifi-mt76-update-debugfs-knob-for-reset-counter-and-.patch b/recipes-wifi/linux-mt76/files/patches/3012-wifi-mt76-update-debugfs-knob-for-reset-counter-and-.patch
similarity index 93%
rename from recipes-wifi/linux-mt76/files/patches/3014-wifi-mt76-update-debugfs-knob-for-reset-counter-and-.patch
rename to recipes-wifi/linux-mt76/files/patches/3012-wifi-mt76-update-debugfs-knob-for-reset-counter-and-.patch
index 96c308b..c852b73 100644
--- a/recipes-wifi/linux-mt76/files/patches/3014-wifi-mt76-update-debugfs-knob-for-reset-counter-and-.patch
+++ b/recipes-wifi/linux-mt76/files/patches/3012-wifi-mt76-update-debugfs-knob-for-reset-counter-and-.patch
@@ -1,7 +1,7 @@
-From 5b02de4f8b414de462c2c2df61aed85e745d5999 Mon Sep 17 00:00:00 2001
+From 655d403531165600ea621dc7889165a091971331 Mon Sep 17 00:00:00 2001
From: Peter Chiu <chui-hao.chiu@mediatek.com>
Date: Mon, 30 Jan 2023 11:36:32 +0800
-Subject: [PATCH 3014/3015] wifi: mt76: update debugfs knob for reset counter
+Subject: [PATCH 3012/3013] wifi: mt76: update debugfs knob for reset counter
and get tx packet error rate
---
@@ -9,7 +9,7 @@
1 file changed, 62 insertions(+)
diff --git a/mt7915/mtk_debugfs.c b/mt7915/mtk_debugfs.c
-index d203facf..479da4a0 100644
+index 2dc4cb87..87a7ca98 100644
--- a/mt7915/mtk_debugfs.c
+++ b/mt7915/mtk_debugfs.c
@@ -3190,6 +3190,66 @@ mt7915_sw_aci_set(void *data, u64 val)
diff --git a/recipes-wifi/linux-mt76/files/patches/3015-mt76-connac-wed-add-wed-rx-copy-skb-and-revert-page_.patch b/recipes-wifi/linux-mt76/files/patches/3013-mt76-connac-wed-add-wed-rx-copy-skb-and-revert-page_.patch
similarity index 93%
rename from recipes-wifi/linux-mt76/files/patches/3015-mt76-connac-wed-add-wed-rx-copy-skb-and-revert-page_.patch
rename to recipes-wifi/linux-mt76/files/patches/3013-mt76-connac-wed-add-wed-rx-copy-skb-and-revert-page_.patch
index 883312e..89b423c 100644
--- a/recipes-wifi/linux-mt76/files/patches/3015-mt76-connac-wed-add-wed-rx-copy-skb-and-revert-page_.patch
+++ b/recipes-wifi/linux-mt76/files/patches/3013-mt76-connac-wed-add-wed-rx-copy-skb-and-revert-page_.patch
@@ -1,7 +1,7 @@
-From a8e76b8635c6daf65fb029ea4476ef777768c092 Mon Sep 17 00:00:00 2001
+From 40bc4191469a25ab239596071faf7d8ad69e9fb3 Mon Sep 17 00:00:00 2001
From: Sujuan Chen <sujuan.chen@mediatek.com>
Date: Thu, 5 Jan 2023 16:43:57 +0800
-Subject: [PATCH 3015/3015] mt76: connac: wed: add wed rx copy skb and revert
+Subject: [PATCH 3013/3013] mt76: connac: wed: add wed rx copy skb and revert
page_pool
Signed-off-by: Sujuan Chen <sujuan.chen@mediatek.com>
@@ -13,10 +13,10 @@
mt7915/mmio.c | 74 +++++++++++++++++++--------
mt7921/main.c | 31 ++----------
usb.c | 42 +++++++--------
- 7 files changed, 180 insertions(+), 210 deletions(-)
+ 7 files changed, 179 insertions(+), 211 deletions(-)
diff --git a/dma.c b/dma.c
-index 76af6506..79da538c 100644
+index d1a1dae4..3adb1136 100644
--- a/dma.c
+++ b/dma.c
@@ -173,7 +173,7 @@ mt76_free_pending_rxwi(struct mt76_dev *dev)
@@ -66,7 +66,7 @@
{
struct mt76_queue_entry *e = &q->entry[idx];
struct mt76_desc *desc = &q->desc[idx];
-@@ -435,15 +437,47 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
+@@ -433,15 +435,47 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
if (!r)
return NULL;
@@ -121,7 +121,7 @@
if (drop) {
u32 ctrl = le32_to_cpu(READ_ONCE(desc->ctrl));
-@@ -463,9 +497,9 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
+@@ -454,9 +488,9 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
} else {
buf = e->buf;
e->buf = NULL;
@@ -134,7 +134,7 @@
}
return buf;
-@@ -489,7 +523,7 @@ mt76_dma_dequeue(struct mt76_dev *dev, struct mt76_queue *q, bool flush,
+@@ -480,7 +514,7 @@ mt76_dma_dequeue(struct mt76_dev *dev, struct mt76_queue *q, bool flush,
q->tail = (q->tail + 1) % q->ndesc;
q->queued--;
@@ -143,7 +143,7 @@
}
static int
-@@ -616,11 +650,12 @@ free_skb:
+@@ -607,11 +641,12 @@ free_skb:
}
static int
@@ -159,7 +159,7 @@
if (!q->ndesc)
return 0;
-@@ -628,31 +663,35 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q,
+@@ -619,31 +654,35 @@ mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q,
spin_lock_bh(&q->lock);
while (q->queued < q->ndesc - 1) {
@@ -208,7 +208,7 @@
mt76_dma_kick_queue(dev, q);
spin_unlock_bh(&q->lock);
-@@ -690,7 +729,7 @@ int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset)
+@@ -681,7 +720,7 @@ int mt76_dma_wed_setup(struct mt76_dev *dev, struct mt76_queue *q, bool reset)
/* WED txfree queue needs ring to be initialized before setup */
q->flags = 0;
mt76_dma_queue_reset(dev, q);
@@ -217,7 +217,7 @@
q->flags = flags;
ret = mtk_wed_device_txfree_ring_setup(wed, q->regs);
-@@ -738,10 +777,6 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
+@@ -729,10 +768,6 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
if (!q->entry)
return -ENOMEM;
@@ -228,7 +228,7 @@
ret = mt76_dma_wed_setup(dev, q, false);
if (ret)
return ret;
-@@ -755,6 +790,7 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
+@@ -746,6 +781,7 @@ mt76_dma_alloc_queue(struct mt76_dev *dev, struct mt76_queue *q,
static void
mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
{
@@ -236,7 +236,7 @@
void *buf;
bool more;
-@@ -768,7 +804,7 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
+@@ -759,7 +795,7 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
if (!buf)
break;
@@ -245,7 +245,7 @@
} while (1);
if (q->rx_head) {
-@@ -777,6 +813,15 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
+@@ -768,6 +804,15 @@ mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)
}
spin_unlock_bh(&q->lock);
@@ -261,7 +261,7 @@
}
static void
-@@ -797,7 +842,7 @@ mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid)
+@@ -788,7 +833,7 @@ mt76_dma_rx_reset(struct mt76_dev *dev, enum mt76_rxq_id qid)
mt76_dma_wed_setup(dev, q, true);
if (q->flags != MT_WED_Q_TXFREE) {
mt76_dma_sync_idx(dev, q);
@@ -270,7 +270,7 @@
}
}
-@@ -815,7 +860,7 @@ mt76_add_fragment(struct mt76_dev *dev, struct mt76_queue *q, void *data,
+@@ -806,7 +851,7 @@ mt76_add_fragment(struct mt76_dev *dev, struct mt76_queue *q, void *data,
skb_add_rx_frag(skb, nr_frags, page, offset, len, q->buf_size);
} else {
@@ -279,7 +279,7 @@
}
if (more)
-@@ -888,7 +933,6 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
+@@ -879,7 +924,6 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
goto free_frag;
skb_reserve(skb, q->buf_offset);
@@ -287,7 +287,7 @@
*(u32 *)skb->cb = info;
-@@ -904,10 +948,10 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
+@@ -895,10 +939,10 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
continue;
free_frag:
@@ -300,7 +300,7 @@
return done;
}
-@@ -952,7 +996,7 @@ mt76_dma_init(struct mt76_dev *dev,
+@@ -943,7 +987,7 @@ mt76_dma_init(struct mt76_dev *dev,
mt76_for_each_q_rx(dev, i) {
netif_napi_add(&dev->napi_dev, &dev->napi[i], poll);
@@ -309,7 +309,7 @@
napi_enable(&dev->napi[i]);
}
-@@ -1003,8 +1047,6 @@ void mt76_dma_cleanup(struct mt76_dev *dev)
+@@ -994,8 +1038,6 @@ void mt76_dma_cleanup(struct mt76_dev *dev)
netif_napi_del(&dev->napi[i]);
mt76_dma_rx_cleanup(dev, q);
@@ -319,7 +319,7 @@
mt76_free_pending_txwi(dev);
diff --git a/mac80211.c b/mac80211.c
-index 95861d47..90447472 100644
+index 4655f814..4dc7627e 100644
--- a/mac80211.c
+++ b/mac80211.c
@@ -4,7 +4,6 @@
@@ -330,7 +330,7 @@
#include "mt76.h"
#define CHAN2G(_idx, _freq) { \
-@@ -569,47 +568,6 @@ void mt76_unregister_phy(struct mt76_phy *phy)
+@@ -573,47 +572,6 @@ void mt76_unregister_phy(struct mt76_phy *phy)
}
EXPORT_SYMBOL_GPL(mt76_unregister_phy);
@@ -378,7 +378,7 @@
struct mt76_dev *
mt76_alloc_device(struct device *pdev, unsigned int size,
const struct ieee80211_ops *ops,
-@@ -1745,21 +1703,6 @@ void mt76_ethtool_worker(struct mt76_ethtool_worker_info *wi,
+@@ -1753,21 +1711,6 @@ void mt76_ethtool_worker(struct mt76_ethtool_worker_info *wi,
}
EXPORT_SYMBOL_GPL(mt76_ethtool_worker);
@@ -401,10 +401,10 @@
{
struct ieee80211_hw *hw = phy->hw;
diff --git a/mt76.h b/mt76.h
-index 22c6531a..19100d62 100644
+index bc0c9ae7..d17650d0 100644
--- a/mt76.h
+++ b/mt76.h
-@@ -210,7 +210,7 @@ struct mt76_queue {
+@@ -209,7 +209,7 @@ struct mt76_queue {
dma_addr_t desc_dma;
struct sk_buff *rx_head;
@@ -633,7 +633,7 @@
return -ENOMEM;
}
diff --git a/mt7921/main.c b/mt7921/main.c
-index 75eaf86c..1434ca79 100644
+index a72964e7..4c400223 100644
--- a/mt7921/main.c
+++ b/mt7921/main.c
@@ -1090,34 +1090,17 @@ static void
@@ -699,7 +699,7 @@
static u64
diff --git a/usb.c b/usb.c
-index b88959ef..3e281715 100644
+index 5e5c7bf5..f0a50f57 100644
--- a/usb.c
+++ b/usb.c
@@ -319,27 +319,29 @@ mt76u_set_endpoints(struct usb_interface *intf,
@@ -816,12 +816,12 @@
int i;
for (i = 0; i < q->ndesc; i++) {
-@@ -705,7 +701,13 @@ mt76u_free_rx_queue(struct mt76_dev *dev, struct mt76_queue *q)
+@@ -705,8 +701,12 @@ mt76u_free_rx_queue(struct mt76_dev *dev, struct mt76_queue *q)
mt76u_urb_free(q->entry[i].urb);
q->entry[i].urb = NULL;
}
- page_pool_destroy(q->page_pool);
-+
+- q->page_pool = NULL;
+ if (!q->rx_page.va)
+ return;
+
diff --git a/recipes-wifi/linux-mt76/files/patches/4001-mt76-revert-get_of_mac_addr.patch b/recipes-wifi/linux-mt76/files/patches/4001-mt76-revert-get_of_mac_addr.patch
index 143f279..7a0aa12 100644
--- a/recipes-wifi/linux-mt76/files/patches/4001-mt76-revert-get_of_mac_addr.patch
+++ b/recipes-wifi/linux-mt76/files/patches/4001-mt76-revert-get_of_mac_addr.patch
@@ -1,4 +1,4 @@
-From d5719b44dcc2f6ef728a63f523dbbe9f089a2eaf Mon Sep 17 00:00:00 2001
+From 5b3d131191690db907ee5c0ba43a80cb0f23b3bc Mon Sep 17 00:00:00 2001
From: Shayne Chen <shayne.chen@mediatek.com>
Date: Tue, 13 Dec 2022 10:51:46 +0800
Subject: [PATCH 4001/4005] mt76: revert get_of_mac_addr
@@ -8,7 +8,7 @@
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/eeprom.c b/eeprom.c
-index d1612641..1f29cf99 100644
+index 6e6d84e3..b2df0f44 100644
--- a/eeprom.c
+++ b/eeprom.c
@@ -128,9 +128,15 @@ void
diff --git a/recipes-wifi/linux-mt76/files/patches/4002-mt76-include-header-files-for-module-param.patch b/recipes-wifi/linux-mt76/files/patches/4002-mt76-include-header-files-for-module-param.patch
index 509b828..e7661df 100644
--- a/recipes-wifi/linux-mt76/files/patches/4002-mt76-include-header-files-for-module-param.patch
+++ b/recipes-wifi/linux-mt76/files/patches/4002-mt76-include-header-files-for-module-param.patch
@@ -1,4 +1,4 @@
-From 83be679b14eb071b0eb1cedac9d004901322b2f3 Mon Sep 17 00:00:00 2001
+From 227f29f577dda88bda5c6213a655e89ff3b9203c Mon Sep 17 00:00:00 2001
From: Shayne Chen <shayne.chen@mediatek.com>
Date: Tue, 13 Dec 2022 10:38:13 +0800
Subject: [PATCH 4002/4005] mt76: include header files for module param
@@ -47,7 +47,7 @@
int mt76_connac_mcu_start_firmware(struct mt76_dev *dev, u32 addr, u32 option)
{
diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index b5a0967b..f4867ea7 100644
+index e1c08178..37291865 100644
--- a/mt7915/mcu.c
+++ b/mt7915/mcu.c
@@ -6,6 +6,7 @@
diff --git a/recipes-wifi/linux-mt76/files/patches/4003-mt76-revert-kernel-api-for-kernel-5.4.patch b/recipes-wifi/linux-mt76/files/patches/4003-mt76-revert-kernel-api-for-kernel-5.4.patch
index d7d40c2..a75825e 100644
--- a/recipes-wifi/linux-mt76/files/patches/4003-mt76-revert-kernel-api-for-kernel-5.4.patch
+++ b/recipes-wifi/linux-mt76/files/patches/4003-mt76-revert-kernel-api-for-kernel-5.4.patch
@@ -1,4 +1,4 @@
-From 1796376cd4aedff17a93f6a28c5b321d678ebf95 Mon Sep 17 00:00:00 2001
+From be0397f77f21cfbc5f865d89d9c4dcdc87f06233 Mon Sep 17 00:00:00 2001
From: Peter Chiu <chui-hao.chiu@mediatek.com>
Date: Fri, 30 Dec 2022 11:11:59 +0800
Subject: [PATCH 4003/4005] mt76: revert kernel api for kernel 5.4
@@ -24,10 +24,10 @@
return 0;
}
diff --git a/dma.c b/dma.c
-index 79da538c..e6021369 100644
+index 3adb1136..1fc4bd2d 100644
--- a/dma.c
+++ b/dma.c
-@@ -928,7 +928,7 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
+@@ -919,7 +919,7 @@ mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)
!(dev->drv->rx_check(dev, data, len)))
goto free_frag;
diff --git a/recipes-wifi/linux-mt76/files/patches/4004-mt76-revert-for-backports-5.15-wireless-stack.patch b/recipes-wifi/linux-mt76/files/patches/4004-mt76-revert-for-backports-5.15-wireless-stack.patch
index 1059763..652fa50 100644
--- a/recipes-wifi/linux-mt76/files/patches/4004-mt76-revert-for-backports-5.15-wireless-stack.patch
+++ b/recipes-wifi/linux-mt76/files/patches/4004-mt76-revert-for-backports-5.15-wireless-stack.patch
@@ -1,4 +1,4 @@
-From fb3205686d76d409b1cdd4a25c2dd526fda4b2e4 Mon Sep 17 00:00:00 2001
+From 1a40927274d316173f1aa460083eea54e2804a0a Mon Sep 17 00:00:00 2001
From: Shayne Chen <shayne.chen@mediatek.com>
Date: Fri, 30 Dec 2022 11:12:07 +0800
Subject: [PATCH 4004/4005] mt76: revert for backports-5.15 wireless stack
@@ -22,10 +22,10 @@
15 files changed, 168 insertions(+), 178 deletions(-)
diff --git a/dma.c b/dma.c
-index e6021369..c2125106 100644
+index 1fc4bd2d..e7d174b8 100644
--- a/dma.c
+++ b/dma.c
-@@ -995,7 +995,7 @@ mt76_dma_init(struct mt76_dev *dev,
+@@ -986,7 +986,7 @@ mt76_dma_init(struct mt76_dev *dev,
init_completion(&dev->mmio.wed_reset_complete);
mt76_for_each_q_rx(dev, i) {
@@ -35,10 +35,10 @@
napi_enable(&dev->napi[i]);
}
diff --git a/mac80211.c b/mac80211.c
-index 90447472..14a02c01 100644
+index 4dc7627e..4c88710f 100644
--- a/mac80211.c
+++ b/mac80211.c
-@@ -1509,7 +1509,7 @@ EXPORT_SYMBOL_GPL(mt76_get_sar_power);
+@@ -1517,7 +1517,7 @@ EXPORT_SYMBOL_GPL(mt76_get_sar_power);
static void
__mt76_csa_finish(void *priv, u8 *mac, struct ieee80211_vif *vif)
{
@@ -47,7 +47,7 @@
ieee80211_csa_finish(vif);
}
-@@ -1531,7 +1531,7 @@ __mt76_csa_check(void *priv, u8 *mac, struct ieee80211_vif *vif)
+@@ -1539,7 +1539,7 @@ __mt76_csa_check(void *priv, u8 *mac, struct ieee80211_vif *vif)
{
struct mt76_dev *dev = priv;
@@ -524,10 +524,10 @@
field = RATE_PARAM_FIXED;
diff --git a/mt7915/dma.c b/mt7915/dma.c
-index 4dd321ee..354d1e0e 100644
+index 6d9b2d15..08322453 100644
--- a/mt7915/dma.c
+++ b/mt7915/dma.c
-@@ -552,8 +552,8 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
+@@ -554,8 +554,8 @@ int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)
if (ret < 0)
return ret;
@@ -539,10 +539,10 @@
mt7915_dma_enable(dev);
diff --git a/mt7915/init.c b/mt7915/init.c
-index a1be5b7d..9e8003d7 100644
+index 70563c9d..0b852286 100644
--- a/mt7915/init.c
+++ b/mt7915/init.c
-@@ -1139,8 +1139,7 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band,
+@@ -1160,8 +1160,7 @@ mt7915_init_he_caps(struct mt7915_phy *phy, enum nl80211_band band,
mt7915_gen_ppe_thresh(he_cap->ppe_thres, nss);
} else {
he_cap_elem->phy_cap_info[9] |=
@@ -553,7 +553,7 @@
if (band == NL80211_BAND_6GHZ) {
diff --git a/mt7915/mac.c b/mt7915/mac.c
-index b7559182..26eb211a 100644
+index 180c1ae3..583b71b1 100644
--- a/mt7915/mac.c
+++ b/mt7915/mac.c
@@ -902,7 +902,7 @@ mt7915_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi)
@@ -610,7 +610,7 @@
mutex_lock(&dev->mt76.mutex);
diff --git a/mt7915/mcu.c b/mt7915/mcu.c
-index 003e33be..a7d3adc2 100644
+index 37291865..4f1bd1cd 100644
--- a/mt7915/mcu.c
+++ b/mt7915/mcu.c
@@ -64,7 +64,7 @@ mt7915_mcu_set_sta_he_mcs(struct ieee80211_sta *sta, __le16 *he_mcs,
diff --git a/recipes-wifi/linux-mt76/files/patches/4005-wifi-mt76-revert-EHT-definitions.patch b/recipes-wifi/linux-mt76/files/patches/4005-wifi-mt76-revert-EHT-definitions.patch
index 8404f7b..479accf 100644
--- a/recipes-wifi/linux-mt76/files/patches/4005-wifi-mt76-revert-EHT-definitions.patch
+++ b/recipes-wifi/linux-mt76/files/patches/4005-wifi-mt76-revert-EHT-definitions.patch
@@ -1,4 +1,4 @@
-From b655964b1f68678a665f30a68c13a73feeffaa73 Mon Sep 17 00:00:00 2001
+From 21286ba6a27ae54885687c0f82a48e52cef638aa Mon Sep 17 00:00:00 2001
From: Peter Chiu <chui-hao.chiu@mediatek.com>
Date: Fri, 3 Feb 2023 17:09:55 +0800
Subject: [PATCH 4005/4005] wifi: mt76: revert EHT definitions
@@ -99,10 +99,10 @@
#define DEFAULT_HE_DURATION_RTS_THRES 1023
static void
diff --git a/mt76_connac_mcu.h b/mt76_connac_mcu.h
-index 747ae7e9..3d4322d1 100644
+index 287cffcc..b80a1011 100644
--- a/mt76_connac_mcu.h
+++ b/mt76_connac_mcu.h
-@@ -1897,12 +1897,8 @@ void mt76_connac_mcu_reg_wr(struct mt76_dev *dev, u32 offset, u32 val);
+@@ -1894,12 +1894,8 @@ void mt76_connac_mcu_reg_wr(struct mt76_dev *dev, u32 offset, u32 val);
const struct ieee80211_sta_he_cap *
mt76_connac_get_he_phy_cap(struct mt76_phy *phy, struct ieee80211_vif *vif);
diff --git a/recipes-wifi/linux-mt76/files/patches/patches.inc b/recipes-wifi/linux-mt76/files/patches/patches.inc
index c041c72..833a2b0 100644
--- a/recipes-wifi/linux-mt76/files/patches/patches.inc
+++ b/recipes-wifi/linux-mt76/files/patches/patches.inc
@@ -1,6 +1,5 @@
#patch patches (come from openwrt/lede/target/linux/mediatek)
SRC_URI_append = " \
- file://0001-wifi-mt76-mt7915-rework-mt7915_thermal_init.patch \
file://1001-mt76-mt7915-add-mtk-internal-debug-tools-for-mt76.patch \
file://1002-mt76-mt7915-csi-implement-csi-support.patch \
file://1003-mt76-mt7915-air-monitor-support.patch \
@@ -32,22 +31,20 @@
file://1130-mt76-mt7915-amsdu-set-and-get-control.patch \
file://1131-wifi-mt76-mt7915-add-support-for-he-ldpc-control-fro.patch \
file://1132-mt76-mt7915-Add-vendor-command-attribute-for-RTS-BW-.patch \
- file://1133-mt76-mt7915-Allow-AP-to-change-channel-width-for-40M.patch \
+ file://1134-mt76-mt7915-add-vendor-cmd-to-get-available-color-bi.patch \
file://3001-mt76-mt7915-wed-add-wed-tx-support.patch \
file://3002-mt76-mt7915-wed-add-wds-support-when-wed-is-enabled.patch \
file://3003-mt76-mt7915-wed-add-fill-receive-path-to-report-wed-.patch \
file://3004-mt76-mt7915-wed-find-rx-token-by-physical-address.patch \
- file://3005-mt76-mt7915-wed-drop-scatter-and-gather-frame.patch \
- file://3006-mt76-mt7915-wed-HW-ATF-support-for-mt7986.patch \
- file://3007-mt76-mt7915-wed-add-mt7916-2-pcie-support-when-wed-o.patch \
- file://3008-mt76-mt7915-wed-add-rxwi-for-further-in-chip-rro.patch \
- file://3009-mt76-mt7915-add-mt7915_net_setup_tc-to-support-wifi2.patch \
- file://3010-wifi-mt76-mt7915-add-wa-command-to-get-tx-msdu-count.patch \
- file://3011-wifi-mt76-get-tx-count-and-tx-failed-from-mcu-comman.patch \
- file://3012-wifi-mt76-mt7915-enable-PPDU-TxS-to-host-when-wed-en.patch \
- file://3013-wifi-mt76-mt7915-get-tx-retries-from-tx-free-done-ev.patch \
- file://3014-wifi-mt76-update-debugfs-knob-for-reset-counter-and-.patch \
- file://3015-mt76-connac-wed-add-wed-rx-copy-skb-and-revert-page_.patch \
+ file://3005-mt76-mt7915-wed-HW-ATF-support-for-mt7986.patch \
+ file://3006-mt76-mt7915-wed-add-rxwi-for-further-in-chip-rro.patch \
+ file://3007-mt76-mt7915-add-mt7915_net_setup_tc-to-support-wifi2.patch \
+ file://3008-wifi-mt76-mt7915-add-wa-command-to-get-tx-msdu-count.patch \
+ file://3009-wifi-mt76-get-tx-count-and-tx-failed-from-mcu-comman.patch \
+ file://3010-wifi-mt76-mt7915-enable-PPDU-TxS-to-host-when-wed-en.patch \
+ file://3011-wifi-mt76-mt7915-get-tx-retries-from-tx-free-done-ev.patch \
+ file://3012-wifi-mt76-update-debugfs-knob-for-reset-counter-and-.patch \
+ file://3013-mt76-connac-wed-add-wed-rx-copy-skb-and-revert-page_.patch \
file://4001-mt76-revert-get_of_mac_addr.patch \
file://4002-mt76-include-header-files-for-module-param.patch \
file://4003-mt76-revert-kernel-api-for-kernel-5.4.patch \
diff --git a/recipes-wifi/linux-mt76/files/src/firmware/mt7981_rom_patch.bin b/recipes-wifi/linux-mt76/files/src/firmware/mt7981_rom_patch.bin
new file mode 100644
index 0000000..ae02f94
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/src/firmware/mt7981_rom_patch.bin
Binary files differ
diff --git a/recipes-wifi/linux-mt76/files/src/firmware/mt7981_wa.bin b/recipes-wifi/linux-mt76/files/src/firmware/mt7981_wa.bin
new file mode 100644
index 0000000..5178123
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/src/firmware/mt7981_wa.bin
Binary files differ
diff --git a/recipes-wifi/linux-mt76/files/src/firmware/mt7981_wm.bin b/recipes-wifi/linux-mt76/files/src/firmware/mt7981_wm.bin
new file mode 100644
index 0000000..f0010ca
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/src/firmware/mt7981_wm.bin
Binary files differ
diff --git a/recipes-wifi/linux-mt76/files/src/firmware/mt7981_wo.bin b/recipes-wifi/linux-mt76/files/src/firmware/mt7981_wo.bin
new file mode 100644
index 0000000..aaf9865
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/src/firmware/mt7981_wo.bin
Binary files differ
diff --git a/recipes-wifi/linux-mt76/files/src/firmware/mt7996/mt7996_eeprom_tm.bin b/recipes-wifi/linux-mt76/files/src/firmware/mt7996/mt7996_eeprom_tm.bin
new file mode 100755
index 0000000..0ff5567
--- /dev/null
+++ b/recipes-wifi/linux-mt76/files/src/firmware/mt7996/mt7996_eeprom_tm.bin
Binary files differ
diff --git a/recipes-wifi/linux-mt76/mt76.inc b/recipes-wifi/linux-mt76/mt76.inc
index 4feb511..1739876 100644
--- a/recipes-wifi/linux-mt76/mt76.inc
+++ b/recipes-wifi/linux-mt76/mt76.inc
@@ -1 +1 @@
-SRCREV ?= "b2360d59747c6fed2b65bc1c3563c10593c83f3e"
+SRCREV ?= "c32d6d849c43792abd8007e13e468b12d6d6e0b7"
diff --git a/recipes-wifi/wifi-test-tool/files/src/wifi-test-tool.c b/recipes-wifi/wifi-test-tool/files/src/wifi-test-tool.c
index 2aabd4b..77b23cf 100644
--- a/recipes-wifi/wifi-test-tool/files/src/wifi-test-tool.c
+++ b/recipes-wifi/wifi-test-tool/files/src/wifi-test-tool.c
@@ -125,10 +125,11 @@
// HT40 -> 11NGHT40PLUS
// VHT40+ -> 11ACVHT40PLUS
// HE80 -> 11AXHE80
- if (strstr(htmode, "+") != NULL) {
+ // EHT320-1 -> 11BEEHT320-1
+ if (strstr(htmode, "40+") != NULL) {
strncpy(tmp, htmode, strlen(htmode) - 1);
strcat(tmp, "PLUS");
- } else if (strstr(htmode, "-") != NULL) {
+ } else if (strstr(htmode, "40-") != NULL) {
strncpy(tmp, htmode, strlen(htmode) - 1);
strcat(tmp, "MINUS");
} else
@@ -137,6 +138,14 @@
if (strstr(htmode, "VHT") != NULL) {
snprintf(radio_param->htmode, sizeof(radio_param->htmode), "11AC%s", tmp);
+ } else if (strstr(htmode, "EHT") != NULL) {
+ snprintf(radio_param->htmode, sizeof(radio_param->htmode), "11BE%s", tmp);
+ if (strstr(htmode, "320-1") != NULL)
+ radio_param->eht_320_conf = 1;
+ else if (strstr(htmode, "320") != NULL) // EHT320 or EHT320-2
+ radio_param->eht_320_conf = 2;
+ else
+ radio_param->eht_320_conf = 0;
} else if (strstr(htmode, "HT") != NULL && strstr(htmode, "NO") == NULL) {
snprintf(radio_param->htmode, sizeof(radio_param->htmode), "11NG%s", tmp);
} else if (strstr(htmode, "HE") != NULL) {
@@ -355,7 +364,7 @@
operationParam.autoChannelEnabled = radio_parameter.auto_channel;
operationParam.channel = radio_parameter.channel;
- //bandwidth
+ // bandwidth
if (radio_parameter.bandwidth == 20){
operationParam.channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
}else if (radio_parameter.bandwidth == 40){
@@ -364,6 +373,13 @@
operationParam.channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
}else if (radio_parameter.bandwidth == 160){
operationParam.channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
+ }else if (radio_parameter.bandwidth == 320){
+ if ((radio_parameter.eht_320_conf == 1 || radio_parameter.channel <= 29) && radio_parameter.channel < 193)
+ operationParam.channelWidth = WIFI_CHANNELBANDWIDTH_320_1MHZ;
+ else if (radio_parameter.eht_320_conf == 2 || radio_parameter.channel >= 193)
+ operationParam.channelWidth = WIFI_CHANNELBANDWIDTH_320_2MHZ;
+ else
+ fprintf(stderr, "[Set EHT 320 bandwidth error with conf %d!!!]\n", radio_parameter.eht_320_conf);
}
// htmode
@@ -372,25 +388,30 @@
mode |= WIFI_80211_VARIANT_B | WIFI_80211_VARIANT_G;
if (strcmp(radio_parameter.htmode, "NOHT") == 0 || strcmp(radio_parameter.htmode, "NONE") == 0)
strcpy(radio_parameter.htmode, "11G");
-
- if (strstr(radio_parameter.htmode, "HE") != NULL)
+ else if (strstr(radio_parameter.htmode, "HE") != NULL)
mode |= WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AX;
+ else if (strstr(radio_parameter.htmode, "EHT") != NULL)
+ mode |= WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AX | WIFI_80211_VARIANT_BE;
+ else if (strstr(radio_parameter.htmode, "HT") != NULL)
+ mode |= WIFI_80211_VARIANT_N;
} else if (strcmp(radio_parameter.band, "5g") == 0) {
mode |= WIFI_80211_VARIANT_A;
if (strcmp(radio_parameter.htmode, "NOHT") == 0 || strcmp(radio_parameter.htmode, "NONE") == 0)
strcpy(radio_parameter.htmode, "11A");
-
- if (strstr(radio_parameter.htmode, "HE") != NULL)
+ else if (strstr(radio_parameter.htmode, "VHT") != NULL)
+ mode |= WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AC;
+ else if (strstr(radio_parameter.htmode, "HE") != NULL)
mode |= WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AC | WIFI_80211_VARIANT_AX;
- }else if (strcmp(radio_parameter.band, "6g") == 0) {
- mode |= WIFI_80211_VARIANT_A | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AC | WIFI_80211_VARIANT_AX;;
- }
-
- if (strstr(radio_parameter.htmode, "VHT") != NULL)
- mode |= WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AC;
- else if (strstr(radio_parameter.htmode, "HT") != NULL && strstr(radio_parameter.htmode, "NO") == NULL)
- mode |= WIFI_80211_VARIANT_N;
+ else if (strstr(radio_parameter.htmode, "EHT") != NULL)
+ mode |= WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AC | WIFI_80211_VARIANT_AX | WIFI_80211_VARIANT_BE;
+ else if (strstr(radio_parameter.htmode, "HT") != NULL)
+ mode |= WIFI_80211_VARIANT_N;
+ } else if (strcmp(radio_parameter.band, "6g") == 0) {
+ mode |= WIFI_80211_VARIANT_AX;
+ if (strstr(radio_parameter.htmode, "EHT") != NULL)
+ mode |= WIFI_80211_VARIANT_BE;
+ }
operationParam.variant = mode;
@@ -843,14 +864,7 @@
}
}
if (parsing_radio == TRUE) {
- char cmd[32] = {0};
- char buf[32] = {0};
set_radio_param(radio_param);
-
- /* sleep 3 to wait ifconfig up state update, workaround to avoid
- disable ap interface fail. */
- sprintf(cmd, "sleep 5");
- _syscmd(cmd, buf, sizeof(buf));
}
else if (intf_param.sta_mode == TRUE)
set_sta_param(intf_param);
@@ -865,10 +879,12 @@
fprintf(stderr, "\n----- Disable all interfaces. -----\n");
for (i = 0; i < max_radio_num; i++ ){
- for(j = MAX_NUM_VAP_PER_RADIO - 1; j >= 0 ; j--) {
- ret = wifi_setApEnable(i*max_radio_num+j, FALSE);
+ for(j = max_radio_num*(MAX_NUM_VAP_PER_RADIO-1) + i; j >= 0; j -= max_radio_num) {
+ ret = wifi_setApEnable(j, FALSE);
if (ret != RETURN_OK)
- fprintf(stderr, "[disable ap %d failed!!!]\n", i*max_radio_num+j);
+ fprintf(stderr, "[disable ap %d failed!!!]\n", j);
+ else
+ fprintf(stderr, "[disable ap %d success.]\n", j);
}
}
fprintf(stderr, "\n----- Start setting Vaps. -----\n");
diff --git a/recipes-wifi/wifi-test-tool/files/src/wifi-test-tool.h b/recipes-wifi/wifi-test-tool/files/src/wifi-test-tool.h
index 2ca1331..a235ed0 100644
--- a/recipes-wifi/wifi-test-tool/files/src/wifi-test-tool.h
+++ b/recipes-wifi/wifi-test-tool/files/src/wifi-test-tool.h
@@ -23,6 +23,7 @@
char band[8];
char htmode[16];
int bandwidth;
+ int eht_320_conf;
int pure_mode;
int chanbw;
char ht_capab[8];
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
deleted file mode 100644
index 3237aa3..0000000
--- a/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0010-hostapd-mtk-Add-DFS-and-ZWDFS-support.patch
+++ /dev/null
@@ -1,376 +0,0 @@
-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_mu(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
-
diff --git a/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0010-hostapd-mtk-Add-DFS-detection-mode.patch b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0010-hostapd-mtk-Add-DFS-detection-mode.patch
new file mode 100644
index 0000000..7ec986a
--- /dev/null
+++ b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0010-hostapd-mtk-Add-DFS-detection-mode.patch
@@ -0,0 +1,136 @@
+From 6828156c206701f5a0e5d30afcc514f452ce0ada Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Mon, 20 Feb 2023 14:55:49 +0800
+Subject: [PATCH 10/16] hostapd: mtk: Add DFS detection mode
+
+Add DFS detection mode for testing radar detection rate.
+If DFS detection mode is on, AP will not switch channels when receiving
+a radar signal.
+This detection mode also supports background chain.
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ hostapd/config_file.c | 4 ++++
+ hostapd/ctrl_iface.c | 23 +++++++++++++++++++++++
+ src/ap/ap_config.h | 13 +++++++++++++
+ src/ap/dfs.c | 10 ++++++++++
+ 4 files changed, 50 insertions(+)
+
+diff --git a/hostapd/config_file.c b/hostapd/config_file.c
+index 63c9d40..cd15349 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 c881d37..0b4c234 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -3522,6 +3522,26 @@ 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_receive_process(struct hostapd_data *hapd,
+ char *buf, char *reply,
+ int reply_size,
+@@ -4081,6 +4101,9 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
+ reply_len = hostapd_ctrl_iface_get_mu(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 {
+ 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 a9e3d2a..77f6169 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 b5d105d..5cb7799 100644
+--- a/src/ap/dfs.c
++++ b/src/ap/dfs.c
+@@ -1317,6 +1317,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 +1370,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;
+--
+2.18.0
+
diff --git a/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0011-hostapd-mtk-Add-DFS-offchan-channel-switch.patch b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0011-hostapd-mtk-Add-DFS-offchan-channel-switch.patch
new file mode 100644
index 0000000..1d8baf8
--- /dev/null
+++ b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0011-hostapd-mtk-Add-DFS-offchan-channel-switch.patch
@@ -0,0 +1,192 @@
+From 88dd3df28e3736af4cca0daf4f7d19ab888ea6c4 Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Mon, 20 Feb 2023 14:56:55 +0800
+Subject: [PATCH 11/16] hostapd: mtk: Add DFS offchan channel switch
+
+Add DFS background chain channel switch command for testing purpose.
+This feature is implemented via hostapd_cli command.
+Command format:
+hostapd_cli -i <interface> raw SET_OFFCHAN_CTRL chan=<dfs_channel>
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ hostapd/ctrl_iface.c | 72 ++++++++++++++++++++++++++++++++++++++++++++
+ src/ap/dfs.c | 25 ++++++---------
+ src/ap/dfs.h | 15 +++++++++
+ 3 files changed, 96 insertions(+), 16 deletions(-)
+
+diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
+index 0b4c234..6ea1573 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -3542,6 +3542,76 @@ hostapd_ctrl_iface_set_dfs_detect_mode(struct hostapd_data *hapd, char *value,
+ }
+
+
++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,
+@@ -4104,6 +4174,8 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
+ } 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/dfs.c b/src/ap/dfs.c
+index 5cb7799..1c3f678 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;
+diff --git a/src/ap/dfs.h b/src/ap/dfs.h
+index 606c1b3..c2556d2 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 */
+--
+2.18.0
+
diff --git a/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0011-hostapd-mtk-Add-amsdu-set-get-ctrl.patch b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0011-hostapd-mtk-Add-amsdu-set-get-ctrl.patch
deleted file mode 100644
index dba90d1..0000000
--- a/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0011-hostapd-mtk-Add-amsdu-set-get-ctrl.patch
+++ /dev/null
@@ -1,400 +0,0 @@
-From bc0722ebc1cc08be6239879fddaef37e0db2d9e0 Mon Sep 17 00:00:00 2001
-From: Evelyn Tsai <evelyn.tsai@mediatek.com>
-Date: Fri, 16 Dec 2022 03:57:11 +0800
-Subject: [PATCH 11/15] hostapd: mtk: Add amsdu set get ctrl
-
----
- hostapd/config_file.c | 9 +++
- hostapd/ctrl_iface.c | 26 +++++++
- hostapd/hostapd_cli.c | 9 +++
- src/ap/ap_config.c | 1 +
- src/ap/ap_config.h | 1 +
- src/ap/ap_drv_ops.c | 14 ++++
- src/ap/ap_drv_ops.h | 2 +
- src/ap/hostapd.c | 2 +
- src/common/mtk_vendor.h | 17 ++++-
- src/drivers/driver.h | 9 +++
- src/drivers/driver_nl80211.c | 114 ++++++++++++++++++++++++++++++
- src/drivers/driver_nl80211.h | 1 +
- src/drivers/driver_nl80211_capa.c | 3 +
- 13 files changed, 207 insertions(+), 1 deletion(-)
-
-diff --git a/hostapd/config_file.c b/hostapd/config_file.c
-index cd1534952..10ea52518 100644
---- a/hostapd/config_file.c
-+++ b/hostapd/config_file.c
-@@ -4807,6 +4807,15 @@ static int hostapd_config_fill(struct hostapd_config *conf,
- u8 en = strtol(pos, NULL, 10);
-
- conf->dfs_detect_mode = en;
-+ } else if (os_strcmp(buf, "amsdu") == 0) {
-+ int val = atoi(pos);
-+ if (val < 0 || val > 1) {
-+ wpa_printf(MSG_ERROR,
-+ "Line %d: invalid amsdu value",
-+ line);
-+ return 1;
-+ }
-+ conf->amsdu = val;
- } else {
- wpa_printf(MSG_ERROR,
- "Line %d: unknown configuration item '%s'",
-diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
-index 6ea1573b8..0ad8451aa 100644
---- a/hostapd/ctrl_iface.c
-+++ b/hostapd/ctrl_iface.c
-@@ -3612,6 +3612,30 @@ hostapd_ctrl_iface_set_offchan_ctrl(struct hostapd_data *hapd, char *cmd,
- }
-
-
-+static int
-+hostapd_ctrl_iface_get_amsdu(struct hostapd_data *hapd, char *buf,
-+ size_t buflen)
-+{
-+ u8 amsdu;
-+ int ret;
-+ char *pos, *end;
-+
-+ pos = buf;
-+ end = buf + buflen;
-+
-+ if (hostapd_drv_amsdu_dump(hapd, &amsdu) == 0) {
-+ hapd->iconf->amsdu = amsdu;
-+ ret = os_snprintf(pos, end - pos, "[hostapd_cli] AMSDU: %u\n",
-+ hapd->iconf->amsdu);
-+ }
-+
-+ if (os_snprintf_error(end - pos, ret))
-+ return 0;
-+
-+ return ret;
-+}
-+
-+
- static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
- char *buf, char *reply,
- int reply_size,
-@@ -4176,6 +4200,8 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
- 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 if (os_strncmp(buf, "GET_AMSDU", 9) == 0) {
-+ reply_len = hostapd_ctrl_iface_get_amsdu(hapd, reply, reply_size);
- } else {
- os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
- reply_len = 16;
-diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
-index c2a123a8c..30b3392e6 100644
---- a/hostapd/hostapd_cli.c
-+++ b/hostapd/hostapd_cli.c
-@@ -1593,6 +1593,13 @@ static int hostapd_cli_cmd_get_ibf(struct wpa_ctrl *ctrl, int argc,
- }
-
-
-+static int hostapd_cli_cmd_get_amsdu(struct wpa_ctrl *ctrl, int argc,
-+ char *argv[])
-+{
-+ return hostapd_cli_cmd(ctrl, "GET_AMSDU", 0, NULL, NULL);
-+}
-+
-+
- struct hostapd_cli_cmd {
- const char *cmd;
- int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
-@@ -1796,6 +1803,8 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
- "<tx type(0/1/2)> <interval> = runtime set inband discovery" },
- { "get_ibf", hostapd_cli_cmd_get_ibf, NULL,
- " = show iBF state (enabled/disabled)"},
-+ { "get_amsdu", hostapd_cli_cmd_get_amsdu, NULL,
-+ " = show AMSDU state"},
- { NULL, NULL, NULL, NULL }
- };
-
-diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
-index 7a96cb8b2..85ad5e444 100644
---- a/src/ap/ap_config.c
-+++ b/src/ap/ap_config.c
-@@ -299,6 +299,7 @@ struct hostapd_config * hostapd_config_defaults(void)
- conf->edcca_compensation = EDCCA_DEFAULT_COMPENSATION;
- conf->three_wire_enable = THREE_WIRE_MODE_DISABLE;
- conf->ibf_enable = IBF_DEFAULT_ENABLE;
-+ conf->amsdu = 1;
-
- return conf;
- }
-diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
-index 77f6169d2..a9ac39619 100644
---- a/src/ap/ap_config.h
-+++ b/src/ap/ap_config.h
-@@ -1161,6 +1161,7 @@ struct hostapd_config {
- u8 three_wire_enable;
- u8 ibf_enable;
- u8 dfs_detect_mode;
-+ u8 amsdu;
- };
-
- enum three_wire_mode {
-diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
-index 60ae8253b..1a82f234c 100644
---- a/src/ap/ap_drv_ops.c
-+++ b/src/ap/ap_drv_ops.c
-@@ -1077,4 +1077,18 @@ int hostapd_drv_ibf_dump(struct hostapd_data *hapd, u8 *ibf_enable)
- if (!hapd->driver || !hapd->driver->ibf_dump)
- return 0;
- return hapd->driver->ibf_dump(hapd->drv_priv, ibf_enable);
-+}
-+
-+int hostapd_drv_amsdu_ctrl(struct hostapd_data *hapd)
-+{
-+ if (!hapd->driver || !hapd->driver->amsdu_ctrl)
-+ return 0;
-+ return hapd->driver->amsdu_ctrl(hapd->drv_priv, hapd->iconf->amsdu);
-+}
-+
-+int hostapd_drv_amsdu_dump(struct hostapd_data *hapd, u8 *amsdu)
-+{
-+ if (!hapd->driver || !hapd->driver->amsdu_dump)
-+ return 0;
-+ return hapd->driver->amsdu_dump(hapd->drv_priv, amsdu);
- }
-\ No newline at end of file
-diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
-index ab9aedcee..4406666fd 100644
---- a/src/ap/ap_drv_ops.h
-+++ b/src/ap/ap_drv_ops.h
-@@ -147,6 +147,8 @@ int hostapd_drv_mu_dump(struct hostapd_data *hapd, u8 *mu_onoff);
- int hostapd_drv_three_wire_ctrl(struct hostapd_data *hapd);
- int hostapd_drv_ibf_ctrl(struct hostapd_data *hapd);
- int hostapd_drv_ibf_dump(struct hostapd_data *hapd, u8 *ibf_enable);
-+int hostapd_drv_amsdu_ctrl(struct hostapd_data *hapd);
-+int hostapd_drv_amsdu_dump(struct hostapd_data *hapd, u8 *amsdu);
-
- #include "drivers/driver.h"
-
-diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
-index a0229c9ca..152060db4 100644
---- a/src/ap/hostapd.c
-+++ b/src/ap/hostapd.c
-@@ -2310,6 +2310,8 @@ dfs_offload:
- goto fail;
- if (hostapd_drv_ibf_ctrl(hapd) < 0)
- goto fail;
-+ if (hostapd_drv_amsdu_ctrl(hapd) < 0)
-+ goto fail;
-
- wpa_printf(MSG_DEBUG, "%s: Setup of interface done.",
- iface->bss[0]->conf->iface);
-diff --git a/src/common/mtk_vendor.h b/src/common/mtk_vendor.h
-index 4050cf886..0999ea9e2 100644
---- a/src/common/mtk_vendor.h
-+++ b/src/common/mtk_vendor.h
-@@ -167,7 +167,6 @@ enum mtk_vendor_attr_wireless_ctrl {
- MTK_VENDOR_ATTR_WIRELESS_CTRL_NUSERS_OFDMA,
- MTK_VENDOR_ATTR_WIRELESS_CTRL_BA_BUFFER_SIZE,
- MTK_VENDOR_ATTR_WIRELESS_CTRL_MIMO,
-- MTK_VENDOR_ATTR_WIRELESS_CTRL_AMPDU,
- MTK_VENDOR_ATTR_WIRELESS_CTRL_AMSDU,
- MTK_VENDOR_ATTR_WIRELESS_CTRL_CERT,
-
-@@ -177,6 +176,22 @@ enum mtk_vendor_attr_wireless_ctrl {
- NUM_MTK_VENDOR_ATTRS_WIRELESS_CTRL - 1
- };
-
-+enum mtk_vendor_attr_wireless_dump {
-+ MTK_VENDOR_ATTR_WIRELESS_DUMP_UNSPEC,
-+
-+ MTK_VENDOR_ATTR_WIRELESS_DUMP_AMSDU,
-+
-+ /* keep last */
-+ NUM_MTK_VENDOR_ATTRS_WIRELESS_DUMP,
-+ MTK_VENDOR_ATTR_WIRELESS_DUMP_MAX =
-+ NUM_MTK_VENDOR_ATTRS_WIRELESS_DUMP - 1
-+};
-+
-+static const struct nla_policy
-+wireless_dump_policy[NUM_MTK_VENDOR_ATTRS_WIRELESS_DUMP] = {
-+ [MTK_VENDOR_ATTR_WIRELESS_DUMP_AMSDU] = { .type = NLA_U8 },
-+};
-+
- enum mtk_vendor_attr_rfeature_ctrl {
- MTK_VENDOR_ATTR_RFEATURE_CTRL_UNSPEC,
-
-diff --git a/src/drivers/driver.h b/src/drivers/driver.h
-index aa23fbdb3..b07aaf3fe 100644
---- a/src/drivers/driver.h
-+++ b/src/drivers/driver.h
-@@ -4727,6 +4727,15 @@ struct wpa_driver_ops {
- *
- */
- int (*start_disabled)(void *priv);
-+
-+ /**
-+ * amsdu_ctrl - enable/disable amsdu
-+ * amsdu_dump - get current amsdu status
-+ * @priv: Private driver interface data
-+ *
-+ */
-+ int (*amsdu_ctrl)(void *priv, u8 amsdu);
-+ int (*amsdu_dump)(void *priv, u8 *amsdu);
- };
-
- /**
-diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
-index 7472542cc..6702384ef 100644
---- a/src/drivers/driver_nl80211.c
-+++ b/src/drivers/driver_nl80211.c
-@@ -12804,6 +12804,118 @@ fail:
- return ret;
- }
-
-+static int nl80211_enable_amsdu(void *priv, u8 amsdu)
-+{
-+ struct i802_bss *bss = priv;
-+ struct wpa_driver_nl80211_data *drv = bss->drv;
-+ struct nl_msg *msg;
-+ struct nlattr *data;
-+ int ret;
-+
-+ if (!drv->mtk_wireless_vendor_cmd_avail) {
-+ wpa_printf(MSG_INFO,
-+ "nl80211: Driver does not support setting ap wireless control");
-+ return 0;
-+ }
-+
-+ msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR);
-+ if (!msg)
-+ goto fail;
-+
-+ if (nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_MTK) ||
-+ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, MTK_NL80211_VENDOR_SUBCMD_WIRELESS_CTRL))
-+ goto fail;
-+
-+ data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
-+ if (!data)
-+ goto fail;
-+
-+ nla_put_u8(msg, MTK_VENDOR_ATTR_WIRELESS_CTRL_AMSDU, amsdu);
-+
-+ nla_nest_end(msg, data);
-+ ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
-+ if (ret) {
-+ wpa_printf(MSG_ERROR, "Failed to set amsdu. ret=%d (%s)", ret, strerror(-ret));
-+ }
-+
-+ return ret;
-+
-+fail:
-+ nlmsg_free(msg);
-+ return -ENOBUFS;
-+}
-+
-+static int dump_amsdu_handler(struct nl_msg *msg, void *arg)
-+{
-+ u8 *amsdu = (u8 *) arg;
-+ struct nlattr *tb[NL80211_ATTR_MAX + 1];
-+ struct nlattr *tb_vendor[MTK_VENDOR_ATTR_WIRELESS_DUMP_MAX + 1];
-+ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
-+ struct nlattr *nl_vend, *attr_amsdu;
-+
-+ nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
-+ genlmsg_attrlen(gnlh, 0), NULL);
-+
-+ nl_vend = tb[NL80211_ATTR_VENDOR_DATA];
-+ if (!nl_vend)
-+ return NL_SKIP;
-+
-+ nla_parse(tb_vendor, MTK_VENDOR_ATTR_WIRELESS_DUMP_MAX,
-+ nla_data(nl_vend), nla_len(nl_vend), NULL);
-+
-+ attr_amsdu = tb_vendor[MTK_VENDOR_ATTR_WIRELESS_DUMP_AMSDU];
-+ if (!attr_amsdu ){
-+ wpa_printf(MSG_ERROR, "nl80211: cannot find vendor attributes");
-+ return NL_SKIP;
-+ }
-+
-+ *amsdu = nla_get_u8(attr_amsdu);
-+
-+ return NL_SKIP;
-+}
-+
-+static int
-+nl80211_dump_amsdu(void *priv, u8 *amsdu)
-+{
-+ struct i802_bss *bss = priv;
-+ struct wpa_driver_nl80211_data *drv = bss->drv;
-+ struct nl_msg *msg;
-+ struct nlattr *data;
-+ int ret;
-+
-+ if (!drv->mtk_wireless_vendor_cmd_avail) {
-+ wpa_printf(MSG_INFO,
-+ "nl80211: Driver does not support ap_wireless control");
-+ return 0;
-+ }
-+
-+ msg = nl80211_drv_msg(drv, NLM_F_DUMP, NL80211_CMD_VENDOR);
-+ if (!msg)
-+ goto fail;
-+
-+ if (nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_MTK) ||
-+ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, MTK_NL80211_VENDOR_SUBCMD_WIRELESS_CTRL))
-+ goto fail;
-+
-+ data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
-+ if (!data)
-+ goto fail;
-+
-+ nla_nest_end(msg, data);
-+
-+ ret = send_and_recv_msgs(drv, msg, dump_amsdu_handler, amsdu, NULL, NULL);
-+
-+ if (ret) {
-+ wpa_printf(MSG_ERROR, "Failed to dump amsdu. ret=%d (%s)", ret, strerror(-ret));
-+ }
-+
-+ return ret;
-+
-+fail:
-+ nlmsg_free(msg);
-+ return -ENOBUFS;
-+}
-+
- const struct wpa_driver_ops wpa_driver_nl80211_ops = {
- .name = "nl80211",
- .desc = "Linux nl80211/cfg80211",
-@@ -12959,4 +13071,6 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
- .ibf_ctrl = nl80211_ibf_enable,
- .ibf_dump = nl80211_ibf_dump,
- .start_disabled = nl80211_start_disabled,
-+ .amsdu_ctrl = nl80211_enable_amsdu,
-+ .amsdu_dump = nl80211_dump_amsdu,
- };
-diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h
-index 607592ceb..e57022409 100644
---- a/src/drivers/driver_nl80211.h
-+++ b/src/drivers/driver_nl80211.h
-@@ -185,6 +185,7 @@ struct wpa_driver_nl80211_data {
- unsigned int mtk_mu_vendor_cmd_avail:1;
- unsigned int mtk_3wire_vendor_cmd_avail:1;
- unsigned int mtk_ibf_vendor_cmd_avail:1;
-+ unsigned int mtk_wireless_vendor_cmd_avail:1;
-
- u64 vendor_scan_cookie;
- u64 remain_on_chan_cookie;
-diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
-index 9ecc0ff9a..fcfa68bf7 100644
---- a/src/drivers/driver_nl80211_capa.c
-+++ b/src/drivers/driver_nl80211_capa.c
-@@ -1065,6 +1065,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
- case MTK_NL80211_VENDOR_SUBCMD_IBF_CTRL:
- drv->mtk_ibf_vendor_cmd_avail = 1;
- break;
-+ case MTK_NL80211_VENDOR_SUBCMD_WIRELESS_CTRL:
-+ drv->mtk_wireless_vendor_cmd_avail = 1;
-+ break;
- }
- }
-
---
-2.25.1
-
diff --git a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0011-hostapd-mtk-Add-amsdu-set-get-ctrl.patch b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0012-hostapd-mtk-Add-amsdu-set-get-ctrl.patch
similarity index 92%
copy from recipes-wifi/hostapd/files/patches-2.10.3/mtk-0011-hostapd-mtk-Add-amsdu-set-get-ctrl.patch
copy to recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0012-hostapd-mtk-Add-amsdu-set-get-ctrl.patch
index dba90d1..7db3ae2 100644
--- a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0011-hostapd-mtk-Add-amsdu-set-get-ctrl.patch
+++ b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0012-hostapd-mtk-Add-amsdu-set-get-ctrl.patch
@@ -1,7 +1,7 @@
-From bc0722ebc1cc08be6239879fddaef37e0db2d9e0 Mon Sep 17 00:00:00 2001
+From d0128fc60d38ce4f20f8368bdc5ea9ed19a329b7 Mon Sep 17 00:00:00 2001
From: Evelyn Tsai <evelyn.tsai@mediatek.com>
Date: Fri, 16 Dec 2022 03:57:11 +0800
-Subject: [PATCH 11/15] hostapd: mtk: Add amsdu set get ctrl
+Subject: [PATCH 12/16] hostapd: mtk: Add amsdu set get ctrl
---
hostapd/config_file.c | 9 +++
@@ -20,7 +20,7 @@
13 files changed, 207 insertions(+), 1 deletion(-)
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
-index cd1534952..10ea52518 100644
+index cd15349..10ea525 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -4807,6 +4807,15 @@ static int hostapd_config_fill(struct hostapd_config *conf,
@@ -40,7 +40,7 @@
wpa_printf(MSG_ERROR,
"Line %d: unknown configuration item '%s'",
diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
-index 6ea1573b8..0ad8451aa 100644
+index 6ea1573..0ad8451 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -3612,6 +3612,30 @@ hostapd_ctrl_iface_set_offchan_ctrl(struct hostapd_data *hapd, char *cmd,
@@ -84,7 +84,7 @@
os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
reply_len = 16;
diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
-index c2a123a8c..30b3392e6 100644
+index c2a123a..30b3392 100644
--- a/hostapd/hostapd_cli.c
+++ b/hostapd/hostapd_cli.c
@@ -1593,6 +1593,13 @@ static int hostapd_cli_cmd_get_ibf(struct wpa_ctrl *ctrl, int argc,
@@ -111,7 +111,7 @@
};
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
-index 7a96cb8b2..85ad5e444 100644
+index 7a96cb8..85ad5e4 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -299,6 +299,7 @@ struct hostapd_config * hostapd_config_defaults(void)
@@ -123,7 +123,7 @@
return conf;
}
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
-index 77f6169d2..a9ac39619 100644
+index 77f6169..a9ac396 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -1161,6 +1161,7 @@ struct hostapd_config {
@@ -135,7 +135,7 @@
enum three_wire_mode {
diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
-index 60ae8253b..1a82f234c 100644
+index 60ae825..1a82f23 100644
--- a/src/ap/ap_drv_ops.c
+++ b/src/ap/ap_drv_ops.c
@@ -1077,4 +1077,18 @@ int hostapd_drv_ibf_dump(struct hostapd_data *hapd, u8 *ibf_enable)
@@ -159,7 +159,7 @@
}
\ No newline at end of file
diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
-index ab9aedcee..4406666fd 100644
+index ab9aedc..4406666 100644
--- a/src/ap/ap_drv_ops.h
+++ b/src/ap/ap_drv_ops.h
@@ -147,6 +147,8 @@ int hostapd_drv_mu_dump(struct hostapd_data *hapd, u8 *mu_onoff);
@@ -172,10 +172,10 @@
#include "drivers/driver.h"
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
-index a0229c9ca..152060db4 100644
+index da7f7d8..a18e744 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
-@@ -2310,6 +2310,8 @@ dfs_offload:
+@@ -2308,6 +2308,8 @@ dfs_offload:
goto fail;
if (hostapd_drv_ibf_ctrl(hapd) < 0)
goto fail;
@@ -185,7 +185,7 @@
wpa_printf(MSG_DEBUG, "%s: Setup of interface done.",
iface->bss[0]->conf->iface);
diff --git a/src/common/mtk_vendor.h b/src/common/mtk_vendor.h
-index 4050cf886..0999ea9e2 100644
+index 4050cf8..0999ea9 100644
--- a/src/common/mtk_vendor.h
+++ b/src/common/mtk_vendor.h
@@ -167,7 +167,6 @@ enum mtk_vendor_attr_wireless_ctrl {
@@ -220,13 +220,13 @@
MTK_VENDOR_ATTR_RFEATURE_CTRL_UNSPEC,
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
-index aa23fbdb3..b07aaf3fe 100644
+index 71ded61..265d86d 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
-@@ -4727,6 +4727,15 @@ struct wpa_driver_ops {
+@@ -4720,6 +4720,15 @@ struct wpa_driver_ops {
*
*/
- int (*start_disabled)(void *priv);
+ int (*ibf_dump)(void *priv, u8 *ibf_enable);
+
+ /**
+ * amsdu_ctrl - enable/disable amsdu
@@ -240,11 +240,11 @@
/**
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
-index 7472542cc..6702384ef 100644
+index 5c2a291..d91b29c 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
-@@ -12804,6 +12804,118 @@ fail:
- return ret;
+@@ -12776,6 +12776,118 @@ fail:
+ return -ENOBUFS;
}
+static int nl80211_enable_amsdu(void *priv, u8 amsdu)
@@ -362,15 +362,15 @@
const struct wpa_driver_ops wpa_driver_nl80211_ops = {
.name = "nl80211",
.desc = "Linux nl80211/cfg80211",
-@@ -12959,4 +13071,6 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
+@@ -12930,4 +13042,6 @@ 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,
+ .amsdu_ctrl = nl80211_enable_amsdu,
+ .amsdu_dump = nl80211_dump_amsdu,
};
diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h
-index 607592ceb..e57022409 100644
+index 607592c..e570224 100644
--- a/src/drivers/driver_nl80211.h
+++ b/src/drivers/driver_nl80211.h
@@ -185,6 +185,7 @@ struct wpa_driver_nl80211_data {
@@ -382,7 +382,7 @@
u64 vendor_scan_cookie;
u64 remain_on_chan_cookie;
diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
-index 9ecc0ff9a..fcfa68bf7 100644
+index 9ecc0ff..fcfa68b 100644
--- a/src/drivers/driver_nl80211_capa.c
+++ b/src/drivers/driver_nl80211_capa.c
@@ -1065,6 +1065,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
@@ -396,5 +396,5 @@
}
--
-2.25.1
+2.18.0
diff --git a/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0012-hostapd-mtk-Add-he_ldpc-configuration.patch b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0012-hostapd-mtk-Add-he_ldpc-configuration.patch
deleted file mode 100644
index 63101e0..0000000
--- a/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0012-hostapd-mtk-Add-he_ldpc-configuration.patch
+++ /dev/null
@@ -1,102 +0,0 @@
-From b49ce922afa13fe8ea5d847753dfb7641b70c9a4 Mon Sep 17 00:00:00 2001
-From: MeiChia Chiu <meichia.chiu@mediatek.com>
-Date: Thu, 12 Jan 2023 15:18:19 +0800
-Subject: [PATCH 12/15] hostapd: mtk: Add he_ldpc configuration
-
----
- hostapd/config_file.c | 2 ++
- hostapd/hostapd.conf | 5 +++++
- src/ap/ap_config.c | 1 +
- src/ap/ap_config.h | 1 +
- src/ap/ieee802_11_he.c | 7 +++++++
- src/common/ieee802_11_defs.h | 3 +++
- 6 files changed, 19 insertions(+)
-
-diff --git a/hostapd/config_file.c b/hostapd/config_file.c
-index 10ea52518..4237a5cca 100644
---- a/hostapd/config_file.c
-+++ b/hostapd/config_file.c
-@@ -3508,6 +3508,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
- conf->he_phy_capab.he_su_beamformee = atoi(pos);
- } else if (os_strcmp(buf, "he_mu_beamformer") == 0) {
- conf->he_phy_capab.he_mu_beamformer = atoi(pos);
-+ } else if (os_strcmp(buf, "he_ldpc") == 0) {
-+ conf->he_phy_capab.he_ldpc = atoi(pos);
- } else if (os_strcmp(buf, "he_bss_color") == 0) {
- conf->he_op.he_bss_color = atoi(pos) & 0x3f;
- conf->he_op.he_bss_color_disabled = 0;
-diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
-index ea67aa100..e3a5eb365 100644
---- a/hostapd/hostapd.conf
-+++ b/hostapd/hostapd.conf
-@@ -830,6 +830,11 @@ wmm_ac_vo_acm=0
- # 1 = supported
- #he_mu_beamformer=1
-
-+#he_ldpc: HE LDPC support
-+# 0 = not supported
-+# 1 = supported (default)
-+#he_ldpc=1
-+
- # he_bss_color: BSS color (1-63)
- #he_bss_color=1
-
-diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
-index 85ad5e444..b283de624 100644
---- a/src/ap/ap_config.c
-+++ b/src/ap/ap_config.c
-@@ -268,6 +268,7 @@ struct hostapd_config * hostapd_config_defaults(void)
- #endif /* CONFIG_ACS */
-
- #ifdef CONFIG_IEEE80211AX
-+ conf->he_phy_capab.he_ldpc = 1;
- conf->he_op.he_rts_threshold = HE_OPERATION_RTS_THRESHOLD_MASK >>
- HE_OPERATION_RTS_THRESHOLD_OFFSET;
- /* Set default basic MCS/NSS set to single stream MCS 0-7 */
-diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
-index a9ac39619..b8b20a7aa 100644
---- a/src/ap/ap_config.h
-+++ b/src/ap/ap_config.h
-@@ -929,6 +929,7 @@ struct hostapd_bss_config {
- * struct he_phy_capabilities_info - HE PHY capabilities
- */
- struct he_phy_capabilities_info {
-+ bool he_ldpc;
- bool he_su_beamformer;
- bool he_su_beamformee;
- bool he_mu_beamformer;
-diff --git a/src/ap/ieee802_11_he.c b/src/ap/ieee802_11_he.c
-index b5b7e5d46..f27aeb196 100644
---- a/src/ap/ieee802_11_he.c
-+++ b/src/ap/ieee802_11_he.c
-@@ -138,6 +138,13 @@ u8 * hostapd_eid_he_capab(struct hostapd_data *hapd, u8 *eid,
- os_memcpy(&cap->optional[mcs_nss_size],
- mode->he_capab[opmode].ppet, ppet_size);
-
-+ if (hapd->iface->conf->he_phy_capab.he_ldpc)
-+ cap->he_phy_capab_info[HE_PHYCAP_LDPC_CODING_IN_PAYLOAD_IDX] |=
-+ HE_PHYCAP_LDPC_CODING_IN_PAYLOAD;
-+ else
-+ cap->he_phy_capab_info[HE_PHYCAP_LDPC_CODING_IN_PAYLOAD_IDX] &=
-+ ~HE_PHYCAP_LDPC_CODING_IN_PAYLOAD;
-+
- if (hapd->iface->conf->he_phy_capab.he_su_beamformer)
- cap->he_phy_capab_info[HE_PHYCAP_SU_BEAMFORMER_CAPAB_IDX] |=
- HE_PHYCAP_SU_BEAMFORMER_CAPAB;
-diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
-index 65e125e83..62088bda6 100644
---- a/src/common/ieee802_11_defs.h
-+++ b/src/common/ieee802_11_defs.h
-@@ -2298,6 +2298,9 @@ struct ieee80211_spatial_reuse {
- #define HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G ((u8) BIT(3))
- #define HE_PHYCAP_CHANNEL_WIDTH_SET_80PLUS80MHZ_IN_5G ((u8) BIT(4))
-
-+#define HE_PHYCAP_LDPC_CODING_IN_PAYLOAD_IDX 1
-+#define HE_PHYCAP_LDPC_CODING_IN_PAYLOAD ((u8) BIT(5))
-+
- #define HE_PHYCAP_SU_BEAMFORMER_CAPAB_IDX 3
- #define HE_PHYCAP_SU_BEAMFORMER_CAPAB ((u8) BIT(7))
- #define HE_PHYCAP_SU_BEAMFORMEE_CAPAB_IDX 4
---
-2.25.1
-
diff --git a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0012-hostapd-mtk-Add-he_ldpc-configuration.patch b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0013-hostapd-mtk-Add-he_ldpc-configuration.patch
similarity index 90%
copy from recipes-wifi/hostapd/files/patches-2.10.3/mtk-0012-hostapd-mtk-Add-he_ldpc-configuration.patch
copy to recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0013-hostapd-mtk-Add-he_ldpc-configuration.patch
index 63101e0..4df0ba6 100644
--- a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0012-hostapd-mtk-Add-he_ldpc-configuration.patch
+++ b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0013-hostapd-mtk-Add-he_ldpc-configuration.patch
@@ -1,7 +1,7 @@
-From b49ce922afa13fe8ea5d847753dfb7641b70c9a4 Mon Sep 17 00:00:00 2001
+From ebbf23ac8c19224b34523e8b9820e32f0789fe11 Mon Sep 17 00:00:00 2001
From: MeiChia Chiu <meichia.chiu@mediatek.com>
Date: Thu, 12 Jan 2023 15:18:19 +0800
-Subject: [PATCH 12/15] hostapd: mtk: Add he_ldpc configuration
+Subject: [PATCH 13/16] hostapd: mtk: Add he_ldpc configuration
---
hostapd/config_file.c | 2 ++
@@ -13,7 +13,7 @@
6 files changed, 19 insertions(+)
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
-index 10ea52518..4237a5cca 100644
+index 10ea525..4237a5c 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -3508,6 +3508,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
@@ -26,7 +26,7 @@
conf->he_op.he_bss_color = atoi(pos) & 0x3f;
conf->he_op.he_bss_color_disabled = 0;
diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
-index ea67aa100..e3a5eb365 100644
+index ea67aa1..e3a5eb3 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -830,6 +830,11 @@ wmm_ac_vo_acm=0
@@ -42,7 +42,7 @@
#he_bss_color=1
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
-index 85ad5e444..b283de624 100644
+index 85ad5e4..b283de6 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -268,6 +268,7 @@ struct hostapd_config * hostapd_config_defaults(void)
@@ -54,7 +54,7 @@
HE_OPERATION_RTS_THRESHOLD_OFFSET;
/* Set default basic MCS/NSS set to single stream MCS 0-7 */
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
-index a9ac39619..b8b20a7aa 100644
+index a9ac396..b8b20a7 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -929,6 +929,7 @@ struct hostapd_bss_config {
@@ -66,7 +66,7 @@
bool he_su_beamformee;
bool he_mu_beamformer;
diff --git a/src/ap/ieee802_11_he.c b/src/ap/ieee802_11_he.c
-index b5b7e5d46..f27aeb196 100644
+index b5b7e5d..f27aeb1 100644
--- a/src/ap/ieee802_11_he.c
+++ b/src/ap/ieee802_11_he.c
@@ -138,6 +138,13 @@ u8 * hostapd_eid_he_capab(struct hostapd_data *hapd, u8 *eid,
@@ -84,7 +84,7 @@
cap->he_phy_capab_info[HE_PHYCAP_SU_BEAMFORMER_CAPAB_IDX] |=
HE_PHYCAP_SU_BEAMFORMER_CAPAB;
diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
-index 65e125e83..62088bda6 100644
+index 65e125e..62088bd 100644
--- a/src/common/ieee802_11_defs.h
+++ b/src/common/ieee802_11_defs.h
@@ -2298,6 +2298,9 @@ struct ieee80211_spatial_reuse {
@@ -98,5 +98,5 @@
#define HE_PHYCAP_SU_BEAMFORMER_CAPAB ((u8) BIT(7))
#define HE_PHYCAP_SU_BEAMFORMEE_CAPAB_IDX 4
--
-2.25.1
+2.18.0
diff --git a/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0013-hostapd-mtk-Add-the-broadcast-destination-address-of.patch b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0013-hostapd-mtk-Add-the-broadcast-destination-address-of.patch
deleted file mode 100644
index 1222510..0000000
--- a/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0013-hostapd-mtk-Add-the-broadcast-destination-address-of.patch
+++ /dev/null
@@ -1,43 +0,0 @@
-From 52a1775318c9926a1dbf4f7c563e95b5be3c9bd6 Mon Sep 17 00:00:00 2001
-From: MeiChia Chiu <meichia.chiu@mediatek.com>
-Date: Tue, 17 Jan 2023 13:25:18 +0800
-Subject: [PATCH 13/15] hostapd: mtk: Add the broadcast destination address of
- Probe Response frame on 6 GHz
-
-According to IEEE 802.11ax 26.17.2.3.2,
-if a 6 GHz AP receives a Probe Request frame and responds with a Probe Response frame,
-the Address 1 field of the Probe Response frame shall be set to the broadcast address,
-unless the AP is not indicating its actual SSID in the SSID element of its Beacon frames.
-
-Without this, hostapd fill the Address 1 feild of the Probe Response frame
-with the source address from Probe Request frame on 6 GHz.
-Fix this to use broadcast address instead.
-
-Signed-off-by: MeiChia Chiu <meichia.chiu@mediatek.com>
----
- src/ap/beacon.c | 9 +++++++--
- 1 file changed, 7 insertions(+), 2 deletions(-)
-
-diff --git a/src/ap/beacon.c b/src/ap/beacon.c
-index 1a26f11ff..f3ea5c277 100644
---- a/src/ap/beacon.c
-+++ b/src/ap/beacon.c
-@@ -1156,8 +1156,13 @@ void handle_probe_req(struct hostapd_data *hapd,
- wpa_msg_ctrl(hapd->msg_ctx, MSG_INFO, RX_PROBE_REQUEST "sa=" MACSTR
- " signal=%d", MAC2STR(mgmt->sa), ssi_signal);
-
-- resp = hostapd_gen_probe_resp(hapd, mgmt, elems.p2p != NULL,
-- &resp_len, false);
-+ if (is_6ghz_op_class(hapd->iconf->op_class) &&
-+ is_broadcast_ether_addr(mgmt->da))
-+ resp = hostapd_gen_probe_resp(hapd, NULL, elems.p2p != NULL,
-+ &resp_len, true);
-+ else
-+ resp = hostapd_gen_probe_resp(hapd, mgmt, elems.p2p != NULL,
-+ &resp_len, false);
- if (resp == NULL)
- return;
-
---
-2.25.1
-
diff --git a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0013-hostapd-mtk-Add-the-broadcast-destination-address-of.patch b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0014-hostapd-mtk-Add-the-broadcast-destination-address-of.patch
similarity index 89%
copy from recipes-wifi/hostapd/files/patches-2.10.3/mtk-0013-hostapd-mtk-Add-the-broadcast-destination-address-of.patch
copy to recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0014-hostapd-mtk-Add-the-broadcast-destination-address-of.patch
index 1222510..f0d25c6 100644
--- a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0013-hostapd-mtk-Add-the-broadcast-destination-address-of.patch
+++ b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0014-hostapd-mtk-Add-the-broadcast-destination-address-of.patch
@@ -1,7 +1,7 @@
-From 52a1775318c9926a1dbf4f7c563e95b5be3c9bd6 Mon Sep 17 00:00:00 2001
+From bb5cb086162828392a04820063ad7997d8ae26d7 Mon Sep 17 00:00:00 2001
From: MeiChia Chiu <meichia.chiu@mediatek.com>
Date: Tue, 17 Jan 2023 13:25:18 +0800
-Subject: [PATCH 13/15] hostapd: mtk: Add the broadcast destination address of
+Subject: [PATCH 14/16] hostapd: mtk: Add the broadcast destination address of
Probe Response frame on 6 GHz
According to IEEE 802.11ax 26.17.2.3.2,
@@ -19,7 +19,7 @@
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/src/ap/beacon.c b/src/ap/beacon.c
-index 1a26f11ff..f3ea5c277 100644
+index 1a26f11..f3ea5c2 100644
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -1156,8 +1156,13 @@ void handle_probe_req(struct hostapd_data *hapd,
@@ -39,5 +39,5 @@
return;
--
-2.25.1
+2.18.0
diff --git a/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0014-hostapd-mtk-Add-vendor-command-attribute-for-RTS-BW-.patch b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0014-hostapd-mtk-Add-vendor-command-attribute-for-RTS-BW-.patch
deleted file mode 100644
index 3689f74..0000000
--- a/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0014-hostapd-mtk-Add-vendor-command-attribute-for-RTS-BW-.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-From 7d741c99f2e211abe70593ff6e8265633bed0d8a Mon Sep 17 00:00:00 2001
-From: "himanshu.goyal" <himanshu.goyal@mediatek.com>
-Date: Tue, 24 Jan 2023 19:06:44 +0800
-Subject: [PATCH 14/15] hostapd: mtk: Add vendor command attribute for RTS BW
- signaling.
-
-Signed-off-by: himanshu.goyal <himanshu.goyal@mediatek.com>
----
- src/common/mtk_vendor.h | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/src/common/mtk_vendor.h b/src/common/mtk_vendor.h
-index 0999ea9e2..fb12895ce 100644
---- a/src/common/mtk_vendor.h
-+++ b/src/common/mtk_vendor.h
-@@ -169,6 +169,7 @@ enum mtk_vendor_attr_wireless_ctrl {
- MTK_VENDOR_ATTR_WIRELESS_CTRL_MIMO,
- MTK_VENDOR_ATTR_WIRELESS_CTRL_AMSDU,
- MTK_VENDOR_ATTR_WIRELESS_CTRL_CERT,
-+ MTK_VENDOR_ATTR_WIRELESS_CTRL_RTS_SIGTA,
-
- /* keep last */
- NUM_MTK_VENDOR_ATTRS_WIRELESS_CTRL,
---
-2.25.1
-
diff --git a/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0015-hostapd-mtk-6G-band-does-not-require-DFS.patch b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0015-hostapd-mtk-6G-band-does-not-require-DFS.patch
deleted file mode 100644
index 642c625..0000000
--- a/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0015-hostapd-mtk-6G-band-does-not-require-DFS.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-From 619075bb430c908c61a818c45e36f1ca76020741 Mon Sep 17 00:00:00 2001
-From: Peter Chiu <chui-hao.chiu@mediatek.com>
-Date: Mon, 13 Feb 2023 11:03:53 +0800
-Subject: [PATCH 15/15] hostapd: mtk: 6G band does not require DFS
-
----
- src/ap/dfs.c | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/src/ap/dfs.c b/src/ap/dfs.c
-index 1c3f6785b..4b1e64246 100644
---- a/src/ap/dfs.c
-+++ b/src/ap/dfs.c
-@@ -1506,6 +1506,7 @@ int hostapd_is_dfs_required(struct hostapd_iface *iface)
- if ((!(iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) &&
- !iface->conf->ieee80211h) ||
- !iface->current_mode ||
-+ is_6ghz_freq(iface->freq) ||
- iface->current_mode->mode != HOSTAPD_MODE_IEEE80211A)
- return 0;
-
---
-2.25.1
-
diff --git a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0014-hostapd-mtk-Add-vendor-command-attribute-for-RTS-BW-.patch b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0015-hostapd-mtk-Add-vendor-command-attribute-for-RTS-BW-.patch
similarity index 79%
copy from recipes-wifi/hostapd/files/patches-2.10.3/mtk-0014-hostapd-mtk-Add-vendor-command-attribute-for-RTS-BW-.patch
copy to recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0015-hostapd-mtk-Add-vendor-command-attribute-for-RTS-BW-.patch
index 3689f74..5fcd0c5 100644
--- a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0014-hostapd-mtk-Add-vendor-command-attribute-for-RTS-BW-.patch
+++ b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0015-hostapd-mtk-Add-vendor-command-attribute-for-RTS-BW-.patch
@@ -1,7 +1,7 @@
-From 7d741c99f2e211abe70593ff6e8265633bed0d8a Mon Sep 17 00:00:00 2001
+From 1db373190399a907b27141c199841aeafd4643da Mon Sep 17 00:00:00 2001
From: "himanshu.goyal" <himanshu.goyal@mediatek.com>
Date: Tue, 24 Jan 2023 19:06:44 +0800
-Subject: [PATCH 14/15] hostapd: mtk: Add vendor command attribute for RTS BW
+Subject: [PATCH 15/16] hostapd: mtk: Add vendor command attribute for RTS BW
signaling.
Signed-off-by: himanshu.goyal <himanshu.goyal@mediatek.com>
@@ -10,7 +10,7 @@
1 file changed, 1 insertion(+)
diff --git a/src/common/mtk_vendor.h b/src/common/mtk_vendor.h
-index 0999ea9e2..fb12895ce 100644
+index 0999ea9..fb12895 100644
--- a/src/common/mtk_vendor.h
+++ b/src/common/mtk_vendor.h
@@ -169,6 +169,7 @@ enum mtk_vendor_attr_wireless_ctrl {
@@ -22,5 +22,5 @@
/* keep last */
NUM_MTK_VENDOR_ATTRS_WIRELESS_CTRL,
--
-2.25.1
+2.18.0
diff --git a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0015-hostapd-mtk-6G-band-does-not-require-DFS.patch b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0016-hostapd-mtk-6G-band-does-not-require-DFS.patch
similarity index 76%
copy from recipes-wifi/hostapd/files/patches-2.10.3/mtk-0015-hostapd-mtk-6G-band-does-not-require-DFS.patch
copy to recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0016-hostapd-mtk-6G-band-does-not-require-DFS.patch
index 642c625..33fea78 100644
--- a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0015-hostapd-mtk-6G-band-does-not-require-DFS.patch
+++ b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0016-hostapd-mtk-6G-band-does-not-require-DFS.patch
@@ -1,14 +1,14 @@
-From 619075bb430c908c61a818c45e36f1ca76020741 Mon Sep 17 00:00:00 2001
+From efa1d271d28c84b8ca77ffc3ca7cb75e727088a0 Mon Sep 17 00:00:00 2001
From: Peter Chiu <chui-hao.chiu@mediatek.com>
Date: Mon, 13 Feb 2023 11:03:53 +0800
-Subject: [PATCH 15/15] hostapd: mtk: 6G band does not require DFS
+Subject: [PATCH 16/16] hostapd: mtk: 6G band does not require DFS
---
src/ap/dfs.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/ap/dfs.c b/src/ap/dfs.c
-index 1c3f6785b..4b1e64246 100644
+index 1c3f678..4b1e642 100644
--- a/src/ap/dfs.c
+++ b/src/ap/dfs.c
@@ -1506,6 +1506,7 @@ int hostapd_is_dfs_required(struct hostapd_iface *iface)
@@ -20,5 +20,5 @@
return 0;
--
-2.25.1
+2.18.0
diff --git a/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0016-hostapd-mtk-Add-available-color-bitmap.patch b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0016-hostapd-mtk-Add-available-color-bitmap.patch
new file mode 100644
index 0000000..9bbbf87
--- /dev/null
+++ b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0016-hostapd-mtk-Add-available-color-bitmap.patch
@@ -0,0 +1,337 @@
+From e7790a1bceca6b7612f29b00c429cf23f5dd9e3a Mon Sep 17 00:00:00 2001
+From: Yi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
+Date: Thu, 26 Jan 2023 09:16:00 +0800
+Subject: [PATCH] hostapd: mtk: Add available color bitmap
+
+Signed-off-by: Yi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
+---
+ hostapd/ctrl_iface.c | 74 +++++++++++++++++++++++++++++++
+ hostapd/hostapd_cli.c | 18 ++++++++
+ src/ap/ap_drv_ops.c | 10 ++++-
+ src/ap/ap_drv_ops.h | 2 +
+ src/common/mtk_vendor.h | 11 +++++
+ src/drivers/driver.h | 8 ++++
+ src/drivers/driver_nl80211.c | 66 +++++++++++++++++++++++++++
+ src/drivers/driver_nl80211.h | 1 +
+ src/drivers/driver_nl80211_capa.c | 3 ++
+ 9 files changed, 192 insertions(+), 1 deletion(-)
+
+diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
+index 0ad8451..b0d5ded 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -3635,6 +3635,76 @@ hostapd_ctrl_iface_get_amsdu(struct hostapd_data *hapd, char *buf,
+ return ret;
+ }
+
++static int
++hostapd_ctrl_iface_get_bss_color(struct hostapd_data *hapd, char *buf,
++ size_t buflen)
++{
++ int ret;
++ char *pos, *end;
++ int i;
++
++ pos = buf;
++ end = buf + buflen;
++
++ if (hapd->iface->conf->he_op.he_bss_color_disabled)
++ ret = os_snprintf(buf, buflen, "BSS Color disabled\n");
++ else
++ ret = os_snprintf(buf, buflen, "BSS Color=%u\n",
++ hapd->iface->conf->he_op.he_bss_color);
++
++ pos += ret;
++
++ return pos - buf;
++}
++
++
++static int
++hostapd_ctrl_iface_get_aval_color_bmp(struct hostapd_data *hapd, char *buf,
++ size_t buflen)
++{
++ int ret;
++ char *pos, *end;
++ int i;
++ u64 aval_color_bmp = 0;
++
++ hostapd_drv_get_aval_bss_color_bmp(hapd, &aval_color_bmp);
++ hapd->color_collision_bitmap = ~aval_color_bmp;
++
++ pos = buf;
++ end = buf + buflen;
++
++ ret = os_snprintf(buf, buflen,
++ "available color bitmap=0x%llx\n",
++ aval_color_bmp);
++ if (os_snprintf_error(end - pos, ret))
++ return pos - buf;
++ pos += ret;
++
++ for (i = 0; i < HE_OPERATION_BSS_COLOR_MAX; i++) {
++ int bit = !!((aval_color_bmp >> i) & 1LLU);
++
++ if (i % 8 == 0) {
++ ret = os_snprintf(pos, end - pos, "%2d: ", i);
++ if (os_snprintf_error(end - pos, ret))
++ return pos - buf;
++ pos += ret;
++ }
++
++ ret = os_snprintf(pos, end - pos, "%d ", bit);
++ if (os_snprintf_error(end - pos, ret))
++ return pos - buf;
++ pos += ret;
++
++ if (i % 8 == 7) {
++ ret = os_snprintf(pos, end - pos, "\n");
++ if (os_snprintf_error(end - pos, ret))
++ return pos - buf;
++ pos += ret;
++ }
++ }
++ return pos - buf;
++}
++
+
+ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
+ char *buf, char *reply,
+@@ -4202,6 +4272,10 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
+ reply_len = hostapd_ctrl_iface_set_offchan_ctrl(hapd, buf + 16, reply, reply_size);
+ } else if (os_strncmp(buf, "GET_AMSDU", 9) == 0) {
+ reply_len = hostapd_ctrl_iface_get_amsdu(hapd, reply, reply_size);
++ } else if (os_strncmp(buf, "GET_BSS_COLOR", 13) == 0) {
++ reply_len = hostapd_ctrl_iface_get_bss_color(hapd, reply, reply_size);
++ } else if (os_strncmp(buf, "AVAL_COLOR_BMP", 14) == 0) {
++ reply_len = hostapd_ctrl_iface_get_aval_color_bmp(hapd, reply, reply_size);
+ } else {
+ os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
+ reply_len = 16;
+diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
+index 30b3392..b6cf52e 100644
+--- a/hostapd/hostapd_cli.c
++++ b/hostapd/hostapd_cli.c
+@@ -1578,6 +1578,20 @@ static int hostapd_cli_cmd_reload_wpa_psk(struct wpa_ctrl *ctrl, int argc,
+ }
+
+
++static int hostapd_cli_cmd_get_bss_color(struct wpa_ctrl *ctrl, int argc,
++ char *argv[])
++{
++ return wpa_ctrl_command(ctrl, "GET_BSS_COLOR");
++}
++
++
++static int hostapd_cli_cmd_get_aval_color_bmp(struct wpa_ctrl *ctrl, int argc,
++ char *argv[])
++{
++ return wpa_ctrl_command(ctrl, "AVAL_COLOR_BMP");
++}
++
++
+ #ifdef ANDROID
+ static int hostapd_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[])
+ {
+@@ -1795,6 +1809,10 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
+ "<addr> [req_mode=] <measurement request hexdump> = send a Beacon report request to a station" },
+ { "reload_wpa_psk", hostapd_cli_cmd_reload_wpa_psk, NULL,
+ "= reload wpa_psk_file only" },
++ { "get_bss_color", hostapd_cli_cmd_get_bss_color, NULL,
++ "= get current BSS color" },
++ { "get_color_bmp", hostapd_cli_cmd_get_aval_color_bmp, NULL,
++ "= get available BSS color bitmap" },
+ #ifdef ANDROID
+ { "driver", hostapd_cli_cmd_driver, NULL,
+ "<driver sub command> [<hex formatted data>] = send driver command data" },
+diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
+index 1a82f23..decffdd 100644
+--- a/src/ap/ap_drv_ops.c
++++ b/src/ap/ap_drv_ops.c
+@@ -1091,4 +1091,12 @@ int hostapd_drv_amsdu_dump(struct hostapd_data *hapd, u8 *amsdu)
+ if (!hapd->driver || !hapd->driver->amsdu_dump)
+ return 0;
+ return hapd->driver->amsdu_dump(hapd->drv_priv, amsdu);
+-}
+\ No newline at end of file
++}
++
++int hostapd_drv_get_aval_bss_color_bmp(struct hostapd_data *hapd, u64 *aval_color_bmp)
++{
++ if (!hapd->driver || !hapd->driver->get_aval_color_bmp ||
++ hapd->iface->conf->he_op.he_bss_color_disabled)
++ return 0;
++ return hapd->driver->get_aval_color_bmp(hapd->drv_priv, aval_color_bmp);
++}
+diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
+index 4406666..61c1360 100644
+--- a/src/ap/ap_drv_ops.h
++++ b/src/ap/ap_drv_ops.h
+@@ -149,6 +149,8 @@ int hostapd_drv_ibf_ctrl(struct hostapd_data *hapd);
+ int hostapd_drv_ibf_dump(struct hostapd_data *hapd, u8 *ibf_enable);
+ int hostapd_drv_amsdu_ctrl(struct hostapd_data *hapd);
+ int hostapd_drv_amsdu_dump(struct hostapd_data *hapd, u8 *amsdu);
++int hostapd_drv_get_aval_bss_color_bmp(struct hostapd_data *hapd,
++ u64 *aval_color_bmp);
+
+ #include "drivers/driver.h"
+
+diff --git a/src/common/mtk_vendor.h b/src/common/mtk_vendor.h
+index 0999ea9..f2afb2e 100644
+--- a/src/common/mtk_vendor.h
++++ b/src/common/mtk_vendor.h
+@@ -15,6 +15,7 @@ enum mtk_nl80211_vendor_subcmds {
+ MTK_NL80211_VENDOR_SUBCMD_EDCCA_CTRL = 0xc7,
+ MTK_NL80211_VENDOR_SUBCMD_3WIRE_CTRL = 0xc8,
+ MTK_NL80211_VENDOR_SUBCMD_IBF_CTRL = 0xc9,
++ MTK_NL80211_VENDOR_SUBCMD_BSS_COLOR_CTRL = 0xca,
+ };
+
+ enum mtk_vendor_attr_edcca_ctrl {
+@@ -252,6 +253,16 @@ ibf_dump_policy[NUM_MTK_VENDOR_ATTRS_IBF_DUMP] = {
+ [MTK_VENDOR_ATTR_IBF_DUMP_ENABLE] = { .type = NLA_U8 },
+ };
+
++enum mtk_vendor_attr_bss_color_ctrl {
++ MTK_VENDOR_ATTR_BSS_COLOR_CTRL_UNSPEC,
++
++ MTK_VENDOR_ATTR_AVAL_BSS_COLOR_BMP,
++
++ /* keep last */
++ NUM_MTK_VENDOR_ATTRS_BSS_COLOR_CTRL,
++ MTK_VENDOR_ATTR_BSS_COLOR_CTRL_MAX =
++ NUM_MTK_VENDOR_ATTRS_BSS_COLOR_CTRL - 1
++};
+
+ #define CSI_MAX_COUNT 256
+ #define ETH_ALEN 6
+diff --git a/src/drivers/driver.h b/src/drivers/driver.h
+index b07aaf3..266c630 100644
+--- a/src/drivers/driver.h
++++ b/src/drivers/driver.h
+@@ -4736,6 +4736,14 @@ struct wpa_driver_ops {
+ */
+ int (*amsdu_ctrl)(void *priv, u8 amsdu);
+ int (*amsdu_dump)(void *priv, u8 *amsdu);
++
++ /**
++ * get_aval_color_bmp - get available BSS color bitmap
++ * @priv: Private driver interface data
++ * @aval_color_bmp: available bss color bitmap
++ *
++ */
++ int (*get_aval_color_bmp)(void *priv, u64 *aval_color_bmp);
+ };
+
+ /**
+diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
+index 6702384..c8771f7 100644
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -12433,6 +12433,71 @@ static int nl80211_dpp_listen(void *priv, bool enable)
+ }
+ #endif /* CONFIG_DPP */
+
++static int nl80211_get_aval_color_bmp_handler(struct nl_msg *msg, void *arg)
++{
++ u64 *aval_color_bmp = arg;
++ struct nlattr *tb[NL80211_ATTR_MAX + 1];
++ struct nlattr *tb_vendor[MTK_VENDOR_ATTR_BSS_COLOR_CTRL_MAX + 1];
++ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
++ struct nlattr *nl_vend, *attr;
++
++ static const struct nla_policy
++ bss_color_ctrl_policy[NUM_MTK_VENDOR_ATTRS_BSS_COLOR_CTRL + 1] = {
++ [MTK_VENDOR_ATTR_AVAL_BSS_COLOR_BMP] = { .type = NLA_U64 },
++ };
++
++ nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
++ genlmsg_attrlen(gnlh, 0), NULL);
++
++ nl_vend = tb[NL80211_ATTR_VENDOR_DATA];
++ if (!nl_vend)
++ return NL_SKIP;
++
++ nla_parse(tb_vendor, MTK_VENDOR_ATTR_BSS_COLOR_CTRL_MAX,
++ nla_data(nl_vend), nla_len(nl_vend), NULL);
++
++ *aval_color_bmp = nla_get_u64(tb_vendor[MTK_VENDOR_ATTR_AVAL_BSS_COLOR_BMP]);
++
++ return 0;
++}
++
++static int nl80211_get_aval_color_bmp(void *priv, u64 *aval_color_bmp)
++{
++ struct i802_bss *bss = priv;
++ struct wpa_driver_nl80211_data *drv = bss->drv;
++ struct nl_msg *msg;
++ struct nlattr *attr;
++ int ret;
++
++ if (!drv->mtk_bss_color_vendor_cmd_avail) {
++ wpa_printf(MSG_INFO,
++ "nl80211: Driver does not support BSS COLOR vendor cmd");
++ return 0;
++ }
++
++ if (!(msg = nl80211_drv_msg(drv, NLM_F_DUMP, NL80211_CMD_VENDOR)) ||
++ nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_MTK) ||
++ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
++ MTK_NL80211_VENDOR_SUBCMD_BSS_COLOR_CTRL))
++ return -ENOBUFS;
++
++ attr = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
++ if (!attr) {
++ nlmsg_free(msg);
++ return -1;
++ }
++
++ nla_nest_end(msg, attr);
++
++ ret = send_and_recv_msgs(drv, msg,
++ nl80211_get_aval_color_bmp_handler, aval_color_bmp, NULL, NULL);
++
++ if (ret) {
++ wpa_printf(MSG_ERROR, "Failed to send BSS COLOR vendor cmd. ret=%d (%s) ",
++ ret, strerror(-ret));
++ }
++ return ret;
++}
+
+ #ifdef CONFIG_TESTING_OPTIONS
+
+@@ -13073,4 +13138,5 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
+ .start_disabled = nl80211_start_disabled,
+ .amsdu_ctrl = nl80211_enable_amsdu,
+ .amsdu_dump = nl80211_dump_amsdu,
++ .get_aval_color_bmp = nl80211_get_aval_color_bmp,
+ };
+diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h
+index e570224..b90c8fa 100644
+--- a/src/drivers/driver_nl80211.h
++++ b/src/drivers/driver_nl80211.h
+@@ -186,6 +186,7 @@ struct wpa_driver_nl80211_data {
+ unsigned int mtk_3wire_vendor_cmd_avail:1;
+ unsigned int mtk_ibf_vendor_cmd_avail:1;
+ unsigned int mtk_wireless_vendor_cmd_avail:1;
++ unsigned int mtk_bss_color_vendor_cmd_avail:1;
+
+ u64 vendor_scan_cookie;
+ u64 remain_on_chan_cookie;
+diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
+index fcfa68b..c3c7b41 100644
+--- a/src/drivers/driver_nl80211_capa.c
++++ b/src/drivers/driver_nl80211_capa.c
+@@ -1068,6 +1068,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
+ case MTK_NL80211_VENDOR_SUBCMD_WIRELESS_CTRL:
+ drv->mtk_wireless_vendor_cmd_avail = 1;
+ break;
++ case MTK_NL80211_VENDOR_SUBCMD_BSS_COLOR_CTRL :
++ drv->mtk_bss_color_vendor_cmd_avail = 1;
++ break;
+ }
+ }
+
+--
+2.39.0
+
diff --git a/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0017-hostapd-mtk-Fix-sending-wrong-VHT-operation-IE-in-CS.patch b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0017-hostapd-mtk-Fix-sending-wrong-VHT-operation-IE-in-CS.patch
new file mode 100644
index 0000000..265c37a
--- /dev/null
+++ b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0017-hostapd-mtk-Fix-sending-wrong-VHT-operation-IE-in-CS.patch
@@ -0,0 +1,46 @@
+From f6bfd9a4a6c0d08e0dec9311873c9e863a07c9a8 Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Mon, 20 Feb 2023 11:01:18 +0800
+Subject: [PATCH] hostapd: mtk: Fix sending wrong VHT operation IE in CSA while
+ using ZWDFS
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ src/ap/dfs.c | 14 +++++++++-----
+ 1 file changed, 9 insertions(+), 5 deletions(-)
+
+diff --git a/src/ap/dfs.c b/src/ap/dfs.c
+index 4b1e642..307a4e1 100644
+--- a/src/ap/dfs.c
++++ b/src/ap/dfs.c
+@@ -1110,6 +1110,14 @@ static int
+ hostapd_dfs_start_channel_switch_background(struct hostapd_iface *iface)
+ {
+ u8 current_vht_oper_chwidth = hostapd_get_oper_chwidth(iface->conf);
++ int ret;
++
++ ret = hostapd_dfs_request_channel_switch(iface, iface->radar_background.channel,
++ iface->radar_background.freq,
++ iface->radar_background.secondary_channel,
++ current_vht_oper_chwidth,
++ iface->radar_background.centr_freq_seg0_idx,
++ iface->radar_background.centr_freq_seg1_idx);
+
+ iface->conf->channel = iface->radar_background.channel;
+ iface->freq = iface->radar_background.freq;
+@@ -1122,11 +1130,7 @@ hostapd_dfs_start_channel_switch_background(struct hostapd_iface *iface)
+
+ hostpad_dfs_update_background_chain(iface);
+
+- return hostapd_dfs_request_channel_switch(
+- iface, iface->conf->channel, iface->freq,
+- iface->conf->secondary_channel, current_vht_oper_chwidth,
+- hostapd_get_oper_centr_freq_seg0_idx(iface->conf),
+- hostapd_get_oper_centr_freq_seg1_idx(iface->conf));
++ return ret;
+ }
+
+
+--
+2.18.0
+
diff --git a/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0018-hostapd-mtk-Add-sta-assisted-DFS-state-update-mechan.patch b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0018-hostapd-mtk-Add-sta-assisted-DFS-state-update-mechan.patch
new file mode 100644
index 0000000..db3c813
--- /dev/null
+++ b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0018-hostapd-mtk-Add-sta-assisted-DFS-state-update-mechan.patch
@@ -0,0 +1,189 @@
+From 3337e7b4f75a66e53e1320e49deba2b58a8a80b0 Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Mon, 20 Feb 2023 10:51:47 +0800
+Subject: [PATCH 18/19] hostapd: mtk: Add sta-assisted DFS state update
+ mechanism
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ src/ap/dfs.c | 20 ++++++++++++++++++++
+ src/ap/dfs.h | 3 +++
+ src/ap/drv_callbacks.c | 28 ++++++++++++++++++++++++++++
+ src/common/wpa_ctrl.h | 1 +
+ src/drivers/driver.h | 14 ++++++++++++++
+ src/drivers/driver_nl80211_event.c | 6 ++++++
+ src/drivers/nl80211_copy.h | 6 ++++++
+ 7 files changed, 78 insertions(+)
+
+diff --git a/src/ap/dfs.c b/src/ap/dfs.c
+index 307a4e1..d082fe0 100644
+--- a/src/ap/dfs.c
++++ b/src/ap/dfs.c
+@@ -1503,6 +1503,26 @@ int hostapd_dfs_nop_finished(struct hostapd_iface *iface, int freq,
+ }
+
+
++int hostapd_dfs_sta_update_state(struct hostapd_iface *iface, int freq,
++ int ht_enabled, int chan_offset, int chan_width,
++ int cf1, int cf2, u32 state)
++{
++ wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_STA_UPDATE
++ "freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d state=%s",
++ freq, ht_enabled, chan_offset, chan_width, cf1, cf2,
++ (state == HOSTAPD_CHAN_DFS_AVAILABLE) ? "available" : "usable");
++
++ /* Proceed only if DFS is not offloaded to the driver */
++ if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD)
++ return 0;
++
++ set_dfs_state(iface, freq, ht_enabled, chan_offset, chan_width,
++ cf1, cf2, state);
++
++ return 0;
++}
++
++
+ int hostapd_is_dfs_required(struct hostapd_iface *iface)
+ {
+ int n_chans, n_chans1, start_chan_idx, start_chan_idx1, res;
+diff --git a/src/ap/dfs.h b/src/ap/dfs.h
+index c2556d2..25ba29c 100644
+--- a/src/ap/dfs.h
++++ b/src/ap/dfs.h
+@@ -30,6 +30,9 @@ int hostapd_dfs_radar_detected(struct hostapd_iface *iface, int freq,
+ int hostapd_dfs_nop_finished(struct hostapd_iface *iface, int freq,
+ int ht_enabled,
+ int chan_offset, int chan_width, int cf1, int cf2);
++int hostapd_dfs_sta_update_state(struct hostapd_iface *iface, int freq,
++ int ht_enabled, int chan_offset, int chan_width,
++ int cf1, int cf2, u32 state);
+ int hostapd_is_dfs_required(struct hostapd_iface *iface);
+ int hostapd_is_dfs_chan_available(struct hostapd_iface *iface);
+ int hostapd_dfs_start_cac(struct hostapd_iface *iface, int freq,
+diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
+index 09783cb..275f6b3 100644
+--- a/src/ap/drv_callbacks.c
++++ b/src/ap/drv_callbacks.c
+@@ -1790,6 +1790,24 @@ static void hostapd_event_dfs_cac_started(struct hostapd_data *hapd,
+ radar->cf1, radar->cf2);
+ }
+
++static void hostapd_event_dfs_sta_cac_skipped(struct hostapd_data *hapd,
++ struct dfs_event *radar)
++{
++ wpa_printf(MSG_DEBUG, "DFS CAC skipped (by STA) on %d MHz", radar->freq);
++ hostapd_dfs_sta_update_state(hapd->iface, radar->freq, radar->ht_enabled,
++ radar->chan_offset, radar->chan_width,
++ radar->cf1, radar->cf2, HOSTAPD_CHAN_DFS_AVAILABLE);
++}
++
++static void hostapd_event_dfs_sta_cac_expired(struct hostapd_data *hapd,
++ struct dfs_event *radar)
++{
++ wpa_printf(MSG_DEBUG, "DFS CAC expired (by STA) on %d MHz", radar->freq);
++ hostapd_dfs_sta_update_state(hapd->iface, radar->freq, radar->ht_enabled,
++ radar->chan_offset, radar->chan_width,
++ radar->cf1, radar->cf2, HOSTAPD_CHAN_DFS_USABLE);
++}
++
+ #endif /* NEED_AP_MLME */
+
+
+@@ -2064,6 +2082,16 @@ void hostapd_wpa_event(void *ctx, enum wpa_event_type event,
+ break;
+ hostapd_event_dfs_nop_finished(hapd, &data->dfs_event);
+ break;
++ case EVENT_DFS_STA_CAC_SKIPPED:
++ if (!data)
++ break;
++ hostapd_event_dfs_sta_cac_skipped(hapd, &data->dfs_event);
++ break;
++ case EVENT_DFS_STA_CAC_EXPIRED:
++ if (!data)
++ break;
++ hostapd_event_dfs_sta_cac_expired(hapd, &data->dfs_event);
++ break;
+ case EVENT_CHANNEL_LIST_CHANGED:
+ /* channel list changed (regulatory?), update channel list */
+ /* TODO: check this. hostapd_get_hw_features() initializes
+diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h
+index 3435084..79c8a82 100644
+--- a/src/common/wpa_ctrl.h
++++ b/src/common/wpa_ctrl.h
+@@ -360,6 +360,7 @@ extern "C" {
+ #define DFS_EVENT_CAC_COMPLETED "DFS-CAC-COMPLETED "
+ #define DFS_EVENT_NOP_FINISHED "DFS-NOP-FINISHED "
+ #define DFS_EVENT_PRE_CAC_EXPIRED "DFS-PRE-CAC-EXPIRED "
++#define DFS_EVENT_STA_UPDATE "DFS-STA-UPDATE "
+
+ #define AP_CSA_FINISHED "AP-CSA-FINISHED "
+
+diff --git a/src/drivers/driver.h b/src/drivers/driver.h
+index 265d86d..b5de0e6 100644
+--- a/src/drivers/driver.h
++++ b/src/drivers/driver.h
+@@ -5317,6 +5317,20 @@ enum wpa_event_type {
+ * EVENT_CCA_NOTIFY - Notification that CCA has completed
+ */
+ EVENT_CCA_NOTIFY,
++
++ /**
++ * EVENT_DFS_STA_CAC_SKIPPED - Notification that CAC has been skipped
++ *
++ * The channel in the notification is now marked as available.
++ */
++ EVENT_DFS_STA_CAC_SKIPPED,
++
++ /**
++ * EVENT_DFS_STA_CAC_EXPIRED - Notification that CAC has expired
++ *
++ * The channel in the notification is now marked as usable.
++ */
++ EVENT_DFS_STA_CAC_EXPIRED,
+ };
+
+
+diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c
+index 73bb7a4..ee922ac 100644
+--- a/src/drivers/driver_nl80211_event.c
++++ b/src/drivers/driver_nl80211_event.c
+@@ -1854,6 +1854,12 @@ static void nl80211_radar_event(struct wpa_driver_nl80211_data *drv,
+ case NL80211_RADAR_CAC_STARTED:
+ wpa_supplicant_event(drv->ctx, EVENT_DFS_CAC_STARTED, &data);
+ break;
++ case NL80211_RADAR_STA_CAC_SKIPPED:
++ wpa_supplicant_event(drv->ctx, EVENT_DFS_STA_CAC_SKIPPED, &data);
++ break;
++ case NL80211_RADAR_STA_CAC_EXPIRED:
++ wpa_supplicant_event(drv->ctx, EVENT_DFS_STA_CAC_EXPIRED, &data);
++ break;
+ default:
+ wpa_printf(MSG_DEBUG, "nl80211: Unknown radar event %d "
+ "received", event_type);
+diff --git a/src/drivers/nl80211_copy.h b/src/drivers/nl80211_copy.h
+index c4bf3ad..0937752 100644
+--- a/src/drivers/nl80211_copy.h
++++ b/src/drivers/nl80211_copy.h
+@@ -6431,6 +6431,10 @@ enum nl80211_smps_mode {
+ * applicable for ETSI dfs domain where pre-CAC is valid for ever.
+ * @NL80211_RADAR_CAC_STARTED: Channel Availability Check has been started,
+ * should be generated by HW if NL80211_EXT_FEATURE_DFS_OFFLOAD is enabled.
++ * @NL80211_RADAR_STA_CAC_SKIPPED: STA set the DFS state to available
++ * when receiving CSA/assoc resp
++ * @NL80211_RADAR_STA_CAC_EXPIRED: STA set the DFS state to usable
++ * when STA is disconnected or leaving the channel
+ */
+ enum nl80211_radar_event {
+ NL80211_RADAR_DETECTED,
+@@ -6439,6 +6443,8 @@ enum nl80211_radar_event {
+ NL80211_RADAR_NOP_FINISHED,
+ NL80211_RADAR_PRE_CAC_EXPIRED,
+ NL80211_RADAR_CAC_STARTED,
++ NL80211_RADAR_STA_CAC_SKIPPED,
++ NL80211_RADAR_STA_CAC_EXPIRED,
+ };
+
+ /**
+--
+2.18.0
+
diff --git a/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0019-hostapd-mtk-Fix-auto-ht-issue-when-switching-to-DFS-.patch b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0019-hostapd-mtk-Fix-auto-ht-issue-when-switching-to-DFS-.patch
new file mode 100644
index 0000000..8340fd9
--- /dev/null
+++ b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0019-hostapd-mtk-Fix-auto-ht-issue-when-switching-to-DFS-.patch
@@ -0,0 +1,43 @@
+From 83ab1a9cc51225095842d3c62bf75cf4efe63075 Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Mon, 20 Feb 2023 16:58:20 +0800
+Subject: [PATCH] hostapd: mtk: Fix auto ht issue when switching to DFS channel
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ hostapd/ctrl_iface.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
+index 0ad8451..407790f 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -2698,6 +2698,12 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
+ break;
+ }
+
++ if (os_strstr(pos, " auto-ht")) {
++ settings.freq_params.ht_enabled = iface->conf->ieee80211n;
++ settings.freq_params.vht_enabled = iface->conf->ieee80211ac;
++ settings.freq_params.he_enabled = iface->conf->ieee80211ax;
++ }
++
+ if (settings.freq_params.center_freq1)
+ dfs_range += hostapd_is_dfs_overlap(
+ iface, bandwidth, settings.freq_params.center_freq1);
+@@ -2735,12 +2741,6 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
+ return 0;
+ }
+
+- if (os_strstr(pos, " auto-ht")) {
+- settings.freq_params.ht_enabled = iface->conf->ieee80211n;
+- settings.freq_params.vht_enabled = iface->conf->ieee80211ac;
+- settings.freq_params.he_enabled = iface->conf->ieee80211ax;
+- }
+-
+ for (i = 0; i < iface->num_bss; i++) {
+
+ /* Save CHAN_SWITCH VHT, HE, and EHT config */
+--
+2.18.0
+
diff --git a/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0020-hostapd-mtk-Mark-DFS-channel-as-available-for-CSA.patch b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0020-hostapd-mtk-Mark-DFS-channel-as-available-for-CSA.patch
new file mode 100644
index 0000000..1fe5c88
--- /dev/null
+++ b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0020-hostapd-mtk-Mark-DFS-channel-as-available-for-CSA.patch
@@ -0,0 +1,60 @@
+From 3e9500a42a41e8cd7c2d7bc20aba96e1e17161fb Mon Sep 17 00:00:00 2001
+From: "himanshu.goyal" <himanshu.goyal@mediatek.com>
+Date: Fri, 3 Mar 2023 12:45:42 +0800
+Subject: [PATCH] hostapd: mtk: Mark DFS channel as available for CSA.
+
+---
+ hostapd/ctrl_iface.c | 10 ++++++++++
+ hostapd/hostapd_cli.c | 2 +-
+ src/ap/ctrl_iface_ap.c | 1 +
+ 3 files changed, 12 insertions(+), 1 deletion(-)
+
+diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
+index c33b7a4..9ba6992 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -2704,6 +2704,16 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
+ settings.freq_params.he_enabled = iface->conf->ieee80211ax;
+ }
+
++ if (settings.freq_params.radar_background) {
++ hostapd_dfs_sta_update_state(iface,
++ settings.freq_params.freq,
++ settings.freq_params.ht_enabled,
++ settings.freq_params.sec_channel_offset,
++ bandwidth, settings.freq_params.center_freq1,
++ settings.freq_params.center_freq2,
++ HOSTAPD_CHAN_DFS_AVAILABLE);
++ }
++
+ if (settings.freq_params.center_freq1)
+ dfs_range += hostapd_is_dfs_overlap(
+ iface, bandwidth, settings.freq_params.center_freq1);
+diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
+index 0da18e2..6231e51 100644
+--- a/hostapd/hostapd_cli.c
++++ b/hostapd/hostapd_cli.c
+@@ -1693,7 +1693,7 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
+ "<addr> = send QoS Map Configure frame" },
+ { "chan_switch", hostapd_cli_cmd_chan_switch, NULL,
+ "<cs_count> <freq> [sec_channel_offset=] [center_freq1=]\n"
+- " [center_freq2=] [bandwidth=] [blocktx] [ht|vht]\n"
++ " [center_freq2=] [bandwidth=] [blocktx] [ht|vht] [skip_cac]\n"
+ " = initiate channel switch announcement" },
+ { "hs20_wnm_notif", hostapd_cli_cmd_hs20_wnm_notif, NULL,
+ "<addr> <url>\n"
+diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c
+index 18bae5c..2fae590 100644
+--- a/src/ap/ctrl_iface_ap.c
++++ b/src/ap/ctrl_iface_ap.c
+@@ -938,6 +938,7 @@ int hostapd_parse_csa_settings(const char *pos,
+ settings->freq_params.vht_enabled = !!os_strstr(pos, " vht");
+ settings->freq_params.he_enabled = !!os_strstr(pos, " he");
+ settings->freq_params.eht_enabled = !!os_strstr(pos, " eht");
++ settings->freq_params.radar_background = !!os_strstr(pos, " skip_cac");
+ settings->block_tx = !!os_strstr(pos, " blocktx");
+ #undef SET_CSA_SETTING
+
+--
+2.18.0
+
diff --git a/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0020-hostapd-mtk-add-11v_mbss-and-ema-support.patch b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0020-hostapd-mtk-add-11v_mbss-and-ema-support.patch
new file mode 100644
index 0000000..8d59a0f
--- /dev/null
+++ b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/mtk-0020-hostapd-mtk-add-11v_mbss-and-ema-support.patch
@@ -0,0 +1,1175 @@
+From 8cbdb9a59e3bbe8804f909b13ce6df6e2777c3da Mon Sep 17 00:00:00 2001
+From: mtk20656 <chank.chen@mediatek.com>
+Date: Thu, 2 Mar 2023 10:51:43 +0800
+Subject: [PATCH] hostapd: mtk: add 11v_mbss and ema support for hostapd
+
+Signed-off-by: mtk20656 <chank.chen@mediatek.com>
+---
+ hostapd/config_file.c | 9 +
+ hostapd/hostapd.conf | 58 +++++++
+ hostapd/main.c | 3 +
+ src/ap/ap_config.c | 12 ++
+ src/ap/ap_config.h | 6 +
+ src/ap/beacon.c | 124 ++++++++++++--
+ src/ap/hostapd.c | 72 +++++++-
+ src/ap/hostapd.h | 7 +
+ src/ap/ieee802_11.c | 276 +++++++++++++++++++++++++++++-
+ src/ap/ieee802_11.h | 7 +-
+ src/ap/ieee802_11_shared.c | 11 ++
+ src/common/ieee802_11_common.c | 4 +
+ src/common/ieee802_11_common.h | 3 +
+ src/common/ieee802_11_defs.h | 5 +
+ src/drivers/driver.h | 42 +++++
+ src/drivers/driver_nl80211.c | 52 ++++++
+ src/drivers/driver_nl80211_capa.c | 27 +++
+ 17 files changed, 698 insertions(+), 20 deletions(-)
+
+diff --git a/hostapd/config_file.c b/hostapd/config_file.c
+index 649618b..3f26191 100644
+--- a/hostapd/config_file.c
++++ b/hostapd/config_file.c
+@@ -3663,6 +3663,15 @@ static int hostapd_config_fill(struct hostapd_config *conf,
+ return 1;
+ }
+ bss->unsol_bcast_probe_resp_interval = val;
++ } else if (os_strcmp(buf, "mbssid") == 0) {
++ int mbssid = atoi(pos);
++ if (mbssid < 0 || mbssid > ENHANCED_MBSSID_ENABLED) {
++ wpa_printf(MSG_ERROR,
++ "Line %d: invalid mbssid (%d): '%s'.",
++ line, mbssid, pos);
++ return 1;
++ }
++ conf->mbssid = mbssid;
+ } else if (os_strcmp(buf, "mu_onoff") == 0) {
+ int val = atoi(pos);
+ if (val < 0 || val > 15) {
+diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
+index e3a5eb3..f926029 100644
+--- a/hostapd/hostapd.conf
++++ b/hostapd/hostapd.conf
+@@ -3123,3 +3123,61 @@ own_ip_addr=127.0.0.1
+ #bss=wlan0_1
+ #bssid=00:13:10:95:fe:0b
+ # ...
++#
++# Multiple BSSID Advertisement in 802.11ax
++# IEEE Std 802.11ax-2021 added a feature where instead of multiple interfaces
++# on a common radio transmitting individual beacons, those can form a set with
++# a common beacon is transmitted for all. The interface which is brought up
++# first is called as the transmitting profile of the MBSSID set which transmits
++# the beacons. The remaining interfaces are called as the non-transmitting
++# profiles and these are advertised inside the multiple BSSID element in the
++# beacons and probe response frames.
++# The transmitting interface is visible to all clients in the vicinity, however
++# the clients which do not support parsing of the multiple BSSID element will
++# not be able to connect to the non-transmitting interfaces.
++#
++# Enhanced Multiple BSSID Advertisements (EMA)
++# When enabled, the non-transmitting interfaces are split into multiple
++# beacons. The number of beacons required to cover all the non-transmitting
++# profiles is called as the profile periodicity.
++#
++# Refer to IEEE Std 802.11-2020 for details regarding the procedure and
++# required MAC address assignment.
++#
++# Following configuration is per radio.
++# 0 = Disabled (Default)
++# 1 = Multiple BSSID advertisements enabled.
++# 2 = Enhanced multiple BSSID advertisements enabled.
++#mbssid=0
++#
++# The transmitting interface should be added with 'interface' option while
++# the non-transmitting interfaces should be added using 'bss' option.
++# Security configuration should be added separately per interface, if required.
++#
++# Example:
++#mbssid=2
++#interface=wlan2
++#ctrl_interface=/var/run/hostapd
++#wpa_passphrase=0123456789
++#ieee80211w=2
++#sae_pwe=1
++#auth_algs=1
++#wpa=2
++#wpa_pairwise=CCMP
++#ssid=<SSID-0>
++#bridge=br-lan
++#wpa_key_mgmt=SAE
++#bssid=00:03:7f:12:84:84
++#
++#bss=wlan2-1
++#ctrl_interface=/var/run/hostapd
++#wpa_passphrase=0123456789
++#ieee80211w=2
++#sae_pwe=1
++#auth_algs=1
++#wpa=2
++#wpa_pairwise=CCMP
++#ssid=<SSID-1>
++#bridge=br-lan
++#wpa_key_mgmt=SAE
++#bssid=00:03:7f:12:84:85
+diff --git a/hostapd/main.c b/hostapd/main.c
+index 70a4b32..1b6474a 100644
+--- a/hostapd/main.c
++++ b/hostapd/main.c
+@@ -253,6 +253,9 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
+ wpa_printf(MSG_ERROR, "set_wowlan failed");
+ }
+ os_free(triggs);
++
++ iface->mbssid_max_interfaces = capa.mbssid_max_interfaces;
++ iface->ema_max_periodicity = capa.ema_max_periodicity;
+ }
+
+ return 0;
+diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
+index 4e46a62..7d9d5cb 100644
+--- a/src/ap/ap_config.c
++++ b/src/ap/ap_config.c
+@@ -1462,6 +1462,12 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
+ }
+ #endif /* CONFIG_IEEE80211BE */
+
++ if (full_config && bss->ignore_broadcast_ssid && conf->mbssid) {
++ wpa_printf(MSG_ERROR,
++ "Hidden SSID is not suppored when MBSSID is enabled");
++ return -1;
++ }
++
+ return 0;
+ }
+
+@@ -1545,6 +1551,12 @@ int hostapd_config_check(struct hostapd_config *conf, int full_config)
+ }
+ #endif /* CONFIG_IEEE80211BE */
+
++ if (full_config && conf->mbssid && !conf->ieee80211ax) {
++ wpa_printf(MSG_ERROR,
++ "Cannot enable multiple BSSID support without ieee80211ax");
++ return -1;
++ }
++
+ for (i = 0; i < conf->num_bss; i++) {
+ if (hostapd_config_check_bss(conf->bss[i], conf, full_config))
+ return -1;
+diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
+index 7aeb176..51476b8 100644
+--- a/src/ap/ap_config.h
++++ b/src/ap/ap_config.h
+@@ -923,6 +923,8 @@ struct hostapd_bss_config {
+ u8 ext_capa[EXT_CAPA_MAX_LEN];
+
+ u8 rnr;
++
++ bool xrates_supported;
+ };
+
+ /**
+@@ -1163,6 +1165,10 @@ struct hostapd_config {
+ u8 ibf_enable;
+ u8 dfs_detect_mode;
+ u8 amsdu;
++
++#define MBSSID_ENABLED 1
++#define ENHANCED_MBSSID_ENABLED 2
++ u8 mbssid;
+ };
+
+ enum three_wire_mode {
+diff --git a/src/ap/beacon.c b/src/ap/beacon.c
+index f3ea5c2..51db23a 100644
+--- a/src/ap/beacon.c
++++ b/src/ap/beacon.c
+@@ -462,15 +462,77 @@ static u8 * hostapd_eid_supported_op_classes(struct hostapd_data *hapd, u8 *eid)
+ }
+
+
++static int ieee802_11_build_ap_params_mbssid(struct hostapd_data *hapd,
++ struct wpa_driver_ap_params *params,
++ u8 **eid)
++{
++ struct hostapd_iface *iface = hapd->iface;
++ struct hostapd_data *tx_bss;
++ size_t len;
++ u8 elem_count = 0, *elem = NULL, **elem_offset = NULL, *end;
++ u8 *tailpos = *eid;
++
++ if (!iface->mbssid_max_interfaces ||
++ iface->num_bss > iface->mbssid_max_interfaces ||
++ (iface->conf->mbssid == ENHANCED_MBSSID_ENABLED &&
++ !iface->ema_max_periodicity))
++ goto fail;
++
++ tx_bss = hostapd_mbssid_get_tx_bss(hapd);
++ len = hostapd_eid_mbssid_len(tx_bss, WLAN_FC_STYPE_BEACON, &elem_count,
++ NULL, 0);
++ if (!len || (iface->conf->mbssid == ENHANCED_MBSSID_ENABLED &&
++ elem_count > iface->ema_max_periodicity))
++ goto fail;
++
++ elem = os_zalloc(len);
++ if (!elem)
++ goto fail;
++
++ elem_offset = os_zalloc(elem_count * sizeof(u8 *));
++ if (!elem_offset)
++ goto fail;
++
++ end = hostapd_eid_mbssid(tx_bss, elem, elem + len, WLAN_FC_STYPE_BEACON,
++ elem_count, elem_offset, NULL, 0);
++
++ params->mbssid_tx_iface = tx_bss->conf->iface;
++ params->mbssid_index = hostapd_mbssid_get_bss_index(hapd);
++ params->mbssid_elem = elem;
++ params->mbssid_elem_len = end - elem;
++ params->mbssid_elem_count = elem_count;
++ params->mbssid_elem_offset = elem_offset;
++ if (iface->conf->mbssid == ENHANCED_MBSSID_ENABLED) {
++ params->ema = true;
++ *tailpos++ = WLAN_EID_EXTENSION;
++ *tailpos++ = 3;
++ *tailpos++ = WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION;
++ *tailpos++ = iface->num_bss;
++ *tailpos++ = params->mbssid_elem_count;
++ *eid = tailpos;
++ }
++
++ return 0;
++
++fail:
++ os_free(elem);
++ wpa_printf(MSG_ERROR, "MBSSID: Configuration failed");
++ return -1;
++}
++
++
+ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
+ const struct ieee80211_mgmt *req,
+ int is_p2p, size_t *resp_len,
+- bool bcast_probe_resp)
++ bool bcast_probe_resp, const u8 *known_bss,
++ u8 known_bss_len)
+ {
+ struct ieee80211_mgmt *resp;
+- u8 *pos, *epos, *csa_pos;
++ u8 *pos, *epos, *csa_pos, *ext_cap_pos;
+ size_t buflen;
+
++ hapd = hostapd_mbssid_get_tx_bss(hapd);
++
+ #define MAX_PROBERESP_LEN 768
+ buflen = MAX_PROBERESP_LEN;
+ #ifdef CONFIG_WPS
+@@ -517,6 +579,8 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
+ }
+ #endif /* CONFIG_IEEE80211BE */
+
++ buflen += hostapd_eid_mbssid_len(hapd, WLAN_FC_STYPE_PROBE_RESP, NULL,
++ known_bss, known_bss_len);
+ buflen += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_PROBE_RESP);
+ buflen += hostapd_mbo_ie_len(hapd);
+ buflen += hostapd_eid_owe_trans_len(hapd);
+@@ -588,8 +652,16 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
+ pos = hostapd_eid_supported_op_classes(hapd, pos);
+ pos = hostapd_eid_ht_capabilities(hapd, pos);
+ pos = hostapd_eid_ht_operation(hapd, pos);
++ pos = hostapd_eid_mbssid(hapd, pos, epos, WLAN_FC_STYPE_PROBE_RESP, 0,
++ NULL, known_bss, known_bss_len);
+
++ ext_cap_pos = pos;
+ pos = hostapd_eid_ext_capab(hapd, pos);
++ if (hapd->iconf->mbssid >= MBSSID_ENABLED && !known_bss_len)
++ ext_cap_pos[12] |= 0x01; /* Probe responses always include all
++ * non-tx profiles except when a list
++ * of known BSSes is included in the
++ * probe request. */
+
+ pos = hostapd_eid_time_adv(hapd, pos);
+ pos = hostapd_eid_time_zone(hapd, pos);
+@@ -1153,16 +1225,23 @@ void handle_probe_req(struct hostapd_data *hapd,
+ }
+ #endif /* CONFIG_TESTING_OPTIONS */
+
++ /* Do not send probe response from a non-transmitting multiple BSSID
++ * profile unless the probe request is directed at that paticular BSS */
++ if (hapd != hostapd_mbssid_get_tx_bss(hapd) && res != EXACT_SSID_MATCH)
++ return;
++
+ wpa_msg_ctrl(hapd->msg_ctx, MSG_INFO, RX_PROBE_REQUEST "sa=" MACSTR
+ " signal=%d", MAC2STR(mgmt->sa), ssi_signal);
+
+ if (is_6ghz_op_class(hapd->iconf->op_class) &&
+ is_broadcast_ether_addr(mgmt->da))
+ resp = hostapd_gen_probe_resp(hapd, NULL, elems.p2p != NULL,
+- &resp_len, true);
++ &resp_len, false, elems.mbssid_known_bss,
++ elems.mbssid_known_bss_len);
+ else
+ resp = hostapd_gen_probe_resp(hapd, mgmt, elems.p2p != NULL,
+- &resp_len, false);
++ &resp_len, false, elems.mbssid_known_bss,
++ elems.mbssid_known_bss_len);
+ if (resp == NULL)
+ return;
+
+@@ -1184,7 +1263,8 @@ void handle_probe_req(struct hostapd_data *hapd,
+ hapd->cs_c_off_ecsa_proberesp;
+ }
+
+- ret = hostapd_drv_send_mlme(hapd, resp, resp_len, noack,
++ ret = hostapd_drv_send_mlme(hostapd_mbssid_get_tx_bss(hapd), resp,
++ resp_len, noack,
+ csa_offs_len ? csa_offs : NULL,
+ csa_offs_len, 0);
+
+@@ -1231,7 +1311,7 @@ static u8 * hostapd_probe_resp_offloads(struct hostapd_data *hapd,
+ "this");
+
+ /* Generate a Probe Response template for the non-P2P case */
+- return hostapd_gen_probe_resp(hapd, NULL, 0, resp_len, false);
++ return hostapd_gen_probe_resp(hapd, NULL, 0, resp_len, false, NULL, 0);
+ }
+
+ #endif /* NEED_AP_MLME */
+@@ -1250,7 +1330,7 @@ static u8 * hostapd_unsol_bcast_probe_resp(struct hostapd_data *hapd,
+
+ return hostapd_gen_probe_resp(hapd, NULL, 0,
+ ¶ms->unsol_bcast_probe_resp_tmpl_len,
+- true);
++ true, NULL, 0);
+ }
+ #endif /* CONFIG_IEEE80211AX */
+
+@@ -1533,8 +1613,12 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
+ size_t resp_len = 0;
+ #ifdef NEED_AP_MLME
+ u16 capab_info;
+- u8 *pos, *tailpos, *tailend, *csa_pos;
++ u8 *pos, *tailpos, *tailend, *csa_pos, *ext_cap_pos;
++#endif /* NEED_AP_MLME */
+
++ os_memset(params, 0, sizeof(*params));
++
++#ifdef NEED_AP_MLME
+ #define BEACON_HEAD_BUF_SIZE 256
+ #define BEACON_TAIL_BUF_SIZE 512
+ head = os_zalloc(BEACON_HEAD_BUF_SIZE);
+@@ -1586,6 +1670,9 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
+ }
+ #endif /* CONFIG_IEEE80211BE */
+
++ if (hapd->iconf->mbssid == ENHANCED_MBSSID_ENABLED &&
++ hapd == hostapd_mbssid_get_tx_bss(hapd))
++ tail_len += 5; /* Multiple BSSID Configuration element */
+ tail_len += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_BEACON);
+ tail_len += hostapd_mbo_ie_len(hapd);
+ tail_len += hostapd_eid_owe_trans_len(hapd);
+@@ -1671,9 +1758,23 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
+ tailpos = hostapd_eid_supported_op_classes(hapd, tailpos);
+ tailpos = hostapd_eid_ht_capabilities(hapd, tailpos);
+ tailpos = hostapd_eid_ht_operation(hapd, tailpos);
+-
++ ext_cap_pos = tailpos;
+ tailpos = hostapd_eid_ext_capab(hapd, tailpos);
+
++ if (hapd->iconf->mbssid && hapd->iconf->num_bss > 1) {
++ if (ieee802_11_build_ap_params_mbssid(hapd, params, &tailpos)) {
++ os_free(head);
++ os_free(tail);
++ wpa_printf(MSG_ERROR, "Failed to set beacon data");
++ return -1;
++ } else if (hapd->iconf->mbssid == MBSSID_ENABLED ||
++ (hapd->iconf->mbssid == ENHANCED_MBSSID_ENABLED &&
++ params->mbssid_elem_count == 1)) {
++ /* Set the extended capability bit for "complete list
++ * of non-tx profiles" */
++ ext_cap_pos[12] |= 0x01;
++ }
++ }
+ /*
+ * TODO: Time Advertisement element should only be included in some
+ * DTIM Beacon frames.
+@@ -1794,7 +1895,6 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
+ resp = hostapd_probe_resp_offloads(hapd, &resp_len);
+ #endif /* NEED_AP_MLME */
+
+- os_memset(params, 0, sizeof(*params));
+ params->head = (u8 *) head;
+ params->head_len = head_len;
+ params->tail = tail;
+@@ -1897,6 +1997,10 @@ void ieee802_11_free_ap_params(struct wpa_driver_ap_params *params)
+ params->head = NULL;
+ os_free(params->proberesp);
+ params->proberesp = NULL;
++ os_free(params->mbssid_elem);
++ params->mbssid_elem = NULL;
++ os_free(params->mbssid_elem_offset);
++ params->mbssid_elem_offset = NULL;
+ #ifdef CONFIG_FILS
+ os_free(params->fd_frame_tmpl);
+ params->fd_frame_tmpl = NULL;
+diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
+index 42e8ed7..82cc155 100644
+--- a/src/ap/hostapd.c
++++ b/src/ap/hostapd.c
+@@ -91,6 +91,29 @@ int hostapd_for_each_interface(struct hapd_interfaces *interfaces,
+ }
+
+
++struct hostapd_data * hostapd_mbssid_get_tx_bss(struct hostapd_data *hapd)
++{
++ if (hapd->iconf->mbssid)
++ return hapd->iface->bss[0];
++
++ return hapd;
++}
++
++
++int hostapd_mbssid_get_bss_index(struct hostapd_data *hapd)
++{
++ if (hapd->iconf->mbssid) {
++ size_t i;
++
++ for (i = 1; i < hapd->iface->num_bss; i++)
++ if (hapd->iface->bss[i] == hapd)
++ return i;
++ }
++
++ return 0;
++}
++
++
+ void hostapd_reconfig_encryption(struct hostapd_data *hapd)
+ {
+ if (hapd->wpa_auth)
+@@ -1179,19 +1202,37 @@ static int db_table_create_radius_attributes(sqlite3 *db)
+
+ #endif /* CONFIG_NO_RADIUS */
+
++static int hostapd_start_beacon(struct hostapd_data *hapd)
++{
++ struct hostapd_bss_config *conf = hapd->conf;
++
++ if (!conf->start_disabled && ieee802_11_set_beacon(hapd) < 0)
++ return -1;
++
++ if (hapd->driver && hapd->driver->set_operstate)
++ hapd->driver->set_operstate(hapd->drv_priv, 1);
++
++ return 0;
++}
+
+ /**
+ * hostapd_setup_bss - Per-BSS setup (initialization)
+ * @hapd: Pointer to BSS data
+ * @first: Whether this BSS is the first BSS of an interface; -1 = not first,
+ * but interface may exist
++ * @start_beacon: Whether beacons should be configured and transmission started
++ * at this time. This is used when MBSSID IE is enabled where the
++ * information regarding all BSSes should be retrieved before configuring
++ * the beacons. The calling functions are responsible to configure the
++ * beacon explicitly if this is set to 'false'.
+ *
+ * This function is used to initialize all per-BSS data structures and
+ * resources. This gets called in a loop for each BSS when an interface is
+ * initialized. Most of the modules that are initialized here will be
+ * deinitialized in hostapd_cleanup().
+ */
+-static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
++static int hostapd_setup_bss(struct hostapd_data *hapd, int first,
++ bool start_beacon)
+ {
+ struct hostapd_bss_config *conf = hapd->conf;
+ u8 ssid[SSID_MAX_LEN + 1];
+@@ -1464,9 +1505,6 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
+ return -1;
+ }
+
+- if (!conf->start_disabled && ieee802_11_set_beacon(hapd) < 0)
+- return -1;
+-
+ if (flush_old_stations && !conf->start_disabled &&
+ conf->broadcast_deauth) {
+ u8 addr[ETH_ALEN];
+@@ -1485,8 +1523,8 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
+ if (hapd->wpa_auth && wpa_init_keys(hapd->wpa_auth) < 0)
+ return -1;
+
+- if (hapd->driver && hapd->driver->set_operstate)
+- hapd->driver->set_operstate(hapd->drv_priv, 1);
++ if (start_beacon)
++ return hostapd_start_beacon(hapd);
+
+ hostapd_ubus_add_bss(hapd);
+
+@@ -2214,7 +2252,7 @@ static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface,
+ hapd = iface->bss[j];
+ if (j)
+ os_memcpy(hapd->own_addr, prev_addr, ETH_ALEN);
+- if (hostapd_setup_bss(hapd, j == 0)) {
++ if (hostapd_setup_bss(hapd, j == 0, !iface->conf->mbssid)) {
+ for (;;) {
+ hapd = iface->bss[j];
+ hostapd_bss_deinit_no_free(hapd);
+@@ -2228,6 +2266,24 @@ static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface,
+ if (is_zero_ether_addr(hapd->conf->bssid))
+ prev_addr = hapd->own_addr;
+ }
++
++ if (hapd->iconf->mbssid) {
++ for (j = 0; j < iface->num_bss; j++) {
++ hapd = iface->bss[j];
++ if (hostapd_start_beacon(hapd)) {
++ for (;;) {
++ hapd = iface->bss[j];
++ hostapd_bss_deinit_no_free(hapd);
++ hostapd_free_hapd_data(hapd);
++ if (j == 0)
++ break;
++ j--;
++ }
++ goto fail;
++ }
++ }
++ }
++
+ hapd = iface->bss[0];
+
+ hostapd_tx_queue_params(iface);
+@@ -3130,7 +3186,7 @@ int hostapd_add_iface(struct hapd_interfaces *interfaces, char *buf)
+
+ if (start_ctrl_iface_bss(hapd) < 0 ||
+ (hapd_iface->state == HAPD_IFACE_ENABLED &&
+- hostapd_setup_bss(hapd, -1))) {
++ hostapd_setup_bss(hapd, -1, true))) {
+ hostapd_cleanup(hapd);
+ hapd_iface->bss[hapd_iface->num_bss - 1] = NULL;
+ hapd_iface->conf->num_bss--;
+diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
+index 56d96a5..093c28a 100644
+--- a/src/ap/hostapd.h
++++ b/src/ap/hostapd.h
+@@ -660,6 +660,11 @@ struct hostapd_iface {
+ /* Previous WMM element information */
+ struct hostapd_wmm_ac_params prev_wmm[WMM_AC_NUM];
+
++ /* Maximum number of interfaces supported for MBSSID advertisements */
++ u8 mbssid_max_interfaces;
++ /* Maximum profile periodicity for enhanced MBSSID advertisements */
++ u8 ema_max_periodicity;
++
+ int (*enable_iface_cb)(struct hostapd_iface *iface);
+ int (*disable_iface_cb)(struct hostapd_iface *iface);
+ };
+@@ -762,5 +767,7 @@ void fst_hostapd_fill_iface_obj(struct hostapd_data *hapd,
+ #endif /* CONFIG_FST */
+
+ int hostapd_set_acl(struct hostapd_data *hapd);
++struct hostapd_data * hostapd_mbssid_get_tx_bss(struct hostapd_data *hapd);
++int hostapd_mbssid_get_bss_index(struct hostapd_data *hapd);
+
+ #endif /* HOSTAPD_H */
+diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
+index 098793e..30bfa30 100644
+--- a/src/ap/ieee802_11.c
++++ b/src/ap/ieee802_11.c
+@@ -165,6 +165,7 @@ u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid)
+ int i, num, count;
+ int h2e_required;
+
++ hapd->conf->xrates_supported = 0;
+ if (hapd->iface->current_rates == NULL)
+ return eid;
+
+@@ -214,6 +215,7 @@ u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid)
+ *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_SAE_H2E_ONLY;
+ }
+
++ hapd->conf->xrates_supported = 1;
+ return pos;
+ }
+
+@@ -3979,6 +3981,23 @@ static void handle_auth(struct hostapd_data *hapd,
+ }
+
+
++static u8 hostapd_max_bssid_indicator(struct hostapd_data *hapd)
++{
++ size_t num_bss_nontx;
++ u8 max_bssid_ind = 0;
++
++ if (!hapd->iconf->mbssid || hapd->iface->num_bss <= 1)
++ return 0;
++
++ num_bss_nontx = hapd->iface->num_bss - 1;
++ while (num_bss_nontx > 0) {
++ max_bssid_ind++;
++ num_bss_nontx >>= 1;
++ }
++ return max_bssid_ind;
++}
++
++
+ int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta)
+ {
+ int i, j = 32, aid;
+@@ -4004,7 +4023,10 @@ int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta)
+ }
+ if (j == 32)
+ return -1;
+- aid = i * 32 + j + 1;
++ aid = i * 32 + j;
++
++ aid += (1 << hostapd_max_bssid_indicator(hapd));
++
+ if (aid > 2007)
+ return -1;
+
+@@ -7579,4 +7601,256 @@ u8 * hostapd_eid_rnr(struct hostapd_data *hapd, u8 *eid, u32 type)
+ return eid;
+ }
+
++
++static size_t hostapd_eid_mbssid_elem_len(struct hostapd_data *hapd,
++ u32 frame_type, size_t *bss_index,
++ const u8 *known_bss,
++ size_t known_bss_len)
++{
++ struct hostapd_data *tx_bss = hostapd_mbssid_get_tx_bss(hapd);
++ size_t len = 3, i;
++
++ for (i = *bss_index; i < hapd->iface->num_bss; i++) {
++ struct hostapd_data *bss = hapd->iface->bss[i];
++ const u8 *auth, *rsn = NULL, *rsnx = NULL;
++ size_t nontx_profile_len, auth_len;
++ u8 ie_count = 0;
++
++ if (known_bss && (known_bss_len > (i / 8))) {
++ known_bss = &known_bss[i / 8];
++ if (*known_bss & (u8)(BIT(i % 8)))
++ continue;
++ }
++
++ if (!bss || !bss->conf || !bss->started)
++ continue;
++
++ /*
++ * Sublement ID: 1 byte
++ * Length: 1 byte
++ * Nontransmitted capabilities: 4 bytes
++ * SSID element: 2 + variable
++ * Multiple BSSID Index Element: 3 bytes (+2 bytes in beacons)
++ * Fixed length = 1 + 1 + 4 + 2 + 3 = 11
++ */
++ nontx_profile_len = 11 + bss->conf->ssid.ssid_len;
++
++ if (frame_type == WLAN_FC_STYPE_BEACON)
++ nontx_profile_len += 2;
++
++ auth = wpa_auth_get_wpa_ie(bss->wpa_auth, &auth_len);
++ if (auth) {
++ rsn = get_ie(auth, auth_len, WLAN_EID_RSN);
++ if (rsn)
++ nontx_profile_len += (2 + rsn[1]);
++
++ rsnx = get_ie(auth, auth_len, WLAN_EID_RSNX);
++ if (rsnx)
++ nontx_profile_len += (2 + rsnx[1]);
++ }
++ if (!rsn && hostapd_wpa_ie(tx_bss, WLAN_EID_RSN))
++ ie_count++;
++ if (!rsnx && hostapd_wpa_ie(tx_bss, WLAN_EID_RSNX))
++ ie_count++;
++ if (bss->conf->xrates_supported)
++ nontx_profile_len += 8;
++ else if (hapd->conf->xrates_supported)
++ ie_count++;
++ if (ie_count)
++ nontx_profile_len += (4 + ie_count);
++
++ if ((len + nontx_profile_len) > 255)
++ goto mbssid_too_big;
++
++ len += nontx_profile_len;
++ }
++
++mbssid_too_big:
++ *bss_index = i;
++ return len;
++}
++
++
++size_t hostapd_eid_mbssid_len(struct hostapd_data *hapd, u32 frame_type,
++ u8 *elem_count, const u8 *known_bss,
++ size_t known_bss_len)
++{
++ size_t len = 0, bss_index = 1;
++
++ if (!hapd->iconf->mbssid || hapd->iface->num_bss <= 1 ||
++ (frame_type != WLAN_FC_STYPE_BEACON &&
++ frame_type != WLAN_FC_STYPE_PROBE_RESP))
++ return 0;
++
++ if (frame_type == WLAN_FC_STYPE_BEACON) {
++ if (!elem_count) {
++ wpa_printf(MSG_ERROR,
++ "MBSSID: Insufficient data for beacons");
++ return 0;
++ }
++ *elem_count = 0;
++ }
++
++ while (bss_index < hapd->iface->num_bss) {
++ len += hostapd_eid_mbssid_elem_len(hapd, frame_type,
++ &bss_index, known_bss,
++ known_bss_len);
++
++ if (frame_type == WLAN_FC_STYPE_BEACON)
++ *elem_count += 1;
++ }
++ return len;
++}
++
++
++static u8 * hostapd_eid_mbssid_elem(struct hostapd_data *hapd, u8 *eid, u8 *end,
++ u32 frame_type, u8 max_bssid_indicator,
++ size_t *bss_index, u8 elem_count,
++ const u8 *known_bss, size_t known_bss_len)
++{
++ struct hostapd_data *tx_bss = hostapd_mbssid_get_tx_bss(hapd);
++ size_t i;
++ u8 *eid_len_offset, *max_bssid_indicator_offset;
++
++ *eid++ = WLAN_EID_MULTIPLE_BSSID;
++ eid_len_offset = eid++;
++ max_bssid_indicator_offset = eid++;
++
++ for (i = *bss_index; i < hapd->iface->num_bss; i++) {
++ struct hostapd_data *bss = hapd->iface->bss[i];
++ struct hostapd_bss_config *conf;
++ u8 *eid_len_pos, *nontx_bss_start = eid;
++ const u8 *auth, *rsn = NULL, *rsnx = NULL;
++ u8 ie_count = 0, non_inherit_ie[3];
++ size_t auth_len = 0;
++ u16 capab_info;
++
++ if (known_bss && (known_bss_len > (i / 8))) {
++ known_bss = &known_bss[i / 8];
++ if (*known_bss & (u8)(BIT(i % 8)))
++ continue;
++ }
++
++ if (!bss || !bss->conf || !bss->started)
++ continue;
++ conf = bss->conf;
++
++ *eid++ = WLAN_EID_SUBELEMENT_NONTRANSMITTED_BSSID_PROFILE;
++ eid_len_pos = eid++;
++
++ *eid++ = WLAN_EID_NONTRANSMITTED_BSSID_CAPA;
++ *eid++ = sizeof(capab_info);
++ capab_info = host_to_le16(hostapd_own_capab_info(bss));
++ os_memcpy(eid, (const void *)&capab_info, sizeof(capab_info));
++ eid += sizeof(capab_info);
++
++ *eid++ = WLAN_EID_SSID;
++ *eid++ = conf->ssid.ssid_len;
++ os_memcpy(eid, conf->ssid.ssid, conf->ssid.ssid_len);
++ eid += conf->ssid.ssid_len;
++
++ *eid++ = WLAN_EID_MULTIPLE_BSSID_INDEX;
++ if (frame_type == WLAN_FC_STYPE_BEACON) {
++ *eid++ = 3;
++ *eid++ = i;
++ if (hapd->iconf->mbssid == ENHANCED_MBSSID_ENABLED &&
++ (conf->dtim_period % elem_count))
++ conf->dtim_period = elem_count;
++ *eid++ = conf->dtim_period;
++ *eid++ = 0xFF;
++ } else {
++ *eid++ = 1;
++ *eid++ = i;
++ }
++
++ auth = wpa_auth_get_wpa_ie(bss->wpa_auth, &auth_len);
++ if (auth) {
++ rsn = get_ie(auth, auth_len, WLAN_EID_RSN);
++ if (rsn) {
++ os_memcpy(eid, rsn, 2 + rsn[1]);
++ eid += (2 + rsn[1]);
++ }
++
++ rsnx = get_ie(auth, auth_len, WLAN_EID_RSNX);
++ if (rsnx) {
++ os_memcpy(eid, rsnx, 2 + rsnx[1]);
++ eid += (2 + rsnx[1]);
++ }
++ }
++ if (!rsn && hostapd_wpa_ie(tx_bss, WLAN_EID_RSN)) {
++ non_inherit_ie[ie_count] = WLAN_EID_RSN;
++ ie_count++;
++ }
++ if (!rsnx && hostapd_wpa_ie(tx_bss, WLAN_EID_RSNX)) {
++ non_inherit_ie[ie_count] = WLAN_EID_RSNX;
++ ie_count++;
++ }
++ if (hapd->conf->xrates_supported &&
++ !bss->conf->xrates_supported) {
++ non_inherit_ie[ie_count] = WLAN_EID_EXT_SUPP_RATES;
++ ie_count++;
++ }
++ if (ie_count) {
++ *eid++ = WLAN_EID_EXTENSION;
++ *eid++ = 2 + ie_count;
++ *eid++ = WLAN_EID_EXT_NON_INHERITANCE;
++ *eid++ = ie_count;
++ os_memcpy(eid, non_inherit_ie, ie_count);
++ eid += ie_count;
++ }
++
++ *eid_len_pos = (eid - eid_len_pos) - 1;
++
++ if (((eid - eid_len_offset) - 1) > 255) {
++ eid = nontx_bss_start;
++ goto mbssid_too_big;
++ }
++ }
++
++mbssid_too_big:
++ *bss_index = i;
++ *max_bssid_indicator_offset = max_bssid_indicator;
++ if (*max_bssid_indicator_offset < 1)
++ *max_bssid_indicator_offset = 1;
++ *eid_len_offset = (eid - eid_len_offset) - 1;
++ return eid;
++}
++
++
++u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end,
++ u32 frame_type, u8 elem_count, u8 **elem_offset,
++ const u8 *known_bss, size_t known_bss_len)
++{
++ size_t bss_index = 1;
++ u8 elem_index = 0;
++
++ if (!hapd->iconf->mbssid || hapd->iface->num_bss <= 1 ||
++ (frame_type != WLAN_FC_STYPE_BEACON &&
++ frame_type != WLAN_FC_STYPE_PROBE_RESP))
++ return eid;
++
++ if (frame_type == WLAN_FC_STYPE_BEACON && !elem_offset) {
++ wpa_printf(MSG_ERROR, "MBSSID: Insufficient data for beacons");
++ return eid;
++ }
++
++ while (bss_index < hapd->iface->num_bss) {
++ if (frame_type == WLAN_FC_STYPE_BEACON) {
++ if (elem_index == elem_count) {
++ wpa_printf(MSG_WARNING,
++ "MBSSID: More number of elements than provided array");
++ break;
++ }
++
++ elem_offset[elem_index] = eid;
++ elem_index = elem_index + 1;
++ }
++ eid = hostapd_eid_mbssid_elem(hapd, eid, end, frame_type,
++ hostapd_max_bssid_indicator(hapd),
++ &bss_index, elem_count,
++ known_bss, known_bss_len);
++ }
++ return eid;
++}
++
+ #endif /* CONFIG_NATIVE_WINDOWS */
+diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h
+index fa1f47b..bb454bb 100644
+--- a/src/ap/ieee802_11.h
++++ b/src/ap/ieee802_11.h
+@@ -214,5 +214,10 @@ u16 copy_sta_eht_capab(struct hostapd_data *hapd, struct sta_info *sta,
+ enum ieee80211_op_mode opmode,
+ const u8 *he_capab, size_t he_capab_len,
+ const u8 *eht_capab, size_t eht_capab_len);
+-
++size_t hostapd_eid_mbssid_len(struct hostapd_data *hapd, u32 frame_type,
++ u8 *elem_count, const u8 *known_bss,
++ size_t known_bss_len);
++u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end,
++ u32 frame_type, u8 elem_count, u8 **elem_offset,
++ const u8 *known_bss, size_t known_bss_len);
+ #endif /* IEEE802_11_H */
+diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c
+index 4f85d78..7f5b475 100644
+--- a/src/ap/ieee802_11_shared.c
++++ b/src/ap/ieee802_11_shared.c
+@@ -364,6 +364,8 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx)
+ *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
+ if (hapd->conf->bss_transition)
+ *pos |= 0x08; /* Bit 19 - BSS Transition */
++ if (hapd->iconf->mbssid)
++ *pos |= 0x40; /* Bit 22 - Multiple BSSID */
+ break;
+ case 3: /* Bits 24-31 */
+ #ifdef CONFIG_WNM_AP
+@@ -436,6 +438,8 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx)
+ (hapd->iface->drv_flags &
+ WPA_DRIVER_FLAGS_BEACON_PROTECTION))
+ *pos |= 0x10; /* Bit 84 - Beacon Protection Enabled */
++ if (hapd->iconf->mbssid == ENHANCED_MBSSID_ENABLED)
++ *pos |= 0x08; /* Bit 83 - Enhanced multiple BSSID */
+ break;
+ case 11: /* Bits 88-95 */
+ #ifdef CONFIG_SAE_PK
+@@ -471,6 +475,13 @@ u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid)
+ *pos &= ~hapd->conf->ext_capa_mask[i];
+ *pos |= hapd->conf->ext_capa[i];
+ }
++
++ /* Clear bits 83 and 22 if EMA and MBSSID are not enabled
++ * otherwise association fails with some clients */
++ if (i == 10 && hapd->iconf->mbssid < ENHANCED_MBSSID_ENABLED)
++ *pos &= ~0x08;
++ if (i == 2 && !hapd->iconf->mbssid)
++ *pos &= ~0x40;
+ }
+
+ while (len > 0 && eid[1 + len] == 0) {
+diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c
+index c8ee90c..2fab7c3 100644
+--- a/src/common/ieee802_11_common.c
++++ b/src/common/ieee802_11_common.c
+@@ -315,6 +315,10 @@ static int ieee802_11_parse_extension(const u8 *pos, size_t elen,
+ elems->eht_operation = pos;
+ elems->eht_operation_len = elen;
+ break;
++ case WLAN_EID_EXT_KNOWN_BSSID:
++ elems->mbssid_known_bss = pos;
++ elems->mbssid_known_bss_len = elen;
++ break;
+ default:
+ if (show_errors) {
+ wpa_printf(MSG_MSGDUMP,
+diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h
+index 94e1d7b..1e4e27d 100644
+--- a/src/common/ieee802_11_common.h
++++ b/src/common/ieee802_11_common.h
+@@ -119,6 +119,7 @@ struct ieee802_11_elems {
+ const u8 *pasn_params;
+ const u8 *eht_capabilities;
+ const u8 *eht_operation;
++ const u8 *mbssid_known_bss;
+
+ u8 ssid_len;
+ u8 supp_rates_len;
+@@ -176,6 +177,8 @@ struct ieee802_11_elems {
+ u8 eht_capabilities_len;
+ u8 eht_operation_len;
+
++ u8 mbssid_known_bss_len;
++
+ struct mb_ies_info mb_ies;
+ struct frag_ies_info frag_ies;
+ };
+diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
+index 62088bd..0bbbca9 100644
+--- a/src/common/ieee802_11_defs.h
++++ b/src/common/ieee802_11_defs.h
+@@ -481,6 +481,9 @@
+ #define WLAN_EID_EXT_SPATIAL_REUSE 39
+ #define WLAN_EID_EXT_COLOR_CHANGE_ANNOUNCEMENT 42
+ #define WLAN_EID_EXT_OCV_OCI 54
++#define WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION 55
++#define WLAN_EID_EXT_NON_INHERITANCE 56
++#define WLAN_EID_EXT_KNOWN_BSSID 57
+ #define WLAN_EID_EXT_SHORT_SSID_LIST 58
+ #define WLAN_EID_EXT_HE_6GHZ_BAND_CAP 59
+ #define WLAN_EID_EXT_EDMG_CAPABILITIES 61
+@@ -497,6 +500,8 @@
+ #define WLAN_EID_EXT_MULTI_LINK_TRAFFIC_INDICATION 110
+ #define WLAN_EID_EXT_AKM_SUITE_SELECTOR 114
+
++#define WLAN_EID_SUBELEMENT_NONTRANSMITTED_BSSID_PROFILE 0
++
+ /* Extended Capabilities field */
+ #define WLAN_EXT_CAPAB_20_40_COEX 0
+ #define WLAN_EXT_CAPAB_GLK 1
+diff --git a/src/drivers/driver.h b/src/drivers/driver.h
+index 82daef0..36f465c 100644
+--- a/src/drivers/driver.h
++++ b/src/drivers/driver.h
+@@ -1633,6 +1633,43 @@ struct wpa_driver_ap_params {
+ * ibf_enable=<val>
+ */
+ u8 ibf_enable;
++
++ /**
++ * mbssid_tx_iface - Transmitting interface of the MBSSID set
++ */
++ const char *mbssid_tx_iface;
++
++ /**
++ * mbssid_index - The index of this BSS in the MBSSID set
++ */
++ unsigned int mbssid_index;
++
++ /**
++ * mbssid_elem - Buffer containing all MBSSID elements
++ */
++ u8 *mbssid_elem;
++
++ /**
++ * mbssid_elem_len - Total length of all MBSSID elements
++ */
++ size_t mbssid_elem_len;
++
++ /**
++ * mbssid_elem_count - The number of MBSSID elements
++ */
++ u8 mbssid_elem_count;
++
++ /**
++ * mbssid_elem_offset - Offsets to elements in mbssid_elem.
++ * Kernel will use these offsets to generate multiple BSSID beacons.
++ */
++ u8 **mbssid_elem_offset;
++
++ /**
++ * ema - Enhanced MBSSID advertisements support.
++ */
++ bool ema;
++
+ };
+
+ struct wpa_driver_mesh_bss_params {
+@@ -2197,6 +2234,11 @@ struct wpa_driver_capa {
+
+ /* Maximum number of supported CSA counters */
+ u16 max_csa_counters;
++
++ /* Maximum number of interfaces supported for MBSSID advertisements */
++ u8 mbssid_max_interfaces;
++ /* Maximum profile periodicity for enhanced MBSSID advertisements */
++ u8 ema_max_periodicity;
+ };
+
+
+diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
+index 6c65901..3753409 100644
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -4540,6 +4540,55 @@ static int nl80211_unsol_bcast_probe_resp(struct i802_bss *bss,
+ nla_nest_end(msg, attr);
+ return 0;
+ }
++
++
++static int nl80211_mbssid(struct nl_msg *msg,
++ struct wpa_driver_ap_params *params)
++{
++ struct nlattr *config, *elems;
++ int ifidx;
++
++ if (!params->mbssid_tx_iface)
++ return 0;
++
++ config = nla_nest_start(msg, NL80211_ATTR_MBSSID_CONFIG);
++ if (!config)
++ return -1;
++
++ nla_put_u8(msg, NL80211_MBSSID_CONFIG_ATTR_INDEX, params->mbssid_index);
++ if (params->mbssid_tx_iface) {
++ ifidx = if_nametoindex(params->mbssid_tx_iface);
++ if (ifidx <= 0)
++ return -1;
++ nla_put_u32(msg,
++ NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX,
++ ifidx);
++ }
++
++ if (params->ema)
++ nla_put_flag(msg, NL80211_MBSSID_CONFIG_ATTR_EMA);
++
++ nla_nest_end(msg, config);
++
++ if (params->mbssid_elem_count && params->mbssid_elem_len &&
++ params->mbssid_elem_offset && *params->mbssid_elem_offset) {
++ u8 i, **offs = params->mbssid_elem_offset;
++
++ elems = nla_nest_start(msg, NL80211_ATTR_MBSSID_ELEMS);
++ if (!elems)
++ return -1;
++
++ for (i = 0; i < params->mbssid_elem_count - 1; i++)
++ nla_put(msg, i + 1, offs[i + 1] - offs[i], offs[i]);
++
++ nla_put(msg, i + 1,
++ *offs + params->mbssid_elem_len - offs[i],
++ offs[i]);
++
++ nla_nest_end(msg, elems);
++ }
++ return 0;
++}
+ #endif /* CONFIG_IEEE80211AX */
+
+
+@@ -4838,6 +4887,9 @@ static int wpa_driver_nl80211_set_ap(void *priv,
+ if (params->unsol_bcast_probe_resp_interval &&
+ nl80211_unsol_bcast_probe_resp(bss, msg, params) < 0)
+ goto fail;
++
++ if (nl80211_mbssid(msg, params) < 0)
++ goto fail;
+ #endif /* CONFIG_IEEE80211AX */
+
+ #ifdef CONFIG_SAE
+diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
+index 06a52db..d8078bc 100644
+--- a/src/drivers/driver_nl80211_capa.c
++++ b/src/drivers/driver_nl80211_capa.c
+@@ -857,6 +857,30 @@ err:
+ }
+
+
++static void wiphy_info_mbssid(struct wpa_driver_capa *cap, struct nlattr *attr)
++{
++ struct nlattr *config[NL80211_MBSSID_CONFIG_ATTR_MAX + 1];
++
++ if (nla_parse_nested(config, NL80211_MBSSID_CONFIG_ATTR_MAX, attr,
++ NULL))
++ return;
++
++ if (!config[NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES])
++ return;
++
++ cap->mbssid_max_interfaces =
++ nla_get_u8(config[NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES]);
++
++ if (config[NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY])
++ cap->ema_max_periodicity =
++ nla_get_u8(config[NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY]);
++
++ wpa_printf(MSG_DEBUG,
++ "multiple_bssid: max interfaces %u, max profile periodicity %u\n",
++ cap->mbssid_max_interfaces, cap->ema_max_periodicity);
++}
++
++
+ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
+ {
+ struct nlattr *tb[NL80211_ATTR_MAX + 1];
+@@ -1106,6 +1130,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
+ if (tb[NL80211_ATTR_WIPHY_SELF_MANAGED_REG])
+ capa->flags |= WPA_DRIVER_FLAGS_SELF_MANAGED_REGULATORY;
+
++ if (tb[NL80211_ATTR_MBSSID_CONFIG])
++ wiphy_info_mbssid(capa, tb[NL80211_ATTR_MBSSID_CONFIG]);
++
+ return NL_SKIP;
+ }
+
+--
+2.18.0
+
diff --git a/recipes-wifi/wpa-supplicant/files/patches-2.10.3/patches.inc b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/patches.inc
index 4a42f53..5e6bf88 100644
--- a/recipes-wifi/wpa-supplicant/files/patches-2.10.3/patches.inc
+++ b/recipes-wifi/wpa-supplicant/files/patches-2.10.3/patches.inc
@@ -71,11 +71,18 @@
file://mtk-0007-hostapd-mtk-Add-three-wire-PTA-ctrl-hostapd-vendor-c.patch \
file://mtk-0008-hostapd-mtk-Add-hostapd-iBF-control.patch \
file://mtk-0009-hostapd-mtk-Do-not-include-HE-capab-IE-if-associated.patch \
- file://mtk-0010-hostapd-mtk-Add-DFS-and-ZWDFS-support.patch \
- file://mtk-0011-hostapd-mtk-Add-amsdu-set-get-ctrl.patch \
- file://mtk-0012-hostapd-mtk-Add-he_ldpc-configuration.patch \
- file://mtk-0013-hostapd-mtk-Add-the-broadcast-destination-address-of.patch \
- file://mtk-0014-hostapd-mtk-Add-vendor-command-attribute-for-RTS-BW-.patch \
- file://mtk-0015-hostapd-mtk-6G-band-does-not-require-DFS.patch \
+ file://mtk-0010-hostapd-mtk-Add-DFS-detection-mode.patch \
+ file://mtk-0011-hostapd-mtk-Add-DFS-offchan-channel-switch.patch \
+ file://mtk-0012-hostapd-mtk-Add-amsdu-set-get-ctrl.patch \
+ file://mtk-0013-hostapd-mtk-Add-he_ldpc-configuration.patch \
+ file://mtk-0014-hostapd-mtk-Add-the-broadcast-destination-address-of.patch \
+ file://mtk-0015-hostapd-mtk-Add-vendor-command-attribute-for-RTS-BW-.patch \
+ file://mtk-0016-hostapd-mtk-6G-band-does-not-require-DFS.patch \
+ file://mtk-0016-hostapd-mtk-Add-available-color-bitmap.patch \
+ file://mtk-0017-hostapd-mtk-Fix-sending-wrong-VHT-operation-IE-in-CS.patch \
+ file://mtk-0018-hostapd-mtk-Add-sta-assisted-DFS-state-update-mechan.patch \
+ file://mtk-0019-hostapd-mtk-Fix-auto-ht-issue-when-switching-to-DFS-.patch \
+ file://mtk-0020-hostapd-mtk-Mark-DFS-channel-as-available-for-CSA.patch \
+ file://mtk-0020-hostapd-mtk-add-11v_mbss-and-ema-support.patch \
file://mtk-0100-hostapd-mtk-update-eht-operation-elem.patch \
"
diff --git a/recipes-wifi/wpa-supplicant/files/patches/mtk-0010-hostapd-mtk-Add-DFS-and-ZWDFS-support.patch b/recipes-wifi/wpa-supplicant/files/patches/mtk-0010-hostapd-mtk-Add-DFS-and-ZWDFS-support.patch
deleted file mode 100644
index 3237aa3..0000000
--- a/recipes-wifi/wpa-supplicant/files/patches/mtk-0010-hostapd-mtk-Add-DFS-and-ZWDFS-support.patch
+++ /dev/null
@@ -1,376 +0,0 @@
-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_mu(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
-
diff --git a/recipes-wifi/wpa-supplicant/files/patches/mtk-0010-hostapd-mtk-Add-DFS-detection-mode.patch b/recipes-wifi/wpa-supplicant/files/patches/mtk-0010-hostapd-mtk-Add-DFS-detection-mode.patch
new file mode 100644
index 0000000..7ec986a
--- /dev/null
+++ b/recipes-wifi/wpa-supplicant/files/patches/mtk-0010-hostapd-mtk-Add-DFS-detection-mode.patch
@@ -0,0 +1,136 @@
+From 6828156c206701f5a0e5d30afcc514f452ce0ada Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Mon, 20 Feb 2023 14:55:49 +0800
+Subject: [PATCH 10/16] hostapd: mtk: Add DFS detection mode
+
+Add DFS detection mode for testing radar detection rate.
+If DFS detection mode is on, AP will not switch channels when receiving
+a radar signal.
+This detection mode also supports background chain.
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ hostapd/config_file.c | 4 ++++
+ hostapd/ctrl_iface.c | 23 +++++++++++++++++++++++
+ src/ap/ap_config.h | 13 +++++++++++++
+ src/ap/dfs.c | 10 ++++++++++
+ 4 files changed, 50 insertions(+)
+
+diff --git a/hostapd/config_file.c b/hostapd/config_file.c
+index 63c9d40..cd15349 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 c881d37..0b4c234 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -3522,6 +3522,26 @@ 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_receive_process(struct hostapd_data *hapd,
+ char *buf, char *reply,
+ int reply_size,
+@@ -4081,6 +4101,9 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
+ reply_len = hostapd_ctrl_iface_get_mu(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 {
+ 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 a9e3d2a..77f6169 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 b5d105d..5cb7799 100644
+--- a/src/ap/dfs.c
++++ b/src/ap/dfs.c
+@@ -1317,6 +1317,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 +1370,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;
+--
+2.18.0
+
diff --git a/recipes-wifi/wpa-supplicant/files/patches/mtk-0011-hostapd-mtk-Add-DFS-offchan-channel-switch.patch b/recipes-wifi/wpa-supplicant/files/patches/mtk-0011-hostapd-mtk-Add-DFS-offchan-channel-switch.patch
new file mode 100644
index 0000000..1d8baf8
--- /dev/null
+++ b/recipes-wifi/wpa-supplicant/files/patches/mtk-0011-hostapd-mtk-Add-DFS-offchan-channel-switch.patch
@@ -0,0 +1,192 @@
+From 88dd3df28e3736af4cca0daf4f7d19ab888ea6c4 Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Mon, 20 Feb 2023 14:56:55 +0800
+Subject: [PATCH 11/16] hostapd: mtk: Add DFS offchan channel switch
+
+Add DFS background chain channel switch command for testing purpose.
+This feature is implemented via hostapd_cli command.
+Command format:
+hostapd_cli -i <interface> raw SET_OFFCHAN_CTRL chan=<dfs_channel>
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ hostapd/ctrl_iface.c | 72 ++++++++++++++++++++++++++++++++++++++++++++
+ src/ap/dfs.c | 25 ++++++---------
+ src/ap/dfs.h | 15 +++++++++
+ 3 files changed, 96 insertions(+), 16 deletions(-)
+
+diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
+index 0b4c234..6ea1573 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -3542,6 +3542,76 @@ hostapd_ctrl_iface_set_dfs_detect_mode(struct hostapd_data *hapd, char *value,
+ }
+
+
++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,
+@@ -4104,6 +4174,8 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
+ } 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/dfs.c b/src/ap/dfs.c
+index 5cb7799..1c3f678 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;
+diff --git a/src/ap/dfs.h b/src/ap/dfs.h
+index 606c1b3..c2556d2 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 */
+--
+2.18.0
+
diff --git a/recipes-wifi/wpa-supplicant/files/patches/mtk-0011-hostapd-mtk-Add-amsdu-set-get-ctrl.patch b/recipes-wifi/wpa-supplicant/files/patches/mtk-0011-hostapd-mtk-Add-amsdu-set-get-ctrl.patch
deleted file mode 100644
index dba90d1..0000000
--- a/recipes-wifi/wpa-supplicant/files/patches/mtk-0011-hostapd-mtk-Add-amsdu-set-get-ctrl.patch
+++ /dev/null
@@ -1,400 +0,0 @@
-From bc0722ebc1cc08be6239879fddaef37e0db2d9e0 Mon Sep 17 00:00:00 2001
-From: Evelyn Tsai <evelyn.tsai@mediatek.com>
-Date: Fri, 16 Dec 2022 03:57:11 +0800
-Subject: [PATCH 11/15] hostapd: mtk: Add amsdu set get ctrl
-
----
- hostapd/config_file.c | 9 +++
- hostapd/ctrl_iface.c | 26 +++++++
- hostapd/hostapd_cli.c | 9 +++
- src/ap/ap_config.c | 1 +
- src/ap/ap_config.h | 1 +
- src/ap/ap_drv_ops.c | 14 ++++
- src/ap/ap_drv_ops.h | 2 +
- src/ap/hostapd.c | 2 +
- src/common/mtk_vendor.h | 17 ++++-
- src/drivers/driver.h | 9 +++
- src/drivers/driver_nl80211.c | 114 ++++++++++++++++++++++++++++++
- src/drivers/driver_nl80211.h | 1 +
- src/drivers/driver_nl80211_capa.c | 3 +
- 13 files changed, 207 insertions(+), 1 deletion(-)
-
-diff --git a/hostapd/config_file.c b/hostapd/config_file.c
-index cd1534952..10ea52518 100644
---- a/hostapd/config_file.c
-+++ b/hostapd/config_file.c
-@@ -4807,6 +4807,15 @@ static int hostapd_config_fill(struct hostapd_config *conf,
- u8 en = strtol(pos, NULL, 10);
-
- conf->dfs_detect_mode = en;
-+ } else if (os_strcmp(buf, "amsdu") == 0) {
-+ int val = atoi(pos);
-+ if (val < 0 || val > 1) {
-+ wpa_printf(MSG_ERROR,
-+ "Line %d: invalid amsdu value",
-+ line);
-+ return 1;
-+ }
-+ conf->amsdu = val;
- } else {
- wpa_printf(MSG_ERROR,
- "Line %d: unknown configuration item '%s'",
-diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
-index 6ea1573b8..0ad8451aa 100644
---- a/hostapd/ctrl_iface.c
-+++ b/hostapd/ctrl_iface.c
-@@ -3612,6 +3612,30 @@ hostapd_ctrl_iface_set_offchan_ctrl(struct hostapd_data *hapd, char *cmd,
- }
-
-
-+static int
-+hostapd_ctrl_iface_get_amsdu(struct hostapd_data *hapd, char *buf,
-+ size_t buflen)
-+{
-+ u8 amsdu;
-+ int ret;
-+ char *pos, *end;
-+
-+ pos = buf;
-+ end = buf + buflen;
-+
-+ if (hostapd_drv_amsdu_dump(hapd, &amsdu) == 0) {
-+ hapd->iconf->amsdu = amsdu;
-+ ret = os_snprintf(pos, end - pos, "[hostapd_cli] AMSDU: %u\n",
-+ hapd->iconf->amsdu);
-+ }
-+
-+ if (os_snprintf_error(end - pos, ret))
-+ return 0;
-+
-+ return ret;
-+}
-+
-+
- static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
- char *buf, char *reply,
- int reply_size,
-@@ -4176,6 +4200,8 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
- 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 if (os_strncmp(buf, "GET_AMSDU", 9) == 0) {
-+ reply_len = hostapd_ctrl_iface_get_amsdu(hapd, reply, reply_size);
- } else {
- os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
- reply_len = 16;
-diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
-index c2a123a8c..30b3392e6 100644
---- a/hostapd/hostapd_cli.c
-+++ b/hostapd/hostapd_cli.c
-@@ -1593,6 +1593,13 @@ static int hostapd_cli_cmd_get_ibf(struct wpa_ctrl *ctrl, int argc,
- }
-
-
-+static int hostapd_cli_cmd_get_amsdu(struct wpa_ctrl *ctrl, int argc,
-+ char *argv[])
-+{
-+ return hostapd_cli_cmd(ctrl, "GET_AMSDU", 0, NULL, NULL);
-+}
-+
-+
- struct hostapd_cli_cmd {
- const char *cmd;
- int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
-@@ -1796,6 +1803,8 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
- "<tx type(0/1/2)> <interval> = runtime set inband discovery" },
- { "get_ibf", hostapd_cli_cmd_get_ibf, NULL,
- " = show iBF state (enabled/disabled)"},
-+ { "get_amsdu", hostapd_cli_cmd_get_amsdu, NULL,
-+ " = show AMSDU state"},
- { NULL, NULL, NULL, NULL }
- };
-
-diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
-index 7a96cb8b2..85ad5e444 100644
---- a/src/ap/ap_config.c
-+++ b/src/ap/ap_config.c
-@@ -299,6 +299,7 @@ struct hostapd_config * hostapd_config_defaults(void)
- conf->edcca_compensation = EDCCA_DEFAULT_COMPENSATION;
- conf->three_wire_enable = THREE_WIRE_MODE_DISABLE;
- conf->ibf_enable = IBF_DEFAULT_ENABLE;
-+ conf->amsdu = 1;
-
- return conf;
- }
-diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
-index 77f6169d2..a9ac39619 100644
---- a/src/ap/ap_config.h
-+++ b/src/ap/ap_config.h
-@@ -1161,6 +1161,7 @@ struct hostapd_config {
- u8 three_wire_enable;
- u8 ibf_enable;
- u8 dfs_detect_mode;
-+ u8 amsdu;
- };
-
- enum three_wire_mode {
-diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
-index 60ae8253b..1a82f234c 100644
---- a/src/ap/ap_drv_ops.c
-+++ b/src/ap/ap_drv_ops.c
-@@ -1077,4 +1077,18 @@ int hostapd_drv_ibf_dump(struct hostapd_data *hapd, u8 *ibf_enable)
- if (!hapd->driver || !hapd->driver->ibf_dump)
- return 0;
- return hapd->driver->ibf_dump(hapd->drv_priv, ibf_enable);
-+}
-+
-+int hostapd_drv_amsdu_ctrl(struct hostapd_data *hapd)
-+{
-+ if (!hapd->driver || !hapd->driver->amsdu_ctrl)
-+ return 0;
-+ return hapd->driver->amsdu_ctrl(hapd->drv_priv, hapd->iconf->amsdu);
-+}
-+
-+int hostapd_drv_amsdu_dump(struct hostapd_data *hapd, u8 *amsdu)
-+{
-+ if (!hapd->driver || !hapd->driver->amsdu_dump)
-+ return 0;
-+ return hapd->driver->amsdu_dump(hapd->drv_priv, amsdu);
- }
-\ No newline at end of file
-diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
-index ab9aedcee..4406666fd 100644
---- a/src/ap/ap_drv_ops.h
-+++ b/src/ap/ap_drv_ops.h
-@@ -147,6 +147,8 @@ int hostapd_drv_mu_dump(struct hostapd_data *hapd, u8 *mu_onoff);
- int hostapd_drv_three_wire_ctrl(struct hostapd_data *hapd);
- int hostapd_drv_ibf_ctrl(struct hostapd_data *hapd);
- int hostapd_drv_ibf_dump(struct hostapd_data *hapd, u8 *ibf_enable);
-+int hostapd_drv_amsdu_ctrl(struct hostapd_data *hapd);
-+int hostapd_drv_amsdu_dump(struct hostapd_data *hapd, u8 *amsdu);
-
- #include "drivers/driver.h"
-
-diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
-index a0229c9ca..152060db4 100644
---- a/src/ap/hostapd.c
-+++ b/src/ap/hostapd.c
-@@ -2310,6 +2310,8 @@ dfs_offload:
- goto fail;
- if (hostapd_drv_ibf_ctrl(hapd) < 0)
- goto fail;
-+ if (hostapd_drv_amsdu_ctrl(hapd) < 0)
-+ goto fail;
-
- wpa_printf(MSG_DEBUG, "%s: Setup of interface done.",
- iface->bss[0]->conf->iface);
-diff --git a/src/common/mtk_vendor.h b/src/common/mtk_vendor.h
-index 4050cf886..0999ea9e2 100644
---- a/src/common/mtk_vendor.h
-+++ b/src/common/mtk_vendor.h
-@@ -167,7 +167,6 @@ enum mtk_vendor_attr_wireless_ctrl {
- MTK_VENDOR_ATTR_WIRELESS_CTRL_NUSERS_OFDMA,
- MTK_VENDOR_ATTR_WIRELESS_CTRL_BA_BUFFER_SIZE,
- MTK_VENDOR_ATTR_WIRELESS_CTRL_MIMO,
-- MTK_VENDOR_ATTR_WIRELESS_CTRL_AMPDU,
- MTK_VENDOR_ATTR_WIRELESS_CTRL_AMSDU,
- MTK_VENDOR_ATTR_WIRELESS_CTRL_CERT,
-
-@@ -177,6 +176,22 @@ enum mtk_vendor_attr_wireless_ctrl {
- NUM_MTK_VENDOR_ATTRS_WIRELESS_CTRL - 1
- };
-
-+enum mtk_vendor_attr_wireless_dump {
-+ MTK_VENDOR_ATTR_WIRELESS_DUMP_UNSPEC,
-+
-+ MTK_VENDOR_ATTR_WIRELESS_DUMP_AMSDU,
-+
-+ /* keep last */
-+ NUM_MTK_VENDOR_ATTRS_WIRELESS_DUMP,
-+ MTK_VENDOR_ATTR_WIRELESS_DUMP_MAX =
-+ NUM_MTK_VENDOR_ATTRS_WIRELESS_DUMP - 1
-+};
-+
-+static const struct nla_policy
-+wireless_dump_policy[NUM_MTK_VENDOR_ATTRS_WIRELESS_DUMP] = {
-+ [MTK_VENDOR_ATTR_WIRELESS_DUMP_AMSDU] = { .type = NLA_U8 },
-+};
-+
- enum mtk_vendor_attr_rfeature_ctrl {
- MTK_VENDOR_ATTR_RFEATURE_CTRL_UNSPEC,
-
-diff --git a/src/drivers/driver.h b/src/drivers/driver.h
-index aa23fbdb3..b07aaf3fe 100644
---- a/src/drivers/driver.h
-+++ b/src/drivers/driver.h
-@@ -4727,6 +4727,15 @@ struct wpa_driver_ops {
- *
- */
- int (*start_disabled)(void *priv);
-+
-+ /**
-+ * amsdu_ctrl - enable/disable amsdu
-+ * amsdu_dump - get current amsdu status
-+ * @priv: Private driver interface data
-+ *
-+ */
-+ int (*amsdu_ctrl)(void *priv, u8 amsdu);
-+ int (*amsdu_dump)(void *priv, u8 *amsdu);
- };
-
- /**
-diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
-index 7472542cc..6702384ef 100644
---- a/src/drivers/driver_nl80211.c
-+++ b/src/drivers/driver_nl80211.c
-@@ -12804,6 +12804,118 @@ fail:
- return ret;
- }
-
-+static int nl80211_enable_amsdu(void *priv, u8 amsdu)
-+{
-+ struct i802_bss *bss = priv;
-+ struct wpa_driver_nl80211_data *drv = bss->drv;
-+ struct nl_msg *msg;
-+ struct nlattr *data;
-+ int ret;
-+
-+ if (!drv->mtk_wireless_vendor_cmd_avail) {
-+ wpa_printf(MSG_INFO,
-+ "nl80211: Driver does not support setting ap wireless control");
-+ return 0;
-+ }
-+
-+ msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR);
-+ if (!msg)
-+ goto fail;
-+
-+ if (nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_MTK) ||
-+ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, MTK_NL80211_VENDOR_SUBCMD_WIRELESS_CTRL))
-+ goto fail;
-+
-+ data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
-+ if (!data)
-+ goto fail;
-+
-+ nla_put_u8(msg, MTK_VENDOR_ATTR_WIRELESS_CTRL_AMSDU, amsdu);
-+
-+ nla_nest_end(msg, data);
-+ ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
-+ if (ret) {
-+ wpa_printf(MSG_ERROR, "Failed to set amsdu. ret=%d (%s)", ret, strerror(-ret));
-+ }
-+
-+ return ret;
-+
-+fail:
-+ nlmsg_free(msg);
-+ return -ENOBUFS;
-+}
-+
-+static int dump_amsdu_handler(struct nl_msg *msg, void *arg)
-+{
-+ u8 *amsdu = (u8 *) arg;
-+ struct nlattr *tb[NL80211_ATTR_MAX + 1];
-+ struct nlattr *tb_vendor[MTK_VENDOR_ATTR_WIRELESS_DUMP_MAX + 1];
-+ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
-+ struct nlattr *nl_vend, *attr_amsdu;
-+
-+ nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
-+ genlmsg_attrlen(gnlh, 0), NULL);
-+
-+ nl_vend = tb[NL80211_ATTR_VENDOR_DATA];
-+ if (!nl_vend)
-+ return NL_SKIP;
-+
-+ nla_parse(tb_vendor, MTK_VENDOR_ATTR_WIRELESS_DUMP_MAX,
-+ nla_data(nl_vend), nla_len(nl_vend), NULL);
-+
-+ attr_amsdu = tb_vendor[MTK_VENDOR_ATTR_WIRELESS_DUMP_AMSDU];
-+ if (!attr_amsdu ){
-+ wpa_printf(MSG_ERROR, "nl80211: cannot find vendor attributes");
-+ return NL_SKIP;
-+ }
-+
-+ *amsdu = nla_get_u8(attr_amsdu);
-+
-+ return NL_SKIP;
-+}
-+
-+static int
-+nl80211_dump_amsdu(void *priv, u8 *amsdu)
-+{
-+ struct i802_bss *bss = priv;
-+ struct wpa_driver_nl80211_data *drv = bss->drv;
-+ struct nl_msg *msg;
-+ struct nlattr *data;
-+ int ret;
-+
-+ if (!drv->mtk_wireless_vendor_cmd_avail) {
-+ wpa_printf(MSG_INFO,
-+ "nl80211: Driver does not support ap_wireless control");
-+ return 0;
-+ }
-+
-+ msg = nl80211_drv_msg(drv, NLM_F_DUMP, NL80211_CMD_VENDOR);
-+ if (!msg)
-+ goto fail;
-+
-+ if (nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_MTK) ||
-+ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, MTK_NL80211_VENDOR_SUBCMD_WIRELESS_CTRL))
-+ goto fail;
-+
-+ data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
-+ if (!data)
-+ goto fail;
-+
-+ nla_nest_end(msg, data);
-+
-+ ret = send_and_recv_msgs(drv, msg, dump_amsdu_handler, amsdu, NULL, NULL);
-+
-+ if (ret) {
-+ wpa_printf(MSG_ERROR, "Failed to dump amsdu. ret=%d (%s)", ret, strerror(-ret));
-+ }
-+
-+ return ret;
-+
-+fail:
-+ nlmsg_free(msg);
-+ return -ENOBUFS;
-+}
-+
- const struct wpa_driver_ops wpa_driver_nl80211_ops = {
- .name = "nl80211",
- .desc = "Linux nl80211/cfg80211",
-@@ -12959,4 +13071,6 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
- .ibf_ctrl = nl80211_ibf_enable,
- .ibf_dump = nl80211_ibf_dump,
- .start_disabled = nl80211_start_disabled,
-+ .amsdu_ctrl = nl80211_enable_amsdu,
-+ .amsdu_dump = nl80211_dump_amsdu,
- };
-diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h
-index 607592ceb..e57022409 100644
---- a/src/drivers/driver_nl80211.h
-+++ b/src/drivers/driver_nl80211.h
-@@ -185,6 +185,7 @@ struct wpa_driver_nl80211_data {
- unsigned int mtk_mu_vendor_cmd_avail:1;
- unsigned int mtk_3wire_vendor_cmd_avail:1;
- unsigned int mtk_ibf_vendor_cmd_avail:1;
-+ unsigned int mtk_wireless_vendor_cmd_avail:1;
-
- u64 vendor_scan_cookie;
- u64 remain_on_chan_cookie;
-diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
-index 9ecc0ff9a..fcfa68bf7 100644
---- a/src/drivers/driver_nl80211_capa.c
-+++ b/src/drivers/driver_nl80211_capa.c
-@@ -1065,6 +1065,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
- case MTK_NL80211_VENDOR_SUBCMD_IBF_CTRL:
- drv->mtk_ibf_vendor_cmd_avail = 1;
- break;
-+ case MTK_NL80211_VENDOR_SUBCMD_WIRELESS_CTRL:
-+ drv->mtk_wireless_vendor_cmd_avail = 1;
-+ break;
- }
- }
-
---
-2.25.1
-
diff --git a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0011-hostapd-mtk-Add-amsdu-set-get-ctrl.patch b/recipes-wifi/wpa-supplicant/files/patches/mtk-0012-hostapd-mtk-Add-amsdu-set-get-ctrl.patch
similarity index 92%
copy from recipes-wifi/hostapd/files/patches-2.10.3/mtk-0011-hostapd-mtk-Add-amsdu-set-get-ctrl.patch
copy to recipes-wifi/wpa-supplicant/files/patches/mtk-0012-hostapd-mtk-Add-amsdu-set-get-ctrl.patch
index dba90d1..7db3ae2 100644
--- a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0011-hostapd-mtk-Add-amsdu-set-get-ctrl.patch
+++ b/recipes-wifi/wpa-supplicant/files/patches/mtk-0012-hostapd-mtk-Add-amsdu-set-get-ctrl.patch
@@ -1,7 +1,7 @@
-From bc0722ebc1cc08be6239879fddaef37e0db2d9e0 Mon Sep 17 00:00:00 2001
+From d0128fc60d38ce4f20f8368bdc5ea9ed19a329b7 Mon Sep 17 00:00:00 2001
From: Evelyn Tsai <evelyn.tsai@mediatek.com>
Date: Fri, 16 Dec 2022 03:57:11 +0800
-Subject: [PATCH 11/15] hostapd: mtk: Add amsdu set get ctrl
+Subject: [PATCH 12/16] hostapd: mtk: Add amsdu set get ctrl
---
hostapd/config_file.c | 9 +++
@@ -20,7 +20,7 @@
13 files changed, 207 insertions(+), 1 deletion(-)
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
-index cd1534952..10ea52518 100644
+index cd15349..10ea525 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -4807,6 +4807,15 @@ static int hostapd_config_fill(struct hostapd_config *conf,
@@ -40,7 +40,7 @@
wpa_printf(MSG_ERROR,
"Line %d: unknown configuration item '%s'",
diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
-index 6ea1573b8..0ad8451aa 100644
+index 6ea1573..0ad8451 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -3612,6 +3612,30 @@ hostapd_ctrl_iface_set_offchan_ctrl(struct hostapd_data *hapd, char *cmd,
@@ -84,7 +84,7 @@
os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
reply_len = 16;
diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
-index c2a123a8c..30b3392e6 100644
+index c2a123a..30b3392 100644
--- a/hostapd/hostapd_cli.c
+++ b/hostapd/hostapd_cli.c
@@ -1593,6 +1593,13 @@ static int hostapd_cli_cmd_get_ibf(struct wpa_ctrl *ctrl, int argc,
@@ -111,7 +111,7 @@
};
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
-index 7a96cb8b2..85ad5e444 100644
+index 7a96cb8..85ad5e4 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -299,6 +299,7 @@ struct hostapd_config * hostapd_config_defaults(void)
@@ -123,7 +123,7 @@
return conf;
}
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
-index 77f6169d2..a9ac39619 100644
+index 77f6169..a9ac396 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -1161,6 +1161,7 @@ struct hostapd_config {
@@ -135,7 +135,7 @@
enum three_wire_mode {
diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
-index 60ae8253b..1a82f234c 100644
+index 60ae825..1a82f23 100644
--- a/src/ap/ap_drv_ops.c
+++ b/src/ap/ap_drv_ops.c
@@ -1077,4 +1077,18 @@ int hostapd_drv_ibf_dump(struct hostapd_data *hapd, u8 *ibf_enable)
@@ -159,7 +159,7 @@
}
\ No newline at end of file
diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
-index ab9aedcee..4406666fd 100644
+index ab9aedc..4406666 100644
--- a/src/ap/ap_drv_ops.h
+++ b/src/ap/ap_drv_ops.h
@@ -147,6 +147,8 @@ int hostapd_drv_mu_dump(struct hostapd_data *hapd, u8 *mu_onoff);
@@ -172,10 +172,10 @@
#include "drivers/driver.h"
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
-index a0229c9ca..152060db4 100644
+index da7f7d8..a18e744 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
-@@ -2310,6 +2310,8 @@ dfs_offload:
+@@ -2308,6 +2308,8 @@ dfs_offload:
goto fail;
if (hostapd_drv_ibf_ctrl(hapd) < 0)
goto fail;
@@ -185,7 +185,7 @@
wpa_printf(MSG_DEBUG, "%s: Setup of interface done.",
iface->bss[0]->conf->iface);
diff --git a/src/common/mtk_vendor.h b/src/common/mtk_vendor.h
-index 4050cf886..0999ea9e2 100644
+index 4050cf8..0999ea9 100644
--- a/src/common/mtk_vendor.h
+++ b/src/common/mtk_vendor.h
@@ -167,7 +167,6 @@ enum mtk_vendor_attr_wireless_ctrl {
@@ -220,13 +220,13 @@
MTK_VENDOR_ATTR_RFEATURE_CTRL_UNSPEC,
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
-index aa23fbdb3..b07aaf3fe 100644
+index 71ded61..265d86d 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
-@@ -4727,6 +4727,15 @@ struct wpa_driver_ops {
+@@ -4720,6 +4720,15 @@ struct wpa_driver_ops {
*
*/
- int (*start_disabled)(void *priv);
+ int (*ibf_dump)(void *priv, u8 *ibf_enable);
+
+ /**
+ * amsdu_ctrl - enable/disable amsdu
@@ -240,11 +240,11 @@
/**
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
-index 7472542cc..6702384ef 100644
+index 5c2a291..d91b29c 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
-@@ -12804,6 +12804,118 @@ fail:
- return ret;
+@@ -12776,6 +12776,118 @@ fail:
+ return -ENOBUFS;
}
+static int nl80211_enable_amsdu(void *priv, u8 amsdu)
@@ -362,15 +362,15 @@
const struct wpa_driver_ops wpa_driver_nl80211_ops = {
.name = "nl80211",
.desc = "Linux nl80211/cfg80211",
-@@ -12959,4 +13071,6 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
+@@ -12930,4 +13042,6 @@ 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,
+ .amsdu_ctrl = nl80211_enable_amsdu,
+ .amsdu_dump = nl80211_dump_amsdu,
};
diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h
-index 607592ceb..e57022409 100644
+index 607592c..e570224 100644
--- a/src/drivers/driver_nl80211.h
+++ b/src/drivers/driver_nl80211.h
@@ -185,6 +185,7 @@ struct wpa_driver_nl80211_data {
@@ -382,7 +382,7 @@
u64 vendor_scan_cookie;
u64 remain_on_chan_cookie;
diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
-index 9ecc0ff9a..fcfa68bf7 100644
+index 9ecc0ff..fcfa68b 100644
--- a/src/drivers/driver_nl80211_capa.c
+++ b/src/drivers/driver_nl80211_capa.c
@@ -1065,6 +1065,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
@@ -396,5 +396,5 @@
}
--
-2.25.1
+2.18.0
diff --git a/recipes-wifi/wpa-supplicant/files/patches/mtk-0012-hostapd-mtk-Add-he_ldpc-configuration.patch b/recipes-wifi/wpa-supplicant/files/patches/mtk-0012-hostapd-mtk-Add-he_ldpc-configuration.patch
deleted file mode 100644
index 63101e0..0000000
--- a/recipes-wifi/wpa-supplicant/files/patches/mtk-0012-hostapd-mtk-Add-he_ldpc-configuration.patch
+++ /dev/null
@@ -1,102 +0,0 @@
-From b49ce922afa13fe8ea5d847753dfb7641b70c9a4 Mon Sep 17 00:00:00 2001
-From: MeiChia Chiu <meichia.chiu@mediatek.com>
-Date: Thu, 12 Jan 2023 15:18:19 +0800
-Subject: [PATCH 12/15] hostapd: mtk: Add he_ldpc configuration
-
----
- hostapd/config_file.c | 2 ++
- hostapd/hostapd.conf | 5 +++++
- src/ap/ap_config.c | 1 +
- src/ap/ap_config.h | 1 +
- src/ap/ieee802_11_he.c | 7 +++++++
- src/common/ieee802_11_defs.h | 3 +++
- 6 files changed, 19 insertions(+)
-
-diff --git a/hostapd/config_file.c b/hostapd/config_file.c
-index 10ea52518..4237a5cca 100644
---- a/hostapd/config_file.c
-+++ b/hostapd/config_file.c
-@@ -3508,6 +3508,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
- conf->he_phy_capab.he_su_beamformee = atoi(pos);
- } else if (os_strcmp(buf, "he_mu_beamformer") == 0) {
- conf->he_phy_capab.he_mu_beamformer = atoi(pos);
-+ } else if (os_strcmp(buf, "he_ldpc") == 0) {
-+ conf->he_phy_capab.he_ldpc = atoi(pos);
- } else if (os_strcmp(buf, "he_bss_color") == 0) {
- conf->he_op.he_bss_color = atoi(pos) & 0x3f;
- conf->he_op.he_bss_color_disabled = 0;
-diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
-index ea67aa100..e3a5eb365 100644
---- a/hostapd/hostapd.conf
-+++ b/hostapd/hostapd.conf
-@@ -830,6 +830,11 @@ wmm_ac_vo_acm=0
- # 1 = supported
- #he_mu_beamformer=1
-
-+#he_ldpc: HE LDPC support
-+# 0 = not supported
-+# 1 = supported (default)
-+#he_ldpc=1
-+
- # he_bss_color: BSS color (1-63)
- #he_bss_color=1
-
-diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
-index 85ad5e444..b283de624 100644
---- a/src/ap/ap_config.c
-+++ b/src/ap/ap_config.c
-@@ -268,6 +268,7 @@ struct hostapd_config * hostapd_config_defaults(void)
- #endif /* CONFIG_ACS */
-
- #ifdef CONFIG_IEEE80211AX
-+ conf->he_phy_capab.he_ldpc = 1;
- conf->he_op.he_rts_threshold = HE_OPERATION_RTS_THRESHOLD_MASK >>
- HE_OPERATION_RTS_THRESHOLD_OFFSET;
- /* Set default basic MCS/NSS set to single stream MCS 0-7 */
-diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
-index a9ac39619..b8b20a7aa 100644
---- a/src/ap/ap_config.h
-+++ b/src/ap/ap_config.h
-@@ -929,6 +929,7 @@ struct hostapd_bss_config {
- * struct he_phy_capabilities_info - HE PHY capabilities
- */
- struct he_phy_capabilities_info {
-+ bool he_ldpc;
- bool he_su_beamformer;
- bool he_su_beamformee;
- bool he_mu_beamformer;
-diff --git a/src/ap/ieee802_11_he.c b/src/ap/ieee802_11_he.c
-index b5b7e5d46..f27aeb196 100644
---- a/src/ap/ieee802_11_he.c
-+++ b/src/ap/ieee802_11_he.c
-@@ -138,6 +138,13 @@ u8 * hostapd_eid_he_capab(struct hostapd_data *hapd, u8 *eid,
- os_memcpy(&cap->optional[mcs_nss_size],
- mode->he_capab[opmode].ppet, ppet_size);
-
-+ if (hapd->iface->conf->he_phy_capab.he_ldpc)
-+ cap->he_phy_capab_info[HE_PHYCAP_LDPC_CODING_IN_PAYLOAD_IDX] |=
-+ HE_PHYCAP_LDPC_CODING_IN_PAYLOAD;
-+ else
-+ cap->he_phy_capab_info[HE_PHYCAP_LDPC_CODING_IN_PAYLOAD_IDX] &=
-+ ~HE_PHYCAP_LDPC_CODING_IN_PAYLOAD;
-+
- if (hapd->iface->conf->he_phy_capab.he_su_beamformer)
- cap->he_phy_capab_info[HE_PHYCAP_SU_BEAMFORMER_CAPAB_IDX] |=
- HE_PHYCAP_SU_BEAMFORMER_CAPAB;
-diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
-index 65e125e83..62088bda6 100644
---- a/src/common/ieee802_11_defs.h
-+++ b/src/common/ieee802_11_defs.h
-@@ -2298,6 +2298,9 @@ struct ieee80211_spatial_reuse {
- #define HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G ((u8) BIT(3))
- #define HE_PHYCAP_CHANNEL_WIDTH_SET_80PLUS80MHZ_IN_5G ((u8) BIT(4))
-
-+#define HE_PHYCAP_LDPC_CODING_IN_PAYLOAD_IDX 1
-+#define HE_PHYCAP_LDPC_CODING_IN_PAYLOAD ((u8) BIT(5))
-+
- #define HE_PHYCAP_SU_BEAMFORMER_CAPAB_IDX 3
- #define HE_PHYCAP_SU_BEAMFORMER_CAPAB ((u8) BIT(7))
- #define HE_PHYCAP_SU_BEAMFORMEE_CAPAB_IDX 4
---
-2.25.1
-
diff --git a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0012-hostapd-mtk-Add-he_ldpc-configuration.patch b/recipes-wifi/wpa-supplicant/files/patches/mtk-0013-hostapd-mtk-Add-he_ldpc-configuration.patch
similarity index 90%
copy from recipes-wifi/hostapd/files/patches-2.10.3/mtk-0012-hostapd-mtk-Add-he_ldpc-configuration.patch
copy to recipes-wifi/wpa-supplicant/files/patches/mtk-0013-hostapd-mtk-Add-he_ldpc-configuration.patch
index 63101e0..4df0ba6 100644
--- a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0012-hostapd-mtk-Add-he_ldpc-configuration.patch
+++ b/recipes-wifi/wpa-supplicant/files/patches/mtk-0013-hostapd-mtk-Add-he_ldpc-configuration.patch
@@ -1,7 +1,7 @@
-From b49ce922afa13fe8ea5d847753dfb7641b70c9a4 Mon Sep 17 00:00:00 2001
+From ebbf23ac8c19224b34523e8b9820e32f0789fe11 Mon Sep 17 00:00:00 2001
From: MeiChia Chiu <meichia.chiu@mediatek.com>
Date: Thu, 12 Jan 2023 15:18:19 +0800
-Subject: [PATCH 12/15] hostapd: mtk: Add he_ldpc configuration
+Subject: [PATCH 13/16] hostapd: mtk: Add he_ldpc configuration
---
hostapd/config_file.c | 2 ++
@@ -13,7 +13,7 @@
6 files changed, 19 insertions(+)
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
-index 10ea52518..4237a5cca 100644
+index 10ea525..4237a5c 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -3508,6 +3508,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
@@ -26,7 +26,7 @@
conf->he_op.he_bss_color = atoi(pos) & 0x3f;
conf->he_op.he_bss_color_disabled = 0;
diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
-index ea67aa100..e3a5eb365 100644
+index ea67aa1..e3a5eb3 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -830,6 +830,11 @@ wmm_ac_vo_acm=0
@@ -42,7 +42,7 @@
#he_bss_color=1
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
-index 85ad5e444..b283de624 100644
+index 85ad5e4..b283de6 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -268,6 +268,7 @@ struct hostapd_config * hostapd_config_defaults(void)
@@ -54,7 +54,7 @@
HE_OPERATION_RTS_THRESHOLD_OFFSET;
/* Set default basic MCS/NSS set to single stream MCS 0-7 */
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
-index a9ac39619..b8b20a7aa 100644
+index a9ac396..b8b20a7 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -929,6 +929,7 @@ struct hostapd_bss_config {
@@ -66,7 +66,7 @@
bool he_su_beamformee;
bool he_mu_beamformer;
diff --git a/src/ap/ieee802_11_he.c b/src/ap/ieee802_11_he.c
-index b5b7e5d46..f27aeb196 100644
+index b5b7e5d..f27aeb1 100644
--- a/src/ap/ieee802_11_he.c
+++ b/src/ap/ieee802_11_he.c
@@ -138,6 +138,13 @@ u8 * hostapd_eid_he_capab(struct hostapd_data *hapd, u8 *eid,
@@ -84,7 +84,7 @@
cap->he_phy_capab_info[HE_PHYCAP_SU_BEAMFORMER_CAPAB_IDX] |=
HE_PHYCAP_SU_BEAMFORMER_CAPAB;
diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
-index 65e125e83..62088bda6 100644
+index 65e125e..62088bd 100644
--- a/src/common/ieee802_11_defs.h
+++ b/src/common/ieee802_11_defs.h
@@ -2298,6 +2298,9 @@ struct ieee80211_spatial_reuse {
@@ -98,5 +98,5 @@
#define HE_PHYCAP_SU_BEAMFORMER_CAPAB ((u8) BIT(7))
#define HE_PHYCAP_SU_BEAMFORMEE_CAPAB_IDX 4
--
-2.25.1
+2.18.0
diff --git a/recipes-wifi/wpa-supplicant/files/patches/mtk-0013-hostapd-mtk-Add-the-broadcast-destination-address-of.patch b/recipes-wifi/wpa-supplicant/files/patches/mtk-0013-hostapd-mtk-Add-the-broadcast-destination-address-of.patch
deleted file mode 100644
index 1222510..0000000
--- a/recipes-wifi/wpa-supplicant/files/patches/mtk-0013-hostapd-mtk-Add-the-broadcast-destination-address-of.patch
+++ /dev/null
@@ -1,43 +0,0 @@
-From 52a1775318c9926a1dbf4f7c563e95b5be3c9bd6 Mon Sep 17 00:00:00 2001
-From: MeiChia Chiu <meichia.chiu@mediatek.com>
-Date: Tue, 17 Jan 2023 13:25:18 +0800
-Subject: [PATCH 13/15] hostapd: mtk: Add the broadcast destination address of
- Probe Response frame on 6 GHz
-
-According to IEEE 802.11ax 26.17.2.3.2,
-if a 6 GHz AP receives a Probe Request frame and responds with a Probe Response frame,
-the Address 1 field of the Probe Response frame shall be set to the broadcast address,
-unless the AP is not indicating its actual SSID in the SSID element of its Beacon frames.
-
-Without this, hostapd fill the Address 1 feild of the Probe Response frame
-with the source address from Probe Request frame on 6 GHz.
-Fix this to use broadcast address instead.
-
-Signed-off-by: MeiChia Chiu <meichia.chiu@mediatek.com>
----
- src/ap/beacon.c | 9 +++++++--
- 1 file changed, 7 insertions(+), 2 deletions(-)
-
-diff --git a/src/ap/beacon.c b/src/ap/beacon.c
-index 1a26f11ff..f3ea5c277 100644
---- a/src/ap/beacon.c
-+++ b/src/ap/beacon.c
-@@ -1156,8 +1156,13 @@ void handle_probe_req(struct hostapd_data *hapd,
- wpa_msg_ctrl(hapd->msg_ctx, MSG_INFO, RX_PROBE_REQUEST "sa=" MACSTR
- " signal=%d", MAC2STR(mgmt->sa), ssi_signal);
-
-- resp = hostapd_gen_probe_resp(hapd, mgmt, elems.p2p != NULL,
-- &resp_len, false);
-+ if (is_6ghz_op_class(hapd->iconf->op_class) &&
-+ is_broadcast_ether_addr(mgmt->da))
-+ resp = hostapd_gen_probe_resp(hapd, NULL, elems.p2p != NULL,
-+ &resp_len, true);
-+ else
-+ resp = hostapd_gen_probe_resp(hapd, mgmt, elems.p2p != NULL,
-+ &resp_len, false);
- if (resp == NULL)
- return;
-
---
-2.25.1
-
diff --git a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0013-hostapd-mtk-Add-the-broadcast-destination-address-of.patch b/recipes-wifi/wpa-supplicant/files/patches/mtk-0014-hostapd-mtk-Add-the-broadcast-destination-address-of.patch
similarity index 89%
copy from recipes-wifi/hostapd/files/patches-2.10.3/mtk-0013-hostapd-mtk-Add-the-broadcast-destination-address-of.patch
copy to recipes-wifi/wpa-supplicant/files/patches/mtk-0014-hostapd-mtk-Add-the-broadcast-destination-address-of.patch
index 1222510..f0d25c6 100644
--- a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0013-hostapd-mtk-Add-the-broadcast-destination-address-of.patch
+++ b/recipes-wifi/wpa-supplicant/files/patches/mtk-0014-hostapd-mtk-Add-the-broadcast-destination-address-of.patch
@@ -1,7 +1,7 @@
-From 52a1775318c9926a1dbf4f7c563e95b5be3c9bd6 Mon Sep 17 00:00:00 2001
+From bb5cb086162828392a04820063ad7997d8ae26d7 Mon Sep 17 00:00:00 2001
From: MeiChia Chiu <meichia.chiu@mediatek.com>
Date: Tue, 17 Jan 2023 13:25:18 +0800
-Subject: [PATCH 13/15] hostapd: mtk: Add the broadcast destination address of
+Subject: [PATCH 14/16] hostapd: mtk: Add the broadcast destination address of
Probe Response frame on 6 GHz
According to IEEE 802.11ax 26.17.2.3.2,
@@ -19,7 +19,7 @@
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/src/ap/beacon.c b/src/ap/beacon.c
-index 1a26f11ff..f3ea5c277 100644
+index 1a26f11..f3ea5c2 100644
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -1156,8 +1156,13 @@ void handle_probe_req(struct hostapd_data *hapd,
@@ -39,5 +39,5 @@
return;
--
-2.25.1
+2.18.0
diff --git a/recipes-wifi/wpa-supplicant/files/patches/mtk-0014-hostapd-mtk-Add-vendor-command-attribute-for-RTS-BW-.patch b/recipes-wifi/wpa-supplicant/files/patches/mtk-0014-hostapd-mtk-Add-vendor-command-attribute-for-RTS-BW-.patch
deleted file mode 100644
index 3689f74..0000000
--- a/recipes-wifi/wpa-supplicant/files/patches/mtk-0014-hostapd-mtk-Add-vendor-command-attribute-for-RTS-BW-.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-From 7d741c99f2e211abe70593ff6e8265633bed0d8a Mon Sep 17 00:00:00 2001
-From: "himanshu.goyal" <himanshu.goyal@mediatek.com>
-Date: Tue, 24 Jan 2023 19:06:44 +0800
-Subject: [PATCH 14/15] hostapd: mtk: Add vendor command attribute for RTS BW
- signaling.
-
-Signed-off-by: himanshu.goyal <himanshu.goyal@mediatek.com>
----
- src/common/mtk_vendor.h | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/src/common/mtk_vendor.h b/src/common/mtk_vendor.h
-index 0999ea9e2..fb12895ce 100644
---- a/src/common/mtk_vendor.h
-+++ b/src/common/mtk_vendor.h
-@@ -169,6 +169,7 @@ enum mtk_vendor_attr_wireless_ctrl {
- MTK_VENDOR_ATTR_WIRELESS_CTRL_MIMO,
- MTK_VENDOR_ATTR_WIRELESS_CTRL_AMSDU,
- MTK_VENDOR_ATTR_WIRELESS_CTRL_CERT,
-+ MTK_VENDOR_ATTR_WIRELESS_CTRL_RTS_SIGTA,
-
- /* keep last */
- NUM_MTK_VENDOR_ATTRS_WIRELESS_CTRL,
---
-2.25.1
-
diff --git a/recipes-wifi/wpa-supplicant/files/patches/mtk-0015-hostapd-mtk-6G-band-does-not-require-DFS.patch b/recipes-wifi/wpa-supplicant/files/patches/mtk-0015-hostapd-mtk-6G-band-does-not-require-DFS.patch
deleted file mode 100644
index 642c625..0000000
--- a/recipes-wifi/wpa-supplicant/files/patches/mtk-0015-hostapd-mtk-6G-band-does-not-require-DFS.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-From 619075bb430c908c61a818c45e36f1ca76020741 Mon Sep 17 00:00:00 2001
-From: Peter Chiu <chui-hao.chiu@mediatek.com>
-Date: Mon, 13 Feb 2023 11:03:53 +0800
-Subject: [PATCH 15/15] hostapd: mtk: 6G band does not require DFS
-
----
- src/ap/dfs.c | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/src/ap/dfs.c b/src/ap/dfs.c
-index 1c3f6785b..4b1e64246 100644
---- a/src/ap/dfs.c
-+++ b/src/ap/dfs.c
-@@ -1506,6 +1506,7 @@ int hostapd_is_dfs_required(struct hostapd_iface *iface)
- if ((!(iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) &&
- !iface->conf->ieee80211h) ||
- !iface->current_mode ||
-+ is_6ghz_freq(iface->freq) ||
- iface->current_mode->mode != HOSTAPD_MODE_IEEE80211A)
- return 0;
-
---
-2.25.1
-
diff --git a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0014-hostapd-mtk-Add-vendor-command-attribute-for-RTS-BW-.patch b/recipes-wifi/wpa-supplicant/files/patches/mtk-0015-hostapd-mtk-Add-vendor-command-attribute-for-RTS-BW-.patch
similarity index 79%
copy from recipes-wifi/hostapd/files/patches-2.10.3/mtk-0014-hostapd-mtk-Add-vendor-command-attribute-for-RTS-BW-.patch
copy to recipes-wifi/wpa-supplicant/files/patches/mtk-0015-hostapd-mtk-Add-vendor-command-attribute-for-RTS-BW-.patch
index 3689f74..5fcd0c5 100644
--- a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0014-hostapd-mtk-Add-vendor-command-attribute-for-RTS-BW-.patch
+++ b/recipes-wifi/wpa-supplicant/files/patches/mtk-0015-hostapd-mtk-Add-vendor-command-attribute-for-RTS-BW-.patch
@@ -1,7 +1,7 @@
-From 7d741c99f2e211abe70593ff6e8265633bed0d8a Mon Sep 17 00:00:00 2001
+From 1db373190399a907b27141c199841aeafd4643da Mon Sep 17 00:00:00 2001
From: "himanshu.goyal" <himanshu.goyal@mediatek.com>
Date: Tue, 24 Jan 2023 19:06:44 +0800
-Subject: [PATCH 14/15] hostapd: mtk: Add vendor command attribute for RTS BW
+Subject: [PATCH 15/16] hostapd: mtk: Add vendor command attribute for RTS BW
signaling.
Signed-off-by: himanshu.goyal <himanshu.goyal@mediatek.com>
@@ -10,7 +10,7 @@
1 file changed, 1 insertion(+)
diff --git a/src/common/mtk_vendor.h b/src/common/mtk_vendor.h
-index 0999ea9e2..fb12895ce 100644
+index 0999ea9..fb12895 100644
--- a/src/common/mtk_vendor.h
+++ b/src/common/mtk_vendor.h
@@ -169,6 +169,7 @@ enum mtk_vendor_attr_wireless_ctrl {
@@ -22,5 +22,5 @@
/* keep last */
NUM_MTK_VENDOR_ATTRS_WIRELESS_CTRL,
--
-2.25.1
+2.18.0
diff --git a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0015-hostapd-mtk-6G-band-does-not-require-DFS.patch b/recipes-wifi/wpa-supplicant/files/patches/mtk-0016-hostapd-mtk-6G-band-does-not-require-DFS.patch
similarity index 76%
copy from recipes-wifi/hostapd/files/patches-2.10.3/mtk-0015-hostapd-mtk-6G-band-does-not-require-DFS.patch
copy to recipes-wifi/wpa-supplicant/files/patches/mtk-0016-hostapd-mtk-6G-band-does-not-require-DFS.patch
index 642c625..33fea78 100644
--- a/recipes-wifi/hostapd/files/patches-2.10.3/mtk-0015-hostapd-mtk-6G-band-does-not-require-DFS.patch
+++ b/recipes-wifi/wpa-supplicant/files/patches/mtk-0016-hostapd-mtk-6G-band-does-not-require-DFS.patch
@@ -1,14 +1,14 @@
-From 619075bb430c908c61a818c45e36f1ca76020741 Mon Sep 17 00:00:00 2001
+From efa1d271d28c84b8ca77ffc3ca7cb75e727088a0 Mon Sep 17 00:00:00 2001
From: Peter Chiu <chui-hao.chiu@mediatek.com>
Date: Mon, 13 Feb 2023 11:03:53 +0800
-Subject: [PATCH 15/15] hostapd: mtk: 6G band does not require DFS
+Subject: [PATCH 16/16] hostapd: mtk: 6G band does not require DFS
---
src/ap/dfs.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/ap/dfs.c b/src/ap/dfs.c
-index 1c3f6785b..4b1e64246 100644
+index 1c3f678..4b1e642 100644
--- a/src/ap/dfs.c
+++ b/src/ap/dfs.c
@@ -1506,6 +1506,7 @@ int hostapd_is_dfs_required(struct hostapd_iface *iface)
@@ -20,5 +20,5 @@
return 0;
--
-2.25.1
+2.18.0
diff --git a/recipes-wifi/wpa-supplicant/files/patches/mtk-0016-hostapd-mtk-Add-available-color-bitmap.patch b/recipes-wifi/wpa-supplicant/files/patches/mtk-0016-hostapd-mtk-Add-available-color-bitmap.patch
new file mode 100644
index 0000000..9bbbf87
--- /dev/null
+++ b/recipes-wifi/wpa-supplicant/files/patches/mtk-0016-hostapd-mtk-Add-available-color-bitmap.patch
@@ -0,0 +1,337 @@
+From e7790a1bceca6b7612f29b00c429cf23f5dd9e3a Mon Sep 17 00:00:00 2001
+From: Yi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
+Date: Thu, 26 Jan 2023 09:16:00 +0800
+Subject: [PATCH] hostapd: mtk: Add available color bitmap
+
+Signed-off-by: Yi-Chia Hsieh <yi-chia.hsieh@mediatek.com>
+---
+ hostapd/ctrl_iface.c | 74 +++++++++++++++++++++++++++++++
+ hostapd/hostapd_cli.c | 18 ++++++++
+ src/ap/ap_drv_ops.c | 10 ++++-
+ src/ap/ap_drv_ops.h | 2 +
+ src/common/mtk_vendor.h | 11 +++++
+ src/drivers/driver.h | 8 ++++
+ src/drivers/driver_nl80211.c | 66 +++++++++++++++++++++++++++
+ src/drivers/driver_nl80211.h | 1 +
+ src/drivers/driver_nl80211_capa.c | 3 ++
+ 9 files changed, 192 insertions(+), 1 deletion(-)
+
+diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
+index 0ad8451..b0d5ded 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -3635,6 +3635,76 @@ hostapd_ctrl_iface_get_amsdu(struct hostapd_data *hapd, char *buf,
+ return ret;
+ }
+
++static int
++hostapd_ctrl_iface_get_bss_color(struct hostapd_data *hapd, char *buf,
++ size_t buflen)
++{
++ int ret;
++ char *pos, *end;
++ int i;
++
++ pos = buf;
++ end = buf + buflen;
++
++ if (hapd->iface->conf->he_op.he_bss_color_disabled)
++ ret = os_snprintf(buf, buflen, "BSS Color disabled\n");
++ else
++ ret = os_snprintf(buf, buflen, "BSS Color=%u\n",
++ hapd->iface->conf->he_op.he_bss_color);
++
++ pos += ret;
++
++ return pos - buf;
++}
++
++
++static int
++hostapd_ctrl_iface_get_aval_color_bmp(struct hostapd_data *hapd, char *buf,
++ size_t buflen)
++{
++ int ret;
++ char *pos, *end;
++ int i;
++ u64 aval_color_bmp = 0;
++
++ hostapd_drv_get_aval_bss_color_bmp(hapd, &aval_color_bmp);
++ hapd->color_collision_bitmap = ~aval_color_bmp;
++
++ pos = buf;
++ end = buf + buflen;
++
++ ret = os_snprintf(buf, buflen,
++ "available color bitmap=0x%llx\n",
++ aval_color_bmp);
++ if (os_snprintf_error(end - pos, ret))
++ return pos - buf;
++ pos += ret;
++
++ for (i = 0; i < HE_OPERATION_BSS_COLOR_MAX; i++) {
++ int bit = !!((aval_color_bmp >> i) & 1LLU);
++
++ if (i % 8 == 0) {
++ ret = os_snprintf(pos, end - pos, "%2d: ", i);
++ if (os_snprintf_error(end - pos, ret))
++ return pos - buf;
++ pos += ret;
++ }
++
++ ret = os_snprintf(pos, end - pos, "%d ", bit);
++ if (os_snprintf_error(end - pos, ret))
++ return pos - buf;
++ pos += ret;
++
++ if (i % 8 == 7) {
++ ret = os_snprintf(pos, end - pos, "\n");
++ if (os_snprintf_error(end - pos, ret))
++ return pos - buf;
++ pos += ret;
++ }
++ }
++ return pos - buf;
++}
++
+
+ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
+ char *buf, char *reply,
+@@ -4202,6 +4272,10 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
+ reply_len = hostapd_ctrl_iface_set_offchan_ctrl(hapd, buf + 16, reply, reply_size);
+ } else if (os_strncmp(buf, "GET_AMSDU", 9) == 0) {
+ reply_len = hostapd_ctrl_iface_get_amsdu(hapd, reply, reply_size);
++ } else if (os_strncmp(buf, "GET_BSS_COLOR", 13) == 0) {
++ reply_len = hostapd_ctrl_iface_get_bss_color(hapd, reply, reply_size);
++ } else if (os_strncmp(buf, "AVAL_COLOR_BMP", 14) == 0) {
++ reply_len = hostapd_ctrl_iface_get_aval_color_bmp(hapd, reply, reply_size);
+ } else {
+ os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
+ reply_len = 16;
+diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
+index 30b3392..b6cf52e 100644
+--- a/hostapd/hostapd_cli.c
++++ b/hostapd/hostapd_cli.c
+@@ -1578,6 +1578,20 @@ static int hostapd_cli_cmd_reload_wpa_psk(struct wpa_ctrl *ctrl, int argc,
+ }
+
+
++static int hostapd_cli_cmd_get_bss_color(struct wpa_ctrl *ctrl, int argc,
++ char *argv[])
++{
++ return wpa_ctrl_command(ctrl, "GET_BSS_COLOR");
++}
++
++
++static int hostapd_cli_cmd_get_aval_color_bmp(struct wpa_ctrl *ctrl, int argc,
++ char *argv[])
++{
++ return wpa_ctrl_command(ctrl, "AVAL_COLOR_BMP");
++}
++
++
+ #ifdef ANDROID
+ static int hostapd_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[])
+ {
+@@ -1795,6 +1809,10 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
+ "<addr> [req_mode=] <measurement request hexdump> = send a Beacon report request to a station" },
+ { "reload_wpa_psk", hostapd_cli_cmd_reload_wpa_psk, NULL,
+ "= reload wpa_psk_file only" },
++ { "get_bss_color", hostapd_cli_cmd_get_bss_color, NULL,
++ "= get current BSS color" },
++ { "get_color_bmp", hostapd_cli_cmd_get_aval_color_bmp, NULL,
++ "= get available BSS color bitmap" },
+ #ifdef ANDROID
+ { "driver", hostapd_cli_cmd_driver, NULL,
+ "<driver sub command> [<hex formatted data>] = send driver command data" },
+diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
+index 1a82f23..decffdd 100644
+--- a/src/ap/ap_drv_ops.c
++++ b/src/ap/ap_drv_ops.c
+@@ -1091,4 +1091,12 @@ int hostapd_drv_amsdu_dump(struct hostapd_data *hapd, u8 *amsdu)
+ if (!hapd->driver || !hapd->driver->amsdu_dump)
+ return 0;
+ return hapd->driver->amsdu_dump(hapd->drv_priv, amsdu);
+-}
+\ No newline at end of file
++}
++
++int hostapd_drv_get_aval_bss_color_bmp(struct hostapd_data *hapd, u64 *aval_color_bmp)
++{
++ if (!hapd->driver || !hapd->driver->get_aval_color_bmp ||
++ hapd->iface->conf->he_op.he_bss_color_disabled)
++ return 0;
++ return hapd->driver->get_aval_color_bmp(hapd->drv_priv, aval_color_bmp);
++}
+diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h
+index 4406666..61c1360 100644
+--- a/src/ap/ap_drv_ops.h
++++ b/src/ap/ap_drv_ops.h
+@@ -149,6 +149,8 @@ int hostapd_drv_ibf_ctrl(struct hostapd_data *hapd);
+ int hostapd_drv_ibf_dump(struct hostapd_data *hapd, u8 *ibf_enable);
+ int hostapd_drv_amsdu_ctrl(struct hostapd_data *hapd);
+ int hostapd_drv_amsdu_dump(struct hostapd_data *hapd, u8 *amsdu);
++int hostapd_drv_get_aval_bss_color_bmp(struct hostapd_data *hapd,
++ u64 *aval_color_bmp);
+
+ #include "drivers/driver.h"
+
+diff --git a/src/common/mtk_vendor.h b/src/common/mtk_vendor.h
+index 0999ea9..f2afb2e 100644
+--- a/src/common/mtk_vendor.h
++++ b/src/common/mtk_vendor.h
+@@ -15,6 +15,7 @@ enum mtk_nl80211_vendor_subcmds {
+ MTK_NL80211_VENDOR_SUBCMD_EDCCA_CTRL = 0xc7,
+ MTK_NL80211_VENDOR_SUBCMD_3WIRE_CTRL = 0xc8,
+ MTK_NL80211_VENDOR_SUBCMD_IBF_CTRL = 0xc9,
++ MTK_NL80211_VENDOR_SUBCMD_BSS_COLOR_CTRL = 0xca,
+ };
+
+ enum mtk_vendor_attr_edcca_ctrl {
+@@ -252,6 +253,16 @@ ibf_dump_policy[NUM_MTK_VENDOR_ATTRS_IBF_DUMP] = {
+ [MTK_VENDOR_ATTR_IBF_DUMP_ENABLE] = { .type = NLA_U8 },
+ };
+
++enum mtk_vendor_attr_bss_color_ctrl {
++ MTK_VENDOR_ATTR_BSS_COLOR_CTRL_UNSPEC,
++
++ MTK_VENDOR_ATTR_AVAL_BSS_COLOR_BMP,
++
++ /* keep last */
++ NUM_MTK_VENDOR_ATTRS_BSS_COLOR_CTRL,
++ MTK_VENDOR_ATTR_BSS_COLOR_CTRL_MAX =
++ NUM_MTK_VENDOR_ATTRS_BSS_COLOR_CTRL - 1
++};
+
+ #define CSI_MAX_COUNT 256
+ #define ETH_ALEN 6
+diff --git a/src/drivers/driver.h b/src/drivers/driver.h
+index b07aaf3..266c630 100644
+--- a/src/drivers/driver.h
++++ b/src/drivers/driver.h
+@@ -4736,6 +4736,14 @@ struct wpa_driver_ops {
+ */
+ int (*amsdu_ctrl)(void *priv, u8 amsdu);
+ int (*amsdu_dump)(void *priv, u8 *amsdu);
++
++ /**
++ * get_aval_color_bmp - get available BSS color bitmap
++ * @priv: Private driver interface data
++ * @aval_color_bmp: available bss color bitmap
++ *
++ */
++ int (*get_aval_color_bmp)(void *priv, u64 *aval_color_bmp);
+ };
+
+ /**
+diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
+index 6702384..c8771f7 100644
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -12433,6 +12433,71 @@ static int nl80211_dpp_listen(void *priv, bool enable)
+ }
+ #endif /* CONFIG_DPP */
+
++static int nl80211_get_aval_color_bmp_handler(struct nl_msg *msg, void *arg)
++{
++ u64 *aval_color_bmp = arg;
++ struct nlattr *tb[NL80211_ATTR_MAX + 1];
++ struct nlattr *tb_vendor[MTK_VENDOR_ATTR_BSS_COLOR_CTRL_MAX + 1];
++ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
++ struct nlattr *nl_vend, *attr;
++
++ static const struct nla_policy
++ bss_color_ctrl_policy[NUM_MTK_VENDOR_ATTRS_BSS_COLOR_CTRL + 1] = {
++ [MTK_VENDOR_ATTR_AVAL_BSS_COLOR_BMP] = { .type = NLA_U64 },
++ };
++
++ nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
++ genlmsg_attrlen(gnlh, 0), NULL);
++
++ nl_vend = tb[NL80211_ATTR_VENDOR_DATA];
++ if (!nl_vend)
++ return NL_SKIP;
++
++ nla_parse(tb_vendor, MTK_VENDOR_ATTR_BSS_COLOR_CTRL_MAX,
++ nla_data(nl_vend), nla_len(nl_vend), NULL);
++
++ *aval_color_bmp = nla_get_u64(tb_vendor[MTK_VENDOR_ATTR_AVAL_BSS_COLOR_BMP]);
++
++ return 0;
++}
++
++static int nl80211_get_aval_color_bmp(void *priv, u64 *aval_color_bmp)
++{
++ struct i802_bss *bss = priv;
++ struct wpa_driver_nl80211_data *drv = bss->drv;
++ struct nl_msg *msg;
++ struct nlattr *attr;
++ int ret;
++
++ if (!drv->mtk_bss_color_vendor_cmd_avail) {
++ wpa_printf(MSG_INFO,
++ "nl80211: Driver does not support BSS COLOR vendor cmd");
++ return 0;
++ }
++
++ if (!(msg = nl80211_drv_msg(drv, NLM_F_DUMP, NL80211_CMD_VENDOR)) ||
++ nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_MTK) ||
++ nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
++ MTK_NL80211_VENDOR_SUBCMD_BSS_COLOR_CTRL))
++ return -ENOBUFS;
++
++ attr = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
++ if (!attr) {
++ nlmsg_free(msg);
++ return -1;
++ }
++
++ nla_nest_end(msg, attr);
++
++ ret = send_and_recv_msgs(drv, msg,
++ nl80211_get_aval_color_bmp_handler, aval_color_bmp, NULL, NULL);
++
++ if (ret) {
++ wpa_printf(MSG_ERROR, "Failed to send BSS COLOR vendor cmd. ret=%d (%s) ",
++ ret, strerror(-ret));
++ }
++ return ret;
++}
+
+ #ifdef CONFIG_TESTING_OPTIONS
+
+@@ -13073,4 +13138,5 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
+ .start_disabled = nl80211_start_disabled,
+ .amsdu_ctrl = nl80211_enable_amsdu,
+ .amsdu_dump = nl80211_dump_amsdu,
++ .get_aval_color_bmp = nl80211_get_aval_color_bmp,
+ };
+diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h
+index e570224..b90c8fa 100644
+--- a/src/drivers/driver_nl80211.h
++++ b/src/drivers/driver_nl80211.h
+@@ -186,6 +186,7 @@ struct wpa_driver_nl80211_data {
+ unsigned int mtk_3wire_vendor_cmd_avail:1;
+ unsigned int mtk_ibf_vendor_cmd_avail:1;
+ unsigned int mtk_wireless_vendor_cmd_avail:1;
++ unsigned int mtk_bss_color_vendor_cmd_avail:1;
+
+ u64 vendor_scan_cookie;
+ u64 remain_on_chan_cookie;
+diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
+index fcfa68b..c3c7b41 100644
+--- a/src/drivers/driver_nl80211_capa.c
++++ b/src/drivers/driver_nl80211_capa.c
+@@ -1068,6 +1068,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
+ case MTK_NL80211_VENDOR_SUBCMD_WIRELESS_CTRL:
+ drv->mtk_wireless_vendor_cmd_avail = 1;
+ break;
++ case MTK_NL80211_VENDOR_SUBCMD_BSS_COLOR_CTRL :
++ drv->mtk_bss_color_vendor_cmd_avail = 1;
++ break;
+ }
+ }
+
+--
+2.39.0
+
diff --git a/recipes-wifi/wpa-supplicant/files/patches/mtk-0017-hostapd-mtk-Fix-sending-wrong-VHT-operation-IE-in-CS.patch b/recipes-wifi/wpa-supplicant/files/patches/mtk-0017-hostapd-mtk-Fix-sending-wrong-VHT-operation-IE-in-CS.patch
new file mode 100644
index 0000000..265c37a
--- /dev/null
+++ b/recipes-wifi/wpa-supplicant/files/patches/mtk-0017-hostapd-mtk-Fix-sending-wrong-VHT-operation-IE-in-CS.patch
@@ -0,0 +1,46 @@
+From f6bfd9a4a6c0d08e0dec9311873c9e863a07c9a8 Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Mon, 20 Feb 2023 11:01:18 +0800
+Subject: [PATCH] hostapd: mtk: Fix sending wrong VHT operation IE in CSA while
+ using ZWDFS
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ src/ap/dfs.c | 14 +++++++++-----
+ 1 file changed, 9 insertions(+), 5 deletions(-)
+
+diff --git a/src/ap/dfs.c b/src/ap/dfs.c
+index 4b1e642..307a4e1 100644
+--- a/src/ap/dfs.c
++++ b/src/ap/dfs.c
+@@ -1110,6 +1110,14 @@ static int
+ hostapd_dfs_start_channel_switch_background(struct hostapd_iface *iface)
+ {
+ u8 current_vht_oper_chwidth = hostapd_get_oper_chwidth(iface->conf);
++ int ret;
++
++ ret = hostapd_dfs_request_channel_switch(iface, iface->radar_background.channel,
++ iface->radar_background.freq,
++ iface->radar_background.secondary_channel,
++ current_vht_oper_chwidth,
++ iface->radar_background.centr_freq_seg0_idx,
++ iface->radar_background.centr_freq_seg1_idx);
+
+ iface->conf->channel = iface->radar_background.channel;
+ iface->freq = iface->radar_background.freq;
+@@ -1122,11 +1130,7 @@ hostapd_dfs_start_channel_switch_background(struct hostapd_iface *iface)
+
+ hostpad_dfs_update_background_chain(iface);
+
+- return hostapd_dfs_request_channel_switch(
+- iface, iface->conf->channel, iface->freq,
+- iface->conf->secondary_channel, current_vht_oper_chwidth,
+- hostapd_get_oper_centr_freq_seg0_idx(iface->conf),
+- hostapd_get_oper_centr_freq_seg1_idx(iface->conf));
++ return ret;
+ }
+
+
+--
+2.18.0
+
diff --git a/recipes-wifi/wpa-supplicant/files/patches/mtk-0018-hostapd-mtk-Add-sta-assisted-DFS-state-update-mechan.patch b/recipes-wifi/wpa-supplicant/files/patches/mtk-0018-hostapd-mtk-Add-sta-assisted-DFS-state-update-mechan.patch
new file mode 100644
index 0000000..db3c813
--- /dev/null
+++ b/recipes-wifi/wpa-supplicant/files/patches/mtk-0018-hostapd-mtk-Add-sta-assisted-DFS-state-update-mechan.patch
@@ -0,0 +1,189 @@
+From 3337e7b4f75a66e53e1320e49deba2b58a8a80b0 Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Mon, 20 Feb 2023 10:51:47 +0800
+Subject: [PATCH 18/19] hostapd: mtk: Add sta-assisted DFS state update
+ mechanism
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ src/ap/dfs.c | 20 ++++++++++++++++++++
+ src/ap/dfs.h | 3 +++
+ src/ap/drv_callbacks.c | 28 ++++++++++++++++++++++++++++
+ src/common/wpa_ctrl.h | 1 +
+ src/drivers/driver.h | 14 ++++++++++++++
+ src/drivers/driver_nl80211_event.c | 6 ++++++
+ src/drivers/nl80211_copy.h | 6 ++++++
+ 7 files changed, 78 insertions(+)
+
+diff --git a/src/ap/dfs.c b/src/ap/dfs.c
+index 307a4e1..d082fe0 100644
+--- a/src/ap/dfs.c
++++ b/src/ap/dfs.c
+@@ -1503,6 +1503,26 @@ int hostapd_dfs_nop_finished(struct hostapd_iface *iface, int freq,
+ }
+
+
++int hostapd_dfs_sta_update_state(struct hostapd_iface *iface, int freq,
++ int ht_enabled, int chan_offset, int chan_width,
++ int cf1, int cf2, u32 state)
++{
++ wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, DFS_EVENT_STA_UPDATE
++ "freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d state=%s",
++ freq, ht_enabled, chan_offset, chan_width, cf1, cf2,
++ (state == HOSTAPD_CHAN_DFS_AVAILABLE) ? "available" : "usable");
++
++ /* Proceed only if DFS is not offloaded to the driver */
++ if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD)
++ return 0;
++
++ set_dfs_state(iface, freq, ht_enabled, chan_offset, chan_width,
++ cf1, cf2, state);
++
++ return 0;
++}
++
++
+ int hostapd_is_dfs_required(struct hostapd_iface *iface)
+ {
+ int n_chans, n_chans1, start_chan_idx, start_chan_idx1, res;
+diff --git a/src/ap/dfs.h b/src/ap/dfs.h
+index c2556d2..25ba29c 100644
+--- a/src/ap/dfs.h
++++ b/src/ap/dfs.h
+@@ -30,6 +30,9 @@ int hostapd_dfs_radar_detected(struct hostapd_iface *iface, int freq,
+ int hostapd_dfs_nop_finished(struct hostapd_iface *iface, int freq,
+ int ht_enabled,
+ int chan_offset, int chan_width, int cf1, int cf2);
++int hostapd_dfs_sta_update_state(struct hostapd_iface *iface, int freq,
++ int ht_enabled, int chan_offset, int chan_width,
++ int cf1, int cf2, u32 state);
+ int hostapd_is_dfs_required(struct hostapd_iface *iface);
+ int hostapd_is_dfs_chan_available(struct hostapd_iface *iface);
+ int hostapd_dfs_start_cac(struct hostapd_iface *iface, int freq,
+diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
+index 09783cb..275f6b3 100644
+--- a/src/ap/drv_callbacks.c
++++ b/src/ap/drv_callbacks.c
+@@ -1790,6 +1790,24 @@ static void hostapd_event_dfs_cac_started(struct hostapd_data *hapd,
+ radar->cf1, radar->cf2);
+ }
+
++static void hostapd_event_dfs_sta_cac_skipped(struct hostapd_data *hapd,
++ struct dfs_event *radar)
++{
++ wpa_printf(MSG_DEBUG, "DFS CAC skipped (by STA) on %d MHz", radar->freq);
++ hostapd_dfs_sta_update_state(hapd->iface, radar->freq, radar->ht_enabled,
++ radar->chan_offset, radar->chan_width,
++ radar->cf1, radar->cf2, HOSTAPD_CHAN_DFS_AVAILABLE);
++}
++
++static void hostapd_event_dfs_sta_cac_expired(struct hostapd_data *hapd,
++ struct dfs_event *radar)
++{
++ wpa_printf(MSG_DEBUG, "DFS CAC expired (by STA) on %d MHz", radar->freq);
++ hostapd_dfs_sta_update_state(hapd->iface, radar->freq, radar->ht_enabled,
++ radar->chan_offset, radar->chan_width,
++ radar->cf1, radar->cf2, HOSTAPD_CHAN_DFS_USABLE);
++}
++
+ #endif /* NEED_AP_MLME */
+
+
+@@ -2064,6 +2082,16 @@ void hostapd_wpa_event(void *ctx, enum wpa_event_type event,
+ break;
+ hostapd_event_dfs_nop_finished(hapd, &data->dfs_event);
+ break;
++ case EVENT_DFS_STA_CAC_SKIPPED:
++ if (!data)
++ break;
++ hostapd_event_dfs_sta_cac_skipped(hapd, &data->dfs_event);
++ break;
++ case EVENT_DFS_STA_CAC_EXPIRED:
++ if (!data)
++ break;
++ hostapd_event_dfs_sta_cac_expired(hapd, &data->dfs_event);
++ break;
+ case EVENT_CHANNEL_LIST_CHANGED:
+ /* channel list changed (regulatory?), update channel list */
+ /* TODO: check this. hostapd_get_hw_features() initializes
+diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h
+index 3435084..79c8a82 100644
+--- a/src/common/wpa_ctrl.h
++++ b/src/common/wpa_ctrl.h
+@@ -360,6 +360,7 @@ extern "C" {
+ #define DFS_EVENT_CAC_COMPLETED "DFS-CAC-COMPLETED "
+ #define DFS_EVENT_NOP_FINISHED "DFS-NOP-FINISHED "
+ #define DFS_EVENT_PRE_CAC_EXPIRED "DFS-PRE-CAC-EXPIRED "
++#define DFS_EVENT_STA_UPDATE "DFS-STA-UPDATE "
+
+ #define AP_CSA_FINISHED "AP-CSA-FINISHED "
+
+diff --git a/src/drivers/driver.h b/src/drivers/driver.h
+index 265d86d..b5de0e6 100644
+--- a/src/drivers/driver.h
++++ b/src/drivers/driver.h
+@@ -5317,6 +5317,20 @@ enum wpa_event_type {
+ * EVENT_CCA_NOTIFY - Notification that CCA has completed
+ */
+ EVENT_CCA_NOTIFY,
++
++ /**
++ * EVENT_DFS_STA_CAC_SKIPPED - Notification that CAC has been skipped
++ *
++ * The channel in the notification is now marked as available.
++ */
++ EVENT_DFS_STA_CAC_SKIPPED,
++
++ /**
++ * EVENT_DFS_STA_CAC_EXPIRED - Notification that CAC has expired
++ *
++ * The channel in the notification is now marked as usable.
++ */
++ EVENT_DFS_STA_CAC_EXPIRED,
+ };
+
+
+diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c
+index 73bb7a4..ee922ac 100644
+--- a/src/drivers/driver_nl80211_event.c
++++ b/src/drivers/driver_nl80211_event.c
+@@ -1854,6 +1854,12 @@ static void nl80211_radar_event(struct wpa_driver_nl80211_data *drv,
+ case NL80211_RADAR_CAC_STARTED:
+ wpa_supplicant_event(drv->ctx, EVENT_DFS_CAC_STARTED, &data);
+ break;
++ case NL80211_RADAR_STA_CAC_SKIPPED:
++ wpa_supplicant_event(drv->ctx, EVENT_DFS_STA_CAC_SKIPPED, &data);
++ break;
++ case NL80211_RADAR_STA_CAC_EXPIRED:
++ wpa_supplicant_event(drv->ctx, EVENT_DFS_STA_CAC_EXPIRED, &data);
++ break;
+ default:
+ wpa_printf(MSG_DEBUG, "nl80211: Unknown radar event %d "
+ "received", event_type);
+diff --git a/src/drivers/nl80211_copy.h b/src/drivers/nl80211_copy.h
+index c4bf3ad..0937752 100644
+--- a/src/drivers/nl80211_copy.h
++++ b/src/drivers/nl80211_copy.h
+@@ -6431,6 +6431,10 @@ enum nl80211_smps_mode {
+ * applicable for ETSI dfs domain where pre-CAC is valid for ever.
+ * @NL80211_RADAR_CAC_STARTED: Channel Availability Check has been started,
+ * should be generated by HW if NL80211_EXT_FEATURE_DFS_OFFLOAD is enabled.
++ * @NL80211_RADAR_STA_CAC_SKIPPED: STA set the DFS state to available
++ * when receiving CSA/assoc resp
++ * @NL80211_RADAR_STA_CAC_EXPIRED: STA set the DFS state to usable
++ * when STA is disconnected or leaving the channel
+ */
+ enum nl80211_radar_event {
+ NL80211_RADAR_DETECTED,
+@@ -6439,6 +6443,8 @@ enum nl80211_radar_event {
+ NL80211_RADAR_NOP_FINISHED,
+ NL80211_RADAR_PRE_CAC_EXPIRED,
+ NL80211_RADAR_CAC_STARTED,
++ NL80211_RADAR_STA_CAC_SKIPPED,
++ NL80211_RADAR_STA_CAC_EXPIRED,
+ };
+
+ /**
+--
+2.18.0
+
diff --git a/recipes-wifi/wpa-supplicant/files/patches/mtk-0019-hostapd-mtk-Fix-auto-ht-issue-when-switching-to-DFS-.patch b/recipes-wifi/wpa-supplicant/files/patches/mtk-0019-hostapd-mtk-Fix-auto-ht-issue-when-switching-to-DFS-.patch
new file mode 100644
index 0000000..8340fd9
--- /dev/null
+++ b/recipes-wifi/wpa-supplicant/files/patches/mtk-0019-hostapd-mtk-Fix-auto-ht-issue-when-switching-to-DFS-.patch
@@ -0,0 +1,43 @@
+From 83ab1a9cc51225095842d3c62bf75cf4efe63075 Mon Sep 17 00:00:00 2001
+From: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+Date: Mon, 20 Feb 2023 16:58:20 +0800
+Subject: [PATCH] hostapd: mtk: Fix auto ht issue when switching to DFS channel
+
+Signed-off-by: StanleyYP Wang <StanleyYP.Wang@mediatek.com>
+---
+ hostapd/ctrl_iface.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
+index 0ad8451..407790f 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -2698,6 +2698,12 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
+ break;
+ }
+
++ if (os_strstr(pos, " auto-ht")) {
++ settings.freq_params.ht_enabled = iface->conf->ieee80211n;
++ settings.freq_params.vht_enabled = iface->conf->ieee80211ac;
++ settings.freq_params.he_enabled = iface->conf->ieee80211ax;
++ }
++
+ if (settings.freq_params.center_freq1)
+ dfs_range += hostapd_is_dfs_overlap(
+ iface, bandwidth, settings.freq_params.center_freq1);
+@@ -2735,12 +2741,6 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
+ return 0;
+ }
+
+- if (os_strstr(pos, " auto-ht")) {
+- settings.freq_params.ht_enabled = iface->conf->ieee80211n;
+- settings.freq_params.vht_enabled = iface->conf->ieee80211ac;
+- settings.freq_params.he_enabled = iface->conf->ieee80211ax;
+- }
+-
+ for (i = 0; i < iface->num_bss; i++) {
+
+ /* Save CHAN_SWITCH VHT, HE, and EHT config */
+--
+2.18.0
+
diff --git a/recipes-wifi/wpa-supplicant/files/patches/mtk-0020-hostapd-mtk-Mark-DFS-channel-as-available-for-CSA.patch b/recipes-wifi/wpa-supplicant/files/patches/mtk-0020-hostapd-mtk-Mark-DFS-channel-as-available-for-CSA.patch
new file mode 100644
index 0000000..1fe5c88
--- /dev/null
+++ b/recipes-wifi/wpa-supplicant/files/patches/mtk-0020-hostapd-mtk-Mark-DFS-channel-as-available-for-CSA.patch
@@ -0,0 +1,60 @@
+From 3e9500a42a41e8cd7c2d7bc20aba96e1e17161fb Mon Sep 17 00:00:00 2001
+From: "himanshu.goyal" <himanshu.goyal@mediatek.com>
+Date: Fri, 3 Mar 2023 12:45:42 +0800
+Subject: [PATCH] hostapd: mtk: Mark DFS channel as available for CSA.
+
+---
+ hostapd/ctrl_iface.c | 10 ++++++++++
+ hostapd/hostapd_cli.c | 2 +-
+ src/ap/ctrl_iface_ap.c | 1 +
+ 3 files changed, 12 insertions(+), 1 deletion(-)
+
+diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
+index c33b7a4..9ba6992 100644
+--- a/hostapd/ctrl_iface.c
++++ b/hostapd/ctrl_iface.c
+@@ -2704,6 +2704,16 @@ static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface,
+ settings.freq_params.he_enabled = iface->conf->ieee80211ax;
+ }
+
++ if (settings.freq_params.radar_background) {
++ hostapd_dfs_sta_update_state(iface,
++ settings.freq_params.freq,
++ settings.freq_params.ht_enabled,
++ settings.freq_params.sec_channel_offset,
++ bandwidth, settings.freq_params.center_freq1,
++ settings.freq_params.center_freq2,
++ HOSTAPD_CHAN_DFS_AVAILABLE);
++ }
++
+ if (settings.freq_params.center_freq1)
+ dfs_range += hostapd_is_dfs_overlap(
+ iface, bandwidth, settings.freq_params.center_freq1);
+diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
+index 0da18e2..6231e51 100644
+--- a/hostapd/hostapd_cli.c
++++ b/hostapd/hostapd_cli.c
+@@ -1693,7 +1693,7 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
+ "<addr> = send QoS Map Configure frame" },
+ { "chan_switch", hostapd_cli_cmd_chan_switch, NULL,
+ "<cs_count> <freq> [sec_channel_offset=] [center_freq1=]\n"
+- " [center_freq2=] [bandwidth=] [blocktx] [ht|vht]\n"
++ " [center_freq2=] [bandwidth=] [blocktx] [ht|vht] [skip_cac]\n"
+ " = initiate channel switch announcement" },
+ { "hs20_wnm_notif", hostapd_cli_cmd_hs20_wnm_notif, NULL,
+ "<addr> <url>\n"
+diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c
+index 18bae5c..2fae590 100644
+--- a/src/ap/ctrl_iface_ap.c
++++ b/src/ap/ctrl_iface_ap.c
+@@ -938,6 +938,7 @@ int hostapd_parse_csa_settings(const char *pos,
+ settings->freq_params.vht_enabled = !!os_strstr(pos, " vht");
+ settings->freq_params.he_enabled = !!os_strstr(pos, " he");
+ settings->freq_params.eht_enabled = !!os_strstr(pos, " eht");
++ settings->freq_params.radar_background = !!os_strstr(pos, " skip_cac");
+ settings->block_tx = !!os_strstr(pos, " blocktx");
+ #undef SET_CSA_SETTING
+
+--
+2.18.0
+
diff --git a/recipes-wifi/wpa-supplicant/files/patches/mtk-0020-hostapd-mtk-add-11v_mbss-and-ema-support.patch b/recipes-wifi/wpa-supplicant/files/patches/mtk-0020-hostapd-mtk-add-11v_mbss-and-ema-support.patch
new file mode 100644
index 0000000..8d59a0f
--- /dev/null
+++ b/recipes-wifi/wpa-supplicant/files/patches/mtk-0020-hostapd-mtk-add-11v_mbss-and-ema-support.patch
@@ -0,0 +1,1175 @@
+From 8cbdb9a59e3bbe8804f909b13ce6df6e2777c3da Mon Sep 17 00:00:00 2001
+From: mtk20656 <chank.chen@mediatek.com>
+Date: Thu, 2 Mar 2023 10:51:43 +0800
+Subject: [PATCH] hostapd: mtk: add 11v_mbss and ema support for hostapd
+
+Signed-off-by: mtk20656 <chank.chen@mediatek.com>
+---
+ hostapd/config_file.c | 9 +
+ hostapd/hostapd.conf | 58 +++++++
+ hostapd/main.c | 3 +
+ src/ap/ap_config.c | 12 ++
+ src/ap/ap_config.h | 6 +
+ src/ap/beacon.c | 124 ++++++++++++--
+ src/ap/hostapd.c | 72 +++++++-
+ src/ap/hostapd.h | 7 +
+ src/ap/ieee802_11.c | 276 +++++++++++++++++++++++++++++-
+ src/ap/ieee802_11.h | 7 +-
+ src/ap/ieee802_11_shared.c | 11 ++
+ src/common/ieee802_11_common.c | 4 +
+ src/common/ieee802_11_common.h | 3 +
+ src/common/ieee802_11_defs.h | 5 +
+ src/drivers/driver.h | 42 +++++
+ src/drivers/driver_nl80211.c | 52 ++++++
+ src/drivers/driver_nl80211_capa.c | 27 +++
+ 17 files changed, 698 insertions(+), 20 deletions(-)
+
+diff --git a/hostapd/config_file.c b/hostapd/config_file.c
+index 649618b..3f26191 100644
+--- a/hostapd/config_file.c
++++ b/hostapd/config_file.c
+@@ -3663,6 +3663,15 @@ static int hostapd_config_fill(struct hostapd_config *conf,
+ return 1;
+ }
+ bss->unsol_bcast_probe_resp_interval = val;
++ } else if (os_strcmp(buf, "mbssid") == 0) {
++ int mbssid = atoi(pos);
++ if (mbssid < 0 || mbssid > ENHANCED_MBSSID_ENABLED) {
++ wpa_printf(MSG_ERROR,
++ "Line %d: invalid mbssid (%d): '%s'.",
++ line, mbssid, pos);
++ return 1;
++ }
++ conf->mbssid = mbssid;
+ } else if (os_strcmp(buf, "mu_onoff") == 0) {
+ int val = atoi(pos);
+ if (val < 0 || val > 15) {
+diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
+index e3a5eb3..f926029 100644
+--- a/hostapd/hostapd.conf
++++ b/hostapd/hostapd.conf
+@@ -3123,3 +3123,61 @@ own_ip_addr=127.0.0.1
+ #bss=wlan0_1
+ #bssid=00:13:10:95:fe:0b
+ # ...
++#
++# Multiple BSSID Advertisement in 802.11ax
++# IEEE Std 802.11ax-2021 added a feature where instead of multiple interfaces
++# on a common radio transmitting individual beacons, those can form a set with
++# a common beacon is transmitted for all. The interface which is brought up
++# first is called as the transmitting profile of the MBSSID set which transmits
++# the beacons. The remaining interfaces are called as the non-transmitting
++# profiles and these are advertised inside the multiple BSSID element in the
++# beacons and probe response frames.
++# The transmitting interface is visible to all clients in the vicinity, however
++# the clients which do not support parsing of the multiple BSSID element will
++# not be able to connect to the non-transmitting interfaces.
++#
++# Enhanced Multiple BSSID Advertisements (EMA)
++# When enabled, the non-transmitting interfaces are split into multiple
++# beacons. The number of beacons required to cover all the non-transmitting
++# profiles is called as the profile periodicity.
++#
++# Refer to IEEE Std 802.11-2020 for details regarding the procedure and
++# required MAC address assignment.
++#
++# Following configuration is per radio.
++# 0 = Disabled (Default)
++# 1 = Multiple BSSID advertisements enabled.
++# 2 = Enhanced multiple BSSID advertisements enabled.
++#mbssid=0
++#
++# The transmitting interface should be added with 'interface' option while
++# the non-transmitting interfaces should be added using 'bss' option.
++# Security configuration should be added separately per interface, if required.
++#
++# Example:
++#mbssid=2
++#interface=wlan2
++#ctrl_interface=/var/run/hostapd
++#wpa_passphrase=0123456789
++#ieee80211w=2
++#sae_pwe=1
++#auth_algs=1
++#wpa=2
++#wpa_pairwise=CCMP
++#ssid=<SSID-0>
++#bridge=br-lan
++#wpa_key_mgmt=SAE
++#bssid=00:03:7f:12:84:84
++#
++#bss=wlan2-1
++#ctrl_interface=/var/run/hostapd
++#wpa_passphrase=0123456789
++#ieee80211w=2
++#sae_pwe=1
++#auth_algs=1
++#wpa=2
++#wpa_pairwise=CCMP
++#ssid=<SSID-1>
++#bridge=br-lan
++#wpa_key_mgmt=SAE
++#bssid=00:03:7f:12:84:85
+diff --git a/hostapd/main.c b/hostapd/main.c
+index 70a4b32..1b6474a 100644
+--- a/hostapd/main.c
++++ b/hostapd/main.c
+@@ -253,6 +253,9 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
+ wpa_printf(MSG_ERROR, "set_wowlan failed");
+ }
+ os_free(triggs);
++
++ iface->mbssid_max_interfaces = capa.mbssid_max_interfaces;
++ iface->ema_max_periodicity = capa.ema_max_periodicity;
+ }
+
+ return 0;
+diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
+index 4e46a62..7d9d5cb 100644
+--- a/src/ap/ap_config.c
++++ b/src/ap/ap_config.c
+@@ -1462,6 +1462,12 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
+ }
+ #endif /* CONFIG_IEEE80211BE */
+
++ if (full_config && bss->ignore_broadcast_ssid && conf->mbssid) {
++ wpa_printf(MSG_ERROR,
++ "Hidden SSID is not suppored when MBSSID is enabled");
++ return -1;
++ }
++
+ return 0;
+ }
+
+@@ -1545,6 +1551,12 @@ int hostapd_config_check(struct hostapd_config *conf, int full_config)
+ }
+ #endif /* CONFIG_IEEE80211BE */
+
++ if (full_config && conf->mbssid && !conf->ieee80211ax) {
++ wpa_printf(MSG_ERROR,
++ "Cannot enable multiple BSSID support without ieee80211ax");
++ return -1;
++ }
++
+ for (i = 0; i < conf->num_bss; i++) {
+ if (hostapd_config_check_bss(conf->bss[i], conf, full_config))
+ return -1;
+diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
+index 7aeb176..51476b8 100644
+--- a/src/ap/ap_config.h
++++ b/src/ap/ap_config.h
+@@ -923,6 +923,8 @@ struct hostapd_bss_config {
+ u8 ext_capa[EXT_CAPA_MAX_LEN];
+
+ u8 rnr;
++
++ bool xrates_supported;
+ };
+
+ /**
+@@ -1163,6 +1165,10 @@ struct hostapd_config {
+ u8 ibf_enable;
+ u8 dfs_detect_mode;
+ u8 amsdu;
++
++#define MBSSID_ENABLED 1
++#define ENHANCED_MBSSID_ENABLED 2
++ u8 mbssid;
+ };
+
+ enum three_wire_mode {
+diff --git a/src/ap/beacon.c b/src/ap/beacon.c
+index f3ea5c2..51db23a 100644
+--- a/src/ap/beacon.c
++++ b/src/ap/beacon.c
+@@ -462,15 +462,77 @@ static u8 * hostapd_eid_supported_op_classes(struct hostapd_data *hapd, u8 *eid)
+ }
+
+
++static int ieee802_11_build_ap_params_mbssid(struct hostapd_data *hapd,
++ struct wpa_driver_ap_params *params,
++ u8 **eid)
++{
++ struct hostapd_iface *iface = hapd->iface;
++ struct hostapd_data *tx_bss;
++ size_t len;
++ u8 elem_count = 0, *elem = NULL, **elem_offset = NULL, *end;
++ u8 *tailpos = *eid;
++
++ if (!iface->mbssid_max_interfaces ||
++ iface->num_bss > iface->mbssid_max_interfaces ||
++ (iface->conf->mbssid == ENHANCED_MBSSID_ENABLED &&
++ !iface->ema_max_periodicity))
++ goto fail;
++
++ tx_bss = hostapd_mbssid_get_tx_bss(hapd);
++ len = hostapd_eid_mbssid_len(tx_bss, WLAN_FC_STYPE_BEACON, &elem_count,
++ NULL, 0);
++ if (!len || (iface->conf->mbssid == ENHANCED_MBSSID_ENABLED &&
++ elem_count > iface->ema_max_periodicity))
++ goto fail;
++
++ elem = os_zalloc(len);
++ if (!elem)
++ goto fail;
++
++ elem_offset = os_zalloc(elem_count * sizeof(u8 *));
++ if (!elem_offset)
++ goto fail;
++
++ end = hostapd_eid_mbssid(tx_bss, elem, elem + len, WLAN_FC_STYPE_BEACON,
++ elem_count, elem_offset, NULL, 0);
++
++ params->mbssid_tx_iface = tx_bss->conf->iface;
++ params->mbssid_index = hostapd_mbssid_get_bss_index(hapd);
++ params->mbssid_elem = elem;
++ params->mbssid_elem_len = end - elem;
++ params->mbssid_elem_count = elem_count;
++ params->mbssid_elem_offset = elem_offset;
++ if (iface->conf->mbssid == ENHANCED_MBSSID_ENABLED) {
++ params->ema = true;
++ *tailpos++ = WLAN_EID_EXTENSION;
++ *tailpos++ = 3;
++ *tailpos++ = WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION;
++ *tailpos++ = iface->num_bss;
++ *tailpos++ = params->mbssid_elem_count;
++ *eid = tailpos;
++ }
++
++ return 0;
++
++fail:
++ os_free(elem);
++ wpa_printf(MSG_ERROR, "MBSSID: Configuration failed");
++ return -1;
++}
++
++
+ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
+ const struct ieee80211_mgmt *req,
+ int is_p2p, size_t *resp_len,
+- bool bcast_probe_resp)
++ bool bcast_probe_resp, const u8 *known_bss,
++ u8 known_bss_len)
+ {
+ struct ieee80211_mgmt *resp;
+- u8 *pos, *epos, *csa_pos;
++ u8 *pos, *epos, *csa_pos, *ext_cap_pos;
+ size_t buflen;
+
++ hapd = hostapd_mbssid_get_tx_bss(hapd);
++
+ #define MAX_PROBERESP_LEN 768
+ buflen = MAX_PROBERESP_LEN;
+ #ifdef CONFIG_WPS
+@@ -517,6 +579,8 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
+ }
+ #endif /* CONFIG_IEEE80211BE */
+
++ buflen += hostapd_eid_mbssid_len(hapd, WLAN_FC_STYPE_PROBE_RESP, NULL,
++ known_bss, known_bss_len);
+ buflen += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_PROBE_RESP);
+ buflen += hostapd_mbo_ie_len(hapd);
+ buflen += hostapd_eid_owe_trans_len(hapd);
+@@ -588,8 +652,16 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
+ pos = hostapd_eid_supported_op_classes(hapd, pos);
+ pos = hostapd_eid_ht_capabilities(hapd, pos);
+ pos = hostapd_eid_ht_operation(hapd, pos);
++ pos = hostapd_eid_mbssid(hapd, pos, epos, WLAN_FC_STYPE_PROBE_RESP, 0,
++ NULL, known_bss, known_bss_len);
+
++ ext_cap_pos = pos;
+ pos = hostapd_eid_ext_capab(hapd, pos);
++ if (hapd->iconf->mbssid >= MBSSID_ENABLED && !known_bss_len)
++ ext_cap_pos[12] |= 0x01; /* Probe responses always include all
++ * non-tx profiles except when a list
++ * of known BSSes is included in the
++ * probe request. */
+
+ pos = hostapd_eid_time_adv(hapd, pos);
+ pos = hostapd_eid_time_zone(hapd, pos);
+@@ -1153,16 +1225,23 @@ void handle_probe_req(struct hostapd_data *hapd,
+ }
+ #endif /* CONFIG_TESTING_OPTIONS */
+
++ /* Do not send probe response from a non-transmitting multiple BSSID
++ * profile unless the probe request is directed at that paticular BSS */
++ if (hapd != hostapd_mbssid_get_tx_bss(hapd) && res != EXACT_SSID_MATCH)
++ return;
++
+ wpa_msg_ctrl(hapd->msg_ctx, MSG_INFO, RX_PROBE_REQUEST "sa=" MACSTR
+ " signal=%d", MAC2STR(mgmt->sa), ssi_signal);
+
+ if (is_6ghz_op_class(hapd->iconf->op_class) &&
+ is_broadcast_ether_addr(mgmt->da))
+ resp = hostapd_gen_probe_resp(hapd, NULL, elems.p2p != NULL,
+- &resp_len, true);
++ &resp_len, false, elems.mbssid_known_bss,
++ elems.mbssid_known_bss_len);
+ else
+ resp = hostapd_gen_probe_resp(hapd, mgmt, elems.p2p != NULL,
+- &resp_len, false);
++ &resp_len, false, elems.mbssid_known_bss,
++ elems.mbssid_known_bss_len);
+ if (resp == NULL)
+ return;
+
+@@ -1184,7 +1263,8 @@ void handle_probe_req(struct hostapd_data *hapd,
+ hapd->cs_c_off_ecsa_proberesp;
+ }
+
+- ret = hostapd_drv_send_mlme(hapd, resp, resp_len, noack,
++ ret = hostapd_drv_send_mlme(hostapd_mbssid_get_tx_bss(hapd), resp,
++ resp_len, noack,
+ csa_offs_len ? csa_offs : NULL,
+ csa_offs_len, 0);
+
+@@ -1231,7 +1311,7 @@ static u8 * hostapd_probe_resp_offloads(struct hostapd_data *hapd,
+ "this");
+
+ /* Generate a Probe Response template for the non-P2P case */
+- return hostapd_gen_probe_resp(hapd, NULL, 0, resp_len, false);
++ return hostapd_gen_probe_resp(hapd, NULL, 0, resp_len, false, NULL, 0);
+ }
+
+ #endif /* NEED_AP_MLME */
+@@ -1250,7 +1330,7 @@ static u8 * hostapd_unsol_bcast_probe_resp(struct hostapd_data *hapd,
+
+ return hostapd_gen_probe_resp(hapd, NULL, 0,
+ ¶ms->unsol_bcast_probe_resp_tmpl_len,
+- true);
++ true, NULL, 0);
+ }
+ #endif /* CONFIG_IEEE80211AX */
+
+@@ -1533,8 +1613,12 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
+ size_t resp_len = 0;
+ #ifdef NEED_AP_MLME
+ u16 capab_info;
+- u8 *pos, *tailpos, *tailend, *csa_pos;
++ u8 *pos, *tailpos, *tailend, *csa_pos, *ext_cap_pos;
++#endif /* NEED_AP_MLME */
+
++ os_memset(params, 0, sizeof(*params));
++
++#ifdef NEED_AP_MLME
+ #define BEACON_HEAD_BUF_SIZE 256
+ #define BEACON_TAIL_BUF_SIZE 512
+ head = os_zalloc(BEACON_HEAD_BUF_SIZE);
+@@ -1586,6 +1670,9 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
+ }
+ #endif /* CONFIG_IEEE80211BE */
+
++ if (hapd->iconf->mbssid == ENHANCED_MBSSID_ENABLED &&
++ hapd == hostapd_mbssid_get_tx_bss(hapd))
++ tail_len += 5; /* Multiple BSSID Configuration element */
+ tail_len += hostapd_eid_rnr_len(hapd, WLAN_FC_STYPE_BEACON);
+ tail_len += hostapd_mbo_ie_len(hapd);
+ tail_len += hostapd_eid_owe_trans_len(hapd);
+@@ -1671,9 +1758,23 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
+ tailpos = hostapd_eid_supported_op_classes(hapd, tailpos);
+ tailpos = hostapd_eid_ht_capabilities(hapd, tailpos);
+ tailpos = hostapd_eid_ht_operation(hapd, tailpos);
+-
++ ext_cap_pos = tailpos;
+ tailpos = hostapd_eid_ext_capab(hapd, tailpos);
+
++ if (hapd->iconf->mbssid && hapd->iconf->num_bss > 1) {
++ if (ieee802_11_build_ap_params_mbssid(hapd, params, &tailpos)) {
++ os_free(head);
++ os_free(tail);
++ wpa_printf(MSG_ERROR, "Failed to set beacon data");
++ return -1;
++ } else if (hapd->iconf->mbssid == MBSSID_ENABLED ||
++ (hapd->iconf->mbssid == ENHANCED_MBSSID_ENABLED &&
++ params->mbssid_elem_count == 1)) {
++ /* Set the extended capability bit for "complete list
++ * of non-tx profiles" */
++ ext_cap_pos[12] |= 0x01;
++ }
++ }
+ /*
+ * TODO: Time Advertisement element should only be included in some
+ * DTIM Beacon frames.
+@@ -1794,7 +1895,6 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
+ resp = hostapd_probe_resp_offloads(hapd, &resp_len);
+ #endif /* NEED_AP_MLME */
+
+- os_memset(params, 0, sizeof(*params));
+ params->head = (u8 *) head;
+ params->head_len = head_len;
+ params->tail = tail;
+@@ -1897,6 +1997,10 @@ void ieee802_11_free_ap_params(struct wpa_driver_ap_params *params)
+ params->head = NULL;
+ os_free(params->proberesp);
+ params->proberesp = NULL;
++ os_free(params->mbssid_elem);
++ params->mbssid_elem = NULL;
++ os_free(params->mbssid_elem_offset);
++ params->mbssid_elem_offset = NULL;
+ #ifdef CONFIG_FILS
+ os_free(params->fd_frame_tmpl);
+ params->fd_frame_tmpl = NULL;
+diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
+index 42e8ed7..82cc155 100644
+--- a/src/ap/hostapd.c
++++ b/src/ap/hostapd.c
+@@ -91,6 +91,29 @@ int hostapd_for_each_interface(struct hapd_interfaces *interfaces,
+ }
+
+
++struct hostapd_data * hostapd_mbssid_get_tx_bss(struct hostapd_data *hapd)
++{
++ if (hapd->iconf->mbssid)
++ return hapd->iface->bss[0];
++
++ return hapd;
++}
++
++
++int hostapd_mbssid_get_bss_index(struct hostapd_data *hapd)
++{
++ if (hapd->iconf->mbssid) {
++ size_t i;
++
++ for (i = 1; i < hapd->iface->num_bss; i++)
++ if (hapd->iface->bss[i] == hapd)
++ return i;
++ }
++
++ return 0;
++}
++
++
+ void hostapd_reconfig_encryption(struct hostapd_data *hapd)
+ {
+ if (hapd->wpa_auth)
+@@ -1179,19 +1202,37 @@ static int db_table_create_radius_attributes(sqlite3 *db)
+
+ #endif /* CONFIG_NO_RADIUS */
+
++static int hostapd_start_beacon(struct hostapd_data *hapd)
++{
++ struct hostapd_bss_config *conf = hapd->conf;
++
++ if (!conf->start_disabled && ieee802_11_set_beacon(hapd) < 0)
++ return -1;
++
++ if (hapd->driver && hapd->driver->set_operstate)
++ hapd->driver->set_operstate(hapd->drv_priv, 1);
++
++ return 0;
++}
+
+ /**
+ * hostapd_setup_bss - Per-BSS setup (initialization)
+ * @hapd: Pointer to BSS data
+ * @first: Whether this BSS is the first BSS of an interface; -1 = not first,
+ * but interface may exist
++ * @start_beacon: Whether beacons should be configured and transmission started
++ * at this time. This is used when MBSSID IE is enabled where the
++ * information regarding all BSSes should be retrieved before configuring
++ * the beacons. The calling functions are responsible to configure the
++ * beacon explicitly if this is set to 'false'.
+ *
+ * This function is used to initialize all per-BSS data structures and
+ * resources. This gets called in a loop for each BSS when an interface is
+ * initialized. Most of the modules that are initialized here will be
+ * deinitialized in hostapd_cleanup().
+ */
+-static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
++static int hostapd_setup_bss(struct hostapd_data *hapd, int first,
++ bool start_beacon)
+ {
+ struct hostapd_bss_config *conf = hapd->conf;
+ u8 ssid[SSID_MAX_LEN + 1];
+@@ -1464,9 +1505,6 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
+ return -1;
+ }
+
+- if (!conf->start_disabled && ieee802_11_set_beacon(hapd) < 0)
+- return -1;
+-
+ if (flush_old_stations && !conf->start_disabled &&
+ conf->broadcast_deauth) {
+ u8 addr[ETH_ALEN];
+@@ -1485,8 +1523,8 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
+ if (hapd->wpa_auth && wpa_init_keys(hapd->wpa_auth) < 0)
+ return -1;
+
+- if (hapd->driver && hapd->driver->set_operstate)
+- hapd->driver->set_operstate(hapd->drv_priv, 1);
++ if (start_beacon)
++ return hostapd_start_beacon(hapd);
+
+ hostapd_ubus_add_bss(hapd);
+
+@@ -2214,7 +2252,7 @@ static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface,
+ hapd = iface->bss[j];
+ if (j)
+ os_memcpy(hapd->own_addr, prev_addr, ETH_ALEN);
+- if (hostapd_setup_bss(hapd, j == 0)) {
++ if (hostapd_setup_bss(hapd, j == 0, !iface->conf->mbssid)) {
+ for (;;) {
+ hapd = iface->bss[j];
+ hostapd_bss_deinit_no_free(hapd);
+@@ -2228,6 +2266,24 @@ static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface,
+ if (is_zero_ether_addr(hapd->conf->bssid))
+ prev_addr = hapd->own_addr;
+ }
++
++ if (hapd->iconf->mbssid) {
++ for (j = 0; j < iface->num_bss; j++) {
++ hapd = iface->bss[j];
++ if (hostapd_start_beacon(hapd)) {
++ for (;;) {
++ hapd = iface->bss[j];
++ hostapd_bss_deinit_no_free(hapd);
++ hostapd_free_hapd_data(hapd);
++ if (j == 0)
++ break;
++ j--;
++ }
++ goto fail;
++ }
++ }
++ }
++
+ hapd = iface->bss[0];
+
+ hostapd_tx_queue_params(iface);
+@@ -3130,7 +3186,7 @@ int hostapd_add_iface(struct hapd_interfaces *interfaces, char *buf)
+
+ if (start_ctrl_iface_bss(hapd) < 0 ||
+ (hapd_iface->state == HAPD_IFACE_ENABLED &&
+- hostapd_setup_bss(hapd, -1))) {
++ hostapd_setup_bss(hapd, -1, true))) {
+ hostapd_cleanup(hapd);
+ hapd_iface->bss[hapd_iface->num_bss - 1] = NULL;
+ hapd_iface->conf->num_bss--;
+diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
+index 56d96a5..093c28a 100644
+--- a/src/ap/hostapd.h
++++ b/src/ap/hostapd.h
+@@ -660,6 +660,11 @@ struct hostapd_iface {
+ /* Previous WMM element information */
+ struct hostapd_wmm_ac_params prev_wmm[WMM_AC_NUM];
+
++ /* Maximum number of interfaces supported for MBSSID advertisements */
++ u8 mbssid_max_interfaces;
++ /* Maximum profile periodicity for enhanced MBSSID advertisements */
++ u8 ema_max_periodicity;
++
+ int (*enable_iface_cb)(struct hostapd_iface *iface);
+ int (*disable_iface_cb)(struct hostapd_iface *iface);
+ };
+@@ -762,5 +767,7 @@ void fst_hostapd_fill_iface_obj(struct hostapd_data *hapd,
+ #endif /* CONFIG_FST */
+
+ int hostapd_set_acl(struct hostapd_data *hapd);
++struct hostapd_data * hostapd_mbssid_get_tx_bss(struct hostapd_data *hapd);
++int hostapd_mbssid_get_bss_index(struct hostapd_data *hapd);
+
+ #endif /* HOSTAPD_H */
+diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
+index 098793e..30bfa30 100644
+--- a/src/ap/ieee802_11.c
++++ b/src/ap/ieee802_11.c
+@@ -165,6 +165,7 @@ u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid)
+ int i, num, count;
+ int h2e_required;
+
++ hapd->conf->xrates_supported = 0;
+ if (hapd->iface->current_rates == NULL)
+ return eid;
+
+@@ -214,6 +215,7 @@ u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid)
+ *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_SAE_H2E_ONLY;
+ }
+
++ hapd->conf->xrates_supported = 1;
+ return pos;
+ }
+
+@@ -3979,6 +3981,23 @@ static void handle_auth(struct hostapd_data *hapd,
+ }
+
+
++static u8 hostapd_max_bssid_indicator(struct hostapd_data *hapd)
++{
++ size_t num_bss_nontx;
++ u8 max_bssid_ind = 0;
++
++ if (!hapd->iconf->mbssid || hapd->iface->num_bss <= 1)
++ return 0;
++
++ num_bss_nontx = hapd->iface->num_bss - 1;
++ while (num_bss_nontx > 0) {
++ max_bssid_ind++;
++ num_bss_nontx >>= 1;
++ }
++ return max_bssid_ind;
++}
++
++
+ int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta)
+ {
+ int i, j = 32, aid;
+@@ -4004,7 +4023,10 @@ int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta)
+ }
+ if (j == 32)
+ return -1;
+- aid = i * 32 + j + 1;
++ aid = i * 32 + j;
++
++ aid += (1 << hostapd_max_bssid_indicator(hapd));
++
+ if (aid > 2007)
+ return -1;
+
+@@ -7579,4 +7601,256 @@ u8 * hostapd_eid_rnr(struct hostapd_data *hapd, u8 *eid, u32 type)
+ return eid;
+ }
+
++
++static size_t hostapd_eid_mbssid_elem_len(struct hostapd_data *hapd,
++ u32 frame_type, size_t *bss_index,
++ const u8 *known_bss,
++ size_t known_bss_len)
++{
++ struct hostapd_data *tx_bss = hostapd_mbssid_get_tx_bss(hapd);
++ size_t len = 3, i;
++
++ for (i = *bss_index; i < hapd->iface->num_bss; i++) {
++ struct hostapd_data *bss = hapd->iface->bss[i];
++ const u8 *auth, *rsn = NULL, *rsnx = NULL;
++ size_t nontx_profile_len, auth_len;
++ u8 ie_count = 0;
++
++ if (known_bss && (known_bss_len > (i / 8))) {
++ known_bss = &known_bss[i / 8];
++ if (*known_bss & (u8)(BIT(i % 8)))
++ continue;
++ }
++
++ if (!bss || !bss->conf || !bss->started)
++ continue;
++
++ /*
++ * Sublement ID: 1 byte
++ * Length: 1 byte
++ * Nontransmitted capabilities: 4 bytes
++ * SSID element: 2 + variable
++ * Multiple BSSID Index Element: 3 bytes (+2 bytes in beacons)
++ * Fixed length = 1 + 1 + 4 + 2 + 3 = 11
++ */
++ nontx_profile_len = 11 + bss->conf->ssid.ssid_len;
++
++ if (frame_type == WLAN_FC_STYPE_BEACON)
++ nontx_profile_len += 2;
++
++ auth = wpa_auth_get_wpa_ie(bss->wpa_auth, &auth_len);
++ if (auth) {
++ rsn = get_ie(auth, auth_len, WLAN_EID_RSN);
++ if (rsn)
++ nontx_profile_len += (2 + rsn[1]);
++
++ rsnx = get_ie(auth, auth_len, WLAN_EID_RSNX);
++ if (rsnx)
++ nontx_profile_len += (2 + rsnx[1]);
++ }
++ if (!rsn && hostapd_wpa_ie(tx_bss, WLAN_EID_RSN))
++ ie_count++;
++ if (!rsnx && hostapd_wpa_ie(tx_bss, WLAN_EID_RSNX))
++ ie_count++;
++ if (bss->conf->xrates_supported)
++ nontx_profile_len += 8;
++ else if (hapd->conf->xrates_supported)
++ ie_count++;
++ if (ie_count)
++ nontx_profile_len += (4 + ie_count);
++
++ if ((len + nontx_profile_len) > 255)
++ goto mbssid_too_big;
++
++ len += nontx_profile_len;
++ }
++
++mbssid_too_big:
++ *bss_index = i;
++ return len;
++}
++
++
++size_t hostapd_eid_mbssid_len(struct hostapd_data *hapd, u32 frame_type,
++ u8 *elem_count, const u8 *known_bss,
++ size_t known_bss_len)
++{
++ size_t len = 0, bss_index = 1;
++
++ if (!hapd->iconf->mbssid || hapd->iface->num_bss <= 1 ||
++ (frame_type != WLAN_FC_STYPE_BEACON &&
++ frame_type != WLAN_FC_STYPE_PROBE_RESP))
++ return 0;
++
++ if (frame_type == WLAN_FC_STYPE_BEACON) {
++ if (!elem_count) {
++ wpa_printf(MSG_ERROR,
++ "MBSSID: Insufficient data for beacons");
++ return 0;
++ }
++ *elem_count = 0;
++ }
++
++ while (bss_index < hapd->iface->num_bss) {
++ len += hostapd_eid_mbssid_elem_len(hapd, frame_type,
++ &bss_index, known_bss,
++ known_bss_len);
++
++ if (frame_type == WLAN_FC_STYPE_BEACON)
++ *elem_count += 1;
++ }
++ return len;
++}
++
++
++static u8 * hostapd_eid_mbssid_elem(struct hostapd_data *hapd, u8 *eid, u8 *end,
++ u32 frame_type, u8 max_bssid_indicator,
++ size_t *bss_index, u8 elem_count,
++ const u8 *known_bss, size_t known_bss_len)
++{
++ struct hostapd_data *tx_bss = hostapd_mbssid_get_tx_bss(hapd);
++ size_t i;
++ u8 *eid_len_offset, *max_bssid_indicator_offset;
++
++ *eid++ = WLAN_EID_MULTIPLE_BSSID;
++ eid_len_offset = eid++;
++ max_bssid_indicator_offset = eid++;
++
++ for (i = *bss_index; i < hapd->iface->num_bss; i++) {
++ struct hostapd_data *bss = hapd->iface->bss[i];
++ struct hostapd_bss_config *conf;
++ u8 *eid_len_pos, *nontx_bss_start = eid;
++ const u8 *auth, *rsn = NULL, *rsnx = NULL;
++ u8 ie_count = 0, non_inherit_ie[3];
++ size_t auth_len = 0;
++ u16 capab_info;
++
++ if (known_bss && (known_bss_len > (i / 8))) {
++ known_bss = &known_bss[i / 8];
++ if (*known_bss & (u8)(BIT(i % 8)))
++ continue;
++ }
++
++ if (!bss || !bss->conf || !bss->started)
++ continue;
++ conf = bss->conf;
++
++ *eid++ = WLAN_EID_SUBELEMENT_NONTRANSMITTED_BSSID_PROFILE;
++ eid_len_pos = eid++;
++
++ *eid++ = WLAN_EID_NONTRANSMITTED_BSSID_CAPA;
++ *eid++ = sizeof(capab_info);
++ capab_info = host_to_le16(hostapd_own_capab_info(bss));
++ os_memcpy(eid, (const void *)&capab_info, sizeof(capab_info));
++ eid += sizeof(capab_info);
++
++ *eid++ = WLAN_EID_SSID;
++ *eid++ = conf->ssid.ssid_len;
++ os_memcpy(eid, conf->ssid.ssid, conf->ssid.ssid_len);
++ eid += conf->ssid.ssid_len;
++
++ *eid++ = WLAN_EID_MULTIPLE_BSSID_INDEX;
++ if (frame_type == WLAN_FC_STYPE_BEACON) {
++ *eid++ = 3;
++ *eid++ = i;
++ if (hapd->iconf->mbssid == ENHANCED_MBSSID_ENABLED &&
++ (conf->dtim_period % elem_count))
++ conf->dtim_period = elem_count;
++ *eid++ = conf->dtim_period;
++ *eid++ = 0xFF;
++ } else {
++ *eid++ = 1;
++ *eid++ = i;
++ }
++
++ auth = wpa_auth_get_wpa_ie(bss->wpa_auth, &auth_len);
++ if (auth) {
++ rsn = get_ie(auth, auth_len, WLAN_EID_RSN);
++ if (rsn) {
++ os_memcpy(eid, rsn, 2 + rsn[1]);
++ eid += (2 + rsn[1]);
++ }
++
++ rsnx = get_ie(auth, auth_len, WLAN_EID_RSNX);
++ if (rsnx) {
++ os_memcpy(eid, rsnx, 2 + rsnx[1]);
++ eid += (2 + rsnx[1]);
++ }
++ }
++ if (!rsn && hostapd_wpa_ie(tx_bss, WLAN_EID_RSN)) {
++ non_inherit_ie[ie_count] = WLAN_EID_RSN;
++ ie_count++;
++ }
++ if (!rsnx && hostapd_wpa_ie(tx_bss, WLAN_EID_RSNX)) {
++ non_inherit_ie[ie_count] = WLAN_EID_RSNX;
++ ie_count++;
++ }
++ if (hapd->conf->xrates_supported &&
++ !bss->conf->xrates_supported) {
++ non_inherit_ie[ie_count] = WLAN_EID_EXT_SUPP_RATES;
++ ie_count++;
++ }
++ if (ie_count) {
++ *eid++ = WLAN_EID_EXTENSION;
++ *eid++ = 2 + ie_count;
++ *eid++ = WLAN_EID_EXT_NON_INHERITANCE;
++ *eid++ = ie_count;
++ os_memcpy(eid, non_inherit_ie, ie_count);
++ eid += ie_count;
++ }
++
++ *eid_len_pos = (eid - eid_len_pos) - 1;
++
++ if (((eid - eid_len_offset) - 1) > 255) {
++ eid = nontx_bss_start;
++ goto mbssid_too_big;
++ }
++ }
++
++mbssid_too_big:
++ *bss_index = i;
++ *max_bssid_indicator_offset = max_bssid_indicator;
++ if (*max_bssid_indicator_offset < 1)
++ *max_bssid_indicator_offset = 1;
++ *eid_len_offset = (eid - eid_len_offset) - 1;
++ return eid;
++}
++
++
++u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end,
++ u32 frame_type, u8 elem_count, u8 **elem_offset,
++ const u8 *known_bss, size_t known_bss_len)
++{
++ size_t bss_index = 1;
++ u8 elem_index = 0;
++
++ if (!hapd->iconf->mbssid || hapd->iface->num_bss <= 1 ||
++ (frame_type != WLAN_FC_STYPE_BEACON &&
++ frame_type != WLAN_FC_STYPE_PROBE_RESP))
++ return eid;
++
++ if (frame_type == WLAN_FC_STYPE_BEACON && !elem_offset) {
++ wpa_printf(MSG_ERROR, "MBSSID: Insufficient data for beacons");
++ return eid;
++ }
++
++ while (bss_index < hapd->iface->num_bss) {
++ if (frame_type == WLAN_FC_STYPE_BEACON) {
++ if (elem_index == elem_count) {
++ wpa_printf(MSG_WARNING,
++ "MBSSID: More number of elements than provided array");
++ break;
++ }
++
++ elem_offset[elem_index] = eid;
++ elem_index = elem_index + 1;
++ }
++ eid = hostapd_eid_mbssid_elem(hapd, eid, end, frame_type,
++ hostapd_max_bssid_indicator(hapd),
++ &bss_index, elem_count,
++ known_bss, known_bss_len);
++ }
++ return eid;
++}
++
+ #endif /* CONFIG_NATIVE_WINDOWS */
+diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h
+index fa1f47b..bb454bb 100644
+--- a/src/ap/ieee802_11.h
++++ b/src/ap/ieee802_11.h
+@@ -214,5 +214,10 @@ u16 copy_sta_eht_capab(struct hostapd_data *hapd, struct sta_info *sta,
+ enum ieee80211_op_mode opmode,
+ const u8 *he_capab, size_t he_capab_len,
+ const u8 *eht_capab, size_t eht_capab_len);
+-
++size_t hostapd_eid_mbssid_len(struct hostapd_data *hapd, u32 frame_type,
++ u8 *elem_count, const u8 *known_bss,
++ size_t known_bss_len);
++u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end,
++ u32 frame_type, u8 elem_count, u8 **elem_offset,
++ const u8 *known_bss, size_t known_bss_len);
+ #endif /* IEEE802_11_H */
+diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c
+index 4f85d78..7f5b475 100644
+--- a/src/ap/ieee802_11_shared.c
++++ b/src/ap/ieee802_11_shared.c
+@@ -364,6 +364,8 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx)
+ *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
+ if (hapd->conf->bss_transition)
+ *pos |= 0x08; /* Bit 19 - BSS Transition */
++ if (hapd->iconf->mbssid)
++ *pos |= 0x40; /* Bit 22 - Multiple BSSID */
+ break;
+ case 3: /* Bits 24-31 */
+ #ifdef CONFIG_WNM_AP
+@@ -436,6 +438,8 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx)
+ (hapd->iface->drv_flags &
+ WPA_DRIVER_FLAGS_BEACON_PROTECTION))
+ *pos |= 0x10; /* Bit 84 - Beacon Protection Enabled */
++ if (hapd->iconf->mbssid == ENHANCED_MBSSID_ENABLED)
++ *pos |= 0x08; /* Bit 83 - Enhanced multiple BSSID */
+ break;
+ case 11: /* Bits 88-95 */
+ #ifdef CONFIG_SAE_PK
+@@ -471,6 +475,13 @@ u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid)
+ *pos &= ~hapd->conf->ext_capa_mask[i];
+ *pos |= hapd->conf->ext_capa[i];
+ }
++
++ /* Clear bits 83 and 22 if EMA and MBSSID are not enabled
++ * otherwise association fails with some clients */
++ if (i == 10 && hapd->iconf->mbssid < ENHANCED_MBSSID_ENABLED)
++ *pos &= ~0x08;
++ if (i == 2 && !hapd->iconf->mbssid)
++ *pos &= ~0x40;
+ }
+
+ while (len > 0 && eid[1 + len] == 0) {
+diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c
+index c8ee90c..2fab7c3 100644
+--- a/src/common/ieee802_11_common.c
++++ b/src/common/ieee802_11_common.c
+@@ -315,6 +315,10 @@ static int ieee802_11_parse_extension(const u8 *pos, size_t elen,
+ elems->eht_operation = pos;
+ elems->eht_operation_len = elen;
+ break;
++ case WLAN_EID_EXT_KNOWN_BSSID:
++ elems->mbssid_known_bss = pos;
++ elems->mbssid_known_bss_len = elen;
++ break;
+ default:
+ if (show_errors) {
+ wpa_printf(MSG_MSGDUMP,
+diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h
+index 94e1d7b..1e4e27d 100644
+--- a/src/common/ieee802_11_common.h
++++ b/src/common/ieee802_11_common.h
+@@ -119,6 +119,7 @@ struct ieee802_11_elems {
+ const u8 *pasn_params;
+ const u8 *eht_capabilities;
+ const u8 *eht_operation;
++ const u8 *mbssid_known_bss;
+
+ u8 ssid_len;
+ u8 supp_rates_len;
+@@ -176,6 +177,8 @@ struct ieee802_11_elems {
+ u8 eht_capabilities_len;
+ u8 eht_operation_len;
+
++ u8 mbssid_known_bss_len;
++
+ struct mb_ies_info mb_ies;
+ struct frag_ies_info frag_ies;
+ };
+diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
+index 62088bd..0bbbca9 100644
+--- a/src/common/ieee802_11_defs.h
++++ b/src/common/ieee802_11_defs.h
+@@ -481,6 +481,9 @@
+ #define WLAN_EID_EXT_SPATIAL_REUSE 39
+ #define WLAN_EID_EXT_COLOR_CHANGE_ANNOUNCEMENT 42
+ #define WLAN_EID_EXT_OCV_OCI 54
++#define WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION 55
++#define WLAN_EID_EXT_NON_INHERITANCE 56
++#define WLAN_EID_EXT_KNOWN_BSSID 57
+ #define WLAN_EID_EXT_SHORT_SSID_LIST 58
+ #define WLAN_EID_EXT_HE_6GHZ_BAND_CAP 59
+ #define WLAN_EID_EXT_EDMG_CAPABILITIES 61
+@@ -497,6 +500,8 @@
+ #define WLAN_EID_EXT_MULTI_LINK_TRAFFIC_INDICATION 110
+ #define WLAN_EID_EXT_AKM_SUITE_SELECTOR 114
+
++#define WLAN_EID_SUBELEMENT_NONTRANSMITTED_BSSID_PROFILE 0
++
+ /* Extended Capabilities field */
+ #define WLAN_EXT_CAPAB_20_40_COEX 0
+ #define WLAN_EXT_CAPAB_GLK 1
+diff --git a/src/drivers/driver.h b/src/drivers/driver.h
+index 82daef0..36f465c 100644
+--- a/src/drivers/driver.h
++++ b/src/drivers/driver.h
+@@ -1633,6 +1633,43 @@ struct wpa_driver_ap_params {
+ * ibf_enable=<val>
+ */
+ u8 ibf_enable;
++
++ /**
++ * mbssid_tx_iface - Transmitting interface of the MBSSID set
++ */
++ const char *mbssid_tx_iface;
++
++ /**
++ * mbssid_index - The index of this BSS in the MBSSID set
++ */
++ unsigned int mbssid_index;
++
++ /**
++ * mbssid_elem - Buffer containing all MBSSID elements
++ */
++ u8 *mbssid_elem;
++
++ /**
++ * mbssid_elem_len - Total length of all MBSSID elements
++ */
++ size_t mbssid_elem_len;
++
++ /**
++ * mbssid_elem_count - The number of MBSSID elements
++ */
++ u8 mbssid_elem_count;
++
++ /**
++ * mbssid_elem_offset - Offsets to elements in mbssid_elem.
++ * Kernel will use these offsets to generate multiple BSSID beacons.
++ */
++ u8 **mbssid_elem_offset;
++
++ /**
++ * ema - Enhanced MBSSID advertisements support.
++ */
++ bool ema;
++
+ };
+
+ struct wpa_driver_mesh_bss_params {
+@@ -2197,6 +2234,11 @@ struct wpa_driver_capa {
+
+ /* Maximum number of supported CSA counters */
+ u16 max_csa_counters;
++
++ /* Maximum number of interfaces supported for MBSSID advertisements */
++ u8 mbssid_max_interfaces;
++ /* Maximum profile periodicity for enhanced MBSSID advertisements */
++ u8 ema_max_periodicity;
+ };
+
+
+diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
+index 6c65901..3753409 100644
+--- a/src/drivers/driver_nl80211.c
++++ b/src/drivers/driver_nl80211.c
+@@ -4540,6 +4540,55 @@ static int nl80211_unsol_bcast_probe_resp(struct i802_bss *bss,
+ nla_nest_end(msg, attr);
+ return 0;
+ }
++
++
++static int nl80211_mbssid(struct nl_msg *msg,
++ struct wpa_driver_ap_params *params)
++{
++ struct nlattr *config, *elems;
++ int ifidx;
++
++ if (!params->mbssid_tx_iface)
++ return 0;
++
++ config = nla_nest_start(msg, NL80211_ATTR_MBSSID_CONFIG);
++ if (!config)
++ return -1;
++
++ nla_put_u8(msg, NL80211_MBSSID_CONFIG_ATTR_INDEX, params->mbssid_index);
++ if (params->mbssid_tx_iface) {
++ ifidx = if_nametoindex(params->mbssid_tx_iface);
++ if (ifidx <= 0)
++ return -1;
++ nla_put_u32(msg,
++ NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX,
++ ifidx);
++ }
++
++ if (params->ema)
++ nla_put_flag(msg, NL80211_MBSSID_CONFIG_ATTR_EMA);
++
++ nla_nest_end(msg, config);
++
++ if (params->mbssid_elem_count && params->mbssid_elem_len &&
++ params->mbssid_elem_offset && *params->mbssid_elem_offset) {
++ u8 i, **offs = params->mbssid_elem_offset;
++
++ elems = nla_nest_start(msg, NL80211_ATTR_MBSSID_ELEMS);
++ if (!elems)
++ return -1;
++
++ for (i = 0; i < params->mbssid_elem_count - 1; i++)
++ nla_put(msg, i + 1, offs[i + 1] - offs[i], offs[i]);
++
++ nla_put(msg, i + 1,
++ *offs + params->mbssid_elem_len - offs[i],
++ offs[i]);
++
++ nla_nest_end(msg, elems);
++ }
++ return 0;
++}
+ #endif /* CONFIG_IEEE80211AX */
+
+
+@@ -4838,6 +4887,9 @@ static int wpa_driver_nl80211_set_ap(void *priv,
+ if (params->unsol_bcast_probe_resp_interval &&
+ nl80211_unsol_bcast_probe_resp(bss, msg, params) < 0)
+ goto fail;
++
++ if (nl80211_mbssid(msg, params) < 0)
++ goto fail;
+ #endif /* CONFIG_IEEE80211AX */
+
+ #ifdef CONFIG_SAE
+diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
+index 06a52db..d8078bc 100644
+--- a/src/drivers/driver_nl80211_capa.c
++++ b/src/drivers/driver_nl80211_capa.c
+@@ -857,6 +857,30 @@ err:
+ }
+
+
++static void wiphy_info_mbssid(struct wpa_driver_capa *cap, struct nlattr *attr)
++{
++ struct nlattr *config[NL80211_MBSSID_CONFIG_ATTR_MAX + 1];
++
++ if (nla_parse_nested(config, NL80211_MBSSID_CONFIG_ATTR_MAX, attr,
++ NULL))
++ return;
++
++ if (!config[NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES])
++ return;
++
++ cap->mbssid_max_interfaces =
++ nla_get_u8(config[NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES]);
++
++ if (config[NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY])
++ cap->ema_max_periodicity =
++ nla_get_u8(config[NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY]);
++
++ wpa_printf(MSG_DEBUG,
++ "multiple_bssid: max interfaces %u, max profile periodicity %u\n",
++ cap->mbssid_max_interfaces, cap->ema_max_periodicity);
++}
++
++
+ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
+ {
+ struct nlattr *tb[NL80211_ATTR_MAX + 1];
+@@ -1106,6 +1130,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
+ if (tb[NL80211_ATTR_WIPHY_SELF_MANAGED_REG])
+ capa->flags |= WPA_DRIVER_FLAGS_SELF_MANAGED_REGULATORY;
+
++ if (tb[NL80211_ATTR_MBSSID_CONFIG])
++ wiphy_info_mbssid(capa, tb[NL80211_ATTR_MBSSID_CONFIG]);
++
+ return NL_SKIP;
+ }
+
+--
+2.18.0
+
diff --git a/recipes-wifi/wpa-supplicant/files/patches/patches.inc b/recipes-wifi/wpa-supplicant/files/patches/patches.inc
index b2f59b9..48bd493 100644
--- a/recipes-wifi/wpa-supplicant/files/patches/patches.inc
+++ b/recipes-wifi/wpa-supplicant/files/patches/patches.inc
@@ -71,10 +71,17 @@
file://mtk-0007-hostapd-mtk-Add-three-wire-PTA-ctrl-hostapd-vendor-c.patch \
file://mtk-0008-hostapd-mtk-Add-hostapd-iBF-control.patch \
file://mtk-0009-hostapd-mtk-Do-not-include-HE-capab-IE-if-associated.patch \
- file://mtk-0010-hostapd-mtk-Add-DFS-and-ZWDFS-support.patch \
- file://mtk-0011-hostapd-mtk-Add-amsdu-set-get-ctrl.patch \
- file://mtk-0012-hostapd-mtk-Add-he_ldpc-configuration.patch \
- file://mtk-0013-hostapd-mtk-Add-the-broadcast-destination-address-of.patch \
- file://mtk-0014-hostapd-mtk-Add-vendor-command-attribute-for-RTS-BW-.patch \
- file://mtk-0015-hostapd-mtk-6G-band-does-not-require-DFS.patch \
+ file://mtk-0010-hostapd-mtk-Add-DFS-detection-mode.patch \
+ file://mtk-0011-hostapd-mtk-Add-DFS-offchan-channel-switch.patch \
+ file://mtk-0012-hostapd-mtk-Add-amsdu-set-get-ctrl.patch \
+ file://mtk-0013-hostapd-mtk-Add-he_ldpc-configuration.patch \
+ file://mtk-0014-hostapd-mtk-Add-the-broadcast-destination-address-of.patch \
+ file://mtk-0015-hostapd-mtk-Add-vendor-command-attribute-for-RTS-BW-.patch \
+ file://mtk-0016-hostapd-mtk-6G-band-does-not-require-DFS.patch \
+ file://mtk-0016-hostapd-mtk-Add-available-color-bitmap.patch \
+ file://mtk-0017-hostapd-mtk-Fix-sending-wrong-VHT-operation-IE-in-CS.patch \
+ file://mtk-0018-hostapd-mtk-Add-sta-assisted-DFS-state-update-mechan.patch \
+ file://mtk-0019-hostapd-mtk-Fix-auto-ht-issue-when-switching-to-DFS-.patch \
+ file://mtk-0020-hostapd-mtk-Mark-DFS-channel-as-available-for-CSA.patch \
+ file://mtk-0020-hostapd-mtk-add-11v_mbss-and-ema-support.patch \
"
diff --git a/recipes-wifi/wpa-supplicant/files/src/src/ap/ubus.c b/recipes-wifi/wpa-supplicant/files/src/src/ap/ubus.c
index 5001225..ddd8644 100644
--- a/recipes-wifi/wpa-supplicant/files/src/src/ap/ubus.c
+++ b/recipes-wifi/wpa-supplicant/files/src/src/ap/ubus.c
@@ -1084,6 +1084,8 @@
}
__hostapd_bss_mgmt_enable(hapd, flags);
+
+ return 0;
}