summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBjoern A. Zeeb <bz@FreeBSD.org>2026-04-13 22:25:41 +0000
committerBjoern A. Zeeb <bz@FreeBSD.org>2026-04-13 22:25:41 +0000
commitbbc9d102496a6ee93c55d32a9ce40d2f737fc9e7 (patch)
treee7dc0bb81dec3af67dc8337addd7987fbb224df5
parent91a3131f2f8e4db6b8b7999fed893ff2bedb0d2d (diff)
-rw-r--r--ce.c12
-rw-r--r--htt_rx.c3
-rw-r--r--mac.c10
-rw-r--r--qmi.c10
-rw-r--r--sdio.c10
-rw-r--r--snoc.c53
-rw-r--r--snoc.h3
-rw-r--r--txrx.c2
-rw-r--r--usb.c2
-rw-r--r--wmi-tlv.c10
-rw-r--r--wmi.c32
-rw-r--r--wow.c4
12 files changed, 100 insertions, 51 deletions
diff --git a/ce.c b/ce.c
index 82f120ee1c66..a9cbe955e084 100644
--- a/ce.c
+++ b/ce.c
@@ -1461,8 +1461,7 @@ ath10k_ce_alloc_src_ring(struct ath10k *ar, unsigned int ce_id,
nentries = roundup_pow_of_two(nentries);
- src_ring = kzalloc(struct_size(src_ring, per_transfer_context,
- nentries), GFP_KERNEL);
+ src_ring = kzalloc_flex(*src_ring, per_transfer_context, nentries);
if (src_ring == NULL)
return ERR_PTR(-ENOMEM);
@@ -1519,8 +1518,7 @@ ath10k_ce_alloc_src_ring_64(struct ath10k *ar, unsigned int ce_id,
nentries = roundup_pow_of_two(nentries);
- src_ring = kzalloc(struct_size(src_ring, per_transfer_context,
- nentries), GFP_KERNEL);
+ src_ring = kzalloc_flex(*src_ring, per_transfer_context, nentries);
if (!src_ring)
return ERR_PTR(-ENOMEM);
@@ -1575,8 +1573,7 @@ ath10k_ce_alloc_dest_ring(struct ath10k *ar, unsigned int ce_id,
nentries = roundup_pow_of_two(attr->dest_nentries);
- dest_ring = kzalloc(struct_size(dest_ring, per_transfer_context,
- nentries), GFP_KERNEL);
+ dest_ring = kzalloc_flex(*dest_ring, per_transfer_context, nentries);
if (dest_ring == NULL)
return ERR_PTR(-ENOMEM);
@@ -1619,8 +1616,7 @@ ath10k_ce_alloc_dest_ring_64(struct ath10k *ar, unsigned int ce_id,
nentries = roundup_pow_of_two(attr->dest_nentries);
- dest_ring = kzalloc(struct_size(dest_ring, per_transfer_context,
- nentries), GFP_KERNEL);
+ dest_ring = kzalloc_flex(*dest_ring, per_transfer_context, nentries);
if (!dest_ring)
return ERR_PTR(-ENOMEM);
diff --git a/htt_rx.c b/htt_rx.c
index d7e429041065..25ab945fecef 100644
--- a/htt_rx.c
+++ b/htt_rx.c
@@ -807,8 +807,7 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt)
}
htt->rx_ring.netbufs_ring =
- kcalloc(htt->rx_ring.size, sizeof(struct sk_buff *),
- GFP_KERNEL);
+ kzalloc_objs(struct sk_buff *, htt->rx_ring.size);
if (!htt->rx_ring.netbufs_ring)
goto err_netbuf;
diff --git a/mac.c b/mac.c
index da6f7957a0ae..8e604697d6c2 100644
--- a/mac.c
+++ b/mac.c
@@ -6431,7 +6431,7 @@ static int ath10k_hw_scan(struct ieee80211_hw *hw,
if (ret)
goto exit;
- arg = kzalloc(sizeof(*arg), GFP_KERNEL);
+ arg = kzalloc_obj(*arg);
if (!arg) {
ret = -ENOMEM;
goto exit;
@@ -7559,8 +7559,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
}
if (ath10k_debug_is_extd_tx_stats_enabled(ar)) {
- arsta->tx_stats = kzalloc(sizeof(*arsta->tx_stats),
- GFP_KERNEL);
+ arsta->tx_stats = kzalloc_obj(*arsta->tx_stats);
if (!arsta->tx_stats) {
ath10k_mac_dec_num_stations(arvif, sta);
ret = -ENOMEM;
@@ -7972,7 +7971,7 @@ static int ath10k_remain_on_channel(struct ieee80211_hw *hw,
scan_time_msec = ar->hw->wiphy->max_remain_on_channel_duration * 2;
- arg = kzalloc(sizeof(*arg), GFP_KERNEL);
+ arg = kzalloc_obj(*arg);
if (!arg) {
ret = -ENOMEM;
goto exit;
@@ -8954,8 +8953,7 @@ ath10k_mac_op_change_chanctx(struct ieee80211_hw *hw,
if (arg.n_vifs == 0)
goto radar;
- arg.vifs = kcalloc(arg.n_vifs, sizeof(arg.vifs[0]),
- GFP_KERNEL);
+ arg.vifs = kzalloc_objs(arg.vifs[0], arg.n_vifs);
if (!arg.vifs)
goto radar;
diff --git a/qmi.c b/qmi.c
index 8275345631a0..eebd78e7ff6b 100644
--- a/qmi.c
+++ b/qmi.c
@@ -245,7 +245,7 @@ static int ath10k_qmi_bdf_dnld_send_sync(struct ath10k_qmi *qmi)
const u8 *temp;
int ret;
- req = kzalloc(sizeof(*req), GFP_KERNEL);
+ req = kzalloc_obj(*req);
if (!req)
return -ENOMEM;
@@ -437,7 +437,7 @@ ath10k_qmi_cfg_send_sync_msg(struct ath10k *ar,
int ret;
u32 i;
- req = kzalloc(sizeof(*req), GFP_KERNEL);
+ req = kzalloc_obj(*req);
if (!req)
return -ENOMEM;
@@ -578,7 +578,7 @@ static int ath10k_qmi_cap_send_sync_msg(struct ath10k_qmi *qmi)
struct qmi_txn txn;
int ret;
- resp = kzalloc(sizeof(*resp), GFP_KERNEL);
+ resp = kzalloc_obj(*resp);
if (!resp)
return -ENOMEM;
@@ -877,7 +877,7 @@ ath10k_qmi_driver_event_post(struct ath10k_qmi *qmi,
{
struct ath10k_qmi_driver_event *event;
- event = kzalloc(sizeof(*event), GFP_ATOMIC);
+ event = kzalloc_obj(*event, GFP_ATOMIC);
if (!event)
return -ENOMEM;
@@ -1075,7 +1075,7 @@ int ath10k_qmi_init(struct ath10k *ar, u32 msa_size)
struct ath10k_qmi *qmi;
int ret;
- qmi = kzalloc(sizeof(*qmi), GFP_KERNEL);
+ qmi = kzalloc_obj(*qmi);
if (!qmi)
return -ENOMEM;
diff --git a/sdio.c b/sdio.c
index c06d50db40b8..43a6b1ba8fb8 100644
--- a/sdio.c
+++ b/sdio.c
@@ -246,7 +246,7 @@ static int ath10k_sdio_writesb32(struct ath10k *ar, u32 addr, u32 val)
__le32 *buf;
int ret;
- buf = kzalloc(sizeof(*buf), GFP_KERNEL);
+ buf = kzalloc_obj(*buf);
if (!buf)
return -ENOMEM;
@@ -1766,7 +1766,7 @@ static int ath10k_sdio_diag_read32(struct ath10k *ar, u32 address,
__le32 *val;
int ret;
- val = kzalloc(sizeof(*val), GFP_KERNEL);
+ val = kzalloc_obj(*val);
if (!val)
return -ENOMEM;
@@ -2487,7 +2487,11 @@ void ath10k_sdio_fw_crashed_dump(struct ath10k *ar)
if (fast_dump)
ath10k_bmi_start(ar);
+ mutex_lock(&ar->dump_mutex);
+
+ spin_lock_bh(&ar->data_lock);
ar->stats.fw_crash_counter++;
+ spin_unlock_bh(&ar->data_lock);
ath10k_sdio_disable_intrs(ar);
@@ -2505,6 +2509,8 @@ void ath10k_sdio_fw_crashed_dump(struct ath10k *ar)
ath10k_sdio_enable_intrs(ar);
+ mutex_unlock(&ar->dump_mutex);
+
ath10k_core_start_recovery(ar);
}
diff --git a/snoc.c b/snoc.c
index b3f6424c17d3..f72f236fb9eb 100644
--- a/snoc.c
+++ b/snoc.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: ISC
/*
* Copyright (c) 2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <linux/bits.h>
@@ -11,6 +12,7 @@
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/property.h>
+#include <linux/pwrseq/consumer.h>
#include <linux/regulator/consumer.h>
#include <linux/remoteproc/qcom_rproc.h>
#include <linux/of_reserved_mem.h>
@@ -1023,10 +1025,14 @@ static int ath10k_hw_power_on(struct ath10k *ar)
ath10k_dbg(ar, ATH10K_DBG_SNOC, "soc power on\n");
- ret = regulator_bulk_enable(ar_snoc->num_vregs, ar_snoc->vregs);
+ ret = pwrseq_power_on(ar_snoc->pwrseq);
if (ret)
return ret;
+ ret = regulator_bulk_enable(ar_snoc->num_vregs, ar_snoc->vregs);
+ if (ret)
+ goto pwrseq_off;
+
ret = clk_bulk_prepare_enable(ar_snoc->num_clks, ar_snoc->clks);
if (ret)
goto vreg_off;
@@ -1035,18 +1041,28 @@ static int ath10k_hw_power_on(struct ath10k *ar)
vreg_off:
regulator_bulk_disable(ar_snoc->num_vregs, ar_snoc->vregs);
+pwrseq_off:
+ pwrseq_power_off(ar_snoc->pwrseq);
+
return ret;
}
static int ath10k_hw_power_off(struct ath10k *ar)
{
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
+ int ret_seq = 0;
+ int ret_vreg;
ath10k_dbg(ar, ATH10K_DBG_SNOC, "soc power off\n");
clk_bulk_disable_unprepare(ar_snoc->num_clks, ar_snoc->clks);
- return regulator_bulk_disable(ar_snoc->num_vregs, ar_snoc->vregs);
+ ret_vreg = regulator_bulk_disable(ar_snoc->num_vregs, ar_snoc->vregs);
+
+ if (ar_snoc->pwrseq)
+ ret_seq = pwrseq_power_off(ar_snoc->pwrseq);
+
+ return ret_vreg ? : ret_seq;
}
static void ath10k_snoc_wlan_disable(struct ath10k *ar)
@@ -1762,7 +1778,38 @@ static int ath10k_snoc_probe(struct platform_device *pdev)
goto err_release_resource;
}
- ar_snoc->num_vregs = ARRAY_SIZE(ath10k_regulators);
+ /*
+ * devm_pwrseq_get() can return -EPROBE_DEFER in two cases:
+ * - it is not supposed to be used
+ * - it is supposed to be used, but the driver hasn't probed yet.
+ *
+ * There is no simple way to distinguish between these two cases, but:
+ * - if it is not supposed to be used, then regulator_bulk_get() will
+ * return all regulators as expected, continuing the probe
+ * - if it is supposed to be used, but wasn't probed yet, we will get
+ * -EPROBE_DEFER from regulator_bulk_get() too.
+ *
+ * For backwards compatibility with DTs specifying regulators directly
+ * rather than using the PMU device, ignore the defer error from
+ * pwrseq.
+ */
+ ar_snoc->pwrseq = devm_pwrseq_get(&pdev->dev, "wlan");
+ if (IS_ERR(ar_snoc->pwrseq)) {
+ ret = PTR_ERR(ar_snoc->pwrseq);
+ ar_snoc->pwrseq = NULL;
+ if (ret != -EPROBE_DEFER)
+ goto err_free_irq;
+
+ ar_snoc->num_vregs = ARRAY_SIZE(ath10k_regulators);
+ } else {
+ /*
+ * The first regulator (vdd-0.8-cx-mx) is used to power on part
+ * of the SoC rather than the PMU on WCN399x, the rest are
+ * handled via pwrseq.
+ */
+ ar_snoc->num_vregs = 1;
+ }
+
ar_snoc->vregs = devm_kcalloc(&pdev->dev, ar_snoc->num_vregs,
sizeof(*ar_snoc->vregs), GFP_KERNEL);
if (!ar_snoc->vregs) {
diff --git a/snoc.h b/snoc.h
index d4bce1707696..1ecae34687c2 100644
--- a/snoc.h
+++ b/snoc.h
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: ISC */
/*
* Copyright (c) 2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#ifndef _SNOC_H_
@@ -53,6 +54,7 @@ enum ath10k_snoc_flags {
};
struct clk_bulk_data;
+struct pwrseq_desc;
struct regulator_bulk_data;
struct ath10k_snoc {
@@ -73,6 +75,7 @@ struct ath10k_snoc {
struct ath10k_snoc_ce_irq ce_irqs[CE_COUNT_MAX];
struct ath10k_ce ce;
struct timer_list rx_post_retry;
+ struct pwrseq_desc *pwrseq;
struct regulator_bulk_data *vregs;
size_t num_vregs;
struct clk_bulk_data *clks;
diff --git a/txrx.c b/txrx.c
index 493bfb410aff..50a3498a0bfd 100644
--- a/txrx.c
+++ b/txrx.c
@@ -230,7 +230,7 @@ void ath10k_peer_map_event(struct ath10k_htt *htt,
spin_lock_bh(&ar->data_lock);
peer = ath10k_peer_find(ar, ev->vdev_id, ev->addr);
if (!peer) {
- peer = kzalloc(sizeof(*peer), GFP_ATOMIC);
+ peer = kzalloc_obj(*peer, GFP_ATOMIC);
if (!peer)
goto exit;
diff --git a/usb.c b/usb.c
index 1732a4f98418..6661fff326e0 100644
--- a/usb.c
+++ b/usb.c
@@ -799,7 +799,7 @@ static int ath10k_usb_alloc_pipe_resources(struct ath10k *ar,
init_usb_anchor(&pipe->urb_submitted);
for (i = 0; i < urb_cnt; i++) {
- urb_context = kzalloc(sizeof(*urb_context), GFP_KERNEL);
+ urb_context = kzalloc_obj(*urb_context);
if (!urb_context)
return -ENOMEM;
diff --git a/wmi-tlv.c b/wmi-tlv.c
index 16d07d619b4d..ec8e91707f84 100644
--- a/wmi-tlv.c
+++ b/wmi-tlv.c
@@ -145,7 +145,7 @@ ath10k_wmi_tlv_parse_alloc(struct ath10k *ar, const void *ptr,
const void **tb;
int ret;
- tb = kcalloc(WMI_TLV_TAG_MAX, sizeof(*tb), gfp);
+ tb = kzalloc_objs(*tb, WMI_TLV_TAG_MAX, gfp);
if (!tb)
return ERR_PTR(-ENOMEM);
@@ -1546,7 +1546,7 @@ static int ath10k_wmi_tlv_op_pull_fw_stats(struct ath10k *ar,
data += sizeof(*src);
data_len -= sizeof(*src);
- dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
+ dst = kzalloc_obj(*dst, GFP_ATOMIC);
if (!dst)
continue;
@@ -1569,7 +1569,7 @@ static int ath10k_wmi_tlv_op_pull_fw_stats(struct ath10k *ar,
data += sizeof(*src);
data_len -= sizeof(*src);
- dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
+ dst = kzalloc_obj(*dst, GFP_ATOMIC);
if (!dst)
continue;
@@ -1590,7 +1590,7 @@ static int ath10k_wmi_tlv_op_pull_fw_stats(struct ath10k *ar,
data += sizeof(*src);
data_len -= sizeof(*src);
- dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
+ dst = kzalloc_obj(*dst, GFP_ATOMIC);
if (!dst)
continue;
@@ -3063,7 +3063,7 @@ ath10k_wmi_mgmt_tx_alloc_msdu_id(struct ath10k *ar, struct sk_buff *skb,
struct ath10k_mgmt_tx_pkt_addr *pkt_addr;
int ret;
- pkt_addr = kmalloc(sizeof(*pkt_addr), GFP_ATOMIC);
+ pkt_addr = kmalloc_obj(*pkt_addr, GFP_ATOMIC);
if (!pkt_addr)
return -ENOMEM;
diff --git a/wmi.c b/wmi.c
index b4aad6604d6d..0bdb38edd915 100644
--- a/wmi.c
+++ b/wmi.c
@@ -3046,7 +3046,7 @@ static int ath10k_wmi_main_op_pull_fw_stats(struct ath10k *ar,
if (!skb_pull(skb, sizeof(*src)))
return -EPROTO;
- dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
+ dst = kzalloc_obj(*dst, GFP_ATOMIC);
if (!dst)
continue;
@@ -3067,7 +3067,7 @@ static int ath10k_wmi_main_op_pull_fw_stats(struct ath10k *ar,
if (!skb_pull(skb, sizeof(*src)))
return -EPROTO;
- dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
+ dst = kzalloc_obj(*dst, GFP_ATOMIC);
if (!dst)
continue;
@@ -3100,7 +3100,7 @@ static int ath10k_wmi_10x_op_pull_fw_stats(struct ath10k *ar,
if (!skb_pull(skb, sizeof(*src)))
return -EPROTO;
- dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
+ dst = kzalloc_obj(*dst, GFP_ATOMIC);
if (!dst)
continue;
@@ -3122,7 +3122,7 @@ static int ath10k_wmi_10x_op_pull_fw_stats(struct ath10k *ar,
if (!skb_pull(skb, sizeof(*src)))
return -EPROTO;
- dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
+ dst = kzalloc_obj(*dst, GFP_ATOMIC);
if (!dst)
continue;
@@ -3161,7 +3161,7 @@ static int ath10k_wmi_10_2_op_pull_fw_stats(struct ath10k *ar,
if (!skb_pull(skb, sizeof(*src)))
return -EPROTO;
- dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
+ dst = kzalloc_obj(*dst, GFP_ATOMIC);
if (!dst)
continue;
@@ -3198,7 +3198,7 @@ static int ath10k_wmi_10_2_op_pull_fw_stats(struct ath10k *ar,
if (!skb_pull(skb, sizeof(*src)))
return -EPROTO;
- dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
+ dst = kzalloc_obj(*dst, GFP_ATOMIC);
if (!dst)
continue;
@@ -3238,7 +3238,7 @@ static int ath10k_wmi_10_2_4_op_pull_fw_stats(struct ath10k *ar,
if (!skb_pull(skb, sizeof(*src)))
return -EPROTO;
- dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
+ dst = kzalloc_obj(*dst, GFP_ATOMIC);
if (!dst)
continue;
@@ -3281,7 +3281,7 @@ static int ath10k_wmi_10_2_4_op_pull_fw_stats(struct ath10k *ar,
if (!skb_pull(skb, stats_len))
return -EPROTO;
- dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
+ dst = kzalloc_obj(*dst, GFP_ATOMIC);
if (!dst)
continue;
@@ -3330,7 +3330,7 @@ static int ath10k_wmi_10_4_op_pull_fw_stats(struct ath10k *ar,
if (!skb_pull(skb, sizeof(*src)))
return -EPROTO;
- dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
+ dst = kzalloc_obj(*dst, GFP_ATOMIC);
if (!dst)
continue;
@@ -3376,7 +3376,7 @@ static int ath10k_wmi_10_4_op_pull_fw_stats(struct ath10k *ar,
if (!skb_pull(skb, sizeof(*src)))
return -EPROTO;
- dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
+ dst = kzalloc_obj(*dst, GFP_ATOMIC);
if (!dst)
continue;
@@ -3409,7 +3409,7 @@ static int ath10k_wmi_10_4_op_pull_fw_stats(struct ath10k *ar,
if (!skb_pull(skb, sizeof(*src)))
return -EPROTO;
- dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
+ dst = kzalloc_obj(*dst, GFP_ATOMIC);
if (!dst)
continue;
@@ -3429,7 +3429,7 @@ static int ath10k_wmi_10_4_op_pull_fw_stats(struct ath10k *ar,
if (!skb_pull(skb, sizeof(*src)))
return -EPROTO;
- dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
+ dst = kzalloc_obj(*dst, GFP_ATOMIC);
if (!dst)
continue;
ath10k_wmi_10_4_pull_vdev_stats(src, dst);
@@ -4912,7 +4912,7 @@ void ath10k_wmi_event_pdev_tpc_config(struct ath10k *ar, struct sk_buff *skb)
rate_max = WMI_TPC_RATE_MAX;
}
- tpc_stats = kzalloc(sizeof(*tpc_stats), GFP_ATOMIC);
+ tpc_stats = kzalloc_obj(*tpc_stats, GFP_ATOMIC);
if (!tpc_stats)
return;
@@ -5168,7 +5168,7 @@ void ath10k_wmi_event_tpc_final_table(struct ath10k *ar, struct sk_buff *skb)
rate_max = WMI_TPC_FINAL_RATE_MAX;
}
- tpc_stats = kzalloc(sizeof(*tpc_stats), GFP_ATOMIC);
+ tpc_stats = kzalloc_obj(*tpc_stats, GFP_ATOMIC);
if (!tpc_stats)
return;
@@ -5289,8 +5289,6 @@ ath10k_wmi_event_peer_sta_ps_state_chg(struct ath10k *ar, struct sk_buff *skb)
struct ath10k_sta *arsta;
u8 peer_addr[ETH_ALEN];
- lockdep_assert_held(&ar->data_lock);
-
ev = (struct wmi_peer_sta_ps_state_chg_event *)skb->data;
ether_addr_copy(peer_addr, ev->peer_macaddr.addr);
@@ -5305,7 +5303,9 @@ ath10k_wmi_event_peer_sta_ps_state_chg(struct ath10k *ar, struct sk_buff *skb)
}
arsta = (struct ath10k_sta *)sta->drv_priv;
+ spin_lock_bh(&ar->data_lock);
arsta->peer_ps_state = __le32_to_cpu(ev->peer_ps_state);
+ spin_unlock_bh(&ar->data_lock);
exit:
rcu_read_unlock();
diff --git a/wow.c b/wow.c
index aa7b2e703f3d..78653f257925 100644
--- a/wow.c
+++ b/wow.c
@@ -301,7 +301,7 @@ static int ath10k_vif_wow_set_wakeups(struct ath10k_vif *arvif,
struct wmi_pno_scan_req *pno;
int ret;
- pno = kzalloc(sizeof(*pno), GFP_KERNEL);
+ pno = kzalloc_obj(*pno);
if (!pno)
return -ENOMEM;
@@ -413,7 +413,7 @@ static int ath10k_vif_wow_clean_nlo(struct ath10k_vif *arvif)
if (ar->nlo_enabled) {
struct wmi_pno_scan_req *pno;
- pno = kzalloc(sizeof(*pno), GFP_KERNEL);
+ pno = kzalloc_obj(*pno);
if (!pno)
return -ENOMEM;