spectral.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056
  1. // SPDX-License-Identifier: BSD-3-Clause-Clear
  2. /*
  3. * Copyright (c) 2019-2020 The Linux Foundation. All rights reserved.
  4. * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
  5. * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
  6. */
  7. #include <linux/relay.h>
  8. #include "core.h"
  9. #include "debug.h"
  10. #define ATH11K_SPECTRAL_NUM_RESP_PER_EVENT 2
  11. #define ATH11K_SPECTRAL_EVENT_TIMEOUT_MS 1
  12. #define ATH11K_SPECTRAL_DWORD_SIZE 4
  13. #define ATH11K_SPECTRAL_MIN_BINS 32
  14. #define ATH11K_SPECTRAL_MIN_IB_BINS (ATH11K_SPECTRAL_MIN_BINS >> 1)
  15. #define ATH11K_SPECTRAL_MAX_IB_BINS(x) ((x)->hw_params.spectral.max_fft_bins >> 1)
  16. #define ATH11K_SPECTRAL_SCAN_COUNT_MAX 4095
  17. /* Max channel computed by sum of 2g and 5g band channels */
  18. #define ATH11K_SPECTRAL_TOTAL_CHANNEL 41
  19. #define ATH11K_SPECTRAL_SAMPLES_PER_CHANNEL 70
  20. #define ATH11K_SPECTRAL_PER_SAMPLE_SIZE(x) (sizeof(struct fft_sample_ath11k) + \
  21. ATH11K_SPECTRAL_MAX_IB_BINS(x))
  22. #define ATH11K_SPECTRAL_TOTAL_SAMPLE (ATH11K_SPECTRAL_TOTAL_CHANNEL * \
  23. ATH11K_SPECTRAL_SAMPLES_PER_CHANNEL)
  24. #define ATH11K_SPECTRAL_SUB_BUFF_SIZE(x) ATH11K_SPECTRAL_PER_SAMPLE_SIZE(x)
  25. #define ATH11K_SPECTRAL_NUM_SUB_BUF ATH11K_SPECTRAL_TOTAL_SAMPLE
  26. #define ATH11K_SPECTRAL_20MHZ 20
  27. #define ATH11K_SPECTRAL_40MHZ 40
  28. #define ATH11K_SPECTRAL_80MHZ 80
  29. #define ATH11K_SPECTRAL_160MHZ 160
  30. #define ATH11K_SPECTRAL_SIGNATURE 0xFA
  31. #define ATH11K_SPECTRAL_TAG_RADAR_SUMMARY 0x0
  32. #define ATH11K_SPECTRAL_TAG_RADAR_FFT 0x1
  33. #define ATH11K_SPECTRAL_TAG_SCAN_SUMMARY 0x2
  34. #define ATH11K_SPECTRAL_TAG_SCAN_SEARCH 0x3
  35. #define SPECTRAL_TLV_HDR_LEN GENMASK(15, 0)
  36. #define SPECTRAL_TLV_HDR_TAG GENMASK(23, 16)
  37. #define SPECTRAL_TLV_HDR_SIGN GENMASK(31, 24)
  38. #define SPECTRAL_SUMMARY_INFO0_AGC_TOTAL_GAIN GENMASK(7, 0)
  39. #define SPECTRAL_SUMMARY_INFO0_OB_FLAG BIT(8)
  40. #define SPECTRAL_SUMMARY_INFO0_GRP_IDX GENMASK(16, 9)
  41. #define SPECTRAL_SUMMARY_INFO0_RECENT_RFSAT BIT(17)
  42. #define SPECTRAL_SUMMARY_INFO0_INBAND_PWR_DB GENMASK(27, 18)
  43. #define SPECTRAL_SUMMARY_INFO0_FALSE_SCAN BIT(28)
  44. #define SPECTRAL_SUMMARY_INFO0_DETECTOR_ID GENMASK(30, 29)
  45. #define SPECTRAL_SUMMARY_INFO0_PRI80 BIT(31)
  46. #define SPECTRAL_SUMMARY_INFO2_PEAK_SIGNED_IDX GENMASK(11, 0)
  47. #define SPECTRAL_SUMMARY_INFO2_PEAK_MAGNITUDE GENMASK(21, 12)
  48. #define SPECTRAL_SUMMARY_INFO2_NARROWBAND_MASK GENMASK(29, 22)
  49. #define SPECTRAL_SUMMARY_INFO2_GAIN_CHANGE BIT(30)
  50. struct spectral_tlv {
  51. __le32 timestamp;
  52. __le32 header;
  53. } __packed;
  54. struct spectral_summary_fft_report {
  55. __le32 timestamp;
  56. __le32 tlv_header;
  57. __le32 info0;
  58. __le32 reserve0;
  59. __le32 info2;
  60. __le32 reserve1;
  61. } __packed;
  62. struct ath11k_spectral_summary_report {
  63. struct wmi_dma_buf_release_meta_data meta;
  64. u32 timestamp;
  65. u8 agc_total_gain;
  66. u8 grp_idx;
  67. u16 inb_pwr_db;
  68. s16 peak_idx;
  69. u16 peak_mag;
  70. u8 detector_id;
  71. bool out_of_band_flag;
  72. bool rf_saturation;
  73. bool primary80;
  74. bool gain_change;
  75. bool false_scan;
  76. };
  77. #define SPECTRAL_FFT_REPORT_INFO0_DETECTOR_ID GENMASK(1, 0)
  78. #define SPECTRAL_FFT_REPORT_INFO0_FFT_NUM GENMASK(4, 2)
  79. #define SPECTRAL_FFT_REPORT_INFO0_RADAR_CHECK GENMASK(16, 5)
  80. #define SPECTRAL_FFT_REPORT_INFO0_PEAK_SIGNED_IDX GENMASK(27, 17)
  81. #define SPECTRAL_FFT_REPORT_INFO0_CHAIN_IDX GENMASK(30, 28)
  82. #define SPECTRAL_FFT_REPORT_INFO1_BASE_PWR_DB GENMASK(8, 0)
  83. #define SPECTRAL_FFT_REPORT_INFO1_TOTAL_GAIN_DB GENMASK(16, 9)
  84. #define SPECTRAL_FFT_REPORT_INFO2_NUM_STRONG_BINS GENMASK(7, 0)
  85. #define SPECTRAL_FFT_REPORT_INFO2_PEAK_MAGNITUDE GENMASK(17, 8)
  86. #define SPECTRAL_FFT_REPORT_INFO2_AVG_PWR_DB GENMASK(24, 18)
  87. #define SPECTRAL_FFT_REPORT_INFO2_REL_PWR_DB GENMASK(31, 25)
  88. struct spectral_search_fft_report {
  89. __le32 timestamp;
  90. __le32 tlv_header;
  91. __le32 info0;
  92. __le32 info1;
  93. __le32 info2;
  94. __le32 reserve0;
  95. u8 bins[];
  96. } __packed;
  97. struct ath11k_spectral_search_report {
  98. u32 timestamp;
  99. u8 detector_id;
  100. u8 fft_count;
  101. u16 radar_check;
  102. s16 peak_idx;
  103. u8 chain_idx;
  104. u16 base_pwr_db;
  105. u8 total_gain_db;
  106. u8 strong_bin_count;
  107. u16 peak_mag;
  108. u8 avg_pwr_db;
  109. u8 rel_pwr_db;
  110. };
  111. static struct dentry *create_buf_file_handler(const char *filename,
  112. struct dentry *parent,
  113. umode_t mode,
  114. struct rchan_buf *buf,
  115. int *is_global)
  116. {
  117. struct dentry *buf_file;
  118. buf_file = debugfs_create_file(filename, mode, parent, buf,
  119. &relay_file_operations);
  120. *is_global = 1;
  121. return buf_file;
  122. }
  123. static int remove_buf_file_handler(struct dentry *dentry)
  124. {
  125. debugfs_remove(dentry);
  126. return 0;
  127. }
  128. static const struct rchan_callbacks rfs_scan_cb = {
  129. .create_buf_file = create_buf_file_handler,
  130. .remove_buf_file = remove_buf_file_handler,
  131. };
  132. static struct ath11k_vif *ath11k_spectral_get_vdev(struct ath11k *ar)
  133. {
  134. struct ath11k_vif *arvif;
  135. lockdep_assert_held(&ar->conf_mutex);
  136. if (list_empty(&ar->arvifs))
  137. return NULL;
  138. /* if there already is a vif doing spectral, return that. */
  139. list_for_each_entry(arvif, &ar->arvifs, list)
  140. if (arvif->spectral_enabled)
  141. return arvif;
  142. /* otherwise, return the first vif. */
  143. return list_first_entry(&ar->arvifs, typeof(*arvif), list);
  144. }
  145. static int ath11k_spectral_scan_trigger(struct ath11k *ar)
  146. {
  147. struct ath11k_vif *arvif;
  148. int ret;
  149. lockdep_assert_held(&ar->conf_mutex);
  150. arvif = ath11k_spectral_get_vdev(ar);
  151. if (!arvif)
  152. return -ENODEV;
  153. if (ar->spectral.mode == ATH11K_SPECTRAL_DISABLED)
  154. return 0;
  155. ar->spectral.is_primary = true;
  156. ret = ath11k_wmi_vdev_spectral_enable(ar, arvif->vdev_id,
  157. ATH11K_WMI_SPECTRAL_TRIGGER_CMD_CLEAR,
  158. ATH11K_WMI_SPECTRAL_ENABLE_CMD_ENABLE);
  159. if (ret)
  160. return ret;
  161. ret = ath11k_wmi_vdev_spectral_enable(ar, arvif->vdev_id,
  162. ATH11K_WMI_SPECTRAL_TRIGGER_CMD_TRIGGER,
  163. ATH11K_WMI_SPECTRAL_ENABLE_CMD_ENABLE);
  164. if (ret)
  165. return ret;
  166. return 0;
  167. }
  168. static int ath11k_spectral_scan_config(struct ath11k *ar,
  169. enum ath11k_spectral_mode mode)
  170. {
  171. struct ath11k_wmi_vdev_spectral_conf_param param = {};
  172. struct ath11k_vif *arvif;
  173. int ret, count;
  174. lockdep_assert_held(&ar->conf_mutex);
  175. arvif = ath11k_spectral_get_vdev(ar);
  176. if (!arvif)
  177. return -ENODEV;
  178. arvif->spectral_enabled = (mode != ATH11K_SPECTRAL_DISABLED);
  179. spin_lock_bh(&ar->spectral.lock);
  180. ar->spectral.mode = mode;
  181. spin_unlock_bh(&ar->spectral.lock);
  182. ret = ath11k_wmi_vdev_spectral_enable(ar, arvif->vdev_id,
  183. ATH11K_WMI_SPECTRAL_TRIGGER_CMD_CLEAR,
  184. ATH11K_WMI_SPECTRAL_ENABLE_CMD_DISABLE);
  185. if (ret) {
  186. ath11k_warn(ar->ab, "failed to enable spectral scan: %d\n", ret);
  187. return ret;
  188. }
  189. if (mode == ATH11K_SPECTRAL_DISABLED)
  190. return 0;
  191. if (mode == ATH11K_SPECTRAL_BACKGROUND)
  192. count = ATH11K_WMI_SPECTRAL_COUNT_DEFAULT;
  193. else
  194. count = max_t(u16, 1, ar->spectral.count);
  195. param.vdev_id = arvif->vdev_id;
  196. param.scan_count = count;
  197. param.scan_fft_size = ar->spectral.fft_size;
  198. param.scan_period = ATH11K_WMI_SPECTRAL_PERIOD_DEFAULT;
  199. param.scan_priority = ATH11K_WMI_SPECTRAL_PRIORITY_DEFAULT;
  200. param.scan_gc_ena = ATH11K_WMI_SPECTRAL_GC_ENA_DEFAULT;
  201. param.scan_restart_ena = ATH11K_WMI_SPECTRAL_RESTART_ENA_DEFAULT;
  202. param.scan_noise_floor_ref = ATH11K_WMI_SPECTRAL_NOISE_FLOOR_REF_DEFAULT;
  203. param.scan_init_delay = ATH11K_WMI_SPECTRAL_INIT_DELAY_DEFAULT;
  204. param.scan_nb_tone_thr = ATH11K_WMI_SPECTRAL_NB_TONE_THR_DEFAULT;
  205. param.scan_str_bin_thr = ATH11K_WMI_SPECTRAL_STR_BIN_THR_DEFAULT;
  206. param.scan_wb_rpt_mode = ATH11K_WMI_SPECTRAL_WB_RPT_MODE_DEFAULT;
  207. param.scan_rssi_rpt_mode = ATH11K_WMI_SPECTRAL_RSSI_RPT_MODE_DEFAULT;
  208. param.scan_rssi_thr = ATH11K_WMI_SPECTRAL_RSSI_THR_DEFAULT;
  209. param.scan_pwr_format = ATH11K_WMI_SPECTRAL_PWR_FORMAT_DEFAULT;
  210. param.scan_rpt_mode = ATH11K_WMI_SPECTRAL_RPT_MODE_DEFAULT;
  211. param.scan_bin_scale = ATH11K_WMI_SPECTRAL_BIN_SCALE_DEFAULT;
  212. param.scan_dbm_adj = ATH11K_WMI_SPECTRAL_DBM_ADJ_DEFAULT;
  213. param.scan_chn_mask = ATH11K_WMI_SPECTRAL_CHN_MASK_DEFAULT;
  214. ret = ath11k_wmi_vdev_spectral_conf(ar, &param);
  215. if (ret) {
  216. ath11k_warn(ar->ab, "failed to configure spectral scan: %d\n", ret);
  217. return ret;
  218. }
  219. return 0;
  220. }
  221. static ssize_t ath11k_read_file_spec_scan_ctl(struct file *file,
  222. char __user *user_buf,
  223. size_t count, loff_t *ppos)
  224. {
  225. struct ath11k *ar = file->private_data;
  226. char *mode = "";
  227. size_t len;
  228. enum ath11k_spectral_mode spectral_mode;
  229. mutex_lock(&ar->conf_mutex);
  230. spectral_mode = ar->spectral.mode;
  231. mutex_unlock(&ar->conf_mutex);
  232. switch (spectral_mode) {
  233. case ATH11K_SPECTRAL_DISABLED:
  234. mode = "disable";
  235. break;
  236. case ATH11K_SPECTRAL_BACKGROUND:
  237. mode = "background";
  238. break;
  239. case ATH11K_SPECTRAL_MANUAL:
  240. mode = "manual";
  241. break;
  242. }
  243. len = strlen(mode);
  244. return simple_read_from_buffer(user_buf, count, ppos, mode, len);
  245. }
  246. static ssize_t ath11k_write_file_spec_scan_ctl(struct file *file,
  247. const char __user *user_buf,
  248. size_t count, loff_t *ppos)
  249. {
  250. struct ath11k *ar = file->private_data;
  251. char buf[32];
  252. ssize_t len;
  253. int ret;
  254. len = min(count, sizeof(buf) - 1);
  255. if (copy_from_user(buf, user_buf, len))
  256. return -EFAULT;
  257. buf[len] = '\0';
  258. mutex_lock(&ar->conf_mutex);
  259. if (strncmp("trigger", buf, 7) == 0) {
  260. if (ar->spectral.mode == ATH11K_SPECTRAL_MANUAL ||
  261. ar->spectral.mode == ATH11K_SPECTRAL_BACKGROUND) {
  262. /* reset the configuration to adopt possibly changed
  263. * debugfs parameters
  264. */
  265. ret = ath11k_spectral_scan_config(ar, ar->spectral.mode);
  266. if (ret) {
  267. ath11k_warn(ar->ab, "failed to reconfigure spectral scan: %d\n",
  268. ret);
  269. goto unlock;
  270. }
  271. ret = ath11k_spectral_scan_trigger(ar);
  272. if (ret) {
  273. ath11k_warn(ar->ab, "failed to trigger spectral scan: %d\n",
  274. ret);
  275. }
  276. } else {
  277. ret = -EINVAL;
  278. }
  279. } else if (strncmp("background", buf, 10) == 0) {
  280. ret = ath11k_spectral_scan_config(ar, ATH11K_SPECTRAL_BACKGROUND);
  281. } else if (strncmp("manual", buf, 6) == 0) {
  282. ret = ath11k_spectral_scan_config(ar, ATH11K_SPECTRAL_MANUAL);
  283. } else if (strncmp("disable", buf, 7) == 0) {
  284. ret = ath11k_spectral_scan_config(ar, ATH11K_SPECTRAL_DISABLED);
  285. } else {
  286. ret = -EINVAL;
  287. }
  288. unlock:
  289. mutex_unlock(&ar->conf_mutex);
  290. if (ret)
  291. return ret;
  292. return count;
  293. }
  294. static const struct file_operations fops_scan_ctl = {
  295. .read = ath11k_read_file_spec_scan_ctl,
  296. .write = ath11k_write_file_spec_scan_ctl,
  297. .open = simple_open,
  298. .owner = THIS_MODULE,
  299. .llseek = default_llseek,
  300. };
  301. static ssize_t ath11k_read_file_spectral_count(struct file *file,
  302. char __user *user_buf,
  303. size_t count, loff_t *ppos)
  304. {
  305. struct ath11k *ar = file->private_data;
  306. char buf[32];
  307. size_t len;
  308. u16 spectral_count;
  309. mutex_lock(&ar->conf_mutex);
  310. spectral_count = ar->spectral.count;
  311. mutex_unlock(&ar->conf_mutex);
  312. len = sprintf(buf, "%d\n", spectral_count);
  313. return simple_read_from_buffer(user_buf, count, ppos, buf, len);
  314. }
  315. static ssize_t ath11k_write_file_spectral_count(struct file *file,
  316. const char __user *user_buf,
  317. size_t count, loff_t *ppos)
  318. {
  319. struct ath11k *ar = file->private_data;
  320. unsigned long val;
  321. ssize_t ret;
  322. ret = kstrtoul_from_user(user_buf, count, 0, &val);
  323. if (ret)
  324. return ret;
  325. if (val > ATH11K_SPECTRAL_SCAN_COUNT_MAX)
  326. return -EINVAL;
  327. mutex_lock(&ar->conf_mutex);
  328. ar->spectral.count = val;
  329. mutex_unlock(&ar->conf_mutex);
  330. return count;
  331. }
  332. static const struct file_operations fops_scan_count = {
  333. .read = ath11k_read_file_spectral_count,
  334. .write = ath11k_write_file_spectral_count,
  335. .open = simple_open,
  336. .owner = THIS_MODULE,
  337. .llseek = default_llseek,
  338. };
  339. static ssize_t ath11k_read_file_spectral_bins(struct file *file,
  340. char __user *user_buf,
  341. size_t count, loff_t *ppos)
  342. {
  343. struct ath11k *ar = file->private_data;
  344. char buf[32];
  345. unsigned int bins, fft_size;
  346. size_t len;
  347. mutex_lock(&ar->conf_mutex);
  348. fft_size = ar->spectral.fft_size;
  349. bins = 1 << fft_size;
  350. mutex_unlock(&ar->conf_mutex);
  351. len = sprintf(buf, "%d\n", bins);
  352. return simple_read_from_buffer(user_buf, count, ppos, buf, len);
  353. }
  354. static ssize_t ath11k_write_file_spectral_bins(struct file *file,
  355. const char __user *user_buf,
  356. size_t count, loff_t *ppos)
  357. {
  358. struct ath11k *ar = file->private_data;
  359. unsigned long val;
  360. ssize_t ret;
  361. ret = kstrtoul_from_user(user_buf, count, 0, &val);
  362. if (ret)
  363. return ret;
  364. if (val < ATH11K_SPECTRAL_MIN_BINS ||
  365. val > ar->ab->hw_params.spectral.max_fft_bins)
  366. return -EINVAL;
  367. if (!is_power_of_2(val))
  368. return -EINVAL;
  369. mutex_lock(&ar->conf_mutex);
  370. ar->spectral.fft_size = ilog2(val);
  371. mutex_unlock(&ar->conf_mutex);
  372. return count;
  373. }
  374. static const struct file_operations fops_scan_bins = {
  375. .read = ath11k_read_file_spectral_bins,
  376. .write = ath11k_write_file_spectral_bins,
  377. .open = simple_open,
  378. .owner = THIS_MODULE,
  379. .llseek = default_llseek,
  380. };
  381. static int ath11k_spectral_pull_summary(struct ath11k *ar,
  382. struct wmi_dma_buf_release_meta_data *meta,
  383. struct spectral_summary_fft_report *summary,
  384. struct ath11k_spectral_summary_report *report)
  385. {
  386. report->timestamp = __le32_to_cpu(summary->timestamp);
  387. report->agc_total_gain = FIELD_GET(SPECTRAL_SUMMARY_INFO0_AGC_TOTAL_GAIN,
  388. __le32_to_cpu(summary->info0));
  389. report->out_of_band_flag = FIELD_GET(SPECTRAL_SUMMARY_INFO0_OB_FLAG,
  390. __le32_to_cpu(summary->info0));
  391. report->grp_idx = FIELD_GET(SPECTRAL_SUMMARY_INFO0_GRP_IDX,
  392. __le32_to_cpu(summary->info0));
  393. report->rf_saturation = FIELD_GET(SPECTRAL_SUMMARY_INFO0_RECENT_RFSAT,
  394. __le32_to_cpu(summary->info0));
  395. report->inb_pwr_db = FIELD_GET(SPECTRAL_SUMMARY_INFO0_INBAND_PWR_DB,
  396. __le32_to_cpu(summary->info0));
  397. report->false_scan = FIELD_GET(SPECTRAL_SUMMARY_INFO0_FALSE_SCAN,
  398. __le32_to_cpu(summary->info0));
  399. report->detector_id = FIELD_GET(SPECTRAL_SUMMARY_INFO0_DETECTOR_ID,
  400. __le32_to_cpu(summary->info0));
  401. report->primary80 = FIELD_GET(SPECTRAL_SUMMARY_INFO0_PRI80,
  402. __le32_to_cpu(summary->info0));
  403. report->peak_idx = FIELD_GET(SPECTRAL_SUMMARY_INFO2_PEAK_SIGNED_IDX,
  404. __le32_to_cpu(summary->info2));
  405. report->peak_mag = FIELD_GET(SPECTRAL_SUMMARY_INFO2_PEAK_MAGNITUDE,
  406. __le32_to_cpu(summary->info2));
  407. report->gain_change = FIELD_GET(SPECTRAL_SUMMARY_INFO2_GAIN_CHANGE,
  408. __le32_to_cpu(summary->info2));
  409. memcpy(&report->meta, meta, sizeof(*meta));
  410. return 0;
  411. }
  412. static int ath11k_spectral_pull_search(struct ath11k *ar,
  413. struct spectral_search_fft_report *search,
  414. struct ath11k_spectral_search_report *report)
  415. {
  416. report->timestamp = __le32_to_cpu(search->timestamp);
  417. report->detector_id = FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_DETECTOR_ID,
  418. __le32_to_cpu(search->info0));
  419. report->fft_count = FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_FFT_NUM,
  420. __le32_to_cpu(search->info0));
  421. report->radar_check = FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_RADAR_CHECK,
  422. __le32_to_cpu(search->info0));
  423. report->peak_idx = FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_PEAK_SIGNED_IDX,
  424. __le32_to_cpu(search->info0));
  425. report->chain_idx = FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_CHAIN_IDX,
  426. __le32_to_cpu(search->info0));
  427. report->base_pwr_db = FIELD_GET(SPECTRAL_FFT_REPORT_INFO1_BASE_PWR_DB,
  428. __le32_to_cpu(search->info1));
  429. report->total_gain_db = FIELD_GET(SPECTRAL_FFT_REPORT_INFO1_TOTAL_GAIN_DB,
  430. __le32_to_cpu(search->info1));
  431. report->strong_bin_count = FIELD_GET(SPECTRAL_FFT_REPORT_INFO2_NUM_STRONG_BINS,
  432. __le32_to_cpu(search->info2));
  433. report->peak_mag = FIELD_GET(SPECTRAL_FFT_REPORT_INFO2_PEAK_MAGNITUDE,
  434. __le32_to_cpu(search->info2));
  435. report->avg_pwr_db = FIELD_GET(SPECTRAL_FFT_REPORT_INFO2_AVG_PWR_DB,
  436. __le32_to_cpu(search->info2));
  437. report->rel_pwr_db = FIELD_GET(SPECTRAL_FFT_REPORT_INFO2_REL_PWR_DB,
  438. __le32_to_cpu(search->info2));
  439. return 0;
  440. }
  441. static u8 ath11k_spectral_get_max_exp(s8 max_index, u8 max_magnitude,
  442. int bin_len, u8 *bins)
  443. {
  444. int dc_pos;
  445. u8 max_exp;
  446. dc_pos = bin_len / 2;
  447. /* peak index outside of bins */
  448. if (dc_pos <= max_index || -dc_pos >= max_index)
  449. return 0;
  450. for (max_exp = 0; max_exp < 8; max_exp++) {
  451. if (bins[dc_pos + max_index] == (max_magnitude >> max_exp))
  452. break;
  453. }
  454. /* max_exp not found */
  455. if (bins[dc_pos + max_index] != (max_magnitude >> max_exp))
  456. return 0;
  457. return max_exp;
  458. }
  459. static void ath11k_spectral_parse_fft(u8 *outbins, u8 *inbins, int num_bins, u8 fft_sz)
  460. {
  461. int i, j;
  462. i = 0;
  463. j = 0;
  464. while (i < num_bins) {
  465. outbins[i] = inbins[j];
  466. i++;
  467. j += fft_sz;
  468. }
  469. }
  470. static
  471. int ath11k_spectral_process_fft(struct ath11k *ar,
  472. struct ath11k_spectral_summary_report *summary,
  473. void *data,
  474. struct fft_sample_ath11k *fft_sample,
  475. u32 data_len)
  476. {
  477. struct ath11k_base *ab = ar->ab;
  478. struct spectral_search_fft_report *fft_report = data;
  479. struct ath11k_spectral_search_report search;
  480. struct spectral_tlv *tlv;
  481. int tlv_len, bin_len, num_bins;
  482. u16 length, freq;
  483. u8 chan_width_mhz, bin_sz;
  484. int ret;
  485. u32 check_length;
  486. bool fragment_sample = false;
  487. lockdep_assert_held(&ar->spectral.lock);
  488. if (!ab->hw_params.spectral.fft_sz) {
  489. ath11k_warn(ab, "invalid bin size type for hw rev %d\n",
  490. ab->hw_rev);
  491. return -EINVAL;
  492. }
  493. tlv = data;
  494. tlv_len = FIELD_GET(SPECTRAL_TLV_HDR_LEN, __le32_to_cpu(tlv->header));
  495. /* convert Dword into bytes */
  496. tlv_len *= ATH11K_SPECTRAL_DWORD_SIZE;
  497. bin_len = tlv_len - ab->hw_params.spectral.fft_hdr_len;
  498. if (data_len < (bin_len + sizeof(*fft_report))) {
  499. ath11k_warn(ab, "mismatch in expected bin len %d and data len %d\n",
  500. bin_len, data_len);
  501. return -EINVAL;
  502. }
  503. bin_sz = ab->hw_params.spectral.fft_sz + ab->hw_params.spectral.fft_pad_sz;
  504. num_bins = bin_len / bin_sz;
  505. /* Only In-band bins are useful to user for visualize */
  506. num_bins >>= 1;
  507. if (num_bins < ATH11K_SPECTRAL_MIN_IB_BINS ||
  508. num_bins > ATH11K_SPECTRAL_MAX_IB_BINS(ab) ||
  509. !is_power_of_2(num_bins)) {
  510. ath11k_warn(ab, "Invalid num of bins %d\n", num_bins);
  511. return -EINVAL;
  512. }
  513. check_length = sizeof(*fft_report) + (num_bins * ab->hw_params.spectral.fft_sz);
  514. ret = ath11k_dbring_validate_buffer(ar, data, check_length);
  515. if (ret) {
  516. ath11k_warn(ar->ab, "found magic value in fft data, dropping\n");
  517. return ret;
  518. }
  519. ret = ath11k_spectral_pull_search(ar, data, &search);
  520. if (ret) {
  521. ath11k_warn(ab, "failed to pull search report %d\n", ret);
  522. return ret;
  523. }
  524. chan_width_mhz = summary->meta.ch_width;
  525. switch (chan_width_mhz) {
  526. case ATH11K_SPECTRAL_20MHZ:
  527. case ATH11K_SPECTRAL_40MHZ:
  528. case ATH11K_SPECTRAL_80MHZ:
  529. fft_sample->chan_width_mhz = chan_width_mhz;
  530. break;
  531. case ATH11K_SPECTRAL_160MHZ:
  532. if (ab->hw_params.spectral.fragment_160mhz) {
  533. chan_width_mhz /= 2;
  534. fragment_sample = true;
  535. }
  536. fft_sample->chan_width_mhz = chan_width_mhz;
  537. break;
  538. default:
  539. ath11k_warn(ab, "invalid channel width %d\n", chan_width_mhz);
  540. return -EINVAL;
  541. }
  542. length = sizeof(*fft_sample) - sizeof(struct fft_sample_tlv) + num_bins;
  543. fft_sample->tlv.type = ATH_FFT_SAMPLE_ATH11K;
  544. fft_sample->tlv.length = __cpu_to_be16(length);
  545. fft_sample->tsf = __cpu_to_be32(search.timestamp);
  546. fft_sample->max_magnitude = __cpu_to_be16(search.peak_mag);
  547. fft_sample->max_index = FIELD_GET(SPECTRAL_FFT_REPORT_INFO0_PEAK_SIGNED_IDX,
  548. __le32_to_cpu(fft_report->info0));
  549. summary->inb_pwr_db >>= 1;
  550. fft_sample->rssi = __cpu_to_be16(summary->inb_pwr_db);
  551. fft_sample->noise = __cpu_to_be32(summary->meta.noise_floor[search.chain_idx]);
  552. freq = summary->meta.freq1;
  553. fft_sample->freq1 = __cpu_to_be16(freq);
  554. freq = summary->meta.freq2;
  555. fft_sample->freq2 = __cpu_to_be16(freq);
  556. /* If freq2 is available then the spectral scan results are fragmented
  557. * as primary and secondary
  558. */
  559. if (fragment_sample && freq) {
  560. if (!ar->spectral.is_primary)
  561. fft_sample->freq1 = cpu_to_be16(freq);
  562. /* We have to toggle the is_primary to handle the next report */
  563. ar->spectral.is_primary = !ar->spectral.is_primary;
  564. }
  565. ath11k_spectral_parse_fft(fft_sample->data, fft_report->bins, num_bins,
  566. ab->hw_params.spectral.fft_sz);
  567. fft_sample->max_exp = ath11k_spectral_get_max_exp(fft_sample->max_index,
  568. search.peak_mag,
  569. num_bins,
  570. fft_sample->data);
  571. if (ar->spectral.rfs_scan)
  572. relay_write(ar->spectral.rfs_scan, fft_sample,
  573. length + sizeof(struct fft_sample_tlv));
  574. return 0;
  575. }
  576. static int ath11k_spectral_process_data(struct ath11k *ar,
  577. struct ath11k_dbring_data *param)
  578. {
  579. struct ath11k_base *ab = ar->ab;
  580. struct spectral_tlv *tlv;
  581. struct spectral_summary_fft_report *summary = NULL;
  582. struct ath11k_spectral_summary_report summ_rpt;
  583. struct fft_sample_ath11k *fft_sample = NULL;
  584. u8 *data;
  585. u32 data_len, i;
  586. u8 sign, tag;
  587. int tlv_len, sample_sz;
  588. int ret;
  589. bool quit = false;
  590. spin_lock_bh(&ar->spectral.lock);
  591. if (!ar->spectral.enabled) {
  592. ret = -EINVAL;
  593. goto unlock;
  594. }
  595. sample_sz = sizeof(*fft_sample) + ATH11K_SPECTRAL_MAX_IB_BINS(ab);
  596. fft_sample = kmalloc(sample_sz, GFP_ATOMIC);
  597. if (!fft_sample) {
  598. ret = -ENOBUFS;
  599. goto unlock;
  600. }
  601. data = param->data;
  602. data_len = param->data_sz;
  603. i = 0;
  604. while (!quit && (i < data_len)) {
  605. if ((i + sizeof(*tlv)) > data_len) {
  606. ath11k_warn(ab, "failed to parse spectral tlv hdr at bytes %d\n",
  607. i);
  608. ret = -EINVAL;
  609. goto err;
  610. }
  611. tlv = (struct spectral_tlv *)&data[i];
  612. sign = FIELD_GET(SPECTRAL_TLV_HDR_SIGN,
  613. __le32_to_cpu(tlv->header));
  614. if (sign != ATH11K_SPECTRAL_SIGNATURE) {
  615. ath11k_warn(ab, "Invalid sign 0x%x at bytes %d\n",
  616. sign, i);
  617. ret = -EINVAL;
  618. goto err;
  619. }
  620. tlv_len = FIELD_GET(SPECTRAL_TLV_HDR_LEN,
  621. __le32_to_cpu(tlv->header));
  622. /* convert Dword into bytes */
  623. tlv_len *= ATH11K_SPECTRAL_DWORD_SIZE;
  624. if ((i + sizeof(*tlv) + tlv_len) > data_len) {
  625. ath11k_warn(ab, "failed to parse spectral tlv payload at bytes %d tlv_len:%d data_len:%d\n",
  626. i, tlv_len, data_len);
  627. ret = -EINVAL;
  628. goto err;
  629. }
  630. tag = FIELD_GET(SPECTRAL_TLV_HDR_TAG,
  631. __le32_to_cpu(tlv->header));
  632. switch (tag) {
  633. case ATH11K_SPECTRAL_TAG_SCAN_SUMMARY:
  634. /* HW bug in tlv length of summary report,
  635. * HW report 3 DWORD size but the data payload
  636. * is 4 DWORD size (16 bytes).
  637. * Need to remove this workaround once HW bug fixed
  638. */
  639. tlv_len = sizeof(*summary) - sizeof(*tlv) +
  640. ab->hw_params.spectral.summary_pad_sz;
  641. if (tlv_len < (sizeof(*summary) - sizeof(*tlv))) {
  642. ath11k_warn(ab, "failed to parse spectral summary at bytes %d tlv_len:%d\n",
  643. i, tlv_len);
  644. ret = -EINVAL;
  645. goto err;
  646. }
  647. ret = ath11k_dbring_validate_buffer(ar, data, tlv_len);
  648. if (ret) {
  649. ath11k_warn(ar->ab, "found magic value in spectral summary, dropping\n");
  650. goto err;
  651. }
  652. summary = (struct spectral_summary_fft_report *)tlv;
  653. ath11k_spectral_pull_summary(ar, &param->meta,
  654. summary, &summ_rpt);
  655. break;
  656. case ATH11K_SPECTRAL_TAG_SCAN_SEARCH:
  657. if (tlv_len < (sizeof(struct spectral_search_fft_report) -
  658. sizeof(*tlv))) {
  659. ath11k_warn(ab, "failed to parse spectral search fft at bytes %d\n",
  660. i);
  661. ret = -EINVAL;
  662. goto err;
  663. }
  664. memset(fft_sample, 0, sample_sz);
  665. ret = ath11k_spectral_process_fft(ar, &summ_rpt, tlv,
  666. fft_sample,
  667. data_len - i);
  668. if (ret) {
  669. ath11k_warn(ab, "failed to process spectral fft at bytes %d\n",
  670. i);
  671. goto err;
  672. }
  673. quit = true;
  674. break;
  675. }
  676. i += sizeof(*tlv) + tlv_len;
  677. }
  678. ret = 0;
  679. err:
  680. kfree(fft_sample);
  681. unlock:
  682. spin_unlock_bh(&ar->spectral.lock);
  683. return ret;
  684. }
  685. static int ath11k_spectral_ring_alloc(struct ath11k *ar,
  686. struct ath11k_dbring_cap *db_cap)
  687. {
  688. struct ath11k_spectral *sp = &ar->spectral;
  689. int ret;
  690. ret = ath11k_dbring_srng_setup(ar, &sp->rx_ring,
  691. 0, db_cap->min_elem);
  692. if (ret) {
  693. ath11k_warn(ar->ab, "failed to setup db ring\n");
  694. return ret;
  695. }
  696. ath11k_dbring_set_cfg(ar, &sp->rx_ring,
  697. ATH11K_SPECTRAL_NUM_RESP_PER_EVENT,
  698. ATH11K_SPECTRAL_EVENT_TIMEOUT_MS,
  699. ath11k_spectral_process_data);
  700. ret = ath11k_dbring_buf_setup(ar, &sp->rx_ring, db_cap);
  701. if (ret) {
  702. ath11k_warn(ar->ab, "failed to setup db ring buffer\n");
  703. goto srng_cleanup;
  704. }
  705. ret = ath11k_dbring_wmi_cfg_setup(ar, &sp->rx_ring,
  706. WMI_DIRECT_BUF_SPECTRAL);
  707. if (ret) {
  708. ath11k_warn(ar->ab, "failed to setup db ring cfg\n");
  709. goto buffer_cleanup;
  710. }
  711. return 0;
  712. buffer_cleanup:
  713. ath11k_dbring_buf_cleanup(ar, &sp->rx_ring);
  714. srng_cleanup:
  715. ath11k_dbring_srng_cleanup(ar, &sp->rx_ring);
  716. return ret;
  717. }
  718. static inline void ath11k_spectral_ring_free(struct ath11k *ar)
  719. {
  720. struct ath11k_spectral *sp = &ar->spectral;
  721. ath11k_dbring_srng_cleanup(ar, &sp->rx_ring);
  722. ath11k_dbring_buf_cleanup(ar, &sp->rx_ring);
  723. }
  724. static inline void ath11k_spectral_debug_unregister(struct ath11k *ar)
  725. {
  726. debugfs_remove(ar->spectral.scan_bins);
  727. ar->spectral.scan_bins = NULL;
  728. debugfs_remove(ar->spectral.scan_count);
  729. ar->spectral.scan_count = NULL;
  730. debugfs_remove(ar->spectral.scan_ctl);
  731. ar->spectral.scan_ctl = NULL;
  732. if (ar->spectral.rfs_scan) {
  733. relay_close(ar->spectral.rfs_scan);
  734. ar->spectral.rfs_scan = NULL;
  735. }
  736. }
  737. int ath11k_spectral_vif_stop(struct ath11k_vif *arvif)
  738. {
  739. if (!arvif->spectral_enabled)
  740. return 0;
  741. return ath11k_spectral_scan_config(arvif->ar, ATH11K_SPECTRAL_DISABLED);
  742. }
  743. void ath11k_spectral_reset_buffer(struct ath11k *ar)
  744. {
  745. if (!ar->spectral.enabled)
  746. return;
  747. if (ar->spectral.rfs_scan)
  748. relay_reset(ar->spectral.rfs_scan);
  749. }
  750. void ath11k_spectral_deinit(struct ath11k_base *ab)
  751. {
  752. struct ath11k *ar;
  753. struct ath11k_spectral *sp;
  754. int i;
  755. for (i = 0; i < ab->num_radios; i++) {
  756. ar = ab->pdevs[i].ar;
  757. sp = &ar->spectral;
  758. if (!sp->enabled)
  759. continue;
  760. mutex_lock(&ar->conf_mutex);
  761. ath11k_spectral_scan_config(ar, ATH11K_SPECTRAL_DISABLED);
  762. mutex_unlock(&ar->conf_mutex);
  763. spin_lock_bh(&sp->lock);
  764. sp->enabled = false;
  765. spin_unlock_bh(&sp->lock);
  766. ath11k_spectral_debug_unregister(ar);
  767. ath11k_spectral_ring_free(ar);
  768. }
  769. }
  770. static inline int ath11k_spectral_debug_register(struct ath11k *ar)
  771. {
  772. int ret;
  773. ar->spectral.rfs_scan = relay_open("spectral_scan",
  774. ar->debug.debugfs_pdev,
  775. ATH11K_SPECTRAL_SUB_BUFF_SIZE(ar->ab),
  776. ATH11K_SPECTRAL_NUM_SUB_BUF,
  777. &rfs_scan_cb, NULL);
  778. if (!ar->spectral.rfs_scan) {
  779. ath11k_warn(ar->ab, "failed to open relay in pdev %d\n",
  780. ar->pdev_idx);
  781. return -EINVAL;
  782. }
  783. ar->spectral.scan_ctl = debugfs_create_file("spectral_scan_ctl",
  784. 0600,
  785. ar->debug.debugfs_pdev, ar,
  786. &fops_scan_ctl);
  787. if (!ar->spectral.scan_ctl) {
  788. ath11k_warn(ar->ab, "failed to open debugfs in pdev %d\n",
  789. ar->pdev_idx);
  790. ret = -EINVAL;
  791. goto debug_unregister;
  792. }
  793. ar->spectral.scan_count = debugfs_create_file("spectral_count",
  794. 0600,
  795. ar->debug.debugfs_pdev, ar,
  796. &fops_scan_count);
  797. if (!ar->spectral.scan_count) {
  798. ath11k_warn(ar->ab, "failed to open debugfs in pdev %d\n",
  799. ar->pdev_idx);
  800. ret = -EINVAL;
  801. goto debug_unregister;
  802. }
  803. ar->spectral.scan_bins = debugfs_create_file("spectral_bins",
  804. 0600,
  805. ar->debug.debugfs_pdev, ar,
  806. &fops_scan_bins);
  807. if (!ar->spectral.scan_bins) {
  808. ath11k_warn(ar->ab, "failed to open debugfs in pdev %d\n",
  809. ar->pdev_idx);
  810. ret = -EINVAL;
  811. goto debug_unregister;
  812. }
  813. return 0;
  814. debug_unregister:
  815. ath11k_spectral_debug_unregister(ar);
  816. return ret;
  817. }
  818. int ath11k_spectral_init(struct ath11k_base *ab)
  819. {
  820. struct ath11k *ar;
  821. struct ath11k_spectral *sp;
  822. struct ath11k_dbring_cap db_cap;
  823. int ret;
  824. int i;
  825. if (!test_bit(WMI_TLV_SERVICE_FREQINFO_IN_METADATA,
  826. ab->wmi_ab.svc_map))
  827. return 0;
  828. if (!ab->hw_params.spectral.fft_sz)
  829. return 0;
  830. for (i = 0; i < ab->num_radios; i++) {
  831. ar = ab->pdevs[i].ar;
  832. sp = &ar->spectral;
  833. ret = ath11k_dbring_get_cap(ar->ab, ar->pdev_idx,
  834. WMI_DIRECT_BUF_SPECTRAL,
  835. &db_cap);
  836. if (ret)
  837. continue;
  838. idr_init(&sp->rx_ring.bufs_idr);
  839. spin_lock_init(&sp->rx_ring.idr_lock);
  840. spin_lock_init(&sp->lock);
  841. ret = ath11k_spectral_ring_alloc(ar, &db_cap);
  842. if (ret) {
  843. ath11k_warn(ab, "failed to init spectral ring for pdev %d\n",
  844. i);
  845. goto deinit;
  846. }
  847. spin_lock_bh(&sp->lock);
  848. sp->mode = ATH11K_SPECTRAL_DISABLED;
  849. sp->count = ATH11K_WMI_SPECTRAL_COUNT_DEFAULT;
  850. sp->fft_size = ATH11K_WMI_SPECTRAL_FFT_SIZE_DEFAULT;
  851. sp->enabled = true;
  852. spin_unlock_bh(&sp->lock);
  853. ret = ath11k_spectral_debug_register(ar);
  854. if (ret) {
  855. ath11k_warn(ab, "failed to register spectral for pdev %d\n",
  856. i);
  857. goto deinit;
  858. }
  859. }
  860. return 0;
  861. deinit:
  862. ath11k_spectral_deinit(ab);
  863. return ret;
  864. }
  865. enum ath11k_spectral_mode ath11k_spectral_get_mode(struct ath11k *ar)
  866. {
  867. if (ar->spectral.enabled)
  868. return ar->spectral.mode;
  869. else
  870. return ATH11K_SPECTRAL_DISABLED;
  871. }
  872. struct ath11k_dbring *ath11k_spectral_get_dbring(struct ath11k *ar)
  873. {
  874. if (ar->spectral.enabled)
  875. return &ar->spectral.rx_ring;
  876. else
  877. return NULL;
  878. }