Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 06 Dec 2025 10:22:55 +0000
From:      Bjoern A. Zeeb <bz@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: c95ea407b322 - main - ath11k: update Atheros/QCA's ath11k driver
Message-ID:  <693403ff.389ef.72e27fb8@gitrepo.freebsd.org>

index | next in thread | raw e-mail

The branch main has been updated by bz:

URL: https://cgit.FreeBSD.org/src/commit/?id=c95ea407b322379bcb3c013a2dca9a18072c1df8

commit c95ea407b322379bcb3c013a2dca9a18072c1df8
Merge: fe7b6fc32455 989a88787ef2
Author:     Bjoern A. Zeeb <bz@FreeBSD.org>
AuthorDate: 2025-12-06 10:16:36 +0000
Commit:     Bjoern A. Zeeb <bz@FreeBSD.org>
CommitDate: 2025-12-06 10:16:36 +0000

    ath11k: update Atheros/QCA's ath11k driver
    
    This version is based on
    git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
    7d0a66e4bb9081d75c82ec4957c50034cb0ea449 ( tag: v6.18 ).
    
    Merge commit '989a88787ef2c1a73f44b82031a6f4f4470e2676'
    
    Sponsored by:   The FreeBSD Foundation

 sys/contrib/dev/athk/ath11k/Kconfig             |    3 +-
 sys/contrib/dev/athk/ath11k/Makefile            |    5 +-
 sys/contrib/dev/athk/ath11k/ahb.c               |  149 +-
 sys/contrib/dev/athk/ath11k/ce.c                |   19 +-
 sys/contrib/dev/athk/ath11k/ce.h                |    8 +-
 sys/contrib/dev/athk/ath11k/core.c              |  817 +++++++--
 sys/contrib/dev/athk/ath11k/core.h              |  132 +-
 sys/contrib/dev/athk/ath11k/coredump.c          |   54 +
 sys/contrib/dev/athk/ath11k/coredump.h          |   79 +
 sys/contrib/dev/athk/ath11k/dbring.c            |    4 +-
 sys/contrib/dev/athk/ath11k/dbring.h            |    1 +
 sys/contrib/dev/athk/ath11k/debug.c             |    3 +
 sys/contrib/dev/athk/ath11k/debug.h             |    2 +-
 sys/contrib/dev/athk/ath11k/debugfs.c           |  228 +--
 sys/contrib/dev/athk/ath11k/debugfs.h           |   21 +-
 sys/contrib/dev/athk/ath11k/debugfs_htt_stats.c |   17 +-
 sys/contrib/dev/athk/ath11k/debugfs_htt_stats.h |    2 +-
 sys/contrib/dev/athk/ath11k/debugfs_sta.c       |   42 +-
 sys/contrib/dev/athk/ath11k/debugfs_sta.h       |    1 +
 sys/contrib/dev/athk/ath11k/dp.c                |   42 +-
 sys/contrib/dev/athk/ath11k/dp.h                |   32 +-
 sys/contrib/dev/athk/ath11k/dp_rx.c             |  335 ++--
 sys/contrib/dev/athk/ath11k/dp_rx.h             |    3 +
 sys/contrib/dev/athk/ath11k/dp_tx.c             |   59 +-
 sys/contrib/dev/athk/ath11k/dp_tx.h             |    3 +-
 sys/contrib/dev/athk/ath11k/fw.c                |  171 ++
 sys/contrib/dev/athk/ath11k/fw.h                |   27 +
 sys/contrib/dev/athk/ath11k/hal.c               |   99 +-
 sys/contrib/dev/athk/ath11k/hal.h               |   14 +-
 sys/contrib/dev/athk/ath11k/hal_desc.h          |    1 +
 sys/contrib/dev/athk/ath11k/hal_rx.c            |   37 +-
 sys/contrib/dev/athk/ath11k/hal_rx.h            |   19 +-
 sys/contrib/dev/athk/ath11k/hal_tx.c            |    2 +-
 sys/contrib/dev/athk/ath11k/hal_tx.h            |    4 +-
 sys/contrib/dev/athk/ath11k/hif.h               |   68 +-
 sys/contrib/dev/athk/ath11k/htc.c               |    3 +-
 sys/contrib/dev/athk/ath11k/htc.h               |   18 +-
 sys/contrib/dev/athk/ath11k/hw.c                |    4 +-
 sys/contrib/dev/athk/ath11k/hw.h                |    6 +-
 sys/contrib/dev/athk/ath11k/mac.c               | 2038 ++++++++++++++++-------
 sys/contrib/dev/athk/ath11k/mac.h               |    6 +
 sys/contrib/dev/athk/ath11k/mhi.c               |  129 +-
 sys/contrib/dev/athk/ath11k/mhi.h               |    4 +-
 sys/contrib/dev/athk/ath11k/p2p.c               |  149 ++
 sys/contrib/dev/athk/ath11k/p2p.h               |   22 +
 sys/contrib/dev/athk/ath11k/pci.c               |  311 +++-
 sys/contrib/dev/athk/ath11k/pci.h               |    4 +-
 sys/contrib/dev/athk/ath11k/pcic.c              |   70 +-
 sys/contrib/dev/athk/ath11k/peer.c              |    4 +-
 sys/contrib/dev/athk/ath11k/peer.h              |    2 +-
 sys/contrib/dev/athk/ath11k/qmi.c               |  142 +-
 sys/contrib/dev/athk/ath11k/qmi.h               |   12 +-
 sys/contrib/dev/athk/ath11k/reg.c               |  398 ++++-
 sys/contrib/dev/athk/ath11k/reg.h               |   16 +-
 sys/contrib/dev/athk/ath11k/rx_desc.h           |    1 +
 sys/contrib/dev/athk/ath11k/spectral.c          |   32 +-
 sys/contrib/dev/athk/ath11k/spectral.h          |    1 +
 sys/contrib/dev/athk/ath11k/testmode.c          |   86 +-
 sys/contrib/dev/athk/ath11k/testmode_i.h        |   66 -
 sys/contrib/dev/athk/ath11k/thermal.c           |   28 +-
 sys/contrib/dev/athk/ath11k/thermal.h           |    9 +-
 sys/contrib/dev/athk/ath11k/trace.c             |    2 +
 sys/contrib/dev/athk/ath11k/trace.h             |   45 +-
 sys/contrib/dev/athk/ath11k/wmi.c               |  554 +++---
 sys/contrib/dev/athk/ath11k/wmi.h               |  299 ++--
 sys/contrib/dev/athk/ath11k/wow.c               |   45 +-
 sys/contrib/dev/athk/ath11k/wow.h               |    1 +
 67 files changed, 4897 insertions(+), 2113 deletions(-)

