Path: blob/main/sys/contrib/dev/athk/ath11k/core.c
48378 views
// SPDX-License-Identifier: BSD-3-Clause-Clear1/*2* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.3* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.4*/56#if defined(__FreeBSD__)7#define LINUXKPI_PARAM_PREFIX ath11k_core_8#endif910#include <linux/module.h>11#include <linux/slab.h>12#include <linux/remoteproc.h>13#include <linux/firmware.h>14#if defined(CONFIG_OF)15#include <linux/of.h>16#endif17#if defined(__FreeBSD__)18#include <linux/delay.h>19#endif2021#include "core.h"22#include "dp_tx.h"23#include "dp_rx.h"24#include "debug.h"25#include "hif.h"26#include "wow.h"2728unsigned int ath11k_debug_mask;29EXPORT_SYMBOL(ath11k_debug_mask);30module_param_named(debug_mask, ath11k_debug_mask, uint, 0644);31MODULE_PARM_DESC(debug_mask, "Debugging mask");3233static unsigned int ath11k_crypto_mode;34module_param_named(crypto_mode, ath11k_crypto_mode, uint, 0644);35MODULE_PARM_DESC(crypto_mode, "crypto mode: 0-hardware, 1-software");3637/* frame mode values are mapped as per enum ath11k_hw_txrx_mode */38unsigned int ath11k_frame_mode = ATH11K_HW_TXRX_NATIVE_WIFI;39module_param_named(frame_mode, ath11k_frame_mode, uint, 0644);40MODULE_PARM_DESC(frame_mode,41"Datapath frame mode (0: raw, 1: native wifi (default), 2: ethernet)");4243bool ath11k_ftm_mode;44module_param_named(ftm_mode, ath11k_ftm_mode, bool, 0444);45MODULE_PARM_DESC(ftm_mode, "Boots up in factory test mode");4647static const struct ath11k_hw_params ath11k_hw_params[] = {48{49.hw_rev = ATH11K_HW_IPQ8074,50.name = "ipq8074 hw2.0",51.fw = {52.dir = "IPQ8074/hw2.0",53.board_size = 256 * 1024,54.cal_offset = 128 * 1024,55},56.max_radios = 3,57.bdf_addr = 0x4B0C0000,58.hw_ops = &ipq8074_ops,59.ring_mask = &ath11k_hw_ring_mask_ipq8074,60.internal_sleep_clock = false,61.regs = &ipq8074_regs,62.qmi_service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_IPQ8074,63.host_ce_config = ath11k_host_ce_config_ipq8074,64.ce_count = 12,65.target_ce_config = ath11k_target_ce_config_wlan_ipq8074,66.target_ce_count = 11,67.svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_ipq8074,68.svc_to_ce_map_len = 21,69.ce_ie_addr = &ath11k_ce_ie_addr_ipq8074,70.single_pdev_only = false,71.rxdma1_enable = true,72.num_rxmda_per_pdev = 1,73.rx_mac_buf_ring = false,74.vdev_start_delay = false,75.htt_peer_map_v2 = true,7677.spectral = {78.fft_sz = 2,79/* HW bug, expected BIN size is 2 bytes but HW report as 4 bytes.80* so added pad size as 2 bytes to compensate the BIN size81*/82.fft_pad_sz = 2,83.summary_pad_sz = 0,84.fft_hdr_len = 16,85.max_fft_bins = 512,86.fragment_160mhz = true,87},8889.interface_modes = BIT(NL80211_IFTYPE_STATION) |90BIT(NL80211_IFTYPE_AP) |91BIT(NL80211_IFTYPE_MESH_POINT),92.supports_monitor = true,93.full_monitor_mode = false,94.supports_shadow_regs = false,95.idle_ps = false,96.supports_sta_ps = false,97.coldboot_cal_mm = true,98.coldboot_cal_ftm = true,99.cbcal_restart_fw = true,100.fw_mem_mode = 0,101.num_vdevs = 16 + 1,102.num_peers = 512,103.supports_suspend = false,104.hal_desc_sz = sizeof(struct hal_rx_desc_ipq8074),105.supports_regdb = false,106.fix_l1ss = true,107.credit_flow = false,108.max_tx_ring = DP_TCL_NUM_RING_MAX,109.hal_params = &ath11k_hw_hal_params_ipq8074,110.supports_dynamic_smps_6ghz = false,111.alloc_cacheable_memory = true,112.supports_rssi_stats = false,113.fw_wmi_diag_event = false,114.current_cc_support = false,115.dbr_debug_support = true,116.global_reset = false,117.bios_sar_capa = NULL,118.m3_fw_support = false,119.fixed_bdf_addr = true,120.fixed_mem_region = true,121.static_window_map = false,122.hybrid_bus_type = false,123.fixed_fw_mem = false,124.support_off_channel_tx = false,125.supports_multi_bssid = false,126127.sram_dump = {},128129.tcl_ring_retry = true,130.tx_ring_size = DP_TCL_DATA_RING_SIZE,131.smp2p_wow_exit = false,132},133{134.hw_rev = ATH11K_HW_IPQ6018_HW10,135.name = "ipq6018 hw1.0",136.fw = {137.dir = "IPQ6018/hw1.0",138.board_size = 256 * 1024,139.cal_offset = 128 * 1024,140},141.max_radios = 2,142.bdf_addr = 0x4ABC0000,143.hw_ops = &ipq6018_ops,144.ring_mask = &ath11k_hw_ring_mask_ipq8074,145.internal_sleep_clock = false,146.regs = &ipq8074_regs,147.qmi_service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_IPQ8074,148.host_ce_config = ath11k_host_ce_config_ipq8074,149.ce_count = 12,150.target_ce_config = ath11k_target_ce_config_wlan_ipq8074,151.target_ce_count = 11,152.svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_ipq6018,153.svc_to_ce_map_len = 19,154.ce_ie_addr = &ath11k_ce_ie_addr_ipq8074,155.single_pdev_only = false,156.rxdma1_enable = true,157.num_rxmda_per_pdev = 1,158.rx_mac_buf_ring = false,159.vdev_start_delay = false,160.htt_peer_map_v2 = true,161162.spectral = {163.fft_sz = 4,164.fft_pad_sz = 0,165.summary_pad_sz = 0,166.fft_hdr_len = 16,167.max_fft_bins = 512,168.fragment_160mhz = true,169},170171.interface_modes = BIT(NL80211_IFTYPE_STATION) |172BIT(NL80211_IFTYPE_AP) |173BIT(NL80211_IFTYPE_MESH_POINT),174.supports_monitor = true,175.full_monitor_mode = false,176.supports_shadow_regs = false,177.idle_ps = false,178.supports_sta_ps = false,179.coldboot_cal_mm = true,180.coldboot_cal_ftm = true,181.cbcal_restart_fw = true,182.fw_mem_mode = 0,183.num_vdevs = 16 + 1,184.num_peers = 512,185.supports_suspend = false,186.hal_desc_sz = sizeof(struct hal_rx_desc_ipq8074),187.supports_regdb = false,188.fix_l1ss = true,189.credit_flow = false,190.max_tx_ring = DP_TCL_NUM_RING_MAX,191.hal_params = &ath11k_hw_hal_params_ipq8074,192.supports_dynamic_smps_6ghz = false,193.alloc_cacheable_memory = true,194.supports_rssi_stats = false,195.fw_wmi_diag_event = false,196.current_cc_support = false,197.dbr_debug_support = true,198.global_reset = false,199.bios_sar_capa = NULL,200.m3_fw_support = false,201.fixed_bdf_addr = true,202.fixed_mem_region = true,203.static_window_map = false,204.hybrid_bus_type = false,205.fixed_fw_mem = false,206.support_off_channel_tx = false,207.supports_multi_bssid = false,208209.sram_dump = {},210211.tcl_ring_retry = true,212.tx_ring_size = DP_TCL_DATA_RING_SIZE,213.smp2p_wow_exit = false,214.support_fw_mac_sequence = false,215},216{217.name = "qca6390 hw2.0",218.hw_rev = ATH11K_HW_QCA6390_HW20,219.fw = {220.dir = "QCA6390/hw2.0",221.board_size = 256 * 1024,222.cal_offset = 128 * 1024,223},224.max_radios = 3,225.bdf_addr = 0x4B0C0000,226.hw_ops = &qca6390_ops,227.ring_mask = &ath11k_hw_ring_mask_qca6390,228.internal_sleep_clock = true,229.regs = &qca6390_regs,230.qmi_service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_QCA6390,231.host_ce_config = ath11k_host_ce_config_qca6390,232.ce_count = 9,233.target_ce_config = ath11k_target_ce_config_wlan_qca6390,234.target_ce_count = 9,235.svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_qca6390,236.svc_to_ce_map_len = 14,237.ce_ie_addr = &ath11k_ce_ie_addr_ipq8074,238.single_pdev_only = true,239.rxdma1_enable = false,240.num_rxmda_per_pdev = 2,241.rx_mac_buf_ring = true,242.vdev_start_delay = true,243.htt_peer_map_v2 = false,244245.spectral = {246.fft_sz = 0,247.fft_pad_sz = 0,248.summary_pad_sz = 0,249.fft_hdr_len = 0,250.max_fft_bins = 0,251.fragment_160mhz = false,252},253254.interface_modes = BIT(NL80211_IFTYPE_STATION) |255BIT(NL80211_IFTYPE_AP),256.supports_monitor = false,257.full_monitor_mode = false,258.supports_shadow_regs = true,259.idle_ps = true,260.supports_sta_ps = true,261.coldboot_cal_mm = false,262.coldboot_cal_ftm = false,263.cbcal_restart_fw = false,264.fw_mem_mode = 0,265.num_vdevs = 16 + 1,266.num_peers = 512,267.supports_suspend = true,268.hal_desc_sz = sizeof(struct hal_rx_desc_ipq8074),269.supports_regdb = false,270.fix_l1ss = true,271.credit_flow = true,272.max_tx_ring = DP_TCL_NUM_RING_MAX_QCA6390,273.hal_params = &ath11k_hw_hal_params_qca6390,274.supports_dynamic_smps_6ghz = false,275.alloc_cacheable_memory = false,276.supports_rssi_stats = true,277.fw_wmi_diag_event = true,278.current_cc_support = true,279.dbr_debug_support = false,280.global_reset = true,281.bios_sar_capa = NULL,282.m3_fw_support = true,283.fixed_bdf_addr = false,284.fixed_mem_region = false,285.static_window_map = false,286.hybrid_bus_type = false,287.fixed_fw_mem = false,288.support_off_channel_tx = true,289.supports_multi_bssid = true,290291.sram_dump = {292.start = 0x01400000,293.end = 0x0171ffff,294},295296.tcl_ring_retry = true,297.tx_ring_size = DP_TCL_DATA_RING_SIZE,298.smp2p_wow_exit = false,299.support_fw_mac_sequence = true,300},301{302.name = "qcn9074 hw1.0",303.hw_rev = ATH11K_HW_QCN9074_HW10,304.fw = {305.dir = "QCN9074/hw1.0",306.board_size = 256 * 1024,307.cal_offset = 128 * 1024,308},309.max_radios = 1,310.single_pdev_only = false,311.qmi_service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_QCN9074,312.hw_ops = &qcn9074_ops,313.ring_mask = &ath11k_hw_ring_mask_qcn9074,314.internal_sleep_clock = false,315.regs = &qcn9074_regs,316.host_ce_config = ath11k_host_ce_config_qcn9074,317.ce_count = 6,318.target_ce_config = ath11k_target_ce_config_wlan_qcn9074,319.target_ce_count = 9,320.svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_qcn9074,321.svc_to_ce_map_len = 18,322.ce_ie_addr = &ath11k_ce_ie_addr_ipq8074,323.rxdma1_enable = true,324.num_rxmda_per_pdev = 1,325.rx_mac_buf_ring = false,326.vdev_start_delay = false,327.htt_peer_map_v2 = true,328329.spectral = {330.fft_sz = 2,331.fft_pad_sz = 0,332.summary_pad_sz = 16,333.fft_hdr_len = 24,334.max_fft_bins = 1024,335.fragment_160mhz = false,336},337338.interface_modes = BIT(NL80211_IFTYPE_STATION) |339BIT(NL80211_IFTYPE_AP) |340BIT(NL80211_IFTYPE_MESH_POINT),341.supports_monitor = true,342.full_monitor_mode = true,343.supports_shadow_regs = false,344.idle_ps = false,345.supports_sta_ps = false,346.coldboot_cal_mm = false,347.coldboot_cal_ftm = true,348.cbcal_restart_fw = true,349.fw_mem_mode = 2,350.num_vdevs = 8,351.num_peers = 128,352.supports_suspend = false,353.hal_desc_sz = sizeof(struct hal_rx_desc_qcn9074),354.supports_regdb = false,355.fix_l1ss = true,356.credit_flow = false,357.max_tx_ring = DP_TCL_NUM_RING_MAX,358.hal_params = &ath11k_hw_hal_params_ipq8074,359.supports_dynamic_smps_6ghz = true,360.alloc_cacheable_memory = true,361.supports_rssi_stats = false,362.fw_wmi_diag_event = false,363.current_cc_support = false,364.dbr_debug_support = true,365.global_reset = false,366.bios_sar_capa = NULL,367.m3_fw_support = true,368.fixed_bdf_addr = false,369.fixed_mem_region = false,370.static_window_map = true,371.hybrid_bus_type = false,372.fixed_fw_mem = false,373.support_off_channel_tx = false,374.supports_multi_bssid = false,375376.sram_dump = {},377378.tcl_ring_retry = true,379.tx_ring_size = DP_TCL_DATA_RING_SIZE,380.smp2p_wow_exit = false,381.support_fw_mac_sequence = false,382},383{384.name = "wcn6855 hw2.0",385.hw_rev = ATH11K_HW_WCN6855_HW20,386.fw = {387.dir = "WCN6855/hw2.0",388.board_size = 256 * 1024,389.cal_offset = 128 * 1024,390},391.max_radios = 3,392.bdf_addr = 0x4B0C0000,393.hw_ops = &wcn6855_ops,394.ring_mask = &ath11k_hw_ring_mask_qca6390,395.internal_sleep_clock = true,396.regs = &wcn6855_regs,397.qmi_service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_QCA6390,398.host_ce_config = ath11k_host_ce_config_qca6390,399.ce_count = 9,400.target_ce_config = ath11k_target_ce_config_wlan_qca6390,401.target_ce_count = 9,402.svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_qca6390,403.svc_to_ce_map_len = 14,404.ce_ie_addr = &ath11k_ce_ie_addr_ipq8074,405.single_pdev_only = true,406.rxdma1_enable = false,407.num_rxmda_per_pdev = 2,408.rx_mac_buf_ring = true,409.vdev_start_delay = true,410.htt_peer_map_v2 = false,411412.spectral = {413.fft_sz = 0,414.fft_pad_sz = 0,415.summary_pad_sz = 0,416.fft_hdr_len = 0,417.max_fft_bins = 0,418.fragment_160mhz = false,419},420421.interface_modes = BIT(NL80211_IFTYPE_STATION) |422BIT(NL80211_IFTYPE_AP),423.supports_monitor = false,424.full_monitor_mode = false,425.supports_shadow_regs = true,426.idle_ps = true,427.supports_sta_ps = true,428.coldboot_cal_mm = false,429.coldboot_cal_ftm = false,430.cbcal_restart_fw = false,431.fw_mem_mode = 0,432.num_vdevs = 16 + 1,433.num_peers = 512,434.supports_suspend = true,435.hal_desc_sz = sizeof(struct hal_rx_desc_wcn6855),436.supports_regdb = true,437.fix_l1ss = false,438.credit_flow = true,439.max_tx_ring = DP_TCL_NUM_RING_MAX_QCA6390,440.hal_params = &ath11k_hw_hal_params_qca6390,441.supports_dynamic_smps_6ghz = false,442.alloc_cacheable_memory = false,443.supports_rssi_stats = true,444.fw_wmi_diag_event = true,445.current_cc_support = true,446.dbr_debug_support = false,447.global_reset = true,448.bios_sar_capa = &ath11k_hw_sar_capa_wcn6855,449.m3_fw_support = true,450.fixed_bdf_addr = false,451.fixed_mem_region = false,452.static_window_map = false,453.hybrid_bus_type = false,454.fixed_fw_mem = false,455.support_off_channel_tx = true,456.supports_multi_bssid = true,457458.sram_dump = {459.start = 0x01400000,460.end = 0x0177ffff,461},462463.tcl_ring_retry = true,464.tx_ring_size = DP_TCL_DATA_RING_SIZE,465.smp2p_wow_exit = false,466.support_fw_mac_sequence = true,467},468{469.name = "wcn6855 hw2.1",470.hw_rev = ATH11K_HW_WCN6855_HW21,471.fw = {472.dir = "WCN6855/hw2.1",473.board_size = 256 * 1024,474.cal_offset = 128 * 1024,475},476.max_radios = 3,477.bdf_addr = 0x4B0C0000,478.hw_ops = &wcn6855_ops,479.ring_mask = &ath11k_hw_ring_mask_qca6390,480.internal_sleep_clock = true,481.regs = &wcn6855_regs,482.qmi_service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_QCA6390,483.host_ce_config = ath11k_host_ce_config_qca6390,484.ce_count = 9,485.target_ce_config = ath11k_target_ce_config_wlan_qca6390,486.target_ce_count = 9,487.svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_qca6390,488.svc_to_ce_map_len = 14,489.single_pdev_only = true,490.rxdma1_enable = false,491.num_rxmda_per_pdev = 2,492.rx_mac_buf_ring = true,493.vdev_start_delay = true,494.htt_peer_map_v2 = false,495496.spectral = {497.fft_sz = 0,498.fft_pad_sz = 0,499.summary_pad_sz = 0,500.fft_hdr_len = 0,501.max_fft_bins = 0,502.fragment_160mhz = false,503},504505.interface_modes = BIT(NL80211_IFTYPE_STATION) |506BIT(NL80211_IFTYPE_AP),507.supports_monitor = false,508.supports_shadow_regs = true,509.idle_ps = true,510.supports_sta_ps = true,511.coldboot_cal_mm = false,512.coldboot_cal_ftm = false,513.cbcal_restart_fw = false,514.fw_mem_mode = 0,515.num_vdevs = 16 + 1,516.num_peers = 512,517.supports_suspend = true,518.hal_desc_sz = sizeof(struct hal_rx_desc_wcn6855),519.supports_regdb = true,520.fix_l1ss = false,521.credit_flow = true,522.max_tx_ring = DP_TCL_NUM_RING_MAX_QCA6390,523.hal_params = &ath11k_hw_hal_params_qca6390,524.supports_dynamic_smps_6ghz = false,525.alloc_cacheable_memory = false,526.supports_rssi_stats = true,527.fw_wmi_diag_event = true,528.current_cc_support = true,529.dbr_debug_support = false,530.global_reset = true,531.bios_sar_capa = &ath11k_hw_sar_capa_wcn6855,532.m3_fw_support = true,533.fixed_bdf_addr = false,534.fixed_mem_region = false,535.static_window_map = false,536.hybrid_bus_type = false,537.fixed_fw_mem = false,538.support_off_channel_tx = true,539.supports_multi_bssid = true,540541.sram_dump = {542.start = 0x01400000,543.end = 0x0177ffff,544},545546.tcl_ring_retry = true,547.tx_ring_size = DP_TCL_DATA_RING_SIZE,548.smp2p_wow_exit = false,549.support_fw_mac_sequence = true,550},551{552.name = "wcn6750 hw1.0",553.hw_rev = ATH11K_HW_WCN6750_HW10,554.fw = {555.dir = "WCN6750/hw1.0",556.board_size = 256 * 1024,557.cal_offset = 128 * 1024,558},559.max_radios = 1,560.bdf_addr = 0x4B0C0000,561.hw_ops = &wcn6750_ops,562.ring_mask = &ath11k_hw_ring_mask_wcn6750,563.internal_sleep_clock = false,564.regs = &wcn6750_regs,565.qmi_service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_WCN6750,566.host_ce_config = ath11k_host_ce_config_qca6390,567.ce_count = 9,568.target_ce_config = ath11k_target_ce_config_wlan_qca6390,569.target_ce_count = 9,570.svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_qca6390,571.svc_to_ce_map_len = 14,572.ce_ie_addr = &ath11k_ce_ie_addr_ipq8074,573.single_pdev_only = true,574.rxdma1_enable = false,575.num_rxmda_per_pdev = 1,576.rx_mac_buf_ring = true,577.vdev_start_delay = true,578.htt_peer_map_v2 = false,579580.spectral = {581.fft_sz = 0,582.fft_pad_sz = 0,583.summary_pad_sz = 0,584.fft_hdr_len = 0,585.max_fft_bins = 0,586.fragment_160mhz = false,587},588589.interface_modes = BIT(NL80211_IFTYPE_STATION) |590BIT(NL80211_IFTYPE_AP),591.supports_monitor = false,592.supports_shadow_regs = true,593.idle_ps = true,594.supports_sta_ps = true,595.coldboot_cal_mm = true,596.coldboot_cal_ftm = true,597.cbcal_restart_fw = false,598.fw_mem_mode = 0,599.num_vdevs = 16 + 1,600.num_peers = 512,601.supports_suspend = false,602.hal_desc_sz = sizeof(struct hal_rx_desc_qcn9074),603.supports_regdb = true,604.fix_l1ss = false,605.credit_flow = true,606.max_tx_ring = DP_TCL_NUM_RING_MAX,607.hal_params = &ath11k_hw_hal_params_wcn6750,608.supports_dynamic_smps_6ghz = false,609.alloc_cacheable_memory = false,610.supports_rssi_stats = true,611.fw_wmi_diag_event = false,612.current_cc_support = true,613.dbr_debug_support = false,614.global_reset = false,615.bios_sar_capa = &ath11k_hw_sar_capa_wcn6855,616.m3_fw_support = false,617.fixed_bdf_addr = false,618.fixed_mem_region = false,619.static_window_map = true,620.hybrid_bus_type = true,621.fixed_fw_mem = true,622.support_off_channel_tx = true,623.supports_multi_bssid = true,624625.sram_dump = {},626627.tcl_ring_retry = false,628.tx_ring_size = DP_TCL_DATA_RING_SIZE_WCN6750,629.smp2p_wow_exit = true,630.support_fw_mac_sequence = true,631},632{633.hw_rev = ATH11K_HW_IPQ5018_HW10,634.name = "ipq5018 hw1.0",635.fw = {636.dir = "IPQ5018/hw1.0",637.board_size = 256 * 1024,638.cal_offset = 128 * 1024,639},640.max_radios = MAX_RADIOS_5018,641.bdf_addr = 0x4BA00000,642/* hal_desc_sz and hw ops are similar to qcn9074 */643.hal_desc_sz = sizeof(struct hal_rx_desc_qcn9074),644.qmi_service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_IPQ8074,645.ring_mask = &ath11k_hw_ring_mask_ipq8074,646.credit_flow = false,647.max_tx_ring = 1,648.spectral = {649.fft_sz = 2,650.fft_pad_sz = 0,651.summary_pad_sz = 16,652.fft_hdr_len = 24,653.max_fft_bins = 1024,654},655.internal_sleep_clock = false,656.regs = &ipq5018_regs,657.hw_ops = &ipq5018_ops,658.host_ce_config = ath11k_host_ce_config_qcn9074,659.ce_count = CE_CNT_5018,660.target_ce_config = ath11k_target_ce_config_wlan_ipq5018,661.target_ce_count = TARGET_CE_CNT_5018,662.svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_ipq5018,663.svc_to_ce_map_len = SVC_CE_MAP_LEN_5018,664.ce_ie_addr = &ath11k_ce_ie_addr_ipq5018,665.ce_remap = &ath11k_ce_remap_ipq5018,666.rxdma1_enable = true,667.num_rxmda_per_pdev = RXDMA_PER_PDEV_5018,668.rx_mac_buf_ring = false,669.vdev_start_delay = false,670.htt_peer_map_v2 = true,671.interface_modes = BIT(NL80211_IFTYPE_STATION) |672BIT(NL80211_IFTYPE_AP) |673BIT(NL80211_IFTYPE_MESH_POINT),674.supports_monitor = false,675.supports_sta_ps = false,676.supports_shadow_regs = false,677.fw_mem_mode = 0,678.num_vdevs = 16 + 1,679.num_peers = 512,680.supports_regdb = false,681.idle_ps = false,682.supports_suspend = false,683.hal_params = &ath11k_hw_hal_params_ipq8074,684.single_pdev_only = false,685.coldboot_cal_mm = true,686.coldboot_cal_ftm = true,687.cbcal_restart_fw = true,688.fix_l1ss = true,689.supports_dynamic_smps_6ghz = false,690.alloc_cacheable_memory = true,691.supports_rssi_stats = false,692.fw_wmi_diag_event = false,693.current_cc_support = false,694.dbr_debug_support = true,695.global_reset = false,696.bios_sar_capa = NULL,697.m3_fw_support = false,698.fixed_bdf_addr = true,699.fixed_mem_region = true,700.static_window_map = false,701.hybrid_bus_type = false,702.fixed_fw_mem = false,703.support_off_channel_tx = false,704.supports_multi_bssid = false,705706.sram_dump = {},707708.tcl_ring_retry = true,709.tx_ring_size = DP_TCL_DATA_RING_SIZE,710.smp2p_wow_exit = false,711.support_fw_mac_sequence = false,712},713};714715static inline struct ath11k_pdev *ath11k_core_get_single_pdev(struct ath11k_base *ab)716{717WARN_ON(!ab->hw_params.single_pdev_only);718719return &ab->pdevs[0];720}721722void ath11k_fw_stats_pdevs_free(struct list_head *head)723{724struct ath11k_fw_stats_pdev *i, *tmp;725726list_for_each_entry_safe(i, tmp, head, list) {727list_del(&i->list);728kfree(i);729}730}731732void ath11k_fw_stats_vdevs_free(struct list_head *head)733{734struct ath11k_fw_stats_vdev *i, *tmp;735736list_for_each_entry_safe(i, tmp, head, list) {737list_del(&i->list);738kfree(i);739}740}741742void ath11k_fw_stats_bcn_free(struct list_head *head)743{744struct ath11k_fw_stats_bcn *i, *tmp;745746list_for_each_entry_safe(i, tmp, head, list) {747list_del(&i->list);748kfree(i);749}750}751752void ath11k_fw_stats_init(struct ath11k *ar)753{754INIT_LIST_HEAD(&ar->fw_stats.pdevs);755INIT_LIST_HEAD(&ar->fw_stats.vdevs);756INIT_LIST_HEAD(&ar->fw_stats.bcn);757758init_completion(&ar->fw_stats_complete);759}760761void ath11k_fw_stats_free(struct ath11k_fw_stats *stats)762{763ath11k_fw_stats_pdevs_free(&stats->pdevs);764ath11k_fw_stats_vdevs_free(&stats->vdevs);765ath11k_fw_stats_bcn_free(&stats->bcn);766}767768bool ath11k_core_coldboot_cal_support(struct ath11k_base *ab)769{770if (!ath11k_cold_boot_cal)771return false;772773if (ath11k_ftm_mode)774return ab->hw_params.coldboot_cal_ftm;775776else777return ab->hw_params.coldboot_cal_mm;778}779780int ath11k_core_suspend(struct ath11k_base *ab)781{782int ret;783struct ath11k_pdev *pdev;784struct ath11k *ar;785786if (!ab->hw_params.supports_suspend)787return -EOPNOTSUPP;788789/* so far single_pdev_only chips have supports_suspend as true790* and only the first pdev is valid.791*/792pdev = ath11k_core_get_single_pdev(ab);793ar = pdev->ar;794if (!ar || ar->state != ATH11K_STATE_OFF)795return 0;796797ret = ath11k_dp_rx_pktlog_stop(ab, true);798if (ret) {799ath11k_warn(ab, "failed to stop dp rx (and timer) pktlog during suspend: %d\n",800ret);801return ret;802}803804ret = ath11k_mac_wait_tx_complete(ar);805if (ret) {806ath11k_warn(ab, "failed to wait tx complete: %d\n", ret);807return ret;808}809810ret = ath11k_wow_enable(ab);811if (ret) {812ath11k_warn(ab, "failed to enable wow during suspend: %d\n", ret);813return ret;814}815816ret = ath11k_dp_rx_pktlog_stop(ab, false);817if (ret) {818ath11k_warn(ab, "failed to stop dp rx pktlog during suspend: %d\n",819ret);820return ret;821}822823ath11k_ce_stop_shadow_timers(ab);824ath11k_dp_stop_shadow_timers(ab);825826ath11k_hif_irq_disable(ab);827ath11k_hif_ce_irq_disable(ab);828829ret = ath11k_hif_suspend(ab);830if (ret) {831ath11k_warn(ab, "failed to suspend hif: %d\n", ret);832return ret;833}834835return 0;836}837EXPORT_SYMBOL(ath11k_core_suspend);838839int ath11k_core_resume(struct ath11k_base *ab)840{841int ret;842struct ath11k_pdev *pdev;843struct ath11k *ar;844845if (!ab->hw_params.supports_suspend)846return -EOPNOTSUPP;847848/* so far signle_pdev_only chips have supports_suspend as true849* and only the first pdev is valid.850*/851pdev = ath11k_core_get_single_pdev(ab);852ar = pdev->ar;853if (!ar || ar->state != ATH11K_STATE_OFF)854return 0;855856ret = ath11k_hif_resume(ab);857if (ret) {858ath11k_warn(ab, "failed to resume hif during resume: %d\n", ret);859return ret;860}861862ath11k_hif_ce_irq_enable(ab);863ath11k_hif_irq_enable(ab);864865ret = ath11k_dp_rx_pktlog_start(ab);866if (ret) {867ath11k_warn(ab, "failed to start rx pktlog during resume: %d\n",868ret);869return ret;870}871872ret = ath11k_wow_wakeup(ab);873if (ret) {874ath11k_warn(ab, "failed to wakeup wow during resume: %d\n", ret);875return ret;876}877878return 0;879}880EXPORT_SYMBOL(ath11k_core_resume);881882static void ath11k_core_check_cc_code_bdfext(const struct dmi_header *hdr, void *data)883{884struct ath11k_base *ab = data;885const char *magic = ATH11K_SMBIOS_BDF_EXT_MAGIC;886#if defined(__linux__)887struct ath11k_smbios_bdf *smbios = (struct ath11k_smbios_bdf *)hdr;888#elif defined(__FreeBSD__)889const struct ath11k_smbios_bdf *smbios = (const struct ath11k_smbios_bdf *)hdr;890#endif891ssize_t copied;892size_t len;893int i;894895if (ab->qmi.target.bdf_ext[0] != '\0')896return;897898if (hdr->type != ATH11K_SMBIOS_BDF_EXT_TYPE)899return;900901if (hdr->length != ATH11K_SMBIOS_BDF_EXT_LENGTH) {902ath11k_dbg(ab, ATH11K_DBG_BOOT,903"wrong smbios bdf ext type length (%d).\n",904hdr->length);905return;906}907908spin_lock_bh(&ab->base_lock);909910switch (smbios->country_code_flag) {911case ATH11K_SMBIOS_CC_ISO:912ab->new_alpha2[0] = (smbios->cc_code >> 8) & 0xff;913ab->new_alpha2[1] = smbios->cc_code & 0xff;914ath11k_dbg(ab, ATH11K_DBG_BOOT, "smbios cc_code %c%c\n",915ab->new_alpha2[0], ab->new_alpha2[1]);916break;917case ATH11K_SMBIOS_CC_WW:918ab->new_alpha2[0] = '0';919ab->new_alpha2[1] = '0';920ath11k_dbg(ab, ATH11K_DBG_BOOT, "smbios worldwide regdomain\n");921break;922default:923ath11k_dbg(ab, ATH11K_DBG_BOOT, "ignore smbios country code setting %d\n",924smbios->country_code_flag);925break;926}927928spin_unlock_bh(&ab->base_lock);929930if (!smbios->bdf_enabled) {931ath11k_dbg(ab, ATH11K_DBG_BOOT, "bdf variant name not found.\n");932return;933}934935/* Only one string exists (per spec) */936if (memcmp(smbios->bdf_ext, magic, strlen(magic)) != 0) {937ath11k_dbg(ab, ATH11K_DBG_BOOT,938"bdf variant magic does not match.\n");939return;940}941942len = min_t(size_t,943strlen(smbios->bdf_ext), sizeof(ab->qmi.target.bdf_ext));944for (i = 0; i < len; i++) {945if (!isascii(smbios->bdf_ext[i]) || !isprint(smbios->bdf_ext[i])) {946ath11k_dbg(ab, ATH11K_DBG_BOOT,947"bdf variant name contains non ascii chars.\n");948return;949}950}951952/* Copy extension name without magic prefix */953copied = strscpy(ab->qmi.target.bdf_ext, smbios->bdf_ext + strlen(magic),954sizeof(ab->qmi.target.bdf_ext));955if (copied < 0) {956ath11k_dbg(ab, ATH11K_DBG_BOOT,957"bdf variant string is longer than the buffer can accommodate\n");958return;959}960961ath11k_dbg(ab, ATH11K_DBG_BOOT,962"found and validated bdf variant smbios_type 0x%x bdf %s\n",963ATH11K_SMBIOS_BDF_EXT_TYPE, ab->qmi.target.bdf_ext);964}965966int ath11k_core_check_smbios(struct ath11k_base *ab)967{968ab->qmi.target.bdf_ext[0] = '\0';969dmi_walk(ath11k_core_check_cc_code_bdfext, ab);970971if (ab->qmi.target.bdf_ext[0] == '\0')972return -ENODATA;973974return 0;975}976977int ath11k_core_check_dt(struct ath11k_base *ab)978{979#if defined(__linux__)980size_t max_len = sizeof(ab->qmi.target.bdf_ext);981const char *variant = NULL;982struct device_node *node;983984node = ab->dev->of_node;985if (!node)986return -ENOENT;987988of_property_read_string(node, "qcom,ath11k-calibration-variant",989&variant);990if (!variant)991return -ENODATA;992993if (strscpy(ab->qmi.target.bdf_ext, variant, max_len) < 0)994ath11k_dbg(ab, ATH11K_DBG_BOOT,995"bdf variant string is longer than the buffer can accommodate (variant: %s)\n",996variant);997998return 0;999#elif defined(__FreeBSD__)1000return -ENOENT;1001#endif1002}10031004static int __ath11k_core_create_board_name(struct ath11k_base *ab, char *name,1005size_t name_len, bool with_variant,1006bool bus_type_mode)1007{1008/* strlen(',variant=') + strlen(ab->qmi.target.bdf_ext) */1009char variant[9 + ATH11K_QMI_BDF_EXT_STR_LENGTH] = { 0 };10101011if (with_variant && ab->qmi.target.bdf_ext[0] != '\0')1012scnprintf(variant, sizeof(variant), ",variant=%s",1013ab->qmi.target.bdf_ext);10141015switch (ab->id.bdf_search) {1016case ATH11K_BDF_SEARCH_BUS_AND_BOARD:1017if (bus_type_mode)1018scnprintf(name, name_len,1019"bus=%s",1020ath11k_bus_str(ab->hif.bus));1021else1022scnprintf(name, name_len,1023"bus=%s,vendor=%04x,device=%04x,subsystem-vendor=%04x,subsystem-device=%04x,qmi-chip-id=%d,qmi-board-id=%d%s",1024ath11k_bus_str(ab->hif.bus),1025ab->id.vendor, ab->id.device,1026ab->id.subsystem_vendor,1027ab->id.subsystem_device,1028ab->qmi.target.chip_id,1029ab->qmi.target.board_id,1030variant);1031break;1032default:1033scnprintf(name, name_len,1034"bus=%s,qmi-chip-id=%d,qmi-board-id=%d%s",1035ath11k_bus_str(ab->hif.bus),1036ab->qmi.target.chip_id,1037ab->qmi.target.board_id, variant);1038break;1039}10401041ath11k_dbg(ab, ATH11K_DBG_BOOT, "using board name '%s'\n", name);10421043return 0;1044}10451046static int ath11k_core_create_board_name(struct ath11k_base *ab, char *name,1047size_t name_len)1048{1049return __ath11k_core_create_board_name(ab, name, name_len, true, false);1050}10511052static int ath11k_core_create_fallback_board_name(struct ath11k_base *ab, char *name,1053size_t name_len)1054{1055return __ath11k_core_create_board_name(ab, name, name_len, false, false);1056}10571058static int ath11k_core_create_bus_type_board_name(struct ath11k_base *ab, char *name,1059size_t name_len)1060{1061return __ath11k_core_create_board_name(ab, name, name_len, false, true);1062}10631064const struct firmware *ath11k_core_firmware_request(struct ath11k_base *ab,1065const char *file)1066{1067const struct firmware *fw;1068char path[100];1069int ret;10701071if (file == NULL)1072return ERR_PTR(-ENOENT);10731074ath11k_core_create_firmware_path(ab, file, path, sizeof(path));10751076ret = firmware_request_nowarn(&fw, path, ab->dev);1077if (ret)1078return ERR_PTR(ret);10791080ath11k_dbg(ab, ATH11K_DBG_BOOT, "firmware request %s size %zu\n",1081path, fw->size);10821083return fw;1084}10851086void ath11k_core_free_bdf(struct ath11k_base *ab, struct ath11k_board_data *bd)1087{1088if (!IS_ERR(bd->fw))1089release_firmware(bd->fw);10901091memset(bd, 0, sizeof(*bd));1092}10931094static int ath11k_core_parse_bd_ie_board(struct ath11k_base *ab,1095struct ath11k_board_data *bd,1096#if defined(__linux__)1097const void *buf, size_t buf_len,1098#elif defined(__FreeBSD__)1099const u8 *buf, size_t buf_len,1100#endif1101const char *boardname,1102int ie_id,1103int name_id,1104int data_id)1105{1106const struct ath11k_fw_ie *hdr;1107bool name_match_found;1108int ret, board_ie_id;1109size_t board_ie_len;1110const void *board_ie_data;11111112name_match_found = false;11131114/* go through ATH11K_BD_IE_BOARD_/ATH11K_BD_IE_REGDB_ elements */1115while (buf_len > sizeof(struct ath11k_fw_ie)) {1116#if defined(__linux__)1117hdr = buf;1118#elif defined(__FreeBSD__)1119hdr = (const struct ath11k_fw_ie *)buf;1120#endif1121board_ie_id = le32_to_cpu(hdr->id);1122board_ie_len = le32_to_cpu(hdr->len);1123board_ie_data = hdr->data;11241125buf_len -= sizeof(*hdr);1126buf += sizeof(*hdr);11271128if (buf_len < ALIGN(board_ie_len, 4)) {1129ath11k_err(ab, "invalid %s length: %zu < %zu\n",1130ath11k_bd_ie_type_str(ie_id),1131buf_len, ALIGN(board_ie_len, 4));1132ret = -EINVAL;1133goto out;1134}11351136if (board_ie_id == name_id) {1137ath11k_dbg_dump(ab, ATH11K_DBG_BOOT, "board name", "",1138board_ie_data, board_ie_len);11391140if (board_ie_len != strlen(boardname))1141goto next;11421143ret = memcmp(board_ie_data, boardname, strlen(boardname));1144if (ret)1145goto next;11461147name_match_found = true;1148ath11k_dbg(ab, ATH11K_DBG_BOOT,1149"found match %s for name '%s'",1150ath11k_bd_ie_type_str(ie_id),1151boardname);1152} else if (board_ie_id == data_id) {1153if (!name_match_found)1154/* no match found */1155goto next;11561157ath11k_dbg(ab, ATH11K_DBG_BOOT,1158"found %s for '%s'",1159ath11k_bd_ie_type_str(ie_id),1160boardname);11611162bd->data = board_ie_data;1163bd->len = board_ie_len;11641165ret = 0;1166goto out;1167} else {1168ath11k_warn(ab, "unknown %s id found: %d\n",1169ath11k_bd_ie_type_str(ie_id),1170board_ie_id);1171}1172next:1173/* jump over the padding */1174board_ie_len = ALIGN(board_ie_len, 4);11751176buf_len -= board_ie_len;1177buf += board_ie_len;1178}11791180/* no match found */1181ret = -ENOENT;11821183out:1184return ret;1185}11861187static int ath11k_core_fetch_board_data_api_n(struct ath11k_base *ab,1188struct ath11k_board_data *bd,1189const char *boardname,1190int ie_id_match,1191int name_id,1192int data_id)1193{1194size_t len, magic_len;1195const u8 *data;1196char *filename, filepath[100];1197size_t ie_len;1198#if defined(__linux__)1199struct ath11k_fw_ie *hdr;1200#elif defined(__FreeBSD__)1201const struct ath11k_fw_ie *hdr;1202#endif1203int ret, ie_id;12041205filename = ATH11K_BOARD_API2_FILE;12061207if (!bd->fw)1208bd->fw = ath11k_core_firmware_request(ab, filename);12091210if (IS_ERR(bd->fw))1211return PTR_ERR(bd->fw);12121213data = bd->fw->data;1214len = bd->fw->size;12151216ath11k_core_create_firmware_path(ab, filename,1217filepath, sizeof(filepath));12181219/* magic has extra null byte padded */1220magic_len = strlen(ATH11K_BOARD_MAGIC) + 1;1221if (len < magic_len) {1222ath11k_err(ab, "failed to find magic value in %s, file too short: %zu\n",1223filepath, len);1224ret = -EINVAL;1225goto err;1226}12271228if (memcmp(data, ATH11K_BOARD_MAGIC, magic_len)) {1229ath11k_err(ab, "found invalid board magic\n");1230ret = -EINVAL;1231goto err;1232}12331234/* magic is padded to 4 bytes */1235magic_len = ALIGN(magic_len, 4);1236if (len < magic_len) {1237ath11k_err(ab, "failed: %s too small to contain board data, len: %zu\n",1238filepath, len);1239ret = -EINVAL;1240goto err;1241}12421243data += magic_len;1244len -= magic_len;12451246while (len > sizeof(struct ath11k_fw_ie)) {1247#if defined(__linux__)1248hdr = (struct ath11k_fw_ie *)data;1249#elif defined(__FreeBSD__)1250hdr = (const struct ath11k_fw_ie *)data;1251#endif1252ie_id = le32_to_cpu(hdr->id);1253ie_len = le32_to_cpu(hdr->len);12541255len -= sizeof(*hdr);1256data = hdr->data;12571258if (len < ALIGN(ie_len, 4)) {1259ath11k_err(ab, "invalid length for board ie_id %d ie_len %zu len %zu\n",1260ie_id, ie_len, len);1261ret = -EINVAL;1262goto err;1263}12641265if (ie_id == ie_id_match) {1266ret = ath11k_core_parse_bd_ie_board(ab, bd, data,1267ie_len,1268boardname,1269ie_id_match,1270name_id,1271data_id);1272if (ret == -ENOENT)1273/* no match found, continue */1274goto next;1275else if (ret)1276/* there was an error, bail out */1277goto err;1278/* either found or error, so stop searching */1279goto out;1280}1281next:1282/* jump over the padding */1283ie_len = ALIGN(ie_len, 4);12841285len -= ie_len;1286data += ie_len;1287}12881289out:1290if (!bd->data || !bd->len) {1291ath11k_dbg(ab, ATH11K_DBG_BOOT,1292"failed to fetch %s for %s from %s\n",1293ath11k_bd_ie_type_str(ie_id_match),1294boardname, filepath);1295ret = -ENODATA;1296goto err;1297}12981299return 0;13001301err:1302ath11k_core_free_bdf(ab, bd);1303return ret;1304}13051306int ath11k_core_fetch_board_data_api_1(struct ath11k_base *ab,1307struct ath11k_board_data *bd,1308const char *name)1309{1310bd->fw = ath11k_core_firmware_request(ab, name);13111312if (IS_ERR(bd->fw))1313return PTR_ERR(bd->fw);13141315bd->data = bd->fw->data;1316bd->len = bd->fw->size;13171318return 0;1319}13201321#define BOARD_NAME_SIZE 2001322int ath11k_core_fetch_bdf(struct ath11k_base *ab, struct ath11k_board_data *bd)1323{1324char boardname[BOARD_NAME_SIZE], fallback_boardname[BOARD_NAME_SIZE];1325char *filename, filepath[100];1326int ret;13271328filename = ATH11K_BOARD_API2_FILE;13291330ret = ath11k_core_create_board_name(ab, boardname, sizeof(boardname));1331if (ret) {1332ath11k_err(ab, "failed to create board name: %d", ret);1333return ret;1334}13351336ab->bd_api = 2;1337ret = ath11k_core_fetch_board_data_api_n(ab, bd, boardname,1338ATH11K_BD_IE_BOARD,1339ATH11K_BD_IE_BOARD_NAME,1340ATH11K_BD_IE_BOARD_DATA);1341if (!ret)1342goto success;13431344ret = ath11k_core_create_fallback_board_name(ab, fallback_boardname,1345sizeof(fallback_boardname));1346if (ret) {1347ath11k_err(ab, "failed to create fallback board name: %d", ret);1348return ret;1349}13501351ret = ath11k_core_fetch_board_data_api_n(ab, bd, fallback_boardname,1352ATH11K_BD_IE_BOARD,1353ATH11K_BD_IE_BOARD_NAME,1354ATH11K_BD_IE_BOARD_DATA);1355if (!ret)1356goto success;13571358ab->bd_api = 1;1359ret = ath11k_core_fetch_board_data_api_1(ab, bd, ATH11K_DEFAULT_BOARD_FILE);1360if (ret) {1361ath11k_core_create_firmware_path(ab, filename,1362filepath, sizeof(filepath));1363ath11k_err(ab, "failed to fetch board data for %s from %s\n",1364boardname, filepath);1365if (memcmp(boardname, fallback_boardname, strlen(boardname)))1366ath11k_err(ab, "failed to fetch board data for %s from %s\n",1367fallback_boardname, filepath);13681369ath11k_err(ab, "failed to fetch board.bin from %s\n",1370ab->hw_params.fw.dir);1371return ret;1372}13731374success:1375ath11k_dbg(ab, ATH11K_DBG_BOOT, "using board api %d\n", ab->bd_api);1376return 0;1377}13781379int ath11k_core_fetch_regdb(struct ath11k_base *ab, struct ath11k_board_data *bd)1380{1381char boardname[BOARD_NAME_SIZE], default_boardname[BOARD_NAME_SIZE];1382int ret;13831384ret = ath11k_core_create_board_name(ab, boardname, BOARD_NAME_SIZE);1385if (ret) {1386ath11k_dbg(ab, ATH11K_DBG_BOOT,1387"failed to create board name for regdb: %d", ret);1388goto exit;1389}13901391ret = ath11k_core_fetch_board_data_api_n(ab, bd, boardname,1392ATH11K_BD_IE_REGDB,1393ATH11K_BD_IE_REGDB_NAME,1394ATH11K_BD_IE_REGDB_DATA);1395if (!ret)1396goto exit;13971398ret = ath11k_core_create_bus_type_board_name(ab, default_boardname,1399BOARD_NAME_SIZE);1400if (ret) {1401ath11k_dbg(ab, ATH11K_DBG_BOOT,1402"failed to create default board name for regdb: %d", ret);1403goto exit;1404}14051406ret = ath11k_core_fetch_board_data_api_n(ab, bd, default_boardname,1407ATH11K_BD_IE_REGDB,1408ATH11K_BD_IE_REGDB_NAME,1409ATH11K_BD_IE_REGDB_DATA);1410if (!ret)1411goto exit;14121413ret = ath11k_core_fetch_board_data_api_1(ab, bd, ATH11K_REGDB_FILE_NAME);1414if (ret)1415ath11k_dbg(ab, ATH11K_DBG_BOOT, "failed to fetch %s from %s\n",1416ATH11K_REGDB_FILE_NAME, ab->hw_params.fw.dir);14171418exit:1419if (!ret)1420ath11k_dbg(ab, ATH11K_DBG_BOOT, "fetched regdb\n");14211422return ret;1423}14241425static void ath11k_core_stop(struct ath11k_base *ab)1426{1427if (!test_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags))1428ath11k_qmi_firmware_stop(ab);14291430ath11k_hif_stop(ab);1431ath11k_wmi_detach(ab);1432ath11k_dp_pdev_reo_cleanup(ab);14331434/* De-Init of components as needed */1435}14361437static int ath11k_core_soc_create(struct ath11k_base *ab)1438{1439int ret;14401441if (ath11k_ftm_mode) {1442ab->fw_mode = ATH11K_FIRMWARE_MODE_FTM;1443ath11k_info(ab, "Booting in factory test mode\n");1444}14451446ret = ath11k_qmi_init_service(ab);1447if (ret) {1448ath11k_err(ab, "failed to initialize qmi :%d\n", ret);1449return ret;1450}14511452ret = ath11k_debugfs_soc_create(ab);1453if (ret) {1454ath11k_err(ab, "failed to create ath11k debugfs\n");1455goto err_qmi_deinit;1456}14571458ret = ath11k_hif_power_up(ab);1459if (ret) {1460ath11k_err(ab, "failed to power up :%d\n", ret);1461goto err_debugfs_reg;1462}14631464return 0;14651466err_debugfs_reg:1467ath11k_debugfs_soc_destroy(ab);1468err_qmi_deinit:1469ath11k_qmi_deinit_service(ab);1470return ret;1471}14721473static void ath11k_core_soc_destroy(struct ath11k_base *ab)1474{1475ath11k_debugfs_soc_destroy(ab);1476ath11k_dp_free(ab);1477ath11k_reg_free(ab);1478ath11k_qmi_deinit_service(ab);1479}14801481static int ath11k_core_pdev_create(struct ath11k_base *ab)1482{1483int ret;14841485ret = ath11k_debugfs_pdev_create(ab);1486if (ret) {1487ath11k_err(ab, "failed to create core pdev debugfs: %d\n", ret);1488return ret;1489}14901491ret = ath11k_dp_pdev_alloc(ab);1492if (ret) {1493ath11k_err(ab, "failed to attach DP pdev: %d\n", ret);1494goto err_pdev_debug;1495}14961497ret = ath11k_mac_register(ab);1498if (ret) {1499ath11k_err(ab, "failed register the radio with mac80211: %d\n", ret);1500goto err_dp_pdev_free;1501}15021503ret = ath11k_thermal_register(ab);1504if (ret) {1505ath11k_err(ab, "could not register thermal device: %d\n",1506ret);1507goto err_mac_unregister;1508}15091510ret = ath11k_spectral_init(ab);1511if (ret) {1512ath11k_err(ab, "failed to init spectral %d\n", ret);1513goto err_thermal_unregister;1514}15151516return 0;15171518err_thermal_unregister:1519ath11k_thermal_unregister(ab);1520err_mac_unregister:1521ath11k_mac_unregister(ab);1522err_dp_pdev_free:1523ath11k_dp_pdev_free(ab);1524err_pdev_debug:1525ath11k_debugfs_pdev_destroy(ab);15261527return ret;1528}15291530static void ath11k_core_pdev_destroy(struct ath11k_base *ab)1531{1532ath11k_spectral_deinit(ab);1533ath11k_thermal_unregister(ab);1534ath11k_mac_unregister(ab);1535ath11k_hif_irq_disable(ab);1536ath11k_dp_pdev_free(ab);1537ath11k_debugfs_pdev_destroy(ab);1538}15391540static int ath11k_core_start(struct ath11k_base *ab)1541{1542int ret;15431544ret = ath11k_wmi_attach(ab);1545if (ret) {1546ath11k_err(ab, "failed to attach wmi: %d\n", ret);1547return ret;1548}15491550ret = ath11k_htc_init(ab);1551if (ret) {1552ath11k_err(ab, "failed to init htc: %d\n", ret);1553goto err_wmi_detach;1554}15551556ret = ath11k_hif_start(ab);1557if (ret) {1558ath11k_err(ab, "failed to start HIF: %d\n", ret);1559goto err_wmi_detach;1560}15611562ret = ath11k_htc_wait_target(&ab->htc);1563if (ret) {1564ath11k_err(ab, "failed to connect to HTC: %d\n", ret);1565goto err_hif_stop;1566}15671568ret = ath11k_dp_htt_connect(&ab->dp);1569if (ret) {1570ath11k_err(ab, "failed to connect to HTT: %d\n", ret);1571goto err_hif_stop;1572}15731574ret = ath11k_wmi_connect(ab);1575if (ret) {1576ath11k_err(ab, "failed to connect wmi: %d\n", ret);1577goto err_hif_stop;1578}15791580ret = ath11k_htc_start(&ab->htc);1581if (ret) {1582ath11k_err(ab, "failed to start HTC: %d\n", ret);1583goto err_hif_stop;1584}15851586ret = ath11k_wmi_wait_for_service_ready(ab);1587if (ret) {1588ath11k_err(ab, "failed to receive wmi service ready event: %d\n",1589ret);1590goto err_hif_stop;1591}15921593ret = ath11k_mac_allocate(ab);1594if (ret) {1595ath11k_err(ab, "failed to create new hw device with mac80211 :%d\n",1596ret);1597goto err_hif_stop;1598}15991600ath11k_dp_pdev_pre_alloc(ab);16011602ret = ath11k_dp_pdev_reo_setup(ab);1603if (ret) {1604ath11k_err(ab, "failed to initialize reo destination rings: %d\n", ret);1605goto err_mac_destroy;1606}16071608ret = ath11k_wmi_cmd_init(ab);1609if (ret) {1610ath11k_err(ab, "failed to send wmi init cmd: %d\n", ret);1611goto err_reo_cleanup;1612}16131614ret = ath11k_wmi_wait_for_unified_ready(ab);1615if (ret) {1616ath11k_err(ab, "failed to receive wmi unified ready event: %d\n",1617ret);1618goto err_reo_cleanup;1619}16201621/* put hardware to DBS mode */1622if (ab->hw_params.single_pdev_only && ab->hw_params.num_rxmda_per_pdev > 1) {1623ret = ath11k_wmi_set_hw_mode(ab, WMI_HOST_HW_MODE_DBS);1624if (ret) {1625ath11k_err(ab, "failed to send dbs mode: %d\n", ret);1626goto err_hif_stop;1627}1628}16291630ret = ath11k_dp_tx_htt_h2t_ver_req_msg(ab);1631if (ret) {1632ath11k_err(ab, "failed to send htt version request message: %d\n",1633ret);1634goto err_reo_cleanup;1635}16361637return 0;16381639err_reo_cleanup:1640ath11k_dp_pdev_reo_cleanup(ab);1641err_mac_destroy:1642ath11k_mac_destroy(ab);1643err_hif_stop:1644ath11k_hif_stop(ab);1645err_wmi_detach:1646ath11k_wmi_detach(ab);16471648return ret;1649}16501651static int ath11k_core_start_firmware(struct ath11k_base *ab,1652enum ath11k_firmware_mode mode)1653{1654int ret;16551656ath11k_ce_get_shadow_config(ab, &ab->qmi.ce_cfg.shadow_reg_v2,1657&ab->qmi.ce_cfg.shadow_reg_v2_len);16581659ret = ath11k_qmi_firmware_start(ab, mode);1660if (ret) {1661ath11k_err(ab, "failed to send firmware start: %d\n", ret);1662return ret;1663}16641665return ret;1666}16671668int ath11k_core_qmi_firmware_ready(struct ath11k_base *ab)1669{1670int ret;16711672ret = ath11k_core_start_firmware(ab, ab->fw_mode);1673if (ret) {1674ath11k_err(ab, "failed to start firmware: %d\n", ret);1675return ret;1676}16771678ret = ath11k_ce_init_pipes(ab);1679if (ret) {1680ath11k_err(ab, "failed to initialize CE: %d\n", ret);1681goto err_firmware_stop;1682}16831684ret = ath11k_dp_alloc(ab);1685if (ret) {1686ath11k_err(ab, "failed to init DP: %d\n", ret);1687goto err_firmware_stop;1688}16891690switch (ath11k_crypto_mode) {1691case ATH11K_CRYPT_MODE_SW:1692set_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags);1693set_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags);1694break;1695case ATH11K_CRYPT_MODE_HW:1696clear_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags);1697clear_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags);1698break;1699default:1700ath11k_info(ab, "invalid crypto_mode: %d\n", ath11k_crypto_mode);1701return -EINVAL;1702}17031704if (ath11k_frame_mode == ATH11K_HW_TXRX_RAW)1705set_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags);17061707mutex_lock(&ab->core_lock);1708ret = ath11k_core_start(ab);1709if (ret) {1710ath11k_err(ab, "failed to start core: %d\n", ret);1711goto err_dp_free;1712}17131714ret = ath11k_core_pdev_create(ab);1715if (ret) {1716ath11k_err(ab, "failed to create pdev core: %d\n", ret);1717goto err_core_stop;1718}1719ath11k_hif_irq_enable(ab);1720mutex_unlock(&ab->core_lock);17211722return 0;17231724err_core_stop:1725ath11k_core_stop(ab);1726ath11k_mac_destroy(ab);1727err_dp_free:1728ath11k_dp_free(ab);1729mutex_unlock(&ab->core_lock);1730err_firmware_stop:1731ath11k_qmi_firmware_stop(ab);17321733return ret;1734}17351736static int ath11k_core_reconfigure_on_crash(struct ath11k_base *ab)1737{1738int ret;17391740mutex_lock(&ab->core_lock);1741ath11k_thermal_unregister(ab);1742ath11k_hif_irq_disable(ab);1743ath11k_dp_pdev_free(ab);1744ath11k_spectral_deinit(ab);1745ath11k_hif_stop(ab);1746ath11k_wmi_detach(ab);1747ath11k_dp_pdev_reo_cleanup(ab);1748mutex_unlock(&ab->core_lock);17491750ath11k_dp_free(ab);1751ath11k_hal_srng_deinit(ab);17521753ab->free_vdev_map = (1LL << (ab->num_radios * TARGET_NUM_VDEVS(ab))) - 1;17541755ret = ath11k_hal_srng_init(ab);1756if (ret)1757return ret;17581759clear_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags);17601761ret = ath11k_core_qmi_firmware_ready(ab);1762if (ret)1763goto err_hal_srng_deinit;17641765clear_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags);17661767return 0;17681769err_hal_srng_deinit:1770ath11k_hal_srng_deinit(ab);1771return ret;1772}17731774void ath11k_core_halt(struct ath11k *ar)1775{1776struct ath11k_base *ab = ar->ab;17771778lockdep_assert_held(&ar->conf_mutex);17791780ar->num_created_vdevs = 0;1781ar->allocated_vdev_map = 0;17821783ath11k_mac_scan_finish(ar);1784ath11k_mac_peer_cleanup_all(ar);1785cancel_delayed_work_sync(&ar->scan.timeout);1786cancel_work_sync(&ar->regd_update_work);1787cancel_work_sync(&ab->update_11d_work);17881789rcu_assign_pointer(ab->pdevs_active[ar->pdev_idx], NULL);1790synchronize_rcu();1791INIT_LIST_HEAD(&ar->arvifs);1792idr_init(&ar->txmgmt_idr);1793}17941795static void ath11k_update_11d(struct work_struct *work)1796{1797struct ath11k_base *ab = container_of(work, struct ath11k_base, update_11d_work);1798struct ath11k *ar;1799struct ath11k_pdev *pdev;1800struct wmi_set_current_country_params set_current_param = {};1801int ret, i;18021803spin_lock_bh(&ab->base_lock);1804memcpy(&set_current_param.alpha2, &ab->new_alpha2, 2);1805spin_unlock_bh(&ab->base_lock);18061807ath11k_dbg(ab, ATH11K_DBG_WMI, "update 11d new cc %c%c\n",1808set_current_param.alpha2[0],1809set_current_param.alpha2[1]);18101811for (i = 0; i < ab->num_radios; i++) {1812pdev = &ab->pdevs[i];1813ar = pdev->ar;18141815memcpy(&ar->alpha2, &set_current_param.alpha2, 2);1816ret = ath11k_wmi_send_set_current_country_cmd(ar, &set_current_param);1817if (ret)1818ath11k_warn(ar->ab,1819"pdev id %d failed set current country code: %d\n",1820i, ret);1821}1822}18231824void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab)1825{1826struct ath11k *ar;1827struct ath11k_pdev *pdev;1828int i;18291830spin_lock_bh(&ab->base_lock);1831ab->stats.fw_crash_counter++;1832spin_unlock_bh(&ab->base_lock);18331834for (i = 0; i < ab->num_radios; i++) {1835pdev = &ab->pdevs[i];1836ar = pdev->ar;1837if (!ar || ar->state == ATH11K_STATE_OFF ||1838ar->state == ATH11K_STATE_FTM)1839continue;18401841ieee80211_stop_queues(ar->hw);1842ath11k_mac_drain_tx(ar);1843ar->state_11d = ATH11K_11D_IDLE;1844complete(&ar->completed_11d_scan);1845complete(&ar->scan.started);1846complete_all(&ar->scan.completed);1847complete(&ar->scan.on_channel);1848complete(&ar->peer_assoc_done);1849complete(&ar->peer_delete_done);1850complete(&ar->install_key_done);1851complete(&ar->vdev_setup_done);1852complete(&ar->vdev_delete_done);1853complete(&ar->bss_survey_done);1854complete(&ar->thermal.wmi_sync);18551856wake_up(&ar->dp.tx_empty_waitq);1857idr_for_each(&ar->txmgmt_idr,1858ath11k_mac_tx_mgmt_pending_free, ar);1859idr_destroy(&ar->txmgmt_idr);1860wake_up(&ar->txmgmt_empty_waitq);18611862ar->monitor_vdev_id = -1;1863clear_bit(ATH11K_FLAG_MONITOR_STARTED, &ar->monitor_flags);1864clear_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags);1865}18661867wake_up(&ab->wmi_ab.tx_credits_wq);1868wake_up(&ab->peer_mapping_wq);18691870reinit_completion(&ab->driver_recovery);1871}18721873static void ath11k_core_post_reconfigure_recovery(struct ath11k_base *ab)1874{1875struct ath11k *ar;1876struct ath11k_pdev *pdev;1877int i;18781879for (i = 0; i < ab->num_radios; i++) {1880pdev = &ab->pdevs[i];1881ar = pdev->ar;1882if (!ar || ar->state == ATH11K_STATE_OFF)1883continue;18841885mutex_lock(&ar->conf_mutex);18861887switch (ar->state) {1888case ATH11K_STATE_ON:1889ar->state = ATH11K_STATE_RESTARTING;1890ath11k_core_halt(ar);1891ieee80211_restart_hw(ar->hw);1892break;1893case ATH11K_STATE_OFF:1894ath11k_warn(ab,1895"cannot restart radio %d that hasn't been started\n",1896i);1897break;1898case ATH11K_STATE_RESTARTING:1899break;1900case ATH11K_STATE_RESTARTED:1901ar->state = ATH11K_STATE_WEDGED;1902fallthrough;1903case ATH11K_STATE_WEDGED:1904ath11k_warn(ab,1905"device is wedged, will not restart radio %d\n", i);1906break;1907case ATH11K_STATE_FTM:1908ath11k_dbg(ab, ATH11K_DBG_TESTMODE,1909"fw mode reset done radio %d\n", i);1910break;1911}19121913mutex_unlock(&ar->conf_mutex);1914}1915complete(&ab->driver_recovery);1916}19171918static void ath11k_core_restart(struct work_struct *work)1919{1920struct ath11k_base *ab = container_of(work, struct ath11k_base, restart_work);1921int ret;19221923ret = ath11k_core_reconfigure_on_crash(ab);1924if (ret) {1925ath11k_err(ab, "failed to reconfigure driver on crash recovery\n");1926return;1927}19281929if (ab->is_reset)1930complete_all(&ab->reconfigure_complete);19311932if (!ab->is_reset)1933ath11k_core_post_reconfigure_recovery(ab);1934}19351936static void ath11k_core_reset(struct work_struct *work)1937{1938struct ath11k_base *ab = container_of(work, struct ath11k_base, reset_work);1939int reset_count, fail_cont_count;1940long time_left;19411942if (!(test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags))) {1943ath11k_warn(ab, "ignore reset dev flags 0x%lx\n", ab->dev_flags);1944return;1945}19461947/* Sometimes the recovery will fail and then the next all recovery fail,1948* this is to avoid infinite recovery since it can not recovery success.1949*/1950fail_cont_count = atomic_read(&ab->fail_cont_count);19511952if (fail_cont_count >= ATH11K_RESET_MAX_FAIL_COUNT_FINAL)1953return;19541955if (fail_cont_count >= ATH11K_RESET_MAX_FAIL_COUNT_FIRST &&1956time_before(jiffies, ab->reset_fail_timeout))1957return;19581959reset_count = atomic_inc_return(&ab->reset_count);19601961if (reset_count > 1) {1962/* Sometimes it happened another reset worker before the previous one1963* completed, then the second reset worker will destroy the previous one,1964* thus below is to avoid that.1965*/1966ath11k_warn(ab, "already resetting count %d\n", reset_count);19671968reinit_completion(&ab->reset_complete);1969time_left = wait_for_completion_timeout(&ab->reset_complete,1970ATH11K_RESET_TIMEOUT_HZ);19711972if (time_left) {1973ath11k_dbg(ab, ATH11K_DBG_BOOT, "to skip reset\n");1974atomic_dec(&ab->reset_count);1975return;1976}19771978ab->reset_fail_timeout = jiffies + ATH11K_RESET_FAIL_TIMEOUT_HZ;1979/* Record the continuous recovery fail count when recovery failed*/1980atomic_inc(&ab->fail_cont_count);1981}19821983ath11k_dbg(ab, ATH11K_DBG_BOOT, "reset starting\n");19841985ab->is_reset = true;1986atomic_set(&ab->recovery_count, 0);1987reinit_completion(&ab->recovery_start);1988atomic_set(&ab->recovery_start_count, 0);19891990ath11k_core_pre_reconfigure_recovery(ab);19911992reinit_completion(&ab->reconfigure_complete);1993ath11k_core_post_reconfigure_recovery(ab);19941995ath11k_dbg(ab, ATH11K_DBG_BOOT, "waiting recovery start...\n");19961997time_left = wait_for_completion_timeout(&ab->recovery_start,1998ATH11K_RECOVER_START_TIMEOUT_HZ);19992000ath11k_hif_power_down(ab);2001ath11k_hif_power_up(ab);20022003ath11k_dbg(ab, ATH11K_DBG_BOOT, "reset started\n");2004}20052006static int ath11k_init_hw_params(struct ath11k_base *ab)2007{2008const struct ath11k_hw_params *hw_params = NULL;2009int i;20102011for (i = 0; i < ARRAY_SIZE(ath11k_hw_params); i++) {2012hw_params = &ath11k_hw_params[i];20132014if (hw_params->hw_rev == ab->hw_rev)2015break;2016}20172018if (i == ARRAY_SIZE(ath11k_hw_params)) {2019ath11k_err(ab, "Unsupported hardware version: 0x%x\n", ab->hw_rev);2020return -EINVAL;2021}20222023ab->hw_params = *hw_params;20242025ath11k_info(ab, "%s\n", ab->hw_params.name);20262027return 0;2028}20292030int ath11k_core_pre_init(struct ath11k_base *ab)2031{2032int ret;20332034ret = ath11k_init_hw_params(ab);2035if (ret) {2036ath11k_err(ab, "failed to get hw params: %d\n", ret);2037return ret;2038}20392040return 0;2041}2042EXPORT_SYMBOL(ath11k_core_pre_init);20432044int ath11k_core_init(struct ath11k_base *ab)2045{2046int ret;20472048ret = ath11k_core_soc_create(ab);2049if (ret) {2050ath11k_err(ab, "failed to create soc core: %d\n", ret);2051return ret;2052}20532054return 0;2055}2056EXPORT_SYMBOL(ath11k_core_init);20572058void ath11k_core_deinit(struct ath11k_base *ab)2059{2060mutex_lock(&ab->core_lock);20612062ath11k_core_pdev_destroy(ab);2063ath11k_core_stop(ab);20642065mutex_unlock(&ab->core_lock);20662067ath11k_hif_power_down(ab);2068ath11k_mac_destroy(ab);2069ath11k_core_soc_destroy(ab);2070}2071EXPORT_SYMBOL(ath11k_core_deinit);20722073void ath11k_core_free(struct ath11k_base *ab)2074{2075destroy_workqueue(ab->workqueue_aux);2076destroy_workqueue(ab->workqueue);20772078kfree(ab);2079}2080EXPORT_SYMBOL(ath11k_core_free);20812082struct ath11k_base *ath11k_core_alloc(struct device *dev, size_t priv_size,2083enum ath11k_bus bus)2084{2085struct ath11k_base *ab;20862087ab = kzalloc(sizeof(*ab) + priv_size, GFP_KERNEL);2088if (!ab)2089return NULL;20902091init_completion(&ab->driver_recovery);20922093ab->workqueue = create_singlethread_workqueue("ath11k_wq");2094if (!ab->workqueue)2095goto err_sc_free;20962097ab->workqueue_aux = create_singlethread_workqueue("ath11k_aux_wq");2098if (!ab->workqueue_aux)2099goto err_free_wq;21002101mutex_init(&ab->core_lock);2102mutex_init(&ab->tbl_mtx_lock);2103spin_lock_init(&ab->base_lock);2104mutex_init(&ab->vdev_id_11d_lock);2105init_completion(&ab->reset_complete);2106init_completion(&ab->reconfigure_complete);2107init_completion(&ab->recovery_start);21082109INIT_LIST_HEAD(&ab->peers);2110init_waitqueue_head(&ab->peer_mapping_wq);2111init_waitqueue_head(&ab->wmi_ab.tx_credits_wq);2112init_waitqueue_head(&ab->qmi.cold_boot_waitq);2113INIT_WORK(&ab->restart_work, ath11k_core_restart);2114INIT_WORK(&ab->update_11d_work, ath11k_update_11d);2115INIT_WORK(&ab->reset_work, ath11k_core_reset);2116timer_setup(&ab->rx_replenish_retry, ath11k_ce_rx_replenish_retry, 0);2117init_completion(&ab->htc_suspend);2118init_completion(&ab->wow.wakeup_completed);21192120ab->dev = dev;2121ab->hif.bus = bus;21222123return ab;21242125err_free_wq:2126destroy_workqueue(ab->workqueue);2127err_sc_free:2128kfree(ab);2129return NULL;2130}2131EXPORT_SYMBOL(ath11k_core_alloc);21322133MODULE_DESCRIPTION("Core module for Qualcomm Atheros 802.11ax wireless LAN cards.");2134MODULE_LICENSE("Dual BSD/GPL");213521362137