target_if_spectral_sim.c 25 KB

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