Provide a relayfs interface to collect the CFR dump from
the user space.
'/sys/kernel/debug/ieee80211/phyX/ath11k/cfr_capture' is exposed
to user space to get CFR data.
CFR format to user space:
___________________________________________
| CFR header | CFR payload | CFR tail data |
|____________|_____________|_______________|
CFR header contains the following fields,
* Start magic number 0xDEADBEAF - 4bytes
* vendor id - 4bytes
* cfr metadata version - 1byte
* cfr data version - 1byte
* chip type - 1byte
* platform type - 1byte
* CFR metadata length - 4bytes
* metadata - 92bytes
peer mac - 6bytes
capture status - 1byte (1 for success 0 for failure)
capture_bw - 1byte
channel_bw - 1byte
phy_mode - 1byte
prim20_chan - 2bytes
center_freq1 - 2bytes
center_freq2 - 2bytes
capture_mode - 1byte
capture_type - 1byte
sts_count - 1byte
num_rx_chain - 1byte
timestamp - 4bytes
length - 4bytes
chain_rssi - 32bytes (4bytes for each chain)
chain_phase - 16bytes (2bytes for each chain)
cfo_measurement - 4bytes
agc_gain - 8bytes (1 bytes for each chain)
rx_start_ts - 4bytes
CFR payload:
CFR payload contains 8bytes of ucode header followed by the
tone information. Tone order is positive tones, followed by
PHY memory garbage, followed by negative tones. Dummy tones
are uploaded to make number of tones always integer number
of 64. Number of tones is not preamble type dependent.
Each CFR tone has 14-bit I component and 14-bit Q component
and is sign extended to 16-bit I/Q. Two tones are packed
into one 64-bit unit as:
[63:0] = [Tone1_Q(63:48) Tone1_I(47:32) Tone0_Q(31:16) Tone0_I(15:0)]
CFR tail: end magic number 0xBEAFDEAD
Tested-on: IPQ8074 WLAN.HK.2.5.0.1-00991-QCAHKSWPL_SILICONZ-1
Signed-off-by: Venkateswara Naralasetty <[email protected]>
---
drivers/net/wireless/ath/ath11k/cfr.c | 43 +++++++++++++++++++++++++++++++++++
drivers/net/wireless/ath/ath11k/cfr.h | 1 +
2 files changed, 44 insertions(+)
diff --git a/drivers/net/wireless/ath/ath11k/cfr.c b/drivers/net/wireless/ath/ath11k/cfr.c
index f5cc250..00230e0 100644
--- a/drivers/net/wireless/ath/ath11k/cfr.c
+++ b/drivers/net/wireless/ath/ath11k/cfr.c
@@ -14,6 +14,32 @@ static int ath11k_cfr_process_data(struct ath11k *ar,
return 0;
}
+static struct dentry *create_buf_file_handler(const char *filename,
+ struct dentry *parent,
+ umode_t mode,
+ struct rchan_buf *buf,
+ int *is_global)
+{
+ struct dentry *buf_file;
+
+ buf_file = debugfs_create_file(filename, mode, parent, buf,
+ &relay_file_operations);
+ *is_global = 1;
+ return buf_file;
+}
+
+static int remove_buf_file_handler(struct dentry *dentry)
+{
+ debugfs_remove(dentry);
+
+ return 0;
+}
+
+static const struct rchan_callbacks rfs_cfr_capture_cb = {
+ .create_buf_file = create_buf_file_handler,
+ .remove_buf_file = remove_buf_file_handler,
+};
+
void ath11k_cfr_lut_update_paddr(struct ath11k *ar, dma_addr_t paddr,
u32 buf_id)
{
@@ -87,6 +113,11 @@ void ath11k_cfr_deinit(struct ath11k_base *ab)
ar = ab->pdevs[i].ar;
cfr = &ar->cfr;
+ if (ar->cfr.rfs_cfr_capture) {
+ relay_close(ar->cfr.rfs_cfr_capture);
+ ar->cfr.rfs_cfr_capture = NULL;
+ }
+
ath11k_cfr_ring_free(ar);
spin_lock_bh(&cfr->lut_lock);
@@ -151,6 +182,18 @@ int ath11k_cfr_init(struct ath11k_base *ab)
}
ar->cfr_enabled = true;
+
+ ar->cfr.rfs_cfr_capture =
+ relay_open("cfr_capture",
+ ar->debug.debugfs_pdev,
+ ar->ab->hw_params.cfr_stream_buf_size,
+ ar->ab->hw_params.cfr_num_stream_bufs,
+ &rfs_cfr_capture_cb, NULL);
+ if (!ar->cfr.rfs_cfr_capture) {
+ ath11k_warn(ar->ab, "failed to open relay for cfr in pdev %d\n",
+ ar->pdev_idx);
+ return -EINVAL;
+ }
}
return 0;
diff --git a/drivers/net/wireless/ath/ath11k/cfr.h b/drivers/net/wireless/ath/ath11k/cfr.h
index c050f03..f39b82c 100644
--- a/drivers/net/wireless/ath/ath11k/cfr.h
+++ b/drivers/net/wireless/ath/ath11k/cfr.h
@@ -46,6 +46,7 @@ struct ath11k_cfr {
struct ath11k_dbring rx_ring;
/* Protects cfr data */
spinlock_t lock;
+ struct rchan *rfs_cfr_capture;
struct ath11k_look_up_table *lut;
u32 lut_num;
u32 dbr_buf_size;
--
2.7.4