target_if_spectral_sim.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970
  1. /*
  2. * Copyright (c) 2015,2017-2019 The Linux Foundation. All rights reserved.
  3. *
  4. *
  5. * Permission to use, copy, modify, and/or distribute this software for
  6. * any purpose with or without fee is hereby granted, provided that the
  7. * above copyright notice and this permission notice appear in all
  8. * copies.
  9. *
  10. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
  11. * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
  12. * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
  13. * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  14. * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  15. * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  16. * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  17. * PERFORMANCE OF THIS SOFTWARE.
  18. */
  19. #ifdef QCA_SUPPORT_SPECTRAL_SIMULATION
  20. #include "target_if_spectral.h"
  21. #include "target_if_spectral_sim.h"
  22. #include "target_if_spectral_sim_int.h"
  23. #include "_ieee80211.h"
  24. #include "ieee80211_api.h"
  25. #include "ieee80211_defines.h"
  26. #include "qdf_types.h"
  27. #include "ieee80211_var.h"
  28. #include <wlan_mlme_dispatcher.h>
  29. #include <qdf_module.h>
  30. /* Helper functions */
  31. static int target_if_populate_report_static_gen2(
  32. struct spectralsim_report *report,
  33. enum phy_ch_width width, bool is_80_80);
  34. static int target_if_populate_report_static_gen3(
  35. struct spectralsim_report *report,
  36. enum phy_ch_width width, bool is_80_80);
  37. static void target_if_depopulate_report(
  38. struct spectralsim_report *report);
  39. static int target_if_populate_reportset_static(
  40. struct spectralsim_context *simctx,
  41. struct spectralsim_reportset *reportset,
  42. enum phy_ch_width width, bool is_80_80);
  43. static void target_if_depopulate_reportset(
  44. struct spectralsim_reportset *
  45. reportset);
  46. static int target_if_populate_simdata(struct spectralsim_context *simctx);
  47. static void target_if_depopulate_simdata(struct spectralsim_context *simctx);
  48. static OS_TIMER_FUNC(target_if_spectral_sim_phyerrdelivery_handler);
  49. /*
  50. * Static configuration.
  51. * For now, we will be having a single configuration per BW, and a single
  52. * report per configuration (since we need the data only for ensuring correct
  53. * format handling).
  54. *
  55. * Extend this for more functionality if required in the future.
  56. */
  57. /**
  58. * target_if_populate_report_static_gen2() - Statically populate simulation
  59. * data for one report for generation 2 chipsets
  60. * @report: Pointer to spectral report data instance
  61. * @width : Channel bandwidth enumeration
  62. * @is_80_80: Whether the channel is operating in 80-80 mode
  63. *
  64. * Statically populate simulation data for one report for generation 2 chipsets
  65. *
  66. * Return: 0 on success, negative error code on failure
  67. */
  68. static int
  69. target_if_populate_report_static_gen2(
  70. struct spectralsim_report *report,
  71. enum phy_ch_width width, bool is_80_80)
  72. {
  73. qdf_assert_always(report);
  74. switch (width) {
  75. case CH_WIDTH_20MHZ:
  76. report->data = NULL;
  77. report->data = (uint8_t *)
  78. qdf_mem_malloc(sizeof(reportdata_20_gen2));
  79. if (!report->data)
  80. goto bad;
  81. report->datasize = sizeof(reportdata_20_gen2);
  82. qdf_mem_copy(report->data,
  83. reportdata_20_gen2, report->datasize);
  84. qdf_mem_copy(&report->rfqual_info,
  85. &rfqual_info_20, sizeof(report->rfqual_info));
  86. qdf_mem_copy(&report->chan_info,
  87. &chan_info_20, sizeof(report->chan_info));
  88. break;
  89. case CH_WIDTH_40MHZ:
  90. report->data = NULL;
  91. report->data = (uint8_t *)
  92. qdf_mem_malloc(sizeof(reportdata_40_gen2));
  93. if (!report->data)
  94. goto bad;
  95. report->datasize = sizeof(reportdata_40_gen2);
  96. qdf_mem_copy(report->data,
  97. reportdata_40_gen2, report->datasize);
  98. qdf_mem_copy(&report->rfqual_info,
  99. &rfqual_info_40, sizeof(report->rfqual_info));
  100. qdf_mem_copy(&report->chan_info,
  101. &chan_info_40, sizeof(report->chan_info));
  102. break;
  103. case CH_WIDTH_80MHZ:
  104. report->data = NULL;
  105. report->data = (uint8_t *)
  106. qdf_mem_malloc(sizeof(reportdata_80_gen2));
  107. if (!report->data)
  108. goto bad;
  109. report->datasize = sizeof(reportdata_80_gen2);
  110. qdf_mem_copy(report->data,
  111. reportdata_80_gen2, report->datasize);
  112. qdf_mem_copy(&report->rfqual_info,
  113. &rfqual_info_80, sizeof(report->rfqual_info));
  114. qdf_mem_copy(&report->chan_info,
  115. &chan_info_80, sizeof(report->chan_info));
  116. break;
  117. case CH_WIDTH_160MHZ:
  118. if (is_80_80) {
  119. report->data = NULL;
  120. report->data = (uint8_t *)
  121. qdf_mem_malloc(sizeof(reportdata_80_80_gen2));
  122. if (!report->data)
  123. goto bad;
  124. report->datasize = sizeof(reportdata_80_80_gen2);
  125. qdf_mem_copy(report->data,
  126. reportdata_80_80_gen2, report->datasize);
  127. qdf_mem_copy(&report->rfqual_info,
  128. &rfqual_info_80_80,
  129. sizeof(report->rfqual_info));
  130. qdf_mem_copy(&report->chan_info,
  131. &chan_info_80_80,
  132. sizeof(report->chan_info));
  133. } else {
  134. report->data = NULL;
  135. report->data = (uint8_t *)
  136. qdf_mem_malloc(sizeof(reportdata_160_gen2));
  137. if (!report->data)
  138. goto bad;
  139. report->datasize = sizeof(reportdata_160_gen2);
  140. qdf_mem_copy(report->data,
  141. reportdata_160_gen2, report->datasize);
  142. qdf_mem_copy(&report->rfqual_info,
  143. &rfqual_info_160,
  144. sizeof(report->rfqual_info));
  145. qdf_mem_copy(&report->chan_info,
  146. &chan_info_160, sizeof(report->chan_info));
  147. }
  148. break;
  149. default:
  150. spectral_err("Unhandled width. Please correct. Asserting");
  151. qdf_assert_always(0);
  152. }
  153. return 0;
  154. bad:
  155. return -EPERM;
  156. }
  157. /**
  158. * target_if_populate_report_static_gen3() - Statically populate simulation
  159. * data for one report for generation 3 chipsets
  160. * @report: Pointer to spectral report data instance
  161. * @width : Channel bandwidth enumeration
  162. * @is_80_80: Whether the channel is operating in 80-80 mode
  163. *
  164. * Statically populate simulation data for one report for generation 3 chipsets
  165. *
  166. * Return: 0 on success, negative error code on failure
  167. */
  168. static int
  169. target_if_populate_report_static_gen3(
  170. struct spectralsim_report *report,
  171. enum phy_ch_width width, bool is_80_80)
  172. {
  173. qdf_assert_always(report);
  174. switch (width) {
  175. case CH_WIDTH_20MHZ:
  176. report->data = NULL;
  177. report->data = (uint8_t *)
  178. qdf_mem_malloc(sizeof(reportdata_20_gen3));
  179. if (!report->data)
  180. goto bad;
  181. report->datasize = sizeof(reportdata_20_gen3);
  182. qdf_mem_copy(report->data,
  183. reportdata_20_gen3, report->datasize);
  184. qdf_mem_copy(&report->rfqual_info,
  185. &rfqual_info_20, sizeof(report->rfqual_info));
  186. qdf_mem_copy(&report->chan_info,
  187. &chan_info_20, sizeof(report->chan_info));
  188. break;
  189. case CH_WIDTH_40MHZ:
  190. report->data = NULL;
  191. report->data = (uint8_t *)
  192. qdf_mem_malloc(sizeof(reportdata_40_gen3));
  193. if (!report->data)
  194. goto bad;
  195. report->datasize = sizeof(reportdata_40_gen3);
  196. qdf_mem_copy(report->data,
  197. reportdata_40_gen3, report->datasize);
  198. qdf_mem_copy(&report->rfqual_info,
  199. &rfqual_info_40, sizeof(report->rfqual_info));
  200. qdf_mem_copy(&report->chan_info,
  201. &chan_info_40, sizeof(report->chan_info));
  202. break;
  203. case CH_WIDTH_80MHZ:
  204. report->data = NULL;
  205. report->data = (uint8_t *)
  206. qdf_mem_malloc(sizeof(reportdata_80_gen3));
  207. if (!report->data)
  208. goto bad;
  209. report->datasize = sizeof(reportdata_80_gen3);
  210. qdf_mem_copy(report->data,
  211. reportdata_80_gen3, report->datasize);
  212. qdf_mem_copy(&report->rfqual_info,
  213. &rfqual_info_80, sizeof(report->rfqual_info));
  214. qdf_mem_copy(&report->chan_info,
  215. &chan_info_80, sizeof(report->chan_info));
  216. break;
  217. case CH_WIDTH_160MHZ:
  218. if (is_80_80) {
  219. report->data = NULL;
  220. report->data = (uint8_t *)
  221. qdf_mem_malloc(sizeof(reportdata_80_80_gen3));
  222. if (!report->data)
  223. goto bad;
  224. report->datasize = sizeof(reportdata_80_80_gen3);
  225. qdf_mem_copy(report->data,
  226. reportdata_80_80_gen3, report->datasize);
  227. qdf_mem_copy(&report->rfqual_info,
  228. &rfqual_info_80_80,
  229. sizeof(report->rfqual_info));
  230. qdf_mem_copy(&report->chan_info,
  231. &chan_info_80_80,
  232. sizeof(report->chan_info));
  233. } else {
  234. report->data = NULL;
  235. report->data = (uint8_t *)
  236. qdf_mem_malloc(sizeof(reportdata_160_gen3));
  237. if (!report->data)
  238. goto bad;
  239. report->datasize = sizeof(reportdata_160_gen3);
  240. qdf_mem_copy(report->data,
  241. reportdata_160_gen3, report->datasize);
  242. qdf_mem_copy(&report->rfqual_info,
  243. &rfqual_info_160,
  244. sizeof(report->rfqual_info));
  245. qdf_mem_copy(&report->chan_info,
  246. &chan_info_160, sizeof(report->chan_info));
  247. }
  248. break;
  249. default:
  250. spectral_err("Unhandled width. Please correct. Asserting");
  251. qdf_assert_always(0);
  252. }
  253. return 0;
  254. bad:
  255. return -EPERM;
  256. }
  257. /**
  258. * target_if_depopulate_report() - Free the given instances of
  259. * struct spectralsim_report
  260. * @report: instance of struct spectralsim_report
  261. *
  262. * Free the given instances of struct spectralsim_report
  263. *
  264. * Return: None
  265. */
  266. static void
  267. target_if_depopulate_report(
  268. struct spectralsim_report *report)
  269. {
  270. if (!report)
  271. return;
  272. if (report->data) {
  273. qdf_mem_free(report->data);
  274. report->data = NULL;
  275. report->datasize = 0;
  276. }
  277. }
  278. /**
  279. * target_if_populate_reportset_static() - Statically populate simulation data
  280. * for a given configuration
  281. * @simctx: Pointer to struct spectralsim_context
  282. * @reportset: Set of spectral report data instances
  283. * @width : Channel bandwidth enumeration
  284. * @is_80_80: Whether the channel is operating in 80+80 mode
  285. *
  286. * Statically populate simulation data for a given configuration
  287. *
  288. * Return: 0 on success, negative error code on failure
  289. */
  290. static int
  291. target_if_populate_reportset_static(
  292. struct spectralsim_context *simctx,
  293. struct spectralsim_reportset *reportset,
  294. enum phy_ch_width width, bool is_80_80)
  295. {
  296. int ret = 0;
  297. struct spectralsim_report *report = NULL;
  298. qdf_assert_always(reportset);
  299. reportset->headreport = NULL;
  300. reportset->curr_report = NULL;
  301. /* For now, we populate only one report */
  302. report = (struct spectralsim_report *)
  303. qdf_mem_malloc(sizeof(struct spectralsim_report));
  304. if (!report)
  305. goto bad;
  306. qdf_mem_zero(report, sizeof(*report));
  307. switch (width) {
  308. case CH_WIDTH_20MHZ:
  309. qdf_mem_copy(&reportset->config,
  310. &config_20_1, sizeof(reportset->config));
  311. ret = simctx->populate_report_static(report, CH_WIDTH_20MHZ, 0);
  312. if (ret != 0)
  313. goto bad;
  314. report->next = NULL;
  315. reportset->headreport = report;
  316. break;
  317. case CH_WIDTH_40MHZ:
  318. qdf_mem_copy(&reportset->config,
  319. &config_40_1, sizeof(reportset->config));
  320. ret = simctx->populate_report_static(report, CH_WIDTH_40MHZ, 0);
  321. if (ret != 0)
  322. goto bad;
  323. report->next = NULL;
  324. reportset->headreport = report;
  325. break;
  326. case CH_WIDTH_80MHZ:
  327. qdf_mem_copy(&reportset->config,
  328. &config_80_1, sizeof(reportset->config));
  329. ret = simctx->populate_report_static(report, CH_WIDTH_80MHZ, 0);
  330. if (ret != 0)
  331. goto bad;
  332. report->next = NULL;
  333. reportset->headreport = report;
  334. break;
  335. case CH_WIDTH_160MHZ:
  336. if (is_80_80) {
  337. qdf_mem_copy(&reportset->config,
  338. &config_80_80_1,
  339. sizeof(reportset->config));
  340. ret = simctx->populate_report_static(report,
  341. CH_WIDTH_160MHZ,
  342. 1);
  343. if (ret != 0)
  344. goto bad;
  345. report->next = NULL;
  346. reportset->headreport = report;
  347. } else {
  348. qdf_mem_copy(&reportset->config,
  349. &config_160_1, sizeof(reportset->config));
  350. ret = simctx->populate_report_static(report,
  351. CH_WIDTH_160MHZ,
  352. 0);
  353. if (ret != 0)
  354. goto bad;
  355. report->next = NULL;
  356. reportset->headreport = report;
  357. }
  358. break;
  359. default:
  360. spectral_err("Unhandled width. Please rectify.");
  361. qdf_assert_always(0);
  362. };
  363. reportset->curr_report = reportset->headreport;
  364. return 0;
  365. bad:
  366. target_if_depopulate_reportset(reportset);
  367. return -EPERM;
  368. }
  369. /**
  370. * target_if_depopulate_reportset() - Free all the instances of
  371. * struct spectralsim_reportset
  372. * @report: head pointer to struct spectralsim_reportset linked list
  373. *
  374. * Free all the instances of struct spectralsim_reportset
  375. *
  376. * Return: None
  377. */
  378. static void
  379. target_if_depopulate_reportset(
  380. struct spectralsim_reportset *reportset)
  381. {
  382. struct spectralsim_report *curr_report = NULL;
  383. struct spectralsim_report *next_report = NULL;
  384. if (!reportset)
  385. return;
  386. curr_report = reportset->headreport;
  387. while (curr_report) {
  388. next_report = curr_report->next;
  389. target_if_depopulate_report(curr_report);
  390. qdf_mem_free(curr_report);
  391. curr_report = next_report;
  392. }
  393. }
  394. /**
  395. * target_if_populate_simdata() - Populate simulation data
  396. * @simctx: Pointer to struct spectralsim_context
  397. *
  398. * Populate simulation data
  399. *
  400. * Return: 0 on success, negative error code on failure
  401. */
  402. static int
  403. target_if_populate_simdata(
  404. struct spectralsim_context *simctx)
  405. {
  406. /*
  407. * For now, we use static population. Switch to loading from a file if
  408. * needed in the future.
  409. */
  410. simctx->bw20_headreportset = NULL;
  411. SPECTRAL_SIM_REPORTSET_ALLOCPOPL_SINGLE(simctx,
  412. simctx->bw20_headreportset,
  413. CH_WIDTH_20MHZ, 0);
  414. simctx->bw40_headreportset = NULL;
  415. SPECTRAL_SIM_REPORTSET_ALLOCPOPL_SINGLE(simctx,
  416. simctx->bw40_headreportset,
  417. CH_WIDTH_40MHZ, 0);
  418. simctx->bw80_headreportset = NULL;
  419. SPECTRAL_SIM_REPORTSET_ALLOCPOPL_SINGLE(simctx,
  420. simctx->bw80_headreportset,
  421. CH_WIDTH_80MHZ, 0);
  422. simctx->bw160_headreportset = NULL;
  423. SPECTRAL_SIM_REPORTSET_ALLOCPOPL_SINGLE(simctx,
  424. simctx->bw160_headreportset,
  425. CH_WIDTH_160MHZ, 0);
  426. simctx->bw80_80_headreportset = NULL;
  427. SPECTRAL_SIM_REPORTSET_ALLOCPOPL_SINGLE(simctx,
  428. simctx->bw80_80_headreportset,
  429. CH_WIDTH_160MHZ, 1);
  430. simctx->curr_reportset = NULL;
  431. simctx->is_enabled = false;
  432. simctx->is_active = false;
  433. simctx->ssim_starting_tsf64 = 0;
  434. simctx->ssim_count = 0;
  435. simctx->ssim_period_ms = 0;
  436. return 0;
  437. }
  438. /**
  439. * target_if_depopulate_simdata() - De-populate simulation data
  440. * @simctx: Pointer to struct spectralsim_context
  441. *
  442. * De-populate simulation data
  443. *
  444. * Return: none
  445. */
  446. static void
  447. target_if_depopulate_simdata(
  448. struct spectralsim_context *simctx)
  449. {
  450. if (!simctx)
  451. return;
  452. SPECTRAL_SIM_REPORTSET_DEPOPLFREE_LIST(simctx->bw20_headreportset);
  453. SPECTRAL_SIM_REPORTSET_DEPOPLFREE_LIST(simctx->bw40_headreportset);
  454. SPECTRAL_SIM_REPORTSET_DEPOPLFREE_LIST(simctx->bw80_headreportset);
  455. SPECTRAL_SIM_REPORTSET_DEPOPLFREE_LIST(simctx->bw160_headreportset);
  456. SPECTRAL_SIM_REPORTSET_DEPOPLFREE_LIST(simctx->bw80_80_headreportset);
  457. }
  458. /**
  459. * target_if_spectral_sim_phyerrdelivery_handler() - Phyerr delivery handler
  460. *
  461. * Return: none
  462. */
  463. static
  464. OS_TIMER_FUNC(target_if_spectral_sim_phyerrdelivery_handler)
  465. {
  466. struct target_if_spectral *spectral = NULL;
  467. struct spectralsim_context *simctx = NULL;
  468. struct spectralsim_reportset *curr_reportset = NULL;
  469. struct spectralsim_report *curr_report = NULL;
  470. struct target_if_spectral_acs_stats acs_stats;
  471. uint64_t curr_tsf64 = 0;
  472. struct target_if_spectral_ops *p_sops;
  473. OS_GET_TIMER_ARG(spectral, struct target_if_spectral *);
  474. qdf_assert_always(spectral);
  475. p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral);
  476. qdf_assert_always(spectral);
  477. simctx = (struct spectralsim_context *)spectral->simctx;
  478. qdf_assert_always(simctx);
  479. if (!simctx->is_active)
  480. return;
  481. curr_reportset = simctx->curr_reportset;
  482. qdf_assert_always(curr_reportset);
  483. curr_report = curr_reportset->curr_report;
  484. qdf_assert_always(curr_report);
  485. qdf_assert_always(curr_reportset->headreport);
  486. /*
  487. * We use a simulation TSF since in offload architectures we can't
  488. * expect to
  489. * get an accurate current TSF from HW.
  490. * In case of TSF wrap over, we'll use it as-is for now since the
  491. * simulation
  492. * is intended only for format verification.
  493. */
  494. curr_tsf64 = simctx->ssim_starting_tsf64 +
  495. ((simctx->ssim_period_ms * simctx->ssim_count) * 1000);
  496. p_sops->spectral_process_phyerr(spectral,
  497. curr_report->data,
  498. curr_report->datasize,
  499. &curr_report->rfqual_info,
  500. &curr_report->chan_info,
  501. curr_tsf64, &acs_stats);
  502. simctx->ssim_count++;
  503. if (curr_report->next)
  504. curr_reportset->curr_report = curr_report->next;
  505. else
  506. curr_reportset->curr_report = curr_reportset->headreport;
  507. if (curr_reportset->config.ss_count != 0 &&
  508. simctx->ssim_count == curr_reportset->config.ss_count) {
  509. target_if_spectral_sops_sim_stop_scan(spectral);
  510. } else {
  511. qdf_timer_start(&simctx->ssim_pherrdelivery_timer,
  512. simctx->ssim_period_ms);
  513. }
  514. }
  515. /* Module services */
  516. int
  517. target_if_spectral_sim_attach(struct target_if_spectral *spectral)
  518. {
  519. struct spectralsim_context *simctx = NULL;
  520. qdf_assert_always(spectral);
  521. simctx = (struct spectralsim_context *)
  522. qdf_mem_malloc(sizeof(struct spectralsim_context));
  523. if (!simctx)
  524. return -EPERM;
  525. qdf_mem_zero(simctx, sizeof(*simctx));
  526. spectral->simctx = simctx;
  527. if (spectral->spectral_gen == SPECTRAL_GEN2)
  528. simctx->populate_report_static =
  529. target_if_populate_report_static_gen2;
  530. else if (spectral->spectral_gen == SPECTRAL_GEN3)
  531. simctx->populate_report_static =
  532. target_if_populate_report_static_gen3;
  533. if (target_if_populate_simdata(simctx) != 0) {
  534. qdf_mem_free(simctx);
  535. spectral->simctx = NULL;
  536. spectral_err("Spectral simulation attach failed");
  537. return -EPERM;
  538. }
  539. qdf_timer_init(NULL,
  540. &simctx->ssim_pherrdelivery_timer,
  541. target_if_spectral_sim_phyerrdelivery_handler,
  542. (void *)(spectral), QDF_TIMER_TYPE_WAKE_APPS);
  543. spectral_info("Spectral simulation attached");
  544. return 0;
  545. }
  546. void
  547. target_if_spectral_sim_detach(struct target_if_spectral *spectral)
  548. {
  549. struct spectralsim_context *simctx = NULL;
  550. qdf_assert_always(spectral);
  551. simctx = (struct spectralsim_context *)spectral->simctx;
  552. qdf_assert_always(simctx);
  553. qdf_timer_free(&simctx->ssim_pherrdelivery_timer);
  554. target_if_depopulate_simdata(simctx);
  555. qdf_mem_free(simctx);
  556. spectral->simctx = NULL;
  557. spectral_info("Spectral simulation detached");
  558. }
  559. uint32_t
  560. target_if_spectral_sops_sim_is_active(void *arg)
  561. {
  562. struct target_if_spectral *spectral = NULL;
  563. struct spectralsim_context *simctx = NULL;
  564. spectral = (struct target_if_spectral *)arg;
  565. qdf_assert_always(spectral);
  566. simctx = (struct spectralsim_context *)spectral->simctx;
  567. qdf_assert_always(simctx);
  568. return simctx->is_active;
  569. }
  570. qdf_export_symbol(target_if_spectral_sops_sim_is_active);
  571. uint32_t
  572. target_if_spectral_sops_sim_is_enabled(void *arg)
  573. {
  574. struct target_if_spectral *spectral = NULL;
  575. struct spectralsim_context *simctx = NULL;
  576. spectral = (struct target_if_spectral *)arg;
  577. qdf_assert_always(spectral);
  578. simctx = (struct spectralsim_context *)spectral->simctx;
  579. qdf_assert_always(simctx);
  580. return simctx->is_enabled;
  581. }
  582. qdf_export_symbol(target_if_spectral_sops_sim_is_enabled);
  583. uint32_t
  584. target_if_spectral_sops_sim_start_scan(void *arg)
  585. {
  586. struct target_if_spectral *spectral = NULL;
  587. struct spectralsim_context *simctx = NULL;
  588. spectral = (struct target_if_spectral *)arg;
  589. qdf_assert_always(spectral);
  590. simctx = (struct spectralsim_context *)spectral->simctx;
  591. qdf_assert_always(simctx);
  592. if (!simctx->curr_reportset) {
  593. spectral_err("Spectral simulation: No current report set configured - unable to start simulated Spectral scan");
  594. return 0;
  595. }
  596. if (!simctx->curr_reportset->curr_report) {
  597. spectral_err("Spectral simulation: No report data instances populated - unable to start simulated Spectral scan");
  598. return 0;
  599. }
  600. if (!simctx->is_enabled)
  601. simctx->is_enabled = true;
  602. simctx->is_active = true;
  603. /* Hardcoding current time as zero since it is simulation */
  604. simctx->ssim_starting_tsf64 = 0;
  605. simctx->ssim_count = 0;
  606. /*
  607. * TODO: Support high resolution timer in microseconds if required, so
  608. * that
  609. * we can support default periods such as ~200 us. For now, we use 1
  610. * millisecond since the current use case for the simulation is to
  611. * validate
  612. * formats rather than have a time dependent classification.
  613. */
  614. simctx->ssim_period_ms = 1;
  615. qdf_timer_start(&simctx->ssim_pherrdelivery_timer,
  616. simctx->ssim_period_ms);
  617. return 1;
  618. }
  619. qdf_export_symbol(target_if_spectral_sops_sim_start_scan);
  620. uint32_t
  621. target_if_spectral_sops_sim_stop_scan(void *arg)
  622. {
  623. struct target_if_spectral *spectral = NULL;
  624. struct spectralsim_context *simctx = NULL;
  625. spectral = (struct target_if_spectral *)arg;
  626. qdf_assert_always(spectral);
  627. simctx = (struct spectralsim_context *)spectral->simctx;
  628. qdf_assert_always(simctx);
  629. qdf_timer_stop(&simctx->ssim_pherrdelivery_timer);
  630. simctx->is_active = false;
  631. simctx->is_enabled = false;
  632. simctx->ssim_starting_tsf64 = 0;
  633. simctx->ssim_count = 0;
  634. simctx->ssim_period_ms = 0;
  635. return 1;
  636. }
  637. qdf_export_symbol(target_if_spectral_sops_sim_stop_scan);
  638. #ifdef SPECTRAL_SIM_DUMP_PARAM_DATA
  639. static void
  640. target_if_log_sim_spectral_params(struct spectral_config *params)
  641. {
  642. int i = 0;
  643. spectral_debug("\n");
  644. spectral_debug("Spectral simulation: Param data dump:\nss_fft_period=%hu\nss_period=%hu\nss_count=%hu\nss_short_report=%hu\nradar_bin_thresh_sel=%hhu\nss_spectral_pri=%hu\nss_fft_size=%hu\nss_gc_ena=%hu\nss_restart_ena=%hu\nss_noise_floor_ref=%hu\nss_init_delay=%hu\nss_nb_tone_thr=%hu\nss_str_bin_thr=%hu\nss_wb_rpt_mode=%hu\nss_rssi_rpt_mode=%hu\nss_rssi_thr=%hu\nss_pwr_format=%hu\nss_rpt_mode=%hu\nss_bin_scale=%hu\nss_dbm_adj=%hu\nss_chn_mask=%hu\nss_nf_temp_data=%d",
  645. params->ss_fft_period,
  646. params->ss_period,
  647. params->ss_count,
  648. params->ss_short_report,
  649. params->radar_bin_thresh_sel,
  650. params->ss_spectral_pri,
  651. params->ss_fft_size,
  652. params->ss_gc_ena,
  653. params->ss_restart_ena,
  654. params->ss_noise_floor_ref,
  655. params->ss_init_delay,
  656. params->ss_nb_tone_thr,
  657. params->ss_str_bin_thr,
  658. params->ss_wb_rpt_mode,
  659. params->ss_rssi_rpt_mode,
  660. params->ss_rssi_thr,
  661. params->ss_pwr_format,
  662. params->ss_rpt_mode,
  663. params->ss_bin_scale,
  664. params->ss_dbm_adj,
  665. params->ss_chn_mask, params->ss_nf_temp_data);
  666. for (i = 0; i < AH_MAX_CHAINS * 2; i++)
  667. spectral_debug("ss_nf_cal[%d]=%hhd", i, params->ss_nf_cal[i]);
  668. for (i = 0; i < AH_MAX_CHAINS * 2; i++)
  669. spectral_debug("ss_nf_pwr[%d]=%hhd", i, params->ss_nf_pwr[i]);
  670. spectral_info("\n");
  671. }
  672. #else
  673. static void
  674. target_if_log_sim_spectral_params(struct spectral_config *params)
  675. {
  676. }
  677. #endif /* SPECTRAL_SIM_DUMP_PARAM_DATA */
  678. uint32_t
  679. target_if_spectral_sops_sim_configure_params(
  680. void *arg,
  681. struct spectral_config *params)
  682. {
  683. struct target_if_spectral *spectral = NULL;
  684. struct spectralsim_context *simctx = NULL;
  685. enum wlan_phymode phymode;
  686. uint8_t bw;
  687. struct spectralsim_reportset *des_headreportset = NULL;
  688. struct spectralsim_reportset *temp_reportset = NULL;
  689. bool is_invalid_width = false;
  690. struct wlan_objmgr_vdev *vdev = NULL;
  691. qdf_assert_always(params);
  692. target_if_log_sim_spectral_params(params);
  693. spectral = (struct target_if_spectral *)arg;
  694. qdf_assert_always(spectral);
  695. simctx = (struct spectralsim_context *)spectral->simctx;
  696. qdf_assert_always(simctx);
  697. vdev = target_if_spectral_get_vdev(spectral);
  698. if (!vdev) {
  699. spectral_warn("Spectral simulation: No VAPs found - not proceeding with param config.");
  700. return 0;
  701. }
  702. bw = target_if_vdev_get_ch_width(vdev);
  703. switch (bw) {
  704. case CH_WIDTH_20MHZ:
  705. des_headreportset = simctx->bw20_headreportset;
  706. break;
  707. case CH_WIDTH_40MHZ:
  708. des_headreportset = simctx->bw40_headreportset;
  709. break;
  710. case CH_WIDTH_80MHZ:
  711. des_headreportset = simctx->bw80_headreportset;
  712. break;
  713. case CH_WIDTH_160MHZ:
  714. phymode = wlan_vdev_get_phymode(vdev);
  715. if (phymode == WLAN_PHYMODE_11AC_VHT160) {
  716. des_headreportset = simctx->bw160_headreportset;
  717. } else if (phymode == WLAN_PHYMODE_11AC_VHT80_80) {
  718. des_headreportset = simctx->bw80_80_headreportset;
  719. } else {
  720. spectral_err("Spectral simulation: Unexpected PHY mode %u found for width 160 MHz...asserting.",
  721. phymode);
  722. qdf_assert_always(0);
  723. }
  724. break;
  725. case IEEE80211_CWM_WIDTHINVALID:
  726. spectral_err("Spectral simulation: Invalid width configured - not proceeding with param config.");
  727. is_invalid_width = true;
  728. default:
  729. spectral_err("Spectral simulation: Unknown width %u...asserting",
  730. bw);
  731. qdf_assert_always(0);
  732. break;
  733. }
  734. wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
  735. if (is_invalid_width)
  736. return 0;
  737. if (!des_headreportset) {
  738. spectral_warn("Spectral simulation: No simulation data present for configured bandwidth/PHY mode - unable to proceed with param config.");
  739. return 0;
  740. }
  741. simctx->curr_reportset = NULL;
  742. temp_reportset = des_headreportset;
  743. while (temp_reportset) {
  744. if (qdf_mem_cmp(&temp_reportset->config,
  745. params, sizeof(struct spectral_config)) == 0) {
  746. /* Found a matching config. We are done. */
  747. simctx->curr_reportset = temp_reportset;
  748. break;
  749. }
  750. temp_reportset = temp_reportset->next;
  751. }
  752. if (!simctx->curr_reportset) {
  753. spectral_warn("Spectral simulation: No simulation data present for desired Spectral configuration - unable to proceed with param config.");
  754. return 0;
  755. }
  756. if (!simctx->curr_reportset->curr_report) {
  757. spectral_warn("Spectral simulation: No report data instances populated for desired Spectral configuration - unable to proceed with param config");
  758. return 0;
  759. }
  760. return 1;
  761. }
  762. qdf_export_symbol(target_if_spectral_sops_sim_configure_params);
  763. uint32_t
  764. target_if_spectral_sops_sim_get_params(
  765. void *arg, struct spectral_config *params)
  766. {
  767. struct target_if_spectral *spectral = NULL;
  768. struct spectralsim_context *simctx = NULL;
  769. qdf_assert_always(params);
  770. spectral = (struct target_if_spectral *)arg;
  771. qdf_assert_always(spectral);
  772. simctx = (struct spectralsim_context *)spectral->simctx;
  773. qdf_assert_always(simctx);
  774. if (!simctx->curr_reportset) {
  775. spectral_warn("Spectral simulation: No configured reportset found.");
  776. return 0;
  777. }
  778. qdf_mem_copy(params, &simctx->curr_reportset->config, sizeof(*params));
  779. return 1;
  780. }
  781. qdf_export_symbol(target_if_spectral_sops_sim_get_params);
  782. #endif /* QCA_SUPPORT_SPECTRAL_SIMULATION */