* [PATCH ath-next] wifi: ath12k: avoid dynamic alloc when parsing wmi tb
From: Nicolas Escande @ 2026-03-09 15:20 UTC (permalink / raw)
To: ath12k; +Cc: linux-wireless
On each WMI message received from the hardware, we alloc a temporary array
of WMI_TAG_MAX entries of type void *. This array is then populated with
pointers of parsed structs depending on the WMI type, and then freed. This
alloc can fail when memory pressure in the system is high enough.
Given the fact that it is scheduled in softirq with the system_bh_wq, we
should not be able to parse more than one WMI message per CPU at any time
So instead lets move to a per cpu allocated array, stored in the struct
ath12k_base, that is reused accros calls. The ath12k_wmi_tlv_parse_alloc()
is also renamed into / merged with ath12k_wmi_tlv_parse() as it no longer
allocs memory but returns the existing per-cpu one.
Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00218-QCAHKSWPL_SILICONZ-1
Signed-off-by: Nicolas Escande <nico.escande@gmail.com>
---
changes from RFC:
- rebased on ath-next 8e0ab5b9adb7
- converted missing call sites ath12k_wmi_obss_color_collision_event()
& ath12k_wmi_pdev_temperature_event()
- changed alloc order & cleanup path in ath12k_core_alloc() as it seems
it confused people
- used sizeof(*tb) in ath12k_wmi_tlv_parse()
Note I did try to move to a DEFINE_PER_CPU() allocated array but the module
loader complained about the array size. So I stuck to the per ab alloc.
---
drivers/net/wireless/ath/ath12k/core.c | 7 +
drivers/net/wireless/ath/ath12k/core.h | 2 +
drivers/net/wireless/ath/ath12k/wmi.c | 178 ++++++-------------------
3 files changed, 51 insertions(+), 136 deletions(-)
diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c
index c31c47fb5a73..c1de70b24828 100644
--- a/drivers/net/wireless/ath/ath12k/core.c
+++ b/drivers/net/wireless/ath/ath12k/core.c
@@ -2258,6 +2258,7 @@ void ath12k_core_free(struct ath12k_base *ab)
timer_delete_sync(&ab->rx_replenish_retry);
destroy_workqueue(ab->workqueue_aux);
destroy_workqueue(ab->workqueue);
+ free_percpu(ab->wmi_tb);
kfree(ab);
}
@@ -2270,6 +2271,11 @@ struct ath12k_base *ath12k_core_alloc(struct device *dev, size_t priv_size,
if (!ab)
return NULL;
+ ab->wmi_tb = __alloc_percpu(WMI_TAG_MAX * sizeof(void *),
+ __alignof__(void *));
+ if (!ab->wmi_tb)
+ goto err_sc_free;
+
init_completion(&ab->driver_recovery);
ab->workqueue = create_singlethread_workqueue("ath12k_wq");
@@ -2317,6 +2323,7 @@ struct ath12k_base *ath12k_core_alloc(struct device *dev, size_t priv_size,
err_free_wq:
destroy_workqueue(ab->workqueue);
err_sc_free:
+ free_percpu(ab->wmi_tb);
kfree(ab);
return NULL;
}
diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h
index 59c193b24764..ebe7b94fd712 100644
--- a/drivers/net/wireless/ath/ath12k/core.h
+++ b/drivers/net/wireless/ath/ath12k/core.h
@@ -19,6 +19,7 @@
#include <linux/average.h>
#include <linux/of.h>
#include <linux/rhashtable.h>
+#include <linux/percpu.h>
#include "qmi.h"
#include "htc.h"
#include "wmi.h"
@@ -937,6 +938,7 @@ struct ath12k_base {
struct device *dev;
struct ath12k_qmi qmi;
struct ath12k_wmi_base wmi_ab;
+ void __percpu *wmi_tb;
struct completion fw_ready;
u8 device_id;
int num_radios;
diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c
index 8e13c3ec1cc7..73bbb2eb4fce 100644
--- a/drivers/net/wireless/ath/ath12k/wmi.c
+++ b/drivers/net/wireless/ath/ath12k/wmi.c
@@ -289,29 +289,19 @@ static int ath12k_wmi_tlv_iter_parse(struct ath12k_base *ab, u16 tag, u16 len,
return 0;
}
-static int ath12k_wmi_tlv_parse(struct ath12k_base *ar, const void **tb,
- const void *ptr, size_t len)
-{
- return ath12k_wmi_tlv_iter(ar, ptr, len, ath12k_wmi_tlv_iter_parse,
- (void *)tb);
-}
-
static const void **
-ath12k_wmi_tlv_parse_alloc(struct ath12k_base *ab,
- struct sk_buff *skb, gfp_t gfp)
+ath12k_wmi_tlv_parse(struct ath12k_base *ab, struct sk_buff *skb)
{
const void **tb;
int ret;
- tb = kzalloc_objs(*tb, WMI_TAG_MAX, gfp);
- if (!tb)
- return ERR_PTR(-ENOMEM);
+ tb = this_cpu_ptr(ab->wmi_tb);
+ memset(tb, 0, WMI_TAG_MAX * sizeof(*tb));
- ret = ath12k_wmi_tlv_parse(ab, tb, skb->data, skb->len);
- if (ret) {
- kfree(tb);
+ ret = ath12k_wmi_tlv_iter(ab, skb->data, skb->len,
+ ath12k_wmi_tlv_iter_parse, (void *)tb);
+ if (ret)
return ERR_PTR(ret);
- }
return tb;
}
@@ -3913,7 +3903,7 @@ ath12k_wmi_obss_color_collision_event(struct ath12k_base *ab, struct sk_buff *sk
u32 vdev_id, evt_type;
u64 bitmap;
- const void **tb __free(kfree) = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+ const void **tb = ath12k_wmi_tlv_parse(ab, skb);
if (IS_ERR(tb)) {
ath12k_warn(ab, "failed to parse OBSS color collision tlv %ld\n",
PTR_ERR(tb));
@@ -5714,7 +5704,7 @@ static int ath12k_pull_vdev_start_resp_tlv(struct ath12k_base *ab, struct sk_buf
const struct wmi_vdev_start_resp_event *ev;
int ret;
- tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+ tb = ath12k_wmi_tlv_parse(ab, skb);
if (IS_ERR(tb)) {
ret = PTR_ERR(tb);
ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
@@ -5724,13 +5714,11 @@ static int ath12k_pull_vdev_start_resp_tlv(struct ath12k_base *ab, struct sk_buf
ev = tb[WMI_TAG_VDEV_START_RESPONSE_EVENT];
if (!ev) {
ath12k_warn(ab, "failed to fetch vdev start resp ev");
- kfree(tb);
return -EPROTO;
}
*vdev_rsp = *ev;
- kfree(tb);
return 0;
}
@@ -5809,7 +5797,7 @@ static int ath12k_pull_reg_chan_list_ext_update_ev(struct ath12k_base *ab,
ath12k_dbg(ab, ATH12K_DBG_WMI, "processing regulatory ext channel list\n");
- tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+ tb = ath12k_wmi_tlv_parse(ab, skb);
if (IS_ERR(tb)) {
ret = PTR_ERR(tb);
ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
@@ -5819,7 +5807,6 @@ static int ath12k_pull_reg_chan_list_ext_update_ev(struct ath12k_base *ab,
ev = tb[WMI_TAG_REG_CHAN_LIST_CC_EXT_EVENT];
if (!ev) {
ath12k_warn(ab, "failed to fetch reg chan list ext update ev\n");
- kfree(tb);
return -EPROTO;
}
@@ -5849,7 +5836,6 @@ static int ath12k_pull_reg_chan_list_ext_update_ev(struct ath12k_base *ab,
if (num_2g_reg_rules > MAX_REG_RULES || num_5g_reg_rules > MAX_REG_RULES) {
ath12k_warn(ab, "Num reg rules for 2G/5G exceeds max limit (num_2g_reg_rules: %d num_5g_reg_rules: %d max_rules: %d)\n",
num_2g_reg_rules, num_5g_reg_rules, MAX_REG_RULES);
- kfree(tb);
return -EINVAL;
}
@@ -5859,7 +5845,6 @@ static int ath12k_pull_reg_chan_list_ext_update_ev(struct ath12k_base *ab,
if (num_6g_reg_rules_ap[i] > MAX_6GHZ_REG_RULES) {
ath12k_warn(ab, "Num 6G reg rules for AP mode(%d) exceeds max limit (num_6g_reg_rules_ap: %d, max_rules: %d)\n",
i, num_6g_reg_rules_ap[i], MAX_6GHZ_REG_RULES);
- kfree(tb);
return -EINVAL;
}
@@ -5884,14 +5869,12 @@ static int ath12k_pull_reg_chan_list_ext_update_ev(struct ath12k_base *ab,
num_6g_reg_rules_cl[WMI_REG_VLP_AP][i] > MAX_6GHZ_REG_RULES) {
ath12k_warn(ab, "Num 6g client reg rules exceeds max limit, for client(type: %d)\n",
i);
- kfree(tb);
return -EINVAL;
}
}
if (!total_reg_rules) {
ath12k_warn(ab, "No reg rules available\n");
- kfree(tb);
return -EINVAL;
}
@@ -5993,7 +5976,6 @@ static int ath12k_pull_reg_chan_list_ext_update_ev(struct ath12k_base *ab,
ext_wmi_reg_rule);
if (!reg_info->reg_rules_2g_ptr) {
- kfree(tb);
ath12k_warn(ab, "Unable to Allocate memory for 2g rules\n");
return -ENOMEM;
}
@@ -6027,7 +6009,6 @@ static int ath12k_pull_reg_chan_list_ext_update_ev(struct ath12k_base *ab,
ext_wmi_reg_rule);
if (!reg_info->reg_rules_5g_ptr) {
- kfree(tb);
ath12k_warn(ab, "Unable to Allocate memory for 5g rules\n");
return -ENOMEM;
}
@@ -6046,7 +6027,6 @@ static int ath12k_pull_reg_chan_list_ext_update_ev(struct ath12k_base *ab,
ext_wmi_reg_rule);
if (!reg_info->reg_rules_6g_ap_ptr[i]) {
- kfree(tb);
ath12k_warn(ab, "Unable to Allocate memory for 6g ap rules\n");
return -ENOMEM;
}
@@ -6061,7 +6041,6 @@ static int ath12k_pull_reg_chan_list_ext_update_ev(struct ath12k_base *ab,
ext_wmi_reg_rule);
if (!reg_info->reg_rules_6g_client_ptr[j][i]) {
- kfree(tb);
ath12k_warn(ab, "Unable to Allocate memory for 6g client rules\n");
return -ENOMEM;
}
@@ -6096,7 +6075,6 @@ static int ath12k_pull_reg_chan_list_ext_update_ev(struct ath12k_base *ab,
ath12k_dbg(ab, ATH12K_DBG_WMI, "processed regulatory ext channel list\n");
- kfree(tb);
return 0;
}
@@ -6107,7 +6085,7 @@ static int ath12k_pull_peer_del_resp_ev(struct ath12k_base *ab, struct sk_buff *
const struct wmi_peer_delete_resp_event *ev;
int ret;
- tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+ tb = ath12k_wmi_tlv_parse(ab, skb);
if (IS_ERR(tb)) {
ret = PTR_ERR(tb);
ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
@@ -6117,7 +6095,6 @@ static int ath12k_pull_peer_del_resp_ev(struct ath12k_base *ab, struct sk_buff *
ev = tb[WMI_TAG_PEER_DELETE_RESP_EVENT];
if (!ev) {
ath12k_warn(ab, "failed to fetch peer delete resp ev");
- kfree(tb);
return -EPROTO;
}
@@ -6127,7 +6104,6 @@ static int ath12k_pull_peer_del_resp_ev(struct ath12k_base *ab, struct sk_buff *
ether_addr_copy(peer_del_resp->peer_macaddr.addr,
ev->peer_macaddr.addr);
- kfree(tb);
return 0;
}
@@ -6139,7 +6115,7 @@ static int ath12k_pull_vdev_del_resp_ev(struct ath12k_base *ab,
const struct wmi_vdev_delete_resp_event *ev;
int ret;
- tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+ tb = ath12k_wmi_tlv_parse(ab, skb);
if (IS_ERR(tb)) {
ret = PTR_ERR(tb);
ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
@@ -6149,13 +6125,11 @@ static int ath12k_pull_vdev_del_resp_ev(struct ath12k_base *ab,
ev = tb[WMI_TAG_VDEV_DELETE_RESP_EVENT];
if (!ev) {
ath12k_warn(ab, "failed to fetch vdev delete resp ev");
- kfree(tb);
return -EPROTO;
}
*vdev_id = le32_to_cpu(ev->vdev_id);
- kfree(tb);
return 0;
}
@@ -6167,7 +6141,7 @@ static int ath12k_pull_bcn_tx_status_ev(struct ath12k_base *ab,
const struct wmi_bcn_tx_status_event *ev;
int ret;
- tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+ tb = ath12k_wmi_tlv_parse(ab, skb);
if (IS_ERR(tb)) {
ret = PTR_ERR(tb);
ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
@@ -6177,14 +6151,12 @@ static int ath12k_pull_bcn_tx_status_ev(struct ath12k_base *ab,
ev = tb[WMI_TAG_OFFLOAD_BCN_TX_STATUS_EVENT];
if (!ev) {
ath12k_warn(ab, "failed to fetch bcn tx status ev");
- kfree(tb);
return -EPROTO;
}
*vdev_id = le32_to_cpu(ev->vdev_id);
*tx_status = le32_to_cpu(ev->tx_status);
- kfree(tb);
return 0;
}
@@ -6195,7 +6167,7 @@ static int ath12k_pull_vdev_stopped_param_tlv(struct ath12k_base *ab, struct sk_
const struct wmi_vdev_stopped_event *ev;
int ret;
- tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+ tb = ath12k_wmi_tlv_parse(ab, skb);
if (IS_ERR(tb)) {
ret = PTR_ERR(tb);
ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
@@ -6205,13 +6177,11 @@ static int ath12k_pull_vdev_stopped_param_tlv(struct ath12k_base *ab, struct sk_
ev = tb[WMI_TAG_VDEV_STOPPED_EVENT];
if (!ev) {
ath12k_warn(ab, "failed to fetch vdev stop ev");
- kfree(tb);
return -EPROTO;
}
*vdev_id = le32_to_cpu(ev->vdev_id);
- kfree(tb);
return 0;
}
@@ -6350,7 +6320,7 @@ static int ath12k_pull_mgmt_tx_compl_param_tlv(struct ath12k_base *ab,
const struct wmi_mgmt_tx_compl_event *ev;
int ret;
- tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+ tb = ath12k_wmi_tlv_parse(ab, skb);
if (IS_ERR(tb)) {
ret = PTR_ERR(tb);
ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
@@ -6360,7 +6330,6 @@ static int ath12k_pull_mgmt_tx_compl_param_tlv(struct ath12k_base *ab,
ev = tb[WMI_TAG_MGMT_TX_COMPL_EVENT];
if (!ev) {
ath12k_warn(ab, "failed to fetch mgmt tx compl ev");
- kfree(tb);
return -EPROTO;
}
@@ -6370,7 +6339,6 @@ static int ath12k_pull_mgmt_tx_compl_param_tlv(struct ath12k_base *ab,
param->ppdu_id = ev->ppdu_id;
param->ack_rssi = ev->ack_rssi;
- kfree(tb);
return 0;
}
@@ -6533,7 +6501,7 @@ static int ath12k_pull_scan_ev(struct ath12k_base *ab, struct sk_buff *skb,
const struct wmi_scan_event *ev;
int ret;
- tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+ tb = ath12k_wmi_tlv_parse(ab, skb);
if (IS_ERR(tb)) {
ret = PTR_ERR(tb);
ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
@@ -6543,7 +6511,6 @@ static int ath12k_pull_scan_ev(struct ath12k_base *ab, struct sk_buff *skb,
ev = tb[WMI_TAG_SCAN_EVENT];
if (!ev) {
ath12k_warn(ab, "failed to fetch scan ev");
- kfree(tb);
return -EPROTO;
}
@@ -6555,7 +6522,6 @@ static int ath12k_pull_scan_ev(struct ath12k_base *ab, struct sk_buff *skb,
scan_evt_param->vdev_id = ev->vdev_id;
scan_evt_param->tsf_timestamp = ev->tsf_timestamp;
- kfree(tb);
return 0;
}
@@ -6566,7 +6532,7 @@ static int ath12k_pull_peer_sta_kickout_ev(struct ath12k_base *ab, struct sk_buf
const struct wmi_peer_sta_kickout_event *ev;
int ret;
- tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+ tb = ath12k_wmi_tlv_parse(ab, skb);
if (IS_ERR(tb)) {
ret = PTR_ERR(tb);
ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
@@ -6576,7 +6542,6 @@ static int ath12k_pull_peer_sta_kickout_ev(struct ath12k_base *ab, struct sk_buf
ev = tb[WMI_TAG_PEER_STA_KICKOUT_EVENT];
if (!ev) {
ath12k_warn(ab, "failed to fetch peer sta kickout ev");
- kfree(tb);
return -EPROTO;
}
@@ -6584,7 +6549,6 @@ static int ath12k_pull_peer_sta_kickout_ev(struct ath12k_base *ab, struct sk_buf
arg->reason = le32_to_cpu(ev->reason);
arg->rssi = le32_to_cpu(ev->rssi);
- kfree(tb);
return 0;
}
@@ -6595,7 +6559,7 @@ static int ath12k_pull_roam_ev(struct ath12k_base *ab, struct sk_buff *skb,
const struct wmi_roam_event *ev;
int ret;
- tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+ tb = ath12k_wmi_tlv_parse(ab, skb);
if (IS_ERR(tb)) {
ret = PTR_ERR(tb);
ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
@@ -6605,7 +6569,6 @@ static int ath12k_pull_roam_ev(struct ath12k_base *ab, struct sk_buff *skb,
ev = tb[WMI_TAG_ROAM_EVENT];
if (!ev) {
ath12k_warn(ab, "failed to fetch roam ev");
- kfree(tb);
return -EPROTO;
}
@@ -6613,7 +6576,6 @@ static int ath12k_pull_roam_ev(struct ath12k_base *ab, struct sk_buff *skb,
roam_ev->reason = ev->reason;
roam_ev->rssi = ev->rssi;
- kfree(tb);
return 0;
}
@@ -6647,7 +6609,7 @@ static int ath12k_pull_chan_info_ev(struct ath12k_base *ab, struct sk_buff *skb,
const struct wmi_chan_info_event *ev;
int ret;
- tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+ tb = ath12k_wmi_tlv_parse(ab, skb);
if (IS_ERR(tb)) {
ret = PTR_ERR(tb);
ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
@@ -6657,7 +6619,6 @@ static int ath12k_pull_chan_info_ev(struct ath12k_base *ab, struct sk_buff *skb,
ev = tb[WMI_TAG_CHAN_INFO_EVENT];
if (!ev) {
ath12k_warn(ab, "failed to fetch chan info ev");
- kfree(tb);
return -EPROTO;
}
@@ -6674,7 +6635,6 @@ static int ath12k_pull_chan_info_ev(struct ath12k_base *ab, struct sk_buff *skb,
ch_info_ev->mac_clk_mhz = ev->mac_clk_mhz;
ch_info_ev->vdev_id = ev->vdev_id;
- kfree(tb);
return 0;
}
@@ -6686,7 +6646,7 @@ ath12k_pull_pdev_bss_chan_info_ev(struct ath12k_base *ab, struct sk_buff *skb,
const struct wmi_pdev_bss_chan_info_event *ev;
int ret;
- tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+ tb = ath12k_wmi_tlv_parse(ab, skb);
if (IS_ERR(tb)) {
ret = PTR_ERR(tb);
ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
@@ -6696,7 +6656,6 @@ ath12k_pull_pdev_bss_chan_info_ev(struct ath12k_base *ab, struct sk_buff *skb,
ev = tb[WMI_TAG_PDEV_BSS_CHAN_INFO_EVENT];
if (!ev) {
ath12k_warn(ab, "failed to fetch pdev bss chan info ev");
- kfree(tb);
return -EPROTO;
}
@@ -6714,7 +6673,6 @@ ath12k_pull_pdev_bss_chan_info_ev(struct ath12k_base *ab, struct sk_buff *skb,
bss_ch_info_ev->rx_bss_cycle_count_low = ev->rx_bss_cycle_count_low;
bss_ch_info_ev->rx_bss_cycle_count_high = ev->rx_bss_cycle_count_high;
- kfree(tb);
return 0;
}
@@ -6726,7 +6684,7 @@ ath12k_pull_vdev_install_key_compl_ev(struct ath12k_base *ab, struct sk_buff *sk
const struct wmi_vdev_install_key_compl_event *ev;
int ret;
- tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+ tb = ath12k_wmi_tlv_parse(ab, skb);
if (IS_ERR(tb)) {
ret = PTR_ERR(tb);
ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
@@ -6736,7 +6694,6 @@ ath12k_pull_vdev_install_key_compl_ev(struct ath12k_base *ab, struct sk_buff *sk
ev = tb[WMI_TAG_VDEV_INSTALL_KEY_COMPLETE_EVENT];
if (!ev) {
ath12k_warn(ab, "failed to fetch vdev install key compl ev");
- kfree(tb);
return -EPROTO;
}
@@ -6746,7 +6703,6 @@ ath12k_pull_vdev_install_key_compl_ev(struct ath12k_base *ab, struct sk_buff *sk
arg->key_flags = le32_to_cpu(ev->key_flags);
arg->status = le32_to_cpu(ev->status);
- kfree(tb);
return 0;
}
@@ -6757,7 +6713,7 @@ static int ath12k_pull_peer_assoc_conf_ev(struct ath12k_base *ab, struct sk_buff
const struct wmi_peer_assoc_conf_event *ev;
int ret;
- tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+ tb = ath12k_wmi_tlv_parse(ab, skb);
if (IS_ERR(tb)) {
ret = PTR_ERR(tb);
ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
@@ -6767,14 +6723,12 @@ static int ath12k_pull_peer_assoc_conf_ev(struct ath12k_base *ab, struct sk_buff
ev = tb[WMI_TAG_PEER_ASSOC_CONF_EVENT];
if (!ev) {
ath12k_warn(ab, "failed to fetch peer assoc conf ev");
- kfree(tb);
return -EPROTO;
}
peer_assoc_conf->vdev_id = le32_to_cpu(ev->vdev_id);
peer_assoc_conf->macaddr = ev->peer_macaddr.addr;
- kfree(tb);
return 0;
}
@@ -6792,7 +6746,7 @@ static int ath12k_reg_11d_new_cc_event(struct ath12k_base *ab, struct sk_buff *s
const void **tb;
int ret, i;
- tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+ tb = ath12k_wmi_tlv_parse(ab, skb);
if (IS_ERR(tb)) {
ret = PTR_ERR(tb);
ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
@@ -6801,7 +6755,6 @@ static int ath12k_reg_11d_new_cc_event(struct ath12k_base *ab, struct sk_buff *s
ev = tb[WMI_TAG_11D_NEW_COUNTRY_EVENT];
if (!ev) {
- kfree(tb);
ath12k_warn(ab, "failed to fetch 11d new cc ev");
return -EPROTO;
}
@@ -6814,8 +6767,6 @@ static int ath12k_reg_11d_new_cc_event(struct ath12k_base *ab, struct sk_buff *s
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;
@@ -8567,7 +8518,7 @@ static void ath12k_pdev_ctl_failsafe_check_event(struct ath12k_base *ab,
const struct wmi_pdev_ctl_failsafe_chk_event *ev;
int ret;
- tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+ tb = ath12k_wmi_tlv_parse(ab, skb);
if (IS_ERR(tb)) {
ret = PTR_ERR(tb);
ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
@@ -8577,7 +8528,6 @@ static void ath12k_pdev_ctl_failsafe_check_event(struct ath12k_base *ab,
ev = tb[WMI_TAG_PDEV_CTL_FAILSAFE_CHECK_EVENT];
if (!ev) {
ath12k_warn(ab, "failed to fetch pdev ctl failsafe check ev");
- kfree(tb);
return;
}
@@ -8591,8 +8541,6 @@ static void ath12k_pdev_ctl_failsafe_check_event(struct ath12k_base *ab,
if (ev->ctl_failsafe_status != 0)
ath12k_warn(ab, "pdev ctl failsafe failure status %d",
ev->ctl_failsafe_status);
-
- kfree(tb);
}
static void
@@ -8664,7 +8612,7 @@ ath12k_wmi_pdev_csa_switch_count_status_event(struct ath12k_base *ab,
const u32 *vdev_ids;
int ret;
- tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+ tb = ath12k_wmi_tlv_parse(ab, skb);
if (IS_ERR(tb)) {
ret = PTR_ERR(tb);
ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
@@ -8676,7 +8624,6 @@ ath12k_wmi_pdev_csa_switch_count_status_event(struct ath12k_base *ab,
if (!ev || !vdev_ids) {
ath12k_warn(ab, "failed to fetch pdev csa switch count ev");
- kfree(tb);
return;
}
@@ -8686,8 +8633,6 @@ ath12k_wmi_pdev_csa_switch_count_status_event(struct ath12k_base *ab,
ev->num_vdevs);
ath12k_wmi_process_csa_switch_count_event(ab, ev, vdev_ids);
-
- kfree(tb);
}
static void
@@ -8699,7 +8644,7 @@ ath12k_wmi_pdev_dfs_radar_detected_event(struct ath12k_base *ab, struct sk_buff
struct ath12k *ar;
int ret;
- tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+ tb = ath12k_wmi_tlv_parse(ab, skb);
if (IS_ERR(tb)) {
ret = PTR_ERR(tb);
ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
@@ -8710,7 +8655,6 @@ ath12k_wmi_pdev_dfs_radar_detected_event(struct ath12k_base *ab, struct sk_buff
if (!ev) {
ath12k_warn(ab, "failed to fetch pdev dfs radar detected ev");
- kfree(tb);
return;
}
@@ -8749,8 +8693,6 @@ ath12k_wmi_pdev_dfs_radar_detected_event(struct ath12k_base *ab, struct sk_buff
exit:
rcu_read_unlock();
-
- kfree(tb);
}
static void ath12k_tm_wmi_event_segmented(struct ath12k_base *ab, u32 cmd_id,
@@ -8761,7 +8703,7 @@ static void ath12k_tm_wmi_event_segmented(struct ath12k_base *ab, u32 cmd_id,
int ret;
u16 length;
- tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+ tb = ath12k_wmi_tlv_parse(ab, skb);
if (IS_ERR(tb)) {
ret = PTR_ERR(tb);
@@ -8772,14 +8714,11 @@ static void ath12k_tm_wmi_event_segmented(struct ath12k_base *ab, u32 cmd_id,
ev = tb[WMI_TAG_ARRAY_BYTE];
if (!ev) {
ath12k_warn(ab, "failed to fetch ftm msg\n");
- kfree(tb);
return;
}
length = skb->len - TLV_HDR_SIZE;
ath12k_tm_process_event(ab, cmd_id, ev, length);
- kfree(tb);
- tb = NULL;
}
static void
@@ -8792,7 +8731,7 @@ ath12k_wmi_pdev_temperature_event(struct ath12k_base *ab,
int temp;
u32 pdev_id;
- tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+ tb = ath12k_wmi_tlv_parse(ab, skb);
if (IS_ERR(tb)) {
ath12k_warn(ab, "failed to parse tlv: %ld\n", PTR_ERR(tb));
return;
@@ -8801,15 +8740,12 @@ ath12k_wmi_pdev_temperature_event(struct ath12k_base *ab,
ev = tb[WMI_TAG_PDEV_TEMPERATURE_EVENT];
if (!ev) {
ath12k_warn(ab, "failed to fetch pdev temp ev\n");
- kfree(tb);
return;
}
temp = a_sle32_to_cpu(ev->temp);
pdev_id = le32_to_cpu(ev->pdev_id);
- kfree(tb);
-
ath12k_dbg(ab, ATH12K_DBG_WMI,
"pdev temperature ev temp %d pdev_id %u\n",
temp, pdev_id);
@@ -8836,7 +8772,7 @@ static void ath12k_fils_discovery_event(struct ath12k_base *ab,
const struct wmi_fils_discovery_event *ev;
int ret;
- tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+ tb = ath12k_wmi_tlv_parse(ab, skb);
if (IS_ERR(tb)) {
ret = PTR_ERR(tb);
ath12k_warn(ab,
@@ -8848,15 +8784,12 @@ static void ath12k_fils_discovery_event(struct ath12k_base *ab,
ev = tb[WMI_TAG_HOST_SWFDA_EVENT];
if (!ev) {
ath12k_warn(ab, "failed to fetch FILS discovery event\n");
- kfree(tb);
return;
}
ath12k_warn(ab,
"FILS discovery frame expected from host for vdev_id: %u, transmission scheduled at %u, next TBTT: %u\n",
ev->vdev_id, ev->fils_tt, ev->tbtt);
-
- kfree(tb);
}
static void ath12k_probe_resp_tx_status_event(struct ath12k_base *ab,
@@ -8866,7 +8799,7 @@ static void ath12k_probe_resp_tx_status_event(struct ath12k_base *ab,
const struct wmi_probe_resp_tx_status_event *ev;
int ret;
- tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+ tb = ath12k_wmi_tlv_parse(ab, skb);
if (IS_ERR(tb)) {
ret = PTR_ERR(tb);
ath12k_warn(ab,
@@ -8879,7 +8812,6 @@ static void ath12k_probe_resp_tx_status_event(struct ath12k_base *ab,
if (!ev) {
ath12k_warn(ab,
"failed to fetch probe response transmission status event");
- kfree(tb);
return;
}
@@ -8887,8 +8819,6 @@ static void ath12k_probe_resp_tx_status_event(struct ath12k_base *ab,
ath12k_warn(ab,
"Probe response transmission failed for vdev_id %u, status %u\n",
ev->vdev_id, ev->tx_status);
-
- kfree(tb);
}
static int ath12k_wmi_p2p_noa_event(struct ath12k_base *ab,
@@ -8900,7 +8830,7 @@ static int ath12k_wmi_p2p_noa_event(struct ath12k_base *ab,
struct ath12k *ar;
int ret, vdev_id;
- tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+ tb = ath12k_wmi_tlv_parse(ab, skb);
if (IS_ERR(tb)) {
ret = PTR_ERR(tb);
ath12k_warn(ab, "failed to parse P2P NoA TLV: %d\n", ret);
@@ -8910,10 +8840,8 @@ static int ath12k_wmi_p2p_noa_event(struct ath12k_base *ab,
ev = tb[WMI_TAG_P2P_NOA_EVENT];
noa = tb[WMI_TAG_P2P_NOA_INFO];
- if (!ev || !noa) {
- ret = -EPROTO;
- goto out;
- }
+ if (!ev || !noa)
+ return -EPROTO;
vdev_id = __le32_to_cpu(ev->vdev_id);
@@ -8936,8 +8864,6 @@ static int ath12k_wmi_p2p_noa_event(struct ath12k_base *ab,
unlock:
rcu_read_unlock();
-out:
- kfree(tb);
return ret;
}
@@ -8948,7 +8874,7 @@ static void ath12k_rfkill_state_change_event(struct ath12k_base *ab,
const void **tb;
int ret;
- tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+ tb = ath12k_wmi_tlv_parse(ab, skb);
if (IS_ERR(tb)) {
ret = PTR_ERR(tb);
ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
@@ -8956,10 +8882,8 @@ static void ath12k_rfkill_state_change_event(struct ath12k_base *ab,
}
ev = tb[WMI_TAG_RFKILL_EVENT];
- if (!ev) {
- kfree(tb);
+ if (!ev)
return;
- }
ath12k_dbg(ab, ATH12K_DBG_MAC,
"wmi tlv rfkill state change gpio %d type %d radio_state %d\n",
@@ -8972,7 +8896,6 @@ static void ath12k_rfkill_state_change_event(struct ath12k_base *ab,
spin_unlock_bh(&ab->base_lock);
queue_work(ab->workqueue, &ab->rfkill_work);
- kfree(tb);
}
static void
@@ -8988,7 +8911,7 @@ static void ath12k_wmi_twt_enable_event(struct ath12k_base *ab,
const struct wmi_twt_enable_event *ev;
int ret;
- tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+ tb = ath12k_wmi_tlv_parse(ab, skb);
if (IS_ERR(tb)) {
ret = PTR_ERR(tb);
ath12k_warn(ab, "failed to parse wmi twt enable status event tlv: %d\n",
@@ -8999,15 +8922,12 @@ static void ath12k_wmi_twt_enable_event(struct ath12k_base *ab,
ev = tb[WMI_TAG_TWT_ENABLE_COMPLETE_EVENT];
if (!ev) {
ath12k_warn(ab, "failed to fetch twt enable wmi event\n");
- goto exit;
+ return;
}
ath12k_dbg(ab, ATH12K_DBG_MAC, "wmi twt enable event pdev id %u status %u\n",
le32_to_cpu(ev->pdev_id),
le32_to_cpu(ev->status));
-
-exit:
- kfree(tb);
}
static void ath12k_wmi_twt_disable_event(struct ath12k_base *ab,
@@ -9017,7 +8937,7 @@ static void ath12k_wmi_twt_disable_event(struct ath12k_base *ab,
const struct wmi_twt_disable_event *ev;
int ret;
- tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+ tb = ath12k_wmi_tlv_parse(ab, skb);
if (IS_ERR(tb)) {
ret = PTR_ERR(tb);
ath12k_warn(ab, "failed to parse wmi twt disable status event tlv: %d\n",
@@ -9028,15 +8948,12 @@ static void ath12k_wmi_twt_disable_event(struct ath12k_base *ab,
ev = tb[WMI_TAG_TWT_DISABLE_COMPLETE_EVENT];
if (!ev) {
ath12k_warn(ab, "failed to fetch twt disable wmi event\n");
- goto exit;
+ return;
}
ath12k_dbg(ab, ATH12K_DBG_MAC, "wmi twt disable event pdev id %d status %u\n",
le32_to_cpu(ev->pdev_id),
le32_to_cpu(ev->status));
-
-exit:
- kfree(tb);
}
static int ath12k_wmi_wow_wakeup_host_parse(struct ath12k_base *ab,
@@ -9109,7 +9026,7 @@ static void ath12k_wmi_gtk_offload_status_event(struct ath12k_base *ab,
const void **tb;
int ret;
- tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+ tb = ath12k_wmi_tlv_parse(ab, skb);
if (IS_ERR(tb)) {
ret = PTR_ERR(tb);
ath12k_warn(ab, "failed to parse tlv: %d\n", ret);
@@ -9119,7 +9036,6 @@ static void ath12k_wmi_gtk_offload_status_event(struct ath12k_base *ab,
ev = tb[WMI_TAG_GTK_OFFLOAD_STATUS_EVENT];
if (!ev) {
ath12k_warn(ab, "failed to fetch gtk offload status ev");
- kfree(tb);
return;
}
@@ -9129,7 +9045,6 @@ static void ath12k_wmi_gtk_offload_status_event(struct ath12k_base *ab,
rcu_read_unlock();
ath12k_warn(ab, "failed to get arvif for vdev_id:%d\n",
le32_to_cpu(ev->vdev_id));
- kfree(tb);
return;
}
@@ -9145,8 +9060,6 @@ static void ath12k_wmi_gtk_offload_status_event(struct ath12k_base *ab,
(void *)&replay_ctr_be, GFP_ATOMIC);
rcu_read_unlock();
-
- kfree(tb);
}
static void ath12k_wmi_event_mlo_setup_complete(struct ath12k_base *ab,
@@ -9158,7 +9071,7 @@ static void ath12k_wmi_event_mlo_setup_complete(struct ath12k_base *ab,
const void **tb;
int ret, i;
- tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+ tb = ath12k_wmi_tlv_parse(ab, skb);
if (IS_ERR(tb)) {
ret = PTR_ERR(tb);
ath12k_warn(ab, "failed to parse mlo setup complete event tlv: %d\n",
@@ -9169,7 +9082,6 @@ static void ath12k_wmi_event_mlo_setup_complete(struct ath12k_base *ab,
ev = tb[WMI_TAG_MLO_SETUP_COMPLETE_EVENT];
if (!ev) {
ath12k_warn(ab, "failed to fetch mlo setup complete event\n");
- kfree(tb);
return;
}
@@ -9188,14 +9100,11 @@ static void ath12k_wmi_event_mlo_setup_complete(struct ath12k_base *ab,
if (!ar) {
ath12k_warn(ab, "invalid pdev_id %d status %u in setup complete event\n",
ev->pdev_id, ev->status);
- goto out;
+ return;
}
ar->mlo_setup_status = le32_to_cpu(ev->status);
complete(&ar->mlo_setup_done);
-
-out:
- kfree(tb);
}
static void ath12k_wmi_event_teardown_complete(struct ath12k_base *ab,
@@ -9205,7 +9114,7 @@ static void ath12k_wmi_event_teardown_complete(struct ath12k_base *ab,
const void **tb;
int ret;
- tb = ath12k_wmi_tlv_parse_alloc(ab, skb, GFP_ATOMIC);
+ tb = ath12k_wmi_tlv_parse(ab, skb);
if (IS_ERR(tb)) {
ret = PTR_ERR(tb);
ath12k_warn(ab, "failed to parse teardown complete event tlv: %d\n", ret);
@@ -9215,11 +9124,8 @@ static void ath12k_wmi_event_teardown_complete(struct ath12k_base *ab,
ev = tb[WMI_TAG_MLO_TEARDOWN_COMPLETE];
if (!ev) {
ath12k_warn(ab, "failed to fetch teardown complete event\n");
- kfree(tb);
return;
}
-
- kfree(tb);
}
#ifdef CONFIG_ATH12K_DEBUGFS
--
2.53.0
^ permalink raw reply related
* Re: [PATCH v2 00/18] wifi: drop redundant USB device references
From: Jeff Johnson @ 2026-03-09 14:25 UTC (permalink / raw)
To: Johannes Berg, Johan Hovold, linux-wireless
Cc: Jeff Johnson, Toke Høiland-Jørgensen, Brian Norris,
Francesco Dolcini, Felix Fietkau, Lorenzo Bianconi, Ryder Lee,
Shayne Chen, Sean Wang, Jakub Kicinski, Stanislaw Gruszka,
Hin-Tak Leung, Jes Sorensen, Ping-Ke Shih, Nicolas Ferre,
Alexandre Belloni, Claudiu Beznea, Matthias Brugger,
AngeloGioacchino Del Regno, Greg Kroah-Hartman, libertas-dev,
linux-kernel
In-Reply-To: <14fc35deb48f21c38bf957afc05eef1664bf3e81.camel@sipsolutions.net>
On 3/8/2026 11:27 PM, Johannes Berg wrote:
> On Fri, 2026-03-06 at 13:39 -0800, Jeff Johnson wrote:
>>
>> Johannes, will you be taking the entire series via wireless-next?
>>
>> Or should the individual wireless driver maintainers take their patches
>> through their individual trees? I'm OK either way.
>
> So far I took the ones patchwork had auto-assigned to me. I can take
> others though, no particular preference, but I guess I already pulled
> the series apart anyway.
>
> Let's just say if you want me to take any, assign them to me in
> patchwork.
ok, then I'll go forward with the ones assigned to me...
/jeff
^ permalink raw reply
* Re: [PATCH v2 03/18] wifi: ath9k: drop redundant device reference
From: Toke Høiland-Jørgensen @ 2026-03-09 11:45 UTC (permalink / raw)
To: Johan Hovold, linux-wireless
Cc: Jeff Johnson, Brian Norris, Francesco Dolcini, Felix Fietkau,
Lorenzo Bianconi, Ryder Lee, Shayne Chen, Sean Wang,
Jakub Kicinski, Stanislaw Gruszka, Hin-Tak Leung, Jes Sorensen,
Ping-Ke Shih, Nicolas Ferre, Alexandre Belloni, Claudiu Beznea,
Matthias Brugger, AngeloGioacchino Del Regno, Greg Kroah-Hartman,
libertas-dev, linux-kernel, Johan Hovold
In-Reply-To: <20260306085144.12064-4-johan@kernel.org>
Johan Hovold <johan@kernel.org> writes:
> Driver core holds a reference to the USB interface and its parent USB
> device while the interface is bound to a driver and there is no need to
> take additional references unless the structures are needed after
> disconnect.
>
> Drop the redundant device reference to reduce cargo culting, make it
> easier to spot drivers where an extra reference is needed, and reduce
> the risk of memory leaks when drivers fail to release it.
>
> Signed-off-by: Johan Hovold <johan@kernel.org>
Acked-by: Toke Høiland-Jørgensen <toke@toke.dk>
^ permalink raw reply
* Re: [PATCH] wifi: mac80211: fix monitor mode frame capture for real chanctx drivers
From: 傅继晗 @ 2026-03-09 10:45 UTC (permalink / raw)
To: johannes
Cc: linux-wireless, linux-kernel, stable, oscar.alfonso.diaz,
傅继晗
In-Reply-To: <8155c8f93c233e430c75c98bcdaea219b16e9596.camel@sipsolutions.net>
On Sun, 2026-03-08 at 16:45 +0000, 傅继晗 wrote:
> Fix this by falling back to the first entry in local->chanctx_list
> when the monitor vif has no chanctx and the driver uses real channel
> contexts. This is analogous to how ieee80211_hw_conf_chan() already
> uses the same pattern.
On Mon, 2026-03-09, Johannes Berg wrote:
> I did have pretty much the same attempt at a fix:
> https://lore.kernel.org/linux-wireless/20251216111909.25076-2-johannes@sipsolutions.net/
>
> but it was reported to cause crashes on certain devices, so we didn't
> think it was very safe at the time.
>
> Is that no longer an issue?
Hi Johannes,
Thanks for the quick review and for pointing me to your earlier v2
patch.
I see the key difference between our approaches: your v2 iterates
the chanctx_list and only proceeds when there is exactly one entry
(going to fail_rcu if more than one exists), while mine blindly takes
the first entry via list_first_entry_or_null(). Your approach is
clearly safer -- in a multi-chanctx scenario, there is no way to know
which channel the user intends to inject on, so refusing is the
correct behaviour.
I have tested my patch on an MT7921AU (mt76, USB) adapter across
v6.13, v6.19, and v7.0-rc2 with managed + monitor coexistence, and
have not observed any crashes. However, my testing was limited to a
single-chanctx scenario (one managed interface + one monitor
interface), so it does not rule out crashes in multi-chanctx
configurations.
Could you share some details about the crashes that were reported
with your v2? For example, which devices/drivers were affected and
what the crash signature looked like? That would help me understand
whether the issue was specific to multi-chanctx usage or something
more fundamental with accessing the chanctx_list in this code path.
If you agree, I would like to send a v2 that combines both approaches:
use list_first_entry_or_null() for simplicity, but add a
list_is_singular() guard so we only proceed when there is exactly one
chanctx -- matching the safety constraint from your v2:
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -2399,10 +2399,24 @@
- if (chanctx_conf)
+ if (chanctx_conf) {
chandef = &chanctx_conf->def;
- else if (local->emulate_chanctx)
+ } else if (local->emulate_chanctx) {
chandef = &local->hw.conf.chandef;
- else
- goto fail_rcu;
+ } else {
+ struct ieee80211_chanctx *ctx;
+
+ ctx = list_first_entry_or_null(&local->chanctx_list,
+ struct ieee80211_chanctx,
+ list);
+ if (ctx && list_is_singular(&local->chanctx_list))
+ chandef = &ctx->conf.def;
+ else
+ goto fail_rcu;
+ }
This avoids the ambiguity of picking an arbitrary chanctx in
multi-chanctx scenarios while still fixing the common single-chanctx
case (e.g. one managed + one monitor interface).
Alternatively, if you would prefer to revive your own patch, I am
happy to help test it on mt76 hardware.
Thanks,
Jihan
^ permalink raw reply
* Re: [PATCH wireless-next] wifi: brcmsmac: use FAM for debug code
From: Johannes Berg @ 2026-03-09 10:40 UTC (permalink / raw)
To: Rosen Penev, linux-wireless
Cc: Arend van Spriel,
open list:BROADCOM BRCM80211 IEEE802.11 WIRELESS DRIVERS,
open list:BROADCOM BRCM80211 IEEE802.11 WIRELESS DRIVERS,
open list
In-Reply-To: <20260223030539.19307-1-rosenp@gmail.com>
On Sun, 2026-02-22 at 19:05 -0800, Rosen Penev wrote:
>
> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.h
> @@ -43,7 +43,7 @@ struct brcms_timer {
> bool set; /* indicates if timer is active */
> struct brcms_timer *next; /* for freeing on unload */
> #ifdef DEBUG
> - char *name; /* Description of the timer */
> + char name[]; /* Description of the timer */
> #endif
>
Might be better to remove that ifdef too, if only to have cleaner code
and get errors when someone tries to add something after it in non-debug
builds?
johannes
^ permalink raw reply
* Re: [PATCH] brcmfmac: Fix error pointer dereference
From: Arend van Spriel @ 2026-03-09 10:13 UTC (permalink / raw)
To: Ethan Tidmore
Cc: linux-wireless, brcm80211, brcm80211-dev-list.pdl, linux-kernel,
johannes.berg
In-Reply-To: <20260217023043.73631-1-ethantidmore06@gmail.com>
On 17/02/2026 03:30, Ethan Tidmore wrote:
> The function brcmf_chip_add_core() can return an error pointer and is
> not checked. Add checks for error pointer.
>
> Detected by Smatch:
> drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c:1010 brcmf_chip_recognition() error:
> 'core' dereferencing possible ERR_PTR()
[...]
> Fixes: cb7cf7be9eba7 ("brcmfmac: make chip related functions host interface independent")
Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
> Signed-off-by: Ethan Tidmore <ethantidmore06@gmail.com>
> ---
> .../wireless/broadcom/brcm80211/brcmfmac/chip.c | 15 +++++++++++++++
> 1 file changed, 15 insertions(+)
^ permalink raw reply
* Re: [PATCH wireless-next 14/35] wifi: mm81x: add mac.c
From: Johannes Berg @ 2026-03-09 9:37 UTC (permalink / raw)
To: Lachlan Hodges
Cc: Dan Callaghan, Arien Judge, Nathan Chancellor, Nick Desaulniers,
Bill Wendling, Justin Stitt, ayman.grais, linux-wireless,
linux-kernel
In-Reply-To: <zcuk2lw4crrx77pel7rjzy6g4dae77psra3sfiytto4ap3b2nt@io3xv6gob7dz>
On Mon, 2026-03-09 at 20:23 +1100, Lachlan Hodges wrote:
> That's the goal of course. As for future work, right now both the
> kernel support + this driver is about as barebones as you get so we
> intend to continue expanding that. It felt best to push the driver
> now as the bare minimum such that people can start using the upstream
> S1G work. We have a lot more to do.
Right, that was definitely sensible (and something we've requested from
others).
> We expect to see some larger features - including monitor mode, and
> mesh in the near to mid-term future within the driver itself, but the
> core development will still remain in mac80211 & cfg80211 as we
> extend the S1G implementation.
Sounds like there would be quite some co-development with cfg/mac and
the driver, which is probably simpler if I apply driver patches too,
otherwise you have to synchronise pull requests to when I apply patches
to my tree? OTOH, to pass the bot checks you already have to do that
anyway, unless sending cfg/mac/driver patches in one series, which also
isn't great since it ends to bury the cfg/mac patches.
> As for workflows, we are still figuring that out for ourselves.
I'm actually not worried really worried about this driver at all, tbh,
since you're clearly around. :) But there's always a chance that you
also get patches from other folks.
I'd prefer if you could create an account on patchwork.kernel.org, and
then I can automatically delegate patches to this driver to you. Whether
or not you then re-assign them to me in patchwork or collect them and
send a pull request is somewhat secondary, but the latter obviously
makes things a bit simpler for me. If you _are_ going to do that longer
term than just the initial driver, probably should document a T: entry
in the maintainers file too.
johannes
^ permalink raw reply
* Re: [PATCH wireless-next 14/35] wifi: mm81x: add mac.c
From: Lachlan Hodges @ 2026-03-09 9:23 UTC (permalink / raw)
To: Johannes Berg
Cc: Dan Callaghan, Arien Judge, Nathan Chancellor, Nick Desaulniers,
Bill Wendling, Justin Stitt, ayman.grais, linux-wireless,
linux-kernel
In-Reply-To: <1ca86ec4a1af1edfb791ca65023ab1979507c5bc.camel@sipsolutions.net>
On Mon, Mar 09, 2026 at 08:08:53AM +0100, Johannes Berg wrote:
> On Mon, 2026-03-09 at 15:43 +1100, Lachlan Hodges wrote:
> > > 2) Are you going to incur the wrath of mm/ folks, where instances of
> > > 'struct mm_struct' are commonly called 'mm'? I can find a few
> > > examples of others (struct drm_buddy *mm, struct mqd_manager *mm),
> > > but you'd double the instances.
> >
> > This.. is definitely something I did not think of. I have no issue with
> > renaming to something else.. maybe mx? I'm not sure.
>
> Yeah I really don't know. There's no 'mm->lock' (any more? for some
> reason _that_ was what caught my eye wrt. the naming) in mm/, and I
> guess soon also not in your driver. I'll try to ask around, but it's
> probably safer to rename, and shouldn't be _that_ hard with spatch I
> guess. I guess 'mx' seems reasonable, 'mmx' is also confusing perhaps,
> and 'mm81x' doesn't lend itself to obvious other abbreviations.
Thanks. Although not a huge deal at all of course. I just copied
what atheros does with ar :-) so mx seems good enough.
> > can we confirm that this means
> > we are to submit subsequent patchset revisions in the same per-file
> > format until everyone is happy with the driver, and then raise the PR?
>
> I wouldn't necessarily way _everyone_, you can probably always find
> someone willing to nitpick if you look hard enough ;-)
:)
> Obviously I hope/expect you're going to continue to maintaining the
> driver and we'll have to figure out the workflow for that
That's the goal of course. As for future work, right now both the
kernel support + this driver is about as barebones as you get so we
intend to continue expanding that. It felt best to push the driver
now as the bare minimum such that people can start using the upstream
S1G work. We have a lot more to do.
> perhaps depending on how much work you're planning to put
> into it.
We expect to see some larger features - including monitor mode, and
mesh in the near to mid-term future within the driver itself, but the
core development will still remain in mac80211 & cfg80211 as we
extend the S1G implementation. As for workflows, we are still figuring
that out for ourselves.
lachlan
^ permalink raw reply
* Re: [PATCH 11/14] media: qcom: Switch to generic PAS TZ APIs
From: Jorge Ramirez @ 2026-03-09 9:12 UTC (permalink / raw)
To: Sumit Garg
Cc: linux-arm-msm, devicetree, dri-devel, freedreno, linux-media,
netdev, linux-wireless, ath12k, linux-remoteproc, andersson,
konradybcio, robh, krzk+dt, conor+dt, robin.clark, sean, akhilpo,
lumag, abhinav.kumar, jesszhan0024, marijn.suijten, airlied,
simona, vikash.garodia, dikshita.agarwal, bod, mchehab, elder,
andrew+netdev, davem, edumazet, kuba, pabeni, jjohnson,
mathieu.poirier, trilokkumar.soni, mukesh.ojha, pavan.kondeti,
jorge.ramirez, tonyh, vignesh.viswanathan, srinivas.kandagatla,
amirreza.zarrabi, jens.wiklander, op-tee, apurupa, skare,
Sumit Garg
In-Reply-To: <20260306105027.290375-12-sumit.garg@kernel.org>
On 06/03/26 16:20:24, Sumit Garg wrote:
> From: Sumit Garg <sumit.garg@oss.qualcomm.com>
>
> Switch qcom media client drivers over to generic PAS TZ APIs. Generic PAS
> TZ service allows to support multiple TZ implementation backends like QTEE
> based SCM PAS service, OP-TEE based PAS service and any further future TZ
> backend service.
>
> Signed-off-by: Sumit Garg <sumit.garg@oss.qualcomm.com>
> ---
> drivers/media/platform/qcom/iris/iris_firmware.c | 9 +++++----
> drivers/media/platform/qcom/venus/firmware.c | 11 ++++++-----
> 2 files changed, 11 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/media/platform/qcom/iris/iris_firmware.c b/drivers/media/platform/qcom/iris/iris_firmware.c
> index 5f408024e967..b3c5281aea91 100644
> --- a/drivers/media/platform/qcom/iris/iris_firmware.c
> +++ b/drivers/media/platform/qcom/iris/iris_firmware.c
> @@ -4,6 +4,7 @@
> */
>
> #include <linux/firmware.h>
> +#include <linux/firmware/qcom/qcom_pas.h>
> #include <linux/firmware/qcom/qcom_scm.h>
> #include <linux/of_address.h>
> #include <linux/of_reserved_mem.h>
> @@ -79,7 +80,7 @@ int iris_fw_load(struct iris_core *core)
> return -ENOMEM;
> }
>
> - ret = qcom_scm_pas_auth_and_reset(core->iris_platform_data->pas_id);
> + ret = qcom_pas_auth_and_reset(core->iris_platform_data->pas_id);
> if (ret) {
> dev_err(core->dev, "auth and reset failed: %d\n", ret);
> return ret;
> @@ -93,7 +94,7 @@ int iris_fw_load(struct iris_core *core)
> cp_config->cp_nonpixel_size);
> if (ret) {
> dev_err(core->dev, "qcom_scm_mem_protect_video_var failed: %d\n", ret);
> - qcom_scm_pas_shutdown(core->iris_platform_data->pas_id);
> + qcom_pas_shutdown(core->iris_platform_data->pas_id);
> return ret;
> }
> }
> @@ -103,10 +104,10 @@ int iris_fw_load(struct iris_core *core)
>
> int iris_fw_unload(struct iris_core *core)
> {
> - return qcom_scm_pas_shutdown(core->iris_platform_data->pas_id);
> + return qcom_pas_shutdown(core->iris_platform_data->pas_id);
> }
>
are the calls to set_remote_state required?
0 is not the IRIS/VENUS remote processor.
If it is legacy, maybe they can be phased out?
> int iris_set_hw_state(struct iris_core *core, bool resume)
> {
> - return qcom_scm_set_remote_state(resume, 0);
> + return qcom_pas_set_remote_state(resume, 0);
> }
> diff --git a/drivers/media/platform/qcom/venus/firmware.c b/drivers/media/platform/qcom/venus/firmware.c
> index 1de7436713ed..3a38ff985822 100644
> --- a/drivers/media/platform/qcom/venus/firmware.c
> +++ b/drivers/media/platform/qcom/venus/firmware.c
> @@ -12,6 +12,7 @@
> #include <linux/of_reserved_mem.h>
> #include <linux/platform_device.h>
> #include <linux/of_device.h>
> +#include <linux/firmware/qcom/qcom_pas.h>
> #include <linux/firmware/qcom/qcom_scm.h>
> #include <linux/sizes.h>
> #include <linux/soc/qcom/mdt_loader.h>
> @@ -58,7 +59,7 @@ int venus_set_hw_state(struct venus_core *core, bool resume)
> int ret;
>
> if (core->use_tz) {
> - ret = qcom_scm_set_remote_state(resume, 0);
> + ret = qcom_pas_set_remote_state(resume, 0);
> if (resume && ret == -EINVAL)
> ret = 0;
> return ret;
^ permalink raw reply
* [PATCH rtw-next] wifi: rtw89: usb: Rx aggregation for RTL8832CU/RTL8851BU
From: Ping-Ke Shih @ 2026-03-09 8:58 UTC (permalink / raw)
To: linux-wireless; +Cc: rtl8821cerfe2, mh_chen, isaiah
From: Shin-Yi Lin <isaiah@realtek.com>
USB RX Aggregation is a performance optimization technique used
in USB network devices to increase throughput.
Instead of sending every received network packet to the host computer
individually, the device hardware groups multiple smaller packets
into a single, large USB Bulk Transfer.
* toAP/toNB use iperf3 respectively.
With BE6000 - iperf3 tcp 10 pair (to another NB)
RTL8832CU-USB3.0
before after
TX 941 941
RX 847 919
RTL8832CU-USB2.0
before after
TX 864 877
RX 864 902
RTL8851BU
before after
TX 115 114
RX 295 306
Signed-off-by: Shin-Yi Lin <isaiah@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
This one is to add USB RX aggregation to improve performance. The other
one is TX aggregation, which we are working on.
---
.../net/wireless/realtek/rtw89/rtw8851bu.c | 1 +
.../net/wireless/realtek/rtw89/rtw8852au.c | 1 +
.../net/wireless/realtek/rtw89/rtw8852bu.c | 1 +
.../net/wireless/realtek/rtw89/rtw8852cu.c | 1 +
drivers/net/wireless/realtek/rtw89/usb.c | 84 ++++++++++++++++---
drivers/net/wireless/realtek/rtw89/usb.h | 12 +++
6 files changed, 87 insertions(+), 13 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851bu.c b/drivers/net/wireless/realtek/rtw89/rtw8851bu.c
index 959d62aefdd8..6a8d31544314 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8851bu.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8851bu.c
@@ -15,6 +15,7 @@ static const struct rtw89_usb_info rtw8851b_usb_info = {
.usb3_mac_npi_config_intf_0 = R_AX_USB3_MAC_NPI_CONFIG_INTF_0,
.usb_endpoint_0 = R_AX_USB_ENDPOINT_0,
.usb_endpoint_2 = R_AX_USB_ENDPOINT_2,
+ .rx_agg_alignment = 8,
.bulkout_id = {
[RTW89_DMA_ACH0] = 3,
[RTW89_DMA_ACH1] = 4,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852au.c b/drivers/net/wireless/realtek/rtw89/rtw8852au.c
index ccdbcc178c2a..4cced4619b7d 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852au.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852au.c
@@ -15,6 +15,7 @@ static const struct rtw89_usb_info rtw8852a_usb_info = {
.usb3_mac_npi_config_intf_0 = R_AX_USB3_MAC_NPI_CONFIG_INTF_0,
.usb_endpoint_0 = R_AX_USB_ENDPOINT_0,
.usb_endpoint_2 = R_AX_USB_ENDPOINT_2,
+ .rx_agg_alignment = 8,
.bulkout_id = {
[RTW89_DMA_ACH0] = 3,
[RTW89_DMA_ACH2] = 5,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852bu.c b/drivers/net/wireless/realtek/rtw89/rtw8852bu.c
index 84cd3ec971f9..37111fed276f 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852bu.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852bu.c
@@ -15,6 +15,7 @@ static const struct rtw89_usb_info rtw8852b_usb_info = {
.usb3_mac_npi_config_intf_0 = R_AX_USB3_MAC_NPI_CONFIG_INTF_0,
.usb_endpoint_0 = R_AX_USB_ENDPOINT_0,
.usb_endpoint_2 = R_AX_USB_ENDPOINT_2,
+ .rx_agg_alignment = 8,
.bulkout_id = {
[RTW89_DMA_ACH0] = 3,
[RTW89_DMA_ACH1] = 4,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852cu.c b/drivers/net/wireless/realtek/rtw89/rtw8852cu.c
index 3b9825c92a0d..0c5aebaed873 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852cu.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852cu.c
@@ -15,6 +15,7 @@ static const struct rtw89_usb_info rtw8852c_usb_info = {
.usb3_mac_npi_config_intf_0 = R_AX_USB3_MAC_NPI_CONFIG_INTF_0_V1,
.usb_endpoint_0 = R_AX_USB_ENDPOINT_0_V1,
.usb_endpoint_2 = R_AX_USB_ENDPOINT_2_V1,
+ .rx_agg_alignment = 8,
.bulkout_id = {
[RTW89_DMA_ACH0] = 3,
[RTW89_DMA_ACH2] = 5,
diff --git a/drivers/net/wireless/realtek/rtw89/usb.c b/drivers/net/wireless/realtek/rtw89/usb.c
index da1b7ce8089e..4482ce61592b 100644
--- a/drivers/net/wireless/realtek/rtw89/usb.c
+++ b/drivers/net/wireless/realtek/rtw89/usb.c
@@ -408,11 +408,14 @@ static int rtw89_usb_ops_tx_write(struct rtw89_dev *rtwdev,
static void rtw89_usb_rx_handler(struct work_struct *work)
{
struct rtw89_usb *rtwusb = container_of(work, struct rtw89_usb, rx_work);
+ const struct rtw89_usb_info *info = rtwusb->info;
struct rtw89_dev *rtwdev = rtwusb->rtwdev;
struct rtw89_rx_desc_info desc_info;
+ s32 aligned_offset, remaining;
struct sk_buff *rx_skb;
struct sk_buff *skb;
u32 pkt_offset;
+ u8 *pkt_ptr;
int limit;
for (limit = 0; limit < 200; limit++) {
@@ -425,23 +428,38 @@ static void rtw89_usb_rx_handler(struct work_struct *work)
goto free_or_reuse;
}
- memset(&desc_info, 0, sizeof(desc_info));
- rtw89_chip_query_rxdesc(rtwdev, &desc_info, rx_skb->data, 0);
+ pkt_ptr = rx_skb->data;
+ remaining = rx_skb->len;
- skb = rtw89_alloc_skb_for_rx(rtwdev, desc_info.pkt_size);
- if (!skb) {
- rtw89_debug(rtwdev, RTW89_DBG_HCI,
- "failed to allocate RX skb of size %u\n",
- desc_info.pkt_size);
- goto free_or_reuse;
- }
+ do {
+ memset(&desc_info, 0, sizeof(desc_info));
+ rtw89_chip_query_rxdesc(rtwdev, &desc_info, pkt_ptr, 0);
- pkt_offset = desc_info.offset + desc_info.rxd_len;
+ pkt_offset = desc_info.offset + desc_info.rxd_len;
+ if (remaining < (pkt_offset + desc_info.pkt_size)) {
+ rtw89_debug(rtwdev, RTW89_DBG_HCI,
+ "Failed to get remaining RX pkt %u > %u\n",
+ pkt_offset + desc_info.pkt_size, remaining);
+ goto free_or_reuse;
+ }
- skb_put_data(skb, rx_skb->data + pkt_offset,
- desc_info.pkt_size);
+ skb = rtw89_alloc_skb_for_rx(rtwdev, desc_info.pkt_size);
+ if (!skb) {
+ rtw89_debug(rtwdev, RTW89_DBG_HCI,
+ "failed to allocate RX skb of size %u\n",
+ desc_info.pkt_size);
+ goto free_or_reuse;
+ }
+
+ skb_put_data(skb, pkt_ptr + pkt_offset, desc_info.pkt_size);
+ rtw89_core_rx(rtwdev, &desc_info, skb);
- rtw89_core_rx(rtwdev, &desc_info, skb);
+ /* next frame */
+ pkt_offset += desc_info.pkt_size;
+ aligned_offset = ALIGN(pkt_offset, info->rx_agg_alignment);
+ pkt_ptr += aligned_offset;
+ remaining -= aligned_offset;
+ } while (remaining > 0);
free_or_reuse:
if (skb_queue_len(&rtwusb->rx_free_queue) >= RTW89_USB_RX_SKB_NUM)
@@ -745,6 +763,44 @@ static int rtw89_usb_ops_mac_pre_deinit(struct rtw89_dev *rtwdev)
return 0; /* Nothing to do. */
}
+static void usb_rx_agg_cfg_v1(struct rtw89_dev *rtwdev)
+{
+ const u32 rxagg_0 = FIELD_PREP_CONST(B_AX_RXAGG_0_EN, 1) |
+ FIELD_PREP_CONST(B_AX_RXAGG_0_NUM_TH, 0) |
+ FIELD_PREP_CONST(B_AX_RXAGG_0_TIME_32US_TH, 32) |
+ FIELD_PREP_CONST(B_AX_RXAGG_0_BUF_SZ_4K, 5);
+
+ rtw89_write32(rtwdev, R_AX_RXAGG_0, rxagg_0);
+}
+
+static void usb_rx_agg_cfg_v2(struct rtw89_dev *rtwdev)
+{
+ const u32 rxagg_0 = FIELD_PREP_CONST(B_AX_RXAGG_0_EN, 1) |
+ FIELD_PREP_CONST(B_AX_RXAGG_0_NUM_TH, 255) |
+ FIELD_PREP_CONST(B_AX_RXAGG_0_TIME_32US_TH, 32) |
+ FIELD_PREP_CONST(B_AX_RXAGG_0_BUF_SZ_K, 20);
+
+ rtw89_write32(rtwdev, R_AX_RXAGG_0_V1, rxagg_0);
+ rtw89_write32(rtwdev, R_AX_RXAGG_1_V1, 0x1F);
+}
+
+static void usb_rx_agg_cfg(struct rtw89_dev *rtwdev)
+{
+ switch (rtwdev->chip->chip_id) {
+ case RTL8851B:
+ case RTL8852A:
+ case RTL8852B:
+ usb_rx_agg_cfg_v1(rtwdev);
+ break;
+ case RTL8852C:
+ usb_rx_agg_cfg_v2(rtwdev);
+ break;
+ default:
+ rtw89_warn(rtwdev, "%s: USB RX agg not support\n", __func__);
+ return;
+ }
+}
+
static int rtw89_usb_ops_mac_post_init(struct rtw89_dev *rtwdev)
{
struct rtw89_usb *rtwusb = rtw89_usb_priv(rtwdev);
@@ -773,6 +829,8 @@ static int rtw89_usb_ops_mac_post_init(struct rtw89_dev *rtwdev)
rtw89_write8(rtwdev, info->usb_endpoint_2 + 1, NUMP);
}
+ usb_rx_agg_cfg(rtwdev);
+
return 0;
}
diff --git a/drivers/net/wireless/realtek/rtw89/usb.h b/drivers/net/wireless/realtek/rtw89/usb.h
index 203ec8e993e9..afc62c1f687f 100644
--- a/drivers/net/wireless/realtek/rtw89/usb.h
+++ b/drivers/net/wireless/realtek/rtw89/usb.h
@@ -20,6 +20,17 @@
#define RTW89_MAX_ENDPOINT_NUM 9
#define RTW89_MAX_BULKOUT_NUM 7
+#define R_AX_RXAGG_0_V1 0x6000
+#define B_AX_RXAGG_0_EN BIT(31)
+#define B_AX_RXAGG_0_NUM_TH GENMASK(23, 16)
+#define B_AX_RXAGG_0_TIME_32US_TH GENMASK(15, 8)
+#define B_AX_RXAGG_0_BUF_SZ_K GENMASK(7, 0)
+
+#define R_AX_RXAGG_1_V1 0x6004
+
+#define R_AX_RXAGG_0 0x8900
+#define B_AX_RXAGG_0_BUF_SZ_4K GENMASK(7, 0)
+
struct rtw89_usb_info {
u32 usb_host_request_2;
u32 usb_wlan0_1;
@@ -27,6 +38,7 @@ struct rtw89_usb_info {
u32 usb3_mac_npi_config_intf_0;
u32 usb_endpoint_0;
u32 usb_endpoint_2;
+ u8 rx_agg_alignment;
u8 bulkout_id[RTW89_DMA_CH_NUM];
};
base-commit: 039cd522dc70151da13329a5e3ae19b1736f468a
--
2.25.1
^ permalink raw reply related
* [PATCH] wifi: cfg80211: scope cfg80211_bss_age() to CONFIG_PM_SLEEP
From: Pengpeng Hou @ 2026-03-09 8:52 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, linux-kernel, Pengpeng Hou
In current linux.git (1954c4f01220), cfg80211_bss_age() is defined
and declared unconditionally. However, its only in-tree caller is within
wiphy_resume() in net/wireless/sysfs.c, which is already guarded by #ifdef
CONFIG_PM_SLEEP.
Match the helper scope to its caller by wrapping the definition in
CONFIG_PM_SLEEP and providing a no-op stub in the header. This fixes the
config-scope mismatch and avoids unnecessary code inclusion when
system sleep support is disabled.
Signed-off-by: Pengpeng Hou <pengpeng.hou@isrc.iscas.ac.cn>
---
diff --git a/net/wireless/core.h b/net/wireless/core.h
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@
void cfg80211_bss_expire(struct cfg80211_registered_device *rdev);
+#ifdef CONFIG_PM_SLEEP
void cfg80211_bss_age(struct cfg80211_registered_device *rdev,
unsigned long age_secs);
+#else
+static inline void cfg80211_bss_age(struct cfg80211_registered_device *rdev,
+ unsigned long age_secs) { }
+#endif
void cfg80211_update_assoc_bss_entry(struct wireless_dev *wdev,
unsigned int link,
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@
-void cfg80211_bss_age(struct cfg80211_registered_device *rdev,
+#ifdef CONFIG_PM_SLEEP
+void cfg80211_bss_age(struct cfg80211_registered_device *rdev,
unsigned long age_secs)
{
struct cfg80211_internal_bss *bss;
@@
list_for_each_entry(bss, &rdev->bss_list, list)
bss->ts -= age_jiffies;
spin_unlock_bh(&rdev->bss_lock);
}
+#endif
void cfg80211_bss_expire(struct cfg80211_registered_device *rdev)
{
^ permalink raw reply
* [PATCH RESEND] wifi: rtlwifi: usb: drop redundant device reference
From: Johan Hovold @ 2026-03-09 8:33 UTC (permalink / raw)
To: linux-wireless; +Cc: Ping-Ke Shih, linux-kernel, Johan Hovold
Driver core holds a reference to the USB interface and its parent USB
device while the interface is bound to a driver and there is no need to
take additional references unless the structures are needed after
disconnect.
Drop the redundant device reference to reduce cargo culting, make it
easier to spot drivers where an extra reference is needed, and reduce
the risk of memory leaks when drivers fail to release it.
Signed-off-by: Johan Hovold <johan@kernel.org>
---
This one fell out when sending v2 of the series:
https://lore.kernel.org/all/20260306085144.12064-2-johan@kernel.org/
so posting again separately.
Sorry for the mess.
Johan
drivers/net/wireless/realtek/rtlwifi/usb.c | 4 ----
1 file changed, 4 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtlwifi/usb.c b/drivers/net/wireless/realtek/rtlwifi/usb.c
index d35ed56d6db9..9a64df9eed39 100644
--- a/drivers/net/wireless/realtek/rtlwifi/usb.c
+++ b/drivers/net/wireless/realtek/rtlwifi/usb.c
@@ -986,7 +986,6 @@ int rtl_usb_probe(struct usb_interface *intf,
init_completion(&rtlpriv->firmware_loading_complete);
SET_IEEE80211_DEV(hw, &intf->dev);
udev = interface_to_usbdev(intf);
- usb_get_dev(udev);
usb_priv = rtl_usbpriv(hw);
memset(usb_priv, 0, sizeof(*usb_priv));
usb_priv->dev.intf = intf;
@@ -1038,7 +1037,6 @@ int rtl_usb_probe(struct usb_interface *intf,
rtl_deinit_core(hw);
error_out2:
_rtl_usb_io_handler_release(hw);
- usb_put_dev(udev);
kfree(rtlpriv->usb_data);
ieee80211_free_hw(hw);
return -ENODEV;
@@ -1050,7 +1048,6 @@ void rtl_usb_disconnect(struct usb_interface *intf)
struct ieee80211_hw *hw = usb_get_intfdata(intf);
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw));
- struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
if (unlikely(!rtlpriv))
return;
@@ -1072,7 +1069,6 @@ void rtl_usb_disconnect(struct usb_interface *intf)
kfree(rtlpriv->usb_data);
rtlpriv->cfg->ops->deinit_sw_vars(hw);
_rtl_usb_io_handler_release(hw);
- usb_put_dev(rtlusb->udev);
usb_set_intfdata(intf, NULL);
ieee80211_free_hw(hw);
}
--
2.52.0
^ permalink raw reply related
* [PATCH wireless-next v2] wifi: mac80211: Remove deleted sta links in ieee80211_ml_reconf_work()
From: Lorenzo Bianconi @ 2026-03-09 8:28 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless, Lorenzo Bianconi
Delete stale station links announced in the reconfiguration IE
transmitted by the AP in the beacon frames.
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
Changes in v2:
- Remove unnecessary read_lock()/read_unlock()
- Link to v1: https://lore.kernel.org/r/20260307-mac80211-reconf-remove-sta-link-v1-1-efe58070cd36@kernel.org
---
net/mac80211/mlme.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 5ecd3d1b172df70c6e447351c89f956b6d873c20..71b8aeb22ea9a77b8ae34397aeb03199c152d313 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -7058,6 +7058,7 @@ static void ieee80211_ml_reconf_work(struct wiphy *wiphy,
container_of(work, struct ieee80211_sub_if_data,
u.mgd.ml_reconf_work.work);
u16 new_valid_links, new_active_links, new_dormant_links;
+ struct sta_info *sta;
int ret;
if (!sdata->u.mgd.removed_links)
@@ -7093,6 +7094,16 @@ static void ieee80211_ml_reconf_work(struct wiphy *wiphy,
}
}
+ sta = sta_info_get(sdata, sdata->vif.cfg.ap_addr);
+ if (sta) {
+ unsigned long removed_links = sdata->u.mgd.removed_links;
+ unsigned int link_id;
+
+ for_each_set_bit(link_id, &removed_links,
+ IEEE80211_MLD_MAX_NUM_LINKS)
+ ieee80211_sta_free_link(sta, link_id);
+ }
+
new_dormant_links = sdata->vif.dormant_links & ~sdata->u.mgd.removed_links;
ret = ieee80211_vif_set_links(sdata, new_valid_links,
---
base-commit: 97492c019da4b62df83255e968b23b81c0315530
change-id: 20260307-mac80211-reconf-remove-sta-link-a47fa95ea7a7
Best regards,
--
Lorenzo Bianconi <lorenzo@kernel.org>
^ permalink raw reply related
* Re: [PATCH wireless-next] wifi: mac80211: Remove deleted sta links in ieee80211_ml_reconf_work()
From: Johannes Berg @ 2026-03-09 8:22 UTC (permalink / raw)
To: Lorenzo Bianconi; +Cc: Lachlan Hodges, linux-wireless
In-Reply-To: <aa6CuVi3BZxLBcPA@lore-desk>
On Mon, 2026-03-09 at 09:20 +0100, Lorenzo Bianconi wrote:
> > Also, I think you need ieee80211_sta_remove_link() to tell the driver?
>
> I think we already inform the driver running ieee80211_set_active_links() so
> ieee80211_sta_remove_link() seems redundant, right?
>
> ieee80211_set_active_links() -> _ieee80211_set_active_links() -> drv_change_sta_links()
Oh, hmm, yeah, good point!
> > And I realized another thing - this needs to destroy TDLS stations that
> > were on the link being removed, but maybe that's a separate commit.
>
> Do you mean ieee80211_teardown_tdls_peers()? Is it done in
> _ieee80211_set_active_links() too?
So ... it was all already consistent all along, at least towards the
driver? I totally missed that, sorry. Thanks for checking!
johannes
^ permalink raw reply
* Re: [PATCH wireless-next] wifi: mac80211: Remove deleted sta links in ieee80211_ml_reconf_work()
From: Lorenzo Bianconi @ 2026-03-09 8:20 UTC (permalink / raw)
To: Johannes Berg; +Cc: Lachlan Hodges, linux-wireless
In-Reply-To: <be1c90f6be71f6118590b0add4d657cd79d2ea2b.camel@sipsolutions.net>
[-- Attachment #1: Type: text/plain, Size: 1665 bytes --]
On Mar 09, Johannes Berg wrote:
> On Sun, 2026-03-08 at 14:28 +0100, Lorenzo Bianconi wrote:
> > > > + rcu_read_lock();
> > > > + sta = sta_info_get(sdata, sdata->vif.cfg.ap_addr);
> > > > + if (sta) {
> > > > + unsigned long removed_links = sdata->u.mgd.removed_links;
> > > > + unsigned int link_id;
> > > > +
> > > > + for_each_set_bit(link_id, &removed_links,
> > > > + IEEE80211_MLD_MAX_NUM_LINKS)
> > > > + ieee80211_sta_free_link(sta, link_id);
> > > > + }
> > > > + rcu_read_unlock();
> > > > +
> > >
> > > Could use scoped_guard(rcu) instead?
> >
> > I do not have a strong opinion here.
> > @Johannes: Which one do you prefer?
> >
>
> To answer the literal question: No strong preference I guess, given that
> there's no error path here this seems fine, and the scoped version would
> just add another indentation level.
>
> But you really should just remove the rcu_read_lock/unlock anyway, it's
> not needed since this holds wiphy mutex, which is sufficient to access
> the STA table etc.
ack, I will fix it in v2.
>
> Also, I think you need ieee80211_sta_remove_link() to tell the driver?
I think we already inform the driver running ieee80211_set_active_links() so
ieee80211_sta_remove_link() seems redundant, right?
ieee80211_set_active_links() -> _ieee80211_set_active_links() -> drv_change_sta_links()
>
> And I realized another thing - this needs to destroy TDLS stations that
> were on the link being removed, but maybe that's a separate commit.
Do you mean ieee80211_teardown_tdls_peers()? Is it done in
_ieee80211_set_active_links() too?
Regards,
Lorenzo
>
> johannes
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH 01/14] arm64: dts: qcom: kodiak: Add EL2 overlay
From: Sumit Garg @ 2026-03-09 8:09 UTC (permalink / raw)
To: Mukesh Ojha
Cc: linux-arm-msm, devicetree, dri-devel, freedreno, linux-media,
netdev, linux-wireless, ath12k, linux-remoteproc, andersson,
konradybcio, robh, krzk+dt, conor+dt, robin.clark, sean, akhilpo,
lumag, abhinav.kumar, jesszhan0024, marijn.suijten, airlied,
simona, vikash.garodia, dikshita.agarwal, bod, mchehab, elder,
andrew+netdev, davem, edumazet, kuba, pabeni, jjohnson,
mathieu.poirier, trilokkumar.soni, pavan.kondeti, jorge.ramirez,
tonyh, vignesh.viswanathan, srinivas.kandagatla, amirreza.zarrabi,
jens.wiklander, op-tee, apurupa, skare, Sumit Garg
In-Reply-To: <20260309080049.si3vzro4z6qn7ewz@hu-mojha-hyd.qualcomm.com>
On Mon, Mar 09, 2026 at 01:30:49PM +0530, Mukesh Ojha wrote:
> On Fri, Mar 06, 2026 at 04:20:14PM +0530, Sumit Garg wrote:
> > From: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com>
> >
> > All the existing variants Kodiak boards are using Gunyah hypervisor
> > which means that, so far, Linux-based OS could only boot in EL1 on those
> > devices. However, it is possible for us to boot Linux at EL2 on these
> > devices [1].
> >
> > When running under Gunyah, the remote processor firmware IOMMU
> > streams are controlled by Gunyah. However, without Gunyah, the IOMMU is
> > managed by the consumer of this DeviceTree. Therefore, describe the
> > firmware streams for each remote processor.
> >
> > Add a EL2-specific DT overlay and apply it to Kodiak IOT variant
> > devices to create -el2.dtb for each of them alongside "normal" dtb.
> >
> > [1]
> > https://docs.qualcomm.com/bundle/publicresource/topics/80-70020-4/boot-developer-touchpoints.html#uefi
> >
> > Signed-off-by: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com>
> > [SG: watchdog fixup]
> > Signed-off-by: Sumit Garg <sumit.garg@oss.qualcomm.com>
>
> Thanks for posting, I was about to add kodiak to the already existing
> list monaco, talos here
> https://lore.kernel.org/lkml/20260127-talos-el2-overlay-v2-0-b6a2266532c4@oss.qualcomm.com/
>
> but did you really miss linux-kernel@vger.kernel.org or is it
> intentional ?
Ah I see, I missed that list. Will add in v2. BTW, this patch in the
series can be applied independently since it will work with existing
SCM interfaces provided by QTEE.
-Sumit
>
> > ---
> > arch/arm64/boot/dts/qcom/Makefile | 2 ++
> > arch/arm64/boot/dts/qcom/kodiak-el2.dtso | 35 ++++++++++++++++++++++++
> > 2 files changed, 37 insertions(+)
> > create mode 100644 arch/arm64/boot/dts/qcom/kodiak-el2.dtso
> >
> > diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile
> > index f80b5d9cf1e8..09a7f943190e 100644
> > --- a/arch/arm64/boot/dts/qcom/Makefile
> > +++ b/arch/arm64/boot/dts/qcom/Makefile
> > @@ -139,6 +139,8 @@ dtb-$(CONFIG_ARCH_QCOM) += qcs404-evb-4000.dtb
> > dtb-$(CONFIG_ARCH_QCOM) += qcs615-ride.dtb
> > dtb-$(CONFIG_ARCH_QCOM) += qcs6490-radxa-dragon-q6a.dtb
> > dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2.dtb
> > +qcs6490-rb3gen2-el2-dtbs := qcs6490-rb3gen2.dtb kodiak-el2.dtbo
> > +dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-el2.dtb
> >
> > qcs6490-rb3gen2-vision-mezzanine-dtbs := qcs6490-rb3gen2.dtb qcs6490-rb3gen2-vision-mezzanine.dtbo
> > qcs6490-rb3gen2-industrial-mezzanine-dtbs := qcs6490-rb3gen2.dtb qcs6490-rb3gen2-industrial-mezzanine.dtbo
> > diff --git a/arch/arm64/boot/dts/qcom/kodiak-el2.dtso b/arch/arm64/boot/dts/qcom/kodiak-el2.dtso
> > new file mode 100644
> > index 000000000000..0b3a69a0d765
> > --- /dev/null
> > +++ b/arch/arm64/boot/dts/qcom/kodiak-el2.dtso
> > @@ -0,0 +1,35 @@
> > +// SPDX-License-Identifier: BSD-3-Clause
> > +/*
> > + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
> > + *
> > + * Kodiak specific modifications required to boot in EL2.
> > + */
> > +
> > +
> > +/dts-v1/;
> > +/plugin/;
> > +
> > +&gpu_zap_shader {
> > + status = "disabled";
> > +};
> > +
> > +&remoteproc_adsp {
> > + iommus = <&apps_smmu 0x1800 0x0>;
> > +};
> > +
> > +&remoteproc_cdsp {
> > + iommus = <&apps_smmu 0x11a0 0x0400>;
> > +};
> > +
> > +&remoteproc_wpss {
> > + iommus = <&apps_smmu 0x1c03 0x1>,
> > + <&apps_smmu 0x1c83 0x1>;
> > +};
> > +
> > +&venus {
> > + status = "disabled";
> > +};
> > +
> > +&watchdog {
> > + status = "okay";
> > +};
> > --
> > 2.51.0
> >
>
> --
> -Mukesh Ojha
>
^ permalink raw reply
* Re: [PATCH 01/14] arm64: dts: qcom: kodiak: Add EL2 overlay
From: Mukesh Ojha @ 2026-03-09 8:00 UTC (permalink / raw)
To: Sumit Garg
Cc: linux-arm-msm, devicetree, dri-devel, freedreno, linux-media,
netdev, linux-wireless, ath12k, linux-remoteproc, andersson,
konradybcio, robh, krzk+dt, conor+dt, robin.clark, sean, akhilpo,
lumag, abhinav.kumar, jesszhan0024, marijn.suijten, airlied,
simona, vikash.garodia, dikshita.agarwal, bod, mchehab, elder,
andrew+netdev, davem, edumazet, kuba, pabeni, jjohnson,
mathieu.poirier, trilokkumar.soni, pavan.kondeti, jorge.ramirez,
tonyh, vignesh.viswanathan, srinivas.kandagatla, amirreza.zarrabi,
jens.wiklander, op-tee, apurupa, skare, Sumit Garg
In-Reply-To: <20260306105027.290375-2-sumit.garg@kernel.org>
On Fri, Mar 06, 2026 at 04:20:14PM +0530, Sumit Garg wrote:
> From: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com>
>
> All the existing variants Kodiak boards are using Gunyah hypervisor
> which means that, so far, Linux-based OS could only boot in EL1 on those
> devices. However, it is possible for us to boot Linux at EL2 on these
> devices [1].
>
> When running under Gunyah, the remote processor firmware IOMMU
> streams are controlled by Gunyah. However, without Gunyah, the IOMMU is
> managed by the consumer of this DeviceTree. Therefore, describe the
> firmware streams for each remote processor.
>
> Add a EL2-specific DT overlay and apply it to Kodiak IOT variant
> devices to create -el2.dtb for each of them alongside "normal" dtb.
>
> [1]
> https://docs.qualcomm.com/bundle/publicresource/topics/80-70020-4/boot-developer-touchpoints.html#uefi
>
> Signed-off-by: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com>
> [SG: watchdog fixup]
> Signed-off-by: Sumit Garg <sumit.garg@oss.qualcomm.com>
Thanks for posting, I was about to add kodiak to the already existing
list monaco, talos here
https://lore.kernel.org/lkml/20260127-talos-el2-overlay-v2-0-b6a2266532c4@oss.qualcomm.com/
but did you really miss linux-kernel@vger.kernel.org or is it
intentional ?
-Mukesh
> ---
> arch/arm64/boot/dts/qcom/Makefile | 2 ++
> arch/arm64/boot/dts/qcom/kodiak-el2.dtso | 35 ++++++++++++++++++++++++
> 2 files changed, 37 insertions(+)
> create mode 100644 arch/arm64/boot/dts/qcom/kodiak-el2.dtso
>
> diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile
> index f80b5d9cf1e8..09a7f943190e 100644
> --- a/arch/arm64/boot/dts/qcom/Makefile
> +++ b/arch/arm64/boot/dts/qcom/Makefile
> @@ -139,6 +139,8 @@ dtb-$(CONFIG_ARCH_QCOM) += qcs404-evb-4000.dtb
> dtb-$(CONFIG_ARCH_QCOM) += qcs615-ride.dtb
> dtb-$(CONFIG_ARCH_QCOM) += qcs6490-radxa-dragon-q6a.dtb
> dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2.dtb
> +qcs6490-rb3gen2-el2-dtbs := qcs6490-rb3gen2.dtb kodiak-el2.dtbo
> +dtb-$(CONFIG_ARCH_QCOM) += qcs6490-rb3gen2-el2.dtb
>
> qcs6490-rb3gen2-vision-mezzanine-dtbs := qcs6490-rb3gen2.dtb qcs6490-rb3gen2-vision-mezzanine.dtbo
> qcs6490-rb3gen2-industrial-mezzanine-dtbs := qcs6490-rb3gen2.dtb qcs6490-rb3gen2-industrial-mezzanine.dtbo
> diff --git a/arch/arm64/boot/dts/qcom/kodiak-el2.dtso b/arch/arm64/boot/dts/qcom/kodiak-el2.dtso
> new file mode 100644
> index 000000000000..0b3a69a0d765
> --- /dev/null
> +++ b/arch/arm64/boot/dts/qcom/kodiak-el2.dtso
> @@ -0,0 +1,35 @@
> +// SPDX-License-Identifier: BSD-3-Clause
> +/*
> + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
> + *
> + * Kodiak specific modifications required to boot in EL2.
> + */
> +
> +
> +/dts-v1/;
> +/plugin/;
> +
> +&gpu_zap_shader {
> + status = "disabled";
> +};
> +
> +&remoteproc_adsp {
> + iommus = <&apps_smmu 0x1800 0x0>;
> +};
> +
> +&remoteproc_cdsp {
> + iommus = <&apps_smmu 0x11a0 0x0400>;
> +};
> +
> +&remoteproc_wpss {
> + iommus = <&apps_smmu 0x1c03 0x1>,
> + <&apps_smmu 0x1c83 0x1>;
> +};
> +
> +&venus {
> + status = "disabled";
> +};
> +
> +&watchdog {
> + status = "okay";
> +};
> --
> 2.51.0
>
--
-Mukesh Ojha
^ permalink raw reply
* Re: [PATCH 02/14] firmware: qcom: Add a generic PAS service
From: Sumit Garg @ 2026-03-09 7:16 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: linux-arm-msm, devicetree, dri-devel, freedreno, linux-media,
netdev, linux-wireless, ath12k, linux-remoteproc, andersson,
konradybcio, robh, krzk+dt, conor+dt, robin.clark, sean, akhilpo,
lumag, abhinav.kumar, jesszhan0024, marijn.suijten, airlied,
simona, vikash.garodia, dikshita.agarwal, bod, mchehab, elder,
andrew+netdev, davem, edumazet, kuba, pabeni, jjohnson,
mathieu.poirier, trilokkumar.soni, mukesh.ojha, pavan.kondeti,
jorge.ramirez, tonyh, vignesh.viswanathan, srinivas.kandagatla,
amirreza.zarrabi, jens.wiklander, op-tee, apurupa, skare,
Sumit Garg
In-Reply-To: <52cd78c2-95e2-4f56-9adc-242b6cf3baab@kernel.org>
On Mon, Mar 09, 2026 at 08:10:02AM +0100, Krzysztof Kozlowski wrote:
> On 09/03/2026 05:55, Sumit Garg wrote:
> > On Fri, Mar 06, 2026 at 12:15:01PM +0100, Krzysztof Kozlowski wrote:
> >> On 06/03/2026 11:50, Sumit Garg wrote:
> >>> From: Sumit Garg <sumit.garg@oss.qualcomm.com>
> >>>
> >>> Qcom platforms has the legacy of using non-standard SCM calls
> >>> splintered over the various kernel drivers. These SCM calls aren't
> >>> compliant with the standard SMC calling conventions which is a
> >>> prerequisite to enable migration to the FF-A specifications from
> >>> Arm.
> >>>
> >>> OP-TEE as an alternative trusted OS to QTEE can't support these non-
> >>> standard SCM calls. And even for newer architectures QTEE won't be able
> >>> to support SCM calls either with FF-A requirements coming in. And with
> >>> both OP-TEE and QTEE drivers well integrated in the TEE subsystem, it
> >>> makes further sense to reuse the TEE bus client drivers infrastructure.
> >>>
> >>> The added benefit of TEE bus infrastructure is that there is support
> >>> for discoverable/enumerable services. With that client drivers don't
> >>> have to manually invoke a special SCM call to know the service status.
> >>>
> >>> So enable the generic Peripheral Authentication Service (PAS) provided
> >>> by the firmware. It acts as the common layer with different TZ
> >>> backends plugged in whether it's an SCM implementation or a proper
> >>> TEE bus based PAS service implementation.
> >>>
> >>> Signed-off-by: Sumit Garg <sumit.garg@oss.qualcomm.com>
> >>> ---
> >>> drivers/firmware/qcom/Kconfig | 8 +
> >>> drivers/firmware/qcom/Makefile | 1 +
> >>> drivers/firmware/qcom/qcom_pas.c | 295 +++++++++++++++++++++++++
> >>> drivers/firmware/qcom/qcom_pas.h | 53 +++++
> >>> include/linux/firmware/qcom/qcom_pas.h | 41 ++++
> >>> 5 files changed, 398 insertions(+)
> >>> create mode 100644 drivers/firmware/qcom/qcom_pas.c
> >>> create mode 100644 drivers/firmware/qcom/qcom_pas.h
> >>> create mode 100644 include/linux/firmware/qcom/qcom_pas.h
> >>>
> >>> diff --git a/drivers/firmware/qcom/Kconfig b/drivers/firmware/qcom/Kconfig
> >>> index b477d54b495a..8653639d06db 100644
> >>> --- a/drivers/firmware/qcom/Kconfig
> >>> +++ b/drivers/firmware/qcom/Kconfig
> >>> @@ -6,6 +6,14 @@
> >>>
> >>> menu "Qualcomm firmware drivers"
> >>>
> >>> +config QCOM_PAS
> >>> + tristate
> >>> + help
> >>> + Enable the generic Peripheral Authentication Service (PAS) provided
> >>> + by the firmware. It acts as the common layer with different TZ
> >>> + backends plugged in whether it's an SCM implementation or a proper
> >>> + TEE bus based PAS service implementation.
> >>> +
> >>> config QCOM_SCM
> >>> select QCOM_TZMEM
> >>> tristate
> >>> diff --git a/drivers/firmware/qcom/Makefile b/drivers/firmware/qcom/Makefile
> >>> index 0be40a1abc13..dc5ab45f906a 100644
> >>> --- a/drivers/firmware/qcom/Makefile
> >>> +++ b/drivers/firmware/qcom/Makefile
> >>> @@ -8,3 +8,4 @@ qcom-scm-objs += qcom_scm.o qcom_scm-smc.o qcom_scm-legacy.o
> >>> obj-$(CONFIG_QCOM_TZMEM) += qcom_tzmem.o
> >>> obj-$(CONFIG_QCOM_QSEECOM) += qcom_qseecom.o
> >>> obj-$(CONFIG_QCOM_QSEECOM_UEFISECAPP) += qcom_qseecom_uefisecapp.o
> >>> +obj-$(CONFIG_QCOM_PAS) += qcom_pas.o
> >>> diff --git a/drivers/firmware/qcom/qcom_pas.c b/drivers/firmware/qcom/qcom_pas.c
> >>> new file mode 100644
> >>> index 000000000000..dc04ff1b6be0
> >>> --- /dev/null
> >>> +++ b/drivers/firmware/qcom/qcom_pas.c
> >>> @@ -0,0 +1,295 @@
> >>> +// SPDX-License-Identifier: GPL-2.0
> >>> +/*
> >>> + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
> >>> + */
> >>> +
> >>> +#include <linux/delay.h>
> >>> +#include <linux/device/devres.h>
> >>> +#include <linux/firmware/qcom/qcom_pas.h>
> >>> +#include <linux/of.h>
> >>> +#include <linux/kernel.h>
> >>> +#include <linux/module.h>
> >>> +#include <linux/slab.h>
> >>> +
> >>> +#include "qcom_pas.h"
> >>> +#include "qcom_scm.h"
> >>> +
> >>> +static struct qcom_pas_ops *ops_ptr;
> >>
> >> I really dislike this singleton design. And it is not even needed! If
> >> you were storing here some allocated instance of SCM/PAS I could
> >> understand, but singleton for only ops? Just implement one driver (so
> >> SCM + whatever you have here) which will decide which ops to use,
> >> through the probe. Really, this is neither needed nor beneficial.
> >
> > The motivation here is rather quite opposite to the single monolithic
> > SCM driver design. The TZ services like PAS, ICE and so on are going to
> > be implemented as independent discoverable devices on TEE bus which
> > rather needs independent kernel client drivers.
>
> You still have singleton here. So if you think you do opposite to
> singleton, then drop this static.
Sure.
>
> >
> > Also, the single driver probe can't work here since the SCM driver is
> > bound to the platform bus whereas the TEE PAS driver is bound to the TEE
> > bus. So there is a reason for the current design.
> >
> >>
> >> It actually leads to more problems with this barrier handling, see
> >> further comments.
> >
> > The barrier handling is something that I carried over from existing
> > implmentation but I can't see a reason why it can't be replaced with a
> > simple mutex. See diff below for mutex.
> >
> >> ...
> >>
> >>> +
> >>> +/**
> >>> + * qcom_pas_shutdown() - Shut down the remote processor
> >>> + * @pas_id: peripheral authentication service id
> >>> + *
> >>> + * Returns 0 on success.
> >>> + */
> >>> +int qcom_pas_shutdown(u32 pas_id)
> >>> +{
> >>> + if (ops_ptr)
> >>> + return ops_ptr->shutdown(ops_ptr->dev, pas_id);
> >>> +
> >>> + return -ENODEV;
> >>> +}
> >>> +EXPORT_SYMBOL_GPL(qcom_pas_shutdown);
> >>> +
> >>> +/**
> >>> + * qcom_pas_supported() - Check if the peripheral authentication service is
> >>> + * available for the given peripheral
> >>> + * @pas_id: peripheral authentication service id
> >>> + *
> >>> + * Returns true if PAS is supported for this peripheral, otherwise false.
> >>> + */
> >>> +bool qcom_pas_supported(u32 pas_id)
> >>> +{
> >>> + if (ops_ptr)
> >>
> >> Lack of barriers here is not looking right. Existing/old code is not a
> >> good example, I fixed only the obvious issue, but new code should be
> >> correct from the beginning.
> >>
> >> Barriers should normally be always paired, unless you have some clear
> >> path no concurrent execution can happen here, but such explanation is
> >> missing, look:
> >
> > Actually concurrent execution is rather required here since TZ can
> > support parallel bring-up of co-processors. The synchonization is only
> > needed when PAS client drivers are performing a deferred probe waiting
> > for the service to be available. However, you are right explanation is
> > missing here which I will add in the next version.
>
> Hm? Existing comments are completely useless. Your comment said just
> "barrier" basically... That's nothing useful.
Agree, following is something I plan for v2 (using mutex instead of a
barrier):
/*
* The ops mutex here is only intended to synchronize when client drivers
* are in parallel checking for PAS service availability. However, once the
* PAS backend becomes available, it is allowed for multiple threads to enter
* TZ for parallel bringup of co-processors during boot.
*/
static DEFINE_MUTEX(ops_mutex);
-Sumit
^ permalink raw reply
* Re: [PATCH wireless-next] wifi: mac80211: Remove deleted sta links in ieee80211_ml_reconf_work()
From: Johannes Berg @ 2026-03-09 7:14 UTC (permalink / raw)
To: Lorenzo Bianconi, Lachlan Hodges; +Cc: linux-wireless
In-Reply-To: <aa15YDx5G7WN-nsH@lore-desk>
On Sun, 2026-03-08 at 14:28 +0100, Lorenzo Bianconi wrote:
> > > + rcu_read_lock();
> > > + sta = sta_info_get(sdata, sdata->vif.cfg.ap_addr);
> > > + if (sta) {
> > > + unsigned long removed_links = sdata->u.mgd.removed_links;
> > > + unsigned int link_id;
> > > +
> > > + for_each_set_bit(link_id, &removed_links,
> > > + IEEE80211_MLD_MAX_NUM_LINKS)
> > > + ieee80211_sta_free_link(sta, link_id);
> > > + }
> > > + rcu_read_unlock();
> > > +
> >
> > Could use scoped_guard(rcu) instead?
>
> I do not have a strong opinion here.
> @Johannes: Which one do you prefer?
>
To answer the literal question: No strong preference I guess, given that
there's no error path here this seems fine, and the scoped version would
just add another indentation level.
But you really should just remove the rcu_read_lock/unlock anyway, it's
not needed since this holds wiphy mutex, which is sufficient to access
the STA table etc.
Also, I think you need ieee80211_sta_remove_link() to tell the driver?
And I realized another thing - this needs to destroy TDLS stations that
were on the link being removed, but maybe that's a separate commit.
johannes
^ permalink raw reply
* Re: [PATCH 02/14] firmware: qcom: Add a generic PAS service
From: Krzysztof Kozlowski @ 2026-03-09 7:10 UTC (permalink / raw)
To: Sumit Garg
Cc: linux-arm-msm, devicetree, dri-devel, freedreno, linux-media,
netdev, linux-wireless, ath12k, linux-remoteproc, andersson,
konradybcio, robh, krzk+dt, conor+dt, robin.clark, sean, akhilpo,
lumag, abhinav.kumar, jesszhan0024, marijn.suijten, airlied,
simona, vikash.garodia, dikshita.agarwal, bod, mchehab, elder,
andrew+netdev, davem, edumazet, kuba, pabeni, jjohnson,
mathieu.poirier, trilokkumar.soni, mukesh.ojha, pavan.kondeti,
jorge.ramirez, tonyh, vignesh.viswanathan, srinivas.kandagatla,
amirreza.zarrabi, jens.wiklander, op-tee, apurupa, skare,
Sumit Garg
In-Reply-To: <aa5Sw1qcCnD5clth@sumit-xelite>
On 09/03/2026 05:55, Sumit Garg wrote:
> On Fri, Mar 06, 2026 at 12:15:01PM +0100, Krzysztof Kozlowski wrote:
>> On 06/03/2026 11:50, Sumit Garg wrote:
>>> From: Sumit Garg <sumit.garg@oss.qualcomm.com>
>>>
>>> Qcom platforms has the legacy of using non-standard SCM calls
>>> splintered over the various kernel drivers. These SCM calls aren't
>>> compliant with the standard SMC calling conventions which is a
>>> prerequisite to enable migration to the FF-A specifications from
>>> Arm.
>>>
>>> OP-TEE as an alternative trusted OS to QTEE can't support these non-
>>> standard SCM calls. And even for newer architectures QTEE won't be able
>>> to support SCM calls either with FF-A requirements coming in. And with
>>> both OP-TEE and QTEE drivers well integrated in the TEE subsystem, it
>>> makes further sense to reuse the TEE bus client drivers infrastructure.
>>>
>>> The added benefit of TEE bus infrastructure is that there is support
>>> for discoverable/enumerable services. With that client drivers don't
>>> have to manually invoke a special SCM call to know the service status.
>>>
>>> So enable the generic Peripheral Authentication Service (PAS) provided
>>> by the firmware. It acts as the common layer with different TZ
>>> backends plugged in whether it's an SCM implementation or a proper
>>> TEE bus based PAS service implementation.
>>>
>>> Signed-off-by: Sumit Garg <sumit.garg@oss.qualcomm.com>
>>> ---
>>> drivers/firmware/qcom/Kconfig | 8 +
>>> drivers/firmware/qcom/Makefile | 1 +
>>> drivers/firmware/qcom/qcom_pas.c | 295 +++++++++++++++++++++++++
>>> drivers/firmware/qcom/qcom_pas.h | 53 +++++
>>> include/linux/firmware/qcom/qcom_pas.h | 41 ++++
>>> 5 files changed, 398 insertions(+)
>>> create mode 100644 drivers/firmware/qcom/qcom_pas.c
>>> create mode 100644 drivers/firmware/qcom/qcom_pas.h
>>> create mode 100644 include/linux/firmware/qcom/qcom_pas.h
>>>
>>> diff --git a/drivers/firmware/qcom/Kconfig b/drivers/firmware/qcom/Kconfig
>>> index b477d54b495a..8653639d06db 100644
>>> --- a/drivers/firmware/qcom/Kconfig
>>> +++ b/drivers/firmware/qcom/Kconfig
>>> @@ -6,6 +6,14 @@
>>>
>>> menu "Qualcomm firmware drivers"
>>>
>>> +config QCOM_PAS
>>> + tristate
>>> + help
>>> + Enable the generic Peripheral Authentication Service (PAS) provided
>>> + by the firmware. It acts as the common layer with different TZ
>>> + backends plugged in whether it's an SCM implementation or a proper
>>> + TEE bus based PAS service implementation.
>>> +
>>> config QCOM_SCM
>>> select QCOM_TZMEM
>>> tristate
>>> diff --git a/drivers/firmware/qcom/Makefile b/drivers/firmware/qcom/Makefile
>>> index 0be40a1abc13..dc5ab45f906a 100644
>>> --- a/drivers/firmware/qcom/Makefile
>>> +++ b/drivers/firmware/qcom/Makefile
>>> @@ -8,3 +8,4 @@ qcom-scm-objs += qcom_scm.o qcom_scm-smc.o qcom_scm-legacy.o
>>> obj-$(CONFIG_QCOM_TZMEM) += qcom_tzmem.o
>>> obj-$(CONFIG_QCOM_QSEECOM) += qcom_qseecom.o
>>> obj-$(CONFIG_QCOM_QSEECOM_UEFISECAPP) += qcom_qseecom_uefisecapp.o
>>> +obj-$(CONFIG_QCOM_PAS) += qcom_pas.o
>>> diff --git a/drivers/firmware/qcom/qcom_pas.c b/drivers/firmware/qcom/qcom_pas.c
>>> new file mode 100644
>>> index 000000000000..dc04ff1b6be0
>>> --- /dev/null
>>> +++ b/drivers/firmware/qcom/qcom_pas.c
>>> @@ -0,0 +1,295 @@
>>> +// SPDX-License-Identifier: GPL-2.0
>>> +/*
>>> + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
>>> + */
>>> +
>>> +#include <linux/delay.h>
>>> +#include <linux/device/devres.h>
>>> +#include <linux/firmware/qcom/qcom_pas.h>
>>> +#include <linux/of.h>
>>> +#include <linux/kernel.h>
>>> +#include <linux/module.h>
>>> +#include <linux/slab.h>
>>> +
>>> +#include "qcom_pas.h"
>>> +#include "qcom_scm.h"
>>> +
>>> +static struct qcom_pas_ops *ops_ptr;
>>
>> I really dislike this singleton design. And it is not even needed! If
>> you were storing here some allocated instance of SCM/PAS I could
>> understand, but singleton for only ops? Just implement one driver (so
>> SCM + whatever you have here) which will decide which ops to use,
>> through the probe. Really, this is neither needed nor beneficial.
>
> The motivation here is rather quite opposite to the single monolithic
> SCM driver design. The TZ services like PAS, ICE and so on are going to
> be implemented as independent discoverable devices on TEE bus which
> rather needs independent kernel client drivers.
You still have singleton here. So if you think you do opposite to
singleton, then drop this static.
>
> Also, the single driver probe can't work here since the SCM driver is
> bound to the platform bus whereas the TEE PAS driver is bound to the TEE
> bus. So there is a reason for the current design.
>
>>
>> It actually leads to more problems with this barrier handling, see
>> further comments.
>
> The barrier handling is something that I carried over from existing
> implmentation but I can't see a reason why it can't be replaced with a
> simple mutex. See diff below for mutex.
>
>> ...
>>
>>> +
>>> +/**
>>> + * qcom_pas_shutdown() - Shut down the remote processor
>>> + * @pas_id: peripheral authentication service id
>>> + *
>>> + * Returns 0 on success.
>>> + */
>>> +int qcom_pas_shutdown(u32 pas_id)
>>> +{
>>> + if (ops_ptr)
>>> + return ops_ptr->shutdown(ops_ptr->dev, pas_id);
>>> +
>>> + return -ENODEV;
>>> +}
>>> +EXPORT_SYMBOL_GPL(qcom_pas_shutdown);
>>> +
>>> +/**
>>> + * qcom_pas_supported() - Check if the peripheral authentication service is
>>> + * available for the given peripheral
>>> + * @pas_id: peripheral authentication service id
>>> + *
>>> + * Returns true if PAS is supported for this peripheral, otherwise false.
>>> + */
>>> +bool qcom_pas_supported(u32 pas_id)
>>> +{
>>> + if (ops_ptr)
>>
>> Lack of barriers here is not looking right. Existing/old code is not a
>> good example, I fixed only the obvious issue, but new code should be
>> correct from the beginning.
>>
>> Barriers should normally be always paired, unless you have some clear
>> path no concurrent execution can happen here, but such explanation is
>> missing, look:
>
> Actually concurrent execution is rather required here since TZ can
> support parallel bring-up of co-processors. The synchonization is only
> needed when PAS client drivers are performing a deferred probe waiting
> for the service to be available. However, you are right explanation is
> missing here which I will add in the next version.
Hm? Existing comments are completely useless. Your comment said just
"barrier" basically... That's nothing useful.
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH wireless-next 14/35] wifi: mm81x: add mac.c
From: Johannes Berg @ 2026-03-09 7:08 UTC (permalink / raw)
To: Lachlan Hodges
Cc: Dan Callaghan, Arien Judge, Nathan Chancellor, Nick Desaulniers,
Bill Wendling, Justin Stitt, ayman.grais, linux-wireless,
linux-kernel
In-Reply-To: <vttdls7sm4h3br7y5kcea5i4teqnuiuzgq3miswg6r45asvng7@jto3tksuvofj>
On Mon, 2026-03-09 at 15:43 +1100, Lachlan Hodges wrote:
> > 2) Are you going to incur the wrath of mm/ folks, where instances of
> > 'struct mm_struct' are commonly called 'mm'? I can find a few
> > examples of others (struct drm_buddy *mm, struct mqd_manager *mm),
> > but you'd double the instances.
>
> This.. is definitely something I did not think of. I have no issue with
> renaming to something else.. maybe mx? I'm not sure.
Yeah I really don't know. There's no 'mm->lock' (any more? for some
reason _that_ was what caught my eye wrt. the naming) in mm/, and I
guess soon also not in your driver. I'll try to ask around, but it's
probably safer to rename, and shouldn't be _that_ hard with spatch I
guess. I guess 'mx' seems reasonable, 'mmx' is also confusing perhaps,
and 'mm81x' doesn't lend itself to obvious other abbreviations.
> > > + /*
> > > + * mm81x only support changing/setting the channel
> > > + * when we create an interface.
> > > + */
> > > + if (WARN_ON(changed & IEEE80211_CHANCTX_CHANGE_CHANNEL))
> > > + mm81x_err(mm, "Changing channel via chanctx not supported");
> >
> > Wait, what, why do you have chanctx support then? This seems highly
> > questionable, how do you not run into this all the time?
> >
> > If it just has a single, wouldn't the chanctx emulation suit the driver
> > better, and that'd make this more obvious? Hmm, but you _do_ support
> > multiple vifs? I'm confused.
>
> We originally used chanctx emulation.. but I suppose in an effort to
> be "modern" we use chanctx. It's probably best to switch back to the
> chanctx emulation anyway. As for why we don't run into this is due
> to no channel switch support yet, iirc mac80211 I think needs a minor
> tweak to work with S1G (which further reinforces the idea that we
> should just emulate chanctx)
I don't mind the emulation _that_ much to force drivers into some
unnatural scheme for them :) This seems even more confusing and
unexpected than the emulation perhaps.
But I don't want to impose here either.
> Thanks for the review. On the other thread [1] you mentioned sending a
> pull request once reviews settle down, as per the documentation in [2]
> (which I should have read earlier... :) ),
Heh, I didn't really know we had that document either, Kalle did all
that :)
> can we confirm that this means
> we are to submit subsequent patchset revisions in the same per-file
> format until everyone is happy with the driver, and then raise the PR?
I wouldn't necessarily way _everyone_, you can probably always find
someone willing to nitpick if you look hard enough ;-)
But yeah, I don't think you have a choice for how to post, the whole
driver as one patch would not really even load well in an email client I
guess, let alone make it possible to comment on easily.
As I said there, for the merge I'd prefer just a single commit as a pull
request.
Obviously I hope/expect you're going to continue to maintaining the
driver and we'll have to figure out the workflow for that - perhaps
depending on how much work you're planning to put into it.
johannes
^ permalink raw reply
* Re: [PATCH] wifi: mac80211: fix monitor mode frame capture for real chanctx drivers
From: Johannes Berg @ 2026-03-09 6:53 UTC (permalink / raw)
To: 傅继晗
Cc: linux-wireless, linux-kernel, stable,
Óscar Alfonso Díaz
In-Reply-To: <20260308164510.5927-1-fjhhz1997@gmail.com>
On Sun, 2026-03-08 at 16:45 +0000, 傅继晗 wrote:
> Commit 0a44dfc07074 ("wifi: mac80211: simplify non-chanctx drivers")
> removed the fallback path in ieee80211_monitor_start_xmit() for when
> the monitor interface has no channel context assigned. This broke frame
> capture and injection for drivers that implement real channel context
> ops (as opposed to the ieee80211_emulate_* helpers), such as the mt76
> family, when a monitor interface runs alongside another interface
> (e.g. managed mode).
It actually broke the others too, as you note later.
> In that scenario the (virtual) monitor sdata does not get a chanctx of
> its own, even though there is an active one from the other interface.
> Before the simplification the code fell back to local->_oper_chandef;
> after it, the code goes straight to fail_rcu and silently drops every
> injected frame.
>
> Commit d594cc6f2c58 ("wifi: mac80211: restore non-chanctx injection
> behaviour") restored the fallback for drivers using emulate_chanctx,
> but explicitly left real chanctx drivers unfixed.
>
> Fix this by falling back to the first entry in local->chanctx_list
> when the monitor vif has no chanctx and the driver uses real channel
> contexts. This is analogous to how ieee80211_hw_conf_chan() already
> uses the same pattern.
I did have pretty much the same attempt at a fix:
https://lore.kernel.org/linux-wireless/20251216111909.25076-2-johannes@sipsolutions.net/
but it was reported to cause crashes on certain devices, so we didn't
think it was very safe at the time.
Is that no longer an issue?
johannes
^ permalink raw reply
* Re: [PATCH 1/2] mt76: connac: fix txpower_cur not updated in mt76_connac_mcu_set_rate_txpower()
From: Sean Wang @ 2026-03-09 6:42 UTC (permalink / raw)
To: bryam vargas
Cc: linux-wireless, nbd, lorenzo,
moderated list:ARM/Mediatek SoC support
In-Reply-To: <CANAPQzi3BkfnRS4CEXAA560O5cO8e6MEYxeVVx1u+xUeXS-gmA@mail.gmail.com>
Hi,
On Fri, Feb 27, 2026 at 3:53 AM bryam vargas
<bryamestebanvargas@gmail.com> wrote:
>
> From 0a29ccaeb2211451b88ad71c4c0cdbc418b7d64d Mon Sep 17 00:00:00 2001
> From: bryam <bryamestebanvargas@gmail.com>
> Date: Fri, 27 Feb 2026 04:30:01 -0500
> Subject: [PATCH 1/2] mt76: connac: fix txpower_cur not updated in
> mt76_connac_mcu_set_rate_txpower()
>
> mt76_connac_mcu_set_rate_txpower() sends the TX power SKU table to the
> firmware but never updates mphy->txpower_cur. This causes mt76_get_txpower()
> to always report 3 dBm regardless of the actual configured power level,
> since txpower_cur remains at its zero-initialized value and only the
> path delta for 2 chains (6 units of 0.5 dBm) gets applied.
>
> Fix this by calculating the effective TX power using the same approach
> as mt7915: mt76_get_power_bound() applies SAR constraints and chain
> delta, then mt76_get_rate_power_limits() applies the per-rate EEPROM
> limits, yielding the actual value the firmware will use.
I wonder if this would fit better in .get_txpower instead.
mt76_connac_mcu_set_rate_txpower() is primarily a programming path
that pushes the SKU table to firmware. Updating txpower_cur there
mixes write-side configuration with reporting logic.
It might be cleaner to handle this in .get_txpower with an
mt7921-specific callback that derives the reported TX power from the
SKU limits instead of updating the cached value in the write path.
>
> Fixes: 3b4a3bdba808 ("mt76: mt7921: add support for reporting tx power")
> Signed-off-by: Bryam Vargas <bryamestebanvargas@gmail.com>
> ---
> .../net/wireless/mediatek/mt76/mt76_connac_mcu.c | 14 ++++++++++++++
> 1 file changed, 14 insertions(+)
>
> diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
> b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
> index fc3e672..4ed31ff 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
> @@ -2272,6 +2272,20 @@ int mt76_connac_mcu_set_rate_txpower(struct
> mt76_phy *phy)
> return err;
> }
>
> + /* Update txpower_cur so mt76_get_txpower() reports the actual
> + * configured TX power instead of always returning 3 dBm due to
> + * txpower_cur being left at its zero-initialized value.
> + * The value is stored in 0.5 dBm units as used by the SKU table.
> + */
> + if (phy->chandef.chan) {
> + struct mt76_power_limits limits;
> + s8 tx_power;
> +
> + tx_power = mt76_get_power_bound(phy, phy->chandef.chan->max_power);
> + tx_power = mt76_get_rate_power_limits(phy, phy->chandef.chan,
> + &limits, tx_power);
> + phy->txpower_cur = tx_power;
> + }
> return 0;
> }
> EXPORT_SYMBOL_GPL(mt76_connac_mcu_set_rate_txpower);
> --
> 2.43.0
>
^ permalink raw reply
* Re: [PATCH 02/14] firmware: qcom: Add a generic PAS service
From: Sumit Garg @ 2026-03-09 6:36 UTC (permalink / raw)
To: Jeff Johnson
Cc: Trilok Soni, linux-arm-msm, devicetree, dri-devel, freedreno,
linux-media, netdev, linux-wireless, ath12k, linux-remoteproc,
andersson, konradybcio, robh, krzk+dt, conor+dt, robin.clark,
sean, akhilpo, lumag, abhinav.kumar, jesszhan0024, marijn.suijten,
airlied, simona, vikash.garodia, dikshita.agarwal, bod, mchehab,
elder, andrew+netdev, davem, edumazet, kuba, pabeni, jjohnson,
mathieu.poirier, mukesh.ojha, pavan.kondeti, jorge.ramirez, tonyh,
vignesh.viswanathan, srinivas.kandagatla, amirreza.zarrabi,
jens.wiklander, op-tee, apurupa, skare, Sumit Garg
In-Reply-To: <13091f47-938d-43fb-a8c0-4b081818b557@oss.qualcomm.com>
On Fri, Mar 06, 2026 at 02:00:48PM -0800, Jeff Johnson wrote:
> On 3/6/2026 11:47 AM, Trilok Soni wrote:
> > On 3/6/2026 2:50 AM, Sumit Garg wrote:
> >> +MODULE_LICENSE("GPL");
> >> +MODULE_AUTHOR("Sumit Garg <sumit.garg@oss.qualcomm.com>");
> >
> > What is the convention for Qualcomm authored drivers? In some drivers
> > I find that Qualcomm doesn't add MODULE_AUTHOR. Can Qualcomm community
> > clarify it here. I prefer consistency here for the Qualcomm submissions.
>
> WLAN team was told to not have MODULE_AUTHOR(), so ath10k was the last WLAN
> driver that had a MODULE_AUTHOR() -- ath11k and ath12k do not have one.
As I said in my other reply, it is quite subsystem specific.
>
> And in reality it is very rare for a given module, over time, to only have a
> single author. The git history contains the real authorship. So just for that
> reason I'd drop it.
Sure, but you would like the driver author to be involved in future
maintenence of the driver. In my experience that's how usually the kernel
development process works. If a separate maintainer's entry is fine then I
can switch to that instead.
-Sumit
^ permalink raw reply
* Re: [PATCH v2 00/18] wifi: drop redundant USB device references
From: Johannes Berg @ 2026-03-09 6:27 UTC (permalink / raw)
To: Jeff Johnson, Johan Hovold, linux-wireless
Cc: Jeff Johnson, Toke Høiland-Jørgensen, Brian Norris,
Francesco Dolcini, Felix Fietkau, Lorenzo Bianconi, Ryder Lee,
Shayne Chen, Sean Wang, Jakub Kicinski, Stanislaw Gruszka,
Hin-Tak Leung, Jes Sorensen, Ping-Ke Shih, Nicolas Ferre,
Alexandre Belloni, Claudiu Beznea, Matthias Brugger,
AngeloGioacchino Del Regno, Greg Kroah-Hartman, libertas-dev,
linux-kernel
In-Reply-To: <beaed1d8-6c51-4aef-9fd7-00d9646db948@oss.qualcomm.com>
On Fri, 2026-03-06 at 13:39 -0800, Jeff Johnson wrote:
>
> Johannes, will you be taking the entire series via wireless-next?
>
> Or should the individual wireless driver maintainers take their patches
> through their individual trees? I'm OK either way.
So far I took the ones patchwork had auto-assigned to me. I can take
others though, no particular preference, but I guess I already pulled
the series apart anyway.
Let's just say if you want me to take any, assign them to me in
patchwork.
johannes
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox