diff --git a/README.md b/README.md
index 4e330a72fa7..080bc4e4e19 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,3 @@
-<<<<<<< HEAD
# 适用于 IPQ系列设备的 OpenWrt 源码仓库
## 注意
@@ -60,173 +59,3 @@
```
7. 编译完成后输出路径:bin/targets
-=======
-# NSS Fork for IPQ807x
-| Branch | mac80211 Version | Notes |
-|-----------------------------------------------------------------------------------------|------------------|----------------------------------------------------------------------|
-| [qualcommax-6.x-nss-wifi](https://github.com/qosmio/openwrt-ipq/tree/qualcommax-6.x-nss-wifi) |6.11|Current with upstream|
-| [qualcommax-6.x-nss-mx4300](https://github.com/qosmio/openwrt-ipq/tree/qualcommax-6.x-nss-mx4300) |6.11|Current with upstream. [Supports Linksys MX4300](https://github.com/openwrt/openwrt/pull/16070) |
-| [qualcommax-6.x-nss-wifi-6.9](https://github.com/qosmio/openwrt-ipq/tree/qualcommax-6.x-nss-wifi-6.9) |6.9.9|Current with upstream, except older mac80211|
-| [qualcommax-6.x-nss-mx4300-6.9](https://github.com/qosmio/openwrt-ipq/tree/qualcommax-6.x-nss-mx4300-6.11) |6.9.9|Current with upstream, except older mac80211. [Supports Linksys MX4300](https://github.com/openwrt/openwrt/pull/16070) |
-
-NOTE: The 6.9 branches are meant for folks having issues with the current 6.11.2 version of backports/mac80211. These are mostly just meant as a workaround for the time being. I don't plan on supporting these branches longterm.
-
-The MX4300 branches will soon be merged in once the PR for MX4300 is approved upstream.
-
-## Table of Contents
-- [Overview](#overview)
-- [What's NSS?](#whats-nss)
-- [How Does OpenWrt "Offload" Traffic?](#how-does-openwrt-offload-traffic)
-- [How Is NSS Different from OpenWrt's Offloading Options?](#how-is-nss-different-from-openwrts-offloading-options)
-- [Do I Need NSS?](#do-i-need-nss)
-- [OK, I Want NSS. Does My Device Support It?](#ok-i-want-nss-does-my-device-support-it)
-- [Quickstart](#quickstart)
-- [Important Note](#important-note)
-- [Donate](#donate)
-
----
-
-## Overview
-This repository contains a fork of OpenWrt that integrates Qualcomm's NSS (Network Subsystem) support for the IPQ807x and IPQ6018 series of SoCs. The goal of this project is to provide enhanced network performance and reliability through hardware offloading, leveraging NSS's capabilities to improve throughput and reduce CPU load.
-
----
-#### What's NSS?
-
-NSS (**N**etwork **S**ub**s**ystem) is a specialized hardware offloading engine developed by Qualcomm, integrated into their IPQ series SoCs (System-on-Chip), such as the IPQ807x and IPQ6018. NSS is designed to handle high-throughput network tasks like NAT, routing, and even security tasks such as IPsec, without burdening the main CPU cores.
-
----
-#### How Does OpenWrt "Offload" Traffic?
-
-OpenWrt offers three primary methods for offloading network traffic, each aimed at reducing CPU load and improving throughput:
-
-1. **Packet Steering**: Distributes network processing across multiple CPU cores. It helps balance the load on multi-core CPUs but still relies on the CPU to handle packet processing.
-
-2. **Software Flow Offloading**: Accelerates traffic processing by using the CPU’s fast path, allowing more efficient handling of routing and NAT (Network Address Translation) by bypassing the kernel's normal slow path. This relies entirely on the CPU to speed up packet forwarding.
-
-3. **Hardware Flow Offloading**: Available only on select devices (e.g., Mediatek), this method offloads packet forwarding directly to the network hardware using kernel-based mechanisms (nftables/iptables) to accelerate traffic. However, this is limited to devices that have hardware acceleration capabilities supported by OpenWrt.
-
----
-#### Why Isn't NSS Supported in Vanilla OpenWrt?
-
-NSS requires proprietary binaries (NSS firmware) and extensive patches to the Linux kernel and networking stack. Qualcomm does not openly release the necessary firmware or detailed documentation on how to integrate NSS support, making it extremely difficult for the OpenWrt community to maintain. The required patches are invasive and complex, altering significant portions of the network stack, which makes upstream integration into OpenWrt unlikely. Maintaining compatibility with each new kernel version is another barrier, as Qualcomm’s support for these patches is minimal and sporadic.
-
----
-
-#### How Is NSS Different from OpenWrt's Offloading Options?
-
-The main difference between NSS and OpenWrt's offloading methods is that NSS provides **hardware acceleration** directly within the SoC, bypassing the CPU almost entirely for certain network tasks. OpenWrt's offloading, on the other hand, relies heavily on the **CPU** to manage and accelerate traffic, either via multi-core CPU distribution (Packet Steering) or kernel-level acceleration (Software/Hardware Flow Offloading).
-
-NSS doesn’t play nice with OpenWrt’s built-in offloading because they conflict in how they handle packets, leading to performance issues or even outright failures.
-
----
-
-#### Key Differences:
-
-- **Packet Steering**: While it redistributes packet processing across multiple CPU cores, it still involves the CPU heavily. With NSS, dedicated hardware cores handle packet processing, so packet steering can interfere by unnecessarily involving the CPU, reducing the benefits of offloading to hardware.
-
-- **Software Flow Offloading**: This uses kernel-level mechanisms (nftables/iptables) to accelerate packet forwarding by utilizing the CPU’s fast path. NSS, however, bypasses the kernel’s networking stack and offloads these tasks directly to the hardware. If both are enabled, packet handling may be done redundantly in software and hardware, leading to inefficiencies or conflicts.
-
-- **Hardware Flow Offloading**: Available only for certain devices like Mediatek, this method offloads packet processing to specific hardware via kernel drivers. However, this hardware-based acceleration is entirely separate from NSS and not as efficient on Qualcomm devices. Using it alongside NSS can lead to unpredictable behavior, as both try to accelerate traffic but in incompatible ways.
-
----
-
-#### Do I Need NSS?
-
-Here are some reasons you might need NSS:
-
-- You require high network throughput (e.g., gigabit speeds) on devices like the IPQ807x or IPQ6018 series.
-- Your router handles resource-intensive tasks like NAT, VPN (IPsec), or other routing-heavy activities that would otherwise overwhelm the CPU.
-- You’re seeking better performance than what OpenWrt’s software and hardware offloading options can provide.
-
-However, it’s important to note that **NSS is NOT supported upstream** in OpenWrt. As of now, there are only a few community-driven projects that maintain NSS patches.
-
-I personally maintain an NSS fork of OpenWrt [qosmio/openwrt-ipq](https://github.com/qosmio/openwrt-ipq) and the necessary NSS packages [qosmio/nss-packages](https://github.com/qosmio/nss-packages).
-
----
-
-#### OK, I Want NSS. Does My Device Support It?
-
-NSS is available for most Qualcomm IPQ807x and IPQ6018 devices. If your device is part of this chipset family and supported in OpenWrt, it can run NSS.
-
-Supported devices include, but are not limited to:
-- Devices based on the **IPQ807x** (e.g., some high-end Netgear and TP-Link routers)
-- Devices based on the **IPQ6018** (e.g., certain enterprise routers)
-
----
-
-## Quickstart
-
-1. Clone this repository:
- ```bash
- git clone https://github.com/qosmio/openwrt-ipq -b qualcommax-6.x-nss-wifi
- cd openwrt-ipq
- ```
-2. Update feeds:
- ```bash
- ./scripts/feeds update
- ./scripts/feeds install -a
- ```
-3. Copy over the seed file
- ```bash
- cp nss-setup/config-nss.seed .config
- ```
-4. Open the `.config` in a text editor, find your device, and remove the "#" and change `"is not set"` to `"=y"`
-
- Example:
- ```diff
- -# CONFIG_TARGET_qualcommax_ipq807x_DEVICE_dynalink_dl-wrx36 is not set
- +CONFIG_TARGET_qualcommax_ipq807x_DEVICE_dynalink_dl-wrx36=y
- ```
-6. Generate the full config
- ```bash
- make defconfig V=s
- ```
-7. Now run full build
- ```bash
- make download -j$(nproc) V=s
- make -j$(nproc) V=s
- ```
----
-### Important Note:
-
-Many users report issues after enabling Packet Steering or Flow Offloading (Software or Hardware), often because they are used to these options or they get carried over during a sysupgrade. Even if the setup seems to work initially, it is not optimized for NSS offloading, and you are losing the full benefits of hardware acceleration.
-
-If you plan to use NSS, **start fresh** and **disable all other offloading options**.
-
-By default OpenWrt's offloading is disabled, but if you ever happen to enable it accidentally, make sure you disable it.
-
----
- ```bash
- uci set network.@device[0].packet_steering=0
- uci set network.@device[0].flow_offloading=0
- uci set network.@device[0].flow_offloading_hw=0
- uci commit network
- ```
-If you have questions or issues, please join the discussion on OpenWrt's forums.
-[Qualcomm NSS Build](https://forum.openwrt.org/t/qualcommax-nss-build)
-
-## Please remember when posting about an issue:
- 1. Include your device make and model.
- 2. Relevant logs and screenshots.
- 3. State clearly and concisely the issue you're having.
- > "My router doesn't work", "I'm getting an error"
-
- Is not something I can help with.
- 4. Include the specific commit you're building from.
- > "I'm building from latest"
-
- Also not helpful as I'm always pushing changes...
-
- 5. Be respectful and mindful. I dedicate my free time to maintain and improve this project, and I do it for the benefit of the community. Remember that I'm not a full-time developer or support team—I'm just an individual sharing my work. Constructive feedback is always welcome, but please refrain from being overly critical or demanding.
-
-## Support the Project
-
-I never really thought about setting up donations before, but with so many people being receptive and appreciative and asking how to contribute, I figured, why not? Of course, this project also builds on the incredible work done by the talented devs upstream who put in countless hours into OpenWrt itself. I’ll definitely continue working on this, but if you’d like to support, every bit helps.
-
-[![Donate with PayPal](./paypal.png)](https://www.paypal.com/donate?business=3V3H2SZFY7DNQ&item_name=Maintaining+NSS+fork+of+OpenWRT+and+NSS+packages.)
-
-
-
-
-Consider donating to the [OpenWrt Foundation](https://openwrt.org/donate)
->>>>>>> qos/qualcommax-6.x-nss-wifi
diff --git a/include/kernel-6.6 b/include/kernel-6.6
index a5048a4e6f4..df3464ab411 100644
--- a/include/kernel-6.6
+++ b/include/kernel-6.6
@@ -1,2 +1,2 @@
-LINUX_VERSION-6.6 = .57
-LINUX_KERNEL_HASH-6.6.57 = 66ce426ef96f99b8e1ef7ac72e780c730ef8b970f7aa5708501c4274d7abb7b3
+LINUX_VERSION-6.6 = .58
+LINUX_KERNEL_HASH-6.6.58 = e7df81e588d70fab5ec3ec3bb04ac53d51f0860fc3b1ec45e0a4167a026899db
diff --git a/include/package-pack.mk b/include/package-pack.mk
index 26a32788343..9991050c14c 100644
--- a/include/package-pack.mk
+++ b/include/package-pack.mk
@@ -339,10 +339,12 @@ else
$(FAKEROOT) $(STAGING_DIR_HOST)/bin/apk mkpkg \
--info "name:$(1)$$(ABIV_$(1))" \
--info "version:$(VERSION)" \
- --info "description:" \
+ --info "description:$$(strip $$(Package/$(1)/description))" \
--info "arch:$(PKGARCH)" \
--info "license:$(LICENSE)" \
--info "origin:$(SOURCE)" \
+ --info "url:$(URL)" \
+ --info "maintainer:$(MAINTAINER)" \
--info "provides:$$(foreach prov,$$(filter-out $(1)$$(ABIV_$(1)),$(PROVIDES)$$(if $$(ABIV_$(1)), \
$(1) $(foreach provide,$(PROVIDES),$(provide)$$(ABIV_$(1))))),$$(prov)=$(VERSION) )" \
--script "post-install:$$(ADIR_$(1))/post-install" \
diff --git a/package/boot/uboot-envtools/files/ath79 b/package/boot/uboot-envtools/files/ath79
index 4f3bc2de6c0..1d9d3bcfaa1 100644
--- a/package/boot/uboot-envtools/files/ath79
+++ b/package/boot/uboot-envtools/files/ath79
@@ -20,6 +20,7 @@ alfa-network,n5q|\
alfa-network,pi-wifi4|\
alfa-network,r36a|\
alfa-network,tube-2hq|\
+alfa-network,wifi-camppro-nano-duo|\
araknis,an-300-ap-i-n|\
arduino,yun|\
asus,rt-ac59u|\
diff --git a/package/firmware/linux-firmware/mediatek.mk b/package/firmware/linux-firmware/mediatek.mk
index 5c448e1033c..d520557196d 100644
--- a/package/firmware/linux-firmware/mediatek.mk
+++ b/package/firmware/linux-firmware/mediatek.mk
@@ -96,3 +96,13 @@ define Package/mt7988-2p5g-phy-firmware/install
$(1)/lib/firmware/mediatek/mt7988
endef
$(eval $(call BuildPackage,mt7988-2p5g-phy-firmware))
+
+Package/mt7988-wo-firmware = $(call Package/firmware-default,MT7988 offload firmware,,LICENCE.mediatek)
+define Package/mt7988-wo-firmware/install
+ $(INSTALL_DIR) $(1)/lib/firmware/mediatek/mt7988
+ $(INSTALL_DATA) \
+ $(PKG_BUILD_DIR)/mediatek/mt7988/mt7988_wo_0.bin \
+ $(PKG_BUILD_DIR)/mediatek/mt7988/mt7988_wo_1.bin \
+ $(1)/lib/firmware/mediatek/mt7988
+endef
+$(eval $(call BuildPackage,mt7988-wo-firmware))
diff --git a/package/kernel/mac80211/patches/subsys/331-wifi-cfg80211-check-radio-iface-combination-for-mult.patch b/package/kernel/mac80211/patches/subsys/331-wifi-cfg80211-check-radio-iface-combination-for-mult.patch
new file mode 100644
index 00000000000..76c351aa831
--- /dev/null
+++ b/package/kernel/mac80211/patches/subsys/331-wifi-cfg80211-check-radio-iface-combination-for-mult.patch
@@ -0,0 +1,122 @@
+From: Karthikeyan Periyasamy
+Date: Tue, 17 Sep 2024 19:32:39 +0530
+Subject: [PATCH] wifi: cfg80211: check radio iface combination for multi radio
+ per wiphy
+
+Currently, wiphy_verify_combinations() fails for the multi-radio per wiphy
+due to the condition check on new global interface combination that DFS
+only works on one channel. In a multi-radio scenario, new global interface
+combination encompasses the capabilities of all radio combinations, so it
+supports more than one channel with DFS. For multi-radio per wiphy,
+interface combination verification needs to be performed for radio specific
+interface combinations. This is necessary as the new global interface
+combination combines the capabilities of all radio combinations.
+
+Fixes: a01b1e9f9955 ("wifi: mac80211: add support for DFS with multiple radios")
+Signed-off-by: Karthikeyan Periyasamy
+---
+
+--- a/net/wireless/core.c
++++ b/net/wireless/core.c
+@@ -599,16 +599,20 @@ use_default_name:
+ }
+ EXPORT_SYMBOL(wiphy_new_nm);
+
+-static int wiphy_verify_combinations(struct wiphy *wiphy)
++static
++int wiphy_verify_iface_combinations(struct wiphy *wiphy,
++ const struct ieee80211_iface_combination *iface_comb,
++ int n_iface_comb,
++ bool combined_radio)
+ {
+ const struct ieee80211_iface_combination *c;
+ int i, j;
+
+- for (i = 0; i < wiphy->n_iface_combinations; i++) {
++ for (i = 0; i < n_iface_comb; i++) {
+ u32 cnt = 0;
+ u16 all_iftypes = 0;
+
+- c = &wiphy->iface_combinations[i];
++ c = &iface_comb[i];
+
+ /*
+ * Combinations with just one interface aren't real,
+@@ -621,9 +625,13 @@ static int wiphy_verify_combinations(str
+ if (WARN_ON(!c->num_different_channels))
+ return -EINVAL;
+
+- /* DFS only works on one channel. */
+- if (WARN_ON(c->radar_detect_widths &&
+- (c->num_different_channels > 1)))
++ /* DFS only works on one channel. Avoid this check
++ * for multi-radio global combination, since it hold
++ * the capabilities of all radio combinations.
++ */
++ if (!combined_radio &&
++ WARN_ON(c->radar_detect_widths &&
++ c->num_different_channels > 1))
+ return -EINVAL;
+
+ if (WARN_ON(!c->n_limits))
+@@ -644,13 +652,21 @@ static int wiphy_verify_combinations(str
+ if (WARN_ON(wiphy->software_iftypes & types))
+ return -EINVAL;
+
+- /* Only a single P2P_DEVICE can be allowed */
+- if (WARN_ON(types & BIT(NL80211_IFTYPE_P2P_DEVICE) &&
++ /* Only a single P2P_DEVICE can be allowed, avoid this
++ * check for multi-radio global combination, since it
++ * hold the capabilities of all radio combinations.
++ */
++ if (!combined_radio &&
++ WARN_ON(types & BIT(NL80211_IFTYPE_P2P_DEVICE) &&
+ c->limits[j].max > 1))
+ return -EINVAL;
+
+- /* Only a single NAN can be allowed */
+- if (WARN_ON(types & BIT(NL80211_IFTYPE_NAN) &&
++ /* Only a single NAN can be allowed, avoid this
++ * check for multi-radio global combination, since it
++ * hold the capabilities of all radio combinations.
++ */
++ if (!combined_radio &&
++ WARN_ON(types & BIT(NL80211_IFTYPE_NAN) &&
+ c->limits[j].max > 1))
+ return -EINVAL;
+
+@@ -674,6 +690,34 @@ static int wiphy_verify_combinations(str
+ return 0;
+ }
+
++static int wiphy_verify_combinations(struct wiphy *wiphy)
++{
++ int i, ret;
++ bool combined_radio = false;
++
++ if (wiphy->n_radio) {
++ for (i = 0; i < wiphy->n_radio; i++) {
++ const struct wiphy_radio *radio = &wiphy->radio[i];
++
++ ret = wiphy_verify_iface_combinations(wiphy,
++ radio->iface_combinations,
++ radio->n_iface_combinations,
++ false);
++ if (ret)
++ return ret;
++ }
++
++ combined_radio = true;
++ }
++
++ ret = wiphy_verify_iface_combinations(wiphy,
++ wiphy->iface_combinations,
++ wiphy->n_iface_combinations,
++ combined_radio);
++
++ return ret;
++}
++
+ int wiphy_register(struct wiphy *wiphy)
+ {
+ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
diff --git a/package/kernel/mac80211/patches/subsys/350-wifi-cfg80211-add-option-for-vif-allowed-radios.patch b/package/kernel/mac80211/patches/subsys/350-wifi-cfg80211-add-option-for-vif-allowed-radios.patch
new file mode 100644
index 00000000000..d5b42f3a3a5
--- /dev/null
+++ b/package/kernel/mac80211/patches/subsys/350-wifi-cfg80211-add-option-for-vif-allowed-radios.patch
@@ -0,0 +1,309 @@
+From: Felix Fietkau
+Date: Wed, 17 Jul 2024 15:43:52 +0200
+Subject: [PATCH] wifi: cfg80211: add option for vif allowed radios
+
+This allows users to prevent a vif from affecting radios other than the
+configured ones. This can be useful in cases where e.g. an AP is running
+on one radio, and triggering a scan on another radio should not disturb it.
+
+Changing the allowed radios list for a vif is supported, but only while
+it is down.
+
+While it is possible to achieve the same by always explicitly specifying
+a frequency list for scan requests and ensuring that the wrong channel/band
+is never accidentally set on an unrelated interface, this change makes
+multi-radio wiphy setups a lot easier to deal with for CLI users.
+
+By itself, this patch only enforces the radio mask for scanning requests
+and remain-on-channel. Follow-up changes build on this to limit configured
+frequencies.
+
+Signed-off-by: Felix Fietkau
+---
+
+--- a/include/net/cfg80211.h
++++ b/include/net/cfg80211.h
+@@ -6227,6 +6227,7 @@ enum ieee80211_ap_reg_power {
+ * entered.
+ * @links[].cac_time_ms: CAC time in ms
+ * @valid_links: bitmap describing what elements of @links are valid
++ * @radio_mask: Bitmask of radios that this interface is allowed to operate on.
+ */
+ struct wireless_dev {
+ struct wiphy *wiphy;
+@@ -6339,6 +6340,8 @@ struct wireless_dev {
+ unsigned int cac_time_ms;
+ } links[IEEE80211_MLD_MAX_NUM_LINKS];
+ u16 valid_links;
++
++ u32 radio_mask;
+ };
+
+ static inline const u8 *wdev_address(struct wireless_dev *wdev)
+@@ -6525,6 +6528,17 @@ bool cfg80211_radio_chandef_valid(const
+ const struct cfg80211_chan_def *chandef);
+
+ /**
++ * cfg80211_wdev_channel_allowed - Check if the wdev may use the channel
++ *
++ * @wdev: the wireless device
++ * @chan: channel to check
++ *
++ * Return: whether or not the wdev may use the channel
++ */
++bool cfg80211_wdev_channel_allowed(struct wireless_dev *wdev,
++ struct ieee80211_channel *chan);
++
++/**
+ * ieee80211_get_response_rate - get basic rate for a given rate
+ *
+ * @sband: the band to look for rates in
+--- a/include/uapi/linux/nl80211.h
++++ b/include/uapi/linux/nl80211.h
+@@ -2868,6 +2868,9 @@ enum nl80211_commands {
+ * nested item, it contains attributes defined in
+ * &enum nl80211_if_combination_attrs.
+ *
++ * @NL80211_ATTR_VIF_RADIO_MASK: Bitmask of allowed radios (u32).
++ * A value of 0 means all radios.
++ *
+ * @NUM_NL80211_ATTR: total number of nl80211_attrs available
+ * @NL80211_ATTR_MAX: highest attribute number currently defined
+ * @__NL80211_ATTR_AFTER_LAST: internal use
+@@ -3416,6 +3419,8 @@ enum nl80211_attrs {
+ NL80211_ATTR_WIPHY_RADIOS,
+ NL80211_ATTR_WIPHY_INTERFACE_COMBINATIONS,
+
++ NL80211_ATTR_VIF_RADIO_MASK,
++
+ /* add attributes here, update the policy in nl80211.c */
+
+ __NL80211_ATTR_AFTER_LAST,
+--- a/net/wireless/nl80211.c
++++ b/net/wireless/nl80211.c
+@@ -829,6 +829,7 @@ static const struct nla_policy nl80211_p
+ [NL80211_ATTR_MLO_TTLM_DLINK] = NLA_POLICY_EXACT_LEN(sizeof(u16) * 8),
+ [NL80211_ATTR_MLO_TTLM_ULINK] = NLA_POLICY_EXACT_LEN(sizeof(u16) * 8),
+ [NL80211_ATTR_ASSOC_SPP_AMSDU] = { .type = NLA_FLAG },
++ [NL80211_ATTR_VIF_RADIO_MASK] = { .type = NLA_U32 },
+ };
+
+ /* policy for the key attributes */
+@@ -3996,7 +3997,8 @@ static int nl80211_send_iface(struct sk_
+ nla_put_u32(msg, NL80211_ATTR_GENERATION,
+ rdev->devlist_generation ^
+ (cfg80211_rdev_list_generation << 2)) ||
+- nla_put_u8(msg, NL80211_ATTR_4ADDR, wdev->use_4addr))
++ nla_put_u8(msg, NL80211_ATTR_4ADDR, wdev->use_4addr) ||
++ nla_put_u32(msg, NL80211_ATTR_VIF_RADIO_MASK, wdev->radio_mask))
+ goto nla_put_failure;
+
+ if (rdev->ops->get_channel && !wdev->valid_links) {
+@@ -4312,6 +4314,29 @@ static int nl80211_valid_4addr(struct cf
+ return -EOPNOTSUPP;
+ }
+
++static int nl80211_parse_vif_radio_mask(struct genl_info *info,
++ u32 *radio_mask)
++{
++ struct cfg80211_registered_device *rdev = info->user_ptr[0];
++ struct nlattr *attr = info->attrs[NL80211_ATTR_VIF_RADIO_MASK];
++ u32 mask, allowed;
++
++ if (!attr) {
++ *radio_mask = 0;
++ return 0;
++ }
++
++ allowed = BIT(rdev->wiphy.n_radio) - 1;
++ mask = nla_get_u32(attr);
++ if (mask & ~allowed)
++ return -EINVAL;
++ if (!mask)
++ mask = allowed;
++ *radio_mask = mask;
++
++ return 1;
++}
++
+ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
+ {
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
+@@ -4319,6 +4344,8 @@ static int nl80211_set_interface(struct
+ int err;
+ enum nl80211_iftype otype, ntype;
+ struct net_device *dev = info->user_ptr[1];
++ struct wireless_dev *wdev = dev->ieee80211_ptr;
++ u32 radio_mask = 0;
+ bool change = false;
+
+ memset(¶ms, 0, sizeof(params));
+@@ -4332,8 +4359,6 @@ static int nl80211_set_interface(struct
+ }
+
+ if (info->attrs[NL80211_ATTR_MESH_ID]) {
+- struct wireless_dev *wdev = dev->ieee80211_ptr;
+-
+ if (ntype != NL80211_IFTYPE_MESH_POINT)
+ return -EINVAL;
+ if (otype != NL80211_IFTYPE_MESH_POINT)
+@@ -4364,6 +4389,12 @@ static int nl80211_set_interface(struct
+ if (err > 0)
+ change = true;
+
++ err = nl80211_parse_vif_radio_mask(info, &radio_mask);
++ if (err < 0)
++ return err;
++ if (err && netif_running(dev))
++ return -EBUSY;
++
+ if (change)
+ err = cfg80211_change_iface(rdev, dev, ntype, ¶ms);
+ else
+@@ -4372,11 +4403,11 @@ static int nl80211_set_interface(struct
+ if (!err && params.use_4addr != -1)
+ dev->ieee80211_ptr->use_4addr = params.use_4addr;
+
+- if (change && !err) {
+- struct wireless_dev *wdev = dev->ieee80211_ptr;
++ if (radio_mask)
++ wdev->radio_mask = radio_mask;
+
++ if (change && !err)
+ nl80211_notify_iface(rdev, wdev, NL80211_CMD_SET_INTERFACE);
+- }
+
+ return err;
+ }
+@@ -4387,6 +4418,7 @@ static int _nl80211_new_interface(struct
+ struct vif_params params;
+ struct wireless_dev *wdev;
+ struct sk_buff *msg;
++ u32 radio_mask;
+ int err;
+ enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED;
+
+@@ -4424,6 +4456,10 @@ static int _nl80211_new_interface(struct
+ if (err < 0)
+ return err;
+
++ err = nl80211_parse_vif_radio_mask(info, &radio_mask);
++ if (err < 0)
++ return err;
++
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+ if (!msg)
+ return -ENOMEM;
+@@ -4465,6 +4501,9 @@ static int _nl80211_new_interface(struct
+ break;
+ }
+
++ if (radio_mask)
++ wdev->radio_mask = radio_mask;
++
+ if (nl80211_send_iface(msg, info->snd_portid, info->snd_seq, 0,
+ rdev, wdev, NL80211_CMD_NEW_INTERFACE) < 0) {
+ nlmsg_free(msg);
+@@ -9180,6 +9219,9 @@ static bool cfg80211_off_channel_oper_al
+
+ lockdep_assert_wiphy(wdev->wiphy);
+
++ if (!cfg80211_wdev_channel_allowed(wdev, chan))
++ return false;
++
+ if (!cfg80211_beaconing_iface_active(wdev))
+ return true;
+
+@@ -9392,7 +9434,8 @@ static int nl80211_trigger_scan(struct s
+ }
+
+ /* ignore disabled channels */
+- if (chan->flags & IEEE80211_CHAN_DISABLED)
++ if (chan->flags & IEEE80211_CHAN_DISABLED ||
++ !cfg80211_wdev_channel_allowed(wdev, chan))
+ continue;
+
+ request->channels[i] = chan;
+@@ -9412,7 +9455,8 @@ static int nl80211_trigger_scan(struct s
+
+ chan = &wiphy->bands[band]->channels[j];
+
+- if (chan->flags & IEEE80211_CHAN_DISABLED)
++ if (chan->flags & IEEE80211_CHAN_DISABLED ||
++ !cfg80211_wdev_channel_allowed(wdev, chan))
+ continue;
+
+ request->channels[i] = chan;
+--- a/net/wireless/scan.c
++++ b/net/wireless/scan.c
+@@ -956,7 +956,8 @@ static int cfg80211_scan_6ghz(struct cfg
+ struct ieee80211_channel *chan =
+ ieee80211_get_channel(&rdev->wiphy, ap->center_freq);
+
+- if (!chan || chan->flags & IEEE80211_CHAN_DISABLED)
++ if (!chan || chan->flags & IEEE80211_CHAN_DISABLED ||
++ !cfg80211_wdev_channel_allowed(rdev_req->wdev, chan))
+ continue;
+
+ for (i = 0; i < rdev_req->n_channels; i++) {
+@@ -3490,9 +3491,12 @@ int cfg80211_wext_siwscan(struct net_dev
+ continue;
+
+ for (j = 0; j < wiphy->bands[band]->n_channels; j++) {
++ struct ieee80211_channel *chan;
++
+ /* ignore disabled channels */
+- if (wiphy->bands[band]->channels[j].flags &
+- IEEE80211_CHAN_DISABLED)
++ chan = &wiphy->bands[band]->channels[j];
++ if (chan->flags & IEEE80211_CHAN_DISABLED ||
++ !cfg80211_wdev_channel_allowed(creq->wdev, chan))
+ continue;
+
+ /* If we have a wireless request structure and the
+--- a/net/wireless/util.c
++++ b/net/wireless/util.c
+@@ -2923,3 +2923,32 @@ bool cfg80211_radio_chandef_valid(const
+ return true;
+ }
+ EXPORT_SYMBOL(cfg80211_radio_chandef_valid);
++
++bool cfg80211_wdev_channel_allowed(struct wireless_dev *wdev,
++ struct ieee80211_channel *chan)
++{
++ struct wiphy *wiphy = wdev->wiphy;
++ const struct wiphy_radio *radio;
++ struct cfg80211_chan_def chandef;
++ u32 radio_mask;
++ int i;
++
++ radio_mask = wdev->radio_mask;
++ if (!wiphy->n_radio || radio_mask == BIT(wiphy->n_radio) - 1)
++ return true;
++
++ cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_HT20);
++ for (i = 0; i < wiphy->n_radio; i++) {
++ if (!(radio_mask & BIT(i)))
++ continue;
++
++ radio = &wiphy->radio[i];
++ if (!cfg80211_radio_chandef_valid(radio, &chandef))
++ continue;
++
++ return true;
++ }
++
++ return false;
++}
++EXPORT_SYMBOL(cfg80211_wdev_channel_allowed);
+--- a/net/wireless/core.c
++++ b/net/wireless/core.c
+@@ -1415,6 +1415,8 @@ void cfg80211_init_wdev(struct wireless_
+ /* allow mac80211 to determine the timeout */
+ wdev->ps_timeout = -1;
+
++ wdev->radio_mask = BIT(wdev->wiphy->n_radio) - 1;
++
+ if ((wdev->iftype == NL80211_IFTYPE_STATION ||
+ wdev->iftype == NL80211_IFTYPE_P2P_CLIENT ||
+ wdev->iftype == NL80211_IFTYPE_ADHOC) && !wdev->use_4addr)
diff --git a/package/kernel/mac80211/patches/subsys/351-wifi-mac80211-use-vif-radio-mask-to-limit-ibss-scan-.patch b/package/kernel/mac80211/patches/subsys/351-wifi-mac80211-use-vif-radio-mask-to-limit-ibss-scan-.patch
new file mode 100644
index 00000000000..7363c3873f6
--- /dev/null
+++ b/package/kernel/mac80211/patches/subsys/351-wifi-mac80211-use-vif-radio-mask-to-limit-ibss-scan-.patch
@@ -0,0 +1,79 @@
+From: Felix Fietkau
+Date: Thu, 26 Sep 2024 14:06:11 +0200
+Subject: [PATCH] wifi: mac80211: use vif radio mask to limit ibss scan
+ frequencies
+
+Reject frequencies not supported by any radio that the vif is allowed to use.
+
+Signed-off-by: Felix Fietkau
+---
+
+--- a/net/mac80211/scan.c
++++ b/net/mac80211/scan.c
+@@ -1178,14 +1178,14 @@ int ieee80211_request_ibss_scan(struct i
+ unsigned int n_channels)
+ {
+ struct ieee80211_local *local = sdata->local;
+- int ret = -EBUSY, i, n_ch = 0;
++ int i, n_ch = 0;
+ enum nl80211_band band;
+
+ lockdep_assert_wiphy(local->hw.wiphy);
+
+ /* busy scanning */
+ if (local->scan_req)
+- goto unlock;
++ return -EBUSY;
+
+ /* fill internal scan request */
+ if (!channels) {
+@@ -1202,7 +1202,9 @@ int ieee80211_request_ibss_scan(struct i
+ &local->hw.wiphy->bands[band]->channels[i];
+
+ if (tmp_ch->flags & (IEEE80211_CHAN_NO_IR |
+- IEEE80211_CHAN_DISABLED))
++ IEEE80211_CHAN_DISABLED) ||
++ !cfg80211_wdev_channel_allowed(&sdata->wdev,
++ tmp_ch))
+ continue;
+
+ local->int_scan_req->channels[n_ch] = tmp_ch;
+@@ -1211,21 +1213,23 @@ int ieee80211_request_ibss_scan(struct i
+ }
+
+ if (WARN_ON_ONCE(n_ch == 0))
+- goto unlock;
++ return -EINVAL;
+
+ local->int_scan_req->n_channels = n_ch;
+ } else {
+ for (i = 0; i < n_channels; i++) {
+ if (channels[i]->flags & (IEEE80211_CHAN_NO_IR |
+- IEEE80211_CHAN_DISABLED))
++ IEEE80211_CHAN_DISABLED) ||
++ !cfg80211_wdev_channel_allowed(&sdata->wdev,
++ channels[i]))
+ continue;
+
+ local->int_scan_req->channels[n_ch] = channels[i];
+ n_ch++;
+ }
+
+- if (WARN_ON_ONCE(n_ch == 0))
+- goto unlock;
++ if (n_ch == 0)
++ return -EINVAL;
+
+ local->int_scan_req->n_channels = n_ch;
+ }
+@@ -1235,9 +1239,7 @@ int ieee80211_request_ibss_scan(struct i
+ memcpy(local->int_scan_req->ssids[0].ssid, ssid, IEEE80211_MAX_SSID_LEN);
+ local->int_scan_req->ssids[0].ssid_len = ssid_len;
+
+- ret = __ieee80211_start_scan(sdata, sdata->local->int_scan_req);
+- unlock:
+- return ret;
++ return __ieee80211_start_scan(sdata, sdata->local->int_scan_req);
+ }
+
+ void ieee80211_scan_cancel(struct ieee80211_local *local)
diff --git a/package/kernel/mac80211/patches/subsys/352-wifi-mac80211-use-vif-radio-mask-to-limit-chanctx-an.patch b/package/kernel/mac80211/patches/subsys/352-wifi-mac80211-use-vif-radio-mask-to-limit-chanctx-an.patch
new file mode 100644
index 00000000000..ac3d1011489
--- /dev/null
+++ b/package/kernel/mac80211/patches/subsys/352-wifi-mac80211-use-vif-radio-mask-to-limit-chanctx-an.patch
@@ -0,0 +1,52 @@
+From: Felix Fietkau
+Date: Thu, 26 Sep 2024 14:07:50 +0200
+Subject: [PATCH] wifi: mac80211: use vif radio mask to limit creating chanctx
+
+Reject frequencies not supported by any radio that the vif is allowed to use.
+
+Signed-off-by: Felix Fietkau
+---
+
+--- a/net/mac80211/chan.c
++++ b/net/mac80211/chan.c
+@@ -1167,7 +1167,7 @@ ieee80211_replace_chanctx(struct ieee802
+ static bool
+ ieee80211_find_available_radio(struct ieee80211_local *local,
+ const struct ieee80211_chan_req *chanreq,
+- int *radio_idx)
++ u32 radio_mask, int *radio_idx)
+ {
+ struct wiphy *wiphy = local->hw.wiphy;
+ const struct wiphy_radio *radio;
+@@ -1178,6 +1178,9 @@ ieee80211_find_available_radio(struct ie
+ return true;
+
+ for (i = 0; i < wiphy->n_radio; i++) {
++ if (!(radio_mask & BIT(i)))
++ continue;
++
+ radio = &wiphy->radio[i];
+ if (!cfg80211_radio_chandef_valid(radio, &chanreq->oper))
+ continue;
+@@ -1211,7 +1214,9 @@ int ieee80211_link_reserve_chanctx(struc
+ new_ctx = ieee80211_find_reservation_chanctx(local, chanreq, mode);
+ if (!new_ctx) {
+ if (ieee80211_can_create_new_chanctx(local, -1) &&
+- ieee80211_find_available_radio(local, chanreq, &radio_idx))
++ ieee80211_find_available_radio(local, chanreq,
++ sdata->wdev.radio_mask,
++ &radio_idx))
+ new_ctx = ieee80211_new_chanctx(local, chanreq, mode,
+ false, radio_idx);
+ else
+@@ -1881,7 +1886,9 @@ int _ieee80211_link_use_channel(struct i
+ /* Note: context is now reserved */
+ if (ctx)
+ reserved = true;
+- else if (!ieee80211_find_available_radio(local, chanreq, &radio_idx))
++ else if (!ieee80211_find_available_radio(local, chanreq,
++ sdata->wdev.radio_mask,
++ &radio_idx))
+ ctx = ERR_PTR(-EBUSY);
+ else
+ ctx = ieee80211_new_chanctx(local, chanreq, mode,
diff --git a/package/kernel/mac80211/patches/subsys/353-wifi-mac80211-remove-status-ampdu_delimiter_crc.patch b/package/kernel/mac80211/patches/subsys/353-wifi-mac80211-remove-status-ampdu_delimiter_crc.patch
new file mode 100644
index 00000000000..c0cdcdd6bc1
--- /dev/null
+++ b/package/kernel/mac80211/patches/subsys/353-wifi-mac80211-remove-status-ampdu_delimiter_crc.patch
@@ -0,0 +1,67 @@
+From: Felix Fietkau
+Date: Wed, 17 Jul 2024 22:49:16 +0200
+Subject: [PATCH] wifi: mac80211: remove status->ampdu_delimiter_crc
+
+This was never used by any driver, so remove it to free up some space.
+
+Signed-off-by: Felix Fietkau
+---
+
+--- a/include/net/mac80211.h
++++ b/include/net/mac80211.h
+@@ -1448,8 +1448,6 @@ ieee80211_tx_info_clear_status(struct ie
+ * @RX_FLAG_AMPDU_IS_LAST: this subframe is the last subframe of the A-MPDU
+ * @RX_FLAG_AMPDU_DELIM_CRC_ERROR: A delimiter CRC error has been detected
+ * on this subframe
+- * @RX_FLAG_AMPDU_DELIM_CRC_KNOWN: The delimiter CRC field is known (the CRC
+- * is stored in the @ampdu_delimiter_crc field)
+ * @RX_FLAG_MIC_STRIPPED: The mic was stripped of this packet. Decryption was
+ * done by the hardware
+ * @RX_FLAG_ONLY_MONITOR: Report frame only to monitor interfaces without
+@@ -1521,7 +1519,7 @@ enum mac80211_rx_flags {
+ RX_FLAG_AMPDU_LAST_KNOWN = BIT(12),
+ RX_FLAG_AMPDU_IS_LAST = BIT(13),
+ RX_FLAG_AMPDU_DELIM_CRC_ERROR = BIT(14),
+- RX_FLAG_AMPDU_DELIM_CRC_KNOWN = BIT(15),
++ /* one free bit at 15 */
+ RX_FLAG_MACTIME = BIT(16) | BIT(17),
+ RX_FLAG_MACTIME_PLCP_START = 1 << 16,
+ RX_FLAG_MACTIME_START = 2 << 16,
+@@ -1618,7 +1616,6 @@ enum mac80211_rx_encoding {
+ * @rx_flags: internal RX flags for mac80211
+ * @ampdu_reference: A-MPDU reference number, must be a different value for
+ * each A-MPDU but the same for each subframe within one A-MPDU
+- * @ampdu_delimiter_crc: A-MPDU delimiter CRC
+ * @zero_length_psdu_type: radiotap type of the 0-length PSDU
+ * @link_valid: if the link which is identified by @link_id is valid. This flag
+ * is set only when connection is MLO.
+@@ -1656,7 +1653,6 @@ struct ieee80211_rx_status {
+ s8 signal;
+ u8 chains;
+ s8 chain_signal[IEEE80211_MAX_CHAINS];
+- u8 ampdu_delimiter_crc;
+ u8 zero_length_psdu_type;
+ u8 link_valid:1, link_id:4;
+ };
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -508,18 +508,13 @@ ieee80211_add_rx_radiotap_header(struct
+ flags |= IEEE80211_RADIOTAP_AMPDU_IS_LAST;
+ if (status->flag & RX_FLAG_AMPDU_DELIM_CRC_ERROR)
+ flags |= IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR;
+- if (status->flag & RX_FLAG_AMPDU_DELIM_CRC_KNOWN)
+- flags |= IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN;
+ if (status->flag & RX_FLAG_AMPDU_EOF_BIT_KNOWN)
+ flags |= IEEE80211_RADIOTAP_AMPDU_EOF_KNOWN;
+ if (status->flag & RX_FLAG_AMPDU_EOF_BIT)
+ flags |= IEEE80211_RADIOTAP_AMPDU_EOF;
+ put_unaligned_le16(flags, pos);
+ pos += 2;
+- if (status->flag & RX_FLAG_AMPDU_DELIM_CRC_KNOWN)
+- *pos++ = status->ampdu_delimiter_crc;
+- else
+- *pos++ = 0;
++ *pos++ = 0;
+ *pos++ = 0;
+ }
+
diff --git a/package/kernel/mac80211/patches/subsys/354-wifi-cfg80211-pass-net_device-to-.set_monitor_channel.patch b/package/kernel/mac80211/patches/subsys/354-wifi-cfg80211-pass-net_device-to-.set_monitor_channel.patch
new file mode 100644
index 00000000000..c2a915963c2
--- /dev/null
+++ b/package/kernel/mac80211/patches/subsys/354-wifi-cfg80211-pass-net_device-to-.set_monitor_channel.patch
@@ -0,0 +1,165 @@
+From: Felix Fietkau
+Date: Thu, 26 Sep 2024 19:52:30 +0200
+Subject: [PATCH] wifi: cfg80211: pass net_device to .set_monitor_channel
+
+Preparation for allowing multiple monitor interfaces with different channels
+on a multi-radio wiphy.
+
+Signed-off-by: Felix Fietkau
+---
+
+--- a/drivers/net/wireless/ath/wil6210/cfg80211.c
++++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
+@@ -1493,6 +1493,7 @@ out:
+ }
+
+ static int wil_cfg80211_set_channel(struct wiphy *wiphy,
++ struct net_device *dev,
+ struct cfg80211_chan_def *chandef)
+ {
+ struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+--- a/drivers/net/wireless/marvell/libertas/cfg.c
++++ b/drivers/net/wireless/marvell/libertas/cfg.c
+@@ -486,6 +486,7 @@ static int lbs_add_wps_enrollee_tlv(u8 *
+ */
+
+ static int lbs_cfg_set_monitor_channel(struct wiphy *wiphy,
++ struct net_device *dev,
+ struct cfg80211_chan_def *chandef)
+ {
+ struct lbs_private *priv = wiphy_priv(wiphy);
+--- a/drivers/net/wireless/microchip/wilc1000/cfg80211.c
++++ b/drivers/net/wireless/microchip/wilc1000/cfg80211.c
+@@ -231,6 +231,7 @@ struct wilc_vif *wilc_get_wl_to_vif(stru
+ }
+
+ static int set_channel(struct wiphy *wiphy,
++ struct net_device *dev,
+ struct cfg80211_chan_def *chandef)
+ {
+ struct wilc *wl = wiphy_priv(wiphy);
+@@ -1424,7 +1425,7 @@ static int start_ap(struct wiphy *wiphy,
+ struct wilc_vif *vif = netdev_priv(dev);
+ int ret;
+
+- ret = set_channel(wiphy, &settings->chandef);
++ ret = set_channel(wiphy, dev, &settings->chandef);
+ if (ret != 0)
+ netdev_err(dev, "Error in setting channel\n");
+
+--- a/include/net/cfg80211.h
++++ b/include/net/cfg80211.h
+@@ -4700,6 +4700,7 @@ struct cfg80211_ops {
+ struct ieee80211_channel *chan);
+
+ int (*set_monitor_channel)(struct wiphy *wiphy,
++ struct net_device *dev,
+ struct cfg80211_chan_def *chandef);
+
+ int (*scan)(struct wiphy *wiphy,
+--- a/net/mac80211/cfg.c
++++ b/net/mac80211/cfg.c
+@@ -879,6 +879,7 @@ static int ieee80211_get_station(struct
+ }
+
+ static int ieee80211_set_monitor_channel(struct wiphy *wiphy,
++ struct net_device *dev,
+ struct cfg80211_chan_def *chandef)
+ {
+ struct ieee80211_local *local = wiphy_priv(wiphy);
+--- a/net/wireless/chan.c
++++ b/net/wireless/chan.c
+@@ -1673,6 +1673,7 @@ bool cfg80211_reg_check_beaconing(struct
+ EXPORT_SYMBOL(cfg80211_reg_check_beaconing);
+
+ int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev,
++ struct net_device *dev,
+ struct cfg80211_chan_def *chandef)
+ {
+ if (!rdev->ops->set_monitor_channel)
+@@ -1680,7 +1681,7 @@ int cfg80211_set_monitor_channel(struct
+ if (!cfg80211_has_monitors_only(rdev))
+ return -EBUSY;
+
+- return rdev_set_monitor_channel(rdev, chandef);
++ return rdev_set_monitor_channel(rdev, dev, chandef);
+ }
+
+ bool cfg80211_any_usable_channels(struct wiphy *wiphy,
+--- a/net/wireless/core.h
++++ b/net/wireless/core.h
+@@ -510,6 +510,7 @@ static inline unsigned int elapsed_jiffi
+ }
+
+ int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev,
++ struct net_device *dev,
+ struct cfg80211_chan_def *chandef);
+
+ int ieee80211_get_ratemask(struct ieee80211_supported_band *sband,
+--- a/net/wireless/nl80211.c
++++ b/net/wireless/nl80211.c
+@@ -3562,7 +3562,7 @@ static int __nl80211_set_channel(struct
+ case NL80211_IFTYPE_MESH_POINT:
+ return cfg80211_set_mesh_channel(rdev, wdev, &chandef);
+ case NL80211_IFTYPE_MONITOR:
+- return cfg80211_set_monitor_channel(rdev, &chandef);
++ return cfg80211_set_monitor_channel(rdev, dev, &chandef);
+ default:
+ break;
+ }
+--- a/net/wireless/rdev-ops.h
++++ b/net/wireless/rdev-ops.h
+@@ -445,11 +445,12 @@ rdev_libertas_set_mesh_channel(struct cf
+
+ static inline int
+ rdev_set_monitor_channel(struct cfg80211_registered_device *rdev,
++ struct net_device *dev,
+ struct cfg80211_chan_def *chandef)
+ {
+ int ret;
+- trace_rdev_set_monitor_channel(&rdev->wiphy, chandef);
+- ret = rdev->ops->set_monitor_channel(&rdev->wiphy, chandef);
++ trace_rdev_set_monitor_channel(&rdev->wiphy, dev, chandef);
++ ret = rdev->ops->set_monitor_channel(&rdev->wiphy, dev, chandef);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+ }
+--- a/net/wireless/trace.h
++++ b/net/wireless/trace.h
+@@ -1318,19 +1318,21 @@ TRACE_EVENT(rdev_libertas_set_mesh_chann
+ );
+
+ TRACE_EVENT(rdev_set_monitor_channel,
+- TP_PROTO(struct wiphy *wiphy,
++ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+ struct cfg80211_chan_def *chandef),
+- TP_ARGS(wiphy, chandef),
++ TP_ARGS(wiphy, netdev, chandef),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
++ NETDEV_ENTRY
+ CHAN_DEF_ENTRY
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
++ NETDEV_ASSIGN;
+ CHAN_DEF_ASSIGN(chandef);
+ ),
+- TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT,
+- WIPHY_PR_ARG, CHAN_DEF_PR_ARG)
++ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " CHAN_DEF_PR_FMT,
++ WIPHY_PR_ARG, NETDEV_PR_ARG, CHAN_DEF_PR_ARG)
+ );
+
+ TRACE_EVENT(rdev_auth,
+--- a/net/wireless/wext-compat.c
++++ b/net/wireless/wext-compat.c
+@@ -830,7 +830,7 @@ static int cfg80211_wext_siwfreq(struct
+ ret = -EINVAL;
+ break;
+ }
+- ret = cfg80211_set_monitor_channel(rdev, &chandef);
++ ret = cfg80211_set_monitor_channel(rdev, dev, &chandef);
+ break;
+ case NL80211_IFTYPE_MESH_POINT:
+ freq = cfg80211_wext_freq(wextfreq);
diff --git a/package/kernel/mac80211/patches/subsys/355-wifi-mac80211-add-flag-to-opt-out-of-virtual-monitor.patch b/package/kernel/mac80211/patches/subsys/355-wifi-mac80211-add-flag-to-opt-out-of-virtual-monitor.patch
new file mode 100644
index 00000000000..2510cb0dbe9
--- /dev/null
+++ b/package/kernel/mac80211/patches/subsys/355-wifi-mac80211-add-flag-to-opt-out-of-virtual-monitor.patch
@@ -0,0 +1,337 @@
+From: Felix Fietkau
+Date: Mon, 30 Sep 2024 15:09:45 +0200
+Subject: [PATCH] wifi: mac80211: add flag to opt out of virtual monitor
+ support
+
+This is useful for multi-radio devices that are capable of monitoring on
+multiple channels simultanenously. When this flag is set, each monitor
+interface is passed to the driver individually and can have a configured
+channel.
+
+Signed-off-by: Felix Fietkau
+---
+
+--- a/include/net/mac80211.h
++++ b/include/net/mac80211.h
+@@ -2679,6 +2679,11 @@ struct ieee80211_txq {
+ * a virtual monitor interface when monitor interfaces are the only
+ * active interfaces.
+ *
++ * @IEEE80211_HW_NO_VIRTUAL_MONITOR: The driver would like to be informed
++ * of any monitor interface, as well as their configured channel.
++ * This is useful for supporting multiple monitor interfaces on different
++ * channels.
++ *
+ * @IEEE80211_HW_NO_AUTO_VIF: The driver would like for no wlanX to
+ * be created. It is expected user-space will create vifs as
+ * desired (and thus have them named as desired).
+@@ -2838,6 +2843,7 @@ enum ieee80211_hw_flags {
+ IEEE80211_HW_SUPPORTS_DYNAMIC_PS,
+ IEEE80211_HW_MFP_CAPABLE,
+ IEEE80211_HW_WANT_MONITOR_VIF,
++ IEEE80211_HW_NO_VIRTUAL_MONITOR,
+ IEEE80211_HW_NO_AUTO_VIF,
+ IEEE80211_HW_SW_CRYPTO_CONTROL,
+ IEEE80211_HW_SUPPORT_FAST_XMIT,
+--- a/net/mac80211/cfg.c
++++ b/net/mac80211/cfg.c
+@@ -105,8 +105,11 @@ static int ieee80211_set_mon_options(str
+ }
+
+ /* also validate MU-MIMO change */
+- monitor_sdata = wiphy_dereference(local->hw.wiphy,
+- local->monitor_sdata);
++ if (ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR))
++ monitor_sdata = sdata;
++ else
++ monitor_sdata = wiphy_dereference(local->hw.wiphy,
++ local->monitor_sdata);
+
+ if (!monitor_sdata &&
+ (params->vht_mumimo_groups || params->vht_mumimo_follow_addr))
+@@ -114,7 +117,9 @@ static int ieee80211_set_mon_options(str
+
+ /* apply all changes now - no failures allowed */
+
+- if (monitor_sdata && ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF))
++ if (monitor_sdata &&
++ (ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF) ||
++ ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR)))
+ ieee80211_set_mu_mimo_follow(monitor_sdata, params);
+
+ if (params->flags) {
+@@ -889,22 +894,25 @@ static int ieee80211_set_monitor_channel
+
+ lockdep_assert_wiphy(local->hw.wiphy);
+
+- if (cfg80211_chandef_identical(&local->monitor_chanreq.oper,
+- &chanreq.oper))
+- return 0;
++ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ if (!ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR)) {
++ if (cfg80211_chandef_identical(&local->monitor_chanreq.oper,
++ &chanreq.oper))
++ return 0;
+
+- sdata = wiphy_dereference(local->hw.wiphy,
+- local->monitor_sdata);
+- if (!sdata)
+- goto done;
++ sdata = wiphy_dereference(wiphy, local->monitor_sdata);
++ if (!sdata)
++ goto done;
++ }
+
+- if (cfg80211_chandef_identical(&sdata->vif.bss_conf.chanreq.oper,
++ if (rcu_access_pointer(sdata->deflink.conf->chanctx_conf) &&
++ cfg80211_chandef_identical(&sdata->vif.bss_conf.chanreq.oper,
+ &chanreq.oper))
+ return 0;
+
+ ieee80211_link_release_channel(&sdata->deflink);
+ ret = ieee80211_link_use_channel(&sdata->deflink, &chanreq,
+- IEEE80211_CHANCTX_EXCLUSIVE);
++ IEEE80211_CHANCTX_SHARED);
+ if (ret)
+ return ret;
+ done:
+@@ -3049,7 +3057,8 @@ static int ieee80211_set_tx_power(struct
+ if (wdev) {
+ sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
+
+- if (sdata->vif.type == NL80211_IFTYPE_MONITOR) {
++ if (sdata->vif.type == NL80211_IFTYPE_MONITOR &&
++ !ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR)) {
+ if (!ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF))
+ return -EOPNOTSUPP;
+
+@@ -3097,7 +3106,8 @@ static int ieee80211_set_tx_power(struct
+ }
+
+ list_for_each_entry(sdata, &local->interfaces, list) {
+- if (sdata->vif.type == NL80211_IFTYPE_MONITOR) {
++ if (sdata->vif.type == NL80211_IFTYPE_MONITOR &&
++ !ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR)) {
+ has_monitor = true;
+ continue;
+ }
+@@ -3107,7 +3117,8 @@ static int ieee80211_set_tx_power(struct
+ sdata->vif.bss_conf.txpower_type = txp_type;
+ }
+ list_for_each_entry(sdata, &local->interfaces, list) {
+- if (sdata->vif.type == NL80211_IFTYPE_MONITOR)
++ if (sdata->vif.type == NL80211_IFTYPE_MONITOR &&
++ !ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR))
+ continue;
+ ieee80211_recalc_txpower(sdata, update_txp_type);
+ }
+@@ -4299,7 +4310,8 @@ static int ieee80211_cfg_get_channel(str
+ if (chanctx_conf) {
+ *chandef = link->conf->chanreq.oper;
+ ret = 0;
+- } else if (local->open_count > 0 &&
++ } else if (!ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR) &&
++ local->open_count > 0 &&
+ local->open_count == local->monitors &&
+ sdata->vif.type == NL80211_IFTYPE_MONITOR) {
+ *chandef = local->monitor_chanreq.oper;
+--- a/net/mac80211/chan.c
++++ b/net/mac80211/chan.c
+@@ -337,6 +337,10 @@ ieee80211_get_chanctx_max_required_bw(st
+ case NL80211_IFTYPE_P2P_DEVICE:
+ case NL80211_IFTYPE_NAN:
+ continue;
++ case NL80211_IFTYPE_MONITOR:
++ WARN_ON_ONCE(!ieee80211_hw_check(&local->hw,
++ NO_VIRTUAL_MONITOR));
++ fallthrough;
+ case NL80211_IFTYPE_ADHOC:
+ case NL80211_IFTYPE_MESH_POINT:
+ case NL80211_IFTYPE_OCB:
+@@ -345,7 +349,6 @@ ieee80211_get_chanctx_max_required_bw(st
+ case NL80211_IFTYPE_WDS:
+ case NL80211_IFTYPE_UNSPECIFIED:
+ case NUM_NL80211_IFTYPES:
+- case NL80211_IFTYPE_MONITOR:
+ case NL80211_IFTYPE_P2P_CLIENT:
+ case NL80211_IFTYPE_P2P_GO:
+ WARN_ON_ONCE(1);
+@@ -954,6 +957,10 @@ void ieee80211_recalc_smps_chanctx(struc
+ if (!link->sdata->u.mgd.associated)
+ continue;
+ break;
++ case NL80211_IFTYPE_MONITOR:
++ if (!ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR))
++ continue;
++ break;
+ case NL80211_IFTYPE_AP:
+ case NL80211_IFTYPE_ADHOC:
+ case NL80211_IFTYPE_MESH_POINT:
+@@ -966,6 +973,11 @@ void ieee80211_recalc_smps_chanctx(struc
+ if (rcu_access_pointer(link->conf->chanctx_conf) != &chanctx->conf)
+ continue;
+
++ if (link->sdata->vif.type == NL80211_IFTYPE_MONITOR) {
++ rx_chains_dynamic = rx_chains_static = local->rx_chains;
++ break;
++ }
++
+ switch (link->smps_mode) {
+ default:
+ WARN_ONCE(1, "Invalid SMPS mode %d\n",
+--- a/net/mac80211/debugfs.c
++++ b/net/mac80211/debugfs.c
+@@ -465,6 +465,7 @@ static const char *hw_flag_names[] = {
+ FLAG(SUPPORTS_DYNAMIC_PS),
+ FLAG(MFP_CAPABLE),
+ FLAG(WANT_MONITOR_VIF),
++ FLAG(NO_VIRTUAL_MONITOR),
+ FLAG(NO_AUTO_VIF),
+ FLAG(SW_CRYPTO_CONTROL),
+ FLAG(SUPPORT_FAST_XMIT),
+--- a/net/mac80211/driver-ops.c
++++ b/net/mac80211/driver-ops.c
+@@ -65,6 +65,7 @@ int drv_add_interface(struct ieee80211_l
+ if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
+ (sdata->vif.type == NL80211_IFTYPE_MONITOR &&
+ !ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF) &&
++ !ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR) &&
+ !(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE))))
+ return -EINVAL;
+
+--- a/net/mac80211/iface.c
++++ b/net/mac80211/iface.c
+@@ -279,8 +279,13 @@ static int _ieee80211_change_mac(struct
+ ret = eth_mac_addr(sdata->dev, sa);
+
+ if (ret == 0) {
+- memcpy(sdata->vif.addr, sa->sa_data, ETH_ALEN);
+- ether_addr_copy(sdata->vif.bss_conf.addr, sdata->vif.addr);
++ if (check_dup) {
++ memcpy(sdata->vif.addr, sa->sa_data, ETH_ALEN);
++ ether_addr_copy(sdata->vif.bss_conf.addr, sdata->vif.addr);
++ } else {
++ memset(sdata->vif.addr, 0, ETH_ALEN);
++ memset(sdata->vif.bss_conf.addr, 0, ETH_ALEN);
++ }
+ }
+
+ /* Regardless of eth_mac_addr() return we still want to add the
+@@ -699,9 +704,11 @@ static void ieee80211_do_stop(struct iee
+ ieee80211_recalc_idle(local);
+ ieee80211_recalc_offload(local);
+
+- if (!(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE))
++ if (!(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) &&
++ !ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR))
+ break;
+
++ ieee80211_link_release_channel(&sdata->deflink);
+ fallthrough;
+ default:
+ if (!going_down)
+@@ -1131,7 +1138,8 @@ int ieee80211_add_virtual_monitor(struct
+ ASSERT_RTNL();
+ lockdep_assert_wiphy(local->hw.wiphy);
+
+- if (local->monitor_sdata)
++ if (local->monitor_sdata ||
++ ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR))
+ return 0;
+
+ sdata = kzalloc(sizeof(*sdata) + local->hw.vif_data_size, GFP_KERNEL);
+@@ -1193,6 +1201,9 @@ void ieee80211_del_virtual_monitor(struc
+ {
+ struct ieee80211_sub_if_data *sdata;
+
++ if (ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR))
++ return;
++
+ ASSERT_RTNL();
+ lockdep_assert_wiphy(local->hw.wiphy);
+
+@@ -1328,7 +1339,8 @@ int ieee80211_do_open(struct wireless_de
+ break;
+ }
+
+- if (sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) {
++ if ((sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) ||
++ ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR)) {
+ res = drv_add_interface(local, sdata);
+ if (res)
+ goto err_stop;
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -840,6 +840,9 @@ ieee80211_rx_monitor(struct ieee80211_lo
+ bool last_monitor = list_is_last(&sdata->u.mntr.list,
+ &local->mon_list);
+
++ if (ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR))
++ ieee80211_handle_mu_mimo_mon(sdata, origskb, rtap_space);
++
+ if (!monskb)
+ monskb = ieee80211_make_monitor_skb(local, &origskb,
+ rate, rtap_space,
+--- a/net/mac80211/tx.c
++++ b/net/mac80211/tx.c
+@@ -1763,7 +1763,8 @@ static bool __ieee80211_tx(struct ieee80
+
+ switch (sdata->vif.type) {
+ case NL80211_IFTYPE_MONITOR:
+- if (sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) {
++ if ((sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) ||
++ ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR)) {
+ vif = &sdata->vif;
+ break;
+ }
+@@ -3952,7 +3953,8 @@ begin:
+
+ switch (tx.sdata->vif.type) {
+ case NL80211_IFTYPE_MONITOR:
+- if (tx.sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) {
++ if ((tx.sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) ||
++ ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR)) {
+ vif = &tx.sdata->vif;
+ break;
+ }
+--- a/net/mac80211/util.c
++++ b/net/mac80211/util.c
+@@ -754,7 +754,8 @@ static void __iterate_interfaces(struct
+ list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+ switch (sdata->vif.type) {
+ case NL80211_IFTYPE_MONITOR:
+- if (!(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE))
++ if (!(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) &&
++ !ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR))
+ continue;
+ break;
+ case NL80211_IFTYPE_AP_VLAN:
+@@ -1857,8 +1858,10 @@ int ieee80211_reconfig(struct ieee80211_
+ }
+
+ list_for_each_entry(sdata, &local->interfaces, list) {
++ if (sdata->vif.type == NL80211_IFTYPE_MONITOR &&
++ !ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR))
++ continue;
+ if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
+- sdata->vif.type != NL80211_IFTYPE_MONITOR &&
+ ieee80211_sdata_running(sdata)) {
+ res = drv_add_interface(local, sdata);
+ if (WARN_ON(res))
+@@ -1871,11 +1874,14 @@ int ieee80211_reconfig(struct ieee80211_
+ */
+ if (res) {
+ list_for_each_entry_continue_reverse(sdata, &local->interfaces,
+- list)
++ list) {
++ if (sdata->vif.type == NL80211_IFTYPE_MONITOR &&
++ !ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR))
++ continue;
+ if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
+- sdata->vif.type != NL80211_IFTYPE_MONITOR &&
+ ieee80211_sdata_running(sdata))
+ drv_remove_interface(local, sdata);
++ }
+ ieee80211_handle_reconfig_failure(local);
+ return res;
+ }
diff --git a/package/kernel/mac80211/patches/subsys/356-wifi-cfg80211-add-monitor-SKIP_TX-flag.patch b/package/kernel/mac80211/patches/subsys/356-wifi-cfg80211-add-monitor-SKIP_TX-flag.patch
new file mode 100644
index 00000000000..dfc01c6c9bc
--- /dev/null
+++ b/package/kernel/mac80211/patches/subsys/356-wifi-cfg80211-add-monitor-SKIP_TX-flag.patch
@@ -0,0 +1,56 @@
+From: Felix Fietkau
+Date: Mon, 30 Sep 2024 17:04:09 +0200
+Subject: [PATCH] wifi: cfg80211: add monitor SKIP_TX flag
+
+This can be used to indicate that the user is not interested in receiving
+locally sent packets on the monitor interface.
+
+Signed-off-by: Felix Fietkau
+---
+
+--- a/include/net/cfg80211.h
++++ b/include/net/cfg80211.h
+@@ -2272,6 +2272,7 @@ static inline int cfg80211_get_station(s
+ * @MONITOR_FLAG_OTHER_BSS: disable BSSID filtering
+ * @MONITOR_FLAG_COOK_FRAMES: report frames after processing
+ * @MONITOR_FLAG_ACTIVE: active monitor, ACKs frames on its MAC address
++ * @MONITOR_FLAG_SKIP_TX: do not pass locally transmitted frames
+ */
+ enum monitor_flags {
+ MONITOR_FLAG_CHANGED = BIT(__NL80211_MNTR_FLAG_INVALID),
+@@ -2281,6 +2282,7 @@ enum monitor_flags {
+ MONITOR_FLAG_OTHER_BSS = BIT(NL80211_MNTR_FLAG_OTHER_BSS),
+ MONITOR_FLAG_COOK_FRAMES = BIT(NL80211_MNTR_FLAG_COOK_FRAMES),
+ MONITOR_FLAG_ACTIVE = BIT(NL80211_MNTR_FLAG_ACTIVE),
++ MONITOR_FLAG_SKIP_TX = BIT(NL80211_MNTR_FLAG_SKIP_TX),
+ };
+
+ /**
+--- a/include/uapi/linux/nl80211.h
++++ b/include/uapi/linux/nl80211.h
+@@ -4703,6 +4703,7 @@ enum nl80211_survey_info {
+ * overrides all other flags.
+ * @NL80211_MNTR_FLAG_ACTIVE: use the configured MAC address
+ * and ACK incoming unicast packets.
++ * @NL80211_MNTR_FLAG_SKIP_TX: do not pass local tx packets
+ *
+ * @__NL80211_MNTR_FLAG_AFTER_LAST: internal use
+ * @NL80211_MNTR_FLAG_MAX: highest possible monitor flag
+@@ -4715,6 +4716,7 @@ enum nl80211_mntr_flags {
+ NL80211_MNTR_FLAG_OTHER_BSS,
+ NL80211_MNTR_FLAG_COOK_FRAMES,
+ NL80211_MNTR_FLAG_ACTIVE,
++ NL80211_MNTR_FLAG_SKIP_TX,
+
+ /* keep last */
+ __NL80211_MNTR_FLAG_AFTER_LAST,
+--- a/net/wireless/nl80211.c
++++ b/net/wireless/nl80211.c
+@@ -4201,6 +4201,7 @@ static const struct nla_policy mntr_flag
+ [NL80211_MNTR_FLAG_OTHER_BSS] = { .type = NLA_FLAG },
+ [NL80211_MNTR_FLAG_COOK_FRAMES] = { .type = NLA_FLAG },
+ [NL80211_MNTR_FLAG_ACTIVE] = { .type = NLA_FLAG },
++ [NL80211_MNTR_FLAG_SKIP_TX] = { .type = NLA_FLAG },
+ };
+
+ static int parse_monitor_flags(struct nlattr *nla, u32 *mntrflags)
diff --git a/package/kernel/mac80211/patches/subsys/357-wifi-mac80211-add-support-for-the-monitor-SKIP_TX-fl.patch b/package/kernel/mac80211/patches/subsys/357-wifi-mac80211-add-support-for-the-monitor-SKIP_TX-fl.patch
new file mode 100644
index 00000000000..e62c15c19d1
--- /dev/null
+++ b/package/kernel/mac80211/patches/subsys/357-wifi-mac80211-add-support-for-the-monitor-SKIP_TX-fl.patch
@@ -0,0 +1,54 @@
+From: Felix Fietkau
+Date: Mon, 30 Sep 2024 17:05:18 +0200
+Subject: [PATCH] wifi: mac80211: add support for the monitor SKIP_TX flag
+
+Do not pass locally sent packets to monitor interfaces with this flag set.
+Skip processing tx packets on the status call entirely if no monitor
+interfaces without this flag are present.
+
+Signed-off-by: Felix Fietkau
+---
+
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -1374,7 +1374,7 @@ struct ieee80211_local {
+ spinlock_t queue_stop_reason_lock;
+
+ int open_count;
+- int monitors, cooked_mntrs;
++ int monitors, cooked_mntrs, tx_mntrs;
+ /* number of interfaces with corresponding FIF_ flags */
+ int fif_fcsfail, fif_plcpfail, fif_control, fif_other_bss, fif_pspoll,
+ fif_probe_req;
+--- a/net/mac80211/iface.c
++++ b/net/mac80211/iface.c
+@@ -1094,6 +1094,8 @@ void ieee80211_adjust_monitor_flags(stru
+ ADJUST(CONTROL, control);
+ ADJUST(CONTROL, pspoll);
+ ADJUST(OTHER_BSS, other_bss);
++ if (!(flags & MONITOR_FLAG_SKIP_TX))
++ local->tx_mntrs += offset;
+
+ #undef ADJUST
+ }
+--- a/net/mac80211/status.c
++++ b/net/mac80211/status.c
+@@ -927,6 +927,9 @@ void ieee80211_tx_monitor(struct ieee802
+ if (!ieee80211_sdata_running(sdata))
+ continue;
+
++ if (sdata->u.mntr.flags & MONITOR_FLAG_SKIP_TX)
++ continue;
++
+ if ((sdata->u.mntr.flags & MONITOR_FLAG_COOK_FRAMES) &&
+ !send_to_cooked)
+ continue;
+@@ -1099,7 +1102,7 @@ static void __ieee80211_tx_status(struct
+ * This is a bit racy but we can avoid a lot of work
+ * with this test...
+ */
+- if (!local->monitors && (!send_to_cooked || !local->cooked_mntrs)) {
++ if (!local->tx_mntrs && (!send_to_cooked || !local->cooked_mntrs)) {
+ if (status->free_list)
+ list_add_tail(&skb->list, status->free_list);
+ else
diff --git a/package/kernel/mac80211/patches/subsys/358-wifi-mac80211-refactor-ieee80211_rx_monitor.patch b/package/kernel/mac80211/patches/subsys/358-wifi-mac80211-refactor-ieee80211_rx_monitor.patch
new file mode 100644
index 00000000000..cc976060d4c
--- /dev/null
+++ b/package/kernel/mac80211/patches/subsys/358-wifi-mac80211-refactor-ieee80211_rx_monitor.patch
@@ -0,0 +1,94 @@
+From: Felix Fietkau
+Date: Wed, 2 Oct 2024 12:31:22 +0200
+Subject: [PATCH] wifi: mac80211: refactor ieee80211_rx_monitor
+
+Rework the monitor mode interface iteration to get rid of the last_monitor
+condition. Preparation for further filtering received monitor packets.
+
+Signed-off-by: Felix Fietkau
+---
+
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -762,8 +762,8 @@ ieee80211_rx_monitor(struct ieee80211_lo
+ struct ieee80211_rate *rate)
+ {
+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(origskb);
+- struct ieee80211_sub_if_data *sdata;
+- struct sk_buff *monskb = NULL;
++ struct ieee80211_sub_if_data *sdata, *prev_sdata = NULL;
++ struct sk_buff *skb, *monskb = NULL;
+ int present_fcs_len = 0;
+ unsigned int rtap_space = 0;
+ struct ieee80211_sub_if_data *monitor_sdata =
+@@ -837,8 +837,10 @@ ieee80211_rx_monitor(struct ieee80211_lo
+ ieee80211_handle_mu_mimo_mon(monitor_sdata, origskb, rtap_space);
+
+ list_for_each_entry_rcu(sdata, &local->mon_list, u.mntr.list) {
+- bool last_monitor = list_is_last(&sdata->u.mntr.list,
+- &local->mon_list);
++ if (!prev_sdata) {
++ prev_sdata = sdata;
++ continue;
++ }
+
+ if (ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR))
+ ieee80211_handle_mu_mimo_mon(sdata, origskb, rtap_space);
+@@ -846,34 +848,34 @@ ieee80211_rx_monitor(struct ieee80211_lo
+ if (!monskb)
+ monskb = ieee80211_make_monitor_skb(local, &origskb,
+ rate, rtap_space,
+- only_monitor &&
+- last_monitor);
+-
+- if (monskb) {
+- struct sk_buff *skb;
++ false);
++ if (!monskb)
++ continue;
+
+- if (last_monitor) {
+- skb = monskb;
+- monskb = NULL;
+- } else {
+- skb = skb_clone(monskb, GFP_ATOMIC);
+- }
++ skb = skb_clone(monskb, GFP_ATOMIC);
++ if (!skb)
++ continue;
++
++ skb->dev = prev_sdata->dev;
++ dev_sw_netstats_rx_add(skb->dev, skb->len);
++ netif_receive_skb(skb);
++ prev_sdata = sdata;
++ }
+
+- if (skb) {
+- skb->dev = sdata->dev;
+- dev_sw_netstats_rx_add(skb->dev, skb->len);
+- netif_receive_skb(skb);
+- }
++ if (prev_sdata) {
++ if (monskb)
++ skb = monskb;
++ else
++ skb = ieee80211_make_monitor_skb(local, &origskb,
++ rate, rtap_space,
++ only_monitor);
++ if (skb) {
++ skb->dev = prev_sdata->dev;
++ dev_sw_netstats_rx_add(skb->dev, skb->len);
++ netif_receive_skb(skb);
+ }
+-
+- if (last_monitor)
+- break;
+ }
+
+- /* this happens if last_monitor was erroneously false */
+- dev_kfree_skb(monskb);
+-
+- /* ditto */
+ if (!origskb)
+ return NULL;
+
diff --git a/package/kernel/mac80211/patches/subsys/359-wifi-mac80211-filter-on-monitor-interfaces-based-on-.patch b/package/kernel/mac80211/patches/subsys/359-wifi-mac80211-filter-on-monitor-interfaces-based-on-.patch
new file mode 100644
index 00000000000..4b2c67aeba5
--- /dev/null
+++ b/package/kernel/mac80211/patches/subsys/359-wifi-mac80211-filter-on-monitor-interfaces-based-on-.patch
@@ -0,0 +1,29 @@
+From: Felix Fietkau
+Date: Wed, 2 Oct 2024 12:35:13 +0200
+Subject: [PATCH] wifi: mac80211: filter on monitor interfaces based on
+ configured channel
+
+When a monitor interface has an assigned channel (only happens with the
+NO_VIRTUAL_MONITOR feature), only pass packets received on that channel.
+This is useful for monitoring on multiple channels at the same time using
+multiple monitor interfaces.
+
+Signed-off-by: Felix Fietkau
+---
+
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -837,6 +837,13 @@ ieee80211_rx_monitor(struct ieee80211_lo
+ ieee80211_handle_mu_mimo_mon(monitor_sdata, origskb, rtap_space);
+
+ list_for_each_entry_rcu(sdata, &local->mon_list, u.mntr.list) {
++ struct cfg80211_chan_def *chandef;
++
++ chandef = &sdata->vif.bss_conf.chanreq.oper;
++ if (chandef->chan &&
++ chandef->chan->center_freq != status->freq)
++ continue;
++
+ if (!prev_sdata) {
+ prev_sdata = sdata;
+ continue;
diff --git a/package/kernel/mac80211/patches/subsys/360-wifi-cfg80211-report-per-wiphy-radio-antenna-mask.patch b/package/kernel/mac80211/patches/subsys/360-wifi-cfg80211-report-per-wiphy-radio-antenna-mask.patch
new file mode 100644
index 00000000000..178e01dc163
--- /dev/null
+++ b/package/kernel/mac80211/patches/subsys/360-wifi-cfg80211-report-per-wiphy-radio-antenna-mask.patch
@@ -0,0 +1,64 @@
+From: Felix Fietkau
+Date: Wed, 7 Aug 2024 13:31:07 +0200
+Subject: [PATCH] wifi: cfg80211: report per wiphy radio antenna mask
+
+With multi-radio devices, each radio typically gets a fixed set of antennas.
+In order to be able to disable specific antennas for some radios, user space
+needs to know which antenna mask bits are assigned to which radio.
+
+Signed-off-by: Felix Fietkau
+---
+
+--- a/include/net/cfg80211.h
++++ b/include/net/cfg80211.h
+@@ -5443,6 +5443,8 @@ struct wiphy_radio_freq_range {
+ * @iface_combinations: Valid interface combinations array, should not
+ * list single interface types.
+ * @n_iface_combinations: number of entries in @iface_combinations array.
++ *
++ * @antenna_mask: bitmask of antennas connected to this radio.
+ */
+ struct wiphy_radio {
+ const struct wiphy_radio_freq_range *freq_range;
+@@ -5450,6 +5452,8 @@ struct wiphy_radio {
+
+ const struct ieee80211_iface_combination *iface_combinations;
+ int n_iface_combinations;
++
++ u32 antenna_mask;
+ };
+
+ #define CFG80211_HW_TIMESTAMP_ALL_PEERS 0xffff
+--- a/include/uapi/linux/nl80211.h
++++ b/include/uapi/linux/nl80211.h
+@@ -8038,6 +8038,8 @@ enum nl80211_ap_settings_flags {
+ * @NL80211_WIPHY_RADIO_ATTR_INTERFACE_COMBINATION: Supported interface
+ * combination for this radio. Attribute may be present multiple times
+ * and contains attributes defined in &enum nl80211_if_combination_attrs.
++ * @NL80211_WIPHY_RADIO_ATTR_ANTENNA_MASK: bitmask (u32) of antennas
++ * connected to this radio.
+ *
+ * @__NL80211_WIPHY_RADIO_ATTR_LAST: Internal
+ * @NL80211_WIPHY_RADIO_ATTR_MAX: Highest attribute
+@@ -8048,6 +8050,7 @@ enum nl80211_wiphy_radio_attrs {
+ NL80211_WIPHY_RADIO_ATTR_INDEX,
+ NL80211_WIPHY_RADIO_ATTR_FREQ_RANGE,
+ NL80211_WIPHY_RADIO_ATTR_INTERFACE_COMBINATION,
++ NL80211_WIPHY_RADIO_ATTR_ANTENNA_MASK,
+
+ /* keep last */
+ __NL80211_WIPHY_RADIO_ATTR_LAST,
+--- a/net/wireless/nl80211.c
++++ b/net/wireless/nl80211.c
+@@ -2431,6 +2431,11 @@ static int nl80211_put_radio(struct wiph
+ if (nla_put_u32(msg, NL80211_WIPHY_RADIO_ATTR_INDEX, idx))
+ goto nla_put_failure;
+
++ if (r->antenna_mask &&
++ nla_put_u32(msg, NL80211_WIPHY_RADIO_ATTR_ANTENNA_MASK,
++ r->antenna_mask))
++ goto nla_put_failure;
++
+ for (i = 0; i < r->n_freq_range; i++) {
+ const struct wiphy_radio_freq_range *range = &r->freq_range[i];
+
diff --git a/package/libs/mbedtls/Makefile b/package/libs/mbedtls/Makefile
index 19d8c273034..2efdf86cd20 100644
--- a/package/libs/mbedtls/Makefile
+++ b/package/libs/mbedtls/Makefile
@@ -8,13 +8,13 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=mbedtls
-PKG_VERSION:=3.6.1
+PKG_VERSION:=3.6.2
PKG_RELEASE:=1
PKG_BUILD_FLAGS:=no-mips16 gc-sections no-lto
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
PKG_SOURCE_URL=https://github.com/Mbed-TLS/$(PKG_NAME)/releases/download/$(PKG_NAME)-$(PKG_VERSION)
-PKG_HASH:=fc8bef0991b43629b7e5319de6f34f13359011105e08e3e16eed3a9fe6ffd3a3
+PKG_HASH:=8b54fb9bcf4d5a7078028e0520acddefb7900b3e66fec7f7175bb5b7d85ccdca
PKG_LICENSE:=GPL-2.0-or-later
PKG_LICENSE_FILES:=LICENSE
diff --git a/package/libs/uclient/Makefile b/package/libs/uclient/Makefile
index 10ed668814b..065e089bdc4 100644
--- a/package/libs/uclient/Makefile
+++ b/package/libs/uclient/Makefile
@@ -5,9 +5,9 @@ PKG_RELEASE=1
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL=$(PROJECT_GIT)/project/uclient.git
-PKG_MIRROR_HASH:=b3d2a5948cd1d3bb9a05515f0b07364e1da74bd99b3d8ebc4cff316eb271348e
-PKG_SOURCE_DATE:=2024-06-27
-PKG_SOURCE_VERSION:=a220818a1435cfa2b153aa36e6b9c543546fd9b8
+PKG_MIRROR_HASH:=13af83ef1db3665d38d3c0cf30b5223216b05eaeca4880d7ef7494610ddd7458
+PKG_SOURCE_DATE:=2024-10-22
+PKG_SOURCE_VERSION:=88ae8f208dd313f69e268234f7db55956aef1cb9
CMAKE_INSTALL:=1
PKG_BUILD_DEPENDS:=ustream-ssl
diff --git a/package/network/config/wifi-scripts/files/lib/netifd/wireless/mac80211.sh b/package/network/config/wifi-scripts/files/lib/netifd/wireless/mac80211.sh
index 23e557105bd..9998e26ec13 100755
--- a/package/network/config/wifi-scripts/files/lib/netifd/wireless/mac80211.sh
+++ b/package/network/config/wifi-scripts/files/lib/netifd/wireless/mac80211.sh
@@ -29,7 +29,7 @@ drv_mac80211_init_device_config() {
config_add_string path phy 'macaddr:macaddr'
config_add_string tx_burst
config_add_string distance
- config_add_int beacon_int chanbw frag rts
+ config_add_int radio beacon_int chanbw frag rts
config_add_int rxantenna txantenna txpower min_tx_power
config_add_int num_global_macaddr multiple_bssid
config_add_boolean noscan ht_coex acs_exclude_dfs background_radar
@@ -556,7 +556,7 @@ mac80211_hostapd_setup_bss() {
}
[ "$staidx" -gt 0 -o "$start_disabled" -eq 1 ] && append hostapd_cfg "start_disabled=1" "$N"
- cat >> /var/run/hostapd-$phy.conf <> /var/run/hostapd-$phy$vif_phy_suffix.conf < /dev/null
+ ubus_call hostapd config_set '{ "phy": "'"$phy"'", "radio": '"$radio"', "config": "", "prev_config": "'"${hostapd_conf_file}.prev"'" }' > /dev/null
return 0;
}
ubus wait_for hostapd
- local hostapd_res="$(ubus_call hostapd config_set "{ \"phy\": \"$phy\", \"config\":\"${hostapd_conf_file}\", \"prev_config\": \"${hostapd_conf_file}.prev\"}")"
+ local hostapd_res="$(ubus_call hostapd config_set "{ \"phy\": \"$phy\", \"radio\": $radio, \"config\":\"${hostapd_conf_file}\", \"prev_config\": \"${hostapd_conf_file}.prev\"}")"
ret="$?"
[ "$ret" != 0 -o -z "$hostapd_res" ] && {
wireless_setup_failed HOSTAPD_START_FAILED
@@ -965,10 +975,11 @@ hostapd_set_config() {
wpa_supplicant_start() {
local phy="$1"
+ local radio="$2"
[ -n "$wpa_supp_init" ] || return 0
- ubus_call wpa_supplicant config_set '{ "phy": "'"$phy"'", "num_global_macaddr": '"$num_global_macaddr"' }' > /dev/null
+ ubus_call wpa_supplicant config_set '{ "phy": "'"$phy"'", "radio": '"$radio"', "num_global_macaddr": '"$num_global_macaddr"' }' > /dev/null
}
mac80211_setup_supplicant() {
@@ -1073,18 +1084,23 @@ drv_mac80211_cleanup() {
}
mac80211_reset_config() {
- local phy="$1"
+ hostapd_conf_file="/var/run/hostapd-$phy$vif_phy_suffix.conf"
+ ubus_call hostapd config_set '{ "phy": "'"$phy"'", "radio": '"$radio"', "config": "", "prev_config": "'"$hostapd_conf_file"'" }' > /dev/null
+ ubus_call wpa_supplicant config_set '{ "phy": "'"$phy"'", "radio": '"$radio"', "config": [] }' > /dev/null
+ wdev_tool "$phy$phy_suffix" set_config '{}'
+}
- hostapd_conf_file="/var/run/hostapd-$phy.conf"
- ubus_call hostapd config_set '{ "phy": "'"$phy"'", "config": "", "prev_config": "'"$hostapd_conf_file"'" }' > /dev/null
- ubus_call wpa_supplicant config_set '{ "phy": "'"$phy"'", "config": [] }' > /dev/null
- wdev_tool "$phy" set_config '{}'
+mac80211_set_suffix() {
+ [ "$radio" = "-1" ] && radio=
+ phy_suffix="${radio:+:$radio}"
+ vif_phy_suffix="${radio:+.$radio}"
+ set_default radio -1
}
drv_mac80211_setup() {
json_select config
json_get_vars \
- phy macaddr path \
+ radio phy macaddr path \
country chanbw distance \
txpower \
rxantenna txantenna \
@@ -1094,6 +1110,8 @@ drv_mac80211_setup() {
json_get_values scan_list scan_list
json_select ..
+ mac80211_set_suffix
+
json_select data && {
json_get_var prev_rxantenna rxantenna
json_get_var prev_txantenna txantenna
@@ -1120,7 +1138,7 @@ drv_mac80211_setup() {
}
}
- hostapd_conf_file="/var/run/hostapd-$phy.conf"
+ hostapd_conf_file="/var/run/hostapd-$phy$vif_phy_suffix.conf"
macidx=0
staidx=0
@@ -1139,17 +1157,11 @@ drv_mac80211_setup() {
[ "$rxantenna" = "all" ] && rxantenna=0xffffffff
[ "$rxantenna" = "$prev_rxantenna" -a "$txantenna" = "$prev_txantenna" ] || mac80211_reset_config "$phy"
- wireless_set_data phy="$phy" txantenna="$txantenna" rxantenna="$rxantenna"
+ wireless_set_data phy="$phy" radio="$radio" txantenna="$txantenna" rxantenna="$rxantenna"
iw phy "$phy" set antenna $txantenna $rxantenna >/dev/null 2>&1
iw phy "$phy" set distance "$distance" >/dev/null 2>&1
- if [ -n "$txpower" ]; then
- iw phy "$phy" set txpower fixed "${txpower%%.*}00"
- else
- iw phy "$phy" set txpower auto
- fi
-
[ -n "$frag" ] && iw phy "$phy" set frag "${frag%%.*}"
[ -n "$rts" ] && iw phy "$phy" set rts "${rts%%.*}"
@@ -1177,13 +1189,13 @@ drv_mac80211_setup() {
for_each_interface "ap sta adhoc mesh monitor" mac80211_prepare_vif
for_each_interface "ap sta adhoc mesh monitor" mac80211_setup_vif
- [ -x /usr/sbin/wpa_supplicant ] && wpa_supplicant_set_config "$phy"
- [ -x /usr/sbin/hostapd ] && hostapd_set_config "$phy"
+ [ -x /usr/sbin/wpa_supplicant ] && wpa_supplicant_set_config "$phy" "$radio"
+ [ -x /usr/sbin/hostapd ] && hostapd_set_config "$phy" "$radio"
- [ -x /usr/sbin/wpa_supplicant ] && wpa_supplicant_start "$phy"
+ [ -x /usr/sbin/wpa_supplicant ] && wpa_supplicant_start "$phy" "$radio"
json_set_namespace wdev_uc prev
- wdev_tool "$phy" set_config "$(json_dump)" $active_ifnames
+ wdev_tool "$phy$phy_suffix" set_config "$(json_dump)" $active_ifnames
json_set_namespace "$prev"
for_each_interface "ap sta adhoc mesh monitor" mac80211_set_vif_txpower
@@ -1210,19 +1222,15 @@ list_phy_interfaces() {
drv_mac80211_teardown() {
json_select data
- json_get_vars phy
+ json_get_vars phy radio
json_select ..
[ -n "$phy" ] || {
echo "Bug: PHY is undefined for device '$1'"
return 1
}
+ mac80211_set_suffix
mac80211_reset_config "$phy"
-
- for wdev in $(list_phy_interfaces "$phy"); do
- ip link set dev "$wdev" down
- iw dev "$wdev" del
- done
}
add_driver mac80211
diff --git a/package/network/config/wifi-scripts/files/lib/wifi/mac80211.uc b/package/network/config/wifi-scripts/files/lib/wifi/mac80211.uc
index 9fd6c35e8b4..e82525e247d 100644
--- a/package/network/config/wifi-scripts/files/lib/wifi/mac80211.uc
+++ b/package/network/config/wifi-scripts/files/lib/wifi/mac80211.uc
@@ -14,10 +14,12 @@ let commit;
let config = uci.cursor().get_all("wireless") ?? {};
-function radio_exists(path, macaddr, phy) {
+function radio_exists(path, macaddr, phy, radio) {
for (let name, s in config) {
if (s[".type"] != "wifi-device")
continue;
+ if (radio != null && int(s.radio) != radio)
+ continue;
if (s.macaddr & lc(s.macaddr) == lc(macaddr))
return true;
if (s.phy == phy)
@@ -34,55 +36,61 @@ for (let phy_name, phy in board.wlan) {
if (!info || !length(info.bands))
continue;
- while (config[`radio${idx}`])
- idx++;
- let name = "radio" + idx++;
+ let radios = length(info.radios) > 0 ? info.radios : [{ bands: info.bands }];
+ for (let radio in radios) {
+ while (config[`radio${idx}`])
+ idx++;
+ let name = "radio" + idx;
- let s = "wireless." + name;
- let si = "wireless.default_" + name;
+ let s = "wireless." + name;
+ let si = "wireless.default_" + name;
- let band_name = filter(bands_order, (b) => info.bands[b])[0];
- if (!band_name)
- continue;
+ let band_name = filter(bands_order, (b) => radio.bands[b])[0];
+ if (!band_name)
+ continue;
- let band = info.bands[band_name];
- let channel = band.default_channel ?? "auto";
+ let band = info.bands[band_name];
+ let rband = radio.bands[band_name];
+ let channel = rband.default_channel ?? "auto";
- let width = band.max_width;
- if (band_name == "2G")
- width = 20;
- else if (width > 80)
- width = 80;
+ let width = band.max_width;
+ if (band_name == "2G")
+ width = 20;
+ else if (width > 80)
+ width = 80;
- let htmode = filter(htmode_order, (m) => band[lc(m)])[0];
- if (htmode)
- htmode += width;
- else
- htmode = "NOHT";
+ let htmode = filter(htmode_order, (m) => band[lc(m)])[0];
+ if (htmode)
+ htmode += width;
+ else
+ htmode = "NOHT";
- if (!phy.path)
- continue;
+ if (!phy.path)
+ continue;
- let macaddr = trim(readfile(`/sys/class/ieee80211/${phy_name}/macaddress`));
- if (radio_exists(phy.path, macaddr, phy_name))
- continue;
+ let macaddr = trim(readfile(`/sys/class/ieee80211/${phy_name}/macaddress`));
+ if (radio_exists(phy.path, macaddr, phy_name, radio.index))
+ continue;
- let id = `phy='${phy_name}'`;
- if (match(phy_name, /^phy[0-9]/))
- id = `path='${phy.path}'`;
+ let id = `phy='${phy_name}'`;
+ if (match(phy_name, /^phy[0-9]/))
+ id = `path='${phy.path}'`;
- band_name = lc(band_name);
+ band_name = lc(band_name);
- let country, defaults, num_global_macaddr;
- if (board.wlan.defaults) {
- defaults = board.wlan.defaults.ssids?.[band_name]?.ssid ? board.wlan.defaults.ssids?.[band_name] : board.wlan.defaults.ssids?.all;
- country = board.wlan.defaults.country;
- if (!country && band_name != '2g')
- defaults = null;
- num_global_macaddr = board.wlan.defaults.ssids?.[band_name]?.mac_count;
- }
+ let country, defaults, num_global_macaddr;
+ if (board.wlan.defaults) {
+ defaults = board.wlan.defaults.ssids?.[band_name]?.ssid ? board.wlan.defaults.ssids?.[band_name] : board.wlan.defaults.ssids?.all;
+ country = board.wlan.defaults.country;
+ if (!country && band_name != '2g')
+ defaults = null;
+ num_global_macaddr = board.wlan.defaults.ssids?.[band_name]?.mac_count;
+ }
- print(`set ${s}=wifi-device
+ if (length(info.radios) > 0)
+ id += `\nset ${s}.radio='${radio.index}'`;
+
+ print(`set ${s}=wifi-device
set ${s}.type='mac80211'
set ${s}.${id}
set ${s}.band='${band_name}'
@@ -101,7 +109,9 @@ set ${si}.encryption='${defaults?.encryption || "none"}'
set ${si}.key='${defaults?.key || ""}'
`);
- commit = true;
+ config[name] = {};
+ commit = true;
+ }
}
if (commit)
diff --git a/package/network/config/wifi-scripts/files/usr/share/hostap/common.uc b/package/network/config/wifi-scripts/files/usr/share/hostap/common.uc
index 750e3ae71c2..c6bfb62ef3c 100644
--- a/package/network/config/wifi-scripts/files/usr/share/hostap/common.uc
+++ b/package/network/config/wifi-scripts/files/usr/share/hostap/common.uc
@@ -1,6 +1,6 @@
import * as nl80211 from "nl80211";
import * as rtnl from "rtnl";
-import { readfile, glob, basename, readlink } from "fs";
+import { readfile, glob, basename, readlink, open } from "fs";
const iftypes = {
ap: nl80211.const.NL80211_IFTYPE_AP,
@@ -74,6 +74,14 @@ function find_reusable_wdev(phyidx)
return null;
}
+function wdev_set_radio_mask(name, mask)
+{
+ nl80211.request(nl80211.const.NL80211_CMD_SET_INTERFACE, 0, {
+ dev: name,
+ vif_radio_mask: mask
+ });
+}
+
function wdev_create(phy, name, data)
{
let phyidx = int(readfile(`/sys/class/ieee80211/${phy}/index`));
@@ -93,24 +101,24 @@ function wdev_create(phy, name, data)
req["4addr"] = data["4addr"];
if (data.macaddr)
req.mac = data.macaddr;
+ if (data.radio != null && data.radio >= 0)
+ req.vif_radio_mask = 1 << data.radio;
nl80211.error();
let reuse_ifname = find_reusable_wdev(phyidx);
if (reuse_ifname &&
(reuse_ifname == name ||
- rtnl.request(rtnl.const.RTM_SETLINK, 0, { dev: reuse_ifname, ifname: name}) != false))
- nl80211.request(
- nl80211.const.NL80211_CMD_SET_INTERFACE, 0, {
- wiphy: phyidx,
- dev: name,
- iftype: iftypes[data.mode],
- });
- else
+ rtnl.request(rtnl.const.RTM_SETLINK, 0, { dev: reuse_ifname, ifname: name}) != false)) {
+ req.dev = req.ifname;
+ delete req.ifname;
+ nl80211.request(nl80211.const.NL80211_CMD_SET_INTERFACE, 0, req);
+ } else {
nl80211.request(
nl80211.const.NL80211_CMD_NEW_INTERFACE,
nl80211.const.NLM_F_CREATE,
req);
+ }
let error = nl80211.error();
if (error)
@@ -190,7 +198,8 @@ const phy_proto = {
},
macaddr_generate: function(data) {
- let phy = this.name;
+ let phy = this.phy;
+ let radio_idx = this.radio;
let idx = int(data.id ?? 0);
let mbssid = int(data.mbssid ?? 0) > 0;
let num_global = int(data.num_global ?? 1);
@@ -200,22 +209,30 @@ const phy_proto = {
if (!base_addr)
return null;
- if (!idx && !mbssid)
- return base_addr;
-
let base_mask = phy_sysfs_file(phy, "address_mask");
if (!base_mask)
return null;
- if (base_mask == "00:00:00:00:00:00" && idx >= num_global) {
+ if (base_mask == "00:00:00:00:00:00" &&
+ (radio_idx > 0 || idx >= num_global)) {
let addrs = split(phy_sysfs_file(phy, "addresses"), "\n");
- if (idx < length(addrs))
- return addrs[idx];
+ if (radio_idx != null) {
+ if (radio_idx && radio_idx < length(addrs))
+ base_addr = addrs[radio_idx];
+ else
+ idx += radio_idx * 16;
+ } else {
+ if (idx < length(addrs))
+ return addrs[idx];
- base_mask = "ff:ff:ff:ff:ff:ff";
+ base_mask = "ff:ff:ff:ff:ff:ff";
+ }
}
+ if (!idx && !mbssid)
+ return base_addr;
+
let addr = macaddr_split(base_addr);
let mask = macaddr_split(base_mask);
let type;
@@ -275,27 +292,55 @@ const phy_proto = {
}
},
+ wdev_add: function(name, data) {
+ let phydev = this;
+ wdev_create(this.phy, name, {
+ ...data,
+ radio: this.radio,
+ });
+ },
+
for_each_wdev: function(cb) {
- let wdevs = glob(`/sys/class/ieee80211/${this.name}/device/net/*`);
- wdevs = map(wdevs, (arg) => basename(arg));
+ let wdevs = nl80211.request(
+ nl80211.const.NL80211_CMD_GET_INTERFACE,
+ nl80211.const.NLM_F_DUMP,
+ { wiphy: this.idx }
+ );
+
+ let mac_wdev = {};
for (let wdev in wdevs) {
- if (basename(readlink(`/sys/class/net/${wdev}/phy80211`)) != this.name)
+ if (wdev.iftype == nl80211.const.NL80211_IFTYPE_AP_VLAN)
+ continue;
+ if (this.radio != null && wdev.vif_radio_mask != null &&
+ !(wdev.vif_radio_mask & (1 << this.radio)))
continue;
+ mac_wdev[wdev.mac] = wdev;
+ }
- cb(wdev);
+ for (let wdev in wdevs) {
+ if (!mac_wdev[wdev.mac])
+ continue;
+
+ cb(wdev.ifname);
}
}
};
-function phy_open(phy)
+function phy_open(phy, radio)
{
let phyidx = readfile(`/sys/class/ieee80211/${phy}/index`);
if (!phyidx)
return null;
+ let name = phy;
+ if (radio === "" || radio < 0)
+ radio = null;
+ if (radio != null)
+ name += "." + radio;
+
return proto({
- name: phy,
- idx: int(phyidx)
+ phy, name, radio,
+ idx: int(phyidx),
}, phy_proto);
}
@@ -365,9 +410,9 @@ function is_equal(val1, val2) {
function vlist_new(cb) {
return proto({
- cb: cb,
- data: {}
- }, vlist_proto);
+ cb: cb,
+ data: {}
+ }, vlist_proto);
}
-export { wdev_remove, wdev_create, wdev_set_mesh_params, wdev_set_up, is_equal, vlist_new, phy_is_fullmac, phy_open };
+export { wdev_remove, wdev_create, wdev_set_mesh_params, wdev_set_radio_mask, wdev_set_up, is_equal, vlist_new, phy_is_fullmac, phy_open };
diff --git a/package/network/config/wifi-scripts/files/usr/share/hostap/wdev.uc b/package/network/config/wifi-scripts/files/usr/share/hostap/wdev.uc
index d505e3035ff..d836a930fc4 100644
--- a/package/network/config/wifi-scripts/files/usr/share/hostap/wdev.uc
+++ b/package/network/config/wifi-scripts/files/usr/share/hostap/wdev.uc
@@ -1,13 +1,13 @@
#!/usr/bin/env ucode
'use strict';
-import { vlist_new, is_equal, wdev_create, wdev_set_mesh_params, wdev_remove, wdev_set_up, phy_open } from "/usr/share/hostap/common.uc";
+import { vlist_new, is_equal, wdev_set_mesh_params, wdev_remove, wdev_set_up, phy_open } from "/usr/share/hostap/common.uc";
import { readfile, writefile, basename, readlink, glob } from "fs";
let libubus = require("ubus");
let keep_devices = {};
-let phy = shift(ARGV);
+let phy_name = shift(ARGV);
let command = shift(ARGV);
-let phydev;
+let phy, phydev;
function iface_stop(wdev)
{
@@ -30,7 +30,7 @@ function iface_start(wdev)
wdev_config[key] = wdev[key];
if (!wdev_config.macaddr && wdev.mode != "monitor")
wdev_config.macaddr = phydev.macaddr_next();
- wdev_create(phy, ifname, wdev_config);
+ phydev.wdev_add(ifname, wdev_config);
wdev_set_up(ifname, true);
let htmode = wdev.htmode || "NOHT";
if (wdev.freq)
@@ -85,20 +85,15 @@ function delete_ifname(config)
delete config[key].ifname;
}
-function add_existing(phy, config)
+function add_existing(phydev, config)
{
- let wdevs = glob(`/sys/class/ieee80211/${phy}/device/net/*`);
- wdevs = map(wdevs, (arg) => basename(arg));
- for (let wdev in wdevs) {
+ phydev.for_each_wdev((wdev) => {
if (config[wdev])
- continue;
-
- if (basename(readlink(`/sys/class/net/${wdev}/phy80211`)) != phy)
- continue;
+ return;
if (trim(readfile(`/sys/class/net/${wdev}/operstate`)) == "down")
config[wdev] = {};
- }
+ });
}
function usage()
@@ -114,7 +109,7 @@ Commands:
const commands = {
set_config: function(args) {
- let statefile = `/var/run/wdev-${phy}.json`;
+ let statefile = `/var/run/wdev-${phy_name}.json`;
let new_config = shift(args);
for (let dev in ARGV)
@@ -137,12 +132,12 @@ const commands = {
if (type(old_config) == "object")
config.data = old_config;
- add_existing(phy, config.data);
+ add_existing(phydev, config.data);
add_ifname(config.data);
drop_inactive(config.data);
let ubus = libubus.connect();
- let data = ubus.call("hostapd", "config_get_macaddr_list", { phy: phy });
+ let data = ubus.call("hostapd", "config_get_macaddr_list", { phy: phydev.name, radio: phydev.radio ?? -1 });
let macaddr_list = [];
if (type(data) == "object" && data.macaddr)
macaddr_list = data.macaddr;
@@ -166,7 +161,7 @@ const commands = {
let macaddr = phydev.macaddr_generate(data);
if (!macaddr) {
- warn(`Could not get MAC address for phy ${phy}\n`);
+ warn(`Could not get MAC address for phy ${phy_name}\n`);
exit(1);
}
@@ -174,12 +169,14 @@ const commands = {
},
};
-if (!phy || !command | !commands[command])
+if (!phy_name || !command | !commands[command])
usage();
-phydev = phy_open(phy);
+let phy_split = split(phy_name, ":");
+phydev = phy_open(phy_split[0], phy_split[1]);
+phy = phydev.phy;
if (!phydev) {
- warn(`PHY ${phy} does not exist\n`);
+ warn(`PHY ${phy_name} does not exist\n`);
exit(1);
}
diff --git a/package/network/config/wifi-scripts/files/usr/share/hostap/wifi-detect.uc b/package/network/config/wifi-scripts/files/usr/share/hostap/wifi-detect.uc
index ee9155b3d0b..db862d40c2a 100644
--- a/package/network/config/wifi-scripts/files/usr/share/hostap/wifi-detect.uc
+++ b/package/network/config/wifi-scripts/files/usr/share/hostap/wifi-detect.uc
@@ -73,6 +73,15 @@ function freq_to_channel(freq) {
return 0;
}
+function freq_range_match(ranges, freq) {
+ freq *= 1000;
+ for (let range in ranges) {
+ if (freq >= range[0] && freq <= range[1])
+ return true;
+ }
+ return false;
+}
+
function wiphy_detect() {
let phys = nl.request(nl.const.NL80211_CMD_GET_WIPHY, nl.const.NLM_F_DUMP, { split_wiphy_dump: true });
if (!phys)
@@ -88,8 +97,27 @@ function wiphy_detect() {
antenna_rx: phy.wiphy_antenna_avail_rx,
antenna_tx: phy.wiphy_antenna_avail_tx,
bands: {},
+ radios: []
};
+ for (let radio in phy.radios) {
+ // S1G is not supported yet
+ radio.freq_ranges = filter(radio.freq_ranges,
+ (range) => range.end > 2000000
+ );
+
+ if (!length(radio.freq_ranges))
+ continue;
+
+ push(info.radios, {
+ index: radio.index,
+ freq_ranges: map(radio.freq_ranges,
+ (range) => [ range.start, range.end ]
+ ),
+ bands: {}
+ });
+ }
+
let bands = info.bands;
for (let band in phy.wiphy_bands) {
if (!band || !band.freqs)
@@ -160,6 +188,25 @@ function wiphy_detect() {
if (eht_phy_cap && he_phy_cap & 2)
push(modes, "EHT40");
+ for (let radio in info.radios) {
+ let freq_match = filter(band.freqs,
+ (freq) => freq_range_match(radio.freq_ranges, freq.freq)
+ );
+ if (!length(freq_match))
+ continue;
+
+ let radio_band = {};
+ radio.bands[band_name] = radio_band;
+
+ freq_match = filter(freq_match,
+ (freq) => !freq.disabled
+ );
+
+ let freq = freq_match[0];
+ if (freq)
+ radio_band.default_channel = freq_to_channel(freq.freq);
+ }
+
for (let freq in band.freqs) {
if (freq.disabled)
continue;
diff --git a/package/network/services/hostapd/files/hostapd.uc b/package/network/services/hostapd/files/hostapd.uc
index 6bcb32131d9..2d9ce287490 100644
--- a/package/network/services/hostapd/files/hostapd.uc
+++ b/package/network/services/hostapd/files/hostapd.uc
@@ -1,6 +1,6 @@
let libubus = require("ubus");
import { open, readfile } from "fs";
-import { wdev_create, wdev_remove, is_equal, vlist_new, phy_is_fullmac, phy_open } from "common";
+import { wdev_remove, is_equal, vlist_new, phy_is_fullmac, phy_open, wdev_set_radio_mask } from "common";
let ubus = libubus.connect(null, 60);
@@ -30,6 +30,23 @@ hostapd.data.iface_fields = {
iapp_interface: true,
};
+hostapd.data.bss_info_fields = {
+ // radio
+ hw_mode: true,
+ channel: true,
+ ieee80211ac: true,
+ ieee80211ax: true,
+
+ // bss
+ bssid: true,
+ ssid: true,
+ wpa: true,
+ wpa_key_mgmt: true,
+ wpa_pairwise: true,
+ auth_algs: true,
+ ieee80211w: true,
+};
+
function iface_remove(cfg)
{
if (!cfg || !cfg.bss || !cfg.bss[0] || !cfg.bss[0].ifname)
@@ -39,7 +56,7 @@ function iface_remove(cfg)
wdev_remove(bss.ifname);
}
-function iface_gen_config(phy, config, start_disabled)
+function iface_gen_config(config, start_disabled)
{
let str = `data:
${join("\n", config.radio.data)}
@@ -100,7 +117,7 @@ function iface_freq_info(iface, config, params)
function iface_add(phy, config, phy_status)
{
- let config_inline = iface_gen_config(phy, config, !!phy_status);
+ let config_inline = iface_gen_config(config, !!phy_status);
let bss = config.bss[0];
let ret = hostapd.add_iface(`bss_config=${phy}:${config_inline}`);
@@ -131,12 +148,16 @@ function iface_config_macaddr_list(config)
return macaddr_list;
}
-function iface_update_supplicant_macaddr(phy, config)
+function iface_update_supplicant_macaddr(phydev, config)
{
let macaddr_list = [];
for (let i = 0; i < length(config.bss); i++)
push(macaddr_list, config.bss[i].bssid);
- ubus.defer("wpa_supplicant", "phy_set_macaddr_list", { phy: phy, macaddr: macaddr_list });
+ ubus.defer("wpa_supplicant", "phy_set_macaddr_list", {
+ phy: phydev.name,
+ radio: phydev.radio ?? -1,
+ macaddr: macaddr_list
+ });
}
function __iface_pending_next(pending, state, ret, data)
@@ -151,19 +172,22 @@ function __iface_pending_next(pending, state, ret, data)
delete pending.defer;
switch (state) {
case "init":
- let macaddr_list = [];
- for (let i = 0; i < length(config.bss); i++)
- push(macaddr_list, config.bss[i].bssid);
- pending.call("wpa_supplicant", "phy_set_macaddr_list", { phy: phy, macaddr: macaddr_list });
+ iface_update_supplicant_macaddr(phydev, config);
return "create_bss";
case "create_bss":
- let err = wdev_create(phy, bss.ifname, { mode: "ap" });
+ let err = phydev.wdev_add(bss.ifname, {
+ mode: "ap",
+ radio: phydev.radio,
+ });
if (err) {
hostapd.printf(`Failed to create ${bss.ifname} on phy ${phy}: ${err}`);
return null;
}
- pending.call("wpa_supplicant", "phy_status", { phy: phy });
+ pending.call("wpa_supplicant", "phy_status", {
+ phy: phydev.phy,
+ radio: phydev.radio,
+ });
return "check_phy";
case "check_phy":
let phy_status = data;
@@ -173,12 +197,20 @@ function __iface_pending_next(pending, state, ret, data)
hostapd.printf(`Failed to bring up phy ${phy} ifname=${bss.ifname} with supplicant provided frequency`);
}
- pending.call("wpa_supplicant", "phy_set_state", { phy: phy, stop: true });
+ pending.call("wpa_supplicant", "phy_set_state", {
+ phy: phydev.phy,
+ radio: phydev.radio,
+ stop: true
+ });
return "wpas_stopped";
case "wpas_stopped":
if (!iface_add(phy, config))
hostapd.printf(`hostapd.add_iface failed for phy ${phy} ifname=${bss.ifname}`);
- pending.call("wpa_supplicant", "phy_set_state", { phy: phy, stop: false });
+ pending.call("wpa_supplicant", "phy_set_state", {
+ phy: phydev.phy,
+ radio: phydev.radio,
+ stop: false
+ });
return null;
case "done":
default:
@@ -193,9 +225,14 @@ function iface_pending_next(ret, data)
let cfg = this;
while (pending) {
- this.next_state = __iface_pending_next(cfg, this.next_state, ret, data);
- if (!this.next_state) {
- __iface_pending_next(cfg, "done");
+ try {
+ this.next_state = __iface_pending_next(cfg, this.next_state, ret, data);
+ if (!this.next_state) {
+ __iface_pending_next(cfg, "done");
+ return;
+ }
+ } catch(e) {
+ hostapd.printf(`Exception: ${e}\n${e.stacktrace[0].context}`);
return;
}
pending = !this.defer;
@@ -381,7 +418,7 @@ function get_config_bss(config, idx)
return hostapd.bss[ifname];
}
-function iface_reload_config(phydev, config, old_config)
+function iface_reload_config(name, phydev, config, old_config)
{
let phy = phydev.name;
@@ -391,13 +428,13 @@ function iface_reload_config(phydev, config, old_config)
if (is_equal(old_config.bss, config.bss))
return true;
- if (hostapd.data.pending_config[phy])
+ if (hostapd.data.pending_config[name])
return false;
if (!old_config.bss || !old_config.bss[0])
return false;
- let iface = hostapd.interfaces[phy];
+ let iface = hostapd.interfaces[name];
let iface_name = old_config.bss[0].ifname;
if (!iface) {
hostapd.printf(`Could not find previous interface ${iface_name}`);
@@ -492,7 +529,7 @@ function iface_reload_config(phydev, config, old_config)
return false;
let ifname = old_config.bss[i].ifname;
- hostapd.printf(`Remove bss '${ifname}' on phy '${phy}'`);
+ hostapd.printf(`Remove bss '${ifname}' on phy '${name}'`);
prev_bss.delete();
wdev_remove(ifname);
}
@@ -557,13 +594,13 @@ function iface_reload_config(phydev, config, old_config)
let addr = phydev.macaddr_next(i);
if (!addr) {
- hostapd.printf(`Failed to generate mac address for phy ${phy}`);
+ hostapd.printf(`Failed to generate mac address for phy ${name}`);
return false;
}
bsscfg.bssid = addr;
}
- let config_inline = iface_gen_config(phy, config);
+ let config_inline = iface_gen_config(config);
// Step 7: fill in the gaps with new interfaces
for (let i = 0; i < length(config.bss); i++) {
@@ -573,17 +610,17 @@ function iface_reload_config(phydev, config, old_config)
if (bss)
continue;
- hostapd.printf(`Add bss ${ifname} on phy ${phy}`);
+ hostapd.printf(`Add bss ${ifname} on phy ${name}`);
bss_list[i] = iface.add_bss(config_inline, i);
if (!bss_list[i]) {
- hostapd.printf(`Failed to add new bss ${ifname} on phy ${phy}`);
+ hostapd.printf(`Failed to add new bss ${ifname} on phy ${name}`);
return false;
}
}
// Step 8: update interface bss order
if (!iface.set_bss_order(bss_list)) {
- hostapd.printf(`Failed to update BSS order on phy '${phy}'`);
+ hostapd.printf(`Failed to update BSS order on phy '${name}'`);
return false;
}
@@ -614,7 +651,7 @@ function iface_reload_config(phydev, config, old_config)
if (is_equal(config.bss[i], bss_list_cfg[i]))
continue;
- hostapd.printf(`Reload config for bss '${config.bss[0].ifname}' on phy '${phy}'`);
+ hostapd.printf(`Reload config for bss '${config.bss[0].ifname}' on phy '${name}'`);
if (bss.set_config(config_inline, i) < 0) {
hostapd.printf(`Failed to set config for bss ${ifname}`);
return false;
@@ -624,35 +661,36 @@ function iface_reload_config(phydev, config, old_config)
return true;
}
-function iface_set_config(phy, config)
+function iface_set_config(name, config)
{
- let old_config = hostapd.data.config[phy];
+ let old_config = hostapd.data.config[name];
- hostapd.data.config[phy] = config;
+ hostapd.data.config[name] = config;
if (!config) {
- hostapd.remove_iface(phy);
+ hostapd.remove_iface(name);
return iface_remove(old_config);
}
- let phydev = phy_open(phy);
+ let phy = config.phy;
+ let phydev = phy_open(phy, config.radio_idx);
if (!phydev) {
hostapd.printf(`Failed to open phy ${phy}`);
return false;
}
try {
- let ret = iface_reload_config(phydev, config, old_config);
+ let ret = iface_reload_config(name, phydev, config, old_config);
if (ret) {
- iface_update_supplicant_macaddr(phy, config);
- hostapd.printf(`Reloaded settings for phy ${phy}`);
+ iface_update_supplicant_macaddr(phydev, config);
+ hostapd.printf(`Reloaded settings for phy ${name}`);
return 0;
}
} catch (e) {
- hostapd.printf(`Error reloading config: ${e}\n${e.stacktrace[0].context}`);
+ hostapd.printf(`Error reloading config: ${e}\n${e.stacktrace[0].context}`);
}
- hostapd.printf(`Restart interface for phy ${phy}`);
+ hostapd.printf(`Restart interface for phy ${name}`);
let ret = iface_restart(phydev, config, old_config);
return ret;
@@ -671,13 +709,18 @@ function config_add_bss(config, name)
return bss;
}
-function iface_load_config(filename)
+function iface_load_config(phy, radio, filename)
{
let f = open(filename, "r");
if (!f)
return null;
+ if (radio < 0)
+ radio = null;
+
let config = {
+ phy,
+ radio_idx: radio,
radio: {
data: []
},
@@ -752,16 +795,39 @@ function ex_wrap(func) {
};
}
+function phy_name(phy, radio)
+{
+ if (!phy)
+ return null;
+
+ if (radio != null && radio >= 0)
+ phy += "." + radio;
+
+ return phy;
+}
+
+function bss_config(bss_name) {
+ for (let phy, config in hostapd.data.config) {
+ if (!config)
+ continue;
+
+ for (let bss in config.bss)
+ if (bss.ifname == bss_name)
+ return [ config, bss ];
+ }
+}
+
let main_obj = {
reload: {
args: {
phy: "",
+ radio: 0,
},
call: ex_wrap(function(req) {
- let phy_list = req.args.phy ? [ req.args.phy ] : keys(hostapd.data.config);
+ let phy_list = req.args.phy ? [ phy_name(req.args.phy, req.args.radio) ] : keys(hostapd.data.config);
for (let phy_name in phy_list) {
let phy = hostapd.data.config[phy_name];
- let config = iface_load_config(phy.orig_file);
+ let config = iface_load_config(phy.phy, radio, phy.orig_file);
iface_set_config(phy_name, config);
}
@@ -771,6 +837,7 @@ let main_obj = {
apsta_state: {
args: {
phy: "",
+ radio: 0,
up: true,
frequency: 0,
sec_chan_offset: 0,
@@ -778,10 +845,10 @@ let main_obj = {
csa_count: 0,
},
call: ex_wrap(function(req) {
- if (req.args.up == null || !req.args.phy)
+ let phy = phy_name(req.args.phy, req.args.radio);
+ if (req.args.up == null || !phy)
return libubus.STATUS_INVALID_ARGUMENT;
- let phy = req.args.phy;
let config = hostapd.data.config[phy];
if (!config || !config.bss || !config.bss[0] || !config.bss[0].ifname)
return 0;
@@ -817,10 +884,11 @@ let main_obj = {
},
config_get_macaddr_list: {
args: {
- phy: ""
+ phy: "",
+ radio: 0,
},
call: ex_wrap(function(req) {
- let phy = req.args.phy;
+ let phy = phy_name(req.args.phy, req.args.radio);
if (!phy)
return libubus.STATUS_INVALID_ARGUMENT;
@@ -839,28 +907,34 @@ let main_obj = {
config_set: {
args: {
phy: "",
+ radio: 0,
config: "",
prev_config: "",
},
call: ex_wrap(function(req) {
let phy = req.args.phy;
+ let radio = req.args.radio;
+ let name = phy_name(phy, radio);
let file = req.args.config;
let prev_file = req.args.prev_config;
if (!phy)
return libubus.STATUS_INVALID_ARGUMENT;
- if (prev_file && !hostapd.data.config[phy]) {
- let config = iface_load_config(prev_file);
+ if (prev_file && !hostapd.data.config[name]) {
+ let config = iface_load_config(phy, radio, prev_file);
if (config)
config.radio.data = [];
- hostapd.data.config[phy] = config;
+ hostapd.data.config[name] = config;
}
- let config = iface_load_config(file);
+ let config = iface_load_config(phy, radio, file);
- hostapd.printf(`Set new config for phy ${phy}: ${file}`);
- iface_set_config(phy, config);
+ hostapd.printf(`Set new config for phy ${name}: ${file}`);
+ iface_set_config(name, config);
+
+ if (hostapd.data.auth_obj)
+ hostapd.data.auth_obj.notify("reload", { phy, radio });
return {
pid: hostapd.getpid()
@@ -896,10 +970,40 @@ let main_obj = {
return 0;
})
},
+ bss_info: {
+ args: {
+ iface: ""
+ },
+ call: ex_wrap(function(req) {
+ if (!req.args.iface)
+ return libubus.STATUS_INVALID_ARGUMENT;
+
+ let config = bss_config(req.args.iface);
+ if (!config)
+ return libubus.STATUS_NOT_FOUND;
+
+ let bss = config[1];
+ config = config[0];
+ let ret = {};
+
+ for (let line in [ ...config.radio.data, ...bss.data ]) {
+ let fields = split(line, "=", 2);
+ let name = fields[0];
+ if (hostapd.data.bss_info_fields[name])
+ ret[name] = fields[1];
+ }
+
+ return ret;
+ })
+ },
};
hostapd.data.ubus = ubus;
hostapd.data.obj = ubus.publish("hostapd", main_obj);
+
+
+let auth_obj = {};
+hostapd.data.auth_obj = ubus.publish("hostapd-auth", auth_obj);
hostapd.udebug_set("hostapd", hostapd.data.ubus);
function bss_event(type, name, data) {
@@ -914,10 +1018,18 @@ function bss_event(type, name, data) {
return {
shutdown: function() {
for (let phy in hostapd.data.config)
- iface_set_config(phy, null);
+ iface_set_config(phy);
hostapd.udebug_set(null);
hostapd.ubus.disconnect();
},
+ bss_create: function(phy, name, obj) {
+ phy = hostapd.data.config[phy];
+ if (!phy)
+ return;
+
+ if (phy.radio_idx != null && phy.radio_idx >= 0)
+ wdev_set_radio_mask(name, 1 << phy.radio_idx);
+ },
bss_add: function(phy, name, obj) {
bss_event("add", name);
},
@@ -926,5 +1038,25 @@ return {
},
bss_remove: function(phy, name, obj) {
bss_event("remove", name);
- }
+ },
+ sta_auth: function(iface, sta) {
+ let msg = { iface, sta };
+ let ret = {};
+ let data_cb = (type, data) => {
+ ret = { ...ret, ...data };
+ };
+ if (hostapd.data.auth_obj)
+ hostapd.data.auth_obj.notify("sta_auth", msg, data_cb, null, null, 1000);
+ return ret;
+ },
+ sta_connected: function(iface, sta, data) {
+ let msg = { iface, sta, ...data };
+ let ret = {};
+ let data_cb = (type, data) => {
+ ret = { ...ret, ...data };
+ };
+ if (hostapd.data.auth_obj)
+ hostapd.data.auth_obj.notify("sta_connected", msg, data_cb, null, null, 1000);
+ return ret;
+ },
};
diff --git a/package/network/services/hostapd/files/wpa_supplicant.uc b/package/network/services/hostapd/files/wpa_supplicant.uc
index 31d45346257..fbea27628e3 100644
--- a/package/network/services/hostapd/files/wpa_supplicant.uc
+++ b/package/network/services/hostapd/files/wpa_supplicant.uc
@@ -37,7 +37,7 @@ function iface_start(phydev, iface, macaddr_list)
wpas.data.iface_phy[ifname] = phy;
wdev_remove(ifname);
- let ret = wdev_create(phy, ifname, wdev_config);
+ let ret = phydev.wdev_add(ifname, wdev_config);
if (ret)
wpas.printf(`Failed to create device ${ifname}: ${ret}`);
wdev_set_up(ifname, true);
@@ -61,22 +61,27 @@ function iface_cb(new_if, old_if)
iface_stop(old_if);
}
-function prepare_config(config)
+function prepare_config(config, radio)
{
config.config_data = readfile(config.config);
- return { config: config };
+ return { config };
}
-function set_config(phy_name, num_global_macaddr, config_list)
+function set_config(config_name, phy_name, radio, num_global_macaddr, config_list)
{
- let phy = wpas.data.config[phy_name];
+ let phy = wpas.data.config[config_name];
+
+ if (radio < 0)
+ radio = null;
if (!phy) {
phy = vlist_new(iface_cb, false);
- wpas.data.config[phy_name] = phy;
+ phy.name = phy_name;
+ wpas.data.config[config_name] = phy;
}
+ phy.radio = radio;
phy.num_global_macaddr = num_global_macaddr;
let values = [];
@@ -94,7 +99,7 @@ function start_pending(phy_name)
if (!phy || !phy.data)
return;
- let phydev = phy_open(phy_name);
+ let phydev = phy_open(phy.name, phy.radio);
if (!phydev) {
wpas.printf(`Could not open phy ${phy_name}`);
return;
@@ -107,17 +112,30 @@ function start_pending(phy_name)
iface_start(phydev, phy.data[ifname]);
}
+function phy_name(phy, radio)
+{
+ if (!phy)
+ return null;
+
+ if (radio != null && radio >= 0)
+ phy += "." + radio;
+
+ return phy;
+}
+
let main_obj = {
phy_set_state: {
args: {
phy: "",
+ radio: 0,
stop: true,
},
call: function(req) {
- if (!req.args.phy || req.args.stop == null)
+ let name = phy_name(req.args.phy, req.args.radio);
+ if (!name || req.args.stop == null)
return libubus.STATUS_INVALID_ARGUMENT;
- let phy = wpas.data.config[req.args.phy];
+ let phy = wpas.data.config[name];
if (!phy)
return libubus.STATUS_NOT_FOUND;
@@ -126,7 +144,7 @@ let main_obj = {
for (let ifname in phy.data)
iface_stop(phy.data[ifname]);
} else {
- start_pending(req.args.phy);
+ start_pending(name);
}
} catch (e) {
wpas.printf(`Error chaging state: ${e}\n${e.stacktrace[0].context}`);
@@ -138,10 +156,11 @@ let main_obj = {
phy_set_macaddr_list: {
args: {
phy: "",
+ radio: 0,
macaddr: [],
},
call: function(req) {
- let phy = req.args.phy;
+ let phy = phy_name(req.args.phy, req.args.radio);
if (!phy)
return libubus.STATUS_INVALID_ARGUMENT;
@@ -151,13 +170,15 @@ let main_obj = {
},
phy_status: {
args: {
- phy: ""
+ phy: "",
+ radio: 0,
},
call: function(req) {
- if (!req.args.phy)
+ let phy = phy_name(req.args.phy, req.args.radio);
+ if (!phy)
return libubus.STATUS_INVALID_ARGUMENT;
- let phy = wpas.data.config[req.args.phy];
+ phy = wpas.data.config[phy];
if (!phy)
return libubus.STATUS_NOT_FOUND;
@@ -187,21 +208,23 @@ let main_obj = {
config_set: {
args: {
phy: "",
+ radio: 0,
num_global_macaddr: 0,
config: [],
defer: true,
},
call: function(req) {
- if (!req.args.phy)
+ let phy = phy_name(req.args.phy, req.args.radio);
+ if (!phy)
return libubus.STATUS_INVALID_ARGUMENT;
- wpas.printf(`Set new config for phy ${req.args.phy}`);
+ wpas.printf(`Set new config for phy ${phy}`);
try {
if (req.args.config)
- set_config(req.args.phy, req.args.num_global_macaddr, req.args.config);
+ set_config(phy, req.args.phy, req.args.radio, req.args.num_global_macaddr, req.args.config);
if (!req.args.defer)
- start_pending(req.args.phy);
+ start_pending(phy);
} catch (e) {
wpas.printf(`Error loading config: ${e}\n${e.stacktrace[0].context}`);
return libubus.STATUS_INVALID_ARGUMENT;
@@ -245,6 +268,33 @@ let main_obj = {
return 0;
}
},
+ bss_info: {
+ args: {
+ iface: "",
+ },
+ call: function(req) {
+ let ifname = req.args.iface;
+ if (!ifname)
+ return libubus.STATUS_INVALID_ARGUMENT;
+
+ let iface = wpas.interfaces[ifname];
+ if (!iface)
+ return libubus.STATUS_NOT_FOUND;
+
+ let status = iface.ctrl("STATUS");
+ if (!status)
+ return libubus.STATUS_NOT_FOUND;
+
+ let ret = {};
+ status = split(status, "\n");
+ for (let line in status) {
+ line = split(line, "=", 2);
+ ret[line[0]] = line[1];
+ }
+
+ return ret;
+ }
+ },
};
wpas.data.ubus = ubus;
diff --git a/package/network/services/hostapd/files/wpad_acl.json b/package/network/services/hostapd/files/wpad_acl.json
index 7532953cabd..755f836b673 100644
--- a/package/network/services/hostapd/files/wpad_acl.json
+++ b/package/network/services/hostapd/files/wpad_acl.json
@@ -15,6 +15,6 @@
}
},
"subscribe": [ "udebug" ],
- "publish": [ "hostapd", "hostapd.*", "wpa_supplicant", "wpa_supplicant.*" ],
+ "publish": [ "hostapd", "hostapd.*", "wpa_supplicant", "wpa_supplicant.*", "hostapd-auth" ],
"send": [ "bss.*", "wps_credentials" ]
}
diff --git a/package/network/services/hostapd/patches/601-ucode_support.patch b/package/network/services/hostapd/patches/601-ucode_support.patch
index 4288e0f7898..5a88687cf22 100644
--- a/package/network/services/hostapd/patches/601-ucode_support.patch
+++ b/package/network/services/hostapd/patches/601-ucode_support.patch
@@ -704,3 +704,142 @@ as adding/removing interfaces.
#ifdef CONFIG_MATCH_IFACE
int matched;
#endif /* CONFIG_MATCH_IFACE */
+--- a/src/ap/ieee802_11.c
++++ b/src/ap/ieee802_11.c
+@@ -555,12 +555,17 @@ const char * sae_get_password(struct hos
+ struct sae_pt **s_pt,
+ const struct sae_pk **s_pk)
+ {
++ struct hostapd_bss_config *conf = hapd->conf;
++ struct hostapd_ssid *ssid = &conf->ssid;
+ const char *password = NULL;
+- struct sae_password_entry *pw;
++ struct sae_password_entry *pw = NULL;
+ struct sae_pt *pt = NULL;
+ const struct sae_pk *pk = NULL;
+ struct hostapd_sta_wpa_psk_short *psk = NULL;
+
++ if (sta && sta->use_sta_psk)
++ goto use_sta_psk;
++
+ for (pw = hapd->conf->sae_passwords; pw; pw = pw->next) {
+ if (!is_broadcast_ether_addr(pw->peer_addr) &&
+ (!sta ||
+@@ -582,12 +587,30 @@ const char * sae_get_password(struct hos
+ pt = hapd->conf->ssid.pt;
+ }
+
++use_sta_psk:
+ if (!password && sta) {
+ for (psk = sta->psk; psk; psk = psk->next) {
+- if (psk->is_passphrase) {
+- password = psk->passphrase;
++ if (!psk->is_passphrase)
++ continue;
++
++ password = psk->passphrase;
++ if (!sta->use_sta_psk)
++ break;
++
++#ifdef CONFIG_SAE
++ if (sta->sae_pt) {
++ pt = sta->sae_pt;
+ break;
+ }
++
++ pt = sae_derive_pt(conf->sae_groups, ssid->ssid,
++ ssid->ssid_len,
++ (const u8 *) password,
++ os_strlen(password),
++ NULL);
++ sta->sae_pt = pt;
++ break;
++#endif
+ }
+ }
+
+@@ -3229,6 +3252,12 @@ static void handle_auth(struct hostapd_d
+ goto fail;
+ }
+
++ res = hostapd_ucode_sta_auth(hapd, sta);
++ if (res) {
++ resp = res;
++ goto fail;
++ }
++
+ sta->flags &= ~WLAN_STA_PREAUTH;
+ ieee802_1x_notify_pre_auth(sta->eapol_sm, 0);
+
+--- a/src/ap/sta_info.c
++++ b/src/ap/sta_info.c
+@@ -474,6 +474,11 @@ void ap_free_sta(struct hostapd_data *ha
+ forced_memzero(sta->last_tk, WPA_TK_MAX_LEN);
+ #endif /* CONFIG_TESTING_OPTIONS */
+
++#ifdef CONFIG_SAE
++ if (sta->sae_pt)
++ sae_deinit_pt(sta->sae_pt);
++#endif
++
+ os_free(sta);
+ }
+
+@@ -1507,6 +1512,8 @@ void ap_sta_set_authorized_event(struct
+ #endif /* CONFIG_P2P */
+ const u8 *ip_ptr = NULL;
+
++ if (authorized)
++ hostapd_ucode_sta_connected(hapd, sta);
+ #ifdef CONFIG_P2P
+ if (hapd->p2p_group == NULL) {
+ if (sta->p2p_ie != NULL &&
+--- a/src/ap/sta_info.h
++++ b/src/ap/sta_info.h
+@@ -180,6 +180,9 @@ struct sta_info {
+ int vlan_id_bound; /* updated by ap_sta_bind_vlan() */
+ /* PSKs from RADIUS authentication server */
+ struct hostapd_sta_wpa_psk_short *psk;
++ struct sae_pt *sae_pt;
++ int use_sta_psk;
++ int psk_idx;
+
+ char *identity; /* User-Name from RADIUS */
+ char *radius_cui; /* Chargeable-User-Identity from RADIUS */
+--- a/src/ap/wpa_auth_glue.c
++++ b/src/ap/wpa_auth_glue.c
+@@ -400,6 +400,7 @@ static const u8 * hostapd_wpa_auth_get_p
+ struct sta_info *sta = ap_get_sta(hapd, addr);
+ const u8 *psk;
+
++ sta->psk_idx = 0;
+ if (vlan_id)
+ *vlan_id = 0;
+ if (psk_len)
+@@ -446,13 +447,16 @@ static const u8 * hostapd_wpa_auth_get_p
+ * returned psk which should not be returned again.
+ * logic list (all hostapd_get_psk; all sta->psk)
+ */
++ if (sta && sta->use_sta_psk)
++ psk = NULL;
+ if (sta && sta->psk && !psk) {
+ struct hostapd_sta_wpa_psk_short *pos;
++ int psk_idx = 1;
+
+ if (vlan_id)
+ *vlan_id = 0;
+ psk = sta->psk->psk;
+- for (pos = sta->psk; pos; pos = pos->next) {
++ for (pos = sta->psk; pos; pos = pos->next, psk_idx++) {
+ if (pos->is_passphrase) {
+ if (pbkdf2_sha1(pos->passphrase,
+ hapd->conf->ssid.ssid,
+@@ -469,6 +473,8 @@ static const u8 * hostapd_wpa_auth_get_p
+ break;
+ }
+ }
++ if (psk)
++ sta->psk_idx = psk_idx;
+ }
+ return psk;
+ }
diff --git a/package/network/services/hostapd/patches/780-Implement-APuP-Access-Point-Micro-Peering.patch b/package/network/services/hostapd/patches/780-Implement-APuP-Access-Point-Micro-Peering.patch
index 6a8fa1f8312..dae7ad180c9 100644
--- a/package/network/services/hostapd/patches/780-Implement-APuP-Access-Point-Micro-Peering.patch
+++ b/package/network/services/hostapd/patches/780-Implement-APuP-Access-Point-Micro-Peering.patch
@@ -372,7 +372,7 @@ Hotfix-by: Sebastian Gottschall https://github.com/mirror/dd-wrt/commit/0c3001a6
#ifdef CONFIG_FILS
static struct wpabuf *
-@@ -3588,8 +3591,8 @@ static u16 check_multi_ap(struct hostapd
+@@ -3617,8 +3620,8 @@ static u16 check_multi_ap(struct hostapd
}
@@ -383,7 +383,7 @@ Hotfix-by: Sebastian Gottschall https://github.com/mirror/dd-wrt/commit/0c3001a6
{
/* Supported rates not used in IEEE 802.11ad/DMG */
if (hapd->iface->current_mode &&
-@@ -3976,7 +3979,7 @@ static int __check_assoc_ies(struct host
+@@ -4005,7 +4008,7 @@ static int __check_assoc_ies(struct host
elems->ext_capab_len);
if (resp != WLAN_STATUS_SUCCESS)
return resp;
@@ -392,7 +392,7 @@ Hotfix-by: Sebastian Gottschall https://github.com/mirror/dd-wrt/commit/0c3001a6
if (resp != WLAN_STATUS_SUCCESS)
return resp;
-@@ -6031,6 +6034,11 @@ static void handle_beacon(struct hostapd
+@@ -6060,6 +6063,11 @@ static void handle_beacon(struct hostapd
0);
ap_list_process_beacon(hapd->iface, mgmt, &elems, fi);
diff --git a/package/network/services/hostapd/patches/803-hostapd-fix-80211be-build.patch b/package/network/services/hostapd/patches/803-hostapd-fix-80211be-build.patch
index 55c6e635813..cbd6298d9d3 100644
--- a/package/network/services/hostapd/patches/803-hostapd-fix-80211be-build.patch
+++ b/package/network/services/hostapd/patches/803-hostapd-fix-80211be-build.patch
@@ -1,6 +1,6 @@
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
-@@ -1836,3 +1836,22 @@ void ap_sta_free_sta_profile(struct mld_
+@@ -1914,3 +1914,22 @@ void ap_sta_free_sta_profile(struct mld_
}
}
#endif /* CONFIG_IEEE80211BE */
@@ -25,7 +25,7 @@
+
--- a/src/ap/sta_info.h
+++ b/src/ap/sta_info.h
-@@ -417,23 +417,8 @@ int ap_sta_re_add(struct hostapd_data *h
+@@ -408,23 +408,8 @@ int ap_sta_re_add(struct hostapd_data *h
void ap_free_sta_pasn(struct hostapd_data *hapd, struct sta_info *sta);
diff --git a/package/network/services/hostapd/src/src/ap/ucode.c b/package/network/services/hostapd/src/src/ap/ucode.c
index a5630d7eaac..2da2b4dc938 100644
--- a/package/network/services/hostapd/src/src/ap/ucode.c
+++ b/package/network/services/hostapd/src/src/ap/ucode.c
@@ -9,6 +9,7 @@
#include "ap_drv_ops.h"
#include "dfs.h"
#include "acs.h"
+#include "ieee802_11_auth.h"
#include
static uc_resource_type_t *global_type, *bss_type, *iface_type;
@@ -711,6 +712,110 @@ uc_hostapd_bss_rename(uc_vm_t *vm, size_t nargs)
return ret ? NULL : ucv_boolean_new(true);
}
+int hostapd_ucode_sta_auth(struct hostapd_data *hapd, struct sta_info *sta)
+{
+ char addr[sizeof(MACSTR)];
+ uc_value_t *val, *cur;
+ int ret = 0;
+
+ if (wpa_ucode_call_prepare("sta_auth"))
+ return 0;
+
+ uc_value_push(ucv_get(ucv_string_new(hapd->conf->iface)));
+
+ snprintf(addr, sizeof(addr), MACSTR, MAC2STR(sta->addr));
+ val = ucv_string_new(addr);
+ uc_value_push(ucv_get(val));
+
+ val = wpa_ucode_call(2);
+
+ cur = ucv_object_get(val, "psk", NULL);
+ if (ucv_type(cur) == UC_ARRAY) {
+ struct hostapd_sta_wpa_psk_short *p, **next;
+ size_t len = ucv_array_length(cur);
+
+ next = &sta->psk;
+ hostapd_free_psk_list(*next);
+ *next = NULL;
+
+ for (size_t i = 0; i < len; i++) {
+ uc_value_t *cur_psk;
+ const char *str;
+ size_t str_len;
+
+ cur_psk = ucv_array_get(cur, i);
+ str = ucv_string_get(cur_psk);
+ str_len = strlen(str);
+ if (!str || str_len < 8 || str_len > 64)
+ continue;
+
+ p = os_zalloc(sizeof(*p));
+ if (len == 64) {
+ if (hexstr2bin(str, p->psk, PMK_LEN) < 0) {
+ free(p);
+ continue;
+ }
+ } else {
+ p->is_passphrase = 1;
+ memcpy(p->passphrase, str, str_len + 1);
+ }
+
+ *next = p;
+ next = &p->next;
+ }
+ }
+
+ cur = ucv_object_get(val, "force_psk", NULL);
+ sta->use_sta_psk = ucv_is_truish(cur);
+
+ cur = ucv_object_get(val, "status", NULL);
+ if (ucv_type(cur) == UC_INTEGER)
+ ret = ucv_int64_get(cur);
+
+ ucv_put(val);
+ ucv_gc(vm);
+
+ return ret;
+}
+
+void hostapd_ucode_sta_connected(struct hostapd_data *hapd, struct sta_info *sta)
+{
+ char addr[sizeof(MACSTR)];
+ uc_value_t *val, *cur;
+ int ret = 0;
+
+ if (wpa_ucode_call_prepare("sta_connected"))
+ return;
+
+ uc_value_push(ucv_get(ucv_string_new(hapd->conf->iface)));
+
+ snprintf(addr, sizeof(addr), MACSTR, MAC2STR(sta->addr));
+ val = ucv_string_new(addr);
+ uc_value_push(ucv_get(val));
+
+ val = ucv_object_new(vm);
+ if (sta->psk_idx)
+ ucv_object_add(val, "psk_idx", ucv_int64_new(sta->psk_idx - 1));
+ uc_value_push(ucv_get(val));
+
+ val = wpa_ucode_call(3);
+ if (ucv_type(val) != UC_OBJECT)
+ goto out;
+
+ cur = ucv_object_get(val, "vlan", NULL);
+ if (ucv_type(cur) == UC_INTEGER) {
+ struct vlan_description vdesc = {
+ .notempty = 1,
+ .untagged = ucv_int64_get(cur),
+ };
+
+ ap_sta_set_vlan(hapd, sta, &vdesc);
+ ap_sta_bind_vlan(hapd, sta);
+ }
+
+out:
+ ucv_put(val);
+}
int hostapd_ucode_init(struct hapd_interfaces *ifaces)
{
diff --git a/package/network/services/hostapd/src/src/ap/ucode.h b/package/network/services/hostapd/src/src/ap/ucode.h
index 2f7bcd6542a..d0b00e59652 100644
--- a/package/network/services/hostapd/src/src/ap/ucode.h
+++ b/package/network/services/hostapd/src/src/ap/ucode.h
@@ -25,6 +25,8 @@ void hostapd_ucode_free(void);
void hostapd_ucode_free_iface(struct hostapd_iface *iface);
void hostapd_ucode_free_bss(struct hostapd_data *hapd);
void hostapd_ucode_bss_cb(struct hostapd_data *hapd, const char *type);
+int hostapd_ucode_sta_auth(struct hostapd_data *hapd, struct sta_info *sta);
+void hostapd_ucode_sta_connected(struct hostapd_data *hapd, struct sta_info *sta);
#ifdef CONFIG_APUP
void hostapd_ucode_apup_newpeer(struct hostapd_data *hapd, const char *ifname);
@@ -45,6 +47,13 @@ static inline void hostapd_ucode_free_iface(struct hostapd_iface *iface)
static inline void hostapd_ucode_bss_cb(struct hostapd_data *hapd, const char *type)
{
}
+static inline int hostapd_ucode_sta_auth(struct hostapd_data *hapd, struct sta_info *sta)
+{
+ return 0;
+}
+static inline void hostapd_ucode_sta_connected(struct hostapd_data *hapd, struct sta_info *sta)
+{
+}
static inline void hostapd_ucode_free_bss(struct hostapd_data *hapd)
{
}
diff --git a/package/network/services/hostapd/src/wpa_supplicant/ucode.c b/package/network/services/hostapd/src/wpa_supplicant/ucode.c
index 397f85bde7f..9380b301c36 100644
--- a/package/network/services/hostapd/src/wpa_supplicant/ucode.c
+++ b/package/network/services/hostapd/src/wpa_supplicant/ucode.c
@@ -5,6 +5,7 @@
#include "ap/hostapd.h"
#include "wpa_supplicant_i.h"
#include "wps_supplicant.h"
+#include "ctrl_iface.h"
#include "bss.h"
#include "ucode.h"
@@ -255,6 +256,31 @@ uc_wpas_iface_status(uc_vm_t *vm, size_t nargs)
return ret;
}
+static uc_value_t *
+uc_wpas_iface_ctrl(uc_vm_t *vm, size_t nargs)
+{
+ struct wpa_supplicant *wpa_s = uc_fn_thisval("wpas.iface");
+ uc_value_t *arg = uc_fn_arg(0);
+ size_t reply_len;
+ uc_value_t *ret;
+ char *reply;
+
+ if (!wpa_s || ucv_type(arg) != UC_STRING)
+ return NULL;
+
+ reply = wpa_supplicant_ctrl_iface_process(wpa_s, ucv_string_get(arg), &reply_len);
+ if (reply_len < 0)
+ return NULL;
+
+ if (reply_len && reply[reply_len - 1] == '\n')
+ reply_len--;
+
+ ret = ucv_string_new_length(reply, reply_len);
+ free(reply);
+
+ return ret;
+}
+
int wpas_ucode_init(struct wpa_global *gl)
{
static const uc_function_list_t global_fns[] = {
@@ -266,6 +292,7 @@ int wpas_ucode_init(struct wpa_global *gl)
};
static const uc_function_list_t iface_fns[] = {
{ "status", uc_wpas_iface_status },
+ { "ctrl", uc_wpas_iface_ctrl },
};
uc_value_t *data, *proto;
diff --git a/package/network/services/ppp/Makefile b/package/network/services/ppp/Makefile
index 5f1ebd4e7d1..760a31dc0d0 100644
--- a/package/network/services/ppp/Makefile
+++ b/package/network/services/ppp/Makefile
@@ -192,6 +192,8 @@ endif
define Build/InstallDev
$(INSTALL_DIR) $(1)/usr/include
$(CP) $(PKG_INSTALL_DIR)/usr/include/pppd $(1)/usr/include/
+ $(INSTALL_DIR) $(1)/usr/lib/pkgconfig
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/*.pc $(1)/usr/lib/pkgconfig
endef
define Package/ppp/script_install
diff --git a/package/network/utils/iw/patches/001-nl80211_h_sync.patch b/package/network/utils/iw/patches/001-nl80211_h_sync.patch
new file mode 100644
index 00000000000..f48c083575d
--- /dev/null
+++ b/package/network/utils/iw/patches/001-nl80211_h_sync.patch
@@ -0,0 +1,98 @@
+--- a/nl80211.h
++++ b/nl80211.h
+@@ -2061,6 +2061,10 @@ enum nl80211_commands {
+ * @NL80211_ATTR_INTERFACE_COMBINATIONS: Nested attribute listing the supported
+ * interface combinations. In each nested item, it contains attributes
+ * defined in &enum nl80211_if_combination_attrs.
++ * If the wiphy uses multiple radios (@NL80211_ATTR_WIPHY_RADIOS is set),
++ * this attribute contains the interface combinations of the first radio.
++ * See @NL80211_ATTR_WIPHY_INTERFACE_COMBINATIONS for the global wiphy
++ * combinations for the sum of all radios.
+ * @NL80211_ATTR_SOFTWARE_IFTYPES: Nested attribute (just like
+ * %NL80211_ATTR_SUPPORTED_IFTYPES) containing the interface types that
+ * are managed in software: interfaces of these types aren't subject to
+@@ -2856,6 +2860,17 @@ enum nl80211_commands {
+ * %NL80211_CMD_ASSOCIATE indicating the SPP A-MSDUs
+ * are used on this connection
+ *
++ * @NL80211_ATTR_WIPHY_RADIOS: Nested attribute describing physical radios
++ * belonging to this wiphy. See &enum nl80211_wiphy_radio_attrs.
++ *
++ * @NL80211_ATTR_WIPHY_INTERFACE_COMBINATIONS: Nested attribute listing the
++ * supported interface combinations for all radios combined. In each
++ * nested item, it contains attributes defined in
++ * &enum nl80211_if_combination_attrs.
++ *
++ * @NL80211_ATTR_VIF_RADIO_MASK: Bitmask of allowed radios (u32).
++ * A value of 0 means all radios.
++ *
+ * @NUM_NL80211_ATTR: total number of nl80211_attrs available
+ * @NL80211_ATTR_MAX: highest attribute number currently defined
+ * @__NL80211_ATTR_AFTER_LAST: internal use
+@@ -3401,6 +3416,11 @@ enum nl80211_attrs {
+
+ NL80211_ATTR_ASSOC_SPP_AMSDU,
+
++ NL80211_ATTR_WIPHY_RADIOS,
++ NL80211_ATTR_WIPHY_INTERFACE_COMBINATIONS,
++
++ NL80211_ATTR_VIF_RADIO_MASK,
++
+ /* add attributes here, update the policy in nl80211.c */
+
+ __NL80211_ATTR_AFTER_LAST,
+@@ -7987,4 +8007,54 @@ enum nl80211_ap_settings_flags {
+ NL80211_AP_SETTINGS_SA_QUERY_OFFLOAD_SUPPORT = 1 << 1,
+ };
+
++/**
++ * enum nl80211_wiphy_radio_attrs - wiphy radio attributes
++ *
++ * @__NL80211_WIPHY_RADIO_ATTR_INVALID: Invalid
++ *
++ * @NL80211_WIPHY_RADIO_ATTR_INDEX: Index of this radio (u32)
++ * @NL80211_WIPHY_RADIO_ATTR_FREQ_RANGE: Frequency range supported by this
++ * radio. Attribute may be present multiple times.
++ * @NL80211_WIPHY_RADIO_ATTR_INTERFACE_COMBINATION: Supported interface
++ * combination for this radio. Attribute may be present multiple times
++ * and contains attributes defined in &enum nl80211_if_combination_attrs.
++ *
++ * @__NL80211_WIPHY_RADIO_ATTR_LAST: Internal
++ * @NL80211_WIPHY_RADIO_ATTR_MAX: Highest attribute
++ */
++enum nl80211_wiphy_radio_attrs {
++ __NL80211_WIPHY_RADIO_ATTR_INVALID,
++
++ NL80211_WIPHY_RADIO_ATTR_INDEX,
++ NL80211_WIPHY_RADIO_ATTR_FREQ_RANGE,
++ NL80211_WIPHY_RADIO_ATTR_INTERFACE_COMBINATION,
++
++ /* keep last */
++ __NL80211_WIPHY_RADIO_ATTR_LAST,
++ NL80211_WIPHY_RADIO_ATTR_MAX = __NL80211_WIPHY_RADIO_ATTR_LAST - 1,
++};
++
++/**
++ * enum nl80211_wiphy_radio_freq_range - wiphy radio frequency range
++ *
++ * @__NL80211_WIPHY_RADIO_FREQ_ATTR_INVALID: Invalid
++ *
++ * @NL80211_WIPHY_RADIO_FREQ_ATTR_START: Frequency range start (u32).
++ * The unit is kHz.
++ * @NL80211_WIPHY_RADIO_FREQ_ATTR_END: Frequency range end (u32).
++ * The unit is kHz.
++ *
++ * @__NL80211_WIPHY_RADIO_FREQ_ATTR_LAST: Internal
++ * @NL80211_WIPHY_RADIO_FREQ_ATTR_MAX: Highest attribute
++ */
++enum nl80211_wiphy_radio_freq_range {
++ __NL80211_WIPHY_RADIO_FREQ_ATTR_INVALID,
++
++ NL80211_WIPHY_RADIO_FREQ_ATTR_START,
++ NL80211_WIPHY_RADIO_FREQ_ATTR_END,
++
++ __NL80211_WIPHY_RADIO_FREQ_ATTR_LAST,
++ NL80211_WIPHY_RADIO_FREQ_ATTR_MAX = __NL80211_WIPHY_RADIO_FREQ_ATTR_LAST - 1,
++};
++
+ #endif /* __LINUX_NL80211_H */
diff --git a/package/network/utils/iw/patches/300-wiphy_radios.patch b/package/network/utils/iw/patches/300-wiphy_radios.patch
new file mode 100644
index 00000000000..534addf8975
--- /dev/null
+++ b/package/network/utils/iw/patches/300-wiphy_radios.patch
@@ -0,0 +1,252 @@
+--- a/info.c
++++ b/info.c
+@@ -295,6 +295,151 @@ static void print_pmsr_capabilities(stru
+ }
+ }
+
++static void print_interface_combinations(struct nlattr *ifcomb, bool radio)
++{
++ const char *indent = radio ? "\t" : "";
++ struct nlattr *nl_combi;
++ bool have_combinations = false;
++ int rem;
++
++ nla_for_each_nested(nl_combi, ifcomb, rem) {
++ static struct nla_policy iface_combination_policy[NUM_NL80211_IFACE_COMB] = {
++ [NL80211_IFACE_COMB_LIMITS] = { .type = NLA_NESTED },
++ [NL80211_IFACE_COMB_MAXNUM] = { .type = NLA_U32 },
++ [NL80211_IFACE_COMB_STA_AP_BI_MATCH] = { .type = NLA_FLAG },
++ [NL80211_IFACE_COMB_NUM_CHANNELS] = { .type = NLA_U32 },
++ [NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS] = { .type = NLA_U32 },
++ };
++ struct nlattr *tb_comb[NUM_NL80211_IFACE_COMB];
++ static struct nla_policy iface_limit_policy[NUM_NL80211_IFACE_LIMIT] = {
++ [NL80211_IFACE_LIMIT_TYPES] = { .type = NLA_NESTED },
++ [NL80211_IFACE_LIMIT_MAX] = { .type = NLA_U32 },
++ };
++ struct nlattr *tb_limit[NUM_NL80211_IFACE_LIMIT];
++ struct nlattr *nl_limit;
++ int err, rem_limit;
++ bool comma = false;
++
++ if (radio && nla_type(nl_combi) !=
++ NL80211_WIPHY_RADIO_ATTR_INTERFACE_COMBINATION)
++ continue;
++
++ if (!have_combinations) {
++ printf("\t%svalid interface combinations:\n", indent);
++ have_combinations = true;
++ }
++
++ printf("\t\t%s * ", indent);
++
++ err = nla_parse_nested(tb_comb, MAX_NL80211_IFACE_COMB,
++ nl_combi, iface_combination_policy);
++ if (err || !tb_comb[NL80211_IFACE_COMB_LIMITS] ||
++ !tb_comb[NL80211_IFACE_COMB_MAXNUM] ||
++ !tb_comb[NL80211_IFACE_COMB_NUM_CHANNELS]) {
++ printf(" \n");
++ goto broken_combination;
++ }
++
++ nla_for_each_nested(nl_limit, tb_comb[NL80211_IFACE_COMB_LIMITS], rem_limit) {
++ err = nla_parse_nested(tb_limit, MAX_NL80211_IFACE_LIMIT,
++ nl_limit, iface_limit_policy);
++ if (err || !tb_limit[NL80211_IFACE_LIMIT_TYPES]) {
++ printf("\n");
++ goto broken_combination;
++ }
++
++ if (comma)
++ printf(", ");
++ comma = true;
++ printf("#{ ");
++ print_iftype_line(tb_limit[NL80211_IFACE_LIMIT_TYPES]);
++ printf(" } <= %u", nla_get_u32(tb_limit[NL80211_IFACE_LIMIT_MAX]));
++ }
++ printf(",\n\t\t%s ", indent);
++
++ printf("total <= %d, #channels <= %d%s",
++ nla_get_u32(tb_comb[NL80211_IFACE_COMB_MAXNUM]),
++ nla_get_u32(tb_comb[NL80211_IFACE_COMB_NUM_CHANNELS]),
++ tb_comb[NL80211_IFACE_COMB_STA_AP_BI_MATCH] ?
++ ", STA/AP BI must match" : "");
++ if (tb_comb[NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS]) {
++ unsigned long widths = nla_get_u32(tb_comb[NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS]);
++
++ if (widths) {
++ int width;
++ bool first = true;
++
++ printf(", radar detect widths: {");
++ for (width = 0; width < 32; width++)
++ if (widths & (1 << width)) {
++ printf("%s %s",
++ first ? "":",",
++ channel_width_name(width));
++ first = false;
++ }
++ printf(" }\n");
++ }
++ }
++ printf("\n");
++broken_combination:
++ ;
++ }
++
++ if (!have_combinations)
++ printf("\t%sinterface combinations are not supported\n", indent);
++}
++
++static void print_radio_freq(struct nlattr *freqs)
++{
++ struct nlattr *freq;
++ int rem;
++
++ nla_for_each_nested(freq, freqs, rem) {
++ static struct nla_policy freq_policy[NL80211_WIPHY_RADIO_FREQ_ATTR_MAX + 1] = {
++ [NL80211_WIPHY_RADIO_FREQ_ATTR_START] = { .type = NLA_U32 },
++ [NL80211_WIPHY_RADIO_FREQ_ATTR_END] = { .type = NLA_U32 },
++ };
++ struct nlattr *tb[NL80211_WIPHY_RADIO_FREQ_ATTR_MAX + 1];
++ uint32_t start, end;
++
++ if (nla_type(freq) != NL80211_WIPHY_RADIO_ATTR_FREQ_RANGE)
++ continue;
++
++ if (nla_parse_nested(tb, NL80211_WIPHY_RADIO_ATTR_MAX + 1,
++ freq, freq_policy) ||
++ !tb[NL80211_WIPHY_RADIO_FREQ_ATTR_START] ||
++ !tb[NL80211_WIPHY_RADIO_FREQ_ATTR_END])
++ continue;
++
++ start = nla_get_u32(tb[NL80211_WIPHY_RADIO_FREQ_ATTR_START]);
++ end = nla_get_u32(tb[NL80211_WIPHY_RADIO_FREQ_ATTR_END]);
++
++ printf("\t\tfreq range: %.1f MHz - %.1f MHz\n", (float)start / 1000, (float)end / 1000);
++ }
++}
++
++static void print_radios(struct nlattr *radios)
++{
++ struct nlattr *radio;
++ int rem, idx = 0;
++
++ nla_for_each_nested(radio, radios, rem) {
++ static struct nla_policy radio_policy[NL80211_WIPHY_RADIO_ATTR_MAX + 1] = {
++ [NL80211_WIPHY_RADIO_ATTR_INDEX] = { .type = NLA_U32 },
++ };
++ struct nlattr *tb[NL80211_WIPHY_RADIO_ATTR_MAX + 1];
++
++ if (nla_parse_nested(tb, NL80211_WIPHY_RADIO_ATTR_MAX + 1,
++ radio, radio_policy) ||
++ !tb[NL80211_WIPHY_RADIO_ATTR_INDEX])
++ continue;
++
++ printf("\twiphy radio %d:\n", nla_get_u32(tb[NL80211_WIPHY_RADIO_ATTR_INDEX]));
++ print_radio_freq(radio);
++ print_interface_combinations(radio, true);
++ }
++}
++
+ static int print_phy_handler(struct nl_msg *msg, void *arg)
+ {
+ struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
+@@ -565,93 +710,11 @@ next:
+ "\t\t", tb_msg[NL80211_ATTR_SOFTWARE_IFTYPES]);
+ #endif
+
+- if (tb_msg[NL80211_ATTR_INTERFACE_COMBINATIONS]) {
+- struct nlattr *nl_combi;
+- int rem_combi;
+- bool have_combinations = false;
+-
+- nla_for_each_nested(nl_combi, tb_msg[NL80211_ATTR_INTERFACE_COMBINATIONS], rem_combi) {
+- static struct nla_policy iface_combination_policy[NUM_NL80211_IFACE_COMB] = {
+- [NL80211_IFACE_COMB_LIMITS] = { .type = NLA_NESTED },
+- [NL80211_IFACE_COMB_MAXNUM] = { .type = NLA_U32 },
+- [NL80211_IFACE_COMB_STA_AP_BI_MATCH] = { .type = NLA_FLAG },
+- [NL80211_IFACE_COMB_NUM_CHANNELS] = { .type = NLA_U32 },
+- [NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS] = { .type = NLA_U32 },
+- };
+- struct nlattr *tb_comb[NUM_NL80211_IFACE_COMB];
+- static struct nla_policy iface_limit_policy[NUM_NL80211_IFACE_LIMIT] = {
+- [NL80211_IFACE_LIMIT_TYPES] = { .type = NLA_NESTED },
+- [NL80211_IFACE_LIMIT_MAX] = { .type = NLA_U32 },
+- };
+- struct nlattr *tb_limit[NUM_NL80211_IFACE_LIMIT];
+- struct nlattr *nl_limit;
+- int err, rem_limit;
+- bool comma = false;
+-
+- if (!have_combinations) {
+- printf("\tvalid interface combinations:\n");
+- have_combinations = true;
+- }
+-
+- printf("\t\t * ");
++ if (tb_msg[NL80211_ATTR_INTERFACE_COMBINATIONS])
++ print_interface_combinations(tb_msg[NL80211_ATTR_INTERFACE_COMBINATIONS], false);
+
+- err = nla_parse_nested(tb_comb, MAX_NL80211_IFACE_COMB,
+- nl_combi, iface_combination_policy);
+- if (err || !tb_comb[NL80211_IFACE_COMB_LIMITS] ||
+- !tb_comb[NL80211_IFACE_COMB_MAXNUM] ||
+- !tb_comb[NL80211_IFACE_COMB_NUM_CHANNELS]) {
+- printf(" \n");
+- goto broken_combination;
+- }
+-
+- nla_for_each_nested(nl_limit, tb_comb[NL80211_IFACE_COMB_LIMITS], rem_limit) {
+- err = nla_parse_nested(tb_limit, MAX_NL80211_IFACE_LIMIT,
+- nl_limit, iface_limit_policy);
+- if (err || !tb_limit[NL80211_IFACE_LIMIT_TYPES]) {
+- printf("\n");
+- goto broken_combination;
+- }
+-
+- if (comma)
+- printf(", ");
+- comma = true;
+- printf("#{ ");
+- print_iftype_line(tb_limit[NL80211_IFACE_LIMIT_TYPES]);
+- printf(" } <= %u", nla_get_u32(tb_limit[NL80211_IFACE_LIMIT_MAX]));
+- }
+- printf(",\n\t\t ");
+-
+- printf("total <= %d, #channels <= %d%s",
+- nla_get_u32(tb_comb[NL80211_IFACE_COMB_MAXNUM]),
+- nla_get_u32(tb_comb[NL80211_IFACE_COMB_NUM_CHANNELS]),
+- tb_comb[NL80211_IFACE_COMB_STA_AP_BI_MATCH] ?
+- ", STA/AP BI must match" : "");
+- if (tb_comb[NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS]) {
+- unsigned long widths = nla_get_u32(tb_comb[NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS]);
+-
+- if (widths) {
+- int width;
+- bool first = true;
+-
+- printf(", radar detect widths: {");
+- for (width = 0; width < 32; width++)
+- if (widths & (1 << width)) {
+- printf("%s %s",
+- first ? "":",",
+- channel_width_name(width));
+- first = false;
+- }
+- printf(" }\n");
+- }
+- }
+- printf("\n");
+-broken_combination:
+- ;
+- }
+-
+- if (!have_combinations)
+- printf("\tinterface combinations are not supported\n");
+- }
++ if (tb_msg[NL80211_ATTR_WIPHY_RADIOS])
++ print_radios(tb_msg[NL80211_ATTR_WIPHY_RADIOS]);
+
+ #ifdef IW_FULL
+ if (tb_msg[NL80211_ATTR_SUPPORTED_COMMANDS]) {
diff --git a/package/network/utils/iw/patches/310-vif_radio_mask.patch b/package/network/utils/iw/patches/310-vif_radio_mask.patch
new file mode 100644
index 00000000000..724f71cdad5
--- /dev/null
+++ b/package/network/utils/iw/patches/310-vif_radio_mask.patch
@@ -0,0 +1,99 @@
+--- a/interface.c
++++ b/interface.c
+@@ -226,6 +226,43 @@ nla_put_failure:
+ return 1;
+ }
+
++static int parse_radio_list(char *str, struct nl_msg *msg)
++{
++ unsigned int mask = 0;
++ unsigned long id;
++ char *end;
++
++ if (!str)
++ return 1;
++
++ if (!strcmp(str, "all"))
++ goto out;
++
++ while (1) {
++ if (!*str)
++ return 1;
++
++ id = strtoul(str, &end, 0);
++ if (id > 31)
++ return 1;
++
++ mask |= 1 << id;
++ if (!*end)
++ break;
++
++ if (end == str || *end != ',')
++ return 1;
++
++ str = end + 1;
++ }
++
++out:
++ NLA_PUT_U32(msg, NL80211_ATTR_VIF_RADIO_MASK, mask);
++ return 0;
++nla_put_failure:
++ return 1;
++}
++
+ static int handle_interface_add(struct nl80211_state *state,
+ struct nl_msg *msg,
+ int argc, char **argv,
+@@ -287,6 +324,15 @@ try_another:
+ fprintf(stderr, "flags error\n");
+ return 2;
+ }
++ } else if (strcmp(argv[0], "radios") == 0) {
++ argc--;
++ argv++;
++ if (parse_radio_list(argv[0], msg)) {
++ fprintf(stderr, "Invalid radio list\n");
++ return 2;
++ }
++ argc--;
++ argv++;
+ } else {
+ return 1;
+ }
+@@ -306,14 +352,14 @@ try_another:
+ nla_put_failure:
+ return -ENOBUFS;
+ }
+-COMMAND(interface, add, " type [mesh_id ] [4addr on|off] [flags *] [addr ]",
++COMMAND(interface, add, " type [mesh_id ] [4addr on|off] [flags *] [addr ] [radios all|[,...]]",
+ NL80211_CMD_NEW_INTERFACE, 0, CIB_PHY, handle_interface_add,
+ "Add a new virtual interface with the given configuration.\n"
+ IFACE_TYPES "\n\n"
+ "The flags are only used for monitor interfaces, valid flags are:\n"
+ VALID_FLAGS "\n\n"
+ "The mesh_id is used only for mesh mode.");
+-COMMAND(interface, add, " type [mesh_id ] [4addr on|off] [flags *] [addr ]",
++COMMAND(interface, add, " type [mesh_id ] [4addr on|off] [flags *] [addr ] [radios all|[,...]]",
+ NL80211_CMD_NEW_INTERFACE, 0, CIB_NETDEV, handle_interface_add, NULL);
+
+ static int handle_interface_del(struct nl80211_state *state,
+@@ -493,6 +539,19 @@ static int print_iface_handler(struct nl
+ printf("\n");
+ }
+ }
++
++ if (tb_msg[NL80211_ATTR_VIF_RADIO_MASK]) {
++ uint32_t mask = nla_get_u32(tb_msg[NL80211_ATTR_VIF_RADIO_MASK]);
++ int i;
++
++ if (mask) {
++ printf("%s\tRadios:", indent);
++ for (i = 0; mask; i++, mask >>= 1)
++ if (mask & 1)
++ printf(" %d", i);
++ printf("\n");
++ }
++ }
+
+ return NL_SKIP;
+ }
diff --git a/package/network/utils/iwinfo/patches/100-multi_radio.patch b/package/network/utils/iwinfo/patches/100-multi_radio.patch
new file mode 100644
index 00000000000..3ad3b4fd10c
--- /dev/null
+++ b/package/network/utils/iwinfo/patches/100-multi_radio.patch
@@ -0,0 +1,1498 @@
+--- a/api/nl80211.h
++++ b/api/nl80211.h
+@@ -11,7 +11,7 @@
+ * Copyright 2008 Jouni Malinen
+ * Copyright 2008 Colin McCabe
+ * Copyright 2015-2017 Intel Deutschland GmbH
+- * Copyright (C) 2018-2023 Intel Corporation
++ * Copyright (C) 2018-2024 Intel Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+@@ -72,7 +72,7 @@
+ * For drivers supporting TDLS with external setup (WIPHY_FLAG_SUPPORTS_TDLS
+ * and WIPHY_FLAG_TDLS_EXTERNAL_SETUP), the station lifetime is as follows:
+ * - a setup station entry is added, not yet authorized, without any rate
+- * or capability information, this just exists to avoid race conditions
++ * or capability information; this just exists to avoid race conditions
+ * - when the TDLS setup is done, a single NL80211_CMD_SET_STATION is valid
+ * to add rate and capability information to the station and at the same
+ * time mark it authorized.
+@@ -87,7 +87,7 @@
+ * DOC: Frame transmission/registration support
+ *
+ * Frame transmission and registration support exists to allow userspace
+- * management entities such as wpa_supplicant react to management frames
++ * management entities such as wpa_supplicant to react to management frames
+ * that are not being handled by the kernel. This includes, for example,
+ * certain classes of action frames that cannot be handled in the kernel
+ * for various reasons.
+@@ -113,7 +113,7 @@
+ *
+ * Frame transmission allows userspace to send for example the required
+ * responses to action frames. It is subject to some sanity checking,
+- * but many frames can be transmitted. When a frame was transmitted, its
++ * but many frames can be transmitted. When a frame is transmitted, its
+ * status is indicated to the sending socket.
+ *
+ * For more technical details, see the corresponding command descriptions
+@@ -123,7 +123,7 @@
+ /**
+ * DOC: Virtual interface / concurrency capabilities
+ *
+- * Some devices are able to operate with virtual MACs, they can have
++ * Some devices are able to operate with virtual MACs; they can have
+ * more than one virtual interface. The capability handling for this
+ * is a bit complex though, as there may be a number of restrictions
+ * on the types of concurrency that are supported.
+@@ -135,7 +135,7 @@
+ * Once concurrency is desired, more attributes must be observed:
+ * To start with, since some interface types are purely managed in
+ * software, like the AP-VLAN type in mac80211 for example, there's
+- * an additional list of these, they can be added at any time and
++ * an additional list of these; they can be added at any time and
+ * are only restricted by some semantic restrictions (e.g. AP-VLAN
+ * cannot be added without a corresponding AP interface). This list
+ * is exported in the %NL80211_ATTR_SOFTWARE_IFTYPES attribute.
+@@ -164,17 +164,17 @@
+ * Packet coalesce feature helps to reduce number of received interrupts
+ * to host by buffering these packets in firmware/hardware for some
+ * predefined time. Received interrupt will be generated when one of the
+- * following events occur.
++ * following events occurs.
+ * a) Expiration of hardware timer whose expiration time is set to maximum
+ * coalescing delay of matching coalesce rule.
+- * b) Coalescing buffer in hardware reaches it's limit.
++ * b) Coalescing buffer in hardware reaches its limit.
+ * c) Packet doesn't match any of the configured coalesce rules.
+ *
+ * User needs to configure following parameters for creating a coalesce
+ * rule.
+ * a) Maximum coalescing delay
+ * b) List of packet patterns which needs to be matched
+- * c) Condition for coalescence. pattern 'match' or 'no match'
++ * c) Condition for coalescence: pattern 'match' or 'no match'
+ * Multiple such rules can be created.
+ */
+
+@@ -213,7 +213,7 @@
+ /**
+ * DOC: FILS shared key authentication offload
+ *
+- * FILS shared key authentication offload can be advertized by drivers by
++ * FILS shared key authentication offload can be advertised by drivers by
+ * setting @NL80211_EXT_FEATURE_FILS_SK_OFFLOAD flag. The drivers that support
+ * FILS shared key authentication offload should be able to construct the
+ * authentication and association frames for FILS shared key authentication and
+@@ -239,7 +239,7 @@
+ * The PMKSA can be maintained in userspace persistently so that it can be used
+ * later after reboots or wifi turn off/on also.
+ *
+- * %NL80211_ATTR_FILS_CACHE_ID is the cache identifier advertized by a FILS
++ * %NL80211_ATTR_FILS_CACHE_ID is the cache identifier advertised by a FILS
+ * capable AP supporting PMK caching. It specifies the scope within which the
+ * PMKSAs are cached in an ESS. %NL80211_CMD_SET_PMKSA and
+ * %NL80211_CMD_DEL_PMKSA are enhanced to allow support for PMKSA caching based
+@@ -290,12 +290,12 @@
+ * If the configuration needs to be applied for specific peer then the MAC
+ * address of the peer needs to be passed in %NL80211_ATTR_MAC, otherwise the
+ * configuration will be applied for all the connected peers in the vif except
+- * any peers that have peer specific configuration for the TID by default; if
+- * the %NL80211_TID_CONFIG_ATTR_OVERRIDE flag is set, peer specific values
++ * any peers that have peer-specific configuration for the TID by default; if
++ * the %NL80211_TID_CONFIG_ATTR_OVERRIDE flag is set, peer-specific values
+ * will be overwritten.
+ *
+- * All this configuration is valid only for STA's current connection
+- * i.e. the configuration will be reset to default when the STA connects back
++ * All this configuration is valid only for STA's current connection,
++ * i.e., the configuration will be reset to default when the STA connects back
+ * after disconnection/roaming, and this configuration will be cleared when
+ * the interface goes down.
+ */
+@@ -326,7 +326,7 @@
+ /**
+ * DOC: Multi-Link Operation
+ *
+- * In Multi-Link Operation, a connection between to MLDs utilizes multiple
++ * In Multi-Link Operation, a connection between two MLDs utilizes multiple
+ * links. To use this in nl80211, various commands and responses now need
+ * to or will include the new %NL80211_ATTR_MLO_LINKS attribute.
+ * Additionally, various commands that need to operate on a specific link
+@@ -335,6 +335,15 @@
+ */
+
+ /**
++ * DOC: OWE DH IE handling offload
++ *
++ * By setting @NL80211_EXT_FEATURE_OWE_OFFLOAD flag, drivers can indicate
++ * kernel/application space to avoid DH IE handling. When this flag is
++ * advertised, the driver/device will take care of DH IE inclusion and
++ * processing of peer DH IE to generate PMK.
++ */
++
++/**
+ * enum nl80211_commands - supported nl80211 commands
+ *
+ * @NL80211_CMD_UNSPEC: unspecified command to catch errors
+@@ -404,8 +413,8 @@
+ * are like for %NL80211_CMD_SET_BEACON, and additionally parameters that
+ * do not change are used, these include %NL80211_ATTR_BEACON_INTERVAL,
+ * %NL80211_ATTR_DTIM_PERIOD, %NL80211_ATTR_SSID,
+- * %NL80211_ATTR_HIDDEN_SSID, %NL80211_ATTR_CIPHERS_PAIRWISE,
+- * %NL80211_ATTR_CIPHER_GROUP, %NL80211_ATTR_WPA_VERSIONS,
++ * %NL80211_ATTR_HIDDEN_SSID, %NL80211_ATTR_CIPHER_SUITES_PAIRWISE,
++ * %NL80211_ATTR_CIPHER_SUITE_GROUP, %NL80211_ATTR_WPA_VERSIONS,
+ * %NL80211_ATTR_AKM_SUITES, %NL80211_ATTR_PRIVACY,
+ * %NL80211_ATTR_AUTH_TYPE, %NL80211_ATTR_INACTIVITY_TIMEOUT,
+ * %NL80211_ATTR_ACL_POLICY and %NL80211_ATTR_MAC_ADDRS.
+@@ -429,23 +438,19 @@
+ * %NL80211_ATTR_REASON_CODE can optionally be used to specify which type
+ * of disconnection indication should be sent to the station
+ * (Deauthentication or Disassociation frame and reason code for that
+- * frame).
++ * frame). %NL80211_ATTR_MLO_LINK_ID can be used optionally to remove
++ * stations connected and using at least that link as one of its links.
+ *
+ * @NL80211_CMD_GET_MPATH: Get mesh path attributes for mesh path to
+- * destination %NL80211_ATTR_MAC on the interface identified by
+- * %NL80211_ATTR_IFINDEX.
++ * destination %NL80211_ATTR_MAC on the interface identified by
++ * %NL80211_ATTR_IFINDEX.
+ * @NL80211_CMD_SET_MPATH: Set mesh path attributes for mesh path to
+- * destination %NL80211_ATTR_MAC on the interface identified by
+- * %NL80211_ATTR_IFINDEX.
++ * destination %NL80211_ATTR_MAC on the interface identified by
++ * %NL80211_ATTR_IFINDEX.
+ * @NL80211_CMD_NEW_MPATH: Create a new mesh path for the destination given by
+ * %NL80211_ATTR_MAC via %NL80211_ATTR_MPATH_NEXT_HOP.
+ * @NL80211_CMD_DEL_MPATH: Delete a mesh path to the destination given by
+ * %NL80211_ATTR_MAC.
+- * @NL80211_CMD_NEW_PATH: Add a mesh path with given attributes to the
+- * interface identified by %NL80211_ATTR_IFINDEX.
+- * @NL80211_CMD_DEL_PATH: Remove a mesh path identified by %NL80211_ATTR_MAC
+- * or, if no MAC address given, all mesh paths, on the interface identified
+- * by %NL80211_ATTR_IFINDEX.
+ * @NL80211_CMD_SET_BSS: Set BSS attributes for BSS identified by
+ * %NL80211_ATTR_IFINDEX.
+ *
+@@ -466,15 +471,15 @@
+ * after being queried by the kernel. CRDA replies by sending a regulatory
+ * domain structure which consists of %NL80211_ATTR_REG_ALPHA set to our
+ * current alpha2 if it found a match. It also provides
+- * NL80211_ATTR_REG_RULE_FLAGS, and a set of regulatory rules. Each
+- * regulatory rule is a nested set of attributes given by
+- * %NL80211_ATTR_REG_RULE_FREQ_[START|END] and
+- * %NL80211_ATTR_FREQ_RANGE_MAX_BW with an attached power rule given by
+- * %NL80211_ATTR_REG_RULE_POWER_MAX_ANT_GAIN and
+- * %NL80211_ATTR_REG_RULE_POWER_MAX_EIRP.
++ * NL80211_ATTR_REG_RULE_FLAGS, and a set of regulatory rules. Each
++ * regulatory rule is a nested set of attributes given by
++ * %NL80211_ATTR_REG_RULE_FREQ_[START|END] and
++ * %NL80211_ATTR_FREQ_RANGE_MAX_BW with an attached power rule given by
++ * %NL80211_ATTR_REG_RULE_POWER_MAX_ANT_GAIN and
++ * %NL80211_ATTR_REG_RULE_POWER_MAX_EIRP.
+ * @NL80211_CMD_REQ_SET_REG: ask the wireless core to set the regulatory domain
+- * to the specified ISO/IEC 3166-1 alpha2 country code. The core will
+- * store this as a valid request and then query userspace for it.
++ * to the specified ISO/IEC 3166-1 alpha2 country code. The core will
++ * store this as a valid request and then query userspace for it.
+ *
+ * @NL80211_CMD_GET_MESH_CONFIG: Get mesh networking properties for the
+ * interface identified by %NL80211_ATTR_IFINDEX
+@@ -512,7 +517,7 @@
+ * %NL80211_ATTR_SCHED_SCAN_PLANS. If %NL80211_ATTR_SCHED_SCAN_PLANS is
+ * not specified and only %NL80211_ATTR_SCHED_SCAN_INTERVAL is specified,
+ * scheduled scan will run in an infinite loop with the specified interval.
+- * These attributes are mutually exculsive,
++ * These attributes are mutually exclusive,
+ * i.e. NL80211_ATTR_SCHED_SCAN_INTERVAL must not be passed if
+ * NL80211_ATTR_SCHED_SCAN_PLANS is defined.
+ * If for some reason scheduled scan is aborted by the driver, all scan
+@@ -543,7 +548,7 @@
+ * %NL80211_CMD_STOP_SCHED_SCAN command is received or when the interface
+ * is brought down while a scheduled scan was running.
+ *
+- * @NL80211_CMD_GET_SURVEY: get survey resuls, e.g. channel occupation
++ * @NL80211_CMD_GET_SURVEY: get survey results, e.g. channel occupation
+ * or noise level
+ * @NL80211_CMD_NEW_SURVEY_RESULTS: survey data notification (as a reply to
+ * NL80211_CMD_GET_SURVEY and on the "scan" multicast group)
+@@ -554,40 +559,41 @@
+ * using %NL80211_ATTR_SSID, %NL80211_ATTR_FILS_CACHE_ID,
+ * %NL80211_ATTR_PMKID, and %NL80211_ATTR_PMK in case of FILS
+ * authentication where %NL80211_ATTR_FILS_CACHE_ID is the identifier
+- * advertized by a FILS capable AP identifying the scope of PMKSA in an
++ * advertised by a FILS capable AP identifying the scope of PMKSA in an
+ * ESS.
+ * @NL80211_CMD_DEL_PMKSA: Delete a PMKSA cache entry, using %NL80211_ATTR_MAC
+ * (for the BSSID) and %NL80211_ATTR_PMKID or using %NL80211_ATTR_SSID,
+ * %NL80211_ATTR_FILS_CACHE_ID, and %NL80211_ATTR_PMKID in case of FILS
+- * authentication.
++ * authentication. Additionally in case of SAE offload and OWE offloads
++ * PMKSA entry can be deleted using %NL80211_ATTR_SSID.
+ * @NL80211_CMD_FLUSH_PMKSA: Flush all PMKSA cache entries.
+ *
+ * @NL80211_CMD_REG_CHANGE: indicates to userspace the regulatory domain
+- * has been changed and provides details of the request information
+- * that caused the change such as who initiated the regulatory request
+- * (%NL80211_ATTR_REG_INITIATOR), the wiphy_idx
+- * (%NL80211_ATTR_REG_ALPHA2) on which the request was made from if
+- * the initiator was %NL80211_REGDOM_SET_BY_COUNTRY_IE or
+- * %NL80211_REGDOM_SET_BY_DRIVER, the type of regulatory domain
+- * set (%NL80211_ATTR_REG_TYPE), if the type of regulatory domain is
+- * %NL80211_REG_TYPE_COUNTRY the alpha2 to which we have moved on
+- * to (%NL80211_ATTR_REG_ALPHA2).
++ * has been changed and provides details of the request information
++ * that caused the change such as who initiated the regulatory request
++ * (%NL80211_ATTR_REG_INITIATOR), the wiphy_idx
++ * (%NL80211_ATTR_REG_ALPHA2) on which the request was made from if
++ * the initiator was %NL80211_REGDOM_SET_BY_COUNTRY_IE or
++ * %NL80211_REGDOM_SET_BY_DRIVER, the type of regulatory domain
++ * set (%NL80211_ATTR_REG_TYPE), if the type of regulatory domain is
++ * %NL80211_REG_TYPE_COUNTRY the alpha2 to which we have moved on
++ * to (%NL80211_ATTR_REG_ALPHA2).
+ * @NL80211_CMD_REG_BEACON_HINT: indicates to userspace that an AP beacon
+- * has been found while world roaming thus enabling active scan or
+- * any mode of operation that initiates TX (beacons) on a channel
+- * where we would not have been able to do either before. As an example
+- * if you are world roaming (regulatory domain set to world or if your
+- * driver is using a custom world roaming regulatory domain) and while
+- * doing a passive scan on the 5 GHz band you find an AP there (if not
+- * on a DFS channel) you will now be able to actively scan for that AP
+- * or use AP mode on your card on that same channel. Note that this will
+- * never be used for channels 1-11 on the 2 GHz band as they are always
+- * enabled world wide. This beacon hint is only sent if your device had
+- * either disabled active scanning or beaconing on a channel. We send to
+- * userspace the wiphy on which we removed a restriction from
+- * (%NL80211_ATTR_WIPHY) and the channel on which this occurred
+- * before (%NL80211_ATTR_FREQ_BEFORE) and after (%NL80211_ATTR_FREQ_AFTER)
+- * the beacon hint was processed.
++ * has been found while world roaming thus enabling active scan or
++ * any mode of operation that initiates TX (beacons) on a channel
++ * where we would not have been able to do either before. As an example
++ * if you are world roaming (regulatory domain set to world or if your
++ * driver is using a custom world roaming regulatory domain) and while
++ * doing a passive scan on the 5 GHz band you find an AP there (if not
++ * on a DFS channel) you will now be able to actively scan for that AP
++ * or use AP mode on your card on that same channel. Note that this will
++ * never be used for channels 1-11 on the 2 GHz band as they are always
++ * enabled world wide. This beacon hint is only sent if your device had
++ * either disabled active scanning or beaconing on a channel. We send to
++ * userspace the wiphy on which we removed a restriction from
++ * (%NL80211_ATTR_WIPHY) and the channel on which this occurred
++ * before (%NL80211_ATTR_FREQ_BEFORE) and after (%NL80211_ATTR_FREQ_AFTER)
++ * the beacon hint was processed.
+ *
+ * @NL80211_CMD_AUTHENTICATE: authentication request and notification.
+ * This command is used both as a command (request to authenticate) and
+@@ -598,7 +604,7 @@
+ * BSSID in case of station mode). %NL80211_ATTR_SSID is used to specify
+ * the SSID (mainly for association, but is included in authentication
+ * request, too, to help BSS selection. %NL80211_ATTR_WIPHY_FREQ +
+- * %NL80211_ATTR_WIPHY_FREQ_OFFSET is used to specify the frequence of the
++ * %NL80211_ATTR_WIPHY_FREQ_OFFSET is used to specify the frequency of the
+ * channel in MHz. %NL80211_ATTR_AUTH_TYPE is used to specify the
+ * authentication type. %NL80211_ATTR_IE is used to define IEs
+ * (VendorSpecificInfo, but also including RSN IE and FT IEs) to be added
+@@ -807,7 +813,7 @@
+ * reached.
+ * @NL80211_CMD_SET_CHANNEL: Set the channel (using %NL80211_ATTR_WIPHY_FREQ
+ * and the attributes determining channel width) the given interface
+- * (identifed by %NL80211_ATTR_IFINDEX) shall operate on.
++ * (identified by %NL80211_ATTR_IFINDEX) shall operate on.
+ * In case multiple channels are supported by the device, the mechanism
+ * with which it switches channels is implementation-defined.
+ * When a monitor interface is given, it can only switch channel while
+@@ -879,7 +885,7 @@
+ * inform userspace of the new replay counter.
+ *
+ * @NL80211_CMD_PMKSA_CANDIDATE: This is used as an event to inform userspace
+- * of PMKSA caching dandidates.
++ * of PMKSA caching candidates.
+ *
+ * @NL80211_CMD_TDLS_OPER: Perform a high-level TDLS command (e.g. link setup).
+ * In addition, this can be used as an event to request userspace to take
+@@ -915,7 +921,7 @@
+ *
+ * @NL80211_CMD_PROBE_CLIENT: Probe an associated station on an AP interface
+ * by sending a null data frame to it and reporting when the frame is
+- * acknowleged. This is used to allow timing out inactive clients. Uses
++ * acknowledged. This is used to allow timing out inactive clients. Uses
+ * %NL80211_ATTR_IFINDEX and %NL80211_ATTR_MAC. The command returns a
+ * direct reply with an %NL80211_ATTR_COOKIE that is later used to match
+ * up the event with the request. The event includes the same data and
+@@ -1109,7 +1115,7 @@
+ * current configuration is not changed. If it is present but
+ * set to zero, the configuration is changed to don't-care
+ * (i.e. the device can decide what to do).
+- * @NL80211_CMD_NAN_FUNC_MATCH: Notification sent when a match is reported.
++ * @NL80211_CMD_NAN_MATCH: Notification sent when a match is reported.
+ * This will contain a %NL80211_ATTR_NAN_MATCH nested attribute and
+ * %NL80211_ATTR_COOKIE.
+ *
+@@ -1126,11 +1132,15 @@
+ * @NL80211_CMD_DEL_PMK: For offloaded 4-Way handshake, delete the previously
+ * configured PMK for the authenticator address identified by
+ * %NL80211_ATTR_MAC.
+- * @NL80211_CMD_PORT_AUTHORIZED: An event that indicates an 802.1X FT roam was
+- * completed successfully. Drivers that support 4 way handshake offload
+- * should send this event after indicating 802.1X FT assocation with
+- * %NL80211_CMD_ROAM. If the 4 way handshake failed %NL80211_CMD_DISCONNECT
+- * should be indicated instead.
++ * @NL80211_CMD_PORT_AUTHORIZED: An event that indicates port is authorized and
++ * open for regular data traffic. For STA/P2P-client, this event is sent
++ * with AP MAC address and for AP/P2P-GO, the event carries the STA/P2P-
++ * client MAC address.
++ * Drivers that support 4 way handshake offload should send this event for
++ * STA/P2P-client after successful 4-way HS or after 802.1X FT following
++ * NL80211_CMD_CONNECT or NL80211_CMD_ROAM. Drivers using AP/P2P-GO 4-way
++ * handshake offload should send this event on successful completion of
++ * 4-way handshake with the peer (STA/P2P-client).
+ * @NL80211_CMD_CONTROL_PORT_FRAME: Control Port (e.g. PAE) frame TX request
+ * and RX notification. This command is used both as a request to transmit
+ * a control port frame and as a notification that a control port frame
+@@ -1314,6 +1324,11 @@
+ * Multi-Link reconfiguration. %NL80211_ATTR_MLO_LINKS is used to provide
+ * information about the removed STA MLD setup links.
+ *
++ * @NL80211_CMD_SET_TID_TO_LINK_MAPPING: Set the TID to Link Mapping for a
++ * non-AP MLD station. The %NL80211_ATTR_MLO_TTLM_DLINK and
++ * %NL80211_ATTR_MLO_TTLM_ULINK attributes are used to specify the
++ * TID to Link mapping for downlink/uplink traffic.
++ *
+ * @NL80211_CMD_MAX: highest used command number
+ * @__NL80211_CMD_AFTER_LAST: internal use
+ */
+@@ -1569,6 +1584,8 @@ enum nl80211_commands {
+
+ NL80211_CMD_LINKS_REMOVED,
+
++ NL80211_CMD_SET_TID_TO_LINK_MAPPING,
++
+ /* add new commands above here */
+
+ /* used to define NL80211_CMD_MAX below */
+@@ -1693,21 +1710,21 @@ enum nl80211_commands {
+ * (see &enum nl80211_plink_action).
+ * @NL80211_ATTR_MPATH_NEXT_HOP: MAC address of the next hop for a mesh path.
+ * @NL80211_ATTR_MPATH_INFO: information about a mesh_path, part of mesh path
+- * info given for %NL80211_CMD_GET_MPATH, nested attribute described at
++ * info given for %NL80211_CMD_GET_MPATH, nested attribute described at
+ * &enum nl80211_mpath_info.
+ *
+ * @NL80211_ATTR_MNTR_FLAGS: flags, nested element with NLA_FLAG attributes of
+ * &enum nl80211_mntr_flags.
+ *
+ * @NL80211_ATTR_REG_ALPHA2: an ISO-3166-alpha2 country code for which the
+- * current regulatory domain should be set to or is already set to.
+- * For example, 'CR', for Costa Rica. This attribute is used by the kernel
+- * to query the CRDA to retrieve one regulatory domain. This attribute can
+- * also be used by userspace to query the kernel for the currently set
+- * regulatory domain. We chose an alpha2 as that is also used by the
+- * IEEE-802.11 country information element to identify a country.
+- * Users can also simply ask the wireless core to set regulatory domain
+- * to a specific alpha2.
++ * current regulatory domain should be set to or is already set to.
++ * For example, 'CR', for Costa Rica. This attribute is used by the kernel
++ * to query the CRDA to retrieve one regulatory domain. This attribute can
++ * also be used by userspace to query the kernel for the currently set
++ * regulatory domain. We chose an alpha2 as that is also used by the
++ * IEEE-802.11 country information element to identify a country.
++ * Users can also simply ask the wireless core to set regulatory domain
++ * to a specific alpha2.
+ * @NL80211_ATTR_REG_RULES: a nested array of regulatory domain regulatory
+ * rules.
+ *
+@@ -1750,9 +1767,9 @@ enum nl80211_commands {
+ * @NL80211_ATTR_BSS: scan result BSS
+ *
+ * @NL80211_ATTR_REG_INITIATOR: indicates who requested the regulatory domain
+- * currently in effect. This could be any of the %NL80211_REGDOM_SET_BY_*
++ * currently in effect. This could be any of the %NL80211_REGDOM_SET_BY_*
+ * @NL80211_ATTR_REG_TYPE: indicates the type of the regulatory domain currently
+- * set. This can be one of the nl80211_reg_type (%NL80211_REGDOM_TYPE_*)
++ * set. This can be one of the nl80211_reg_type (%NL80211_REGDOM_TYPE_*)
+ *
+ * @NL80211_ATTR_SUPPORTED_COMMANDS: wiphy attribute that specifies
+ * an array of command numbers (i.e. a mapping index to command number)
+@@ -1771,15 +1788,15 @@ enum nl80211_commands {
+ * a u32
+ *
+ * @NL80211_ATTR_FREQ_BEFORE: A channel which has suffered a regulatory change
+- * due to considerations from a beacon hint. This attribute reflects
+- * the state of the channel _before_ the beacon hint processing. This
+- * attributes consists of a nested attribute containing
+- * NL80211_FREQUENCY_ATTR_*
++ * due to considerations from a beacon hint. This attribute reflects
++ * the state of the channel _before_ the beacon hint processing. This
++ * attributes consists of a nested attribute containing
++ * NL80211_FREQUENCY_ATTR_*
+ * @NL80211_ATTR_FREQ_AFTER: A channel which has suffered a regulatory change
+- * due to considerations from a beacon hint. This attribute reflects
+- * the state of the channel _after_ the beacon hint processing. This
+- * attributes consists of a nested attribute containing
+- * NL80211_FREQUENCY_ATTR_*
++ * due to considerations from a beacon hint. This attribute reflects
++ * the state of the channel _after_ the beacon hint processing. This
++ * attributes consists of a nested attribute containing
++ * NL80211_FREQUENCY_ATTR_*
+ *
+ * @NL80211_ATTR_CIPHER_SUITES: a set of u32 values indicating the supported
+ * cipher suites
+@@ -1826,7 +1843,7 @@ enum nl80211_commands {
+ * using %CMD_CONTROL_PORT_FRAME. If control port routing over NL80211 is
+ * to be used then userspace must also use the %NL80211_ATTR_SOCKET_OWNER
+ * flag. When used with %NL80211_ATTR_CONTROL_PORT_NO_PREAUTH, pre-auth
+- * frames are not forwared over the control port.
++ * frames are not forwarded over the control port.
+ *
+ * @NL80211_ATTR_TESTDATA: Testmode data blob, passed through to the driver.
+ * We recommend using nested, driver-specific attributes within this.
+@@ -1840,12 +1857,6 @@ enum nl80211_commands {
+ * that protected APs should be used. This is also used with NEW_BEACON to
+ * indicate that the BSS is to use protection.
+ *
+- * @NL80211_ATTR_CIPHERS_PAIRWISE: Used with CONNECT, ASSOCIATE, and NEW_BEACON
+- * to indicate which unicast key ciphers will be used with the connection
+- * (an array of u32).
+- * @NL80211_ATTR_CIPHER_GROUP: Used with CONNECT, ASSOCIATE, and NEW_BEACON to
+- * indicate which group key cipher will be used with the connection (a
+- * u32).
+ * @NL80211_ATTR_WPA_VERSIONS: Used with CONNECT, ASSOCIATE, and NEW_BEACON to
+ * indicate which WPA version(s) the AP we want to associate with is using
+ * (a u32 with flags from &enum nl80211_wpa_versions).
+@@ -1876,6 +1887,7 @@ enum nl80211_commands {
+ * with %NL80211_KEY_* sub-attributes
+ *
+ * @NL80211_ATTR_PID: Process ID of a network namespace.
++ * @NL80211_ATTR_NETNS_FD: File descriptor of a network namespace.
+ *
+ * @NL80211_ATTR_GENERATION: Used to indicate consistent snapshots for
+ * dumps. This number increases whenever the object list being
+@@ -1930,6 +1942,7 @@ enum nl80211_commands {
+ *
+ * @NL80211_ATTR_ACK: Flag attribute indicating that the frame was
+ * acknowledged by the recipient.
++ * @NL80211_ATTR_ACK_SIGNAL: Station's ack signal strength (s32)
+ *
+ * @NL80211_ATTR_PS_STATE: powersave state, using &enum nl80211_ps_state values.
+ *
+@@ -1963,10 +1976,10 @@ enum nl80211_commands {
+ * bit. Depending on which antennas are selected in the bitmap, 802.11n
+ * drivers can derive which chainmasks to use (if all antennas belonging to
+ * a particular chain are disabled this chain should be disabled) and if
+- * a chain has diversity antennas wether diversity should be used or not.
++ * a chain has diversity antennas whether diversity should be used or not.
+ * HT capabilities (STBC, TX Beamforming, Antenna selection) can be
+ * derived from the available chains after applying the antenna mask.
+- * Non-802.11n drivers can derive wether to use diversity or not.
++ * Non-802.11n drivers can derive whether to use diversity or not.
+ * Drivers may reject configurations or RX/TX mask combinations they cannot
+ * support by returning -EINVAL.
+ *
+@@ -2039,6 +2052,10 @@ enum nl80211_commands {
+ * @NL80211_ATTR_INTERFACE_COMBINATIONS: Nested attribute listing the supported
+ * interface combinations. In each nested item, it contains attributes
+ * defined in &enum nl80211_if_combination_attrs.
++ * If the wiphy uses multiple radios (@NL80211_ATTR_WIPHY_RADIOS is set),
++ * this attribute contains the interface combinations of the first radio.
++ * See @NL80211_ATTR_WIPHY_INTERFACE_COMBINATIONS for the global wiphy
++ * combinations for the sum of all radios.
+ * @NL80211_ATTR_SOFTWARE_IFTYPES: Nested attribute (just like
+ * %NL80211_ATTR_SUPPORTED_IFTYPES) containing the interface types that
+ * are managed in software: interfaces of these types aren't subject to
+@@ -2127,6 +2144,9 @@ enum nl80211_commands {
+ * @NL80211_ATTR_DISABLE_HE: Force HE capable interfaces to disable
+ * this feature during association. This is a flag attribute.
+ * Currently only supported in mac80211 drivers.
++ * @NL80211_ATTR_DISABLE_EHT: Force EHT capable interfaces to disable
++ * this feature during association. This is a flag attribute.
++ * Currently only supported in mac80211 drivers.
+ * @NL80211_ATTR_HT_CAPABILITY_MASK: Specify which bits of the
+ * ATTR_HT_CAPABILITY to which attention should be paid.
+ * Currently, only mac80211 NICs support this feature.
+@@ -2136,6 +2156,12 @@ enum nl80211_commands {
+ * All values are treated as suggestions and may be ignored
+ * by the driver as required. The actual values may be seen in
+ * the station debugfs ht_caps file.
++ * @NL80211_ATTR_VHT_CAPABILITY_MASK: Specify which bits of the
++ * ATTR_VHT_CAPABILITY to which attention should be paid.
++ * Currently, only mac80211 NICs support this feature.
++ * All values are treated as suggestions and may be ignored
++ * by the driver as required. The actual values may be seen in
++ * the station debugfs vht_caps file.
+ *
+ * @NL80211_ATTR_DFS_REGION: region for regulatory rules which this country
+ * abides to when initiating radiation on DFS channels. A country maps
+@@ -2394,7 +2420,7 @@ enum nl80211_commands {
+ * scheduled scan is started. Or the delay before a WoWLAN
+ * net-detect scan is started, counting from the moment the
+ * system is suspended. This value is a u32, in seconds.
+-
++ *
+ * @NL80211_ATTR_REG_INDOOR: flag attribute, if set indicates that the device
+ * is operating in an indoor environment.
+ *
+@@ -2536,7 +2562,7 @@ enum nl80211_commands {
+ * from successful FILS authentication and is used with
+ * %NL80211_CMD_CONNECT.
+ *
+- * @NL80211_ATTR_FILS_CACHE_ID: A 2-octet identifier advertized by a FILS AP
++ * @NL80211_ATTR_FILS_CACHE_ID: A 2-octet identifier advertised by a FILS AP
+ * identifying the scope of PMKSAs. This is used with
+ * @NL80211_CMD_SET_PMKSA and @NL80211_CMD_DEL_PMKSA.
+ *
+@@ -2690,11 +2716,13 @@ enum nl80211_commands {
+ *
+ * @NL80211_ATTR_FILS_DISCOVERY: Optional parameter to configure FILS
+ * discovery. It is a nested attribute, see
+- * &enum nl80211_fils_discovery_attributes.
++ * &enum nl80211_fils_discovery_attributes. Userspace should pass an empty
++ * nested attribute to disable this feature and delete the templates.
+ *
+ * @NL80211_ATTR_UNSOL_BCAST_PROBE_RESP: Optional parameter to configure
+ * unsolicited broadcast probe response. It is a nested attribute, see
+- * &enum nl80211_unsol_bcast_probe_resp_attributes.
++ * &enum nl80211_unsol_bcast_probe_resp_attributes. Userspace should pass an empty
++ * nested attribute to disable this feature and delete the templates.
+ *
+ * @NL80211_ATTR_S1G_CAPABILITY: S1G Capability information element (from
+ * association request when used with NL80211_CMD_NEW_STATION)
+@@ -2815,6 +2843,34 @@ enum nl80211_commands {
+ * @NL80211_ATTR_MLO_LINK_DISABLED: Flag attribute indicating that the link is
+ * disabled.
+ *
++ * @NL80211_ATTR_BSS_DUMP_INCLUDE_USE_DATA: Include BSS usage data, i.e.
++ * include BSSes that can only be used in restricted scenarios and/or
++ * cannot be used at all.
++ *
++ * @NL80211_ATTR_MLO_TTLM_DLINK: Binary attribute specifying the downlink TID to
++ * link mapping. The length is 8 * sizeof(u16). For each TID the link
++ * mapping is as defined in section 9.4.2.314 (TID-To-Link Mapping element)
++ * in Draft P802.11be_D4.0.
++ * @NL80211_ATTR_MLO_TTLM_ULINK: Binary attribute specifying the uplink TID to
++ * link mapping. The length is 8 * sizeof(u16). For each TID the link
++ * mapping is as defined in section 9.4.2.314 (TID-To-Link Mapping element)
++ * in Draft P802.11be_D4.0.
++ *
++ * @NL80211_ATTR_ASSOC_SPP_AMSDU: flag attribute used with
++ * %NL80211_CMD_ASSOCIATE indicating the SPP A-MSDUs
++ * are used on this connection
++ *
++ * @NL80211_ATTR_WIPHY_RADIOS: Nested attribute describing physical radios
++ * belonging to this wiphy. See &enum nl80211_wiphy_radio_attrs.
++ *
++ * @NL80211_ATTR_WIPHY_INTERFACE_COMBINATIONS: Nested attribute listing the
++ * supported interface combinations for all radios combined. In each
++ * nested item, it contains attributes defined in
++ * &enum nl80211_if_combination_attrs.
++ *
++ * @NL80211_ATTR_VIF_RADIO_MASK: Bitmask of allowed radios (u32).
++ * A value of 0 means all radios.
++ *
+ * @NUM_NL80211_ATTR: total number of nl80211_attrs available
+ * @NL80211_ATTR_MAX: highest attribute number currently defined
+ * @__NL80211_ATTR_AFTER_LAST: internal use
+@@ -3353,6 +3409,18 @@ enum nl80211_attrs {
+
+ NL80211_ATTR_MLO_LINK_DISABLED,
+
++ NL80211_ATTR_BSS_DUMP_INCLUDE_USE_DATA,
++
++ NL80211_ATTR_MLO_TTLM_DLINK,
++ NL80211_ATTR_MLO_TTLM_ULINK,
++
++ NL80211_ATTR_ASSOC_SPP_AMSDU,
++
++ NL80211_ATTR_WIPHY_RADIOS,
++ NL80211_ATTR_WIPHY_INTERFACE_COMBINATIONS,
++
++ NL80211_ATTR_VIF_RADIO_MASK,
++
+ /* add attributes here, update the policy in nl80211.c */
+
+ __NL80211_ATTR_AFTER_LAST,
+@@ -3493,6 +3561,7 @@ enum nl80211_iftype {
+ * @NL80211_STA_FLAG_ASSOCIATED: station is associated; used with drivers
+ * that support %NL80211_FEATURE_FULL_AP_CLIENT_STATE to transition a
+ * previously added station into associated state
++ * @NL80211_STA_FLAG_SPP_AMSDU: station supports SPP A-MSDUs
+ * @NL80211_STA_FLAG_MAX: highest station flag number currently defined
+ * @__NL80211_STA_FLAG_AFTER_LAST: internal use
+ */
+@@ -3505,6 +3574,7 @@ enum nl80211_sta_flags {
+ NL80211_STA_FLAG_AUTHENTICATED,
+ NL80211_STA_FLAG_TDLS_PEER,
+ NL80211_STA_FLAG_ASSOCIATED,
++ NL80211_STA_FLAG_SPP_AMSDU,
+
+ /* keep last */
+ __NL80211_STA_FLAG_AFTER_LAST,
+@@ -3515,7 +3585,7 @@ enum nl80211_sta_flags {
+ * enum nl80211_sta_p2p_ps_status - station support of P2P PS
+ *
+ * @NL80211_P2P_PS_UNSUPPORTED: station doesn't support P2P PS mechanism
+- * @@NL80211_P2P_PS_SUPPORTED: station supports P2P PS mechanism
++ * @NL80211_P2P_PS_SUPPORTED: station supports P2P PS mechanism
+ * @NUM_NL80211_P2P_PS_STATUS: number of values
+ */
+ enum nl80211_sta_p2p_ps_status {
+@@ -3553,9 +3623,9 @@ enum nl80211_he_gi {
+
+ /**
+ * enum nl80211_he_ltf - HE long training field
+- * @NL80211_RATE_INFO_HE_1xLTF: 3.2 usec
+- * @NL80211_RATE_INFO_HE_2xLTF: 6.4 usec
+- * @NL80211_RATE_INFO_HE_4xLTF: 12.8 usec
++ * @NL80211_RATE_INFO_HE_1XLTF: 3.2 usec
++ * @NL80211_RATE_INFO_HE_2XLTF: 6.4 usec
++ * @NL80211_RATE_INFO_HE_4XLTF: 12.8 usec
+ */
+ enum nl80211_he_ltf {
+ NL80211_RATE_INFO_HE_1XLTF,
+@@ -3670,7 +3740,7 @@ enum nl80211_eht_ru_alloc {
+ * @NL80211_RATE_INFO_HE_GI: HE guard interval identifier
+ * (u8, see &enum nl80211_he_gi)
+ * @NL80211_RATE_INFO_HE_DCM: HE DCM value (u8, 0/1)
+- * @NL80211_RATE_INFO_RU_ALLOC: HE RU allocation, if not present then
++ * @NL80211_RATE_INFO_HE_RU_ALLOC: HE RU allocation, if not present then
+ * non-OFDMA was used (u8, see &enum nl80211_he_ru_alloc)
+ * @NL80211_RATE_INFO_320_MHZ_WIDTH: 320 MHz bitrate
+ * @NL80211_RATE_INFO_EHT_MCS: EHT MCS index (u8, 0-15)
+@@ -3773,7 +3843,7 @@ enum nl80211_sta_bss_param {
+ * (u64, to this station)
+ * @NL80211_STA_INFO_SIGNAL: signal strength of last received PPDU (u8, dBm)
+ * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate, nested attribute
+- * containing info as possible, see &enum nl80211_rate_info
++ * containing info as possible, see &enum nl80211_rate_info
+ * @NL80211_STA_INFO_RX_PACKETS: total received packet (MSDUs and MMPDUs)
+ * (u32, from this station)
+ * @NL80211_STA_INFO_TX_PACKETS: total transmitted packets (MSDUs and MMPDUs)
+@@ -3802,8 +3872,8 @@ enum nl80211_sta_bss_param {
+ * Contains a nested array of signal strength attributes (u8, dBm)
+ * @NL80211_STA_INFO_CHAIN_SIGNAL_AVG: per-chain signal strength average
+ * Same format as NL80211_STA_INFO_CHAIN_SIGNAL.
+- * @NL80211_STA_EXPECTED_THROUGHPUT: expected throughput considering also the
+- * 802.11 header (u32, kbps)
++ * @NL80211_STA_INFO_EXPECTED_THROUGHPUT: expected throughput considering also
++ * the 802.11 header (u32, kbps)
+ * @NL80211_STA_INFO_RX_DROP_MISC: RX packets dropped for unspecified reasons
+ * (u64)
+ * @NL80211_STA_INFO_BEACON_RX: number of beacons received from this peer (u64)
+@@ -3989,7 +4059,7 @@ enum nl80211_mpath_flags {
+ * @NL80211_MPATH_INFO_METRIC: metric (cost) of this mesh path
+ * @NL80211_MPATH_INFO_EXPTIME: expiration time for the path, in msec from now
+ * @NL80211_MPATH_INFO_FLAGS: mesh path flags, enumerated in
+- * &enum nl80211_mpath_flags;
++ * &enum nl80211_mpath_flags;
+ * @NL80211_MPATH_INFO_DISCOVERY_TIMEOUT: total path discovery timeout, in msec
+ * @NL80211_MPATH_INFO_DISCOVERY_RETRIES: mesh path discovery retries
+ * @NL80211_MPATH_INFO_HOP_COUNT: hop count to destination
+@@ -4129,7 +4199,7 @@ enum nl80211_band_attr {
+ * @NL80211_WMMR_CW_MAX: Maximum contention window slot.
+ * @NL80211_WMMR_AIFSN: Arbitration Inter Frame Space.
+ * @NL80211_WMMR_TXOP: Maximum allowed tx operation time.
+- * @nl80211_WMMR_MAX: highest possible wmm rule.
++ * @NL80211_WMMR_MAX: highest possible wmm rule.
+ * @__NL80211_WMMR_LAST: Internal use.
+ */
+ enum nl80211_wmm_rule {
+@@ -4151,15 +4221,16 @@ enum nl80211_wmm_rule {
+ * @NL80211_FREQUENCY_ATTR_DISABLED: Channel is disabled in current
+ * regulatory domain.
+ * @NL80211_FREQUENCY_ATTR_NO_IR: no mechanisms that initiate radiation
+- * are permitted on this channel, this includes sending probe
+- * requests, or modes of operation that require beaconing.
++ * are permitted on this channel, this includes sending probe
++ * requests, or modes of operation that require beaconing.
++ * @__NL80211_FREQUENCY_ATTR_NO_IBSS: obsolete, same as _NO_IR
+ * @NL80211_FREQUENCY_ATTR_RADAR: Radar detection is mandatory
+ * on this channel in current regulatory domain.
+ * @NL80211_FREQUENCY_ATTR_MAX_TX_POWER: Maximum transmission power in mBm
+ * (100 * dBm).
+ * @NL80211_FREQUENCY_ATTR_DFS_STATE: current state for DFS
+ * (enum nl80211_dfs_state)
+- * @NL80211_FREQUENCY_ATTR_DFS_TIME: time in miliseconds for how long
++ * @NL80211_FREQUENCY_ATTR_DFS_TIME: time in milliseconds for how long
+ * this channel is in this DFS state.
+ * @NL80211_FREQUENCY_ATTR_NO_HT40_MINUS: HT40- isn't possible with this
+ * channel as the control channel
+@@ -4213,6 +4284,21 @@ enum nl80211_wmm_rule {
+ * as the primary or any of the secondary channels isn't possible
+ * @NL80211_FREQUENCY_ATTR_NO_EHT: EHT operation is not allowed on this channel
+ * in current regulatory domain.
++ * @NL80211_FREQUENCY_ATTR_PSD: Power spectral density (in dBm) that
++ * is allowed on this channel in current regulatory domain.
++ * @NL80211_FREQUENCY_ATTR_DFS_CONCURRENT: Operation on this channel is
++ * allowed for peer-to-peer or adhoc communication under the control
++ * of a DFS master which operates on the same channel (FCC-594280 D01
++ * Section B.3). Should be used together with %NL80211_RRF_DFS only.
++ * @NL80211_FREQUENCY_ATTR_NO_6GHZ_VLP_CLIENT: Client connection to VLP AP
++ * not allowed using this channel
++ * @NL80211_FREQUENCY_ATTR_NO_6GHZ_AFC_CLIENT: Client connection to AFC AP
++ * not allowed using this channel
++ * @NL80211_FREQUENCY_ATTR_CAN_MONITOR: This channel can be used in monitor
++ * mode despite other (regulatory) restrictions, even if the channel is
++ * otherwise completely disabled.
++ * @NL80211_FREQUENCY_ATTR_ALLOW_6GHZ_VLP_AP: This channel can be used for a
++ * very low power (VLP) AP, despite being NO_IR.
+ * @NL80211_FREQUENCY_ATTR_MAX: highest frequency attribute number
+ * currently defined
+ * @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use
+@@ -4251,6 +4337,12 @@ enum nl80211_frequency_attr {
+ NL80211_FREQUENCY_ATTR_16MHZ,
+ NL80211_FREQUENCY_ATTR_NO_320MHZ,
+ NL80211_FREQUENCY_ATTR_NO_EHT,
++ NL80211_FREQUENCY_ATTR_PSD,
++ NL80211_FREQUENCY_ATTR_DFS_CONCURRENT,
++ NL80211_FREQUENCY_ATTR_NO_6GHZ_VLP_CLIENT,
++ NL80211_FREQUENCY_ATTR_NO_6GHZ_AFC_CLIENT,
++ NL80211_FREQUENCY_ATTR_CAN_MONITOR,
++ NL80211_FREQUENCY_ATTR_ALLOW_6GHZ_VLP_AP,
+
+ /* keep last */
+ __NL80211_FREQUENCY_ATTR_AFTER_LAST,
+@@ -4263,6 +4355,10 @@ enum nl80211_frequency_attr {
+ #define NL80211_FREQUENCY_ATTR_NO_IR NL80211_FREQUENCY_ATTR_NO_IR
+ #define NL80211_FREQUENCY_ATTR_GO_CONCURRENT \
+ NL80211_FREQUENCY_ATTR_IR_CONCURRENT
++#define NL80211_FREQUENCY_ATTR_NO_UHB_VLP_CLIENT \
++ NL80211_FREQUENCY_ATTR_NO_6GHZ_VLP_CLIENT
++#define NL80211_FREQUENCY_ATTR_NO_UHB_AFC_CLIENT \
++ NL80211_FREQUENCY_ATTR_NO_6GHZ_AFC_CLIENT
+
+ /**
+ * enum nl80211_bitrate_attr - bitrate attributes
+@@ -4285,16 +4381,16 @@ enum nl80211_bitrate_attr {
+ };
+
+ /**
+- * enum nl80211_initiator - Indicates the initiator of a reg domain request
++ * enum nl80211_reg_initiator - Indicates the initiator of a reg domain request
+ * @NL80211_REGDOM_SET_BY_CORE: Core queried CRDA for a dynamic world
+- * regulatory domain.
++ * regulatory domain.
+ * @NL80211_REGDOM_SET_BY_USER: User asked the wireless core to set the
+- * regulatory domain.
++ * regulatory domain.
+ * @NL80211_REGDOM_SET_BY_DRIVER: a wireless drivers has hinted to the
+- * wireless core it thinks its knows the regulatory domain we should be in.
++ * wireless core it thinks its knows the regulatory domain we should be in.
+ * @NL80211_REGDOM_SET_BY_COUNTRY_IE: the wireless core has received an
+- * 802.11 country information element with regulatory information it
+- * thinks we should consider. cfg80211 only processes the country
++ * 802.11 country information element with regulatory information it
++ * thinks we should consider. cfg80211 only processes the country
+ * code from the IE, and relies on the regulatory domain information
+ * structure passed by userspace (CRDA) from our wireless-regdb.
+ * If a channel is enabled but the country code indicates it should
+@@ -4313,11 +4409,11 @@ enum nl80211_reg_initiator {
+ * to a specific country. When this is set you can count on the
+ * ISO / IEC 3166 alpha2 country code being valid.
+ * @NL80211_REGDOM_TYPE_WORLD: the regulatory set domain is the world regulatory
+- * domain.
++ * domain.
+ * @NL80211_REGDOM_TYPE_CUSTOM_WORLD: the regulatory domain set is a custom
+- * driver specific world regulatory domain. These do not apply system-wide
+- * and are only applicable to the individual devices which have requested
+- * them to be applied.
++ * driver specific world regulatory domain. These do not apply system-wide
++ * and are only applicable to the individual devices which have requested
++ * them to be applied.
+ * @NL80211_REGDOM_TYPE_INTERSECTION: the regulatory domain set is the product
+ * of an intersection between two regulatory domains -- the previously
+ * set regulatory domain on the system and the last accepted regulatory
+@@ -4334,23 +4430,25 @@ enum nl80211_reg_type {
+ * enum nl80211_reg_rule_attr - regulatory rule attributes
+ * @__NL80211_REG_RULE_ATTR_INVALID: attribute number 0 is reserved
+ * @NL80211_ATTR_REG_RULE_FLAGS: a set of flags which specify additional
+- * considerations for a given frequency range. These are the
+- * &enum nl80211_reg_rule_flags.
++ * considerations for a given frequency range. These are the
++ * &enum nl80211_reg_rule_flags.
+ * @NL80211_ATTR_FREQ_RANGE_START: starting frequencry for the regulatory
+- * rule in KHz. This is not a center of frequency but an actual regulatory
+- * band edge.
++ * rule in KHz. This is not a center of frequency but an actual regulatory
++ * band edge.
+ * @NL80211_ATTR_FREQ_RANGE_END: ending frequency for the regulatory rule
+- * in KHz. This is not a center a frequency but an actual regulatory
+- * band edge.
++ * in KHz. This is not a center a frequency but an actual regulatory
++ * band edge.
+ * @NL80211_ATTR_FREQ_RANGE_MAX_BW: maximum allowed bandwidth for this
+ * frequency range, in KHz.
+ * @NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN: the maximum allowed antenna gain
+- * for a given frequency range. The value is in mBi (100 * dBi).
+- * If you don't have one then don't send this.
++ * for a given frequency range. The value is in mBi (100 * dBi).
++ * If you don't have one then don't send this.
+ * @NL80211_ATTR_POWER_RULE_MAX_EIRP: the maximum allowed EIRP for
+- * a given frequency range. The value is in mBm (100 * dBm).
++ * a given frequency range. The value is in mBm (100 * dBm).
+ * @NL80211_ATTR_DFS_CAC_TIME: DFS CAC time in milliseconds.
+ * If not present or 0 default CAC time will be used.
++ * @NL80211_ATTR_POWER_RULE_PSD: power spectral density (in dBm).
++ * This could be negative.
+ * @NL80211_REG_RULE_ATTR_MAX: highest regulatory rule attribute number
+ * currently defined
+ * @__NL80211_REG_RULE_ATTR_AFTER_LAST: internal use
+@@ -4368,6 +4466,8 @@ enum nl80211_reg_rule_attr {
+
+ NL80211_ATTR_DFS_CAC_TIME,
+
++ NL80211_ATTR_POWER_RULE_PSD,
++
+ /* keep last */
+ __NL80211_REG_RULE_ATTR_AFTER_LAST,
+ NL80211_REG_RULE_ATTR_MAX = __NL80211_REG_RULE_ATTR_AFTER_LAST - 1
+@@ -4396,14 +4496,7 @@ enum nl80211_reg_rule_attr {
+ * value as specified by &struct nl80211_bss_select_rssi_adjust.
+ * @NL80211_SCHED_SCAN_MATCH_ATTR_BSSID: BSSID to be used for matching
+ * (this cannot be used together with SSID).
+- * @NL80211_SCHED_SCAN_MATCH_PER_BAND_RSSI: Nested attribute that carries the
+- * band specific minimum rssi thresholds for the bands defined in
+- * enum nl80211_band. The minimum rssi threshold value(s32) specific to a
+- * band shall be encapsulated in attribute with type value equals to one
+- * of the NL80211_BAND_* defined in enum nl80211_band. For example, the
+- * minimum rssi threshold value for 2.4GHZ band shall be encapsulated
+- * within an attribute of type NL80211_BAND_2GHZ. And one or more of such
+- * attributes will be nested within this attribute.
++ * @NL80211_SCHED_SCAN_MATCH_PER_BAND_RSSI: Obsolete
+ * @NL80211_SCHED_SCAN_MATCH_ATTR_MAX: highest scheduled scan filter
+ * attribute number currently defined
+ * @__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST: internal use
+@@ -4416,7 +4509,7 @@ enum nl80211_sched_scan_match_attr {
+ NL80211_SCHED_SCAN_MATCH_ATTR_RELATIVE_RSSI,
+ NL80211_SCHED_SCAN_MATCH_ATTR_RSSI_ADJUST,
+ NL80211_SCHED_SCAN_MATCH_ATTR_BSSID,
+- NL80211_SCHED_SCAN_MATCH_PER_BAND_RSSI,
++ NL80211_SCHED_SCAN_MATCH_PER_BAND_RSSI, /* obsolete */
+
+ /* keep last */
+ __NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST,
+@@ -4438,8 +4531,9 @@ enum nl80211_sched_scan_match_attr {
+ * @NL80211_RRF_PTP_ONLY: this is only for Point To Point links
+ * @NL80211_RRF_PTMP_ONLY: this is only for Point To Multi Point links
+ * @NL80211_RRF_NO_IR: no mechanisms that initiate radiation are allowed,
+- * this includes probe requests or modes of operation that require
+- * beaconing.
++ * this includes probe requests or modes of operation that require
++ * beaconing.
++ * @__NL80211_RRF_NO_IBSS: obsolete, same as NO_IR
+ * @NL80211_RRF_AUTO_BW: maximum available bandwidth should be calculated
+ * base on contiguous rules and wider channels will be allowed to cross
+ * multiple contiguous/overlapping frequency ranges.
+@@ -4451,6 +4545,15 @@ enum nl80211_sched_scan_match_attr {
+ * @NL80211_RRF_NO_HE: HE operation not allowed
+ * @NL80211_RRF_NO_320MHZ: 320MHz operation not allowed
+ * @NL80211_RRF_NO_EHT: EHT operation not allowed
++ * @NL80211_RRF_PSD: Ruleset has power spectral density value
++ * @NL80211_RRF_DFS_CONCURRENT: Operation on this channel is allowed for
++ * peer-to-peer or adhoc communication under the control of a DFS master
++ * which operates on the same channel (FCC-594280 D01 Section B.3).
++ * Should be used together with %NL80211_RRF_DFS only.
++ * @NL80211_RRF_NO_6GHZ_VLP_CLIENT: Client connection to VLP AP not allowed
++ * @NL80211_RRF_NO_6GHZ_AFC_CLIENT: Client connection to AFC AP not allowed
++ * @NL80211_RRF_ALLOW_6GHZ_VLP_AP: Very low power (VLP) AP can be permitted
++ * despite NO_IR configuration.
+ */
+ enum nl80211_reg_rule_flags {
+ NL80211_RRF_NO_OFDM = 1<<0,
+@@ -4471,6 +4574,11 @@ enum nl80211_reg_rule_flags {
+ NL80211_RRF_NO_HE = 1<<17,
+ NL80211_RRF_NO_320MHZ = 1<<18,
+ NL80211_RRF_NO_EHT = 1<<19,
++ NL80211_RRF_PSD = 1<<20,
++ NL80211_RRF_DFS_CONCURRENT = 1<<21,
++ NL80211_RRF_NO_6GHZ_VLP_CLIENT = 1<<22,
++ NL80211_RRF_NO_6GHZ_AFC_CLIENT = 1<<23,
++ NL80211_RRF_ALLOW_6GHZ_VLP_AP = 1<<24,
+ };
+
+ #define NL80211_RRF_PASSIVE_SCAN NL80211_RRF_NO_IR
+@@ -4479,6 +4587,8 @@ enum nl80211_reg_rule_flags {
+ #define NL80211_RRF_NO_HT40 (NL80211_RRF_NO_HT40MINUS |\
+ NL80211_RRF_NO_HT40PLUS)
+ #define NL80211_RRF_GO_CONCURRENT NL80211_RRF_IR_CONCURRENT
++#define NL80211_RRF_NO_UHB_VLP_CLIENT NL80211_RRF_NO_6GHZ_VLP_CLIENT
++#define NL80211_RRF_NO_UHB_AFC_CLIENT NL80211_RRF_NO_6GHZ_AFC_CLIENT
+
+ /* For backport compatibility with older userspace */
+ #define NL80211_RRF_NO_IR_ALL (NL80211_RRF_NO_IR | __NL80211_RRF_NO_IBSS)
+@@ -4593,6 +4703,7 @@ enum nl80211_survey_info {
+ * overrides all other flags.
+ * @NL80211_MNTR_FLAG_ACTIVE: use the configured MAC address
+ * and ACK incoming unicast packets.
++ * @NL80211_MNTR_FLAG_SKIP_TX: do not pass local tx packets
+ *
+ * @__NL80211_MNTR_FLAG_AFTER_LAST: internal use
+ * @NL80211_MNTR_FLAG_MAX: highest possible monitor flag
+@@ -4605,6 +4716,7 @@ enum nl80211_mntr_flags {
+ NL80211_MNTR_FLAG_OTHER_BSS,
+ NL80211_MNTR_FLAG_COOK_FRAMES,
+ NL80211_MNTR_FLAG_ACTIVE,
++ NL80211_MNTR_FLAG_SKIP_TX,
+
+ /* keep last */
+ __NL80211_MNTR_FLAG_AFTER_LAST,
+@@ -4625,8 +4737,8 @@ enum nl80211_mntr_flags {
+ * alternate between Active and Doze states, but may not wake up
+ * for neighbor's beacons.
+ *
+- * @__NL80211_MESH_POWER_AFTER_LAST - internal use
+- * @NL80211_MESH_POWER_MAX - highest possible power save level
++ * @__NL80211_MESH_POWER_AFTER_LAST: internal use
++ * @NL80211_MESH_POWER_MAX: highest possible power save level
+ */
+
+ enum nl80211_mesh_power_mode {
+@@ -5008,6 +5120,36 @@ enum nl80211_bss_scan_width {
+ };
+
+ /**
++ * enum nl80211_bss_use_for - bitmap indicating possible BSS use
++ * @NL80211_BSS_USE_FOR_NORMAL: Use this BSS for normal "connection",
++ * including IBSS/MBSS depending on the type.
++ * @NL80211_BSS_USE_FOR_MLD_LINK: This BSS can be used as a link in an
++ * MLO connection. Note that for an MLO connection, all links including
++ * the assoc link must have this flag set, and the assoc link must
++ * additionally have %NL80211_BSS_USE_FOR_NORMAL set.
++ */
++enum nl80211_bss_use_for {
++ NL80211_BSS_USE_FOR_NORMAL = 1 << 0,
++ NL80211_BSS_USE_FOR_MLD_LINK = 1 << 1,
++};
++
++/**
++ * enum nl80211_bss_cannot_use_reasons - reason(s) connection to a
++ * BSS isn't possible
++ * @NL80211_BSS_CANNOT_USE_NSTR_NONPRIMARY: NSTR nonprimary links aren't
++ * supported by the device, and this BSS entry represents one.
++ * @NL80211_BSS_CANNOT_USE_6GHZ_PWR_MISMATCH: STA is not supporting
++ * the AP power type (SP, VLP, AP) that the AP uses.
++ */
++enum nl80211_bss_cannot_use_reasons {
++ NL80211_BSS_CANNOT_USE_NSTR_NONPRIMARY = 1 << 0,
++ NL80211_BSS_CANNOT_USE_6GHZ_PWR_MISMATCH = 1 << 1,
++};
++
++#define NL80211_BSS_CANNOT_USE_UHB_PWR_MISMATCH \
++ NL80211_BSS_CANNOT_USE_6GHZ_PWR_MISMATCH
++
++/**
+ * enum nl80211_bss - netlink attributes for a BSS
+ *
+ * @__NL80211_BSS_INVALID: invalid
+@@ -5038,7 +5180,7 @@ enum nl80211_bss_scan_width {
+ * elements from a Beacon frame (bin); not present if no Beacon frame has
+ * yet been received
+ * @NL80211_BSS_CHAN_WIDTH: channel width of the control channel
+- * (u32, enum nl80211_bss_scan_width)
++ * (u32, enum nl80211_bss_scan_width) - No longer used!
+ * @NL80211_BSS_BEACON_TSF: TSF of the last received beacon (u64)
+ * (not present if no beacon frame has been received yet)
+ * @NL80211_BSS_PRESP_DATA: the data in @NL80211_BSS_INFORMATION_ELEMENTS and
+@@ -5059,6 +5201,14 @@ enum nl80211_bss_scan_width {
+ * @NL80211_BSS_FREQUENCY_OFFSET: frequency offset in KHz
+ * @NL80211_BSS_MLO_LINK_ID: MLO link ID of the BSS (u8).
+ * @NL80211_BSS_MLD_ADDR: MLD address of this BSS if connected to it.
++ * @NL80211_BSS_USE_FOR: u32 bitmap attribute indicating what the BSS can be
++ * used for, see &enum nl80211_bss_use_for.
++ * @NL80211_BSS_CANNOT_USE_REASONS: Indicates the reason that this BSS cannot
++ * be used for all or some of the possible uses by the device reporting it,
++ * even though its presence was detected.
++ * This is a u64 attribute containing a bitmap of values from
++ * &enum nl80211_cannot_use_reasons, note that the attribute may be missing
++ * if no reasons are specified.
+ * @__NL80211_BSS_AFTER_LAST: internal
+ * @NL80211_BSS_MAX: highest BSS attribute
+ */
+@@ -5086,6 +5236,8 @@ enum nl80211_bss {
+ NL80211_BSS_FREQUENCY_OFFSET,
+ NL80211_BSS_MLO_LINK_ID,
+ NL80211_BSS_MLD_ADDR,
++ NL80211_BSS_USE_FOR,
++ NL80211_BSS_CANNOT_USE_REASONS,
+
+ /* keep last */
+ __NL80211_BSS_AFTER_LAST,
+@@ -5434,7 +5586,7 @@ enum nl80211_tx_rate_setting {
+ * (%NL80211_TID_CONFIG_ATTR_TIDS, %NL80211_TID_CONFIG_ATTR_OVERRIDE).
+ * @NL80211_TID_CONFIG_ATTR_PEER_SUPP: same as the previous per-vif one, but
+ * per peer instead.
+- * @NL80211_TID_CONFIG_ATTR_OVERRIDE: flag attribue, if set indicates
++ * @NL80211_TID_CONFIG_ATTR_OVERRIDE: flag attribute, if set indicates
+ * that the new configuration overrides all previous peer
+ * configurations, otherwise previous peer specific configurations
+ * should be left untouched.
+@@ -5606,7 +5758,7 @@ struct nl80211_pattern_support {
+ * "TCP connection wakeup" for more details. This is a nested attribute
+ * containing the exact information for establishing and keeping alive
+ * the TCP connection.
+- * @NL80211_WOWLAN_TRIG_TCP_WAKEUP_MATCH: For wakeup reporting only, the
++ * @NL80211_WOWLAN_TRIG_WAKEUP_TCP_MATCH: For wakeup reporting only, the
+ * wakeup packet was received on the TCP connection
+ * @NL80211_WOWLAN_TRIG_WAKEUP_TCP_CONNLOST: For wakeup reporting only, the
+ * TCP connection was lost or failed to be established
+@@ -5635,6 +5787,8 @@ struct nl80211_pattern_support {
+ * %NL80211_ATTR_SCAN_FREQUENCIES contains more than one
+ * frequency, it means that the match occurred in more than one
+ * channel.
++ * @NL80211_WOWLAN_TRIG_UNPROTECTED_DEAUTH_DISASSOC: For wakeup reporting only.
++ * Wake up happened due to unprotected deauth or disassoc frame in MFP.
+ * @NUM_NL80211_WOWLAN_TRIG: number of wake on wireless triggers
+ * @MAX_NL80211_WOWLAN_TRIG: highest wowlan trigger attribute number
+ *
+@@ -5662,6 +5816,7 @@ enum nl80211_wowlan_triggers {
+ NL80211_WOWLAN_TRIG_WAKEUP_TCP_NOMORETOKENS,
+ NL80211_WOWLAN_TRIG_NET_DETECT,
+ NL80211_WOWLAN_TRIG_NET_DETECT_RESULTS,
++ NL80211_WOWLAN_TRIG_UNPROTECTED_DEAUTH_DISASSOC,
+
+ /* keep last */
+ NUM_NL80211_WOWLAN_TRIG,
+@@ -5817,7 +5972,7 @@ enum nl80211_attr_coalesce_rule {
+
+ /**
+ * enum nl80211_coalesce_condition - coalesce rule conditions
+- * @NL80211_COALESCE_CONDITION_MATCH: coalaesce Rx packets when patterns
++ * @NL80211_COALESCE_CONDITION_MATCH: coalesce Rx packets when patterns
+ * in a rule are matched.
+ * @NL80211_COALESCE_CONDITION_NO_MATCH: coalesce Rx packets when patterns
+ * in a rule are not matched.
+@@ -5916,7 +6071,7 @@ enum nl80211_if_combination_attrs {
+ * enum nl80211_plink_state - state of a mesh peer link finite state machine
+ *
+ * @NL80211_PLINK_LISTEN: initial state, considered the implicit
+- * state of non existent mesh peer links
++ * state of non-existent mesh peer links
+ * @NL80211_PLINK_OPN_SNT: mesh plink open frame has been sent to
+ * this mesh peer
+ * @NL80211_PLINK_OPN_RCVD: mesh plink open frame has been received
+@@ -5952,7 +6107,7 @@ enum nl80211_plink_state {
+ * @NL80211_PLINK_ACTION_BLOCK: block traffic from this mesh peer
+ * @NUM_NL80211_PLINK_ACTIONS: number of possible actions
+ */
+-enum plink_actions {
++enum nl80211_plink_action {
+ NL80211_PLINK_ACTION_NO_ACTION,
+ NL80211_PLINK_ACTION_OPEN,
+ NL80211_PLINK_ACTION_BLOCK,
+@@ -6209,7 +6364,7 @@ enum nl80211_feature_flags {
+ * request to use RRM (see %NL80211_ATTR_USE_RRM) with
+ * %NL80211_CMD_ASSOCIATE and %NL80211_CMD_CONNECT requests, which will set
+ * the ASSOC_REQ_USE_RRM flag in the association request even if
+- * NL80211_FEATURE_QUIET is not advertized.
++ * NL80211_FEATURE_QUIET is not advertised.
+ * @NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER: This device supports MU-MIMO air
+ * sniffer which means that it can be configured to hear packets from
+ * certain groups which can be configured by the
+@@ -6221,13 +6376,15 @@ enum nl80211_feature_flags {
+ * the BSS that the interface that requested the scan is connected to
+ * (if available).
+ * @NL80211_EXT_FEATURE_BSS_PARENT_TSF: Per BSS, this driver reports the
+- * time the last beacon/probe was received. The time is the TSF of the
+- * BSS that the interface that requested the scan is connected to
+- * (if available).
++ * time the last beacon/probe was received. For a non-MLO connection, the
++ * time is the TSF of the BSS that the interface that requested the scan is
++ * connected to (if available). For an MLO connection, the time is the TSF
++ * of the BSS corresponding with link ID specified in the scan request (if
++ * specified).
+ * @NL80211_EXT_FEATURE_SET_SCAN_DWELL: This driver supports configuration of
+ * channel dwell time.
+ * @NL80211_EXT_FEATURE_BEACON_RATE_LEGACY: Driver supports beacon rate
+- * configuration (AP/mesh), supporting a legacy (non HT/VHT) rate.
++ * configuration (AP/mesh), supporting a legacy (non-HT/VHT) rate.
+ * @NL80211_EXT_FEATURE_BEACON_RATE_HT: Driver supports beacon rate
+ * configuration (AP/mesh) with HT rates.
+ * @NL80211_EXT_FEATURE_BEACON_RATE_VHT: Driver supports beacon rate
+@@ -6277,6 +6434,7 @@ enum nl80211_feature_flags {
+ * receiving control port frames over nl80211 instead of the netdevice.
+ * @NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT: This driver/device supports
+ * (average) ACK signal strength reporting.
++ * @NL80211_EXT_FEATURE_DATA_ACK_SIGNAL_SUPPORT: Backward-compatible ID
+ * @NL80211_EXT_FEATURE_TXQS: Driver supports FQ-CoDel-enabled intermediate
+ * TXQs.
+ * @NL80211_EXT_FEATURE_SCAN_RANDOM_SN: Driver/device supports randomizing the
+@@ -6301,8 +6459,7 @@ enum nl80211_feature_flags {
+ * @NL80211_EXT_FEATURE_AP_PMKSA_CACHING: Driver/device supports PMKSA caching
+ * (set/del PMKSA operations) in AP mode.
+ *
+- * @NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD: Driver supports
+- * filtering of sched scan results using band specific RSSI thresholds.
++ * @NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD: Obsolete
+ *
+ * @NL80211_EXT_FEATURE_STA_TX_PWR: This driver supports controlling tx power
+ * to a station.
+@@ -6400,6 +6557,22 @@ enum nl80211_feature_flags {
+ * in authentication and deauthentication frames sent to unassociated peer
+ * using @NL80211_CMD_FRAME.
+ *
++ * @NL80211_EXT_FEATURE_OWE_OFFLOAD: Driver/Device wants to do OWE DH IE
++ * handling in station mode.
++ *
++ * @NL80211_EXT_FEATURE_OWE_OFFLOAD_AP: Driver/Device wants to do OWE DH IE
++ * handling in AP mode.
++ *
++ * @NL80211_EXT_FEATURE_DFS_CONCURRENT: The device supports peer-to-peer or
++ * ad hoc operation on DFS channels under the control of a concurrent
++ * DFS master on the same channel as described in FCC-594280 D01
++ * (Section B.3). This, for example, allows P2P GO and P2P clients to
++ * operate on DFS channels as long as there's a concurrent BSS connection.
++ *
++ * @NL80211_EXT_FEATURE_SPP_AMSDU_SUPPORT: The driver has support for SPP
++ * (signaling and payload protected) A-MSDUs and this shall be advertised
++ * in the RSNXE.
++ *
+ * @NUM_NL80211_EXT_FEATURES: number of extended features.
+ * @MAX_NL80211_EXT_FEATURES: highest extended feature index.
+ */
+@@ -6441,7 +6614,7 @@ enum nl80211_ext_feature_index {
+ NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER,
+ NL80211_EXT_FEATURE_AIRTIME_FAIRNESS,
+ NL80211_EXT_FEATURE_AP_PMKSA_CACHING,
+- NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD,
++ NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD, /* obsolete */
+ NL80211_EXT_FEATURE_EXT_KEY_ID,
+ NL80211_EXT_FEATURE_STA_TX_PWR,
+ NL80211_EXT_FEATURE_SAE_OFFLOAD,
+@@ -6471,6 +6644,10 @@ enum nl80211_ext_feature_index {
+ NL80211_EXT_FEATURE_PUNCT,
+ NL80211_EXT_FEATURE_SECURE_NAN,
+ NL80211_EXT_FEATURE_AUTH_AND_DEAUTH_RANDOM_TA,
++ NL80211_EXT_FEATURE_OWE_OFFLOAD,
++ NL80211_EXT_FEATURE_OWE_OFFLOAD_AP,
++ NL80211_EXT_FEATURE_DFS_CONCURRENT,
++ NL80211_EXT_FEATURE_SPP_AMSDU_SUPPORT,
+
+ /* add new features before the definition below */
+ NUM_NL80211_EXT_FEATURES,
+@@ -6555,7 +6732,7 @@ enum nl80211_timeout_reason {
+ * request parameters IE in the probe request
+ * @NL80211_SCAN_FLAG_ACCEPT_BCAST_PROBE_RESP: accept broadcast probe responses
+ * @NL80211_SCAN_FLAG_OCE_PROBE_REQ_HIGH_TX_RATE: send probe request frames at
+- * rate of at least 5.5M. In case non OCE AP is discovered in the channel,
++ * rate of at least 5.5M. In case non-OCE AP is discovered in the channel,
+ * only the first probe req in the channel will be sent in high rate.
+ * @NL80211_SCAN_FLAG_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION: allow probe request
+ * tx deferral (dot11FILSProbeDelay shall be set to 15ms)
+@@ -6591,7 +6768,7 @@ enum nl80211_timeout_reason {
+ * received on the 2.4/5 GHz channels to actively scan only the 6GHz
+ * channels on which APs are expected to be found. Note that when not set,
+ * the scan logic would scan all 6GHz channels, but since transmission of
+- * probe requests on non PSC channels is limited, it is highly likely that
++ * probe requests on non-PSC channels is limited, it is highly likely that
+ * these channels would passively be scanned. Also note that when the flag
+ * is set, in addition to the colocated APs, PSC channels would also be
+ * scanned if the user space has asked for it.
+@@ -6641,6 +6818,8 @@ enum nl80211_acl_policy {
+ * @NL80211_SMPS_STATIC: static SMPS (use a single antenna)
+ * @NL80211_SMPS_DYNAMIC: dynamic smps (start with a single antenna and
+ * turn on other antennas after CTS/RTS).
++ * @__NL80211_SMPS_AFTER_LAST: internal
++ * @NL80211_SMPS_MAX: highest used enumeration
+ */
+ enum nl80211_smps_mode {
+ NL80211_SMPS_OFF,
+@@ -6671,14 +6850,6 @@ 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_BACKGROUND_CHAN_UPDATE: background channel is updated by the
+- * driver.
+- * @NL80211_RADAR_BACKGROUND_CHAN_EXPAND: background channel is updated by the
+- * driver and required to expand main operating channel.
+- * @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,
+@@ -6687,10 +6858,6 @@ enum nl80211_radar_event {
+ NL80211_RADAR_NOP_FINISHED,
+ NL80211_RADAR_PRE_CAC_EXPIRED,
+ NL80211_RADAR_CAC_STARTED,
+- NL80211_RADAR_BACKGROUND_CHAN_UPDATE,
+- NL80211_RADAR_BACKGROUND_CHAN_EXPAND,
+- NL80211_RADAR_STA_CAC_SKIPPED,
+- NL80211_RADAR_STA_CAC_EXPIRED,
+ };
+
+ /**
+@@ -6874,6 +7041,8 @@ enum nl80211_bss_select_attr {
+ * @NL80211_NAN_FUNC_PUBLISH: function is publish
+ * @NL80211_NAN_FUNC_SUBSCRIBE: function is subscribe
+ * @NL80211_NAN_FUNC_FOLLOW_UP: function is follow-up
++ * @__NL80211_NAN_FUNC_TYPE_AFTER_LAST: internal use
++ * @NL80211_NAN_FUNC_MAX_TYPE: internal use
+ */
+ enum nl80211_nan_function_type {
+ NL80211_NAN_FUNC_PUBLISH,
+@@ -6935,7 +7104,7 @@ enum nl80211_nan_func_term_reason {
+ * The instance ID for the follow up Service Discovery Frame. This is u8.
+ * @NL80211_NAN_FUNC_FOLLOW_UP_REQ_ID: relevant if the function's type
+ * is follow up. This is a u8.
+- * The requestor instance ID for the follow up Service Discovery Frame.
++ * The requester instance ID for the follow up Service Discovery Frame.
+ * @NL80211_NAN_FUNC_FOLLOW_UP_DEST: the MAC address of the recipient of the
+ * follow up Service Discovery Frame. This is a binary attribute.
+ * @NL80211_NAN_FUNC_CLOSE_RANGE: is this function limited for devices in a
+@@ -7034,7 +7203,7 @@ enum nl80211_nan_match_attributes {
+ };
+
+ /**
+- * nl80211_external_auth_action - Action to perform with external
++ * enum nl80211_external_auth_action - Action to perform with external
+ * authentication request. Used by NL80211_ATTR_EXTERNAL_AUTH_ACTION.
+ * @NL80211_EXTERNAL_AUTH_START: Start the authentication.
+ * @NL80211_EXTERNAL_AUTH_ABORT: Abort the ongoing authentication.
+@@ -7052,7 +7221,7 @@ enum nl80211_external_auth_action {
+ * @NL80211_FTM_RESP_ATTR_LCI: The content of Measurement Report Element
+ * (9.4.2.22 in 802.11-2016) with type 8 - LCI (9.4.2.22.10),
+ * i.e. starting with the measurement token
+- * @NL80211_FTM_RESP_ATTR_CIVIC: The content of Measurement Report Element
++ * @NL80211_FTM_RESP_ATTR_CIVICLOC: The content of Measurement Report Element
+ * (9.4.2.22 in 802.11-2016) with type 11 - Civic (Section 9.4.2.22.13),
+ * i.e. starting with the measurement token
+ * @__NL80211_FTM_RESP_ATTR_LAST: Internal
+@@ -7325,7 +7494,7 @@ enum nl80211_peer_measurement_attrs {
+ * @NL80211_PMSR_FTM_CAPA_ATTR_TRIGGER_BASED: flag attribute indicating if
+ * trigger based ranging measurement is supported
+ * @NL80211_PMSR_FTM_CAPA_ATTR_NON_TRIGGER_BASED: flag attribute indicating
+- * if non trigger based ranging measurement is supported
++ * if non-trigger-based ranging measurement is supported
+ *
+ * @NUM_NL80211_PMSR_FTM_CAPA_ATTR: internal
+ * @NL80211_PMSR_FTM_CAPA_ATTR_MAX: highest attribute number
+@@ -7379,7 +7548,7 @@ enum nl80211_peer_measurement_ftm_capa {
+ * if neither %NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED nor
+ * %NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED is set, EDCA based
+ * ranging will be used.
+- * @NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED: request non trigger based
++ * @NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED: request non-trigger-based
+ * ranging measurement (flag)
+ * This attribute and %NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED are
+ * mutually exclusive.
+@@ -7457,7 +7626,7 @@ enum nl80211_peer_measurement_ftm_failur
+ * @NL80211_PMSR_FTM_RESP_ATTR_NUM_FTMR_ATTEMPTS: number of FTM Request frames
+ * transmitted (u32, optional)
+ * @NL80211_PMSR_FTM_RESP_ATTR_NUM_FTMR_SUCCESSES: number of FTM Request frames
+- * that were acknowleged (u32, optional)
++ * that were acknowledged (u32, optional)
+ * @NL80211_PMSR_FTM_RESP_ATTR_BUSY_RETRY_TIME: retry time received from the
+ * busy peer (u32, seconds)
+ * @NL80211_PMSR_FTM_RESP_ATTR_NUM_BURSTS_EXP: actual number of bursts exponent
+@@ -7618,7 +7787,7 @@ enum nl80211_iftype_akm_attributes {
+ * @NL80211_FILS_DISCOVERY_ATTR_INT_MIN: Minimum packet interval (u32, TU).
+ * Allowed range: 0..10000 (TU = Time Unit)
+ * @NL80211_FILS_DISCOVERY_ATTR_INT_MAX: Maximum packet interval (u32, TU).
+- * Allowed range: 0..10000 (TU = Time Unit)
++ * Allowed range: 0..10000 (TU = Time Unit). If set to 0, the feature is disabled.
+ * @NL80211_FILS_DISCOVERY_ATTR_TMPL: Template data for FILS discovery action
+ * frame including the headers.
+ *
+@@ -7631,7 +7800,6 @@ enum nl80211_fils_discovery_attributes {
+ NL80211_FILS_DISCOVERY_ATTR_INT_MIN,
+ NL80211_FILS_DISCOVERY_ATTR_INT_MAX,
+ NL80211_FILS_DISCOVERY_ATTR_TMPL,
+- NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INTE,
+
+ /* keep last */
+ __NL80211_FILS_DISCOVERY_ATTR_LAST,
+@@ -7652,7 +7820,8 @@ enum nl80211_fils_discovery_attributes {
+ *
+ * @NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INT: Maximum packet interval (u32, TU).
+ * Allowed range: 0..20 (TU = Time Unit). IEEE P802.11ax/D6.0
+- * 26.17.2.3.2 (AP behavior for fast passive scanning).
++ * 26.17.2.3.2 (AP behavior for fast passive scanning). If set to 0, the feature is
++ * disabled.
+ * @NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL: Unsolicited broadcast probe response
+ * frame template (binary).
+ *
+@@ -7695,6 +7864,7 @@ enum nl80211_sae_pwe_mechanism {
+ *
+ * @NL80211_SAR_TYPE_POWER: power limitation specified in 0.25dBm unit
+ *
++ * @NUM_NL80211_SAR_TYPE: internal
+ */
+ enum nl80211_sar_type {
+ NL80211_SAR_TYPE_POWER,
+@@ -7708,6 +7878,8 @@ enum nl80211_sar_type {
+ /**
+ * enum nl80211_sar_attrs - Attributes for SAR spec
+ *
++ * @__NL80211_SAR_ATTR_INVALID: Invalid
++ *
+ * @NL80211_SAR_ATTR_TYPE: the SAR type as defined in &enum nl80211_sar_type.
+ *
+ * @NL80211_SAR_ATTR_SPECS: Nested array of SAR power
+@@ -7739,6 +7911,8 @@ enum nl80211_sar_attrs {
+ /**
+ * enum nl80211_sar_specs_attrs - Attributes for SAR power limit specs
+ *
++ * @__NL80211_SAR_ATTR_SPECS_INVALID: Invalid
++ *
+ * @NL80211_SAR_ATTR_SPECS_POWER: Required (s32)value to specify the actual
+ * power limit value in units of 0.25 dBm if type is
+ * NL80211_SAR_TYPE_POWER. (i.e., a value of 44 represents 11 dBm).
+@@ -7853,4 +8027,54 @@ enum nl80211_ap_settings_flags {
+ NL80211_AP_SETTINGS_SA_QUERY_OFFLOAD_SUPPORT = 1 << 1,
+ };
+
++/**
++ * enum nl80211_wiphy_radio_attrs - wiphy radio attributes
++ *
++ * @__NL80211_WIPHY_RADIO_ATTR_INVALID: Invalid
++ *
++ * @NL80211_WIPHY_RADIO_ATTR_INDEX: Index of this radio (u32)
++ * @NL80211_WIPHY_RADIO_ATTR_FREQ_RANGE: Frequency range supported by this
++ * radio. Attribute may be present multiple times.
++ * @NL80211_WIPHY_RADIO_ATTR_INTERFACE_COMBINATION: Supported interface
++ * combination for this radio. Attribute may be present multiple times
++ * and contains attributes defined in &enum nl80211_if_combination_attrs.
++ *
++ * @__NL80211_WIPHY_RADIO_ATTR_LAST: Internal
++ * @NL80211_WIPHY_RADIO_ATTR_MAX: Highest attribute
++ */
++enum nl80211_wiphy_radio_attrs {
++ __NL80211_WIPHY_RADIO_ATTR_INVALID,
++
++ NL80211_WIPHY_RADIO_ATTR_INDEX,
++ NL80211_WIPHY_RADIO_ATTR_FREQ_RANGE,
++ NL80211_WIPHY_RADIO_ATTR_INTERFACE_COMBINATION,
++
++ /* keep last */
++ __NL80211_WIPHY_RADIO_ATTR_LAST,
++ NL80211_WIPHY_RADIO_ATTR_MAX = __NL80211_WIPHY_RADIO_ATTR_LAST - 1,
++};
++
++/**
++ * enum nl80211_wiphy_radio_freq_range - wiphy radio frequency range
++ *
++ * @__NL80211_WIPHY_RADIO_FREQ_ATTR_INVALID: Invalid
++ *
++ * @NL80211_WIPHY_RADIO_FREQ_ATTR_START: Frequency range start (u32).
++ * The unit is kHz.
++ * @NL80211_WIPHY_RADIO_FREQ_ATTR_END: Frequency range end (u32).
++ * The unit is kHz.
++ *
++ * @__NL80211_WIPHY_RADIO_FREQ_ATTR_LAST: Internal
++ * @NL80211_WIPHY_RADIO_FREQ_ATTR_MAX: Highest attribute
++ */
++enum nl80211_wiphy_radio_freq_range {
++ __NL80211_WIPHY_RADIO_FREQ_ATTR_INVALID,
++
++ NL80211_WIPHY_RADIO_FREQ_ATTR_START,
++ NL80211_WIPHY_RADIO_FREQ_ATTR_END,
++
++ __NL80211_WIPHY_RADIO_FREQ_ATTR_LAST,
++ NL80211_WIPHY_RADIO_FREQ_ATTR_MAX = __NL80211_WIPHY_RADIO_FREQ_ATTR_LAST - 1,
++};
++
+ #endif /* __LINUX_NL80211_H */
+--- a/iwinfo_nl80211.c
++++ b/iwinfo_nl80211.c
+@@ -37,6 +37,11 @@
+
+ static struct nl80211_state *nls = NULL;
+
++struct nl80211_if_data {
++ int mode;
++ int radio_idx;
++};
++
+ static void nl80211_close(void)
+ {
+ if (nls)
+@@ -862,7 +867,7 @@ static char * nl80211_phy2ifname(const c
+
+ static int nl80211_get_mode_cb(struct nl_msg *msg, void *arg)
+ {
+- int *mode = arg;
++ struct nl80211_if_data *data = arg;
+ struct nlattr **tb = nl80211_parse(msg);
+ const int ifmodes[NL80211_IFTYPE_MAX + 1] = {
+ IWINFO_OPMODE_UNKNOWN, /* unspecified */
+@@ -878,37 +883,57 @@ static int nl80211_get_mode_cb(struct nl
+ };
+
+ if (tb[NL80211_ATTR_IFTYPE])
+- *mode = ifmodes[nla_get_u32(tb[NL80211_ATTR_IFTYPE])];
++ data->mode = ifmodes[nla_get_u32(tb[NL80211_ATTR_IFTYPE])];
++
++ if (tb[NL80211_ATTR_VIF_RADIO_MASK]) {
++ uint32_t mask = nla_get_u32(tb[NL80211_ATTR_VIF_RADIO_MASK]);
++
++ for (int i = 0; mask && i < 32; i++, mask >>= 1)
++ if (mask & 1)
++ data->radio_idx = i;
++ }
+
+ return NL_SKIP;
+ }
+
+
+-static int nl80211_get_mode(const char *ifname, int *buf)
++static int nl80211_get_if_data(const char *ifname, struct nl80211_if_data *data)
+ {
+ char *res;
+
+- *buf = IWINFO_OPMODE_UNKNOWN;
+-
+ res = nl80211_phy2ifname(ifname);
+
++ data->mode = IWINFO_OPMODE_UNKNOWN;
++ data->radio_idx = -1;
+ nl80211_request(res ? res : ifname, NL80211_CMD_GET_INTERFACE, 0,
+- nl80211_get_mode_cb, buf);
++ nl80211_get_mode_cb, data);
+
+- return (*buf == IWINFO_OPMODE_UNKNOWN) ? -1 : 0;
++ return (data->mode == IWINFO_OPMODE_UNKNOWN) ? -1 : 0;
++}
++
++static int nl80211_get_mode(const char *ifname, int *buf)
++{
++ struct nl80211_if_data data = {};
++ int ret;
++
++ ret = nl80211_get_if_data(ifname, &data);
++ *buf = data.mode;
++
++ return ret;
+ }
+
+ static int __nl80211_hostapd_query(const char *ifname, ...)
+ {
++ struct nl80211_if_data data = {};
+ va_list ap, ap_cur;
+ char *phy, *search, *dest, *key, *val, buf[128];
+- int len, mode, found = 0, match = 1;
++ int len, found = 0, match = 1;
+ FILE *fp;
+
+- if (nl80211_get_mode(ifname, &mode))
++ if (nl80211_get_if_data(ifname, &data))
+ return 0;
+
+- if (mode != IWINFO_OPMODE_MASTER && mode != IWINFO_OPMODE_AP_VLAN)
++ if (data.mode != IWINFO_OPMODE_MASTER && data.mode != IWINFO_OPMODE_AP_VLAN)
+ return 0;
+
+ phy = nl80211_ifname2phy(ifname);
+@@ -916,7 +941,10 @@ static int __nl80211_hostapd_query(const
+ if (!phy)
+ return 0;
+
+- snprintf(buf, sizeof(buf), "/var/run/hostapd-%s.conf", phy);
++ if (data.radio_idx >= 0)
++ snprintf(buf, sizeof(buf), "/var/run/hostapd-%s.%d.conf", phy, data.radio_idx);
++ else
++ snprintf(buf, sizeof(buf), "/var/run/hostapd-%s.conf", phy);
+ fp = fopen(buf, "r");
+
+ if (!fp)
diff --git a/package/utils/ucode/patches/100-nl80211_vif_radio_mask.patch b/package/utils/ucode/patches/100-nl80211_vif_radio_mask.patch
new file mode 100644
index 00000000000..22e05f7c620
--- /dev/null
+++ b/package/utils/ucode/patches/100-nl80211_vif_radio_mask.patch
@@ -0,0 +1,40 @@
+--- a/include/linux/nl80211.h
++++ b/include/linux/nl80211.h
+@@ -2868,6 +2868,9 @@ enum nl80211_commands {
+ * nested item, it contains attributes defined in
+ * &enum nl80211_if_combination_attrs.
+ *
++ * @NL80211_ATTR_VIF_RADIO_MASK: Bitmask of allowed radios (u32).
++ * A value of 0 means all radios.
++ *
+ * @NUM_NL80211_ATTR: total number of nl80211_attrs available
+ * @NL80211_ATTR_MAX: highest attribute number currently defined
+ * @__NL80211_ATTR_AFTER_LAST: internal use
+@@ -3416,6 +3419,8 @@ enum nl80211_attrs {
+ NL80211_ATTR_WIPHY_RADIOS,
+ NL80211_ATTR_WIPHY_INTERFACE_COMBINATIONS,
+
++ NL80211_ATTR_VIF_RADIO_MASK,
++
+ /* add attributes here, update the policy in nl80211.c */
+
+ __NL80211_ATTR_AFTER_LAST,
+--- a/lib/nl80211.c
++++ b/lib/nl80211.c
+@@ -829,7 +829,7 @@ static const uc_nl_nested_spec_t nl80211
+
+ static const uc_nl_nested_spec_t nl80211_msg = {
+ .headsize = 0,
+- .nattrs = 128,
++ .nattrs = 129,
+ .attrs = {
+ { NL80211_ATTR_4ADDR, "4addr", DT_U8, 0, NULL },
+ { NL80211_ATTR_AIRTIME_WEIGHT, "airtime_weight", DT_U16, 0, NULL },
+@@ -959,6 +959,7 @@ static const uc_nl_nested_spec_t nl80211
+ { NL80211_ATTR_MAX_AP_ASSOC_STA, "max_ap_assoc", DT_U16, 0, NULL },
+ { NL80211_ATTR_SURVEY_INFO, "survey_info", DT_NESTED, 0, &nl80211_survey_info_nla },
+ { NL80211_ATTR_WIPHY_RADIOS, "radios", DT_NESTED, DF_MULTIPLE|DF_AUTOIDX, &nl80211_wiphy_radio_nla },
++ { NL80211_ATTR_VIF_RADIO_MASK, "vif_radio_mask", DT_U32, 0, NULL },
+ }
+ };
+
diff --git a/scripts/kconfig-reorder.sh b/scripts/kconfig-reorder.sh
new file mode 100755
index 00000000000..9ab7858d49b
--- /dev/null
+++ b/scripts/kconfig-reorder.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+# This script reorders all config-* files in the target directory.
+
+find_files=$(find target -type f -name 'config-*' -print)
+
+if [ -n "$find_files" ]; then
+ for file in $find_files; do
+ echo "Reordering options in $file"
+ LANG=C ./scripts/kconfig.pl '+' "$file" /dev/null > "$file"-new
+ mv "$file"-new "$file"
+ done
+else
+ echo "No files named config-* found."
+fi
+
diff --git a/scripts/linksys-image.sh b/scripts/linksys-image.sh
index f0398662fb9..d35439907ea 100755
--- a/scripts/linksys-image.sh
+++ b/scripts/linksys-image.sh
@@ -38,8 +38,8 @@ gen_fwinfo() {
echo 'FW_VERSION=1.01.100\nBOOT_VERSION=01.00.01'
}
-# The central upgrade script. It allows to install OpenWrt only to first partition.
-gen_imageupgrade() {
+# NOR upgrade script. It allows to install OpenWrt only to first partition.
+gen_nor_upgrade() {
echo '#!/bin/sh'
echo 'flash_bank=65536'
echo 'filesize=`stat --format=%s ./series_vmlinux.bix`'
@@ -58,16 +58,34 @@ gen_imageupgrade() {
echo 'esac'
}
+# NAND upgrade script. It allows to install OpenWrt only to first partition.
+gen_nand_upgrade() {
+ echo '#!/bin/sh'
+ echo 'case $1 in'
+ echo '1)'
+ echo 'flash_eraseall $2 >/dev/null 2>&1'
+ echo 'nandwrite -p $2 ./series_vmlinux.bix >/dev/null 2>&1'
+ echo 'mtd_debug read $2 0 100 image1.img >/dev/null 2>&1'
+ echo 'CreateImage -r ./image1.img > /tmp/app/image1.txt'
+ echo 'echo 0'
+ echo ';;'
+ echo '*)'
+ echo 'echo 1'
+ echo 'esac'
+}
+
tmpdir="$( mktemp -d 2> /dev/null )"
imgdir=$tmpdir/image
mkdir $imgdir
gen_imagecheck $3 > $imgdir/iss_imagecheck.sh
-gen_imageupgrade > $imgdir/iss_imageupgrade.sh
+gen_nor_upgrade > $imgdir/iss_imageupgrade.sh
+gen_nand_upgrade > $imgdir/iss_nand_imageupgrade.sh
gen_fwinfo > $imgdir/firmware_information.txt
chmod +x $imgdir/iss_imagecheck.sh
chmod +x $imgdir/iss_imageupgrade.sh
+chmod +x $imgdir/iss_nand_imageupgrade.sh
cp $1 $imgdir/series_vmlinux.bix
diff --git a/target/imagebuilder/Makefile b/target/imagebuilder/Makefile
index 7127df5ebcd..ecc791b8e9b 100644
--- a/target/imagebuilder/Makefile
+++ b/target/imagebuilder/Makefile
@@ -114,6 +114,7 @@ endif
rm -f $(IB_KDIR)/vmlinux.debug
# remove any file for initramfs and Per Device Rootfs initramfs files
rm -f $(IB_KDIR)/vmlinux-initramfs*
+ rm -f $(IB_KDIR)/vmlinuz-initramfs*
rm -f $(IB_KDIR)/Image-initramfs*
if [ -x $(LINUX_DIR)/scripts/dtc/dtc ]; then \
$(INSTALL_DIR) $(IB_LDIR)/scripts/dtc; \
diff --git a/target/linux/airoha/Makefile b/target/linux/airoha/Makefile
index 58d5f1f78ad..61b7b876922 100644
--- a/target/linux/airoha/Makefile
+++ b/target/linux/airoha/Makefile
@@ -3,7 +3,7 @@ include $(TOPDIR)/rules.mk
ARCH:=arm
BOARD:=airoha
BOARDNAME:=Airoha ARM
-SUBTARGETS:=en7523 en7581
+SUBTARGETS:=en7523 an7581
FEATURES:=dt squashfs nand ramdisk gpio
KERNEL_PATCHVER:=6.6
diff --git a/target/linux/airoha/en7581/config-6.6 b/target/linux/airoha/an7581/config-6.6
similarity index 100%
rename from target/linux/airoha/en7581/config-6.6
rename to target/linux/airoha/an7581/config-6.6
diff --git a/target/linux/airoha/en7581/target.mk b/target/linux/airoha/an7581/target.mk
similarity index 55%
rename from target/linux/airoha/en7581/target.mk
rename to target/linux/airoha/an7581/target.mk
index d890d9ef58c..1c0e8d02f63 100644
--- a/target/linux/airoha/en7581/target.mk
+++ b/target/linux/airoha/an7581/target.mk
@@ -1,11 +1,11 @@
ARCH:=aarch64
-SUBTARGET:=en7581
-BOARDNAME:=EN7581
+SUBTARGET:=an7581
+BOARDNAME:=AN7581
CPU_TYPE:=cortex-a53
KERNELNAME:=Image dtbs
FEATURES+=pwm source-only
define Target/Description
- Build firmware images for Airoha en7581 ARM based boards.
+ Build firmware images for Airoha an7581 ARM based boards.
endef
diff --git a/target/linux/airoha/dts/en7581-evb-emmc.dts b/target/linux/airoha/dts/an7581-evb-emmc.dts
similarity index 95%
rename from target/linux/airoha/dts/en7581-evb-emmc.dts
rename to target/linux/airoha/dts/an7581-evb-emmc.dts
index 04c09e77b3a..91d79777956 100644
--- a/target/linux/airoha/dts/en7581-evb-emmc.dts
+++ b/target/linux/airoha/dts/an7581-evb-emmc.dts
@@ -6,11 +6,11 @@
#include
#include
-#include "en7581.dtsi"
+#include "an7581.dtsi"
/ {
- model = "Airoha EN7581 Evaluation Board";
- compatible = "airoha,en7581-evb", "airoha,en7581";
+ model = "Airoha AN7581 Evaluation Board";
+ compatible = "airoha,an7581-evb", "airoha,an7581", "airoha,en7581";
aliases {
serial0 = &uart1;
diff --git a/target/linux/airoha/dts/en7581-evb.dts b/target/linux/airoha/dts/an7581-evb.dts
similarity index 96%
rename from target/linux/airoha/dts/en7581-evb.dts
rename to target/linux/airoha/dts/an7581-evb.dts
index 630cd76ae81..3cf531a29c4 100644
--- a/target/linux/airoha/dts/en7581-evb.dts
+++ b/target/linux/airoha/dts/an7581-evb.dts
@@ -7,11 +7,11 @@
#include
#include
#include
-#include "en7581.dtsi"
+#include "an7581.dtsi"
/ {
- model = "Airoha EN7581 Evaluation Board";
- compatible = "airoha,en7581-evb", "airoha,en7581";
+ model = "Airoha AN7581 Evaluation Board";
+ compatible = "airoha,an7581-evb", "airoha,an7581", "airoha,en7581";
aliases {
serial0 = &uart1;
diff --git a/target/linux/airoha/dts/en7581.dtsi b/target/linux/airoha/dts/an7581.dtsi
similarity index 100%
rename from target/linux/airoha/dts/en7581.dtsi
rename to target/linux/airoha/dts/an7581.dtsi
diff --git a/target/linux/airoha/image/en7581.mk b/target/linux/airoha/image/an7581.mk
similarity index 55%
rename from target/linux/airoha/image/en7581.mk
rename to target/linux/airoha/image/an7581.mk
index 7fc6b8ec0e4..78918879f7d 100644
--- a/target/linux/airoha/image/en7581.mk
+++ b/target/linux/airoha/image/an7581.mk
@@ -4,24 +4,24 @@ define Device/FitImageLzma
KERNEL_NAME := Image
endef
-define Device/airoha_en7581-evb
+define Device/airoha_an7581-evb
$(call Device/FitImageLzma)
DEVICE_VENDOR := Airoha
- DEVICE_MODEL := EN7581 Evaluation Board (SNAND)
- DEVICE_PACKAGES := kmod-leds-pwm kmod-i2c-en7581 kmod-pwm-airoha kmod-input-gpio-keys-polled
- DEVICE_DTS := en7581-evb
+ DEVICE_MODEL := AN7581 Evaluation Board (SNAND)
+ DEVICE_PACKAGES := kmod-leds-pwm kmod-i2c-an7581 kmod-pwm-airoha kmod-input-gpio-keys-polled
+ DEVICE_DTS := an7581-evb
DEVICE_DTS_DIR := ../dts
DEVICE_DTS_CONFIG := config@1
KERNEL_LOADADDR := 0x80088000
IMAGE/sysupgrade.bin := append-kernel | pad-to 128k | append-rootfs | pad-rootfs | append-metadata
endef
-TARGET_DEVICES += airoha_en7581-evb
+TARGET_DEVICES += airoha_an7581-evb
-define Device/airoha_en7581-evb-emmc
+define Device/airoha_an7581-evb-emmc
DEVICE_VENDOR := Airoha
- DEVICE_MODEL := EN7581 Evaluation Board (EMMC)
- DEVICE_DTS := en7581-evb-emmc
+ DEVICE_MODEL := AN7581 Evaluation Board (EMMC)
+ DEVICE_DTS := an7581-evb-emmc
DEVICE_DTS_DIR := ../dts
- DEVICE_PACKAGES := kmod-i2c-en7581
+ DEVICE_PACKAGES := kmod-i2c-an7581
endef
-TARGET_DEVICES += airoha_en7581-evb-emmc
+TARGET_DEVICES += airoha_an7581-evb-emmc
diff --git a/target/linux/airoha/modules.mk b/target/linux/airoha/modules.mk
index 38126d5bc48..cbefe38996f 100644
--- a/target/linux/airoha/modules.mk
+++ b/target/linux/airoha/modules.mk
@@ -5,25 +5,25 @@ OTHER_MENU:=Other modules
I2C_MT7621_MODULES:= \
CONFIG_I2C_MT7621:drivers/i2c/busses/i2c-mt7621
-define KernelPackage/i2c-en7581
+define KernelPackage/i2c-an7581
SUBMENU:=$(OTHER_MENU)
$(call i2c_defaults,$(I2C_MT7621_MODULES),79)
TITLE:=Airoha I2C Controller
DEPENDS:=+kmod-i2c-core \
- @(TARGET_airoha_en7581)
+ @(TARGET_airoha_an7581)
endef
-define KernelPackage/i2c-en7581/description
+define KernelPackage/i2c-an7581/description
Kernel modules for enable mt7621 i2c controller.
endef
-$(eval $(call KernelPackage,i2c-en7581))
+$(eval $(call KernelPackage,i2c-an7581))
-define KernelPackage/pwm-en7581
+define KernelPackage/pwm-an7581
SUBMENU:=$(OTHER_MENU)
TITLE:=Airoha EN7581 PWM
- DEPENDS:=@(TARGET_airoha_en7581)
+ DEPENDS:=@(TARGET_airoha_an7581)
KCONFIG:= \
CONFIG_PWM=y \
CONFIG_PWM_AIROHA=y \
@@ -33,10 +33,10 @@ define KernelPackage/pwm-en7581
AUTOLOAD:=$(call AutoProbe,pwm-airoha)
endef
-define KernelPackage/pwm-en7581/description
+define KernelPackage/pwm-an7581/description
Kernel module to use the PWM channel on Airoha SoC
endef
-$(eval $(call KernelPackage,pwm-en7581))
+$(eval $(call KernelPackage,pwm-an7581))
diff --git a/target/linux/airoha/patches-6.6/108-pwm-airoha-Add-support-for-EN7581-SoC.patch b/target/linux/airoha/patches-6.6/108-pwm-airoha-Add-support-for-EN7581-SoC.patch
index 5eb4696b39b..8f83c696c4f 100644
--- a/target/linux/airoha/patches-6.6/108-pwm-airoha-Add-support-for-EN7581-SoC.patch
+++ b/target/linux/airoha/patches-6.6/108-pwm-airoha-Add-support-for-EN7581-SoC.patch
@@ -1,18 +1,19 @@
-From b235c45e83c8c2a24746652982d569896b142de9 Mon Sep 17 00:00:00 2001
+From 97e4e7b106b08373f90ff1b8c4daf6c2254386a8 Mon Sep 17 00:00:00 2001
From: Benjamin Larsson
-Date: Wed, 16 Oct 2024 12:07:34 +0200
-Subject: [PATCH 2/2] pwm: airoha: Add support for EN7581 SoC
+Date: Wed, 23 Oct 2024 01:20:06 +0200
+Subject: [PATCH] pwm: airoha: Add support for EN7581 SoC
Introduce driver for PWM module available on EN7581 SoC.
Signed-off-by: Benjamin Larsson
+Reviewed-by: AngeloGioacchino Del Regno
Co-developed-by: Lorenzo Bianconi
Signed-off-by: Lorenzo Bianconi
---
- drivers/pwm/Kconfig | 11 +
+ drivers/pwm/Kconfig | 11 ++
drivers/pwm/Makefile | 1 +
- drivers/pwm/pwm-airoha.c | 424 +++++++++++++++++++++++++++++++++++++++
- 3 files changed, 436 insertions(+)
+ drivers/pwm/pwm-airoha.c | 386 +++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 398 insertions(+)
create mode 100644 drivers/pwm/pwm-airoha.c
--- a/drivers/pwm/Kconfig
@@ -47,7 +48,7 @@ Signed-off-by: Lorenzo Bianconi
obj-$(CONFIG_PWM_ATMEL_HLCDC_PWM) += pwm-atmel-hlcdc.o
--- /dev/null
+++ b/drivers/pwm/pwm-airoha.c
-@@ -0,0 +1,424 @@
+@@ -0,0 +1,400 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2022 Markus Gothe
@@ -80,11 +81,12 @@ Signed-off-by: Lorenzo Bianconi
+#define SGPIO_LED_DATA_DATA GENMASK(16, 0)
+
+#define REG_SGPIO_CLK_DIVR 0x0028
++#define REG_SGPIO_CLK_DIVR_MASK GENMASK(1, 0)
+#define REG_SGPIO_CLK_DLY 0x002c
+
+#define REG_SIPO_FLASH_MODE_CFG 0x0030
+#define SERIAL_GPIO_FLASH_MODE BIT(1)
-+#define SERIAL_GPIO_MODE BIT(0)
++#define SERIAL_GPIO_MODE_74HC164 BIT(0)
+
+#define REG_GPIO_FLASH_PRD_SET(_n) (0x003c + ((_n) << 2))
+#define GPIO_FLASH_PRD_MASK(_n) GENMASK(15 + ((_n) << 4), ((_n) << 4))
@@ -98,7 +100,7 @@ Signed-off-by: Lorenzo Bianconi
+#define REG_CYCLE_CFG_VALUE(_n) (0x0098 + ((_n) << 2))
+#define WAVE_GEN_CYCLE_MASK(_n) GENMASK(7 + ((_n) << 3), ((_n) << 3))
+
-+#define EN7581_NUM_BUCKETS 8
++#define PWM_NUM_BUCKETS 8
+
+struct airoha_pwm_bucket {
+ /* Bitmask of PWM channels using this bucket */
@@ -115,7 +117,7 @@ Signed-off-by: Lorenzo Bianconi
+ struct device_node *np;
+ u64 initialized;
+
-+ struct airoha_pwm_bucket bucket[EN7581_NUM_BUCKETS];
++ struct airoha_pwm_bucket bucket[PWM_NUM_BUCKETS];
+};
+
+/*
@@ -200,62 +202,25 @@ Signed-off-by: Lorenzo Bianconi
+
+static int airoha_pwm_sipo_init(struct airoha_pwm *pc)
+{
-+ u32 clk_divr_val, sipo_clock_delay, sipo_clock_divisor;
+ u32 val;
+
+ if (!(pc->initialized >> PWM_NUM_GPIO))
+ return 0;
+
-+ /*
-+ * Select the right shift register chip.
-+ * By default 74HC164 is assumed. With this enabled
-+ * 74HC595 chip is used that requires the latch pin
-+ * to be triggered to apply the configuration.
-+ */
-+ if (of_property_read_bool(pc->np, "airoha,74hc595-mode"))
-+ regmap_set_bits(pc->regmap, REG_SIPO_FLASH_MODE_CFG,
-+ SERIAL_GPIO_MODE);
-+ else
-+ regmap_clear_bits(pc->regmap, REG_SIPO_FLASH_MODE_CFG,
-+ SERIAL_GPIO_MODE);
-+
-+ if (of_property_read_u32(pc->np, "airoha,sipo-clock-divisor",
-+ &sipo_clock_divisor))
-+ sipo_clock_divisor = 32;
-+
-+ switch (sipo_clock_divisor) {
-+ case 4:
-+ clk_divr_val = 0;
-+ break;
-+ case 8:
-+ clk_divr_val = 1;
-+ break;
-+ case 16:
-+ clk_divr_val = 2;
-+ break;
-+ case 32:
-+ clk_divr_val = 3;
-+ break;
-+ default:
-+ return -EINVAL;
-+ }
-+
-+ /* Configure shift register timings */
-+ regmap_write(pc->regmap, REG_SGPIO_CLK_DIVR, clk_divr_val);
++ regmap_clear_bits(pc->regmap, REG_SIPO_FLASH_MODE_CFG,
++ SERIAL_GPIO_MODE_74HC164);
+
-+ if (of_property_read_u32(pc->np, "airoha,sipo-clock-delay",
-+ &sipo_clock_delay))
-+ sipo_clock_delay = 1;
-+
-+ if (sipo_clock_delay < 1 || sipo_clock_delay > sipo_clock_divisor / 2)
-+ return -EINVAL;
++ /* Configure shift register timings, use 32x divisor */
++ regmap_write(pc->regmap, REG_SGPIO_CLK_DIVR,
++ FIELD_PREP(REG_SGPIO_CLK_DIVR_MASK, 0x3));
+
+ /*
-+ * The actual delay is sclkdly + 1 so subtract 1 from
-+ * sipo-clock-delay to calculate the register value
++ * The actual delay is clock + 1.
++ * Notice that clock delay should not be greater
++ * than (divisor / 2) - 1.
++ * Set to 0 by default. (aka 1)
+ */
-+ sipo_clock_delay--;
-+ regmap_write(pc->regmap, REG_SGPIO_CLK_DLY, sipo_clock_delay);
++ regmap_write(pc->regmap, REG_SGPIO_CLK_DLY, 0x0);
+
+ /*
+ * It it necessary to after muxing explicitly shift out all
@@ -365,7 +330,7 @@ Signed-off-by: Lorenzo Bianconi
+
+static void airoha_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
-+ struct airoha_pwm *pc = pwmchip_get_drvdata(chip);
++ struct airoha_pwm *pc = container_of(chip, struct airoha_pwm, chip);
+
+ /* Disable PWM and release the waveform */
+ airoha_pwm_config_flash_map(pc, pwm->hwpwm, -1);
@@ -380,7 +345,7 @@ Signed-off-by: Lorenzo Bianconi
+static int airoha_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
+ const struct pwm_state *state)
+{
-+ struct airoha_pwm *pc = pwmchip_get_drvdata(chip);
++ struct airoha_pwm *pc = container_of(chip, struct airoha_pwm, chip);
+ u64 duty = state->enabled ? state->duty_cycle : 0;
+ u64 period = state->period;
+
@@ -405,7 +370,7 @@ Signed-off-by: Lorenzo Bianconi
+static int airoha_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
+ struct pwm_state *state)
+{
-+ struct airoha_pwm *pc = pwmchip_get_drvdata(chip);
++ struct airoha_pwm *pc = container_of(chip, struct airoha_pwm, chip);
+ int i;
+
+ /* find hwpwm in waveform generator bucket */
@@ -428,28 +393,39 @@ Signed-off-by: Lorenzo Bianconi
+static const struct pwm_ops airoha_pwm_ops = {
+ .get_state = airoha_pwm_get_state,
+ .apply = airoha_pwm_apply,
++ .owner = THIS_MODULE,
+};
+
+static int airoha_pwm_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct airoha_pwm *pc;
-+ struct pwm_chip *chip;
+
-+ chip = devm_pwmchip_alloc(dev, PWM_NUM_GPIO + PWM_NUM_SIPO,
-+ sizeof(*pc));
-+ if (IS_ERR(chip))
-+ return PTR_ERR(chip);
++ pc = devm_kzalloc(dev, sizeof(*pc), GFP_KERNEL);
++ if (!pc)
++ return -ENOMEM;
+
-+ chip->ops = &airoha_pwm_ops;
-+ pc = pwmchip_get_drvdata(chip);
+ pc->np = dev->of_node;
++ pc->chip.dev = dev;
++ pc->chip.ops = &airoha_pwm_ops;
++ pc->chip.npwm = PWM_NUM_GPIO + PWM_NUM_SIPO;
+
+ pc->regmap = device_node_to_regmap(dev->parent->of_node);
+ if (IS_ERR(pc->regmap))
+ return PTR_ERR(pc->regmap);
+
-+ return devm_pwmchip_add(&pdev->dev, chip);
++ platform_set_drvdata(pdev, pc);
++
++ return pwmchip_add(&pc->chip);
++}
++
++static int airoha_pwm_remove(struct platform_device *pdev)
++{
++ struct airoha_pwm *pc = platform_get_drvdata(pdev);
++
++ pwmchip_remove(&pc->chip);
++
++ return 0;
+}
+
+static const struct of_device_id airoha_pwm_of_match[] = {
@@ -464,6 +440,7 @@ Signed-off-by: Lorenzo Bianconi
+ .of_match_table = airoha_pwm_of_match,
+ },
+ .probe = airoha_pwm_probe,
++ .remove = airoha_pwm_remove,
+};
+module_platform_driver(airoha_pwm_driver);
+
diff --git a/target/linux/apm821xx/config-6.6 b/target/linux/apm821xx/config-6.6
index 23342e78aa8..33e586632cd 100644
--- a/target/linux/apm821xx/config-6.6
+++ b/target/linux/apm821xx/config-6.6
@@ -100,6 +100,7 @@ CONFIG_GENERIC_IRQ_SHOW_LEVEL=y
CONFIG_GENERIC_ISA_DMA=y
CONFIG_GENERIC_MSI_IRQ=y
CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_PHY=y
CONFIG_GENERIC_SMP_IDLE_THREAD=y
CONFIG_GENERIC_STRNCPY_FROM_USER=y
CONFIG_GENERIC_STRNLEN_USER=y
diff --git a/target/linux/apm821xx/nand/config-default b/target/linux/apm821xx/nand/config-default
index 220ee3b9c0f..6c425553b4a 100644
--- a/target/linux/apm821xx/nand/config-default
+++ b/target/linux/apm821xx/nand/config-default
@@ -2,7 +2,6 @@ CONFIG_AT803X_PHY=y
CONFIG_BCH=y
CONFIG_CRYPTO_HASH_INFO=y
CONFIG_CRYPTO_ZSTD=y
-CONFIG_GENERIC_PHY=y
CONFIG_GRO_CELLS=y
CONFIG_HWMON=y
CONFIG_MTD_NAND_CORE=y
diff --git a/target/linux/apm821xx/sata/config-default b/target/linux/apm821xx/sata/config-default
index 7efb914885f..fdd5bf8bbd7 100644
--- a/target/linux/apm821xx/sata/config-default
+++ b/target/linux/apm821xx/sata/config-default
@@ -1,31 +1,24 @@
CONFIG_APOLLO3G=y
-CONFIG_BROADCOM_PHY=y
-CONFIG_EXT4_FS=y
-# CONFIG_SATA_DWC_OLD_DMA is not set
CONFIG_ATA=y
-CONFIG_ATA_SFF=y
CONFIG_ATA_BMDMA=y
-CONFIG_SATA_PMP=y
-CONFIG_GENERIC_PHY=y
-CONFIG_SATA_DWC=y
-# CONFIG_SATA_DWC_DEBUG is not set
+CONFIG_ATA_SFF=y
+CONFIG_BLK_DEV_DM=y
+CONFIG_BLK_DEV_DM_BUILTIN=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_MD=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_BLK_PM=y
+CONFIG_BROADCOM_PHY=y
CONFIG_CRYPTO_MD5_PPC=y
CONFIG_CRYPTO_SHA1_PPC=y
CONFIG_EXT4_FS=y
CONFIG_F2FS_FS=y
CONFIG_FREEZER=y
CONFIG_FW_CACHE=y
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_BLK_PM=y
+CONFIG_GPIO_74XX_MMIO=y
CONFIG_GPIO_GENERIC=y
CONFIG_GPIO_GENERIC_PLATFORM=y
-CONFIG_GPIO_74XX_MMIO=y
CONFIG_LEDS_TRIGGER_DISK=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_DM=y
-CONFIG_BLK_DEV_DM_BUILTIN=y
-CONFIG_BLK_DEV_MD=y
CONFIG_MD=y
CONFIG_MD_AUTODETECT=y
# CONFIG_MD_LINEAR is not set
@@ -34,8 +27,8 @@ CONFIG_MD_RAID0=y
CONFIG_MD_RAID1=y
# CONFIG_MD_RAID10 is not set
# CONFIG_MD_RAID456 is not set
-CONFIG_MTD_PHYSMAP=y
CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_PHYSMAP=y
CONFIG_PM=y
CONFIG_PM_AUTOSLEEP=y
CONFIG_PM_CLK=y
@@ -44,14 +37,19 @@ CONFIG_PM_SLEEP=y
CONFIG_PM_WAKELOCKS=y
CONFIG_PM_WAKELOCKS_GC=y
CONFIG_PM_WAKELOCKS_LIMIT=100
+CONFIG_PPC4xx_CPM=y
CONFIG_PPC_EARLY_DEBUG=y
-CONFIG_PPC_EARLY_DEBUG_44x=y
-# CONFIG_PPC_EARLY_DEBUG_MEMCONS is not set
# CONFIG_PPC_EARLY_DEBUG_16550 is not set
+CONFIG_PPC_EARLY_DEBUG_44x=y
CONFIG_PPC_EARLY_DEBUG_44x_PHYSHIGH=0x4
CONFIG_PPC_EARLY_DEBUG_44x_PHYSLOW=0xef600300
-CONFIG_PPC4xx_CPM=y
+# CONFIG_PPC_EARLY_DEBUG_MEMCONS is not set
CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_SATA_DWC=y
+# CONFIG_SATA_DWC_DEBUG is not set
+# CONFIG_SATA_DWC_OLD_DMA is not set
+CONFIG_SATA_PMP=y
+CONFIG_SCSI=y
CONFIG_SUSPEND=y
CONFIG_SUSPEND_FREEZER=y
CONFIG_USB=y
diff --git a/target/linux/ath79/dts/qca9531_alfa-network_wifi-camppro-nano-duo.dts b/target/linux/ath79/dts/qca9531_alfa-network_wifi-camppro-nano-duo.dts
new file mode 100644
index 00000000000..e505081f989
--- /dev/null
+++ b/target/linux/ath79/dts/qca9531_alfa-network_wifi-camppro-nano-duo.dts
@@ -0,0 +1,60 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+
+#include
+
+#include "qca9531_alfa-network_r36a.dtsi"
+
+/ {
+ model = "ALFA Network WiFi CampPro Nano Duo";
+ compatible = "alfa-network,wifi-camppro-nano-duo", "qca,qca9531";
+
+ aliases {
+ led-boot = &led_status;
+ led-failsafe = &led_status;
+ led-running = &led_status;
+ led-upgrade = &led_status;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&enable_gpio4>;
+
+ lan {
+ function = LED_FUNCTION_LAN;
+ color = ;
+ gpios = <&gpio 4 GPIO_ACTIVE_LOW>;
+ };
+
+ led_status: status {
+ function = LED_FUNCTION_STATUS;
+ color = ;
+ gpios = <&gpio 12 GPIO_ACTIVE_LOW>;
+ };
+
+ wlan2g {
+ function = LED_FUNCTION_WLAN_2GHZ;
+ color = ;
+ gpios = <&gpio 11 GPIO_ACTIVE_LOW>;
+ linux,default-trigger = "phy1tpt";
+ };
+ };
+};
+
+ð0 {
+ nvmem-cells = <&macaddr_art_1002 (-1)>;
+ nvmem-cell-names = "mac-address";
+};
+
+ð1 {
+ compatible = "syscon", "simple-mfd";
+};
+
+&gpio_export {
+ usb-power {
+ gpio-export,name = "usb-power";
+ gpio-export,output = <0>;
+ gpios = <&gpio 3 GPIO_ACTIVE_LOW>;
+ };
+};
diff --git a/target/linux/ath79/generic/base-files/etc/board.d/01_leds b/target/linux/ath79/generic/base-files/etc/board.d/01_leds
index 143309a8b24..0e5731dd743 100644
--- a/target/linux/ath79/generic/base-files/etc/board.d/01_leds
+++ b/target/linux/ath79/generic/base-files/etc/board.d/01_leds
@@ -22,6 +22,7 @@ alcatel,hh40v)
;;
alfa-network,ap121f|\
alfa-network,ap121fe|\
+alfa-network,wifi-camppro-nano-duo|\
avm,fritz450e|\
glinet,6408|\
glinet,6416|\
diff --git a/target/linux/ath79/generic/base-files/etc/board.d/02_network b/target/linux/ath79/generic/base-files/etc/board.d/02_network
index 2ad4c899e09..8474c1c4c2d 100644
--- a/target/linux/ath79/generic/base-files/etc/board.d/02_network
+++ b/target/linux/ath79/generic/base-files/etc/board.d/02_network
@@ -14,6 +14,7 @@ ath79_setup_interfaces()
alfa-network,ap121f|\
alfa-network,pi-wifi4|\
alfa-network,tube-2hq|\
+ alfa-network,wifi-camppro-nano-duo|\
araknis,an-300-ap-i-n|\
araknis,an-500-ap-i-ac|\
araknis,an-700-ap-i-ac|\
@@ -622,6 +623,7 @@ ath79_setup_macs()
alfa-network,pi-wifi4|\
alfa-network,r36a|\
alfa-network,tube-2hq|\
+ alfa-network,wifi-camppro-nano-duo|\
engenius,eap300-v2|\
engenius,ens202ext-v1)
label_mac=$(mtd_get_mac_binary art 0x1002)
diff --git a/target/linux/ath79/image/generic.mk b/target/linux/ath79/image/generic.mk
index 06448f21723..c075f050db2 100644
--- a/target/linux/ath79/image/generic.mk
+++ b/target/linux/ath79/image/generic.mk
@@ -346,6 +346,16 @@ define Device/alfa-network_tube-2hq
endef
TARGET_DEVICES += alfa-network_tube-2hq
+define Device/alfa-network_wifi-camppro-nano-duo
+ SOC := qca9531
+ DEVICE_VENDOR := ALFA Network
+ DEVICE_MODEL := WiFi CampPro Nano Duo
+ DEVICE_PACKAGES := kmod-usb2 kmod-mt76x0u -swconfig
+ IMAGE_SIZE := 15872k
+ SUPPORTED_DEVICES += campnano-duo
+endef
+TARGET_DEVICES += alfa-network_wifi-camppro-nano-duo
+
define Device/allnet_all-wap02860ac
$(Device/senao_loader_okli)
SOC := qca9558
diff --git a/target/linux/bcm27xx/patches-6.6/950-0518-net-macb-Also-set-DMA-coherent-mask.patch b/target/linux/bcm27xx/patches-6.6/950-0518-net-macb-Also-set-DMA-coherent-mask.patch
index 508aaad932c..cbfab3e4e6c 100644
--- a/target/linux/bcm27xx/patches-6.6/950-0518-net-macb-Also-set-DMA-coherent-mask.patch
+++ b/target/linux/bcm27xx/patches-6.6/950-0518-net-macb-Also-set-DMA-coherent-mask.patch
@@ -191,7 +191,7 @@ Signed-off-by: Jonathan Bell
static void macb_init_buffers(struct macb *bp)
{
struct macb_queue *queue;
-@@ -969,6 +985,7 @@ static int macb_mii_init(struct macb *bp
+@@ -977,6 +993,7 @@ static int macb_mii_init(struct macb *bp
bp->mii_bus->write = &macb_mdio_write_c22;
bp->mii_bus->read_c45 = &macb_mdio_read_c45;
bp->mii_bus->write_c45 = &macb_mdio_write_c45;
@@ -199,7 +199,7 @@ Signed-off-by: Jonathan Bell
snprintf(bp->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
bp->pdev->name, bp->pdev->id);
bp->mii_bus->priv = bp;
-@@ -1640,6 +1657,11 @@ static int macb_rx(struct macb_queue *qu
+@@ -1648,6 +1665,11 @@ static int macb_rx(struct macb_queue *qu
macb_init_rx_ring(queue);
queue_writel(queue, RBQP, queue->rx_ring_dma);
@@ -211,7 +211,7 @@ Signed-off-by: Jonathan Bell
macb_writel(bp, NCR, ctrl | MACB_BIT(RE));
-@@ -1940,8 +1962,9 @@ static irqreturn_t macb_interrupt(int ir
+@@ -1948,8 +1970,9 @@ static irqreturn_t macb_interrupt(int ir
queue_writel(queue, ISR, MACB_BIT(TCOMP) |
MACB_BIT(TXUBR));
@@ -222,7 +222,7 @@ Signed-off-by: Jonathan Bell
wmb(); // ensure softirq can see update
}
-@@ -2394,6 +2417,11 @@ static netdev_tx_t macb_start_xmit(struc
+@@ -2402,6 +2425,11 @@ static netdev_tx_t macb_start_xmit(struc
skb_tx_timestamp(skb);
spin_lock_irq(&bp->lock);
@@ -234,7 +234,7 @@ Signed-off-by: Jonathan Bell
macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TSTART));
spin_unlock_irq(&bp->lock);
-@@ -2768,6 +2796,37 @@ static void macb_configure_dma(struct ma
+@@ -2776,6 +2804,37 @@ static void macb_configure_dma(struct ma
}
}
@@ -272,7 +272,7 @@ Signed-off-by: Jonathan Bell
static void macb_init_hw(struct macb *bp)
{
u32 config;
-@@ -2796,6 +2855,11 @@ static void macb_init_hw(struct macb *bp
+@@ -2804,6 +2863,11 @@ static void macb_init_hw(struct macb *bp
if (bp->caps & MACB_CAPS_JUMBO)
bp->rx_frm_len_mask = MACB_RX_JFRMLEN_MASK;
@@ -284,7 +284,7 @@ Signed-off-by: Jonathan Bell
macb_configure_dma(bp);
/* Enable RX partial store and forward and set watermark */
-@@ -3157,6 +3221,52 @@ static void gem_get_ethtool_strings(stru
+@@ -3165,6 +3229,52 @@ static void gem_get_ethtool_strings(stru
}
}
@@ -337,7 +337,7 @@ Signed-off-by: Jonathan Bell
static struct net_device_stats *macb_get_stats(struct net_device *dev)
{
struct macb *bp = netdev_priv(dev);
-@@ -3749,6 +3859,8 @@ static const struct ethtool_ops macb_eth
+@@ -3757,6 +3867,8 @@ static const struct ethtool_ops macb_eth
};
static const struct ethtool_ops gem_ethtool_ops = {
@@ -346,7 +346,7 @@ Signed-off-by: Jonathan Bell
.get_regs_len = macb_get_regs_len,
.get_regs = macb_get_regs,
.get_wol = macb_get_wol,
-@@ -3758,6 +3870,8 @@ static const struct ethtool_ops gem_etht
+@@ -3766,6 +3878,8 @@ static const struct ethtool_ops gem_etht
.get_ethtool_stats = gem_get_ethtool_stats,
.get_strings = gem_get_ethtool_strings,
.get_sset_count = gem_get_sset_count,
@@ -355,7 +355,7 @@ Signed-off-by: Jonathan Bell
.get_link_ksettings = macb_get_link_ksettings,
.set_link_ksettings = macb_set_link_ksettings,
.get_ringparam = macb_get_ringparam,
-@@ -5054,6 +5168,11 @@ static int macb_probe(struct platform_de
+@@ -5062,6 +5176,11 @@ static int macb_probe(struct platform_de
}
}
}
@@ -367,7 +367,7 @@ Signed-off-by: Jonathan Bell
spin_lock_init(&bp->lock);
/* setup capabilities */
-@@ -5109,6 +5228,21 @@ static int macb_probe(struct platform_de
+@@ -5117,6 +5236,21 @@ static int macb_probe(struct platform_de
else
bp->phy_interface = interface;
@@ -389,7 +389,7 @@ Signed-off-by: Jonathan Bell
/* IP specific init */
err = init(pdev);
if (err)
-@@ -5185,6 +5319,19 @@ static int macb_remove(struct platform_d
+@@ -5193,6 +5327,19 @@ static int macb_remove(struct platform_d
return 0;
}
@@ -409,7 +409,7 @@ Signed-off-by: Jonathan Bell
static int __maybe_unused macb_suspend(struct device *dev)
{
struct net_device *netdev = dev_get_drvdata(dev);
-@@ -5399,6 +5546,7 @@ static const struct dev_pm_ops macb_pm_o
+@@ -5407,6 +5554,7 @@ static const struct dev_pm_ops macb_pm_o
static struct platform_driver macb_driver = {
.probe = macb_probe,
.remove = macb_remove,
diff --git a/target/linux/bcm53xx/config-6.6 b/target/linux/bcm53xx/config-6.6
index ace9e7d615c..34dcf86e7b8 100644
--- a/target/linux/bcm53xx/config-6.6
+++ b/target/linux/bcm53xx/config-6.6
@@ -245,8 +245,8 @@ CONFIG_NET_DSA_TAG_BRCM=y
CONFIG_NET_DSA_TAG_BRCM_COMMON=y
CONFIG_NET_DSA_TAG_BRCM_LEGACY=y
CONFIG_NET_DSA_TAG_BRCM_PREPEND=y
-CONFIG_NET_DSA_TAG_QCA=y
CONFIG_NET_DSA_TAG_NONE=y
+CONFIG_NET_DSA_TAG_QCA=y
CONFIG_NET_EGRESS=y
CONFIG_NET_FLOW_LIMIT=y
CONFIG_NET_INGRESS=y
diff --git a/target/linux/d1/config-6.6 b/target/linux/d1/config-6.6
index 957c3fba4d9..5a5b4c3d36d 100644
--- a/target/linux/d1/config-6.6
+++ b/target/linux/d1/config-6.6
@@ -143,13 +143,13 @@ CONFIG_I2C_MV64XXX=y
CONFIG_I2C_OCORES=y
CONFIG_INITRAMFS_SOURCE=""
CONFIG_INPUT=y
+# CONFIG_IOMMUFD is not set
CONFIG_IOMMU_API=y
# CONFIG_IOMMU_DEBUGFS is not set
# CONFIG_IOMMU_DEFAULT_DMA_LAZY is not set
CONFIG_IOMMU_DEFAULT_DMA_STRICT=y
# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set
CONFIG_IOMMU_SUPPORT=y
-# CONFIG_IOMMUFD is not set
CONFIG_IO_URING=y
CONFIG_IRQCHIP=y
CONFIG_IRQ_DOMAIN=y
diff --git a/target/linux/generic/config-6.6 b/target/linux/generic/config-6.6
index 7f569b9eedd..61a890fa3e8 100644
--- a/target/linux/generic/config-6.6
+++ b/target/linux/generic/config-6.6
@@ -880,7 +880,6 @@ CONFIG_CFG80211_HEADERS=y
# CONFIG_CHELSIO_T4 is not set
# CONFIG_CHELSIO_T4VF is not set
# CONFIG_CHROME_PLATFORMS is not set
-# CONFIG_CZNIC_PLATFORMS is not set
# CONFIG_CHR_DEV_SCH is not set
# CONFIG_CHR_DEV_SG is not set
# CONFIG_CHR_DEV_ST is not set
@@ -1247,6 +1246,7 @@ CONFIG_CRYPTO_SKCIPHER2=y
# CONFIG_CXL_BASE is not set
# CONFIG_CXL_BUS is not set
# CONFIG_CYPRESS_FIRMWARE is not set
+# CONFIG_CZNIC_PLATFORMS is not set
# CONFIG_DA280 is not set
# CONFIG_DA311 is not set
# CONFIG_DAMON is not set
@@ -5175,8 +5175,8 @@ CONFIG_RTC_SYSTOHC_DEVICE="rtc0"
# CONFIG_RTL_CARDS is not set
# CONFIG_RTS5208 is not set
CONFIG_RT_MUTEXES=y
-# CONFIG_RUST is not set
CONFIG_RUNTIME_TESTING_MENU=y
+# CONFIG_RUST is not set
# CONFIG_RV is not set
CONFIG_RXKAD=y
# CONFIG_RXPERF is not set
diff --git a/target/linux/generic/config-filter b/target/linux/generic/config-filter
index e7eda471d04..e72c334ee7a 100644
--- a/target/linux/generic/config-filter
+++ b/target/linux/generic/config-filter
@@ -1,17 +1,17 @@
+# CONFIG_ARCH_(ENABLE|HAS|HAVE|INLINE|SUPPORTS|USE|WANT|STACKWALK)_.* is not set
# CONFIG_ARM64_AS_.* is not set
# CONFIG_ARM64_CONT_.*_SHIFT is not set
-# CONFIG_ARCH_(ENABLE|HAS|HAVE|INLINE|SUPPORTS|USE|WANT|STACKWALK)_.* is not set
# CONFIG_AS_.* is not set
# CONFIG_CC_(CAN|HAS|IS|VERSION)_.* is not set
CONFIG_CLANG_VERSION=.*
-# CONFIG_GCC_VERSION is not set
CONFIG_FRAME_WARN=.*
+# CONFIG_GCC_VERSION is not set
# CONFIG_HAVE_(?!(ARCH_TIMER|TCM|SMP)).* is not set
# CONFIG_INLINE_.* is not set
# CONFIG_LD_.* is not set
CONFIG_LLD_VERSION=.*
-CONFIG_PAHOLE_VERSION=.*
CONFIG_PAHOLE_HAS_SPLIT_BTF=.*
+CONFIG_PAHOLE_VERSION=.*
CONFIG_PLUGIN_HOSTCC=".*"
# CONFIG_SET_FS is not set
# CONFIG_TASKS_.* is not set
diff --git a/target/linux/generic/hack-6.6/780-usb-net-MeigLink_modem_support.patch b/target/linux/generic/hack-6.6/780-usb-net-MeigLink_modem_support.patch
index 73a27ef6e2e..e80dfbeb0f3 100644
--- a/target/linux/generic/hack-6.6/780-usb-net-MeigLink_modem_support.patch
+++ b/target/linux/generic/hack-6.6/780-usb-net-MeigLink_modem_support.patch
@@ -43,7 +43,7 @@ Subject: [PATCH] net/usb/qmi_wwan: add MeigLink modem support
#define QUECTEL_VENDOR_ID 0x2c7c
/* These Quectel products use Quectel's vendor ID */
-@@ -1158,6 +1163,11 @@ static const struct usb_device_id option
+@@ -1159,6 +1164,11 @@ static const struct usb_device_id option
{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x0023)}, /* ONYX 3G device */
{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9000), /* SIMCom SIM5218 */
.driver_info = NCTRL(0) | NCTRL(1) | NCTRL(2) | NCTRL(3) | RSVD(4) },
@@ -55,7 +55,7 @@ Subject: [PATCH] net/usb/qmi_wwan: add MeigLink modem support
/* Quectel products using Qualcomm vendor ID */
{ USB_DEVICE(QUALCOMM_VENDOR_ID, QUECTEL_PRODUCT_UC15)},
{ USB_DEVICE(QUALCOMM_VENDOR_ID, QUECTEL_PRODUCT_UC20),
-@@ -1199,6 +1209,11 @@ static const struct usb_device_id option
+@@ -1200,6 +1210,11 @@ static const struct usb_device_id option
.driver_info = ZLP },
{ USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_BG96),
.driver_info = RSVD(4) },
diff --git a/target/linux/imx/config-6.6 b/target/linux/imx/config-6.6
index 6cb1d8a8f63..f70e7e15016 100644
--- a/target/linux/imx/config-6.6
+++ b/target/linux/imx/config-6.6
@@ -116,12 +116,12 @@ CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API=y
CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_DESC=y
# CONFIG_CRYPTO_DEV_FSL_CAAM_DEBUG is not set
# CONFIG_CRYPTO_DEV_FSL_CAAM_INTC is not set
-# CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_TEST is not set
CONFIG_CRYPTO_DEV_FSL_CAAM_JR=y
CONFIG_CRYPTO_DEV_FSL_CAAM_PKC_API=y
CONFIG_CRYPTO_DEV_FSL_CAAM_PRNG_API=y
CONFIG_CRYPTO_DEV_FSL_CAAM_RINGSIZE=9
CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API=y
+# CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_TEST is not set
CONFIG_CRYPTO_DRBG=y
CONFIG_CRYPTO_DRBG_HMAC=y
CONFIG_CRYPTO_DRBG_MENU=y
@@ -167,19 +167,13 @@ CONFIG_DMA_ENGINE=y
CONFIG_DMA_OF=y
CONFIG_DMA_OPS=y
CONFIG_DMA_VIRTUAL_CHANNELS=y
+# CONFIG_DRM_DW_HDMI_GP_AUDIO is not set
# CONFIG_DRM_FSL_LDB is not set
# CONFIG_DRM_IMX8QM_LDB is not set
# CONFIG_DRM_IMX8QXP_LDB is not set
# CONFIG_DRM_IMX8QXP_PIXEL_COMBINER is not set
# CONFIG_DRM_IMX8QXP_PIXEL_LINK_TO_DPI is not set
# CONFIG_DRM_IMX_LCDC is not set
-# CONFIG_DRM_DW_HDMI_GP_AUDIO is not set
-# CONFIG_VIDEO_IMX_MIPI_CSIS is not set
-# CONFIG_VIDEO_IMX8_ISI is not set
-# CONFIG_VIDEO_IMX8MQ_MIPI_CSI2 is not set
-# CONFIG_VIDEO_DW100 is not set
-# CONFIG_VIDEO_ROCKCHIP_ISP1 is not set
-# CONFIG_VIDEO_HANTRO is not set
CONFIG_DTC=y
CONFIG_EDAC_ATOMIC_SCRUB=y
CONFIG_EDAC_SUPPORT=y
@@ -351,6 +345,7 @@ CONFIG_PAGE_OFFSET=0x80000000
CONFIG_PAGE_POOL=y
CONFIG_PAGE_SIZE_LESS_THAN_256KB=y
CONFIG_PAGE_SIZE_LESS_THAN_64KB=y
+CONFIG_PCI_IMX6_HOST=y
CONFIG_PERF_USE_VMALLOC=y
CONFIG_PGTABLE_LEVELS=2
CONFIG_PHYLIB=y
@@ -360,7 +355,6 @@ CONFIG_PINCTRL=y
# CONFIG_PINCTRL_IMX93 is not set
# CONFIG_PINCTRL_IMXRT1050 is not set
# CONFIG_PINCTRL_IMXRT1170 is not set
-CONFIG_PCI_IMX6_HOST=y
CONFIG_PL310_ERRATA_769419=y
CONFIG_PM=y
CONFIG_PM_CLK=y
@@ -392,8 +386,8 @@ CONFIG_RESET_CONTROLLER=y
CONFIG_RFS_ACCEL=y
CONFIG_RPS=y
CONFIG_RTC_CLASS=y
-# CONFIG_RTC_DRV_CMOS is not set
# CONFIG_RTC_DRV_BBNSM is not set
+# CONFIG_RTC_DRV_CMOS is not set
# CONFIG_RTC_DRV_IMXDI is not set
# CONFIG_RTC_DRV_MXC is not set
# CONFIG_RTC_DRV_MXC_V2 is not set
@@ -474,9 +468,15 @@ CONFIG_USB_STORAGE=y
CONFIG_USB_SUPPORT=y
CONFIG_USB_ULPI_BUS=y
CONFIG_USE_OF=y
-# CONFIG_VIDEO_IMX7_CSI is not set
CONFIG_VFP=y
CONFIG_VFPv3=y
+# CONFIG_VIDEO_DW100 is not set
+# CONFIG_VIDEO_HANTRO is not set
+# CONFIG_VIDEO_IMX7_CSI is not set
+# CONFIG_VIDEO_IMX8MQ_MIPI_CSI2 is not set
+# CONFIG_VIDEO_IMX8_ISI is not set
+# CONFIG_VIDEO_IMX_MIPI_CSIS is not set
+# CONFIG_VIDEO_ROCKCHIP_ISP1 is not set
CONFIG_VMSPLIT_2G=y
# CONFIG_VMSPLIT_3G is not set
CONFIG_WATCHDOG_CORE=y
diff --git a/target/linux/imx/cortexa53/config-default b/target/linux/imx/cortexa53/config-default
index 026ddf67081..ac8e646da49 100644
--- a/target/linux/imx/cortexa53/config-default
+++ b/target/linux/imx/cortexa53/config-default
@@ -59,7 +59,6 @@ CONFIG_CRYPTO_SHA256_ARM64=y
CONFIG_CRYPTO_SHA2_ARM64_CE=y
CONFIG_CRYPTO_SHA512_ARM64=y
CONFIG_CRYPTO_SHA512_ARM64_CE=y
-# CONFIG_DRM_IMX_DCSS is not set
# CONFIG_DEVFREQ_GOV_PASSIVE is not set
# CONFIG_DEVFREQ_GOV_PERFORMANCE is not set
# CONFIG_DEVFREQ_GOV_POWERSAVE is not set
@@ -68,6 +67,7 @@ CONFIG_DEVFREQ_GOV_USERSPACE=y
# CONFIG_DEVFREQ_THERMAL is not set
# CONFIG_DMA_CMA is not set
CONFIG_DMA_DIRECT_REMAP=y
+# CONFIG_DRM_IMX_DCSS is not set
CONFIG_DUMMY_CONSOLE=y
CONFIG_DWMAC_DWC_QOS_ETH=y
CONFIG_DWMAC_GENERIC=y
diff --git a/target/linux/ipq40xx/config-6.6 b/target/linux/ipq40xx/config-6.6
index 683463628f3..0ee2f433b1e 100644
--- a/target/linux/ipq40xx/config-6.6
+++ b/target/linux/ipq40xx/config-6.6
@@ -220,11 +220,11 @@ CONFIG_I2C_HELPER_AUTO=y
# CONFIG_I2C_QCOM_CCI is not set
CONFIG_I2C_QUP=y
CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_IOMMUFD is not set
# CONFIG_IOMMU_DEBUGFS is not set
# CONFIG_IOMMU_IO_PGTABLE_ARMV7S is not set
# CONFIG_IOMMU_IO_PGTABLE_LPAE is not set
CONFIG_IOMMU_SUPPORT=y
-# CONFIG_IOMMUFD is not set
# CONFIG_IPQ_APSS_PLL is not set
CONFIG_IPQ_GCC_4019=y
# CONFIG_IPQ_GCC_6018 is not set
@@ -243,11 +243,11 @@ CONFIG_KMAP_LOCAL=y
CONFIG_KMAP_LOCAL_NON_LINEAR_PTE_ARRAY=y
# CONFIG_KPSS_XCC is not set
# CONFIG_KRAITCC is not set
-CONFIG_LED_TRIGGER_PHY=y
CONFIG_LEDS_LP5523=y
CONFIG_LEDS_LP5562=y
CONFIG_LEDS_LP55XX_COMMON=y
CONFIG_LEDS_TLC591XX=y
+CONFIG_LED_TRIGGER_PHY=y
CONFIG_LIBFDT=y
CONFIG_LOCK_DEBUGGING_SUPPORT=y
CONFIG_LOCK_SPIN_ON_OWNER=y
@@ -326,8 +326,8 @@ CONFIG_NVMEM=y
CONFIG_NVMEM_QCOM_QFPROM=y
# CONFIG_NVMEM_QCOM_SEC_QFPROM is not set
# CONFIG_NVMEM_SPMI_SDAM is not set
-CONFIG_NVMEM_U_BOOT_ENV=y
CONFIG_NVMEM_SYSFS=y
+CONFIG_NVMEM_U_BOOT_ENV=y
CONFIG_OF=y
CONFIG_OF_ADDRESS=y
CONFIG_OF_EARLY_FLATTREE=y
@@ -369,11 +369,11 @@ CONFIG_PHY_QCOM_IPQ4019_USB=y
# CONFIG_PHY_QCOM_PCIE2 is not set
# CONFIG_PHY_QCOM_QMP is not set
# CONFIG_PHY_QCOM_QUSB2 is not set
+# CONFIG_PHY_QCOM_SGMII_ETH is not set
# CONFIG_PHY_QCOM_SNPS_EUSB2 is not set
# CONFIG_PHY_QCOM_USB_HS_28NM is not set
# CONFIG_PHY_QCOM_USB_SNPS_FEMTO_V2 is not set
# CONFIG_PHY_QCOM_USB_SS is not set
-# CONFIG_PHY_QCOM_SGMII_ETH is not set
CONFIG_PINCTRL=y
# CONFIG_PINCTRL_APQ8064 is not set
# CONFIG_PINCTRL_APQ8084 is not set
@@ -418,9 +418,9 @@ CONFIG_QCOM_IPQ4019_ESS_EDMA=y
# CONFIG_QCOM_OCMEM is not set
# CONFIG_QCOM_PDC is not set
# CONFIG_QCOM_RAMP_CTRL is not set
-# CONFIG_QCOM_RPM_MASTER_STATS is not set
# CONFIG_QCOM_RMTFS_MEM is not set
# CONFIG_QCOM_RPMH is not set
+# CONFIG_QCOM_RPM_MASTER_STATS is not set
CONFIG_QCOM_SCM=y
# CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set
CONFIG_QCOM_SMEM=y
@@ -479,7 +479,6 @@ CONFIG_RWSEM_SPIN_ON_OWNER=y
# CONFIG_SDM_VIDEOCC_845 is not set
# CONFIG_SDX_GCC_65 is not set
# CONFIG_SDX_GCC_75 is not set
-# CONFIG_SM_GCC_7150 is not set
CONFIG_SERIAL_8250_FSL=y
CONFIG_SERIAL_MCTRL_GPIO=y
CONFIG_SERIAL_MSM=y
@@ -489,6 +488,7 @@ CONFIG_SKB_EXTENSIONS=y
CONFIG_SMP=y
CONFIG_SMP_ON_UP=y
# CONFIG_SM_CAMCC_8450 is not set
+# CONFIG_SM_GCC_7150 is not set
# CONFIG_SM_GCC_8150 is not set
# CONFIG_SM_GCC_8250 is not set
# CONFIG_SM_GCC_8450 is not set
diff --git a/target/linux/ipq40xx/mikrotik/config-default b/target/linux/ipq40xx/mikrotik/config-default
index 7234e4b8f61..9f90ea4193f 100644
--- a/target/linux/ipq40xx/mikrotik/config-default
+++ b/target/linux/ipq40xx/mikrotik/config-default
@@ -4,10 +4,10 @@ CONFIG_MIKROTIK_WLAN_DECOMPRESS_LZ77=y
CONFIG_MTD_ROUTERBOOT_PARTS=y
CONFIG_MTD_SPI_NOR_USE_VARIABLE_ERASE=y
CONFIG_MTD_SPLIT_MINOR_FW=y
-# CONFIG_NVMEM_LAYOUT_MIKROTIK is not set
CONFIG_MTD_UBI=y
CONFIG_MTD_UBI_BEB_LIMIT=20
CONFIG_MTD_UBI_BLOCK=y
CONFIG_MTD_UBI_NVMEM=y
CONFIG_MTD_UBI_WL_THRESHOLD=4096
+# CONFIG_NVMEM_LAYOUT_MIKROTIK is not set
CONFIG_UBIFS_FS=y
diff --git a/target/linux/ipq806x/config-6.6 b/target/linux/ipq806x/config-6.6
index 8c62332fce2..88ec58e2c95 100644
--- a/target/linux/ipq806x/config-6.6
+++ b/target/linux/ipq806x/config-6.6
@@ -209,11 +209,11 @@ CONFIG_I2C_HELPER_AUTO=y
# CONFIG_I2C_QCOM_CCI is not set
CONFIG_I2C_QUP=y
CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_IOMMUFD is not set
# CONFIG_IOMMU_DEBUGFS is not set
# CONFIG_IOMMU_IO_PGTABLE_ARMV7S is not set
# CONFIG_IOMMU_IO_PGTABLE_LPAE is not set
CONFIG_IOMMU_SUPPORT=y
-# CONFIG_IOMMUFD is not set
# CONFIG_IPQ_APSS_PLL is not set
# CONFIG_IPQ_GCC_4019 is not set
# CONFIG_IPQ_GCC_6018 is not set
@@ -366,11 +366,11 @@ CONFIG_PHY_QCOM_IPQ806X_SATA=y
# CONFIG_PHY_QCOM_PCIE2 is not set
# CONFIG_PHY_QCOM_QMP is not set
# CONFIG_PHY_QCOM_QUSB2 is not set
+# CONFIG_PHY_QCOM_SGMII_ETH is not set
+# CONFIG_PHY_QCOM_SNPS_EUSB2 is not set
# CONFIG_PHY_QCOM_USB_HS_28NM is not set
# CONFIG_PHY_QCOM_USB_SNPS_FEMTO_V2 is not set
# CONFIG_PHY_QCOM_USB_SS is not set
-# CONFIG_PHY_QCOM_SGMII_ETH is not set
-# CONFIG_PHY_QCOM_SNPS_EUSB2 is not set
CONFIG_PINCTRL=y
# CONFIG_PINCTRL_APQ8064 is not set
# CONFIG_PINCTRL_APQ8084 is not set
@@ -418,9 +418,9 @@ CONFIG_QCOM_NET_PHYLIB=y
# CONFIG_QCOM_PDC is not set
# CONFIG_QCOM_RAMP_CTRL is not set
# CONFIG_QCOM_RMTFS_MEM is not set
-CONFIG_QCOM_RPM_MASTER_STATS=y
CONFIG_QCOM_RPMCC=y
# CONFIG_QCOM_RPMH is not set
+CONFIG_QCOM_RPM_MASTER_STATS=y
CONFIG_QCOM_SCM=y
# CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set
CONFIG_QCOM_SMEM=y
diff --git a/target/linux/mediatek/image/filogic.mk b/target/linux/mediatek/image/filogic.mk
index ac535aeaa0f..37fe740c31d 100644
--- a/target/linux/mediatek/image/filogic.mk
+++ b/target/linux/mediatek/image/filogic.mk
@@ -208,7 +208,7 @@ define Device/smartrg_sdg-8733
$(call Device/adtran_smartrg)
DEVICE_MODEL := SDG-8733
DEVICE_DTS := mt7988a-smartrg-SDG-8733
- DEVICE_PACKAGES += kmod-mt7996-firmware kmod-phy-aquantia kmod-usb3
+ DEVICE_PACKAGES += kmod-mt7996-firmware kmod-phy-aquantia kmod-usb3 mt7988-wo-firmware
endef
TARGET_DEVICES += smartrg_sdg-8733
@@ -216,7 +216,7 @@ define Device/smartrg_sdg-8733a
$(call Device/adtran_smartrg)
DEVICE_MODEL := SDG-8733A
DEVICE_DTS := mt7988d-smartrg-SDG-8733A
- DEVICE_PACKAGES += mt7988-2p5g-phy-firmware kmod-mt7996-233-firmware kmod-phy-aquantia
+ DEVICE_PACKAGES += mt7988-2p5g-phy-firmware kmod-mt7996-233-firmware kmod-phy-aquantia mt7988-wo-firmware
endef
TARGET_DEVICES += smartrg_sdg-8733a
@@ -224,7 +224,7 @@ define Device/smartrg_sdg-8734
$(call Device/adtran_smartrg)
DEVICE_MODEL := SDG-8734
DEVICE_DTS := mt7988a-smartrg-SDG-8734
- DEVICE_PACKAGES += kmod-mt7996-firmware kmod-phy-aquantia kmod-sfp kmod-usb3
+ DEVICE_PACKAGES += kmod-mt7996-firmware kmod-phy-aquantia kmod-sfp kmod-usb3 mt7988-wo-firmware
endef
TARGET_DEVICES += smartrg_sdg-8734
@@ -378,7 +378,7 @@ define Device/bananapi_bpi-r4-common
DEVICE_DTS_OVERLAY:= mt7988a-bananapi-bpi-r4-emmc mt7988a-bananapi-bpi-r4-rtc mt7988a-bananapi-bpi-r4-sd mt7988a-bananapi-bpi-r4-wifi-mt7996a
DEVICE_DTC_FLAGS := --pad 4096
DEVICE_PACKAGES := kmod-hwmon-pwmfan kmod-i2c-mux-pca954x kmod-eeprom-at24 kmod-mt7996-firmware kmod-mt7996-233-firmware \
- kmod-rtc-pcf8563 kmod-sfp kmod-usb3 e2fsprogs f2fsck mkf2fs
+ kmod-rtc-pcf8563 kmod-sfp kmod-usb3 e2fsprogs f2fsck mkf2fs mt7988-wo-firmware
IMAGES := sysupgrade.itb
KERNEL_LOADADDR := 0x46000000
KERNEL_INITRAMFS_SUFFIX := -recovery.itb
diff --git a/target/linux/mediatek/mt7623/config-6.6 b/target/linux/mediatek/mt7623/config-6.6
index e34822d9922..baa31b465df 100644
--- a/target/linux/mediatek/mt7623/config-6.6
+++ b/target/linux/mediatek/mt7623/config-6.6
@@ -273,7 +273,6 @@ CONFIG_GPIO_CDEV=y
CONFIG_GRO_CELLS=y
# CONFIG_HARDEN_BRANCH_HISTORY is not set
# CONFIG_HARDEN_BRANCH_PREDICTOR is not set
-CONFIG_HARDEN_BRANCH_PREDICTOR=y
CONFIG_HARDIRQS_SW_RESEND=y
CONFIG_HAS_DMA=y
CONFIG_HAS_IOMEM=y
diff --git a/target/linux/mediatek/mt7629/config-6.6 b/target/linux/mediatek/mt7629/config-6.6
index 81c07a54922..5169acb99f0 100644
--- a/target/linux/mediatek/mt7629/config-6.6
+++ b/target/linux/mediatek/mt7629/config-6.6
@@ -147,7 +147,6 @@ CONFIG_GPIO_CDEV=y
CONFIG_GRO_CELLS=y
# CONFIG_HARDEN_BRANCH_HISTORY is not set
# CONFIG_HARDEN_BRANCH_PREDICTOR is not set
-CONFIG_HARDEN_BRANCH_PREDICTOR=y
CONFIG_HARDIRQS_SW_RESEND=y
CONFIG_HAS_DMA=y
CONFIG_HAS_IOMEM=y
diff --git a/target/linux/mpc85xx/config-6.6 b/target/linux/mpc85xx/config-6.6
index ef08a51979a..14d5650fb50 100644
--- a/target/linux/mpc85xx/config-6.6
+++ b/target/linux/mpc85xx/config-6.6
@@ -165,6 +165,7 @@ CONFIG_MTD_NAND_ECC=y
CONFIG_MTD_NAND_ECC_SW_HAMMING=y
CONFIG_MTD_RAW_NAND=y
CONFIG_MTD_SPI_NOR=y
+CONFIG_MTD_SPLIT_FIRMWARE=y
# CONFIG_MVME2500 is not set
CONFIG_NEED_PER_CPU_KM=y
CONFIG_NEED_SG_DMA_LENGTH=y
diff --git a/target/linux/mpc85xx/p1010/config-default b/target/linux/mpc85xx/p1010/config-default
index 1cd84b52cad..5a17e38f5c7 100644
--- a/target/linux/mpc85xx/p1010/config-default
+++ b/target/linux/mpc85xx/p1010/config-default
@@ -8,7 +8,6 @@ CONFIG_MEMORY=y
CONFIG_MTD_CFI=y
CONFIG_MTD_NAND_FSL_IFC=y
CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_SPLIT_FIRMWARE=y
CONFIG_MTD_SPLIT_TPLINK_FW=y
CONFIG_MTD_SPLIT_UIMAGE_FW=y
CONFIG_MTD_UBI=y
diff --git a/target/linux/mpc85xx/p1020/config-default b/target/linux/mpc85xx/p1020/config-default
index 36ace8015f7..66710a9aceb 100644
--- a/target/linux/mpc85xx/p1020/config-default
+++ b/target/linux/mpc85xx/p1020/config-default
@@ -11,12 +11,10 @@ CONFIG_EEPROM_LEGACY=y
CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
CONFIG_GENERIC_TBSYNC=y
CONFIG_GPIO_74X164=y
-CONFIG_GRO_CELLS=y
# CONFIG_GPIO_MAX77620 is not set
+CONFIG_GRO_CELLS=y
CONFIG_HAVE_RCU_TABLE_FREE=y
CONFIG_HIVEAP_330=y
-CONFIG_PANDA=y
-CONFIG_MSM460=y
CONFIG_I2C_CHARDEV=y
CONFIG_LEDS_LP5521=y
CONFIG_LEDS_LP55XX_COMMON=y
@@ -25,10 +23,10 @@ CONFIG_LOCK_SPIN_ON_OWNER=y
# CONFIG_MAX77620_WATCHDOG is not set
CONFIG_MFD_CORE=y
CONFIG_MFD_MAX77620=y
+CONFIG_MSM460=y
CONFIG_MTD_CFI=y
CONFIG_MTD_NAND_FSL_ELBC=y
CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_SPLIT_FIRMWARE=y
CONFIG_MTD_SPLIT_FIT_FW=y
CONFIG_MTD_SPLIT_UIMAGE_FW=y
CONFIG_MTD_UBI=y
@@ -47,6 +45,7 @@ CONFIG_NET_FLOW_LIMIT=y
CONFIG_NET_SWITCHDEV=y
CONFIG_NR_CPUS=2
CONFIG_PADATA=y
+CONFIG_PANDA=y
CONFIG_REGMAP_IRQ=y
CONFIG_REGULATOR=y
CONFIG_RFS_ACCEL=y
diff --git a/target/linux/mpc85xx/p2020/config-default b/target/linux/mpc85xx/p2020/config-default
index 01774cd6d68..ff8c8cb9393 100644
--- a/target/linux/mpc85xx/p2020/config-default
+++ b/target/linux/mpc85xx/p2020/config-default
@@ -15,7 +15,6 @@ CONFIG_MPC85xx_RDB=y
CONFIG_MTD_CFI=y
CONFIG_MTD_NAND_FSL_ELBC=y
CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_SPLIT_FIRMWARE=y
CONFIG_MTD_SPLIT_FIT_FW=y
CONFIG_MUTEX_SPIN_ON_OWNER=y
CONFIG_NEED_DMA_MAP_STATE=y
diff --git a/target/linux/mvebu/cortexa72/config-6.6 b/target/linux/mvebu/cortexa72/config-6.6
index af9dcf36329..d6aaa8d0bd2 100644
--- a/target/linux/mvebu/cortexa72/config-6.6
+++ b/target/linux/mvebu/cortexa72/config-6.6
@@ -59,11 +59,11 @@ CONFIG_MARVELL_10G_PHY=y
CONFIG_MFD_CORE=y
CONFIG_MFD_IEI_WT61P803_PUZZLE=y
CONFIG_MFD_SYSCON=y
-CONFIG_MMC_SDHCI_XENON=y
-CONFIG_MODULES_USE_ELF_RELA=y
CONFIG_MIKROTIK=y
CONFIG_MIKROTIK_RB_SYSFS=y
# CONFIG_MIKROTIK_WLAN_DECOMPRESS_LZ77 is not set
+CONFIG_MMC_SDHCI_XENON=y
+CONFIG_MODULES_USE_ELF_RELA=y
CONFIG_MTD_ROUTERBOOT_PARTS=y
CONFIG_MTD_SPI_NOR_USE_VARIABLE_ERASE=y
CONFIG_MVEBU_GICP=y
diff --git a/target/linux/qualcommax/Makefile b/target/linux/qualcommax/Makefile
index 0f63135b992..dc7c8305c21 100644
--- a/target/linux/qualcommax/Makefile
+++ b/target/linux/qualcommax/Makefile
@@ -15,14 +15,7 @@ DEFAULT_PACKAGES += \
kmod-usb3 kmod-usb-dwc3 kmod-usb-dwc3-qcom \
kmod-leds-gpio kmod-gpio-button-hotplug \
kmod-qca-nss-dp kmod-ath11k-ahb \
-<<<<<<< HEAD
wpad-openssl uboot-envtools \
e2fsprogs kmod-fs-ext4 losetup autocore cpufreq
-=======
- wpad-basic-mbedtls uboot-envtools \
- e2fsprogs kmod-fs-ext4 losetup \
- kmod-qca-nss-drv kmod-qca-nss-ecm \
- kmod-qca-nss-drv-bridge-mgr
->>>>>>> qos/qualcommax-6.x-nss-wifi
$(eval $(call BuildTarget))
diff --git a/target/linux/realtek/rtl839x/config-6.6 b/target/linux/realtek/rtl839x/config-6.6
index c8d841c01e9..a357eb39666 100644
--- a/target/linux/realtek/rtl839x/config-6.6
+++ b/target/linux/realtek/rtl839x/config-6.6
@@ -102,8 +102,8 @@ CONFIG_I2C=y
CONFIG_I2C_ALGOBIT=y
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_GPIO=y
-# CONFIG_I2C_RTL9300 is not set
# CONFIG_I2C_MUX_RTL9300 is not set
+# CONFIG_I2C_RTL9300 is not set
CONFIG_INITRAMFS_SOURCE=""
CONFIG_IRQCHIP=y
CONFIG_IRQ_DOMAIN=y
diff --git a/target/linux/sifiveu/config-6.6 b/target/linux/sifiveu/config-6.6
index 9a8cf8e48c3..2e5474ce2f5 100644
--- a/target/linux/sifiveu/config-6.6
+++ b/target/linux/sifiveu/config-6.6
@@ -9,10 +9,10 @@ CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=17
CONFIG_ARCH_OPTIONAL_KERNEL_RWX=y
CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT=y
CONFIG_ARCH_RV64I=y
-# CONFIG_ARCH_THEAD is not set
CONFIG_ARCH_SELECT_MEMORY_MODEL=y
CONFIG_ARCH_SPARSEMEM_ENABLE=y
CONFIG_ARCH_STACKWALK=y
+# CONFIG_ARCH_THEAD is not set
CONFIG_ARCH_WANTS_THP_SWAP=y
CONFIG_ASN1=y
CONFIG_ASSOCIATIVE_ARRAY=y
@@ -171,15 +171,15 @@ CONFIG_I2C_HELPER_AUTO=y
CONFIG_I2C_OCORES=y
CONFIG_INITRAMFS_SOURCE=""
CONFIG_INPUT=y
-# CONFIG_IOMMU_DEBUGFS is not set
# CONFIG_IOMMUFD is not set
+# CONFIG_IOMMU_DEBUGFS is not set
CONFIG_IOMMU_SUPPORT=y
CONFIG_IO_URING=y
-CONFIG_IRQ_STACKS=y
CONFIG_IRQCHIP=y
CONFIG_IRQ_DOMAIN=y
CONFIG_IRQ_DOMAIN_HIERARCHY=y
CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_IRQ_STACKS=y
CONFIG_IRQ_WORK=y
CONFIG_JBD2=y
CONFIG_KALLSYMS=y
@@ -316,8 +316,8 @@ CONFIG_RISCV_ISA_SVPBMT=y
CONFIG_RISCV_ISA_V=y
CONFIG_RISCV_ISA_V_DEFAULT_ENABLE=y
CONFIG_RISCV_ISA_ZBB=y
-CONFIG_RISCV_ISA_ZICBOZ=y
CONFIG_RISCV_ISA_ZICBOM=y
+CONFIG_RISCV_ISA_ZICBOZ=y
CONFIG_RISCV_SBI=y
CONFIG_RISCV_SBI_V01=y
CONFIG_RISCV_TIMER=y
diff --git a/target/linux/starfive/config-6.6 b/target/linux/starfive/config-6.6
index cb39210a422..8ebced1165c 100644
--- a/target/linux/starfive/config-6.6
+++ b/target/linux/starfive/config-6.6
@@ -166,10 +166,10 @@ CONFIG_EFI_STUB=y
# CONFIG_EFI_TEST is not set
# CONFIG_EFI_ZBOOT is not set
# CONFIG_ERRATA_ANDES is not set
-CONFIG_ERRATA_STARFIVE_JH7100=y
CONFIG_ERRATA_SIFIVE=y
CONFIG_ERRATA_SIFIVE_CIP_1200=y
CONFIG_ERRATA_SIFIVE_CIP_453=y
+CONFIG_ERRATA_STARFIVE_JH7100=y
# CONFIG_ERRATA_THEAD is not set
CONFIG_EXCLUSIVE_SYSTEM_RAM=y
CONFIG_EXT4_FS=y
@@ -308,9 +308,9 @@ CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_DEFAULT="iso8859-15"
CONFIG_NLS_ISO8859_1=y
CONFIG_NLS_ISO8859_15=y
+CONFIG_NONPORTABLE=y
CONFIG_NO_HZ_COMMON=y
CONFIG_NO_HZ_IDLE=y
-CONFIG_NONPORTABLE=y
CONFIG_NR_CPUS=8
CONFIG_NVMEM=y
CONFIG_NVMEM_SYSFS=y
@@ -499,8 +499,8 @@ CONFIG_SPI_MASTER=y
CONFIG_SPI_MEM=y
CONFIG_SPI_SPIDEV=y
CONFIG_SRCU=y
-CONFIG_STARFIVE_TIMER=y
CONFIG_STARFIVE_JH7110_TIMER=y
+CONFIG_STARFIVE_TIMER=y
CONFIG_STARFIVE_WATCHDOG=y
CONFIG_STMMAC_ETH=y
CONFIG_STMMAC_PLATFORM=y
diff --git a/target/linux/sunxi/cortexa53/config-6.6 b/target/linux/sunxi/cortexa53/config-6.6
index 55bcd4e8e54..89cd43a54ef 100644
--- a/target/linux/sunxi/cortexa53/config-6.6
+++ b/target/linux/sunxi/cortexa53/config-6.6
@@ -4,18 +4,19 @@ CONFIG_ARCH_MMAP_RND_BITS=18
CONFIG_ARCH_MMAP_RND_BITS_MAX=24
CONFIG_ARCH_MMAP_RND_BITS_MIN=18
CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11
+# CONFIG_ARCH_NXP is not set
CONFIG_ARCH_PROC_KCORE_TEXT=y
CONFIG_ARCH_STACKWALK=y
CONFIG_ARCH_WANTS_NO_INSTR=y
CONFIG_ARM64=y
CONFIG_ARM64_4K_PAGES=y
CONFIG_ARM64_CRYPTO=y
-CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y
CONFIG_ARM64_ERRATUM_2051678=y
-CONFIG_ARM64_ERRATUM_2077057=y
-CONFIG_ARM64_ERRATUM_2658417=y
CONFIG_ARM64_ERRATUM_2054223=y
CONFIG_ARM64_ERRATUM_2067961=y
+CONFIG_ARM64_ERRATUM_2077057=y
+CONFIG_ARM64_ERRATUM_2658417=y
+CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y
CONFIG_ARM64_PAGE_SHIFT=12
CONFIG_ARM64_PA_BITS=48
CONFIG_ARM64_PA_BITS_48=y
@@ -38,8 +39,11 @@ CONFIG_CRYPTO_CRCT10DIF_ARM64_CE=y
CONFIG_CRYPTO_CRYPTD=y
CONFIG_CRYPTO_GHASH_ARM64_CE=y
CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y
+# CONFIG_CRYPTO_POLYVAL_ARM64_CE is not set
CONFIG_CRYPTO_SHA1_ARM64_CE=y
CONFIG_CRYPTO_SIMD=y
+# CONFIG_CRYPTO_SM4_ARM64_CE_BLK is not set
+# CONFIG_CRYPTO_SM4_ARM64_NEON_BLK is not set
CONFIG_DMA_DIRECT_REMAP=y
CONFIG_DWMAC_SUN8I=y
CONFIG_EEPROM_AT24=y
@@ -59,6 +63,7 @@ CONFIG_MUSB_PIO_ONLY=y
CONFIG_NEED_SG_DMA_LENGTH=y
CONFIG_NOP_USB_XCEIV=y
CONFIG_NO_IOPORT_MAP=y
+# CONFIG_PAGE_TABLE_CHECK is not set
CONFIG_PARTITION_PERCPU=y
CONFIG_PHY_SUN50I_USB3=y
CONFIG_PINCTRL_SUN50I_A100=y
@@ -67,12 +72,13 @@ CONFIG_PINCTRL_SUN50I_A64=y
CONFIG_PINCTRL_SUN50I_A64_R=y
CONFIG_PINCTRL_SUN50I_H5=y
CONFIG_PINCTRL_SUN50I_H6=y
-CONFIG_PINCTRL_SUN50I_H6_R=y
CONFIG_PINCTRL_SUN50I_H616=y
CONFIG_PINCTRL_SUN50I_H616_R=y
+CONFIG_PINCTRL_SUN50I_H6_R=y
# CONFIG_PREEMPT_DYNAMIC is not set
CONFIG_QUEUED_RWLOCKS=y
CONFIG_QUEUED_SPINLOCKS=y
+CONFIG_RANDOMIZE_KSTACK_OFFSET=y
CONFIG_RODATA_FULL_DEFAULT_ENABLED=y
# CONFIG_SCHED_CLUSTER is not set
# CONFIG_SHADOW_CALL_STACK is not set
@@ -91,6 +97,7 @@ CONFIG_SUN50I_H616_CCU=y
CONFIG_SUN50I_H6_CCU=y
CONFIG_SUN50I_H6_R_CCU=y
# CONFIG_SUN6I_RTC_CCU is not set
+CONFIG_SURFACE_PLATFORMS=y
CONFIG_SYSCTL_EXCEPTION_TRACE=y
CONFIG_THREAD_INFO_IN_TASK=y
CONFIG_UNMAP_KERNEL_AT_EL0=y
@@ -100,10 +107,3 @@ CONFIG_USB_MUSB_SUNXI=y
CONFIG_USB_PHY=y
CONFIG_VMAP_STACK=y
CONFIG_ZONE_DMA32=y
-CONFIG_SURFACE_PLATFORMS=y
-# CONFIG_CRYPTO_POLYVAL_ARM64_CE is not set
-# CONFIG_CRYPTO_SM4_ARM64_CE_BLK is not set
-# CONFIG_CRYPTO_SM4_ARM64_NEON_BLK is not set
-# CONFIG_PAGE_TABLE_CHECK is not set
-CONFIG_RANDOMIZE_KSTACK_OFFSET=y
-# CONFIG_ARCH_NXP is not set
diff --git a/target/linux/x86/64/config-6.6 b/target/linux/x86/64/config-6.6
index b443231120c..def4527f771 100644
--- a/target/linux/x86/64/config-6.6
+++ b/target/linux/x86/64/config-6.6
@@ -49,11 +49,11 @@ CONFIG_AGP_INTEL=y
# CONFIG_AGP_SIS is not set
# CONFIG_AGP_VIA is not set
# CONFIG_AMD_HSMP is not set
-# CONFIG_AMD_SFH_HID is not set
CONFIG_AMD_IOMMU=y
CONFIG_AMD_IOMMU_V2=y
# CONFIG_AMD_PMF is not set
# CONFIG_AMD_PTDMA is not set
+# CONFIG_AMD_SFH_HID is not set
CONFIG_APERTURE_HELPERS=y
CONFIG_ARCH_CPUIDLE_HALTPOLL=y
CONFIG_ARCH_DMA_ADDR_T_64BIT=y
@@ -100,13 +100,13 @@ CONFIG_CRC64_ROCKSOFT=y
CONFIG_CRC_T10DIF=y
CONFIG_CRYPTO_AES_NI_INTEL=y
CONFIG_CRYPTO_ARCH_HAVE_LIB_BLAKE2S=y
-# CONFIG_CRYPTO_ARIA_AESNI_AVX_X86_64 is not set
# CONFIG_CRYPTO_ARIA_AESNI_AVX2_X86_64 is not set
+# CONFIG_CRYPTO_ARIA_AESNI_AVX_X86_64 is not set
# CONFIG_CRYPTO_ARIA_GFNI_AVX512_X86_64 is not set
CONFIG_CRYPTO_BLAKE2S_X86=y
# CONFIG_CRYPTO_BLOWFISH_X86_64 is not set
-# CONFIG_CRYPTO_CAMELLIA_AESNI_AVX_X86_64 is not set
# CONFIG_CRYPTO_CAMELLIA_AESNI_AVX2_X86_64 is not set
+# CONFIG_CRYPTO_CAMELLIA_AESNI_AVX_X86_64 is not set
# CONFIG_CRYPTO_CAMELLIA_X86_64 is not set
# CONFIG_CRYPTO_CAST5_AVX_X86_64 is not set
# CONFIG_CRYPTO_CAST6_AVX_X86_64 is not set
@@ -121,16 +121,16 @@ CONFIG_CRYPTO_LRW=y
# CONFIG_CRYPTO_NHPOLY1305_AVX2 is not set
# CONFIG_CRYPTO_NHPOLY1305_SSE2 is not set
# CONFIG_CRYPTO_POLYVAL_CLMUL_NI is not set
-# CONFIG_CRYPTO_SERPENT_AVX_X86_64 is not set
# CONFIG_CRYPTO_SERPENT_AVX2_X86_64 is not set
+# CONFIG_CRYPTO_SERPENT_AVX_X86_64 is not set
# CONFIG_CRYPTO_SERPENT_SSE2_X86_64 is not set
# CONFIG_CRYPTO_SHA1_SSSE3 is not set
# CONFIG_CRYPTO_SHA256_SSSE3 is not set
# CONFIG_CRYPTO_SHA512_SSSE3 is not set
CONFIG_CRYPTO_SIMD=y
# CONFIG_CRYPTO_SM3_AVX_X86_64 is not set
-# CONFIG_CRYPTO_SM4_AESNI_AVX_X86_64 is not set
# CONFIG_CRYPTO_SM4_AESNI_AVX2_X86_64 is not set
+# CONFIG_CRYPTO_SM4_AESNI_AVX_X86_64 is not set
# CONFIG_CRYPTO_TWOFISH_AVX_X86_64 is not set
# CONFIG_CRYPTO_TWOFISH_X86_64 is not set
# CONFIG_CRYPTO_TWOFISH_X86_64_3WAY is not set
@@ -229,8 +229,8 @@ CONFIG_FB_SYS_FOPS=y
CONFIG_FB_SYS_IMAGEBLIT=y
CONFIG_FB_TILEBLITTING=y
# CONFIG_FB_VESA is not set
-CONFIG_FONT_8x8=y
CONFIG_FONT_8x16=y
+CONFIG_FONT_8x8=y
CONFIG_FONT_SUPPORT=y
CONFIG_FRAMEBUFFER_CONSOLE=y
CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
diff --git a/target/linux/x86/generic/config-6.6 b/target/linux/x86/generic/config-6.6
index 6729f0e9cd1..091584e0774 100644
--- a/target/linux/x86/generic/config-6.6
+++ b/target/linux/x86/generic/config-6.6
@@ -162,8 +162,8 @@ CONFIG_FB_SYS_FILLRECT=y
CONFIG_FB_SYS_FOPS=y
CONFIG_FB_SYS_IMAGEBLIT=y
# CONFIG_FB_VESA is not set
-CONFIG_FONT_8x8=y
CONFIG_FONT_8x16=y
+CONFIG_FONT_8x8=y
CONFIG_FONT_SUPPORT=y
CONFIG_FRAMEBUFFER_CONSOLE=y
CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
diff --git a/target/linux/x86/geode/config-6.6 b/target/linux/x86/geode/config-6.6
index 729dc30c27a..f9f4a6aea9f 100644
--- a/target/linux/x86/geode/config-6.6
+++ b/target/linux/x86/geode/config-6.6
@@ -37,8 +37,8 @@ CONFIG_ACPI_THERMAL=y
# CONFIG_ADV_SWBUTTON is not set
CONFIG_ALIX=y
# CONFIG_AMD_PMF is not set
-# CONFIG_ASUS_TF103C_DOCK is not set
CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC=y
+# CONFIG_ASUS_TF103C_DOCK is not set
# CONFIG_ATA_PIIX is not set
CONFIG_CS5535_CLOCK_EVENT_SRC=y
CONFIG_CS5535_MFGPT=y
diff --git a/target/linux/x86/legacy/config-6.6 b/target/linux/x86/legacy/config-6.6
index d5c4a55e5e9..8ce9237a21d 100644
--- a/target/linux/x86/legacy/config-6.6
+++ b/target/linux/x86/legacy/config-6.6
@@ -45,8 +45,8 @@ CONFIG_AGP_INTEL=y
# CONFIG_AMD_PMF is not set
CONFIG_APERTURE_HELPERS=y
CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC=y
-CONFIG_AUXILIARY_BUS=y
# CONFIG_ASUS_TF103C_DOCK is not set
+CONFIG_AUXILIARY_BUS=y
CONFIG_BACKLIGHT_CLASS_DEVICE=y
CONFIG_BLK_DEV_SR=y
CONFIG_CDROM=y
@@ -120,8 +120,8 @@ CONFIG_FB_SYS_FILLRECT=y
CONFIG_FB_SYS_FOPS=y
CONFIG_FB_SYS_IMAGEBLIT=y
# CONFIG_FB_VESA is not set
-CONFIG_FONT_8x8=y
CONFIG_FONT_8x16=y
+CONFIG_FONT_8x8=y
CONFIG_FONT_SUPPORT=y
CONFIG_FRAMEBUFFER_CONSOLE=y
CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y