Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 19 Apr 2026 15:39:19 +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: 60bac4d6438b - main - ath12k: update Atheros/QCA's ath12k driver
Message-ID:  <69e4f727.314f7.4c24b36c@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=60bac4d6438b6bcb3d7b439684211d05396d90ce

commit 60bac4d6438b6bcb3d7b439684211d05396d90ce
Merge: 20cf11812ac7 80f1906e3b91
Author:     Bjoern A. Zeeb <bz@FreeBSD.org>
AuthorDate: 2026-04-19 15:38:33 +0000
Commit:     Bjoern A. Zeeb <bz@FreeBSD.org>
CommitDate: 2026-04-19 15:38:33 +0000

    ath12k: update Atheros/QCA's ath12k driver
    
    This version is based on
    git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
    028ef9c96e96197026887c0f092424679298aae8 ( tag: v7.0 ).
    
    Sponsored by:   The FreeBSD Foundation
    MFC after:      3 days

 sys/contrib/dev/athk/ath12k/Makefile               |    8 +-
 sys/contrib/dev/athk/ath12k/ahb.c                  |  165 +-
 sys/contrib/dev/athk/ath12k/ahb.h                  |   31 +-
 sys/contrib/dev/athk/ath12k/ce.c                   |  328 +-
 sys/contrib/dev/athk/ath12k/ce.h                   |    7 +-
 sys/contrib/dev/athk/ath12k/cmn_defs.h             |   20 +
 sys/contrib/dev/athk/ath12k/core.c                 |   77 +-
 sys/contrib/dev/athk/ath12k/core.h                 |  209 +-
 sys/contrib/dev/athk/ath12k/dbring.c               |    6 +-
 sys/contrib/dev/athk/ath12k/debug.c                |    8 +-
 sys/contrib/dev/athk/ath12k/debugfs.c              |    8 +-
 sys/contrib/dev/athk/ath12k/debugfs_htt_stats.c    |  197 +-
 sys/contrib/dev/athk/ath12k/debugfs_htt_stats.h    |   85 +-
 sys/contrib/dev/athk/ath12k/debugfs_sta.c          |   62 +-
 sys/contrib/dev/athk/ath12k/dp.c                   |  586 +---
 sys/contrib/dev/athk/ath12k/dp.h                   | 1746 ++--------
 sys/contrib/dev/athk/ath12k/dp_cmn.h               |  106 +
 sys/contrib/dev/athk/ath12k/dp_htt.c               | 1353 +++++++
 sys/contrib/dev/athk/ath12k/dp_htt.h               | 1546 ++++++++
 sys/contrib/dev/athk/ath12k/dp_mon.c               | 3685 +-------------------
 sys/contrib/dev/athk/ath12k/dp_mon.h               |   58 +-
 sys/contrib/dev/athk/ath12k/dp_peer.c              |  690 ++++
 sys/contrib/dev/athk/ath12k/dp_peer.h              |  182 +
 sys/contrib/dev/athk/ath12k/dp_rx.c                | 3544 ++-----------------
 sys/contrib/dev/athk/ath12k/dp_rx.h                |  191 +-
 sys/contrib/dev/athk/ath12k/dp_tx.c                | 1634 +--------
 sys/contrib/dev/athk/ath12k/dp_tx.h                |   39 +-
 sys/contrib/dev/athk/ath12k/fw.c                   |   10 +-
 sys/contrib/dev/athk/ath12k/fw.h                   |    3 +-
 sys/contrib/dev/athk/ath12k/hal.c                  | 2147 +-----------
 sys/contrib/dev/athk/ath12k/hal.h                  | 1523 +++++---
 sys/contrib/dev/athk/ath12k/htc.c                  |    3 +-
 sys/contrib/dev/athk/ath12k/hw.c                   | 1680 ---------
 sys/contrib/dev/athk/ath12k/hw.h                   |   96 +-
 sys/contrib/dev/athk/ath12k/mac.c                  | 1294 ++++---
 sys/contrib/dev/athk/ath12k/mac.h                  |  142 +-
 sys/contrib/dev/athk/ath12k/mhi.c                  |  134 +-
 sys/contrib/dev/athk/ath12k/mhi.h                  |    5 +-
 sys/contrib/dev/athk/ath12k/pci.c                  |  261 +-
 sys/contrib/dev/athk/ath12k/pci.h                  |   49 +-
 sys/contrib/dev/athk/ath12k/peer.c                 |  453 +--
 sys/contrib/dev/athk/ath12k/peer.h                 |  112 +-
 sys/contrib/dev/athk/ath12k/qmi.c                  |  192 +-
 sys/contrib/dev/athk/ath12k/qmi.h                  |   16 +
 sys/contrib/dev/athk/ath12k/reg.c                  |    2 +-
 sys/contrib/dev/athk/ath12k/testmode.c             |    3 +-
 sys/contrib/dev/athk/ath12k/wifi7/Makefile         |   20 +
 sys/contrib/dev/athk/ath12k/wifi7/ahb.c            |   75 +
 sys/contrib/dev/athk/ath12k/wifi7/ahb.h            |   20 +
 sys/contrib/dev/athk/ath12k/wifi7/ce.c             |  973 ++++++
 sys/contrib/dev/athk/ath12k/wifi7/ce.h             |   22 +
 sys/contrib/dev/athk/ath12k/wifi7/core.c           |   68 +
 sys/contrib/dev/athk/ath12k/wifi7/core.h           |   11 +
 sys/contrib/dev/athk/ath12k/wifi7/dp.c             |  181 +
 sys/contrib/dev/athk/ath12k/wifi7/dp.h             |   20 +
 sys/contrib/dev/athk/ath12k/wifi7/dp_mon.c         | 3385 ++++++++++++++++++
 sys/contrib/dev/athk/ath12k/wifi7/dp_mon.h         |   23 +
 sys/contrib/dev/athk/ath12k/wifi7/dp_rx.c          | 2246 ++++++++++++
 sys/contrib/dev/athk/ath12k/wifi7/dp_rx.h          |   60 +
 sys/contrib/dev/athk/ath12k/wifi7/dp_tx.c          |  978 ++++++
 sys/contrib/dev/athk/ath12k/wifi7/dp_tx.h          |   16 +
 sys/contrib/dev/athk/ath12k/wifi7/hal.c            |  713 ++++
 sys/contrib/dev/athk/ath12k/wifi7/hal.h            |  561 +++
 sys/contrib/dev/athk/ath12k/{ => wifi7}/hal_desc.h |  331 +-
 sys/contrib/dev/athk/ath12k/wifi7/hal_qcc2072.c    |  503 +++
 sys/contrib/dev/athk/ath12k/wifi7/hal_qcc2072.h    |   13 +
 sys/contrib/dev/athk/ath12k/wifi7/hal_qcn9274.c    | 1038 ++++++
 sys/contrib/dev/athk/ath12k/wifi7/hal_qcn9274.h    |   45 +
 sys/contrib/dev/athk/ath12k/{ => wifi7}/hal_rx.c   |  284 +-
 sys/contrib/dev/athk/ath12k/{ => wifi7}/hal_rx.h   |  424 +--
 .../athk/ath12k/{rx_desc.h => wifi7/hal_rx_desc.h} |   72 +-
 sys/contrib/dev/athk/ath12k/{ => wifi7}/hal_tx.c   |   23 +-
 sys/contrib/dev/athk/ath12k/{ => wifi7}/hal_tx.h   |   30 +-
 sys/contrib/dev/athk/ath12k/wifi7/hal_wcn7850.c    |  809 +++++
 sys/contrib/dev/athk/ath12k/wifi7/hal_wcn7850.h    |   40 +
 sys/contrib/dev/athk/ath12k/wifi7/hw.c             | 1049 ++++++
 sys/contrib/dev/athk/ath12k/wifi7/hw.h             |   13 +
 sys/contrib/dev/athk/ath12k/wifi7/mhi.c            |  134 +
 sys/contrib/dev/athk/ath12k/wifi7/mhi.h            |   11 +
 sys/contrib/dev/athk/ath12k/wifi7/pci.c            |  215 ++
 sys/contrib/dev/athk/ath12k/wifi7/pci.h            |   12 +
 sys/contrib/dev/athk/ath12k/wifi7/wmi.c            |  110 +
 sys/contrib/dev/athk/ath12k/wifi7/wmi.h            |   15 +
 sys/contrib/dev/athk/ath12k/wmi.c                  |  383 +-
 sys/contrib/dev/athk/ath12k/wmi.h                  |   61 +-
 sys/contrib/dev/athk/ath12k/wow.c                  |   27 +-
 86 files changed, 22058 insertions(+), 17652 deletions(-)

