summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2026-04-08 09:34:51 +0300
committerJohannes Berg <johannes.berg@intel.com>2026-04-08 09:35:27 +0300
commitc9b7f640426ca0fbaa506df13feabfc5b05bf071 (patch)
treebcf3d0fe24c9a239f5e8958a11fae359f28812ac
parente801194b604cd9fdb24c2958892fd79e1aa3b651 (diff)
parent8fb66931fe31094aa2e1b2a5c015050b8b4cb2ec (diff)
downloadlinux-c9b7f640426ca0fbaa506df13feabfc5b05bf071.tar.xz
Merge tag 'ath-next-20260407' of git://git.kernel.org/pub/scm/linux/kernel/git/ath/ath
Jeff Johnson says: ================== ath.git patches for v7.1 (PR #3) Add ath12k support for IPQ5424. And of course there is the usual set of cleanups and bug fixes touching the ath10k and ath12k drivers. ================== Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--Documentation/devicetree/bindings/net/wireless/qcom,ipq5332-wifi.yaml1
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi-tlv.c26
-rw-r--r--drivers/net/wireless/ath/ath12k/ahb.c36
-rw-r--r--drivers/net/wireless/ath/ath12k/ahb.h1
-rw-r--r--drivers/net/wireless/ath/ath12k/ce.h13
-rw-r--r--drivers/net/wireless/ath/ath12k/core.c4
-rw-r--r--drivers/net/wireless/ath/ath12k/core.h13
-rw-r--r--drivers/net/wireless/ath/ath12k/debugfs.c29
-rw-r--r--drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c72
-rw-r--r--drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h26
-rw-r--r--drivers/net/wireless/ath/ath12k/mac.c4
-rw-r--r--drivers/net/wireless/ath/ath12k/wifi7/ahb.c8
-rw-r--r--drivers/net/wireless/ath/ath12k/wifi7/hal.c7
-rw-r--r--drivers/net/wireless/ath/ath12k/wifi7/hal.h3
-rw-r--r--drivers/net/wireless/ath/ath12k/wifi7/hal_qcn9274.c88
-rw-r--r--drivers/net/wireless/ath/ath12k/wifi7/hal_qcn9274.h1
-rw-r--r--drivers/net/wireless/ath/ath12k/wifi7/hw.c97
17 files changed, 383 insertions, 46 deletions
diff --git a/Documentation/devicetree/bindings/net/wireless/qcom,ipq5332-wifi.yaml b/Documentation/devicetree/bindings/net/wireless/qcom,ipq5332-wifi.yaml
index 363a0ecb6ad9..37d8a0da7780 100644
--- a/Documentation/devicetree/bindings/net/wireless/qcom,ipq5332-wifi.yaml
+++ b/Documentation/devicetree/bindings/net/wireless/qcom,ipq5332-wifi.yaml
@@ -17,6 +17,7 @@ properties:
compatible:
enum:
- qcom,ipq5332-wifi
+ - qcom,ipq5424-wifi
reg:
maxItems: 1
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
index ec8e91707f84..01f2d1fa9d7d 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
@@ -3,7 +3,7 @@
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
- * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include "core.h"
#include "debug.h"
@@ -14,6 +14,7 @@
#include "wmi-tlv.h"
#include "p2p.h"
#include "testmode.h"
+#include "txrx.h"
#include <linux/bitfield.h>
/***************/
@@ -224,8 +225,9 @@ static int ath10k_wmi_tlv_parse_peer_stats_info(struct ath10k *ar, u16 tag, u16
const void *ptr, void *data)
{
const struct wmi_tlv_peer_stats_info *stat = ptr;
- struct ieee80211_sta *sta;
+ u32 vdev_id = *(u32 *)data;
struct ath10k_sta *arsta;
+ struct ath10k_peer *peer;
if (tag != WMI_TLV_TAG_STRUCT_PEER_STATS_INFO)
return -EPROTO;
@@ -241,20 +243,20 @@ static int ath10k_wmi_tlv_parse_peer_stats_info(struct ath10k *ar, u16 tag, u16
__le32_to_cpu(stat->last_tx_rate_code),
__le32_to_cpu(stat->last_tx_bitrate_kbps));
- rcu_read_lock();
- sta = ieee80211_find_sta_by_ifaddr(ar->hw, stat->peer_macaddr.addr, NULL);
- if (!sta) {
- rcu_read_unlock();
- ath10k_warn(ar, "not found station for peer stats\n");
+ guard(spinlock_bh)(&ar->data_lock);
+
+ peer = ath10k_peer_find(ar, vdev_id, stat->peer_macaddr.addr);
+ if (!peer || !peer->sta) {
+ ath10k_warn(ar, "not found %s with vdev id %u mac addr %pM for peer stats\n",
+ peer ? "sta" : "peer", vdev_id, stat->peer_macaddr.addr);
return -EINVAL;
}
- arsta = (struct ath10k_sta *)sta->drv_priv;
+ arsta = (struct ath10k_sta *)peer->sta->drv_priv;
arsta->rx_rate_code = __le32_to_cpu(stat->last_rx_rate_code);
arsta->rx_bitrate_kbps = __le32_to_cpu(stat->last_rx_bitrate_kbps);
arsta->tx_rate_code = __le32_to_cpu(stat->last_tx_rate_code);
arsta->tx_bitrate_kbps = __le32_to_cpu(stat->last_tx_bitrate_kbps);
- rcu_read_unlock();
return 0;
}
@@ -266,6 +268,7 @@ static int ath10k_wmi_tlv_op_pull_peer_stats_info(struct ath10k *ar,
const struct wmi_tlv_peer_stats_info_ev *ev;
const void *data;
u32 num_peer_stats;
+ u32 vdev_id;
int ret;
tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
@@ -284,15 +287,16 @@ static int ath10k_wmi_tlv_op_pull_peer_stats_info(struct ath10k *ar,
}
num_peer_stats = __le32_to_cpu(ev->num_peers);
+ vdev_id = __le32_to_cpu(ev->vdev_id);
ath10k_dbg(ar, ATH10K_DBG_WMI,
"wmi tlv peer stats info update peer vdev id %d peers %i more data %d\n",
- __le32_to_cpu(ev->vdev_id),
+ vdev_id,
num_peer_stats,
__le32_to_cpu(ev->more_data));
ret = ath10k_wmi_tlv_iter(ar, data, ath10k_wmi_tlv_len(data),
- ath10k_wmi_tlv_parse_peer_stats_info, NULL);
+ ath10k_wmi_tlv_parse_peer_stats_info, &vdev_id);
if (ret)
ath10k_warn(ar, "failed to parse stats info tlv: %d\n", ret);
diff --git a/drivers/net/wireless/ath/ath12k/ahb.c b/drivers/net/wireless/ath/ath12k/ahb.c
index 9a4d34e49104..2dcf0a52e4c1 100644
--- a/drivers/net/wireless/ath/ath12k/ahb.c
+++ b/drivers/net/wireless/ath/ath12k/ahb.c
@@ -382,8 +382,12 @@ static int ath12k_ahb_power_up(struct ath12k_base *ab)
ATH12K_AHB_UPD_SWID;
/* Load FW image to a reserved memory location */
- ret = qcom_mdt_load(dev, fw, fw_name, pasid, mem_region, mem_phys, mem_size,
- &mem_phys);
+ if (ab_ahb->scm_auth_enabled)
+ ret = qcom_mdt_load(dev, fw, fw_name, pasid, mem_region,
+ mem_phys, mem_size, &mem_phys);
+ else
+ ret = qcom_mdt_load_no_init(dev, fw, fw_name, mem_region,
+ mem_phys, mem_size, &mem_phys);
if (ret) {
ath12k_err(ab, "Failed to load MDT segments: %d\n", ret);
goto err_fw;
@@ -414,11 +418,13 @@ static int ath12k_ahb_power_up(struct ath12k_base *ab)
goto err_fw2;
}
- /* Authenticate FW image using peripheral ID */
- ret = qcom_scm_pas_auth_and_reset(pasid);
- if (ret) {
- ath12k_err(ab, "failed to boot the remote processor %d\n", ret);
- goto err_fw2;
+ if (ab_ahb->scm_auth_enabled) {
+ /* Authenticate FW image using peripheral ID */
+ ret = qcom_scm_pas_auth_and_reset(pasid);
+ if (ret) {
+ ath12k_err(ab, "failed to boot the remote processor %d\n", ret);
+ goto err_fw2;
+ }
}
/* Instruct Q6 to spawn userPD thread */
@@ -475,13 +481,15 @@ static void ath12k_ahb_power_down(struct ath12k_base *ab, bool is_suspend)
qcom_smem_state_update_bits(ab_ahb->stop_state, BIT(ab_ahb->stop_bit), 0);
- pasid = (u32_encode_bits(ab_ahb->userpd_id, ATH12K_USERPD_ID_MASK)) |
- ATH12K_AHB_UPD_SWID;
- /* Release the firmware */
- ret = qcom_scm_pas_shutdown(pasid);
- if (ret)
- ath12k_err(ab, "scm pas shutdown failed for userPD%d: %d\n",
- ab_ahb->userpd_id, ret);
+ if (ab_ahb->scm_auth_enabled) {
+ pasid = (u32_encode_bits(ab_ahb->userpd_id, ATH12K_USERPD_ID_MASK)) |
+ ATH12K_AHB_UPD_SWID;
+ /* Release the firmware */
+ ret = qcom_scm_pas_shutdown(pasid);
+ if (ret)
+ ath12k_err(ab, "scm pas shutdown failed for userPD%d\n",
+ ab_ahb->userpd_id);
+ }
}
static void ath12k_ahb_init_qmi_ce_config(struct ath12k_base *ab)
diff --git a/drivers/net/wireless/ath/ath12k/ahb.h b/drivers/net/wireless/ath/ath12k/ahb.h
index be9e31b3682d..0fa15daaa3e6 100644
--- a/drivers/net/wireless/ath/ath12k/ahb.h
+++ b/drivers/net/wireless/ath/ath12k/ahb.h
@@ -68,6 +68,7 @@ struct ath12k_ahb {
int userpd_irq_num[ATH12K_USERPD_MAX_IRQ];
const struct ath12k_ahb_ops *ahb_ops;
const struct ath12k_ahb_device_family_ops *device_family_ops;
+ bool scm_auth_enabled;
};
struct ath12k_ahb_driver {
diff --git a/drivers/net/wireless/ath/ath12k/ce.h b/drivers/net/wireless/ath/ath12k/ce.h
index df4f2a4f8480..009cddf2d68d 100644
--- a/drivers/net/wireless/ath/ath12k/ce.h
+++ b/drivers/net/wireless/ath/ath12k/ce.h
@@ -38,10 +38,15 @@
#define PIPEDIR_INOUT 3 /* bidirectional */
#define PIPEDIR_INOUT_H2H 4 /* bidirectional, host to host */
-/* CE address/mask */
-#define CE_HOST_IE_ADDRESS 0x75804C
-#define CE_HOST_IE_2_ADDRESS 0x758050
-#define CE_HOST_IE_3_ADDRESS CE_HOST_IE_ADDRESS
+/* IPQ5332 CE address/mask */
+#define CE_HOST_IPQ5332_IE_ADDRESS 0x75804C
+#define CE_HOST_IPQ5332_IE_2_ADDRESS 0x758050
+#define CE_HOST_IPQ5332_IE_3_ADDRESS CE_HOST_IPQ5332_IE_ADDRESS
+
+/* IPQ5424 CE address/mask */
+#define CE_HOST_IPQ5424_IE_ADDRESS 0x21804C
+#define CE_HOST_IPQ5424_IE_2_ADDRESS 0x218050
+#define CE_HOST_IPQ5424_IE_3_ADDRESS CE_HOST_IPQ5424_IE_ADDRESS
#define CE_HOST_IE_3_SHIFT 0xC
diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c
index c31c47fb5a73..2519e2400d58 100644
--- a/drivers/net/wireless/ath/ath12k/core.c
+++ b/drivers/net/wireless/ath/ath12k/core.c
@@ -835,8 +835,6 @@ static int ath12k_core_soc_create(struct ath12k_base *ab)
goto err_qmi_deinit;
}
- ath12k_debugfs_pdev_create(ab);
-
return 0;
err_qmi_deinit:
@@ -869,6 +867,8 @@ static int ath12k_core_pdev_create(struct ath12k_base *ab)
goto err_dp_pdev_free;
}
+ ath12k_debugfs_pdev_create(ab);
+
return 0;
err_dp_pdev_free:
diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h
index 59c193b24764..8be435535a4e 100644
--- a/drivers/net/wireless/ath/ath12k/core.h
+++ b/drivers/net/wireless/ath/ath12k/core.h
@@ -157,6 +157,7 @@ enum ath12k_hw_rev {
ATH12K_HW_WCN7850_HW20,
ATH12K_HW_IPQ5332_HW10,
ATH12K_HW_QCC2072_HW10,
+ ATH12K_HW_IPQ5424_HW10,
};
enum ath12k_firmware_mode {
@@ -588,6 +589,7 @@ struct ath12k_dbg_htt_stats {
struct ath12k_debug {
struct dentry *debugfs_pdev;
struct dentry *debugfs_pdev_symlink;
+ struct dentry *debugfs_pdev_symlink_default;
struct ath12k_dbg_htt_stats htt_stats;
enum wmi_halphy_ctrl_path_stats_id tpc_stats_type;
bool tpc_request;
@@ -673,6 +675,7 @@ struct ath12k {
u8 pdev_idx;
u8 lmac_id;
u8 hw_link_id;
+ u8 radio_idx;
struct completion peer_assoc_done;
struct completion peer_delete_done;
@@ -1366,13 +1369,13 @@ static inline struct ath12k_hw *ath12k_hw_to_ah(struct ieee80211_hw *hw)
return hw->priv;
}
-static inline struct ath12k *ath12k_ah_to_ar(struct ath12k_hw *ah, u8 hw_link_id)
+static inline struct ath12k *ath12k_ah_to_ar(struct ath12k_hw *ah, u8 radio_idx)
{
- if (WARN(hw_link_id >= ah->num_radio,
- "bad hw link id %d, so switch to default link\n", hw_link_id))
- hw_link_id = 0;
+ if (WARN(radio_idx >= ah->num_radio,
+ "bad radio index %d, use default radio\n", radio_idx))
+ radio_idx = 0;
- return &ah->radio[hw_link_id];
+ return &ah->radio[radio_idx];
}
static inline struct ath12k_hw *ath12k_ar_to_ah(struct ath12k *ar)
diff --git a/drivers/net/wireless/ath/ath12k/debugfs.c b/drivers/net/wireless/ath/ath12k/debugfs.c
index 358031fa14eb..8c81a1c22449 100644
--- a/drivers/net/wireless/ath/ath12k/debugfs.c
+++ b/drivers/net/wireless/ath/ath12k/debugfs.c
@@ -1473,18 +1473,35 @@ void ath12k_debugfs_register(struct ath12k *ar)
{
struct ath12k_base *ab = ar->ab;
struct ieee80211_hw *hw = ar->ah->hw;
- char pdev_name[5];
+ struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
+ struct dentry *ath12k_fs;
char buf[100] = {};
+ char pdev_name[5];
scnprintf(pdev_name, sizeof(pdev_name), "%s%d", "mac", ar->pdev_idx);
ar->debug.debugfs_pdev = debugfs_create_dir(pdev_name, ab->debugfs_soc);
/* Create a symlink under ieee80211/phy* */
- scnprintf(buf, sizeof(buf), "../../ath12k/%pd2", ar->debug.debugfs_pdev);
- ar->debug.debugfs_pdev_symlink = debugfs_create_symlink("ath12k",
- hw->wiphy->debugfsdir,
- buf);
+ if (ar->radio_idx == 0) {
+ scnprintf(buf, sizeof(buf), "../../ath12k/%pd2",
+ ar->debug.debugfs_pdev);
+ ath12k_fs = hw->wiphy->debugfsdir;
+
+ /* symbolic link for compatibility */
+ ar->debug.debugfs_pdev_symlink_default = debugfs_create_symlink("ath12k",
+ ath12k_fs,
+ buf);
+ }
+
+ if (ah->num_radio > 1) {
+ scnprintf(buf, sizeof(buf), "../../../ath12k/%pd2",
+ ar->debug.debugfs_pdev);
+ ath12k_fs = hw->wiphy->radio_cfg[ar->radio_idx].radio_debugfsdir;
+ ar->debug.debugfs_pdev_symlink = debugfs_create_symlink("ath12k",
+ ath12k_fs,
+ buf);
+ }
if (ar->mac.sbands[NL80211_BAND_5GHZ].channels) {
debugfs_create_file("dfs_simulate_radar", 0200,
@@ -1513,7 +1530,9 @@ void ath12k_debugfs_unregister(struct ath12k *ar)
/* Remove symlink under ieee80211/phy* */
debugfs_remove(ar->debug.debugfs_pdev_symlink);
+ debugfs_remove(ar->debug.debugfs_pdev_symlink_default);
debugfs_remove_recursive(ar->debug.debugfs_pdev);
ar->debug.debugfs_pdev_symlink = NULL;
+ ar->debug.debugfs_pdev_symlink_default = NULL;
ar->debug.debugfs_pdev = NULL;
}
diff --git a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c
index 7f6ca07fb335..b772181a496e 100644
--- a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c
+++ b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c
@@ -5722,6 +5722,75 @@ ath12k_htt_print_tx_hwq_stats_cmn_tlv(const void *tag_buf, u16 tag_len,
stats_req->buf_len = len;
}
+static void
+ath12k_htt_print_chan_switch_stats_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_chan_switch_stats_tlv *sbuf = tag_buf;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+ u32 switch_freq, switch_profile;
+ u32 len = stats_req->buf_len;
+ u8 *buf = stats_req->buf;
+ u8 i;
+
+ if (tag_len < sizeof(*sbuf))
+ return;
+
+ i = min(le32_to_cpu(sbuf->switch_count), ATH12K_HTT_CHAN_SWITCH_STATS_BUF_LEN);
+ if (!i)
+ return;
+
+ len += scnprintf(buf + len, buf_len - len, "Channel Change Timings:\n");
+ len += scnprintf(buf + len, buf_len - len,
+ "|%-20s|%-21s|%-7s|%-12s|%-12s|%-15s|",
+ "PRIMARY CHANNEL FREQ", "BANDWIDTH CENTER FREQ", "PHYMODE",
+ "TX_CHAINMASK", "RX_CHAINMASK", "SWITCH TIME(us)");
+ len += scnprintf(buf + len, buf_len - len,
+ "%-7s|%-11s|%-7s|%-8s|%-7s|%-10s|\n",
+ "INI(us)", "TPC+CTL(us)", "CAL(us)", "MISC(us)", "CTL(us)",
+ "SW PROFILE");
+
+ /*
+ * sbuf->switch_count has the number of successful channel changes. The firmware
+ * sends the record of channel change in such a way that sbuf->chan_stats[0] will
+ * point to the channel change that occurred first and the recent channel change
+ * records will be stored in sbuf->chan_stats[9]. As and when new channel change
+ * occurs, sbuf->chan_stats[0] will be replaced by records from the next index,
+ * sbuf->chan_stats[1]. While printing the records, reverse chronological order
+ * is followed, i.e., the most recent channel change records are printed first
+ * and the oldest one, last.
+ */
+ while (i--) {
+ switch_freq = le32_to_cpu(sbuf->chan_stats[i].chan_switch_freq);
+ switch_profile = le32_to_cpu(sbuf->chan_stats[i].chan_switch_profile);
+
+ len += scnprintf(buf + len, buf_len - len,
+ "|%20u|%21u|%7u|%12u|%12u|%15u|",
+ u32_get_bits(switch_freq,
+ ATH12K_HTT_STATS_CHAN_SWITCH_BW_MHZ),
+ u32_get_bits(switch_freq,
+ ATH12K_HTT_STATS_CHAN_SWITCH_BAND_FREQ),
+ u32_get_bits(switch_profile,
+ ATH12K_HTT_STATS_CHAN_SWITCH_PHY_MODE),
+ u32_get_bits(switch_profile,
+ ATH12K_HTT_STATS_CHAN_SWITCH_TX_CHAINMASK),
+ u32_get_bits(switch_profile,
+ ATH12K_HTT_STATS_CHAN_SWITCH_RX_CHAINMASK),
+ le32_to_cpu(sbuf->chan_stats[i].chan_switch_time));
+ len += scnprintf(buf + len, buf_len - len,
+ "%7u|%11u|%7u|%8u|%7u|%10u|\n",
+ le32_to_cpu(sbuf->chan_stats[i].ini_module_time),
+ le32_to_cpu(sbuf->chan_stats[i].tpc_module_time),
+ le32_to_cpu(sbuf->chan_stats[i].cal_module_time),
+ le32_to_cpu(sbuf->chan_stats[i].misc_module_time),
+ le32_to_cpu(sbuf->chan_stats[i].ctl_module_time),
+ u32_get_bits(switch_profile,
+ ATH12K_HTT_STATS_CHAN_SWITCH_SW_PROFILE));
+ }
+
+ stats_req->buf_len = len;
+}
+
static int ath12k_dbg_htt_ext_stats_parse(struct ath12k_base *ab,
u16 tag, u16 len, const void *tag_buf,
void *user_data)
@@ -6024,6 +6093,9 @@ static int ath12k_dbg_htt_ext_stats_parse(struct ath12k_base *ab,
case HTT_STATS_TX_HWQ_CMN_TAG:
ath12k_htt_print_tx_hwq_stats_cmn_tlv(tag_buf, len, stats_req);
break;
+ case HTT_STATS_CHAN_SWITCH_STATS_TAG:
+ ath12k_htt_print_chan_switch_stats_tlv(tag_buf, len, stats_req);
+ break;
default:
break;
}
diff --git a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h
index bfabe6500d44..82ab7b9e4db9 100644
--- a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h
+++ b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h
@@ -164,6 +164,7 @@ enum ath12k_dbg_htt_ext_stats_type {
ATH12K_DBG_HTT_PDEV_MLO_IPC_STATS = 64,
ATH12K_DBG_HTT_EXT_PDEV_RTT_RESP_STATS = 65,
ATH12K_DBG_HTT_EXT_PDEV_RTT_INITIATOR_STATS = 66,
+ ATH12K_DBG_HTT_EXT_CHAN_SWITCH_STATS = 76,
/* keep this last */
ATH12K_DBG_HTT_NUM_EXT_STATS,
@@ -267,6 +268,7 @@ enum ath12k_dbg_htt_tlv_tag {
HTT_STATS_PDEV_RTT_HW_STATS_TAG = 196,
HTT_STATS_PDEV_RTT_TBR_SELFGEN_QUEUED_STATS_TAG = 197,
HTT_STATS_PDEV_RTT_TBR_CMD_RESULT_STATS_TAG = 198,
+ HTT_STATS_CHAN_SWITCH_STATS_TAG = 213,
HTT_STATS_MAX_TAG,
};
@@ -2156,4 +2158,28 @@ struct htt_tx_hwq_stats_cmn_tlv {
__le32 txq_timeout;
} __packed;
+#define ATH12K_HTT_CHAN_SWITCH_STATS_BUF_LEN 10
+
+#define ATH12K_HTT_STATS_CHAN_SWITCH_BW_MHZ GENMASK(15, 0)
+#define ATH12K_HTT_STATS_CHAN_SWITCH_BAND_FREQ GENMASK(31, 16)
+#define ATH12K_HTT_STATS_CHAN_SWITCH_PHY_MODE GENMASK(7, 0)
+#define ATH12K_HTT_STATS_CHAN_SWITCH_TX_CHAINMASK GENMASK(15, 8)
+#define ATH12K_HTT_STATS_CHAN_SWITCH_RX_CHAINMASK GENMASK(23, 16)
+#define ATH12K_HTT_STATS_CHAN_SWITCH_SW_PROFILE GENMASK(31, 24)
+
+struct ath12k_htt_chan_switch_stats_tlv {
+ struct {
+ __le32 chan_switch_freq;
+ __le32 chan_switch_profile;
+ __le32 chan_switch_time;
+ __le32 cal_module_time;
+ __le32 ini_module_time;
+ __le32 tpc_module_time;
+ __le32 misc_module_time;
+ __le32 ctl_module_time;
+ __le32 reserved;
+ } chan_stats[ATH12K_HTT_CHAN_SWITCH_STATS_BUF_LEN];
+ __le32 switch_count; /* shows how many channel changes have occurred */
+} __packed;
+
#endif
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index 553ec28b6aaa..fbdfe6424fd7 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -11131,7 +11131,7 @@ ath12k_mac_mlo_get_vdev_args(struct ath12k_link_vif *arvif,
if (arvif == arvif_p)
continue;
- if (!arvif_p->is_created)
+ if (!arvif_p->is_started)
continue;
link_conf = wiphy_dereference(ahvif->ah->hw->wiphy,
@@ -15065,6 +15065,7 @@ static struct ath12k_hw *ath12k_mac_hw_allocate(struct ath12k_hw_group *ag,
ar->hw_link_id = pdev->hw_link_id;
ar->pdev = pdev;
ar->pdev_idx = pdev_idx;
+ ar->radio_idx = i;
pdev->ar = ar;
ag->hw_links[ar->hw_link_id].device_id = ab->device_id;
@@ -15132,7 +15133,6 @@ int ath12k_mac_allocate(struct ath12k_hw_group *ag)
if (!ab)
continue;
- ath12k_debugfs_pdev_create(ab);
ath12k_mac_set_device_defaults(ab);
total_radio += ab->num_radios;
}
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/ahb.c b/drivers/net/wireless/ath/ath12k/wifi7/ahb.c
index a6c5f7689edd..6a8b8b2a56f9 100644
--- a/drivers/net/wireless/ath/ath12k/wifi7/ahb.c
+++ b/drivers/net/wireless/ath/ath12k/wifi7/ahb.c
@@ -19,6 +19,9 @@ static const struct of_device_id ath12k_wifi7_ahb_of_match[] = {
{ .compatible = "qcom,ipq5332-wifi",
.data = (void *)ATH12K_HW_IPQ5332_HW10,
},
+ { .compatible = "qcom,ipq5424-wifi",
+ .data = (void *)ATH12K_HW_IPQ5424_HW10,
+ },
{ }
};
@@ -38,6 +41,11 @@ static int ath12k_wifi7_ahb_probe(struct platform_device *pdev)
switch (hw_rev) {
case ATH12K_HW_IPQ5332_HW10:
ab_ahb->userpd_id = ATH12K_IPQ5332_USERPD_ID;
+ ab_ahb->scm_auth_enabled = true;
+ break;
+ case ATH12K_HW_IPQ5424_HW10:
+ ab_ahb->userpd_id = ATH12K_IPQ5332_USERPD_ID;
+ ab_ahb->scm_auth_enabled = false;
break;
default:
return -EOPNOTSUPP;
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hal.c b/drivers/net/wireless/ath/ath12k/wifi7/hal.c
index bd1753ca0db6..a0a1902fb491 100644
--- a/drivers/net/wireless/ath/ath12k/wifi7/hal.c
+++ b/drivers/net/wireless/ath/ath12k/wifi7/hal.c
@@ -50,6 +50,13 @@ static const struct ath12k_hw_version_map ath12k_wifi7_hw_ver_map[] = {
.hal_params = &ath12k_hw_hal_params_wcn7850,
.hw_regs = &qcc2072_regs,
},
+ [ATH12K_HW_IPQ5424_HW10] = {
+ .hal_ops = &hal_qcn9274_ops,
+ .hal_desc_sz = sizeof(struct hal_rx_desc_qcn9274_compact),
+ .tcl_to_wbm_rbm_map = ath12k_hal_tcl_to_wbm_rbm_map_qcn9274,
+ .hal_params = &ath12k_hw_hal_params_ipq5332,
+ .hw_regs = &ipq5424_regs,
+ },
};
int ath12k_wifi7_hal_init(struct ath12k_base *ab)
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hal.h b/drivers/net/wireless/ath/ath12k/wifi7/hal.h
index 9337225a5253..3d9386198893 100644
--- a/drivers/net/wireless/ath/ath12k/wifi7/hal.h
+++ b/drivers/net/wireless/ath/ath12k/wifi7/hal.h
@@ -364,6 +364,9 @@
#define HAL_IPQ5332_CE_WFSS_REG_BASE 0x740000
#define HAL_IPQ5332_CE_SIZE 0x100000
+#define HAL_IPQ5424_CE_WFSS_REG_BASE 0x200000
+#define HAL_IPQ5424_CE_SIZE 0x100000
+
#define HAL_RX_MAX_BA_WINDOW 256
#define HAL_DEFAULT_BE_BK_VI_REO_TIMEOUT_USEC (100 * 1000)
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hal_qcn9274.c b/drivers/net/wireless/ath/ath12k/wifi7/hal_qcn9274.c
index 41c918eb1767..ba9ce1e718e8 100644
--- a/drivers/net/wireless/ath/ath12k/wifi7/hal_qcn9274.c
+++ b/drivers/net/wireless/ath/ath12k/wifi7/hal_qcn9274.c
@@ -484,6 +484,94 @@ const struct ath12k_hw_regs ipq5332_regs = {
HAL_IPQ5332_CE_WFSS_REG_BASE,
};
+const struct ath12k_hw_regs ipq5424_regs = {
+ /* SW2TCL(x) R0 ring configuration address */
+ .tcl1_ring_id = 0x00000918,
+ .tcl1_ring_misc = 0x00000920,
+ .tcl1_ring_tp_addr_lsb = 0x0000092c,
+ .tcl1_ring_tp_addr_msb = 0x00000930,
+ .tcl1_ring_consumer_int_setup_ix0 = 0x00000940,
+ .tcl1_ring_consumer_int_setup_ix1 = 0x00000944,
+ .tcl1_ring_msi1_base_lsb = 0x00000958,
+ .tcl1_ring_msi1_base_msb = 0x0000095c,
+ .tcl1_ring_base_lsb = 0x00000910,
+ .tcl1_ring_base_msb = 0x00000914,
+ .tcl1_ring_msi1_data = 0x00000960,
+ .tcl2_ring_base_lsb = 0x00000988,
+ .tcl_ring_base_lsb = 0x00000b68,
+
+ /* TCL STATUS ring address */
+ .tcl_status_ring_base_lsb = 0x00000d48,
+
+ /* REO DEST ring address */
+ .reo2_ring_base = 0x00000578,
+ .reo1_misc_ctrl_addr = 0x00000b9c,
+ .reo1_sw_cookie_cfg0 = 0x0000006c,
+ .reo1_sw_cookie_cfg1 = 0x00000070,
+ .reo1_qdesc_lut_base0 = 0x00000074,
+ .reo1_qdesc_lut_base1 = 0x00000078,
+ .reo1_ring_base_lsb = 0x00000500,
+ .reo1_ring_base_msb = 0x00000504,
+ .reo1_ring_id = 0x00000508,
+ .reo1_ring_misc = 0x00000510,
+ .reo1_ring_hp_addr_lsb = 0x00000514,
+ .reo1_ring_hp_addr_msb = 0x00000518,
+ .reo1_ring_producer_int_setup = 0x00000524,
+ .reo1_ring_msi1_base_lsb = 0x00000548,
+ .reo1_ring_msi1_base_msb = 0x0000054C,
+ .reo1_ring_msi1_data = 0x00000550,
+ .reo1_aging_thres_ix0 = 0x00000B28,
+ .reo1_aging_thres_ix1 = 0x00000B2C,
+ .reo1_aging_thres_ix2 = 0x00000B30,
+ .reo1_aging_thres_ix3 = 0x00000B34,
+
+ /* REO Exception ring address */
+ .reo2_sw0_ring_base = 0x000008c0,
+
+ /* REO Reinject ring address */
+ .sw2reo_ring_base = 0x00000320,
+ .sw2reo1_ring_base = 0x00000398,
+
+ /* REO cmd ring address */
+ .reo_cmd_ring_base = 0x000002A8,
+
+ /* REO status ring address */
+ .reo_status_ring_base = 0x00000aa0,
+
+ /* WBM idle link ring address */
+ .wbm_idle_ring_base_lsb = 0x00000d3c,
+ .wbm_idle_ring_misc_addr = 0x00000d4c,
+ .wbm_r0_idle_list_cntl_addr = 0x00000240,
+ .wbm_r0_idle_list_size_addr = 0x00000244,
+ .wbm_scattered_ring_base_lsb = 0x00000250,
+ .wbm_scattered_ring_base_msb = 0x00000254,
+ .wbm_scattered_desc_head_info_ix0 = 0x00000260,
+ .wbm_scattered_desc_head_info_ix1 = 0x00000264,
+ .wbm_scattered_desc_tail_info_ix0 = 0x00000270,
+ .wbm_scattered_desc_tail_info_ix1 = 0x00000274,
+ .wbm_scattered_desc_ptr_hp_addr = 0x0000027c,
+
+ /* SW2WBM release ring address */
+ .wbm_sw_release_ring_base_lsb = 0x0000037c,
+
+ /* WBM2SW release ring address */
+ .wbm0_release_ring_base_lsb = 0x00000e08,
+ .wbm1_release_ring_base_lsb = 0x00000e80,
+
+ /* PPE release ring address */
+ .ppe_rel_ring_base = 0x0000046c,
+
+ /* CE address */
+ .umac_ce0_src_reg_base = 0x00200000 -
+ HAL_IPQ5424_CE_WFSS_REG_BASE,
+ .umac_ce0_dest_reg_base = 0x00201000 -
+ HAL_IPQ5424_CE_WFSS_REG_BASE,
+ .umac_ce1_src_reg_base = 0x00202000 -
+ HAL_IPQ5424_CE_WFSS_REG_BASE,
+ .umac_ce1_dest_reg_base = 0x00203000 -
+ HAL_IPQ5424_CE_WFSS_REG_BASE,
+};
+
static inline
bool ath12k_hal_rx_desc_get_first_msdu_qcn9274(struct hal_rx_desc *desc)
{
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hal_qcn9274.h b/drivers/net/wireless/ath/ath12k/wifi7/hal_qcn9274.h
index 08c0a0469474..03cf3792d523 100644
--- a/drivers/net/wireless/ath/ath12k/wifi7/hal_qcn9274.h
+++ b/drivers/net/wireless/ath/ath12k/wifi7/hal_qcn9274.h
@@ -17,6 +17,7 @@ extern const struct hal_ops hal_qcn9274_ops;
extern const struct ath12k_hw_regs qcn9274_v1_regs;
extern const struct ath12k_hw_regs qcn9274_v2_regs;
extern const struct ath12k_hw_regs ipq5332_regs;
+extern const struct ath12k_hw_regs ipq5424_regs;
extern const struct ath12k_hal_tcl_to_wbm_rbm_map
ath12k_hal_tcl_to_wbm_rbm_map_qcn9274[DP_TCL_NUM_RING_MAX];
extern const struct ath12k_hw_hal_params ath12k_hw_hal_params_qcn9274;
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hw.c b/drivers/net/wireless/ath/ath12k/wifi7/hw.c
index ec6dba96640b..cb3185850439 100644
--- a/drivers/net/wireless/ath/ath12k/wifi7/hw.c
+++ b/drivers/net/wireless/ath/ath12k/wifi7/hw.c
@@ -329,9 +329,15 @@ static const struct ath12k_hw_ring_mask ath12k_wifi7_hw_ring_mask_wcn7850 = {
};
static const struct ce_ie_addr ath12k_wifi7_ce_ie_addr_ipq5332 = {
- .ie1_reg_addr = CE_HOST_IE_ADDRESS - HAL_IPQ5332_CE_WFSS_REG_BASE,
- .ie2_reg_addr = CE_HOST_IE_2_ADDRESS - HAL_IPQ5332_CE_WFSS_REG_BASE,
- .ie3_reg_addr = CE_HOST_IE_3_ADDRESS - HAL_IPQ5332_CE_WFSS_REG_BASE,
+ .ie1_reg_addr = CE_HOST_IPQ5332_IE_ADDRESS - HAL_IPQ5332_CE_WFSS_REG_BASE,
+ .ie2_reg_addr = CE_HOST_IPQ5332_IE_2_ADDRESS - HAL_IPQ5332_CE_WFSS_REG_BASE,
+ .ie3_reg_addr = CE_HOST_IPQ5332_IE_3_ADDRESS - HAL_IPQ5332_CE_WFSS_REG_BASE,
+};
+
+static const struct ce_ie_addr ath12k_wifi7_ce_ie_addr_ipq5424 = {
+ .ie1_reg_addr = CE_HOST_IPQ5424_IE_ADDRESS - HAL_IPQ5424_CE_WFSS_REG_BASE,
+ .ie2_reg_addr = CE_HOST_IPQ5424_IE_2_ADDRESS - HAL_IPQ5424_CE_WFSS_REG_BASE,
+ .ie3_reg_addr = CE_HOST_IPQ5424_IE_3_ADDRESS - HAL_IPQ5424_CE_WFSS_REG_BASE,
};
static const struct ce_remap ath12k_wifi7_ce_remap_ipq5332 = {
@@ -340,6 +346,12 @@ static const struct ce_remap ath12k_wifi7_ce_remap_ipq5332 = {
.cmem_offset = HAL_SEQ_WCSS_CMEM_OFFSET,
};
+static const struct ce_remap ath12k_wifi7_ce_remap_ipq5424 = {
+ .base = HAL_IPQ5424_CE_WFSS_REG_BASE,
+ .size = HAL_IPQ5424_CE_SIZE,
+ .cmem_offset = HAL_SEQ_WCSS_CMEM_OFFSET,
+};
+
static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {
{
.name = "qcn9274 hw1.0",
@@ -753,6 +765,85 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {
.dp_primary_link_only = false,
},
+ {
+ .name = "ipq5424 hw1.0",
+ .hw_rev = ATH12K_HW_IPQ5424_HW10,
+ .fw = {
+ .dir = "IPQ5424/hw1.0",
+ .board_size = 256 * 1024,
+ .cal_offset = 128 * 1024,
+ .m3_loader = ath12k_m3_fw_loader_remoteproc,
+ .download_aux_ucode = false,
+ },
+ .max_radios = 1,
+ .single_pdev_only = false,
+ .qmi_service_ins_id = ATH12K_QMI_WLFW_SERVICE_INS_ID_V01_IPQ5332,
+ .internal_sleep_clock = false,
+
+ .hw_ops = &qcn9274_ops,
+ .ring_mask = &ath12k_wifi7_hw_ring_mask_ipq5332,
+
+ .host_ce_config = ath12k_wifi7_host_ce_config_ipq5332,
+ .ce_count = 12,
+ .target_ce_config = ath12k_wifi7_target_ce_config_wlan_ipq5332,
+ .target_ce_count = 12,
+ .svc_to_ce_map =
+ ath12k_wifi7_target_service_to_ce_map_wlan_ipq5332,
+ .svc_to_ce_map_len = 18,
+
+ .rxdma1_enable = true,
+ .num_rxdma_per_pdev = 1,
+ .num_rxdma_dst_ring = 0,
+ .rx_mac_buf_ring = false,
+ .vdev_start_delay = false,
+
+ .interface_modes = BIT(NL80211_IFTYPE_STATION) |
+ BIT(NL80211_IFTYPE_AP) |
+ BIT(NL80211_IFTYPE_MESH_POINT),
+ .supports_monitor = true,
+
+ .idle_ps = false,
+ .download_calib = true,
+ .supports_suspend = false,
+ .tcl_ring_retry = true,
+ .reoq_lut_support = false,
+ .supports_shadow_regs = false,
+
+ .num_tcl_banks = 48,
+ .max_tx_ring = 4,
+
+ .mhi_config = NULL,
+
+ .wmi_init = &ath12k_wifi7_wmi_init_qcn9274,
+
+ .qmi_cnss_feature_bitmap = BIT(CNSS_QDSS_CFG_MISS_V01),
+
+ .rfkill_pin = 0,
+ .rfkill_cfg = 0,
+ .rfkill_on_level = 0,
+
+ .rddm_size = 0,
+
+ .def_num_link = 0,
+ .max_mlo_peer = 256,
+
+ .otp_board_id_register = 0,
+
+ .supports_sta_ps = false,
+
+ .acpi_guid = NULL,
+ .supports_dynamic_smps_6ghz = false,
+ .iova_mask = 0,
+ .supports_aspm = false,
+
+ .ce_ie_addr = &ath12k_wifi7_ce_ie_addr_ipq5424,
+ .ce_remap = &ath12k_wifi7_ce_remap_ipq5424,
+ .bdf_addr_offset = 0x940000,
+
+ .current_cc_support = false,
+
+ .dp_primary_link_only = true,
+ },
};
/* Note: called under rcu_read_lock() */