--- /dev/null
+--- a/ath10k-6.9/mac.c
++++ b/ath10k-6.9/mac.c
+@@ -6238,7 +6238,7 @@ err:
+ return ret;
+ }
+
+-static void ath10k_stop(struct ieee80211_hw *hw)
++static void ath10k_stop(struct ieee80211_hw *hw, bool suspend)
+ {
+ struct ath10k *ar = hw->priv;
+ u32 opt;
PKG_NAME:=mac80211
-PKG_VERSION:=6.9.9
+PKG_VERSION:=6.11
PKG_RELEASE:=1
PKG_LICENSE:=GPL-2.0-only
PKG_LICENSE_FILES:=COPYING
PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources/
-PKG_HASH:=3417da091a57c7b1c145d44c1fae9f1e0bac6d0c8ad61b37e57b0a802eeb2837
+PKG_HASH:=2c091ce9520c2e4c8a9c91a294f3c040f90cd76222674928e61542ead06cfa41
PKG_SOURCE:=backports-$(PKG_VERSION).tar.xz
PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(if $(BUILD_VARIANT),$(PKG_NAME)-$(BUILD_VARIANT)/)backports-$(PKG_VERSION)
help
--- a/local-symbols
+++ b/local-symbols
-@@ -94,6 +94,7 @@ ADM8211=
+@@ -96,6 +96,7 @@ ADM8211=
ATH_COMMON=
WLAN_VENDOR_ATH=
ATH_DEBUG=
--- a/drivers/net/wireless/ath/ath10k/Kconfig
+++ b/drivers/net/wireless/ath/ath10k/Kconfig
-@@ -88,6 +88,12 @@ config ATH10K_TRACING
+@@ -94,6 +94,12 @@ config ATH10K_TRACING
help
Select this to ath10k use tracing infrastructure.
ath10k_core-$(CPTCFG_ATH10K_TRACING) += trace.o
-ath10k_core-$(CONFIG_THERMAL) += thermal.o
+ath10k_core-$(CPTCFG_ATH10K_THERMAL) += thermal.o
+ ath10k_core-$(CPTCFG_ATH10K_LEDS) += leds.o
ath10k_core-$(CPTCFG_MAC80211_DEBUGFS) += debugfs_sta.o
ath10k_core-$(CONFIG_PM) += wow.o
- ath10k_core-$(CONFIG_DEV_COREDUMP) += coredump.o
--- a/drivers/net/wireless/ath/ath10k/thermal.h
+++ b/drivers/net/wireless/ath/ath10k/thermal.h
@@ -25,7 +25,7 @@ struct ath10k_thermal {
void ath10k_thermal_event_temperature(struct ath10k *ar, int temperature);
--- a/local-symbols
+++ b/local-symbols
-@@ -153,6 +153,7 @@ ATH10K_SNOC=
- ATH10K_DEBUG=
+@@ -156,6 +156,7 @@ ATH10K_DEBUG=
ATH10K_DEBUGFS=
+ ATH10K_LEDS=
ATH10K_SPECTRAL=
+ATH10K_THERMAL=
ATH10K_TRACING=
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
-@@ -3527,6 +3527,16 @@ int ath10k_core_register(struct ath10k *
+@@ -3539,6 +3539,16 @@ int ath10k_core_register(struct ath10k *
queue_work(ar->workqueue, &ar->register_work);
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
-@@ -9918,6 +9918,21 @@ static int ath10k_mac_init_rd(struct ath
+@@ -9919,6 +9919,21 @@ static int ath10k_mac_init_rd(struct ath
return 0;
}
int ath10k_mac_register(struct ath10k *ar)
{
static const u32 cipher_suites[] = {
-@@ -10280,6 +10295,12 @@ int ath10k_mac_register(struct ath10k *a
+@@ -10281,6 +10296,12 @@ int ath10k_mac_register(struct ath10k *a
ar->hw->weight_multiplier = ATH10K_AIRTIME_WEIGHT_MULTIPLIER;
+++ /dev/null
-From 8e1debd82466a3fe711784ab37e6b54e56011267 Mon Sep 17 00:00:00 2001
-From: Sebastian Gottschall <s.gottschall@dd-wrt.com>
-Date: Mon, 13 May 2024 17:22:25 +0300
-Subject: [PATCH] wifi: ath10k: add LED and GPIO controlling support for
- various chipsets
-
-Adds LED and GPIO Control support for 988x, 9887, 9888, 99x0, 9984
-based chipsets with on chipset connected led's using WMI Firmware API.
-The LED device will get available named as "ath10k-phyX" at sysfs and
-can be controlled with various triggers.
-Adds also debugfs interface for gpio control.
-
-Signed-off-by: Sebastian Gottschall <s.gottschall@dd-wrt.com>
-Reviewed-by: Steve deRosier <derosier@cal-sierra.com>
-[kvalo: major reorg and cleanup]
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
-[ansuel: rebase and small cleanup]
-Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
-Tested-by: Stefan Lippers-Hollmann <s.l-h@gmx.de>
-Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
-Link: https://msgid.link/20230611080505.17393-1-ansuelsmth@gmail.com
----
- drivers/net/wireless/ath/ath10k/Kconfig | 6 ++
- drivers/net/wireless/ath/ath10k/Makefile | 1 +
- drivers/net/wireless/ath/ath10k/core.c | 32 ++++++++
- drivers/net/wireless/ath/ath10k/core.h | 8 ++
- drivers/net/wireless/ath/ath10k/hw.h | 1 +
- drivers/net/wireless/ath/ath10k/leds.c | 90 +++++++++++++++++++++++
- drivers/net/wireless/ath/ath10k/leds.h | 34 +++++++++
- drivers/net/wireless/ath/ath10k/mac.c | 1 +
- drivers/net/wireless/ath/ath10k/wmi-ops.h | 32 ++++++++
- drivers/net/wireless/ath/ath10k/wmi-tlv.c | 2 +
- drivers/net/wireless/ath/ath10k/wmi.c | 54 ++++++++++++++
- drivers/net/wireless/ath/ath10k/wmi.h | 35 +++++++++
- 12 files changed, 296 insertions(+)
- create mode 100644 drivers/net/wireless/ath/ath10k/leds.c
- create mode 100644 drivers/net/wireless/ath/ath10k/leds.h
-
---- a/drivers/net/wireless/ath/ath10k/Kconfig
-+++ b/drivers/net/wireless/ath/ath10k/Kconfig
-@@ -73,6 +73,12 @@ config ATH10K_DEBUGFS
-
- If unsure, say Y to make it easier to debug problems.
-
-+config ATH10K_LEDS
-+ bool
-+ depends on ATH10K
-+ depends on LEDS_CLASS=y || LEDS_CLASS=MAC80211
-+ default y
-+
- config ATH10K_SPECTRAL
- bool "Atheros ath10k spectral scan support"
- depends on ATH10K_DEBUGFS
---- a/drivers/net/wireless/ath/ath10k/Makefile
-+++ b/drivers/net/wireless/ath/ath10k/Makefile
-@@ -19,6 +19,7 @@ ath10k_core-$(CPTCFG_ATH10K_SPECTRAL) +=
- ath10k_core-$(CPTCFG_NL80211_TESTMODE) += testmode.o
- ath10k_core-$(CPTCFG_ATH10K_TRACING) += trace.o
- ath10k_core-$(CPTCFG_ATH10K_THERMAL) += thermal.o
-+ath10k_core-$(CPTCFG_ATH10K_LEDS) += leds.o
- ath10k_core-$(CPTCFG_MAC80211_DEBUGFS) += debugfs_sta.o
- ath10k_core-$(CONFIG_PM) += wow.o
- ath10k_core-$(CONFIG_DEV_COREDUMP) += coredump.o
---- a/local-symbols
-+++ b/local-symbols
-@@ -154,6 +154,7 @@ ATH10K_DEBUG=
- ATH10K_DEBUGFS=
- ATH10K_SPECTRAL=
- ATH10K_THERMAL=
-+ATH10K_LEDS=
- ATH10K_TRACING=
- ATH10K_DFS_CERTIFIED=
- WCN36XX=
---- a/drivers/net/wireless/ath/ath10k/core.c
-+++ b/drivers/net/wireless/ath/ath10k/core.c
-@@ -27,6 +27,7 @@
- #include "testmode.h"
- #include "wmi-ops.h"
- #include "coredump.h"
-+#include "leds.h"
-
- unsigned int ath10k_debug_mask;
- EXPORT_SYMBOL(ath10k_debug_mask);
-@@ -68,6 +69,7 @@ static const struct ath10k_hw_params ath
- .name = "qca988x hw2.0",
- .patch_load_addr = QCA988X_HW_2_0_PATCH_LOAD_ADDR,
- .uart_pin = 7,
-+ .led_pin = 1,
- .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_ALL,
- .otp_exe_param = 0,
- .channel_counters_freq_hz = 88000,
-@@ -109,6 +111,7 @@ static const struct ath10k_hw_params ath
- .name = "qca988x hw2.0 ubiquiti",
- .patch_load_addr = QCA988X_HW_2_0_PATCH_LOAD_ADDR,
- .uart_pin = 7,
-+ .led_pin = 0,
- .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_ALL,
- .otp_exe_param = 0,
- .channel_counters_freq_hz = 88000,
-@@ -151,6 +154,7 @@ static const struct ath10k_hw_params ath
- .name = "qca9887 hw1.0",
- .patch_load_addr = QCA9887_HW_1_0_PATCH_LOAD_ADDR,
- .uart_pin = 7,
-+ .led_pin = 1,
- .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_ALL,
- .otp_exe_param = 0,
- .channel_counters_freq_hz = 88000,
-@@ -193,6 +197,7 @@ static const struct ath10k_hw_params ath
- .name = "qca6174 hw3.2 sdio",
- .patch_load_addr = QCA6174_HW_3_0_PATCH_LOAD_ADDR,
- .uart_pin = 19,
-+ .led_pin = 0,
- .otp_exe_param = 0,
- .channel_counters_freq_hz = 88000,
- .max_probe_resp_desc_thres = 0,
-@@ -230,6 +235,7 @@ static const struct ath10k_hw_params ath
- .name = "qca6164 hw2.1",
- .patch_load_addr = QCA6174_HW_2_1_PATCH_LOAD_ADDR,
- .uart_pin = 6,
-+ .led_pin = 0,
- .otp_exe_param = 0,
- .channel_counters_freq_hz = 88000,
- .max_probe_resp_desc_thres = 0,
-@@ -271,6 +277,7 @@ static const struct ath10k_hw_params ath
- .name = "qca6174 hw2.1",
- .patch_load_addr = QCA6174_HW_2_1_PATCH_LOAD_ADDR,
- .uart_pin = 6,
-+ .led_pin = 0,
- .otp_exe_param = 0,
- .channel_counters_freq_hz = 88000,
- .max_probe_resp_desc_thres = 0,
-@@ -312,6 +319,7 @@ static const struct ath10k_hw_params ath
- .name = "qca6174 hw3.0",
- .patch_load_addr = QCA6174_HW_3_0_PATCH_LOAD_ADDR,
- .uart_pin = 6,
-+ .led_pin = 0,
- .otp_exe_param = 0,
- .channel_counters_freq_hz = 88000,
- .max_probe_resp_desc_thres = 0,
-@@ -353,6 +361,7 @@ static const struct ath10k_hw_params ath
- .name = "qca6174 hw3.2",
- .patch_load_addr = QCA6174_HW_3_0_PATCH_LOAD_ADDR,
- .uart_pin = 6,
-+ .led_pin = 0,
- .otp_exe_param = 0,
- .channel_counters_freq_hz = 88000,
- .max_probe_resp_desc_thres = 0,
-@@ -398,6 +407,7 @@ static const struct ath10k_hw_params ath
- .name = "qca99x0 hw2.0",
- .patch_load_addr = QCA99X0_HW_2_0_PATCH_LOAD_ADDR,
- .uart_pin = 7,
-+ .led_pin = 17,
- .otp_exe_param = 0x00000700,
- .continuous_frag_desc = true,
- .cck_rate_map_rev2 = true,
-@@ -445,6 +455,7 @@ static const struct ath10k_hw_params ath
- .name = "qca9984/qca9994 hw1.0",
- .patch_load_addr = QCA9984_HW_1_0_PATCH_LOAD_ADDR,
- .uart_pin = 7,
-+ .led_pin = 17,
- .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_EACH,
- .otp_exe_param = 0x00000700,
- .continuous_frag_desc = true,
-@@ -499,6 +510,7 @@ static const struct ath10k_hw_params ath
- .name = "qca9888 hw2.0",
- .patch_load_addr = QCA9888_HW_2_0_PATCH_LOAD_ADDR,
- .uart_pin = 7,
-+ .led_pin = 17,
- .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_EACH,
- .otp_exe_param = 0x00000700,
- .continuous_frag_desc = true,
-@@ -550,6 +562,7 @@ static const struct ath10k_hw_params ath
- .name = "qca9377 hw1.0",
- .patch_load_addr = QCA9377_HW_1_0_PATCH_LOAD_ADDR,
- .uart_pin = 6,
-+ .led_pin = 0,
- .otp_exe_param = 0,
- .channel_counters_freq_hz = 88000,
- .max_probe_resp_desc_thres = 0,
-@@ -591,6 +604,7 @@ static const struct ath10k_hw_params ath
- .name = "qca9377 hw1.1",
- .patch_load_addr = QCA9377_HW_1_0_PATCH_LOAD_ADDR,
- .uart_pin = 6,
-+ .led_pin = 0,
- .otp_exe_param = 0,
- .channel_counters_freq_hz = 88000,
- .max_probe_resp_desc_thres = 0,
-@@ -634,6 +648,7 @@ static const struct ath10k_hw_params ath
- .name = "qca9377 hw1.1 sdio",
- .patch_load_addr = QCA9377_HW_1_0_PATCH_LOAD_ADDR,
- .uart_pin = 19,
-+ .led_pin = 0,
- .otp_exe_param = 0,
- .channel_counters_freq_hz = 88000,
- .max_probe_resp_desc_thres = 0,
-@@ -668,6 +683,7 @@ static const struct ath10k_hw_params ath
- .name = "qca4019 hw1.0",
- .patch_load_addr = QCA4019_HW_1_0_PATCH_LOAD_ADDR,
- .uart_pin = 7,
-+ .led_pin = 0,
- .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_EACH,
- .otp_exe_param = 0x0010000,
- .continuous_frag_desc = true,
-@@ -714,6 +730,7 @@ static const struct ath10k_hw_params ath
- .dev_id = 0,
- .bus = ATH10K_BUS_SNOC,
- .name = "wcn3990 hw1.0",
-+ .led_pin = 0,
- .continuous_frag_desc = true,
- .tx_chain_mask = 0x7,
- .rx_chain_mask = 0x7,
-@@ -3242,6 +3259,10 @@ int ath10k_core_start(struct ath10k *ar,
- goto err_hif_stop;
- }
-
-+ status = ath10k_leds_start(ar);
-+ if (status)
-+ goto err_hif_stop;
-+
- return 0;
-
- err_hif_stop:
-@@ -3500,9 +3521,18 @@ static void ath10k_core_register_work(st
- goto err_spectral_destroy;
- }
-
-+ status = ath10k_leds_register(ar);
-+ if (status) {
-+ ath10k_err(ar, "could not register leds: %d\n",
-+ status);
-+ goto err_thermal_unregister;
-+ }
-+
- set_bit(ATH10K_FLAG_CORE_REGISTERED, &ar->dev_flags);
- return;
-
-+err_thermal_unregister:
-+ ath10k_thermal_unregister(ar);
- err_spectral_destroy:
- ath10k_spectral_destroy(ar);
- err_debug_destroy:
-@@ -3548,6 +3578,8 @@ void ath10k_core_unregister(struct ath10
- if (!test_bit(ATH10K_FLAG_CORE_REGISTERED, &ar->dev_flags))
- return;
-
-+ ath10k_leds_unregister(ar);
-+
- ath10k_thermal_unregister(ar);
- /* Stop spectral before unregistering from mac80211 to remove the
- * relayfs debugfs file cleanly. Otherwise the parent debugfs tree
---- a/drivers/net/wireless/ath/ath10k/core.h
-+++ b/drivers/net/wireless/ath/ath10k/core.h
-@@ -15,6 +15,7 @@
- #include <linux/pci.h>
- #include <linux/uuid.h>
- #include <linux/time.h>
-+#include <linux/leds.h>
-
- #include "htt.h"
- #include "htc.h"
-@@ -1257,6 +1258,13 @@ struct ath10k {
- } testmode;
-
- struct {
-+ struct gpio_led wifi_led;
-+ struct led_classdev cdev;
-+ char label[48];
-+ u32 gpio_state_pin;
-+ } leds;
-+
-+ struct {
- /* protected by data_lock */
- u32 rx_crc_err_drop;
- u32 fw_crash_counter;
---- a/drivers/net/wireless/ath/ath10k/hw.h
-+++ b/drivers/net/wireless/ath/ath10k/hw.h
-@@ -521,6 +521,7 @@ struct ath10k_hw_params {
- const char *name;
- u32 patch_load_addr;
- int uart_pin;
-+ int led_pin;
- u32 otp_exe_param;
-
- /* Type of hw cycle counter wraparound logic, for more info
---- /dev/null
-+++ b/drivers/net/wireless/ath/ath10k/leds.c
-@@ -0,0 +1,90 @@
-+// SPDX-License-Identifier: ISC
-+/*
-+ * Copyright (c) 2005-2011 Atheros Communications Inc.
-+ * Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
-+ * Copyright (c) 2018 Sebastian Gottschall <s.gottschall@dd-wrt.com>
-+ * Copyright (c) 2018 The Linux Foundation. All rights reserved.
-+ */
-+
-+#include <linux/leds.h>
-+
-+#include "core.h"
-+#include "wmi.h"
-+#include "wmi-ops.h"
-+
-+#include "leds.h"
-+
-+static int ath10k_leds_set_brightness_blocking(struct led_classdev *led_cdev,
-+ enum led_brightness brightness)
-+{
-+ struct ath10k *ar = container_of(led_cdev, struct ath10k,
-+ leds.cdev);
-+ struct gpio_led *led = &ar->leds.wifi_led;
-+
-+ mutex_lock(&ar->conf_mutex);
-+
-+ if (ar->state != ATH10K_STATE_ON)
-+ goto out;
-+
-+ ar->leds.gpio_state_pin = (brightness != LED_OFF) ^ led->active_low;
-+ ath10k_wmi_gpio_output(ar, led->gpio, ar->leds.gpio_state_pin);
-+
-+out:
-+ mutex_unlock(&ar->conf_mutex);
-+
-+ return 0;
-+}
-+
-+int ath10k_leds_start(struct ath10k *ar)
-+{
-+ if (ar->hw_params.led_pin == 0)
-+ /* leds not supported */
-+ return 0;
-+
-+ /* under some circumstances, the gpio pin gets reconfigured
-+ * to default state by the firmware, so we need to
-+ * reconfigure it this behaviour has only ben seen on
-+ * QCA9984 and QCA99XX devices so far
-+ */
-+ ath10k_wmi_gpio_config(ar, ar->hw_params.led_pin, 0,
-+ WMI_GPIO_PULL_NONE, WMI_GPIO_INTTYPE_DISABLE);
-+ ath10k_wmi_gpio_output(ar, ar->hw_params.led_pin, 1);
-+
-+ return 0;
-+}
-+
-+int ath10k_leds_register(struct ath10k *ar)
-+{
-+ int ret;
-+
-+ if (ar->hw_params.led_pin == 0)
-+ /* leds not supported */
-+ return 0;
-+
-+ snprintf(ar->leds.label, sizeof(ar->leds.label), "ath10k-%s",
-+ wiphy_name(ar->hw->wiphy));
-+ ar->leds.wifi_led.active_low = 1;
-+ ar->leds.wifi_led.gpio = ar->hw_params.led_pin;
-+ ar->leds.wifi_led.name = ar->leds.label;
-+ ar->leds.wifi_led.default_state = LEDS_GPIO_DEFSTATE_KEEP;
-+
-+ ar->leds.cdev.name = ar->leds.label;
-+ ar->leds.cdev.brightness_set_blocking = ath10k_leds_set_brightness_blocking;
-+ ar->leds.cdev.default_trigger = ar->leds.wifi_led.default_trigger;
-+
-+ ret = led_classdev_register(wiphy_dev(ar->hw->wiphy), &ar->leds.cdev);
-+ if (ret)
-+ return ret;
-+
-+ return 0;
-+}
-+
-+void ath10k_leds_unregister(struct ath10k *ar)
-+{
-+ if (ar->hw_params.led_pin == 0)
-+ /* leds not supported */
-+ return;
-+
-+ led_classdev_unregister(&ar->leds.cdev);
-+}
-+
---- /dev/null
-+++ b/drivers/net/wireless/ath/ath10k/leds.h
-@@ -0,0 +1,34 @@
-+/* SPDX-License-Identifier: ISC */
-+/*
-+ * Copyright (c) 2005-2011 Atheros Communications Inc.
-+ * Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
-+ * Copyright (c) 2018 Sebastian Gottschall <s.gottschall@dd-wrt.com>
-+ * Copyright (c) 2018 The Linux Foundation. All rights reserved.
-+ */
-+
-+#ifndef _LEDS_H_
-+#define _LEDS_H_
-+
-+#include "core.h"
-+
-+#ifdef CPTCFG_ATH10K_LEDS
-+void ath10k_leds_unregister(struct ath10k *ar);
-+int ath10k_leds_start(struct ath10k *ar);
-+int ath10k_leds_register(struct ath10k *ar);
-+#else
-+static inline void ath10k_leds_unregister(struct ath10k *ar)
-+{
-+}
-+
-+static inline int ath10k_leds_start(struct ath10k *ar)
-+{
-+ return 0;
-+}
-+
-+static inline int ath10k_leds_register(struct ath10k *ar)
-+{
-+ return 0;
-+}
-+
-+#endif
-+#endif /* _LEDS_H_ */
---- a/drivers/net/wireless/ath/ath10k/mac.c
-+++ b/drivers/net/wireless/ath/ath10k/mac.c
-@@ -25,6 +25,7 @@
- #include "wmi-tlv.h"
- #include "wmi-ops.h"
- #include "wow.h"
-+#include "leds.h"
-
- /*********/
- /* Rates */
---- a/drivers/net/wireless/ath/ath10k/wmi-ops.h
-+++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h
-@@ -226,7 +226,10 @@ struct wmi_ops {
- const struct wmi_bb_timing_cfg_arg *arg);
- struct sk_buff *(*gen_per_peer_per_tid_cfg)(struct ath10k *ar,
- const struct wmi_per_peer_per_tid_cfg_arg *arg);
-+ struct sk_buff *(*gen_gpio_config)(struct ath10k *ar, u32 gpio_num,
-+ u32 input, u32 pull_type, u32 intr_mode);
-
-+ struct sk_buff *(*gen_gpio_output)(struct ath10k *ar, u32 gpio_num, u32 set);
- };
-
- int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id);
-@@ -1122,6 +1125,35 @@ ath10k_wmi_force_fw_hang(struct ath10k *
- return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->force_fw_hang_cmdid);
- }
-
-+static inline int ath10k_wmi_gpio_config(struct ath10k *ar, u32 gpio_num,
-+ u32 input, u32 pull_type, u32 intr_mode)
-+{
-+ struct sk_buff *skb;
-+
-+ if (!ar->wmi.ops->gen_gpio_config)
-+ return -EOPNOTSUPP;
-+
-+ skb = ar->wmi.ops->gen_gpio_config(ar, gpio_num, input, pull_type, intr_mode);
-+ if (IS_ERR(skb))
-+ return PTR_ERR(skb);
-+
-+ return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->gpio_config_cmdid);
-+}
-+
-+static inline int ath10k_wmi_gpio_output(struct ath10k *ar, u32 gpio_num, u32 set)
-+{
-+ struct sk_buff *skb;
-+
-+ if (!ar->wmi.ops->gen_gpio_config)
-+ return -EOPNOTSUPP;
-+
-+ skb = ar->wmi.ops->gen_gpio_output(ar, gpio_num, set);
-+ if (IS_ERR(skb))
-+ return PTR_ERR(skb);
-+
-+ return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->gpio_output_cmdid);
-+}
-+
- static inline int
- ath10k_wmi_dbglog_cfg(struct ath10k *ar, u64 module_enable, u32 log_level)
- {
---- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c
-+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
-@@ -4606,6 +4606,8 @@ static const struct wmi_ops wmi_tlv_ops
- .gen_echo = ath10k_wmi_tlv_op_gen_echo,
- .gen_vdev_spectral_conf = ath10k_wmi_tlv_op_gen_vdev_spectral_conf,
- .gen_vdev_spectral_enable = ath10k_wmi_tlv_op_gen_vdev_spectral_enable,
-+ /* .gen_gpio_config not implemented */
-+ /* .gen_gpio_output not implemented */
- };
-
- static const struct wmi_peer_flags_map wmi_tlv_peer_flags_map = {
---- a/drivers/net/wireless/ath/ath10k/wmi.c
-+++ b/drivers/net/wireless/ath/ath10k/wmi.c
-@@ -7493,6 +7493,49 @@ ath10k_wmi_op_gen_peer_set_param(struct
- return skb;
- }
-
-+static struct sk_buff *ath10k_wmi_op_gen_gpio_config(struct ath10k *ar,
-+ u32 gpio_num, u32 input,
-+ u32 pull_type, u32 intr_mode)
-+{
-+ struct wmi_gpio_config_cmd *cmd;
-+ struct sk_buff *skb;
-+
-+ skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
-+ if (!skb)
-+ return ERR_PTR(-ENOMEM);
-+
-+ cmd = (struct wmi_gpio_config_cmd *)skb->data;
-+ cmd->pull_type = __cpu_to_le32(pull_type);
-+ cmd->gpio_num = __cpu_to_le32(gpio_num);
-+ cmd->input = __cpu_to_le32(input);
-+ cmd->intr_mode = __cpu_to_le32(intr_mode);
-+
-+ ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi gpio_config gpio_num 0x%08x input 0x%08x pull_type 0x%08x intr_mode 0x%08x\n",
-+ gpio_num, input, pull_type, intr_mode);
-+
-+ return skb;
-+}
-+
-+static struct sk_buff *ath10k_wmi_op_gen_gpio_output(struct ath10k *ar,
-+ u32 gpio_num, u32 set)
-+{
-+ struct wmi_gpio_output_cmd *cmd;
-+ struct sk_buff *skb;
-+
-+ skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
-+ if (!skb)
-+ return ERR_PTR(-ENOMEM);
-+
-+ cmd = (struct wmi_gpio_output_cmd *)skb->data;
-+ cmd->gpio_num = __cpu_to_le32(gpio_num);
-+ cmd->set = __cpu_to_le32(set);
-+
-+ ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi gpio_output gpio_num 0x%08x set 0x%08x\n",
-+ gpio_num, set);
-+
-+ return skb;
-+}
-+
- static struct sk_buff *
- ath10k_wmi_op_gen_set_psmode(struct ath10k *ar, u32 vdev_id,
- enum wmi_sta_ps_mode psmode)
-@@ -9157,6 +9200,9 @@ static const struct wmi_ops wmi_ops = {
- .fw_stats_fill = ath10k_wmi_main_op_fw_stats_fill,
- .get_vdev_subtype = ath10k_wmi_op_get_vdev_subtype,
- .gen_echo = ath10k_wmi_op_gen_echo,
-+ .gen_gpio_config = ath10k_wmi_op_gen_gpio_config,
-+ .gen_gpio_output = ath10k_wmi_op_gen_gpio_output,
-+
- /* .gen_bcn_tmpl not implemented */
- /* .gen_prb_tmpl not implemented */
- /* .gen_p2p_go_bcn_ie not implemented */
-@@ -9227,6 +9273,8 @@ static const struct wmi_ops wmi_10_1_ops
- .fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill,
- .get_vdev_subtype = ath10k_wmi_op_get_vdev_subtype,
- .gen_echo = ath10k_wmi_op_gen_echo,
-+ .gen_gpio_config = ath10k_wmi_op_gen_gpio_config,
-+ .gen_gpio_output = ath10k_wmi_op_gen_gpio_output,
- /* .gen_bcn_tmpl not implemented */
- /* .gen_prb_tmpl not implemented */
- /* .gen_p2p_go_bcn_ie not implemented */
-@@ -9299,6 +9347,8 @@ static const struct wmi_ops wmi_10_2_ops
- .gen_delba_send = ath10k_wmi_op_gen_delba_send,
- .fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill,
- .get_vdev_subtype = ath10k_wmi_op_get_vdev_subtype,
-+ .gen_gpio_config = ath10k_wmi_op_gen_gpio_config,
-+ .gen_gpio_output = ath10k_wmi_op_gen_gpio_output,
- /* .gen_pdev_enable_adaptive_cca not implemented */
- };
-
-@@ -9370,6 +9420,8 @@ static const struct wmi_ops wmi_10_2_4_o
- ath10k_wmi_op_gen_pdev_enable_adaptive_cca,
- .get_vdev_subtype = ath10k_wmi_10_2_4_op_get_vdev_subtype,
- .gen_bb_timing = ath10k_wmi_10_2_4_op_gen_bb_timing,
-+ .gen_gpio_config = ath10k_wmi_op_gen_gpio_config,
-+ .gen_gpio_output = ath10k_wmi_op_gen_gpio_output,
- /* .gen_bcn_tmpl not implemented */
- /* .gen_prb_tmpl not implemented */
- /* .gen_p2p_go_bcn_ie not implemented */
-@@ -9451,6 +9503,8 @@ static const struct wmi_ops wmi_10_4_ops
- .gen_pdev_bss_chan_info_req = ath10k_wmi_10_2_op_gen_pdev_bss_chan_info,
- .gen_echo = ath10k_wmi_op_gen_echo,
- .gen_pdev_get_tpc_config = ath10k_wmi_10_2_4_op_gen_pdev_get_tpc_config,
-+ .gen_gpio_config = ath10k_wmi_op_gen_gpio_config,
-+ .gen_gpio_output = ath10k_wmi_op_gen_gpio_output,
- };
-
- int ath10k_wmi_attach(struct ath10k *ar)
---- a/drivers/net/wireless/ath/ath10k/wmi.h
-+++ b/drivers/net/wireless/ath/ath10k/wmi.h
-@@ -3034,6 +3034,41 @@ enum wmi_10_4_feature_mask {
-
- };
-
-+/* WMI_GPIO_CPTCFG_CMDID */
-+enum {
-+ WMI_GPIO_PULL_NONE,
-+ WMI_GPIO_PULL_UP,
-+ WMI_GPIO_PULL_DOWN,
-+};
-+
-+enum {
-+ WMI_GPIO_INTTYPE_DISABLE,
-+ WMI_GPIO_INTTYPE_RISING_EDGE,
-+ WMI_GPIO_INTTYPE_FALLING_EDGE,
-+ WMI_GPIO_INTTYPE_BOTH_EDGE,
-+ WMI_GPIO_INTTYPE_LEVEL_LOW,
-+ WMI_GPIO_INTTYPE_LEVEL_HIGH
-+};
-+
-+/* WMI_GPIO_CPTCFG_CMDID */
-+struct wmi_gpio_config_cmd {
-+ __le32 gpio_num; /* GPIO number to be setup */
-+ __le32 input; /* 0 - Output/ 1 - Input */
-+ __le32 pull_type; /* Pull type defined above */
-+ __le32 intr_mode; /* Interrupt mode defined above (Input) */
-+} __packed;
-+
-+/* WMI_GPIO_OUTPUT_CMDID */
-+struct wmi_gpio_output_cmd {
-+ __le32 gpio_num; /* GPIO number to be setup */
-+ __le32 set; /* Set the GPIO pin*/
-+} __packed;
-+
-+/* WMI_GPIO_INPUT_EVENTID */
-+struct wmi_gpio_input_event {
-+ __le32 gpio_num; /* GPIO number which changed state */
-+} __packed;
-+
- struct wmi_ext_resource_config_10_4_cmd {
- /* contains enum wmi_host_platform_type */
- __le32 host_platform_config;
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
-@@ -1313,6 +1313,10 @@ struct ath10k {
+@@ -1315,6 +1315,10 @@ struct ath10k {
s32 tx_power_2g_limit;
s32 tx_power_5g_limit;
#include <linux/property.h>
#include <linux/dmi.h>
#include <linux/ctype.h>
-@@ -3429,6 +3430,8 @@ static int ath10k_core_probe_fw(struct a
+@@ -3411,6 +3412,8 @@ static int ath10k_core_probe_fw(struct a
device_get_mac_address(ar->dev, ar->mac_addr);
default:
return "UNKNOWN";
}
-@@ -282,27 +312,14 @@ static void ath11k_mhi_op_status_cb(stru
- if (!(test_bit(ATH11K_FLAG_UNREGISTERING, &ab->dev_flags)))
+@@ -290,6 +320,9 @@ static void ath11k_mhi_op_status_cb(stru
queue_work(ab->workqueue_aux, &ab->reset_work);
+
break;
+ case MHI_CB_EE_SBL_MODE:
+ ath11k_mhi_qrtr_instance_set(mhi_cntrl);
default:
break;
}
+@@ -297,22 +330,6 @@ static void ath11k_mhi_op_status_cb(stru
+ ab_pci->mhi_pre_cb = cb;
}
-static int ath11k_mhi_op_read_reg(struct mhi_controller *mhi_cntrl,
+++ /dev/null
-From 1338da257f299d35b4d954b9fda2cc7e0a54a69d Mon Sep 17 00:00:00 2001
-From: Christian Lamparter <chunkeey@gmail.com>
-Date: Sun, 11 Jun 2023 14:37:32 +0200
-Subject: [PATCH] wifi: ath11k: add support DT ieee80211-freq-limit
-
-The common DT property can be used to limit the available
-channels/frequencies. But ath11k has to manually call
-wiphy_read_of_freq_limits().
-
-Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
----
- drivers/net/wireless/ath/ath11k/mac.c | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/drivers/net/wireless/ath/ath11k/mac.c
-+++ b/drivers/net/wireless/ath/ath11k/mac.c
-@@ -10034,6 +10034,7 @@ static int __ath11k_mac_register(struct
- if (ret)
- goto err;
-
-+ wiphy_read_of_freq_limits(ar->hw->wiphy);
- ath11k_mac_setup_ht_vht_cap(ar, cap, &ht_cap);
- ath11k_mac_setup_he_cap(ar, cap);
-
--- a/drivers/net/wireless/ath/ath11k/Kconfig
+++ b/drivers/net/wireless/ath/ath11k/Kconfig
-@@ -61,3 +61,10 @@ config ATH11K_SPECTRAL
+@@ -62,3 +62,10 @@ config ATH11K_SPECTRAL
Enable ath11k spectral scan support
Say Y to enable access to the FFT/spectral data via debugfs.
+ Enable ath11k thermal sensors and throttling support.
--- a/drivers/net/wireless/ath/ath11k/Makefile
+++ b/drivers/net/wireless/ath/ath11k/Makefile
-@@ -23,7 +23,7 @@ ath11k-y += core.o \
+@@ -24,7 +24,7 @@ ath11k-y += core.o \
ath11k-$(CPTCFG_ATH11K_DEBUGFS) += debugfs.o debugfs_htt_stats.o debugfs_sta.o
ath11k-$(CPTCFG_NL80211_TESTMODE) += testmode.o
ath11k-$(CPTCFG_ATH11K_TRACING) += trace.o
int ath11k_thermal_set_throttling(struct ath11k *ar, u32 throttle_state);
--- a/local-symbols
+++ b/local-symbols
-@@ -166,6 +166,7 @@ ATH11K_DEBUG=
+@@ -168,6 +168,7 @@ ATH11K_DEBUG=
ATH11K_DEBUGFS=
ATH11K_TRACING=
ATH11K_SPECTRAL=
+ATH11K_THERMAL=
ATH12K=
ATH12K_DEBUG=
- ATH12K_TRACING=
+ ATH12K_DEBUGFS=
{
.hw_rev = ATH11K_HW_IPQ8074,
.name = "ipq8074 hw2.0",
-@@ -2138,7 +2138,8 @@ static void ath11k_core_reset(struct wor
+@@ -2147,7 +2147,8 @@ static void ath11k_core_reset(struct wor
static int ath11k_init_hw_params(struct ath11k_base *ab)
{
const struct ath11k_hw_params *hw_params = NULL;
for (i = 0; i < ARRAY_SIZE(ath11k_hw_params); i++) {
hw_params = &ath11k_hw_params[i];
-@@ -2154,7 +2155,31 @@ static int ath11k_init_hw_params(struct
+@@ -2163,7 +2164,31 @@ static int ath11k_init_hw_params(struct
ab->hw_params = *hw_params;
--- a/drivers/net/wireless/ath/ath11k/reg.c
+++ b/drivers/net/wireless/ath/ath11k/reg.c
-@@ -363,134 +363,6 @@ static u32 ath11k_map_fw_phy_flags(u32 p
+@@ -361,134 +361,6 @@ static u32 ath11k_map_fw_phy_flags(u32 p
return flags;
}
static const char *
ath11k_reg_get_regdom_str(enum nl80211_dfs_regions dfs_region)
{
-@@ -641,11 +513,11 @@ ath11k_reg_ap_pwr_convert(enum ieee80211
+@@ -639,11 +511,11 @@ ath11k_reg_ap_pwr_convert(enum ieee80211
struct ieee80211_regdomain *
ath11k_reg_build_regd(struct ath11k_base *ab,
struct cur_reg_rule *reg_rule, *reg_rule_6ghz;
u8 i = 0, j = 0, k = 0;
u8 num_rules;
-@@ -688,26 +560,26 @@ ath11k_reg_build_regd(struct ath11k_base
+@@ -686,26 +558,26 @@ ath11k_reg_build_regd(struct ath11k_base
}
if (!num_rules)
reg_info->dfs_region, num_rules);
/* Update reg_rules[] below. Firmware is expected to
* send these rules in order(2 GHz rules first and then 5 GHz)
-@@ -746,7 +618,7 @@ ath11k_reg_build_regd(struct ath11k_base
+@@ -744,7 +616,7 @@ ath11k_reg_build_regd(struct ath11k_base
flags |= ath11k_map_fw_reg_flags(reg_rule->flags);
flags |= ath11k_map_fw_phy_flags(reg_info->phybitmap);
reg_rule->start_freq,
reg_rule->end_freq, max_bw,
reg_rule->ant_gain, reg_rule->reg_power,
-@@ -761,7 +633,7 @@ ath11k_reg_build_regd(struct ath11k_base
+@@ -759,7 +631,7 @@ ath11k_reg_build_regd(struct ath11k_base
reg_info->dfs_region == ATH11K_DFS_REG_ETSI &&
(reg_rule->end_freq > ETSI_WEATHER_RADAR_BAND_LOW &&
reg_rule->start_freq < ETSI_WEATHER_RADAR_BAND_HIGH)){
reg_rule, &i,
flags, max_bw);
continue;
-@@ -772,51 +644,23 @@ ath11k_reg_build_regd(struct ath11k_base
+@@ -770,51 +642,23 @@ ath11k_reg_build_regd(struct ath11k_base
"\t%d. (%d - %d @ %d) (%d, %d) (%d ms) (FLAGS %d) (%d, %d)\n",
i + 1, reg_rule->start_freq, reg_rule->end_freq,
max_bw, reg_rule->ant_gain, reg_rule->reg_power,
static enum wmi_vdev_type ath11k_reg_get_ar_vdev_type(struct ath11k *ar)
{
struct ath11k_vif *arvif;
-@@ -839,7 +683,6 @@ int ath11k_reg_handle_chan_list(struct a
+@@ -837,7 +681,6 @@ int ath11k_reg_handle_chan_list(struct a
enum ieee80211_ap_reg_power power_type)
{
struct ieee80211_regdomain *regd;
int pdev_idx;
struct ath11k *ar;
enum wmi_vdev_type vdev_type;
-@@ -891,24 +734,14 @@ int ath11k_reg_handle_chan_list(struct a
+@@ -889,24 +732,14 @@ int ath11k_reg_handle_chan_list(struct a
(char *)reg_info->alpha2, 2))
goto retfail;
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -89,7 +89,7 @@ int ath_descdma_setup(struct ath_softc *
+@@ -90,7 +90,7 @@ int ath_descdma_setup(struct ath_softc *
(_l) &= ((_sz) - 1); \
} while (0)
#define AR9160_DEVID_PCI 0x0027
--- a/drivers/net/wireless/ath/ath9k/pci.c
+++ b/drivers/net/wireless/ath/ath9k/pci.c
-@@ -774,6 +774,7 @@ static const struct pci_device_id ath_pc
+@@ -772,6 +772,7 @@ static const struct pci_device_id ath_pc
.driver_data = ATH9K_PCI_BT_ANT_DIV },
#endif
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -844,6 +844,9 @@ static inline int ath9k_dump_btcoex(stru
+@@ -845,6 +845,9 @@ static inline int ath9k_dump_btcoex(stru
#ifdef CPTCFG_MAC80211_LEDS
void ath_init_leds(struct ath_softc *sc);
void ath_deinit_leds(struct ath_softc *sc);
#else
static inline void ath_init_leds(struct ath_softc *sc)
{
-@@ -980,6 +983,13 @@ void ath_ant_comb_scan(struct ath_softc
+@@ -981,6 +984,13 @@ void ath_ant_comb_scan(struct ath_softc
#define ATH9K_NUM_CHANCTX 2 /* supports 2 operating channels */
struct ath_softc {
struct ieee80211_hw *hw;
struct device *dev;
-@@ -1033,9 +1043,8 @@ struct ath_softc {
+@@ -1034,9 +1044,8 @@ struct ath_softc {
spinlock_t chan_lock;
#ifdef CPTCFG_MAC80211_LEDS
#include "common.h"
#include "debug.h"
-@@ -990,6 +991,14 @@ struct ath_led {
+@@ -991,6 +992,14 @@ struct ath_led {
struct led_classdev cdev;
};
struct ath_softc {
struct ieee80211_hw *hw;
struct device *dev;
-@@ -1045,6 +1054,9 @@ struct ath_softc {
+@@ -1046,6 +1055,9 @@ struct ath_softc {
#ifdef CPTCFG_MAC80211_LEDS
const char *led_default_trigger;
struct list_head leds;
---
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -1056,6 +1056,7 @@ struct ath_softc {
+@@ -1057,6 +1057,7 @@ struct ath_softc {
struct list_head leds;
#ifdef CONFIG_GPIOLIB
struct ath9k_gpio_chip *gpiochip;
--- a/local-symbols
+++ b/local-symbols
-@@ -121,6 +121,7 @@ ATH9K_WOW=
+@@ -123,6 +123,7 @@ ATH9K_WOW=
ATH9K_RFKILL=
ATH9K_CHANNEL_CONTEXT=
ATH9K_PCOEM=
#include "common.h"
#include "debug.h"
-@@ -1012,6 +1013,9 @@ struct ath_softc {
+@@ -1013,6 +1014,9 @@ struct ath_softc {
struct ath_hw *sc_ah;
void __iomem *mem;
int irq;
void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,
struct brcmf_mp_device *settings)
{
-@@ -113,6 +143,8 @@ void brcmf_of_probe(struct device *dev,
+@@ -114,6 +144,8 @@ void brcmf_of_probe(struct device *dev,
of_node_put(root);
}
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-@@ -7979,6 +7979,7 @@ static s32 brcmf_translate_country_code(
+@@ -7986,6 +7986,7 @@ static s32 brcmf_translate_country_code(
return 0;
}
static int
brcmf_parse_dump_obss(char *buf, struct brcmf_dump_survey *survey)
{
-@@ -8201,6 +8202,7 @@ exit:
+@@ -8208,6 +8209,7 @@ exit:
brcmf_set_mpc(ifp, 1);
return err;
}
static void brcmf_cfg80211_reg_notifier(struct wiphy *wiphy,
struct regulatory_request *req)
-@@ -8353,8 +8355,10 @@ struct brcmf_cfg80211_info *brcmf_cfg802
+@@ -8360,8 +8362,10 @@ struct brcmf_cfg80211_info *brcmf_cfg802
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL_GTK))
ops->set_rekey_data = brcmf_cfg80211_set_rekey_data;
#endif
+++ /dev/null
---- a/local-symbols
-+++ b/local-symbols
-@@ -471,43 +471,6 @@ USB_VL600=
- USB_NET_CH9200=
- USB_NET_AQC111=
- USB_RTL8153_ECM=
--SSB_POSSIBLE=
--SSB=
--SSB_SPROM=
--SSB_BLOCKIO=
--SSB_PCIHOST_POSSIBLE=
--SSB_PCIHOST=
--SSB_B43_PCI_BRIDGE=
--SSB_PCMCIAHOST_POSSIBLE=
--SSB_PCMCIAHOST=
--SSB_SDIOHOST_POSSIBLE=
--SSB_SDIOHOST=
--SSB_HOST_SOC=
--SSB_SERIAL=
--SSB_DRIVER_PCICORE_POSSIBLE=
--SSB_DRIVER_PCICORE=
--SSB_PCICORE_HOSTMODE=
--SSB_DRIVER_MIPS=
--SSB_SFLASH=
--SSB_EMBEDDED=
--SSB_DRIVER_EXTIF=
--SSB_DRIVER_GIGE=
--SSB_DRIVER_GPIO=
--BCMA_POSSIBLE=
--BCMA=
--BCMA_BLOCKIO=
--BCMA_HOST_PCI_POSSIBLE=
--BCMA_HOST_PCI=
--BCMA_HOST_SOC=
--BCMA_DRIVER_PCI=
--BCMA_DRIVER_PCI_HOSTMODE=
--BCMA_DRIVER_MIPS=
--BCMA_PFLASH=
--BCMA_SFLASH=
--BCMA_NFLASH=
--BCMA_DRIVER_GMAC_CMN=
--BCMA_DRIVER_GPIO=
--BCMA_DEBUG=
- USB_ACM=
- USB_PRINTER=
- USB_WDM=
---- a/drivers/net/wireless/broadcom/b43/Kconfig
-+++ b/drivers/net/wireless/broadcom/b43/Kconfig
-@@ -63,21 +63,21 @@ endchoice
- config B43_PCI_AUTOSELECT
- bool
- depends on B43 && SSB_PCIHOST_POSSIBLE
-- select SSB_PCIHOST
-- select SSB_B43_PCI_BRIDGE
-+ depends on SSB_PCIHOST
-+ depends on SSB_B43_PCI_BRIDGE
- default y
-
- # Auto-select SSB PCICORE driver, if possible
- config B43_PCICORE_AUTOSELECT
- bool
- depends on B43 && SSB_DRIVER_PCICORE_POSSIBLE
-- select SSB_DRIVER_PCICORE
-+ depends on SSB_DRIVER_PCICORE
- default y
-
- config B43_SDIO
- bool "Broadcom 43xx SDIO device support"
- depends on B43 && B43_SSB && SSB_SDIOHOST_POSSIBLE
-- select SSB_SDIOHOST
-+ depends on SSB_SDIOHOST
- help
- Broadcom 43xx device support for Soft-MAC SDIO devices.
-
-@@ -96,13 +96,13 @@ config B43_SDIO
- config B43_BCMA_PIO
- bool
- depends on B43 && B43_BCMA
-- select BCMA_BLOCKIO
-+ depends on BCMA_BLOCKIO
- default y
-
- config B43_PIO
- bool
- depends on B43 && B43_SSB
-- select SSB_BLOCKIO
-+ depends on SSB_BLOCKIO
- default y
-
- config B43_PHY_G
---- a/drivers/net/wireless/broadcom/b43/main.c
-+++ b/drivers/net/wireless/broadcom/b43/main.c
-@@ -2854,7 +2854,7 @@ static struct ssb_device *b43_ssb_gpio_d
- {
- struct ssb_bus *bus = dev->dev->sdev->bus;
-
--#ifdef CPTCFG_SSB_DRIVER_PCICORE
-+#ifdef CONFIG_SSB_DRIVER_PCICORE
- return (bus->chipco.dev ? bus->chipco.dev : bus->pcicore.dev);
- #else
- return bus->chipco.dev;
-@@ -4873,7 +4873,7 @@ static int b43_wireless_core_init(struct
- }
- if (sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW)
- hf |= B43_HF_DSCRQ; /* Disable slowclock requests from ucode. */
--#if defined(CPTCFG_B43_SSB) && defined(CPTCFG_SSB_DRIVER_PCICORE)
-+#if defined(CPTCFG_B43_SSB) && defined(CONFIG_SSB_DRIVER_PCICORE)
- if (dev->dev->bus_type == B43_BUS_SSB &&
- dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI &&
- dev->dev->sdev->bus->pcicore.dev->id.revision <= 10)
---- a/drivers/net/wireless/broadcom/b43legacy/Kconfig
-+++ b/drivers/net/wireless/broadcom/b43legacy/Kconfig
-@@ -3,7 +3,7 @@ config B43LEGACY
- tristate "Broadcom 43xx-legacy wireless support (mac80211 stack)"
- depends on m
- depends on SSB_POSSIBLE && MAC80211 && HAS_DMA
-- select SSB
-+ depends on SSB
- depends on FW_LOADER
- help
- b43legacy is a driver for 802.11b devices from Broadcom (BCM4301 and
-@@ -25,15 +25,15 @@ config B43LEGACY
- config B43LEGACY_PCI_AUTOSELECT
- bool
- depends on B43LEGACY && SSB_PCIHOST_POSSIBLE
-- select SSB_PCIHOST
-- select SSB_B43_PCI_BRIDGE
-+ depends on SSB_PCIHOST
-+ depends on SSB_B43_PCI_BRIDGE
- default y
-
- # Auto-select SSB PCICORE driver, if possible
- config B43LEGACY_PCICORE_AUTOSELECT
- bool
- depends on B43LEGACY && SSB_DRIVER_PCICORE_POSSIBLE
-- select SSB_DRIVER_PCICORE
-+ depends on SSB_DRIVER_PCICORE
- default y
-
- # LED support
---- a/drivers/net/wireless/broadcom/b43legacy/main.c
-+++ b/drivers/net/wireless/broadcom/b43legacy/main.c
-@@ -1907,7 +1907,7 @@ static int b43legacy_gpio_init(struct b4
- if (dev->dev->id.revision >= 2)
- mask |= 0x0010; /* FIXME: This is redundant. */
-
--#ifdef CPTCFG_SSB_DRIVER_PCICORE
-+#ifdef CONFIG_SSB_DRIVER_PCICORE
- pcidev = bus->pcicore.dev;
- #endif
- gpiodev = bus->chipco.dev ? : pcidev;
-@@ -1926,7 +1926,7 @@ static void b43legacy_gpio_cleanup(struc
- struct ssb_bus *bus = dev->dev->bus;
- struct ssb_device *gpiodev, *pcidev = NULL;
-
--#ifdef CPTCFG_SSB_DRIVER_PCICORE
-+#ifdef CONFIG_SSB_DRIVER_PCICORE
- pcidev = bus->pcicore.dev;
- #endif
- gpiodev = bus->chipco.dev ? : pcidev;
---- a/drivers/net/wireless/broadcom/brcm80211/Kconfig
-+++ b/drivers/net/wireless/broadcom/brcm80211/Kconfig
-@@ -8,7 +8,7 @@ config BRCMSMAC
- depends on m
- depends on MAC80211
- depends on BCMA_POSSIBLE
-- select BCMA
-+ depends on BCMA
- select BRCMUTIL
- depends on FW_LOADER
- depends on CORDIC
---- a/Kconfig.local
-+++ b/Kconfig.local
-@@ -1417,117 +1417,6 @@ config BACKPORTED_USB_NET_AQC111
- config BACKPORTED_USB_RTL8153_ECM
- tristate
- default USB_RTL8153_ECM
--config BACKPORTED_SSB_POSSIBLE
-- tristate
-- default SSB_POSSIBLE
--config BACKPORTED_SSB
-- tristate
-- default SSB
--config BACKPORTED_SSB_SPROM
-- tristate
-- default SSB_SPROM
--config BACKPORTED_SSB_BLOCKIO
-- tristate
-- default SSB_BLOCKIO
--config BACKPORTED_SSB_PCIHOST_POSSIBLE
-- tristate
-- default SSB_PCIHOST_POSSIBLE
--config BACKPORTED_SSB_PCIHOST
-- tristate
-- default SSB_PCIHOST
--config BACKPORTED_SSB_B43_PCI_BRIDGE
-- tristate
-- default SSB_B43_PCI_BRIDGE
--config BACKPORTED_SSB_PCMCIAHOST_POSSIBLE
-- tristate
-- default SSB_PCMCIAHOST_POSSIBLE
--config BACKPORTED_SSB_PCMCIAHOST
-- tristate
-- default SSB_PCMCIAHOST
--config BACKPORTED_SSB_SDIOHOST_POSSIBLE
-- tristate
-- default SSB_SDIOHOST_POSSIBLE
--config BACKPORTED_SSB_SDIOHOST
-- tristate
-- default SSB_SDIOHOST
--config BACKPORTED_SSB_HOST_SOC
-- tristate
-- default SSB_HOST_SOC
--config BACKPORTED_SSB_SERIAL
-- tristate
-- default SSB_SERIAL
--config BACKPORTED_SSB_DRIVER_PCICORE_POSSIBLE
-- tristate
-- default SSB_DRIVER_PCICORE_POSSIBLE
--config BACKPORTED_SSB_DRIVER_PCICORE
-- tristate
-- default SSB_DRIVER_PCICORE
--config BACKPORTED_SSB_PCICORE_HOSTMODE
-- tristate
-- default SSB_PCICORE_HOSTMODE
--config BACKPORTED_SSB_DRIVER_MIPS
-- tristate
-- default SSB_DRIVER_MIPS
--config BACKPORTED_SSB_SFLASH
-- tristate
-- default SSB_SFLASH
--config BACKPORTED_SSB_EMBEDDED
-- tristate
-- default SSB_EMBEDDED
--config BACKPORTED_SSB_DRIVER_EXTIF
-- tristate
-- default SSB_DRIVER_EXTIF
--config BACKPORTED_SSB_DRIVER_GIGE
-- tristate
-- default SSB_DRIVER_GIGE
--config BACKPORTED_SSB_DRIVER_GPIO
-- tristate
-- default SSB_DRIVER_GPIO
--config BACKPORTED_BCMA_POSSIBLE
-- tristate
-- default BCMA_POSSIBLE
--config BACKPORTED_BCMA
-- tristate
-- default BCMA
--config BACKPORTED_BCMA_BLOCKIO
-- tristate
-- default BCMA_BLOCKIO
--config BACKPORTED_BCMA_HOST_PCI_POSSIBLE
-- tristate
-- default BCMA_HOST_PCI_POSSIBLE
--config BACKPORTED_BCMA_HOST_PCI
-- tristate
-- default BCMA_HOST_PCI
--config BACKPORTED_BCMA_HOST_SOC
-- tristate
-- default BCMA_HOST_SOC
--config BACKPORTED_BCMA_DRIVER_PCI
-- tristate
-- default BCMA_DRIVER_PCI
--config BACKPORTED_BCMA_DRIVER_PCI_HOSTMODE
-- tristate
-- default BCMA_DRIVER_PCI_HOSTMODE
--config BACKPORTED_BCMA_DRIVER_MIPS
-- tristate
-- default BCMA_DRIVER_MIPS
--config BACKPORTED_BCMA_PFLASH
-- tristate
-- default BCMA_PFLASH
--config BACKPORTED_BCMA_SFLASH
-- tristate
-- default BCMA_SFLASH
--config BACKPORTED_BCMA_NFLASH
-- tristate
-- default BCMA_NFLASH
--config BACKPORTED_BCMA_DRIVER_GMAC_CMN
-- tristate
-- default BCMA_DRIVER_GMAC_CMN
--config BACKPORTED_BCMA_DRIVER_GPIO
-- tristate
-- default BCMA_DRIVER_GPIO
--config BACKPORTED_BCMA_DEBUG
-- tristate
-- default BCMA_DEBUG
- config BACKPORTED_USB_ACM
- tristate
- default USB_ACM
---- a/Kconfig.sources
-+++ b/Kconfig.sources
-@@ -10,9 +10,6 @@ source "$BACKPORT_DIR/drivers/soc/qcom/K
- source "$BACKPORT_DIR/drivers/net/wireless/Kconfig"
- source "$BACKPORT_DIR/drivers/net/usb/Kconfig"
-
--source "$BACKPORT_DIR/drivers/ssb/Kconfig"
--source "$BACKPORT_DIR/drivers/bcma/Kconfig"
--
- source "$BACKPORT_DIR/drivers/usb/class/Kconfig"
-
- source "$BACKPORT_DIR/drivers/staging/Kconfig"
---- a/Makefile.kernel
-+++ b/Makefile.kernel
-@@ -42,8 +42,6 @@ obj-$(CPTCFG_QRTR) += net/qrtr/
- obj-$(CPTCFG_QCOM_QMI_HELPERS) += drivers/soc/qcom/
- obj-$(CPTCFG_MHI_BUS) += drivers/bus/mhi/
- obj-$(CPTCFG_WLAN) += drivers/net/wireless/
--obj-$(CPTCFG_SSB) += drivers/ssb/
--obj-$(CPTCFG_BCMA) += drivers/bcma/
- obj-$(CPTCFG_USB_NET_RNDIS_WLAN) += drivers/net/usb/
-
- obj-$(CPTCFG_USB_WDM) += drivers/usb/class/
+++ /dev/null
---- /dev/null
-+++ b/backport-include/linux/bcma/bcma_driver_chipcommon.h
-@@ -0,0 +1,10 @@
-+#ifndef __BACKPORT_BCMA_DRIVER_CHIPCOMMON_H
-+#define __BACKPORT_BCMA_DRIVER_CHIPCOMMON_H
-+
-+#include_next <linux/bcma/bcma_driver_chipcommon.h>
-+
-+#ifndef BCMA_CC_SROM_CONTROL_OTP_PRESENT
-+#define BCMA_CC_SROM_CONTROL_OTP_PRESENT 0x00000020
-+#endif
-+
-+#endif
+ depends on MHI_BUS
+ depends on QRTR
+ depends on QRTR_MHI
+ select PCI_PWRCTL_PWRSEQ if HAVE_PWRCTL
help
This module adds support for PCIE bus
-
--- a/local-symbols
+++ b/local-symbols
@@ -59,14 +59,6 @@ MAC80211_MESH_PS_DEBUG=
--- /dev/null
+--- a/drivers/bus/mhi/host/trace.h
++++ b/drivers/bus/mhi/host/trace.h
+@@ -103,7 +103,7 @@ TRACE_EVENT(mhi_gen_tre,
+ ),
+
+ TP_fast_assign(
+- __assign_str(name);
++ __assign_str(name, mhi_cntrl->mhi_dev->name);
+ __entry->ch_num = mhi_chan->chan;
+ __entry->wp = mhi_tre;
+ __entry->tre_ptr = mhi_tre->ptr;
+@@ -131,7 +131,7 @@ TRACE_EVENT(mhi_intvec_states,
+ ),
+
+ TP_fast_assign(
+- __assign_str(name);
++ __assign_str(name, mhi_cntrl->mhi_dev->name);
+ __entry->local_ee = mhi_cntrl->ee;
+ __entry->state = mhi_cntrl->dev_state;
+ __entry->dev_ee = dev_ee;
+@@ -158,7 +158,7 @@ TRACE_EVENT(mhi_tryset_pm_state,
+ ),
+
+ TP_fast_assign(
+- __assign_str(name);
++ __assign_str(name, mhi_cntrl->mhi_dev->name);
+ if (pm_state)
+ pm_state = __fls(pm_state);
+ __entry->pm_state = pm_state;
+@@ -184,7 +184,7 @@ DECLARE_EVENT_CLASS(mhi_process_event_ri
+ ),
+
+ TP_fast_assign(
+- __assign_str(name);
++ __assign_str(name, mhi_cntrl->mhi_dev->name);
+ __entry->rp = rp;
+ __entry->ptr = rp->ptr;
+ __entry->dword0 = rp->dword[0];
+@@ -226,7 +226,7 @@ DECLARE_EVENT_CLASS(mhi_update_channel_s
+ ),
+
+ TP_fast_assign(
+- __assign_str(name);
++ __assign_str(name, mhi_cntrl->mhi_dev->name);
+ __entry->ch_num = mhi_chan->chan;
+ __entry->state = state;
+ __entry->reason = reason;
+@@ -265,7 +265,7 @@ TRACE_EVENT(mhi_pm_st_transition,
+ ),
+
+ TP_fast_assign(
+- __assign_str(name);
++ __assign_str(name, mhi_cntrl->mhi_dev->name);
+ __entry->state = state;
+ ),
+
+--- a/drivers/net/wireless/ath/ath10k/trace.h
++++ b/drivers/net/wireless/ath/ath10k/trace.h
+@@ -55,8 +55,8 @@ DECLARE_EVENT_CLASS(ath10k_log_event,
+ __vstring(msg, vaf->fmt, vaf->va)
+ ),
+ TP_fast_assign(
+- __assign_str(device);
+- __assign_str(driver);
++ __assign_str(device, dev_name(ar->dev));
++ __assign_str(driver, dev_driver_string(ar->dev));
+ __assign_vstr(msg, vaf->fmt, vaf->va);
+ ),
+ TP_printk(
+@@ -92,8 +92,8 @@ TRACE_EVENT(ath10k_log_dbg,
+ __vstring(msg, vaf->fmt, vaf->va)
+ ),
+ TP_fast_assign(
+- __assign_str(device);
+- __assign_str(driver);
++ __assign_str(device, dev_name(ar->dev));
++ __assign_str(driver, dev_driver_string(ar->dev));
+ __entry->level = level;
+ __assign_vstr(msg, vaf->fmt, vaf->va);
+ ),
+@@ -121,10 +121,10 @@ TRACE_EVENT(ath10k_log_dbg_dump,
+ ),
+
+ TP_fast_assign(
+- __assign_str(device);
+- __assign_str(driver);
+- __assign_str(msg);
+- __assign_str(prefix);
++ __assign_str(device, dev_name(ar->dev));
++ __assign_str(driver, dev_driver_string(ar->dev));
++ __assign_str(msg, msg);
++ __assign_str(prefix, prefix);
+ __entry->buf_len = buf_len;
+ memcpy(__get_dynamic_array(buf), buf, buf_len);
+ ),
+@@ -152,8 +152,8 @@ TRACE_EVENT(ath10k_wmi_cmd,
+ ),
+
+ TP_fast_assign(
+- __assign_str(device);
+- __assign_str(driver);
++ __assign_str(device, dev_name(ar->dev));
++ __assign_str(driver, dev_driver_string(ar->dev));
+ __entry->id = id;
+ __entry->buf_len = buf_len;
+ memcpy(__get_dynamic_array(buf), buf, buf_len);
+@@ -182,8 +182,8 @@ TRACE_EVENT(ath10k_wmi_event,
+ ),
+
+ TP_fast_assign(
+- __assign_str(device);
+- __assign_str(driver);
++ __assign_str(device, dev_name(ar->dev));
++ __assign_str(driver, dev_driver_string(ar->dev));
+ __entry->id = id;
+ __entry->buf_len = buf_len;
+ memcpy(__get_dynamic_array(buf), buf, buf_len);
+@@ -211,8 +211,8 @@ TRACE_EVENT(ath10k_htt_stats,
+ ),
+
+ TP_fast_assign(
+- __assign_str(device);
+- __assign_str(driver);
++ __assign_str(device, dev_name(ar->dev));
++ __assign_str(driver, dev_driver_string(ar->dev));
+ __entry->buf_len = buf_len;
+ memcpy(__get_dynamic_array(buf), buf, buf_len);
+ ),
+@@ -239,8 +239,8 @@ TRACE_EVENT(ath10k_wmi_dbglog,
+ ),
+
+ TP_fast_assign(
+- __assign_str(device);
+- __assign_str(driver);
++ __assign_str(device, dev_name(ar->dev));
++ __assign_str(driver, dev_driver_string(ar->dev));
+ __entry->hw_type = ar->hw_rev;
+ __entry->buf_len = buf_len;
+ memcpy(__get_dynamic_array(buf), buf, buf_len);
+@@ -269,8 +269,8 @@ TRACE_EVENT(ath10k_htt_pktlog,
+ ),
+
+ TP_fast_assign(
+- __assign_str(device);
+- __assign_str(driver);
++ __assign_str(device, dev_name(ar->dev));
++ __assign_str(driver, dev_driver_string(ar->dev));
+ __entry->hw_type = ar->hw_rev;
+ __entry->buf_len = buf_len;
+ memcpy(__get_dynamic_array(pktlog), buf, buf_len);
+@@ -301,8 +301,8 @@ TRACE_EVENT(ath10k_htt_tx,
+ ),
+
+ TP_fast_assign(
+- __assign_str(device);
+- __assign_str(driver);
++ __assign_str(device, dev_name(ar->dev));
++ __assign_str(driver, dev_driver_string(ar->dev));
+ __entry->msdu_id = msdu_id;
+ __entry->msdu_len = msdu_len;
+ __entry->vdev_id = vdev_id;
+@@ -332,8 +332,8 @@ TRACE_EVENT(ath10k_txrx_tx_unref,
+ ),
+
+ TP_fast_assign(
+- __assign_str(device);
+- __assign_str(driver);
++ __assign_str(device, dev_name(ar->dev));
++ __assign_str(driver, dev_driver_string(ar->dev));
+ __entry->msdu_id = msdu_id;
+ ),
+
+@@ -358,8 +358,8 @@ DECLARE_EVENT_CLASS(ath10k_hdr_event,
+ ),
+
+ TP_fast_assign(
+- __assign_str(device);
+- __assign_str(driver);
++ __assign_str(device, dev_name(ar->dev));
++ __assign_str(driver, dev_driver_string(ar->dev));
+ __entry->len = ath10k_frm_hdr_len(data, len);
+ memcpy(__get_dynamic_array(data), data, __entry->len);
+ ),
+@@ -386,8 +386,8 @@ DECLARE_EVENT_CLASS(ath10k_payload_event
+ ),
+
+ TP_fast_assign(
+- __assign_str(device);
+- __assign_str(driver);
++ __assign_str(device, dev_name(ar->dev));
++ __assign_str(driver, dev_driver_string(ar->dev));
+ __entry->len = len - ath10k_frm_hdr_len(data, len);
+ memcpy(__get_dynamic_array(payload),
+ data + ath10k_frm_hdr_len(data, len), __entry->len);
+@@ -435,8 +435,8 @@ TRACE_EVENT(ath10k_htt_rx_desc,
+ ),
+
+ TP_fast_assign(
+- __assign_str(device);
+- __assign_str(driver);
++ __assign_str(device, dev_name(ar->dev));
++ __assign_str(driver, dev_driver_string(ar->dev));
+ __entry->hw_type = ar->hw_rev;
+ __entry->len = len;
+ memcpy(__get_dynamic_array(rxdesc), data, len);
+@@ -472,8 +472,8 @@ TRACE_EVENT(ath10k_wmi_diag_container,
+ ),
+
+ TP_fast_assign(
+- __assign_str(device);
+- __assign_str(driver);
++ __assign_str(device, dev_name(ar->dev));
++ __assign_str(driver, dev_driver_string(ar->dev));
+ __entry->type = type;
+ __entry->timestamp = timestamp;
+ __entry->code = code;
+@@ -505,8 +505,8 @@ TRACE_EVENT(ath10k_wmi_diag,
+ ),
+
+ TP_fast_assign(
+- __assign_str(device);
+- __assign_str(driver);
++ __assign_str(device, dev_name(ar->dev));
++ __assign_str(driver, dev_driver_string(ar->dev));
+ __entry->len = len;
+ memcpy(__get_dynamic_array(data), data, len);
+ ),
+--- a/drivers/net/wireless/ath/ath11k/trace.h
++++ b/drivers/net/wireless/ath/ath11k/trace.h
+@@ -48,8 +48,8 @@ TRACE_EVENT(ath11k_htt_pktlog,
+ ),
+
+ TP_fast_assign(
+- __assign_str(device);
+- __assign_str(driver);
++ __assign_str(device, dev_name(ar->ab->dev));
++ __assign_str(driver, dev_driver_string(ar->ab->dev));
+ __entry->buf_len = buf_len;
+ __entry->pktlog_checksum = pktlog_checksum;
+ memcpy(__get_dynamic_array(pktlog), buf, buf_len);
+@@ -77,8 +77,8 @@ TRACE_EVENT(ath11k_htt_ppdu_stats,
+ ),
+
+ TP_fast_assign(
+- __assign_str(device);
+- __assign_str(driver);
++ __assign_str(device, dev_name(ar->ab->dev));
++ __assign_str(driver, dev_driver_string(ar->ab->dev));
+ __entry->len = len;
+ memcpy(__get_dynamic_array(ppdu), data, len);
+ ),
+@@ -105,8 +105,8 @@ TRACE_EVENT(ath11k_htt_rxdesc,
+ ),
+
+ TP_fast_assign(
+- __assign_str(device);
+- __assign_str(driver);
++ __assign_str(device, dev_name(ar->ab->dev));
++ __assign_str(driver, dev_driver_string(ar->ab->dev));
+ __entry->len = len;
+ __entry->log_type = log_type;
+ memcpy(__get_dynamic_array(rxdesc), data, len);
+@@ -130,8 +130,8 @@ DECLARE_EVENT_CLASS(ath11k_log_event,
+ __vstring(msg, vaf->fmt, vaf->va)
+ ),
+ TP_fast_assign(
+- __assign_str(device);
+- __assign_str(driver);
++ __assign_str(device, dev_name(ab->dev));
++ __assign_str(driver, dev_driver_string(ab->dev));
+ __assign_vstr(msg, vaf->fmt, vaf->va);
+ ),
+ TP_printk(
+@@ -171,8 +171,8 @@ TRACE_EVENT(ath11k_wmi_cmd,
+ ),
+
+ TP_fast_assign(
+- __assign_str(device);
+- __assign_str(driver);
++ __assign_str(device, dev_name(ab->dev));
++ __assign_str(driver, dev_driver_string(ab->dev));
+ __entry->id = id;
+ __entry->buf_len = buf_len;
+ memcpy(__get_dynamic_array(buf), buf, buf_len);
+@@ -201,8 +201,8 @@ TRACE_EVENT(ath11k_wmi_event,
+ ),
+
+ TP_fast_assign(
+- __assign_str(device);
+- __assign_str(driver);
++ __assign_str(device, dev_name(ab->dev));
++ __assign_str(driver, dev_driver_string(ab->dev));
+ __entry->id = id;
+ __entry->buf_len = buf_len;
+ memcpy(__get_dynamic_array(buf), buf, buf_len);
+@@ -230,8 +230,8 @@ TRACE_EVENT(ath11k_log_dbg,
+ ),
+
+ TP_fast_assign(
+- __assign_str(device);
+- __assign_str(driver);
++ __assign_str(device, dev_name(ab->dev));
++ __assign_str(driver, dev_driver_string(ab->dev));
+ __entry->level = level;
+ WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg),
+ ATH11K_MSG_MAX, vaf->fmt,
+@@ -262,10 +262,10 @@ TRACE_EVENT(ath11k_log_dbg_dump,
+ ),
+
+ TP_fast_assign(
+- __assign_str(device);
+- __assign_str(driver);
+- __assign_str(msg);
+- __assign_str(prefix);
++ __assign_str(device, dev_name(ab->dev));
++ __assign_str(driver, dev_driver_string(ab->dev));
++ __assign_str(msg, msg);
++ __assign_str(prefix, prefix);
+ __entry->buf_len = buf_len;
+ memcpy(__get_dynamic_array(buf), buf, buf_len);
+ ),
+@@ -292,8 +292,8 @@ TRACE_EVENT(ath11k_wmi_diag,
+ ),
+
+ TP_fast_assign(
+- __assign_str(device);
+- __assign_str(driver);
++ __assign_str(device, dev_name(ab->dev));
++ __assign_str(driver, dev_driver_string(ab->dev));
+ __entry->len = len;
+ memcpy(__get_dynamic_array(data), data, len);
+ ),
+@@ -318,8 +318,8 @@ TRACE_EVENT(ath11k_ps_timekeeper,
+ __field(u32, peer_ps_timestamp)
+ ),
+
+- TP_fast_assign(__assign_str(device);
+- __assign_str(driver);
++ TP_fast_assign(__assign_str(device, dev_name(ar->ab->dev));
++ __assign_str(driver, dev_driver_string(ar->ab->dev));
+ memcpy(__get_dynamic_array(peer_addr), peer_addr,
+ ETH_ALEN);
+ __entry->peer_ps_state = peer_ps_state;
+--- a/drivers/net/wireless/ath/ath12k/trace.h
++++ b/drivers/net/wireless/ath/ath12k/trace.h
+@@ -36,8 +36,8 @@ TRACE_EVENT(ath12k_htt_pktlog,
+ ),
+
+ TP_fast_assign(
+- __assign_str(device);
+- __assign_str(driver);
++ __assign_str(device, dev_name(ar->ab->dev));
++ __assign_str(driver, dev_driver_string(ar->ab->dev));
+ __entry->buf_len = buf_len;
+ __entry->pktlog_checksum = pktlog_checksum;
+ memcpy(__get_dynamic_array(pktlog), buf, buf_len);
+@@ -73,8 +73,8 @@ TRACE_EVENT(ath12k_htt_ppdu_stats,
+ ),
+
+ TP_fast_assign(
+- __assign_str(device);
+- __assign_str(driver);
++ __assign_str(device, dev_name(ar->ab->dev));
++ __assign_str(driver, dev_driver_string(ar->ab->dev));
+ __entry->len = len;
+ __entry->info = ar->pdev->timestamp.info;
+ __entry->sync_tstmp_lo_us = ar->pdev->timestamp.sync_timestamp_hi_us;
+@@ -117,8 +117,8 @@ TRACE_EVENT(ath12k_htt_rxdesc,
+ ),
+
+ TP_fast_assign(
+- __assign_str(device);
+- __assign_str(driver);
++ __assign_str(device, dev_name(ar->ab->dev));
++ __assign_str(driver, dev_driver_string(ar->ab->dev));
+ __entry->len = len;
+ __entry->type = type;
+ __entry->info = ar->pdev->timestamp.info;
+@@ -153,8 +153,8 @@ TRACE_EVENT(ath12k_wmi_diag,
+ ),
+
+ TP_fast_assign(
+- __assign_str(device);
+- __assign_str(driver);
++ __assign_str(device, dev_name(ab->dev));
++ __assign_str(driver, dev_driver_string(ab->dev));
+ __entry->len = len;
+ memcpy(__get_dynamic_array(data), data, len);
+ ),
+--- a/drivers/net/wireless/ath/ath6kl/trace.h
++++ b/drivers/net/wireless/ath/ath6kl/trace.h
+@@ -304,8 +304,8 @@ TRACE_EVENT(ath6kl_log_dbg_dump,
+ ),
+
+ TP_fast_assign(
+- __assign_str(msg);
+- __assign_str(prefix);
++ __assign_str(msg, msg);
++ __assign_str(prefix, prefix);
+ __entry->buf_len = buf_len;
+ memcpy(__get_dynamic_array(buf), buf, buf_len);
+ ),
+--- a/drivers/net/wireless/ath/trace.h
++++ b/drivers/net/wireless/ath/trace.h
+@@ -44,8 +44,8 @@ TRACE_EVENT(ath_log,
+ ),
+
+ TP_fast_assign(
+- __assign_str(device);
+- __assign_str(driver);
++ __assign_str(device, wiphy_name(wiphy));
++ __assign_str(driver, KBUILD_MODNAME);
+ __assign_vstr(msg, vaf->fmt, vaf->va);
+ ),
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/tracepoint.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/tracepoint.h
+@@ -41,7 +41,7 @@ TRACE_EVENT(brcmf_err,
+ __vstring(msg, vaf->fmt, vaf->va)
+ ),
+ TP_fast_assign(
+- __assign_str(func);
++ __assign_str(func, func);
+ __assign_vstr(msg, vaf->fmt, vaf->va);
+ ),
+ TP_printk("%s: %s", __get_str(func), __get_str(msg))
+@@ -57,7 +57,7 @@ TRACE_EVENT(brcmf_dbg,
+ ),
+ TP_fast_assign(
+ __entry->level = level;
+- __assign_str(func);
++ __assign_str(func, func);
+ __assign_vstr(msg, vaf->fmt, vaf->va);
+ ),
+ TP_printk("%s: %s", __get_str(func), __get_str(msg))
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/brcms_trace_brcmsmac.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/brcms_trace_brcmsmac.h
+@@ -81,7 +81,7 @@ TRACE_EVENT(brcms_macintstatus,
+ __field(u32, mask)
+ ),
+ TP_fast_assign(
+- __assign_str(dev);
++ __assign_str(dev, dev_name(dev));
+ __entry->in_isr = in_isr;
+ __entry->macintstatus = macintstatus;
+ __entry->mask = mask;
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/brcms_trace_brcmsmac_msg.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/brcms_trace_brcmsmac_msg.h
+@@ -71,7 +71,7 @@ TRACE_EVENT(brcms_dbg,
+ ),
+ TP_fast_assign(
+ __entry->level = level;
+- __assign_str(func);
++ __assign_str(func, func);
+ __assign_vstr(msg, vaf->fmt, vaf->va);
+ ),
+ TP_printk("%s: %s", __get_str(func), __get_str(msg))
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/brcms_trace_brcmsmac_tx.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/brcms_trace_brcmsmac_tx.h
+@@ -31,7 +31,7 @@ TRACE_EVENT(brcms_txdesc,
+ __dynamic_array(u8, txh, txh_len)
+ ),
+ TP_fast_assign(
+- __assign_str(dev);
++ __assign_str(dev, dev_name(dev));
+ memcpy(__get_dynamic_array(txh), txh, txh_len);
+ ),
+ TP_printk("[%s] txdesc", __get_str(dev))
+@@ -54,7 +54,7 @@ TRACE_EVENT(brcms_txstatus,
+ __field(u16, ackphyrxsh)
+ ),
+ TP_fast_assign(
+- __assign_str(dev);
++ __assign_str(dev, dev_name(dev));
+ __entry->framelen = framelen;
+ __entry->frameid = frameid;
+ __entry->status = status;
+@@ -85,7 +85,7 @@ TRACE_EVENT(brcms_ampdu_session,
+ __field(u16, dma_len)
+ ),
+ TP_fast_assign(
+- __assign_str(dev);
++ __assign_str(dev, dev_name(dev));
+ __entry->max_ampdu_len = max_ampdu_len;
+ __entry->max_ampdu_frames = max_ampdu_frames;
+ __entry->ampdu_len = ampdu_len;
+--- a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-msg.h
++++ b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace-msg.h
+@@ -57,7 +57,7 @@ TRACE_EVENT(iwlwifi_dbg,
+ ),
+ TP_fast_assign(
+ __entry->level = level;
+- __assign_str(function);
++ __assign_str(function, function);
+ __assign_vstr(msg, vaf->fmt, vaf->va);
+ ),
+ TP_printk("%s", __get_str(msg))
+--- a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace.h
++++ b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace.h
+@@ -87,7 +87,7 @@ static inline void trace_ ## name(proto)
+ #endif
+
+ #define DEV_ENTRY __string(dev, dev_name(dev))
+-#define DEV_ASSIGN __assign_str(dev)
++#define DEV_ASSIGN __assign_str(dev, dev_name(dev))
+
+ #include "iwl-devtrace-io.h"
+ #include "iwl-devtrace-ucode.h"
+--- a/include/trace/events/qrtr.h
++++ b/include/trace/events/qrtr.h
+@@ -102,7 +102,7 @@ TRACE_EVENT(qrtr_ns_message,
+ ),
+
+ TP_fast_assign(
+- __assign_str(ctrl_pkt_str);
++ __assign_str(ctrl_pkt_str, ctrl_pkt_str);
+ __entry->sq_node = sq_node;
+ __entry->sq_port = sq_port;
+ ),
+--- a/net/mac80211/trace.h
++++ b/net/mac80211/trace.h
+@@ -33,7 +33,7 @@
+ __string(vif_name, sdata->name)
+ #define VIF_ASSIGN __entry->vif_type = sdata->vif.type; __entry->sdata = sdata; \
+ __entry->p2p = sdata->vif.p2p; \
+- __assign_str(vif_name)
++ __assign_str(vif_name, sdata->name)
+ #define VIF_PR_FMT " vif:%s(%d%s)"
+ #define VIF_PR_ARG __get_str(vif_name), __entry->vif_type, __entry->p2p ? "/p2p" : ""
+
+--- a/net/wireless/trace.h
++++ b/net/wireless/trace.h
+@@ -446,7 +446,7 @@ TRACE_EVENT(rdev_add_virtual_intf,
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+- __assign_str(vir_intf_name);
++ __assign_str(vir_intf_name, name ? name : "<noname>");
+ __entry->type = type;
+ ),
+ TP_printk(WIPHY_PR_FMT ", virtual intf name: %s, type: %d",
--- /dev/null
+--- a/drivers/net/wireless/ath/ath10k/snoc.c
++++ b/drivers/net/wireless/ath/ath10k/snoc.c
+@@ -1635,10 +1635,10 @@ static int ath10k_fw_init(struct ath10k
+
+ ar_snoc->fw.dev = &pdev->dev;
+
+- iommu_dom = iommu_paging_domain_alloc(ar_snoc->fw.dev);
+- if (IS_ERR(iommu_dom)) {
++ iommu_dom = iommu_domain_alloc(&platform_bus_type);
++ if (!iommu_dom) {
+ ath10k_err(ar, "failed to allocate iommu domain\n");
+- ret = PTR_ERR(iommu_dom);
++ ret = -ENOMEM;
+ goto err_unregister;
+ }
+
+--- a/drivers/net/wireless/ath/ath11k/ahb.c
++++ b/drivers/net/wireless/ath/ath11k/ahb.c
+@@ -1031,10 +1031,10 @@ static int ath11k_ahb_fw_resources_init(
+
+ ab_ahb->fw.dev = &pdev->dev;
+
+- iommu_dom = iommu_paging_domain_alloc(ab_ahb->fw.dev);
+- if (IS_ERR(iommu_dom)) {
++ iommu_dom = iommu_domain_alloc(&platform_bus_type);
++ if (!iommu_dom) {
+ ath11k_err(ab, "failed to allocate iommu domain\n");
+- ret = PTR_ERR(iommu_dom);
++ ret = -ENOMEM;
+ goto err_unregister;
+ }
+
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c
-@@ -689,13 +689,23 @@ static void iwl_mvm_thermal_zone_registe
+@@ -638,8 +638,13 @@ static int iwl_mvm_tzone_get_temp(struct
+ return 0;
+ }
+
++#if LINUX_VERSION_IS_GEQ(6,11,0)
+ static int iwl_mvm_tzone_set_trip_temp(struct thermal_zone_device *device,
+ const struct thermal_trip *trip, int temp)
++#else
++static int iwl_mvm_tzone_set_trip_temp(struct thermal_zone_device *device,
++ int trip, int temp)
++#endif
+ {
+ struct iwl_mvm *mvm = thermal_zone_device_priv(device);
+
+@@ -682,13 +687,23 @@ static void iwl_mvm_thermal_zone_registe
for (i = 0 ; i < IWL_MAX_DTS_TRIPS; i++) {
mvm->tz_device.trips[i].temperature = THERMAL_TEMP_INVALID;
mvm->tz_device.trips[i].type = THERMAL_TRIP_PASSIVE;
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
-@@ -16383,9 +16383,14 @@ static u32 nl80211_internal_flags[] = {
+@@ -16529,9 +16529,14 @@ static u32 nl80211_internal_flags[] = {
#undef SELECTOR
};
{
struct cfg80211_registered_device *rdev = NULL;
struct wireless_dev *wdev = NULL;
-@@ -16485,9 +16490,14 @@ out_unlock:
+@@ -16631,9 +16636,14 @@ out_unlock:
return err;
}
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
-@@ -1581,7 +1581,11 @@ static int brcmf_usb_reset_device(struct
+@@ -1574,7 +1574,11 @@ static int brcmf_usb_reset_device(struct
void brcmf_usb_exit(void)
{
--- a/drivers/net/wireless/marvell/mwl8k.c
+++ b/drivers/net/wireless/marvell/mwl8k.c
-@@ -5707,6 +5707,7 @@ MODULE_FIRMWARE("mwl8k/fmimage_8366.fw")
+@@ -5709,6 +5709,7 @@ MODULE_FIRMWARE("mwl8k/fmimage_8366.fw")
MODULE_FIRMWARE(MWL8K_8366_AP_FW(MWL8K_8366_AP_FW_API));
static const struct pci_device_id mwl8k_pci_id_table[] = {
--- a/drivers/net/wireless/marvell/mwl8k.c
+++ b/drivers/net/wireless/marvell/mwl8k.c
-@@ -6293,6 +6293,8 @@ static int mwl8k_probe(struct pci_dev *p
+@@ -6295,6 +6295,8 @@ static int mwl8k_probe(struct pci_dev *p
priv->running_bsses = 0;
return rc;
err_stop_firmware:
-@@ -6326,8 +6328,6 @@ static void mwl8k_remove(struct pci_dev
+@@ -6328,8 +6330,6 @@ static void mwl8k_remove(struct pci_dev
return;
priv = hw->priv;
--- a/local-symbols
+++ b/local-symbols
-@@ -334,6 +334,7 @@ RT2X00_LIB_FIRMWARE=
+@@ -339,6 +339,7 @@ RT2X00_LIB_FIRMWARE=
RT2X00_LIB_CRYPTO=
RT2X00_LIB_LEDS=
RT2X00_LIB_DEBUGFS=
.drv_init_registers = rt2800mmio_init_registers,
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
-@@ -703,6 +703,7 @@ enum rt2x00_capability_flags {
+@@ -693,6 +693,7 @@ enum rt2x00_capability_flags {
REQUIRE_HT_TX_DESC,
REQUIRE_PS_AUTOWAKE,
REQUIRE_DELAYED_RFKILL,
num_rates += 4;
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
-@@ -408,6 +408,7 @@ struct hw_mode_spec {
+@@ -398,6 +398,7 @@ struct hw_mode_spec {
unsigned int supported_bands;
#define SUPPORT_BAND_2GHZ 0x00000001
#define SUPPORT_BAND_5GHZ 0x00000002
#include <linux/rt2x00_platform.h>
#include <net/mac80211.h>
-@@ -1027,6 +1028,11 @@ struct rt2x00_dev {
+@@ -1017,6 +1018,11 @@ struct rt2x00_dev {
/* Clock for System On Chip devices. */
struct clk *clk;
+++ /dev/null
-From 25eaef533bf3ccc6fee5067aac16f41f280e343e Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Marcin=20=C5=9Alusarz?= <mslusarz@renau.com>
-Date: Tue, 28 May 2024 13:02:46 +0200
-Subject: [PATCH] wifi: rtw88: usb: schedule rx work after everything is set up
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-[ Upstream commit adc539784c98a7cc602cbf557debfc2e7b9be8b3 ]
-
-Right now it's possible to hit NULL pointer dereference in
-rtw_rx_fill_rx_status on hw object and/or its fields because
-initialization routine can start getting USB replies before
-rtw_dev is fully setup.
-
-The stack trace looks like this:
-
-rtw_rx_fill_rx_status
-rtw8821c_query_rx_desc
-rtw_usb_rx_handler
-...
-queue_work
-rtw_usb_read_port_complete
-...
-usb_submit_urb
-rtw_usb_rx_resubmit
-rtw_usb_init_rx
-rtw_usb_probe
-
-So while we do the async stuff rtw_usb_probe continues and calls
-rtw_register_hw, which does all kinds of initialization (e.g.
-via ieee80211_register_hw) that rtw_rx_fill_rx_status relies on.
-
-Fix this by moving the first usb_submit_urb after everything
-is set up.
-
-For me, this bug manifested as:
-[ 8.893177] rtw_8821cu 1-1:1.2: band wrong, packet dropped
-[ 8.910904] rtw_8821cu 1-1:1.2: hw->conf.chandef.chan NULL in rtw_rx_fill_rx_status
-because I'm using Larry's backport of rtw88 driver with the NULL
-checks in rtw_rx_fill_rx_status.
-
-Link: https://lore.kernel.org/linux-wireless/CA+shoWQ7P49jhQasofDcTdQhiuarPTjYEDa--NiVVx494WcuQw@mail.gmail.com/
-Signed-off-by: Marcin Ślusarz <mslusarz@renau.com>
-Cc: Tim K <tpkuester@gmail.com>
-Cc: Ping-Ke Shih <pkshih@realtek.com>
-Cc: Larry Finger <Larry.Finger@lwfinger.net>
-Cc: Kalle Valo <kvalo@kernel.org>
-Cc: linux-wireless@vger.kernel.org
-Cc: linux-kernel@vger.kernel.org
-Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
-Link: https://patch.msgid.link/20240528110246.477321-1-marcin.slusarz@gmail.com
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- drivers/net/wireless/realtek/rtw88/usb.c | 13 ++++++++++---
- 1 file changed, 10 insertions(+), 3 deletions(-)
-
---- a/drivers/net/wireless/realtek/rtw88/usb.c
-+++ b/drivers/net/wireless/realtek/rtw88/usb.c
-@@ -740,7 +740,6 @@ static struct rtw_hci_ops rtw_usb_ops =
- static int rtw_usb_init_rx(struct rtw_dev *rtwdev)
- {
- struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
-- int i;
-
- rtwusb->rxwq = create_singlethread_workqueue("rtw88_usb: rx wq");
- if (!rtwusb->rxwq) {
-@@ -752,13 +751,19 @@ static int rtw_usb_init_rx(struct rtw_de
-
- INIT_WORK(&rtwusb->rx_work, rtw_usb_rx_handler);
-
-+ return 0;
-+}
-+
-+static void rtw_usb_setup_rx(struct rtw_dev *rtwdev)
-+{
-+ struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
-+ int i;
-+
- for (i = 0; i < RTW_USB_RXCB_NUM; i++) {
- struct rx_usb_ctrl_block *rxcb = &rtwusb->rx_cb[i];
-
- rtw_usb_rx_resubmit(rtwusb, rxcb);
- }
--
-- return 0;
- }
-
- static void rtw_usb_deinit_rx(struct rtw_dev *rtwdev)
-@@ -895,6 +900,8 @@ int rtw_usb_probe(struct usb_interface *
- goto err_destroy_rxwq;
- }
-
-+ rtw_usb_setup_rx(rtwdev);
-+
- return 0;
-
- err_destroy_rxwq:
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
-@@ -1647,12 +1647,6 @@ static int ieee80211_stop_ap(struct wiph
+@@ -1649,12 +1649,6 @@ static int ieee80211_stop_ap(struct wiph
__sta_info_flush(sdata, true, link_id);
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
-@@ -1564,24 +1564,6 @@ int ieee80211_register_hw(struct ieee802
+@@ -1581,24 +1581,6 @@ int ieee80211_register_hw(struct ieee802
ieee80211_check_wbrf_support(local);
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
-@@ -2844,6 +2844,8 @@ static int ieee80211_scan(struct wiphy *
+@@ -2863,6 +2863,8 @@ static int ieee80211_scan(struct wiphy *
*/
fallthrough;
case NL80211_IFTYPE_AP:
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
-@@ -101,6 +101,8 @@ ieee80211_sta_keep_active(struct sta_inf
+@@ -103,6 +103,8 @@ ieee80211_sta_keep_active(struct sta_inf
return time_before_eq(jiffies, sta->airtime[ac].last_active + HZ / 10);
}
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
-@@ -4082,7 +4082,7 @@ struct ieee80211_txq *ieee80211_next_txq
+@@ -4081,7 +4081,7 @@ struct ieee80211_txq *ieee80211_next_txq
if (deficit < 0)
sta->airtime[txqi->txq.ac].deficit +=
if (deficit < 0 || !aql_check) {
list_move_tail(&txqi->schedule_order,
-@@ -4225,7 +4225,8 @@ bool ieee80211_txq_may_transmit(struct i
+@@ -4224,7 +4224,8 @@ bool ieee80211_txq_may_transmit(struct i
}
sta = container_of(iter->txq.sta, struct sta_info, sta);
if (ieee80211_sta_deficit(sta, ac) < 0)
list_move_tail(&iter->schedule_order, &local->active_txqs[ac]);
}
-@@ -4233,7 +4234,7 @@ bool ieee80211_txq_may_transmit(struct i
+@@ -4232,7 +4233,7 @@ bool ieee80211_txq_may_transmit(struct i
if (sta->airtime[ac].deficit >= 0)
goto out;
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Wed, 3 Jul 2024 12:10:01 +0200
-Subject: [PATCH] wifi: mac80211: clear vif drv_priv after calling
- remove_interface
-
-Avoid reusing stale driver data when an interface is brought down and up
-again. In order to avoid having to duplicate the memset in every single
-driver, do it here.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/iface.c
-+++ b/net/mac80211/iface.c
-@@ -693,8 +693,12 @@ static void ieee80211_do_stop(struct iee
-
- fallthrough;
- default:
-- if (going_down)
-- drv_remove_interface(local, sdata);
-+ if (!going_down)
-+ break;
-+ drv_remove_interface(local, sdata);
-+
-+ /* Clear private driver data to prevent reuse */
-+ memset(sdata->vif.drv_priv, 0, local->hw.vif_data_size);
- }
-
- ieee80211_recalc_ps(local);
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
-@@ -189,6 +189,8 @@ enum ieee80211_channel_flags {
+@@ -187,6 +187,8 @@ enum ieee80211_channel_flags {
* @dfs_state: current state of this channel. Only relevant if radar is required
* on this channel.
* @dfs_state_entered: timestamp (jiffies) when the dfs state was entered.
* @dfs_cac_ms: DFS CAC time in milliseconds, this is valid for DFS channels.
* @psd: power spectral density (in dBm)
*/
-@@ -206,6 +208,7 @@ struct ieee80211_channel {
+@@ -204,6 +206,7 @@ struct ieee80211_channel {
int orig_mag, orig_mpwr;
enum nl80211_dfs_state dfs_state;
unsigned long dfs_state_entered;
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
-@@ -560,6 +560,8 @@ static void cfg80211_set_chans_dfs_state
+@@ -598,6 +598,8 @@ static void cfg80211_set_chans_dfs_state
c->dfs_state = dfs_state;
c->dfs_state_entered = jiffies;
}
}
-@@ -1049,6 +1051,49 @@ static bool cfg80211_get_chans_dfs_avail
+@@ -1087,6 +1089,49 @@ static bool cfg80211_get_chans_dfs_avail
return true;
}
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
-@@ -3416,6 +3416,7 @@ enum wiphy_params_flags {
+@@ -3423,6 +3423,7 @@ enum wiphy_params_flags {
/* The per TXQ device queue limit in airtime */
#define IEEE80211_DEFAULT_AQL_TXQ_LIMIT_L 5000
#define IEEE80211_DEFAULT_AQL_TXQ_LIMIT_H 12000
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
-@@ -1338,10 +1338,12 @@ struct ieee80211_local {
+@@ -1351,10 +1351,12 @@ struct ieee80211_local {
spinlock_t handle_wake_tx_queue_lock;
u16 airtime_flags;
const struct ieee80211_ops *ops;
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
-@@ -944,6 +944,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_
+@@ -952,6 +952,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_
spin_lock_init(&local->rx_path_lock);
spin_lock_init(&local->queue_stop_reason_lock);
spin_unlock_irqrestore(&local->ack_status_lock, flags);
if (id >= 0) {
-@@ -3983,20 +3983,20 @@ begin:
+@@ -3982,20 +3982,20 @@ begin:
encap_out:
info->control.vif = vif;
}
return skb;
-@@ -4048,6 +4048,7 @@ struct ieee80211_txq *ieee80211_next_txq
+@@ -4047,6 +4047,7 @@ struct ieee80211_txq *ieee80211_next_txq
struct ieee80211_txq *ret = NULL;
struct txq_info *txqi = NULL, *head = NULL;
bool found_eligible_txq = false;
spin_lock_bh(&local->active_txq_lock[ac]);
-@@ -4071,26 +4072,26 @@ struct ieee80211_txq *ieee80211_next_txq
+@@ -4070,26 +4071,26 @@ struct ieee80211_txq *ieee80211_next_txq
if (!head)
head = txqi;
if (txqi->schedule_round == local->schedule_round[ac])
goto out;
-@@ -4155,7 +4156,8 @@ bool ieee80211_txq_airtime_check(struct
+@@ -4154,7 +4155,8 @@ bool ieee80211_txq_airtime_check(struct
return true;
if (!txq->sta)
if (unlikely(txq->tid == IEEE80211_NUM_TIDS))
return true;
-@@ -4204,15 +4206,15 @@ bool ieee80211_txq_may_transmit(struct i
+@@ -4203,15 +4205,15 @@ bool ieee80211_txq_may_transmit(struct i
spin_lock_bh(&local->active_txq_lock[ac]);
if (iter == txqi)
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
-@@ -1180,8 +1180,8 @@ struct ieee80211_tx_info {
+@@ -1221,8 +1221,8 @@ struct ieee80211_tx_info {
status_data_idr:1,
status_data:13,
hw_queue:4,
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
-@@ -717,7 +717,7 @@ static void ieee80211_report_used_skb(st
+@@ -734,7 +734,7 @@ static void ieee80211_report_used_skb(st
ieee80211_sta_update_pending_airtime(local, sta,
skb_get_queue_mapping(skb),
tx_time_est,
rcu_read_unlock();
}
-@@ -1138,10 +1138,11 @@ void ieee80211_tx_status_ext(struct ieee
+@@ -1158,10 +1158,11 @@ void ieee80211_tx_status_ext(struct ieee
/* Do this here to avoid the expensive lookup of the sta
* in ieee80211_report_used_skb().
*/
+++ /dev/null
-From: Michael-CY Lee <michael-cy.lee@mediatek.com>
-Date: Tue, 26 Mar 2024 08:30:36 +0800
-Subject: [PATCH] wifi: mac80211: extend IEEE80211_KEY_FLAG_GENERATE_MMIE to
- other ciphers
-
-Extend the flag IEEE80211_KEY_FLAG_GENERATE_MMIE to BIP-CMAC-256,
-BIP-GMAC-128 and BIP-GMAC-256 for the same reason and in the same
-way that the flag was added originally in commit a0b4496a4368
-("mac80211: add IEEE80211_KEY_FLAG_GENERATE_MMIE to ieee80211_key_flags").
-
-Signed-off-by: Michael-CY Lee <michael-cy.lee@mediatek.com>
-Link: https://msgid.link/20240326003036.15215-1-michael-cy.lee@mediatek.com
-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
----
-
---- a/include/net/mac80211.h
-+++ b/include/net/mac80211.h
-@@ -2123,8 +2123,8 @@ static inline bool lockdep_vif_wiphy_mut
- * @IEEE80211_KEY_FLAG_GENERATE_MMIC on the same key.
- * @IEEE80211_KEY_FLAG_NO_AUTO_TX: Key needs explicit Tx activation.
- * @IEEE80211_KEY_FLAG_GENERATE_MMIE: This flag should be set by the driver
-- * for a AES_CMAC key to indicate that it requires sequence number
-- * generation only
-+ * for a AES_CMAC or a AES_GMAC key to indicate that it requires sequence
-+ * number generation only
- * @IEEE80211_KEY_FLAG_SPP_AMSDU: SPP A-MSDUs can be used with this key
- * (set by mac80211 from the sta->spp_amsdu flag)
- */
---- a/net/mac80211/wpa.c
-+++ b/net/mac80211/wpa.c
-@@ -895,7 +895,8 @@ ieee80211_crypto_aes_cmac_256_encrypt(st
-
- info = IEEE80211_SKB_CB(skb);
-
-- if (info->control.hw_key)
-+ if (info->control.hw_key &&
-+ !(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIE))
- return TX_CONTINUE;
-
- if (WARN_ON(skb_tailroom(skb) < sizeof(*mmie)))
-@@ -911,6 +912,9 @@ ieee80211_crypto_aes_cmac_256_encrypt(st
-
- bip_ipn_set64(mmie->sequence_number, pn64);
-
-+ if (info->control.hw_key)
-+ return TX_CONTINUE;
-+
- bip_aad(skb, aad);
-
- /* MIC = AES-256-CMAC(IGTK, AAD || Management Frame Body || MMIE, 128)
-@@ -1040,7 +1044,8 @@ ieee80211_crypto_aes_gmac_encrypt(struct
-
- info = IEEE80211_SKB_CB(skb);
-
-- if (info->control.hw_key)
-+ if (info->control.hw_key &&
-+ !(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIE))
- return TX_CONTINUE;
-
- if (WARN_ON(skb_tailroom(skb) < sizeof(*mmie)))
-@@ -1056,6 +1061,9 @@ ieee80211_crypto_aes_gmac_encrypt(struct
-
- bip_ipn_set64(mmie->sequence_number, pn64);
-
-+ if (info->control.hw_key)
-+ return TX_CONTINUE;
-+
- bip_aad(skb, aad);
-
- hdr = (struct ieee80211_hdr *)skb->data;
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Tue, 4 Jun 2024 14:31:09 +0200
-Subject: [PATCH] wifi: nl80211: split helper function from
- nl80211_put_iface_combinations
-
-Create a helper function that puts the data from struct
-ieee80211_iface_combination to a nl80211 message.
-This will be used for adding per-radio interface combination data.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/wireless/nl80211.c
-+++ b/net/wireless/nl80211.c
-@@ -1620,71 +1620,78 @@ nla_put_failure:
- return -ENOBUFS;
- }
-
--static int nl80211_put_iface_combinations(struct wiphy *wiphy,
-- struct sk_buff *msg,
-- bool large)
-+static int nl80211_put_ifcomb_data(struct sk_buff *msg, bool large, int idx,
-+ const struct ieee80211_iface_combination *c)
- {
-- struct nlattr *nl_combis;
-- int i, j;
-+ struct nlattr *nl_combi, *nl_limits;
-+ int i;
-
-- nl_combis = nla_nest_start_noflag(msg,
-- NL80211_ATTR_INTERFACE_COMBINATIONS);
-- if (!nl_combis)
-+ nl_combi = nla_nest_start_noflag(msg, idx);
-+ if (!nl_combi)
- goto nla_put_failure;
-
-- for (i = 0; i < wiphy->n_iface_combinations; i++) {
-- const struct ieee80211_iface_combination *c;
-- struct nlattr *nl_combi, *nl_limits;
-+ nl_limits = nla_nest_start_noflag(msg, NL80211_IFACE_COMB_LIMITS);
-+ if (!nl_limits)
-+ goto nla_put_failure;
-
-- c = &wiphy->iface_combinations[i];
-+ for (i = 0; i < c->n_limits; i++) {
-+ struct nlattr *nl_limit;
-
-- nl_combi = nla_nest_start_noflag(msg, i + 1);
-- if (!nl_combi)
-+ nl_limit = nla_nest_start_noflag(msg, i + 1);
-+ if (!nl_limit)
- goto nla_put_failure;
--
-- nl_limits = nla_nest_start_noflag(msg,
-- NL80211_IFACE_COMB_LIMITS);
-- if (!nl_limits)
-+ if (nla_put_u32(msg, NL80211_IFACE_LIMIT_MAX, c->limits[i].max))
- goto nla_put_failure;
-+ if (nl80211_put_iftypes(msg, NL80211_IFACE_LIMIT_TYPES,
-+ c->limits[i].types))
-+ goto nla_put_failure;
-+ nla_nest_end(msg, nl_limit);
-+ }
-
-- for (j = 0; j < c->n_limits; j++) {
-- struct nlattr *nl_limit;
-+ nla_nest_end(msg, nl_limits);
-
-- nl_limit = nla_nest_start_noflag(msg, j + 1);
-- if (!nl_limit)
-- goto nla_put_failure;
-- if (nla_put_u32(msg, NL80211_IFACE_LIMIT_MAX,
-- c->limits[j].max))
-- goto nla_put_failure;
-- if (nl80211_put_iftypes(msg, NL80211_IFACE_LIMIT_TYPES,
-- c->limits[j].types))
-- goto nla_put_failure;
-- nla_nest_end(msg, nl_limit);
-- }
-+ if (c->beacon_int_infra_match &&
-+ nla_put_flag(msg, NL80211_IFACE_COMB_STA_AP_BI_MATCH))
-+ goto nla_put_failure;
-+ if (nla_put_u32(msg, NL80211_IFACE_COMB_NUM_CHANNELS,
-+ c->num_different_channels) ||
-+ nla_put_u32(msg, NL80211_IFACE_COMB_MAXNUM,
-+ c->max_interfaces))
-+ goto nla_put_failure;
-+ if (large &&
-+ (nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS,
-+ c->radar_detect_widths) ||
-+ nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_REGIONS,
-+ c->radar_detect_regions)))
-+ goto nla_put_failure;
-+ if (c->beacon_int_min_gcd &&
-+ nla_put_u32(msg, NL80211_IFACE_COMB_BI_MIN_GCD,
-+ c->beacon_int_min_gcd))
-+ goto nla_put_failure;
-
-- nla_nest_end(msg, nl_limits);
-+ nla_nest_end(msg, nl_combi);
-
-- if (c->beacon_int_infra_match &&
-- nla_put_flag(msg, NL80211_IFACE_COMB_STA_AP_BI_MATCH))
-- goto nla_put_failure;
-- if (nla_put_u32(msg, NL80211_IFACE_COMB_NUM_CHANNELS,
-- c->num_different_channels) ||
-- nla_put_u32(msg, NL80211_IFACE_COMB_MAXNUM,
-- c->max_interfaces))
-- goto nla_put_failure;
-- if (large &&
-- (nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS,
-- c->radar_detect_widths) ||
-- nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_REGIONS,
-- c->radar_detect_regions)))
-- goto nla_put_failure;
-- if (c->beacon_int_min_gcd &&
-- nla_put_u32(msg, NL80211_IFACE_COMB_BI_MIN_GCD,
-- c->beacon_int_min_gcd))
-- goto nla_put_failure;
-+ return 0;
-+nla_put_failure:
-+ return -ENOBUFS;
-+}
-
-- nla_nest_end(msg, nl_combi);
-- }
-+static int nl80211_put_iface_combinations(struct wiphy *wiphy,
-+ struct sk_buff *msg,
-+ bool large)
-+{
-+ struct nlattr *nl_combis;
-+ int i;
-+
-+ nl_combis = nla_nest_start_noflag(msg,
-+ NL80211_ATTR_INTERFACE_COMBINATIONS);
-+ if (!nl_combis)
-+ goto nla_put_failure;
-+
-+ for (i = 0; i < wiphy->n_iface_combinations; i++)
-+ if (nl80211_put_ifcomb_data(msg, large, i + 1,
-+ &wiphy->iface_combinations[i]))
-+ goto nla_put_failure;
-
- nla_nest_end(msg, nl_combis);
-
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Wed, 22 May 2024 11:42:57 +0200
-Subject: [PATCH] wifi: cfg80211: add support for advertising multiple
- radios belonging to a wiphy
-
-The prerequisite for MLO support in cfg80211/mac80211 is that all the links
-participating in MLO must be from the same wiphy/ieee80211_hw. To meet this
-expectation, some drivers may need to group multiple discrete hardware each
-acting as a link in MLO under single wiphy.
-
-With this change, supported frequencies and interface combinations of each
-individual radio are reported to user space. This allows user space to figure
-out the limitations of what combination of channels can be used concurrently.
-
-Even for non-MLO devices, this improves support for devices capable of
-running on multiple channels at the same time.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/include/net/cfg80211.h
-+++ b/include/net/cfg80211.h
-@@ -5045,7 +5045,9 @@ struct ieee80211_iface_limit {
- * struct ieee80211_iface_combination - possible interface combination
- *
- * With this structure the driver can describe which interface
-- * combinations it supports concurrently.
-+ * combinations it supports concurrently. When set in a struct wiphy_radio,
-+ * the combinations refer to combinations of interfaces currently active on
-+ * that radio.
- *
- * Examples:
- *
-@@ -5403,6 +5405,38 @@ struct wiphy_iftype_akm_suites {
- int n_akm_suites;
- };
-
-+/**
-+ * struct wiphy_radio_freq_range - wiphy frequency range
-+ * @start_freq: start range edge frequency (kHz)
-+ * @end_freq: end range edge frequency (kHz)
-+ */
-+struct wiphy_radio_freq_range {
-+ u32 start_freq;
-+ u32 end_freq;
-+};
-+
-+
-+/**
-+ * struct wiphy_radio - physical radio of a wiphy
-+ * This structure describes a physical radio belonging to a wiphy.
-+ * It is used to describe concurrent-channel capabilities. Only one channel
-+ * can be active on the radio described by struct wiphy_radio.
-+ *
-+ * @freq_range: frequency range that the radio can operate on.
-+ * @n_freq_range: number of elements in @freq_range
-+ *
-+ * @iface_combinations: Valid interface combinations array, should not
-+ * list single interface types.
-+ * @n_iface_combinations: number of entries in @iface_combinations array.
-+ */
-+struct wiphy_radio {
-+ const struct wiphy_radio_freq_range *freq_range;
-+ int n_freq_range;
-+
-+ const struct ieee80211_iface_combination *iface_combinations;
-+ int n_iface_combinations;
-+};
-+
- #define CFG80211_HW_TIMESTAMP_ALL_PEERS 0xffff
-
- /**
-@@ -5621,6 +5655,9 @@ struct wiphy_iftype_akm_suites {
- * A value of %CFG80211_HW_TIMESTAMP_ALL_PEERS indicates the driver
- * supports enabling HW timestamping for all peers (i.e. no need to
- * specify a mac address).
-+ *
-+ * @radio: radios belonging to this wiphy
-+ * @n_radio: number of radios
- */
- struct wiphy {
- struct mutex mtx;
-@@ -5771,6 +5808,9 @@ struct wiphy {
-
- u16 hw_timestamp_max_peers;
-
-+ int n_radio;
-+ const struct wiphy_radio *radio;
-+
- char priv[] __aligned(NETDEV_ALIGN);
- };
-
---- a/include/uapi/linux/nl80211.h
-+++ b/include/uapi/linux/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,14 @@ 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.
-+ *
- * @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 +3413,9 @@ enum nl80211_attrs {
-
- NL80211_ATTR_ASSOC_SPP_AMSDU,
-
-+ NL80211_ATTR_WIPHY_RADIOS,
-+ NL80211_ATTR_WIPHY_INTERFACE_COMBINATIONS,
-+
- /* add attributes here, update the policy in nl80211.c */
-
- __NL80211_ATTR_AFTER_LAST,
-@@ -7987,4 +8002,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/net/wireless/nl80211.c
-+++ b/net/wireless/nl80211.c
-@@ -1621,16 +1621,18 @@ nla_put_failure:
- }
-
- static int nl80211_put_ifcomb_data(struct sk_buff *msg, bool large, int idx,
-- const struct ieee80211_iface_combination *c)
-+ const struct ieee80211_iface_combination *c,
-+ u16 nested)
- {
- struct nlattr *nl_combi, *nl_limits;
- int i;
-
-- nl_combi = nla_nest_start_noflag(msg, idx);
-+ nl_combi = nla_nest_start_noflag(msg, idx | nested);
- if (!nl_combi)
- goto nla_put_failure;
-
-- nl_limits = nla_nest_start_noflag(msg, NL80211_IFACE_COMB_LIMITS);
-+ nl_limits = nla_nest_start_noflag(msg, NL80211_IFACE_COMB_LIMITS |
-+ nested);
- if (!nl_limits)
- goto nla_put_failure;
-
-@@ -1678,19 +1680,26 @@ nla_put_failure:
-
- static int nl80211_put_iface_combinations(struct wiphy *wiphy,
- struct sk_buff *msg,
-- bool large)
-+ int attr, int radio,
-+ bool large, u16 nested)
- {
-+ const struct ieee80211_iface_combination *c;
- struct nlattr *nl_combis;
-- int i;
-+ int i, n;
-
-- nl_combis = nla_nest_start_noflag(msg,
-- NL80211_ATTR_INTERFACE_COMBINATIONS);
-+ nl_combis = nla_nest_start_noflag(msg, attr | nested);
- if (!nl_combis)
- goto nla_put_failure;
-
-- for (i = 0; i < wiphy->n_iface_combinations; i++)
-- if (nl80211_put_ifcomb_data(msg, large, i + 1,
-- &wiphy->iface_combinations[i]))
-+ if (radio >= 0) {
-+ c = wiphy->radio[0].iface_combinations;
-+ n = wiphy->radio[0].n_iface_combinations;
-+ } else {
-+ c = wiphy->iface_combinations;
-+ n = wiphy->n_iface_combinations;
-+ }
-+ for (i = 0; i < n; i++)
-+ if (nl80211_put_ifcomb_data(msg, large, i + 1, &c[i], nested))
- goto nla_put_failure;
-
- nla_nest_end(msg, nl_combis);
-@@ -2397,6 +2406,80 @@ fail:
- return -ENOBUFS;
- }
-
-+static int nl80211_put_radio(struct wiphy *wiphy, struct sk_buff *msg, int idx)
-+{
-+ const struct wiphy_radio *r = &wiphy->radio[idx];
-+ struct nlattr *radio, *freq;
-+ int i;
-+
-+ radio = nla_nest_start(msg, idx);
-+ if (!radio)
-+ return -ENOBUFS;
-+
-+ if (nla_put_u32(msg, NL80211_WIPHY_RADIO_ATTR_INDEX, idx))
-+ goto nla_put_failure;
-+
-+ for (i = 0; i < r->n_freq_range; i++) {
-+ const struct wiphy_radio_freq_range *range = &r->freq_range[i];
-+
-+ freq = nla_nest_start(msg, NL80211_WIPHY_RADIO_ATTR_FREQ_RANGE);
-+ if (!freq)
-+ goto nla_put_failure;
-+
-+ if (nla_put_u32(msg, NL80211_WIPHY_RADIO_FREQ_ATTR_START,
-+ range->start_freq) ||
-+ nla_put_u32(msg, NL80211_WIPHY_RADIO_FREQ_ATTR_END,
-+ range->end_freq))
-+ goto nla_put_failure;
-+
-+ nla_nest_end(msg, freq);
-+ }
-+
-+ for (i = 0; i < r->n_iface_combinations; i++)
-+ if (nl80211_put_ifcomb_data(msg, true,
-+ NL80211_WIPHY_RADIO_ATTR_INTERFACE_COMBINATION,
-+ &r->iface_combinations[i],
-+ NLA_F_NESTED))
-+ goto nla_put_failure;
-+
-+ nla_nest_end(msg, radio);
-+
-+ return 0;
-+
-+nla_put_failure:
-+ return -ENOBUFS;
-+}
-+
-+static int nl80211_put_radios(struct wiphy *wiphy, struct sk_buff *msg)
-+{
-+ struct nlattr *radios;
-+ int i;
-+
-+ if (!wiphy->n_radio)
-+ return 0;
-+
-+ radios = nla_nest_start(msg, NL80211_ATTR_WIPHY_RADIOS);
-+ if (!radios)
-+ return -ENOBUFS;
-+
-+ for (i = 0; i < wiphy->n_radio; i++)
-+ if (nl80211_put_radio(wiphy, msg, i))
-+ goto fail;
-+
-+ nla_nest_end(msg, radios);
-+
-+ if (nl80211_put_iface_combinations(wiphy, msg,
-+ NL80211_ATTR_WIPHY_INTERFACE_COMBINATIONS,
-+ -1, true, NLA_F_NESTED))
-+ return -ENOBUFS;
-+
-+ return 0;
-+
-+fail:
-+ nla_nest_cancel(msg, radios);
-+ return -ENOBUFS;
-+}
-+
- struct nl80211_dump_wiphy_state {
- s64 filter_wiphy;
- long start;
-@@ -2692,7 +2775,9 @@ static int nl80211_send_wiphy(struct cfg
- goto nla_put_failure;
-
- if (nl80211_put_iface_combinations(&rdev->wiphy, msg,
-- state->split))
-+ NL80211_ATTR_INTERFACE_COMBINATIONS,
-+ rdev->wiphy.n_radio ? 0 : -1,
-+ state->split, 0))
- goto nla_put_failure;
-
- state->split_start++;
-@@ -3006,6 +3091,12 @@ static int nl80211_send_wiphy(struct cfg
- rdev->wiphy.hw_timestamp_max_peers))
- goto nla_put_failure;
-
-+ state->split_start++;
-+ break;
-+ case 17:
-+ if (nl80211_put_radios(&rdev->wiphy, msg))
-+ goto nla_put_failure;
-+
- /* done */
- state->split_start = 0;
- break;
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Tue, 4 Jun 2024 21:01:50 +0200
-Subject: [PATCH] wifi: cfg80211: extend interface combination check for
- multi-radio
-
-Add a field in struct iface_combination_params to check per-radio
-interface combinations instead of per-wiphy ones.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/include/net/cfg80211.h
-+++ b/include/net/cfg80211.h
-@@ -1598,6 +1598,7 @@ struct cfg80211_color_change_settings {
- *
- * Used to pass interface combination parameters
- *
-+ * @radio_idx: wiphy radio index or -1 for global
- * @num_different_channels: the number of different channels we want
- * to use for verification
- * @radar_detect: a bitmap where each bit corresponds to a channel
-@@ -1611,6 +1612,7 @@ struct cfg80211_color_change_settings {
- * the verification
- */
- struct iface_combination_params {
-+ int radio_idx;
- int num_different_channels;
- u8 radar_detect;
- int iftype_num[NUM_NL80211_IFTYPES];
-@@ -4579,6 +4581,8 @@ struct mgmt_frame_regs {
- *
- * @set_hw_timestamp: Enable/disable HW timestamping of TM/FTM frames.
- * @set_ttlm: set the TID to link mapping.
-+ * @get_radio_mask: get bitmask of radios in use.
-+ * (invoked with the wiphy mutex held)
- */
- struct cfg80211_ops {
- int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
-@@ -4940,6 +4944,7 @@ struct cfg80211_ops {
- struct cfg80211_set_hw_timestamp *hwts);
- int (*set_ttlm)(struct wiphy *wiphy, struct net_device *dev,
- struct cfg80211_ttlm_params *params);
-+ u32 (*get_radio_mask)(struct wiphy *wiphy, struct net_device *dev);
- };
-
- /*
---- a/net/mac80211/util.c
-+++ b/net/mac80211/util.c
-@@ -3930,6 +3930,7 @@ int ieee80211_check_combinations(struct
- int total = 1;
- struct iface_combination_params params = {
- .radar_detect = radar_detect,
-+ .radio_idx = -1,
- };
-
- lockdep_assert_wiphy(local->hw.wiphy);
-@@ -4020,7 +4021,9 @@ int ieee80211_max_num_channels(struct ie
- struct ieee80211_chanctx *ctx;
- u32 max_num_different_channels = 1;
- int err;
-- struct iface_combination_params params = {0};
-+ struct iface_combination_params params = {
-+ .radio_idx = -1,
-+ };
-
- lockdep_assert_wiphy(local->hw.wiphy);
-
---- a/net/wireless/rdev-ops.h
-+++ b/net/wireless/rdev-ops.h
-@@ -1542,4 +1542,16 @@ rdev_set_ttlm(struct cfg80211_registered
-
- return ret;
- }
-+
-+static inline u32
-+rdev_get_radio_mask(struct cfg80211_registered_device *rdev,
-+ struct net_device *dev)
-+{
-+ struct wiphy *wiphy = &rdev->wiphy;
-+
-+ if (!rdev->ops->get_radio_mask)
-+ return 0;
-+
-+ return rdev->ops->get_radio_mask(wiphy, dev);
-+}
- #endif /* __CFG80211_RDEV_OPS */
---- a/net/wireless/util.c
-+++ b/net/wireless/util.c
-@@ -2305,13 +2305,16 @@ static int cfg80211_wdev_bi(struct wirel
-
- static void cfg80211_calculate_bi_data(struct wiphy *wiphy, u32 new_beacon_int,
- u32 *beacon_int_gcd,
-- bool *beacon_int_different)
-+ bool *beacon_int_different,
-+ int radio_idx)
- {
-+ struct cfg80211_registered_device *rdev;
- struct wireless_dev *wdev;
-
- *beacon_int_gcd = 0;
- *beacon_int_different = false;
-
-+ rdev = wiphy_to_rdev(wiphy);
- list_for_each_entry(wdev, &wiphy->wdev_list, list) {
- int wdev_bi;
-
-@@ -2319,6 +2322,11 @@ static void cfg80211_calculate_bi_data(s
- if (wdev->valid_links)
- continue;
-
-+ /* skip wdevs not active on the given wiphy radio */
-+ if (radio_idx >= 0 &&
-+ !(rdev_get_radio_mask(rdev, wdev->netdev) & BIT(radio_idx)))
-+ continue;
-+
- wdev_bi = cfg80211_wdev_bi(wdev);
-
- if (!wdev_bi)
-@@ -2366,14 +2374,19 @@ int cfg80211_iter_combinations(struct wi
- void *data),
- void *data)
- {
-+ const struct wiphy_radio *radio = NULL;
-+ const struct ieee80211_iface_combination *c, *cs;
- const struct ieee80211_regdomain *regdom;
- enum nl80211_dfs_regions region = 0;
-- int i, j, iftype;
-+ int i, j, n, iftype;
- int num_interfaces = 0;
- u32 used_iftypes = 0;
- u32 beacon_int_gcd;
- bool beacon_int_different;
-
-+ if (params->radio_idx >= 0)
-+ radio = &wiphy->radio[params->radio_idx];
-+
- /*
- * This is a bit strange, since the iteration used to rely only on
- * the data given by the driver, but here it now relies on context,
-@@ -2385,7 +2398,8 @@ int cfg80211_iter_combinations(struct wi
- * interfaces (while being brought up) and channel/radar data.
- */
- cfg80211_calculate_bi_data(wiphy, params->new_beacon_int,
-- &beacon_int_gcd, &beacon_int_different);
-+ &beacon_int_gcd, &beacon_int_different,
-+ params->radio_idx);
-
- if (params->radar_detect) {
- rcu_read_lock();
-@@ -2402,13 +2416,18 @@ int cfg80211_iter_combinations(struct wi
- used_iftypes |= BIT(iftype);
- }
-
-- for (i = 0; i < wiphy->n_iface_combinations; i++) {
-- const struct ieee80211_iface_combination *c;
-+ if (radio) {
-+ cs = radio->iface_combinations;
-+ n = radio->n_iface_combinations;
-+ } else {
-+ cs = wiphy->iface_combinations;
-+ n = wiphy->n_iface_combinations;
-+ }
-+ for (i = 0; i < n; i++) {
- struct ieee80211_iface_limit *limits;
- u32 all_iftypes = 0;
-
-- c = &wiphy->iface_combinations[i];
--
-+ c = &cs[i];
- if (num_interfaces > c->max_interfaces)
- continue;
- if (params->num_different_channels > c->num_different_channels)
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Fri, 7 Jun 2024 17:58:54 +0200
-Subject: [PATCH] wifi: cfg80211: add helper for checking if a chandef is
- valid on a radio
-
-Check if the full channel width is in the radio's frequency range.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/include/net/cfg80211.h
-+++ b/include/net/cfg80211.h
-@@ -6485,6 +6485,15 @@ static inline bool cfg80211_channel_is_p
- }
-
- /**
-+ * cfg80211_radio_chandef_valid - Check if the radio supports the chandef
-+ *
-+ * @radio: wiphy radio
-+ * @chandef: chandef for current channel
-+ */
-+bool cfg80211_radio_chandef_valid(const struct wiphy_radio *radio,
-+ const struct cfg80211_chan_def *chandef);
-+
-+/**
- * ieee80211_get_response_rate - get basic rate for a given rate
- *
- * @sband: the band to look for rates in
---- a/net/wireless/util.c
-+++ b/net/wireless/util.c
-@@ -2884,3 +2884,38 @@ cfg80211_get_iftype_ext_capa(struct wiph
- return NULL;
- }
- EXPORT_SYMBOL(cfg80211_get_iftype_ext_capa);
-+
-+static bool
-+ieee80211_radio_freq_range_valid(const struct wiphy_radio *radio,
-+ u32 freq, u32 width)
-+{
-+ const struct wiphy_radio_freq_range *r;
-+ int i;
-+
-+ for (i = 0; i < radio->n_freq_range; i++) {
-+ r = &radio->freq_range[i];
-+ if (freq - width / 2 >= r->start_freq &&
-+ freq + width / 2 <= r->end_freq)
-+ return true;
-+ }
-+
-+ return false;
-+}
-+
-+bool cfg80211_radio_chandef_valid(const struct wiphy_radio *radio,
-+ const struct cfg80211_chan_def *chandef)
-+{
-+ u32 freq, width;
-+
-+ freq = ieee80211_chandef_to_khz(chandef);
-+ width = nl80211_chan_width_to_mhz(chandef->width);
-+ if (!ieee80211_radio_freq_range_valid(radio, freq, width))
-+ return false;
-+
-+ freq = MHZ_TO_KHZ(chandef->center_freq2);
-+ if (freq && !ieee80211_radio_freq_range_valid(radio, freq, width))
-+ return false;
-+
-+ return true;
-+}
-+EXPORT_SYMBOL(cfg80211_radio_chandef_valid);
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Thu, 6 Jun 2024 12:19:08 +0200
-Subject: [PATCH] wifi: mac80211: add support for DFS with multiple
- radios
-
-DFS can be supported with multi-channel combinations, as long as each DFS
-capable radio only supports one channel.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/main.c
-+++ b/net/mac80211/main.c
-@@ -1084,6 +1084,27 @@ static int ieee80211_init_cipher_suites(
- return 0;
- }
-
-+static bool
-+ieee80211_ifcomb_check(const struct ieee80211_iface_combination *c, int n_comb)
-+{
-+ int i, j;
-+
-+ for (i = 0; i < n_comb; i++, c++) {
-+ /* DFS is not supported with multi-channel combinations yet */
-+ if (c->radar_detect_widths &&
-+ c->num_different_channels > 1)
-+ return false;
-+
-+ /* mac80211 doesn't support more than one IBSS interface */
-+ for (j = 0; j < c->n_limits; j++)
-+ if ((c->limits[j].types & BIT(NL80211_IFTYPE_ADHOC)) &&
-+ c->limits[j].max > 1)
-+ return false;
-+ }
-+
-+ return true;
-+}
-+
- int ieee80211_register_hw(struct ieee80211_hw *hw)
- {
- struct ieee80211_local *local = hw_to_local(hw);
-@@ -1173,17 +1194,20 @@ int ieee80211_register_hw(struct ieee802
- if (comb->num_different_channels > 1)
- return -EINVAL;
- }
-- } else {
-- /* DFS is not supported with multi-channel combinations yet */
-- for (i = 0; i < local->hw.wiphy->n_iface_combinations; i++) {
-- const struct ieee80211_iface_combination *comb;
-+ }
-
-- comb = &local->hw.wiphy->iface_combinations[i];
-+ if (hw->wiphy->n_radio) {
-+ for (i = 0; i < hw->wiphy->n_radio; i++) {
-+ const struct wiphy_radio *radio = &hw->wiphy->radio[i];
-
-- if (comb->radar_detect_widths &&
-- comb->num_different_channels > 1)
-+ if (!ieee80211_ifcomb_check(radio->iface_combinations,
-+ radio->n_iface_combinations))
- return -EINVAL;
- }
-+ } else {
-+ if (!ieee80211_ifcomb_check(hw->wiphy->iface_combinations,
-+ hw->wiphy->n_iface_combinations))
-+ return -EINVAL;
- }
-
- /* Only HW csum features are currently compatible with mac80211 */
-@@ -1313,18 +1337,6 @@ int ieee80211_register_hw(struct ieee802
- hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR);
- hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_MONITOR);
-
-- /* mac80211 doesn't support more than one IBSS interface right now */
-- for (i = 0; i < hw->wiphy->n_iface_combinations; i++) {
-- const struct ieee80211_iface_combination *c;
-- int j;
--
-- c = &hw->wiphy->iface_combinations[i];
--
-- for (j = 0; j < c->n_limits; j++)
-- if ((c->limits[j].types & BIT(NL80211_IFTYPE_ADHOC)) &&
-- c->limits[j].max > 1)
-- return -EINVAL;
-- }
-
- local->int_scan_req = kzalloc(sizeof(*local->int_scan_req) +
- sizeof(void *) * channels, GFP_KERNEL);
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Wed, 5 Jun 2024 10:41:34 +0200
-Subject: [PATCH] wifi: mac80211: add radio index to
- ieee80211_chanctx_conf
-
-Will be used to explicitly assign a channel context to a wiphy radio.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/include/net/mac80211.h
-+++ b/include/net/mac80211.h
-@@ -250,6 +250,7 @@ struct ieee80211_chan_req {
- * @min_def: the minimum channel definition currently required.
- * @ap: the channel definition the AP actually is operating as,
- * for use with (wider bandwidth) OFDMA
-+ * @radio_idx: index of the wiphy radio used used for this channel
- * @rx_chains_static: The number of RX chains that must always be
- * active on the channel to receive MIMO transmissions
- * @rx_chains_dynamic: The number of RX chains that must be enabled
-@@ -264,6 +265,7 @@ struct ieee80211_chanctx_conf {
- struct cfg80211_chan_def min_def;
- struct cfg80211_chan_def ap;
-
-+ int radio_idx;
- u8 rx_chains_static, rx_chains_dynamic;
-
- bool radar_enabled;
---- a/net/mac80211/chan.c
-+++ b/net/mac80211/chan.c
-@@ -623,7 +623,8 @@ ieee80211_chanctx_radar_required(struct
- static struct ieee80211_chanctx *
- ieee80211_alloc_chanctx(struct ieee80211_local *local,
- const struct ieee80211_chan_req *chanreq,
-- enum ieee80211_chanctx_mode mode)
-+ enum ieee80211_chanctx_mode mode,
-+ int radio_idx)
- {
- struct ieee80211_chanctx *ctx;
-
-@@ -641,6 +642,7 @@ ieee80211_alloc_chanctx(struct ieee80211
- ctx->conf.rx_chains_dynamic = 1;
- ctx->mode = mode;
- ctx->conf.radar_enabled = false;
-+ ctx->conf.radio_idx = radio_idx;
- _ieee80211_recalc_chanctx_min_def(local, ctx, NULL);
-
- return ctx;
-@@ -680,7 +682,7 @@ ieee80211_new_chanctx(struct ieee80211_l
-
- lockdep_assert_wiphy(local->hw.wiphy);
-
-- ctx = ieee80211_alloc_chanctx(local, chanreq, mode);
-+ ctx = ieee80211_alloc_chanctx(local, chanreq, mode, -1);
- if (!ctx)
- return ERR_PTR(-ENOMEM);
-
-@@ -1098,7 +1100,7 @@ int ieee80211_link_reserve_chanctx(struc
- !list_empty(&curr_ctx->reserved_links))
- return -EBUSY;
-
-- new_ctx = ieee80211_alloc_chanctx(local, chanreq, mode);
-+ new_ctx = ieee80211_alloc_chanctx(local, chanreq, mode, -1);
- if (!new_ctx)
- return -ENOMEM;
-
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Tue, 4 Jun 2024 21:48:48 +0200
-Subject: [PATCH] wifi: mac80211: extend ifcomb check functions for
- multi-radio
-
-Add support for counting global and per-radio max/current number of
-channels, as well as checking radio-specific interface combinations.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/cfg.c
-+++ b/net/mac80211/cfg.c
-@@ -263,7 +263,7 @@ static int ieee80211_start_p2p_device(st
-
- lockdep_assert_wiphy(sdata->local->hw.wiphy);
-
-- ret = ieee80211_check_combinations(sdata, NULL, 0, 0);
-+ ret = ieee80211_check_combinations(sdata, NULL, 0, 0, -1);
- if (ret < 0)
- return ret;
-
-@@ -285,7 +285,7 @@ static int ieee80211_start_nan(struct wi
-
- lockdep_assert_wiphy(sdata->local->hw.wiphy);
-
-- ret = ieee80211_check_combinations(sdata, NULL, 0, 0);
-+ ret = ieee80211_check_combinations(sdata, NULL, 0, 0, -1);
- if (ret < 0)
- return ret;
-
-@@ -3992,7 +3992,7 @@ __ieee80211_channel_switch(struct wiphy
- goto out;
-
- /* if reservation is invalid then this will fail */
-- err = ieee80211_check_combinations(sdata, NULL, chanctx->mode, 0);
-+ err = ieee80211_check_combinations(sdata, NULL, chanctx->mode, 0, -1);
- if (err) {
- ieee80211_link_unreserve_chanctx(link_data);
- goto out;
-@@ -5161,4 +5161,5 @@ const struct cfg80211_ops mac80211_confi
- .del_link_station = ieee80211_del_link_station,
- .set_hw_timestamp = ieee80211_set_hw_timestamp,
- .set_ttlm = ieee80211_set_ttlm,
-+ .get_radio_mask = ieee80211_get_radio_mask,
- };
---- a/net/mac80211/chan.c
-+++ b/net/mac80211/chan.c
-@@ -47,24 +47,29 @@ int ieee80211_chanctx_refcount(struct ie
- ieee80211_chanctx_num_reserved(local, ctx);
- }
-
--static int ieee80211_num_chanctx(struct ieee80211_local *local)
-+static int ieee80211_num_chanctx(struct ieee80211_local *local, int radio_idx)
- {
- struct ieee80211_chanctx *ctx;
- int num = 0;
-
- lockdep_assert_wiphy(local->hw.wiphy);
-
-- list_for_each_entry(ctx, &local->chanctx_list, list)
-+ list_for_each_entry(ctx, &local->chanctx_list, list) {
-+ if (radio_idx >= 0 && ctx->conf.radio_idx != radio_idx)
-+ continue;
- num++;
-+ }
-
- return num;
- }
-
--static bool ieee80211_can_create_new_chanctx(struct ieee80211_local *local)
-+static bool ieee80211_can_create_new_chanctx(struct ieee80211_local *local,
-+ int radio_idx)
- {
- lockdep_assert_wiphy(local->hw.wiphy);
-
-- return ieee80211_num_chanctx(local) < ieee80211_max_num_channels(local);
-+ return ieee80211_num_chanctx(local, radio_idx) <
-+ ieee80211_max_num_channels(local, radio_idx);
- }
-
- static struct ieee80211_chanctx *
-@@ -1045,7 +1050,7 @@ 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)) {
-+ if (ieee80211_can_create_new_chanctx(local, -1)) {
- new_ctx = ieee80211_new_chanctx(local, chanreq, mode);
- if (IS_ERR(new_ctx))
- return PTR_ERR(new_ctx);
-@@ -1736,7 +1741,7 @@ int ieee80211_link_use_channel(struct ie
- link->radar_required = ret;
-
- ret = ieee80211_check_combinations(sdata, &chanreq->oper, mode,
-- radar_detect_width);
-+ radar_detect_width, -1);
- if (ret < 0)
- goto out;
-
---- a/net/mac80211/ibss.c
-+++ b/net/mac80211/ibss.c
-@@ -1745,7 +1745,7 @@ int ieee80211_ibss_join(struct ieee80211
- IEEE80211_CHANCTX_SHARED : IEEE80211_CHANCTX_EXCLUSIVE;
-
- ret = ieee80211_check_combinations(sdata, ¶ms->chandef, chanmode,
-- radar_detect_width);
-+ radar_detect_width, -1);
- if (ret < 0)
- return ret;
-
---- a/net/mac80211/ieee80211_i.h
-+++ b/net/mac80211/ieee80211_i.h
-@@ -2596,8 +2596,9 @@ void ieee80211_recalc_dtim(struct ieee80
- int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata,
- const struct cfg80211_chan_def *chandef,
- enum ieee80211_chanctx_mode chanmode,
-- u8 radar_detect);
--int ieee80211_max_num_channels(struct ieee80211_local *local);
-+ u8 radar_detect, int radio_idx);
-+int ieee80211_max_num_channels(struct ieee80211_local *local, int radio_idx);
-+u32 ieee80211_get_radio_mask(struct wiphy *wiphy, struct net_device *dev);
- void ieee80211_recalc_chanctx_chantype(struct ieee80211_local *local,
- struct ieee80211_chanctx *ctx);
-
---- a/net/mac80211/iface.c
-+++ b/net/mac80211/iface.c
-@@ -397,7 +397,7 @@ static int ieee80211_check_concurrent_if
- }
- }
-
-- return ieee80211_check_combinations(sdata, NULL, 0, 0);
-+ return ieee80211_check_combinations(sdata, NULL, 0, 0, -1);
- }
-
- static int ieee80211_check_queues(struct ieee80211_sub_if_data *sdata,
---- a/net/mac80211/util.c
-+++ b/net/mac80211/util.c
-@@ -3918,20 +3918,103 @@ static u8 ieee80211_chanctx_radar_detect
- return radar_detect;
- }
-
-+static u32
-+__ieee80211_get_radio_mask(struct ieee80211_sub_if_data *sdata)
-+{
-+ struct ieee80211_bss_conf *link_conf;
-+ struct ieee80211_chanctx_conf *conf;
-+ unsigned int link_id;
-+ u32 mask = 0;
-+
-+ for_each_vif_active_link(&sdata->vif, link_conf, link_id) {
-+ conf = sdata_dereference(link_conf->chanctx_conf, sdata);
-+ if (!conf || conf->radio_idx < 0)
-+ continue;
-+
-+ mask |= BIT(conf->radio_idx);
-+ }
-+
-+ return mask;
-+}
-+
-+u32 ieee80211_get_radio_mask(struct wiphy *wiphy, struct net_device *dev)
-+{
-+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-+
-+ return __ieee80211_get_radio_mask(sdata);
-+}
-+
-+static bool
-+ieee80211_sdata_uses_radio(struct ieee80211_sub_if_data *sdata, int radio_idx)
-+{
-+ if (radio_idx < 0)
-+ return true;
-+
-+ return __ieee80211_get_radio_mask(sdata) & BIT(radio_idx);
-+}
-+
-+static int
-+ieee80211_fill_ifcomb_params(struct ieee80211_local *local,
-+ struct iface_combination_params *params,
-+ const struct cfg80211_chan_def *chandef,
-+ struct ieee80211_sub_if_data *sdata)
-+{
-+ struct ieee80211_sub_if_data *sdata_iter;
-+ struct ieee80211_chanctx *ctx;
-+ int total = !!sdata;
-+
-+ list_for_each_entry(ctx, &local->chanctx_list, list) {
-+ if (ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED)
-+ continue;
-+
-+ if (params->radio_idx >= 0 &&
-+ ctx->conf.radio_idx != params->radio_idx)
-+ continue;
-+
-+ params->radar_detect |=
-+ ieee80211_chanctx_radar_detect(local, ctx);
-+
-+ if (chandef && ctx->mode != IEEE80211_CHANCTX_EXCLUSIVE &&
-+ cfg80211_chandef_compatible(chandef, &ctx->conf.def))
-+ continue;
-+
-+ params->num_different_channels++;
-+ }
-+
-+ list_for_each_entry(sdata_iter, &local->interfaces, list) {
-+ struct wireless_dev *wdev_iter;
-+
-+ wdev_iter = &sdata_iter->wdev;
-+
-+ if (sdata_iter == sdata ||
-+ !ieee80211_sdata_running(sdata_iter) ||
-+ cfg80211_iftype_allowed(local->hw.wiphy,
-+ wdev_iter->iftype, 0, 1))
-+ continue;
-+
-+ if (!ieee80211_sdata_uses_radio(sdata_iter, params->radio_idx))
-+ continue;
-+
-+ params->iftype_num[wdev_iter->iftype]++;
-+ total++;
-+ }
-+
-+ return total;
-+}
-+
- int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata,
- const struct cfg80211_chan_def *chandef,
- enum ieee80211_chanctx_mode chanmode,
-- u8 radar_detect)
-+ u8 radar_detect, int radio_idx)
- {
-+ bool shared = chanmode == IEEE80211_CHANCTX_SHARED;
- struct ieee80211_local *local = sdata->local;
-- struct ieee80211_sub_if_data *sdata_iter;
- enum nl80211_iftype iftype = sdata->wdev.iftype;
-- struct ieee80211_chanctx *ctx;
-- int total = 1;
- struct iface_combination_params params = {
- .radar_detect = radar_detect,
-- .radio_idx = -1,
-+ .radio_idx = radio_idx,
- };
-+ int total;
-
- lockdep_assert_wiphy(local->hw.wiphy);
-
-@@ -3968,37 +4051,9 @@ int ieee80211_check_combinations(struct
- if (iftype != NL80211_IFTYPE_UNSPECIFIED)
- params.iftype_num[iftype] = 1;
-
-- list_for_each_entry(ctx, &local->chanctx_list, list) {
-- if (ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED)
-- continue;
-- params.radar_detect |=
-- ieee80211_chanctx_radar_detect(local, ctx);
-- if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE) {
-- params.num_different_channels++;
-- continue;
-- }
-- if (chandef && chanmode == IEEE80211_CHANCTX_SHARED &&
-- cfg80211_chandef_compatible(chandef,
-- &ctx->conf.def))
-- continue;
-- params.num_different_channels++;
-- }
--
-- list_for_each_entry_rcu(sdata_iter, &local->interfaces, list) {
-- struct wireless_dev *wdev_iter;
--
-- wdev_iter = &sdata_iter->wdev;
--
-- if (sdata_iter == sdata ||
-- !ieee80211_sdata_running(sdata_iter) ||
-- cfg80211_iftype_allowed(local->hw.wiphy,
-- wdev_iter->iftype, 0, 1))
-- continue;
--
-- params.iftype_num[wdev_iter->iftype]++;
-- total++;
-- }
--
-+ total = ieee80211_fill_ifcomb_params(local, ¶ms,
-+ shared ? chandef : NULL,
-+ sdata);
- if (total == 1 && !params.radar_detect)
- return 0;
-
-@@ -4015,30 +4070,17 @@ ieee80211_iter_max_chans(const struct ie
- c->num_different_channels);
- }
-
--int ieee80211_max_num_channels(struct ieee80211_local *local)
-+int ieee80211_max_num_channels(struct ieee80211_local *local, int radio_idx)
- {
-- struct ieee80211_sub_if_data *sdata;
-- struct ieee80211_chanctx *ctx;
- u32 max_num_different_channels = 1;
- int err;
- struct iface_combination_params params = {
-- .radio_idx = -1,
-+ .radio_idx = radio_idx,
- };
-
- lockdep_assert_wiphy(local->hw.wiphy);
-
-- list_for_each_entry(ctx, &local->chanctx_list, list) {
-- if (ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED)
-- continue;
--
-- params.num_different_channels++;
--
-- params.radar_detect |=
-- ieee80211_chanctx_radar_detect(local, ctx);
-- }
--
-- list_for_each_entry_rcu(sdata, &local->interfaces, list)
-- params.iftype_num[sdata->wdev.iftype]++;
-+ ieee80211_fill_ifcomb_params(local, ¶ms, NULL, NULL);
-
- err = cfg80211_iter_combinations(local->hw.wiphy, ¶ms,
- ieee80211_iter_max_chans,
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Wed, 5 Jun 2024 10:49:22 +0200
-Subject: [PATCH] wifi: mac80211: move code in
- ieee80211_link_reserve_chanctx to a helper
-
-Reduces indentation in preparation for further changes
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/chan.c
-+++ b/net/mac80211/chan.c
-@@ -1033,6 +1033,71 @@ int ieee80211_link_unreserve_chanctx(str
- return 0;
- }
-
-+static struct ieee80211_chanctx *
-+ieee80211_replace_chanctx(struct ieee80211_local *local,
-+ const struct ieee80211_chan_req *chanreq,
-+ enum ieee80211_chanctx_mode mode,
-+ struct ieee80211_chanctx *curr_ctx)
-+{
-+ struct ieee80211_chanctx *new_ctx, *ctx;
-+
-+ if (!curr_ctx || (curr_ctx->replace_state ==
-+ IEEE80211_CHANCTX_WILL_BE_REPLACED) ||
-+ !list_empty(&curr_ctx->reserved_links)) {
-+ /*
-+ * Another link already requested this context for a
-+ * reservation. Find another one hoping all links assigned
-+ * to it will also switch soon enough.
-+ *
-+ * TODO: This needs a little more work as some cases
-+ * (more than 2 chanctx capable devices) may fail which could
-+ * otherwise succeed provided some channel context juggling was
-+ * performed.
-+ *
-+ * Consider ctx1..3, link1..6, each ctx has 2 links. link1 and
-+ * link2 from ctx1 request new different chandefs starting 2
-+ * in-place reserations with ctx4 and ctx5 replacing ctx1 and
-+ * ctx2 respectively. Next link5 and link6 from ctx3 reserve
-+ * ctx4. If link3 and link4 remain on ctx2 as they are then this
-+ * fails unless `replace_ctx` from ctx5 is replaced with ctx3.
-+ */
-+ list_for_each_entry(ctx, &local->chanctx_list, list) {
-+ if (ctx->replace_state !=
-+ IEEE80211_CHANCTX_REPLACE_NONE)
-+ continue;
-+
-+ if (!list_empty(&ctx->reserved_links))
-+ continue;
-+
-+ curr_ctx = ctx;
-+ break;
-+ }
-+ }
-+
-+ /*
-+ * If that's true then all available contexts already have reservations
-+ * and cannot be used.
-+ */
-+ if (!curr_ctx || (curr_ctx->replace_state ==
-+ IEEE80211_CHANCTX_WILL_BE_REPLACED) ||
-+ !list_empty(&curr_ctx->reserved_links))
-+ return ERR_PTR(-EBUSY);
-+
-+ new_ctx = ieee80211_alloc_chanctx(local, chanreq, mode, -1);
-+ if (!new_ctx)
-+ return ERR_PTR(-ENOMEM);
-+
-+ new_ctx->replace_ctx = curr_ctx;
-+ new_ctx->replace_state = IEEE80211_CHANCTX_REPLACES_OTHER;
-+
-+ curr_ctx->replace_ctx = new_ctx;
-+ curr_ctx->replace_state = IEEE80211_CHANCTX_WILL_BE_REPLACED;
-+
-+ list_add_rcu(&new_ctx->list, &local->chanctx_list);
-+
-+ return new_ctx;
-+}
-+
- int ieee80211_link_reserve_chanctx(struct ieee80211_link_data *link,
- const struct ieee80211_chan_req *chanreq,
- enum ieee80211_chanctx_mode mode,
-@@ -1040,7 +1105,7 @@ int ieee80211_link_reserve_chanctx(struc
- {
- struct ieee80211_sub_if_data *sdata = link->sdata;
- struct ieee80211_local *local = sdata->local;
-- struct ieee80211_chanctx *new_ctx, *curr_ctx, *ctx;
-+ struct ieee80211_chanctx *new_ctx, *curr_ctx;
-
- lockdep_assert_wiphy(local->hw.wiphy);
-
-@@ -1050,75 +1115,13 @@ 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)) {
-+ if (ieee80211_can_create_new_chanctx(local, -1))
- new_ctx = ieee80211_new_chanctx(local, chanreq, mode);
-- if (IS_ERR(new_ctx))
-- return PTR_ERR(new_ctx);
-- } else {
-- if (!curr_ctx ||
-- (curr_ctx->replace_state ==
-- IEEE80211_CHANCTX_WILL_BE_REPLACED) ||
-- !list_empty(&curr_ctx->reserved_links)) {
-- /*
-- * Another link already requested this context
-- * for a reservation. Find another one hoping
-- * all links assigned to it will also switch
-- * soon enough.
-- *
-- * TODO: This needs a little more work as some
-- * cases (more than 2 chanctx capable devices)
-- * may fail which could otherwise succeed
-- * provided some channel context juggling was
-- * performed.
-- *
-- * Consider ctx1..3, link1..6, each ctx has 2
-- * links. link1 and link2 from ctx1 request new
-- * different chandefs starting 2 in-place
-- * reserations with ctx4 and ctx5 replacing
-- * ctx1 and ctx2 respectively. Next link5 and
-- * link6 from ctx3 reserve ctx4. If link3 and
-- * link4 remain on ctx2 as they are then this
-- * fails unless `replace_ctx` from ctx5 is
-- * replaced with ctx3.
-- */
-- list_for_each_entry(ctx, &local->chanctx_list,
-- list) {
-- if (ctx->replace_state !=
-- IEEE80211_CHANCTX_REPLACE_NONE)
-- continue;
--
-- if (!list_empty(&ctx->reserved_links))
-- continue;
--
-- curr_ctx = ctx;
-- break;
-- }
-- }
--
-- /*
-- * If that's true then all available contexts already
-- * have reservations and cannot be used.
-- */
-- if (!curr_ctx ||
-- (curr_ctx->replace_state ==
-- IEEE80211_CHANCTX_WILL_BE_REPLACED) ||
-- !list_empty(&curr_ctx->reserved_links))
-- return -EBUSY;
--
-- new_ctx = ieee80211_alloc_chanctx(local, chanreq, mode, -1);
-- if (!new_ctx)
-- return -ENOMEM;
--
-- new_ctx->replace_ctx = curr_ctx;
-- new_ctx->replace_state =
-- IEEE80211_CHANCTX_REPLACES_OTHER;
--
-- curr_ctx->replace_ctx = new_ctx;
-- curr_ctx->replace_state =
-- IEEE80211_CHANCTX_WILL_BE_REPLACED;
--
-- list_add_rcu(&new_ctx->list, &local->chanctx_list);
-- }
-+ else
-+ new_ctx = ieee80211_replace_chanctx(local, chanreq,
-+ mode, curr_ctx);
-+ if (IS_ERR(new_ctx))
-+ return PTR_ERR(new_ctx);
- }
-
- list_add(&link->reserved_chanctx_list, &new_ctx->reserved_links);
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Wed, 5 Jun 2024 18:39:55 +0200
-Subject: [PATCH] wifi: mac80211: add wiphy radio assignment and
- validation
-
-Validate number of channels and interface combinations per radio.
-Assign each channel context to a radio.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/chan.c
-+++ b/net/mac80211/chan.c
-@@ -680,14 +680,15 @@ static int ieee80211_add_chanctx(struct
- static struct ieee80211_chanctx *
- ieee80211_new_chanctx(struct ieee80211_local *local,
- const struct ieee80211_chan_req *chanreq,
-- enum ieee80211_chanctx_mode mode)
-+ enum ieee80211_chanctx_mode mode,
-+ int radio_idx)
- {
- struct ieee80211_chanctx *ctx;
- int err;
-
- lockdep_assert_wiphy(local->hw.wiphy);
-
-- ctx = ieee80211_alloc_chanctx(local, chanreq, mode, -1);
-+ ctx = ieee80211_alloc_chanctx(local, chanreq, mode, radio_idx);
- if (!ctx)
- return ERR_PTR(-ENOMEM);
-
-@@ -1040,6 +1041,8 @@ ieee80211_replace_chanctx(struct ieee802
- struct ieee80211_chanctx *curr_ctx)
- {
- struct ieee80211_chanctx *new_ctx, *ctx;
-+ struct wiphy *wiphy = local->hw.wiphy;
-+ const struct wiphy_radio *radio;
-
- if (!curr_ctx || (curr_ctx->replace_state ==
- IEEE80211_CHANCTX_WILL_BE_REPLACED) ||
-@@ -1069,6 +1072,12 @@ ieee80211_replace_chanctx(struct ieee802
- if (!list_empty(&ctx->reserved_links))
- continue;
-
-+ if (ctx->conf.radio_idx >= 0) {
-+ radio = &wiphy->radio[ctx->conf.radio_idx];
-+ if (!cfg80211_radio_chandef_valid(radio, &chanreq->oper))
-+ continue;
-+ }
-+
- curr_ctx = ctx;
- break;
- }
-@@ -1098,6 +1107,34 @@ ieee80211_replace_chanctx(struct ieee802
- return new_ctx;
- }
-
-+static bool
-+ieee80211_find_available_radio(struct ieee80211_local *local,
-+ const struct ieee80211_chan_req *chanreq,
-+ int *radio_idx)
-+{
-+ struct wiphy *wiphy = local->hw.wiphy;
-+ const struct wiphy_radio *radio;
-+ int i;
-+
-+ *radio_idx = -1;
-+ if (!wiphy->n_radio)
-+ return true;
-+
-+ for (i = 0; i < wiphy->n_radio; i++) {
-+ radio = &wiphy->radio[i];
-+ if (!cfg80211_radio_chandef_valid(radio, &chanreq->oper))
-+ continue;
-+
-+ if (!ieee80211_can_create_new_chanctx(local, i))
-+ continue;
-+
-+ *radio_idx = i;
-+ return true;
-+ }
-+
-+ return false;
-+}
-+
- int ieee80211_link_reserve_chanctx(struct ieee80211_link_data *link,
- const struct ieee80211_chan_req *chanreq,
- enum ieee80211_chanctx_mode mode,
-@@ -1106,6 +1143,7 @@ int ieee80211_link_reserve_chanctx(struc
- struct ieee80211_sub_if_data *sdata = link->sdata;
- struct ieee80211_local *local = sdata->local;
- struct ieee80211_chanctx *new_ctx, *curr_ctx;
-+ int radio_idx;
-
- lockdep_assert_wiphy(local->hw.wiphy);
-
-@@ -1115,8 +1153,10 @@ 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))
-- new_ctx = ieee80211_new_chanctx(local, chanreq, mode);
-+ if (ieee80211_can_create_new_chanctx(local, -1) &&
-+ ieee80211_find_available_radio(local, chanreq, &radio_idx))
-+ new_ctx = ieee80211_new_chanctx(local, chanreq, mode,
-+ radio_idx);
- else
- new_ctx = ieee80211_replace_chanctx(local, chanreq,
- mode, curr_ctx);
-@@ -1724,6 +1764,7 @@ int ieee80211_link_use_channel(struct ie
- struct ieee80211_local *local = sdata->local;
- struct ieee80211_chanctx *ctx;
- u8 radar_detect_width = 0;
-+ int radio_idx;
- int ret;
-
- lockdep_assert_wiphy(local->hw.wiphy);
-@@ -1751,8 +1792,12 @@ int ieee80211_link_use_channel(struct ie
- __ieee80211_link_release_channel(link);
-
- ctx = ieee80211_find_chanctx(local, chanreq, mode);
-- if (!ctx)
-- ctx = ieee80211_new_chanctx(local, chanreq, mode);
-+ if (!ctx) {
-+ if (!ieee80211_find_available_radio(local, chanreq, &radio_idx))
-+ ctx = ERR_PTR(-EBUSY);
-+ else
-+ ctx = ieee80211_new_chanctx(local, chanreq, mode, radio_idx);
-+ }
- if (IS_ERR(ctx)) {
- ret = PTR_ERR(ctx);
- goto out;
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Tue, 11 Jun 2024 09:02:55 +0200
-Subject: [PATCH] wifi: mac80211_hwsim: add support for multi-radio wiphy
-
-This registers one wiphy radio per supported band. Number of different
-channels is set per radio.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/drivers/net/wireless/virtual/mac80211_hwsim.c
-+++ b/drivers/net/wireless/virtual/mac80211_hwsim.c
-@@ -69,6 +69,10 @@ static bool mlo;
- module_param(mlo, bool, 0444);
- MODULE_PARM_DESC(mlo, "Support MLO");
-
-+static bool multi_radio;
-+module_param(multi_radio, bool, 0444);
-+MODULE_PARM_DESC(mlo, "Support Multiple Radios per wiphy");
-+
- /**
- * enum hwsim_regtest - the type of regulatory tests we offer
- *
-@@ -669,6 +673,10 @@ struct mac80211_hwsim_data {
- struct ieee80211_iface_limit if_limits[3];
- int n_if_limits;
-
-+ struct ieee80211_iface_combination if_combination_radio;
-+ struct wiphy_radio_freq_range radio_range[NUM_NL80211_BANDS];
-+ struct wiphy_radio radio[NUM_NL80211_BANDS];
-+
- u32 ciphers[ARRAY_SIZE(hwsim_ciphers)];
-
- struct mac_address addresses[2];
-@@ -917,6 +925,7 @@ static const struct nla_policy hwsim_gen
- [HWSIM_ATTR_MLO_SUPPORT] = { .type = NLA_FLAG },
- [HWSIM_ATTR_PMSR_SUPPORT] = NLA_POLICY_NESTED(hwsim_pmsr_capa_policy),
- [HWSIM_ATTR_PMSR_RESULT] = NLA_POLICY_NESTED(hwsim_pmsr_peers_result_policy),
-+ [HWSIM_ATTR_MULTI_RADIO] = { .type = NLA_FLAG },
- };
-
- #if IS_REACHABLE(CONFIG_VIRTIO)
-@@ -4007,6 +4016,7 @@ struct hwsim_new_radio_params {
- bool reg_strict;
- bool p2p_device;
- bool use_chanctx;
-+ bool multi_radio;
- bool destroy_on_close;
- const char *hwname;
- bool no_vif;
-@@ -4083,6 +4093,12 @@ static int append_radio_msg(struct sk_bu
- return ret;
- }
-
-+ if (param->multi_radio) {
-+ ret = nla_put_flag(skb, HWSIM_ATTR_MULTI_RADIO);
-+ if (ret < 0)
-+ return ret;
-+ }
-+
- if (param->hwname) {
- ret = nla_put(skb, HWSIM_ATTR_RADIO_NAME,
- strlen(param->hwname), param->hwname);
-@@ -5099,6 +5115,7 @@ static int mac80211_hwsim_new_radio(stru
- struct net *net;
- int idx, i;
- int n_limits = 0;
-+ int n_bands = 0;
-
- if (WARN_ON(param->channels > 1 && !param->use_chanctx))
- return -EINVAL;
-@@ -5202,22 +5219,22 @@ static int mac80211_hwsim_new_radio(stru
- n_limits++;
- }
-
-+ data->if_combination.radar_detect_widths =
-+ BIT(NL80211_CHAN_WIDTH_5) |
-+ BIT(NL80211_CHAN_WIDTH_10) |
-+ BIT(NL80211_CHAN_WIDTH_20_NOHT) |
-+ BIT(NL80211_CHAN_WIDTH_20) |
-+ BIT(NL80211_CHAN_WIDTH_40) |
-+ BIT(NL80211_CHAN_WIDTH_80) |
-+ BIT(NL80211_CHAN_WIDTH_160);
-+
- if (data->use_chanctx) {
- hw->wiphy->max_scan_ssids = 255;
- hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
- hw->wiphy->max_remain_on_channel_duration = 1000;
-- data->if_combination.radar_detect_widths = 0;
- data->if_combination.num_different_channels = data->channels;
- } else {
- data->if_combination.num_different_channels = 1;
-- data->if_combination.radar_detect_widths =
-- BIT(NL80211_CHAN_WIDTH_5) |
-- BIT(NL80211_CHAN_WIDTH_10) |
-- BIT(NL80211_CHAN_WIDTH_20_NOHT) |
-- BIT(NL80211_CHAN_WIDTH_20) |
-- BIT(NL80211_CHAN_WIDTH_40) |
-- BIT(NL80211_CHAN_WIDTH_80) |
-- BIT(NL80211_CHAN_WIDTH_160);
- }
-
- if (!n_limits) {
-@@ -5333,6 +5350,9 @@ static int mac80211_hwsim_new_radio(stru
-
- for (band = NL80211_BAND_2GHZ; band < NUM_NL80211_BANDS; band++) {
- struct ieee80211_supported_band *sband = &data->bands[band];
-+ struct wiphy_radio_freq_range *radio_range;
-+ const struct ieee80211_channel *c;
-+ struct wiphy_radio *radio;
-
- sband->band = band;
-
-@@ -5406,8 +5426,36 @@ static int mac80211_hwsim_new_radio(stru
- mac80211_hwsim_sband_capab(sband);
-
- hw->wiphy->bands[band] = sband;
-+
-+ if (!param->multi_radio)
-+ continue;
-+
-+ c = sband->channels;
-+ radio_range = &data->radio_range[n_bands];
-+ radio_range->start_freq = ieee80211_channel_to_khz(c) - 10000;
-+
-+ c += sband->n_channels - 1;
-+ radio_range->end_freq = ieee80211_channel_to_khz(c) + 10000;
-+
-+ radio = &data->radio[n_bands++];
-+ radio->freq_range = radio_range;
-+ radio->n_freq_range = 1;
-+ radio->iface_combinations = &data->if_combination_radio;
-+ radio->n_iface_combinations = 1;
- }
-
-+ if (param->multi_radio) {
-+ hw->wiphy->radio = data->radio;
-+ hw->wiphy->n_radio = n_bands;
-+
-+ memcpy(&data->if_combination_radio, &data->if_combination,
-+ sizeof(data->if_combination));
-+ data->if_combination.num_different_channels *= n_bands;
-+ }
-+
-+ if (data->use_chanctx)
-+ data->if_combination.radar_detect_widths = 0;
-+
- /* By default all radios belong to the first group */
- data->group = 1;
- mutex_init(&data->mutex);
-@@ -6025,6 +6073,9 @@ static int hwsim_new_radio_nl(struct sk_
- else
- param.use_chanctx = (param.channels > 1);
-
-+ if (info->attrs[HWSIM_ATTR_MULTI_RADIO])
-+ param.multi_radio = true;
-+
- if (info->attrs[HWSIM_ATTR_REG_HINT_ALPHA2])
- param.reg_alpha2 =
- nla_data(info->attrs[HWSIM_ATTR_REG_HINT_ALPHA2]);
-@@ -6105,7 +6156,7 @@ static int hwsim_new_radio_nl(struct sk_
-
- param.mlo = info->attrs[HWSIM_ATTR_MLO_SUPPORT];
-
-- if (param.mlo)
-+ if (param.mlo || param.multi_radio)
- param.use_chanctx = true;
-
- if (info->attrs[HWSIM_ATTR_RADIO_NAME]) {
-@@ -6802,7 +6853,8 @@ static int __init init_mac80211_hwsim(vo
-
- param.p2p_device = support_p2p_device;
- param.mlo = mlo;
-- param.use_chanctx = channels > 1 || mlo;
-+ param.multi_radio = multi_radio;
-+ param.use_chanctx = channels > 1 || mlo || multi_radio;
- param.iftypes = HWSIM_IFTYPE_SUPPORT_MASK;
- if (param.p2p_device)
- param.iftypes |= BIT(NL80211_IFTYPE_P2P_DEVICE);
---- a/drivers/net/wireless/virtual/mac80211_hwsim.h
-+++ b/drivers/net/wireless/virtual/mac80211_hwsim.h
-@@ -157,6 +157,9 @@ enum hwsim_commands {
- * to provide details about peer measurement request (nl80211_peer_measurement_attrs)
- * @HWSIM_ATTR_PMSR_RESULT: nested attributed used with %HWSIM_CMD_REPORT_PMSR
- * to provide peer measurement result (nl80211_peer_measurement_attrs)
-+ * @HWSIM_ATTR_MULTI_RADIO: Register multiple wiphy radios (flag).
-+ * Adds one radio for each band. Number of supported channels will be set for
-+ * each radio instead of for the wiphy.
- * @__HWSIM_ATTR_MAX: enum limit
- */
- enum hwsim_attrs {
-@@ -189,6 +192,7 @@ enum hwsim_attrs {
- HWSIM_ATTR_PMSR_SUPPORT,
- HWSIM_ATTR_PMSR_REQUEST,
- HWSIM_ATTR_PMSR_RESULT,
-+ HWSIM_ATTR_MULTI_RADIO,
- __HWSIM_ATTR_MAX,
- };
- #define HWSIM_ATTR_MAX (__HWSIM_ATTR_MAX - 1)
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
-@@ -651,21 +651,6 @@ static int wiphy_verify_combinations(str
+@@ -654,21 +654,6 @@ static int wiphy_verify_combinations(str
c->limits[j].max > 1))
return -EINVAL;
PKG_DRIVERS += \
- rtlwifi rtlwifi-pci rtlwifi-btcoexist rtlwifi-usb rtl8192c-common \
+ rtlwifi rtlwifi-pci rtlwifi-btcoexist rtlwifi-usb rtl8192c-common rtl8192d-common \
rtl8192ce rtl8192se rtl8192de rtl8192cu rtl8723-common rtl8723be rtl8723bs rtl8821ae \
rtl8xxxu rtw88 rtw88-pci rtw88-usb rtw88-sdio rtw88-8821c rtw88-8822b rtw88-8822c \
- rtw88-8723d rtw88-8821ce rtw88-8821cu rtw88-8822be rtw88-8822bu \
+ rtw88-8723x rtw88-8723d rtw88-8821ce rtw88-8821cu rtw88-8822be rtw88-8822bu \
rtw88-8822ce rtw88-8822cu rtw88-8723de rtw88-8723ds rtw88-8723du \
- rtw89 rtw89-pci rtw89-8851be rtw89-8852ae rtw89-8852be rtw89-8852ce
+ rtw89 rtw89-pci rtw89-8851be rtw89-8852ae rtw89-8852b-common rtw89-8852be rtw89-8852ce
config-$(call config_package,rtlwifi) += RTL_CARDS RTLWIFI
config-$(call config_package,rtlwifi-pci) += RTLWIFI_PCI
config-$(call config_package,rtl8192c-common) += RTL8192C_COMMON
config-$(call config_package,rtl8192ce) += RTL8192CE
config-$(call config_package,rtl8192se) += RTL8192SE
+config-$(call config_package,rtl8192d-common) += RTL8192D_COMMON
config-$(call config_package,rtl8192de) += RTL8192DE
config-$(call config_package,rtl8192cu) += RTL8192CU
config-$(call config_package,rtl8821ae) += RTL8821AE
config-$(call config_package,rtw88-8822c) += RTW88_8822C
config-$(call config_package,rtw88-8822ce) += RTW88_8822CE
config-$(call config_package,rtw88-8822cu) += RTW88_8822CU
+config-$(call config_package,rtw88-8723x) += RTW88_8723X
config-$(call config_package,rtw88-8723d) += RTW88_8723D
config-$(call config_package,rtw88-8723de) += RTW88_8723DE
config-$(call config_package,rtw88-8723ds) += RTW88_8723DS
config-$(call config_package,rtw89-pci) += RTW89_PCI
config-$(call config_package,rtw89-8851be) += RTW89_8851B RTW89_8851BE
config-$(call config_package,rtw89-8852ae) += RTW89_8852A RTW89_8852AE
+config-$(call config_package,rtw89-8852b-common) += RTW89_8852B_COMMON
config-$(call config_package,rtw89-8852be) += RTW89_8852B RTW89_8852BE
config-$(call config_package,rtw89-8852ce) += RTW89_8852C RTW89_8852CE
config-$(CONFIG_PACKAGE_RTW89_DEBUG) += RTW89_DEBUG
AUTOLOAD:=$(call AutoProbe,rtl8192se)
endef
+define KernelPackage/rtl8192d-common
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Realtek RTL8192DE/RTL8192DU common support module
+ DEPENDS+= +kmod-rtlwifi
+ FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtlwifi/rtl8192d/rtl8192d-common.ko
+ HIDDEN:=1
+endef
+
define KernelPackage/rtl8192de
$(call KernelPackage/mac80211/Default)
TITLE:=Realtek RTL8192DE/RTL8188DE support
- DEPENDS+= +kmod-rtlwifi-pci +rtl8192de-firmware
+ DEPENDS+= +kmod-rtlwifi-pci +kmod-rtl8192d-common +rtl8192de-firmware
FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtlwifi/rtl8192de/rtl8192de.ko
AUTOLOAD:=$(call AutoProbe,rtl8192de)
endef
HIDDEN:=1
endef
+define KernelPackage/rtw88-8723x
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Realtek RTL8723x family support
+ DEPENDS+= +kmod-rtw88
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8723x.ko
+ AUTOLOAD:=$(call AutoProbe,rtw88_8723x)
+ HIDDEN:=1
+endef
+
define KernelPackage/rtw88-8723d
$(call KernelPackage/mac80211/Default)
TITLE:=Realtek RTL8723D family support
- DEPENDS+= +kmod-rtw88 +rtl8723de-firmware
+ DEPENDS+= +kmod-rtw88-8723x +rtl8723de-firmware
FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8723d.ko
AUTOLOAD:=$(call AutoProbe,rtw88_8723d)
HIDDEN:=1
AUTOLOAD:=$(call AutoProbe,rtw89_8852ae)
endef
+define KernelPackage/rtw89-8852b-common
+ $(call KernelPackage/mac80211/Default)
+ TITLE:=Realtek RTL8852B family support
+ DEPENDS+= +kmod-rtw89-pci
+ FILES:= \
+ $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw89/rtw89_8852b_common.ko
+ AUTOLOAD:=$(call AutoProbe,rtw89_8852b_common)
+ HIDDEN:=1
+endef
+
define KernelPackage/rtw89-8852be
$(call KernelPackage/mac80211/Default)
TITLE:=Realtek RTL8852BE support
- DEPENDS+= +kmod-rtw89-pci +rtl8852be-firmware
+ DEPENDS+= +kmod-rtw89-8852b-common +rtl8852be-firmware
FILES:= \
$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw89/rtw89_8852b.ko \
$(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw89/rtw89_8852be.ko
--- /dev/null
+--- a/mt76.h
++++ b/mt76.h
+@@ -14,6 +14,7 @@
+ #include <linux/usb.h>
+ #include <linux/average.h>
+ #include <linux/soc/mediatek/mtk_wed.h>
++#include <net/netlink.h>
+ #include <net/mac80211.h>
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(6,6,0)
+ #include <net/page_pool.h>
+@@ -1475,6 +1476,7 @@ static inline void mt76_testmode_reset(s
+ #endif
+ }
+
++extern const struct nla_policy mt76_tm_policy[NUM_MT76_TM_ATTRS];
+
+ /* internal */
+ static inline struct ieee80211_hw *
+--- a/mt7603/main.c
++++ b/mt7603/main.c
+@@ -23,7 +23,7 @@ mt7603_start(struct ieee80211_hw *hw)
+ }
+
+ static void
+-mt7603_stop(struct ieee80211_hw *hw)
++mt7603_stop(struct ieee80211_hw *hw, bool suspend)
+ {
+ struct mt7603_dev *dev = hw->priv;
+
+--- a/mt7615/main.c
++++ b/mt7615/main.c
+@@ -91,7 +91,7 @@ out:
+ return ret;
+ }
+
+-static void mt7615_stop(struct ieee80211_hw *hw)
++static void mt7615_stop(struct ieee80211_hw *hw, bool suspend)
+ {
+ struct mt7615_dev *dev = mt7615_hw_dev(hw);
+ struct mt7615_phy *phy = mt7615_hw_phy(hw);
+--- a/mt7615/usb.c
++++ b/mt7615/usb.c
+@@ -79,7 +79,7 @@ static void mt7663u_copy(struct mt76_dev
+ mutex_unlock(&usb->usb_ctrl_mtx);
+ }
+
+-static void mt7663u_stop(struct ieee80211_hw *hw)
++static void mt7663u_stop(struct ieee80211_hw *hw, bool suspend)
+ {
+ struct mt7615_phy *phy = mt7615_hw_phy(hw);
+ struct mt7615_dev *dev = hw->priv;
+--- a/mt76x0/pci.c
++++ b/mt76x0/pci.c
+@@ -44,7 +44,7 @@ static void mt76x0e_stop_hw(struct mt76x
+ mt76_clear(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_RX_DMA_EN);
+ }
+
+-static void mt76x0e_stop(struct ieee80211_hw *hw)
++static void mt76x0e_stop(struct ieee80211_hw *hw, bool suspend)
+ {
+ struct mt76x02_dev *dev = hw->priv;
+
+--- a/mt76x0/usb.c
++++ b/mt76x0/usb.c
+@@ -77,7 +77,7 @@ static void mt76x0u_cleanup(struct mt76x
+ mt76u_queues_deinit(&dev->mt76);
+ }
+
+-static void mt76x0u_stop(struct ieee80211_hw *hw)
++static void mt76x0u_stop(struct ieee80211_hw *hw, bool suspend)
+ {
+ struct mt76x02_dev *dev = hw->priv;
+
+--- a/mt76x2/pci_main.c
++++ b/mt76x2/pci_main.c
+@@ -24,7 +24,7 @@ mt76x2_start(struct ieee80211_hw *hw)
+ }
+
+ static void
+-mt76x2_stop(struct ieee80211_hw *hw)
++mt76x2_stop(struct ieee80211_hw *hw, bool suspend)
+ {
+ struct mt76x02_dev *dev = hw->priv;
+
+--- a/mt76x2/usb_main.c
++++ b/mt76x2/usb_main.c
+@@ -22,7 +22,7 @@ static int mt76x2u_start(struct ieee8021
+ return 0;
+ }
+
+-static void mt76x2u_stop(struct ieee80211_hw *hw)
++static void mt76x2u_stop(struct ieee80211_hw *hw, bool suspend)
+ {
+ struct mt76x02_dev *dev = hw->priv;
+
+--- a/mt7915/main.c
++++ b/mt7915/main.c
+@@ -108,7 +108,7 @@ static int mt7915_start(struct ieee80211
+ return ret;
+ }
+
+-static void mt7915_stop(struct ieee80211_hw *hw)
++static void mt7915_stop(struct ieee80211_hw *hw, bool suspend)
+ {
+ struct mt7915_dev *dev = mt7915_hw_dev(hw);
+ struct mt7915_phy *phy = mt7915_hw_phy(hw);
+--- a/mt7915/mcu.c
++++ b/mt7915/mcu.c
+@@ -335,7 +335,7 @@ mt7915_mcu_cca_finish(void *priv, u8 *ma
+ if (!vif->bss_conf.color_change_active || vif->type == NL80211_IFTYPE_STATION)
+ return;
+
+- ieee80211_color_change_finish(vif);
++ ieee80211_color_change_finish(vif, 0);
+ }
+
+ static void
+--- a/mt7921/main.c
++++ b/mt7921/main.c
+@@ -268,7 +268,7 @@ static int mt7921_start(struct ieee80211
+ return err;
+ }
+
+-static void mt7921_stop(struct ieee80211_hw *hw)
++static void mt7921_stop(struct ieee80211_hw *hw, bool suspend)
+ {
+ struct mt792x_dev *dev = mt792x_hw_dev(hw);
+ int err = 0;
+@@ -281,7 +281,7 @@ static void mt7921_stop(struct ieee80211
+ return;
+ }
+
+- mt792x_stop(hw);
++ mt792x_stop(hw, false);
+ }
+
+ static int
+--- a/mt792x.h
++++ b/mt792x.h
+@@ -337,7 +337,7 @@ static inline bool mt792x_dma_need_reini
+ #define mt792x_mutex_release(dev) \
+ mt76_connac_mutex_release(&(dev)->mt76, &(dev)->pm)
+
+-void mt792x_stop(struct ieee80211_hw *hw);
++void mt792x_stop(struct ieee80211_hw *hw, bool suspend);
+ void mt792x_pm_wake_work(struct work_struct *work);
+ void mt792x_pm_power_save_work(struct work_struct *work);
+ void mt792x_reset(struct mt76_dev *mdev);
+@@ -457,7 +457,7 @@ void mt792xu_wr(struct mt76_dev *dev, u3
+ u32 mt792xu_rmw(struct mt76_dev *dev, u32 addr, u32 mask, u32 val);
+ void mt792xu_copy(struct mt76_dev *dev, u32 offset, const void *data, int len);
+ void mt792xu_disconnect(struct usb_interface *usb_intf);
+-void mt792xu_stop(struct ieee80211_hw *hw);
++void mt792xu_stop(struct ieee80211_hw *hw, bool suspend);
+
+ static inline void
+ mt792x_skb_add_usb_sdio_hdr(struct mt792x_dev *dev, struct sk_buff *skb,
+--- a/mt792x_core.c
++++ b/mt792x_core.c
+@@ -113,7 +113,7 @@ void mt792x_tx(struct ieee80211_hw *hw,
+ }
+ EXPORT_SYMBOL_GPL(mt792x_tx);
+
+-void mt792x_stop(struct ieee80211_hw *hw)
++void mt792x_stop(struct ieee80211_hw *hw, bool suspend)
+ {
+ struct mt792x_dev *dev = mt792x_hw_dev(hw);
+ struct mt792x_phy *phy = mt792x_hw_phy(hw);
+--- a/mt792x_usb.c
++++ b/mt792x_usb.c
+@@ -285,12 +285,12 @@ int mt792xu_init_reset(struct mt792x_dev
+ }
+ EXPORT_SYMBOL_GPL(mt792xu_init_reset);
+
+-void mt792xu_stop(struct ieee80211_hw *hw)
++void mt792xu_stop(struct ieee80211_hw *hw, bool suspend)
+ {
+ struct mt792x_dev *dev = mt792x_hw_dev(hw);
+
+ mt76u_stop_tx(&dev->mt76);
+- mt792x_stop(hw);
++ mt792x_stop(hw, false);
+ }
+ EXPORT_SYMBOL_GPL(mt792xu_stop);
+
+--- a/mt7996/main.c
++++ b/mt7996/main.c
+@@ -93,7 +93,7 @@ static int mt7996_start(struct ieee80211
+ return ret;
+ }
+
+-static void mt7996_stop(struct ieee80211_hw *hw)
++static void mt7996_stop(struct ieee80211_hw *hw, bool suspend)
+ {
+ struct mt7996_dev *dev = mt7996_hw_dev(hw);
+ struct mt7996_phy *phy = mt7996_hw_phy(hw);
+--- a/mt7996/mcu.c
++++ b/mt7996/mcu.c
+@@ -421,7 +421,7 @@ mt7996_mcu_cca_finish(void *priv, u8 *ma
+ if (!vif->bss_conf.color_change_active || vif->type == NL80211_IFTYPE_STATION)
+ return;
+
+- ieee80211_color_change_finish(vif);
++ ieee80211_color_change_finish(vif, 0);
+ }
+
+ static void
+--- a/testmode.h
++++ b/testmode.h
+@@ -193,6 +193,4 @@ enum mt76_testmode_tx_mode {
+ MT76_TM_TX_MODE_MAX = NUM_MT76_TM_TX_MODES - 1,
+ };
+
+-extern const struct nla_policy mt76_tm_policy[NUM_MT76_TM_ATTRS];
+-
+ #endif
+}
--- a/mac80211.c
+++ b/mac80211.c
+@@ -159,7 +159,7 @@ fwcmd_fail:
+ return rc;
+ }
+
+-static void mwl_mac80211_stop(struct ieee80211_hw *hw)
++static void mwl_mac80211_stop(struct ieee80211_hw *hw, bool suspend)
+ {
+ mwl_fwcmd_radio_disable(hw);
+
@@ -368,15 +368,15 @@ static void mwl_mac80211_bss_info_change
}
}