spectral.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568
  1. /*
  2. * Copyright (c) 2013-2017 Qualcomm Atheros, Inc.
  3. *
  4. * Permission to use, copy, modify, and/or distribute this software for any
  5. * purpose with or without fee is hereby granted, provided that the above
  6. * copyright notice and this permission notice appear in all copies.
  7. *
  8. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  9. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  11. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  13. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  14. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. #include <linux/relay.h>
  17. #include "core.h"
  18. #include "debug.h"
  19. #include "wmi-ops.h"
  20. static void send_fft_sample(struct ath10k *ar,
  21. const struct fft_sample_tlv *fft_sample_tlv)
  22. {
  23. int length;
  24. if (!ar->spectral.rfs_chan_spec_scan)
  25. return;
  26. length = __be16_to_cpu(fft_sample_tlv->length) +
  27. sizeof(*fft_sample_tlv);
  28. relay_write(ar->spectral.rfs_chan_spec_scan, fft_sample_tlv, length);
  29. }
  30. static uint8_t get_max_exp(s8 max_index, u16 max_magnitude, size_t bin_len,
  31. u8 *data)
  32. {
  33. int dc_pos;
  34. u8 max_exp;
  35. dc_pos = bin_len / 2;
  36. /* peak index outside of bins */
  37. if (dc_pos < max_index || -dc_pos >= max_index)
  38. return 0;
  39. for (max_exp = 0; max_exp < 8; max_exp++) {
  40. if (data[dc_pos + max_index] == (max_magnitude >> max_exp))
  41. break;
  42. }
  43. /* max_exp not found */
  44. if (data[dc_pos + max_index] != (max_magnitude >> max_exp))
  45. return 0;
  46. return max_exp;
  47. }
  48. static inline size_t ath10k_spectral_fix_bin_size(struct ath10k *ar,
  49. size_t bin_len)
  50. {
  51. /* some chipsets reports bin size as 2^n bytes + 'm' bytes in
  52. * report mode 2. First 2^n bytes carries inband tones and last
  53. * 'm' bytes carries band edge detection data mainly used in
  54. * radar detection purpose. Strip last 'm' bytes to make bin size
  55. * as a valid one. 'm' can take possible values of 4, 12.
  56. */
  57. if (!is_power_of_2(bin_len))
  58. bin_len -= ar->hw_params.spectral_bin_discard;
  59. return bin_len;
  60. }
  61. int ath10k_spectral_process_fft(struct ath10k *ar,
  62. struct wmi_phyerr_ev_arg *phyerr,
  63. const struct phyerr_fft_report *fftr,
  64. size_t bin_len, u64 tsf)
  65. {
  66. struct fft_sample_ath10k *fft_sample;
  67. u8 buf[sizeof(*fft_sample) + SPECTRAL_ATH10K_MAX_NUM_BINS];
  68. u16 freq1, freq2, total_gain_db, base_pwr_db, length, peak_mag;
  69. u32 reg0, reg1;
  70. u8 chain_idx, *bins;
  71. int dc_pos;
  72. fft_sample = (struct fft_sample_ath10k *)&buf;
  73. bin_len = ath10k_spectral_fix_bin_size(ar, bin_len);
  74. if (bin_len < 64 || bin_len > SPECTRAL_ATH10K_MAX_NUM_BINS)
  75. return -EINVAL;
  76. reg0 = __le32_to_cpu(fftr->reg0);
  77. reg1 = __le32_to_cpu(fftr->reg1);
  78. length = sizeof(*fft_sample) - sizeof(struct fft_sample_tlv) + bin_len;
  79. fft_sample->tlv.type = ATH_FFT_SAMPLE_ATH10K;
  80. fft_sample->tlv.length = __cpu_to_be16(length);
  81. /* TODO: there might be a reason why the hardware reports 20/40/80 MHz,
  82. * but the results/plots suggest that its actually 22/44/88 MHz.
  83. */
  84. switch (phyerr->chan_width_mhz) {
  85. case 20:
  86. fft_sample->chan_width_mhz = 22;
  87. break;
  88. case 40:
  89. fft_sample->chan_width_mhz = 44;
  90. break;
  91. case 80:
  92. /* TODO: As experiments with an analogue sender and various
  93. * configurations (fft-sizes of 64/128/256 and 20/40/80 Mhz)
  94. * show, the particular configuration of 80 MHz/64 bins does
  95. * not match with the other samples at all. Until the reason
  96. * for that is found, don't report these samples.
  97. */
  98. if (bin_len == 64)
  99. return -EINVAL;
  100. fft_sample->chan_width_mhz = 88;
  101. break;
  102. default:
  103. fft_sample->chan_width_mhz = phyerr->chan_width_mhz;
  104. }
  105. fft_sample->relpwr_db = MS(reg1, SEARCH_FFT_REPORT_REG1_RELPWR_DB);
  106. fft_sample->avgpwr_db = MS(reg1, SEARCH_FFT_REPORT_REG1_AVGPWR_DB);
  107. peak_mag = MS(reg1, SEARCH_FFT_REPORT_REG1_PEAK_MAG);
  108. fft_sample->max_magnitude = __cpu_to_be16(peak_mag);
  109. fft_sample->max_index = MS(reg0, SEARCH_FFT_REPORT_REG0_PEAK_SIDX);
  110. fft_sample->rssi = phyerr->rssi_combined;
  111. total_gain_db = MS(reg0, SEARCH_FFT_REPORT_REG0_TOTAL_GAIN_DB);
  112. base_pwr_db = MS(reg0, SEARCH_FFT_REPORT_REG0_BASE_PWR_DB);
  113. fft_sample->total_gain_db = __cpu_to_be16(total_gain_db);
  114. fft_sample->base_pwr_db = __cpu_to_be16(base_pwr_db);
  115. freq1 = phyerr->freq1;
  116. freq2 = phyerr->freq2;
  117. fft_sample->freq1 = __cpu_to_be16(freq1);
  118. fft_sample->freq2 = __cpu_to_be16(freq2);
  119. chain_idx = MS(reg0, SEARCH_FFT_REPORT_REG0_FFT_CHN_IDX);
  120. fft_sample->noise = __cpu_to_be16(phyerr->nf_chains[chain_idx]);
  121. bins = (u8 *)fftr;
  122. bins += sizeof(*fftr);
  123. fft_sample->tsf = __cpu_to_be64(tsf);
  124. /* max_exp has been directly reported by previous hardware (ath9k),
  125. * maybe its possible to get it by other means?
  126. */
  127. fft_sample->max_exp = get_max_exp(fft_sample->max_index, peak_mag,
  128. bin_len, bins);
  129. memcpy(fft_sample->data, bins, bin_len);
  130. /* DC value (value in the middle) is the blind spot of the spectral
  131. * sample and invalid, interpolate it.
  132. */
  133. dc_pos = bin_len / 2;
  134. fft_sample->data[dc_pos] = (fft_sample->data[dc_pos + 1] +
  135. fft_sample->data[dc_pos - 1]) / 2;
  136. send_fft_sample(ar, &fft_sample->tlv);
  137. return 0;
  138. }
  139. static struct ath10k_vif *ath10k_get_spectral_vdev(struct ath10k *ar)
  140. {
  141. struct ath10k_vif *arvif;
  142. lockdep_assert_held(&ar->conf_mutex);
  143. if (list_empty(&ar->arvifs))
  144. return NULL;
  145. /* if there already is a vif doing spectral, return that. */
  146. list_for_each_entry(arvif, &ar->arvifs, list)
  147. if (arvif->spectral_enabled)
  148. return arvif;
  149. /* otherwise, return the first vif. */
  150. return list_first_entry(&ar->arvifs, typeof(*arvif), list);
  151. }
  152. static int ath10k_spectral_scan_trigger(struct ath10k *ar)
  153. {
  154. struct ath10k_vif *arvif;
  155. int res;
  156. int vdev_id;
  157. lockdep_assert_held(&ar->conf_mutex);
  158. arvif = ath10k_get_spectral_vdev(ar);
  159. if (!arvif)
  160. return -ENODEV;
  161. vdev_id = arvif->vdev_id;
  162. if (ar->spectral.mode == SPECTRAL_DISABLED)
  163. return 0;
  164. res = ath10k_wmi_vdev_spectral_enable(ar, vdev_id,
  165. WMI_SPECTRAL_TRIGGER_CMD_CLEAR,
  166. WMI_SPECTRAL_ENABLE_CMD_ENABLE);
  167. if (res < 0)
  168. return res;
  169. res = ath10k_wmi_vdev_spectral_enable(ar, vdev_id,
  170. WMI_SPECTRAL_TRIGGER_CMD_TRIGGER,
  171. WMI_SPECTRAL_ENABLE_CMD_ENABLE);
  172. if (res < 0)
  173. return res;
  174. return 0;
  175. }
  176. static int ath10k_spectral_scan_config(struct ath10k *ar,
  177. enum ath10k_spectral_mode mode)
  178. {
  179. struct wmi_vdev_spectral_conf_arg arg;
  180. struct ath10k_vif *arvif;
  181. int vdev_id, count, res = 0;
  182. lockdep_assert_held(&ar->conf_mutex);
  183. arvif = ath10k_get_spectral_vdev(ar);
  184. if (!arvif)
  185. return -ENODEV;
  186. vdev_id = arvif->vdev_id;
  187. arvif->spectral_enabled = (mode != SPECTRAL_DISABLED);
  188. ar->spectral.mode = mode;
  189. res = ath10k_wmi_vdev_spectral_enable(ar, vdev_id,
  190. WMI_SPECTRAL_TRIGGER_CMD_CLEAR,
  191. WMI_SPECTRAL_ENABLE_CMD_DISABLE);
  192. if (res < 0) {
  193. ath10k_warn(ar, "failed to enable spectral scan: %d\n", res);
  194. return res;
  195. }
  196. if (mode == SPECTRAL_DISABLED)
  197. return 0;
  198. if (mode == SPECTRAL_BACKGROUND)
  199. count = WMI_SPECTRAL_COUNT_DEFAULT;
  200. else
  201. count = max_t(u8, 1, ar->spectral.config.count);
  202. arg.vdev_id = vdev_id;
  203. arg.scan_count = count;
  204. arg.scan_period = WMI_SPECTRAL_PERIOD_DEFAULT;
  205. arg.scan_priority = WMI_SPECTRAL_PRIORITY_DEFAULT;
  206. arg.scan_fft_size = ar->spectral.config.fft_size;
  207. arg.scan_gc_ena = WMI_SPECTRAL_GC_ENA_DEFAULT;
  208. arg.scan_restart_ena = WMI_SPECTRAL_RESTART_ENA_DEFAULT;
  209. arg.scan_noise_floor_ref = WMI_SPECTRAL_NOISE_FLOOR_REF_DEFAULT;
  210. arg.scan_init_delay = WMI_SPECTRAL_INIT_DELAY_DEFAULT;
  211. arg.scan_nb_tone_thr = WMI_SPECTRAL_NB_TONE_THR_DEFAULT;
  212. arg.scan_str_bin_thr = WMI_SPECTRAL_STR_BIN_THR_DEFAULT;
  213. arg.scan_wb_rpt_mode = WMI_SPECTRAL_WB_RPT_MODE_DEFAULT;
  214. arg.scan_rssi_rpt_mode = WMI_SPECTRAL_RSSI_RPT_MODE_DEFAULT;
  215. arg.scan_rssi_thr = WMI_SPECTRAL_RSSI_THR_DEFAULT;
  216. arg.scan_pwr_format = WMI_SPECTRAL_PWR_FORMAT_DEFAULT;
  217. arg.scan_rpt_mode = WMI_SPECTRAL_RPT_MODE_DEFAULT;
  218. arg.scan_bin_scale = WMI_SPECTRAL_BIN_SCALE_DEFAULT;
  219. arg.scan_dbm_adj = WMI_SPECTRAL_DBM_ADJ_DEFAULT;
  220. arg.scan_chn_mask = WMI_SPECTRAL_CHN_MASK_DEFAULT;
  221. res = ath10k_wmi_vdev_spectral_conf(ar, &arg);
  222. if (res < 0) {
  223. ath10k_warn(ar, "failed to configure spectral scan: %d\n", res);
  224. return res;
  225. }
  226. return 0;
  227. }
  228. static ssize_t read_file_spec_scan_ctl(struct file *file, char __user *user_buf,
  229. size_t count, loff_t *ppos)
  230. {
  231. struct ath10k *ar = file->private_data;
  232. char *mode = "";
  233. size_t len;
  234. enum ath10k_spectral_mode spectral_mode;
  235. mutex_lock(&ar->conf_mutex);
  236. spectral_mode = ar->spectral.mode;
  237. mutex_unlock(&ar->conf_mutex);
  238. switch (spectral_mode) {
  239. case SPECTRAL_DISABLED:
  240. mode = "disable";
  241. break;
  242. case SPECTRAL_BACKGROUND:
  243. mode = "background";
  244. break;
  245. case SPECTRAL_MANUAL:
  246. mode = "manual";
  247. break;
  248. }
  249. len = strlen(mode);
  250. return simple_read_from_buffer(user_buf, count, ppos, mode, len);
  251. }
  252. static ssize_t write_file_spec_scan_ctl(struct file *file,
  253. const char __user *user_buf,
  254. size_t count, loff_t *ppos)
  255. {
  256. struct ath10k *ar = file->private_data;
  257. char buf[32];
  258. ssize_t len;
  259. int res;
  260. len = min(count, sizeof(buf) - 1);
  261. if (copy_from_user(buf, user_buf, len))
  262. return -EFAULT;
  263. buf[len] = '\0';
  264. mutex_lock(&ar->conf_mutex);
  265. if (strncmp("trigger", buf, 7) == 0) {
  266. if (ar->spectral.mode == SPECTRAL_MANUAL ||
  267. ar->spectral.mode == SPECTRAL_BACKGROUND) {
  268. /* reset the configuration to adopt possibly changed
  269. * debugfs parameters
  270. */
  271. res = ath10k_spectral_scan_config(ar,
  272. ar->spectral.mode);
  273. if (res < 0) {
  274. ath10k_warn(ar, "failed to reconfigure spectral scan: %d\n",
  275. res);
  276. }
  277. res = ath10k_spectral_scan_trigger(ar);
  278. if (res < 0) {
  279. ath10k_warn(ar, "failed to trigger spectral scan: %d\n",
  280. res);
  281. }
  282. } else {
  283. res = -EINVAL;
  284. }
  285. } else if (strncmp("background", buf, 10) == 0) {
  286. res = ath10k_spectral_scan_config(ar, SPECTRAL_BACKGROUND);
  287. } else if (strncmp("manual", buf, 6) == 0) {
  288. res = ath10k_spectral_scan_config(ar, SPECTRAL_MANUAL);
  289. } else if (strncmp("disable", buf, 7) == 0) {
  290. res = ath10k_spectral_scan_config(ar, SPECTRAL_DISABLED);
  291. } else {
  292. res = -EINVAL;
  293. }
  294. mutex_unlock(&ar->conf_mutex);
  295. if (res < 0)
  296. return res;
  297. return count;
  298. }
  299. static const struct file_operations fops_spec_scan_ctl = {
  300. .read = read_file_spec_scan_ctl,
  301. .write = write_file_spec_scan_ctl,
  302. .open = simple_open,
  303. .owner = THIS_MODULE,
  304. .llseek = default_llseek,
  305. };
  306. static ssize_t read_file_spectral_count(struct file *file,
  307. char __user *user_buf,
  308. size_t count, loff_t *ppos)
  309. {
  310. struct ath10k *ar = file->private_data;
  311. char buf[32];
  312. size_t len;
  313. u8 spectral_count;
  314. mutex_lock(&ar->conf_mutex);
  315. spectral_count = ar->spectral.config.count;
  316. mutex_unlock(&ar->conf_mutex);
  317. len = sprintf(buf, "%d\n", spectral_count);
  318. return simple_read_from_buffer(user_buf, count, ppos, buf, len);
  319. }
  320. static ssize_t write_file_spectral_count(struct file *file,
  321. const char __user *user_buf,
  322. size_t count, loff_t *ppos)
  323. {
  324. struct ath10k *ar = file->private_data;
  325. unsigned long val;
  326. char buf[32];
  327. ssize_t len;
  328. len = min(count, sizeof(buf) - 1);
  329. if (copy_from_user(buf, user_buf, len))
  330. return -EFAULT;
  331. buf[len] = '\0';
  332. if (kstrtoul(buf, 0, &val))
  333. return -EINVAL;
  334. if (val > 255)
  335. return -EINVAL;
  336. mutex_lock(&ar->conf_mutex);
  337. ar->spectral.config.count = val;
  338. mutex_unlock(&ar->conf_mutex);
  339. return count;
  340. }
  341. static const struct file_operations fops_spectral_count = {
  342. .read = read_file_spectral_count,
  343. .write = write_file_spectral_count,
  344. .open = simple_open,
  345. .owner = THIS_MODULE,
  346. .llseek = default_llseek,
  347. };
  348. static ssize_t read_file_spectral_bins(struct file *file,
  349. char __user *user_buf,
  350. size_t count, loff_t *ppos)
  351. {
  352. struct ath10k *ar = file->private_data;
  353. char buf[32];
  354. unsigned int bins, fft_size, bin_scale;
  355. size_t len;
  356. mutex_lock(&ar->conf_mutex);
  357. fft_size = ar->spectral.config.fft_size;
  358. bin_scale = WMI_SPECTRAL_BIN_SCALE_DEFAULT;
  359. bins = 1 << (fft_size - bin_scale);
  360. mutex_unlock(&ar->conf_mutex);
  361. len = sprintf(buf, "%d\n", bins);
  362. return simple_read_from_buffer(user_buf, count, ppos, buf, len);
  363. }
  364. static ssize_t write_file_spectral_bins(struct file *file,
  365. const char __user *user_buf,
  366. size_t count, loff_t *ppos)
  367. {
  368. struct ath10k *ar = file->private_data;
  369. unsigned long val;
  370. char buf[32];
  371. ssize_t len;
  372. len = min(count, sizeof(buf) - 1);
  373. if (copy_from_user(buf, user_buf, len))
  374. return -EFAULT;
  375. buf[len] = '\0';
  376. if (kstrtoul(buf, 0, &val))
  377. return -EINVAL;
  378. if (val < 64 || val > SPECTRAL_ATH10K_MAX_NUM_BINS)
  379. return -EINVAL;
  380. if (!is_power_of_2(val))
  381. return -EINVAL;
  382. mutex_lock(&ar->conf_mutex);
  383. ar->spectral.config.fft_size = ilog2(val);
  384. ar->spectral.config.fft_size += WMI_SPECTRAL_BIN_SCALE_DEFAULT;
  385. mutex_unlock(&ar->conf_mutex);
  386. return count;
  387. }
  388. static const struct file_operations fops_spectral_bins = {
  389. .read = read_file_spectral_bins,
  390. .write = write_file_spectral_bins,
  391. .open = simple_open,
  392. .owner = THIS_MODULE,
  393. .llseek = default_llseek,
  394. };
  395. static struct dentry *create_buf_file_handler(const char *filename,
  396. struct dentry *parent,
  397. umode_t mode,
  398. struct rchan_buf *buf,
  399. int *is_global)
  400. {
  401. struct dentry *buf_file;
  402. buf_file = debugfs_create_file(filename, mode, parent, buf,
  403. &relay_file_operations);
  404. *is_global = 1;
  405. return buf_file;
  406. }
  407. static int remove_buf_file_handler(struct dentry *dentry)
  408. {
  409. debugfs_remove(dentry);
  410. return 0;
  411. }
  412. static struct rchan_callbacks rfs_spec_scan_cb = {
  413. .create_buf_file = create_buf_file_handler,
  414. .remove_buf_file = remove_buf_file_handler,
  415. };
  416. int ath10k_spectral_start(struct ath10k *ar)
  417. {
  418. struct ath10k_vif *arvif;
  419. lockdep_assert_held(&ar->conf_mutex);
  420. list_for_each_entry(arvif, &ar->arvifs, list)
  421. arvif->spectral_enabled = 0;
  422. ar->spectral.mode = SPECTRAL_DISABLED;
  423. ar->spectral.config.count = WMI_SPECTRAL_COUNT_DEFAULT;
  424. ar->spectral.config.fft_size = WMI_SPECTRAL_FFT_SIZE_DEFAULT;
  425. return 0;
  426. }
  427. int ath10k_spectral_vif_stop(struct ath10k_vif *arvif)
  428. {
  429. if (!arvif->spectral_enabled)
  430. return 0;
  431. return ath10k_spectral_scan_config(arvif->ar, SPECTRAL_DISABLED);
  432. }
  433. int ath10k_spectral_create(struct ath10k *ar)
  434. {
  435. /* The buffer size covers whole channels in dual bands up to 128 bins.
  436. * Scan with bigger than 128 bins needs to be run on single band each.
  437. */
  438. ar->spectral.rfs_chan_spec_scan = relay_open("spectral_scan",
  439. ar->debug.debugfs_phy,
  440. 1140, 2500,
  441. &rfs_spec_scan_cb, NULL);
  442. debugfs_create_file("spectral_scan_ctl",
  443. 0600,
  444. ar->debug.debugfs_phy, ar,
  445. &fops_spec_scan_ctl);
  446. debugfs_create_file("spectral_count",
  447. 0600,
  448. ar->debug.debugfs_phy, ar,
  449. &fops_spectral_count);
  450. debugfs_create_file("spectral_bins",
  451. 0600,
  452. ar->debug.debugfs_phy, ar,
  453. &fops_spectral_bins);
  454. return 0;
  455. }
  456. void ath10k_spectral_destroy(struct ath10k *ar)
  457. {
  458. if (ar->spectral.rfs_chan_spec_scan) {
  459. relay_close(ar->spectral.rfs_chan_spec_scan);
  460. ar->spectral.rfs_chan_spec_scan = NULL;
  461. }
  462. }