mirror of
https://github.com/torvalds/linux.git
synced 2026-05-27 16:44:58 +02:00
Firmware sends CFR meta data through the WMI event WMI_PEER_CFR_CAPTURE_EVENT. Parse the meta data coming from the firmware and invoke correlate_and_relay function to correlate the CFR meta data with the CFR payload coming from the other WMI event WMI_PDEV_DMA_RING_BUF_RELEASE_EVENT. Release the buffer to user space once correlate and relay return success. Tested-on: IPQ8074 hw2.0 PCI IPQ8074 WLAN.HK.2.5.0.1-00991-QCAHKSWPL_SILICONZ-1 Tested-on: WCN6855 hw2.1 PCI WLAN.HSP.1.1-04685-QCAHSPSWPL_V1_V2_SILICONZ_IOE-1 Signed-off-by: Venkateswara Naralasetty <quic_vnaralas@quicinc.com> Co-developed-by: Yu Zhang (Yuriy) <yu.zhang@oss.qualcomm.com> Signed-off-by: Yu Zhang (Yuriy) <yu.zhang@oss.qualcomm.com> Reviewed-by: Vasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com> Reviewed-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com> Signed-off-by: Qian Zhang <qian.zhang@oss.qualcomm.com> Link: https://patch.msgid.link/20251230082520.3401007-7-qian.zhang@oss.qualcomm.com Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
309 lines
7.3 KiB
C
309 lines
7.3 KiB
C
/* 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 */
|