diff --cc sys/contrib/dev/athk/ath11k/Makefile
index cc47e0114595,000000000000..d9092414b362
mode 100644,000000..100644
--- a/sys/contrib/dev/athk/ath11k/Makefile
+++ b/sys/contrib/dev/athk/ath11k/Makefile
@@@ -1,36 -1,0 +1,39 @@@
 +# SPDX-License-Identifier: BSD-3-Clause-Clear
 +obj-$(CONFIG_ATH11K) += ath11k.o
 +ath11k-y += core.o \
 +	    hal.o \
 +	    hal_tx.o \
 +	    hal_rx.o \
 +	    wmi.o \
 +	    mac.o \
 +	    reg.o \
 +	    htc.o \
 +	    qmi.o \
 +	    dp.o  \
 +	    dp_tx.o \
 +	    dp_rx.o \
 +	    debug.o \
 +	    ce.o \
 +	    peer.o \
 +	    dbring.o \
 +	    hw.o \
- 	    pcic.o
++	    pcic.o \
++	    fw.o \
++	    p2p.o
 +
 +ath11k-$(CONFIG_ATH11K_DEBUGFS) += debugfs.o debugfs_htt_stats.o debugfs_sta.o
 +ath11k-$(CONFIG_NL80211_TESTMODE) += testmode.o
 +ath11k-$(CONFIG_ATH11K_TRACING) += trace.o
 +ath11k-$(CONFIG_THERMAL) += thermal.o
 +ath11k-$(CONFIG_ATH11K_SPECTRAL) += spectral.o
 +ath11k-$(CONFIG_PM) += wow.o
++ath11k-$(CONFIG_DEV_COREDUMP) += coredump.o
 +
 +obj-$(CONFIG_ATH11K_AHB) += ath11k_ahb.o
 +ath11k_ahb-y += ahb.o
 +
 +obj-$(CONFIG_ATH11K_PCI) += ath11k_pci.o
 +ath11k_pci-y += mhi.o pci.o
 +
 +# for tracing framework to find trace.h
 +CFLAGS_trace.o := -I$(src)
diff --cc sys/contrib/dev/athk/ath11k/ce.c
index c6a20a635016,000000000000..1c1bf303ad77
mode 100644,000000..100644
--- a/sys/contrib/dev/athk/ath11k/ce.c
+++ b/sys/contrib/dev/athk/ath11k/ce.c
@@@ -1,1089 -1,0 +1,1088 @@@
 +// SPDX-License-Identifier: BSD-3-Clause-Clear
 +/*
 + * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
-  * Copyright (c) 2021, Qualcomm Innovation Center, Inc. All rights reserved.
++ * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
++ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
 + */
 +
