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 <[email protected]>
AuthorDate: 2025-12-06 10:16:36 +0000
Commit:     Bjoern A. Zeeb <[email protected]>
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 ***

Reply via email to