diff --cc sys/contrib/dev/athk/ath12k/Makefile
index d95ee525a6cd,000000000000..3ba1236956cc
mode 100644,000000..100644
--- a/sys/contrib/dev/athk/ath12k/Makefile
+++ b/sys/contrib/dev/athk/ath12k/Makefile
@@@ -1,35 -1,0 +1,37 @@@
 +# SPDX-License-Identifier: BSD-3-Clause-Clear
 +obj-$(CONFIG_ATH12K) += ath12k.o
 +ath12k-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 \
++	    dp_htt.o \
++	    dp_peer.o \
 +	    debug.o \
 +	    ce.o \
 +	    peer.o \
 +	    dbring.o \
- 	    hw.o \
 +	    mhi.o \
 +	    pci.o \
 +	    dp_mon.o \
 +	    fw.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
 +ath12k-$(CONFIG_PM) += wow.o
 +ath12k-$(CONFIG_ATH12K_COREDUMP) += coredump.o
 +ath12k-$(CONFIG_NL80211_TESTMODE) += testmode.o
 +
 +# for tracing framework to find trace.h
 +CFLAGS_trace.o := -I$(src)
diff --cc sys/contrib/dev/athk/ath12k/cmn_defs.h
index 000000000000,20208ffea1c9..20208ffea1c9
mode 000000,100644..100644
--- a/sys/contrib/dev/athk/ath12k/cmn_defs.h
+++ b/sys/contrib/dev/athk/ath12k/cmn_defs.h
diff --cc sys/contrib/dev/athk/ath12k/core.c
index 9836d0aeba79,000000000000..1763b3b837e5
mode 100644,000000..100644
--- a/sys/contrib/dev/athk/ath12k/core.c
+++ b/sys/contrib/dev/athk/ath12k/core.c
@@@ -1,2344 -1,0 +1,2327 @@@
 +// SPDX-License-Identifier: BSD-3-Clause-Clear
 +/*
 + * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
 + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
 + */
 +
 +#if defined(__FreeBSD__)
 +#define	LINUXKPI_PARAM_PREFIX	ath12k_core_
 +#endif
 +
 +#include <linux/export.h>
 +#include <linux/module.h>
 +#include <linux/slab.h>
 +#include <linux/remoteproc.h>
 +#include <linux/firmware.h>
 +#include <linux/of.h>
 +#if defined(__FreeBSD__)
 +#include <linux/delay.h>
 +#endif
 +#include <linux/of_graph.h>
 +#include "ahb.h"
 +#include "core.h"
 +#include "dp_tx.h"
 +#include "dp_rx.h"
 +#include "debug.h"
 +#include "debugfs.h"
 +#include "fw.h"
 +#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);
 +
 +static DEFINE_MUTEX(ath12k_hw_group_mutex);
 +
 +static const struct
 +ath12k_mem_profile_based_param ath12k_mem_profile_based_param[] = {
 +[ATH12K_QMI_MEMORY_MODE_DEFAULT] = {
 +		.num_vdevs = 17,
 +		.max_client_single = 512,
 +		.max_client_dbs = 128,
 +		.max_client_dbs_sbs = 128,
 +		.dp_params = {
 +			.tx_comp_ring_size = 32768,
 +			.rxdma_monitor_buf_ring_size = 4096,
 +			.rxdma_monitor_dst_ring_size = 8092,
 +			.num_pool_tx_desc = 32768,
 +			.rx_desc_count = 12288,
 +		},
 +	},
 +[ATH12K_QMI_MEMORY_MODE_LOW_512_M] = {
 +		.num_vdevs = 9,
 +		.max_client_single = 128,
 +		.max_client_dbs = 64,
 +		.max_client_dbs_sbs = 64,
 +		.dp_params = {
 +			.tx_comp_ring_size = 16384,
 +			.rxdma_monitor_buf_ring_size = 256,
 +			.rxdma_monitor_dst_ring_size = 512,
 +			.num_pool_tx_desc = 16384,
 +			.rx_desc_count = 6144,
 +		},
 +	},
 +};
 +
 +static int ath12k_core_rfkill_config(struct ath12k_base *ab)
 +{
 +	struct ath12k *ar;
 +	int ret = 0, i;
 +
 +	if (!(ab->target_caps.sys_cap_info & WMI_SYS_CAP_INFO_RFKILL))
 +		return 0;
 +
 +	if (ath12k_acpi_get_disable_rfkill(ab))
 +		return 0;
 +
 +	for (i = 0; i < ab->num_radios; i++) {
 +		ar = ab->pdevs[i].ar;
 +
 +		ret = ath12k_mac_rfkill_config(ar);
 +		if (ret && ret != -EOPNOTSUPP) {
 +			ath12k_warn(ab, "failed to configure rfkill: %d", ret);
 +			return ret;
 +		}
 +	}
 +
 +	return ret;
 +}
 +
 +/* Check if we need to continue with suspend/resume operation.
 + * Return:
 + *	a negative value: error happens and don't continue.
 + *	0:  no error but don't continue.
 + *	positive value: no error and do continue.
 + */
 +static int ath12k_core_continue_suspend_resume(struct ath12k_base *ab)
 +{
 +	struct ath12k *ar;
 +
 +	if (!ab->hw_params->supports_suspend)
 +		return -EOPNOTSUPP;
 +
 +	/* so far single_pdev_only chips have supports_suspend as true
 +	 * so pass 0 as a dummy pdev_id here.
 +	 */
 +	ar = ab->pdevs[0].ar;
 +	if (!ar || !ar->ah || ar->ah->state != ATH12K_HW_STATE_OFF)
 +		return 0;
 +
 +	return 1;
 +}
 +
 +int ath12k_core_suspend(struct ath12k_base *ab)
 +{
 +	struct ath12k *ar;
 +	int ret, i;
 +
 +	ret = ath12k_core_continue_suspend_resume(ab);
 +	if (ret <= 0)
 +		return ret;
 +
 +	for (i = 0; i < ab->num_radios; i++) {
 +		ar = ab->pdevs[i].ar;
 +		if (!ar)
 +			continue;
 +
 +		wiphy_lock(ath12k_ar_to_hw(ar)->wiphy);
 +
 +		ret = ath12k_mac_wait_tx_complete(ar);
 +		if (ret) {
 +			wiphy_unlock(ath12k_ar_to_hw(ar)->wiphy);
 +			ath12k_warn(ab, "failed to wait tx complete: %d\n", ret);
 +			return ret;
 +		}
 +
 +		wiphy_unlock(ath12k_ar_to_hw(ar)->wiphy);
 +	}
 +
 +	/* PM framework skips suspend_late/resume_early callbacks
 +	 * if other devices report errors in their suspend callbacks.
 +	 * However ath12k_core_resume() would still be called because
 +	 * here we return success thus kernel put us on dpm_suspended_list.
 +	 * Since we won't go through a power down/up cycle, there is
 +	 * no chance to call complete(&ab->restart_completed) in
 +	 * ath12k_core_restart(), making ath12k_core_resume() timeout.
 +	 * So call it here to avoid this issue. This also works in case
 +	 * no error happens thus suspend_late/resume_early get called,
 +	 * because it will be reinitialized in ath12k_core_resume_early().
 +	 */
 +	complete(&ab->restart_completed);
 +
 +	return 0;
 +}
 +EXPORT_SYMBOL(ath12k_core_suspend);
 +
 +int ath12k_core_suspend_late(struct ath12k_base *ab)
 +{
 +	int ret;
 +
 +	ret = ath12k_core_continue_suspend_resume(ab);
 +	if (ret <= 0)
 +		return ret;
 +
 +	ath12k_acpi_stop(ab);
 +
 +	ath12k_hif_irq_disable(ab);
 +	ath12k_hif_ce_irq_disable(ab);
 +
 +	ath12k_hif_power_down(ab, true);
 +
 +	return 0;
 +}
 +EXPORT_SYMBOL(ath12k_core_suspend_late);
 +
 +int ath12k_core_resume_early(struct ath12k_base *ab)
 +{
 +	int ret;
 +
 +	ret = ath12k_core_continue_suspend_resume(ab);
 +	if (ret <= 0)
 +		return ret;
 +
 +	reinit_completion(&ab->restart_completed);
 +	ret = ath12k_hif_power_up(ab);
 +	if (ret)
 +		ath12k_warn(ab, "failed to power up hif during resume: %d\n", ret);
 +
 +	return ret;
 +}
 +EXPORT_SYMBOL(ath12k_core_resume_early);
 +
 +int ath12k_core_resume(struct ath12k_base *ab)
 +{
 +	long time_left;
 +	int ret;
 +
 +	ret = ath12k_core_continue_suspend_resume(ab);
 +	if (ret <= 0)
 +		return ret;
 +
 +	time_left = wait_for_completion_timeout(&ab->restart_completed,
 +						ATH12K_RESET_TIMEOUT_HZ);
 +	if (time_left == 0) {
 +		ath12k_warn(ab, "timeout while waiting for restart complete");
 +		return -ETIMEDOUT;
 +	}
 +
 +	return 0;
 +}
 +EXPORT_SYMBOL(ath12k_core_resume);
 +
 +static int __ath12k_core_create_board_name(struct ath12k_base *ab, char *name,
 +					   size_t name_len, bool with_variant,
 +					   bool bus_type_mode, bool with_default)
 +{
 +	/* strlen(',variant=') + strlen(ab->qmi.target.bdf_ext) */
 +	char variant[9 + ATH12K_QMI_BDF_EXT_STR_LENGTH] = {};
 +
 +	if (with_variant && ab->qmi.target.bdf_ext[0] != '\0')
 +		scnprintf(variant, sizeof(variant), ",variant=%s",
 +			  ab->qmi.target.bdf_ext);
 +
 +	switch (ab->id.bdf_search) {
 +	case ATH12K_BDF_SEARCH_BUS_AND_BOARD:
 +		if (bus_type_mode)
 +			scnprintf(name, name_len,
 +				  "bus=%s",
 +				  ath12k_bus_str(ab->hif.bus));
 +		else
 +			scnprintf(name, name_len,
 +				  "bus=%s,vendor=%04x,device=%04x,subsystem-vendor=%04x,subsystem-device=%04x,qmi-chip-id=%d,qmi-board-id=%d%s",
 +				  ath12k_bus_str(ab->hif.bus),
 +				  ab->id.vendor, ab->id.device,
 +				  ab->id.subsystem_vendor,
 +				  ab->id.subsystem_device,
 +				  ab->qmi.target.chip_id,
 +				  ab->qmi.target.board_id,
 +				  variant);
 +		break;
 +	default:
 +		scnprintf(name, name_len,
 +			  "bus=%s,qmi-chip-id=%d,qmi-board-id=%d%s",
 +			  ath12k_bus_str(ab->hif.bus),
 +			  ab->qmi.target.chip_id,
 +			  with_default ?
 +			  ATH12K_BOARD_ID_DEFAULT : ab->qmi.target.board_id,
 +			  variant);
 +		break;
 +	}
 +
 +	ath12k_dbg(ab, ATH12K_DBG_BOOT, "boot using board name '%s'\n", name);
 +
 +	return 0;
 +}
 +
 +static int ath12k_core_create_board_name(struct ath12k_base *ab, char *name,
 +					 size_t name_len)
 +{
 +	return __ath12k_core_create_board_name(ab, name, name_len, true, false, false);
 +}
 +
 +static int ath12k_core_create_fallback_board_name(struct ath12k_base *ab, char *name,
 +						  size_t name_len)
 +{
 +	return __ath12k_core_create_board_name(ab, name, name_len, false, false, true);
 +}
 +
 +static int ath12k_core_create_bus_type_board_name(struct ath12k_base *ab, char *name,
 +						  size_t name_len)
 +{
 +	return __ath12k_core_create_board_name(ab, name, name_len, false, true, true);
 +}
 +
 +const struct firmware *ath12k_core_firmware_request(struct ath12k_base *ab,
 +						    const char *file)
 +{
 +	const struct firmware *fw;
 +	char path[100];
 +	int ret;
 +
 +	if (!file)
 +		return ERR_PTR(-ENOENT);
 +
 +	ath12k_core_create_firmware_path(ab, file, path, sizeof(path));
 +
 +	ret = firmware_request_nowarn(&fw, path, ab->dev);
 +	if (ret)
 +		return ERR_PTR(ret);
 +
 +	ath12k_dbg(ab, ATH12K_DBG_BOOT, "boot firmware request %s size %zu\n",
 +		   path, fw->size);
 +
 +	return fw;
 +}
 +
 +void ath12k_core_free_bdf(struct ath12k_base *ab, struct ath12k_board_data *bd)
 +{
 +	if (!IS_ERR(bd->fw))
 +		release_firmware(bd->fw);
 +
 +	memset(bd, 0, sizeof(*bd));
 +}
 +
 +static int ath12k_core_parse_bd_ie_board(struct ath12k_base *ab,
 +					 struct ath12k_board_data *bd,
 +#if defined(__linux__)
 +					 const void *buf, size_t buf_len,
 +#elif defined(__FreeBSD__)
 +					 const u8 *buf, size_t buf_len,
 +#endif
 +					 const char *boardname,
 +					 int ie_id,
 +					 int name_id,
 +					 int data_id)
 +{
 +	const struct ath12k_fw_ie *hdr;
 +	bool name_match_found;
 +	int ret, board_ie_id;
 +	size_t board_ie_len;
 +	const void *board_ie_data;
 +
 +	name_match_found = false;
 +
 +	/* go through ATH12K_BD_IE_BOARD_/ATH12K_BD_IE_REGDB_ elements */
 +	while (buf_len > sizeof(struct ath12k_fw_ie)) {
 +#if defined(__linux__)
 +		hdr = buf;
 +#elif defined(__FreeBSD__)
 +		hdr = (const struct ath12k_fw_ie *)buf;
 +#endif
 +		board_ie_id = le32_to_cpu(hdr->id);
 +		board_ie_len = le32_to_cpu(hdr->len);
 +		board_ie_data = hdr->data;
 +
 +		buf_len -= sizeof(*hdr);
 +		buf += sizeof(*hdr);
 +
 +		if (buf_len < ALIGN(board_ie_len, 4)) {
 +			ath12k_err(ab, "invalid %s length: %zu < %zu\n",
 +				   ath12k_bd_ie_type_str(ie_id),
 +				   buf_len, ALIGN(board_ie_len, 4));
 +			ret = -EINVAL;
 +			goto out;
 +		}
 +
 +		if (board_ie_id == name_id) {
 +			ath12k_dbg_dump(ab, ATH12K_DBG_BOOT, "board name", "",
 +					board_ie_data, board_ie_len);
 +
 +			if (board_ie_len != strlen(boardname))
 +				goto next;
 +
 +			ret = memcmp(board_ie_data, boardname, strlen(boardname));
 +			if (ret)
 +				goto next;
 +
 +			name_match_found = true;
 +			ath12k_dbg(ab, ATH12K_DBG_BOOT,
 +				   "boot found match %s for name '%s'",
 +				   ath12k_bd_ie_type_str(ie_id),
 +				   boardname);
 +		} else if (board_ie_id == data_id) {
 +			if (!name_match_found)
 +				/* no match found */
 +				goto next;
 +
 +			ath12k_dbg(ab, ATH12K_DBG_BOOT,
 +				   "boot found %s for '%s'",
 +				   ath12k_bd_ie_type_str(ie_id),
 +				   boardname);
 +
 +			bd->data = board_ie_data;
 +			bd->len = board_ie_len;
 +
 +			ret = 0;
 +			goto out;
 +		} else {
 +			ath12k_warn(ab, "unknown %s id found: %d\n",
 +				    ath12k_bd_ie_type_str(ie_id),
 +				    board_ie_id);
 +		}
 +next:
 +		/* jump over the padding */
 +		board_ie_len = ALIGN(board_ie_len, 4);
 +
 +		buf_len -= board_ie_len;
 +		buf += board_ie_len;
 +	}
 +
 +	/* no match found */
 +	ret = -ENOENT;
 +
 +out:
 +	return ret;
 +}
 +
 +static int ath12k_core_fetch_board_data_api_n(struct ath12k_base *ab,
 +					      struct ath12k_board_data *bd,
 +					      const char *boardname,
 +					      int ie_id_match,
 +					      int name_id,
 +					      int data_id)
 +{
 +	size_t len, magic_len;
 +	const u8 *data;
 +	char *filename, filepath[100];
 +	size_t ie_len;
 +#if defined(__linux__)
 +	struct ath12k_fw_ie *hdr;
 +#elif defined(__FreeBSD__)
 +	const struct ath12k_fw_ie *hdr;
 +#endif
 +	int ret, ie_id;
 +
 +	filename = ATH12K_BOARD_API2_FILE;
 +
 +	if (!bd->fw)
 +		bd->fw = ath12k_core_firmware_request(ab, filename);
 +
 +	if (IS_ERR(bd->fw))
 +		return PTR_ERR(bd->fw);
 +
 +	data = bd->fw->data;
 +	len = bd->fw->size;
 +
 +	ath12k_core_create_firmware_path(ab, filename,
 +					 filepath, sizeof(filepath));
 +
 +	/* magic has extra null byte padded */
 +	magic_len = strlen(ATH12K_BOARD_MAGIC) + 1;
 +	if (len < magic_len) {
 +		ath12k_err(ab, "failed to find magic value in %s, file too short: %zu\n",
 +			   filepath, len);
 +		ret = -EINVAL;
 +		goto err;
 +	}
 +
 +	if (memcmp(data, ATH12K_BOARD_MAGIC, magic_len)) {
 +		ath12k_err(ab, "found invalid board magic\n");
 +		ret = -EINVAL;
 +		goto err;
 +	}
 +
 +	/* magic is padded to 4 bytes */
 +	magic_len = ALIGN(magic_len, 4);
 +	if (len < magic_len) {
 +		ath12k_err(ab, "failed: %s too small to contain board data, len: %zu\n",
 +			   filepath, len);
 +		ret = -EINVAL;
 +		goto err;
 +	}
 +
 +	data += magic_len;
 +	len -= magic_len;
 +
 +	while (len > sizeof(struct ath12k_fw_ie)) {
 +#if defined(__linux__)
 +		hdr = (struct ath12k_fw_ie *)data;
 +#elif defined(__FreeBSD__)
 +		hdr = (const struct ath12k_fw_ie *)data;
 +#endif
 +		ie_id = le32_to_cpu(hdr->id);
 +		ie_len = le32_to_cpu(hdr->len);
 +
 +		len -= sizeof(*hdr);
 +		data = hdr->data;
 +
 +		if (len < ALIGN(ie_len, 4)) {
 +			ath12k_err(ab, "invalid length for board ie_id %d ie_len %zu len %zu\n",
 +				   ie_id, ie_len, len);
 +			ret = -EINVAL;
 +			goto err;
 +		}
 +
 +		if (ie_id == ie_id_match) {
 +			ret = ath12k_core_parse_bd_ie_board(ab, bd, data,
 +							    ie_len,
 +							    boardname,
 +							    ie_id_match,
 +							    name_id,
 +							    data_id);
 +			if (ret == -ENOENT)
 +				/* no match found, continue */
 +				goto next;
 +			else if (ret)
 +				/* there was an error, bail out */
 +				goto err;
 +			/* either found or error, so stop searching */
 +			goto out;
 +		}
 +next:
 +		/* jump over the padding */
 +		ie_len = ALIGN(ie_len, 4);
 +
 +		len -= ie_len;
 +		data += ie_len;
 +	}
 +
 +out:
 +	if (!bd->data || !bd->len) {
 +		ath12k_dbg(ab, ATH12K_DBG_BOOT,
 +			   "failed to fetch %s for %s from %s\n",
 +			   ath12k_bd_ie_type_str(ie_id_match),
 +			   boardname, filepath);
 +		ret = -ENODATA;
 +		goto err;
 +	}
 +
 +	return 0;
 +
 +err:
 +	ath12k_core_free_bdf(ab, bd);
 +	return ret;
 +}
 +
 +int ath12k_core_fetch_board_data_api_1(struct ath12k_base *ab,
 +				       struct ath12k_board_data *bd,
 +				       char *filename)
 +{
 +	bd->fw = ath12k_core_firmware_request(ab, filename);
 +	if (IS_ERR(bd->fw))
 +		return PTR_ERR(bd->fw);
 +
 +	bd->data = bd->fw->data;
 +	bd->len = bd->fw->size;
 +
 +	return 0;
 +}
 +
 +#define BOARD_NAME_SIZE 200
 +int ath12k_core_fetch_bdf(struct ath12k_base *ab, struct ath12k_board_data *bd)
 +{
 +	char boardname[BOARD_NAME_SIZE], fallback_boardname[BOARD_NAME_SIZE];
 +	char *filename, filepath[100];
 +	int bd_api;
 +	int ret;
 +
 +	filename = ATH12K_BOARD_API2_FILE;
 +
 +	ret = ath12k_core_create_board_name(ab, boardname, sizeof(boardname));
 +	if (ret) {
 +		ath12k_err(ab, "failed to create board name: %d", ret);
 +		return ret;
 +	}
 +
 +	bd_api = 2;
 +	ret = ath12k_core_fetch_board_data_api_n(ab, bd, boardname,
 +						 ATH12K_BD_IE_BOARD,
 +						 ATH12K_BD_IE_BOARD_NAME,
 +						 ATH12K_BD_IE_BOARD_DATA);
 +	if (!ret)
 +		goto success;
 +
 +	ret = ath12k_core_create_fallback_board_name(ab, fallback_boardname,
 +						     sizeof(fallback_boardname));
 +	if (ret) {
 +		ath12k_err(ab, "failed to create fallback board name: %d", ret);
 +		return ret;
 +	}
 +
 +	ret = ath12k_core_fetch_board_data_api_n(ab, bd, fallback_boardname,
 +						 ATH12K_BD_IE_BOARD,
 +						 ATH12K_BD_IE_BOARD_NAME,
 +						 ATH12K_BD_IE_BOARD_DATA);
 +	if (!ret)
 +		goto success;
 +
 +	bd_api = 1;
 +	ret = ath12k_core_fetch_board_data_api_1(ab, bd, ATH12K_DEFAULT_BOARD_FILE);
 +	if (ret) {
 +		ath12k_core_create_firmware_path(ab, filename,
 +						 filepath, sizeof(filepath));
 +		ath12k_err(ab, "failed to fetch board data for %s from %s\n",
 +			   boardname, filepath);
 +		if (memcmp(boardname, fallback_boardname, strlen(boardname)))
 +			ath12k_err(ab, "failed to fetch board data for %s from %s\n",
 +				   fallback_boardname, filepath);
 +
 +		ath12k_err(ab, "failed to fetch board.bin from %s\n",
 +			   ab->hw_params->fw.dir);
 +		return ret;
 +	}
 +
 +success:
 +	ath12k_dbg(ab, ATH12K_DBG_BOOT, "using board api %d\n", bd_api);
 +	return 0;
 +}
 +
 +int ath12k_core_fetch_regdb(struct ath12k_base *ab, struct ath12k_board_data *bd)
 +{
 +	char boardname[BOARD_NAME_SIZE], default_boardname[BOARD_NAME_SIZE];
 +	int ret;
 +
 +	ret = ath12k_core_create_board_name(ab, boardname, BOARD_NAME_SIZE);
 +	if (ret) {
 +		ath12k_dbg(ab, ATH12K_DBG_BOOT,
 +			   "failed to create board name for regdb: %d", ret);
 +		goto exit;
 +	}
 +
 +	ret = ath12k_core_fetch_board_data_api_n(ab, bd, boardname,
 +						 ATH12K_BD_IE_REGDB,
 +						 ATH12K_BD_IE_REGDB_NAME,
 +						 ATH12K_BD_IE_REGDB_DATA);
 +	if (!ret)
 +		goto exit;
 +
 +	ret = ath12k_core_create_bus_type_board_name(ab, default_boardname,
 +						     BOARD_NAME_SIZE);
 +	if (ret) {
 +		ath12k_dbg(ab, ATH12K_DBG_BOOT,
 +			   "failed to create default board name for regdb: %d", ret);
 +		goto exit;
 +	}
 +
 +	ret = ath12k_core_fetch_board_data_api_n(ab, bd, default_boardname,
 +						 ATH12K_BD_IE_REGDB,
 +						 ATH12K_BD_IE_REGDB_NAME,
 +						 ATH12K_BD_IE_REGDB_DATA);
 +	if (!ret)
 +		goto exit;
 +
 +	ret = ath12k_core_fetch_board_data_api_1(ab, bd, ATH12K_REGDB_FILE_NAME);
 +	if (ret)
 +		ath12k_dbg(ab, ATH12K_DBG_BOOT, "failed to fetch %s from %s\n",
 +			   ATH12K_REGDB_FILE_NAME, ab->hw_params->fw.dir);
 +
 +exit:
 +	if (!ret)
 +		ath12k_dbg(ab, ATH12K_DBG_BOOT, "fetched regdb\n");
 +
 +	return ret;
 +}
 +
 +u32 ath12k_core_get_max_station_per_radio(struct ath12k_base *ab)
 +{
 +	if (ab->num_radios == 2)
 +		return TARGET_NUM_STATIONS(ab, DBS);
 +	if (ab->num_radios == 3)
 +		return TARGET_NUM_STATIONS(ab, DBS_SBS);
 +	return TARGET_NUM_STATIONS(ab, SINGLE);
 +}
 +
 +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)
 +{
 +	struct device *dev = ab->dev;
 +	struct reserved_mem *rmem;
 +	struct device_node *node;
 +
 +	node = of_parse_phandle(dev->of_node, "memory-region", index);
 +	if (!node) {
 +		ath12k_dbg(ab, ATH12K_DBG_BOOT,
 +			   "failed to parse memory-region for index %d\n", index);
 +		return NULL;
 +	}
 +
 +	rmem = of_reserved_mem_lookup(node);
 +	of_node_put(node);
 +	if (!rmem) {
 +		ath12k_dbg(ab, ATH12K_DBG_BOOT,
 +			   "unable to get memory-region for index %d\n", index);
 +		return NULL;
 +	}
 +
 +	return rmem;
 +}
 +
 +static inline
 +void ath12k_core_to_group_ref_get(struct ath12k_base *ab)
 +{
 +	struct ath12k_hw_group *ag = ab->ag;
 +
 +	lockdep_assert_held(&ag->mutex);
 +
 +	if (ab->hw_group_ref) {
 +		ath12k_dbg(ab, ATH12K_DBG_BOOT, "core already attached to group %d\n",
 +			   ag->id);
 +		return;
 +	}
 +
 +	ab->hw_group_ref = true;
 +	ag->num_started++;
 +
 +	ath12k_dbg(ab, ATH12K_DBG_BOOT, "core attached to group %d, num_started %d\n",
 +		   ag->id, ag->num_started);
 +}
 +
 +static inline
 +void ath12k_core_to_group_ref_put(struct ath12k_base *ab)
 +{
 +	struct ath12k_hw_group *ag = ab->ag;
 +
 +	lockdep_assert_held(&ag->mutex);
 +
 +	if (!ab->hw_group_ref) {
 +		ath12k_dbg(ab, ATH12K_DBG_BOOT, "core already de-attached from group %d\n",
 +			   ag->id);
 +		return;
 +	}
 +
 +	ab->hw_group_ref = false;
 +	ag->num_started--;
 +
 +	ath12k_dbg(ab, ATH12K_DBG_BOOT, "core de-attached from group %d, num_started %d\n",
 +		   ag->id, ag->num_started);
 +}
 +
 +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))
 +		ath12k_qmi_firmware_stop(ab);
 +
 +	ath12k_acpi_stop(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 */
 +}
 +
 +static void ath12k_core_check_cc_code_bdfext(const struct dmi_header *hdr, void *data)
 +{
 +	struct ath12k_base *ab = data;
 +	const char *magic = ATH12K_SMBIOS_BDF_EXT_MAGIC;
 +	struct ath12k_smbios_bdf *smbios = (struct ath12k_smbios_bdf *)hdr;
 +	ssize_t copied;
 +	size_t len;
 +	int i;
 +
 +	if (ab->qmi.target.bdf_ext[0] != '\0')
 +		return;
 +
 +	if (hdr->type != ATH12K_SMBIOS_BDF_EXT_TYPE)
 +		return;
 +
 +	if (hdr->length != ATH12K_SMBIOS_BDF_EXT_LENGTH) {
 +		ath12k_dbg(ab, ATH12K_DBG_BOOT,
 +			   "wrong smbios bdf ext type length (%d).\n",
 +			   hdr->length);
 +		return;
 +	}
 +
 +	spin_lock_bh(&ab->base_lock);
 +
 +	switch (smbios->country_code_flag) {
 +	case ATH12K_SMBIOS_CC_ISO:
 +		ab->new_alpha2[0] = u16_get_bits(smbios->cc_code >> 8, 0xff);
 +		ab->new_alpha2[1] = u16_get_bits(smbios->cc_code, 0xff);
 +		ath12k_dbg(ab, ATH12K_DBG_BOOT, "boot smbios cc_code %c%c\n",
 +			   ab->new_alpha2[0], ab->new_alpha2[1]);
 +		break;
 +	case ATH12K_SMBIOS_CC_WW:
 +		ab->new_alpha2[0] = '0';
 +		ab->new_alpha2[1] = '0';
 +		ath12k_dbg(ab, ATH12K_DBG_BOOT, "boot smbios worldwide regdomain\n");
 +		break;
 +	default:
 +		ath12k_dbg(ab, ATH12K_DBG_BOOT, "boot ignore smbios country code setting %d\n",
 +			   smbios->country_code_flag);
 +		break;
 +	}
 +
 +	spin_unlock_bh(&ab->base_lock);
 +
 +	if (!smbios->bdf_enabled) {
 +		ath12k_dbg(ab, ATH12K_DBG_BOOT, "bdf variant name not found.\n");
 +		return;
 +	}
 +
 +	/* Only one string exists (per spec) */
 +	if (memcmp(smbios->bdf_ext, magic, strlen(magic)) != 0) {
 +		ath12k_dbg(ab, ATH12K_DBG_BOOT,
 +			   "bdf variant magic does not match.\n");
 +		return;
 +	}
 +
 +	len = min_t(size_t,
 +		    strlen(smbios->bdf_ext), sizeof(ab->qmi.target.bdf_ext));
 +	for (i = 0; i < len; i++) {
 +		if (!isascii(smbios->bdf_ext[i]) || !isprint(smbios->bdf_ext[i])) {
 +			ath12k_dbg(ab, ATH12K_DBG_BOOT,
 +				   "bdf variant name contains non ascii chars.\n");
 +			return;
 +		}
 +	}
 +
 +	/* Copy extension name without magic prefix */
 +	copied = strscpy(ab->qmi.target.bdf_ext, smbios->bdf_ext + strlen(magic),
 +			 sizeof(ab->qmi.target.bdf_ext));
 +	if (copied < 0) {
 +		ath12k_dbg(ab, ATH12K_DBG_BOOT,
 +			   "bdf variant string is longer than the buffer can accommodate\n");
 +		return;
 +	}
*** 26940 LINES SKIPPED ***


home | help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?69e4f727.314f7.4c24b36c>