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>
