mac80211: update to version 6.11.2

This commit is contained in:
DHDAXCW 2024-10-11 02:53:17 +00:00
parent 95fd4e27af
commit c7ae8f65f0
124 changed files with 3804 additions and 3543 deletions

View File

@ -10,10 +10,10 @@ include $(INCLUDE_DIR)/kernel.mk
PKG_NAME:=mac80211
PKG_VERSION:=6.9.9
PKG_VERSION:=6.11.2
PKG_RELEASE:=1
PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources/
PKG_HASH:=3417da091a57c7b1c145d44c1fae9f1e0bac6d0c8ad61b37e57b0a802eeb2837
PKG_HASH:=700ea5abef8dde9e3c6df2acd32ff443da735d773d56db9a80269e2237549b34
PKG_SOURCE:=backports-$(PKG_VERSION).tar.xz
PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/backports-$(PKG_VERSION)

View File

@ -82,7 +82,7 @@
help
--- a/local-symbols
+++ b/local-symbols
@@ -94,6 +94,7 @@ ADM8211=
@@ -96,6 +96,7 @@ ADM8211=
ATH_COMMON=
WLAN_VENDOR_ATH=
ATH_DEBUG=

View File

@ -1,6 +1,6 @@
--- 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.
@ -21,9 +21,9 @@
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 {
@ -37,9 +37,9 @@
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=

View File

@ -14,7 +14,7 @@ Signed-off-by: Sven Eckelmann <sven@open-mesh.com>
--- 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);

View File

@ -1,6 +1,6 @@
--- 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;
}
@ -22,7 +22,7 @@
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;

View File

@ -1,626 +0,0 @@
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;

View File

@ -16,7 +16,7 @@ Signed-off-by: Mathias Kresin <dev@kresin.me>
--- 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;

View File

@ -26,7 +26,7 @@ Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
#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);

View File

@ -93,9 +93,9 @@ Signed-off-by: Robert Marko <robimarko@gmail.com>
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);
@ -103,6 +103,8 @@ Signed-off-by: Robert Marko <robimarko@gmail.com>
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,

View File

@ -1,24 +0,0 @@
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);

View File

@ -21,7 +21,7 @@ Signed-off-by: Robert Marko <robimarko@gmail.com>
--- 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.
@ -34,7 +34,7 @@ Signed-off-by: Robert Marko <robimarko@gmail.com>
+ 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
@ -56,11 +56,11 @@ Signed-off-by: Robert Marko <robimarko@gmail.com>
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=

View File

