ath.git patches for v6.20 (#2)

Highlights for some specific drivers include:
 
 ath11k:
 Add support for Channel Frequency Response measurement.
 
 ath12k:
 Add support for the QCC2072 chipset.
 
 And of course there is the usual set of cleanups and bug fixes across
 the entire family of "ath" drivers.
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQQ/mtSHzPUi16IfDEksFbugiYzLewUCaW+dBQAKCRAsFbugiYzL
 e1/sAP0fkZQaEECdvUz3VZQuiWQK/+P5wBtXggrjnPDTGkGUowEAs66hradqoKqK
 LQA0pwfT9f1BKvQj1MVnc6o74O+6HAA=
 =AP4S
 -----END PGP SIGNATURE-----

Merge tag 'ath-next-20260120' of git://git.kernel.org/pub/scm/linux/kernel/git/ath/ath

Jeff Johnson says:
==================
ath.git patches for v6.20 (#2)

Highlights for some specific drivers include:

ath11k:
Add support for Channel Frequency Response measurement.

ath12k:
Add support for the QCC2072 chipset.

And of course there is the usual set of cleanups and bug fixes across
the entire family of "ath" drivers.
==================

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Johannes Berg 2026-01-27 13:52:23 +01:00
commit a410d3fb30
59 changed files with 3135 additions and 236 deletions

View File

@ -214,15 +214,6 @@ allOf:
- const: wbm2host-tx-completions-ring2
- const: wbm2host-tx-completions-ring1
- const: tcl2host-status-ring
- if:
properties:
compatible:
contains:
enum:
- qcom,ipq8074-wifi
- qcom,ipq6018-wifi
then:
required:
- interrupt-names

View File

@ -58,3 +58,14 @@ config ATH11K_SPECTRAL
Enable ath11k spectral scan support
Say Y to enable access to the FFT/spectral data via debugfs.
config ATH11K_CFR
bool "ath11k channel frequency response support"
depends on ATH11K_DEBUGFS
depends on RELAY
help
Enable ath11k channel frequency response dump support.
This option exposes debugfs nodes that will allow the user
to enable, disable, and dump data.
Say Y to enable CFR data dump collection via debugfs.

View File

@ -28,6 +28,7 @@ ath11k-$(CONFIG_THERMAL) += thermal.o
ath11k-$(CONFIG_ATH11K_SPECTRAL) += spectral.o
ath11k-$(CONFIG_PM) += wow.o
ath11k-$(CONFIG_DEV_COREDUMP) += coredump.o
ath11k-$(CONFIG_ATH11K_CFR) += cfr.o
obj-$(CONFIG_ATH11K_AHB) += ath11k_ahb.o
ath11k_ahb-y += ahb.o

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,308 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2020-2021 The Linux Foundation. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#ifndef ATH11K_CFR_H
#define ATH11K_CFR_H
#include "dbring.h"
#include "wmi.h"
#define ATH11K_CFR_NUM_RESP_PER_EVENT 1
#define ATH11K_CFR_EVENT_TIMEOUT_MS 1
#define ATH11K_CFR_NUM_RING_ENTRIES 1
#define ATH11K_MAX_CFR_ENABLED_CLIENTS 10
#define CFR_MAX_LUT_ENTRIES 136
#define HOST_MAX_CHAINS 8
enum ath11k_cfr_correlate_event_type {
ATH11K_CORRELATE_DBR_EVENT,
ATH11K_CORRELATE_TX_EVENT,
};
struct ath11k_sta;
struct ath11k_per_peer_cfr_capture;
#define ATH11K_CFR_START_MAGIC 0xDEADBEAF
#define ATH11K_CFR_END_MAGIC 0xBEAFDEAD
#define VENDOR_QCA 0x8cfdf0
#define PLATFORM_TYPE_ARM 2
enum ath11k_cfr_meta_version {
ATH11K_CFR_META_VERSION_NONE,
ATH11K_CFR_META_VERSION_1,
ATH11K_CFR_META_VERSION_2,
ATH11K_CFR_META_VERSION_3,
ATH11K_CFR_META_VERSION_4,
ATH11K_CFR_META_VERSION_MAX = 0xFF,
};
enum ath11k_cfr_data_version {
ATH11K_CFR_DATA_VERSION_NONE,
ATH11K_CFR_DATA_VERSION_1,
ATH11K_CFR_DATA_VERSION_MAX = 0xFF,
};
enum ath11k_cfr_capture_ack_mode {
ATH11K_CFR_CAPTURE_LEGACY_ACK,
ATH11K_CFR_CAPTURE_DUP_LEGACY_ACK,
ATH11K_CFR_CAPTURE_HT_ACK,
ATH11K_CFR_CAPTURE_VHT_ACK,
/*Always keep this at last*/
ATH11K_CFR_CAPTURE_INVALID_ACK
};
enum ath11k_cfr_correlate_status {
ATH11K_CORRELATE_STATUS_RELEASE,
ATH11K_CORRELATE_STATUS_HOLD,
ATH11K_CORRELATE_STATUS_ERR,
};
enum ath11k_cfr_preamble_type {
ATH11K_CFR_PREAMBLE_TYPE_LEGACY,
ATH11K_CFR_PREAMBLE_TYPE_HT,
ATH11K_CFR_PREAMBLE_TYPE_VHT,
};
struct ath11k_cfr_peer_tx_param {
u32 capture_method;
u32 vdev_id;
u8 peer_mac_addr[ETH_ALEN];
u32 primary_20mhz_chan;
u32 bandwidth;
u32 phy_mode;
u32 band_center_freq1;
u32 band_center_freq2;
u32 spatial_streams;
u32 correlation_info_1;
u32 correlation_info_2;
u32 status;
u32 timestamp_us;
u32 counter;
u32 chain_rssi[WMI_MAX_CHAINS];
u16 chain_phase[WMI_MAX_CHAINS];
u32 cfo_measurement;
u8 agc_gain[HOST_MAX_CHAINS];
u32 rx_start_ts;
};
struct cfr_metadata {
u8 peer_addr[ETH_ALEN];
u8 status;
u8 capture_bw;
u8 channel_bw;
u8 phy_mode;
u16 prim20_chan;
u16 center_freq1;
u16 center_freq2;
u8 capture_mode;
u8 capture_type;
u8 sts_count;
u8 num_rx_chain;
u32 timestamp;
u32 length;
u32 chain_rssi[HOST_MAX_CHAINS];
u16 chain_phase[HOST_MAX_CHAINS];
u32 cfo_measurement;
u8 agc_gain[HOST_MAX_CHAINS];
u32 rx_start_ts;
} __packed;
struct ath11k_csi_cfr_header {
u32 start_magic_num;
u32 vendorid;
u8 cfr_metadata_version;
u8 cfr_data_version;
u8 chip_type;
u8 platform_type;
u32 cfr_metadata_len;
struct cfr_metadata meta_data;
} __packed;
#define TONES_IN_20MHZ 256
#define TONES_IN_40MHZ 512
#define TONES_IN_80MHZ 1024
#define TONES_IN_160MHZ 2048 /* 160 MHz isn't supported yet */
#define TONES_INVALID 0
#define CFIR_DMA_HDR_INFO0_TAG GENMASK(7, 0)
#define CFIR_DMA_HDR_INFO0_LEN GENMASK(13, 8)
#define CFIR_DMA_HDR_INFO1_UPLOAD_DONE GENMASK(0, 0)
#define CFIR_DMA_HDR_INFO1_CAPTURE_TYPE GENMASK(3, 1)
#define CFIR_DMA_HDR_INFO1_PREAMBLE_TYPE GENMASK(5, 4)
#define CFIR_DMA_HDR_INFO1_NSS GENMASK(8, 6)
#define CFIR_DMA_HDR_INFO1_NUM_CHAINS GENMASK(11, 9)
#define CFIR_DMA_HDR_INFO1_UPLOAD_PKT_BW GENMASK(14, 12)
#define CFIR_DMA_HDR_INFO1_SW_PEER_ID_VALID GENMASK(15, 15)
struct ath11k_cfr_dma_hdr {
u16 info0;
u16 info1;
u16 sw_peer_id;
u16 phy_ppdu_id;
};
struct ath11k_look_up_table {
bool dbr_recv;
bool tx_recv;
u8 *data;
u32 data_len;
u16 dbr_ppdu_id;
u16 tx_ppdu_id;
dma_addr_t dbr_address;
struct ath11k_csi_cfr_header header;
struct ath11k_cfr_dma_hdr hdr;
u64 txrx_tstamp;
u64 dbr_tstamp;
u32 header_length;
u32 payload_length;
struct ath11k_dbring_element *buff;
};
struct cfr_unassoc_pool_entry {
u8 peer_mac[ETH_ALEN];
u32 period;
bool is_valid;
};
struct ath11k_cfr {
struct ath11k_dbring rx_ring;
/* Protects cfr data */
spinlock_t lock;
/* Protect for lut entries */
spinlock_t lut_lock;
struct ath11k_look_up_table *lut;
struct dentry *enable_cfr;
struct dentry *cfr_unassoc;
struct rchan *rfs_cfr_capture;
u8 cfr_enabled_peer_cnt;
u32 lut_num;
u64 tx_evt_cnt;
u64 dbr_evt_cnt;
u64 release_cnt;
u64 tx_peer_status_cfr_fail;
u64 tx_evt_status_cfr_fail;
u64 tx_dbr_lookup_fail;
u64 last_success_tstamp;
u64 flush_dbr_cnt;
u64 clear_txrx_event;
u64 cfr_dma_aborts;
bool enabled;
enum wmi_phy_mode phymode;
struct cfr_unassoc_pool_entry unassoc_pool[ATH11K_MAX_CFR_ENABLED_CLIENTS];
};
enum ath11k_cfr_capture_method {
ATH11K_CFR_CAPTURE_METHOD_NULL_FRAME,
ATH11K_CFR_CAPTURE_METHOD_NULL_FRAME_WITH_PHASE,
ATH11K_CFR_CAPTURE_METHOD_PROBE_RESP,
ATH11K_CFR_CAPTURE_METHOD_MAX,
};
enum ath11k_cfr_capture_bw {
ATH11K_CFR_CAPTURE_BW_20,
ATH11K_CFR_CAPTURE_BW_40,
ATH11K_CFR_CAPTURE_BW_80,
ATH11K_CFR_CAPTURE_BW_MAX,
};
#ifdef CONFIG_ATH11K_CFR
int ath11k_cfr_init(struct ath11k_base *ab);
void ath11k_cfr_deinit(struct ath11k_base *ab);
void ath11k_cfr_lut_update_paddr(struct ath11k *ar, dma_addr_t paddr,
u32 buf_id);
void ath11k_cfr_decrement_peer_count(struct ath11k *ar,
struct ath11k_sta *arsta);
void ath11k_cfr_update_unassoc_pool_entry(struct ath11k *ar,
const u8 *peer_mac);
bool ath11k_cfr_peer_is_in_cfr_unassoc_pool(struct ath11k *ar,
const u8 *peer_mac);
void ath11k_cfr_update_unassoc_pool(struct ath11k *ar,
struct ath11k_per_peer_cfr_capture *params,
u8 *peer_mac);
int ath11k_cfr_send_peer_cfr_capture_cmd(struct ath11k *ar,
struct ath11k_sta *arsta,
struct ath11k_per_peer_cfr_capture *params,
const u8 *peer_mac);
struct ath11k_dbring *ath11k_cfr_get_dbring(struct ath11k *ar);
void ath11k_cfr_release_lut_entry(struct ath11k_look_up_table *lut);
int ath11k_process_cfr_capture_event(struct ath11k_base *ab,
struct ath11k_cfr_peer_tx_param *params);
void ath11k_cfr_update_phymode(struct ath11k *ar, enum wmi_phy_mode phymode);
#else
static inline void ath11k_cfr_update_phymode(struct ath11k *ar,
enum wmi_phy_mode phymode)
{
}
static inline int ath11k_cfr_init(struct ath11k_base *ab)
{
return 0;
}
static inline void ath11k_cfr_deinit(struct ath11k_base *ab)
{
}
static inline void ath11k_cfr_lut_update_paddr(struct ath11k *ar,
dma_addr_t paddr, u32 buf_id)
{
}
static inline void ath11k_cfr_decrement_peer_count(struct ath11k *ar,
struct ath11k_sta *arsta)
{
}
static inline void ath11k_cfr_update_unassoc_pool_entry(struct ath11k *ar,
const u8 *peer_mac)
{
}
static inline bool
ath11k_cfr_peer_is_in_cfr_unassoc_pool(struct ath11k *ar, const u8 *peer_mac)
{
return false;
}
static inline void
ath11k_cfr_update_unassoc_pool(struct ath11k *ar,
struct ath11k_per_peer_cfr_capture *params,
u8 *peer_mac)
{
}
static inline int
ath11k_cfr_send_peer_cfr_capture_cmd(struct ath11k *ar,
struct ath11k_sta *arsta,
struct ath11k_per_peer_cfr_capture *params,
const u8 *peer_mac)
{
return 0;
}
static inline void ath11k_cfr_release_lut_entry(struct ath11k_look_up_table *lut)
{
}
static inline
struct ath11k_dbring *ath11k_cfr_get_dbring(struct ath11k *ar)
{
return NULL;
}
static inline
int ath11k_process_cfr_capture_event(struct ath11k_base *ab,
struct ath11k_cfr_peer_tx_param *params)
{
return 0;
}
#endif /* CONFIG_ATH11K_CFR */
#endif /* ATH11K_CFR_H */

View File

@ -1,7 +1,6 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
* Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
@ -100,7 +99,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_regdb = false,
.fix_l1ss = true,
.credit_flow = false,
.max_tx_ring = DP_TCL_NUM_RING_MAX,
.hal_params = &ath11k_hw_hal_params_ipq8074,
.supports_dynamic_smps_6ghz = false,
.alloc_cacheable_memory = true,
@ -126,6 +124,9 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.smp2p_wow_exit = false,
.support_dual_stations = false,
.pdev_suspend = false,
.cfr_support = true,
.cfr_num_stream_bufs = 255,
.cfr_stream_buf_size = 8200,
},
{
.hw_rev = ATH11K_HW_IPQ6018_HW10,
@ -184,7 +185,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_regdb = false,
.fix_l1ss = true,
.credit_flow = false,
.max_tx_ring = DP_TCL_NUM_RING_MAX,
.hal_params = &ath11k_hw_hal_params_ipq8074,
.supports_dynamic_smps_6ghz = false,
.alloc_cacheable_memory = true,
@ -211,6 +211,9 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.support_fw_mac_sequence = false,
.support_dual_stations = false,
.pdev_suspend = false,
.cfr_support = false,
.cfr_num_stream_bufs = 0,
.cfr_stream_buf_size = 0,
},
{
.name = "qca6390 hw2.0",
@ -271,7 +274,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_regdb = false,
.fix_l1ss = true,
.credit_flow = true,
.max_tx_ring = DP_TCL_NUM_RING_MAX_QCA6390,
.hal_params = &ath11k_hw_hal_params_qca6390,
.supports_dynamic_smps_6ghz = false,
.alloc_cacheable_memory = false,
@ -301,6 +303,9 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.support_fw_mac_sequence = true,
.support_dual_stations = true,
.pdev_suspend = false,
.cfr_support = false,
.cfr_num_stream_bufs = 0,
.cfr_stream_buf_size = 0,
},
{
.name = "qcn9074 hw1.0",
@ -358,7 +363,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_regdb = false,
.fix_l1ss = true,
.credit_flow = false,
.max_tx_ring = DP_TCL_NUM_RING_MAX,
.hal_params = &ath11k_hw_hal_params_ipq8074,
.supports_dynamic_smps_6ghz = true,
.alloc_cacheable_memory = true,
@ -385,6 +389,9 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.support_fw_mac_sequence = false,
.support_dual_stations = false,
.pdev_suspend = false,
.cfr_support = false,
.cfr_num_stream_bufs = 0,
.cfr_stream_buf_size = 0,
},
{
.name = "wcn6855 hw2.0",
@ -445,7 +452,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_regdb = true,
.fix_l1ss = false,
.credit_flow = true,
.max_tx_ring = DP_TCL_NUM_RING_MAX_QCA6390,
.hal_params = &ath11k_hw_hal_params_qca6390,
.supports_dynamic_smps_6ghz = false,
.alloc_cacheable_memory = false,
@ -475,6 +481,9 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.support_fw_mac_sequence = true,
.support_dual_stations = true,
.pdev_suspend = false,
.cfr_support = false,
.cfr_num_stream_bufs = 0,
.cfr_stream_buf_size = 0,
},
{
.name = "wcn6855 hw2.1",
@ -533,7 +542,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_regdb = true,
.fix_l1ss = false,
.credit_flow = true,
.max_tx_ring = DP_TCL_NUM_RING_MAX_QCA6390,
.hal_params = &ath11k_hw_hal_params_qca6390,
.supports_dynamic_smps_6ghz = false,
.alloc_cacheable_memory = false,
@ -563,6 +571,9 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.support_fw_mac_sequence = true,
.support_dual_stations = true,
.pdev_suspend = false,
.cfr_support = true,
.cfr_num_stream_bufs = 255,
.cfr_stream_buf_size = 8200,
},
{
.name = "wcn6750 hw1.0",
@ -619,7 +630,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_regdb = true,
.fix_l1ss = false,
.credit_flow = true,
.max_tx_ring = DP_TCL_NUM_RING_MAX,
.hal_params = &ath11k_hw_hal_params_wcn6750,
.supports_dynamic_smps_6ghz = false,
.alloc_cacheable_memory = false,
@ -646,6 +656,9 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.support_fw_mac_sequence = true,
.support_dual_stations = false,
.pdev_suspend = true,
.cfr_support = false,
.cfr_num_stream_bufs = 0,
.cfr_stream_buf_size = 0,
},
{
.hw_rev = ATH11K_HW_IPQ5018_HW10,
@ -662,7 +675,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.qmi_service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_IPQ8074,
.ring_mask = &ath11k_hw_ring_mask_ipq8074,
.credit_flow = false,
.max_tx_ring = 1,
.spectral = {
.fft_sz = 2,
.fft_pad_sz = 0,
@ -698,7 +710,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_regdb = false,
.idle_ps = false,
.supports_suspend = false,
.hal_params = &ath11k_hw_hal_params_ipq8074,
.hal_params = &ath11k_hw_hal_params_ipq5018,
.single_pdev_only = false,
.coldboot_cal_mm = true,
.coldboot_cal_ftm = true,
@ -729,6 +741,9 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.support_fw_mac_sequence = false,
.support_dual_stations = false,
.pdev_suspend = false,
.cfr_support = false,
.cfr_num_stream_bufs = 0,
.cfr_stream_buf_size = 0,
},
{
.name = "qca2066 hw2.1",
@ -789,7 +804,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_regdb = true,
.fix_l1ss = false,
.credit_flow = true,
.max_tx_ring = DP_TCL_NUM_RING_MAX_QCA6390,
.hal_params = &ath11k_hw_hal_params_qca6390,
.supports_dynamic_smps_6ghz = false,
.alloc_cacheable_memory = false,
@ -818,6 +832,9 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.smp2p_wow_exit = false,
.support_fw_mac_sequence = true,
.support_dual_stations = true,
.cfr_support = false,
.cfr_num_stream_bufs = 0,
.cfr_stream_buf_size = 0,
},
{
.name = "qca6698aq hw2.1",
@ -876,7 +893,6 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.supports_regdb = true,
.fix_l1ss = false,
.credit_flow = true,
.max_tx_ring = DP_TCL_NUM_RING_MAX_QCA6390,
.hal_params = &ath11k_hw_hal_params_qca6390,
.supports_dynamic_smps_6ghz = false,
.alloc_cacheable_memory = false,
@ -906,6 +922,9 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.support_fw_mac_sequence = true,
.support_dual_stations = true,
.pdev_suspend = false,
.cfr_support = true,
.cfr_num_stream_bufs = 255,
.cfr_stream_buf_size = 8200,
},
};
@ -994,6 +1013,34 @@ static const struct dmi_system_id ath11k_pm_quirk_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "21F9"),
},
},
{
.driver_data = (void *)ATH11K_PM_WOW,
.matches = { /* Z13 G1 */
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "21D2"),
},
},
{
.driver_data = (void *)ATH11K_PM_WOW,
.matches = { /* Z13 G1 */
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "21D3"),
},
},
{
.driver_data = (void *)ATH11K_PM_WOW,
.matches = { /* Z16 G1 */
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "21D4"),
},
},
{
.driver_data = (void *)ATH11K_PM_WOW,
.matches = { /* Z16 G1 */
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "21D5"),
},
},
{}
};
@ -1987,8 +2034,16 @@ static int ath11k_core_pdev_create(struct ath11k_base *ab)
goto err_thermal_unregister;
}
ret = ath11k_cfr_init(ab);
if (ret) {
ath11k_err(ab, "failed to init cfr %d\n", ret);
goto err_spectral_unregister;
}
return 0;
err_spectral_unregister:
ath11k_spectral_deinit(ab);
err_thermal_unregister:
ath11k_thermal_unregister(ab);
err_mac_unregister:
@ -2038,6 +2093,7 @@ static void ath11k_core_pdev_suspend_target(struct ath11k_base *ab)
static void ath11k_core_pdev_destroy(struct ath11k_base *ab)
{
ath11k_cfr_deinit(ab);
ath11k_spectral_deinit(ab);
ath11k_thermal_unregister(ab);
ath11k_mac_unregister(ab);
@ -2250,6 +2306,7 @@ static int ath11k_core_reconfigure_on_crash(struct ath11k_base *ab)
mutex_lock(&ab->core_lock);
ath11k_thermal_unregister(ab);
ath11k_dp_pdev_free(ab);
ath11k_cfr_deinit(ab);
ath11k_spectral_deinit(ab);
ath11k_ce_cleanup_pipes(ab);
ath11k_wmi_detach(ab);

View File

@ -1,7 +1,7 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
* Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#ifndef ATH11K_CORE_H
@ -35,6 +35,7 @@
#include "wow.h"
#include "fw.h"
#include "coredump.h"
#include "cfr.h"
#define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK)
@ -531,6 +532,13 @@ struct ath11k_per_ppdu_tx_stats {
DECLARE_EWMA(avg_rssi, 10, 8)
struct ath11k_per_peer_cfr_capture {
enum ath11k_cfr_capture_method cfr_method;
enum ath11k_cfr_capture_bw cfr_bw;
u32 cfr_enable;
u32 cfr_period;
};
struct ath11k_sta {
struct ath11k_vif *arvif;
@ -571,6 +579,10 @@ struct ath11k_sta {
bool peer_current_ps_valid;
u32 bw_prev;
#ifdef CONFIG_ATH11K_CFR
struct ath11k_per_peer_cfr_capture cfr_capture;
#endif
};
#define ATH11K_MIN_5G_FREQ 4150
@ -795,6 +807,11 @@ struct ath11k {
bool ps_state_enable;
bool ps_timekeeper_enable;
s8 max_allowed_tx_power;
#ifdef CONFIG_ATH11K_CFR
struct ath11k_cfr cfr;
#endif
bool cfr_enabled;
};
struct ath11k_band_cap {

View File

@ -1,7 +1,6 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2019-2020 The Linux Foundation. All rights reserved.
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
@ -37,10 +36,10 @@ static void ath11k_dbring_fill_magic_value(struct ath11k *ar,
memset32(buffer, ATH11K_DB_MAGIC_VALUE, size);
}
static int ath11k_dbring_bufs_replenish(struct ath11k *ar,
struct ath11k_dbring *ring,
struct ath11k_dbring_element *buff,
enum wmi_direct_buffer_module id)
int ath11k_dbring_bufs_replenish(struct ath11k *ar,
struct ath11k_dbring *ring,
struct ath11k_dbring_element *buff,
enum wmi_direct_buffer_module id)
{
struct ath11k_base *ab = ar->ab;
struct hal_srng *srng;
@ -80,6 +79,9 @@ static int ath11k_dbring_bufs_replenish(struct ath11k *ar,
goto err_idr_remove;
}
if (id == WMI_DIRECT_BUF_CFR)
ath11k_cfr_lut_update_paddr(ar, paddr, buf_id);
buff->paddr = paddr;
cookie = FIELD_PREP(DP_RXDMA_BUF_COOKIE_PDEV_ID, ar->pdev_idx) |
@ -155,12 +157,11 @@ int ath11k_dbring_wmi_cfg_setup(struct ath11k *ar,
enum wmi_direct_buffer_module id)
{
struct ath11k_wmi_pdev_dma_ring_cfg_req_cmd param = {};
int ret;
int ret, i;
if (id >= WMI_DIRECT_BUF_MAX)
return -EINVAL;
param.pdev_id = DP_SW2HW_MACID(ring->pdev_id);
param.module_id = id;
param.base_paddr_lo = lower_32_bits(ring->refill_srng.paddr);
param.base_paddr_hi = upper_32_bits(ring->refill_srng.paddr);
@ -173,10 +174,23 @@ int ath11k_dbring_wmi_cfg_setup(struct ath11k *ar,
param.num_resp_per_event = ring->num_resp_per_event;
param.event_timeout_ms = ring->event_timeout_ms;
ret = ath11k_wmi_pdev_dma_ring_cfg(ar, &param);
if (ret) {
ath11k_warn(ar->ab, "failed to setup db ring cfg\n");
return ret;
/* For single pdev, 2GHz and 5GHz use one DBR. */
if (ar->ab->hw_params.single_pdev_only) {
for (i = 0; i < ar->ab->target_pdev_count; i++) {
param.pdev_id = ar->ab->target_pdev_ids[i].pdev_id;
ret = ath11k_wmi_pdev_dma_ring_cfg(ar, &param);
if (ret) {
ath11k_warn(ar->ab, "failed to setup db ring cfg\n");
return ret;
}
}
} else {
param.pdev_id = DP_SW2HW_MACID(ring->pdev_id);
ret = ath11k_wmi_pdev_dma_ring_cfg(ar, &param);
if (ret) {
ath11k_warn(ar->ab, "failed to setup db ring cfg\n");
return ret;
}
}
return 0;
@ -281,10 +295,15 @@ int ath11k_dbring_buffer_release_event(struct ath11k_base *ab,
int size;
dma_addr_t paddr;
int ret = 0;
int status;
pdev_idx = ev->fixed.pdev_id;
module_id = ev->fixed.module_id;
if (ab->hw_params.single_pdev_only &&
pdev_idx < ab->target_pdev_count)
pdev_idx = 0;
if (pdev_idx >= ab->num_radios) {
ath11k_warn(ab, "Invalid pdev id %d\n", pdev_idx);
return -EINVAL;
@ -310,6 +329,9 @@ int ath11k_dbring_buffer_release_event(struct ath11k_base *ab,
case WMI_DIRECT_BUF_SPECTRAL:
ring = ath11k_spectral_get_dbring(ar);
break;
case WMI_DIRECT_BUF_CFR:
ring = ath11k_cfr_get_dbring(ar);
break;
default:
ring = NULL;
ath11k_warn(ab, "Recv dma buffer release ev on unsupp module %d\n",
@ -360,8 +382,12 @@ int ath11k_dbring_buffer_release_event(struct ath11k_base *ab,
handler_data.data = PTR_ALIGN(vaddr_unalign,
ring->buf_align);
handler_data.data_sz = ring->buf_sz;
handler_data.buff = buff;
handler_data.buf_id = buf_id;
ring->handler(ar, &handler_data);
status = ring->handler(ar, &handler_data);
if (status == ATH11K_CORRELATE_STATUS_HOLD)
continue;
}
buff->paddr = 0;

View File

@ -1,7 +1,7 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2019-2020 The Linux Foundation. All rights reserved.
* Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#ifndef ATH11K_DBRING_H
@ -21,6 +21,8 @@ struct ath11k_dbring_data {
void *data;
u32 data_sz;
struct wmi_dma_buf_release_meta_data meta;
struct ath11k_dbring_element *buff;
u32 buf_id;
};
struct ath11k_dbring_buf_release_event {
@ -61,6 +63,10 @@ int ath11k_dbring_set_cfg(struct ath11k *ar,
u32 event_timeout_ms,
int (*handler)(struct ath11k *,
struct ath11k_dbring_data *));
int ath11k_dbring_bufs_replenish(struct ath11k *ar,
struct ath11k_dbring *ring,
struct ath11k_dbring_element *buff,
enum wmi_direct_buffer_module id);
int ath11k_dbring_wmi_cfg_setup(struct ath11k *ar,
struct ath11k_dbring *ring,
enum wmi_direct_buffer_module id);

View File

@ -1,7 +1,7 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#ifndef _ATH11K_DEBUG_H_
@ -27,6 +27,8 @@ enum ath11k_debug_mask {
ATH11K_DBG_DP_TX = 0x00002000,
ATH11K_DBG_DP_RX = 0x00004000,
ATH11K_DBG_CE = 0x00008000,
ATH11K_DBG_CFR = 0x00010000,
ATH11K_DBG_CFR_DUMP = 0x00020000,
};
static inline const char *ath11k_dbg_str(enum ath11k_debug_mask mask)
@ -64,6 +66,10 @@ static inline const char *ath11k_dbg_str(enum ath11k_debug_mask mask)
return "dp_rx";
case ATH11K_DBG_CE:
return "ce";
case ATH11K_DBG_CFR:
return "cfr";
case ATH11K_DBG_CFR_DUMP:
return "cfr_dump";
/* no default handler to allow compiler to check that the
* enum is fully handled

View File

@ -707,7 +707,7 @@ static ssize_t ath11k_debugfs_dump_soc_dp_stats(struct file *file,
len += scnprintf(buf + len, size - len, "\nSOC TX STATS:\n");
len += scnprintf(buf + len, size - len, "\nTCL Ring Full Failures:\n");
for (i = 0; i < ab->hw_params.max_tx_ring; i++)
for (i = 0; i < ab->hw_params.hal_params->num_tx_rings; i++)
len += scnprintf(buf + len, size - len, "ring%d: %u\n",
i, soc_stats->tx_err.desc_na[i]);

View File

@ -1,7 +1,6 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
@ -240,6 +239,140 @@ static const struct file_operations fops_tx_stats = {
.llseek = default_llseek,
};
#ifdef CONFIG_ATH11K_CFR
static ssize_t ath11k_dbg_sta_write_cfr_capture(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ieee80211_sta *sta = file->private_data;
struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
struct ath11k *ar = arsta->arvif->ar;
struct ath11k_cfr *cfr = &ar->cfr;
struct wmi_peer_cfr_capture_conf_arg arg;
u32 cfr_capture_enable = 0, cfr_capture_bw = 0;
u32 cfr_capture_method = 0, cfr_capture_period = 0;
char buf[64] = {};
int ret;
simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
guard(mutex)(&ar->conf_mutex);
if (ar->state != ATH11K_STATE_ON)
return -ENETDOWN;
if (!ar->cfr_enabled)
return -EINVAL;
ret = sscanf(buf, "%u %u %u %u", &cfr_capture_enable, &cfr_capture_bw,
&cfr_capture_period, &cfr_capture_method);
if (ret < 1 || (cfr_capture_enable && ret != 4))
return -EINVAL;
if (cfr_capture_enable == arsta->cfr_capture.cfr_enable &&
(cfr_capture_period &&
cfr_capture_period == arsta->cfr_capture.cfr_period) &&
cfr_capture_bw == arsta->cfr_capture.cfr_bw &&
cfr_capture_method == arsta->cfr_capture.cfr_method)
return count;
if (!cfr_capture_enable &&
cfr_capture_enable == arsta->cfr_capture.cfr_enable)
return count;
if (cfr_capture_enable > WMI_PEER_CFR_CAPTURE_ENABLE ||
cfr_capture_bw > WMI_PEER_CFR_CAPTURE_BW_80 ||
cfr_capture_method > ATH11K_CFR_CAPTURE_METHOD_NULL_FRAME_WITH_PHASE ||
cfr_capture_period > WMI_PEER_CFR_PERIODICITY_MAX)
return -EINVAL;
/* Target expects cfr period in multiple of 10 */
if (cfr_capture_period % 10) {
ath11k_err(ar->ab, "periodicity should be 10x\n");
return -EINVAL;
}
if (ar->cfr.cfr_enabled_peer_cnt >= ATH11K_MAX_CFR_ENABLED_CLIENTS &&
!arsta->cfr_capture.cfr_enable) {
ath11k_err(ar->ab, "CFR enable peer threshold reached %u\n",
ar->cfr.cfr_enabled_peer_cnt);
return -EINVAL;
}
if (!cfr_capture_enable) {
cfr_capture_bw = arsta->cfr_capture.cfr_bw;
cfr_capture_period = arsta->cfr_capture.cfr_period;
cfr_capture_method = arsta->cfr_capture.cfr_method;
}
arg.request = cfr_capture_enable;
arg.periodicity = cfr_capture_period;
arg.bw = cfr_capture_bw;
arg.method = cfr_capture_method;
ret = ath11k_wmi_peer_set_cfr_capture_conf(ar, arsta->arvif->vdev_id,
sta->addr, &arg);
if (ret) {
ath11k_warn(ar->ab,
"failed to send cfr capture info: vdev_id %u peer %pM: %d\n",
arsta->arvif->vdev_id, sta->addr, ret);
return ret;
}
spin_lock_bh(&ar->cfr.lock);
if (cfr_capture_enable &&
cfr_capture_enable != arsta->cfr_capture.cfr_enable)
cfr->cfr_enabled_peer_cnt++;
else if (!cfr_capture_enable)
cfr->cfr_enabled_peer_cnt--;
spin_unlock_bh(&ar->cfr.lock);
arsta->cfr_capture.cfr_enable = cfr_capture_enable;
arsta->cfr_capture.cfr_period = cfr_capture_period;
arsta->cfr_capture.cfr_bw = cfr_capture_bw;
arsta->cfr_capture.cfr_method = cfr_capture_method;
return count;
}
static ssize_t ath11k_dbg_sta_read_cfr_capture(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ieee80211_sta *sta = file->private_data;
struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
struct ath11k *ar = arsta->arvif->ar;
char buf[512] = {};
int len = 0;
mutex_lock(&ar->conf_mutex);
len += scnprintf(buf + len, sizeof(buf) - len, "cfr_enabled = %d\n",
arsta->cfr_capture.cfr_enable);
len += scnprintf(buf + len, sizeof(buf) - len, "bandwidth = %d\n",
arsta->cfr_capture.cfr_bw);
len += scnprintf(buf + len, sizeof(buf) - len, "period = %d\n",
arsta->cfr_capture.cfr_period);
len += scnprintf(buf + len, sizeof(buf) - len, "cfr_method = %d\n",
arsta->cfr_capture.cfr_method);
mutex_unlock(&ar->conf_mutex);
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
static const struct file_operations fops_peer_cfr_capture = {
.write = ath11k_dbg_sta_write_cfr_capture,
.read = ath11k_dbg_sta_read_cfr_capture,
.open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
#endif /* CONFIG_ATH11K_CFR */
static ssize_t ath11k_dbg_sta_dump_rx_stats(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
@ -877,6 +1010,13 @@ void ath11k_debugfs_sta_op_add(struct ieee80211_hw *hw, struct ieee80211_vif *vi
debugfs_create_file("htt_peer_stats_reset", 0600, dir, sta,
&fops_htt_peer_stats_reset);
#ifdef CONFIG_ATH11K_CFR
if (test_bit(WMI_TLV_SERVICE_CFR_CAPTURE_SUPPORT,
ar->ab->wmi_ab.svc_map))
debugfs_create_file("cfr_capture", 0600, dir, sta,
&fops_peer_cfr_capture);
#endif/* CONFIG_ATH11K_CFR */
debugfs_create_file("peer_ps_state", 0400, dir, sta,
&fops_peer_ps_state);

View File

@ -344,7 +344,7 @@ void ath11k_dp_stop_shadow_timers(struct ath11k_base *ab)
if (!ab->hw_params.supports_shadow_regs)
return;
for (i = 0; i < ab->hw_params.max_tx_ring; i++)
for (i = 0; i < ab->hw_params.hal_params->num_tx_rings; i++)
ath11k_dp_shadow_stop_timer(ab, &ab->dp.tx_ring_timer[i]);
ath11k_dp_shadow_stop_timer(ab, &ab->dp.reo_cmd_timer);
@ -359,7 +359,7 @@ static void ath11k_dp_srng_common_cleanup(struct ath11k_base *ab)
ath11k_dp_srng_cleanup(ab, &dp->wbm_desc_rel_ring);
ath11k_dp_srng_cleanup(ab, &dp->tcl_cmd_ring);
ath11k_dp_srng_cleanup(ab, &dp->tcl_status_ring);
for (i = 0; i < ab->hw_params.max_tx_ring; i++) {
for (i = 0; i < ab->hw_params.hal_params->num_tx_rings; i++) {
ath11k_dp_srng_cleanup(ab, &dp->tx_ring[i].tcl_data_ring);
ath11k_dp_srng_cleanup(ab, &dp->tx_ring[i].tcl_comp_ring);
}
@ -400,7 +400,7 @@ static int ath11k_dp_srng_common_setup(struct ath11k_base *ab)
goto err;
}
for (i = 0; i < ab->hw_params.max_tx_ring; i++) {
for (i = 0; i < ab->hw_params.hal_params->num_tx_rings; i++) {
tcl_num = ab->hw_params.hal_params->tcl2wbm_rbm_map[i].tcl_ring_num;
wbm_num = ab->hw_params.hal_params->tcl2wbm_rbm_map[i].wbm_ring_num;
@ -782,7 +782,7 @@ int ath11k_dp_service_srng(struct ath11k_base *ab,
int i, j;
int tot_work_done = 0;
for (i = 0; i < ab->hw_params.max_tx_ring; i++) {
for (i = 0; i < ab->hw_params.hal_params->num_tx_rings; i++) {
if (BIT(ab->hw_params.hal_params->tcl2wbm_rbm_map[i].wbm_ring_num) &
ab->hw_params.ring_mask->tx[grp_id])
ath11k_dp_tx_completion_handler(ab, i);
@ -1035,7 +1035,7 @@ void ath11k_dp_free(struct ath11k_base *ab)
ath11k_dp_reo_cmd_list_cleanup(ab);
for (i = 0; i < ab->hw_params.max_tx_ring; i++) {
for (i = 0; i < ab->hw_params.hal_params->num_tx_rings; i++) {
spin_lock_bh(&dp->tx_ring[i].tx_idr_lock);
idr_for_each(&dp->tx_ring[i].txbuf_idr,
ath11k_dp_tx_pending_cleanup, ab);
@ -1086,7 +1086,7 @@ int ath11k_dp_alloc(struct ath11k_base *ab)
size = sizeof(struct hal_wbm_release_ring) * DP_TX_COMP_RING_SIZE;
for (i = 0; i < ab->hw_params.max_tx_ring; i++) {
for (i = 0; i < ab->hw_params.hal_params->num_tx_rings; i++) {
idr_init(&dp->tx_ring[i].txbuf_idr);
spin_lock_init(&dp->tx_ring[i].tx_idr_lock);
dp->tx_ring[i].tcl_data_ring_id = i;

View File

@ -199,7 +199,6 @@ struct ath11k_pdev_dp {
#define DP_BA_WIN_SZ_MAX 256
#define DP_TCL_NUM_RING_MAX 3
#define DP_TCL_NUM_RING_MAX_QCA6390 1
#define DP_IDLE_SCATTER_BUFS_MAX 16

View File

@ -91,6 +91,7 @@ int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif,
struct hal_srng *tcl_ring;
struct ieee80211_hdr *hdr = (void *)skb->data;
struct dp_tx_ring *tx_ring;
size_t num_tx_rings = ab->hw_params.hal_params->num_tx_rings;
void *hal_tcl_desc;
u8 pool_id;
u8 hal_ring_id;
@ -113,7 +114,7 @@ int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif,
tcl_ring_sel:
tcl_ring_retry = false;
ti.ring_id = ring_selector % ab->hw_params.max_tx_ring;
ti.ring_id = ring_selector % num_tx_rings;
ti.rbm_id = ab->hw_params.hal_params->tcl2wbm_rbm_map[ti.ring_id].rbm_id;
ring_map |= BIT(ti.ring_id);
@ -126,7 +127,7 @@ int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif,
spin_unlock_bh(&tx_ring->tx_idr_lock);
if (unlikely(ret < 0)) {
if (ring_map == (BIT(ab->hw_params.max_tx_ring) - 1) ||
if (ring_map == (BIT(num_tx_rings) - 1) ||
!ab->hw_params.tcl_ring_retry) {
atomic_inc(&ab->soc_stats.tx_err.misc_fail);
return -ENOSPC;
@ -244,8 +245,8 @@ int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif,
* checking this ring earlier for each pkt tx.
* Restart ring selection if some rings are not checked yet.
*/
if (unlikely(ring_map != (BIT(ab->hw_params.max_tx_ring)) - 1) &&
ab->hw_params.tcl_ring_retry && ab->hw_params.max_tx_ring > 1) {
if (unlikely(ring_map != (BIT(num_tx_rings)) - 1) &&
ab->hw_params.tcl_ring_retry && num_tx_rings > 1) {
tcl_ring_retry = true;
ring_selector++;
}

View File

@ -1,7 +1,6 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <linux/dma-mapping.h>
@ -184,7 +183,7 @@ static const struct hal_srng_config hw_srng_config_template[] = {
},
{ /* RXDMA DIR BUF */
.start_ring_id = HAL_SRNG_RING_ID_RXDMA_DIR_BUF,
.max_rings = 1,
.max_rings = 2,
.entry_size = 8 >> 2, /* TODO: Define the struct */
.lmac_ring = true,
.ring_dir = HAL_SRNG_DIR_SRC,

View File

@ -2707,6 +2707,14 @@ const struct ath11k_hw_regs wcn6750_regs = {
.hal_reo1_misc_ctl = 0x000005d8,
};
static const struct ath11k_hw_tcl2wbm_rbm_map ath11k_hw_tcl2wbm_rbm_map_ipq5018[] = {
{
.tcl_ring_num = 0,
.wbm_ring_num = 0,
.rbm_id = HAL_RX_BUF_RBM_SW0_BM,
},
};
static const struct ath11k_hw_tcl2wbm_rbm_map ath11k_hw_tcl2wbm_rbm_map_ipq8074[] = {
{
.tcl_ring_num = 0,
@ -2822,19 +2830,28 @@ const struct ath11k_hw_regs ipq5018_regs = {
.hal_wbm1_release_ring_base_lsb = 0x0000097c,
};
const struct ath11k_hw_hal_params ath11k_hw_hal_params_ipq5018 = {
.rx_buf_rbm = HAL_RX_BUF_RBM_SW3_BM,
.tcl2wbm_rbm_map = ath11k_hw_tcl2wbm_rbm_map_ipq5018,
.num_tx_rings = ARRAY_SIZE(ath11k_hw_tcl2wbm_rbm_map_ipq5018),
};
const struct ath11k_hw_hal_params ath11k_hw_hal_params_ipq8074 = {
.rx_buf_rbm = HAL_RX_BUF_RBM_SW3_BM,
.tcl2wbm_rbm_map = ath11k_hw_tcl2wbm_rbm_map_ipq8074,
.num_tx_rings = ARRAY_SIZE(ath11k_hw_tcl2wbm_rbm_map_ipq8074),
};
const struct ath11k_hw_hal_params ath11k_hw_hal_params_qca6390 = {
.rx_buf_rbm = HAL_RX_BUF_RBM_SW1_BM,
.tcl2wbm_rbm_map = ath11k_hw_tcl2wbm_rbm_map_ipq8074,
.tcl2wbm_rbm_map = ath11k_hw_tcl2wbm_rbm_map_ipq5018,
.num_tx_rings = ARRAY_SIZE(ath11k_hw_tcl2wbm_rbm_map_ipq5018),
};
const struct ath11k_hw_hal_params ath11k_hw_hal_params_wcn6750 = {
.rx_buf_rbm = HAL_RX_BUF_RBM_SW1_BM,
.tcl2wbm_rbm_map = ath11k_hw_tcl2wbm_rbm_map_wcn6750,
.num_tx_rings = ARRAY_SIZE(ath11k_hw_tcl2wbm_rbm_map_wcn6750),
};
static const struct cfg80211_sar_freq_ranges ath11k_hw_sar_freq_ranges_wcn6855[] = {

View File

@ -1,7 +1,7 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#ifndef ATH11K_HW_H
@ -134,6 +134,7 @@ struct ath11k_hw_tcl2wbm_rbm_map {
struct ath11k_hw_hal_params {
enum hal_rx_buf_return_buf_manager rx_buf_rbm;
const struct ath11k_hw_tcl2wbm_rbm_map *tcl2wbm_rbm_map;
size_t num_tx_rings;
};
struct ath11k_hw_params {
@ -198,7 +199,6 @@ struct ath11k_hw_params {
bool supports_regdb;
bool fix_l1ss;
bool credit_flow;
u8 max_tx_ring;
const struct ath11k_hw_hal_params *hal_params;
bool supports_dynamic_smps_6ghz;
bool alloc_cacheable_memory;
@ -228,6 +228,9 @@ struct ath11k_hw_params {
bool support_fw_mac_sequence;
bool support_dual_stations;
bool pdev_suspend;
bool cfr_support;
u32 cfr_num_stream_bufs;
u32 cfr_stream_buf_size;
};
struct ath11k_hw_ops {
@ -291,6 +294,7 @@ extern const struct ce_ie_addr ath11k_ce_ie_addr_ipq5018;
extern const struct ce_remap ath11k_ce_remap_ipq5018;
extern const struct ath11k_hw_hal_params ath11k_hw_hal_params_ipq5018;
extern const struct ath11k_hw_hal_params ath11k_hw_hal_params_ipq8074;
extern const struct ath11k_hw_hal_params ath11k_hw_hal_params_qca6390;
extern const struct ath11k_hw_hal_params ath11k_hw_hal_params_wcn6750;

View File

@ -2911,6 +2911,8 @@ static void ath11k_peer_assoc_h_phymode(struct ath11k *ar,
arg->peer_phymode = phymode;
WARN_ON(phymode == MODE_UNKNOWN);
ath11k_cfr_update_phymode(ar, phymode);
}
static void ath11k_peer_assoc_prepare(struct ath11k *ar,
@ -6186,6 +6188,8 @@ static int ath11k_mac_mgmt_tx_wmi(struct ath11k *ar, struct ath11k_vif *arvif,
dma_addr_t paddr;
int buf_id;
int ret;
bool tx_params_valid = false;
bool peer_in_unassoc_pool;
ATH11K_SKB_CB(skb)->ar = ar;
@ -6224,7 +6228,18 @@ static int ath11k_mac_mgmt_tx_wmi(struct ath11k *ar, struct ath11k_vif *arvif,
ATH11K_SKB_CB(skb)->paddr = paddr;
ret = ath11k_wmi_mgmt_send(ar, arvif->vdev_id, buf_id, skb);
peer_in_unassoc_pool = ath11k_cfr_peer_is_in_cfr_unassoc_pool(ar, hdr->addr1);
if (ar->cfr_enabled &&
ieee80211_is_probe_resp(hdr->frame_control) &&
peer_in_unassoc_pool)
tx_params_valid = true;
if (peer_in_unassoc_pool)
ath11k_cfr_update_unassoc_pool_entry(ar, hdr->addr1);
ret = ath11k_wmi_mgmt_send(ar, arvif->vdev_id, buf_id, skb,
tx_params_valid);
if (ret) {
ath11k_warn(ar->ab, "failed to send mgmt frame: %d\n", ret);
goto err_unmap_buf;
@ -7392,7 +7407,7 @@ static void ath11k_mac_op_remove_interface(struct ieee80211_hw *hw,
idr_for_each(&ar->txmgmt_idr,
ath11k_mac_vif_txmgmt_idr_remove, vif);
for (i = 0; i < ab->hw_params.max_tx_ring; i++) {
for (i = 0; i < ab->hw_params.hal_params->num_tx_rings; i++) {
spin_lock_bh(&ab->dp.tx_ring[i].tx_idr_lock);
idr_for_each(&ab->dp.tx_ring[i].txbuf_idr,
ath11k_mac_vif_unref, vif);
@ -9979,6 +9994,8 @@ static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw,
}
spin_unlock_bh(&ar->ab->base_lock);
mutex_unlock(&ar->ab->tbl_mtx_lock);
ath11k_cfr_decrement_peer_count(ar, arsta);
} else if (old_state == IEEE80211_STA_AUTH &&
new_state == IEEE80211_STA_ASSOC &&
(vif->type == NL80211_IFTYPE_AP ||
@ -10640,7 +10657,7 @@ static int __ath11k_mac_register(struct ath11k *ar)
if (!ab->hw_params.supports_monitor)
/* There's a race between calling ieee80211_register_hw()
* and here where the monitor mode is enabled for a little
* while. But that time is so short and in practise it make
* while. But that time is so short and in practice it doesn't make
* a difference in real life.
*/
ar->hw->wiphy->interface_modes &= ~BIT(NL80211_IFTYPE_MONITOR);

View File

@ -1,7 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
* Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include <linux/rtnetlink.h>
@ -926,8 +926,11 @@ int ath11k_reg_handle_chan_list(struct ath11k_base *ab,
*/
if (ab->default_regd[pdev_idx] && !ab->new_regd[pdev_idx] &&
!memcmp((char *)ab->default_regd[pdev_idx]->alpha2,
(char *)reg_info->alpha2, 2))
goto retfail;
(char *)reg_info->alpha2, 2) &&
power_type == IEEE80211_REG_UNSET_AP) {
ath11k_reg_reset_info(reg_info);
return 0;
}
/* Intersect new rules with default regd if a new country setting was
* requested, i.e a default regd was already set during initialization

View File

@ -651,11 +651,12 @@ static u32 ath11k_wmi_mgmt_get_freq(struct ath11k *ar,
}
int ath11k_wmi_mgmt_send(struct ath11k *ar, u32 vdev_id, u32 buf_id,
struct sk_buff *frame)
struct sk_buff *frame, bool tx_params_valid)
{
struct ath11k_pdev_wmi *wmi = ar->wmi;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(frame);
struct wmi_mgmt_send_cmd *cmd;
struct wmi_mgmt_send_params *params;
struct wmi_tlv *frame_tlv;
struct sk_buff *skb;
u32 buf_len;
@ -665,6 +666,8 @@ int ath11k_wmi_mgmt_send(struct ath11k *ar, u32 vdev_id, u32 buf_id,
frame->len : WMI_MGMT_SEND_DOWNLD_LEN;
len = sizeof(*cmd) + sizeof(*frame_tlv) + roundup(buf_len, 4);
if (tx_params_valid)
len += sizeof(*params);
skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len);
if (!skb)
@ -680,7 +683,7 @@ int ath11k_wmi_mgmt_send(struct ath11k *ar, u32 vdev_id, u32 buf_id,
cmd->paddr_hi = upper_32_bits(ATH11K_SKB_CB(frame)->paddr);
cmd->frame_len = frame->len;
cmd->buf_len = buf_len;
cmd->tx_params_valid = 0;
cmd->tx_params_valid = !!tx_params_valid;
frame_tlv = (struct wmi_tlv *)(skb->data + sizeof(*cmd));
frame_tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_BYTE) |
@ -690,6 +693,15 @@ int ath11k_wmi_mgmt_send(struct ath11k *ar, u32 vdev_id, u32 buf_id,
ath11k_ce_byte_swap(frame_tlv->value, buf_len);
if (tx_params_valid) {
params =
(struct wmi_mgmt_send_params *)(skb->data + (len - sizeof(*params)));
params->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_TX_SEND_PARAMS) |
FIELD_PREP(WMI_TLV_LEN,
sizeof(*params) - TLV_HDR_SIZE);
params->tx_params_dword1 |= WMI_TX_PARAMS_DWORD1_CFR_CAPTURE;
}
ret = ath11k_wmi_cmd_send(wmi, skb, WMI_MGMT_TX_SEND_CMDID);
if (ret) {
ath11k_warn(ar->ab,
@ -3941,6 +3953,47 @@ int ath11k_wmi_fils_discovery_tmpl(struct ath11k *ar, u32 vdev_id,
return 0;
}
int ath11k_wmi_peer_set_cfr_capture_conf(struct ath11k *ar,
u32 vdev_id, const u8 *mac_addr,
struct wmi_peer_cfr_capture_conf_arg *arg)
{
struct ath11k_pdev_wmi *wmi = ar->wmi;
struct wmi_peer_cfr_capture_cmd_fixed_param *cmd;
struct sk_buff *skb;
int ret;
skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));
if (!skb)
return -ENOMEM;
cmd = (struct wmi_peer_cfr_capture_cmd_fixed_param *)skb->data;
cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG,
WMI_TAG_PEER_CFR_CAPTURE_CMD) |
FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE);
memcpy(&cmd->mac_addr, mac_addr, ETH_ALEN);
cmd->request = arg->request;
cmd->vdev_id = vdev_id;
cmd->periodicity = arg->periodicity;
cmd->bandwidth = arg->bw;
cmd->capture_method = arg->method;
ret = ath11k_wmi_cmd_send(ar->wmi, skb, WMI_PEER_CFR_CAPTURE_CMDID);
if (ret) {
ath11k_warn(ar->ab,
"WMI vdev %d failed to send peer cfr capture cmd: %d\n",
vdev_id, ret);
dev_kfree_skb(skb);
}
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
"WMI peer CFR capture cmd req %u id %u period %u bw %u mode %u\n",
arg->request, vdev_id, arg->periodicity,
arg->bw, arg->method);
return ret;
}
int ath11k_wmi_probe_resp_tmpl(struct ath11k *ar, u32 vdev_id,
struct sk_buff *tmpl)
{
@ -8752,6 +8805,93 @@ static void ath11k_wmi_p2p_noa_event(struct ath11k_base *ab,
kfree(tb);
}
static void ath11k_wmi_tlv_cfr_capture_event_fixed_param(const void *ptr,
void *data)
{
struct ath11k_cfr_peer_tx_param *tx_params = data;
const struct ath11k_wmi_cfr_peer_tx_event_param *params = ptr;
tx_params->capture_method = params->capture_method;
tx_params->vdev_id = params->vdev_id;
ether_addr_copy(tx_params->peer_mac_addr, params->mac_addr.addr);
tx_params->primary_20mhz_chan = params->chan_mhz;
tx_params->bandwidth = params->bandwidth;
tx_params->phy_mode = params->phy_mode;
tx_params->band_center_freq1 = params->band_center_freq1;
tx_params->band_center_freq2 = params->band_center_freq2;
tx_params->spatial_streams = params->sts_count;
tx_params->correlation_info_1 = params->correlation_info_1;
tx_params->correlation_info_2 = params->correlation_info_2;
tx_params->status = params->status;
tx_params->timestamp_us = params->timestamp_us;
tx_params->counter = params->counter;
tx_params->rx_start_ts = params->rx_start_ts;
memcpy(tx_params->chain_rssi, params->chain_rssi,
sizeof(tx_params->chain_rssi));
if (WMI_CFR_CFO_MEASUREMENT_VALID & params->cfo_measurement)
tx_params->cfo_measurement = FIELD_GET(WMI_CFR_CFO_MEASUREMENT_RAW_DATA,
params->cfo_measurement);
}
static void ath11k_wmi_tlv_cfr_capture_phase_fixed_param(const void *ptr,
void *data)
{
struct ath11k_cfr_peer_tx_param *tx_params = data;
const struct ath11k_wmi_cfr_peer_tx_event_phase_param *params = ptr;
int i;
for (i = 0; i < WMI_MAX_CHAINS; i++) {
tx_params->chain_phase[i] = params->chain_phase[i];
tx_params->agc_gain[i] = params->agc_gain[i];
}
}
static int ath11k_wmi_tlv_cfr_capture_evt_parse(struct ath11k_base *ab,
u16 tag, u16 len,
const void *ptr, void *data)
{
switch (tag) {
case WMI_TAG_PEER_CFR_CAPTURE_EVENT:
ath11k_wmi_tlv_cfr_capture_event_fixed_param(ptr, data);
break;
case WMI_TAG_CFR_CAPTURE_PHASE_PARAM:
ath11k_wmi_tlv_cfr_capture_phase_fixed_param(ptr, data);
break;
default:
ath11k_warn(ab, "Invalid tag received tag %d len %d\n",
tag, len);
return -EINVAL;
}
return 0;
}
static void ath11k_wmi_parse_cfr_capture_event(struct ath11k_base *ab,
struct sk_buff *skb)
{
struct ath11k_cfr_peer_tx_param params = {};
int ret;
ath11k_dbg_dump(ab, ATH11K_DBG_CFR_DUMP, "cfr_dump:", "",
skb->data, skb->len);
ret = ath11k_wmi_tlv_iter(ab, skb->data, skb->len,
ath11k_wmi_tlv_cfr_capture_evt_parse,
&params);
if (ret) {
ath11k_warn(ab, "failed to parse cfr capture event tlv %d\n",
ret);
return;
}
ret = ath11k_process_cfr_capture_event(ab, &params);
if (ret)
ath11k_dbg(ab, ATH11K_DBG_CFR,
"failed to process cfr capture ret = %d\n", ret);
}
static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb)
{
struct wmi_cmd_hdr *cmd_hdr;
@ -8882,6 +9022,9 @@ static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb)
case WMI_P2P_NOA_EVENTID:
ath11k_wmi_p2p_noa_event(ab, skb);
break;
case WMI_PEER_CFR_CAPTURE_EVENTID:
ath11k_wmi_parse_cfr_capture_event(ab, skb);
break;
default:
ath11k_dbg(ab, ATH11K_DBG_WMI, "unsupported event id 0x%x\n", id);
break;

View File

@ -362,6 +362,10 @@ enum wmi_tlv_cmd_id {
WMI_PEER_REORDER_QUEUE_REMOVE_CMDID,
WMI_PEER_SET_RX_BLOCKSIZE_CMDID,
WMI_PEER_ANTDIV_INFO_REQ_CMDID,
WMI_PEER_RESERVED0_CMDID,
WMI_PEER_TID_MSDUQ_QDEPTH_THRESH_UPDATE_CMDID,
WMI_PEER_TID_CONFIGURATIONS_CMDID,
WMI_PEER_CFR_CAPTURE_CMDID,
WMI_BCN_TX_CMDID = WMI_TLV_CMD(WMI_GRP_MGMT),
WMI_PDEV_SEND_BCN_CMDID,
WMI_BCN_TMPL_CMDID,
@ -981,6 +985,7 @@ enum wmi_tlv_pdev_param {
WMI_PDEV_PARAM_RADIO_CHAN_STATS_ENABLE,
WMI_PDEV_PARAM_RADIO_DIAGNOSIS_ENABLE,
WMI_PDEV_PARAM_MESH_MCAST_ENABLE,
WMI_PDEV_PARAM_PER_PEER_CFR_ENABLE = 0xa8,
WMI_PDEV_PARAM_SET_CMD_OBSS_PD_THRESHOLD = 0xbc,
WMI_PDEV_PARAM_SET_CMD_OBSS_PD_PER_AC = 0xbe,
WMI_PDEV_PARAM_ENABLE_SR_PROHIBIT = 0xc6,
@ -1884,6 +1889,8 @@ enum wmi_tlv_tag {
WMI_TAG_NDP_EVENT,
WMI_TAG_PDEV_PEER_PKTLOG_FILTER_CMD = 0x301,
WMI_TAG_PDEV_PEER_PKTLOG_FILTER_INFO,
WMI_TAG_PEER_CFR_CAPTURE_EVENT = 0x317,
WMI_TAG_CFR_CAPTURE_PHASE_PARAM = 0x33b,
WMI_TAG_FILS_DISCOVERY_TMPL_CMD = 0x344,
WMI_TAG_PDEV_SRG_BSS_COLOR_BITMAP_CMD = 0x37b,
WMI_TAG_PDEV_SRG_PARTIAL_BSSID_BITMAP_CMD,
@ -3832,7 +3839,8 @@ struct wmi_scan_prob_req_oui_cmd {
#define WMI_TX_PARAMS_DWORD1_BW_MASK GENMASK(14, 8)
#define WMI_TX_PARAMS_DWORD1_PREAMBLE_TYPE GENMASK(19, 15)
#define WMI_TX_PARAMS_DWORD1_FRAME_TYPE BIT(20)
#define WMI_TX_PARAMS_DWORD1_RSVD GENMASK(31, 21)
#define WMI_TX_PARAMS_DWORD1_CFR_CAPTURE BIT(21)
#define WMI_TX_PARAMS_DWORD1_RSVD GENMASK(31, 22)
struct wmi_mgmt_send_params {
u32 tlv_header;
@ -4217,6 +4225,87 @@ enum cc_setting_code {
*/
};
enum ath11k_wmi_cfr_capture_bw {
WMI_PEER_CFR_CAPTURE_BW_20,
WMI_PEER_CFR_CAPTURE_BW_40,
WMI_PEER_CFR_CAPTURE_BW_80,
WMI_PEER_CFR_CAPTURE_BW_MAX,
};
enum ath11k_wmi_cfr_capture_method {
WMI_CFR_CAPTURE_METHOD_NULL_FRAME,
WMI_CFR_CAPTURE_METHOD_NULL_FRAME_WITH_PHASE,
WMI_CFR_CAPTURE_METHOD_PROBE_RESP,
WMI_CFR_CAPTURE_METHOD_MAX,
};
#define WMI_CFR_FRAME_TX_STATUS GENMASK(1, 0)
#define WMI_CFR_CAPTURE_STATUS_PEER_PS BIT(30)
#define WMI_CFR_PEER_CAPTURE_STATUS BIT(31)
#define WMI_CFR_CORRELATION_INFO2_BUF_ADDR_HIGH GENMASK(3, 0)
#define WMI_CFR_CORRELATION_INFO2_PPDU_ID GENMASK(31, 16)
#define WMI_CFR_CFO_MEASUREMENT_VALID BIT(0)
#define WMI_CFR_CFO_MEASUREMENT_RAW_DATA GENMASK(14, 1)
struct ath11k_wmi_cfr_peer_tx_event_param {
u32 capture_method;
u32 vdev_id;
struct wmi_mac_addr mac_addr;
u32 chan_mhz;
u32 bandwidth;
u32 phy_mode;
u32 band_center_freq1;
u32 band_center_freq2;
u32 sts_count;
u32 correlation_info_1;
u32 correlation_info_2;
u32 status;
u32 timestamp_us;
u32 counter;
u32 chain_rssi[WMI_MAX_CHAINS];
u32 cfo_measurement;
u32 rx_start_ts;
} __packed;
struct ath11k_wmi_cfr_peer_tx_event_phase_param {
u32 chain_phase[WMI_MAX_CHAINS];
u8 agc_gain[WMI_MAX_CHAINS];
} __packed;
enum ath11k_wmi_frame_tx_status {
WMI_FRAME_TX_STATUS_OK,
WMI_FRAME_TX_STATUS_XRETRY,
WMI_FRAME_TX_STATUS_DROP,
WMI_FRAME_TX_STATUS_FILTERED,
};
struct wmi_peer_cfr_capture_conf_arg {
enum ath11k_wmi_cfr_capture_bw bw;
enum ath11k_wmi_cfr_capture_method method;
u32 request;
u32 periodicity;
};
struct wmi_peer_cfr_capture_cmd_fixed_param {
u32 tlv_header;
u32 request;
struct wmi_mac_addr mac_addr;
u32 vdev_id;
u32 periodicity;
/* BW of measurement - of type enum ath11k_wmi_cfr_capture_bw */
u32 bandwidth;
/* Method used to capture CFR - of type enum ath11k_wmi_cfr_capture_method */
u32 capture_method;
} __packed;
#define WMI_PEER_CFR_CAPTURE_ENABLE 1
#define WMI_PEER_CFR_CAPTURE_DISABLE 0
/*periodicity in ms */
#define WMI_PEER_CFR_PERIODICITY_MAX 600000
static inline enum cc_setting_code
ath11k_wmi_cc_setting_code_to_reg(enum wmi_reg_cc_setting_code status_code)
{
@ -6346,7 +6435,7 @@ int ath11k_wmi_cmd_send(struct ath11k_pdev_wmi *wmi, struct sk_buff *skb,
u32 cmd_id);
struct sk_buff *ath11k_wmi_alloc_skb(struct ath11k_wmi_base *wmi_sc, u32 len);
int ath11k_wmi_mgmt_send(struct ath11k *ar, u32 vdev_id, u32 buf_id,
struct sk_buff *frame);
struct sk_buff *frame, bool tx_params_valid);
int ath11k_wmi_p2p_go_bcn_ie(struct ath11k *ar, u32 vdev_id,
const u8 *p2p_ie);
int ath11k_wmi_bcn_tmpl(struct ath11k *ar, u32 vdev_id,
@ -6531,5 +6620,7 @@ bool ath11k_wmi_supports_6ghz_cc_ext(struct ath11k *ar);
int ath11k_wmi_send_vdev_set_tpc_power(struct ath11k *ar,
u32 vdev_id,
struct ath11k_reg_tpc_power_info *param);
int ath11k_wmi_peer_set_cfr_capture_conf(struct ath11k *ar,
u32 vdev_id, const u8 *mac,
struct wmi_peer_cfr_capture_conf_arg *arg);
#endif

View File

@ -155,6 +155,7 @@ enum ath12k_hw_rev {
ATH12K_HW_QCN9274_HW20,
ATH12K_HW_WCN7850_HW20,
ATH12K_HW_IPQ5332_HW10,
ATH12K_HW_QCC2072_HW10,
};
enum ath12k_firmware_mode {
@ -1081,6 +1082,8 @@ struct ath12k_base {
size_t amss_dualmac_len;
const u8 *m3_data;
size_t m3_len;
const u8 *aux_uc_data;
size_t aux_uc_len;
DECLARE_BITMAP(fw_features, ATH12K_FW_FEATURE_COUNT);
bool fw_features_valid;

View File

@ -1513,7 +1513,7 @@ static int ath12k_dp_setup(struct ath12k_base *ab)
HAL_WBM_IDLE_LINK, srng, n_link_desc);
if (ret) {
ath12k_warn(ab, "failed to setup link desc: %d\n", ret);
return ret;
goto rhash_destroy;
}
ret = ath12k_dp_cc_init(ab);

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include "core.h"
@ -121,6 +121,14 @@ static int ath12k_fw_request_firmware_api_n(struct ath12k_base *ab,
ab->fw.m3_data = data;
ab->fw.m3_len = ie_len;
break;
case ATH12K_FW_IE_AUX_UC_IMAGE:
ath12k_dbg(ab, ATH12K_DBG_BOOT,
"found aux_uc image ie (%zd B)\n",
ie_len);
ab->fw.aux_uc_data = data;
ab->fw.aux_uc_len = ie_len;
break;
case ATH12K_FW_IE_AMSS_DUALMAC_IMAGE:
ath12k_dbg(ab, ATH12K_DBG_BOOT,
"found dualmac fw image ie (%zd B)\n",

View File

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#ifndef ATH12K_FW_H
@ -15,6 +15,7 @@ enum ath12k_fw_ie_type {
ATH12K_FW_IE_AMSS_IMAGE = 2,
ATH12K_FW_IE_M3_IMAGE = 3,
ATH12K_FW_IE_AMSS_DUALMAC_IMAGE = 4,
ATH12K_FW_IE_AUX_UC_IMAGE = 5,
};
enum ath12k_fw_features {

View File

@ -823,3 +823,49 @@ void ath12k_hal_dump_srng_stats(struct ath12k_base *ab)
jiffies_to_msecs(jiffies - srng->timestamp));
}
}
void *ath12k_hal_encode_tlv64_hdr(void *tlv, u64 tag, u64 len)
{
struct hal_tlv_64_hdr *tlv64 = tlv;
tlv64->tl = le64_encode_bits(tag, HAL_TLV_HDR_TAG) |
le64_encode_bits(len, HAL_TLV_HDR_LEN);
return tlv64->value;
}
EXPORT_SYMBOL(ath12k_hal_encode_tlv64_hdr);
void *ath12k_hal_encode_tlv32_hdr(void *tlv, u64 tag, u64 len)
{
struct hal_tlv_hdr *tlv32 = tlv;
tlv32->tl = le32_encode_bits(tag, HAL_TLV_HDR_TAG) |
le32_encode_bits(len, HAL_TLV_HDR_LEN);
return tlv32->value;
}
EXPORT_SYMBOL(ath12k_hal_encode_tlv32_hdr);
u16 ath12k_hal_decode_tlv64_hdr(void *tlv, void **desc)
{
struct hal_tlv_64_hdr *tlv64 = tlv;
u16 tag;
tag = le64_get_bits(tlv64->tl, HAL_SRNG_TLV_HDR_TAG);
*desc = tlv64->value;
return tag;
}
EXPORT_SYMBOL(ath12k_hal_decode_tlv64_hdr);
u16 ath12k_hal_decode_tlv32_hdr(void *tlv, void **desc)
{
struct hal_tlv_hdr *tlv32 = tlv;
u16 tag;
tag = le32_get_bits(tlv32->tl, HAL_SRNG_TLV_HDR_TAG);
*desc = tlv32->value;
return tag;
}
EXPORT_SYMBOL(ath12k_hal_decode_tlv32_hdr);

View File

@ -1121,6 +1121,8 @@ struct ath12k_hw_hal_params {
u32 wbm2sw_cc_enable;
};
#define ATH12K_HW_REG_UNDEFINED 0xdeadbeaf
struct ath12k_hw_regs {
u32 tcl1_ring_id;
u32 tcl1_ring_misc;
@ -1199,6 +1201,8 @@ struct ath12k_hw_regs {
u32 reo_status_ring_base;
u32 gcc_gcc_pcie_hot_rst;
u32 qrtr_node_id;
};
/* HAL context to be used to access SRNG APIs (currently used by data path
@ -1426,8 +1430,34 @@ struct hal_ops {
u32 *sw_cookie,
struct ath12k_buffer_addr **pp_buf_addr,
u8 *rbm, u32 *msdu_cnt);
void *(*reo_cmd_enc_tlv_hdr)(void *tlv, u64 tag, u64 len);
u16 (*reo_status_dec_tlv_hdr)(void *tlv, void **desc);
};
#define HAL_TLV_HDR_TAG GENMASK(9, 1)
#define HAL_TLV_HDR_LEN GENMASK(25, 10)
#define HAL_TLV_USR_ID GENMASK(31, 26)
#define HAL_TLV_ALIGN 4
struct hal_tlv_hdr {
__le32 tl;
u8 value[];
} __packed;
#define HAL_TLV_64_HDR_TAG GENMASK(9, 1)
#define HAL_TLV_64_HDR_LEN GENMASK(21, 10)
#define HAL_TLV_64_USR_ID GENMASK(31, 26)
#define HAL_TLV_64_ALIGN 8
struct hal_tlv_64_hdr {
__le64 tl;
u8 value[];
} __packed;
#define HAL_SRNG_TLV_HDR_TAG GENMASK(9, 1)
#define HAL_SRNG_TLV_HDR_LEN GENMASK(25, 10)
dma_addr_t ath12k_hal_srng_get_tp_addr(struct ath12k_base *ab,
struct hal_srng *srng);
dma_addr_t ath12k_hal_srng_get_hp_addr(struct ath12k_base *ab,
@ -1515,4 +1545,8 @@ void ath12k_hal_rx_reo_ent_buf_paddr_get(struct ath12k_hal *hal, void *rx_desc,
dma_addr_t *paddr, u32 *sw_cookie,
struct ath12k_buffer_addr **pp_buf_addr,
u8 *rbm, u32 *msdu_cnt);
void *ath12k_hal_encode_tlv64_hdr(void *tlv, u64 tag, u64 len);
void *ath12k_hal_encode_tlv32_hdr(void *tlv, u64 tag, u64 len);
u16 ath12k_hal_decode_tlv64_hdr(void *tlv, void **desc);
u16 ath12k_hal_decode_tlv32_hdr(void *tlv, void **desc);
#endif

View File

@ -78,6 +78,7 @@
#define ATH12K_DEFAULT_CAL_FILE "caldata.bin"
#define ATH12K_AMSS_FILE "amss.bin"
#define ATH12K_M3_FILE "m3.bin"
#define ATH12K_AUX_UC_FILE "aux_ucode.bin"
#define ATH12K_REGDB_FILE_NAME "regdb.bin"
#define ATH12K_PCIE_MAX_PAYLOAD_SIZE 128
@ -142,6 +143,7 @@ struct ath12k_hw_params {
size_t board_size;
size_t cal_offset;
enum ath12k_m3_fw_loaders m3_loader;
bool download_aux_ucode:1;
} fw;
u8 max_radios;

View File

@ -14530,7 +14530,7 @@ static int ath12k_mac_hw_register(struct ath12k_hw *ah)
if (is_monitor_disable)
/* There's a race between calling ieee80211_register_hw()
* and here where the monitor mode is enabled for a little
* while. But that time is so short and in practise it make
* while. But that time is so short and in practice it doesn't make
* a difference in real life.
*/
wiphy->interface_modes &= ~BIT(NL80211_IFTYPE_MONITOR);

View File

@ -23,7 +23,6 @@
#define ATH12K_PCI_IRQ_CE0_OFFSET 3
#define WINDOW_ENABLE_BIT 0x40000000
#define WINDOW_REG_ADDRESS 0x310c
#define WINDOW_VALUE_MASK GENMASK(24, 19)
#define WINDOW_START 0x80000
#define WINDOW_RANGE_MASK GENMASK(18, 0)
@ -35,10 +34,6 @@
*/
#define ACCESS_ALWAYS_OFF 0xFE0
#define PCIE_LOCAL_REG_QRTR_NODE_ID 0x1E03164
#define DOMAIN_NUMBER_MASK GENMASK(7, 4)
#define BUS_NUMBER_MASK GENMASK(3, 0)
static struct ath12k_pci_driver *ath12k_pci_family_drivers[ATH12K_DEVICE_FAMILY_MAX];
static const struct ath12k_msi_config msi_config_one_msi = {
.total_vectors = 1,
@ -125,8 +120,8 @@ static void ath12k_pci_select_window(struct ath12k_pci *ab_pci, u32 offset)
if (window != ab_pci->register_window) {
iowrite32(WINDOW_ENABLE_BIT | window,
ab->mem + WINDOW_REG_ADDRESS);
ioread32(ab->mem + WINDOW_REG_ADDRESS);
ab->mem + ab_pci->window_reg_addr);
ioread32(ab->mem + ab_pci->window_reg_addr);
ab_pci->register_window = window;
}
}
@ -145,7 +140,7 @@ static void ath12k_pci_select_static_window(struct ath12k_pci *ab_pci)
ab_pci->register_window = window;
spin_unlock_bh(&ab_pci->window_lock);
iowrite32(WINDOW_ENABLE_BIT | window, ab_pci->ab->mem + WINDOW_REG_ADDRESS);
iowrite32(WINDOW_ENABLE_BIT | window, ab_pci->ab->mem + ab_pci->window_reg_addr);
}
static u32 ath12k_pci_get_window_start(struct ath12k_base *ab,
@ -178,8 +173,8 @@ static void ath12k_pci_restore_window(struct ath12k_base *ab)
spin_lock_bh(&ab_pci->window_lock);
iowrite32(WINDOW_ENABLE_BIT | ab_pci->register_window,
ab->mem + WINDOW_REG_ADDRESS);
ioread32(ab->mem + WINDOW_REG_ADDRESS);
ab->mem + ab_pci->window_reg_addr);
ioread32(ab->mem + ab_pci->window_reg_addr);
spin_unlock_bh(&ab_pci->window_lock);
}
@ -919,7 +914,7 @@ static void ath12k_pci_update_qrtr_node_id(struct ath12k_base *ab)
* writes to the given register, it is available for firmware when the QMI service
* is spawned.
*/
reg = PCIE_LOCAL_REG_QRTR_NODE_ID & WINDOW_RANGE_MASK;
reg = PCIE_LOCAL_REG_QRTR_NODE_ID(ab) & WINDOW_RANGE_MASK;
ath12k_pci_write32(ab, reg, ab_pci->qmi_instance);
ath12k_dbg(ab, ATH12K_DBG_PCI, "pci reg 0x%x instance 0x%x read val 0x%x\n",
@ -1541,7 +1536,6 @@ static int ath12k_pci_probe(struct pci_dev *pdev,
}
ab->dev = &pdev->dev;
pci_set_drvdata(pdev, ab);
ab_pci = ath12k_pci_priv(ab);
ab_pci->dev_id = pci_dev->device;
ab_pci->ab = ab;

View File

@ -59,6 +59,11 @@
#define QCN9274_QFPROM_RAW_RFA_PDET_ROW13_LSB 0x1E20338
#define OTP_BOARD_ID_MASK GENMASK(15, 0)
#define PCIE_LOCAL_REG_QRTR_NODE_ID(ab) \
((ab)->hal.regs->qrtr_node_id)
#define DOMAIN_NUMBER_MASK GENMASK(7, 4)
#define BUS_NUMBER_MASK GENMASK(3, 0)
#define PCI_BAR_WINDOW0_BASE 0x1E00000
#define PCI_BAR_WINDOW0_END 0x1E7FFFC
#define PCI_SOC_RANGE_MASK 0x3FFF
@ -130,6 +135,8 @@ struct ath12k_pci {
u64 dma_mask;
const struct ath12k_pci_device_family_ops *device_family_ops;
const struct ath12k_pci_reg_base *reg_base;
u32 window_reg_addr;
};
struct ath12k_pci_driver {

View File

@ -1623,6 +1623,47 @@ static const struct qmi_elem_info qmi_wlanfw_m3_info_resp_msg_v01_ei[] = {
},
};
static const struct qmi_elem_info qmi_wlanfw_aux_uc_info_req_msg_v01_ei[] = {
{
.data_type = QMI_UNSIGNED_8_BYTE,
.elem_len = 1,
.elem_size = sizeof(u64),
.array_type = NO_ARRAY,
.tlv_type = 0x01,
.offset = offsetof(struct qmi_wlanfw_aux_uc_info_req_msg_v01, addr),
},
{
.data_type = QMI_UNSIGNED_4_BYTE,
.elem_len = 1,
.elem_size = sizeof(u32),
.array_type = NO_ARRAY,
.tlv_type = 0x02,
.offset = offsetof(struct qmi_wlanfw_aux_uc_info_req_msg_v01, size),
},
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
},
};
static const struct qmi_elem_info qmi_wlanfw_aux_uc_info_resp_msg_v01_ei[] = {
{
.data_type = QMI_STRUCT,
.elem_len = 1,
.elem_size = sizeof(struct qmi_response_type_v01),
.array_type = NO_ARRAY,
.tlv_type = 0x02,
.offset = offsetof(struct qmi_wlanfw_aux_uc_info_resp_msg_v01, resp),
.ei_array = qmi_response_type_v01_ei,
},
{
.data_type = QMI_EOTI,
.array_type = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
},
};
static const struct qmi_elem_info qmi_wlanfw_ce_tgt_pipe_cfg_s_v01_ei[] = {
{
.data_type = QMI_UNSIGNED_4_BYTE,
@ -2609,6 +2650,7 @@ static int ath12k_qmi_alloc_target_mem_chunk(struct ath12k_base *ab)
case M3_DUMP_REGION_TYPE:
case PAGEABLE_MEM_REGION_TYPE:
case CALDB_MEM_REGION_TYPE:
case LPASS_SHARED_V01_REGION_TYPE:
ret = ath12k_qmi_alloc_chunk(ab, chunk);
if (ret)
goto err;
@ -3236,6 +3278,131 @@ int ath12k_qmi_wlanfw_m3_info_send(struct ath12k_base *ab)
return ret;
}
static void ath12k_qmi_aux_uc_free(struct ath12k_base *ab)
{
struct m3_mem_region *aux_uc_mem = &ab->qmi.aux_uc_mem;
if (!aux_uc_mem->vaddr)
return;
dma_free_coherent(ab->dev, aux_uc_mem->total_size,
aux_uc_mem->vaddr, aux_uc_mem->paddr);
aux_uc_mem->vaddr = NULL;
aux_uc_mem->total_size = 0;
aux_uc_mem->size = 0;
}
static int ath12k_qmi_aux_uc_load(struct ath12k_base *ab)
{
struct m3_mem_region *aux_uc_mem = &ab->qmi.aux_uc_mem;
const struct firmware *fw = NULL;
const void *aux_uc_data;
char path[100];
size_t aux_uc_len;
int ret;
if (ab->fw.aux_uc_data && ab->fw.aux_uc_len > 0) {
/* firmware-N.bin had a aux_uc firmware file so use that */
aux_uc_data = ab->fw.aux_uc_data;
aux_uc_len = ab->fw.aux_uc_len;
} else {
/*
* No aux_uc file in firmware-N.bin so try to request old
* separate aux_ucode.bin.
*/
fw = ath12k_core_firmware_request(ab, ATH12K_AUX_UC_FILE);
if (IS_ERR(fw)) {
ret = PTR_ERR(fw);
ath12k_core_create_firmware_path(ab, ATH12K_AUX_UC_FILE,
path, sizeof(path));
ath12k_err(ab, "failed to load %s: %d\n", path, ret);
return ret;
}
aux_uc_data = fw->data;
aux_uc_len = fw->size;
}
/* In recovery/resume cases, AUX_UC buffer is not freed, try to reuse that */
if (aux_uc_mem->vaddr) {
if (aux_uc_mem->total_size >= aux_uc_len)
goto copy;
/* Old buffer is too small, free and reallocate */
ath12k_qmi_aux_uc_free(ab);
}
aux_uc_mem->vaddr = dma_alloc_coherent(ab->dev, aux_uc_len,
&aux_uc_mem->paddr, GFP_KERNEL);
if (!aux_uc_mem->vaddr) {
ret = -ENOMEM;
goto out;
}
aux_uc_mem->total_size = aux_uc_len;
copy:
memcpy(aux_uc_mem->vaddr, aux_uc_data, aux_uc_len);
aux_uc_mem->size = aux_uc_len;
ret = 0;
out:
release_firmware(fw);
return ret;
}
static noinline_for_stack
int ath12k_qmi_wlanfw_aux_uc_info_send(struct ath12k_base *ab)
{
struct m3_mem_region *aux_uc_mem = &ab->qmi.aux_uc_mem;
struct qmi_wlanfw_aux_uc_info_req_msg_v01 req = {};
struct qmi_wlanfw_aux_uc_info_resp_msg_v01 resp = {};
struct qmi_txn txn;
int ret = 0;
ret = ath12k_qmi_aux_uc_load(ab);
if (ret) {
ath12k_err(ab, "failed to load aux_uc firmware: %d", ret);
return ret;
}
req.addr = aux_uc_mem->paddr;
req.size = aux_uc_mem->size;
ret = qmi_txn_init(&ab->qmi.handle, &txn,
qmi_wlanfw_aux_uc_info_resp_msg_v01_ei, &resp);
if (ret < 0)
goto out;
ret = qmi_send_request(&ab->qmi.handle, NULL, &txn,
QMI_WLANFW_AUX_UC_INFO_REQ_V01,
QMI_WLANFW_AUX_UC_INFO_REQ_MSG_V01_MAX_MSG_LEN,
qmi_wlanfw_aux_uc_info_req_msg_v01_ei, &req);
if (ret < 0) {
qmi_txn_cancel(&txn);
ath12k_warn(ab, "qmi failed to send AUX_UC information request, err = %d\n",
ret);
goto out;
}
ret = qmi_txn_wait(&txn, msecs_to_jiffies(ATH12K_QMI_WLANFW_TIMEOUT_MS));
if (ret < 0) {
ath12k_warn(ab, "qmi failed AUX_UC information request %d\n", ret);
goto out;
}
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
ath12k_warn(ab, "qmi AUX_UC info request failed, result: %d, err: %d\n",
resp.resp.result, resp.resp.error);
ret = -EINVAL;
goto out;
}
out:
return ret;
}
static int ath12k_qmi_wlanfw_mode_send(struct ath12k_base *ab,
u32 mode)
{
@ -3600,6 +3767,7 @@ static noinline_for_stack
int ath12k_qmi_event_load_bdf(struct ath12k_qmi *qmi)
{
struct ath12k_base *ab = qmi->ab;
const struct ath12k_hw_params *hw_params = ab->hw_params;
int ret;
ret = ath12k_qmi_request_target_cap(ab);
@ -3620,7 +3788,7 @@ int ath12k_qmi_event_load_bdf(struct ath12k_qmi *qmi)
return ret;
}
if (ab->hw_params->download_calib) {
if (hw_params->download_calib) {
ret = ath12k_qmi_load_bdf_qmi(ab, ATH12K_QMI_BDF_TYPE_CALIBRATION);
if (ret < 0)
ath12k_warn(ab, "qmi failed to load calibrated data :%d\n", ret);
@ -3632,6 +3800,14 @@ int ath12k_qmi_event_load_bdf(struct ath12k_qmi *qmi)
return ret;
}
if (hw_params->fw.download_aux_ucode) {
ret = ath12k_qmi_wlanfw_aux_uc_info_send(ab);
if (ret < 0) {
ath12k_warn(ab, "qmi failed to send aux_uc info req: %d\n", ret);
return ret;
}
}
return ret;
}
@ -3905,6 +4081,7 @@ void ath12k_qmi_deinit_service(struct ath12k_base *ab)
qmi_handle_release(&ab->qmi.handle);
cancel_work_sync(&ab->qmi.event_work);
destroy_workqueue(ab->qmi.event_wq);
ath12k_qmi_aux_uc_free(ab);
ath12k_qmi_m3_free(ab);
ath12k_qmi_free_target_mem_chunk(ab);
ab->qmi.ab = NULL;
@ -3913,5 +4090,6 @@ void ath12k_qmi_deinit_service(struct ath12k_base *ab)
void ath12k_qmi_free_resource(struct ath12k_base *ab)
{
ath12k_qmi_free_target_mem_chunk(ab);
ath12k_qmi_aux_uc_free(ab);
ath12k_qmi_m3_free(ab);
}

View File

@ -154,6 +154,7 @@ struct ath12k_qmi {
u8 num_radios;
struct target_info target;
struct m3_mem_region m3_mem;
struct m3_mem_region aux_uc_mem;
unsigned int service_ins_id;
struct dev_mem_info dev_mem[ATH12K_QMI_WLFW_MAX_DEV_MEM_NUM_V01];
};
@ -178,6 +179,7 @@ enum ath12k_qmi_target_mem {
CALDB_MEM_REGION_TYPE = 0x4,
MLO_GLOBAL_MEM_REGION_TYPE = 0x8,
PAGEABLE_MEM_REGION_TYPE = 0x9,
LPASS_SHARED_V01_REGION_TYPE = 0xb,
};
enum qmi_wlanfw_host_build_type {
@ -202,6 +204,7 @@ enum ath12k_qmi_cnss_feature {
CNSS_FEATURE_MIN_ENUM_VAL_V01 = INT_MIN,
CNSS_QDSS_CFG_MISS_V01 = 3,
CNSS_PCIE_PERST_NO_PULL_V01 = 4,
CNSS_AUX_UC_SUPPORT_V01 = 6,
CNSS_MAX_FEATURE_V01 = 64,
CNSS_FEATURE_MAX_ENUM_VAL_V01 = INT_MAX,
};
@ -540,6 +543,19 @@ struct qmi_wlanfw_m3_info_resp_msg_v01 {
struct qmi_response_type_v01 resp;
};
#define QMI_WLANFW_AUX_UC_INFO_REQ_MSG_V01_MAX_MSG_LEN 18
#define QMI_WLANFW_AUX_UC_INFO_RESP_MSG_V01_MAX_MSG_LEN 7
#define QMI_WLANFW_AUX_UC_INFO_REQ_V01 0x005A
struct qmi_wlanfw_aux_uc_info_req_msg_v01 {
u64 addr;
u32 size;
};
struct qmi_wlanfw_aux_uc_info_resp_msg_v01 {
struct qmi_response_type_v01 resp;
};
#define QMI_WLANFW_WLAN_MODE_REQ_MSG_V01_MAX_LEN 11
#define QMI_WLANFW_WLAN_MODE_RESP_MSG_V01_MAX_LEN 7
#define QMI_WLANFW_WLAN_CFG_REQ_MSG_V01_MAX_LEN 803

View File

@ -14,6 +14,7 @@ ath12k_wifi7-y += core.o \
dp_mon.o \
hal.o \
hal_qcn9274.o \
hal_wcn7850.o
hal_wcn7850.o \
hal_qcc2072.o
ath12k_wifi7-$(CONFIG_ATH12K_AHB) += ahb.o

View File

@ -9,6 +9,7 @@
#include "../peer.h"
#include "hal_qcn9274.h"
#include "hal_wcn7850.h"
#include "hal_qcc2072.h"
static u16 ath12k_wifi7_dp_rx_get_peer_id(struct ath12k_dp *dp,
enum ath12k_peer_metadata_version ver,
@ -2110,16 +2111,59 @@ int ath12k_dp_rxdma_ring_sel_config_wcn7850(struct ath12k_base *ab)
return ret;
}
int ath12k_dp_rxdma_ring_sel_config_qcc2072(struct ath12k_base *ab)
{
struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
struct htt_rx_ring_tlv_filter tlv_filter = {};
u32 ring_id;
int ret = 0;
u32 hal_rx_desc_sz = ab->hal.hal_desc_sz;
int i;
ring_id = dp->rx_refill_buf_ring.refill_buf_ring.ring_id;
tlv_filter.rx_filter = HTT_RX_TLV_FLAGS_RXDMA_RING;
tlv_filter.pkt_filter_flags2 = HTT_RX_FP_CTRL_PKT_FILTER_TLV_FLAGS2_BAR;
tlv_filter.pkt_filter_flags3 = HTT_RX_FP_DATA_PKT_FILTER_TLV_FLASG3_MCAST |
HTT_RX_FP_DATA_PKT_FILTER_TLV_FLASG3_UCAST |
HTT_RX_FP_DATA_PKT_FILTER_TLV_FLASG3_NULL_DATA;
tlv_filter.offset_valid = true;
tlv_filter.rx_packet_offset = hal_rx_desc_sz;
tlv_filter.rx_header_offset = offsetof(struct hal_rx_desc_qcc2072, pkt_hdr_tlv);
tlv_filter.rx_mpdu_start_offset =
ath12k_hal_rx_desc_get_mpdu_start_offset_qcc2072();
tlv_filter.rx_msdu_end_offset =
ath12k_hal_rx_desc_get_msdu_end_offset_qcc2072();
/*
* TODO: Selectively subscribe to required qwords within msdu_end
* and mpdu_start and setup the mask in below msg
* and modify the rx_desc struct
*/
for (i = 0; i < ab->hw_params->num_rxdma_per_pdev; i++) {
ring_id = dp->rx_mac_buf_ring[i].ring_id;
ret = ath12k_dp_tx_htt_rx_filter_setup(ab, ring_id, i,
HAL_RXDMA_BUF,
DP_RXDMA_REFILL_RING_SIZE,
&tlv_filter);
}
return ret;
}
void ath12k_wifi7_dp_rx_process_reo_status(struct ath12k_dp *dp)
{
struct ath12k_base *ab = dp->ab;
struct ath12k_hal *hal = dp->hal;
struct hal_tlv_64_hdr *hdr;
struct hal_srng *srng;
struct ath12k_dp_rx_reo_cmd *cmd, *tmp;
bool found = false;
u16 tag;
struct hal_reo_status reo_status;
void *hdr, *desc;
srng = &hal->srng_list[dp->reo_status_ring.ring_id];
@ -2130,35 +2174,35 @@ void ath12k_wifi7_dp_rx_process_reo_status(struct ath12k_dp *dp)
ath12k_hal_srng_access_begin(ab, srng);
while ((hdr = ath12k_hal_srng_dst_get_next_entry(ab, srng))) {
tag = le64_get_bits(hdr->tl, HAL_SRNG_TLV_HDR_TAG);
tag = hal->ops->reo_status_dec_tlv_hdr(hdr, &desc);
switch (tag) {
case HAL_REO_GET_QUEUE_STATS_STATUS:
ath12k_wifi7_hal_reo_status_queue_stats(ab, hdr,
ath12k_wifi7_hal_reo_status_queue_stats(ab, desc,
&reo_status);
break;
case HAL_REO_FLUSH_QUEUE_STATUS:
ath12k_wifi7_hal_reo_flush_queue_status(ab, hdr,
ath12k_wifi7_hal_reo_flush_queue_status(ab, desc,
&reo_status);
break;
case HAL_REO_FLUSH_CACHE_STATUS:
ath12k_wifi7_hal_reo_flush_cache_status(ab, hdr,
ath12k_wifi7_hal_reo_flush_cache_status(ab, desc,
&reo_status);
break;
case HAL_REO_UNBLOCK_CACHE_STATUS:
ath12k_wifi7_hal_reo_unblk_cache_status(ab, hdr,
ath12k_wifi7_hal_reo_unblk_cache_status(ab, desc,
&reo_status);
break;
case HAL_REO_FLUSH_TIMEOUT_LIST_STATUS:
ath12k_wifi7_hal_reo_flush_timeout_list_status(ab, hdr,
ath12k_wifi7_hal_reo_flush_timeout_list_status(ab, desc,
&reo_status);
break;
case HAL_REO_DESCRIPTOR_THRESHOLD_REACHED_STATUS:
ath12k_wifi7_hal_reo_desc_thresh_reached_status(ab, hdr,
ath12k_wifi7_hal_reo_desc_thresh_reached_status(ab, desc,
&reo_status);
break;
case HAL_REO_UPDATE_RX_REO_QUEUE_STATUS:
ath12k_wifi7_hal_reo_update_rx_reo_queue_status(ab, hdr,
ath12k_wifi7_hal_reo_update_rx_reo_queue_status(ab, desc,
&reo_status);
break;
default:

View File

@ -22,6 +22,7 @@ int ath12k_wifi7_dp_rx_process(struct ath12k_dp *dp, int mac_id,
void ath12k_wifi7_dp_rx_process_reo_status(struct ath12k_dp *dp);
int ath12k_dp_rxdma_ring_sel_config_qcn9274(struct ath12k_base *ab);
int ath12k_dp_rxdma_ring_sel_config_wcn7850(struct ath12k_base *ab);
int ath12k_dp_rxdma_ring_sel_config_qcc2072(struct ath12k_base *ab);
void ath12k_wifi7_dp_setup_pn_check_reo_cmd(struct ath12k_hal_reo_cmd *cmd,
struct ath12k_dp_rx_tid *rx_tid,
u32 cipher, enum set_key_cmd key_cmd);

View File

@ -12,6 +12,7 @@
#include "../hif.h"
#include "hal_qcn9274.h"
#include "hal_wcn7850.h"
#include "hal_qcc2072.h"
static const struct ath12k_hw_version_map ath12k_wifi7_hw_ver_map[] = {
[ATH12K_HW_QCN9274_HW10] = {
@ -42,6 +43,13 @@ static const struct ath12k_hw_version_map ath12k_wifi7_hw_ver_map[] = {
.hal_params = &ath12k_hw_hal_params_ipq5332,
.hw_regs = &ipq5332_regs,
},
[ATH12K_HW_QCC2072_HW10] = {
.hal_ops = &hal_qcc2072_ops,
.hal_desc_sz = sizeof(struct hal_rx_desc_qcc2072),
.tcl_to_wbm_rbm_map = ath12k_hal_tcl_to_wbm_rbm_map_wcn7850,
.hal_params = &ath12k_hw_hal_params_wcn7850,
.hw_regs = &qcc2072_regs,
},
};
int ath12k_wifi7_hal_init(struct ath12k_base *ab)

View File

@ -369,9 +369,6 @@
#define HAL_DEFAULT_BE_BK_VI_REO_TIMEOUT_USEC (100 * 1000)
#define HAL_DEFAULT_VO_REO_TIMEOUT_USEC (40 * 1000)
#define HAL_SRNG_TLV_HDR_TAG GENMASK(9, 1)
#define HAL_SRNG_TLV_HDR_LEN GENMASK(25, 10)
#define HAL_SRNG_DESC_LOOP_CNT 0xf0000000
#define HAL_REO_CMD_FLG_NEED_STATUS BIT(0)

View File

@ -487,27 +487,6 @@ enum hal_tlv_tag {
HAL_TLV_BASE = 511 /* 0x1ff */,
};
#define HAL_TLV_HDR_TAG GENMASK(9, 1)
#define HAL_TLV_HDR_LEN GENMASK(25, 10)
#define HAL_TLV_USR_ID GENMASK(31, 26)
#define HAL_TLV_ALIGN 4
struct hal_tlv_hdr {
__le32 tl;
u8 value[];
} __packed;
#define HAL_TLV_64_HDR_TAG GENMASK(9, 1)
#define HAL_TLV_64_HDR_LEN GENMASK(21, 10)
#define HAL_TLV_64_USR_ID GENMASK(31, 26)
#define HAL_TLV_64_ALIGN 8
struct hal_tlv_64_hdr {
__le64 tl;
u8 value[];
} __packed;
#define RX_MPDU_DESC_INFO0_MSDU_COUNT GENMASK(7, 0)
#define RX_MPDU_DESC_INFO0_FRAG_FLAG BIT(8)
#define RX_MPDU_DESC_INFO0_MPDU_RETRY BIT(9)
@ -1070,6 +1049,13 @@ struct hal_reo_get_queue_stats {
* Hole_count
*/
struct hal_reo_get_queue_stats_qcc2072 {
struct hal_reo_cmd_hdr cmd;
__le32 queue_addr_lo;
__le32 info0;
__le32 rsvd0[6];
} __packed;
#define HAL_REO_FLUSH_QUEUE_INFO0_DESC_ADDR_HI GENMASK(7, 0)
#define HAL_REO_FLUSH_QUEUE_INFO0_BLOCK_DESC_ADDR BIT(8)
#define HAL_REO_FLUSH_QUEUE_INFO0_BLOCK_RESRC_IDX GENMASK(10, 9)
@ -2453,6 +2439,11 @@ struct hal_reo_get_queue_stats_status {
* entries into this Ring has looped around the ring.
*/
struct hal_reo_get_queue_stats_status_qcc2072 {
__le32 tlv32_padding;
struct hal_reo_get_queue_stats_status status;
} __packed;
#define HAL_REO_STATUS_LOOP_CNT GENMASK(31, 28)
#define HAL_REO_FLUSH_QUEUE_INFO0_ERR_DETECTED BIT(0)

View File

@ -0,0 +1,503 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include "hal_qcc2072.h"
#include "hal_wcn7850.h"
const struct ath12k_hw_regs qcc2072_regs = {
/* SW2TCL(x) R0 ring configuration address */
.tcl1_ring_id = 0x00000920,
.tcl1_ring_misc = 0x00000928,
.tcl1_ring_tp_addr_lsb = 0x00000934,
.tcl1_ring_tp_addr_msb = 0x00000938,
.tcl1_ring_consumer_int_setup_ix0 = 0x00000948,
.tcl1_ring_consumer_int_setup_ix1 = 0x0000094c,
.tcl1_ring_msi1_base_lsb = 0x00000960,
.tcl1_ring_msi1_base_msb = 0x00000964,
.tcl1_ring_msi1_data = 0x00000968,
.tcl_ring_base_lsb = 0x00000b70,
.tcl1_ring_base_lsb = 0x00000918,
.tcl1_ring_base_msb = 0x0000091c,
.tcl2_ring_base_lsb = 0x00000990,
/* TCL STATUS ring address */
.tcl_status_ring_base_lsb = 0x00000d50,
.wbm_idle_ring_base_lsb = 0x00000d3c,
.wbm_idle_ring_misc_addr = 0x00000d4c,
.wbm_r0_idle_list_cntl_addr = 0x00000240,
.wbm_r0_idle_list_size_addr = 0x00000244,
.wbm_scattered_ring_base_lsb = 0x00000250,
.wbm_scattered_ring_base_msb = 0x00000254,
.wbm_scattered_desc_head_info_ix0 = 0x00000260,
.wbm_scattered_desc_head_info_ix1 = 0x00000264,
.wbm_scattered_desc_tail_info_ix0 = 0x00000270,
.wbm_scattered_desc_tail_info_ix1 = 0x00000274,
.wbm_scattered_desc_ptr_hp_addr = 0x00000027c,
.wbm_sw_release_ring_base_lsb = 0x0000037c,
.wbm_sw1_release_ring_base_lsb = ATH12K_HW_REG_UNDEFINED,
.wbm0_release_ring_base_lsb = 0x00000e08,
.wbm1_release_ring_base_lsb = 0x00000e80,
/* PCIe base address */
.pcie_qserdes_sysclk_en_sel = 0x01e0c0ac,
.pcie_pcs_osc_dtct_config_base = 0x01e0cc58,
/* PPE release ring address */
.ppe_rel_ring_base = 0x0000046c,
/* REO DEST ring address */
.reo2_ring_base = 0x00000578,
.reo1_misc_ctrl_addr = 0x00000ba0,
.reo1_sw_cookie_cfg0 = 0x0000006c,
.reo1_sw_cookie_cfg1 = 0x00000070,
.reo1_qdesc_lut_base0 = ATH12K_HW_REG_UNDEFINED,
.reo1_qdesc_lut_base1 = ATH12K_HW_REG_UNDEFINED,
.reo1_ring_base_lsb = 0x00000500,
.reo1_ring_base_msb = 0x00000504,
.reo1_ring_id = 0x00000508,
.reo1_ring_misc = 0x00000510,
.reo1_ring_hp_addr_lsb = 0x00000514,
.reo1_ring_hp_addr_msb = 0x00000518,
.reo1_ring_producer_int_setup = 0x00000524,
.reo1_ring_msi1_base_lsb = 0x00000548,
.reo1_ring_msi1_base_msb = 0x0000054c,
.reo1_ring_msi1_data = 0x00000550,
.reo1_aging_thres_ix0 = 0x00000b2c,
.reo1_aging_thres_ix1 = 0x00000b30,
.reo1_aging_thres_ix2 = 0x00000b34,
.reo1_aging_thres_ix3 = 0x00000b38,
/* REO Exception ring address */
.reo2_sw0_ring_base = 0x000008c0,
/* REO Reinject ring address */
.sw2reo_ring_base = 0x00000320,
.sw2reo1_ring_base = 0x00000398,
/* REO cmd ring address */
.reo_cmd_ring_base = 0x000002a8,
/* REO status ring address */
.reo_status_ring_base = 0x00000aa0,
/* CE base address */
.umac_ce0_src_reg_base = 0x01b80000,
.umac_ce0_dest_reg_base = 0x01b81000,
.umac_ce1_src_reg_base = 0x01b82000,
.umac_ce1_dest_reg_base = 0x01b83000,
.gcc_gcc_pcie_hot_rst = 0x1e65304,
.qrtr_node_id = 0x1e03300,
};
static void ath12k_hal_rx_desc_set_msdu_len_qcc2072(struct hal_rx_desc *desc, u16 len)
{
u32 info = __le32_to_cpu(desc->u.qcc2072.msdu_end.info10);
info &= ~RX_MSDU_END_INFO10_MSDU_LENGTH;
info |= u32_encode_bits(len, RX_MSDU_END_INFO10_MSDU_LENGTH);
desc->u.qcc2072.msdu_end.info10 = __cpu_to_le32(info);
}
static void ath12k_hal_rx_desc_get_dot11_hdr_qcc2072(struct hal_rx_desc *desc,
struct ieee80211_hdr *hdr)
{
hdr->frame_control = desc->u.qcc2072.mpdu_start.frame_ctrl;
hdr->duration_id = desc->u.qcc2072.mpdu_start.duration;
ether_addr_copy(hdr->addr1, desc->u.qcc2072.mpdu_start.addr1);
ether_addr_copy(hdr->addr2, desc->u.qcc2072.mpdu_start.addr2);
ether_addr_copy(hdr->addr3, desc->u.qcc2072.mpdu_start.addr3);
if (__le32_to_cpu(desc->u.qcc2072.mpdu_start.info4) &
RX_MPDU_START_INFO4_MAC_ADDR4_VALID)
ether_addr_copy(hdr->addr4, desc->u.qcc2072.mpdu_start.addr4);
hdr->seq_ctrl = desc->u.qcc2072.mpdu_start.seq_ctrl;
}
static void ath12k_hal_rx_desc_get_crypto_hdr_qcc2072(struct hal_rx_desc *desc,
u8 *crypto_hdr,
enum hal_encrypt_type enctype)
{
unsigned int key_id;
switch (enctype) {
case HAL_ENCRYPT_TYPE_OPEN:
return;
case HAL_ENCRYPT_TYPE_TKIP_NO_MIC:
case HAL_ENCRYPT_TYPE_TKIP_MIC:
crypto_hdr[0] =
HAL_RX_MPDU_INFO_PN_GET_BYTE2(desc->u.qcc2072.mpdu_start.pn[0]);
crypto_hdr[1] = 0;
crypto_hdr[2] =
HAL_RX_MPDU_INFO_PN_GET_BYTE1(desc->u.qcc2072.mpdu_start.pn[0]);
break;
case HAL_ENCRYPT_TYPE_CCMP_128:
case HAL_ENCRYPT_TYPE_CCMP_256:
case HAL_ENCRYPT_TYPE_GCMP_128:
case HAL_ENCRYPT_TYPE_AES_GCMP_256:
crypto_hdr[0] =
HAL_RX_MPDU_INFO_PN_GET_BYTE1(desc->u.qcc2072.mpdu_start.pn[0]);
crypto_hdr[1] =
HAL_RX_MPDU_INFO_PN_GET_BYTE2(desc->u.qcc2072.mpdu_start.pn[0]);
crypto_hdr[2] = 0;
break;
case HAL_ENCRYPT_TYPE_WEP_40:
case HAL_ENCRYPT_TYPE_WEP_104:
case HAL_ENCRYPT_TYPE_WEP_128:
case HAL_ENCRYPT_TYPE_WAPI_GCM_SM4:
case HAL_ENCRYPT_TYPE_WAPI:
return;
}
key_id = u32_get_bits(__le32_to_cpu(desc->u.qcc2072.mpdu_start.info5),
RX_MPDU_START_INFO5_KEY_ID);
crypto_hdr[3] = 0x20 | (key_id << 6);
crypto_hdr[4] = HAL_RX_MPDU_INFO_PN_GET_BYTE3(desc->u.qcc2072.mpdu_start.pn[0]);
crypto_hdr[5] = HAL_RX_MPDU_INFO_PN_GET_BYTE4(desc->u.qcc2072.mpdu_start.pn[0]);
crypto_hdr[6] = HAL_RX_MPDU_INFO_PN_GET_BYTE1(desc->u.qcc2072.mpdu_start.pn[1]);
crypto_hdr[7] = HAL_RX_MPDU_INFO_PN_GET_BYTE2(desc->u.qcc2072.mpdu_start.pn[1]);
}
static void ath12k_hal_rx_desc_copy_end_tlv_qcc2072(struct hal_rx_desc *fdesc,
struct hal_rx_desc *ldesc)
{
memcpy(&fdesc->u.qcc2072.msdu_end, &ldesc->u.qcc2072.msdu_end,
sizeof(struct rx_msdu_end_qcn9274));
}
static u8 ath12k_hal_rx_desc_get_msdu_src_link_qcc2072(struct hal_rx_desc *desc)
{
return 0;
}
static u8 ath12k_hal_rx_desc_get_l3_pad_bytes_qcc2072(struct hal_rx_desc *desc)
{
return le16_get_bits(desc->u.qcc2072.msdu_end.info5,
RX_MSDU_END_INFO5_L3_HDR_PADDING);
}
static u32 ath12k_hal_rx_desc_get_mpdu_start_tag_qcc2072(struct hal_rx_desc *desc)
{
return le32_get_bits(desc->u.qcc2072.mpdu_start_tag,
HAL_TLV_HDR_TAG);
}
static u32 ath12k_hal_rx_desc_get_mpdu_ppdu_id_qcc2072(struct hal_rx_desc *desc)
{
return __le16_to_cpu(desc->u.qcc2072.mpdu_start.phy_ppdu_id);
}
static u8 *ath12k_hal_rx_desc_get_msdu_payload_qcc2072(struct hal_rx_desc *desc)
{
return &desc->u.qcc2072.msdu_payload[0];
}
static bool ath12k_hal_rx_desc_get_first_msdu_qcc2072(struct hal_rx_desc *desc)
{
return !!le16_get_bits(desc->u.qcc2072.msdu_end.info5,
RX_MSDU_END_INFO5_FIRST_MSDU);
}
static bool ath12k_hal_rx_desc_get_last_msdu_qcc2072(struct hal_rx_desc *desc)
{
return !!le16_get_bits(desc->u.qcc2072.msdu_end.info5,
RX_MSDU_END_INFO5_LAST_MSDU);
}
static bool ath12k_hal_rx_desc_encrypt_valid_qcc2072(struct hal_rx_desc *desc)
{
return !!le32_get_bits(desc->u.qcc2072.mpdu_start.info4,
RX_MPDU_START_INFO4_ENCRYPT_INFO_VALID);
}
static u32 ath12k_hal_rx_desc_get_encrypt_type_qcc2072(struct hal_rx_desc *desc)
{
if (!ath12k_hal_rx_desc_encrypt_valid_qcc2072(desc))
return HAL_ENCRYPT_TYPE_OPEN;
return le32_get_bits(desc->u.qcc2072.mpdu_start.info2,
RX_MPDU_START_INFO2_ENC_TYPE);
}
static u8 ath12k_hal_rx_desc_get_decap_type_qcc2072(struct hal_rx_desc *desc)
{
return le32_get_bits(desc->u.qcc2072.msdu_end.info11,
RX_MSDU_END_INFO11_DECAP_FORMAT);
}
static u8 ath12k_hal_rx_desc_get_mesh_ctl_qcc2072(struct hal_rx_desc *desc)
{
return le32_get_bits(desc->u.qcc2072.msdu_end.info11,
RX_MSDU_END_INFO11_MESH_CTRL_PRESENT);
}
static bool ath12k_hal_rx_desc_get_mpdu_seq_ctl_vld_qcc2072(struct hal_rx_desc *desc)
{
return !!le32_get_bits(desc->u.qcc2072.mpdu_start.info4,
RX_MPDU_START_INFO4_MPDU_SEQ_CTRL_VALID);
}
static bool ath12k_hal_rx_desc_get_mpdu_fc_valid_qcc2072(struct hal_rx_desc *desc)
{
return !!le32_get_bits(desc->u.qcc2072.mpdu_start.info4,
RX_MPDU_START_INFO4_MPDU_FCTRL_VALID);
}
static u16 ath12k_hal_rx_desc_get_mpdu_start_seq_no_qcc2072(struct hal_rx_desc *desc)
{
return le32_get_bits(desc->u.qcc2072.mpdu_start.info4,
RX_MPDU_START_INFO4_MPDU_SEQ_NUM);
}
static u16 ath12k_hal_rx_desc_get_msdu_len_qcc2072(struct hal_rx_desc *desc)
{
return le32_get_bits(desc->u.qcc2072.msdu_end.info10,
RX_MSDU_END_INFO10_MSDU_LENGTH);
}
static u8 ath12k_hal_rx_desc_get_msdu_sgi_qcc2072(struct hal_rx_desc *desc)
{
return le32_get_bits(desc->u.qcc2072.msdu_end.info12,
RX_MSDU_END_INFO12_SGI);
}
static u8 ath12k_hal_rx_desc_get_msdu_rate_mcs_qcc2072(struct hal_rx_desc *desc)
{
return le32_get_bits(desc->u.qcc2072.msdu_end.info12,
RX_MSDU_END_INFO12_RATE_MCS);
}
static u8 ath12k_hal_rx_desc_get_msdu_rx_bw_qcc2072(struct hal_rx_desc *desc)
{
return le32_get_bits(desc->u.qcc2072.msdu_end.info12,
RX_MSDU_END_INFO12_RECV_BW);
}
static u32 ath12k_hal_rx_desc_get_msdu_freq_qcc2072(struct hal_rx_desc *desc)
{
return __le32_to_cpu(desc->u.qcc2072.msdu_end.phy_meta_data);
}
static u8 ath12k_hal_rx_desc_get_msdu_pkt_type_qcc2072(struct hal_rx_desc *desc)
{
return le32_get_bits(desc->u.qcc2072.msdu_end.info12,
RX_MSDU_END_INFO12_PKT_TYPE);
}
static u8 ath12k_hal_rx_desc_get_msdu_nss_qcc2072(struct hal_rx_desc *desc)
{
return le32_get_bits(desc->u.qcc2072.msdu_end.info12,
RX_MSDU_END_INFO12_MIMO_SS_BITMAP);
}
static u8 ath12k_hal_rx_desc_get_mpdu_tid_qcc2072(struct hal_rx_desc *desc)
{
return le32_get_bits(desc->u.qcc2072.mpdu_start.info2,
RX_MPDU_START_INFO2_TID);
}
static u16 ath12k_hal_rx_desc_get_mpdu_peer_id_qcc2072(struct hal_rx_desc *desc)
{
return __le16_to_cpu(desc->u.qcc2072.mpdu_start.sw_peer_id);
}
static bool ath12k_hal_rx_desc_mac_addr2_valid_qcc2072(struct hal_rx_desc *desc)
{
return __le32_to_cpu(desc->u.qcc2072.mpdu_start.info4) &
RX_MPDU_START_INFO4_MAC_ADDR2_VALID;
}
static u8 *ath12k_hal_rx_desc_mpdu_start_addr2_qcc2072(struct hal_rx_desc *desc)
{
return desc->u.qcc2072.mpdu_start.addr2;
}
static bool ath12k_hal_rx_desc_is_da_mcbc_qcc2072(struct hal_rx_desc *desc)
{
return __le32_to_cpu(desc->u.qcc2072.msdu_end.info13) &
RX_MSDU_END_INFO13_MCAST_BCAST;
}
static bool ath12k_hal_rx_h_msdu_done_qcc2072(struct hal_rx_desc *desc)
{
return !!le32_get_bits(desc->u.qcc2072.msdu_end.info14,
RX_MSDU_END_INFO14_MSDU_DONE);
}
static bool ath12k_hal_rx_h_l4_cksum_fail_qcc2072(struct hal_rx_desc *desc)
{
return !!le32_get_bits(desc->u.qcc2072.msdu_end.info13,
RX_MSDU_END_INFO13_TCP_UDP_CKSUM_FAIL);
}
static bool ath12k_hal_rx_h_ip_cksum_fail_qcc2072(struct hal_rx_desc *desc)
{
return !!le32_get_bits(desc->u.qcc2072.msdu_end.info13,
RX_MSDU_END_INFO13_IP_CKSUM_FAIL);
}
static bool ath12k_hal_rx_h_is_decrypted_qcc2072(struct hal_rx_desc *desc)
{
return (le32_get_bits(desc->u.qcc2072.msdu_end.info14,
RX_MSDU_END_INFO14_DECRYPT_STATUS_CODE) ==
RX_DESC_DECRYPT_STATUS_CODE_OK);
}
static u32 ath12k_hal_rx_h_mpdu_err_qcc2072(struct hal_rx_desc *desc)
{
u32 info = __le32_to_cpu(desc->u.qcc2072.msdu_end.info13);
u32 errmap = 0;
if (info & RX_MSDU_END_INFO13_FCS_ERR)
errmap |= HAL_RX_MPDU_ERR_FCS;
if (info & RX_MSDU_END_INFO13_DECRYPT_ERR)
errmap |= HAL_RX_MPDU_ERR_DECRYPT;
if (info & RX_MSDU_END_INFO13_TKIP_MIC_ERR)
errmap |= HAL_RX_MPDU_ERR_TKIP_MIC;
if (info & RX_MSDU_END_INFO13_A_MSDU_ERROR)
errmap |= HAL_RX_MPDU_ERR_AMSDU_ERR;
if (info & RX_MSDU_END_INFO13_OVERFLOW_ERR)
errmap |= HAL_RX_MPDU_ERR_OVERFLOW;
if (info & RX_MSDU_END_INFO13_MSDU_LEN_ERR)
errmap |= HAL_RX_MPDU_ERR_MSDU_LEN;
if (info & RX_MSDU_END_INFO13_MPDU_LEN_ERR)
errmap |= HAL_RX_MPDU_ERR_MPDU_LEN;
return errmap;
}
static void ath12k_hal_extract_rx_desc_data_qcc2072(struct hal_rx_desc_data *rx_desc_data,
struct hal_rx_desc *rx_desc,
struct hal_rx_desc *ldesc)
{
rx_desc_data->is_first_msdu = ath12k_hal_rx_desc_get_first_msdu_qcc2072(ldesc);
rx_desc_data->is_last_msdu = ath12k_hal_rx_desc_get_last_msdu_qcc2072(ldesc);
rx_desc_data->l3_pad_bytes = ath12k_hal_rx_desc_get_l3_pad_bytes_qcc2072(ldesc);
rx_desc_data->enctype = ath12k_hal_rx_desc_get_encrypt_type_qcc2072(rx_desc);
rx_desc_data->decap_type = ath12k_hal_rx_desc_get_decap_type_qcc2072(rx_desc);
rx_desc_data->mesh_ctrl_present =
ath12k_hal_rx_desc_get_mesh_ctl_qcc2072(rx_desc);
rx_desc_data->seq_ctl_valid =
ath12k_hal_rx_desc_get_mpdu_seq_ctl_vld_qcc2072(rx_desc);
rx_desc_data->fc_valid = ath12k_hal_rx_desc_get_mpdu_fc_valid_qcc2072(rx_desc);
rx_desc_data->seq_no = ath12k_hal_rx_desc_get_mpdu_start_seq_no_qcc2072(rx_desc);
rx_desc_data->msdu_len = ath12k_hal_rx_desc_get_msdu_len_qcc2072(ldesc);
rx_desc_data->sgi = ath12k_hal_rx_desc_get_msdu_sgi_qcc2072(rx_desc);
rx_desc_data->rate_mcs = ath12k_hal_rx_desc_get_msdu_rate_mcs_qcc2072(rx_desc);
rx_desc_data->bw = ath12k_hal_rx_desc_get_msdu_rx_bw_qcc2072(rx_desc);
rx_desc_data->phy_meta_data = ath12k_hal_rx_desc_get_msdu_freq_qcc2072(rx_desc);
rx_desc_data->pkt_type = ath12k_hal_rx_desc_get_msdu_pkt_type_qcc2072(rx_desc);
rx_desc_data->nss = hweight8(ath12k_hal_rx_desc_get_msdu_nss_qcc2072(rx_desc));
rx_desc_data->tid = ath12k_hal_rx_desc_get_mpdu_tid_qcc2072(rx_desc);
rx_desc_data->peer_id = ath12k_hal_rx_desc_get_mpdu_peer_id_qcc2072(rx_desc);
rx_desc_data->addr2_present = ath12k_hal_rx_desc_mac_addr2_valid_qcc2072(rx_desc);
rx_desc_data->addr2 = ath12k_hal_rx_desc_mpdu_start_addr2_qcc2072(rx_desc);
rx_desc_data->is_mcbc = ath12k_hal_rx_desc_is_da_mcbc_qcc2072(rx_desc);
rx_desc_data->msdu_done = ath12k_hal_rx_h_msdu_done_qcc2072(ldesc);
rx_desc_data->l4_csum_fail = ath12k_hal_rx_h_l4_cksum_fail_qcc2072(rx_desc);
rx_desc_data->ip_csum_fail = ath12k_hal_rx_h_ip_cksum_fail_qcc2072(rx_desc);
rx_desc_data->is_decrypted = ath12k_hal_rx_h_is_decrypted_qcc2072(rx_desc);
rx_desc_data->err_bitmap = ath12k_hal_rx_h_mpdu_err_qcc2072(rx_desc);
}
static int ath12k_hal_srng_create_config_qcc2072(struct ath12k_hal *hal)
{
struct hal_srng_config *s;
int ret;
ret = ath12k_hal_srng_create_config_wcn7850(hal);
if (ret)
return ret;
s = &hal->srng_config[HAL_REO_CMD];
s->entry_size = (sizeof(struct hal_tlv_hdr) +
sizeof(struct hal_reo_get_queue_stats_qcc2072)) >> 2;
s = &hal->srng_config[HAL_REO_STATUS];
s->entry_size = (sizeof(struct hal_tlv_hdr) +
sizeof(struct hal_reo_get_queue_stats_status_qcc2072)) >> 2;
return 0;
}
static u16 ath12k_hal_reo_status_dec_tlv_hdr_qcc2072(void *tlv, void **desc)
{
struct hal_reo_get_queue_stats_status_qcc2072 *status_tlv;
u16 tag;
tag = ath12k_hal_decode_tlv32_hdr(tlv, (void **)&status_tlv);
/*
* actual desc of REO status entry starts after tlv32_padding,
* see hal_reo_get_queue_stats_status_qcc2072
*/
*desc = &status_tlv->status;
return tag;
}
const struct hal_ops hal_qcc2072_ops = {
.create_srng_config = ath12k_hal_srng_create_config_qcc2072,
.rx_desc_set_msdu_len = ath12k_hal_rx_desc_set_msdu_len_qcc2072,
.rx_desc_get_dot11_hdr = ath12k_hal_rx_desc_get_dot11_hdr_qcc2072,
.rx_desc_get_crypto_header = ath12k_hal_rx_desc_get_crypto_hdr_qcc2072,
.rx_desc_copy_end_tlv = ath12k_hal_rx_desc_copy_end_tlv_qcc2072,
.rx_desc_get_msdu_src_link_id = ath12k_hal_rx_desc_get_msdu_src_link_qcc2072,
.extract_rx_desc_data = ath12k_hal_extract_rx_desc_data_qcc2072,
.rx_desc_get_l3_pad_bytes = ath12k_hal_rx_desc_get_l3_pad_bytes_qcc2072,
.rx_desc_get_mpdu_start_tag = ath12k_hal_rx_desc_get_mpdu_start_tag_qcc2072,
.rx_desc_get_mpdu_ppdu_id = ath12k_hal_rx_desc_get_mpdu_ppdu_id_qcc2072,
.rx_desc_get_msdu_payload = ath12k_hal_rx_desc_get_msdu_payload_qcc2072,
.ce_dst_setup = ath12k_wifi7_hal_ce_dst_setup,
.srng_src_hw_init = ath12k_wifi7_hal_srng_src_hw_init,
.srng_dst_hw_init = ath12k_wifi7_hal_srng_dst_hw_init,
.set_umac_srng_ptr_addr = ath12k_wifi7_hal_set_umac_srng_ptr_addr,
.srng_update_shadow_config = ath12k_wifi7_hal_srng_update_shadow_config,
.srng_get_ring_id = ath12k_wifi7_hal_srng_get_ring_id,
.ce_get_desc_size = ath12k_wifi7_hal_ce_get_desc_size,
.ce_src_set_desc = ath12k_wifi7_hal_ce_src_set_desc,
.ce_dst_set_desc = ath12k_wifi7_hal_ce_dst_set_desc,
.ce_dst_status_get_length = ath12k_wifi7_hal_ce_dst_status_get_length,
.set_link_desc_addr = ath12k_wifi7_hal_set_link_desc_addr,
.tx_set_dscp_tid_map = ath12k_wifi7_hal_tx_set_dscp_tid_map,
.tx_configure_bank_register =
ath12k_wifi7_hal_tx_configure_bank_register,
.reoq_lut_addr_read_enable = ath12k_wifi7_hal_reoq_lut_addr_read_enable,
.reoq_lut_set_max_peerid = ath12k_wifi7_hal_reoq_lut_set_max_peerid,
.write_reoq_lut_addr = ath12k_wifi7_hal_write_reoq_lut_addr,
.write_ml_reoq_lut_addr = ath12k_wifi7_hal_write_ml_reoq_lut_addr,
.setup_link_idle_list = ath12k_wifi7_hal_setup_link_idle_list,
.reo_init_cmd_ring = ath12k_wifi7_hal_reo_init_cmd_ring_tlv32,
.reo_hw_setup = ath12k_wifi7_hal_reo_hw_setup,
.rx_buf_addr_info_set = ath12k_wifi7_hal_rx_buf_addr_info_set,
.rx_buf_addr_info_get = ath12k_wifi7_hal_rx_buf_addr_info_get,
.cc_config = ath12k_wifi7_hal_cc_config,
.get_idle_link_rbm = ath12k_wifi7_hal_get_idle_link_rbm,
.rx_msdu_list_get = ath12k_wifi7_hal_rx_msdu_list_get,
.rx_reo_ent_buf_paddr_get = ath12k_wifi7_hal_rx_reo_ent_buf_paddr_get,
.reo_cmd_enc_tlv_hdr = ath12k_hal_encode_tlv32_hdr,
.reo_status_dec_tlv_hdr = ath12k_hal_reo_status_dec_tlv_hdr_qcc2072,
};
u32 ath12k_hal_rx_desc_get_mpdu_start_offset_qcc2072(void)
{
return offsetof(struct hal_rx_desc_qcc2072, mpdu_start_tag);
}
u32 ath12k_hal_rx_desc_get_msdu_end_offset_qcc2072(void)
{
return offsetof(struct hal_rx_desc_qcc2072, msdu_end_tag);
}

View File

@ -0,0 +1,13 @@
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#include "../hal.h"
#include "hal.h"
extern const struct ath12k_hw_regs qcc2072_regs;
extern const struct hal_ops hal_qcc2072_ops;
u32 ath12k_hal_rx_desc_get_mpdu_start_offset_qcc2072(void);
u32 ath12k_hal_rx_desc_get_msdu_end_offset_qcc2072(void);

View File

@ -297,6 +297,8 @@ const struct ath12k_hw_regs qcn9274_v1_regs = {
.umac_ce1_dest_reg_base = 0x01b83000,
.gcc_gcc_pcie_hot_rst = 0x1e38338,
.qrtr_node_id = 0x1e03164,
};
const struct ath12k_hw_regs qcn9274_v2_regs = {
@ -390,6 +392,8 @@ const struct ath12k_hw_regs qcn9274_v2_regs = {
.umac_ce1_dest_reg_base = 0x01b83000,
.gcc_gcc_pcie_hot_rst = 0x1e38338,
.qrtr_node_id = 0x1e03164,
};
const struct ath12k_hw_regs ipq5332_regs = {
@ -1020,7 +1024,7 @@ const struct hal_ops hal_qcn9274_ops = {
.write_reoq_lut_addr = ath12k_wifi7_hal_write_reoq_lut_addr,
.write_ml_reoq_lut_addr = ath12k_wifi7_hal_write_ml_reoq_lut_addr,
.setup_link_idle_list = ath12k_wifi7_hal_setup_link_idle_list,
.reo_init_cmd_ring = ath12k_wifi7_hal_reo_init_cmd_ring,
.reo_init_cmd_ring = ath12k_wifi7_hal_reo_init_cmd_ring_tlv64,
.reo_hw_setup = ath12k_wifi7_hal_reo_hw_setup,
.reo_shared_qaddr_cache_clear = ath12k_wifi7_hal_reo_shared_qaddr_cache_clear,
.rx_buf_addr_info_set = ath12k_wifi7_hal_rx_buf_addr_info_set,
@ -1029,4 +1033,6 @@ const struct hal_ops hal_qcn9274_ops = {
.get_idle_link_rbm = ath12k_wifi7_hal_get_idle_link_rbm,
.rx_msdu_list_get = ath12k_wifi7_hal_rx_msdu_list_get,
.rx_reo_ent_buf_paddr_get = ath12k_wifi7_hal_rx_reo_ent_buf_paddr_get,
.reo_cmd_enc_tlv_hdr = ath12k_hal_encode_tlv64_hdr,
.reo_status_dec_tlv_hdr = ath12k_hal_decode_tlv64_hdr,
};

View File

@ -23,15 +23,13 @@ void ath12k_wifi7_hal_reo_set_desc_hdr(struct hal_desc_header *hdr,
hdr->info0 |= le32_encode_bits(magic, HAL_DESC_HDR_INFO0_DBG_RESERVED);
}
static int ath12k_wifi7_hal_reo_cmd_queue_stats(struct hal_tlv_64_hdr *tlv,
static int ath12k_wifi7_hal_reo_cmd_queue_stats(struct ath12k_hal *hal, void *tlv,
struct ath12k_hal_reo_cmd *cmd)
{
struct hal_reo_get_queue_stats *desc;
tlv->tl = le64_encode_bits(HAL_REO_GET_QUEUE_STATS, HAL_TLV_HDR_TAG) |
le64_encode_bits(sizeof(*desc), HAL_TLV_HDR_LEN);
desc = (struct hal_reo_get_queue_stats *)tlv->value;
desc = hal->ops->reo_cmd_enc_tlv_hdr(tlv, HAL_REO_GET_QUEUE_STATS,
sizeof(*desc));
memset_startat(desc, 0, queue_addr_lo);
desc->cmd.info0 &= ~cpu_to_le32(HAL_REO_CMD_HDR_INFO0_STATUS_REQUIRED);
@ -47,8 +45,7 @@ static int ath12k_wifi7_hal_reo_cmd_queue_stats(struct hal_tlv_64_hdr *tlv,
return le32_get_bits(desc->cmd.info0, HAL_REO_CMD_HDR_INFO0_CMD_NUMBER);
}
static int ath12k_wifi7_hal_reo_cmd_flush_cache(struct ath12k_hal *hal,
struct hal_tlv_64_hdr *tlv,
static int ath12k_wifi7_hal_reo_cmd_flush_cache(struct ath12k_hal *hal, void *tlv,
struct ath12k_hal_reo_cmd *cmd)
{
struct hal_reo_flush_cache *desc;
@ -61,10 +58,8 @@ static int ath12k_wifi7_hal_reo_cmd_flush_cache(struct ath12k_hal *hal,
hal->current_blk_index = avail_slot;
}
tlv->tl = le64_encode_bits(HAL_REO_FLUSH_CACHE, HAL_TLV_HDR_TAG) |
le64_encode_bits(sizeof(*desc), HAL_TLV_HDR_LEN);
desc = (struct hal_reo_flush_cache *)tlv->value;
desc = hal->ops->reo_cmd_enc_tlv_hdr(tlv, HAL_REO_FLUSH_CACHE,
sizeof(*desc));
memset_startat(desc, 0, cache_addr_lo);
desc->cmd.info0 &= ~cpu_to_le32(HAL_REO_CMD_HDR_INFO0_STATUS_REQUIRED);
@ -98,15 +93,13 @@ static int ath12k_wifi7_hal_reo_cmd_flush_cache(struct ath12k_hal *hal,
}
static int
ath12k_wifi7_hal_reo_cmd_update_rx_queue(struct hal_tlv_64_hdr *tlv,
ath12k_wifi7_hal_reo_cmd_update_rx_queue(struct ath12k_hal *hal, void *tlv,
struct ath12k_hal_reo_cmd *cmd)
{
struct hal_reo_update_rx_queue *desc;
tlv->tl = le64_encode_bits(HAL_REO_UPDATE_RX_REO_QUEUE, HAL_TLV_HDR_TAG) |
le64_encode_bits(sizeof(*desc), HAL_TLV_HDR_LEN);
desc = (struct hal_reo_update_rx_queue *)tlv->value;
desc = hal->ops->reo_cmd_enc_tlv_hdr(tlv, HAL_REO_UPDATE_RX_REO_QUEUE,
sizeof(*desc));
memset_startat(desc, 0, queue_addr_lo);
desc->cmd.info0 &= ~cpu_to_le32(HAL_REO_CMD_HDR_INFO0_STATUS_REQUIRED);
@ -227,7 +220,8 @@ int ath12k_wifi7_hal_reo_cmd_send(struct ath12k_base *ab, struct hal_srng *srng,
enum hal_reo_cmd_type type,
struct ath12k_hal_reo_cmd *cmd)
{
struct hal_tlv_64_hdr *reo_desc;
struct ath12k_hal *hal = &ab->hal;
void *reo_desc;
int ret;
spin_lock_bh(&srng->lock);
@ -241,14 +235,13 @@ int ath12k_wifi7_hal_reo_cmd_send(struct ath12k_base *ab, struct hal_srng *srng,
switch (type) {
case HAL_REO_CMD_GET_QUEUE_STATS:
ret = ath12k_wifi7_hal_reo_cmd_queue_stats(reo_desc, cmd);
ret = ath12k_wifi7_hal_reo_cmd_queue_stats(hal, reo_desc, cmd);
break;
case HAL_REO_CMD_FLUSH_CACHE:
ret = ath12k_wifi7_hal_reo_cmd_flush_cache(&ab->hal, reo_desc,
cmd);
ret = ath12k_wifi7_hal_reo_cmd_flush_cache(hal, reo_desc, cmd);
break;
case HAL_REO_CMD_UPDATE_RX_QUEUE:
ret = ath12k_wifi7_hal_reo_cmd_update_rx_queue(reo_desc, cmd);
ret = ath12k_wifi7_hal_reo_cmd_update_rx_queue(hal, reo_desc, cmd);
break;
case HAL_REO_CMD_FLUSH_QUEUE:
case HAL_REO_CMD_UNBLOCK_CACHE:
@ -550,12 +543,9 @@ ath12k_wifi7_hal_rx_msdu_link_desc_set(struct ath12k_base *ab,
}
void ath12k_wifi7_hal_reo_status_queue_stats(struct ath12k_base *ab,
struct hal_tlv_64_hdr *tlv,
struct hal_reo_get_queue_stats_status *desc,
struct hal_reo_status *status)
{
struct hal_reo_get_queue_stats_status *desc =
(struct hal_reo_get_queue_stats_status *)tlv->value;
status->uniform_hdr.cmd_num =
le32_get_bits(desc->hdr.info0,
HAL_REO_STATUS_HDR_INFO0_STATUS_NUM);
@ -614,12 +604,9 @@ void ath12k_wifi7_hal_reo_status_queue_stats(struct ath12k_base *ab,
}
void ath12k_wifi7_hal_reo_flush_queue_status(struct ath12k_base *ab,
struct hal_tlv_64_hdr *tlv,
struct hal_reo_flush_queue_status *desc,
struct hal_reo_status *status)
{
struct hal_reo_flush_queue_status *desc =
(struct hal_reo_flush_queue_status *)tlv->value;
status->uniform_hdr.cmd_num =
le32_get_bits(desc->hdr.info0,
HAL_REO_STATUS_HDR_INFO0_STATUS_NUM);
@ -633,12 +620,10 @@ void ath12k_wifi7_hal_reo_flush_queue_status(struct ath12k_base *ab,
void
ath12k_wifi7_hal_reo_flush_cache_status(struct ath12k_base *ab,
struct hal_tlv_64_hdr *tlv,
struct hal_reo_flush_cache_status *desc,
struct hal_reo_status *status)
{
struct ath12k_hal *hal = &ab->hal;
struct hal_reo_flush_cache_status *desc =
(struct hal_reo_flush_cache_status *)tlv->value;
status->uniform_hdr.cmd_num =
le32_get_bits(desc->hdr.info0,
@ -675,12 +660,10 @@ ath12k_wifi7_hal_reo_flush_cache_status(struct ath12k_base *ab,
}
void ath12k_wifi7_hal_reo_unblk_cache_status(struct ath12k_base *ab,
struct hal_tlv_64_hdr *tlv,
struct hal_reo_unblock_cache_status *desc,
struct hal_reo_status *status)
{
struct ath12k_hal *hal = &ab->hal;
struct hal_reo_unblock_cache_status *desc =
(struct hal_reo_unblock_cache_status *)tlv->value;
status->uniform_hdr.cmd_num =
le32_get_bits(desc->hdr.info0,
@ -704,12 +687,9 @@ void ath12k_wifi7_hal_reo_unblk_cache_status(struct ath12k_base *ab,
void
ath12k_wifi7_hal_reo_flush_timeout_list_status(struct ath12k_base *ab,
struct hal_tlv_64_hdr *tlv,
struct hal_reo_flush_timeout_list_status *desc,
struct hal_reo_status *status)
{
struct hal_reo_flush_timeout_list_status *desc =
(struct hal_reo_flush_timeout_list_status *)tlv->value;
status->uniform_hdr.cmd_num =
le32_get_bits(desc->hdr.info0,
HAL_REO_STATUS_HDR_INFO0_STATUS_NUM);
@ -734,12 +714,9 @@ ath12k_wifi7_hal_reo_flush_timeout_list_status(struct ath12k_base *ab,
void
ath12k_wifi7_hal_reo_desc_thresh_reached_status(struct ath12k_base *ab,
struct hal_tlv_64_hdr *tlv,
struct hal_reo_desc_thresh_reached_status *desc,
struct hal_reo_status *status)
{
struct hal_reo_desc_thresh_reached_status *desc =
(struct hal_reo_desc_thresh_reached_status *)tlv->value;
status->uniform_hdr.cmd_num =
le32_get_bits(desc->hdr.info0,
HAL_REO_STATUS_HDR_INFO0_STATUS_NUM);
@ -769,12 +746,9 @@ ath12k_wifi7_hal_reo_desc_thresh_reached_status(struct ath12k_base *ab,
}
void ath12k_wifi7_hal_reo_update_rx_reo_queue_status(struct ath12k_base *ab,
struct hal_tlv_64_hdr *tlv,
struct hal_reo_status_hdr *desc,
struct hal_reo_status *status)
{
struct hal_reo_status_hdr *desc =
(struct hal_reo_status_hdr *)tlv->value;
status->uniform_hdr.cmd_num =
le32_get_bits(desc->info0,
HAL_REO_STATUS_HDR_INFO0_STATUS_NUM);
@ -891,8 +865,8 @@ void ath12k_wifi7_hal_reo_qdesc_setup(struct hal_rx_reo_queue *qdesc,
REO_QUEUE_DESC_MAGIC_DEBUG_PATTERN_3);
}
void ath12k_wifi7_hal_reo_init_cmd_ring(struct ath12k_base *ab,
struct hal_srng *srng)
void ath12k_wifi7_hal_reo_init_cmd_ring_tlv64(struct ath12k_base *ab,
struct hal_srng *srng)
{
struct hal_srng_params params;
struct hal_tlv_64_hdr *tlv;
@ -916,6 +890,31 @@ void ath12k_wifi7_hal_reo_init_cmd_ring(struct ath12k_base *ab,
}
}
void ath12k_wifi7_hal_reo_init_cmd_ring_tlv32(struct ath12k_base *ab,
struct hal_srng *srng)
{
struct hal_reo_get_queue_stats *desc;
struct hal_srng_params params;
struct hal_tlv_hdr *tlv;
int i, cmd_num = 1;
int entry_size;
u8 *entry;
memset(&params, 0, sizeof(params));
entry_size = ath12k_hal_srng_get_entrysize(ab, HAL_REO_CMD);
ath12k_hal_srng_get_params(ab, srng, &params);
entry = (u8 *)params.ring_base_vaddr;
for (i = 0; i < params.num_entries; i++) {
tlv = (struct hal_tlv_hdr *)entry;
desc = (struct hal_reo_get_queue_stats *)tlv->value;
desc->cmd.info0 = le32_encode_bits(cmd_num++,
HAL_REO_CMD_HDR_INFO0_CMD_NUMBER);
entry += entry_size;
}
}
void ath12k_wifi7_hal_reo_hw_setup(struct ath12k_base *ab, u32 ring_hash_map)
{
struct ath12k_hal *hal = &ab->hal;

View File

@ -813,25 +813,27 @@ enum hal_mon_reception_type {
(HAL_RU(ru_per80, num_80mhz, ru_idx_per80mhz))
void ath12k_wifi7_hal_reo_status_queue_stats(struct ath12k_base *ab,
struct hal_tlv_64_hdr *tlv,
struct hal_reo_get_queue_stats_status *desc,
struct hal_reo_status *status);
void ath12k_wifi7_hal_reo_flush_queue_status(struct ath12k_base *ab,
struct hal_tlv_64_hdr *tlv,
struct hal_reo_flush_queue_status *desc,
struct hal_reo_status *status);
void ath12k_wifi7_hal_reo_flush_cache_status(struct ath12k_base *ab,
struct hal_tlv_64_hdr *tlv,
struct hal_reo_flush_cache_status *desc,
struct hal_reo_status *status);
void ath12k_wifi7_hal_reo_unblk_cache_status(struct ath12k_base *ab,
struct hal_tlv_64_hdr *tlv,
struct hal_reo_unblock_cache_status *desc,
struct hal_reo_status *status);
void ath12k_wifi7_hal_reo_flush_timeout_list_status(struct ath12k_base *ab,
struct hal_tlv_64_hdr *tlv,
struct hal_reo_status *status);
void ath12k_wifi7_hal_reo_desc_thresh_reached_status(struct ath12k_base *ab,
struct hal_tlv_64_hdr *tlv,
struct hal_reo_status *status);
void
ath12k_wifi7_hal_reo_flush_timeout_list_status(struct ath12k_base *ab,
struct hal_reo_flush_timeout_list_status *desc,
struct hal_reo_status *status);
void
ath12k_wifi7_hal_reo_desc_thresh_reached_status(struct ath12k_base *ab,
struct hal_reo_desc_thresh_reached_status *desc,
struct hal_reo_status *status);
void ath12k_wifi7_hal_reo_update_rx_reo_queue_status(struct ath12k_base *ab,
struct hal_tlv_64_hdr *tlv,
struct hal_reo_status_hdr *desc,
struct hal_reo_status *status);
void ath12k_wifi7_hal_rx_msdu_link_info_get(struct hal_rx_msdu_link *link, u32 *num_msdus,
u32 *msdu_cookies,
@ -860,8 +862,10 @@ void ath12k_wifi7_hal_rx_msdu_list_get(struct ath12k *ar,
void *link_desc,
void *msdu_list_opaque,
u16 *num_msdus);
void ath12k_wifi7_hal_reo_init_cmd_ring(struct ath12k_base *ab,
struct hal_srng *srng);
void ath12k_wifi7_hal_reo_init_cmd_ring_tlv64(struct ath12k_base *ab,
struct hal_srng *srng);
void ath12k_wifi7_hal_reo_init_cmd_ring_tlv32(struct ath12k_base *ab,
struct hal_srng *srng);
void ath12k_wifi7_hal_reo_shared_qaddr_cache_clear(struct ath12k_base *ab);
void ath12k_wifi7_hal_reo_hw_setup(struct ath12k_base *ab, u32 ring_hash_map);
void ath12k_wifi7_hal_reo_qdesc_setup(struct hal_rx_reo_queue *qdesc,

View File

@ -1481,10 +1481,27 @@ struct hal_rx_desc_wcn7850 {
u8 msdu_payload[];
};
struct rx_pkt_hdr_tlv_qcc2072 {
__le32 tag;
__le64 phy_ppdu_id;
u8 rx_pkt_hdr[HAL_RX_BE_PKT_HDR_TLV_LEN];
};
struct hal_rx_desc_qcc2072 {
__le32 msdu_end_tag;
struct rx_msdu_end_qcn9274 msdu_end;
u8 rx_padding0[RX_BE_PADDING0_BYTES];
__le32 mpdu_start_tag;
struct rx_mpdu_start_qcn9274 mpdu_start;
struct rx_pkt_hdr_tlv_qcc2072 pkt_hdr_tlv;
u8 msdu_payload[];
};
struct hal_rx_desc {
union {
struct hal_rx_desc_qcn9274_compact qcn9274_compact;
struct hal_rx_desc_wcn7850 wcn7850;
struct hal_rx_desc_qcc2072 qcc2072;
} u;
} __packed;

View File

@ -256,6 +256,8 @@ const struct ath12k_hw_regs wcn7850_regs = {
.umac_ce1_dest_reg_base = 0x01b83000,
.gcc_gcc_pcie_hot_rst = 0x1e40304,
.qrtr_node_id = 0x1e03164,
};
static inline
@ -614,7 +616,7 @@ void ath12k_hal_extract_rx_desc_data_wcn7850(struct hal_rx_desc_data *rx_desc_da
rx_desc_data->err_bitmap = ath12k_hal_rx_h_mpdu_err_wcn7850(rx_desc);
}
static int ath12k_hal_srng_create_config_wcn7850(struct ath12k_hal *hal)
int ath12k_hal_srng_create_config_wcn7850(struct ath12k_hal *hal)
{
struct hal_srng_config *s;
@ -793,7 +795,7 @@ const struct hal_ops hal_wcn7850_ops = {
.write_reoq_lut_addr = ath12k_wifi7_hal_write_reoq_lut_addr,
.write_ml_reoq_lut_addr = ath12k_wifi7_hal_write_ml_reoq_lut_addr,
.setup_link_idle_list = ath12k_wifi7_hal_setup_link_idle_list,
.reo_init_cmd_ring = ath12k_wifi7_hal_reo_init_cmd_ring,
.reo_init_cmd_ring = ath12k_wifi7_hal_reo_init_cmd_ring_tlv64,
.reo_shared_qaddr_cache_clear = ath12k_wifi7_hal_reo_shared_qaddr_cache_clear,
.reo_hw_setup = ath12k_wifi7_hal_reo_hw_setup,
.rx_buf_addr_info_set = ath12k_wifi7_hal_rx_buf_addr_info_set,
@ -802,4 +804,6 @@ const struct hal_ops hal_wcn7850_ops = {
.get_idle_link_rbm = ath12k_wifi7_hal_get_idle_link_rbm,
.rx_msdu_list_get = ath12k_wifi7_hal_rx_msdu_list_get,
.rx_reo_ent_buf_paddr_get = ath12k_wifi7_hal_rx_reo_ent_buf_paddr_get,
.reo_cmd_enc_tlv_hdr = ath12k_hal_encode_tlv64_hdr,
.reo_status_dec_tlv_hdr = ath12k_hal_decode_tlv64_hdr,
};

View File

@ -36,4 +36,5 @@ void ath12k_hal_rx_desc_get_dot11_hdr_wcn7850(struct hal_rx_desc *desc,
void ath12k_hal_extract_rx_desc_data_wcn7850(struct hal_rx_desc_data *rx_desc_data,
struct hal_rx_desc *rx_desc,
struct hal_rx_desc *ldesc);
int ath12k_hal_srng_create_config_wcn7850(struct ath12k_hal *hal);
#endif

View File

@ -170,6 +170,16 @@ static const struct ath12k_hw_ops wcn7850_ops = {
.is_frame_link_agnostic = ath12k_wifi7_is_frame_link_agnostic_wcn7850,
};
static const struct ath12k_hw_ops qcc2072_ops = {
.get_hw_mac_from_pdev_id = ath12k_wifi7_hw_qcn9274_mac_from_pdev_id,
.mac_id_to_pdev_id = ath12k_wifi7_hw_mac_id_to_pdev_id_wcn7850,
.mac_id_to_srng_id = ath12k_wifi7_hw_mac_id_to_srng_id_wcn7850,
.rxdma_ring_sel_config = ath12k_dp_rxdma_ring_sel_config_qcc2072,
.get_ring_selector = ath12k_wifi7_hw_get_ring_selector_wcn7850,
.dp_srng_is_tx_comp_ring = ath12k_wifi7_dp_srng_is_comp_ring_wcn7850,
.is_frame_link_agnostic = ath12k_wifi7_is_frame_link_agnostic_wcn7850,
};
#define ATH12K_TX_RING_MASK_0 0x1
#define ATH12K_TX_RING_MASK_1 0x2
#define ATH12K_TX_RING_MASK_2 0x4
@ -339,6 +349,7 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {
.board_size = 256 * 1024,
.cal_offset = 128 * 1024,
.m3_loader = ath12k_m3_fw_loader_driver,
.download_aux_ucode = false,
},
.max_radios = 1,
.single_pdev_only = false,
@ -421,6 +432,7 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {
.board_size = 256 * 1024,
.cal_offset = 256 * 1024,
.m3_loader = ath12k_m3_fw_loader_driver,
.download_aux_ucode = false,
},
.max_radios = 1,
@ -505,6 +517,7 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {
.board_size = 256 * 1024,
.cal_offset = 128 * 1024,
.m3_loader = ath12k_m3_fw_loader_driver,
.download_aux_ucode = false,
},
.max_radios = 2,
.single_pdev_only = false,
@ -586,6 +599,7 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {
.board_size = 256 * 1024,
.cal_offset = 128 * 1024,
.m3_loader = ath12k_m3_fw_loader_remoteproc,
.download_aux_ucode = false,
},
.max_radios = 1,
.single_pdev_only = false,
@ -652,6 +666,93 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {
.dp_primary_link_only = true,
},
{
.name = "qcc2072 hw1.0",
.hw_rev = ATH12K_HW_QCC2072_HW10,
.fw = {
.dir = "QCC2072/hw1.0",
.board_size = 256 * 1024,
.cal_offset = 256 * 1024,
.m3_loader = ath12k_m3_fw_loader_driver,
.download_aux_ucode = true,
},
.max_radios = 1,
.single_pdev_only = true,
.qmi_service_ins_id = ATH12K_QMI_WLFW_SERVICE_INS_ID_V01_WCN7850,
.internal_sleep_clock = true,
.hw_ops = &qcc2072_ops,
.ring_mask = &ath12k_wifi7_hw_ring_mask_wcn7850,
.host_ce_config = ath12k_wifi7_host_ce_config_wcn7850,
.ce_count = 9,
.target_ce_config = ath12k_wifi7_target_ce_config_wlan_wcn7850,
.target_ce_count = 9,
.svc_to_ce_map =
ath12k_wifi7_target_service_to_ce_map_wlan_wcn7850,
.svc_to_ce_map_len = 14,
.rxdma1_enable = false,
.num_rxdma_per_pdev = 2,
.num_rxdma_dst_ring = 1,
.rx_mac_buf_ring = true,
.vdev_start_delay = true,
.interface_modes = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_P2P_DEVICE) |
BIT(NL80211_IFTYPE_P2P_CLIENT) |
BIT(NL80211_IFTYPE_P2P_GO),
.supports_monitor = true,
.idle_ps = true,
.download_calib = false,
.supports_suspend = true,
.tcl_ring_retry = false,
.reoq_lut_support = false,
.supports_shadow_regs = true,
.num_tcl_banks = 7,
.max_tx_ring = 3,
.mhi_config = &ath12k_wifi7_mhi_config_wcn7850,
.wmi_init = ath12k_wifi7_wmi_init_wcn7850,
.qmi_cnss_feature_bitmap = BIT(CNSS_QDSS_CFG_MISS_V01) |
BIT(CNSS_PCIE_PERST_NO_PULL_V01) |
BIT(CNSS_AUX_UC_SUPPORT_V01),
.rfkill_pin = 0,
.rfkill_cfg = 0,
.rfkill_on_level = 0,
.rddm_size = 0x780000,
.def_num_link = 2,
.max_mlo_peer = 32,
.otp_board_id_register = 0,
.supports_sta_ps = true,
.acpi_guid = &wcn7850_uuid,
.supports_dynamic_smps_6ghz = false,
.iova_mask = 0,
.supports_aspm = true,
.ce_ie_addr = NULL,
.ce_remap = NULL,
.bdf_addr_offset = 0,
.current_cc_support = true,
.dp_primary_link_only = false,
},
};
/* Note: called under rcu_read_lock() */

View File

@ -19,6 +19,7 @@
#define QCN9274_DEVICE_ID 0x1109
#define WCN7850_DEVICE_ID 0x1107
#define QCC2072_DEVICE_ID 0x1112
#define ATH12K_PCI_W7_SOC_HW_VERSION_1 1
#define ATH12K_PCI_W7_SOC_HW_VERSION_2 2
@ -27,9 +28,13 @@
#define TCSR_SOC_HW_VERSION_MAJOR_MASK GENMASK(11, 8)
#define TCSR_SOC_HW_VERSION_MINOR_MASK GENMASK(7, 4)
#define WINDOW_REG_ADDRESS 0x310c
#define WINDOW_REG_ADDRESS_QCC2072 0x3278
static const struct pci_device_id ath12k_wifi7_pci_id_table[] = {
{ PCI_VDEVICE(QCOM, QCN9274_DEVICE_ID) },
{ PCI_VDEVICE(QCOM, WCN7850_DEVICE_ID) },
{ PCI_VDEVICE(QCOM, QCC2072_DEVICE_ID) },
{}
};
@ -104,6 +109,11 @@ static int ath12k_wifi7_pci_probe(struct pci_dev *pdev,
ab_pci->msi_config = &ath12k_wifi7_msi_config[0];
ab->static_window_map = true;
ab_pci->pci_ops = &ath12k_wifi7_pci_ops_qcn9274;
/*
* init window reg addr before reading hardware version
* as it will be used there
*/
ab_pci->window_reg_addr = WINDOW_REG_ADDRESS;
ath12k_wifi7_pci_read_hw_version(ab, &soc_hw_version_major,
&soc_hw_version_minor);
ab->target_mem_mode = ath12k_core_get_memory_mode(ab);
@ -126,6 +136,11 @@ static int ath12k_wifi7_pci_probe(struct pci_dev *pdev,
ab_pci->msi_config = &ath12k_wifi7_msi_config[0];
ab->static_window_map = false;
ab_pci->pci_ops = &ath12k_wifi7_pci_ops_wcn7850;
/*
* init window reg addr before reading hardware version
* as it will be used there
*/
ab_pci->window_reg_addr = WINDOW_REG_ADDRESS;
ath12k_wifi7_pci_read_hw_version(ab, &soc_hw_version_major,
&soc_hw_version_minor);
ab->target_mem_mode = ATH12K_QMI_MEMORY_MODE_DEFAULT;
@ -140,7 +155,16 @@ static int ath12k_wifi7_pci_probe(struct pci_dev *pdev,
return -EOPNOTSUPP;
}
break;
case QCC2072_DEVICE_ID:
ab->id.bdf_search = ATH12K_BDF_SEARCH_BUS_AND_BOARD;
ab_pci->msi_config = &ath12k_wifi7_msi_config[0];
ab->static_window_map = false;
ab_pci->pci_ops = &ath12k_wifi7_pci_ops_wcn7850;
ab_pci->window_reg_addr = WINDOW_REG_ADDRESS_QCC2072;
ab->target_mem_mode = ATH12K_QMI_MEMORY_MODE_DEFAULT;
/* there is only one version till now */
ab->hw_rev = ATH12K_HW_QCC2072_HW10;
break;
default:
dev_err(&pdev->dev, "Unknown Wi-Fi 7 PCI device found: 0x%x\n",
pci_dev->device);

View File

@ -102,4 +102,9 @@ void ath12k_wifi7_wmi_init_wcn7850(struct ath12k_base *ab,
config->num_multicast_filter_entries = 0x20;
config->num_wow_filters = 0x16;
config->num_keep_alive_pattern = 0;
if (test_bit(WMI_TLV_SERVICE_PEER_METADATA_V1A_V1B_SUPPORT, ab->wmi_ab.svc_map))
config->peer_metadata_ver = ATH12K_PEER_METADATA_V1A;
else
config->peer_metadata_ver = ab->wmi_ab.dp_peer_meta_data_ver;
}

View File

@ -399,6 +399,7 @@ ath12k_pull_mac_phy_cap_svc_ready_ext(struct ath12k_wmi_pdev *wmi_handle,
struct ath12k_band_cap *cap_band;
struct ath12k_pdev_cap *pdev_cap = &pdev->cap;
struct ath12k_fw_pdev *fw_pdev;
u32 supported_bands;
u32 phy_map;
u32 hw_idx, phy_idx = 0;
int i;
@ -422,14 +423,19 @@ ath12k_pull_mac_phy_cap_svc_ready_ext(struct ath12k_wmi_pdev *wmi_handle,
return -EINVAL;
mac_caps = wmi_mac_phy_caps + phy_idx;
supported_bands = le32_to_cpu(mac_caps->supported_bands);
if (!(supported_bands & WMI_HOST_WLAN_2GHZ_CAP) &&
!(supported_bands & WMI_HOST_WLAN_5GHZ_CAP))
return -EINVAL;
pdev->pdev_id = ath12k_wmi_mac_phy_get_pdev_id(mac_caps);
pdev->hw_link_id = ath12k_wmi_mac_phy_get_hw_link_id(mac_caps);
pdev_cap->supported_bands |= le32_to_cpu(mac_caps->supported_bands);
pdev_cap->supported_bands |= supported_bands;
pdev_cap->ampdu_density = le32_to_cpu(mac_caps->ampdu_density);
fw_pdev = &ab->fw_pdev[ab->fw_pdev_count];
fw_pdev->supported_bands = le32_to_cpu(mac_caps->supported_bands);
fw_pdev->supported_bands = supported_bands;
fw_pdev->pdev_id = ath12k_wmi_mac_phy_get_pdev_id(mac_caps);
fw_pdev->phy_id = le32_to_cpu(mac_caps->phy_id);
ab->fw_pdev_count++;
@ -438,10 +444,12 @@ ath12k_pull_mac_phy_cap_svc_ready_ext(struct ath12k_wmi_pdev *wmi_handle,
* band to band for a single radio, need to see how this should be
* handled.
*/
if (le32_to_cpu(mac_caps->supported_bands) & WMI_HOST_WLAN_2GHZ_CAP) {
if (supported_bands & WMI_HOST_WLAN_2GHZ_CAP) {
pdev_cap->tx_chain_mask = le32_to_cpu(mac_caps->tx_chain_mask_2g);
pdev_cap->rx_chain_mask = le32_to_cpu(mac_caps->rx_chain_mask_2g);
} else if (le32_to_cpu(mac_caps->supported_bands) & WMI_HOST_WLAN_5GHZ_CAP) {
}
if (supported_bands & WMI_HOST_WLAN_5GHZ_CAP) {
pdev_cap->vht_cap = le32_to_cpu(mac_caps->vht_cap_info_5g);
pdev_cap->vht_mcs = le32_to_cpu(mac_caps->vht_supp_mcs_5g);
pdev_cap->he_mcs = le32_to_cpu(mac_caps->he_supp_mcs_5g);
@ -451,8 +459,6 @@ ath12k_pull_mac_phy_cap_svc_ready_ext(struct ath12k_wmi_pdev *wmi_handle,
WMI_NSS_RATIO_EN_DIS_GET(mac_caps->nss_ratio);
pdev_cap->nss_ratio_info =
WMI_NSS_RATIO_INFO_GET(mac_caps->nss_ratio);
} else {
return -EINVAL;
}
/* tx/rx chainmask reported from fw depends on the actual hw chains used,
@ -468,7 +474,7 @@ ath12k_pull_mac_phy_cap_svc_ready_ext(struct ath12k_wmi_pdev *wmi_handle,
pdev_cap->rx_chain_mask_shift =
find_first_bit((unsigned long *)&pdev_cap->rx_chain_mask, 32);
if (le32_to_cpu(mac_caps->supported_bands) & WMI_HOST_WLAN_2GHZ_CAP) {
if (supported_bands & WMI_HOST_WLAN_2GHZ_CAP) {
cap_band = &pdev_cap->band[NL80211_BAND_2GHZ];
cap_band->phy_id = le32_to_cpu(mac_caps->phy_id);
cap_band->max_bw_supported = le32_to_cpu(mac_caps->max_bw_supported_2g);
@ -488,7 +494,7 @@ ath12k_pull_mac_phy_cap_svc_ready_ext(struct ath12k_wmi_pdev *wmi_handle,
le32_to_cpu(mac_caps->he_ppet2g.ppet16_ppet8_ru3_ru0[i]);
}
if (le32_to_cpu(mac_caps->supported_bands) & WMI_HOST_WLAN_5GHZ_CAP) {
if (supported_bands & WMI_HOST_WLAN_5GHZ_CAP) {
cap_band = &pdev_cap->band[NL80211_BAND_5GHZ];
cap_band->phy_id = le32_to_cpu(mac_caps->phy_id);
cap_band->max_bw_supported =
@ -2800,7 +2806,8 @@ int ath12k_wmi_send_scan_chan_list_cmd(struct ath12k *ar,
max_chan_limit = (wmi->wmi_ab->max_msg_len[ar->pdev_idx] - len) /
sizeof(*chan_info);
num_send_chans = min(arg->nallchans, max_chan_limit);
num_send_chans = min3(arg->nallchans, max_chan_limit,
ATH12K_WMI_MAX_NUM_CHAN_PER_CMD);
arg->nallchans -= num_send_chans;
len += sizeof(*chan_info) * num_send_chans;
@ -4449,7 +4456,7 @@ static int ath12k_wmi_hw_mode_caps(struct ath12k_base *soc,
pref = soc->wmi_ab.preferred_hw_mode;
if (ath12k_hw_mode_pri_map[mode] < ath12k_hw_mode_pri_map[pref]) {
if (ath12k_hw_mode_pri_map[mode] <= ath12k_hw_mode_pri_map[pref]) {
svc_rdy_ext->pref_hw_mode_caps = *hw_mode_caps;
soc->wmi_ab.preferred_hw_mode = mode;
}
@ -4918,19 +4925,10 @@ ath12k_wmi_tlv_mac_phy_caps_ext_parse(struct ath12k_base *ab,
const struct ath12k_wmi_caps_ext_params *caps,
struct ath12k_pdev *pdev)
{
struct ath12k_band_cap *cap_band;
u32 bands, support_320mhz;
u32 bands;
int i;
if (ab->hw_params->single_pdev_only) {
if (caps->hw_mode_id == WMI_HOST_HW_MODE_SINGLE) {
support_320mhz = le32_to_cpu(caps->eht_cap_phy_info_5ghz[0]) &
IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ;
cap_band = &pdev->cap.band[NL80211_BAND_6GHZ];
cap_band->eht_cap_phy_info[0] |= support_320mhz;
return 0;
}
for (i = 0; i < ab->fw_pdev_count; i++) {
struct ath12k_fw_pdev *fw_pdev = &ab->fw_pdev[i];
@ -4983,14 +4981,22 @@ static int ath12k_wmi_tlv_mac_phy_caps_ext(struct ath12k_base *ab, u16 tag,
void *data)
{
const struct ath12k_wmi_caps_ext_params *caps = ptr;
struct ath12k_band_cap *cap_band;
u32 support_320mhz;
int i = 0, ret;
if (tag != WMI_TAG_MAC_PHY_CAPABILITIES_EXT)
return -EPROTO;
if (ab->hw_params->single_pdev_only) {
if (ab->wmi_ab.preferred_hw_mode != le32_to_cpu(caps->hw_mode_id) &&
caps->hw_mode_id != WMI_HOST_HW_MODE_SINGLE)
if (caps->hw_mode_id == WMI_HOST_HW_MODE_SINGLE) {
support_320mhz = le32_to_cpu(caps->eht_cap_phy_info_5ghz[0]) &
IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ;
cap_band = &ab->pdevs[0].cap.band[NL80211_BAND_6GHZ];
cap_band->eht_cap_phy_info[0] |= support_320mhz;
}
if (ab->wmi_ab.preferred_hw_mode != le32_to_cpu(caps->hw_mode_id))
return 0;
} else {
for (i = 0; i < ab->num_radios; i++) {
@ -5471,6 +5477,10 @@ static int ath12k_wmi_svc_rdy_ext2_parse(struct ath12k_base *ab,
ret);
return ret;
}
ab->wmi_ab.dp_peer_meta_data_ver =
u32_get_bits(parse->arg.target_cap_flags,
WMI_TARGET_CAP_FLAGS_RX_PEER_METADATA_VERSION);
break;
case WMI_TAG_ARRAY_STRUCT:

View File

@ -2783,6 +2783,8 @@ enum wmi_channel_width {
#define WMI_EHT_MCS_NSS_10_11 GENMASK(11, 8)
#define WMI_EHT_MCS_NSS_12_13 GENMASK(15, 12)
#define WMI_TARGET_CAP_FLAGS_RX_PEER_METADATA_VERSION GENMASK(1, 0)
struct wmi_service_ready_ext2_event {
__le32 reg_db_version;
__le32 hw_min_max_tx_power_2ghz;
@ -5230,6 +5232,8 @@ struct ath12k_wmi_base {
struct ath12k_svc_ext_info svc_ext_info;
u32 sbs_lower_band_end_freq;
struct ath12k_hw_mode_info hw_mode_info;
u8 dp_peer_meta_data_ver;
};
struct wmi_pdev_set_bios_interface_cmd {
@ -6322,6 +6326,9 @@ struct ath12k_wmi_rssi_dbm_conv_info_arg {
s8 min_nf_dbm;
};
/* each WMI cmd can hold 58 channel entries at most */
#define ATH12K_WMI_MAX_NUM_CHAN_PER_CMD 58
int ath12k_wmi_cmd_send(struct ath12k_wmi_pdev *wmi, struct sk_buff *skb,
u32 cmd_id);
struct sk_buff *ath12k_wmi_alloc_skb(struct ath12k_wmi_base *wmi_sc, u32 len);

View File

@ -135,6 +135,9 @@ static int ath12k_wow_cleanup(struct ath12k *ar)
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
list_for_each_entry(arvif, &ar->arvifs, list) {
if (arvif != &arvif->ahvif->deflink)
continue;
ret = ath12k_wow_vif_cleanup(arvif);
if (ret) {
ath12k_warn(ar->ab, "failed to clean wow wakeups on vdev %i: %d\n",
@ -479,8 +482,12 @@ static int ath12k_wow_set_wakeups(struct ath12k *ar,
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
list_for_each_entry(arvif, &ar->arvifs, list) {
if (arvif != &arvif->ahvif->deflink)
continue;
if (ath12k_wow_is_p2p_vdev(arvif->ahvif))
continue;
ret = ath12k_wow_vif_set_wakeups(arvif, wowlan);
if (ret) {
ath12k_warn(ar->ab, "failed to set wow wakeups on vdev %i: %d\n",
@ -538,6 +545,9 @@ static int ath12k_wow_nlo_cleanup(struct ath12k *ar)
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
list_for_each_entry(arvif, &ar->arvifs, list) {
if (arvif != &arvif->ahvif->deflink)
continue;
if (ath12k_wow_is_p2p_vdev(arvif->ahvif))
continue;
@ -745,6 +755,9 @@ static int ath12k_wow_arp_ns_offload(struct ath12k *ar, bool enable)
list_for_each_entry(arvif, &ar->arvifs, list) {
ahvif = arvif->ahvif;
if (arvif != &ahvif->deflink)
continue;
if (ahvif->vdev_type != WMI_VDEV_TYPE_STA)
continue;
@ -776,6 +789,9 @@ static int ath12k_gtk_rekey_offload(struct ath12k *ar, bool enable)
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
list_for_each_entry(arvif, &ar->arvifs, list) {
if (arvif != &arvif->ahvif->deflink)
continue;
if (arvif->ahvif->vdev_type != WMI_VDEV_TYPE_STA ||
!arvif->is_up ||
!arvif->rekey_data.enable_offload)

View File

@ -80,11 +80,9 @@ struct ath5k_dbg_info {
* @ATH5K_DEBUG_CALIBRATE: periodic calibration
* @ATH5K_DEBUG_TXPOWER: transmit power setting
* @ATH5K_DEBUG_LED: led management
* @ATH5K_DEBUG_DUMP_RX: print received skb content
* @ATH5K_DEBUG_DUMP_TX: print transmit skb content
* @ATH5K_DEBUG_DUMPBANDS: dump bands
* @ATH5K_DEBUG_DMA: debug dma start/stop
* @ATH5K_DEBUG_TRACE: trace function calls
* @ATH5K_DEBUG_ANI: debug Adaptive Noise Immunity
* @ATH5K_DEBUG_DESC: descriptor setup
* @ATH5K_DEBUG_ANY: show at any debug level
*

View File

@ -47,7 +47,7 @@ config ATH9K_PCI
config ATH9K_AHB
bool "Atheros ath9k AHB bus support"
depends on ATH9K
depends on ATH9K && OF
default n
help
This option enables the AHB bus support in ath9k.

View File

@ -19,14 +19,14 @@
/**
* struct ath_rx_stats - RX Statistics
* @rx_pkts_all: No. of total frames received, including ones that
may have had errors.
* may have had errors.
* @rx_bytes_all: No. of total bytes received, including ones that
may have had errors.
* may have had errors.
* @crc_err: No. of frames with incorrect CRC value
* @decrypt_crc_err: No. of frames whose CRC check failed after
decryption process completed
* decryption process completed
* @phy_err: No. of frames whose reception failed because the PHY
encountered an error
* encountered an error
* @mic_err: No. of frames with incorrect TKIP MIC verification failure
* @pre_delim_crc_err: Pre-Frame delimiter CRC error detections
* @post_delim_crc_err: Post-Frame delimiter CRC error detections

View File

@ -142,11 +142,12 @@ struct ath_interrupt_stats {
/**
* struct ath_tx_stats - Statistics about TX
* @tx_pkts_all: No. of total frames transmitted, including ones that
may have had errors.
* may have had errors.
* @tx_bytes_all: No. of total bytes transmitted, including ones that
may have had errors.
* may have had errors.
* @queued: Total MPDUs (non-aggr) queued
* @completed: Total MPDUs (non-aggr) completed
* @xretries: Total MPDUs with xretries
* @a_aggr: Total no. of aggregates queued
* @a_queued_hw: Total AMPDUs queued to hardware
* @a_completed: Total AMPDUs completed
@ -154,14 +155,14 @@ struct ath_interrupt_stats {
* @a_xretries: No. of AMPDUs dropped due to xretries
* @txerr_filtered: No. of frames with TXERR_FILT flag set.
* @fifo_underrun: FIFO underrun occurrences
Valid only for:
- non-aggregate condition.
- first packet of aggregate.
* Valid only for:
* - non-aggregate condition.
* - first packet of aggregate.
* @xtxop: No. of frames filtered because of TXOP limit
* @timer_exp: Transmit timer expiry
* @desc_cfg_err: Descriptor configuration errors
* @data_urn: TX data underrun errors
* @delim_urn: TX delimiter underrun errors
* @data_underrun: TX data underrun errors
* @delim_underrun: TX delimiter underrun errors
* @puttxbuf: Number of times hardware was given txbuf to write.
* @txstart: Number of times hardware was told to start tx.
* @txprocdesc: Number of times tx descriptor was processed

View File

@ -58,7 +58,7 @@ union wil_tx_desc;
*/
#define WIL_MAX_VIFS 4
/**
/*
* extract bits [@b0:@b1] (inclusive) from the value @x
* it should be @b0 <= @b1, or result is incorrect
*/
@ -433,7 +433,7 @@ extern struct fw_map fw_mapping[MAX_FW_MAPPING_TABLE_SIZE];
* @cid: CID value
* @tid: TID value
*
* @cidxtid field encoded as bits 0..3 - CID; 4..7 - TID
* Returns: @cidxtid field encoded as bits 0..3 - CID; 4..7 - TID
*/
static inline u8 mk_cidxtid(u8 cid, u8 tid)
{
@ -444,8 +444,7 @@ static inline u8 mk_cidxtid(u8 cid, u8 tid)
* parse_cidxtid - parse @cidxtid field
* @cid: store CID value here
* @tid: store TID value here
*
* @cidxtid field encoded as bits 0..3 - CID; 4..7 - TID
* @cidxtid: field encoded as bits 0..3 - CID; 4..7 - TID
*/
static inline void parse_cidxtid(u8 cidxtid, u8 *cid, u8 *tid)
{
@ -500,7 +499,7 @@ enum { /* for wil_ctx.mapped_as */
wil_mapped_as_page = 2,
};
/**
/*
* struct wil_ctx - software context for ring descriptor
*/
struct wil_ctx {
@ -514,7 +513,7 @@ struct wil_desc_ring_rx_swtail { /* relevant for enhanced DMA only */
dma_addr_t pa;
};
/**
/*
* A general ring structure, used for RX and TX.
* In legacy DMA it represents the vring,
* In enahnced DMA it represents the descriptor ring (vrings are handled by FW)
@ -531,7 +530,7 @@ struct wil_ring {
bool is_rx;
};
/**
/*
* Additional data for Rx ring.
* Used for enhanced DMA RX chaining.
*/
@ -543,7 +542,7 @@ struct wil_ring_rx_data {
u16 buff_size;
};
/**
/*
* Status ring structure, used for enhanced DMA completions for RX and TX.
*/
struct wil_status_ring {
@ -586,8 +585,8 @@ struct wil_net_stats {
u32 ft_roams; /* relevant in STA mode */
};
/**
* struct tx_rx_ops - different TX/RX ops for legacy and enhanced
/*
* struct wil_txrx_ops - different TX/RX ops for legacy and enhanced
* DMA flow
*/
struct wil_txrx_ops {
@ -627,7 +626,7 @@ struct wil_txrx_ops {
irqreturn_t (*irq_rx)(int irq, void *cookie);
};
/**
/*
* Additional data for Tx ring
*/
struct wil_ring_tx_data {
@ -658,7 +657,7 @@ enum { /* for wil6210_priv.status */
struct pci_dev;
/**
* struct tid_ampdu_rx - TID aggregation information (Rx).
* struct wil_tid_ampdu_rx - TID aggregation information (Rx).
*
* @reorder_buf: buffer to reorder incoming aggregated MPDUs
* @last_rx: jiffies of last rx activity
@ -728,7 +727,7 @@ enum wil_rekey_state {
WIL_REKEY_WAIT_M4_SENT = 2,
};
/**
/*
* struct wil_sta_info - data for peer
*
* Peer identified by its CID (connection ID)
@ -741,7 +740,7 @@ struct wil_sta_info {
u8 mid;
enum wil_sta_status status;
struct wil_net_stats stats;
/**
/*
* 20 latency bins. 1st bin counts packets with latency
* of 0..tx_latency_res, last bin counts packets with latency
* of 19*tx_latency_res and above.
@ -882,7 +881,7 @@ struct wil6210_vif {
struct work_struct enable_tx_key_worker;
};
/**
/*
* RX buffer allocated for enhanced DMA RX descriptors
*/
struct wil_rx_buff {
@ -891,7 +890,7 @@ struct wil_rx_buff {
int id;
};
/**
/*
* During Rx completion processing, the driver extracts a buffer ID which
* is used as an index to the rx_buff_mgmt.buff_arr array and then the SKB
* is given to the network stack and the buffer is moved from the 'active'
@ -1147,7 +1146,7 @@ static inline void wil_c(struct wil6210_priv *wil, u32 reg, u32 val)
wil_w(wil, reg, wil_r(wil, reg) & ~val);
}
/**
/*
* wil_cid_valid - check cid is valid
*/
static inline bool wil_cid_valid(struct wil6210_priv *wil, int cid)