spectral.c 28 KB

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