@ -31,7 +31,7 @@ Signed-off-by: Robert Marko <robimarko@gmail.com>
{
.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;
@ -41,7 +41,7 @@ Signed-off-by: Robert Marko <robimarko@gmail.com>
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;

View File

@ -23,7 +23,7 @@ Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
--- 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;
}
@ -158,7 +158,7 @@ Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
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,
@ -172,7 +172,7 @@ Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
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)
@ -206,7 +206,7 @@ Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
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);
@ -215,7 +215,7 @@ Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
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)){
@ -224,7 +224,7 @@ Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
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,
@ -279,7 +279,7 @@ Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
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;
@ -287,7 +287,7 @@ Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
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;

View File

@ -0,0 +1,924 @@
From patchwork Thu Sep 5 02:35:08 2024
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
X-Patchwork-Submitter: Kang Yang <quic_kangyang@quicinc.com>
X-Patchwork-Id: 13791624
X-Patchwork-Delegate: kvalo@adurom.com
Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com
[205.220.180.131])
(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
(No client certificate requested)
by smtp.subspace.kernel.org (Postfix) with ESMTPS id D313D33CFC
for <linux-wireless@vger.kernel.org>; Thu, 5 Sep 2024 02:36:17 +0000 (UTC)
Authentication-Results: smtp.subspace.kernel.org;
arc=none smtp.client-ip=205.220.180.131
ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;
t=1725503779; cv=none;
b=blv4mH95IN2AR7Rt90gw/V7DnZRtr3upgAP50X6ew3jh0CusPG6/OTO9CSJVthJnqHU3Y3GT88jaeMzb9+f2xzqgl7+E35TmwN3uf6dFmbp7CD8LL0W6xu76ZZgFGxzRspv9YoVy/fydZY6I4JRc2faWqI540+n9bHEXdSJTZMM=
ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org;
s=arc-20240116; t=1725503779; c=relaxed/simple;
bh=vjzfDc6UXtw2Li6Q3bAgcW0K1rcTpi3dAxkQgbT5ogI=;
h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References:
MIME-Version:Content-Type;
b=VMgF0PfIOoXmfB6EARb/O+dooXutjAm/cnemJ0RC7uc8TSIAusH1ffc6jF1XndEp+nPTWnuMQ5/d1cE/bPeIvSTxrtWaUepnKNjQDrNKm4NrqmjR446CT9t0VHG16RZ1cmCmU74qXnfgus4XfTqD093lc1N5Q/YRh/kwmcCzxhY=
ARC-Authentication-Results: i=1; smtp.subspace.kernel.org;
dmarc=pass (p=none dis=none) header.from=quicinc.com;
spf=pass smtp.mailfrom=quicinc.com;
dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com
header.b=E5hktrdm; arc=none smtp.client-ip=205.220.180.131
Authentication-Results: smtp.subspace.kernel.org;
dmarc=pass (p=none dis=none) header.from=quicinc.com
Authentication-Results: smtp.subspace.kernel.org;
spf=pass smtp.mailfrom=quicinc.com
Authentication-Results: smtp.subspace.kernel.org;
dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com
header.b="E5hktrdm"
Received: from pps.filterd (m0279869.ppops.net [127.0.0.1])
by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id
484MRZwS008193;
Thu, 5 Sep 2024 02:36:12 GMT
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h=
cc:content-transfer-encoding:content-type:date:from:in-reply-to
:message-id:mime-version:references:subject:to; s=qcppdkim1; bh=
No6X3gHpioHamjfMDccV8LJEZBGk/uDqbZ/fuGUTvJM=; b=E5hktrdmmOb3KcP6
Qi3M5Y06Yd8RxNJTps8WMEoXZ7xzROVuhmRmlG/mw21NjBMTTMgtjcaen/n8Anj3
Ash1VFK6s7PrLcwoUT/uui6hzleGE+X9Wh8DJXYnZKKWmeQ+8E0yEzNR0kt9FG0n
S+asFc8VYEJHid6QDNAfM9e4JqJgU3NGXYJBTBM2lpdbqeWU7LEYnVTGCqvOPaH2
K+QDwvNiNeXlqbaxnqCYimUrSDnTbSUoiVxSpTe9/muWWAB+6YuUbXRfTceqgcd1
xFIOE1KrtAowMOk5mO3tn6Tjl7nJzewVUm9hncBRfynP8k2jt1xosMezL42dmb56
a9VWLQ==
Received: from nalasppmta03.qualcomm.com (Global_NAT1.qualcomm.com
[129.46.96.20])
by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 41bt674mq1-1
(version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT);
Thu, 05 Sep 2024 02:36:11 +0000 (GMT)
Received: from nalasex01b.na.qualcomm.com (nalasex01b.na.qualcomm.com
[10.47.209.197])
by NALASPPMTA03.qualcomm.com (8.18.1.2/8.18.1.2) with ESMTPS id
4852aAdV010181
(version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT);
Thu, 5 Sep 2024 02:36:10 GMT
Received: from kangyang.ap.qualcomm.com (10.80.80.8) by
nalasex01b.na.qualcomm.com (10.47.209.197) with Microsoft SMTP Server
(version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id
15.2.1544.9; Wed, 4 Sep 2024 19:36:09 -0700
From: Kang Yang <quic_kangyang@quicinc.com>
To: <ath12k@lists.infradead.org>
CC: <linux-wireless@vger.kernel.org>, <quic_kangyang@quicinc.com>
Subject: [PATCH v3 1/4] wifi: ath12k: add configure country code for WCN7850
Date: Thu, 5 Sep 2024 10:35:08 +0800
Message-ID: <20240905023511.362-2-quic_kangyang@quicinc.com>
X-Mailer: git-send-email 2.34.1.windows.1
In-Reply-To: <20240905023511.362-1-quic_kangyang@quicinc.com>
References: <20240905023511.362-1-quic_kangyang@quicinc.com>
Precedence: bulk
X-Mailing-List: linux-wireless@vger.kernel.org
List-Id: <linux-wireless.vger.kernel.org>
List-Subscribe: <mailto:linux-wireless+subscribe@vger.kernel.org>
List-Unsubscribe: <mailto:linux-wireless+unsubscribe@vger.kernel.org>
MIME-Version: 1.0
X-ClientProxiedBy: nasanex01b.na.qualcomm.com (10.46.141.250) To
nalasex01b.na.qualcomm.com (10.47.209.197)
X-QCInternal: smtphost
X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800
signatures=585085
X-Proofpoint-ORIG-GUID: FzfHe7cZy6IUVu8IKORVKLxkYG9f8WUl
X-Proofpoint-GUID: FzfHe7cZy6IUVu8IKORVKLxkYG9f8WUl
X-Proofpoint-Virus-Version: vendor=baseguard
engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.60.29
definitions=2024-09-05_01,2024-09-04_01,2024-09-02_01
X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0
malwarescore=0 adultscore=0
bulkscore=0 mlxscore=0 impostorscore=0 suspectscore=0 phishscore=0
mlxlogscore=999 lowpriorityscore=0 spamscore=0 clxscore=1015
priorityscore=1501 classifier=spam adjust=0 reason=mlx scancount=1
engine=8.19.0-2407110000 definitions=main-2409050018
From: Wen Gong <quic_wgong@quicinc.com>
Add handler to send WMI_SET_CURRENT_COUNTRY_CMDID to firmware, which
is used for WCN7850 to update country code.
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3
Signed-off-by: Wen Gong <quic_wgong@quicinc.com>
Signed-off-by: Kang Yang <quic_kangyang@quicinc.com>
Acked-by: Jeff Johnson <quic_jjohnson@quicinc.com>
---
drivers/net/wireless/ath/ath12k/wmi.c | 36 +++++++++++++++++++++++++++
drivers/net/wireless/ath/ath12k/wmi.h | 13 ++++++++++
2 files changed, 49 insertions(+)
--- a/drivers/net/wireless/ath/ath12k/wmi.c
+++ b/drivers/net/wireless/ath/ath12k/wmi.c
@@ -171,6 +171,8 @@ static const struct ath12k_wmi_tlv_polic
.min_len = sizeof(struct ath12k_wmi_p2p_noa_info) },
[WMI_TAG_P2P_NOA_EVENT] = {
.min_len = sizeof(struct wmi_p2p_noa_event) },
+ [WMI_TAG_11D_NEW_COUNTRY_EVENT] = {
+ .min_len = sizeof(struct wmi_11d_new_cc_event) },
};
static __le32 ath12k_wmi_tlv_hdr(u32 cmd, u32 len)
@@ -2363,7 +2365,10 @@ int ath12k_wmi_send_scan_start_cmd(struc
cmd->scan_id = cpu_to_le32(arg->scan_id);
cmd->scan_req_id = cpu_to_le32(arg->scan_req_id);
cmd->vdev_id = cpu_to_le32(arg->vdev_id);
- cmd->scan_priority = cpu_to_le32(arg->scan_priority);
+ if (ar->state_11d == ATH12K_11D_PREPARING)
+ arg->scan_priority = WMI_SCAN_PRIORITY_MEDIUM;
+ else
+ arg->scan_priority = WMI_SCAN_PRIORITY_LOW;
cmd->notify_scan_events = cpu_to_le32(arg->notify_scan_events);
ath12k_wmi_copy_scan_event_cntrl_flags(cmd, arg);
@@ -3083,6 +3088,110 @@ out:
return ret;
}
+int ath12k_wmi_send_set_current_country_cmd(struct ath12k *ar,
+ struct wmi_set_current_country_arg *arg)
+{
+ struct ath12k_wmi_pdev *wmi = ar->wmi;
+ struct wmi_set_current_country_cmd *cmd;
+ struct sk_buff *skb;
+ int ret;
+
+ skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));
+ if (!skb)
+ return -ENOMEM;
+
+ cmd = (struct wmi_set_current_country_cmd *)skb->data;
+ cmd->tlv_header =
+ ath12k_wmi_tlv_cmd_hdr(WMI_TAG_SET_CURRENT_COUNTRY_CMD,
+ sizeof(*cmd));
+
+ cmd->pdev_id = cpu_to_le32(ar->pdev->pdev_id);
+ memcpy(&cmd->new_alpha2, &arg->alpha2, sizeof(arg->alpha2));
+ ret = ath12k_wmi_cmd_send(wmi, skb, WMI_SET_CURRENT_COUNTRY_CMDID);
+
+ ath12k_dbg(ar->ab, ATH12K_DBG_WMI,
+ "set current country pdev id %d alpha2 %c%c\n",
+ ar->pdev->pdev_id,
+ arg->alpha2[0],
+ arg->alpha2[1]);
+
+ if (ret) {
+ ath12k_warn(ar->ab,
+ "failed to send WMI_SET_CURRENT_COUNTRY_CMDID: %d\n", ret);
+ dev_kfree_skb(skb);
+ }
+
+ return ret;
+}
+
+int ath12k_wmi_send_11d_scan_start_cmd(struct ath12k *ar,
+ struct wmi_11d_scan_start_arg *arg)
+{
+ struct ath12k_wmi_pdev *wmi = ar->wmi;
+ struct wmi_11d_scan_start_cmd *cmd;
+ struct sk_buff *skb;
+ int ret;
+
+ skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));
+ if (!skb)
+ return -ENOMEM;
+
+ cmd = (struct wmi_11d_scan_start_cmd *)skb->data;
+ cmd->tlv_header =
+ ath12k_wmi_tlv_cmd_hdr(WMI_TAG_11D_SCAN_START_CMD,
+ sizeof(*cmd));
+
+ cmd->vdev_id = cpu_to_le32(arg->vdev_id);
+ cmd->scan_period_msec = cpu_to_le32(arg->scan_period_msec);
+ cmd->start_interval_msec = cpu_to_le32(arg->start_interval_msec);
+ ret = ath12k_wmi_cmd_send(wmi, skb, WMI_11D_SCAN_START_CMDID);
+
+ ath12k_dbg(ar->ab, ATH12K_DBG_WMI,
+ "send 11d scan start vdev id %d period %d ms internal %d ms\n",
+ arg->vdev_id, arg->scan_period_msec,
+ arg->start_interval_msec);
+
+ if (ret) {
+ ath12k_warn(ar->ab,
+ "failed to send WMI_11D_SCAN_START_CMDID: %d\n", ret);
+ dev_kfree_skb(skb);
+ }
+
+ return ret;
+}
+
+int ath12k_wmi_send_11d_scan_stop_cmd(struct ath12k *ar, u32 vdev_id)
+{
+ struct ath12k_wmi_pdev *wmi = ar->wmi;
+ struct wmi_11d_scan_stop_cmd *cmd;
+ struct sk_buff *skb;
+ int ret;
+
+ skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));
+ if (!skb)
+ return -ENOMEM;
+
+ cmd = (struct wmi_11d_scan_stop_cmd *)skb->data;
+ cmd->tlv_header =
+ ath12k_wmi_tlv_cmd_hdr(WMI_TAG_11D_SCAN_STOP_CMD,
+ sizeof(*cmd));
+
+ cmd->vdev_id = cpu_to_le32(vdev_id);
+ ret = ath12k_wmi_cmd_send(wmi, skb, WMI_11D_SCAN_STOP_CMDID);
+
+ ath12k_dbg(ar->ab, ATH12K_DBG_WMI,
+ "send 11d scan stop vdev id %d\n",
+ cmd->vdev_id);
+
+ if (ret) {
+ ath12k_warn(ar->ab,
+ "failed to send WMI_11D_SCAN_STOP_CMDID: %d\n", ret);
+ dev_kfree_skb(skb);
+ }
+
+ return ret;
+}
+
int
ath12k_wmi_send_twt_enable_cmd(struct ath12k *ar, u32 pdev_id)
{
@@ -5668,6 +5777,50 @@ static void ath12k_wmi_op_ep_tx_credits(
wake_up(&ab->wmi_ab.tx_credits_wq);
}
+static int ath12k_reg_11d_new_cc_event(struct ath12k_base *ab, struct sk_buff *skb)
+{
+ const struct wmi_11d_new_cc_event *ev;
+ struct ath12k *ar;
+ struct ath12k_pdev *pdev;
+ const void **tb;
+ int ret, i;
+
+ tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+ if (IS_ERR(tb)) {
+ ret = PTR_ERR(tb);
+ ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
+ return ret;
+ }
+
+ ev = tb[WMI_TAG_11D_NEW_COUNTRY_EVENT];
+ if (!ev) {
+ kfree(tb);
+ ath12k_warn(ab, "failed to fetch 11d new cc ev");
+ return -EPROTO;
+ }
+
+ spin_lock_bh(&ab->base_lock);
+ memcpy(&ab->new_alpha2, &ev->new_alpha2, REG_ALPHA2_LEN);
+ spin_unlock_bh(&ab->base_lock);
+
+ ath12k_dbg(ab, ATH12K_DBG_WMI, "wmi 11d new cc %c%c\n",
+ ab->new_alpha2[0],
+ ab->new_alpha2[1]);
+
+ kfree(tb);
+
+ for (i = 0; i < ab->num_radios; i++) {
+ pdev = &ab->pdevs[i];
+ ar = pdev->ar;
+ ar->state_11d = ATH12K_11D_IDLE;
+ complete(&ar->completed_11d_scan);
+ }
+
+ queue_work(ab->workqueue, &ab->update_11d_work);
+
+ return 0;
+}
+
static void ath12k_wmi_htc_tx_complete(struct ath12k_base *ab,
struct sk_buff *skb)
{
@@ -7269,6 +7422,9 @@ static void ath12k_wmi_op_rx(struct ath1
case WMI_GTK_OFFLOAD_STATUS_EVENTID:
ath12k_wmi_gtk_offload_status_event(ab, skb);
break;
+ case WMI_11D_NEW_COUNTRY_EVENTID:
+ ath12k_reg_11d_new_cc_event(ab, skb);
+ break;
/* TODO: Add remaining events */
default:
ath12k_dbg(ab, ATH12K_DBG_WMI, "Unknown eventid: 0x%x\n", id);
--- a/drivers/net/wireless/ath/ath12k/wmi.h
+++ b/drivers/net/wireless/ath/ath12k/wmi.h
@@ -3859,6 +3859,28 @@ struct wmi_init_country_cmd {
} cc_info;
} __packed;
+struct wmi_11d_scan_start_arg {
+ u32 vdev_id;
+ u32 scan_period_msec;
+ u32 start_interval_msec;
+};
+
+struct wmi_11d_scan_start_cmd {
+ __le32 tlv_header;
+ __le32 vdev_id;
+ __le32 scan_period_msec;
+ __le32 start_interval_msec;
+} __packed;
+
+struct wmi_11d_scan_stop_cmd {
+ __le32 tlv_header;
+ __le32 vdev_id;
+} __packed;
+
+struct wmi_11d_new_cc_event {
+ __le32 new_alpha2;
+} __packed;
+
struct wmi_delba_send_cmd {
__le32 tlv_header;
__le32 vdev_id;
@@ -3944,6 +3966,16 @@ struct ath12k_wmi_eht_rate_set_params {
#define MAX_6G_REG_RULES 5
#define REG_US_5G_NUM_REG_RULES 4
+struct wmi_set_current_country_arg {
+ u8 alpha2[REG_ALPHA2_LEN];
+};
+
+struct wmi_set_current_country_cmd {
+ __le32 tlv_header;
+ __le32 pdev_id;
+ __le32 new_alpha2;
+} __packed;
+
enum wmi_start_event_param {
WMI_VDEV_START_RESP_EVENT = 0,
WMI_VDEV_RESTART_RESP_EVENT,
@@ -5546,11 +5578,17 @@ int ath12k_wmi_send_bcn_offload_control_
u32 vdev_id, u32 bcn_ctrl_op);
int ath12k_wmi_send_init_country_cmd(struct ath12k *ar,
struct ath12k_wmi_init_country_arg *arg);
+int
+ath12k_wmi_send_set_current_country_cmd(struct ath12k *ar,
+ struct wmi_set_current_country_arg *arg);
int ath12k_wmi_peer_rx_reorder_queue_setup(struct ath12k *ar,
int vdev_id, const u8 *addr,
dma_addr_t paddr, u8 tid,
u8 ba_window_size_valid,
u32 ba_window_size);
+int ath12k_wmi_send_11d_scan_start_cmd(struct ath12k *ar,
+ struct wmi_11d_scan_start_arg *arg);
+int ath12k_wmi_send_11d_scan_stop_cmd(struct ath12k *ar, u32 vdev_id);
int
ath12k_wmi_rx_reord_queue_remove(struct ath12k *ar,
struct ath12k_wmi_rx_reorder_queue_remove_arg *arg);
--- a/drivers/net/wireless/ath/ath12k/core.c
+++ b/drivers/net/wireless/ath/ath12k/core.c
@@ -1014,6 +1014,7 @@ void ath12k_core_halt(struct ath12k *ar)
cancel_delayed_work_sync(&ar->scan.timeout);
cancel_work_sync(&ar->regd_update_work);
cancel_work_sync(&ab->rfkill_work);
+ cancel_work_sync(&ab->update_11d_work);
rcu_assign_pointer(ab->pdevs_active[ar->pdev_idx], NULL);
synchronize_rcu();
@@ -1021,6 +1022,34 @@ void ath12k_core_halt(struct ath12k *ar)
idr_init(&ar->txmgmt_idr);
}
+static void ath12k_update_11d(struct work_struct *work)
+{
+ struct ath12k_base *ab = container_of(work, struct ath12k_base, update_11d_work);
+ struct ath12k *ar;
+ struct ath12k_pdev *pdev;
+ struct wmi_set_current_country_arg arg = {};
+ int ret, i;
+
+ spin_lock_bh(&ab->base_lock);
+ memcpy(&arg.alpha2, &ab->new_alpha2, 2);
+ spin_unlock_bh(&ab->base_lock);
+
+ ath12k_dbg(ab, ATH12K_DBG_WMI, "update 11d new cc %c%c\n",
+ arg.alpha2[0], arg.alpha2[1]);
+
+ for (i = 0; i < ab->num_radios; i++) {
+ pdev = &ab->pdevs[i];
+ ar = pdev->ar;
+
+ memcpy(&ar->alpha2, &arg.alpha2, 2);
+ ret = ath12k_wmi_send_set_current_country_cmd(ar, &arg);
+ if (ret)
+ ath12k_warn(ar->ab,
+ "pdev id %d failed set current country code: %d\n",
+ i, ret);
+ }
+}
+
static void ath12k_core_pre_reconfigure_recovery(struct ath12k_base *ab)
{
struct ath12k *ar;
@@ -1045,8 +1074,10 @@ static void ath12k_core_pre_reconfigure_
ar = &ah->radio[j];
ath12k_mac_drain_tx(ar);
+ ar->state_11d = ATH12K_11D_IDLE;
+ complete(&ar->completed_11d_scan);
complete(&ar->scan.started);
- complete(&ar->scan.completed);
+ complete_all(&ar->scan.completed);
complete(&ar->scan.on_channel);
complete(&ar->peer_assoc_done);
complete(&ar->peer_delete_done);
@@ -1312,6 +1343,7 @@ struct ath12k_base *ath12k_core_alloc(st
INIT_WORK(&ab->restart_work, ath12k_core_restart);
INIT_WORK(&ab->reset_work, ath12k_core_reset);
INIT_WORK(&ab->rfkill_work, ath12k_rfkill_work);
+ INIT_WORK(&ab->update_11d_work, ath12k_update_11d);
timer_setup(&ab->rx_replenish_retry, ath12k_ce_rx_replenish_retry, 0);
init_completion(&ab->htc_suspend);
--- a/drivers/net/wireless/ath/ath12k/core.h
+++ b/drivers/net/wireless/ath/ath12k/core.h
@@ -199,6 +199,12 @@ enum ath12k_scan_state {
ATH12K_SCAN_ABORTING,
};
+enum ath12k_11d_state {
+ ATH12K_11D_IDLE,
+ ATH12K_11D_PREPARING,
+ ATH12K_11D_RUNNING,
+};
+
enum ath12k_dev_flags {
ATH12K_CAC_RUNNING,
ATH12K_FLAG_CRASH_FLUSH,
@@ -313,6 +319,8 @@ struct ath12k_vif_iter {
#define ATH12K_RX_RATE_TABLE_11AX_NUM 576
#define ATH12K_RX_RATE_TABLE_NUM 320
+#define ATH12K_SCAN_TIMEOUT_HZ (20 * HZ)
+
struct ath12k_rx_peer_rate_stats {
u64 ht_mcs_count[HAL_RX_MAX_MCS_HT + 1];
u64 vht_mcs_count[HAL_RX_MAX_MCS_VHT + 1];
@@ -648,6 +656,13 @@ struct ath12k {
u32 freq_low;
u32 freq_high;
+ /* Protected by wiphy::mtx lock. */
+ u32 vdev_id_11d_scan;
+ struct completion completed_11d_scan;
+ enum ath12k_11d_state state_11d;
+ u8 alpha2[REG_ALPHA2_LEN];
+ bool regdom_set_by_user;
+
bool nlo_enabled;
};
@@ -880,6 +895,8 @@ struct ath12k_base {
/* continuous recovery fail count */
atomic_t fail_cont_count;
unsigned long reset_fail_timeout;
+ struct work_struct update_11d_work;
+ u8 new_alpha2[2];
struct {
/* protected by data_lock */
u32 fw_crash_counter;
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -2947,6 +2947,11 @@ static void ath12k_bss_assoc(struct ath1
if (ret)
ath12k_warn(ar->ab, "failed to set vdev %i OBSS PD parameters: %d\n",
arvif->vdev_id, ret);
+
+ if (test_bit(WMI_TLV_SERVICE_11D_OFFLOAD, ar->ab->wmi_ab.svc_map) &&
+ arvif->vdev_type == WMI_VDEV_TYPE_STA &&
+ arvif->vdev_subtype == WMI_VDEV_SUBTYPE_NONE)
+ ath12k_mac_11d_scan_stop_all(ar->ab);
}
static void ath12k_bss_disassoc(struct ath12k *ar,
@@ -3522,7 +3527,7 @@ void __ath12k_mac_scan_finish(struct ath
ar->scan_channel = NULL;
ar->scan.roc_freq = 0;
cancel_delayed_work(&ar->scan.timeout);
- complete(&ar->scan.completed);
+ complete_all(&ar->scan.completed);
break;
}
}
@@ -3783,7 +3788,12 @@ scan:
ret = ath12k_start_scan(ar, &arg);
if (ret) {
- ath12k_warn(ar->ab, "failed to start hw scan: %d\n", ret);
+ if (ret == -EBUSY)
+ ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
+ "scan engine is busy 11d state %d\n", ar->state_11d);
+ else
+ ath12k_warn(ar->ab, "failed to start hw scan: %d\n", ret);
+
spin_lock_bh(&ar->data_lock);
ar->scan.state = ATH12K_SCAN_IDLE;
spin_unlock_bh(&ar->data_lock);
@@ -3802,6 +3812,11 @@ exit:
mutex_unlock(&ar->conf_mutex);
+ if (ar->state_11d == ATH12K_11D_PREPARING &&
+ arvif->vdev_type == WMI_VDEV_TYPE_STA &&
+ arvif->vdev_subtype == WMI_VDEV_SUBTYPE_NONE)
+ ath12k_mac_11d_scan_start(ar, arvif->vdev_id);
+
return ret;
}
@@ -5986,7 +6001,7 @@ static int ath12k_mac_start(struct ath12
/* TODO: Do we need to enable ANI? */
- ath12k_reg_update_chan_list(ar);
+ ath12k_reg_update_chan_list(ar, false);
ar->num_started_vdevs = 0;
ar->num_created_vdevs = 0;
@@ -6166,6 +6181,9 @@ static void ath12k_mac_stop(struct ath12
cancel_delayed_work_sync(&ar->scan.timeout);
cancel_work_sync(&ar->regd_update_work);
cancel_work_sync(&ar->ab->rfkill_work);
+ cancel_work_sync(&ar->ab->update_11d_work);
+ ar->state_11d = ATH12K_11D_IDLE;
+ complete(&ar->completed_11d_scan);
spin_lock_bh(&ar->data_lock);
list_for_each_entry_safe(ppdu_stats, tmp, &ar->ppdu_stats_info, list) {
@@ -6412,6 +6430,117 @@ static void ath12k_mac_op_update_vif_off
ath12k_mac_update_vif_offload(arvif);
}
+static bool ath12k_mac_vif_ap_active_any(struct ath12k_base *ab)
+{
+ struct ath12k *ar;
+ struct ath12k_pdev *pdev;
+ struct ath12k_vif *arvif;
+ int i;
+
+ for (i = 0; i < ab->num_radios; i++) {
+ pdev = &ab->pdevs[i];
+ ar = pdev->ar;
+ list_for_each_entry(arvif, &ar->arvifs, list) {
+ if (arvif->is_up && arvif->vdev_type == WMI_VDEV_TYPE_AP)
+ return true;
+ }
+ }
+ return false;
+}
+
+void ath12k_mac_11d_scan_start(struct ath12k *ar, u32 vdev_id)
+{
+ struct wmi_11d_scan_start_arg arg;
+ int ret;
+
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
+
+ if (ar->regdom_set_by_user)
+ goto fin;
+
+ if (ar->vdev_id_11d_scan != ATH12K_11D_INVALID_VDEV_ID)
+ goto fin;
+
+ if (!test_bit(WMI_TLV_SERVICE_11D_OFFLOAD, ar->ab->wmi_ab.svc_map))
+ goto fin;
+
+ if (ath12k_mac_vif_ap_active_any(ar->ab))
+ goto fin;
+
+ arg.vdev_id = vdev_id;
+ arg.start_interval_msec = 0;
+ arg.scan_period_msec = ATH12K_SCAN_11D_INTERVAL;
+
+ ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
+ "mac start 11d scan for vdev %d\n", vdev_id);
+
+ ret = ath12k_wmi_send_11d_scan_start_cmd(ar, &arg);
+ if (ret) {
+ ath12k_warn(ar->ab, "failed to start 11d scan vdev %d ret: %d\n",
+ vdev_id, ret);
+ } else {
+ ar->vdev_id_11d_scan = vdev_id;
+ if (ar->state_11d == ATH12K_11D_PREPARING)
+ ar->state_11d = ATH12K_11D_RUNNING;
+ }
+
+fin:
+ if (ar->state_11d == ATH12K_11D_PREPARING) {
+ ar->state_11d = ATH12K_11D_IDLE;
+ complete(&ar->completed_11d_scan);
+ }
+}
+
+void ath12k_mac_11d_scan_stop(struct ath12k *ar)
+{
+ int ret;
+ u32 vdev_id;
+
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
+
+ if (!test_bit(WMI_TLV_SERVICE_11D_OFFLOAD, ar->ab->wmi_ab.svc_map))
+ return;
+
+ ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac stop 11d for vdev %d\n",
+ ar->vdev_id_11d_scan);
+
+ if (ar->state_11d == ATH12K_11D_PREPARING) {
+ ar->state_11d = ATH12K_11D_IDLE;
+ complete(&ar->completed_11d_scan);
+ }
+
+ if (ar->vdev_id_11d_scan != ATH12K_11D_INVALID_VDEV_ID) {
+ vdev_id = ar->vdev_id_11d_scan;
+
+ ret = ath12k_wmi_send_11d_scan_stop_cmd(ar, vdev_id);
+ if (ret) {
+ ath12k_warn(ar->ab,
+ "failed to stopt 11d scan vdev %d ret: %d\n",
+ vdev_id, ret);
+ } else {
+ ar->vdev_id_11d_scan = ATH12K_11D_INVALID_VDEV_ID;
+ ar->state_11d = ATH12K_11D_IDLE;
+ complete(&ar->completed_11d_scan);
+ }
+ }
+}
+
+void ath12k_mac_11d_scan_stop_all(struct ath12k_base *ab)
+{
+ struct ath12k *ar;
+ struct ath12k_pdev *pdev;
+ int i;
+
+ ath12k_dbg(ab, ATH12K_DBG_MAC, "mac stop soc 11d scan\n");
+
+ for (i = 0; i < ab->num_radios; i++) {
+ pdev = &ab->pdevs[i];
+ ar = pdev->ar;
+
+ ath12k_mac_11d_scan_stop(ar);
+ }
+}
+
static int ath12k_mac_vdev_create(struct ath12k *ar, struct ieee80211_vif *vif)
{
struct ath12k_hw *ah = ar->ah;
@@ -6526,6 +6655,7 @@ static int ath12k_mac_vdev_create(struct
arvif->vdev_id, ret);
goto err_peer_del;
}
+ ath12k_mac_11d_scan_stop_all(ar->ab);
break;
case WMI_VDEV_TYPE_STA:
param_id = WMI_STA_PS_PARAM_RX_WAKE_POLICY;
@@ -6564,6 +6694,13 @@ static int ath12k_mac_vdev_create(struct
arvif->vdev_id, ret);
goto err_peer_del;
}
+
+ if (test_bit(WMI_TLV_SERVICE_11D_OFFLOAD, ab->wmi_ab.svc_map) &&
+ arvif->vdev_type == WMI_VDEV_TYPE_STA &&
+ arvif->vdev_subtype == WMI_VDEV_SUBTYPE_NONE) {
+ reinit_completion(&ar->completed_11d_scan);
+ ar->state_11d = ATH12K_11D_PREPARING;
+ }
break;
default:
break;
@@ -6904,6 +7041,11 @@ static void ath12k_mac_op_remove_interfa
ath12k_dbg(ab, ATH12K_DBG_MAC, "mac remove interface (vdev %d)\n",
arvif->vdev_id);
+ if (test_bit(WMI_TLV_SERVICE_11D_OFFLOAD, ab->wmi_ab.svc_map) &&
+ arvif->vdev_type == WMI_VDEV_TYPE_STA &&
+ arvif->vdev_subtype == WMI_VDEV_SUBTYPE_NONE)
+ ath12k_mac_11d_scan_stop(ar);
+
if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
ret = ath12k_peer_delete(ar, arvif->vdev_id, vif->addr);
if (ret)
@@ -7744,6 +7886,14 @@ ath12k_mac_op_unassign_vif_chanctx(struc
ar->num_started_vdevs == 1 && ar->monitor_vdev_created)
ath12k_mac_monitor_stop(ar);
+ if (test_bit(WMI_TLV_SERVICE_11D_OFFLOAD, ab->wmi_ab.svc_map) &&
+ arvif->vdev_type == WMI_VDEV_TYPE_STA &&
+ arvif->vdev_subtype == WMI_VDEV_SUBTYPE_NONE &&
+ ar->state_11d != ATH12K_11D_PREPARING) {
+ reinit_completion(&ar->completed_11d_scan);
+ ar->state_11d = ATH12K_11D_PREPARING;
+ }
+
mutex_unlock(&ar->conf_mutex);
}
@@ -8282,6 +8432,14 @@ ath12k_mac_op_reconfig_complete(struct i
ath12k_warn(ar->ab, "pdev %d successfully recovered\n",
ar->pdev->pdev_id);
+ if (ar->ab->hw_params->current_cc_support &&
+ ar->alpha2[0] != 0 && ar->alpha2[1] != 0) {
+ struct wmi_set_current_country_arg arg = {};
+
+ memcpy(&arg.alpha2, ar->alpha2, 2);
+ ath12k_wmi_send_set_current_country_cmd(ar, &arg);
+ }
+
if (ab->is_reset) {
recovery_count = atomic_inc_return(&ab->recovery_count);
@@ -9331,6 +9489,9 @@ static void ath12k_mac_setup(struct ath1
INIT_WORK(&ar->wmi_mgmt_tx_work, ath12k_mgmt_over_wmi_tx_work);
skb_queue_head_init(&ar->wmi_mgmt_tx_queue);
+
+ ar->vdev_id_11d_scan = ATH12K_11D_INVALID_VDEV_ID;
+ init_completion(&ar->completed_11d_scan);
}
int ath12k_mac_register(struct ath12k_base *ab)
--- a/drivers/net/wireless/ath/ath12k/mac.h
+++ b/drivers/net/wireless/ath/ath12k/mac.h
@@ -51,6 +51,13 @@ enum ath12k_supported_bw {
extern const struct htt_rx_ring_tlv_filter ath12k_mac_mon_status_filter_default;
+#define ATH12K_SCAN_11D_INTERVAL 600000
+#define ATH12K_11D_INVALID_VDEV_ID 0xFFFF
+
+void ath12k_mac_11d_scan_start(struct ath12k *ar, u32 vdev_id);
+void ath12k_mac_11d_scan_stop(struct ath12k *ar);
+void ath12k_mac_11d_scan_stop_all(struct ath12k_base *ab);
+
void ath12k_mac_destroy(struct ath12k_base *ab);
void ath12k_mac_unregister(struct ath12k_base *ab);
int ath12k_mac_register(struct ath12k_base *ab);
--- a/drivers/net/wireless/ath/ath12k/reg.c
+++ b/drivers/net/wireless/ath/ath12k/reg.c
@@ -48,6 +48,7 @@ ath12k_reg_notifier(struct wiphy *wiphy,
{
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
struct ath12k_wmi_init_country_arg arg;
+ struct wmi_set_current_country_arg current_arg = {};
struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
struct ath12k *ar = ath12k_ah_to_ar(ah, 0);
int ret, i;
@@ -77,27 +78,38 @@ ath12k_reg_notifier(struct wiphy *wiphy,
return;
}
- /* Set the country code to the firmware and wait for
- * the WMI_REG_CHAN_LIST_CC EVENT for updating the
- * reg info
- */
- arg.flags = ALPHA_IS_SET;
- memcpy(&arg.cc_info.alpha2, request->alpha2, 2);
- arg.cc_info.alpha2[2] = 0;
-
/* Allow fresh updates to wiphy regd */
ah->regd_updated = false;
/* Send the reg change request to all the radios */
for_each_ar(ah, ar, i) {
- ret = ath12k_wmi_send_init_country_cmd(ar, &arg);
- if (ret)
- ath12k_warn(ar->ab,
- "INIT Country code set to fw failed : %d\n", ret);
+ if (ar->ab->hw_params->current_cc_support) {
+ memcpy(&current_arg.alpha2, request->alpha2, 2);
+ memcpy(&ar->alpha2, &current_arg.alpha2, 2);
+ ret = ath12k_wmi_send_set_current_country_cmd(ar, &current_arg);
+ if (ret)
+ ath12k_warn(ar->ab,
+ "failed set current country code: %d\n", ret);
+ } else {
+ arg.flags = ALPHA_IS_SET;
+ memcpy(&arg.cc_info.alpha2, request->alpha2, 2);
+ arg.cc_info.alpha2[2] = 0;
+
+ ret = ath12k_wmi_send_init_country_cmd(ar, &arg);
+ if (ret)
+ ath12k_warn(ar->ab,
+ "failed set INIT Country code: %d\n", ret);
+ }
+
+ wiphy_lock(wiphy);
+ ath12k_mac_11d_scan_stop(ar);
+ wiphy_unlock(wiphy);
+
+ ar->regdom_set_by_user = true;
}
}
-int ath12k_reg_update_chan_list(struct ath12k *ar)
+int ath12k_reg_update_chan_list(struct ath12k *ar, bool wait)
{
struct ieee80211_supported_band **bands;
struct ath12k_wmi_scan_chan_list_arg *arg;
@@ -106,7 +118,35 @@ int ath12k_reg_update_chan_list(struct a
struct ath12k_wmi_channel_arg *ch;
enum nl80211_band band;
int num_channels = 0;
- int i, ret;
+ int i, ret, left;
+
+ if (wait && ar->state_11d != ATH12K_11D_IDLE) {
+ left = wait_for_completion_timeout(&ar->completed_11d_scan,
+ ATH12K_SCAN_TIMEOUT_HZ);
+ if (!left) {
+ ath12k_dbg(ar->ab, ATH12K_DBG_REG,
+ "failed to receive 11d scan complete: timed out\n");
+ ar->state_11d = ATH12K_11D_IDLE;
+ }
+ ath12k_dbg(ar->ab, ATH12K_DBG_REG,
+ "reg 11d scan wait left time %d\n", left);
+ }
+
+ if (wait &&
+ (ar->scan.state == ATH12K_SCAN_STARTING ||
+ ar->scan.state == ATH12K_SCAN_RUNNING)) {
+ left = wait_for_completion_timeout(&ar->scan.completed,
+ ATH12K_SCAN_TIMEOUT_HZ);
+ if (!left)
+ ath12k_dbg(ar->ab, ATH12K_DBG_REG,
+ "failed to receive hw scan complete: timed out\n");
+
+ ath12k_dbg(ar->ab, ATH12K_DBG_REG,
+ "reg hw scan wait left time %d\n", left);
+ }
+
+ if (ar->ah->state == ATH12K_HW_STATE_RESTARTING)
+ return 0;
bands = hw->wiphy->bands;
for (band = 0; band < NUM_NL80211_BANDS; band++) {
@@ -295,7 +335,7 @@ int ath12k_regd_update(struct ath12k *ar
*/
for_each_ar(ah, ar, i) {
ab = ar->ab;
- ret = ath12k_reg_update_chan_list(ar);
+ ret = ath12k_reg_update_chan_list(ar, true);
if (ret)
goto err;
}
--- a/drivers/net/wireless/ath/ath12k/reg.h
+++ b/drivers/net/wireless/ath/ath12k/reg.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2019-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef ATH12K_REG_H
@@ -96,6 +96,6 @@ struct ieee80211_regdomain *ath12k_reg_b
struct ath12k_reg_info *reg_info,
bool intersect);
int ath12k_regd_update(struct ath12k *ar, bool init);
-int ath12k_reg_update_chan_list(struct ath12k *ar);
+int ath12k_reg_update_chan_list(struct ath12k *ar, bool wait);
#endif
--- a/drivers/net/wireless/ath/ath12k/hw.c
+++ b/drivers/net/wireless/ath/ath12k/hw.c
@@ -926,6 +926,7 @@ static const struct ath12k_hw_params ath
.supports_dynamic_smps_6ghz = true,
.iova_mask = 0,
+ .current_cc_support = false,
},
{
.name = "wcn7850 hw2.0",
@@ -1004,6 +1005,7 @@ static const struct ath12k_hw_params ath
.supports_dynamic_smps_6ghz = false,
.iova_mask = ATH12K_PCIE_MAX_PAYLOAD_SIZE - 1,
+ .current_cc_support = true,
},
{
.name = "qcn9274 hw2.0",
@@ -1078,6 +1080,7 @@ static const struct ath12k_hw_params ath
.supports_dynamic_smps_6ghz = true,
.iova_mask = 0,
+ .current_cc_support = false,
},
};
--- a/drivers/net/wireless/ath/ath12k/hw.h
+++ b/drivers/net/wireless/ath/ath12k/hw.h
@@ -189,6 +189,7 @@ struct ath12k_hw_params {
bool tcl_ring_retry:1;
bool reoq_lut_support:1;
bool supports_shadow_regs:1;
+ bool current_cc_support:1;
u32 num_tcl_banks;
u32 max_tx_ring;

View File

@ -0,0 +1,17 @@
Fix ltssm crashes on BPI-Rx boards.
Seems read32/write32 using wrong address which
is not a problem on x86/64 PCI controllers.
But have issues on BPI-Rx boards.
--- a/drivers/net/wireless/ath/ath12k/pci.c
+++ b/drivers/net/wireless/ath/ath12k/pci.c
@@ -277,6 +277,9 @@ static void ath12k_pci_enable_ltssm(stru
u32 val;
int i;
+ /* Prevent startup crash on BPI-Rx */
+ return;
+
val = ath12k_pci_read32(ab, PCIE_PCIE_PARF_LTSSM);
/* PCIE link seems very unstable after the Hot Reset*/

View File

@ -1,6 +1,6 @@
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -1431,6 +1431,7 @@ int ath9k_init_debug(struct ath_hw *ah)
@@ -1429,6 +1429,7 @@ int ath9k_init_debug(struct ath_hw *ah)
ath9k_cmn_debug_base_eeprom(sc->debug.debugfs_phy, sc->sc_ah);
ath9k_cmn_debug_modal_eeprom(sc->debug.debugfs_phy, sc->sc_ah);
@ -82,7 +82,7 @@
void ath9k_cmn_debug_recv(struct dentry *debugfs_phy,
--- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
@@ -514,6 +514,7 @@ int ath9k_htc_init_debug(struct ath_hw *
@@ -512,6 +512,7 @@ int ath9k_htc_init_debug(struct ath_hw *
ath9k_cmn_debug_base_eeprom(priv->debug.debugfs_phy, priv->ah);
ath9k_cmn_debug_modal_eeprom(priv->debug.debugfs_phy, priv->ah);

View File

@ -1,6 +1,6 @@
--- 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)

View File

@ -1,6 +1,6 @@
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -1432,6 +1432,7 @@ int ath9k_init_debug(struct ath_hw *ah)
@@ -1430,6 +1430,7 @@ int ath9k_init_debug(struct ath_hw *ah)
ath9k_cmn_debug_base_eeprom(sc->debug.debugfs_phy, sc->sc_ah);
ath9k_cmn_debug_modal_eeprom(sc->debug.debugfs_phy, sc->sc_ah);
ath9k_cmn_debug_eeprom(sc->debug.debugfs_phy, sc->sc_ah);
@ -137,7 +137,7 @@
+EXPORT_SYMBOL(ath9k_cmn_debug_chanbw);
--- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
@@ -515,6 +515,7 @@ int ath9k_htc_init_debug(struct ath_hw *
@@ -513,6 +513,7 @@ int ath9k_htc_init_debug(struct ath_hw *
ath9k_cmn_debug_base_eeprom(priv->debug.debugfs_phy, priv->ah);
ath9k_cmn_debug_modal_eeprom(priv->debug.debugfs_phy, priv->ah);
ath9k_cmn_debug_eeprom(priv->debug.debugfs_phy, priv->ah);

View File

@ -20,7 +20,7 @@
#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

View File

@ -1,6 +1,6 @@
--- 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);
@ -10,7 +10,7 @@
#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 */
@ -24,7 +24,7 @@
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
@ -254,7 +254,7 @@
static ssize_t read_file_ani(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
@@ -1392,6 +1447,10 @@ int ath9k_init_debug(struct ath_hw *ah)
@@ -1390,6 +1445,10 @@ int ath9k_init_debug(struct ath_hw *ah)
ath9k_tx99_init_debug(sc);
ath9k_cmn_spectral_init_debug(&sc->spec_priv, sc->debug.debugfs_phy);

View File

@ -51,7 +51,7 @@
int ath9k_init_debug(struct ath_hw *ah)
{
struct ath_common *common = ath9k_hw_common(ah);
@@ -1451,6 +1495,8 @@ int ath9k_init_debug(struct ath_hw *ah)
@@ -1449,6 +1493,8 @@ int ath9k_init_debug(struct ath_hw *ah)
debugfs_create_file("gpio_led", S_IWUSR,
sc->debug.debugfs_phy, sc, &fops_gpio_led);
#endif

View File

@ -18,7 +18,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
#include "common.h"
#include "debug.h"
@@ -990,6 +991,14 @@ struct ath_led {
@@ -991,6 +992,14 @@ struct ath_led {
struct led_classdev cdev;
};
@ -33,7 +33,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
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;
@ -45,7 +45,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
#ifdef CPTCFG_ATH9K_DEBUGFS
--- a/drivers/net/wireless/ath/ath9k/gpio.c
+++ b/drivers/net/wireless/ath/ath9k/gpio.c
@@ -16,13 +16,139 @@
@@ -16,13 +16,135 @@
#include "ath9k.h"
#include <linux/ath9k_platform.h>
@ -127,11 +127,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
+ snprintf(gc->label, sizeof(gc->label), "ath9k-%s",
+ wiphy_name(sc->hw->wiphy));
+#ifdef CONFIG_OF
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,5,0)
+ gc->gchip.parent = sc->dev;
+#else
+ gc->gchip.dev = sc->dev;
+#endif
+#endif
+ gc->gchip.label = gc->label;
+ gc->gchip.base = -1; /* determine base automatically */
@ -187,7 +183,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
static void ath_fill_led_pin(struct ath_softc *sc)
{
struct ath_hw *ah = sc->sc_ah;
@@ -80,6 +206,12 @@ static int ath_add_led(struct ath_softc
@@ -80,6 +202,12 @@ static int ath_add_led(struct ath_softc
else
ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, gpio->active_low);
@ -200,7 +196,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
return 0;
}
@@ -136,17 +268,24 @@ void ath_deinit_leds(struct ath_softc *s
@@ -136,17 +264,24 @@ void ath_deinit_leds(struct ath_softc *s
while (!list_empty(&sc->leds)) {
led = list_first_entry(&sc->leds, struct ath_led, list);
@ -225,7 +221,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
char led_name[32];
const char *trigger;
int i;
@@ -156,6 +295,15 @@ void ath_init_leds(struct ath_softc *sc)
@@ -156,6 +291,15 @@ void ath_init_leds(struct ath_softc *sc)
if (AR_SREV_9100(sc->sc_ah))
return;
@ -241,7 +237,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
ath_fill_led_pin(sc);
if (pdata && pdata->leds && pdata->num_leds)
@@ -180,6 +328,7 @@ void ath_init_leds(struct ath_softc *sc)
@@ -180,6 +324,7 @@ void ath_init_leds(struct ath_softc *sc)
ath_create_gpio_led(sc, sc->sc_ah->led_pin, led_name, trigger,
!sc->sc_ah->config.led_active_high);
}

View File

@ -10,7 +10,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
--- 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;
@ -29,7 +29,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
#ifdef CPTCFG_MAC80211_LEDS
@@ -133,6 +135,67 @@ static void ath9k_unregister_gpio_chip(s
@@ -129,6 +131,67 @@ static void ath9k_unregister_gpio_chip(s
sc->gpiochip = NULL;
}
@ -97,7 +97,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
#else /* CONFIG_GPIOLIB */
static inline void ath9k_register_gpio_chip(struct ath_softc *sc)
@@ -143,6 +206,14 @@ static inline void ath9k_unregister_gpio
@@ -139,6 +202,14 @@ static inline void ath9k_unregister_gpio
{
}
@ -112,7 +112,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
#endif /* CONFIG_GPIOLIB */
/********************************/
@@ -266,6 +337,7 @@ void ath_deinit_leds(struct ath_softc *s
@@ -262,6 +333,7 @@ void ath_deinit_leds(struct ath_softc *s
{
struct ath_led *led;
@ -120,7 +120,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
while (!list_empty(&sc->leds)) {
led = list_first_entry(&sc->leds, struct ath_led, list);
#ifdef CONFIG_GPIOLIB
@@ -305,6 +377,7 @@ void ath_init_leds(struct ath_softc *sc)
@@ -301,6 +373,7 @@ void ath_init_leds(struct ath_softc *sc)
}
ath_fill_led_pin(sc);

View File

@ -371,7 +371,7 @@
--- 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=

View File

@ -272,7 +272,7 @@
#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;

View File

@ -14,7 +14,7 @@ Signed-off-by: Phil Elwell <phil@raspberrypi.org>
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
@@ -3313,6 +3313,10 @@ brcmf_cfg80211_set_power_mgmt(struct wip
@@ -3314,6 +3314,10 @@ brcmf_cfg80211_set_power_mgmt(struct wip
* preference in cfg struct to apply this to
* FW later while initializing the dongle
*/

View File

@ -49,7 +49,7 @@ Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
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);
}

View File

@ -9,7 +9,7 @@ Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
--- 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;
}
@ -17,7 +17,7 @@ Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
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;
}
@ -25,7 +25,7 @@ Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
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

View File

@ -0,0 +1,76 @@
--- a/kconf/conf.c
+++ b/kconf/conf.c
@@ -86,7 +86,7 @@ static int conf_askvalue(struct symbol *
enum symbol_type type = sym_get_type(sym);
if (!sym_has_value(sym))
- printf(_("(NEW) "));
+ printf("%s", _("(NEW) "));
line[0] = '\n';
line[1] = 0;
@@ -282,7 +282,7 @@ static int conf_choice(struct menu *menu
if (child->sym->name)
printf(" (%s)", child->sym->name);
if (!sym_has_value(child->sym))
- printf(_(" (NEW)"));
+ printf("%s", _(" (NEW)"));
printf("\n");
}
printf(_("%*schoice"), indent - 1, "");
@@ -437,7 +437,7 @@ static void check_conf(struct menu *menu
}
} else {
if (!conf_cnt++)
- printf(_("*\n* Restart config...\n*\n"));
+ printf("%s", _("*\n* Restart config...\n*\n"));
rootEntry = menu_get_parent_menu(menu);
conf(rootEntry);
}
@@ -614,7 +614,7 @@ int main(int ac, char **av)
name = getenv("KCONFIG_NOSILENTUPDATE");
if (name && *name) {
fprintf(stderr,
- _("\n*** The configuration requires explicit update.\n\n"));
+ "%s", _("\n*** The configuration requires explicit update.\n\n"));
return 1;
}
}
@@ -666,22 +666,22 @@ int main(int ac, char **av)
* All other commands are only used to generate a config.
*/
if (conf_get_changed() && conf_write(NULL)) {
- fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n"));
+ fprintf(stderr, "%s", _("\n*** Error during writing of the configuration.\n\n"));
exit(1);
}
if (conf_write_autoconf()) {
- fprintf(stderr, _("\n*** Error during update of the configuration.\n\n"));
+ fprintf(stderr, "%s", _("\n*** Error during update of the configuration.\n\n"));
return 1;
}
} else if (input_mode == savedefconfig) {
if (conf_write_defconfig(defconfig_file)) {
- fprintf(stderr, _("n*** Error while saving defconfig to: %s\n\n"),
+ fprintf(stderr, _("\n*** Error while saving defconfig to: %s\n\n"),
defconfig_file);
return 1;
}
} else if (input_mode != listnewconfig) {
if (conf_write(NULL)) {
- fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n"));
+ fprintf(stderr, "%s", _("\n*** Error during writing of the configuration.\n\n"));
exit(1);
}
}
--- a/kconf/Makefile
+++ b/kconf/Makefile
@@ -17,7 +17,7 @@ clean:
zconf.tab.c: zconf.lex.c
%.tab.c: %.y
- $(YACC) -o$@ -t -l $<
+ $(YACC) -Wno-yacc -o$@ -t -l $<
%.lex.c: %.l
$(LEX) -o$@ -L $<

View File

@ -1,314 +0,0 @@
--- 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/

View File

@ -1,13 +0,0 @@
--- /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

View File

@ -54,9 +54,9 @@ Signed-off-by: Robert Marko <robimarko@gmail.com>
+ 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=

View File

@ -1,14 +0,0 @@
--- a/net/wireless/sysfs.c
+++ b/net/wireless/sysfs.c
@@ -154,7 +154,11 @@ static SIMPLE_DEV_PM_OPS(wiphy_pm_ops, w
#define WIPHY_PM_OPS NULL
#endif
+#if LINUX_VERSION_IS_GEQ(6,2,0)
static const void *wiphy_namespace(const struct device *d)
+#else
+static const void *wiphy_namespace(struct device *d)
+#endif
{
struct wiphy *wiphy = container_of(d, struct wiphy, dev);

View File

@ -1,14 +1,3 @@
--- a/backport-include/linux/random.h
+++ b/backport-include/linux/random.h
@@ -15,7 +15,7 @@ static inline u16 get_random_u16(void)
}
#endif
-#if LINUX_VERSION_IS_LESS(6,2,0)
+#if LINUX_VERSION_IS_LESS(6,1,4)
static inline u32 __get_random_u32_below(u32 ceil)
{
/*
--- a/backport-include/net/dropreason.h
+++ b/backport-include/net/dropreason.h
@@ -3,10 +3,9 @@

View File

@ -1,26 +0,0 @@
--- /dev/null
+++ b/backport-include/linux/iommu.h
@@ -0,0 +1,23 @@
+#ifndef __BACKPORT_LINUX_IOMMU_H
+#define __BACKPORT_LINUX_IOMMU_H
+
+#include_next <linux/iommu.h>
+#include <linux/version.h>
+
+#if LINUX_VERSION_IS_LESS(6,3,0)
+
+static inline int LINUX_BACKPORT(iommu_map)(struct iommu_domain *domain,
+ unsigned long iova,
+ phys_addr_t paddr, size_t size,
+ int prot, gfp_t gfp)
+{
+ if (gfp == GFP_ATOMIC)
+ return iommu_map_atomic(domain, iova, paddr, size, prot);
+
+ return iommu_map(domain, iova, paddr, size, prot);
+}
+#define iommu_map LINUX_BACKPORT(iommu_map)
+
+#endif /* < 6.3 */
+
+#endif

View File

@ -0,0 +1,541 @@
--- 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",

View File

@ -0,0 +1,32 @@
--- 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;
}

View File

@ -1,6 +1,20 @@
--- 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;

View File

@ -1,32 +0,0 @@
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -16383,9 +16383,14 @@ static u32 nl80211_internal_flags[] = {
#undef SELECTOR
};
+#if LINUX_VERSION_IS_LESS(6,2,0)
+static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
+ struct genl_info *info)
+#else
static int nl80211_pre_doit(const struct genl_split_ops *ops,
struct sk_buff *skb,
struct genl_info *info)
+#endif
{
struct cfg80211_registered_device *rdev = NULL;
struct wireless_dev *wdev = NULL;
@@ -16485,9 +16490,14 @@ out_unlock:
return err;
}
+#if LINUX_VERSION_IS_LESS(6,2,0)
+static void nl80211_post_doit(const struct genl_ops *ops, struct sk_buff *skb,
+ struct genl_info *info)
+#else
static void nl80211_post_doit(const struct genl_split_ops *ops,
struct sk_buff *skb,
struct genl_info *info)
+#endif
{
u32 internal_flags = nl80211_internal_flags[ops->internal_flags];

View File

@ -1,26 +0,0 @@
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
Date: Fri, 15 Dec 2023 10:17:21 +0100
Subject: [PATCH] list: don't backport list_count_nodes()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
It's redundant in OpenWrt as it backports it on its own. This fixes:
backport-include/linux/list.h:11:22: error: redefinition of 'list_count_nodes'
Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
---
backport-include/linux/list.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/backport-include/linux/list.h
+++ b/backport-include/linux/list.h
@@ -3,7 +3,7 @@
#include_next <linux/list.h>
#include <linux/version.h>
-#if LINUX_VERSION_IS_LESS(6,3,0)
+#if 0 /* OpenWrt backports list_count_nodes() on its own */
/**
* list_count_nodes - count nodes in the list
* @head: the head for your list.

View File

@ -1,6 +1,6 @@
--- 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)
{

View File

@ -0,0 +1,30 @@
--- a/drivers/net/wireless/virtual/mac80211_hwsim.c
+++ b/drivers/net/wireless/virtual/mac80211_hwsim.c
@@ -6629,6 +6629,7 @@ static void hwsim_virtio_rx_done(struct
static int init_vqs(struct virtio_device *vdev)
{
+#if LINUX_VERSION_IS_GEQ(6,11,0)
struct virtqueue_info vqs_info[HWSIM_NUM_VQS] = {
[HWSIM_VQ_TX] = { "tx", hwsim_virtio_tx_done },
[HWSIM_VQ_RX] = { "rx", hwsim_virtio_rx_done },
@@ -6636,6 +6637,19 @@ static int init_vqs(struct virtio_device
return virtio_find_vqs(vdev, HWSIM_NUM_VQS,
hwsim_vqs, vqs_info, NULL);
+#else /* Using the old ABI, copied from kernel 6.6 */
+ vq_callback_t *callbacks[HWSIM_NUM_VQS] = {
+ [HWSIM_VQ_TX] = hwsim_virtio_tx_done,
+ [HWSIM_VQ_RX] = hwsim_virtio_rx_done,
+ };
+ const char *names[HWSIM_NUM_VQS] = {
+ [HWSIM_VQ_TX] = "tx",
+ [HWSIM_VQ_RX] = "rx",
+ };
+
+ return virtio_find_vqs(vdev, HWSIM_NUM_VQS,
+ hwsim_vqs, callbacks, names, NULL);
+#endif
}
static int fill_vq(struct virtqueue *vq)

View File

@ -1,6 +1,6 @@
--- 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[] = {

View File

@ -1,6 +1,6 @@
--- a/drivers/net/wireless/marvell/libertas/cfg.c
+++ b/drivers/net/wireless/marvell/libertas/cfg.c
@@ -2101,6 +2101,8 @@ struct wireless_dev *lbs_cfg_alloc(struc
@@ -2102,6 +2102,8 @@ struct wireless_dev *lbs_cfg_alloc(struc
goto err_wiphy_new;
}

View File

@ -1,6 +1,6 @@
--- a/drivers/net/wireless/marvell/libertas/cfg.c
+++ b/drivers/net/wireless/marvell/libertas/cfg.c
@@ -2178,6 +2178,8 @@ int lbs_cfg_register(struct lbs_private
@@ -2179,6 +2179,8 @@ int lbs_cfg_register(struct lbs_private
wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
wdev->wiphy->reg_notifier = lbs_reg_notifier;

View File

@ -1,6 +1,6 @@
--- 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;
@ -9,7 +9,7 @@
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;

View File

@ -21,7 +21,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
--- 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=
@ -100,7 +100,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
.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,
@ -198,11 +198,23 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_SOC);
retval = rt2x00soc_alloc_reg(rt2x00dev);
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00soc.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00soc.h
@@ -26,4 +26,13 @@ int rt2x00soc_resume(struct platform_dev
#define rt2x00soc_resume NULL
#endif /* CONFIG_PM */
--- a/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
@@ -278,6 +278,9 @@ static int rt2800pci_read_eeprom(struct
{
int retval;
+ if (!rt2x00lib_read_eeprom(rt2x00dev))
+ return 0;
+
if (rt2800pci_efuse_detect(rt2x00dev))
retval = rt2800pci_read_eeprom_efuse(rt2x00dev);
else
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
@@ -270,4 +270,13 @@ void rt2800_get_txwi_rxwi_size(struct rt
unsigned short *rxwi_size);
void rt2800_pre_reset_hw(struct rt2x00_dev *rt2x00dev);
+/*
+ * EEPROM file handlers.
@ -213,4 +225,4 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+#define rt2x00lib_read_eeprom NULL
+#endif /* CPTCFG_RT2X00_LIB_EEPROM */
+
#endif /* RT2X00SOC_H */
#endif /* RT2800LIB_H */

View File

@ -37,7 +37,7 @@
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

View File

@ -83,7 +83,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
#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;

View File

@ -40,7 +40,7 @@
const u8 arg0, const u8 arg1);
--- a/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800pci.c
@@ -286,6 +286,10 @@ static int rt2800pci_read_eeprom(struct
@@ -289,6 +289,10 @@ static int rt2800pci_read_eeprom(struct
return retval;
}
@ -51,7 +51,7 @@
static const struct ieee80211_ops rt2800pci_mac80211_ops = {
.add_chanctx = ieee80211_emulate_add_chanctx,
.remove_chanctx = ieee80211_emulate_remove_chanctx,
@@ -333,6 +337,9 @@ static const struct rt2800_ops rt2800pci
@@ -336,6 +340,9 @@ static const struct rt2800_ops rt2800pci
.drv_init_registers = rt2800mmio_init_registers,
.drv_get_txwi = rt2800mmio_get_txwi,
.drv_get_dma_done = rt2800mmio_get_dma_done,

View File

@ -9,7 +9,7 @@ Used for AP+STA support in OpenWrt - preserve AP mode keys across STA reconnect
--- 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);

View File

@ -1,6 +1,6 @@
--- 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);

View File

@ -8,7 +8,7 @@ Subject: [PATCH] mac80211: allow scans in access point mode (for site survey)
--- 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:

View File

@ -16,7 +16,7 @@ and we should ignore this.
--- 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;

View File

@ -18,7 +18,7 @@ Signed-off-by: David Bauer <mail@david-bauer.net>
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -2459,6 +2459,13 @@ static void sta_stats_decode_rate(struct
@@ -2439,6 +2439,13 @@ static void sta_stats_decode_rate(struct
sband = local->hw.wiphy->bands[band];

View File

@ -28,15 +28,11 @@ Signed-off-by: Johannes Berg <johannes.berg@intel.com>
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -565,6 +565,11 @@ __sta_info_alloc(struct ieee80211_sub_if
@@ -565,6 +565,7 @@ __sta_info_alloc(struct ieee80211_sub_if
spin_lock_init(&sta->ps_lock);
INIT_WORK(&sta->drv_deliver_wk, sta_deliver_ps_frames);
wiphy_work_init(&sta->ampdu_mlme.work, ieee80211_ba_session_work);
+#if LINUX_VERSION_IS_LESS(6,2,0)
+ sta->ampdu_mlme.dialog_token_allocator = prandom_u32_max(U8_MAX);
+#else
+ sta->ampdu_mlme.dialog_token_allocator = get_random_u32_below(U8_MAX);
+#endif
#ifdef CPTCFG_MAC80211_MESH
if (ieee80211_vif_is_mesh(&sdata->vif)) {
sta->mesh = kzalloc(sizeof(*sta->mesh), gfp);

View File

@ -12,7 +12,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
--- 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);
}
@ -23,7 +23,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
--- 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 +=
@ -32,7 +32,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
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)
@ -42,7 +42,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
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;

View File

@ -1,29 +0,0 @@
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);

View File

@ -11,7 +11,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
--- 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.
@ -20,7 +20,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
* @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;
@ -52,7 +52,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
--- 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;
@ -61,7 +61,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
}
}
@@ -1049,6 +1051,49 @@ static bool cfg80211_get_chans_dfs_avail
@@ -1087,6 +1089,49 @@ static bool cfg80211_get_chans_dfs_avail
return true;
}

View File

@ -12,7 +12,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
--- 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
@ -70,7 +70,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
--- 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;
@ -85,7 +85,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
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);
@ -95,7 +95,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
spin_lock_init(&local->active_txq_lock[i]);
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -2357,13 +2357,28 @@ EXPORT_SYMBOL(ieee80211_sta_recalc_aggre
@@ -2353,13 +2353,28 @@ EXPORT_SYMBOL(ieee80211_sta_recalc_aggre
void ieee80211_sta_update_pending_airtime(struct ieee80211_local *local,
struct sta_info *sta, u8 ac,
@ -136,7 +136,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
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;
@ -167,7 +167,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
}
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;
@ -175,7 +175,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
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;
@ -214,7 +214,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
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)
@ -224,7 +224,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
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]);
@ -245,7 +245,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
if (iter == txqi)
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1180,8 +1180,8 @@ struct ieee80211_tx_info {
@@ -1222,8 +1222,8 @@ struct ieee80211_tx_info {
status_data_idr:1,
status_data:13,
hw_queue:4,
@ -269,7 +269,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
--- 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,
@ -278,7 +278,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
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().
*/

View File

@ -0,0 +1,24 @@
From: Felix Fietkau <nbd@nbd.name>
Date: Wed, 2 Oct 2024 11:45:35 +0200
Subject: [PATCH] wifi: mac80211: do not pass a stopped vif to the driver in
.get_txpower
Avoid potentially crashing in the driver because of uninitialized private data
Fixes: 5b3dc42b1b0d ("mac80211: add support for driver tx power reporting")
Cc: stable@vger.kernel.org
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -3134,7 +3134,8 @@ static int ieee80211_get_tx_power(struct
struct ieee80211_local *local = wiphy_priv(wiphy);
struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
- if (local->ops->get_txpower)
+ if (local->ops->get_txpower &&
+ (sdata->flags & IEEE80211_SDATA_IN_DRIVER))
return drv_get_txpower(local, sdata, dbm);
if (local->emulate_chanctx)

View File

@ -0,0 +1,233 @@
From: Ming Yen Hsieh <mingyen.hsieh@mediatek.com>
Date: Wed, 4 Sep 2024 19:12:56 +0800
Subject: [PATCH] wifi: mac80211: introduce EHT rate support in AQL airtime
Add definitions related to EHT mode and airtime calculation
according to the 802.11BE_D4.0.
Co-developed-by: Bo Jiao <Bo.Jiao@mediatek.com>
Signed-off-by: Bo Jiao <Bo.Jiao@mediatek.com>
Signed-off-by: Deren Wu <deren.wu@mediatek.com>
Signed-off-by: Quan Zhou <quan.zhou@mediatek.com>
Signed-off-by: Ming Yen Hsieh <mingyen.hsieh@mediatek.com>
Link: https://patch.msgid.link/20240904111256.11734-1-mingyen.hsieh@mediatek.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
--- a/net/mac80211/airtime.c
+++ b/net/mac80211/airtime.c
@@ -55,10 +55,21 @@
#define HE_DURATION_S(shift, streams, gi, bps) \
(HE_DURATION(streams, gi, bps) >> shift)
+/* gi in HE/EHT is identical. It matches enum nl80211_eht_gi as well */
+#define EHT_GI_08 HE_GI_08
+#define EHT_GI_16 HE_GI_16
+#define EHT_GI_32 HE_GI_32
+
+#define EHT_DURATION(streams, gi, bps) \
+ HE_DURATION(streams, gi, bps)
+#define EHT_DURATION_S(shift, streams, gi, bps) \
+ HE_DURATION_S(shift, streams, gi, bps)
+
#define BW_20 0
#define BW_40 1
#define BW_80 2
#define BW_160 3
+#define BW_320 4
/*
* Define group sort order: HT40 -> SGI -> #streams
@@ -68,17 +79,26 @@
#define IEEE80211_VHT_STREAM_GROUPS 8 /* BW(=4) * SGI(=2) */
#define IEEE80211_HE_MAX_STREAMS 8
+#define IEEE80211_HE_STREAM_GROUPS 12 /* BW(=4) * GI(=3) */
+
+#define IEEE80211_EHT_MAX_STREAMS 8
+#define IEEE80211_EHT_STREAM_GROUPS 15 /* BW(=5) * GI(=3) */
#define IEEE80211_HT_GROUPS_NB (IEEE80211_MAX_STREAMS * \
IEEE80211_HT_STREAM_GROUPS)
#define IEEE80211_VHT_GROUPS_NB (IEEE80211_MAX_STREAMS * \
IEEE80211_VHT_STREAM_GROUPS)
+#define IEEE80211_HE_GROUPS_NB (IEEE80211_HE_MAX_STREAMS * \
+ IEEE80211_HE_STREAM_GROUPS)
+#define IEEE80211_EHT_GROUPS_NB (IEEE80211_EHT_MAX_STREAMS * \
+ IEEE80211_EHT_STREAM_GROUPS)
#define IEEE80211_HT_GROUP_0 0
#define IEEE80211_VHT_GROUP_0 (IEEE80211_HT_GROUP_0 + IEEE80211_HT_GROUPS_NB)
#define IEEE80211_HE_GROUP_0 (IEEE80211_VHT_GROUP_0 + IEEE80211_VHT_GROUPS_NB)
+#define IEEE80211_EHT_GROUP_0 (IEEE80211_HE_GROUP_0 + IEEE80211_HE_GROUPS_NB)
-#define MCS_GROUP_RATES 12
+#define MCS_GROUP_RATES 14
#define HT_GROUP_IDX(_streams, _sgi, _ht40) \
IEEE80211_HT_GROUP_0 + \
@@ -203,6 +223,69 @@
#define HE_GROUP(_streams, _gi, _bw) \
__HE_GROUP(_streams, _gi, _bw, \
HE_GROUP_SHIFT(_streams, _gi, _bw))
+
+#define EHT_BW2VBPS(_bw, r5, r4, r3, r2, r1) \
+ ((_bw) == BW_320 ? r5 : BW2VBPS(_bw, r4, r3, r2, r1))
+
+#define EHT_GROUP_IDX(_streams, _gi, _bw) \
+ (IEEE80211_EHT_GROUP_0 + \
+ IEEE80211_EHT_MAX_STREAMS * 3 * (_bw) + \
+ IEEE80211_EHT_MAX_STREAMS * (_gi) + \
+ (_streams) - 1)
+
+#define __EHT_GROUP(_streams, _gi, _bw, _s) \
+ [EHT_GROUP_IDX(_streams, _gi, _bw)] = { \
+ .shift = _s, \
+ .duration = { \
+ EHT_DURATION_S(_s, _streams, _gi, \
+ EHT_BW2VBPS(_bw, 1960, 980, 490, 234, 117)), \
+ EHT_DURATION_S(_s, _streams, _gi, \
+ EHT_BW2VBPS(_bw, 3920, 1960, 980, 468, 234)), \
+ EHT_DURATION_S(_s, _streams, _gi, \
+ EHT_BW2VBPS(_bw, 5880, 2937, 1470, 702, 351)), \
+ EHT_DURATION_S(_s, _streams, _gi, \
+ EHT_BW2VBPS(_bw, 7840, 3920, 1960, 936, 468)), \
+ EHT_DURATION_S(_s, _streams, _gi, \
+ EHT_BW2VBPS(_bw, 11760, 5880, 2940, 1404, 702)), \
+ EHT_DURATION_S(_s, _streams, _gi, \
+ EHT_BW2VBPS(_bw, 15680, 7840, 3920, 1872, 936)), \
+ EHT_DURATION_S(_s, _streams, _gi, \
+ EHT_BW2VBPS(_bw, 17640, 8820, 4410, 2106, 1053)), \
+ EHT_DURATION_S(_s, _streams, _gi, \
+ EHT_BW2VBPS(_bw, 19600, 9800, 4900, 2340, 1170)), \
+ EHT_DURATION_S(_s, _streams, _gi, \
+ EHT_BW2VBPS(_bw, 23520, 11760, 5880, 2808, 1404)), \
+ EHT_DURATION_S(_s, _streams, _gi, \
+ EHT_BW2VBPS(_bw, 26133, 13066, 6533, 3120, 1560)), \
+ EHT_DURATION_S(_s, _streams, _gi, \
+ EHT_BW2VBPS(_bw, 29400, 14700, 7350, 3510, 1755)), \
+ EHT_DURATION_S(_s, _streams, _gi, \
+ EHT_BW2VBPS(_bw, 32666, 16333, 8166, 3900, 1950)), \
+ EHT_DURATION_S(_s, _streams, _gi, \
+ EHT_BW2VBPS(_bw, 35280, 17640, 8820, 4212, 2106)), \
+ EHT_DURATION_S(_s, _streams, _gi, \
+ EHT_BW2VBPS(_bw, 39200, 19600, 9800, 4680, 2340)) \
+ } \
+}
+
+#define EHT_GROUP_SHIFT(_streams, _gi, _bw) \
+ GROUP_SHIFT(EHT_DURATION(_streams, _gi, \
+ EHT_BW2VBPS(_bw, 1960, 980, 490, 234, 117)))
+
+#define EHT_GROUP(_streams, _gi, _bw) \
+ __EHT_GROUP(_streams, _gi, _bw, \
+ EHT_GROUP_SHIFT(_streams, _gi, _bw))
+
+#define EHT_GROUP_RANGE(_gi, _bw) \
+ EHT_GROUP(1, _gi, _bw), \
+ EHT_GROUP(2, _gi, _bw), \
+ EHT_GROUP(3, _gi, _bw), \
+ EHT_GROUP(4, _gi, _bw), \
+ EHT_GROUP(5, _gi, _bw), \
+ EHT_GROUP(6, _gi, _bw), \
+ EHT_GROUP(7, _gi, _bw), \
+ EHT_GROUP(8, _gi, _bw)
+
struct mcs_group {
u8 shift;
u16 duration[MCS_GROUP_RATES];
@@ -376,6 +459,26 @@ static const struct mcs_group airtime_mc
HE_GROUP(6, HE_GI_32, BW_160),
HE_GROUP(7, HE_GI_32, BW_160),
HE_GROUP(8, HE_GI_32, BW_160),
+
+ EHT_GROUP_RANGE(EHT_GI_08, BW_20),
+ EHT_GROUP_RANGE(EHT_GI_16, BW_20),
+ EHT_GROUP_RANGE(EHT_GI_32, BW_20),
+
+ EHT_GROUP_RANGE(EHT_GI_08, BW_40),
+ EHT_GROUP_RANGE(EHT_GI_16, BW_40),
+ EHT_GROUP_RANGE(EHT_GI_32, BW_40),
+
+ EHT_GROUP_RANGE(EHT_GI_08, BW_80),
+ EHT_GROUP_RANGE(EHT_GI_16, BW_80),
+ EHT_GROUP_RANGE(EHT_GI_32, BW_80),
+
+ EHT_GROUP_RANGE(EHT_GI_08, BW_160),
+ EHT_GROUP_RANGE(EHT_GI_16, BW_160),
+ EHT_GROUP_RANGE(EHT_GI_32, BW_160),
+
+ EHT_GROUP_RANGE(EHT_GI_08, BW_320),
+ EHT_GROUP_RANGE(EHT_GI_16, BW_320),
+ EHT_GROUP_RANGE(EHT_GI_32, BW_320),
};
static u32
@@ -422,6 +525,9 @@ static u32 ieee80211_get_rate_duration(s
case RATE_INFO_BW_160:
bw = BW_160;
break;
+ case RATE_INFO_BW_320:
+ bw = BW_320;
+ break;
default:
WARN_ON_ONCE(1);
return 0;
@@ -443,14 +549,27 @@ static u32 ieee80211_get_rate_duration(s
idx = status->rate_idx;
group = HE_GROUP_IDX(streams, status->he_gi, bw);
break;
+ case RX_ENC_EHT:
+ streams = status->nss;
+ idx = status->rate_idx;
+ group = EHT_GROUP_IDX(streams, status->eht.gi, bw);
+ break;
default:
WARN_ON_ONCE(1);
return 0;
}
- if (WARN_ON_ONCE((status->encoding != RX_ENC_HE && streams > 4) ||
- (status->encoding == RX_ENC_HE && streams > 8)))
- return 0;
+ switch (status->encoding) {
+ case RX_ENC_EHT:
+ case RX_ENC_HE:
+ if (WARN_ON_ONCE(streams > 8))
+ return 0;
+ break;
+ default:
+ if (WARN_ON_ONCE(streams > 4))
+ return 0;
+ break;
+ }
if (idx >= MCS_GROUP_RATES)
return 0;
@@ -517,7 +636,9 @@ static bool ieee80211_fill_rate_info(str
stat->nss = ri->nss;
stat->rate_idx = ri->mcs;
- if (ri->flags & RATE_INFO_FLAGS_HE_MCS)
+ if (ri->flags & RATE_INFO_FLAGS_EHT_MCS)
+ stat->encoding = RX_ENC_EHT;
+ else if (ri->flags & RATE_INFO_FLAGS_HE_MCS)
stat->encoding = RX_ENC_HE;
else if (ri->flags & RATE_INFO_FLAGS_VHT_MCS)
stat->encoding = RX_ENC_VHT;
@@ -529,7 +650,14 @@ static bool ieee80211_fill_rate_info(str
if (ri->flags & RATE_INFO_FLAGS_SHORT_GI)
stat->enc_flags |= RX_ENC_FLAG_SHORT_GI;
- stat->he_gi = ri->he_gi;
+ switch (stat->encoding) {
+ case RX_ENC_EHT:
+ stat->eht.gi = ri->eht_gi;
+ break;
+ default:
+ stat->he_gi = ri->he_gi;
+ break;
+ }
if (stat->encoding != RX_ENC_LEGACY)
return true;

View File

@ -1,70 +0,0 @@
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;

View File

@ -0,0 +1,64 @@
From: Issam Hamdi <ih@simonwunderlich.de>
Date: Fri, 16 Aug 2024 16:24:18 +0200
Subject: [PATCH] wifi: cfg80211: Set correct chandef when starting CAC
When starting CAC in a mode other than AP mode, it return a
"WARNING: CPU: 0 PID: 63 at cfg80211_chandef_dfs_usable+0x20/0xaf [cfg80211]"
caused by the chandef.chan being null at the end of CAC.
Solution: Ensure the channel definition is set for the different modes
when starting CAC to avoid getting a NULL 'chan' at the end of CAC.
Call Trace:
? show_regs.part.0+0x14/0x16
? __warn+0x67/0xc0
? cfg80211_chandef_dfs_usable+0x20/0xaf [cfg80211]
? report_bug+0xa7/0x130
? exc_overflow+0x30/0x30
? handle_bug+0x27/0x50
? exc_invalid_op+0x18/0x60
? handle_exception+0xf6/0xf6
? exc_overflow+0x30/0x30
? cfg80211_chandef_dfs_usable+0x20/0xaf [cfg80211]
? exc_overflow+0x30/0x30
? cfg80211_chandef_dfs_usable+0x20/0xaf [cfg80211]
? regulatory_propagate_dfs_state.cold+0x1b/0x4c [cfg80211]
? cfg80211_propagate_cac_done_wk+0x1a/0x30 [cfg80211]
? process_one_work+0x165/0x280
? worker_thread+0x120/0x3f0
? kthread+0xc2/0xf0
? process_one_work+0x280/0x280
? kthread_complete_and_exit+0x20/0x20
? ret_from_fork+0x19/0x24
Reported-by: Kretschmer Mathias <mathias.kretschmer@fit.fraunhofer.de>
Signed-off-by: Issam Hamdi <ih@simonwunderlich.de>
Link: https://patch.msgid.link/20240816142418.3381951-1-ih@simonwunderlich.de
[shorten subject, remove OCB, reorder cases to match previous list]
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -10144,7 +10144,20 @@ static int nl80211_start_radar_detection
err = rdev_start_radar_detection(rdev, dev, &chandef, cac_time_ms);
if (!err) {
- wdev->links[0].ap.chandef = chandef;
+ switch (wdev->iftype) {
+ case NL80211_IFTYPE_AP:
+ case NL80211_IFTYPE_P2P_GO:
+ wdev->links[0].ap.chandef = chandef;
+ break;
+ case NL80211_IFTYPE_ADHOC:
+ wdev->u.ibss.chandef = chandef;
+ break;
+ case NL80211_IFTYPE_MESH_POINT:
+ wdev->u.mesh.chandef = chandef;
+ break;
+ default:
+ break;
+ }
wdev->cac_started = true;
wdev->cac_start_time = jiffies;
wdev->cac_time_ms = cac_time_ms;

View File

@ -0,0 +1,136 @@
From: Aditya Kumar Singh <quic_adisi@quicinc.com>
Date: Fri, 6 Sep 2024 12:14:19 +0530
Subject: [PATCH] Revert "wifi: mac80211: move radar detect work to sdata"
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This reverts commit ce9e660ef32e ("wifi: mac80211: move radar detect work to sdata").
To enable radar detection with MLO, its essential to handle it on a
per-link basis. This is because when using MLO, multiple links may already
be active and beaconing. In this scenario, another link should be able to
initiate a radar detection. Also, if underlying links are associated with
different hardware devices but grouped together for MLO, they could
potentially start radar detection simultaneously. Therefore, it makes
sense to manage radar detection settings separately for each link by moving
them back to a per-link data structure.
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
Link: https://patch.msgid.link/20240906064426.2101315-2-quic_adisi@quicinc.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1658,7 +1658,7 @@ static int ieee80211_stop_ap(struct wiph
if (sdata->wdev.cac_started) {
chandef = link_conf->chanreq.oper;
- wiphy_delayed_work_cancel(wiphy, &sdata->dfs_cac_timer_work);
+ wiphy_delayed_work_cancel(wiphy, &link->dfs_cac_timer_work);
cfg80211_cac_event(sdata->dev, &chandef,
NL80211_RADAR_CAC_ABORTED,
GFP_KERNEL);
@@ -3482,7 +3482,7 @@ static int ieee80211_start_radar_detecti
if (err)
goto out_unlock;
- wiphy_delayed_work_queue(wiphy, &sdata->dfs_cac_timer_work,
+ wiphy_delayed_work_queue(wiphy, &sdata->deflink.dfs_cac_timer_work,
msecs_to_jiffies(cac_time_ms));
out_unlock:
@@ -3499,7 +3499,7 @@ static void ieee80211_end_cac(struct wip
list_for_each_entry(sdata, &local->interfaces, list) {
wiphy_delayed_work_cancel(wiphy,
- &sdata->dfs_cac_timer_work);
+ &sdata->deflink.dfs_cac_timer_work);
if (sdata->wdev.cac_started) {
ieee80211_link_release_channel(&sdata->deflink);
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1069,6 +1069,7 @@ struct ieee80211_link_data {
int ap_power_level; /* in dBm */
bool radar_required;
+ struct wiphy_delayed_work dfs_cac_timer_work;
union {
struct ieee80211_link_data_managed mgd;
@@ -1167,8 +1168,6 @@ struct ieee80211_sub_if_data {
struct ieee80211_link_data deflink;
struct ieee80211_link_data __rcu *link[IEEE80211_MLD_MAX_NUM_LINKS];
- struct wiphy_delayed_work dfs_cac_timer_work;
-
/* for ieee80211_set_active_links_async() */
struct wiphy_work activate_links_work;
u16 desired_active_links;
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -551,7 +551,7 @@ static void ieee80211_do_stop(struct iee
wiphy_work_cancel(local->hw.wiphy,
&sdata->deflink.color_change_finalize_work);
wiphy_delayed_work_cancel(local->hw.wiphy,
- &sdata->dfs_cac_timer_work);
+ &sdata->deflink.dfs_cac_timer_work);
if (sdata->wdev.cac_started) {
chandef = sdata->vif.bss_conf.chanreq.oper;
@@ -1744,8 +1744,6 @@ static void ieee80211_setup_sdata(struct
wiphy_work_init(&sdata->work, ieee80211_iface_work);
wiphy_work_init(&sdata->activate_links_work,
ieee80211_activate_links_work);
- wiphy_delayed_work_init(&sdata->dfs_cac_timer_work,
- ieee80211_dfs_cac_timer_work);
switch (type) {
case NL80211_IFTYPE_P2P_GO:
--- a/net/mac80211/link.c
+++ b/net/mac80211/link.c
@@ -45,6 +45,8 @@ void ieee80211_link_init(struct ieee8021
ieee80211_color_collision_detection_work);
INIT_LIST_HEAD(&link->assigned_chanctx_list);
INIT_LIST_HEAD(&link->reserved_chanctx_list);
+ wiphy_delayed_work_init(&link->dfs_cac_timer_work,
+ ieee80211_dfs_cac_timer_work);
if (!deflink) {
switch (sdata->vif.type) {
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -3031,15 +3031,16 @@ void ieee80211_dynamic_ps_timer(struct t
void ieee80211_dfs_cac_timer_work(struct wiphy *wiphy, struct wiphy_work *work)
{
- struct ieee80211_sub_if_data *sdata =
- container_of(work, struct ieee80211_sub_if_data,
+ struct ieee80211_link_data *link =
+ container_of(work, struct ieee80211_link_data,
dfs_cac_timer_work.work);
- struct cfg80211_chan_def chandef = sdata->vif.bss_conf.chanreq.oper;
+ struct cfg80211_chan_def chandef = link->conf->chanreq.oper;
+ struct ieee80211_sub_if_data *sdata = link->sdata;
lockdep_assert_wiphy(sdata->local->hw.wiphy);
if (sdata->wdev.cac_started) {
- ieee80211_link_release_channel(&sdata->deflink);
+ ieee80211_link_release_channel(link);
cfg80211_cac_event(sdata->dev, &chandef,
NL80211_RADAR_CAC_FINISHED,
GFP_KERNEL);
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -3460,7 +3460,7 @@ void ieee80211_dfs_cac_cancel(struct iee
list_for_each_entry(sdata, &local->interfaces, list) {
wiphy_delayed_work_cancel(local->hw.wiphy,
- &sdata->dfs_cac_timer_work);
+ &sdata->deflink.dfs_cac_timer_work);
if (sdata->wdev.cac_started) {
chandef = sdata->vif.bss_conf.chanreq.oper;

View File

@ -0,0 +1,50 @@
From: Aditya Kumar Singh <quic_adisi@quicinc.com>
Date: Fri, 6 Sep 2024 12:14:20 +0530
Subject: [PATCH] wifi: mac80211: remove label usage in
ieee80211_start_radar_detection()
After locks rework [1], ieee80211_start_radar_detection() function is no
longer acquiring any lock as such explicitly. Hence, it is not unlocking
anything as well. However, label "out_unlock" is still used which creates
confusion. Also, now there is no need of goto label as such.
Get rid of the goto logic and use direct return statements.
[1]: https://lore.kernel.org/all/20230828135928.b1c6efffe9ad.I4aec875e25abc9ef0b5ad1e70b5747fd483fbd3c@changeid/
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
Link: https://patch.msgid.link/20240906064426.2101315-3-quic_adisi@quicinc.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -3468,10 +3468,8 @@ static int ieee80211_start_radar_detecti
lockdep_assert_wiphy(local->hw.wiphy);
- if (!list_empty(&local->roc_list) || local->scanning) {
- err = -EBUSY;
- goto out_unlock;
- }
+ if (!list_empty(&local->roc_list) || local->scanning)
+ return -EBUSY;
/* whatever, but channel contexts should not complain about that one */
sdata->deflink.smps_mode = IEEE80211_SMPS_OFF;
@@ -3480,13 +3478,12 @@ static int ieee80211_start_radar_detecti
err = ieee80211_link_use_channel(&sdata->deflink, &chanreq,
IEEE80211_CHANCTX_SHARED);
if (err)
- goto out_unlock;
+ return err;
wiphy_delayed_work_queue(wiphy, &sdata->deflink.dfs_cac_timer_work,
msecs_to_jiffies(cac_time_ms));
- out_unlock:
- return err;
+ return 0;
}
static void ieee80211_end_cac(struct wiphy *wiphy,

View File

@ -0,0 +1,42 @@
From: Aditya Kumar Singh <quic_adisi@quicinc.com>
Date: Fri, 6 Sep 2024 12:14:21 +0530
Subject: [PATCH] wifi: trace: unlink rdev_end_cac trace event from
wiphy_netdev_evt class
rdev_end_cac trace event is linked with wiphy_netdev_evt event class.
There is no option to pass link ID currently to wiphy_netdev_evt class.
A subsequent change would pass link ID to rdev_end_cac event and hence
it can no longer derive the event class from wiphy_netdev_evt.
Therefore, unlink rdev_end_cac event from wiphy_netdev_evt and define it's
own independent trace event. Link ID would be passed in subsequent change.
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
Link: https://patch.msgid.link/20240906064426.2101315-4-quic_adisi@quicinc.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -805,9 +805,18 @@ DEFINE_EVENT(wiphy_netdev_evt, rdev_flus
TP_ARGS(wiphy, netdev)
);
-DEFINE_EVENT(wiphy_netdev_evt, rdev_end_cac,
- TP_PROTO(struct wiphy *wiphy, struct net_device *netdev),
- TP_ARGS(wiphy, netdev)
+TRACE_EVENT(rdev_end_cac,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev),
+ TP_ARGS(wiphy, netdev),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ NETDEV_ENTRY
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT, WIPHY_PR_ARG, NETDEV_PR_ARG)
);
DECLARE_EVENT_CLASS(station_add_change,

View File

@ -0,0 +1,309 @@
From: Aditya Kumar Singh <quic_adisi@quicinc.com>
Date: Fri, 6 Sep 2024 12:14:22 +0530
Subject: [PATCH] wifi: cfg80211: move DFS related members to links[] in
wireless_dev
A few members related to DFS handling are currently under per wireless
device data structure. However, in order to support DFS with MLO, there is
a need to have them on a per-link manner.
Hence, as a preliminary step, move members cac_started, cac_start_time
and cac_time_ms to be on a per-link basis.
Since currently, link ID is not known at all places, use default value of
0 for now.
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
Link: https://patch.msgid.link/20240906064426.2101315-5-quic_adisi@quicinc.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
--- a/drivers/net/wireless/marvell/mwifiex/11h.c
+++ b/drivers/net/wireless/marvell/mwifiex/11h.c
@@ -117,7 +117,7 @@ void mwifiex_dfs_cac_work_queue(struct w
dfs_cac_work);
chandef = priv->dfs_chandef;
- if (priv->wdev.cac_started) {
+ if (priv->wdev.links[0].cac_started) {
mwifiex_dbg(priv->adapter, MSG,
"CAC timer finished; No radar detected\n");
cfg80211_cac_event(priv->netdev, &chandef,
@@ -174,7 +174,7 @@ int mwifiex_stop_radar_detection(struct
*/
void mwifiex_abort_cac(struct mwifiex_private *priv)
{
- if (priv->wdev.cac_started) {
+ if (priv->wdev.links[0].cac_started) {
if (mwifiex_stop_radar_detection(priv, &priv->dfs_chandef))
mwifiex_dbg(priv->adapter, ERROR,
"failed to stop CAC in FW\n");
--- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
@@ -1880,7 +1880,7 @@ mwifiex_cfg80211_del_station(struct wiph
struct mwifiex_sta_node *sta_node;
u8 deauth_mac[ETH_ALEN];
- if (!priv->bss_started && priv->wdev.cac_started) {
+ if (!priv->bss_started && priv->wdev.links[0].cac_started) {
mwifiex_dbg(priv->adapter, INFO, "%s: abort CAC!\n", __func__);
mwifiex_abort_cac(priv);
}
@@ -3978,7 +3978,7 @@ mwifiex_cfg80211_channel_switch(struct w
return -EBUSY;
}
- if (priv->wdev.cac_started)
+ if (priv->wdev.links[0].cac_started)
return -EBUSY;
if (cfg80211_chandef_identical(&params->chandef,
--- a/drivers/net/wireless/quantenna/qtnfmac/event.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/event.c
@@ -520,21 +520,21 @@ static int qtnf_event_handle_radar(struc
cfg80211_radar_event(wiphy, &chandef, GFP_KERNEL);
break;
case QLINK_RADAR_CAC_FINISHED:
- if (!vif->wdev.cac_started)
+ if (!vif->wdev.links[0].cac_started)
break;
cfg80211_cac_event(vif->netdev, &chandef,
NL80211_RADAR_CAC_FINISHED, GFP_KERNEL);
break;
case QLINK_RADAR_CAC_ABORTED:
- if (!vif->wdev.cac_started)
+ if (!vif->wdev.links[0].cac_started)
break;
cfg80211_cac_event(vif->netdev, &chandef,
NL80211_RADAR_CAC_ABORTED, GFP_KERNEL);
break;
case QLINK_RADAR_CAC_STARTED:
- if (vif->wdev.cac_started)
+ if (vif->wdev.links[0].cac_started)
break;
if (!wiphy_ext_feature_isset(wiphy,
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -6198,9 +6198,6 @@ enum ieee80211_ap_reg_power {
* @address: The address for this device, valid only if @netdev is %NULL
* @is_running: true if this is a non-netdev device that has been started, e.g.
* the P2P Device.
- * @cac_started: true if DFS channel availability check has been started
- * @cac_start_time: timestamp (jiffies) when the dfs state was entered.
- * @cac_time_ms: CAC time in ms
* @ps: powersave mode is enabled
* @ps_timeout: dynamic powersave timeout
* @ap_unexpected_nlportid: (private) netlink port ID of application
@@ -6224,6 +6221,11 @@ enum ieee80211_ap_reg_power {
* unprotected beacon report
* @links: array of %IEEE80211_MLD_MAX_NUM_LINKS elements containing @addr
* @ap and @client for each link
+ * @links[].cac_started: true if DFS channel availability check has been
+ * started
+ * @links[].cac_start_time: timestamp (jiffies) when the dfs state was
+ * entered.
+ * @links[].cac_time_ms: CAC time in ms
* @valid_links: bitmap describing what elements of @links are valid
*/
struct wireless_dev {
@@ -6265,11 +6267,6 @@ struct wireless_dev {
u32 owner_nlportid;
bool nl_owner_dead;
- /* FIXME: need to rework radar detection for MLO */
- bool cac_started;
- unsigned long cac_start_time;
- unsigned int cac_time_ms;
-
#ifdef CPTCFG_CFG80211_WEXT
/* wext data */
struct {
@@ -6336,6 +6333,10 @@ struct wireless_dev {
struct cfg80211_internal_bss *current_bss;
} client;
};
+
+ bool cac_started;
+ unsigned long cac_start_time;
+ unsigned int cac_time_ms;
} links[IEEE80211_MLD_MAX_NUM_LINKS];
u16 valid_links;
};
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1656,7 +1656,7 @@ static int ieee80211_stop_ap(struct wiph
ieee80211_link_info_change_notify(sdata, link,
BSS_CHANGED_BEACON_ENABLED);
- if (sdata->wdev.cac_started) {
+ if (sdata->wdev.links[0].cac_started) {
chandef = link_conf->chanreq.oper;
wiphy_delayed_work_cancel(wiphy, &link->dfs_cac_timer_work);
cfg80211_cac_event(sdata->dev, &chandef,
@@ -3498,9 +3498,9 @@ static void ieee80211_end_cac(struct wip
wiphy_delayed_work_cancel(wiphy,
&sdata->deflink.dfs_cac_timer_work);
- if (sdata->wdev.cac_started) {
+ if (sdata->wdev.links[0].cac_started) {
ieee80211_link_release_channel(&sdata->deflink);
- sdata->wdev.cac_started = false;
+ sdata->wdev.links[0].cac_started = false;
}
}
}
@@ -3955,7 +3955,7 @@ __ieee80211_channel_switch(struct wiphy
if (!list_empty(&local->roc_list) || local->scanning)
return -EBUSY;
- if (sdata->wdev.cac_started)
+ if (sdata->wdev.links[0].cac_started)
return -EBUSY;
if (WARN_ON(link_id >= IEEE80211_MLD_MAX_NUM_LINKS))
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -553,7 +553,7 @@ static void ieee80211_do_stop(struct iee
wiphy_delayed_work_cancel(local->hw.wiphy,
&sdata->deflink.dfs_cac_timer_work);
- if (sdata->wdev.cac_started) {
+ if (sdata->wdev.links[0].cac_started) {
chandef = sdata->vif.bss_conf.chanreq.oper;
WARN_ON(local->suspended);
ieee80211_link_release_channel(&sdata->deflink);
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -3039,7 +3039,7 @@ void ieee80211_dfs_cac_timer_work(struct
lockdep_assert_wiphy(sdata->local->hw.wiphy);
- if (sdata->wdev.cac_started) {
+ if (sdata->wdev.links[0].cac_started) {
ieee80211_link_release_channel(link);
cfg80211_cac_event(sdata->dev, &chandef,
NL80211_RADAR_CAC_FINISHED,
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -585,7 +585,7 @@ static bool __ieee80211_can_leave_ch(str
return false;
list_for_each_entry(sdata_iter, &local->interfaces, list) {
- if (sdata_iter->wdev.cac_started)
+ if (sdata_iter->wdev.links[0].cac_started)
return false;
}
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -3462,7 +3462,7 @@ void ieee80211_dfs_cac_cancel(struct iee
wiphy_delayed_work_cancel(local->hw.wiphy,
&sdata->deflink.dfs_cac_timer_work);
- if (sdata->wdev.cac_started) {
+ if (sdata->wdev.links[0].cac_started) {
chandef = sdata->vif.bss_conf.chanreq.oper;
ieee80211_link_release_channel(&sdata->deflink);
cfg80211_cac_event(sdata->dev,
--- a/net/wireless/ibss.c
+++ b/net/wireless/ibss.c
@@ -94,7 +94,7 @@ int __cfg80211_join_ibss(struct cfg80211
lockdep_assert_held(&rdev->wiphy.mtx);
- if (wdev->cac_started)
+ if (wdev->links[0].cac_started)
return -EBUSY;
if (wdev->u.ibss.ssid_len)
--- a/net/wireless/mesh.c
+++ b/net/wireless/mesh.c
@@ -127,7 +127,7 @@ int __cfg80211_join_mesh(struct cfg80211
if (!rdev->ops->join_mesh)
return -EOPNOTSUPP;
- if (wdev->cac_started)
+ if (wdev->links[0].cac_started)
return -EBUSY;
if (!setup->chandef.chan) {
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -1124,13 +1124,14 @@ void cfg80211_cac_event(struct net_devic
trace_cfg80211_cac_event(netdev, event);
- if (WARN_ON(!wdev->cac_started && event != NL80211_RADAR_CAC_STARTED))
+ if (WARN_ON(!wdev->links[0].cac_started &&
+ event != NL80211_RADAR_CAC_STARTED))
return;
switch (event) {
case NL80211_RADAR_CAC_FINISHED:
- timeout = wdev->cac_start_time +
- msecs_to_jiffies(wdev->cac_time_ms);
+ timeout = wdev->links[0].cac_start_time +
+ msecs_to_jiffies(wdev->links[0].cac_time_ms);
WARN_ON(!time_after_eq(jiffies, timeout));
cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_AVAILABLE);
memcpy(&rdev->cac_done_chandef, chandef,
@@ -1139,10 +1140,10 @@ void cfg80211_cac_event(struct net_devic
cfg80211_sched_dfs_chan_update(rdev);
fallthrough;
case NL80211_RADAR_CAC_ABORTED:
- wdev->cac_started = false;
+ wdev->links[0].cac_started = false;
break;
case NL80211_RADAR_CAC_STARTED:
- wdev->cac_started = true;
+ wdev->links[0].cac_started = true;
break;
default:
WARN_ON(1);
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -6066,7 +6066,7 @@ static int nl80211_start_ap(struct sk_bu
if (!rdev->ops->start_ap)
return -EOPNOTSUPP;
- if (wdev->cac_started)
+ if (wdev->links[0].cac_started)
return -EBUSY;
if (wdev->links[link_id].ap.beacon_interval)
@@ -10122,7 +10122,7 @@ static int nl80211_start_radar_detection
goto unlock;
}
- if (cfg80211_beaconing_iface_active(wdev) || wdev->cac_started) {
+ if (cfg80211_beaconing_iface_active(wdev) || wdev->links[0].cac_started) {
err = -EBUSY;
goto unlock;
}
@@ -10158,9 +10158,9 @@ static int nl80211_start_radar_detection
default:
break;
}
- wdev->cac_started = true;
- wdev->cac_start_time = jiffies;
- wdev->cac_time_ms = cac_time_ms;
+ wdev->links[0].cac_started = true;
+ wdev->links[0].cac_start_time = jiffies;
+ wdev->links[0].cac_time_ms = cac_time_ms;
}
unlock:
wiphy_unlock(wiphy);
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -4241,7 +4241,7 @@ static void cfg80211_check_and_end_cac(s
list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
struct cfg80211_chan_def *chandef;
- if (!wdev->cac_started)
+ if (!wdev->links[0].cac_started)
continue;
/* FIXME: radar detection is tied to link 0 for now */

View File

@ -0,0 +1,435 @@
From: Aditya Kumar Singh <quic_adisi@quicinc.com>
Date: Fri, 6 Sep 2024 12:14:23 +0530
Subject: [PATCH] wifi: cfg80211: handle DFS per link
Currently, during starting a radar detection, no link id information is
parsed and passed down. In order to support starting radar detection
during Multi Link Operation, it is required to pass link id as well.
Add changes to first parse and then pass link id in the start radar
detection path.
Additionally, update notification APIs to allow drivers/mac80211 to
pass the link ID.
However, everything is handled at link 0 only until all API's are ready to
handle it per link.
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
Link: https://patch.msgid.link/20240906064426.2101315-6-quic_adisi@quicinc.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
--- a/drivers/net/wireless/marvell/mwifiex/11h.c
+++ b/drivers/net/wireless/marvell/mwifiex/11h.c
@@ -122,7 +122,7 @@ void mwifiex_dfs_cac_work_queue(struct w
"CAC timer finished; No radar detected\n");
cfg80211_cac_event(priv->netdev, &chandef,
NL80211_RADAR_CAC_FINISHED,
- GFP_KERNEL);
+ GFP_KERNEL, 0);
}
}
@@ -182,7 +182,8 @@ void mwifiex_abort_cac(struct mwifiex_pr
"Aborting delayed work for CAC.\n");
cancel_delayed_work_sync(&priv->dfs_cac_work);
cfg80211_cac_event(priv->netdev, &priv->dfs_chandef,
- NL80211_RADAR_CAC_ABORTED, GFP_KERNEL);
+ NL80211_RADAR_CAC_ABORTED, GFP_KERNEL,
+ 0);
}
}
@@ -221,7 +222,7 @@ int mwifiex_11h_handle_chanrpt_ready(str
cfg80211_cac_event(priv->netdev,
&priv->dfs_chandef,
NL80211_RADAR_DETECTED,
- GFP_KERNEL);
+ GFP_KERNEL, 0);
}
break;
default:
--- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
@@ -4145,7 +4145,7 @@ static int
mwifiex_cfg80211_start_radar_detection(struct wiphy *wiphy,
struct net_device *dev,
struct cfg80211_chan_def *chandef,
- u32 cac_time_ms)
+ u32 cac_time_ms, int link_id)
{
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
struct mwifiex_radar_params radar_params;
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -837,7 +837,7 @@ static int qtnf_channel_switch(struct wi
static int qtnf_start_radar_detection(struct wiphy *wiphy,
struct net_device *ndev,
struct cfg80211_chan_def *chandef,
- u32 cac_time_ms)
+ u32 cac_time_ms, int link_id)
{
struct qtnf_vif *vif = qtnf_netdev_get_priv(ndev);
int ret;
--- a/drivers/net/wireless/quantenna/qtnfmac/event.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/event.c
@@ -524,14 +524,14 @@ static int qtnf_event_handle_radar(struc
break;
cfg80211_cac_event(vif->netdev, &chandef,
- NL80211_RADAR_CAC_FINISHED, GFP_KERNEL);
+ NL80211_RADAR_CAC_FINISHED, GFP_KERNEL, 0);
break;
case QLINK_RADAR_CAC_ABORTED:
if (!vif->wdev.links[0].cac_started)
break;
cfg80211_cac_event(vif->netdev, &chandef,
- NL80211_RADAR_CAC_ABORTED, GFP_KERNEL);
+ NL80211_RADAR_CAC_ABORTED, GFP_KERNEL, 0);
break;
case QLINK_RADAR_CAC_STARTED:
if (vif->wdev.links[0].cac_started)
@@ -542,7 +542,7 @@ static int qtnf_event_handle_radar(struc
break;
cfg80211_cac_event(vif->netdev, &chandef,
- NL80211_RADAR_CAC_STARTED, GFP_KERNEL);
+ NL80211_RADAR_CAC_STARTED, GFP_KERNEL, 0);
break;
default:
pr_warn("%s: unhandled radar event %u\n",
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -4841,9 +4841,9 @@ struct cfg80211_ops {
int (*start_radar_detection)(struct wiphy *wiphy,
struct net_device *dev,
struct cfg80211_chan_def *chandef,
- u32 cac_time_ms);
+ u32 cac_time_ms, int link_id);
void (*end_cac)(struct wiphy *wiphy,
- struct net_device *dev);
+ struct net_device *dev, unsigned int link_id);
int (*update_ft_ies)(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_update_ft_ies_params *ftie);
int (*crit_proto_start)(struct wiphy *wiphy,
@@ -8745,6 +8745,7 @@ void cfg80211_sta_opmode_change_notify(s
* @chandef: chandef for the current channel
* @event: type of event
* @gfp: context flags
+ * @link_id: valid link_id for MLO operation or 0 otherwise.
*
* This function is called when a Channel availability check (CAC) is finished
* or aborted. This must be called to notify the completion of a CAC process,
@@ -8752,7 +8753,8 @@ void cfg80211_sta_opmode_change_notify(s
*/
void cfg80211_cac_event(struct net_device *netdev,
const struct cfg80211_chan_def *chandef,
- enum nl80211_radar_event event, gfp_t gfp);
+ enum nl80211_radar_event event, gfp_t gfp,
+ unsigned int link_id);
/**
* cfg80211_background_cac_abort - Channel Availability Check offchan abort event
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1661,7 +1661,7 @@ static int ieee80211_stop_ap(struct wiph
wiphy_delayed_work_cancel(wiphy, &link->dfs_cac_timer_work);
cfg80211_cac_event(sdata->dev, &chandef,
NL80211_RADAR_CAC_ABORTED,
- GFP_KERNEL);
+ GFP_KERNEL, 0);
}
drv_stop_ap(sdata->local, sdata, link_conf);
@@ -3459,7 +3459,7 @@ static int ieee80211_set_bitrate_mask(st
static int ieee80211_start_radar_detection(struct wiphy *wiphy,
struct net_device *dev,
struct cfg80211_chan_def *chandef,
- u32 cac_time_ms)
+ u32 cac_time_ms, int link_id)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_chan_req chanreq = { .oper = *chandef };
@@ -3487,7 +3487,7 @@ static int ieee80211_start_radar_detecti
}
static void ieee80211_end_cac(struct wiphy *wiphy,
- struct net_device *dev)
+ struct net_device *dev, unsigned int link_id)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_local *local = sdata->local;
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -559,7 +559,7 @@ static void ieee80211_do_stop(struct iee
ieee80211_link_release_channel(&sdata->deflink);
cfg80211_cac_event(sdata->dev, &chandef,
NL80211_RADAR_CAC_ABORTED,
- GFP_KERNEL);
+ GFP_KERNEL, 0);
}
if (sdata->vif.type == NL80211_IFTYPE_AP) {
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -3043,7 +3043,7 @@ void ieee80211_dfs_cac_timer_work(struct
ieee80211_link_release_channel(link);
cfg80211_cac_event(sdata->dev, &chandef,
NL80211_RADAR_CAC_FINISHED,
- GFP_KERNEL);
+ GFP_KERNEL, 0);
}
}
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -3468,7 +3468,7 @@ void ieee80211_dfs_cac_cancel(struct iee
cfg80211_cac_event(sdata->dev,
&chandef,
NL80211_RADAR_CAC_ABORTED,
- GFP_KERNEL);
+ GFP_KERNEL, 0);
}
}
}
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -1111,18 +1111,19 @@ EXPORT_SYMBOL(__cfg80211_radar_event);
void cfg80211_cac_event(struct net_device *netdev,
const struct cfg80211_chan_def *chandef,
- enum nl80211_radar_event event, gfp_t gfp)
+ enum nl80211_radar_event event, gfp_t gfp,
+ unsigned int link_id)
{
struct wireless_dev *wdev = netdev->ieee80211_ptr;
struct wiphy *wiphy = wdev->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
unsigned long timeout;
- /* not yet supported */
- if (wdev->valid_links)
+ if (WARN_ON(wdev->valid_links &&
+ !(wdev->valid_links & BIT(link_id))))
return;
- trace_cfg80211_cac_event(netdev, event);
+ trace_cfg80211_cac_event(netdev, event, link_id);
if (WARN_ON(!wdev->links[0].cac_started &&
event != NL80211_RADAR_CAC_STARTED))
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -10122,7 +10122,20 @@ static int nl80211_start_radar_detection
goto unlock;
}
- if (cfg80211_beaconing_iface_active(wdev) || wdev->links[0].cac_started) {
+ if (cfg80211_beaconing_iface_active(wdev)) {
+ /* During MLO other link(s) can beacon, only the current link
+ * can not already beacon
+ */
+ if (wdev->valid_links &&
+ !wdev->links[0].ap.beacon_interval) {
+ /* nothing */
+ } else {
+ err = -EBUSY;
+ goto unlock;
+ }
+ }
+
+ if (wdev->links[0].cac_started) {
err = -EBUSY;
goto unlock;
}
@@ -10142,7 +10155,8 @@ static int nl80211_start_radar_detection
if (WARN_ON(!cac_time_ms))
cac_time_ms = IEEE80211_DFS_MIN_CAC_TIME_MS;
- err = rdev_start_radar_detection(rdev, dev, &chandef, cac_time_ms);
+ err = rdev_start_radar_detection(rdev, dev, &chandef, cac_time_ms,
+ 0);
if (!err) {
switch (wdev->iftype) {
case NL80211_IFTYPE_AP:
@@ -16512,10 +16526,10 @@ nl80211_set_ttlm(struct sk_buff *skb, st
SELECTOR(__sel, NETDEV_UP_NOTMX, \
NL80211_FLAG_NEED_NETDEV_UP | \
NL80211_FLAG_NO_WIPHY_MTX) \
- SELECTOR(__sel, NETDEV_UP_NOTMX_NOMLO, \
+ SELECTOR(__sel, NETDEV_UP_NOTMX_MLO, \
NL80211_FLAG_NEED_NETDEV_UP | \
NL80211_FLAG_NO_WIPHY_MTX | \
- NL80211_FLAG_MLO_UNSUPPORTED) \
+ NL80211_FLAG_MLO_VALID_LINK_ID) \
SELECTOR(__sel, NETDEV_UP_CLEAR, \
NL80211_FLAG_NEED_NETDEV_UP | \
NL80211_FLAG_CLEAR_SKB) \
@@ -17410,7 +17424,7 @@ static const struct genl_small_ops nl802
.flags = GENL_UNS_ADMIN_PERM,
.internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NO_WIPHY_MTX |
- NL80211_FLAG_MLO_UNSUPPORTED),
+ NL80211_FLAG_MLO_VALID_LINK_ID),
},
{
.cmd = NL80211_CMD_GET_PROTOCOL_FEATURES,
--- a/net/wireless/rdev-ops.h
+++ b/net/wireless/rdev-ops.h
@@ -1200,26 +1200,27 @@ static inline int
rdev_start_radar_detection(struct cfg80211_registered_device *rdev,
struct net_device *dev,
struct cfg80211_chan_def *chandef,
- u32 cac_time_ms)
+ u32 cac_time_ms, int link_id)
{
int ret = -EOPNOTSUPP;
trace_rdev_start_radar_detection(&rdev->wiphy, dev, chandef,
- cac_time_ms);
+ cac_time_ms, link_id);
if (rdev->ops->start_radar_detection)
ret = rdev->ops->start_radar_detection(&rdev->wiphy, dev,
- chandef, cac_time_ms);
+ chandef, cac_time_ms,
+ link_id);
trace_rdev_return_int(&rdev->wiphy, ret);
return ret;
}
static inline void
rdev_end_cac(struct cfg80211_registered_device *rdev,
- struct net_device *dev)
+ struct net_device *dev, unsigned int link_id)
{
- trace_rdev_end_cac(&rdev->wiphy, dev);
+ trace_rdev_end_cac(&rdev->wiphy, dev, link_id);
if (rdev->ops->end_cac)
- rdev->ops->end_cac(&rdev->wiphy, dev);
+ rdev->ops->end_cac(&rdev->wiphy, dev, link_id);
trace_rdev_return_void(&rdev->wiphy);
}
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -4229,6 +4229,8 @@ EXPORT_SYMBOL(regulatory_pre_cac_allowed
static void cfg80211_check_and_end_cac(struct cfg80211_registered_device *rdev)
{
struct wireless_dev *wdev;
+ unsigned int link_id;
+
/* If we finished CAC or received radar, we should end any
* CAC running on the same channels.
* the check !cfg80211_chandef_dfs_usable contain 2 options:
@@ -4241,16 +4243,17 @@ static void cfg80211_check_and_end_cac(s
list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
struct cfg80211_chan_def *chandef;
- if (!wdev->links[0].cac_started)
- continue;
+ for_each_valid_link(wdev, link_id) {
+ if (!wdev->links[link_id].cac_started)
+ continue;
- /* FIXME: radar detection is tied to link 0 for now */
- chandef = wdev_chandef(wdev, 0);
- if (!chandef)
- continue;
+ chandef = wdev_chandef(wdev, link_id);
+ if (!chandef)
+ continue;
- if (!cfg80211_chandef_dfs_usable(&rdev->wiphy, chandef))
- rdev_end_cac(rdev, wdev->netdev);
+ if (!cfg80211_chandef_dfs_usable(&rdev->wiphy, chandef))
+ rdev_end_cac(rdev, wdev->netdev, link_id);
+ }
}
}
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -806,17 +806,21 @@ DEFINE_EVENT(wiphy_netdev_evt, rdev_flus
);
TRACE_EVENT(rdev_end_cac,
- TP_PROTO(struct wiphy *wiphy, struct net_device *netdev),
- TP_ARGS(wiphy, netdev),
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+ unsigned int link_id),
+ TP_ARGS(wiphy, netdev, link_id),
TP_STRUCT__entry(
WIPHY_ENTRY
NETDEV_ENTRY
+ __field(unsigned int, link_id)
),
TP_fast_assign(
WIPHY_ASSIGN;
NETDEV_ASSIGN;
+ __entry->link_id = link_id;
),
- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT, WIPHY_PR_ARG, NETDEV_PR_ARG)
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", link_id: %d",
+ WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->link_id)
);
DECLARE_EVENT_CLASS(station_add_change,
@@ -2661,24 +2665,26 @@ TRACE_EVENT(rdev_external_auth,
TRACE_EVENT(rdev_start_radar_detection,
TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
struct cfg80211_chan_def *chandef,
- u32 cac_time_ms),
- TP_ARGS(wiphy, netdev, chandef, cac_time_ms),
+ u32 cac_time_ms, int link_id),
+ TP_ARGS(wiphy, netdev, chandef, cac_time_ms, link_id),
TP_STRUCT__entry(
WIPHY_ENTRY
NETDEV_ENTRY
CHAN_DEF_ENTRY
__field(u32, cac_time_ms)
+ __field(int, link_id)
),
TP_fast_assign(
WIPHY_ASSIGN;
NETDEV_ASSIGN;
CHAN_DEF_ASSIGN(chandef);
__entry->cac_time_ms = cac_time_ms;
+ __entry->link_id = link_id;
),
TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " CHAN_DEF_PR_FMT
- ", cac_time_ms=%u",
+ ", cac_time_ms=%u, link_id=%d",
WIPHY_PR_ARG, NETDEV_PR_ARG, CHAN_DEF_PR_ARG,
- __entry->cac_time_ms)
+ __entry->cac_time_ms, __entry->link_id)
);
TRACE_EVENT(rdev_set_mcast_rate,
@@ -3492,18 +3498,21 @@ TRACE_EVENT(cfg80211_radar_event,
);
TRACE_EVENT(cfg80211_cac_event,
- TP_PROTO(struct net_device *netdev, enum nl80211_radar_event evt),
- TP_ARGS(netdev, evt),
+ TP_PROTO(struct net_device *netdev, enum nl80211_radar_event evt,
+ unsigned int link_id),
+ TP_ARGS(netdev, evt, link_id),
TP_STRUCT__entry(
NETDEV_ENTRY
__field(enum nl80211_radar_event, evt)
+ __field(unsigned int, link_id)
),
TP_fast_assign(
NETDEV_ASSIGN;
__entry->evt = evt;
+ __entry->link_id = link_id;
),
- TP_printk(NETDEV_PR_FMT ", event: %d",
- NETDEV_PR_ARG, __entry->evt)
+ TP_printk(NETDEV_PR_FMT ", event: %d, link_id=%u",
+ NETDEV_PR_ARG, __entry->evt, __entry->link_id)
);
DECLARE_EVENT_CLASS(cfg80211_rx_evt,

View File

@ -0,0 +1,134 @@
From: Aditya Kumar Singh <quic_adisi@quicinc.com>
Date: Fri, 6 Sep 2024 12:14:24 +0530
Subject: [PATCH] wifi: mac80211: handle DFS per link
In order to support DFS with MLO, handle the link ID now passed from
cfg80211, adjust the code to do everything per link and call the
notifications to cfg80211 correctly.
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
Link: https://patch.msgid.link/20240906064426.2101315-7-quic_adisi@quicinc.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -3464,6 +3464,7 @@ static int ieee80211_start_radar_detecti
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_chan_req chanreq = { .oper = *chandef };
struct ieee80211_local *local = sdata->local;
+ struct ieee80211_link_data *link_data;
int err;
lockdep_assert_wiphy(local->hw.wiphy);
@@ -3471,16 +3472,20 @@ static int ieee80211_start_radar_detecti
if (!list_empty(&local->roc_list) || local->scanning)
return -EBUSY;
+ link_data = sdata_dereference(sdata->link[link_id], sdata);
+ if (!link_data)
+ return -ENOLINK;
+
/* whatever, but channel contexts should not complain about that one */
- sdata->deflink.smps_mode = IEEE80211_SMPS_OFF;
- sdata->deflink.needed_rx_chains = local->rx_chains;
+ link_data->smps_mode = IEEE80211_SMPS_OFF;
+ link_data->needed_rx_chains = local->rx_chains;
- err = ieee80211_link_use_channel(&sdata->deflink, &chanreq,
+ err = ieee80211_link_use_channel(link_data, &chanreq,
IEEE80211_CHANCTX_SHARED);
if (err)
return err;
- wiphy_delayed_work_queue(wiphy, &sdata->deflink.dfs_cac_timer_work,
+ wiphy_delayed_work_queue(wiphy, &link_data->dfs_cac_timer_work,
msecs_to_jiffies(cac_time_ms));
return 0;
@@ -3491,16 +3496,21 @@ static void ieee80211_end_cac(struct wip
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_local *local = sdata->local;
+ struct ieee80211_link_data *link_data;
lockdep_assert_wiphy(local->hw.wiphy);
list_for_each_entry(sdata, &local->interfaces, list) {
+ link_data = sdata_dereference(sdata->link[link_id], sdata);
+ if (!link_data)
+ continue;
+
wiphy_delayed_work_cancel(wiphy,
- &sdata->deflink.dfs_cac_timer_work);
+ &link_data->dfs_cac_timer_work);
- if (sdata->wdev.links[0].cac_started) {
- ieee80211_link_release_channel(&sdata->deflink);
- sdata->wdev.links[0].cac_started = false;
+ if (sdata->wdev.links[link_id].cac_started) {
+ ieee80211_link_release_channel(link_data);
+ sdata->wdev.links[link_id].cac_started = false;
}
}
}
--- a/net/mac80211/link.c
+++ b/net/mac80211/link.c
@@ -77,6 +77,16 @@ void ieee80211_link_stop(struct ieee8021
&link->color_change_finalize_work);
wiphy_work_cancel(link->sdata->local->hw.wiphy,
&link->csa.finalize_work);
+
+ if (link->sdata->wdev.links[link->link_id].cac_started) {
+ wiphy_delayed_work_cancel(link->sdata->local->hw.wiphy,
+ &link->dfs_cac_timer_work);
+ cfg80211_cac_event(link->sdata->dev,
+ &link->conf->chanreq.oper,
+ NL80211_RADAR_CAC_ABORTED,
+ GFP_KERNEL, link->link_id);
+ }
+
ieee80211_link_release_channel(link);
}
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -3455,20 +3455,30 @@ void ieee80211_dfs_cac_cancel(struct iee
{
struct ieee80211_sub_if_data *sdata;
struct cfg80211_chan_def chandef;
+ struct ieee80211_link_data *link;
+ unsigned int link_id;
lockdep_assert_wiphy(local->hw.wiphy);
list_for_each_entry(sdata, &local->interfaces, list) {
- wiphy_delayed_work_cancel(local->hw.wiphy,
- &sdata->deflink.dfs_cac_timer_work);
+ for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS;
+ link_id++) {
+ link = sdata_dereference(sdata->link[link_id],
+ sdata);
+ if (!link)
+ continue;
- if (sdata->wdev.links[0].cac_started) {
- chandef = sdata->vif.bss_conf.chanreq.oper;
- ieee80211_link_release_channel(&sdata->deflink);
- cfg80211_cac_event(sdata->dev,
- &chandef,
+ wiphy_delayed_work_cancel(local->hw.wiphy,
+ &link->dfs_cac_timer_work);
+
+ if (!sdata->wdev.links[link_id].cac_started)
+ continue;
+
+ chandef = link->conf->chanreq.oper;
+ ieee80211_link_release_channel(link);
+ cfg80211_cac_event(sdata->dev, &chandef,
NL80211_RADAR_CAC_ABORTED,
- GFP_KERNEL, 0);
+ GFP_KERNEL, link_id);
}
}
}

View File

@ -0,0 +1,168 @@
From: Aditya Kumar Singh <quic_adisi@quicinc.com>
Date: Fri, 6 Sep 2024 12:14:25 +0530
Subject: [PATCH] wifi: cfg80211/mac80211: use proper link ID for DFS
Now that all APIs have support to handle DFS per link, use proper link ID
instead of 0.
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
Link: https://patch.msgid.link/20240906064426.2101315-8-quic_adisi@quicinc.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1656,12 +1656,12 @@ static int ieee80211_stop_ap(struct wiph
ieee80211_link_info_change_notify(sdata, link,
BSS_CHANGED_BEACON_ENABLED);
- if (sdata->wdev.links[0].cac_started) {
+ if (sdata->wdev.links[link_id].cac_started) {
chandef = link_conf->chanreq.oper;
wiphy_delayed_work_cancel(wiphy, &link->dfs_cac_timer_work);
cfg80211_cac_event(sdata->dev, &chandef,
NL80211_RADAR_CAC_ABORTED,
- GFP_KERNEL, 0);
+ GFP_KERNEL, link_id);
}
drv_stop_ap(sdata->local, sdata, link_conf);
@@ -3965,7 +3965,7 @@ __ieee80211_channel_switch(struct wiphy
if (!list_empty(&local->roc_list) || local->scanning)
return -EBUSY;
- if (sdata->wdev.links[0].cac_started)
+ if (sdata->wdev.links[link_id].cac_started)
return -EBUSY;
if (WARN_ON(link_id >= IEEE80211_MLD_MAX_NUM_LINKS))
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -3039,11 +3039,11 @@ void ieee80211_dfs_cac_timer_work(struct
lockdep_assert_wiphy(sdata->local->hw.wiphy);
- if (sdata->wdev.links[0].cac_started) {
+ if (sdata->wdev.links[link->link_id].cac_started) {
ieee80211_link_release_channel(link);
cfg80211_cac_event(sdata->dev, &chandef,
NL80211_RADAR_CAC_FINISHED,
- GFP_KERNEL, 0);
+ GFP_KERNEL, link->link_id);
}
}
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -575,6 +575,7 @@ static bool __ieee80211_can_leave_ch(str
{
struct ieee80211_local *local = sdata->local;
struct ieee80211_sub_if_data *sdata_iter;
+ unsigned int link_id;
lockdep_assert_wiphy(local->hw.wiphy);
@@ -585,8 +586,9 @@ static bool __ieee80211_can_leave_ch(str
return false;
list_for_each_entry(sdata_iter, &local->interfaces, list) {
- if (sdata_iter->wdev.links[0].cac_started)
- return false;
+ for_each_valid_link(&sdata_iter->wdev, link_id)
+ if (sdata_iter->wdev.links[link_id].cac_started)
+ return false;
}
return true;
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -1125,14 +1125,14 @@ void cfg80211_cac_event(struct net_devic
trace_cfg80211_cac_event(netdev, event, link_id);
- if (WARN_ON(!wdev->links[0].cac_started &&
+ if (WARN_ON(!wdev->links[link_id].cac_started &&
event != NL80211_RADAR_CAC_STARTED))
return;
switch (event) {
case NL80211_RADAR_CAC_FINISHED:
- timeout = wdev->links[0].cac_start_time +
- msecs_to_jiffies(wdev->links[0].cac_time_ms);
+ timeout = wdev->links[link_id].cac_start_time +
+ msecs_to_jiffies(wdev->links[link_id].cac_time_ms);
WARN_ON(!time_after_eq(jiffies, timeout));
cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_AVAILABLE);
memcpy(&rdev->cac_done_chandef, chandef,
@@ -1141,10 +1141,10 @@ void cfg80211_cac_event(struct net_devic
cfg80211_sched_dfs_chan_update(rdev);
fallthrough;
case NL80211_RADAR_CAC_ABORTED:
- wdev->links[0].cac_started = false;
+ wdev->links[link_id].cac_started = false;
break;
case NL80211_RADAR_CAC_STARTED:
- wdev->links[0].cac_started = true;
+ wdev->links[link_id].cac_started = true;
break;
default:
WARN_ON(1);
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -6066,7 +6066,7 @@ static int nl80211_start_ap(struct sk_bu
if (!rdev->ops->start_ap)
return -EOPNOTSUPP;
- if (wdev->links[0].cac_started)
+ if (wdev->links[link_id].cac_started)
return -EBUSY;
if (wdev->links[link_id].ap.beacon_interval)
@@ -10073,6 +10073,7 @@ static int nl80211_start_radar_detection
struct cfg80211_registered_device *rdev = info->user_ptr[0];
struct net_device *dev = info->user_ptr[1];
struct wireless_dev *wdev = dev->ieee80211_ptr;
+ int link_id = nl80211_link_id(info->attrs);
struct wiphy *wiphy = wdev->wiphy;
struct cfg80211_chan_def chandef;
enum nl80211_dfs_regions dfs_region;
@@ -10127,7 +10128,7 @@ static int nl80211_start_radar_detection
* can not already beacon
*/
if (wdev->valid_links &&
- !wdev->links[0].ap.beacon_interval) {
+ !wdev->links[link_id].ap.beacon_interval) {
/* nothing */
} else {
err = -EBUSY;
@@ -10135,7 +10136,7 @@ static int nl80211_start_radar_detection
}
}
- if (wdev->links[0].cac_started) {
+ if (wdev->links[link_id].cac_started) {
err = -EBUSY;
goto unlock;
}
@@ -10156,7 +10157,7 @@ static int nl80211_start_radar_detection
cac_time_ms = IEEE80211_DFS_MIN_CAC_TIME_MS;
err = rdev_start_radar_detection(rdev, dev, &chandef, cac_time_ms,
- 0);
+ link_id);
if (!err) {
switch (wdev->iftype) {
case NL80211_IFTYPE_AP:
@@ -10172,9 +10173,9 @@ static int nl80211_start_radar_detection
default:
break;
}
- wdev->links[0].cac_started = true;
- wdev->links[0].cac_start_time = jiffies;
- wdev->links[0].cac_time_ms = cac_time_ms;
+ wdev->links[link_id].cac_started = true;
+ wdev->links[link_id].cac_start_time = jiffies;
+ wdev->links[link_id].cac_time_ms = cac_time_ms;
}
unlock:
wiphy_unlock(wiphy);

View File

@ -0,0 +1,360 @@
From: Aditya Kumar Singh <quic_adisi@quicinc.com>
Date: Fri, 6 Sep 2024 12:14:26 +0530
Subject: [PATCH] wifi: mac80211: handle ieee80211_radar_detected() for MLO
Currently DFS works under assumption there could be only one channel
context in the hardware. Hence, drivers just calls the function
ieee80211_radar_detected() passing the hardware structure. However, with
MLO, this obviously will not work since number of channel contexts will be
more than one and hence drivers would need to pass the channel information
as well on which the radar is detected.
Also, when radar is detected in one of the links, other link's CAC should
not be cancelled.
Hence, in order to support DFS with MLO, do the following changes -
* Add channel context conf pointer as an argument to the function
ieee80211_radar_detected(). During MLO, drivers would have to pass on
which channel context conf radar is detected. Otherwise, drivers could
just pass NULL.
* ieee80211_radar_detected() will iterate over all channel contexts
present and
* if channel context conf is passed, only mark that as radar
detected
* if NULL is passed, then mark all channel contexts as radar
detected
* Then as usual, schedule the radar detected work.
* In the worker, go over all the contexts again and for all such context
which is marked with radar detected, cancel the ongoing CAC by calling
ieee80211_dfs_cac_cancel() and then notify cfg80211 via
cfg80211_radar_event().
* To cancel the CAC, pass the channel context as well where radar is
detected to ieee80211_dfs_cac_cancel(). This ensures that CAC is
canceled only on the links using the provided context, leaving other
links unaffected.
This would also help in scenarios where there is split phy 5 GHz radio,
which is capable of DFS channels in both lower and upper band. In this
case, simultaneous radars can be detected.
Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
Link: https://patch.msgid.link/20240906064426.2101315-9-quic_adisi@quicinc.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -3,7 +3,7 @@
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/module.h>
@@ -1774,7 +1774,7 @@ static ssize_t ath10k_write_simulate_rad
if (!arvif->is_started)
return -EINVAL;
- ieee80211_radar_detected(ar->hw);
+ ieee80211_radar_detected(ar->hw, NULL);
return count;
}
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -1437,7 +1437,7 @@ static void ath10k_recalc_radar_detectio
* by indicating that radar was detected.
*/
ath10k_warn(ar, "failed to start CAC: %d\n", ret);
- ieee80211_radar_detected(ar->hw);
+ ieee80211_radar_detected(ar->hw, NULL);
}
}
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -3990,7 +3990,7 @@ static void ath10k_radar_detected(struct
if (ar->dfs_block_radar_events)
ath10k_info(ar, "DFS Radar detected, but ignored as requested\n");
else
- ieee80211_radar_detected(ar->hw);
+ ieee80211_radar_detected(ar->hw, NULL);
}
static void ath10k_radar_confirmation_work(struct work_struct *work)
--- a/drivers/net/wireless/ath/ath11k/wmi.c
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
@@ -8358,7 +8358,7 @@ ath11k_wmi_pdev_dfs_radar_detected_event
if (ar->dfs_block_radar_events)
ath11k_info(ab, "DFS Radar detected, but ignored as requested\n");
else
- ieee80211_radar_detected(ar->hw);
+ ieee80211_radar_detected(ar->hw, NULL);
exit:
rcu_read_unlock();
--- a/drivers/net/wireless/ath/ath12k/wmi.c
+++ b/drivers/net/wireless/ath/ath12k/wmi.c
@@ -6789,7 +6789,7 @@ ath12k_wmi_pdev_dfs_radar_detected_event
if (ar->dfs_block_radar_events)
ath12k_info(ab, "DFS Radar detected, but ignored as requested\n");
else
- ieee80211_radar_detected(ath12k_ar_to_hw(ar));
+ ieee80211_radar_detected(ath12k_ar_to_hw(ar), NULL);
exit:
rcu_read_unlock();
--- a/drivers/net/wireless/ath/ath9k/dfs.c
+++ b/drivers/net/wireless/ath/ath9k/dfs.c
@@ -280,7 +280,7 @@ ath9k_dfs_process_radar_pulse(struct ath
if (!pd->add_pulse(pd, pe, NULL))
return;
DFS_STAT_INC(sc, radar_detected);
- ieee80211_radar_detected(sc->hw);
+ ieee80211_radar_detected(sc->hw, NULL);
}
/*
--- a/drivers/net/wireless/ath/ath9k/dfs_debug.c
+++ b/drivers/net/wireless/ath/ath9k/dfs_debug.c
@@ -116,7 +116,7 @@ static ssize_t write_file_simulate_radar
{
struct ath_softc *sc = file->private_data;
- ieee80211_radar_detected(sc->hw);
+ ieee80211_radar_detected(sc->hw, NULL);
return count;
}
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
@@ -394,7 +394,7 @@ mt7615_mcu_rx_radar_detected(struct mt76
if (mt76_phy_dfs_state(mphy) < MT_DFS_STATE_CAC)
return;
- ieee80211_radar_detected(mphy->hw);
+ ieee80211_radar_detected(mphy->hw, NULL);
dev->hw_pattern++;
}
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c
@@ -630,7 +630,7 @@ static void mt76x02_dfs_tasklet(struct t
radar_detected = mt76x02_dfs_check_detection(dev);
if (radar_detected) {
/* sw detector rx radar pattern */
- ieee80211_radar_detected(dev->mt76.hw);
+ ieee80211_radar_detected(dev->mt76.hw, NULL);
mt76x02_dfs_detector_reset(dev);
return;
@@ -658,7 +658,7 @@ static void mt76x02_dfs_tasklet(struct t
/* hw detector rx radar pattern */
dfs_pd->stats[i].hw_pattern++;
- ieee80211_radar_detected(dev->mt76.hw);
+ ieee80211_radar_detected(dev->mt76.hw, NULL);
mt76x02_dfs_detector_reset(dev);
return;
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
@@ -293,7 +293,7 @@ mt7915_mcu_rx_radar_detected(struct mt79
&dev->rdd2_chandef,
GFP_ATOMIC);
else
- ieee80211_radar_detected(mphy->hw);
+ ieee80211_radar_detected(mphy->hw, NULL);
dev->hw_pattern++;
}
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
@@ -371,7 +371,7 @@ mt7996_mcu_rx_radar_detected(struct mt79
&dev->rdd2_chandef,
GFP_ATOMIC);
else
- ieee80211_radar_detected(mphy->hw);
+ ieee80211_radar_detected(mphy->hw, NULL);
dev->hw_pattern++;
}
--- a/drivers/net/wireless/ti/wl18xx/event.c
+++ b/drivers/net/wireless/ti/wl18xx/event.c
@@ -142,7 +142,7 @@ int wl18xx_process_mailbox_events(struct
wl18xx_radar_type_decode(mbox->radar_type));
if (!wl->radar_debug_mode)
- ieee80211_radar_detected(wl->hw);
+ ieee80211_radar_detected(wl->hw, NULL);
}
if (vector & PERIODIC_SCAN_REPORT_EVENT_ID) {
--- a/drivers/net/wireless/virtual/mac80211_hwsim.c
+++ b/drivers/net/wireless/virtual/mac80211_hwsim.c
@@ -1146,7 +1146,7 @@ static int hwsim_write_simulate_radar(vo
{
struct mac80211_hwsim_data *data = dat;
- ieee80211_radar_detected(data->hw);
+ ieee80211_radar_detected(data->hw, NULL);
return 0;
}
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -6717,8 +6717,11 @@ void ieee80211_cqm_beacon_loss_notify(st
* ieee80211_radar_detected - inform that a radar was detected
*
* @hw: pointer as obtained from ieee80211_alloc_hw()
+ * @chanctx_conf: Channel context on which radar is detected. Mandatory to
+ * pass a valid pointer during MLO. For non-MLO %NULL can be passed
*/
-void ieee80211_radar_detected(struct ieee80211_hw *hw);
+void ieee80211_radar_detected(struct ieee80211_hw *hw,
+ struct ieee80211_chanctx_conf *chanctx_conf);
/**
* ieee80211_chswitch_done - Complete channel switch process
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -681,6 +681,7 @@ ieee80211_alloc_chanctx(struct ieee80211
ctx->mode = mode;
ctx->conf.radar_enabled = false;
ctx->conf.radio_idx = radio_idx;
+ ctx->radar_detected = false;
_ieee80211_recalc_chanctx_min_def(local, ctx, NULL, false);
return ctx;
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -895,6 +895,8 @@ struct ieee80211_chanctx {
struct ieee80211_chan_req req;
struct ieee80211_chanctx_conf conf;
+
+ bool radar_detected;
};
struct mac80211_qos_map {
@@ -2632,7 +2634,8 @@ void ieee80211_recalc_chanctx_min_def(st
bool ieee80211_is_radar_required(struct ieee80211_local *local);
void ieee80211_dfs_cac_timer_work(struct wiphy *wiphy, struct wiphy_work *work);
-void ieee80211_dfs_cac_cancel(struct ieee80211_local *local);
+void ieee80211_dfs_cac_cancel(struct ieee80211_local *local,
+ struct ieee80211_chanctx *chanctx);
void ieee80211_dfs_radar_detected_work(struct wiphy *wiphy,
struct wiphy_work *work);
int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata,
--- a/net/mac80211/pm.c
+++ b/net/mac80211/pm.c
@@ -32,7 +32,7 @@ int __ieee80211_suspend(struct ieee80211
ieee80211_scan_cancel(local);
- ieee80211_dfs_cac_cancel(local);
+ ieee80211_dfs_cac_cancel(local, NULL);
ieee80211_roc_purge(local, NULL);
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -3451,11 +3451,16 @@ u64 ieee80211_calculate_rx_timestamp(str
return ts;
}
-void ieee80211_dfs_cac_cancel(struct ieee80211_local *local)
+/* Cancel CAC for the interfaces under the specified @local. If @ctx is
+ * also provided, only the interfaces using that ctx will be canceled.
+ */
+void ieee80211_dfs_cac_cancel(struct ieee80211_local *local,
+ struct ieee80211_chanctx *ctx)
{
struct ieee80211_sub_if_data *sdata;
struct cfg80211_chan_def chandef;
struct ieee80211_link_data *link;
+ struct ieee80211_chanctx_conf *chanctx_conf;
unsigned int link_id;
lockdep_assert_wiphy(local->hw.wiphy);
@@ -3468,6 +3473,11 @@ void ieee80211_dfs_cac_cancel(struct iee
if (!link)
continue;
+ chanctx_conf = sdata_dereference(link->conf->chanctx_conf,
+ sdata);
+ if (ctx && &ctx->conf != chanctx_conf)
+ continue;
+
wiphy_delayed_work_cancel(local->hw.wiphy,
&link->dfs_cac_timer_work);
@@ -3488,9 +3498,8 @@ void ieee80211_dfs_radar_detected_work(s
{
struct ieee80211_local *local =
container_of(work, struct ieee80211_local, radar_detected_work);
- struct cfg80211_chan_def chandef = local->hw.conf.chandef;
+ struct cfg80211_chan_def chandef;
struct ieee80211_chanctx *ctx;
- int num_chanctx = 0;
lockdep_assert_wiphy(local->hw.wiphy);
@@ -3498,25 +3507,46 @@ void ieee80211_dfs_radar_detected_work(s
if (ctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER)
continue;
- num_chanctx++;
+ if (!ctx->radar_detected)
+ continue;
+
+ ctx->radar_detected = false;
+
chandef = ctx->conf.def;
+
+ ieee80211_dfs_cac_cancel(local, ctx);
+ cfg80211_radar_event(local->hw.wiphy, &chandef, GFP_KERNEL);
}
+}
- ieee80211_dfs_cac_cancel(local);
+static void
+ieee80211_radar_mark_chan_ctx_iterator(struct ieee80211_hw *hw,
+ struct ieee80211_chanctx_conf *chanctx_conf,
+ void *data)
+{
+ struct ieee80211_chanctx *ctx =
+ container_of(chanctx_conf, struct ieee80211_chanctx,
+ conf);
- if (num_chanctx > 1)
- /* XXX: multi-channel is not supported yet */
- WARN_ON(1);
- else
- cfg80211_radar_event(local->hw.wiphy, &chandef, GFP_KERNEL);
+ if (ctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER)
+ return;
+
+ if (data && data != chanctx_conf)
+ return;
+
+ ctx->radar_detected = true;
}
-void ieee80211_radar_detected(struct ieee80211_hw *hw)
+void ieee80211_radar_detected(struct ieee80211_hw *hw,
+ struct ieee80211_chanctx_conf *chanctx_conf)
{
struct ieee80211_local *local = hw_to_local(hw);
trace_api_radar_detected(local);
+ ieee80211_iter_chan_contexts_atomic(hw, ieee80211_radar_mark_chan_ctx_iterator,
+ chanctx_conf);
+
wiphy_work_queue(hw->wiphy, &local->radar_detected_work);
}
EXPORT_SYMBOL(ieee80211_radar_detected);

View File

@ -1,145 +0,0 @@
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);

View File

@ -1,348 +0,0 @@
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;

View File

@ -1,172 +0,0 @@
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)

View File

@ -1,69 +0,0 @@
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);

View File

@ -1,88 +0,0 @@
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);

View File

@ -1,66 +0,0 @@
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;

View File

@ -1,322 +0,0 @@
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, &params->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, &params,
+ 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, &params, NULL, NULL);
err = cfg80211_iter_combinations(local->hw.wiphy, &params,
ieee80211_iter_max_chans,

View File

@ -1,175 +0,0 @@
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);

View File

@ -1,132 +0,0 @@
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;

View File

@ -1,199 +0,0 @@
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)

View File

@ -1,29 +0,0 @@
--- a/backport-include/linux/of_net.h
+++ /dev/null
@@ -1,26 +0,0 @@
-#ifndef _BP_OF_NET_H
-#define _BP_OF_NET_H
-#include_next <linux/of_net.h>
-#include <linux/version.h>
-#include <linux/etherdevice.h>
-
-/* The behavior of of_get_mac_address() changed in kernel 5.2, it now
- * returns an error code and not NULL in case of an error.
- */
-#if LINUX_VERSION_IS_LESS(5,13,0)
-static inline int backport_of_get_mac_address(struct device_node *np, u8 *mac_out)
-{
- const void *mac = of_get_mac_address(np);
-
- if (!mac)
- return -ENODEV;
- if (IS_ERR(mac))
- return PTR_ERR(mac);
- ether_addr_copy(mac_out, mac);
-
- return 0;
-}
-#define of_get_mac_address LINUX_BACKPORT(of_get_mac_address)
-#endif /* < 5.2 */
-
-#endif /* _BP_OF_NET_H */

View File

@ -8,9 +8,9 @@ PKG_LICENSE_FILES:=
PKG_SOURCE_URL:=https://github.com/openwrt/mt76
PKG_SOURCE_PROTO:=git
PKG_SOURCE_DATE:=2024-08-25
PKG_SOURCE_VERSION:=904ef52a8d04f6808284011579fdd45418f643d9
PKG_MIRROR_HASH:=4e285ac767336aab56006fc9f8ca1c35d639926b03de1d6d1667ffc939d81c87
PKG_SOURCE_DATE:=2024-10-10
PKG_SOURCE_VERSION:=6a1199463fc8f7758c32122613288ed95c09e3bd
PKG_MIRROR_HASH:=4b42a586e098c1dc5970fbd3190ac2faf67992c7357161a3ef3040817a8ed8d6
PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name>
PKG_USE_NINJA:=0
@ -237,9 +237,6 @@ define KernelPackage/mt7915e
DEPENDS+=@PCI_SUPPORT +kmod-mt76-connac +kmod-hwmon-core +kmod-thermal +@DRIVER_11AX_SUPPORT +@KERNEL_RELAY
FILES:= $(PKG_BUILD_DIR)/mt7915/mt7915e.ko
AUTOLOAD:=$(call AutoProbe,mt7915e)
ifneq ($(CONFIG_TARGET_mediatek_filogic)$(CONFIG_TARGET_mediatek_mt7622),)
MODPARAMS.mt7915e:=wed_enable=Y
endif
endef
define KernelPackage/mt7916-firmware
@ -290,7 +287,7 @@ define KernelPackage/mt7921-common
$(KernelPackage/mt76-default)
TITLE:=MediaTek MT7921 wireless driver common code
HIDDEN:=1
DEPENDS+=+kmod-mt792x-common +kmod-mt7921-firmware +kmod-mt7922-firmware +@DRIVER_11AX_SUPPORT +kmod-hwmon-core
DEPENDS+=+kmod-mt792x-common +kmod-mt7921-firmware +@DRIVER_11AX_SUPPORT +kmod-hwmon-core
FILES:= $(PKG_BUILD_DIR)/mt7921/mt7921-common.ko
endef
@ -321,22 +318,53 @@ endef
define KernelPackage/mt7996e
$(KernelPackage/mt76-default)
TITLE:=MediaTek MT7996E wireless driver
DEPENDS+=@PCI_SUPPORT +kmod-mt76-connac +kmod-hwmon-core +@DRIVER_11AX_SUPPORT +@KERNEL_RELAY
DEPENDS+=@PCI_SUPPORT +kmod-mt76-connac +kmod-hwmon-core +@DRIVER_11AX_SUPPORT \
+@KERNEL_RELAY +@DRIVER_11BE_SUPPORT
FILES:= $(PKG_BUILD_DIR)/mt7996/mt7996e.ko
AUTOLOAD:=$(call AutoProbe,mt7996e)
endef
define KernelPackage/mt7992-firmware
$(KernelPackage/mt76-default)
TITLE:=MediaTek MT7992 firmware
DEPENDS+=+kmod-mt7996e
endef
define KernelPackage/mt7992-23-firmware
$(KernelPackage/mt76-default)
TITLE:=MediaTek MT7996 firmware (2+3 antenna variant)
DEPENDS+=+kmod-mt7996e
endef
define KernelPackage/mt7996-firmware-common
$(KernelPackage/mt76-default)
TITLE:=MediaTek MT7996 firmware (common files)
HIDDEN:=1
endef
define KernelPackage/mt7996-firmware
$(KernelPackage/mt76-default)
TITLE:=MediaTek MT7996 firmware
DEPENDS+=+kmod-mt7996e
DEPENDS+=+kmod-mt7996e +kmod-mt7996-firmware-common
endef
define KernelPackage/mt7996-233-firmware
$(KernelPackage/mt76-default)
TITLE:=MediaTek MT7996 firmware (2+3+3 antenna variant)
DEPENDS+=+kmod-mt7996e +kmod-mt7996-firmware-common
endef
define KernelPackage/mt7925-firmware
$(KernelPackage/mt76-default)
TITLE:=MediaTek MT7925 firmware
DEPENDS+=+kmod-mt7925e
endef
define KernelPackage/mt7925-common
$(KernelPackage/mt76-default)
TITLE:=MediaTek MT7925 wireless driver common code
HIDDEN:=1
DEPENDS+=+kmod-mt792x-common +@DRIVER_11AX_SUPPORT +kmod-hwmon-core
DEPENDS+=+kmod-mt792x-common +@DRIVER_11AX_SUPPORT +kmod-hwmon-core +@DRIVER_11BE_SUPPORT
FILES:= $(PKG_BUILD_DIR)/mt7925/mt7925-common.ko
endef
@ -345,7 +373,7 @@ define KernelPackage/mt7925u
TITLE:=MediaTek MT7925U wireless driver
DEPENDS+=+kmod-mt792x-usb +kmod-mt7925-common
FILES:= $(PKG_BUILD_DIR)/mt7925/mt7925u.ko
AUTOLOAD:=$(call AutoProbe,mt7921u)
AUTOLOAD:=$(call AutoProbe,mt7925u)
endef
define KernelPackage/mt7925e
@ -353,7 +381,7 @@ define KernelPackage/mt7925e
TITLE:=MediaTek MT7925e wireless driver
DEPENDS+=@PCI_SUPPORT +kmod-mt7925-common
FILES:= $(PKG_BUILD_DIR)/mt7925/mt7925e.ko
AUTOLOAD:=$(call AutoProbe,mt7921e)
AUTOLOAD:=$(call AutoProbe,mt7925e)
endef
define Package/mt76-test
@ -619,23 +647,65 @@ define KernelPackage/mt7922-firmware/install
$(1)/lib/firmware/mediatek
endef
define KernelPackage/mt7925-firmware/install
$(INSTALL_DIR) $(1)/lib/firmware/mediatek/mt7925
cp \
$(PKG_BUILD_DIR)/firmware/mt7925/WIFI_MT7925_PATCH_MCU_1_1_hdr.bin \
$(PKG_BUILD_DIR)/firmware/mt7925/WIFI_RAM_CODE_MT7925_1_1.bin \
$(1)/lib/firmware/mediatek/mt7925
endef
define KernelPackage/mt7992-firmware/install
$(INSTALL_DIR) $(1)/lib/firmware/mediatek/mt7996
cp \
$(PKG_BUILD_DIR)/firmware/mt7996/mt7992_dsp.bin \
$(PKG_BUILD_DIR)/firmware/mt7996/mt7992_eeprom.bin \
$(PKG_BUILD_DIR)/firmware/mt7996/mt7992_eeprom_2i5i.bin \
$(PKG_BUILD_DIR)/firmware/mt7996/mt7992_eeprom_2i5e.bin \
$(PKG_BUILD_DIR)/firmware/mt7996/mt7992_rom_patch.bin \
$(PKG_BUILD_DIR)/firmware/mt7996/mt7992_wa.bin \
$(PKG_BUILD_DIR)/firmware/mt7996/mt7992_wm.bin \
$(1)/lib/firmware/mediatek/mt7996
endef
define KernelPackage/mt7992-23-firmware/install
$(INSTALL_DIR) $(1)/lib/firmware/mediatek/mt7996
cp \
$(PKG_BUILD_DIR)/firmware/mt7996/mt7992_dsp_23.bin \
$(PKG_BUILD_DIR)/firmware/mt7996/mt7992_eeprom_23.bin \
$(PKG_BUILD_DIR)/firmware/mt7996/mt7992_eeprom_23_2i5i.bin \
$(PKG_BUILD_DIR)/firmware/mt7996/mt7992_rom_patch_23.bin \
$(PKG_BUILD_DIR)/firmware/mt7996/mt7992_wa_23.bin \
$(PKG_BUILD_DIR)/firmware/mt7996/mt7992_wm_23.bin \
$(1)/lib/firmware/mediatek/mt7996
endef
define KernelPackage/mt7996-firmware-common/install
$(INSTALL_DIR) $(1)/lib/firmware/mediatek/mt7996
cp \
$(PKG_BUILD_DIR)/firmware/mt7996/mt7996_dsp.bin \
$(1)/lib/firmware/mediatek/mt7996
endef
define KernelPackage/mt7996-firmware/install
$(INSTALL_DIR) $(1)/lib/firmware/mediatek/mt7996
cp \
$(PKG_BUILD_DIR)/firmware/mt7996/mt7996_wa.bin \
$(PKG_BUILD_DIR)/firmware/mt7996/mt7996_wm.bin \
$(PKG_BUILD_DIR)/firmware/mt7996/mt7996_wm_tm.bin \
$(PKG_BUILD_DIR)/firmware/mt7996/mt7996_rom_patch.bin \
$(PKG_BUILD_DIR)/firmware/mt7996/mt7996_dsp.bin \
$(PKG_BUILD_DIR)/firmware/mt7996/mt7996_wa_233.bin \
$(PKG_BUILD_DIR)/firmware/mt7996/mt7996_wm_233.bin \
$(PKG_BUILD_DIR)/firmware/mt7996/mt7996_wm_tm_233.bin \
$(PKG_BUILD_DIR)/firmware/mt7996/mt7996_rom_patch_233.bin \
$(PKG_BUILD_DIR)/firmware/mt7996/mt7996_eeprom.bin \
$(PKG_BUILD_DIR)/firmware/mt7996/mt7996_eeprom_2i5i6i.bin \
$(PKG_BUILD_DIR)/firmware/mt7996/mt7996_rom_patch.bin \
$(PKG_BUILD_DIR)/firmware/mt7996/mt7996_wa.bin \
$(PKG_BUILD_DIR)/firmware/mt7996/mt7996_wm.bin \
$(1)/lib/firmware/mediatek/mt7996
endef
define KernelPackage/mt7996-233-firmware/install
$(INSTALL_DIR) $(1)/lib/firmware/mediatek/mt7996
cp \
$(PKG_BUILD_DIR)/firmware/mt7996/mt7996_eeprom_233.bin \
$(PKG_BUILD_DIR)/firmware/mt7996/mt7996_eeprom_233_2i5i6i.bin \
$(PKG_BUILD_DIR)/firmware/mt7996/mt7996_eeprom_dual_404.bin \
$(PKG_BUILD_DIR)/firmware/mt7996/mt7996_rom_patch_233.bin \
$(PKG_BUILD_DIR)/firmware/mt7996/mt7996_wa_233.bin \
$(PKG_BUILD_DIR)/firmware/mt7996/mt7996_wm_233.bin \
$(1)/lib/firmware/mediatek/mt7996
endef
@ -678,6 +748,7 @@ $(eval $(call KernelPackage,mt7981-firmware))
$(eval $(call KernelPackage,mt7986-firmware))
$(eval $(call KernelPackage,mt7921-firmware))
$(eval $(call KernelPackage,mt7922-firmware))
$(eval $(call KernelPackage,mt7925-firmware))
$(eval $(call KernelPackage,mt792x-common))
$(eval $(call KernelPackage,mt792x-usb))
$(eval $(call KernelPackage,mt7921-common))
@ -688,6 +759,10 @@ $(eval $(call KernelPackage,mt7921e))
$(eval $(call KernelPackage,mt7925u))
$(eval $(call KernelPackage,mt7925e))
$(eval $(call KernelPackage,mt7996e))
$(eval $(call KernelPackage,mt7992-firmware))
$(eval $(call KernelPackage,mt7992-23-firmware))
$(eval $(call KernelPackage,mt7996-firmware-common))
$(eval $(call KernelPackage,mt7996-firmware))
$(eval $(call KernelPackage,mt7996-233-firmware))
$(eval $(call KernelPackage,mt76))
$(eval $(call BuildPackage,mt76-test))

View File

@ -1,67 +0,0 @@
From 72929ea244bc89a596c63fa46c45ed54fa20297a Mon Sep 17 00:00:00 2001
From: Shayne Chen <shayne.chen@mediatek.com>
Date: Fri, 6 Jan 2023 11:28:18 +0800
Subject: [PATCH] wifi: mt76: mt7915: handle unsupported band configuration
Firmware does not support simultaneous 5GHz and 6GHz on the same band.
Force this case to support 5GHz only.
Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
---
mt7915/eeprom.c | 14 ++++++++++----
mt7915/init.c | 4 ++--
2 files changed, 12 insertions(+), 6 deletions(-)
diff --git a/mt7915/eeprom.c b/mt7915/eeprom.c
index 849275e1..1371f55c 100644
--- a/mt7915/eeprom.c
+++ b/mt7915/eeprom.c
@@ -156,15 +156,21 @@ static void mt7915_eeprom_parse_band_config(struct mt7915_phy *phy)
if (!is_mt7915(&dev->mt76)) {
switch (val) {
case MT_EE_V2_BAND_SEL_5GHZ:
+ case MT_EE_V2_BAND_SEL_5GHZ_6GHZ:
phy->mt76->cap.has_5ghz = true;
+
+ if (val == MT_EE_V2_BAND_SEL_5GHZ_6GHZ) {
+ u8p_replace_bits(&eeprom[MT_EE_WIFI_CONF + band],
+ MT_EE_V2_BAND_SEL_5GHZ,
+ MT_EE_WIFI_CONF0_BAND_SEL);
+
+ /* force to buffer mode */
+ dev->flash_mode = true;
+ }
return;
case MT_EE_V2_BAND_SEL_6GHZ:
phy->mt76->cap.has_6ghz = true;
return;
- case MT_EE_V2_BAND_SEL_5GHZ_6GHZ:
- phy->mt76->cap.has_5ghz = true;
- phy->mt76->cap.has_6ghz = true;
- return;
default:
phy->mt76->cap.has_2ghz = true;
return;
diff --git a/mt7915/init.c b/mt7915/init.c
index 9ccbc7bc..74425a59 100755
--- a/mt7915/init.c
+++ b/mt7915/init.c
@@ -1311,14 +1311,14 @@ int mt7915_register_device(struct mt7915_dev *dev)
if (ret)
goto unreg_dev;
- ieee80211_queue_work(mt76_hw(dev), &dev->init_work);
-
if (phy2) {
ret = mt7915_register_ext_phy(dev, phy2);
if (ret)
goto unreg_thermal;
}
+ ieee80211_queue_work(mt76_hw(dev), &dev->init_work);
+
dev->recovery.hw_init_done = true;
ret = mt7915_init_debugfs(&dev->phy);
--
2.25.1

View File

@ -1,238 +0,0 @@
--- /dev/null
+++ b/patches/0001-mt76-allow-VHT-rate-on-2.4GHz.patch
@@ -0,0 +1,234 @@
+From 12c2b3f818d2e0c53e14f0d1b13242cee7138feb Mon Sep 17 00:00:00 2001
+From: DENG Qingfang <dengqf6@mail2.sysu.edu.cn>
+Date: Mon, 23 Nov 2020 10:46:37 +0800
+Subject: [PATCH 1/6] mt76: allow VHT rate on 2.4GHz
+
+Allow chips that support 11ac to use 256QAM on 2.4GHz
+
+Signed-off-by: DENG Qingfang <dqfext@gmail.com>
+Signed-off-by: rany <ranygh@riseup.net>
+---
+ mac80211.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/mac80211.c b/mac80211.c
+index 2c4a5290..df3fbd35 100644
+--- a/mac80211.c
++++ b/mac80211.c
+@@ -282,7 +282,7 @@ static void mt76_init_stream_cap(struct mt76_phy *phy,
+ void mt76_set_stream_caps(struct mt76_phy *phy, bool vht)
+ {
+ if (phy->cap.has_2ghz)
+- mt76_init_stream_cap(phy, &phy->sband_2g.sband, false);
++ mt76_init_stream_cap(phy, &phy->sband_2g.sband, vht);
+ if (phy->cap.has_5ghz)
+ mt76_init_stream_cap(phy, &phy->sband_5g.sband, vht);
+ if (phy->cap.has_6ghz)
+@@ -349,13 +349,13 @@ mt76_init_sband(struct mt76_phy *phy, struct mt76_sband *msband,
+
+ static int
+ mt76_init_sband_2g(struct mt76_phy *phy, struct ieee80211_rate *rates,
+- int n_rates)
++ int n_rates, bool vht)
+ {
+ phy->hw->wiphy->bands[NL80211_BAND_2GHZ] = &phy->sband_2g.sband;
+
+ return mt76_init_sband(phy, &phy->sband_2g, mt76_channels_2ghz,
+ ARRAY_SIZE(mt76_channels_2ghz), rates,
+- n_rates, true, false);
++ n_rates, true, vht);
+ }
+
+ static int
+@@ -508,7 +508,7 @@ int mt76_register_phy(struct mt76_phy *phy, bool vht,
+ return ret;
+
+ if (phy->cap.has_2ghz) {
+- ret = mt76_init_sband_2g(phy, rates, n_rates);
++ ret = mt76_init_sband_2g(phy, rates, n_rates, vht);
+ if (ret)
+ return ret;
+ }
+@@ -691,7 +691,7 @@ int mt76_register_device(struct mt76_dev *dev, bool vht,
+ return ret;
+
+ if (phy->cap.has_2ghz) {
+- ret = mt76_init_sband_2g(phy, rates, n_rates);
++ ret = mt76_init_sband_2g(phy, rates, n_rates, vht);
+ if (ret)
+ return ret;
+ }
+--
+2.34.1
+
+
+From 1eee3cd65b71ad465b07fae78db7a1e6d766e572 Mon Sep 17 00:00:00 2001
+From: rany <ranygh@riseup.net>
+Date: Fri, 12 May 2023 19:49:38 +0300
+Subject: [PATCH 2/6] wifi: mt76: mt7615: add 256-QAM support in 2.4GHz
+
+Signed-off-by: rany <ranygh@riseup.net>
+---
+ mt7615/init.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/mt7615/init.c b/mt7615/init.c
+index 621e69f0..13ada39b 100644
+--- a/mt7615/init.c
++++ b/mt7615/init.c
+@@ -410,6 +410,8 @@ mt7615_init_wiphy(struct ieee80211_hw *hw)
+ hw->max_tx_fragments = MT_HW_TXP_MAX_BUF_NUM;
+
+ phy->mt76->sband_2g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING;
++ phy->mt76->sband_2g.sband.vht_cap.cap |=
++ IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
+ phy->mt76->sband_5g.sband.ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING;
+ phy->mt76->sband_5g.sband.vht_cap.cap |=
+ IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
+--
+2.34.1
+
+
+From b8628fd465befe391a5bdaeb64d6fe34d864dcab Mon Sep 17 00:00:00 2001
+From: rany <ranygh@riseup.net>
+Date: Fri, 12 May 2023 20:01:24 +0300
+Subject: [PATCH 3/6] wifi: mt76: mt7915: add 256-QAM support in 2.4Ghz
+
+Signed-off-by: rany <ranygh@riseup.net>
+---
+ mt7915/init.c | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+diff --git a/mt7915/init.c b/mt7915/init.c
+index ada878e0..2ef0040e 100644
+--- a/mt7915/init.c
++++ b/mt7915/init.c
+@@ -395,11 +395,24 @@ mt7915_init_wiphy(struct mt7915_phy *phy)
+ wiphy->txq_memory_limit = 32 << 20; /* 32 MiB */
+
+ if (phy->mt76->cap.has_2ghz) {
++ struct ieee80211_sta_vht_cap *vht_cap;
++
++ vht_cap = &phy->mt76->sband_2g.sband.vht_cap;
+ phy->mt76->sband_2g.sband.ht_cap.cap |=
+ IEEE80211_HT_CAP_LDPC_CODING |
+ IEEE80211_HT_CAP_MAX_AMSDU;
+ phy->mt76->sband_2g.sband.ht_cap.ampdu_density =
+ IEEE80211_HT_MPDU_DENSITY_4;
++
++ if (is_mt7915(&dev->mt76)) {
++ vht_cap->cap |=
++ IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 |
++ IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
++ } else {
++ vht_cap->cap |=
++ IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 |
++ IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
++ }
+ }
+
+ if (phy->mt76->cap.has_5ghz) {
+--
+2.34.1
+
+
+From 6eea63810b9ee351281f34f36d36f8fe6804d295 Mon Sep 17 00:00:00 2001
+From: rany <ranygh@riseup.net>
+Date: Fri, 12 May 2023 20:03:41 +0300
+Subject: [PATCH 4/6] wifi: mt76: mt7921: add 256-QAM support in 2.4Ghz
+
+Signed-off-by: rany <ranygh@riseup.net>
+---
+ mt7921/init.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/mt7921/init.c b/mt7921/init.c
+index e929f6eb..ba69b063 100644
+--- a/mt7921/init.c
++++ b/mt7921/init.c
+@@ -431,6 +431,12 @@ int mt7921_register_device(struct mt7921_dev *dev)
+ dev->mphy.sband_5g.sband.ht_cap.cap |=
+ IEEE80211_HT_CAP_LDPC_CODING |
+ IEEE80211_HT_CAP_MAX_AMSDU;
++ dev->mphy.sband_2g.sband.vht_cap.cap |=
++ IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 |
++ IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK |
++ IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
++ IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE |
++ (3 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT);
+ dev->mphy.sband_5g.sband.vht_cap.cap |=
+ IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 |
+ IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK |
+--
+2.34.1
+
+
+From c8fac2a17aacb57b73ad139635169e3fd0b8e2fa Mon Sep 17 00:00:00 2001
+From: rany <ranygh@riseup.net>
+Date: Fri, 12 May 2023 20:04:23 +0300
+Subject: [PATCH 5/6] wifi: mt76: mt7996: add 256-QAM support in 2.4Ghz
+
+Signed-off-by: rany <ranygh@riseup.net>
+---
+ mt7996/init.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/mt7996/init.c b/mt7996/init.c
+index f1b48cdd..1e4f1471 100644
+--- a/mt7996/init.c
++++ b/mt7996/init.c
+@@ -201,6 +201,10 @@ mt7996_init_wiphy(struct ieee80211_hw *hw)
+ phy->mt76->sband_2g.sband.ht_cap.cap |=
+ IEEE80211_HT_CAP_LDPC_CODING |
+ IEEE80211_HT_CAP_MAX_AMSDU;
++
++ phy->mt76->sband_2g.sband.vht_cap.cap |=
++ IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 |
++ IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
+ phy->mt76->sband_2g.sband.ht_cap.ampdu_density =
+ IEEE80211_HT_MPDU_DENSITY_2;
+ }
+--
+2.34.1
+
+
+From 4f0670343704f41b68378164092e31c7d2dd6207 Mon Sep 17 00:00:00 2001
+From: Rani Hod <rani.hod@gmail.com>
+Date: Thu, 15 Jun 2023 15:44:32 +0300
+Subject: [PATCH 6/6] Set the vendor_qam256_supported flag when initializing 2g
+ bands.
+
+Signed-off-by: Rani Hod <rani.hod@gmail.com>
+---
+ mac80211.c | 11 ++++++++++-
+ 1 file changed, 10 insertions(+), 1 deletion(-)
+
+diff --git a/mac80211.c b/mac80211.c
+index df3fbd35..c42be544 100644
+--- a/mac80211.c
++++ b/mac80211.c
+@@ -351,11 +351,20 @@ static int
+ mt76_init_sband_2g(struct mt76_phy *phy, struct ieee80211_rate *rates,
+ int n_rates, bool vht)
+ {
++ int ret;
++
+ phy->hw->wiphy->bands[NL80211_BAND_2GHZ] = &phy->sband_2g.sband;
+
+- return mt76_init_sband(phy, &phy->sband_2g, mt76_channels_2ghz,
++ ret = mt76_init_sband(phy, &phy->sband_2g, mt76_channels_2ghz,
+ ARRAY_SIZE(mt76_channels_2ghz), rates,
+ n_rates, true, vht);
++
++ if (ret)
++ return ret;
++
++ phy->sband_2g.sband.vht_cap.vendor_qam256_supported = true;
++
++ return 0;
+ }
+
+ static int
+--
+2.34.1
+

View File

@ -1,174 +0,0 @@
From 8ad06fc44bb989b918e0c86da896235001b14419 Mon Sep 17 00:00:00 2001
From: Shayne Chen <shayne.chen@mediatek.com>
Date: Mon, 17 Jun 2024 16:03:16 +0800
Subject: [PATCH] wifi: mt76: mt7996: support mt7996 2+3+3 variant
Add support for mt7996 tri-band 2+3+3 variant.
Signed-off-by: Shayne Chen <shayne.chen@mediatek.com>
Change-Id: Idd7ed0033e1255018bd03b434d3bd3eacfde7153
---
mt7996/eeprom.c | 2 ++
mt7996/init.c | 25 +++++++++++++++++++++++++
mt7996/mcu.c | 9 ++++++++-
mt7996/mt7996.h | 17 +++++++++++++++--
mt7996/regs.h | 1 +
5 files changed, 51 insertions(+), 3 deletions(-)
diff --git a/mt7996/eeprom.c b/mt7996/eeprom.c
index 4a8237118..7e2d585a2 100644
--- a/mt7996/eeprom.c
+++ b/mt7996/eeprom.c
@@ -26,6 +26,8 @@ static char *mt7996_eeprom_name(struct mt7996_dev *dev)
{
switch (mt76_chip(&dev->mt76)) {
case 0x7990:
+ if (dev->var_type == MT7996_VAR_TYPE_233)
+ return MT7996_EEPROM_DEFAULT_233;
return MT7996_EEPROM_DEFAULT;
case 0x7992:
return MT7992_EEPROM_DEFAULT;
diff --git a/mt7996/init.c b/mt7996/init.c
index 5e9697322..ab1a9a8ee 100644
--- a/mt7996/init.c
+++ b/mt7996/init.c
@@ -884,6 +884,27 @@ static void mt7996_wed_rro_work(struct work_struct *work)
#endif
}
+static int mt7996_chip_variant_init(struct mt7996_dev *dev)
+{
+ u32 val = mt76_rr(dev, MT_PAD_GPIO);
+
+ switch (mt76_chip(&dev->mt76)) {
+ case 0x7990:
+ if (u32_get_bits(val, MT_PAD_GPIO_2ADIE_TBTC))
+ dev->var_type = MT7996_VAR_TYPE_233;
+ else
+ dev->var_type = MT7996_VAR_TYPE_444;
+ break;
+ case 0x7992:
+ dev->var_type = MT7992_VAR_TYPE_44;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static int mt7996_init_hardware(struct mt7996_dev *dev)
{
int ret, idx;
@@ -899,6 +920,10 @@ static int mt7996_init_hardware(struct mt7996_dev *dev)
INIT_LIST_HEAD(&dev->wed_rro.poll_list);
spin_lock_init(&dev->wed_rro.lock);
+ ret = mt7996_chip_variant_init(dev);
+ if (ret)
+ return ret;
+
ret = mt7996_dma_init(dev);
if (ret)
return ret;
diff --git a/mt7996/mcu.c b/mt7996/mcu.c
index b01adae2f..da1292ba2 100644
--- a/mt7996/mcu.c
+++ b/mt7996/mcu.c
@@ -17,6 +17,11 @@
_fw = MT7992_##name; \
break; \
case 0x7990: \
+ if ((_dev)->var_type == MT7996_VAR_TYPE_233) \
+ _fw = MT7996_##name##_233; \
+ else \
+ _fw = MT7996_##name; \
+ break; \
default: \
_fw = MT7996_##name; \
break; \
@@ -2851,6 +2856,7 @@ static int __mt7996_load_ram(struct mt7996_dev *dev, const char *fw_type,
static int mt7996_load_ram(struct mt7996_dev *dev)
{
+ const char *dsp_name;
int ret;
ret = __mt7996_load_ram(dev, "WM", fw_name(dev, FIRMWARE_WM),
@@ -2858,7 +2864,8 @@ static int mt7996_load_ram(struct mt7996_dev *dev)
if (ret)
return ret;
- ret = __mt7996_load_ram(dev, "DSP", fw_name(dev, FIRMWARE_DSP),
+ dsp_name = is_mt7996(&dev->mt76) ? MT7996_FIRMWARE_DSP : MT7992_FIRMWARE_DSP;
+ ret = __mt7996_load_ram(dev, "DSP", dsp_name,
MT7996_RAM_TYPE_DSP);
if (ret)
return ret;
diff --git a/mt7996/mt7996.h b/mt7996/mt7996.h
index ab8c90706..e9fc61344 100644
--- a/mt7996/mt7996.h
+++ b/mt7996/mt7996.h
@@ -34,12 +34,17 @@
#define MT7996_FIRMWARE_DSP "mediatek/mt7996/mt7996_dsp.bin"
#define MT7996_ROM_PATCH "mediatek/mt7996/mt7996_rom_patch.bin"
+#define MT7996_FIRMWARE_WA_233 "mediatek/mt7996/mt7996_wa_233.bin"
+#define MT7996_FIRMWARE_WM_233 "mediatek/mt7996/mt7996_wm_233.bin"
+#define MT7996_ROM_PATCH_233 "mediatek/mt7996/mt7996_rom_patch_233.bin"
+
#define MT7992_FIRMWARE_WA "mediatek/mt7996/mt7992_wa.bin"
#define MT7992_FIRMWARE_WM "mediatek/mt7996/mt7992_wm.bin"
#define MT7992_FIRMWARE_DSP "mediatek/mt7996/mt7992_dsp.bin"
#define MT7992_ROM_PATCH "mediatek/mt7996/mt7992_rom_patch.bin"
#define MT7996_EEPROM_DEFAULT "mediatek/mt7996/mt7996_eeprom.bin"
+#define MT7996_EEPROM_DEFAULT_233 "mediatek/mt7996/mt7996_eeprom_233.bin"
#define MT7992_EEPROM_DEFAULT "mediatek/mt7996/mt7992_eeprom.bin"
#define MT7996_EEPROM_SIZE 7680
#define MT7996_EEPROM_BLOCK_SIZE 16
@@ -89,6 +94,14 @@ struct mt7996_sta;
struct mt7996_dfs_pulse;
struct mt7996_dfs_pattern;
+enum mt7996_var_type {
+ MT7996_VAR_TYPE_444,
+ MT7996_VAR_TYPE_233,
+
+ /* mt7992 */
+ MT7992_VAR_TYPE_44,
+};
+
enum mt7996_ram_type {
MT7996_RAM_TYPE_WM,
MT7996_RAM_TYPE_WA,
@@ -329,6 +342,7 @@ struct mt7996_dev {
spinlock_t reg_lock;
u8 wtbl_size_group;
+ u8 var_type;
};
enum {
@@ -406,8 +420,7 @@ mt7996_band_valid(struct mt7996_dev *dev, u8 band)
return band <= MT_BAND1;
/* tri-band support */
- if (band <= MT_BAND2 &&
- mt76_get_field(dev, MT_PAD_GPIO, MT_PAD_GPIO_ADIE_COMB) <= 1)
+ if (band <= MT_BAND2 && dev->var_type)
return true;
return band == MT_BAND0 || band == MT_BAND2;
diff --git a/mt7996/regs.h b/mt7996/regs.h
index 47b429d8b..734abec45 100644
--- a/mt7996/regs.h
+++ b/mt7996/regs.h
@@ -662,6 +662,7 @@ enum offs_rev {
#define MT_PAD_GPIO 0x700056f0
#define MT_PAD_GPIO_ADIE_COMB GENMASK(16, 15)
+#define MT_PAD_GPIO_2ADIE_TBTC BIT(19)
#define MT_HW_REV 0x70010204
#define MT_HW_REV1 0x8a00

Some files were not shown because too many files have changed in this diff Show More