Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: BSD-3-Clause-Clear
0002 /*
0003  * Copyright (c) 2019-2020 The Linux Foundation. All rights reserved.
0004  */
0005 
0006 #include <linux/relay.h>
0007 #include "core.h"
0008 #include "debug.h"
0009 
0010 #define ATH11K_SPECTRAL_NUM_RESP_PER_EVENT  2
0011 #define ATH11K_SPECTRAL_EVENT_TIMEOUT_MS    1
0012 
0013 #define ATH11K_SPECTRAL_DWORD_SIZE      4
0014 #define ATH11K_SPECTRAL_MIN_BINS        32
0015 #define ATH11K_SPECTRAL_MIN_IB_BINS     (ATH11K_SPECTRAL_MIN_BINS >> 1)
0016 #define ATH11K_SPECTRAL_MAX_IB_BINS(x)  ((x)->hw_params.spectral.max_fft_bins >> 1)
0017 
0018 #define ATH11K_SPECTRAL_SCAN_COUNT_MAX      4095
0019 
0020 /* Max channel computed by sum of 2g and 5g band channels */
0021 #define ATH11K_SPECTRAL_TOTAL_CHANNEL       41
0022 #define ATH11K_SPECTRAL_SAMPLES_PER_CHANNEL 70
0023 #define ATH11K_SPECTRAL_PER_SAMPLE_SIZE(x)  (sizeof(struct fft_sample_ath11k) + \
0024                          ATH11K_SPECTRAL_MAX_IB_BINS(x))
0025 #define ATH11K_SPECTRAL_TOTAL_SAMPLE        (ATH11K_SPECTRAL_TOTAL_CHANNEL * \
0026                          ATH11K_SPECTRAL_SAMPLES_PER_CHANNEL)
0027 #define ATH11K_SPECTRAL_SUB_BUFF_SIZE(x)    ATH11K_SPECTRAL_PER_SAMPLE_SIZE(x)
0028 #define ATH11K_SPECTRAL_NUM_SUB_BUF     ATH11K_SPECTRAL_TOTAL_SAMPLE
0029 
0030 #define ATH11K_SPECTRAL_20MHZ           20
0031 #define ATH11K_SPECTRAL_40MHZ           40
0032 #define ATH11K_SPECTRAL_80MHZ           80
0033 
0034 #define ATH11K_SPECTRAL_SIGNATURE       0xFA
0035 
0036 #define ATH11K_SPECTRAL_TAG_RADAR_SUMMARY   0x0
0037 #define ATH11K_SPECTRAL_TAG_RADAR_FFT       0x1
0038 #define ATH11K_SPECTRAL_TAG_SCAN_SUMMARY    0x2
0039 #define ATH11K_SPECTRAL_TAG_SCAN_SEARCH     0x3
0040 
0041 #define SPECTRAL_TLV_HDR_LEN                GENMASK(15, 0)
0042 #define SPECTRAL_TLV_HDR_TAG                GENMASK(23, 16)
0043 #define SPECTRAL_TLV_HDR_SIGN               GENMASK(31, 24)
0044 
0045 #define SPECTRAL_SUMMARY_INFO0_AGC_TOTAL_GAIN       GENMASK(7, 0)
0046 #define SPECTRAL_SUMMARY_INFO0_OB_FLAG          BIT(8)
0047 #define SPECTRAL_SUMMARY_INFO0_GRP_IDX          GENMASK(16, 9)
0048 #define SPECTRAL_SUMMARY_INFO0_RECENT_RFSAT     BIT(17)
0049 #define SPECTRAL_SUMMARY_INFO0_INBAND_PWR_DB        GENMASK(27, 18)
0050 #define SPECTRAL_SUMMARY_INFO0_FALSE_SCAN       BIT(28)
0051 #define SPECTRAL_SUMMARY_INFO0_DETECTOR_ID      GENMASK(30, 29)
0052 #define SPECTRAL_SUMMARY_INFO0_PRI80            BIT(31)
0053 
0054 #define SPECTRAL_SUMMARY_INFO2_PEAK_SIGNED_IDX      GENMASK(11, 0)
0055 #define SPECTRAL_SUMMARY_INFO2_PEAK_MAGNITUDE       GENMASK(21, 12)
0056 #define SPECTRAL_SUMMARY_INFO2_NARROWBAND_MASK      GENMASK(29, 22)
0057 #define SPECTRAL_SUMMARY_INFO2_GAIN_CHANGE      BIT(30)
0058 
0059 struct spectral_tlv {
0060     __le32 timestamp;
0061     __le32 header;
0062 } __packed;
0063 
0064 struct spectral_summary_fft_report {
0065     __le32 timestamp;
0066     __le32 tlv_header;
0067     __le32 info0;
0068     __le32 reserve0;
0069     __le32 info2;
0070     __le32 reserve1;
0071 } __packed;
0072 
0073 struct ath11k_spectral_summary_report {
0074     struct wmi_dma_buf_release_meta_data meta;
0075     u32 timestamp;
0076     u8 agc_total_gain;
0077     u8 grp_idx;
0078     u16 inb_pwr_db;
0079     s16 peak_idx;
0080     u16 peak_mag;
0081     u8 detector_id;
0082     bool out_of_band_flag;
0083     bool rf_saturation;
0084     bool primary80;
0085     bool gain_change;
0086     bool false_scan;
0087 };
0088 
0089 #define SPECTRAL_FFT_REPORT_INFO0_DETECTOR_ID       GENMASK(1, 0)
0090 #define SPECTRAL_FFT_REPORT_INFO0_FFT_NUM       GENMASK(4, 2)
0091 #define SPECTRAL_FFT_REPORT_INFO0_RADAR_CHECK       GENMASK(16, 5)
0092 #define SPECTRAL_FFT_REPORT_INFO0_PEAK_SIGNED_IDX   GENMASK(27, 17)
0093 #define SPECTRAL_FFT_REPORT_INFO0_CHAIN_IDX     GENMASK(30, 28)
0094 
0095 #define SPECTRAL_FFT_REPORT_INFO1_BASE_PWR_DB       GENMASK(8, 0)
0096 #define SPECTRAL_FFT_REPORT_INFO1_TOTAL_GAIN_DB     GENMASK(16, 9)
0097 
0098 #define SPECTRAL_FFT_REPORT_INFO2_NUM_STRONG_BINS   GENMASK(7, 0)
0099 #define SPECTRAL_FFT_REPORT_INFO2_PEAK_MAGNITUDE    GENMASK(17, 8)
0100 #define SPECTRAL_FFT_REPORT_INFO2_AVG_PWR_DB        GENMASK(24, 18)
0101 #define SPECTRAL_FFT_REPORT_INFO2_REL_PWR_DB        GENMASK(31, 25)
0102 
0103 struct spectral_search_fft_report {
0104     __le32 timestamp;
0105     __le32 tlv_header;
0106     __le32 info0;
0107     __le32 info1;
0108     __le32 info2;
0109     __le32 reserve0;
0110     u8 bins[];
0111 } __packed;
0112 
0113 struct ath11k_spectral_search_report {
0114     u32 timestamp;
0115     u8 detector_id;
0116     u8 fft_count;
0117     u16 radar_check;
0118     s16 peak_idx;
0119     u8 chain_idx;
0120     u16 base_pwr_db;
0121     u8 total_gain_db;
0122     u8 strong_bin_count;
0123     u16 peak_mag;
0124     u8 avg_pwr_db;
0125     u8 rel_pwr_db;
0126 };
0127 
0128 static struct dentry *create_buf_file_handler(const char *filename,
0129                           struct dentry *parent,
0130                           umode_t mode,
0131                           struct rchan_buf *buf,
0132                           int *is_global)
0133 {
0134     struct dentry *buf_file;
0135 
0136     buf_file = debugfs_create_file(filename, mode, parent, buf,
0137                        &relay_file_operations);
0138     *is_global = 1;
0139     return buf_file;
0140 }
0141 
0142 static int remove_buf_file_handler(struct dentry *dentry)
0143 {
0144     debugfs_remove(dentry);
0145 
0146     return 0;
0147 }
0148 
0149 static const struct rchan_callbacks rfs_scan_cb = {
0150     .create_buf_file = create_buf_file_handler,
0151     .remove_buf_file = remove_buf_file_handler,
0152 };
0153 
0154 static struct ath11k_vif *ath11k_spectral_get_vdev(struct ath11k *ar)
0155 {
0156     struct ath11k_vif *arvif;
0157 
0158     lockdep_assert_held(&ar->conf_mutex);
0159 
0160     if (list_empty(&ar->arvifs))
0161         return NULL;
0162 
0163     /* if there already is a vif doing spectral, return that. */
0164     list_for_each_entry(arvif, &ar->arvifs, list)
0165         if (arvif->spectral_enabled)
0166             return arvif;
0167 
0168     /* otherwise, return the first vif. */
0169     return list_first_entry(&ar->arvifs, typeof(*arvif), list);
0170 }
0171 
0172 static int ath11k_spectral_scan_trigger(struct ath11k *ar)
0173 {
0174     struct ath11k_vif *arvif;
0175     int ret;
0176 
0177     lockdep_assert_held(&ar->conf_mutex);
0178 
0179     arvif = ath11k_spectral_get_vdev(ar);
0180     if (!arvif)
0181         return -ENODEV;
0182 
0183     if (ar->spectral.mode == ATH11K_SPECTRAL_DISABLED)
0184         return 0;
0185 
0186     ret = ath11k_wmi_vdev_spectral_enable(ar, arvif->vdev_id,
0187                           ATH11K_WMI_SPECTRAL_TRIGGER_CMD_CLEAR,
0188                           ATH11K_WMI_SPECTRAL_ENABLE_CMD_ENABLE);
0189     if (ret)
0190         return ret;
0191 
0192     ret = ath11k_wmi_vdev_spectral_enable(ar, arvif->vdev_id,
0193                           ATH11K_WMI_SPECTRAL_TRIGGER_CMD_TRIGGER,
0194                           ATH11K_WMI_SPECTRAL_ENABLE_CMD_ENABLE);
0195     if (ret)
0196         return ret;
0197 
0198     return 0;
0199 }
0200 
0201 static int ath11k_spectral_scan_config(struct ath11k *ar,
0202                        enum ath11k_spectral_mode mode)
0203 {
0204     struct ath11k_wmi_vdev_spectral_conf_param param = { 0 };
0205     struct ath11k_vif *arvif;
0206     int ret, count;
0207 
0208     lockdep_assert_held(&ar->conf_mutex);
0209 
0210     arvif = ath11k_spectral_get_vdev(ar);
0211     if (!arvif)
0212         return -ENODEV;
0213 
0214     arvif->spectral_enabled = (mode != ATH11K_SPECTRAL_DISABLED);
0215 
0216     spin_lock_bh(&ar->spectral.lock);
0217     ar->spectral.mode = mode;
0218     spin_unlock_bh(&ar->spectral.lock);
0219 
0220     ret = ath11k_wmi_vdev_spectral_enable(ar, arvif->vdev_id,
0221                           ATH11K_WMI_SPECTRAL_TRIGGER_CMD_CLEAR,
0222                           ATH11K_WMI_SPECTRAL_ENABLE_CMD_DISABLE);
0223     if (ret) {
0224         ath11k_warn(ar->ab, "failed to enable spectral scan: %d\n", ret);
0225         return ret;
0226     }
0227 
0228     if (mode == ATH11K_SPECTRAL_DISABLED)
0229         return 0;
0230 
0231     if (mode == ATH11K_SPECTRAL_BACKGROUND)
0232         count = ATH11K_WMI_SPECTRAL_COUNT_DEFAULT;
0233     else
0234         count = max_t(u16, 1, ar->spectral.count);
0235 
0236     param.vdev_id = arvif->vdev_id;
0237     param.scan_count = count;
0238     param.scan_fft_size = ar->spectral.fft_size;
0239     param.scan_period = ATH11K_WMI_SPECTRAL_PERIOD_DEFAULT;
0240     param.scan_priority = ATH11K_WMI_SPECTRAL_PRIORITY_DEFAULT;
0241     param.scan_gc_ena = ATH11K_WMI_SPECTRAL_GC_ENA_DEFAULT;
0242     param.scan_restart_ena = ATH11K_WMI_SPECTRAL_RESTART_ENA_DEFAULT;
0243     param.scan_noise_floor_ref = ATH11K_WMI_SPECTRAL_NOISE_FLOOR_REF_DEFAULT;
0244     param.scan_init_delay = ATH11K_WMI_SPECTRAL_INIT_DELAY_DEFAULT;
0245     param.scan_nb_tone_thr = ATH11K_WMI_SPECTRAL_NB_TONE_THR_DEFAULT;
0246     param.scan_str_bin_thr = ATH11K_WMI_SPECTRAL_STR_BIN_THR_DEFAULT;
0247     param.scan_wb_rpt_mode = ATH11K_WMI_SPECTRAL_WB_RPT_MODE_DEFAULT;
0248     param.scan_rssi_rpt_mode = ATH11K_WMI_SPECTRAL_RSSI_RPT_MODE_DEFAULT;
0249     param.scan_rssi_thr = ATH11K_WMI_SPECTRAL_RSSI_THR_DEFAULT;
0250     param.scan_pwr_format = ATH11K_WMI_SPECTRAL_PWR_FORMAT_DEFAULT;
0251     param.scan_rpt_mode = ATH11K_WMI_SPECTRAL_RPT_MODE_DEFAULT;
0252     param.scan_bin_scale = ATH11K_WMI_SPECTRAL_BIN_SCALE_DEFAULT;
0253     param.scan_dbm_adj = ATH11K_WMI_SPECTRAL_DBM_ADJ_DEFAULT;
0254     param.scan_chn_mask = ATH11K_WMI_SPECTRAL_CHN_MASK_DEFAULT;
0255 
0256     ret = ath11k_wmi_vdev_spectral_conf(ar, &param);
0257     if (ret) {
0258         ath11k_warn(ar->ab, "failed to configure spectral scan: %d\n", ret);
0259         return ret;
0260     }
0261 
0262     return 0;
0263 }
0264 
0265 static ssize_t ath11k_read_file_spec_scan_ctl(struct file *file,
0266                           char __user *user_buf,
0267                           size_t count, loff_t *ppos)
0268 {
0269     struct ath11k *ar = file->private_data;
0270     char *mode = "";
0271     size_t len;
0272     enum ath11k_spectral_mode spectral_mode;
0273 
0274     mutex_lock(&ar->conf_mutex);
0275     spectral_mode = ar->spectral.mode;
0276     mutex_unlock(&ar->conf_mutex);
0277 
0278     switch (spectral_mode) {
0279     case ATH11K_SPECTRAL_DISABLED:
0280         mode = "disable";
0281         break;
0282     case ATH11K_SPECTRAL_BACKGROUND:
0283         mode = "background";
0284         break;
0285     case ATH11K_SPECTRAL_MANUAL:
0286         mode = "manual";
0287         break;
0288     }
0289 
0290     len = strlen(mode);
0291     return simple_read_from_buffer(user_buf, count, ppos, mode, len);
0292 }
0293 
0294 static ssize_t ath11k_write_file_spec_scan_ctl(struct file *file,
0295                            const char __user *user_buf,
0296                            size_t count, loff_t *ppos)
0297 {
0298     struct ath11k *ar = file->private_data;
0299     char buf[32];
0300     ssize_t len;
0301     int ret;
0302 
0303     len = min(count, sizeof(buf) - 1);
0304     if (copy_from_user(buf, user_buf, len))
0305         return -EFAULT;
0306 
0307     buf[len] = '\0';
0308 
0309     mutex_lock(&ar->conf_mutex);
0310 
0311     if (strncmp("trigger", buf, 7) == 0) {
0312         if (ar->spectral.mode == ATH11K_SPECTRAL_MANUAL ||
0313             ar->spectral.mode == ATH11K_SPECTRAL_BACKGROUND) {
0314             /* reset the configuration to adopt possibly changed
0315              * debugfs parameters
0316              */
0317             ret = ath11k_spectral_scan_config(ar, ar->spectral.mode);
0318             if (ret) {
0319                 ath11k_warn(ar->ab, "failed to reconfigure spectral scan: %d\n",
0320                         ret);
0321                 goto unlock;
0322             }
0323 
0324             ret = ath11k_spectral_scan_trigger(ar);
0325             if (ret) {
0326                 ath11k_warn(ar->ab, "failed to trigger spectral scan: %d\n",
0327                         ret);
0328             }
0329         } else {
0330             ret = -EINVAL;
0331         }
0332     } else if (strncmp("background", buf, 10) == 0) {
0333         ret = ath11k_spectral_scan_config(ar, ATH11K_SPECTRAL_BACKGROUND);
0334     } else if (strncmp("manual", buf, 6) == 0) {
0335         ret = ath11k_spectral_scan_config(ar, ATH11K_SPECTRAL_MANUAL);
0336     } else if (strncmp("disable", buf, 7) == 0) {
0337         ret = ath11k_spectral_scan_config(ar, ATH11K_SPECTRAL_DISABLED);
0338     } else {
0339         ret = -EINVAL;
0340     }
0341 
0342 unlock:
0343     mutex_unlock(&ar->conf_mutex);
0344 
0345     if (ret)
0346         return ret;
0347 
0348     return count;
0349 }
0350 
0351 static const struct file_operations fops_scan_ctl = {
0352     .read = ath11k_read_file_spec_scan_ctl,
0353     .write = ath11k_write_file_spec_scan_ctl,
0354     .open = simple_open,
0355     .owner = THIS_MODULE,
0356     .llseek = default_llseek,
0357 };
0358 
0359 static ssize_t ath11k_read_file_spectral_count(struct file *file,
0360                            char __user *user_buf,
0361                            size_t count, loff_t *ppos)
0362 {
0363     struct ath11k *ar = file->private_data;
0364     char buf[32];
0365     size_t len;
0366     u16 spectral_count;
0367 
0368     mutex_lock(&ar->conf_mutex);
0369     spectral_count = ar->spectral.count;
0370     mutex_unlock(&ar->conf_mutex);
0371 
0372     len = sprintf(buf, "%d\n", spectral_count);
0373     return simple_read_from_buffer(user_buf, count, ppos, buf, len);
0374 }
0375 
0376 static ssize_t ath11k_write_file_spectral_count(struct file *file,
0377                         const char __user *user_buf,
0378                         size_t count, loff_t *ppos)
0379 {
0380     struct ath11k *ar = file->private_data;
0381     unsigned long val;
0382     char buf[32];
0383     ssize_t len;
0384 
0385     len = min(count, sizeof(buf) - 1);
0386     if (copy_from_user(buf, user_buf, len))
0387         return -EFAULT;
0388 
0389     buf[len] = '\0';
0390     if (kstrtoul(buf, 0, &val))
0391         return -EINVAL;
0392 
0393     if (val > ATH11K_SPECTRAL_SCAN_COUNT_MAX)
0394         return -EINVAL;
0395 
0396     mutex_lock(&ar->conf_mutex);
0397     ar->spectral.count = val;
0398     mutex_unlock(&ar->conf_mutex);
0399 
0400     return count;
0401 }
0402 
0403 static const struct file_operations fops_scan_count = {
0404     .read = ath11k_read_file_spectral_count,
0405     .write = ath11k_write_file_spectral_count,
0406     .open = simple_open,
0407     .owner = THIS_MODULE,
0408     .llseek = default_llseek,
0409 };
0410 
0411 static ssize_t ath11k_read_file_spectral_bins(struct file *file,
0412                           char __user *user_buf,
0413                           size_t count, loff_t *ppos)
0414 {
0415     struct ath11k *ar = file->private_data;
0416     char buf[32];
0417     unsigned int bins, fft_size;
0418     size_t len;
0419 
0420     mutex_lock(&ar->conf_mutex);
0421 
0422     fft_size = ar->spectral.fft_size;
0423     bins = 1 << fft_size;
0424 
0425     mutex_unlock(&ar->conf_mutex);
0426 
0427     len = sprintf(buf, "%d\n", bins);
0428     return simple_read_from_buffer(user_buf, count, ppos, buf, len);
0429 }
0430 
0431 static ssize_t ath11k_write_file_spectral_bins(struct file *file,
0432                            const char __user *user_buf,
0433                            size_t count, loff_t *ppos)
0434 {
0435     struct ath11k *ar = file->private_data;
0436     unsigned long val;
0437     char buf[32];
0438     ssize_t len;
0439 
0440     len = min(count, sizeof(buf) - 1);
0441     if (copy_from_user(buf, user_buf, len))
0442         return -EFAULT;
0443 
0444     buf[len] = '\0';
0445     if (kstrtoul(buf, 0, &val))
0446         return -EINVAL;
0447 
0448     if (val < ATH11K_SPECTRAL_MIN_BINS ||
0449         val > ar->ab->hw_params.spectral.max_fft_bins)
0450         return -EINVAL;
0451 
0452     if (!is_power_of_2(val))
0453         return -EINVAL;
0454 
0455     mutex_lock(&ar->conf_mutex);
0456     ar->spectral.fft_size = ilog2(val);
0457     mutex_unlock(&ar->conf_mutex);
0458 
0459     return count;
0460 }
0461 
0462 static const struct file_operations fops_scan_bins = {
0463     .read = ath11k_read_file_spectral_bins,
0464     .write = ath11k_write_file_spectral_bins,
0465     .open = simple_open,
0466     .owner = THIS_MODULE,
0467     .llseek = default_llseek,
0468 };
0469 
0470 static int ath11k_spectral_pull_summary(struct ath11k *ar,
0471                     struct wmi_dma_buf_release_meta_data *meta,
0472                     struct spectral_summary_fft_report *summary,
0473                     struct ath11k_spectral_summary_report *report)
0474 {
0475     report->timestamp = __le32_to_cpu(summary->timestamp);
0476     report->agc_total_gain = FIELD_GET(SPECTRAL_SUMMARY_INFO0_AGC_TOTAL_GAIN,
0477                        __le32_to_cpu(summary->info0));
0478     report->out_of_band_flag = FIELD_GET(SPECTRAL_SUMMARY_INFO0_OB_FLAG,
0479                          __le32_to_cpu(summary->info0));
0480     report->grp_idx = FIELD_GET(SPECTRAL_SUMMARY_INFO0_GRP_IDX,
0481                     __le32_to_cpu(summary->info0));
0482     report->rf_saturation = FIELD_GET(SPECTRAL_SUMMARY_INFO0_RECENT_RFSAT,
0483                       __le32_to_cpu(summary->info0));
0484     report->inb_pwr_db = FIELD_GET(SPECTRAL_SUMMARY_INFO0_INBAND_PWR_DB,
0485                        __le32_to_cpu(summary->info0));
0486     report->false_scan = FIELD_GET(SPECTRAL_SUMMARY_INFO0_FALSE_SCAN,
0487                        __le32_to_cpu(summary->info0));
0488     report->detector_id = FIELD_GET(SPECTRAL_SUMMARY_INFO0_DETECTOR_ID,
0489                     __le32_to_cpu(summary->info0));
0490     report->primary80 = FIELD_GET(SPECTRAL_SUMMARY_INFO0_PRI80,
0491                       __le32_to_cpu(summary->info0));
0492     report->peak_idx = FIELD_GET(SPECTRAL_SUMMARY_INFO2_PEAK_SIGNED_IDX,
0493                      __le32_to_cpu(summary->info2));
0494     report->peak_mag = FIELD_GET(SPECTRAL_SUMMARY_INFO2_PEAK_MAGNITUDE,
0495                      __le32_to_cpu(summary->info2));
0496     report->gain_change = FIELD_GET(SPECTRAL_SUMMARY_INFO2_GAIN_CHANGE,
0497                     __le32_to_cpu(summary->info2));
0498 
0499     memcpy(&report->meta, meta, sizeof(*meta));
0500 
0501     return 0;
0502 }
0503 
0504 static int ath11k_spectral_pull_search(struct ath11k *ar,
0505                        struct spectral_search_fft_report *search,
0506                        struct ath11k_spectral_search_report *report)
0507 {
0508     report->timestamp = __le32_to_cpu(search->timestamp);
0509     report->detector_id = FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_DETECTOR_ID,
0510                     __le32_to_cpu(search->info0));
0511     report->fft_count = FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_FFT_NUM,
0512                       __le32_to_cpu(search->info0));
0513     report->radar_check = FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_RADAR_CHECK,
0514                     __le32_to_cpu(search->info0));
0515     report->peak_idx = FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_PEAK_SIGNED_IDX,
0516                      __le32_to_cpu(search->info0));
0517     report->chain_idx = FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_CHAIN_IDX,
0518                       __le32_to_cpu(search->info0));
0519     report->base_pwr_db = FIELD_GET(SPECTRAL_FFT_REPORT_INFO1_BASE_PWR_DB,
0520                     __le32_to_cpu(search->info1));
0521     report->total_gain_db = FIELD_GET(SPECTRAL_FFT_REPORT_INFO1_TOTAL_GAIN_DB,
0522                       __le32_to_cpu(search->info1));
0523     report->strong_bin_count = FIELD_GET(SPECTRAL_FFT_REPORT_INFO2_NUM_STRONG_BINS,
0524                          __le32_to_cpu(search->info2));
0525     report->peak_mag = FIELD_GET(SPECTRAL_FFT_REPORT_INFO2_PEAK_MAGNITUDE,
0526                      __le32_to_cpu(search->info2));
0527     report->avg_pwr_db = FIELD_GET(SPECTRAL_FFT_REPORT_INFO2_AVG_PWR_DB,
0528                        __le32_to_cpu(search->info2));
0529     report->rel_pwr_db = FIELD_GET(SPECTRAL_FFT_REPORT_INFO2_REL_PWR_DB,
0530                        __le32_to_cpu(search->info2));
0531 
0532     return 0;
0533 }
0534 
0535 static u8 ath11k_spectral_get_max_exp(s8 max_index, u8 max_magnitude,
0536                       int bin_len, u8 *bins)
0537 {
0538     int dc_pos;
0539     u8 max_exp;
0540 
0541     dc_pos = bin_len / 2;
0542 
0543     /* peak index outside of bins */
0544     if (dc_pos <= max_index || -dc_pos >= max_index)
0545         return 0;
0546 
0547     for (max_exp = 0; max_exp < 8; max_exp++) {
0548         if (bins[dc_pos + max_index] == (max_magnitude >> max_exp))
0549             break;
0550     }
0551 
0552     /* max_exp not found */
0553     if (bins[dc_pos + max_index] != (max_magnitude >> max_exp))
0554         return 0;
0555 
0556     return max_exp;
0557 }
0558 
0559 static void ath11k_spectral_parse_fft(u8 *outbins, u8 *inbins, int num_bins, u8 fft_sz)
0560 {
0561     int i, j;
0562 
0563     i = 0;
0564     j = 0;
0565     while (i < num_bins) {
0566         outbins[i] = inbins[j];
0567         i++;
0568         j += fft_sz;
0569     }
0570 }
0571 
0572 static
0573 int ath11k_spectral_process_fft(struct ath11k *ar,
0574                 struct ath11k_spectral_summary_report *summary,
0575                 void *data,
0576                 struct fft_sample_ath11k *fft_sample,
0577                 u32 data_len)
0578 {
0579     struct ath11k_base *ab = ar->ab;
0580     struct spectral_search_fft_report *fft_report = data;
0581     struct ath11k_spectral_search_report search;
0582     struct spectral_tlv *tlv;
0583     int tlv_len, bin_len, num_bins;
0584     u16 length, freq;
0585     u8 chan_width_mhz, bin_sz;
0586     int ret;
0587     u32 check_length;
0588 
0589     lockdep_assert_held(&ar->spectral.lock);
0590 
0591     if (!ab->hw_params.spectral.fft_sz) {
0592         ath11k_warn(ab, "invalid bin size type for hw rev %d\n",
0593                 ab->hw_rev);
0594         return -EINVAL;
0595     }
0596 
0597     tlv = (struct spectral_tlv *)data;
0598     tlv_len = FIELD_GET(SPECTRAL_TLV_HDR_LEN, __le32_to_cpu(tlv->header));
0599     /* convert Dword into bytes */
0600     tlv_len *= ATH11K_SPECTRAL_DWORD_SIZE;
0601     bin_len = tlv_len - ab->hw_params.spectral.fft_hdr_len;
0602 
0603     if (data_len < (bin_len + sizeof(*fft_report))) {
0604         ath11k_warn(ab, "mismatch in expected bin len %d and data len %d\n",
0605                 bin_len, data_len);
0606         return -EINVAL;
0607     }
0608 
0609     bin_sz = ab->hw_params.spectral.fft_sz + ab->hw_params.spectral.fft_pad_sz;
0610     num_bins = bin_len / bin_sz;
0611     /* Only In-band bins are useful to user for visualize */
0612     num_bins >>= 1;
0613 
0614     if (num_bins < ATH11K_SPECTRAL_MIN_IB_BINS ||
0615         num_bins > ATH11K_SPECTRAL_MAX_IB_BINS(ab) ||
0616         !is_power_of_2(num_bins)) {
0617         ath11k_warn(ab, "Invalid num of bins %d\n", num_bins);
0618         return -EINVAL;
0619     }
0620 
0621     check_length = sizeof(*fft_report) + (num_bins * ab->hw_params.spectral.fft_sz);
0622     ret = ath11k_dbring_validate_buffer(ar, data, check_length);
0623     if (ret) {
0624         ath11k_warn(ar->ab, "found magic value in fft data, dropping\n");
0625         return ret;
0626     }
0627 
0628     ret = ath11k_spectral_pull_search(ar, data, &search);
0629     if (ret) {
0630         ath11k_warn(ab, "failed to pull search report %d\n", ret);
0631         return ret;
0632     }
0633 
0634     chan_width_mhz = summary->meta.ch_width;
0635 
0636     switch (chan_width_mhz) {
0637     case ATH11K_SPECTRAL_20MHZ:
0638     case ATH11K_SPECTRAL_40MHZ:
0639     case ATH11K_SPECTRAL_80MHZ:
0640         fft_sample->chan_width_mhz = chan_width_mhz;
0641         break;
0642     default:
0643         ath11k_warn(ab, "invalid channel width %d\n", chan_width_mhz);
0644         return -EINVAL;
0645     }
0646 
0647     length = sizeof(*fft_sample) - sizeof(struct fft_sample_tlv) + num_bins;
0648     fft_sample->tlv.type = ATH_FFT_SAMPLE_ATH11K;
0649     fft_sample->tlv.length = __cpu_to_be16(length);
0650 
0651     fft_sample->tsf = __cpu_to_be32(search.timestamp);
0652     fft_sample->max_magnitude = __cpu_to_be16(search.peak_mag);
0653     fft_sample->max_index = FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_PEAK_SIGNED_IDX,
0654                       __le32_to_cpu(fft_report->info0));
0655 
0656     summary->inb_pwr_db >>= 1;
0657     fft_sample->rssi = __cpu_to_be16(summary->inb_pwr_db);
0658     fft_sample->noise = __cpu_to_be32(summary->meta.noise_floor[search.chain_idx]);
0659 
0660     freq = summary->meta.freq1;
0661     fft_sample->freq1 = __cpu_to_be16(freq);
0662 
0663     freq = summary->meta.freq2;
0664     fft_sample->freq2 = __cpu_to_be16(freq);
0665 
0666     ath11k_spectral_parse_fft(fft_sample->data, fft_report->bins, num_bins,
0667                   ab->hw_params.spectral.fft_sz);
0668 
0669     fft_sample->max_exp = ath11k_spectral_get_max_exp(fft_sample->max_index,
0670                               search.peak_mag,
0671                               num_bins,
0672                               fft_sample->data);
0673 
0674     if (ar->spectral.rfs_scan)
0675         relay_write(ar->spectral.rfs_scan, fft_sample,
0676                 length + sizeof(struct fft_sample_tlv));
0677 
0678     return 0;
0679 }
0680 
0681 static int ath11k_spectral_process_data(struct ath11k *ar,
0682                     struct ath11k_dbring_data *param)
0683 {
0684     struct ath11k_base *ab = ar->ab;
0685     struct spectral_tlv *tlv;
0686     struct spectral_summary_fft_report *summary = NULL;
0687     struct ath11k_spectral_summary_report summ_rpt;
0688     struct fft_sample_ath11k *fft_sample = NULL;
0689     u8 *data;
0690     u32 data_len, i;
0691     u8 sign, tag;
0692     int tlv_len, sample_sz;
0693     int ret;
0694     bool quit = false;
0695 
0696     spin_lock_bh(&ar->spectral.lock);
0697 
0698     if (!ar->spectral.enabled) {
0699         ret = -EINVAL;
0700         goto unlock;
0701     }
0702 
0703     sample_sz = sizeof(*fft_sample) + ATH11K_SPECTRAL_MAX_IB_BINS(ab);
0704     fft_sample = kmalloc(sample_sz, GFP_ATOMIC);
0705     if (!fft_sample) {
0706         ret = -ENOBUFS;
0707         goto unlock;
0708     }
0709 
0710     data = param->data;
0711     data_len = param->data_sz;
0712     i = 0;
0713     while (!quit && (i < data_len)) {
0714         if ((i + sizeof(*tlv)) > data_len) {
0715             ath11k_warn(ab, "failed to parse spectral tlv hdr at bytes %d\n",
0716                     i);
0717             ret = -EINVAL;
0718             goto err;
0719         }
0720 
0721         tlv = (struct spectral_tlv *)&data[i];
0722         sign = FIELD_GET(SPECTRAL_TLV_HDR_SIGN,
0723                  __le32_to_cpu(tlv->header));
0724         if (sign != ATH11K_SPECTRAL_SIGNATURE) {
0725             ath11k_warn(ab, "Invalid sign 0x%x at bytes %d\n",
0726                     sign, i);
0727             ret = -EINVAL;
0728             goto err;
0729         }
0730 
0731         tlv_len = FIELD_GET(SPECTRAL_TLV_HDR_LEN,
0732                     __le32_to_cpu(tlv->header));
0733         /* convert Dword into bytes */
0734         tlv_len *= ATH11K_SPECTRAL_DWORD_SIZE;
0735         if ((i + sizeof(*tlv) + tlv_len) > data_len) {
0736             ath11k_warn(ab, "failed to parse spectral tlv payload at bytes %d tlv_len:%d data_len:%d\n",
0737                     i, tlv_len, data_len);
0738             ret = -EINVAL;
0739             goto err;
0740         }
0741 
0742         tag = FIELD_GET(SPECTRAL_TLV_HDR_TAG,
0743                 __le32_to_cpu(tlv->header));
0744         switch (tag) {
0745         case ATH11K_SPECTRAL_TAG_SCAN_SUMMARY:
0746             /* HW bug in tlv length of summary report,
0747              * HW report 3 DWORD size but the data payload
0748              * is 4 DWORD size (16 bytes).
0749              * Need to remove this workaround once HW bug fixed
0750              */
0751             tlv_len = sizeof(*summary) - sizeof(*tlv) +
0752                   ab->hw_params.spectral.summary_pad_sz;
0753 
0754             if (tlv_len < (sizeof(*summary) - sizeof(*tlv))) {
0755                 ath11k_warn(ab, "failed to parse spectral summary at bytes %d tlv_len:%d\n",
0756                         i, tlv_len);
0757                 ret = -EINVAL;
0758                 goto err;
0759             }
0760 
0761             ret = ath11k_dbring_validate_buffer(ar, data, tlv_len);
0762             if (ret) {
0763                 ath11k_warn(ar->ab, "found magic value in spectral summary, dropping\n");
0764                 goto err;
0765             }
0766 
0767             summary = (struct spectral_summary_fft_report *)tlv;
0768             ath11k_spectral_pull_summary(ar, &param->meta,
0769                              summary, &summ_rpt);
0770             break;
0771         case ATH11K_SPECTRAL_TAG_SCAN_SEARCH:
0772             if (tlv_len < (sizeof(struct spectral_search_fft_report) -
0773                        sizeof(*tlv))) {
0774                 ath11k_warn(ab, "failed to parse spectral search fft at bytes %d\n",
0775                         i);
0776                 ret = -EINVAL;
0777                 goto err;
0778             }
0779 
0780             memset(fft_sample, 0, sample_sz);
0781             ret = ath11k_spectral_process_fft(ar, &summ_rpt, tlv,
0782                               fft_sample,
0783                               data_len - i);
0784             if (ret) {
0785                 ath11k_warn(ab, "failed to process spectral fft at bytes %d\n",
0786                         i);
0787                 goto err;
0788             }
0789             quit = true;
0790             break;
0791         }
0792 
0793         i += sizeof(*tlv) + tlv_len;
0794     }
0795 
0796     ret = 0;
0797 
0798 err:
0799     kfree(fft_sample);
0800 unlock:
0801     spin_unlock_bh(&ar->spectral.lock);
0802     return ret;
0803 }
0804 
0805 static int ath11k_spectral_ring_alloc(struct ath11k *ar,
0806                       struct ath11k_dbring_cap *db_cap)
0807 {
0808     struct ath11k_spectral *sp = &ar->spectral;
0809     int ret;
0810 
0811     ret = ath11k_dbring_srng_setup(ar, &sp->rx_ring,
0812                        0, db_cap->min_elem);
0813     if (ret) {
0814         ath11k_warn(ar->ab, "failed to setup db ring\n");
0815         return ret;
0816     }
0817 
0818     ath11k_dbring_set_cfg(ar, &sp->rx_ring,
0819                   ATH11K_SPECTRAL_NUM_RESP_PER_EVENT,
0820                   ATH11K_SPECTRAL_EVENT_TIMEOUT_MS,
0821                   ath11k_spectral_process_data);
0822 
0823     ret = ath11k_dbring_buf_setup(ar, &sp->rx_ring, db_cap);
0824     if (ret) {
0825         ath11k_warn(ar->ab, "failed to setup db ring buffer\n");
0826         goto srng_cleanup;
0827     }
0828 
0829     ret = ath11k_dbring_wmi_cfg_setup(ar, &sp->rx_ring,
0830                       WMI_DIRECT_BUF_SPECTRAL);
0831     if (ret) {
0832         ath11k_warn(ar->ab, "failed to setup db ring cfg\n");
0833         goto buffer_cleanup;
0834     }
0835 
0836     return 0;
0837 
0838 buffer_cleanup:
0839     ath11k_dbring_buf_cleanup(ar, &sp->rx_ring);
0840 srng_cleanup:
0841     ath11k_dbring_srng_cleanup(ar, &sp->rx_ring);
0842     return ret;
0843 }
0844 
0845 static inline void ath11k_spectral_ring_free(struct ath11k *ar)
0846 {
0847     struct ath11k_spectral *sp = &ar->spectral;
0848 
0849     ath11k_dbring_srng_cleanup(ar, &sp->rx_ring);
0850     ath11k_dbring_buf_cleanup(ar, &sp->rx_ring);
0851 }
0852 
0853 static inline void ath11k_spectral_debug_unregister(struct ath11k *ar)
0854 {
0855     debugfs_remove(ar->spectral.scan_bins);
0856     ar->spectral.scan_bins = NULL;
0857 
0858     debugfs_remove(ar->spectral.scan_count);
0859     ar->spectral.scan_count = NULL;
0860 
0861     debugfs_remove(ar->spectral.scan_ctl);
0862     ar->spectral.scan_ctl = NULL;
0863 
0864     if (ar->spectral.rfs_scan) {
0865         relay_close(ar->spectral.rfs_scan);
0866         ar->spectral.rfs_scan = NULL;
0867     }
0868 }
0869 
0870 int ath11k_spectral_vif_stop(struct ath11k_vif *arvif)
0871 {
0872     if (!arvif->spectral_enabled)
0873         return 0;
0874 
0875     return ath11k_spectral_scan_config(arvif->ar, ATH11K_SPECTRAL_DISABLED);
0876 }
0877 
0878 void ath11k_spectral_reset_buffer(struct ath11k *ar)
0879 {
0880     if (!ar->spectral.enabled)
0881         return;
0882 
0883     if (ar->spectral.rfs_scan)
0884         relay_reset(ar->spectral.rfs_scan);
0885 }
0886 
0887 void ath11k_spectral_deinit(struct ath11k_base *ab)
0888 {
0889     struct ath11k *ar;
0890     struct ath11k_spectral *sp;
0891     int i;
0892 
0893     for (i = 0; i <  ab->num_radios; i++) {
0894         ar = ab->pdevs[i].ar;
0895         sp = &ar->spectral;
0896 
0897         if (!sp->enabled)
0898             continue;
0899 
0900         mutex_lock(&ar->conf_mutex);
0901         ath11k_spectral_scan_config(ar, ATH11K_SPECTRAL_DISABLED);
0902         mutex_unlock(&ar->conf_mutex);
0903 
0904         spin_lock_bh(&sp->lock);
0905         sp->enabled = false;
0906         spin_unlock_bh(&sp->lock);
0907 
0908         ath11k_spectral_debug_unregister(ar);
0909         ath11k_spectral_ring_free(ar);
0910     }
0911 }
0912 
0913 static inline int ath11k_spectral_debug_register(struct ath11k *ar)
0914 {
0915     int ret;
0916 
0917     ar->spectral.rfs_scan = relay_open("spectral_scan",
0918                        ar->debug.debugfs_pdev,
0919                        ATH11K_SPECTRAL_SUB_BUFF_SIZE(ar->ab),
0920                        ATH11K_SPECTRAL_NUM_SUB_BUF,
0921                        &rfs_scan_cb, NULL);
0922     if (!ar->spectral.rfs_scan) {
0923         ath11k_warn(ar->ab, "failed to open relay in pdev %d\n",
0924                 ar->pdev_idx);
0925         return -EINVAL;
0926     }
0927 
0928     ar->spectral.scan_ctl = debugfs_create_file("spectral_scan_ctl",
0929                             0600,
0930                             ar->debug.debugfs_pdev, ar,
0931                             &fops_scan_ctl);
0932     if (!ar->spectral.scan_ctl) {
0933         ath11k_warn(ar->ab, "failed to open debugfs in pdev %d\n",
0934                 ar->pdev_idx);
0935         ret = -EINVAL;
0936         goto debug_unregister;
0937     }
0938 
0939     ar->spectral.scan_count = debugfs_create_file("spectral_count",
0940                               0600,
0941                               ar->debug.debugfs_pdev, ar,
0942                               &fops_scan_count);
0943     if (!ar->spectral.scan_count) {
0944         ath11k_warn(ar->ab, "failed to open debugfs in pdev %d\n",
0945                 ar->pdev_idx);
0946         ret = -EINVAL;
0947         goto debug_unregister;
0948     }
0949 
0950     ar->spectral.scan_bins = debugfs_create_file("spectral_bins",
0951                              0600,
0952                              ar->debug.debugfs_pdev, ar,
0953                              &fops_scan_bins);
0954     if (!ar->spectral.scan_bins) {
0955         ath11k_warn(ar->ab, "failed to open debugfs in pdev %d\n",
0956                 ar->pdev_idx);
0957         ret = -EINVAL;
0958         goto debug_unregister;
0959     }
0960 
0961     return 0;
0962 
0963 debug_unregister:
0964     ath11k_spectral_debug_unregister(ar);
0965     return ret;
0966 }
0967 
0968 int ath11k_spectral_init(struct ath11k_base *ab)
0969 {
0970     struct ath11k *ar;
0971     struct ath11k_spectral *sp;
0972     struct ath11k_dbring_cap db_cap;
0973     int ret;
0974     int i;
0975 
0976     if (!test_bit(WMI_TLV_SERVICE_FREQINFO_IN_METADATA,
0977               ab->wmi_ab.svc_map))
0978         return 0;
0979 
0980     if (!ab->hw_params.spectral.fft_sz)
0981         return 0;
0982 
0983     for (i = 0; i < ab->num_radios; i++) {
0984         ar = ab->pdevs[i].ar;
0985         sp = &ar->spectral;
0986 
0987         ret = ath11k_dbring_get_cap(ar->ab, ar->pdev_idx,
0988                         WMI_DIRECT_BUF_SPECTRAL,
0989                         &db_cap);
0990         if (ret)
0991             continue;
0992 
0993         idr_init(&sp->rx_ring.bufs_idr);
0994         spin_lock_init(&sp->rx_ring.idr_lock);
0995         spin_lock_init(&sp->lock);
0996 
0997         ret = ath11k_spectral_ring_alloc(ar, &db_cap);
0998         if (ret) {
0999             ath11k_warn(ab, "failed to init spectral ring for pdev %d\n",
1000                     i);
1001             goto deinit;
1002         }
1003 
1004         spin_lock_bh(&sp->lock);
1005 
1006         sp->mode = ATH11K_SPECTRAL_DISABLED;
1007         sp->count = ATH11K_WMI_SPECTRAL_COUNT_DEFAULT;
1008         sp->fft_size = ATH11K_WMI_SPECTRAL_FFT_SIZE_DEFAULT;
1009         sp->enabled = true;
1010 
1011         spin_unlock_bh(&sp->lock);
1012 
1013         ret = ath11k_spectral_debug_register(ar);
1014         if (ret) {
1015             ath11k_warn(ab, "failed to register spectral for pdev %d\n",
1016                     i);
1017             goto deinit;
1018         }
1019     }
1020 
1021     return 0;
1022 
1023 deinit:
1024     ath11k_spectral_deinit(ab);
1025     return ret;
1026 }
1027 
1028 enum ath11k_spectral_mode ath11k_spectral_get_mode(struct ath11k *ar)
1029 {
1030     if (ar->spectral.enabled)
1031         return ar->spectral.mode;
1032     else
1033         return ATH11K_SPECTRAL_DISABLED;
1034 }
1035 
1036 struct ath11k_dbring *ath11k_spectral_get_dbring(struct ath11k *ar)
1037 {
1038     if (ar->spectral.enabled)
1039         return &ar->spectral.rx_ring;
1040     else
1041         return NULL;
1042 }