++#include <linux/export.h>
 +#include "dp_rx.h"
 +#include "debug.h"
 +#include "hif.h"
 +
 +const struct ce_attr ath11k_host_ce_config_ipq8074[] = {
 +	/* CE0: host->target HTC control and raw streams */
 +	{
 +		.flags = CE_ATTR_FLAGS,
 +		.src_nentries = 16,
 +		.src_sz_max = 2048,
 +		.dest_nentries = 0,
 +		.send_cb = ath11k_htc_tx_completion_handler,
 +	},
 +
 +	/* CE1: target->host HTT + HTC control */
 +	{
 +		.flags = CE_ATTR_FLAGS,
 +		.src_nentries = 0,
 +		.src_sz_max = 2048,
 +		.dest_nentries = 512,
 +		.recv_cb = ath11k_htc_rx_completion_handler,
 +	},
 +
 +	/* CE2: target->host WMI */
 +	{
 +		.flags = CE_ATTR_FLAGS,
 +		.src_nentries = 0,
 +		.src_sz_max = 2048,
 +		.dest_nentries = 512,
 +		.recv_cb = ath11k_htc_rx_completion_handler,
 +	},
 +
 +	/* CE3: host->target WMI (mac0) */
 +	{
 +		.flags = CE_ATTR_FLAGS,
 +		.src_nentries = 32,
 +		.src_sz_max = 2048,
 +		.dest_nentries = 0,
 +		.send_cb = ath11k_htc_tx_completion_handler,
 +	},
 +
 +	/* 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 = ath11k_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,
 +		.send_cb = ath11k_htc_tx_completion_handler,
 +	},
 +
 +	/* CE8: target autonomous hif_memcpy */
 +	{
 +		.flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
 +		.src_nentries = 0,
 +		.src_sz_max = 0,
 +		.dest_nentries = 0,
 +	},
 +
 +	/* CE9: host->target WMI (mac2) */
 +	{
 +		.flags = CE_ATTR_FLAGS,
 +		.src_nentries = 32,
 +		.src_sz_max = 2048,
 +		.dest_nentries = 0,
 +		.send_cb = ath11k_htc_tx_completion_handler,
 +	},
 +
 +	/* CE10: target->host HTT */
 +	{
 +		.flags = CE_ATTR_FLAGS,
 +		.src_nentries = 0,
 +		.src_sz_max = 2048,
 +		.dest_nentries = 512,
 +		.recv_cb = ath11k_htc_rx_completion_handler,
 +	},
 +
 +	/* CE11: Not used */
 +	{
 +		.flags = CE_ATTR_FLAGS,
 +		.src_nentries = 0,
 +		.src_sz_max = 0,
 +		.dest_nentries = 0,
 +	},
 +};
 +
 +const struct ce_attr ath11k_host_ce_config_qca6390[] = {
 +	/* 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 = ath11k_htc_rx_completion_handler,
 +	},
 +
 +	/* CE2: target->host WMI */
 +	{
 +		.flags = CE_ATTR_FLAGS,
 +		.src_nentries = 0,
 +		.src_sz_max = 2048,
 +		.dest_nentries = 512,
 +		.recv_cb = ath11k_htc_rx_completion_handler,
 +	},
 +
 +	/* CE3: host->target WMI (mac0) */
 +	{
 +		.flags = CE_ATTR_FLAGS,
 +		.src_nentries = 32,
 +		.src_sz_max = 2048,
 +		.dest_nentries = 0,
 +		.send_cb = ath11k_htc_tx_completion_handler,
 +	},
 +
 +	/* 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 = ath11k_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,
 +		.send_cb = ath11k_htc_tx_completion_handler,
 +	},
 +
 +	/* CE8: target autonomous hif_memcpy */
 +	{
 +		.flags = CE_ATTR_FLAGS,
 +		.src_nentries = 0,
 +		.src_sz_max = 0,
 +		.dest_nentries = 0,
 +	},
 +
 +};
 +
 +const struct ce_attr ath11k_host_ce_config_qcn9074[] = {
 +	/* 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 = ath11k_htc_rx_completion_handler,
 +	},
 +
 +	/* CE2: target->host WMI */
 +	{
 +		.flags = CE_ATTR_FLAGS,
 +		.src_nentries = 0,
 +		.src_sz_max = 2048,
 +		.dest_nentries = 32,
 +		.recv_cb = ath11k_htc_rx_completion_handler,
 +	},
 +
 +	/* CE3: host->target WMI (mac0) */
 +	{
 +		.flags = CE_ATTR_FLAGS,
 +		.src_nentries = 32,
 +		.src_sz_max = 2048,
 +		.dest_nentries = 0,
 +		.send_cb = ath11k_htc_tx_completion_handler,
 +	},
 +
 +	/* 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 = ath11k_dp_htt_htc_t2h_msg_handler,
 +	},
 +};
 +
 +static bool ath11k_ce_need_shadow_fix(int ce_id)
 +{
 +	/* only ce4 needs shadow workaround */
 +	if (ce_id == 4)
 +		return true;
 +	return false;
 +}
 +
 +void ath11k_ce_stop_shadow_timers(struct ath11k_base *ab)
 +{
 +	int i;
 +
 +	if (!ab->hw_params.supports_shadow_regs)
 +		return;
 +
 +	for (i = 0; i < ab->hw_params.ce_count; i++)
 +		if (ath11k_ce_need_shadow_fix(i))
 +			ath11k_dp_shadow_stop_timer(ab, &ab->ce.hp_timer[i]);
 +}
 +
 +static int ath11k_ce_rx_buf_enqueue_pipe(struct ath11k_ce_pipe *pipe,
 +					 struct sk_buff *skb, dma_addr_t paddr)
 +{
 +	struct ath11k_base *ab = pipe->ab;
 +	struct ath11k_ce_ring *ring = pipe->dest_ring;
 +	struct hal_srng *srng;
 +	unsigned int write_index;
 +	unsigned int nentries_mask = ring->nentries_mask;
 +	u32 *desc;
 +	int ret;
 +
 +	lockdep_assert_held(&ab->ce.ce_lock);
 +
 +	write_index = ring->write_index;
 +
 +	srng = &ab->hal.srng_list[ring->hal_ring_id];
 +
 +	spin_lock_bh(&srng->lock);
 +
 +	ath11k_hal_srng_access_begin(ab, srng);
 +
 +	if (unlikely(ath11k_hal_srng_src_num_free(ab, srng, false) < 1)) {
 +		ret = -ENOSPC;
 +		goto exit;
 +	}
 +
 +	desc = ath11k_hal_srng_src_get_next_entry(ab, srng);
 +	if (!desc) {
 +		ret = -ENOSPC;
 +		goto exit;
 +	}
 +
 +	ath11k_hal_ce_dst_set_desc(desc, paddr);
 +
 +	ring->skb[write_index] = skb;
 +	write_index = CE_RING_IDX_INCR(nentries_mask, write_index);
 +	ring->write_index = write_index;
 +
 +	pipe->rx_buf_needed--;
 +
 +	ret = 0;
 +exit:
 +	ath11k_hal_srng_access_end(ab, srng);
 +
 +	spin_unlock_bh(&srng->lock);
 +
 +	return ret;
 +}
 +
 +static int ath11k_ce_rx_post_pipe(struct ath11k_ce_pipe *pipe)
 +{
 +	struct ath11k_base *ab = pipe->ab;
 +	struct sk_buff *skb;
 +	dma_addr_t paddr;
 +	int ret = 0;
 +
 +	if (!(pipe->dest_ring || pipe->status_ring))
 +		return 0;
 +
 +	spin_lock_bh(&ab->ce.ce_lock);
 +	while (pipe->rx_buf_needed) {
 +		skb = dev_alloc_skb(pipe->buf_sz);
 +		if (!skb) {
 +			ret = -ENOMEM;
 +			goto exit;
 +		}
 +
 +		WARN_ON_ONCE(!IS_ALIGNED((unsigned long)skb->data, 4));
 +
 +		paddr = dma_map_single(ab->dev, skb->data,
 +				       skb->len + skb_tailroom(skb),
 +				       DMA_FROM_DEVICE);
 +		if (unlikely(dma_mapping_error(ab->dev, paddr))) {
 +			ath11k_warn(ab, "failed to dma map ce rx buf\n");
 +			dev_kfree_skb_any(skb);
 +			ret = -EIO;
 +			goto exit;
 +		}
 +
 +		ATH11K_SKB_RXCB(skb)->paddr = paddr;
 +
 +		ret = ath11k_ce_rx_buf_enqueue_pipe(pipe, skb, paddr);
 +
 +		if (ret) {
- 			ath11k_warn(ab, "failed to enqueue rx buf: %d\n", ret);
++			ath11k_dbg(ab, ATH11K_DBG_CE, "failed to enqueue rx buf: %d\n",
++				   ret);
 +			dma_unmap_single(ab->dev, paddr,
 +					 skb->len + skb_tailroom(skb),
 +					 DMA_FROM_DEVICE);
 +			dev_kfree_skb_any(skb);
 +			goto exit;
 +		}
 +	}
 +
 +exit:
 +	spin_unlock_bh(&ab->ce.ce_lock);
 +	return ret;
 +}
 +
 +static int ath11k_ce_completed_recv_next(struct ath11k_ce_pipe *pipe,
 +					 struct sk_buff **skb, int *nbytes)
 +{
 +	struct ath11k_base *ab = pipe->ab;
 +	struct hal_srng *srng;
 +	unsigned int sw_index;
 +	unsigned int nentries_mask;
 +	u32 *desc;
 +	int ret = 0;
 +
 +	spin_lock_bh(&ab->ce.ce_lock);
 +
 +	sw_index = pipe->dest_ring->sw_index;
 +	nentries_mask = pipe->dest_ring->nentries_mask;
 +
 +	srng = &ab->hal.srng_list[pipe->status_ring->hal_ring_id];
 +
 +	spin_lock_bh(&srng->lock);
 +
 +	ath11k_hal_srng_access_begin(ab, srng);
 +
 +	desc = ath11k_hal_srng_dst_get_next_entry(ab, srng);
 +	if (!desc) {
 +		ret = -EIO;
 +		goto err;
 +	}
 +
 +	*nbytes = ath11k_hal_ce_dst_status_get_length(desc);
- 	if (*nbytes == 0) {
- 		ret = -EIO;
- 		goto err;
- 	}
 +
 +	*skb = pipe->dest_ring->skb[sw_index];
 +	pipe->dest_ring->skb[sw_index] = NULL;
 +
 +	sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index);
 +	pipe->dest_ring->sw_index = sw_index;
 +
 +	pipe->rx_buf_needed++;
 +err:
 +	ath11k_hal_srng_access_end(ab, srng);
 +
 +	spin_unlock_bh(&srng->lock);
 +
 +	spin_unlock_bh(&ab->ce.ce_lock);
 +
 +	return ret;
 +}
 +
 +static void ath11k_ce_recv_process_cb(struct ath11k_ce_pipe *pipe)
 +{
 +	struct ath11k_base *ab = pipe->ab;
 +	struct sk_buff *skb;
 +	struct sk_buff_head list;
 +	unsigned int nbytes, max_nbytes;
 +	int ret;
 +
 +	__skb_queue_head_init(&list);
 +	while (ath11k_ce_completed_recv_next(pipe, &skb, &nbytes) == 0) {
 +		max_nbytes = skb->len + skb_tailroom(skb);
 +		dma_unmap_single(ab->dev, ATH11K_SKB_RXCB(skb)->paddr,
 +				 max_nbytes, DMA_FROM_DEVICE);
 +
- 		if (unlikely(max_nbytes < nbytes)) {
- 			ath11k_warn(ab, "rxed more than expected (nbytes %d, max %d)",
++		if (unlikely(max_nbytes < nbytes || nbytes == 0)) {
++			ath11k_warn(ab, "unexpected rx length (nbytes %d, max %d)",
 +				    nbytes, max_nbytes);
 +			dev_kfree_skb_any(skb);
 +			continue;
 +		}
 +
 +		skb_put(skb, nbytes);
 +		__skb_queue_tail(&list, skb);
 +	}
 +
 +	while ((skb = __skb_dequeue(&list))) {
 +		ath11k_dbg(ab, ATH11K_DBG_CE, "rx ce pipe %d len %d\n",
 +			   pipe->pipe_num, skb->len);
 +		pipe->recv_cb(ab, skb);
 +	}
 +
 +	ret = ath11k_ce_rx_post_pipe(pipe);
 +	if (ret && ret != -ENOSPC) {
 +		ath11k_warn(ab, "failed to post rx buf to pipe: %d err: %d\n",
 +			    pipe->pipe_num, ret);
 +		mod_timer(&ab->rx_replenish_retry,
 +			  jiffies + ATH11K_CE_RX_POST_RETRY_JIFFIES);
 +	}
 +}
 +
 +static struct sk_buff *ath11k_ce_completed_send_next(struct ath11k_ce_pipe *pipe)
 +{
 +	struct ath11k_base *ab = pipe->ab;
 +	struct hal_srng *srng;
 +	unsigned int sw_index;
 +	unsigned int nentries_mask;
 +	struct sk_buff *skb;
 +	u32 *desc;
 +
 +	spin_lock_bh(&ab->ce.ce_lock);
 +
 +	sw_index = pipe->src_ring->sw_index;
 +	nentries_mask = pipe->src_ring->nentries_mask;
 +
 +	srng = &ab->hal.srng_list[pipe->src_ring->hal_ring_id];
 +
 +	spin_lock_bh(&srng->lock);
 +
 +	ath11k_hal_srng_access_begin(ab, srng);
 +
 +	desc = ath11k_hal_srng_src_reap_next(ab, srng);
 +	if (!desc) {
 +		skb = ERR_PTR(-EIO);
 +		goto err_unlock;
 +	}
 +
 +	skb = pipe->src_ring->skb[sw_index];
 +
 +	pipe->src_ring->skb[sw_index] = NULL;
 +
 +	sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index);
 +	pipe->src_ring->sw_index = sw_index;
 +
 +err_unlock:
 +	spin_unlock_bh(&srng->lock);
 +
 +	spin_unlock_bh(&ab->ce.ce_lock);
 +
 +	return skb;
 +}
 +
 +static void ath11k_ce_tx_process_cb(struct ath11k_ce_pipe *pipe)
 +{
 +	struct ath11k_base *ab = pipe->ab;
 +	struct sk_buff *skb;
 +	struct sk_buff_head list;
 +
 +	__skb_queue_head_init(&list);
 +	while (!IS_ERR(skb = ath11k_ce_completed_send_next(pipe))) {
 +		if (!skb)
 +			continue;
 +
 +		dma_unmap_single(ab->dev, ATH11K_SKB_CB(skb)->paddr, skb->len,
 +				 DMA_TO_DEVICE);
 +
 +		if ((!pipe->send_cb) || ab->hw_params.credit_flow) {
 +			dev_kfree_skb_any(skb);
 +			continue;
 +		}
 +
 +		__skb_queue_tail(&list, skb);
 +	}
 +
 +	while ((skb = __skb_dequeue(&list))) {
 +		ath11k_dbg(ab, ATH11K_DBG_CE, "tx ce pipe %d len %d\n",
 +			   pipe->pipe_num, skb->len);
 +		pipe->send_cb(ab, skb);
 +	}
 +}
 +
 +static void ath11k_ce_srng_msi_ring_params_setup(struct ath11k_base *ab, u32 ce_id,
 +						 struct hal_srng_params *ring_params)
 +{
 +	u32 msi_data_start;
 +	u32 msi_data_count, msi_data_idx;
 +	u32 msi_irq_start;
 +	u32 addr_lo;
 +	u32 addr_hi;
 +	int ret;
 +
 +	ret = ath11k_get_user_msi_vector(ab, "CE",
 +					 &msi_data_count, &msi_data_start,
 +					 &msi_irq_start);
 +
 +	if (ret)
 +		return;
 +
 +	ath11k_get_msi_address(ab, &addr_lo, &addr_hi);
 +	ath11k_get_ce_msi_idx(ab, ce_id, &msi_data_idx);
 +
 +	ring_params->msi_addr = addr_lo;
 +	ring_params->msi_addr |= (dma_addr_t)(((uint64_t)addr_hi) << 32);
 +	ring_params->msi_data = (msi_data_idx % msi_data_count) + msi_data_start;
 +	ring_params->flags |= HAL_SRNG_FLAGS_MSI_INTR;
 +}
 +
 +static int ath11k_ce_init_ring(struct ath11k_base *ab,
 +			       struct ath11k_ce_ring *ce_ring,
 +			       int ce_id, enum hal_ring_type type)
 +{
- 	struct hal_srng_params params = { 0 };
++	struct hal_srng_params params = {};
 +	int ret;
 +
 +	params.ring_base_paddr = ce_ring->base_addr_ce_space;
 +	params.ring_base_vaddr = ce_ring->base_addr_owner_space;
 +	params.num_entries = ce_ring->nentries;
 +
 +	if (!(CE_ATTR_DIS_INTR & ab->hw_params.host_ce_config[ce_id].flags))
 +		ath11k_ce_srng_msi_ring_params_setup(ab, ce_id, &params);
 +
 +	switch (type) {
 +	case HAL_CE_SRC:
 +		if (!(CE_ATTR_DIS_INTR & ab->hw_params.host_ce_config[ce_id].flags))
 +			params.intr_batch_cntr_thres_entries = 1;
 +		break;
 +	case HAL_CE_DST:
 +		params.max_buffer_len = ab->hw_params.host_ce_config[ce_id].src_sz_max;
 +		if (!(ab->hw_params.host_ce_config[ce_id].flags & CE_ATTR_DIS_INTR)) {
 +			params.intr_timer_thres_us = 1024;
 +			params.flags |= HAL_SRNG_FLAGS_LOW_THRESH_INTR_EN;
 +			params.low_threshold = ce_ring->nentries - 3;
 +		}
 +		break;
 +	case HAL_CE_DST_STATUS:
 +		if (!(ab->hw_params.host_ce_config[ce_id].flags & CE_ATTR_DIS_INTR)) {
 +			params.intr_batch_cntr_thres_entries = 1;
 +			params.intr_timer_thres_us = 0x1000;
 +		}
 +		break;
 +	default:
 +		ath11k_warn(ab, "Invalid CE ring type %d\n", type);
 +		return -EINVAL;
 +	}
 +
 +	/* TODO: Init other params needed by HAL to init the ring */
 +
 +	ret = ath11k_hal_srng_setup(ab, type, ce_id, 0, &params);
 +	if (ret < 0) {
 +		ath11k_warn(ab, "failed to setup srng: %d ring_id %d\n",
 +			    ret, ce_id);
 +		return ret;
 +	}
 +
 +	ce_ring->hal_ring_id = ret;
 +
 +	if (ab->hw_params.supports_shadow_regs &&
 +	    ath11k_ce_need_shadow_fix(ce_id))
 +		ath11k_dp_shadow_init_timer(ab, &ab->ce.hp_timer[ce_id],
 +					    ATH11K_SHADOW_CTRL_TIMER_INTERVAL,
 +					    ce_ring->hal_ring_id);
 +
 +	return 0;
 +}
 +
 +static struct ath11k_ce_ring *
 +ath11k_ce_alloc_ring(struct ath11k_base *ab, int nentries, int desc_sz)
 +{
 +	struct ath11k_ce_ring *ce_ring;
 +	dma_addr_t base_addr;
 +
 +	ce_ring = kzalloc(struct_size(ce_ring, skb, nentries), GFP_KERNEL);
 +	if (ce_ring == NULL)
 +		return ERR_PTR(-ENOMEM);
 +
 +	ce_ring->nentries = nentries;
 +	ce_ring->nentries_mask = nentries - 1;
 +
 +	/* Legacy platforms that do not support cache
 +	 * coherent DMA are unsupported
 +	 */
 +	ce_ring->base_addr_owner_space_unaligned =
 +		dma_alloc_coherent(ab->dev,
 +				   nentries * desc_sz + CE_DESC_RING_ALIGN,
 +				   &base_addr, GFP_KERNEL);
 +	if (!ce_ring->base_addr_owner_space_unaligned) {
 +		kfree(ce_ring);
 +		return ERR_PTR(-ENOMEM);
 +	}
 +
 +	ce_ring->base_addr_ce_space_unaligned = base_addr;
 +
 +	ce_ring->base_addr_owner_space = PTR_ALIGN(
 +			ce_ring->base_addr_owner_space_unaligned,
 +			CE_DESC_RING_ALIGN);
 +	ce_ring->base_addr_ce_space = ALIGN(
 +			ce_ring->base_addr_ce_space_unaligned,
 +			CE_DESC_RING_ALIGN);
 +
 +	return ce_ring;
 +}
 +
 +static int ath11k_ce_alloc_pipe(struct ath11k_base *ab, int ce_id)
 +{
 +	struct ath11k_ce_pipe *pipe = &ab->ce.ce_pipe[ce_id];
 +	const struct ce_attr *attr = &ab->hw_params.host_ce_config[ce_id];
 +	struct ath11k_ce_ring *ring;
 +	int nentries;
 +	int desc_sz;
 +
 +	pipe->attr_flags = attr->flags;
 +
 +	if (attr->src_nentries) {
 +		pipe->send_cb = attr->send_cb;
 +		nentries = roundup_pow_of_two(attr->src_nentries);
 +		desc_sz = ath11k_hal_ce_get_desc_size(HAL_CE_DESC_SRC);
 +		ring = ath11k_ce_alloc_ring(ab, nentries, desc_sz);
 +		if (IS_ERR(ring))
 +			return PTR_ERR(ring);
 +		pipe->src_ring = ring;
 +	}
 +
 +	if (attr->dest_nentries) {
 +		pipe->recv_cb = attr->recv_cb;
 +		nentries = roundup_pow_of_two(attr->dest_nentries);
 +		desc_sz = ath11k_hal_ce_get_desc_size(HAL_CE_DESC_DST);
 +		ring = ath11k_ce_alloc_ring(ab, nentries, desc_sz);
 +		if (IS_ERR(ring))
 +			return PTR_ERR(ring);
 +		pipe->dest_ring = ring;
 +
 +		desc_sz = ath11k_hal_ce_get_desc_size(HAL_CE_DESC_DST_STATUS);
 +		ring = ath11k_ce_alloc_ring(ab, nentries, desc_sz);
 +		if (IS_ERR(ring))
 +			return PTR_ERR(ring);
 +		pipe->status_ring = ring;
 +	}
 +
 +	return 0;
 +}
 +
 +void ath11k_ce_per_engine_service(struct ath11k_base *ab, u16 ce_id)
 +{
 +	struct ath11k_ce_pipe *pipe = &ab->ce.ce_pipe[ce_id];
 +	const struct ce_attr *attr = &ab->hw_params.host_ce_config[ce_id];
 +
 +	if (attr->src_nentries)
 +		ath11k_ce_tx_process_cb(pipe);
 +
 +	if (pipe->recv_cb)
 +		ath11k_ce_recv_process_cb(pipe);
 +}
 +
 +void ath11k_ce_poll_send_completed(struct ath11k_base *ab, u8 pipe_id)
 +{
 +	struct ath11k_ce_pipe *pipe = &ab->ce.ce_pipe[pipe_id];
 +	const struct ce_attr *attr =  &ab->hw_params.host_ce_config[pipe_id];
 +
 +	if ((pipe->attr_flags & CE_ATTR_DIS_INTR) && attr->src_nentries)
 +		ath11k_ce_tx_process_cb(pipe);
 +}
 +EXPORT_SYMBOL(ath11k_ce_per_engine_service);
 +
 +int ath11k_ce_send(struct ath11k_base *ab, struct sk_buff *skb, u8 pipe_id,
 +		   u16 transfer_id)
 +{
 +	struct ath11k_ce_pipe *pipe = &ab->ce.ce_pipe[pipe_id];
 +	struct hal_srng *srng;
 +	u32 *desc;
 +	unsigned int write_index, sw_index;
 +	unsigned int nentries_mask;
 +	int ret = 0;
 +	u8 byte_swap_data = 0;
 +	int num_used;
 +
 +	/* Check if some entries could be regained by handling tx completion if
 +	 * the CE has interrupts disabled and the used entries is more than the
 +	 * defined usage threshold.
 +	 */
 +	if (pipe->attr_flags & CE_ATTR_DIS_INTR) {
 +		spin_lock_bh(&ab->ce.ce_lock);
 +		write_index = pipe->src_ring->write_index;
 +
 +		sw_index = pipe->src_ring->sw_index;
 +
 +		if (write_index >= sw_index)
 +			num_used = write_index - sw_index;
 +		else
 +			num_used = pipe->src_ring->nentries - sw_index +
 +				   write_index;
 +
 +		spin_unlock_bh(&ab->ce.ce_lock);
 +
 +		if (num_used > ATH11K_CE_USAGE_THRESHOLD)
 +			ath11k_ce_poll_send_completed(ab, pipe->pipe_num);
 +	}
 +
 +	if (test_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags))
 +		return -ESHUTDOWN;
 +
 +	spin_lock_bh(&ab->ce.ce_lock);
 +
 +	write_index = pipe->src_ring->write_index;
 +	nentries_mask = pipe->src_ring->nentries_mask;
 +
 +	srng = &ab->hal.srng_list[pipe->src_ring->hal_ring_id];
 +
 +	spin_lock_bh(&srng->lock);
 +
 +	ath11k_hal_srng_access_begin(ab, srng);
 +
 +	if (unlikely(ath11k_hal_srng_src_num_free(ab, srng, false) < 1)) {
 +		ath11k_hal_srng_access_end(ab, srng);
 +		ret = -ENOBUFS;
 +		goto err_unlock;
 +	}
 +
 +	desc = ath11k_hal_srng_src_get_next_reaped(ab, srng);
 +	if (!desc) {
 +		ath11k_hal_srng_access_end(ab, srng);
 +		ret = -ENOBUFS;
 +		goto err_unlock;
 +	}
 +
 +	if (pipe->attr_flags & CE_ATTR_BYTE_SWAP_DATA)
 +		byte_swap_data = 1;
 +
 +	ath11k_hal_ce_src_set_desc(desc, ATH11K_SKB_CB(skb)->paddr,
 +				   skb->len, transfer_id, byte_swap_data);
 +
 +	pipe->src_ring->skb[write_index] = skb;
 +	pipe->src_ring->write_index = CE_RING_IDX_INCR(nentries_mask,
 +						       write_index);
 +
 +	ath11k_hal_srng_access_end(ab, srng);
 +
 +	if (ath11k_ce_need_shadow_fix(pipe_id))
 +		ath11k_dp_shadow_start_timer(ab, srng, &ab->ce.hp_timer[pipe_id]);
 +
 +	spin_unlock_bh(&srng->lock);
 +
 +	spin_unlock_bh(&ab->ce.ce_lock);
 +
 +	return 0;
 +
 +err_unlock:
 +	spin_unlock_bh(&srng->lock);
 +
 +	spin_unlock_bh(&ab->ce.ce_lock);
 +
 +	return ret;
 +}
 +
 +static void ath11k_ce_rx_pipe_cleanup(struct ath11k_ce_pipe *pipe)
 +{
 +	struct ath11k_base *ab = pipe->ab;
 +	struct ath11k_ce_ring *ring = pipe->dest_ring;
 +	struct sk_buff *skb;
 +	int i;
 +
 +	if (!(ring && pipe->buf_sz))
 +		return;
 +
 +	for (i = 0; i < ring->nentries; i++) {
 +		skb = ring->skb[i];
 +		if (!skb)
 +			continue;
 +
 +		ring->skb[i] = NULL;
 +		dma_unmap_single(ab->dev, ATH11K_SKB_RXCB(skb)->paddr,
 +				 skb->len + skb_tailroom(skb), DMA_FROM_DEVICE);
 +		dev_kfree_skb_any(skb);
 +	}
 +}
 +
 +static void ath11k_ce_shadow_config(struct ath11k_base *ab)
 +{
 +	int i;
 +
 +	for (i = 0; i < ab->hw_params.ce_count; i++) {
 +		if (ab->hw_params.host_ce_config[i].src_nentries)
 +			ath11k_hal_srng_update_shadow_config(ab,
 +							     HAL_CE_SRC, i);
 +
 +		if (ab->hw_params.host_ce_config[i].dest_nentries) {
 +			ath11k_hal_srng_update_shadow_config(ab,
 +							     HAL_CE_DST, i);
 +
 +			ath11k_hal_srng_update_shadow_config(ab,
 +							     HAL_CE_DST_STATUS, i);
*** 41511 LINES SKIPPED ***


help

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?693403ff.389ef.72e27fb8>