wifi_pos_main.c 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242
  1. /*
  2. * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
  3. * Copyright (c) 2021-2022 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. /**
  20. * DOC: wifi_pos_main.c
  21. * This file defines the important functions pertinent to
  22. * wifi positioning to initialize and de-initialize the component.
  23. */
  24. #include <wlan_lmac_if_def.h>
  25. #include "target_if_wifi_pos.h"
  26. #include "wifi_pos_oem_interface_i.h"
  27. #include "wifi_pos_utils_i.h"
  28. #include "wifi_pos_api.h"
  29. #include "wifi_pos_main_i.h"
  30. #include "wifi_pos_ucfg_i.h"
  31. #include "wlan_objmgr_cmn.h"
  32. #include "wlan_objmgr_global_obj.h"
  33. #include "wlan_objmgr_psoc_obj.h"
  34. #include "wlan_objmgr_pdev_obj.h"
  35. #include "wlan_objmgr_vdev_obj.h"
  36. #include "wlan_ptt_sock_svc.h"
  37. #include "target_if.h"
  38. #include "wlan_objmgr_peer_obj.h"
  39. #ifndef CNSS_GENL
  40. #include <wlan_objmgr_global_obj_i.h>
  41. #endif
  42. #include "wlan_reg_services_api.h"
  43. /* forward declartion */
  44. struct regulatory_channel;
  45. #define REG_SET_CHANNEL_REG_POWER(reg_info_1, val) do { \
  46. reg_info_1 &= 0xff00ffff; \
  47. reg_info_1 |= ((val & 0xff) << 16); \
  48. } while (0)
  49. /* max tx power is in 1 dBm units */
  50. #define REG_SET_CHANNEL_MAX_TX_POWER(reg_info_2, val) do { \
  51. reg_info_2 &= 0xffff00ff; \
  52. reg_info_2 |= ((val & 0xff) << 8); \
  53. } while (0)
  54. /* channel info consists of 6 bits of channel mode */
  55. #define REG_SET_CHANNEL_MODE(reg_channel, val) do { \
  56. (reg_channel)->info &= 0xffffffc0; \
  57. (reg_channel)->info |= (val); \
  58. } while (0)
  59. /*
  60. * obj mgr api to iterate over vdevs does not provide a direct array or vdevs,
  61. * rather takes a callback that is called for every vdev. wifi pos needs to
  62. * store device mode and vdev id of all active vdevs and provide this info to
  63. * user space as part of APP registration response. due to this, vdev_idx is
  64. * used to identify how many vdevs have been populated by obj manager API.
  65. */
  66. static uint32_t vdev_idx;
  67. /**
  68. * wifi_pos_get_tlv_support: indicates if firmware supports TLV wifi pos msg
  69. * @psoc: psoc object
  70. *
  71. * Return: status of operation
  72. */
  73. static bool wifi_pos_get_tlv_support(struct wlan_objmgr_psoc *psoc)
  74. {
  75. /* this is TBD */
  76. return true;
  77. }
  78. #ifdef CNSS_GENL
  79. static uint8_t *
  80. wifi_pos_prepare_reg_resp(uint32_t *rsp_len,
  81. struct app_reg_rsp_vdev_info *vdevs_info)
  82. {
  83. uint32_t *nl_sign;
  84. uint8_t *resp_buf;
  85. struct wifi_app_reg_rsp *app_reg_rsp;
  86. /*
  87. * allocate ENHNC_FLAGS_LEN i.e. 4bytes extra memory in app_reg_resp
  88. * to indicate NLA type response is supported for OEM request
  89. * commands.
  90. */
  91. *rsp_len = (sizeof(struct app_reg_rsp_vdev_info) * vdev_idx)
  92. + sizeof(uint8_t) + ENHNC_FLAGS_LEN;
  93. resp_buf = qdf_mem_malloc(*rsp_len);
  94. if (!resp_buf)
  95. return NULL;
  96. app_reg_rsp = (struct wifi_app_reg_rsp *)resp_buf;
  97. app_reg_rsp->num_inf = vdev_idx;
  98. qdf_mem_copy(&app_reg_rsp->vdevs, vdevs_info,
  99. sizeof(struct app_reg_rsp_vdev_info) * vdev_idx);
  100. nl_sign = (uint32_t *)&app_reg_rsp->vdevs[vdev_idx];
  101. *nl_sign |= NL_ENABLE_OEM_REQ_RSP;
  102. return resp_buf;
  103. }
  104. /**
  105. * wifi_pos_get_host_pdev_id: Get host pdev_id
  106. * @psoc: Pointer to psoc object
  107. * @tgt_pdev_id: target_pdev_id
  108. * @host_pdev_id: host pdev_id
  109. *
  110. * Return: QDF_STATUS_SUCCESS in case of success, error codes in case of failure
  111. */
  112. static QDF_STATUS wifi_pos_get_host_pdev_id(
  113. struct wlan_objmgr_psoc *psoc, uint32_t tgt_pdev_id,
  114. uint32_t *host_pdev_id)
  115. {
  116. /* pdev_id in FW starts from 1. So convert it to
  117. * host id by decrementing it.
  118. * zero has special meaning due to backward
  119. * compatibility. Dont change it.
  120. */
  121. if (tgt_pdev_id)
  122. *host_pdev_id = tgt_pdev_id - 1;
  123. else
  124. *host_pdev_id = tgt_pdev_id;
  125. return QDF_STATUS_SUCCESS;
  126. }
  127. #else
  128. static uint8_t *
  129. wifi_pos_prepare_reg_resp(uint32_t *rsp_len,
  130. struct app_reg_rsp_vdev_info *vdevs_info)
  131. {
  132. uint8_t *resp_buf;
  133. struct wifi_app_reg_rsp *app_reg_rsp;
  134. *rsp_len = (sizeof(struct app_reg_rsp_vdev_info) * vdev_idx)
  135. + sizeof(uint8_t);
  136. resp_buf = qdf_mem_malloc(*rsp_len);
  137. if (!resp_buf)
  138. return NULL;
  139. app_reg_rsp = (struct wifi_app_reg_rsp *)resp_buf;
  140. app_reg_rsp->num_inf = vdev_idx;
  141. qdf_mem_copy(&app_reg_rsp->vdevs, vdevs_info,
  142. sizeof(struct app_reg_rsp_vdev_info) * vdev_idx);
  143. return resp_buf;
  144. }
  145. static QDF_STATUS wifi_pos_get_host_pdev_id(
  146. struct wlan_objmgr_psoc *psoc, uint32_t tgt_pdev_id,
  147. uint32_t *host_pdev_id)
  148. {
  149. struct wlan_lmac_if_wifi_pos_tx_ops *tx_ops;
  150. tx_ops = wifi_pos_get_tx_ops(psoc);
  151. if (!tx_ops) {
  152. qdf_print("tx ops null");
  153. return QDF_STATUS_E_NULL_VALUE;
  154. }
  155. if (!tx_ops->wifi_pos_convert_pdev_id_target_to_host) {
  156. wifi_pos_err("wifi_pos_convert_pdev_id_target_to_host is null");
  157. return QDF_STATUS_E_NULL_VALUE;
  158. }
  159. return tx_ops->wifi_pos_convert_pdev_id_target_to_host(
  160. psoc, tgt_pdev_id, host_pdev_id);
  161. }
  162. #endif
  163. static QDF_STATUS wifi_pos_process_data_req(struct wlan_objmgr_psoc *psoc,
  164. struct wifi_pos_req_msg *req)
  165. {
  166. uint8_t idx;
  167. uint32_t sub_type = 0;
  168. uint32_t channel_mhz = 0;
  169. uint32_t host_pdev_id = 0, tgt_pdev_id = 0;
  170. uint32_t offset;
  171. struct oem_data_req data_req;
  172. struct wlan_lmac_if_wifi_pos_tx_ops *tx_ops;
  173. struct wlan_objmgr_pdev *pdev;
  174. struct wifi_pos_psoc_priv_obj *wifi_pos_obj =
  175. wifi_pos_get_psoc_priv_obj(wifi_pos_get_psoc());
  176. QDF_STATUS status;
  177. uint8_t err;
  178. if (!wifi_pos_obj) {
  179. wifi_pos_err("wifi_pos priv obj is null");
  180. return QDF_STATUS_E_INVAL;
  181. }
  182. wifi_pos_debug("Received data req pid(%d), len(%d)",
  183. req->pid, req->buf_len);
  184. /* look for fields */
  185. if (req->field_info_buf)
  186. for (idx = 0; idx < req->field_info_buf->count; idx++) {
  187. offset = req->field_info_buf->fields[idx].offset;
  188. /*
  189. * replace following reads with read_api based on
  190. * length
  191. */
  192. if (req->field_info_buf->fields[idx].id ==
  193. META_DATA_SUB_TYPE) {
  194. sub_type = *((uint32_t *)&req->buf[offset]);
  195. continue;
  196. }
  197. if (req->field_info_buf->fields[idx].id ==
  198. META_DATA_CHANNEL_MHZ) {
  199. channel_mhz = *((uint32_t *)&req->buf[offset]);
  200. continue;
  201. }
  202. if (req->field_info_buf->fields[idx].id ==
  203. META_DATA_PDEV) {
  204. tgt_pdev_id = *((uint32_t *)&req->buf[offset]);
  205. status = wifi_pos_get_host_pdev_id(
  206. psoc, tgt_pdev_id,
  207. &host_pdev_id);
  208. if (QDF_IS_STATUS_ERROR(status)) {
  209. wifi_pos_err("failed to get host pdev_id, tgt_pdev_id = %d",
  210. tgt_pdev_id);
  211. return QDF_STATUS_E_INVAL;
  212. }
  213. continue;
  214. }
  215. }
  216. switch (sub_type) {
  217. case TARGET_OEM_CAPABILITY_REQ:
  218. /* TBD */
  219. break;
  220. case TARGET_OEM_CONFIGURE_LCR:
  221. /* TBD */
  222. break;
  223. case TARGET_OEM_CONFIGURE_LCI:
  224. /* TBD */
  225. break;
  226. case TARGET_OEM_MEASUREMENT_REQ:
  227. /* TBD */
  228. break;
  229. case TARGET_OEM_CONFIGURE_FTMRR:
  230. wifi_pos_debug("FTMRR request");
  231. if (wifi_pos_obj->wifi_pos_send_action)
  232. wifi_pos_obj->wifi_pos_send_action(psoc, sub_type,
  233. req->buf,
  234. req->buf_len);
  235. break;
  236. case TARGET_OEM_CONFIGURE_WRU:
  237. wifi_pos_debug("WRU request");
  238. if (wifi_pos_obj->wifi_pos_send_action)
  239. wifi_pos_obj->wifi_pos_send_action(psoc, sub_type,
  240. req->buf,
  241. req->buf_len);
  242. break;
  243. default:
  244. wifi_pos_debug("invalid sub type or not passed");
  245. tx_ops = wifi_pos_get_tx_ops(psoc);
  246. if (!tx_ops) {
  247. wifi_pos_err("tx ops null");
  248. return QDF_STATUS_E_INVAL;
  249. }
  250. pdev = wlan_objmgr_get_pdev_by_id(psoc, host_pdev_id,
  251. WLAN_WIFI_POS_CORE_ID);
  252. if (!pdev) {
  253. wifi_pos_err("pdev null");
  254. return QDF_STATUS_E_INVAL;
  255. }
  256. status = ucfg_wifi_pos_measurement_request_notification(
  257. pdev, req);
  258. if (QDF_IS_STATUS_ERROR(status)) {
  259. err = OEM_ERR_REQUEST_REJECTED;
  260. wifi_pos_obj->wifi_pos_send_rsp(
  261. psoc, wifi_pos_get_app_pid(psoc),
  262. WIFI_POS_CMD_ERROR, sizeof(err), &err);
  263. wlan_objmgr_pdev_release_ref(pdev,
  264. WLAN_WIFI_POS_CORE_ID);
  265. return QDF_STATUS_E_INVAL;
  266. }
  267. data_req.data_len = req->buf_len;
  268. data_req.data = req->buf;
  269. tx_ops->data_req_tx(pdev, &data_req);
  270. wlan_objmgr_pdev_release_ref(pdev,
  271. WLAN_WIFI_POS_CORE_ID);
  272. break;
  273. }
  274. return QDF_STATUS_SUCCESS;
  275. }
  276. static QDF_STATUS wifi_pos_process_set_cap_req(struct wlan_objmgr_psoc *psoc,
  277. struct wifi_pos_req_msg *req)
  278. {
  279. int error_code;
  280. struct wifi_pos_psoc_priv_obj *wifi_pos_obj =
  281. wifi_pos_get_psoc_priv_obj(psoc);
  282. struct wifi_pos_user_defined_caps *caps =
  283. (struct wifi_pos_user_defined_caps *)req->buf;
  284. if (!wifi_pos_obj) {
  285. wifi_pos_err("wifi_pos priv obj is null");
  286. return QDF_STATUS_E_INVAL;
  287. }
  288. wifi_pos_debug("Received set cap req pid(%d), len(%d)",
  289. req->pid, req->buf_len);
  290. wifi_pos_obj->ftm_rr = caps->ftm_rr;
  291. wifi_pos_obj->lci_capability = caps->lci_capability;
  292. error_code = qdf_status_to_os_return(QDF_STATUS_SUCCESS);
  293. wifi_pos_obj->wifi_pos_send_rsp(psoc, wifi_pos_obj->app_pid,
  294. WIFI_POS_CMD_SET_CAPS,
  295. sizeof(error_code),
  296. (uint8_t *)&error_code);
  297. return QDF_STATUS_SUCCESS;
  298. }
  299. static QDF_STATUS wifi_pos_process_get_cap_req(struct wlan_objmgr_psoc *psoc,
  300. struct wifi_pos_req_msg *req)
  301. {
  302. struct wifi_pos_oem_get_cap_rsp cap_rsp = { { {0} } };
  303. struct wifi_pos_psoc_priv_obj *wifi_pos_obj =
  304. wifi_pos_get_psoc_priv_obj(psoc);
  305. if (!wifi_pos_obj) {
  306. wifi_pos_err("wifi_pos priv obj is null");
  307. return QDF_STATUS_E_INVAL;
  308. }
  309. wifi_pos_debug("Received get cap req pid(%d), len(%d)",
  310. req->pid, req->buf_len);
  311. wifi_pos_populate_caps(psoc, &cap_rsp.driver_cap);
  312. cap_rsp.user_defined_cap.ftm_rr = wifi_pos_obj->ftm_rr;
  313. cap_rsp.user_defined_cap.lci_capability = wifi_pos_obj->lci_capability;
  314. wifi_pos_obj->wifi_pos_send_rsp(psoc, wifi_pos_obj->app_pid,
  315. WIFI_POS_CMD_GET_CAPS,
  316. sizeof(cap_rsp),
  317. (uint8_t *)&cap_rsp);
  318. return QDF_STATUS_SUCCESS;
  319. }
  320. QDF_STATUS wifi_pos_send_report_resp(struct wlan_objmgr_psoc *psoc,
  321. int req_id, uint8_t *dest_mac,
  322. int err_code)
  323. {
  324. struct wifi_pos_err_msg_report err_report = {0};
  325. struct wifi_pos_psoc_priv_obj *wifi_pos_obj =
  326. wifi_pos_get_psoc_priv_obj(psoc);
  327. if (!wifi_pos_obj) {
  328. wifi_pos_err("wifi_pos priv obj is null");
  329. return QDF_STATUS_E_INVAL;
  330. }
  331. err_report.msg_tag_len = OEM_MSG_RSP_HEAD_TAG_ID << 16;
  332. err_report.msg_tag_len |= (sizeof(err_report) -
  333. sizeof(err_report.err_rpt)) & 0x0000FFFF;
  334. err_report.msg_subtype = TARGET_OEM_ERROR_REPORT_RSP;
  335. err_report.req_id = req_id & 0xFFFF;
  336. err_report.req_id |= ((err_code & 0xFF) << 16);
  337. err_report.req_id |= (0x1 << 24);
  338. err_report.time_left = 0xFFFFFFFF;
  339. err_report.err_rpt.tag_len = OEM_MEAS_RSP_HEAD_TAG_ID << 16;
  340. err_report.err_rpt.tag_len |=
  341. (sizeof(struct wifi_pos_err_rpt)) & 0x0000FFFF;
  342. memcpy(&err_report.err_rpt.dest_mac, dest_mac, QDF_MAC_ADDR_SIZE);
  343. wifi_pos_obj->wifi_pos_send_rsp(psoc, wifi_pos_obj->app_pid,
  344. WIFI_POS_CMD_OEM_DATA,
  345. sizeof(err_report),
  346. (uint8_t *)&err_report);
  347. return QDF_STATUS_SUCCESS;
  348. }
  349. static QDF_STATUS wifi_pos_get_vht_ch_width(struct wlan_objmgr_psoc *psoc,
  350. enum phy_ch_width *ch_width)
  351. {
  352. struct wlan_lmac_if_wifi_pos_tx_ops *tx_ops;
  353. tx_ops = wifi_pos_get_tx_ops(psoc);
  354. if (!tx_ops) {
  355. qdf_print("tx ops null");
  356. return QDF_STATUS_E_NULL_VALUE;
  357. }
  358. if (!tx_ops->wifi_pos_get_vht_ch_width) {
  359. wifi_pos_err("wifi pos get vht ch width is null");
  360. return QDF_STATUS_E_NULL_VALUE;
  361. }
  362. return tx_ops->wifi_pos_get_vht_ch_width(
  363. psoc, ch_width);
  364. }
  365. static void wifi_update_channel_bw_info(struct wlan_objmgr_psoc *psoc,
  366. struct wlan_objmgr_pdev *pdev,
  367. uint16_t freq,
  368. struct wifi_pos_channel_power *chan)
  369. {
  370. struct ch_params ch_params = {0};
  371. uint16_t sec_ch_2g = 0;
  372. struct wifi_pos_psoc_priv_obj *wifi_pos_psoc =
  373. wifi_pos_get_psoc_priv_obj(wifi_pos_get_psoc());
  374. uint32_t phy_mode;
  375. QDF_STATUS status;
  376. if (!wifi_pos_psoc) {
  377. wifi_pos_err("wifi_pos priv obj is null");
  378. return;
  379. }
  380. status = wifi_pos_get_vht_ch_width(psoc, &ch_params.ch_width);
  381. if (QDF_IS_STATUS_ERROR(status)) {
  382. wifi_pos_err("can not get vht ch width");
  383. return;
  384. }
  385. wlan_reg_set_channel_params_for_pwrmode(pdev, freq, sec_ch_2g,
  386. &ch_params,
  387. REG_CURRENT_PWR_MODE);
  388. chan->band_center_freq1 = ch_params.mhz_freq_seg0;
  389. if (wifi_pos_psoc->wifi_pos_get_fw_phy_mode_for_freq) {
  390. wifi_pos_psoc->wifi_pos_get_fw_phy_mode_for_freq(
  391. freq, ch_params.ch_width, &phy_mode);
  392. chan->phy_mode = phy_mode;
  393. }
  394. }
  395. /**
  396. * wifi_pos_get_valid_channels: Get the list of valid channels from the
  397. * given channel list
  398. * @chan_freqs: Channel frequencies to be validated
  399. * @num_ch: NUmber of channels in the channel list to be validated
  400. * @valid_channel_list: Pointer to valid channel list
  401. *
  402. * Return: Number of valid channels in the given list
  403. */
  404. static uint32_t wifi_pos_get_valid_channels(qdf_freq_t *chan_freqs,
  405. uint32_t num_ch,
  406. qdf_freq_t *valid_channel_list)
  407. {
  408. uint32_t i, num_valid_channels = 0;
  409. for (i = 0; i < num_ch; i++) {
  410. if (wlan_reg_get_chan_enum_for_freq(chan_freqs[i]) ==
  411. INVALID_CHANNEL)
  412. continue;
  413. valid_channel_list[num_valid_channels++] = chan_freqs[i];
  414. }
  415. return num_valid_channels;
  416. }
  417. static void wifi_pos_pdev_iterator(struct wlan_objmgr_psoc *psoc,
  418. void *obj, void *arg)
  419. {
  420. QDF_STATUS status;
  421. uint8_t num_channels;
  422. struct wlan_objmgr_pdev *pdev = obj;
  423. struct wifi_pos_channel_list *chan_list = arg;
  424. struct channel_power *ch_info = NULL;
  425. struct wifi_pos_channel_power *wifi_pos_ch;
  426. int i;
  427. struct wifi_pos_psoc_priv_obj *wifi_pos_psoc =
  428. wifi_pos_get_psoc_priv_obj(wifi_pos_get_psoc());
  429. if (!wifi_pos_psoc) {
  430. wifi_pos_err("wifi_pos priv obj is null");
  431. return;
  432. }
  433. if (!chan_list) {
  434. wifi_pos_err("wifi_pos priv arg is null");
  435. return;
  436. }
  437. wifi_pos_ch = &chan_list->chan_info[chan_list->num_channels];
  438. ch_info = (struct channel_power *)qdf_mem_malloc(
  439. sizeof(*ch_info) * NUM_CHANNELS);
  440. if (!ch_info) {
  441. wifi_pos_err("ch_info is null");
  442. return;
  443. }
  444. status = wlan_reg_get_channel_list_with_power_for_freq(pdev, ch_info,
  445. &num_channels);
  446. if (QDF_IS_STATUS_ERROR(status)) {
  447. wifi_pos_err("Failed to get valid channel list");
  448. qdf_mem_free(ch_info);
  449. return;
  450. }
  451. if ((chan_list->num_channels + num_channels) > NUM_CHANNELS) {
  452. wifi_pos_err("Invalid number of channels");
  453. qdf_mem_free(ch_info);
  454. return;
  455. }
  456. for (i = 0; i < num_channels; i++) {
  457. wifi_pos_ch[i].ch_power.center_freq = ch_info[i].center_freq;
  458. wifi_pos_ch[i].ch_power.chan_num = ch_info[i].chan_num;
  459. wifi_pos_ch[i].ch_power.tx_power = ch_info[i].tx_power;
  460. wifi_pos_ch[i].is_dfs_chan =
  461. wlan_reg_is_dfs_for_freq(pdev, ch_info[i].center_freq);
  462. wifi_update_channel_bw_info(
  463. psoc, pdev,
  464. ch_info[i].center_freq, &wifi_pos_ch[i]);
  465. }
  466. if (wifi_pos_psoc->wifi_pos_get_max_fw_phymode_for_channels) {
  467. status = wifi_pos_psoc->wifi_pos_get_max_fw_phymode_for_channels(
  468. pdev, wifi_pos_ch, num_channels);
  469. if (QDF_IS_STATUS_ERROR(status)) {
  470. wifi_pos_err("Failed to get phymode");
  471. qdf_mem_free(ch_info);
  472. return;
  473. }
  474. }
  475. chan_list->num_channels += num_channels;
  476. qdf_mem_free(ch_info);
  477. }
  478. #ifdef CNSS_GENL
  479. static bool wifi_pos_is_resp_version_valid(uint32_t rsp_version)
  480. {
  481. return (rsp_version == WIFI_POS_RSP_V2_NL) ? true : false;
  482. }
  483. static void wifi_pos_get_ch_info(struct wlan_objmgr_psoc *psoc,
  484. struct wifi_pos_channel_list *chan_list)
  485. {
  486. wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP,
  487. wifi_pos_pdev_iterator,
  488. chan_list, true, WLAN_WIFI_POS_CORE_ID);
  489. wifi_pos_debug("num channels: %d", chan_list->num_channels);
  490. }
  491. #else
  492. static bool wifi_pos_is_resp_version_valid(uint32_t rsp_version)
  493. {
  494. return ((rsp_version == WIFI_POS_RSP_V2_NL) ||
  495. (rsp_version == WIFI_POS_RSP_V1_FLAT_MEMORY)) ?
  496. true : false;
  497. }
  498. static void wifi_pos_get_ch_info(struct wlan_objmgr_psoc *psoc,
  499. struct wifi_pos_channel_list *chan_list)
  500. {
  501. uint8_t index;
  502. for (index = 0; index < WLAN_OBJMGR_MAX_DEVICES; index++) {
  503. if (g_umac_glb_obj->psoc[index]) {
  504. wlan_objmgr_iterate_obj_list(
  505. g_umac_glb_obj->psoc[index],
  506. WLAN_PDEV_OP, wifi_pos_pdev_iterator,
  507. chan_list, true, WLAN_WIFI_POS_CORE_ID);
  508. }
  509. }
  510. wifi_pos_notice("num channels: %d", chan_list->num_channels);
  511. }
  512. #endif
  513. static QDF_STATUS wifi_pos_process_ch_info_req(struct wlan_objmgr_psoc *psoc,
  514. struct wifi_pos_req_msg *req)
  515. {
  516. uint8_t idx;
  517. uint8_t *buf = NULL;
  518. uint32_t len, i, freq;
  519. qdf_freq_t *chan_freqs = NULL;
  520. bool oem_6g_support_disable;
  521. uint8_t *channels = req->buf;
  522. struct wlan_objmgr_pdev *pdev;
  523. uint32_t num_ch = req->buf_len;
  524. qdf_freq_t valid_channel_list[NUM_CHANNELS];
  525. uint32_t num_valid_channels = 0;
  526. struct wifi_pos_ch_info_rsp *ch_info;
  527. struct wifi_pos_channel_list *ch_list = NULL;
  528. struct wifi_pos_psoc_priv_obj *wifi_pos_obj =
  529. wifi_pos_get_psoc_priv_obj(psoc);
  530. QDF_STATUS ret_val;
  531. struct wifi_pos_channel_power *ch;
  532. if (!wifi_pos_obj) {
  533. wifi_pos_err("wifi_pos priv obj is null");
  534. return QDF_STATUS_E_INVAL;
  535. }
  536. wifi_pos_debug("Received ch info req pid(%d), len(%d)",
  537. req->pid, req->buf_len);
  538. /* get first pdev since we need that only for freq and dfs state */
  539. pdev = wlan_objmgr_get_pdev_by_id(psoc, 0, WLAN_WIFI_POS_CORE_ID);
  540. if (!pdev) {
  541. wifi_pos_err("pdev get API failed");
  542. return QDF_STATUS_E_INVAL;
  543. }
  544. if (num_ch > NUM_CHANNELS) {
  545. wifi_pos_err("Invalid number of channels");
  546. ret_val = QDF_STATUS_E_INVAL;
  547. goto cleanup;
  548. }
  549. chan_freqs = qdf_mem_malloc(NUM_CHANNELS * (sizeof(*chan_freqs)));
  550. if (!chan_freqs) {
  551. ret_val = QDF_STATUS_E_NOMEM;
  552. goto cleanup;
  553. }
  554. ch_list = qdf_mem_malloc(sizeof(*ch_list));
  555. if (!ch_list) {
  556. ret_val = QDF_STATUS_E_NOMEM;
  557. goto cleanup;
  558. }
  559. ch = ch_list->chan_info;
  560. if ((num_ch == 0) &&
  561. wifi_pos_is_resp_version_valid(req->rsp_version)) {
  562. wifi_pos_get_ch_info(psoc, ch_list);
  563. qdf_spin_lock_bh(&wifi_pos_obj->wifi_pos_lock);
  564. oem_6g_support_disable = wifi_pos_obj->oem_6g_support_disable;
  565. qdf_spin_unlock_bh(&wifi_pos_obj->wifi_pos_lock);
  566. /* ch_list has the frequencies in order of 2.4g, 5g & 6g */
  567. for (i = 0; i < ch_list->num_channels; i++) {
  568. freq = ch[i].ch_power.center_freq;
  569. if (oem_6g_support_disable &&
  570. WLAN_REG_IS_6GHZ_CHAN_FREQ(freq))
  571. continue;
  572. num_valid_channels++;
  573. }
  574. } else {
  575. for (i = 0; i < NUM_CHANNELS; i++)
  576. chan_freqs[i] =
  577. wlan_reg_chan_band_to_freq(pdev, channels[i],
  578. BIT(REG_BAND_5G) |
  579. BIT(REG_BAND_2G));
  580. /* v1 has ch_list with frequencies in order of 2.4g, 5g only */
  581. num_valid_channels = wifi_pos_get_valid_channels(
  582. chan_freqs, num_ch,
  583. valid_channel_list);
  584. for (i = 0; i < num_valid_channels; i++) {
  585. ch[i].ch_power.center_freq = valid_channel_list[i];
  586. ch[i].ch_power.chan_num = wlan_reg_freq_to_chan(
  587. pdev, ch[i].ch_power.center_freq);
  588. ch[i].ch_power.tx_power =
  589. wlan_reg_get_channel_reg_power_for_freq(
  590. pdev,
  591. ch[i].ch_power.center_freq);
  592. ch[i].is_dfs_chan = wlan_reg_is_dfs_for_freq(
  593. pdev,
  594. ch[i].ch_power.center_freq);
  595. wifi_update_channel_bw_info(psoc, pdev,
  596. ch[i].ch_power.center_freq,
  597. &ch[i]);
  598. }
  599. }
  600. len = sizeof(uint8_t) + sizeof(struct wifi_pos_ch_info_rsp) *
  601. num_valid_channels;
  602. buf = qdf_mem_malloc(len);
  603. if (!buf) {
  604. ret_val = QDF_STATUS_E_NOMEM;
  605. goto cleanup;
  606. }
  607. /* First byte of message body will have num of channels */
  608. buf[0] = num_valid_channels;
  609. ch_info = (struct wifi_pos_ch_info_rsp *)&buf[1];
  610. for (idx = 0; idx < num_valid_channels; idx++) {
  611. ch_info[idx].reserved0 = 0;
  612. ch_info[idx].chan_id = ch[idx].ch_power.chan_num;
  613. ch_info[idx].mhz = ch[idx].ch_power.center_freq;
  614. ch_info[idx].band_center_freq1 = ch[idx].band_center_freq1;
  615. ch_info[idx].band_center_freq2 = 0;
  616. ch_info[idx].info = 0;
  617. REG_SET_CHANNEL_REG_POWER(ch_info[idx].reg_info_1,
  618. ch[idx].ch_power.tx_power);
  619. REG_SET_CHANNEL_MAX_TX_POWER(ch_info[idx].reg_info_2,
  620. ch[idx].ch_power.tx_power);
  621. if (ch[idx].is_dfs_chan)
  622. WIFI_POS_SET_DFS(ch_info[idx].info);
  623. if (ch[idx].phy_mode)
  624. REG_SET_CHANNEL_MODE(&ch_info[idx], ch[idx].phy_mode);
  625. }
  626. wifi_pos_obj->wifi_pos_send_rsp(psoc, wifi_pos_obj->app_pid,
  627. WIFI_POS_CMD_GET_CH_INFO,
  628. len, buf);
  629. ret_val = QDF_STATUS_SUCCESS;
  630. cleanup:
  631. qdf_mem_free(buf);
  632. qdf_mem_free(ch_list);
  633. qdf_mem_free(chan_freqs);
  634. wlan_objmgr_pdev_release_ref(pdev, WLAN_WIFI_POS_CORE_ID);
  635. return ret_val;
  636. }
  637. static void wifi_pos_vdev_iterator(struct wlan_objmgr_psoc *psoc,
  638. void *vdev, void *arg)
  639. {
  640. struct app_reg_rsp_vdev_info *vdev_info = arg;
  641. vdev_info[vdev_idx].dev_mode = wlan_vdev_mlme_get_opmode(vdev);
  642. vdev_info[vdev_idx].vdev_id = wlan_vdev_get_id(vdev);
  643. vdev_idx++;
  644. }
  645. #ifdef CNSS_GENL
  646. static void wifi_pos_get_vdev_list(struct wlan_objmgr_psoc *psoc,
  647. struct app_reg_rsp_vdev_info *vdevs_info)
  648. {
  649. wlan_objmgr_iterate_obj_list(psoc, WLAN_VDEV_OP,
  650. wifi_pos_vdev_iterator,
  651. vdevs_info, true, WLAN_WIFI_POS_CORE_ID);
  652. }
  653. #else
  654. /* For WIN, WIFI POS command registration is called only for the first
  655. * PSOC. Hence, iterate through all the PSOCs and send the vdev list
  656. * to LOWI.
  657. */
  658. static void wifi_pos_get_vdev_list(struct wlan_objmgr_psoc *psoc,
  659. struct app_reg_rsp_vdev_info *vdevs_info)
  660. {
  661. uint8_t index;
  662. for (index = 0; index < WLAN_OBJMGR_MAX_DEVICES; index++) {
  663. if (g_umac_glb_obj->psoc[index]) {
  664. wlan_objmgr_iterate_obj_list(
  665. g_umac_glb_obj->psoc[index],
  666. WLAN_VDEV_OP, wifi_pos_vdev_iterator,
  667. vdevs_info, true,
  668. WLAN_WIFI_POS_CORE_ID);
  669. }
  670. }
  671. }
  672. #endif
  673. static QDF_STATUS wifi_pos_process_app_reg_req(struct wlan_objmgr_psoc *psoc,
  674. struct wifi_pos_req_msg *req)
  675. {
  676. QDF_STATUS ret = QDF_STATUS_SUCCESS;
  677. uint8_t err = 0, *app_reg_rsp;
  678. uint32_t rsp_len;
  679. char *sign_str = NULL;
  680. struct app_reg_rsp_vdev_info vdevs_info[WLAN_UMAC_PSOC_MAX_VDEVS]
  681. = { { 0 } };
  682. struct wifi_pos_psoc_priv_obj *wifi_pos_obj =
  683. wifi_pos_get_psoc_priv_obj(psoc);
  684. if (!wifi_pos_obj) {
  685. wifi_pos_err("wifi_pos priv obj is null");
  686. return QDF_STATUS_E_INVAL;
  687. }
  688. wifi_pos_debug("Received App Req Req pid(%d), len(%d)",
  689. req->pid, req->buf_len);
  690. sign_str = (char *)req->buf;
  691. /* Registration request is only allowed for QTI Application */
  692. if ((OEM_APP_SIGNATURE_LEN != req->buf_len) ||
  693. (strncmp(sign_str, OEM_APP_SIGNATURE_STR,
  694. OEM_APP_SIGNATURE_LEN))) {
  695. wifi_pos_err("Invalid signature pid(%d)", req->pid);
  696. ret = QDF_STATUS_E_PERM;
  697. err = OEM_ERR_INVALID_SIGNATURE;
  698. goto app_reg_failed;
  699. }
  700. wifi_pos_debug("Valid App Req Req from pid(%d)", req->pid);
  701. qdf_spin_lock_bh(&wifi_pos_obj->wifi_pos_lock);
  702. wifi_pos_obj->is_app_registered = true;
  703. wifi_pos_obj->app_pid = req->pid;
  704. qdf_spin_unlock_bh(&wifi_pos_obj->wifi_pos_lock);
  705. vdev_idx = 0;
  706. wifi_pos_get_vdev_list(psoc, vdevs_info);
  707. app_reg_rsp = wifi_pos_prepare_reg_resp(&rsp_len, vdevs_info);
  708. if (!app_reg_rsp) {
  709. ret = QDF_STATUS_E_NOMEM;
  710. err = OEM_ERR_NULL_CONTEXT;
  711. goto app_reg_failed;
  712. }
  713. if (!vdev_idx)
  714. wifi_pos_debug("no active vdev");
  715. vdev_idx = 0;
  716. wifi_pos_obj->wifi_pos_send_rsp(psoc, req->pid,
  717. WIFI_POS_CMD_REGISTRATION,
  718. rsp_len, (uint8_t *)app_reg_rsp);
  719. qdf_mem_free(app_reg_rsp);
  720. return ret;
  721. app_reg_failed:
  722. wifi_pos_obj->wifi_pos_send_rsp(psoc, req->pid, WIFI_POS_CMD_ERROR,
  723. sizeof(err), &err);
  724. return ret;
  725. }
  726. /**
  727. * wifi_pos_tlv_callback: wifi pos msg handler registered for TLV type req
  728. * @wmi_msg: wmi type request msg
  729. *
  730. * Return: status of operation
  731. */
  732. static QDF_STATUS wifi_pos_tlv_callback(struct wlan_objmgr_psoc *psoc,
  733. struct wifi_pos_req_msg *req)
  734. {
  735. wifi_pos_debug("enter: msg_type: %d", req->msg_type);
  736. switch (req->msg_type) {
  737. case WIFI_POS_CMD_REGISTRATION:
  738. return wifi_pos_process_app_reg_req(psoc, req);
  739. case WIFI_POS_CMD_OEM_DATA:
  740. return wifi_pos_process_data_req(psoc, req);
  741. case WIFI_POS_CMD_GET_CH_INFO:
  742. return wifi_pos_process_ch_info_req(psoc, req);
  743. case WIFI_POS_CMD_SET_CAPS:
  744. return wifi_pos_process_set_cap_req(psoc, req);
  745. case WIFI_POS_CMD_GET_CAPS:
  746. return wifi_pos_process_get_cap_req(psoc, req);
  747. default:
  748. wifi_pos_err("invalid request type");
  749. break;
  750. }
  751. return 0;
  752. }
  753. /**
  754. * wifi_pos_non_tlv_callback: wifi pos msg handler registered for non-TLV
  755. * type req
  756. * @wmi_msg: wmi type request msg
  757. *
  758. * Return: status of operation
  759. */
  760. static QDF_STATUS wifi_pos_non_tlv_callback(struct wlan_objmgr_psoc *psoc,
  761. struct wifi_pos_req_msg *req)
  762. {
  763. return QDF_STATUS_SUCCESS;
  764. }
  765. QDF_STATUS wifi_pos_convert_host_pdev_id_to_target(
  766. struct wlan_objmgr_psoc *psoc, uint32_t host_pdev_id,
  767. uint32_t *target_pdev_id)
  768. {
  769. struct wlan_lmac_if_wifi_pos_tx_ops *tx_ops;
  770. tx_ops = wifi_pos_get_tx_ops(psoc);
  771. if (!tx_ops) {
  772. wifi_pos_err("tx_ops is null");
  773. return QDF_STATUS_E_NULL_VALUE;
  774. }
  775. if (!tx_ops->wifi_pos_convert_pdev_id_host_to_target) {
  776. wifi_pos_err("wifi_pos_convert_pdev_id_host_to_target is null");
  777. return QDF_STATUS_E_NULL_VALUE;
  778. }
  779. return tx_ops->wifi_pos_convert_pdev_id_host_to_target(
  780. psoc, host_pdev_id, target_pdev_id);
  781. }
  782. QDF_STATUS wifi_pos_psoc_obj_created_notification(
  783. struct wlan_objmgr_psoc *psoc, void *arg_list)
  784. {
  785. QDF_STATUS status;
  786. struct wifi_pos_psoc_priv_obj *wifi_pos_obj;
  787. /*
  788. * this is for WIN, if they have multiple psoc, we dont want to create
  789. * multiple priv object. Since there is just one LOWI app registered to
  790. * one driver, avoid 2nd private object with another psoc.
  791. */
  792. if (wifi_pos_get_psoc()) {
  793. wifi_pos_debug("global psoc obj already set. do not allocate another psoc private object");
  794. return QDF_STATUS_SUCCESS;
  795. } else {
  796. wifi_pos_debug("setting global pos object");
  797. wifi_pos_set_psoc(psoc);
  798. }
  799. /* initialize wifi-pos psoc priv object */
  800. wifi_pos_obj = qdf_mem_malloc(sizeof(*wifi_pos_obj));
  801. if (!wifi_pos_obj) {
  802. wifi_pos_clear_psoc();
  803. return QDF_STATUS_E_NOMEM;
  804. }
  805. qdf_spinlock_create(&wifi_pos_obj->wifi_pos_lock);
  806. /* Register TLV or non-TLV callbacks depending on target fw version */
  807. if (wifi_pos_get_tlv_support(psoc))
  808. wifi_pos_obj->wifi_pos_req_handler = wifi_pos_tlv_callback;
  809. else
  810. wifi_pos_obj->wifi_pos_req_handler = wifi_pos_non_tlv_callback;
  811. /*
  812. * MGMT Rx is not handled in this phase since wifi pos only uses few
  813. * measurement subtypes under RRM_RADIO_MEASURE_REQ. Rest of them are
  814. * used for 80211k. That part is not yet converged and still follows
  815. * legacy MGMT Rx to work. Action frame in new TXRX can be registered
  816. * at per ACTION Frame type granularity only.
  817. */
  818. status = wlan_objmgr_psoc_component_obj_attach(psoc,
  819. WLAN_UMAC_COMP_WIFI_POS,
  820. wifi_pos_obj,
  821. QDF_STATUS_SUCCESS);
  822. if (QDF_IS_STATUS_ERROR(status)) {
  823. wifi_pos_err("obj attach with psoc failed with status: %d",
  824. status);
  825. qdf_spinlock_destroy(&wifi_pos_obj->wifi_pos_lock);
  826. qdf_mem_free(wifi_pos_obj);
  827. wifi_pos_clear_psoc();
  828. }
  829. return status;
  830. }
  831. QDF_STATUS wifi_pos_psoc_obj_destroyed_notification(
  832. struct wlan_objmgr_psoc *psoc, void *arg_list)
  833. {
  834. QDF_STATUS status;
  835. struct wifi_pos_psoc_priv_obj *wifi_pos_obj = NULL;
  836. if (wifi_pos_get_psoc() == psoc) {
  837. wifi_pos_debug("deregistering wifi_pos_psoc object");
  838. wifi_pos_clear_psoc();
  839. } else {
  840. wifi_pos_warn("un-related PSOC closed. do nothing");
  841. return QDF_STATUS_SUCCESS;
  842. }
  843. wifi_pos_obj = wifi_pos_get_psoc_priv_obj(psoc);
  844. if (!wifi_pos_obj) {
  845. wifi_pos_err("wifi_pos_obj is NULL");
  846. return QDF_STATUS_E_FAULT;
  847. }
  848. target_if_wifi_pos_deinit_dma_rings(psoc);
  849. status = wlan_objmgr_psoc_component_obj_detach(psoc,
  850. WLAN_UMAC_COMP_WIFI_POS,
  851. wifi_pos_obj);
  852. if (status != QDF_STATUS_SUCCESS)
  853. wifi_pos_err("wifi_pos_obj detach failed");
  854. wifi_pos_debug("wifi_pos_obj deleted with status %d", status);
  855. qdf_spinlock_destroy(&wifi_pos_obj->wifi_pos_lock);
  856. qdf_mem_free(wifi_pos_obj);
  857. return status;
  858. }
  859. #if defined(WIFI_POS_CONVERGED) && defined(WLAN_FEATURE_RTT_11AZ_SUPPORT)
  860. void
  861. wifi_pos_init_11az_context(struct wifi_pos_vdev_priv_obj *vdev_pos_obj)
  862. {
  863. struct wifi_pos_11az_context *pasn_context;
  864. uint8_t i;
  865. pasn_context = &vdev_pos_obj->pasn_context;
  866. for (i = 0; i < WLAN_MAX_11AZ_PEERS; i++) {
  867. qdf_set_macaddr_broadcast(
  868. &pasn_context->secure_peer_list[i].peer_mac);
  869. qdf_set_macaddr_broadcast(
  870. &pasn_context->secure_peer_list[i].self_mac);
  871. pasn_context->secure_peer_list[i].force_self_mac_usage = false;
  872. pasn_context->secure_peer_list[i].control_flags = 0;
  873. qdf_set_macaddr_broadcast(
  874. &pasn_context->unsecure_peer_list[i].peer_mac);
  875. qdf_set_macaddr_broadcast(&pasn_context->failed_peer_list[i]);
  876. }
  877. pasn_context->num_secure_peers = 0;
  878. pasn_context->num_unsecure_peers = 0;
  879. pasn_context->num_failed_peers = 0;
  880. }
  881. #endif
  882. QDF_STATUS
  883. wifi_pos_vdev_created_notification(struct wlan_objmgr_vdev *vdev,
  884. void *arg_list)
  885. {
  886. struct wifi_pos_vdev_priv_obj *vdev_pos_obj;
  887. QDF_STATUS status = QDF_STATUS_E_FAILURE;
  888. vdev_pos_obj = qdf_mem_malloc(sizeof(*vdev_pos_obj));
  889. if (!vdev_pos_obj)
  890. return QDF_STATUS_E_NOMEM;
  891. status = wlan_objmgr_vdev_component_obj_attach(vdev,
  892. WLAN_UMAC_COMP_WIFI_POS,
  893. vdev_pos_obj,
  894. QDF_STATUS_SUCCESS);
  895. if (QDF_IS_STATUS_ERROR(status)) {
  896. qdf_mem_free(vdev_pos_obj);
  897. wifi_pos_err("Wifi pos vdev attach failed");
  898. return status;
  899. }
  900. wifi_pos_init_11az_context(vdev_pos_obj);
  901. return status;
  902. }
  903. QDF_STATUS
  904. wifi_pos_vdev_destroyed_notification(struct wlan_objmgr_vdev *vdev,
  905. void *arg_list)
  906. {
  907. struct wifi_pos_vdev_priv_obj *vdev_pos_obj;
  908. QDF_STATUS status = QDF_STATUS_E_FAILURE;
  909. vdev_pos_obj = wifi_pos_get_vdev_priv_obj(vdev);
  910. if (!vdev_pos_obj) {
  911. wifi_pos_err("Wifi pos vdev priv obj is null");
  912. return QDF_STATUS_E_FAILURE;
  913. }
  914. status = wlan_objmgr_vdev_component_obj_detach(vdev,
  915. WLAN_UMAC_COMP_WIFI_POS,
  916. vdev_pos_obj);
  917. if (QDF_IS_STATUS_ERROR(status))
  918. wifi_pos_err("Detach vdev private obj failed");
  919. qdf_mem_free(vdev_pos_obj);
  920. return status;
  921. }
  922. QDF_STATUS
  923. wifi_pos_peer_object_created_notification(struct wlan_objmgr_peer *peer,
  924. void *arg)
  925. {
  926. struct wlan_wifi_pos_peer_priv_obj *peer_priv;
  927. QDF_STATUS status;
  928. if (!peer) {
  929. wifi_pos_err("Peer is NULL");
  930. return QDF_STATUS_E_NULL_VALUE;
  931. }
  932. peer_priv = qdf_mem_malloc(sizeof(*peer_priv));
  933. if (!peer_priv)
  934. return QDF_STATUS_E_NOMEM;
  935. status = wlan_objmgr_peer_component_obj_attach(peer,
  936. WLAN_UMAC_COMP_WIFI_POS,
  937. (void *)peer_priv,
  938. QDF_STATUS_SUCCESS);
  939. if (QDF_IS_STATUS_ERROR(status)) {
  940. wifi_pos_err("unable to attach peer_priv obj to peer obj");
  941. qdf_mem_free(peer_priv);
  942. }
  943. return status;
  944. }
  945. QDF_STATUS
  946. wifi_pos_peer_object_destroyed_notification(struct wlan_objmgr_peer *peer,
  947. void *arg)
  948. {
  949. struct wlan_wifi_pos_peer_priv_obj *peer_priv;
  950. QDF_STATUS status;
  951. if (!peer) {
  952. wifi_pos_err("Peer is NULL");
  953. return QDF_STATUS_E_NULL_VALUE;
  954. }
  955. peer_priv = wlan_objmgr_peer_get_comp_private_obj(peer,
  956. WLAN_UMAC_COMP_WIFI_POS);
  957. if (!peer_priv) {
  958. wifi_pos_err("peer MLME component object is NULL");
  959. return QDF_STATUS_E_FAILURE;
  960. }
  961. status = wlan_objmgr_peer_component_obj_detach(peer,
  962. WLAN_UMAC_COMP_WIFI_POS,
  963. (void *)peer_priv);
  964. if (QDF_IS_STATUS_ERROR(status))
  965. wifi_pos_err("unable to dettach peer_priv obj to peer obj");
  966. qdf_mem_free(peer_priv);
  967. return status;
  968. }
  969. int wifi_pos_oem_rsp_handler(struct wlan_objmgr_psoc *psoc,
  970. struct oem_data_rsp *oem_rsp)
  971. {
  972. uint32_t len;
  973. uint8_t *data;
  974. uint32_t app_pid;
  975. struct wifi_pos_psoc_priv_obj *priv;
  976. wifi_pos_send_rsp_handler wifi_pos_send_rsp;
  977. priv = wifi_pos_get_psoc_priv_obj(wifi_pos_get_psoc());
  978. if (!priv) {
  979. wifi_pos_err("private object is NULL");
  980. return -EINVAL;
  981. }
  982. qdf_spin_lock_bh(&priv->wifi_pos_lock);
  983. app_pid = priv->app_pid;
  984. wifi_pos_send_rsp = priv->wifi_pos_send_rsp;
  985. qdf_spin_unlock_bh(&priv->wifi_pos_lock);
  986. len = oem_rsp->rsp_len_1 + oem_rsp->rsp_len_2 + oem_rsp->dma_len;
  987. if (oem_rsp->rsp_len_1 > OEM_DATA_RSP_SIZE ||
  988. oem_rsp->rsp_len_2 > OEM_DATA_RSP_SIZE) {
  989. wifi_pos_err("invalid length of Oem Data response");
  990. return -EINVAL;
  991. }
  992. if (!wifi_pos_send_rsp) {
  993. wifi_pos_err("invalid response handler");
  994. return -EINVAL;
  995. }
  996. wifi_pos_debug("oem data rsp, len: %d to pid: %d", len, app_pid);
  997. if (oem_rsp->rsp_len_2 + oem_rsp->dma_len) {
  998. /* stitch togther the msg data_1 + CIR/CFR + data_2 */
  999. data = qdf_mem_malloc(len);
  1000. if (!data)
  1001. return -ENOMEM;
  1002. qdf_mem_copy(data, oem_rsp->data_1, oem_rsp->rsp_len_1);
  1003. qdf_mem_copy(&data[oem_rsp->rsp_len_1],
  1004. oem_rsp->vaddr, oem_rsp->dma_len);
  1005. qdf_mem_copy(&data[oem_rsp->rsp_len_1 + oem_rsp->dma_len],
  1006. oem_rsp->data_2, oem_rsp->rsp_len_2);
  1007. wifi_pos_send_rsp(psoc, app_pid, WIFI_POS_CMD_OEM_DATA, len,
  1008. data);
  1009. qdf_mem_free(data);
  1010. } else {
  1011. wifi_pos_send_rsp(psoc, app_pid, WIFI_POS_CMD_OEM_DATA,
  1012. oem_rsp->rsp_len_1, oem_rsp->data_1);
  1013. }
  1014. return 0;
  1015. }
  1016. void wifi_pos_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops)
  1017. {
  1018. struct wlan_lmac_if_wifi_pos_rx_ops *wifi_pos_rx_ops;
  1019. wifi_pos_rx_ops = &rx_ops->wifi_pos_rx_ops;
  1020. wifi_pos_rx_ops->oem_rsp_event_rx = wifi_pos_oem_rsp_handler;
  1021. }
  1022. QDF_STATUS wifi_pos_populate_caps(struct wlan_objmgr_psoc *psoc,
  1023. struct wifi_pos_driver_caps *caps)
  1024. {
  1025. uint16_t i, count = 0;
  1026. uint32_t freq;
  1027. struct wifi_pos_psoc_priv_obj *wifi_pos_obj =
  1028. wifi_pos_get_psoc_priv_obj(psoc);
  1029. struct wifi_pos_channel_list *ch_list = NULL;
  1030. wifi_pos_debug("Enter");
  1031. if (!wifi_pos_obj) {
  1032. wifi_pos_err("wifi_pos_obj is null");
  1033. return QDF_STATUS_E_NULL_VALUE;
  1034. }
  1035. ch_list = qdf_mem_malloc(sizeof(*ch_list));
  1036. if (!ch_list)
  1037. return QDF_STATUS_E_NOMEM;
  1038. strlcpy(caps->oem_target_signature,
  1039. OEM_TARGET_SIGNATURE,
  1040. OEM_TARGET_SIGNATURE_LEN);
  1041. caps->oem_target_type = wifi_pos_obj->oem_target_type;
  1042. caps->oem_fw_version = wifi_pos_obj->oem_fw_version;
  1043. caps->driver_version.major = wifi_pos_obj->driver_version.major;
  1044. caps->driver_version.minor = wifi_pos_obj->driver_version.minor;
  1045. caps->driver_version.patch = wifi_pos_obj->driver_version.patch;
  1046. caps->driver_version.build = wifi_pos_obj->driver_version.build;
  1047. caps->allowed_dwell_time_min = wifi_pos_obj->allowed_dwell_time_min;
  1048. caps->allowed_dwell_time_max = wifi_pos_obj->allowed_dwell_time_max;
  1049. caps->curr_dwell_time_min = wifi_pos_obj->current_dwell_time_min;
  1050. caps->curr_dwell_time_max = wifi_pos_obj->current_dwell_time_max;
  1051. caps->supported_bands = wlan_objmgr_psoc_get_band_capability(psoc);
  1052. wifi_pos_get_ch_info(psoc, ch_list);
  1053. /* copy valid channels list to caps */
  1054. for (i = 0; i < ch_list->num_channels; i++) {
  1055. freq = ch_list->chan_info[i].ch_power.center_freq;
  1056. if (WLAN_REG_IS_6GHZ_CHAN_FREQ(freq))
  1057. continue;
  1058. caps->channel_list[count++] =
  1059. ch_list->chan_info[i].ch_power.chan_num;
  1060. }
  1061. caps->num_channels = count;
  1062. qdf_mem_free(ch_list);
  1063. return QDF_STATUS_SUCCESS;
  1064. }