Commit 631ee338 authored by Jeff Johnson's avatar Jeff Johnson
Browse files

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: default avatarJeff Johnson <jeff.johnson@oss.qualcomm.com>
parents c99ebb61 5a58414f
Loading
Loading
Loading
Loading
+5 −3
Original line number Diff line number Diff line
@@ -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
+113 −52
Original line number Diff line number Diff line
// 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;
	}

	/* 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, "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_rproc_deconfigure;
		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 @@ static void ath12k_ahb_remove(struct platform_device *pdev)
	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;

	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;
	}

void ath12k_ahb_exit(void)
	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)
{
	platform_driver_unregister(&ath12k_ahb_driver);
	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
Original line number Diff line number Diff line
/* 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
Original line number Diff line number Diff line
// 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
Original line number Diff line number Diff line
/* 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);
Loading