Merge branch 'ath12k-ng' into ath-next

As originally proposed in [1], the ath12k driver was re-architected in
the ath12k-ng branch to separate the logic specific to 802.11be (Wi-Fi
7) from the core logic. This separation will allow ath12k to also
support 802.11bn (Wi-Fi 8) in the future. Now merge this into ath-next.

Many thanks to everyone who worked on this re-architecture. Special
thanks to Vasanthakumar Thiagarajan and Baochen Qiang who reviewed
every patch, and to Ripan Deuri for the ath12k-ng => ath-next merge
conflict resolution.

Link: https://lore.kernel.org/all/4a17d730-ede8-463e-98d8-9b0291d0ca45@oss.qualcomm.com/ # [1]
Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
This commit is contained in:
Jeff Johnson
2025-12-15 08:55:21 -08:00
78 changed files with 20194 additions and 17405 deletions
+5 -3
View File
@@ -2,8 +2,6 @@
obj-$(CONFIG_ATH12K) += ath12k.o
ath12k-y += core.o \
hal.o \
hal_tx.o \
hal_rx.o \
wmi.o \
mac.o \
reg.o \
@@ -12,11 +10,12 @@ ath12k-y += core.o \
dp.o \
dp_tx.o \
dp_rx.o \
dp_htt.o \
dp_peer.o \
debug.o \
ce.o \
peer.o \
dbring.o \
hw.o \
mhi.o \
pci.o \
dp_mon.o \
@@ -24,6 +23,9 @@ ath12k-y += core.o \
p2p.o
ath12k-$(CONFIG_ATH12K_AHB) += ahb.o
obj-$(CONFIG_ATH12K) += wifi7/
ath12k-$(CONFIG_ATH12K_DEBUGFS) += debugfs.o debugfs_htt_stats.o debugfs_sta.o
ath12k-$(CONFIG_ACPI) += acpi.o
ath12k-$(CONFIG_ATH12K_TRACING) += trace.o
+116 -55
View File
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
* Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <linux/dma-mapping.h>
@@ -16,18 +16,11 @@
#include "debug.h"
#include "hif.h"
static const struct of_device_id ath12k_ahb_of_match[] = {
{ .compatible = "qcom,ipq5332-wifi",
.data = (void *)ATH12K_HW_IPQ5332_HW10,
},
{ }
};
MODULE_DEVICE_TABLE(of, ath12k_ahb_of_match);
#define ATH12K_IRQ_CE0_OFFSET 4
#define ATH12K_MAX_UPDS 1
#define ATH12K_UPD_IRQ_WRD_LEN 18
static struct ath12k_ahb_driver *ath12k_ahb_family_drivers[ATH12K_DEVICE_FAMILY_MAX];
static const char ath12k_userpd_irq[][9] = {"spawn",
"ready",
"stop-ack"};
@@ -130,7 +123,7 @@ enum ext_irq_num {
static u32 ath12k_ahb_read32(struct ath12k_base *ab, u32 offset)
{
if (ab->ce_remap && offset < HAL_SEQ_WCSS_CMEM_OFFSET)
if (ab->ce_remap && offset < ab->cmem_offset)
return ioread32(ab->mem_ce + offset);
return ioread32(ab->mem + offset);
}
@@ -138,7 +131,7 @@ static u32 ath12k_ahb_read32(struct ath12k_base *ab, u32 offset)
static void ath12k_ahb_write32(struct ath12k_base *ab, u32 offset,
u32 value)
{
if (ab->ce_remap && offset < HAL_SEQ_WCSS_CMEM_OFFSET)
if (ab->ce_remap && offset < ab->cmem_offset)
iowrite32(value, ab->mem_ce + offset);
else
iowrite32(value, ab->mem + offset);
@@ -531,9 +524,10 @@ static int ath12k_ahb_ext_grp_napi_poll(struct napi_struct *napi, int budget)
struct ath12k_ext_irq_grp,
napi);
struct ath12k_base *ab = irq_grp->ab;
struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
int work_done;
work_done = ath12k_dp_service_srng(ab, irq_grp, budget);
work_done = ath12k_dp_service_srng(dp, irq_grp, budget);
if (work_done < budget) {
napi_complete_done(napi, work_done);
ath12k_ahb_ext_grp_enable(irq_grp);
@@ -563,12 +557,10 @@ static int ath12k_ahb_config_ext_irq(struct ath12k_base *ab)
{
const struct ath12k_hw_ring_mask *ring_mask;
struct ath12k_ext_irq_grp *irq_grp;
const struct hal_ops *hal_ops;
int i, j, irq, irq_idx, ret;
u32 num_irq;
ring_mask = ab->hw_params->ring_mask;
hal_ops = ab->hw_params->hal_ops;
for (i = 0; i < ATH12K_EXT_IRQ_GRP_NUM_MAX; i++) {
irq_grp = &ab->ext_irq_grp[i];
num_irq = 0;
@@ -588,7 +580,7 @@ static int ath12k_ahb_config_ext_irq(struct ath12k_base *ab)
* tcl_to_wbm_rbm_map point to the same ring number.
*/
if (ring_mask->tx[i] &
BIT(hal_ops->tcl_to_wbm_rbm_map[j].wbm_ring_num)) {
BIT(ab->hal.tcl_to_wbm_rbm_map[j].wbm_ring_num)) {
irq_grp->irqs[num_irq++] =
wbm2host_tx_completions_ring1 - j;
}
@@ -698,7 +690,7 @@ static int ath12k_ahb_map_service_to_pipe(struct ath12k_base *ab, u16 service_id
return 0;
}
static const struct ath12k_hif_ops ath12k_ahb_hif_ops_ipq5332 = {
static const struct ath12k_hif_ops ath12k_ahb_hif_ops = {
.start = ath12k_ahb_start,
.stop = ath12k_ahb_stop,
.read32 = ath12k_ahb_read32,
@@ -935,7 +927,8 @@ static int ath12k_ahb_resource_init(struct ath12k_base *ab)
goto err_mem_unmap;
}
ab->ce_remap = true;
ab->ce_remap_base_addr = HAL_IPQ5332_CE_WFSS_REG_BASE;
ab->cmem_offset = ce_remap->cmem_offset;
ab->ce_remap_base_addr = ce_remap->base;
}
ab_ahb->xo_clk = devm_clk_get(ab->dev, "xo");
@@ -988,13 +981,34 @@ static void ath12k_ahb_resource_deinit(struct ath12k_base *ab)
ab_ahb->xo_clk = NULL;
}
static enum ath12k_device_family
ath12k_ahb_get_device_family(const struct platform_device *pdev)
{
enum ath12k_device_family device_family_id;
struct ath12k_ahb_driver *driver;
const struct of_device_id *of_id;
for (device_family_id = ATH12K_DEVICE_FAMILY_START;
device_family_id < ATH12K_DEVICE_FAMILY_MAX; device_family_id++) {
driver = ath12k_ahb_family_drivers[device_family_id];
if (driver) {
of_id = of_match_device(driver->id_table, &pdev->dev);
if (of_id) {
/* Found the driver */
return device_family_id;
}
}
}
return ATH12K_DEVICE_FAMILY_MAX;
}
static int ath12k_ahb_probe(struct platform_device *pdev)
{
struct ath12k_base *ab;
const struct ath12k_hif_ops *hif_ops;
enum ath12k_device_family device_id;
struct ath12k_ahb *ab_ahb;
enum ath12k_hw_rev hw_rev;
u32 addr, userpd_id;
struct ath12k_base *ab;
u32 addr;
int ret;
ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
@@ -1008,25 +1022,32 @@ static int ath12k_ahb_probe(struct platform_device *pdev)
if (!ab)
return -ENOMEM;
hw_rev = (enum ath12k_hw_rev)(kernel_ulong_t)of_device_get_match_data(&pdev->dev);
switch (hw_rev) {
case ATH12K_HW_IPQ5332_HW10:
hif_ops = &ath12k_ahb_hif_ops_ipq5332;
userpd_id = ATH12K_IPQ5332_USERPD_ID;
break;
default:
ret = -EOPNOTSUPP;
ab_ahb = ath12k_ab_to_ahb(ab);
ab_ahb->ab = ab;
ab->hif.ops = &ath12k_ahb_hif_ops;
ab->pdev = pdev;
platform_set_drvdata(pdev, ab);
device_id = ath12k_ahb_get_device_family(pdev);
if (device_id >= ATH12K_DEVICE_FAMILY_MAX) {
ath12k_err(ab, "failed to get device family: %d\n", device_id);
ret = -EINVAL;
goto err_core_free;
}
ab->hif.ops = hif_ops;
ab->pdev = pdev;
ab->hw_rev = hw_rev;
ab->target_mem_mode = ATH12K_QMI_MEMORY_MODE_DEFAULT;
platform_set_drvdata(pdev, ab);
ab_ahb = ath12k_ab_to_ahb(ab);
ab_ahb->ab = ab;
ab_ahb->userpd_id = userpd_id;
ath12k_dbg(ab, ATH12K_DBG_AHB, "AHB device family id: %d\n", device_id);
ab_ahb->device_family_ops = &ath12k_ahb_family_drivers[device_id]->ops;
/* Call device specific probe. This is the callback that can
* be used to override any ops in future
* probe is validated for NULL during registration.
*/
ret = ab_ahb->device_family_ops->probe(pdev);
if (ret) {
ath12k_err(ab, "failed to probe device: %d\n", ret);
goto err_core_free;
}
/* Set fixed_mem_region to true for platforms that support fixed memory
* reservation from DT. If memory is reserved from DT for FW, ath12k driver
@@ -1065,14 +1086,26 @@ static int ath12k_ahb_probe(struct platform_device *pdev)
goto err_rproc_deconfigure;
}
ret = ath12k_core_init(ab);
/* Invoke arch_init here so that arch-specific init operations
* can utilize already initialized ab fields, such as HAL SRNGs.
*/
ret = ab_ahb->device_family_ops->arch_init(ab);
if (ret) {
ath12k_err(ab, "failed to init core: %d\n", ret);
ath12k_err(ab, "AHB arch_init failed %d\n", ret);
goto err_rproc_deconfigure;
}
ret = ath12k_core_init(ab);
if (ret) {
ath12k_err(ab, "failed to init core: %d\n", ret);
goto err_deinit_arch;
}
return 0;
err_deinit_arch:
ab_ahb->device_family_ops->arch_deinit(ab);
err_rproc_deconfigure:
ath12k_ahb_deconfigure_rproc(ab);
@@ -1111,11 +1144,13 @@ static void ath12k_ahb_remove_prepare(struct ath12k_base *ab)
static void ath12k_ahb_free_resources(struct ath12k_base *ab)
{
struct platform_device *pdev = ab->pdev;
struct ath12k_ahb *ab_ahb = ath12k_ab_to_ahb(ab);
ath12k_hal_srng_deinit(ab);
ath12k_ce_free_pipes(ab);
ath12k_ahb_resource_deinit(ab);
ath12k_ahb_deconfigure_rproc(ab);
ab_ahb->device_family_ops->arch_deinit(ab);
ath12k_core_free(ab);
platform_set_drvdata(pdev, NULL);
}
@@ -1136,21 +1171,47 @@ qmi_fail:
ath12k_ahb_free_resources(ab);
}
static struct platform_driver ath12k_ahb_driver = {
.driver = {
.name = "ath12k_ahb",
.of_match_table = ath12k_ahb_of_match,
},
.probe = ath12k_ahb_probe,
.remove = ath12k_ahb_remove,
};
int ath12k_ahb_init(void)
int ath12k_ahb_register_driver(const enum ath12k_device_family device_id,
struct ath12k_ahb_driver *driver)
{
return platform_driver_register(&ath12k_ahb_driver);
}
struct platform_driver *ahb_driver;
void ath12k_ahb_exit(void)
{
platform_driver_unregister(&ath12k_ahb_driver);
if (device_id >= ATH12K_DEVICE_FAMILY_MAX)
return -EINVAL;
if (!driver || !driver->ops.probe ||
!driver->ops.arch_init || !driver->ops.arch_deinit)
return -EINVAL;
if (ath12k_ahb_family_drivers[device_id]) {
pr_err("Driver already registered for id %d\n", device_id);
return -EALREADY;
}
ath12k_ahb_family_drivers[device_id] = driver;
ahb_driver = &ath12k_ahb_family_drivers[device_id]->driver;
ahb_driver->driver.name = driver->name;
ahb_driver->driver.of_match_table = driver->id_table;
ahb_driver->probe = ath12k_ahb_probe;
ahb_driver->remove = ath12k_ahb_remove;
return platform_driver_register(ahb_driver);
}
EXPORT_SYMBOL(ath12k_ahb_register_driver);
void ath12k_ahb_unregister_driver(const enum ath12k_device_family device_id)
{
struct platform_driver *ahb_driver;
if (device_id >= ATH12K_DEVICE_FAMILY_MAX)
return;
if (!ath12k_ahb_family_drivers[device_id])
return;
ahb_driver = &ath12k_ahb_family_drivers[device_id]->driver;
platform_driver_unregister(ahb_driver);
ath12k_ahb_family_drivers[device_id] = NULL;
}
EXPORT_SYMBOL(ath12k_ahb_unregister_driver);
+20 -11
View File
@@ -1,13 +1,14 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
* Copyright (c) 2022-2025, Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#ifndef ATH12K_AHB_H
#define ATH12K_AHB_H
#include <linux/clk.h>
#include <linux/remoteproc/qcom_rproc.h>
#include <linux/platform_device.h>
#include "core.h"
#define ATH12K_AHB_RECOVERY_TIMEOUT (3 * HZ)
@@ -43,6 +44,12 @@ enum ath12k_ahb_userpd_irq {
struct ath12k_base;
struct ath12k_ahb_device_family_ops {
int (*probe)(struct platform_device *pdev);
int (*arch_init)(struct ath12k_base *ab);
void (*arch_deinit)(struct ath12k_base *ab);
};
struct ath12k_ahb {
struct ath12k_base *ab;
struct rproc *tgt_rproc;
@@ -59,6 +66,15 @@ struct ath12k_ahb {
u32 spawn_bit;
u32 stop_bit;
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;
};
struct ath12k_ahb_driver {
const char *name;
const struct of_device_id *id_table;
struct ath12k_ahb_device_family_ops ops;
struct platform_driver driver;
};
static inline struct ath12k_ahb *ath12k_ab_to_ahb(struct ath12k_base *ab)
@@ -66,15 +82,8 @@ static inline struct ath12k_ahb *ath12k_ab_to_ahb(struct ath12k_base *ab)
return (struct ath12k_ahb *)ab->drv_priv;
}
#ifdef CONFIG_ATH12K_AHB
int ath12k_ahb_init(void);
void ath12k_ahb_exit(void);
#else
static inline int ath12k_ahb_init(void)
{
return 0;
}
int ath12k_ahb_register_driver(const enum ath12k_device_family device_id,
struct ath12k_ahb_driver *driver);
void ath12k_ahb_unregister_driver(const enum ath12k_device_family device_id);
static inline void ath12k_ahb_exit(void) {};
#endif
#endif
+15 -311
View File
@@ -1,314 +1,13 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
* Copyright (c) 2021-2022, 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include "dp_rx.h"
#include "debug.h"
#include "hif.h"
const struct ce_attr ath12k_host_ce_config_qcn9274[] = {
/* CE0: host->target HTC control and raw streams */
{
.flags = CE_ATTR_FLAGS,
.src_nentries = 16,
.src_sz_max = 2048,
.dest_nentries = 0,
},
/* CE1: target->host HTT + HTC control */
{
.flags = CE_ATTR_FLAGS,
.src_nentries = 0,
.src_sz_max = 2048,
.dest_nentries = 512,
.recv_cb = ath12k_htc_rx_completion_handler,
},
/* CE2: target->host WMI */
{
.flags = CE_ATTR_FLAGS,
.src_nentries = 0,
.src_sz_max = 2048,
.dest_nentries = 128,
.recv_cb = ath12k_htc_rx_completion_handler,
},
/* CE3: host->target WMI (mac0) */
{
.flags = CE_ATTR_FLAGS,
.src_nentries = 32,
.src_sz_max = 2048,
.dest_nentries = 0,
},
/* CE4: host->target HTT */
{
.flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
.src_nentries = 2048,
.src_sz_max = 256,
.dest_nentries = 0,
},
/* CE5: target->host pktlog */
{
.flags = CE_ATTR_FLAGS,
.src_nentries = 0,
.src_sz_max = 2048,
.dest_nentries = 512,
.recv_cb = ath12k_dp_htt_htc_t2h_msg_handler,
},
/* CE6: target autonomous hif_memcpy */
{
.flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
.src_nentries = 0,
.src_sz_max = 0,
.dest_nentries = 0,
},
/* CE7: host->target WMI (mac1) */
{
.flags = CE_ATTR_FLAGS,
.src_nentries = 32,
.src_sz_max = 2048,
.dest_nentries = 0,
},
/* CE8: target autonomous hif_memcpy */
{
.flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
.src_nentries = 0,
.src_sz_max = 0,
.dest_nentries = 0,
},
/* CE9: MHI */
{
.flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
.src_nentries = 0,
.src_sz_max = 0,
.dest_nentries = 0,
},
/* CE10: MHI */
{
.flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
.src_nentries = 0,
.src_sz_max = 0,
.dest_nentries = 0,
},
/* CE11: MHI */
{
.flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
.src_nentries = 0,
.src_sz_max = 0,
.dest_nentries = 0,
},
/* CE12: CV Prefetch */
{
.flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
.src_nentries = 0,
.src_sz_max = 0,
.dest_nentries = 0,
},
/* CE13: CV Prefetch */
{
.flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
.src_nentries = 0,
.src_sz_max = 0,
.dest_nentries = 0,
},
/* CE14: target->host dbg log */
{
.flags = CE_ATTR_FLAGS,
.src_nentries = 0,
.src_sz_max = 2048,
.dest_nentries = 512,
.recv_cb = ath12k_htc_rx_completion_handler,
},
/* CE15: reserved for future use */
{
.flags = (CE_ATTR_FLAGS | CE_ATTR_DIS_INTR),
.src_nentries = 0,
.src_sz_max = 0,
.dest_nentries = 0,
},
};
const struct ce_attr ath12k_host_ce_config_wcn7850[] = {
/* CE0: host->target HTC control and raw streams */
{
.flags = CE_ATTR_FLAGS,
.src_nentries = 16,
.src_sz_max = 2048,
.dest_nentries = 0,
},
/* CE1: target->host HTT + HTC control */
{
.flags = CE_ATTR_FLAGS,
.src_nentries = 0,
.src_sz_max = 2048,
.dest_nentries = 512,
.recv_cb = ath12k_htc_rx_completion_handler,
},
/* CE2: target->host WMI */
{
.flags = CE_ATTR_FLAGS,
.src_nentries = 0,
.src_sz_max = 2048,
.dest_nentries = 64,
.recv_cb = ath12k_htc_rx_completion_handler,
},
/* CE3: host->target WMI (mac0) */
{
.flags = CE_ATTR_FLAGS,
.src_nentries = 32,
.src_sz_max = 2048,
.dest_nentries = 0,
},
/* CE4: host->target HTT */
{
.flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
.src_nentries = 2048,
.src_sz_max = 256,
.dest_nentries = 0,
},
/* CE5: target->host pktlog */
{
.flags = CE_ATTR_FLAGS,
.src_nentries = 0,
.src_sz_max = 0,
.dest_nentries = 0,
},
/* CE6: target autonomous hif_memcpy */
{
.flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
.src_nentries = 0,
.src_sz_max = 0,
.dest_nentries = 0,
},
/* CE7: host->target WMI (mac1) */
{
.flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
.src_nentries = 0,
.src_sz_max = 2048,
.dest_nentries = 0,
},
/* CE8: target autonomous hif_memcpy */
{
.flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
.src_nentries = 0,
.src_sz_max = 0,
.dest_nentries = 0,
},
};
const struct ce_attr ath12k_host_ce_config_ipq5332[] = {
/* CE0: host->target HTC control and raw streams */
{
.flags = CE_ATTR_FLAGS,
.src_nentries = 16,
.src_sz_max = 2048,
.dest_nentries = 0,
},
/* CE1: target->host HTT + HTC control */
{
.flags = CE_ATTR_FLAGS,
.src_nentries = 0,
.src_sz_max = 2048,
.dest_nentries = 512,
.recv_cb = ath12k_htc_rx_completion_handler,
},
/* CE2: target->host WMI */
{
.flags = CE_ATTR_FLAGS,
.src_nentries = 0,
.src_sz_max = 2048,
.dest_nentries = 128,
.recv_cb = ath12k_htc_rx_completion_handler,
},
/* CE3: host->target WMI */
{
.flags = CE_ATTR_FLAGS,
.src_nentries = 32,
.src_sz_max = 2048,
.dest_nentries = 0,
},
/* CE4: host->target HTT */
{
.flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
.src_nentries = 2048,
.src_sz_max = 256,
.dest_nentries = 0,
},
/* CE5: target -> host PKTLOG */
{
.flags = CE_ATTR_FLAGS,
.src_nentries = 0,
.src_sz_max = 2048,
.dest_nentries = 512,
.recv_cb = ath12k_dp_htt_htc_t2h_msg_handler,
},
/* CE6: Target autonomous HIF_memcpy */
{
.flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
.src_nentries = 0,
.src_sz_max = 0,
.dest_nentries = 0,
},
/* CE7: CV Prefetch */
{
.flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
.src_nentries = 0,
.src_sz_max = 0,
.dest_nentries = 0,
},
/* CE8: Target HIF memcpy (Generic HIF memcypy) */
{
.flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
.src_nentries = 0,
.src_sz_max = 0,
.dest_nentries = 0,
},
/* CE9: WMI logging/CFR/Spectral/Radar */
{
.flags = CE_ATTR_FLAGS,
.src_nentries = 0,
.src_sz_max = 2048,
.dest_nentries = 128,
},
/* CE10: Unused */
{
.flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
.src_nentries = 0,
.src_sz_max = 0,
.dest_nentries = 0,
},
/* CE11: Unused */
{
.flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
.src_nentries = 0,
.src_sz_max = 0,
.dest_nentries = 0,
},
};
static int ath12k_ce_rx_buf_enqueue_pipe(struct ath12k_ce_pipe *pipe,
struct sk_buff *skb, dma_addr_t paddr)
{
@@ -341,7 +40,7 @@ static int ath12k_ce_rx_buf_enqueue_pipe(struct ath12k_ce_pipe *pipe,
goto exit;
}
ath12k_hal_ce_dst_set_desc(desc, paddr);
ath12k_hal_ce_dst_set_desc(&ab->hal, desc, paddr);
ring->skb[write_index] = skb;
write_index = CE_RING_IDX_INCR(nentries_mask, write_index);
@@ -434,7 +133,7 @@ static int ath12k_ce_completed_recv_next(struct ath12k_ce_pipe *pipe,
goto err;
}
*nbytes = ath12k_hal_ce_dst_status_get_length(desc);
*nbytes = ath12k_hal_ce_dst_status_get_length(&ab->hal, desc);
*skb = pipe->dest_ring->skb[sw_index];
pipe->dest_ring->skb[sw_index] = NULL;
@@ -666,6 +365,7 @@ ath12k_ce_alloc_ring(struct ath12k_base *ab, int nentries, int desc_sz)
static int ath12k_ce_alloc_pipe(struct ath12k_base *ab, int ce_id)
{
struct ath12k_hal *hal = &ab->hal;
struct ath12k_ce_pipe *pipe = &ab->ce.ce_pipe[ce_id];
const struct ce_attr *attr = &ab->hw_params->host_ce_config[ce_id];
struct ath12k_ce_ring *ring;
@@ -677,7 +377,7 @@ static int ath12k_ce_alloc_pipe(struct ath12k_base *ab, int ce_id)
if (attr->src_nentries) {
pipe->send_cb = ath12k_ce_send_done_cb;
nentries = roundup_pow_of_two(attr->src_nentries);
desc_sz = ath12k_hal_ce_get_desc_size(HAL_CE_DESC_SRC);
desc_sz = ath12k_hal_ce_get_desc_size(hal, HAL_CE_DESC_SRC);
ring = ath12k_ce_alloc_ring(ab, nentries, desc_sz);
if (IS_ERR(ring))
return PTR_ERR(ring);
@@ -687,13 +387,13 @@ static int ath12k_ce_alloc_pipe(struct ath12k_base *ab, int ce_id)
if (attr->dest_nentries) {
pipe->recv_cb = attr->recv_cb;
nentries = roundup_pow_of_two(attr->dest_nentries);
desc_sz = ath12k_hal_ce_get_desc_size(HAL_CE_DESC_DST);
desc_sz = ath12k_hal_ce_get_desc_size(hal, HAL_CE_DESC_DST);
ring = ath12k_ce_alloc_ring(ab, nentries, desc_sz);
if (IS_ERR(ring))
return PTR_ERR(ring);
pipe->dest_ring = ring;
desc_sz = ath12k_hal_ce_get_desc_size(HAL_CE_DESC_DST_STATUS);
desc_sz = ath12k_hal_ce_get_desc_size(hal, HAL_CE_DESC_DST_STATUS);
ring = ath12k_ce_alloc_ring(ab, nentries, desc_sz);
if (IS_ERR(ring))
return PTR_ERR(ring);
@@ -786,7 +486,7 @@ int ath12k_ce_send(struct ath12k_base *ab, struct sk_buff *skb, u8 pipe_id,
if (pipe->attr_flags & CE_ATTR_BYTE_SWAP_DATA)
byte_swap_data = 1;
ath12k_hal_ce_src_set_desc(desc, ATH12K_SKB_CB(skb)->paddr,
ath12k_hal_ce_src_set_desc(&ab->hal, desc, ATH12K_SKB_CB(skb)->paddr,
skb->len, transfer_id, byte_swap_data);
pipe->src_ring->skb[write_index] = skb;
@@ -972,6 +672,7 @@ int ath12k_ce_init_pipes(struct ath12k_base *ab)
void ath12k_ce_free_pipes(struct ath12k_base *ab)
{
struct ath12k_hal *hal = &ab->hal;
struct ath12k_ce_pipe *pipe;
int desc_sz;
int i;
@@ -980,7 +681,8 @@ void ath12k_ce_free_pipes(struct ath12k_base *ab)
pipe = &ab->ce.ce_pipe[i];
if (pipe->src_ring) {
desc_sz = ath12k_hal_ce_get_desc_size(HAL_CE_DESC_SRC);
desc_sz = ath12k_hal_ce_get_desc_size(hal,
HAL_CE_DESC_SRC);
dma_free_coherent(ab->dev,
pipe->src_ring->nentries * desc_sz +
CE_DESC_RING_ALIGN,
@@ -991,7 +693,8 @@ void ath12k_ce_free_pipes(struct ath12k_base *ab)
}
if (pipe->dest_ring) {
desc_sz = ath12k_hal_ce_get_desc_size(HAL_CE_DESC_DST);
desc_sz = ath12k_hal_ce_get_desc_size(hal,
HAL_CE_DESC_DST);
dma_free_coherent(ab->dev,
pipe->dest_ring->nentries * desc_sz +
CE_DESC_RING_ALIGN,
@@ -1003,7 +706,8 @@ void ath12k_ce_free_pipes(struct ath12k_base *ab)
if (pipe->status_ring) {
desc_sz =
ath12k_hal_ce_get_desc_size(HAL_CE_DESC_DST_STATUS);
ath12k_hal_ce_get_desc_size(hal,
HAL_CE_DESC_DST_STATUS);
dma_free_coherent(ab->dev,
pipe->status_ring->nentries * desc_sz +
CE_DESC_RING_ALIGN,
+2 -5
View File
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
* Copyright (c) 2021-2022, 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#ifndef ATH12K_CE_H
@@ -85,6 +85,7 @@ struct ce_ie_addr {
struct ce_remap {
u32 base;
u32 size;
u32 cmem_offset;
};
struct ce_attr {
@@ -173,10 +174,6 @@ struct ath12k_ce {
struct ath12k_hp_update_timer hp_timer[CE_COUNT_MAX];
};
extern const struct ce_attr ath12k_host_ce_config_qcn9274[];
extern const struct ce_attr ath12k_host_ce_config_wcn7850[];
extern const struct ce_attr ath12k_host_ce_config_ipq5332[];
void ath12k_ce_cleanup_pipes(struct ath12k_base *ab);
void ath12k_ce_rx_replenish_retry(struct timer_list *t);
void ath12k_ce_per_engine_service(struct ath12k_base *ab, u16 ce_id);
@@ -0,0 +1,20 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#ifndef ATH12K_CMN_DEFS_H
#define ATH12K_CMN_DEFS_H
#include <net/mac80211.h>
#define MAX_RADIOS 2
#define ATH12K_MAX_DEVICES 3
#define ATH12K_GROUP_MAX_RADIO (ATH12K_MAX_DEVICES * MAX_RADIOS)
#define ATH12K_SCAN_MAX_LINKS ATH12K_GROUP_MAX_RADIO
/* Define 1 scan link for each radio for parallel scan purposes */
#define ATH12K_NUM_MAX_LINKS (IEEE80211_MLD_MAX_NUM_LINKS + ATH12K_SCAN_MAX_LINKS)
#define MAX_MU_GROUP_ID 64
#endif
+29 -46
View File
@@ -21,15 +21,18 @@
#include "hif.h"
#include "pci.h"
#include "wow.h"
#include "dp_cmn.h"
#include "peer.h"
static int ahb_err, pci_err;
unsigned int ath12k_debug_mask;
module_param_named(debug_mask, ath12k_debug_mask, uint, 0644);
MODULE_PARM_DESC(debug_mask, "Debugging mask");
EXPORT_SYMBOL(ath12k_debug_mask);
bool ath12k_ftm_mode;
module_param_named(ftm_mode, ath12k_ftm_mode, bool, 0444);
MODULE_PARM_DESC(ftm_mode, "Boots up in factory test mode");
EXPORT_SYMBOL(ath12k_ftm_mode);
/* protected with ath12k_hw_group_mutex */
static struct list_head ath12k_hw_group_list = LIST_HEAD_INIT(ath12k_hw_group_list);
@@ -632,6 +635,7 @@ u32 ath12k_core_get_max_peers_per_radio(struct ath12k_base *ab)
{
return ath12k_core_get_max_station_per_radio(ab) + TARGET_NUM_VDEVS(ab);
}
EXPORT_SYMBOL(ath12k_core_get_max_peers_per_radio);
struct reserved_mem *ath12k_core_get_reserved_mem(struct ath12k_base *ab,
int index)
@@ -700,6 +704,8 @@ void ath12k_core_to_group_ref_put(struct ath12k_base *ab)
static void ath12k_core_stop(struct ath12k_base *ab)
{
ath12k_link_sta_rhash_tbl_destroy(ab);
ath12k_core_to_group_ref_put(ab);
if (!test_bit(ATH12K_FLAG_CRASH_FLUSH, &ab->dev_flags))
@@ -710,7 +716,7 @@ static void ath12k_core_stop(struct ath12k_base *ab)
ath12k_dp_rx_pdev_reo_cleanup(ab);
ath12k_hif_stop(ab);
ath12k_wmi_detach(ab);
ath12k_dp_free(ab);
ath12k_dp_cmn_device_deinit(ath12k_ab_to_dp(ab));
/* De-Init of components as needed */
}
@@ -895,7 +901,7 @@ static int ath12k_core_start(struct ath12k_base *ab)
goto err_hif_stop;
}
ret = ath12k_dp_htt_connect(&ab->dp);
ret = ath12k_dp_htt_connect(ath12k_ab_to_dp(ab));
if (ret) {
ath12k_err(ab, "failed to connect to HTT: %d\n", ret);
goto err_hif_stop;
@@ -920,7 +926,7 @@ static int ath12k_core_start(struct ath12k_base *ab)
goto err_hif_stop;
}
ath12k_dp_cc_config(ab);
ath12k_hal_cc_config(ab);
ret = ath12k_dp_rx_pdev_reo_setup(ab);
if (ret) {
@@ -928,8 +934,6 @@ static int ath12k_core_start(struct ath12k_base *ab)
goto err_hif_stop;
}
ath12k_dp_hal_rx_desc_init(ab);
ret = ath12k_wmi_cmd_init(ab);
if (ret) {
ath12k_err(ab, "failed to send wmi init cmd: %d\n", ret);
@@ -964,6 +968,12 @@ static int ath12k_core_start(struct ath12k_base *ab)
/* Indicate the core start in the appropriate group */
ath12k_core_to_group_ref_get(ab);
ret = ath12k_link_sta_rhash_tbl_init(ab);
if (ret) {
ath12k_warn(ab, "failed to init peer addr rhash table %d\n", ret);
goto err_reo_cleanup;
}
return 0;
err_reo_cleanup:
@@ -1288,7 +1298,7 @@ int ath12k_core_qmi_firmware_ready(struct ath12k_base *ab)
goto err_firmware_stop;
}
ret = ath12k_dp_alloc(ab);
ret = ath12k_dp_cmn_device_init(ath12k_ab_to_dp(ab));
if (ret) {
ath12k_err(ab, "failed to init DP: %d\n", ret);
goto err_firmware_stop;
@@ -1300,7 +1310,7 @@ int ath12k_core_qmi_firmware_ready(struct ath12k_base *ab)
ret = ath12k_core_start(ab);
if (ret) {
ath12k_err(ab, "failed to start core: %d\n", ret);
goto err_dp_free;
goto err_deinit;
}
mutex_unlock(&ab->core_lock);
@@ -1333,8 +1343,8 @@ err_core_stop:
mutex_unlock(&ag->mutex);
goto exit;
err_dp_free:
ath12k_dp_free(ab);
err_deinit:
ath12k_dp_cmn_device_deinit(ath12k_ab_to_dp(ab));
mutex_unlock(&ab->core_lock);
mutex_unlock(&ag->mutex);
@@ -1350,13 +1360,14 @@ static int ath12k_core_reconfigure_on_crash(struct ath12k_base *ab)
int ret, total_vdev;
mutex_lock(&ab->core_lock);
ath12k_link_sta_rhash_tbl_destroy(ab);
ath12k_dp_pdev_free(ab);
ath12k_ce_cleanup_pipes(ab);
ath12k_wmi_detach(ab);
ath12k_dp_rx_pdev_reo_cleanup(ab);
mutex_unlock(&ab->core_lock);
ath12k_dp_free(ab);
ath12k_dp_cmn_device_deinit(ath12k_ab_to_dp(ab));
ath12k_hal_srng_deinit(ab);
total_vdev = ab->num_radios * TARGET_NUM_VDEVS(ab);
ab->free_vdev_map = (1LL << total_vdev) - 1;
@@ -1565,6 +1576,7 @@ static void ath12k_core_post_reconfigure_recovery(struct ath12k_base *ab)
ath12k_core_halt(ar);
}
ath12k_mac_dp_peer_cleanup(ah);
break;
case ATH12K_HW_STATE_OFF:
ath12k_warn(ab,
@@ -1739,17 +1751,11 @@ enum ath12k_qmi_mem_mode ath12k_core_get_memory_mode(struct ath12k_base *ab)
return ATH12K_QMI_MEMORY_MODE_DEFAULT;
}
EXPORT_SYMBOL(ath12k_core_get_memory_mode);
int ath12k_core_pre_init(struct ath12k_base *ab)
{
const struct ath12k_mem_profile_based_param *param;
int ret;
ret = ath12k_hw_init(ab);
if (ret) {
ath12k_err(ab, "failed to init hw params: %d\n", ret);
return ret;
}
param = &ath12k_mem_profile_based_param[ab->target_mem_mode];
ab->profile_param = param;
@@ -1996,6 +2002,8 @@ exit:
ag->ab[ab->device_id] = ab;
ab->ag = ag;
ath12k_dp_cmn_hw_group_assign(ath12k_ab_to_dp(ab), ag);
ath12k_dbg(ab, ATH12K_DBG_BOOT, "wsi group-id %d num-devices %d index %d",
ag->id, ag->num_devices, wsi->index);
@@ -2023,6 +2031,8 @@ void ath12k_core_hw_group_unassign(struct ath12k_base *ab)
return;
}
ath12k_dp_cmn_hw_group_unassign(ath12k_ab_to_dp(ab), ag);
ag->ab[device_id] = NULL;
ab->ag = NULL;
ab->device_id = ATH12K_INVALID_DEVICE_ID;
@@ -2253,7 +2263,6 @@ struct ath12k_base *ath12k_core_alloc(struct device *dev, size_t priv_size,
spin_lock_init(&ab->base_lock);
init_completion(&ab->reset_complete);
INIT_LIST_HEAD(&ab->peers);
init_waitqueue_head(&ab->peer_mapping_wq);
init_waitqueue_head(&ab->wmi_ab.tx_credits_wq);
INIT_WORK(&ab->restart_work, ath12k_core_restart);
@@ -2291,31 +2300,5 @@ err_sc_free:
return NULL;
}
static int ath12k_init(void)
{
ahb_err = ath12k_ahb_init();
if (ahb_err)
pr_warn("Failed to initialize ath12k AHB device: %d\n", ahb_err);
pci_err = ath12k_pci_init();
if (pci_err)
pr_warn("Failed to initialize ath12k PCI device: %d\n", pci_err);
/* If both failed, return one of the failures (arbitrary) */
return ahb_err && pci_err ? ahb_err : 0;
}
static void ath12k_exit(void)
{
if (!pci_err)
ath12k_pci_exit();
if (!ahb_err)
ath12k_ahb_exit();
}
module_init(ath12k_init);
module_exit(ath12k_exit);
MODULE_DESCRIPTION("Driver support for Qualcomm Technologies 802.11be WLAN devices");
MODULE_DESCRIPTION("Driver support for Qualcomm Technologies WLAN devices");
MODULE_LICENSE("Dual BSD/GPL");
+43 -133
View File
@@ -18,6 +18,7 @@
#include <linux/panic_notifier.h>
#include <linux/average.h>
#include <linux/of.h>
#include <linux/rhashtable.h>
#include "qmi.h"
#include "htc.h"
#include "wmi.h"
@@ -26,7 +27,6 @@
#include "ce.h"
#include "mac.h"
#include "hw.h"
#include "hal_rx.h"
#include "reg.h"
#include "dbring.h"
#include "fw.h"
@@ -34,6 +34,8 @@
#include "wow.h"
#include "debugfs_htt_stats.h"
#include "coredump.h"
#include "cmn_defs.h"
#include "dp_cmn.h"
#define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK)
@@ -64,8 +66,6 @@
#define ATH12K_RECONFIGURE_TIMEOUT_HZ (10 * HZ)
#define ATH12K_RECOVER_START_TIMEOUT_HZ (20 * HZ)
#define ATH12K_MAX_DEVICES 3
#define ATH12K_GROUP_MAX_RADIO (ATH12K_MAX_DEVICES * MAX_RADIOS)
#define ATH12K_INVALID_GROUP_ID 0xFF
#define ATH12K_INVALID_DEVICE_ID 0xFF
@@ -310,16 +310,9 @@ struct ath12k_link_vif {
u32 vdev_id;
u32 beacon_interval;
u32 dtim_period;
u16 ast_hash;
u16 ast_idx;
u16 tcl_metadata;
u8 hal_addr_search_flags;
u8 search_type;
struct ath12k *ar;
int bank_id;
u8 vdev_id_check_en;
bool beacon_prot;
struct wmi_wmm_params_all_arg wmm_params;
@@ -360,6 +353,8 @@ struct ath12k_link_vif {
};
struct ath12k_vif {
struct ath12k_dp_vif dp_vif;
enum wmi_vdev_type vdev_type;
enum wmi_vdev_subtype vdev_subtype;
struct ieee80211_vif *vif;
@@ -383,10 +378,7 @@ struct ath12k_vif {
} u;
u32 aid;
u32 key_cipher;
u8 tx_encap_type;
bool ps;
atomic_t mcbc_gsn;
struct ath12k_link_vif deflink;
struct ath12k_link_vif __rcu *link[ATH12K_NUM_MAX_LINKS];
@@ -407,51 +399,8 @@ struct ath12k_vif_iter {
struct ath12k_link_vif *arvif;
};
#define HAL_AST_IDX_INVALID 0xFFFF
#define HAL_RX_MAX_MCS 12
#define HAL_RX_MAX_MCS_HT 31
#define HAL_RX_MAX_MCS_VHT 9
#define HAL_RX_MAX_MCS_HE 11
#define HAL_RX_MAX_MCS_BE 15
#define HAL_RX_MAX_NSS 8
#define HAL_RX_MAX_NUM_LEGACY_RATES 12
#define ATH12K_SCAN_TIMEOUT_HZ (20 * HZ)
struct ath12k_rx_peer_rate_stats {
u64 ht_mcs_count[HAL_RX_MAX_MCS_HT + 1];
u64 vht_mcs_count[HAL_RX_MAX_MCS_VHT + 1];
u64 he_mcs_count[HAL_RX_MAX_MCS_HE + 1];
u64 be_mcs_count[HAL_RX_MAX_MCS_BE + 1];
u64 nss_count[HAL_RX_MAX_NSS];
u64 bw_count[HAL_RX_BW_MAX];
u64 gi_count[HAL_RX_GI_MAX];
u64 legacy_count[HAL_RX_MAX_NUM_LEGACY_RATES];
u64 rx_rate[HAL_RX_BW_MAX][HAL_RX_GI_MAX][HAL_RX_MAX_NSS][HAL_RX_MAX_MCS_HT + 1];
};
struct ath12k_rx_peer_stats {
u64 num_msdu;
u64 num_mpdu_fcs_ok;
u64 num_mpdu_fcs_err;
u64 tcp_msdu_count;
u64 udp_msdu_count;
u64 other_msdu_count;
u64 ampdu_msdu_count;
u64 non_ampdu_msdu_count;
u64 stbc_count;
u64 beamformed_count;
u64 coding_count[HAL_RX_SU_MU_CODING_MAX];
u64 tid_count[IEEE80211_NUM_TIDS + 1];
u64 pream_cnt[HAL_RX_PREAMBLE_MAX];
u64 reception_type[HAL_RX_RECEPTION_TYPE_MAX];
u64 rx_duration;
u64 dcm_count;
u64 ru_alloc_cnt[HAL_RX_RU_ALLOC_TYPE_MAX];
struct ath12k_rx_peer_rate_stats pkt_stats;
struct ath12k_rx_peer_rate_stats byte_stats;
};
#define ATH12K_HE_MCS_NUM 12
#define ATH12K_VHT_MCS_NUM 10
#define ATH12K_BW_NUM 5
@@ -533,12 +482,6 @@ struct ath12k_per_ppdu_tx_stats {
u32 retry_bytes;
};
struct ath12k_wbm_tx_stats {
u64 wbm_tx_comp_stats[HAL_WBM_REL_HTT_TX_COMP_STATUS_MAX];
};
DECLARE_EWMA(avg_rssi, 10, 8)
struct ath12k_link_sta {
struct ath12k_link_vif *arvif;
struct ath12k_sta *ahsta;
@@ -553,15 +496,7 @@ struct ath12k_link_sta {
u32 smps;
struct wiphy_work update_wk;
struct rate_info txrate;
struct rate_info last_txrate;
u64 rx_duration;
u64 tx_duration;
u8 rssi_comb;
struct ewma_avg_rssi avg_rssi;
u8 link_id;
struct ath12k_rx_peer_stats *rx_stats;
struct ath12k_wbm_tx_stats *wbm_tx_stats;
u32 bw_prev;
u32 peer_nss;
s8 rssi_beacon;
@@ -572,14 +507,9 @@ struct ath12k_link_sta {
/* for firmware use only */
u8 link_idx;
u32 tx_retry_failed;
u32 tx_retry_count;
};
struct ath12k_reoq_buf {
void *vaddr;
dma_addr_t paddr_aligned;
u32 size;
/* peer addr based rhashtable list pointer */
struct rhash_head rhash_addr;
};
struct ath12k_sta {
@@ -594,8 +524,6 @@ struct ath12k_sta {
u8 num_peer;
enum ieee80211_sta_state state;
struct ath12k_reoq_buf reoq_bufs[IEEE80211_NUM_TIDS + 1];
};
#define ATH12K_HALF_20MHZ_BW 10
@@ -667,23 +595,6 @@ struct ath12k_debug {
bool extd_rx_stats;
};
struct ath12k_per_peer_tx_stats {
u32 succ_bytes;
u32 retry_bytes;
u32 failed_bytes;
u32 duration;
u16 succ_pkts;
u16 retry_pkts;
u16 failed_pkts;
u16 ru_start;
u16 ru_tones;
u8 ba_fails;
u8 ppdu_type;
u32 mu_grpid;
u32 mu_pos;
bool is_ampdu;
};
struct ath12k_pdev_rssi_offsets {
s32 temp_offset;
s8 min_nf_dbm;
@@ -809,9 +720,6 @@ struct ath12k {
struct ath12k_wow wow;
struct completion target_suspend;
bool target_suspend_ack;
struct ath12k_per_peer_tx_stats peer_tx_stats;
struct list_head ppdu_stats_info;
u32 ppdu_stat_list_depth;
struct ath12k_per_peer_tx_stats cached_stats;
u32 last_ppdu_id;
@@ -866,8 +774,7 @@ struct ath12k_hw {
DECLARE_BITMAP(free_ml_peer_id_map, ATH12K_MAX_MLO_PEERS);
/* protected by wiphy_lock() */
struct list_head ml_peers;
struct ath12k_dp_hw dp_hw;
/* Keep last */
struct ath12k radio[] __aligned(sizeof(void *));
@@ -941,32 +848,6 @@ struct ath12k_board_data {
size_t len;
};
struct ath12k_device_dp_tx_err_stats {
/* TCL Ring Descriptor unavailable */
u32 desc_na[DP_TCL_NUM_RING_MAX];
/* Other failures during dp_tx due to mem allocation failure
* idr unavailable etc.
*/
atomic_t misc_fail;
};
struct ath12k_device_dp_stats {
u32 err_ring_pkts;
u32 invalid_rbm;
u32 rxdma_error[HAL_REO_ENTR_RING_RXDMA_ECODE_MAX];
u32 reo_error[HAL_REO_DEST_RING_ERROR_CODE_MAX];
u32 hal_reo_error[DP_REO_DST_RING_MAX];
struct ath12k_device_dp_tx_err_stats tx_err;
u32 reo_rx[DP_REO_DST_RING_MAX][ATH12K_MAX_DEVICES];
u32 rx_wbm_rel_source[HAL_WBM_REL_SRC_MODULE_MAX][ATH12K_MAX_DEVICES];
u32 tqm_rel_reason[MAX_TQM_RELEASE_REASON];
u32 fw_tx_status[MAX_FW_TX_STATUS];
u32 tx_wbm_rel_source[HAL_WBM_REL_SRC_MODULE_MAX];
u32 tx_enqueued[DP_TCL_NUM_RING_MAX];
u32 tx_completed[DP_TCL_NUM_RING_MAX];
u32 reo_excep_msdu_buf_type;
};
struct ath12k_reg_freq {
u32 start_freq;
u32 end_freq;
@@ -987,6 +868,11 @@ struct ath12k_hw_link {
* wiphy, protected with struct ath12k_hw_group::mutex.
*/
struct ath12k_hw_group {
/* Keep dp_hw_grp as the first member to allow efficient
* usage of cache lines for DP fields
*/
struct ath12k_dp_hw_group dp_hw_grp;
struct ath12k_hw_link hw_links[ATH12K_GROUP_MAX_RADIO];
struct list_head list;
u8 id;
u8 num_devices;
@@ -1009,7 +895,6 @@ struct ath12k_hw_group {
bool mlo_capable;
struct device_node *wsi_node[ATH12K_MAX_DEVICES];
struct ath12k_mlo_memory mlo_mem;
struct ath12k_hw_link hw_links[ATH12K_GROUP_MAX_RADIO];
bool hw_link_id_init_done;
};
@@ -1035,6 +920,12 @@ struct ath12k_mem_profile_based_param {
struct ath12k_dp_profile_params dp_params;
};
enum ath12k_device_family {
ATH12K_DEVICE_FAMILY_START,
ATH12K_DEVICE_FAMILY_WIFI7 = ATH12K_DEVICE_FAMILY_START,
ATH12K_DEVICE_FAMILY_MAX,
};
/* Master structure to hold the hw data which may be used in core module */
struct ath12k_base {
enum ath12k_hw_rev hw_rev;
@@ -1054,13 +945,14 @@ struct ath12k_base {
struct ath12k_htc htc;
struct ath12k_dp dp;
struct ath12k_dp *dp;
void __iomem *mem;
unsigned long mem_len;
void __iomem *mem_ce;
u32 ce_remap_base_addr;
u32 cmem_offset;
bool ce_remap;
struct {
@@ -1105,7 +997,6 @@ struct ath12k_base {
struct ath12k_wmi_hal_reg_capabilities_ext_arg hal_reg_cap[MAX_RADIOS];
unsigned long long free_vdev_map;
unsigned long long free_vdev_stats_id_map;
struct list_head peers;
wait_queue_head_t peer_mapping_wq;
u8 mac_addr[ETH_ALEN];
bool wmi_ready;
@@ -1135,7 +1026,6 @@ struct ath12k_base {
/* Current DFS Regulatory */
enum ath12k_dfs_region dfs_region;
struct ath12k_device_dp_stats device_stats;
#ifdef CONFIG_ATH12K_DEBUGFS
struct dentry *debugfs_soc;
#endif
@@ -1196,8 +1086,6 @@ struct ath12k_base {
bool fw_features_valid;
} fw;
const struct hal_rx_ops *hal_rx_ops;
struct completion restart_completed;
#ifdef CONFIG_ACPI
@@ -1241,6 +1129,14 @@ struct ath12k_base {
const struct ath12k_mem_profile_based_param *profile_param;
enum ath12k_qmi_mem_mode target_mem_mode;
/* FIXME: Define this field in a ag equivalent object available
* during the initial phase of probe later.
*/
const struct ieee80211_ops *ath12k_ops;
struct rhashtable *rhead_sta_addr;
struct rhashtable_params rhash_sta_addr_param;
/* must be last */
u8 drv_priv[] __aligned(sizeof(void *));
};
@@ -1516,4 +1412,18 @@ static inline s32 ath12k_pdev_get_noise_floor(struct ath12k *ar)
return ar->rssi_info.noise_floor;
}
/* The @ab->dp NULL check or assertion is intentionally omitted because
* @ab->dp is guaranteed to be non-NULL after a successful probe and
* remains valid until teardown. Invoking this before allocation or
* after teardown is considered invalid usage.
*/
static inline struct ath12k_dp *ath12k_ab_to_dp(struct ath12k_base *ab)
{
return ab->dp;
}
static inline struct ath12k *ath12k_pdev_dp_to_ar(struct ath12k_pdev_dp *dp)
{
return container_of(dp, struct ath12k, dp);
}
#endif /* _CORE_H_ */
+3 -3
View File
@@ -1,12 +1,12 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2019-2021 The Linux Foundation. All rights reserved.
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include "core.h"
#include "debug.h"
#include "hal.h"
static int ath12k_dbring_bufs_replenish(struct ath12k *ar,
struct ath12k_dbring *ring,
@@ -55,7 +55,7 @@ static int ath12k_dbring_bufs_replenish(struct ath12k *ar,
cookie = u32_encode_bits(ar->pdev_idx, DP_RXDMA_BUF_COOKIE_PDEV_ID) |
u32_encode_bits(buf_id, DP_RXDMA_BUF_COOKIE_BUF_ID);
ath12k_hal_rx_buf_addr_info_set(desc, paddr, cookie, 0);
ath12k_hal_rx_buf_addr_info_set(&ab->hal, desc, paddr, cookie, 0);
ath12k_hal_srng_access_end(ab, srng);
@@ -298,7 +298,7 @@ int ath12k_dbring_buffer_release_event(struct ath12k_base *ab,
num_buff_reaped++;
ath12k_hal_rx_buf_addr_info_get(&desc, &paddr, &cookie, &rbm);
ath12k_hal_rx_buf_addr_info_get(&ab->hal, &desc, &paddr, &cookie, &rbm);
buf_id = u32_get_bits(cookie, DP_RXDMA_BUF_COOKIE_BUF_ID);
+7 -1
View File
@@ -1,7 +1,8 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
* Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*
*/
#include <linux/vmalloc.h>
@@ -21,6 +22,7 @@ void ath12k_info(struct ath12k_base *ab, const char *fmt, ...)
/* TODO: Trace the log */
va_end(args);
}
EXPORT_SYMBOL(ath12k_info);
void ath12k_err(struct ath12k_base *ab, const char *fmt, ...)
{
@@ -35,6 +37,7 @@ void ath12k_err(struct ath12k_base *ab, const char *fmt, ...)
/* TODO: Trace the log */
va_end(args);
}
EXPORT_SYMBOL(ath12k_err);
void __ath12k_warn(struct device *dev, const char *fmt, ...)
{
@@ -49,6 +52,7 @@ void __ath12k_warn(struct device *dev, const char *fmt, ...)
/* TODO: Trace the log */
va_end(args);
}
EXPORT_SYMBOL(__ath12k_warn);
#ifdef CONFIG_ATH12K_DEBUG
@@ -72,6 +76,7 @@ void __ath12k_dbg(struct ath12k_base *ab, enum ath12k_debug_mask mask,
va_end(args);
}
EXPORT_SYMBOL(__ath12k_dbg);
void ath12k_dbg_dump(struct ath12k_base *ab,
enum ath12k_debug_mask mask,
@@ -100,5 +105,6 @@ void ath12k_dbg_dump(struct ath12k_base *ab,
}
}
}
EXPORT_SYMBOL(ath12k_dbg_dump);
#endif /* CONFIG_ATH12K_DEBUG */
+6 -2
View File
@@ -967,7 +967,7 @@ static int ath12k_open_link_stats(struct inode *inode, struct file *file)
"\nlink[%d] Tx Frame descriptor Encrypt Type = ",
link_id);
for (i = 0; i < HAL_ENCRYPT_TYPE_MAX; i++) {
for (i = 0; i < DP_ENCRYPT_TYPE_MAX; i++) {
len += scnprintf(buf + len, buf_len - len,
" %d:%d", i,
linkstat.tx_encrypt_type[i]);
@@ -1020,13 +1020,15 @@ void ath12k_debugfs_op_vif_add(struct ieee80211_hw *hw,
debugfs_create_file("link_stats", 0400, vif->debugfs_dir, ahvif,
&ath12k_fops_link_stats);
}
EXPORT_SYMBOL(ath12k_debugfs_op_vif_add);
static ssize_t ath12k_debugfs_dump_device_dp_stats(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath12k_base *ab = file->private_data;
struct ath12k_device_dp_stats *device_stats = &ab->device_stats;
struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
struct ath12k_device_dp_stats *device_stats = &dp->device_stats;
int len = 0, i, j, ret;
struct ath12k *ar;
const int size = 4096;
@@ -1155,6 +1157,7 @@ static ssize_t ath12k_debugfs_dump_device_dp_stats(struct file *file,
len += scnprintf(buf + len, size - len, "\n");
rcu_read_lock();
for (i = 0; i < ab->num_radios; i++) {
ar = ath12k_mac_get_ar_by_pdev_id(ab, DP_SW2HW_MACID(i));
if (ar) {
@@ -1163,6 +1166,7 @@ static ssize_t ath12k_debugfs_dump_device_dp_stats(struct file *file,
atomic_read(&ar->dp.num_tx_pending));
}
}
rcu_read_unlock();
len += scnprintf(buf + len, size - len, "\nREO Rx Received:\n");
@@ -1,12 +1,14 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
* Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#ifndef DEBUG_HTT_STATS_H
#define DEBUG_HTT_STATS_H
#include "dp_htt.h"
#define ATH12K_HTT_STATS_BUF_SIZE (1024 * 512)
#define ATH12K_HTT_STATS_COOKIE_LSB GENMASK_ULL(31, 0)
#define ATH12K_HTT_STATS_COOKIE_MSB GENMASK_ULL(63, 32)
+24 -38
View File
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <linux/vmalloc.h>
@@ -11,6 +11,7 @@
#include "debug.h"
#include "debugfs_htt_stats.h"
#include "debugfs.h"
#include "dp_cmn.h"
static
u32 ath12k_dbg_sta_dump_rate_stats(u8 *buf, u32 offset, const int size,
@@ -144,40 +145,40 @@ static ssize_t ath12k_dbg_sta_dump_rx_stats(struct file *file,
const int size = ATH12K_STA_RX_STATS_BUF_SIZE;
struct ath12k_hw *ah = ahsta->ahvif->ah;
struct ath12k_rx_peer_stats *rx_stats;
struct ath12k_dp_link_peer *link_peer;
struct ath12k_link_sta *arsta;
u8 link_id = link_sta->link_id;
int len = 0, i, ret = 0;
struct ath12k_dp *dp;
bool he_rates_avail;
struct ath12k *ar;
wiphy_lock(ah->hw->wiphy);
guard(wiphy)(ah->hw->wiphy);
if (!(BIT(link_id) & ahsta->links_map)) {
wiphy_unlock(ah->hw->wiphy);
if (!(BIT(link_id) & ahsta->links_map))
return -ENOENT;
}
arsta = wiphy_dereference(ah->hw->wiphy, ahsta->link[link_id]);
if (!arsta || !arsta->arvif->ar) {
wiphy_unlock(ah->hw->wiphy);
if (!arsta || !arsta->arvif->ar)
return -ENOENT;
}
ar = arsta->arvif->ar;
u8 *buf __free(kfree) = kzalloc(size, GFP_KERNEL);
if (!buf) {
ret = -ENOENT;
goto out;
}
if (!buf)
return -ENOMEM;
spin_lock_bh(&ar->ab->base_lock);
dp = ath12k_ab_to_dp(ar->ab);
rx_stats = arsta->rx_stats;
if (!rx_stats) {
ret = -ENOENT;
goto unlock;
}
guard(spinlock_bh)(&dp->dp_lock);
link_peer = ath12k_dp_link_peer_find_by_addr(dp, arsta->addr);
if (!link_peer)
return -ENOENT;
rx_stats = link_peer->peer_stats.rx_stats;
if (!rx_stats)
return -ENOENT;
len += scnprintf(buf + len, size - len, "RX peer stats:\n\n");
len += scnprintf(buf + len, size - len, "Num of MSDUs: %llu\n",
@@ -237,13 +238,8 @@ static ssize_t ath12k_dbg_sta_dump_rx_stats(struct file *file,
len += ath12k_dbg_sta_dump_rate_stats(buf, len, size, he_rates_avail,
&rx_stats->byte_stats);
unlock:
spin_unlock_bh(&ar->ab->base_lock);
if (len)
ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
out:
wiphy_unlock(ah->hw->wiphy);
return ret;
}
@@ -261,10 +257,9 @@ static ssize_t ath12k_dbg_sta_reset_rx_stats(struct file *file,
struct ieee80211_link_sta *link_sta = file->private_data;
struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(link_sta->sta);
struct ath12k_hw *ah = ahsta->ahvif->ah;
struct ath12k_rx_peer_stats *rx_stats;
struct ath12k_link_sta *arsta;
u8 link_id = link_sta->link_id;
struct ath12k *ar;
struct ath12k_link_sta *arsta;
struct ath12k_dp *dp;
bool reset;
int ret;
@@ -288,19 +283,9 @@ static ssize_t ath12k_dbg_sta_reset_rx_stats(struct file *file,
goto out;
}
ar = arsta->arvif->ar;
dp = ath12k_ab_to_dp(arsta->arvif->ar->ab);
spin_lock_bh(&ar->ab->base_lock);
rx_stats = arsta->rx_stats;
if (!rx_stats) {
spin_unlock_bh(&ar->ab->base_lock);
ret = -ENOENT;
goto out;
}
memset(rx_stats, 0, sizeof(*rx_stats));
spin_unlock_bh(&ar->ab->base_lock);
ath12k_dp_link_peer_reset_rx_stats(dp, arsta->addr);
ret = count;
out:
@@ -335,3 +320,4 @@ void ath12k_debugfs_link_sta_op_add(struct ieee80211_hw *hw,
&fops_reset_rx_stats);
}
}
EXPORT_SYMBOL(ath12k_debugfs_link_sta_op_add);
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+106
View File
@@ -0,0 +1,106 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#ifndef ATH12K_DP_CMN_H
#define ATH12K_DP_CMN_H
#include "cmn_defs.h"
struct ath12k_hw_group;
/*
* ML Peer IDs start from 8192, assuming max SLO clients count 1536,
* then max peer id shall be 9728, therefore rounding the peer table size
* to the nearest next power of 2 i.e 16384.
*/
#define MAX_DP_PEER_LIST_SIZE 16384
struct ath12k_dp_hw {
struct ath12k_dp_peer __rcu *dp_peers[MAX_DP_PEER_LIST_SIZE];
/* Lock for protection of dp_peer_list and peers */
spinlock_t peer_lock;
struct list_head dp_peers_list;
};
struct ath12k_dp_hw_group {
struct ath12k_dp *dp[ATH12K_MAX_DEVICES];
};
struct ath12k_dp_link_vif {
u32 vdev_id;
u8 search_type;
u8 hal_addr_search_flags;
u8 pdev_idx;
u8 lmac_id;
u16 ast_idx;
u16 ast_hash;
u16 tcl_metadata;
u8 vdev_id_check_en;
int bank_id;
};
struct ath12k_dp_vif {
u8 tx_encap_type;
u32 key_cipher;
atomic_t mcbc_gsn;
struct ath12k_dp_link_vif dp_link_vif[ATH12K_NUM_MAX_LINKS];
};
/* TODO: Move this to a separate dp_stats file */
struct ath12k_per_peer_tx_stats {
u32 succ_bytes;
u32 retry_bytes;
u32 failed_bytes;
u32 duration;
u16 succ_pkts;
u16 retry_pkts;
u16 failed_pkts;
u16 ru_start;
u16 ru_tones;
u8 ba_fails;
u8 ppdu_type;
u32 mu_grpid;
u32 mu_pos;
bool is_ampdu;
};
struct ath12k_dp_peer_create_params {
struct ieee80211_sta *sta;
bool is_mlo;
u16 peer_id;
bool ucast_ra_only;
};
struct ath12k_dp_link_peer_rate_info {
struct rate_info txrate;
u64 rx_duration;
u64 tx_duration;
u8 rssi_comb;
s8 signal_avg;
};
static inline struct ath12k_dp_link_vif *
ath12k_dp_vif_to_dp_link_vif(struct ath12k_dp_vif *dp_vif, u8 link_id)
{
return &dp_vif->dp_link_vif[link_id];
}
void ath12k_dp_cmn_device_deinit(struct ath12k_dp *dp);
int ath12k_dp_cmn_device_init(struct ath12k_dp *dp);
void ath12k_dp_cmn_hw_group_unassign(struct ath12k_dp *dp,
struct ath12k_hw_group *ag);
void ath12k_dp_cmn_hw_group_assign(struct ath12k_dp *dp,
struct ath12k_hw_group *ag);
int ath12k_dp_link_peer_assign(struct ath12k_dp *dp, struct ath12k_dp_hw *dp_hw,
u8 vdev_id, struct ieee80211_sta *sta, u8 *addr,
u8 link_id, u32 hw_link_id);
void ath12k_dp_link_peer_unassign(struct ath12k_dp *dp, struct ath12k_dp_hw *dp_hw,
u8 vdev_id, u8 *addr, u32 hw_link_id);
void
ath12k_dp_link_peer_get_sta_rate_info_stats(struct ath12k_dp *dp, const u8 *addr,
struct ath12k_dp_link_peer_rate_info *info);
void ath12k_dp_link_peer_reset_rx_stats(struct ath12k_dp *dp, const u8 *addr);
#endif
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+37 -21
View File
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2019-2021 The Linux Foundation. All rights reserved.
* Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#ifndef ATH12K_DP_MON_H
@@ -12,6 +12,12 @@
#define ATH12K_MON_RX_DOT11_OFFSET 5
#define ATH12K_MON_RX_PKT_OFFSET 8
#define ATH12K_LE32_DEC_ENC(value, dec_bits, enc_bits) \
u32_encode_bits(le32_get_bits(value, dec_bits), enc_bits)
#define ATH12K_LE64_DEC_ENC(value, dec_bits, enc_bits) \
u32_encode_bits(le64_get_bits(value, dec_bits), enc_bits)
enum dp_monitor_mode {
ATH12K_DP_TX_MONITOR_MODE,
ATH12K_DP_RX_MONITOR_MODE
@@ -77,31 +83,41 @@ struct dp_mon_tx_ppdu_info {
struct dp_mon_mpdu *tx_mon_mpdu;
};
enum hal_rx_mon_status
ath12k_dp_mon_rx_parse_mon_status(struct ath12k *ar,
struct ath12k_mon_data *pmon,
struct sk_buff *skb,
struct napi_struct *napi);
int ath12k_dp_mon_buf_replenish(struct ath12k_base *ab,
struct dp_rxdma_mon_ring *buf_ring,
int req_entries);
int ath12k_dp_mon_status_bufs_replenish(struct ath12k_base *ab,
struct dp_rxdma_mon_ring *rx_ring,
int req_entries);
int ath12k_dp_mon_process_ring(struct ath12k_base *ab, int mac_id,
struct napi_struct *napi, int budget,
enum dp_monitor_mode monitor_mode);
struct sk_buff *ath12k_dp_mon_tx_alloc_skb(void);
enum dp_mon_tx_tlv_status
ath12k_dp_mon_tx_status_get_num_user(u16 tlv_tag,
struct hal_tlv_hdr *tx_tlv,
u8 *num_users);
enum hal_rx_mon_status
ath12k_dp_mon_tx_parse_mon_status(struct ath12k *ar,
struct ath12k_mon_data *pmon,
struct sk_buff *skb,
struct napi_struct *napi,
u32 ppdu_id);
void ath12k_dp_mon_rx_process_ulofdma(struct hal_rx_mon_ppdu_info *ppdu_info);
int ath12k_dp_mon_srng_process(struct ath12k *ar, int *budget, struct napi_struct *napi);
void
ath12k_dp_mon_rx_update_peer_mu_stats(struct ath12k_base *ab,
struct hal_rx_mon_ppdu_info *ppdu_info);
void ath12k_dp_mon_rx_update_peer_su_stats(struct ath12k_dp_link_peer *peer,
struct hal_rx_mon_ppdu_info *ppdu_info);
int ath12k_dp_pkt_set_pktlen(struct sk_buff *skb, u32 len);
struct sk_buff
*ath12k_dp_rx_alloc_mon_status_buf(struct ath12k_base *ab,
struct dp_rxdma_mon_ring *rx_ring,
int *buf_id);
u32 ath12k_dp_mon_comp_ppduid(u32 msdu_ppdu_id, u32 *ppdu_id);
int
ath12k_dp_mon_parse_status_buf(struct ath12k_pdev_dp *dp_pdev,
struct ath12k_mon_data *pmon,
const struct dp_mon_packet_info *packet_info);
void ath12k_dp_mon_update_radiotap(struct ath12k_pdev_dp *dp_pdev,
struct hal_rx_mon_ppdu_info *ppduinfo,
struct sk_buff *mon_skb,
struct ieee80211_rx_status *rxs);
void ath12k_dp_mon_rx_deliver_msdu(struct ath12k_pdev_dp *dp_pdev,
struct napi_struct *napi,
struct sk_buff *msdu,
const struct hal_rx_mon_ppdu_info *ppduinfo,
struct ieee80211_rx_status *status,
u8 decap);
struct sk_buff *
ath12k_dp_mon_rx_merg_msdus(struct ath12k_pdev_dp *dp_pdev,
struct dp_mon_mpdu *mon_mpdu,
struct hal_rx_mon_ppdu_info *ppdu_info,
struct ieee80211_rx_status *rxs);
#endif

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