target_if_spectral_sim.c 26 KB

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