1 /*
2 * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17 #include "os_if_qmi.h"
18 #include "os_if_qmi_wifi_driver_service_v01.h"
19 #include <qdf_util.h>
20 #include "wlan_qmi_public_struct.h"
21 #include "wlan_dp_ucfg_api.h"
22
23 static struct qmi_handle qmi_wfds;
24
25 /*
26 * os_if_ce_dir_qmi_to_wfds_type() - Convert ce direction from internal
27 * type to type used in QMI message
28 * @ce_dir: internal ce direction
29 *
30 * Return: ce direction in QMI type
31 */
32 static enum wifi_drv_qmi_pipe_dir_v01
os_if_ce_dir_qmi_to_wfds_type(enum wlan_qmi_wfds_pipe_dir ce_dir)33 os_if_ce_dir_qmi_to_wfds_type(enum wlan_qmi_wfds_pipe_dir ce_dir)
34 {
35 switch (ce_dir) {
36 case QMI_WFDS_PIPEDIR_NONE:
37 return WFDS_PIPEDIR_NONE_V01;
38 case QMI_WFDS_PIPEDIR_IN:
39 return WFDS_PIPEDIR_IN_V01;
40 case QMI_WFDS_PIPEDIR_OUT:
41 return WFDS_PIPEDIR_OUT_V01;
42 default:
43 return WIFI_DRV_QMI_PIPE_DIR_MAX_VAL_V01;
44 }
45 }
46
47 /*
48 * os_if_srng_dir_qmi_to_wfds_type() - Convert srng direction from internal
49 * type to type used in QMI message
50 * @srng_dir: internal srng direction
51 *
52 * Return: srng direction in QMI type
53 */
54 static enum wifi_drv_qmi_srng_direction_v01
os_if_srng_dir_qmi_to_wfds_type(enum wlan_qmi_wfds_srng_dir srng_dir)55 os_if_srng_dir_qmi_to_wfds_type(enum wlan_qmi_wfds_srng_dir srng_dir)
56 {
57 switch (srng_dir) {
58 case QMI_WFDS_SRNG_SOURCE_RING:
59 return WFDS_SRNG_SOURCE_RING_V01;
60 case QMI_WFDS_SRNG_DESTINATION_RING:
61 return WFDS_SRNG_DESTINATION_RING_V01;
62 default:
63 return WIFI_DRV_QMI_SRNG_DIRECTION_MAX_VAL_V01;
64 }
65 }
66
67 /*
68 * os_if_qmi_wfds_send_config_msg() - Send config message to QMI server
69 * to QMI server
70 * @src_info: source information to be filled in QMI message
71 *
72 * Return: QDF status
73 */
74 static QDF_STATUS
os_if_qmi_wfds_send_config_msg(struct wlan_qmi_wfds_config_req_msg * src_info)75 os_if_qmi_wfds_send_config_msg(struct wlan_qmi_wfds_config_req_msg *src_info)
76 {
77 struct wfds_config_req_msg_v01 *req;
78 struct wfds_gen_resp_msg_v01 *resp;
79 struct qmi_txn txn;
80 QDF_STATUS status;
81 uint8_t i;
82
83 req = qdf_mem_malloc(sizeof(*req));
84 if (!req)
85 return QDF_STATUS_E_NOMEM;
86
87 resp = qdf_mem_malloc(sizeof(*resp));
88 if (!resp) {
89 qdf_mem_free(req);
90 return QDF_STATUS_E_NOMEM;
91 }
92
93 if (src_info->ce_info_len > QMI_WFDS_CE_MAX_SRNG) {
94 status = QDF_STATUS_E_INVAL;
95 goto out;
96 }
97
98 req->ce_info_len = src_info->ce_info_len;
99 for (i = 0; i < req->ce_info_len; i++) {
100 req->ce_info[i].ce_id = src_info->ce_info[i].ce_id;
101 req->ce_info[i].ce_dir =
102 os_if_ce_dir_qmi_to_wfds_type(src_info->ce_info[i].ce_dir);
103 req->ce_info[i].srng_info.ring_id =
104 src_info->ce_info[i].srng_info.ring_id;
105 req->ce_info[i].srng_info.dir =
106 os_if_srng_dir_qmi_to_wfds_type(src_info->ce_info[i].srng_info.dir);
107 req->ce_info[i].srng_info.num_entries =
108 src_info->ce_info[i].srng_info.num_entries;
109 req->ce_info[i].srng_info.entry_size =
110 src_info->ce_info[i].srng_info.entry_size;
111 req->ce_info[i].srng_info.ring_base_paddr =
112 src_info->ce_info[i].srng_info.ring_base_paddr;
113 req->ce_info[i].srng_info.hp_paddr =
114 src_info->ce_info[i].srng_info.hp_paddr;
115 req->ce_info[i].srng_info.tp_paddr =
116 src_info->ce_info[i].srng_info.tp_paddr;
117 }
118
119 req->rx_refill_ring.ring_id = src_info->rx_refill_ring.ring_id;
120 req->rx_refill_ring.dir =
121 os_if_srng_dir_qmi_to_wfds_type(src_info->rx_refill_ring.dir);
122 req->rx_refill_ring.num_entries = src_info->rx_refill_ring.num_entries;
123 req->rx_refill_ring.entry_size = src_info->rx_refill_ring.entry_size;
124 req->rx_refill_ring.ring_base_paddr =
125 src_info->rx_refill_ring.ring_base_paddr;
126 req->rx_refill_ring.hp_paddr = src_info->rx_refill_ring.hp_paddr;
127 req->rx_refill_ring.tp_paddr = src_info->rx_refill_ring.tp_paddr;
128
129 req->shadow_rdptr_mem_paddr = src_info->shadow_rdptr_mem_paddr;
130 req->shadow_rdptr_mem_size = src_info->shadow_rdptr_mem_size;
131 req->shadow_wrptr_mem_paddr = src_info->shadow_wrptr_mem_paddr;
132 req->shadow_wrptr_mem_size = src_info->shadow_wrptr_mem_size;
133 req->rx_pkt_tlv_len = src_info->rx_pkt_tlv_len;
134 req->rx_rbm = src_info->rx_rbm;
135 req->pcie_bar_pa = src_info->pcie_bar_pa;
136 req->pci_slot = src_info->pci_slot;
137 req->lpass_ep_id = src_info->lpass_ep_id;
138
139 status = os_if_qmi_txn_init(&qmi_wfds, &txn, wfds_gen_resp_msg_v01_ei,
140 resp);
141 if (QDF_IS_STATUS_ERROR(status)) {
142 osif_info("QMI txn init failed for WFDS config message %d",
143 status);
144 goto out;
145 }
146
147 status = os_if_qmi_send_request(&qmi_wfds, NULL, &txn,
148 QMI_WFDS_CONFIG_REQ_V01,
149 WFDS_CONFIG_REQ_MSG_V01_MAX_MSG_LEN,
150 wfds_config_req_msg_v01_ei, req);
151 if (QDF_IS_STATUS_ERROR(status)) {
152 osif_info("QMI WFDS config send request failed %d", status);
153 os_if_qmi_txn_cancel(&txn);
154 goto out;
155 }
156
157 status = os_if_qmi_txn_wait(&txn, QMI_WFDS_TIMEOUT_JF);
158 if (QDF_IS_STATUS_ERROR(status)) {
159 osif_info("Wait for QMI WFDS config response timed out %d",
160 status);
161 goto out;
162 }
163
164 qdf_assert(resp->resp.result == QMI_RESULT_SUCCESS_V01);
165
166 out:
167 qdf_mem_free(resp);
168 qdf_mem_free(req);
169
170 return status;
171 }
172
173 /*
174 * os_if_qmi_wfds_send_req_mem_msg() - Send Request Memory message to QMI server
175 * @src_info: source information to be filled in QMI message
176 *
177 * Return: QDF status
178 */
179 static QDF_STATUS
os_if_qmi_wfds_send_req_mem_msg(struct wlan_qmi_wfds_mem_req_msg * src_info)180 os_if_qmi_wfds_send_req_mem_msg(struct wlan_qmi_wfds_mem_req_msg *src_info)
181 {
182 struct wfds_mem_req_msg_v01 *req;
183 struct wfds_gen_resp_msg_v01 *resp;
184 struct qmi_txn txn;
185 QDF_STATUS status;
186 uint8_t i;
187 uint16_t j;
188
189 req = qdf_mem_malloc(sizeof(*req));
190 if (!req)
191 return QDF_STATUS_E_NOMEM;
192
193 resp = qdf_mem_malloc(sizeof(*resp));
194 if (!resp) {
195 qdf_mem_free(req);
196 return QDF_STATUS_E_NOMEM;
197 }
198
199 if (src_info->mem_arena_page_info_len > QMI_WFDS_MEM_ARENA_MAX) {
200 status = QDF_STATUS_E_INVAL;
201 goto out;
202 }
203
204 req->mem_arena_page_info_len = src_info->mem_arena_page_info_len;
205 for (i = 0; i < req->mem_arena_page_info_len; i++) {
206 req->mem_arena_page_info[i].num_entries_per_page =
207 src_info->mem_arena_page_info[i].num_entries_per_page;
208 req->mem_arena_page_info[i].page_dma_addr_len =
209 src_info->mem_arena_page_info[i].page_dma_addr_len;
210
211 if (src_info->mem_arena_page_info[i].page_dma_addr_len >
212 QMI_WFDS_PAGE_INFO_ARRAY_MAX_SIZE) {
213 status = QDF_STATUS_E_INVAL;
214 goto out;
215 }
216
217 for (j = 0; j < req->mem_arena_page_info[i].page_dma_addr_len;
218 j++)
219 req->mem_arena_page_info[i].page_dma_addr[j] =
220 src_info->mem_arena_page_info[i].page_dma_addr[j];
221 }
222
223 status = os_if_qmi_txn_init(&qmi_wfds, &txn, wfds_gen_resp_msg_v01_ei,
224 resp);
225 if (QDF_IS_STATUS_ERROR(status)) {
226 osif_info("QMI txn init failed for WFDS mem req message %d",
227 status);
228 goto out;
229 }
230
231 status = os_if_qmi_send_request(&qmi_wfds, NULL, &txn,
232 QMI_WFDS_MEM_REQ_V01,
233 WFDS_MEM_REQ_MSG_V01_MAX_MSG_LEN,
234 wfds_mem_req_msg_v01_ei, req);
235 if (QDF_IS_STATUS_ERROR(status)) {
236 osif_info("QMI WFDS mem request send failed %d", status);
237 os_if_qmi_txn_cancel(&txn);
238 goto out;
239 }
240
241 status = os_if_qmi_txn_wait(&txn, QMI_WFDS_TIMEOUT_JF);
242 if (QDF_IS_STATUS_ERROR(status)) {
243 osif_info("Wait for QMI WFDS mem response timed out %d",
244 status);
245 goto out;
246 }
247
248 qdf_assert(resp->resp.result == QMI_RESULT_SUCCESS_V01);
249
250 out:
251 qdf_mem_free(resp);
252 qdf_mem_free(req);
253
254 return status;
255 }
256
257 /*
258 * os_if_qmi_wfds_send_misc_req_msg() - Send misc req message to QMI server
259 * @is_ssr: true if SSR is in progress else false
260 *
261 * Return: QDF status
262 */
263 static QDF_STATUS
os_if_qmi_wfds_send_misc_req_msg(bool is_ssr)264 os_if_qmi_wfds_send_misc_req_msg(bool is_ssr)
265 {
266 struct wfds_misc_req_msg_v01 *req;
267 struct wfds_gen_resp_msg_v01 *resp;
268 struct qmi_txn txn;
269 QDF_STATUS status;
270
271 req = qdf_mem_malloc(sizeof(*req));
272 if (!req)
273 return QDF_STATUS_E_NOMEM;
274
275 resp = qdf_mem_malloc(sizeof(*resp));
276 if (!resp) {
277 qdf_mem_free(req);
278 return QDF_STATUS_E_NOMEM;
279 }
280
281 req->event = (is_ssr) ? WFDS_EVENT_WLAN_SSR_V01 :
282 WFDS_EVENT_WLAN_HOST_RMMOD_V01;
283
284 status = os_if_qmi_txn_init(&qmi_wfds, &txn, wfds_gen_resp_msg_v01_ei,
285 resp);
286 if (QDF_IS_STATUS_ERROR(status)) {
287 osif_info("QMI txn for WFDS misc request failed %d",
288 status);
289 goto out;
290 }
291
292 status = os_if_qmi_send_request(&qmi_wfds, NULL, &txn,
293 QMI_WFDS_MISC_REQ_V01,
294 WFDS_MISC_REQ_MSG_V01_MAX_MSG_LEN,
295 wfds_misc_req_msg_v01_ei, req);
296 if (QDF_IS_STATUS_ERROR(status)) {
297 osif_info("QMI WFDS misc request send failed %d", status);
298 os_if_qmi_txn_cancel(&txn);
299 goto out;
300 }
301
302 status = os_if_qmi_txn_wait(&txn, QMI_WFDS_TIMEOUT_JF);
303 if (QDF_IS_STATUS_ERROR(status)) {
304 osif_info("Failed to wait for WFDS misc response %d", status);
305 goto out;
306 }
307
308 qdf_assert(resp->resp.result == QMI_RESULT_SUCCESS_V01);
309
310 out:
311 qdf_mem_free(resp);
312 qdf_mem_free(req);
313
314 return status;
315 }
316
317 /*
318 * os_if_srng_dir_qmi_to_wfds_type() - Convert status from internal
319 * type to type used in QMI message
320 * @status: internal status
321 *
322 * Return: status in QMI type
323 */
324 static uint8_t
os_if_status_qmi_to_wfds_type(enum wlan_qmi_wfds_status status)325 os_if_status_qmi_to_wfds_type(enum wlan_qmi_wfds_status status)
326 {
327 switch (status) {
328 case QMI_WFDS_STATUS_SUCCESS:
329 return QMI_RESULT_SUCCESS_V01;
330 case QMI_WFDS_STATUS_FAILURE:
331 default:
332 return QMI_RESULT_FAILURE_V01;
333 }
334 }
335
336 /*
337 * os_if_qmi_wfds_ipcc_map_n_cfg_msg() - Send the IPCC map and configure message
338 * to QMI server
339 * @src_info: source information to be filled in QMI message
340 *
341 * Return: QDF status
342 */
343 static QDF_STATUS
os_if_qmi_wfds_ipcc_map_n_cfg_msg(struct wlan_qmi_wfds_ipcc_map_n_cfg_req_msg * src_info)344 os_if_qmi_wfds_ipcc_map_n_cfg_msg(struct wlan_qmi_wfds_ipcc_map_n_cfg_req_msg *src_info)
345 {
346 struct wfds_ipcc_map_n_cfg_req_msg_v01 *req;
347 struct wfds_gen_resp_msg_v01 *resp;
348 struct qmi_txn txn;
349 QDF_STATUS status;
350
351 req = qdf_mem_malloc(sizeof(*req));
352 if (!req)
353 return QDF_STATUS_E_NOMEM;
354
355 resp = qdf_mem_malloc(sizeof(*resp));
356 if (!resp) {
357 qdf_mem_free(req);
358 return QDF_STATUS_E_NOMEM;
359 }
360
361 req->status = os_if_status_qmi_to_wfds_type(src_info->status);
362
363 status = os_if_qmi_txn_init(&qmi_wfds, &txn, wfds_gen_resp_msg_v01_ei,
364 resp);
365 if (QDF_IS_STATUS_ERROR(status)) {
366 osif_info("QMI txn init failed for WFDS ipcc cfg req message %d",
367 status);
368 goto out;
369 }
370
371 status = os_if_qmi_send_request(&qmi_wfds, NULL, &txn,
372 QMI_WFDS_IPCC_MAP_N_CFG_REQ_V01,
373 WFDS_IPCC_MAP_N_CFG_REQ_MSG_V01_MAX_MSG_LEN,
374 wfds_ipcc_map_n_cfg_req_msg_v01_ei, req);
375 if (QDF_IS_STATUS_ERROR(status)) {
376 osif_info("QMI WFDS IPCC cfg request send failed %d", status);
377 os_if_qmi_txn_cancel(&txn);
378 goto out;
379 }
380
381 status = os_if_qmi_txn_wait(&txn, QMI_WFDS_TIMEOUT_JF);
382 if (QDF_IS_STATUS_ERROR(status)) {
383 osif_info("Wait for QMI WFDS IPCC response timed out %d",
384 status);
385 goto out;
386 }
387
388 qdf_assert(resp->resp.result == QMI_RESULT_SUCCESS_V01);
389
390 out:
391 qdf_mem_free(resp);
392 qdf_mem_free(req);
393
394 return status;
395 }
396
397 /*
398 * os_if_qmi_wfds_request_mem_ind_cb() - Process request memory indication
399 * received from QMI server
400 * @qmi_hdl: QMI handle
401 * @sq: pointer to QRTR sock address
402 * @qmi_txn: pointer to QMI transaction
403 * @data: pointer to QMI data
404 *
405 * Return: None
406 */
os_if_qmi_wfds_request_mem_ind_cb(struct qmi_handle * qmi_hdl,struct sockaddr_qrtr * sq,struct qmi_txn * qmi_txn,const void * data)407 static void os_if_qmi_wfds_request_mem_ind_cb(struct qmi_handle *qmi_hdl,
408 struct sockaddr_qrtr *sq,
409 struct qmi_txn *qmi_txn,
410 const void *data)
411 {
412 struct wfds_mem_ind_msg_v01 *src_info =
413 (struct wfds_mem_ind_msg_v01 *)data;
414 struct wlan_qmi_wfds_mem_ind_msg mem_ind_msg = {0};
415 uint8_t i;
416
417 if (!qmi_hdl || !qmi_txn)
418 return;
419
420 if (src_info->mem_arena_info_len > QMI_WFDS_MEM_ARENA_MAX) {
421 osif_info("Memory arena information array size %d exceeds max length",
422 src_info->mem_arena_info_len);
423 return;
424 }
425
426 mem_ind_msg.mem_arena_info_len = src_info->mem_arena_info_len;
427 for (i = 0; i < src_info->mem_arena_info_len; i++) {
428 mem_ind_msg.mem_arena_info[i].entry_size =
429 src_info->mem_arena_info[i].entry_size;
430 mem_ind_msg.mem_arena_info[i].num_entries =
431 src_info->mem_arena_info[i].num_entries;
432 }
433
434 ucfg_dp_wfds_handle_request_mem_ind(&mem_ind_msg);
435 }
436
437 /*
438 * os_if_wfds_ipcc_map_n_cfg_ind_cb() - Process IPCC map and configure
439 * indication received from QMI server
440 * @qmi_hdl: QMI handle
441 * @sq: pointer to QRTR sock address
442 * @qmi_txn: pointer to QMI transaction
443 * @data: pointer to QMI data
444 *
445 * Return: None
446 */
os_if_wfds_ipcc_map_n_cfg_ind_cb(struct qmi_handle * qmi_hdl,struct sockaddr_qrtr * sq,struct qmi_txn * qmi_txn,const void * data)447 static void os_if_wfds_ipcc_map_n_cfg_ind_cb(struct qmi_handle *qmi_hdl,
448 struct sockaddr_qrtr *sq,
449 struct qmi_txn *qmi_txn,
450 const void *data)
451 {
452 struct wfds_ipcc_map_n_cfg_ind_msg_v01 *src_info =
453 (struct wfds_ipcc_map_n_cfg_ind_msg_v01 *)data;
454 struct wlan_qmi_wfds_ipcc_map_n_cfg_ind_msg ipcc_ind_msg = {0};
455 uint8_t i;
456
457 if (!qmi_hdl || !qmi_txn)
458 return;
459
460 if (src_info->ipcc_ce_info_len > QMI_WFDS_CE_MAX_SRNG) {
461 osif_info("IPCC CE information array size %d exceeds max length",
462 src_info->ipcc_ce_info_len);
463 return;
464 }
465
466 ipcc_ind_msg.ipcc_ce_info_len = src_info->ipcc_ce_info_len;
467 for (i = 0; i < src_info->ipcc_ce_info_len; i++) {
468 ipcc_ind_msg.ipcc_ce_info[i].ce_id =
469 src_info->ipcc_ce_info[i].ce_id;
470 ipcc_ind_msg.ipcc_ce_info[i].ipcc_trig_addr =
471 src_info->ipcc_ce_info[i].ipcc_trig_addr;
472 ipcc_ind_msg.ipcc_ce_info[i].ipcc_trig_data =
473 src_info->ipcc_ce_info[i].ipcc_trig_data;
474 }
475
476 ucfg_dp_wfds_handle_ipcc_map_n_cfg_ind(&ipcc_ind_msg);
477 }
478
479 QDF_STATUS
os_if_qmi_wfds_send_ut_cmd_req_msg(struct os_if_qmi_wfds_ut_cmd_info * cmd_info)480 os_if_qmi_wfds_send_ut_cmd_req_msg(struct os_if_qmi_wfds_ut_cmd_info *cmd_info)
481 {
482 struct wfds_ut_cmd_req_msg_v01 *req;
483 struct wfds_gen_resp_msg_v01 *resp;
484 struct qmi_txn txn;
485 QDF_STATUS status;
486 int i;
487
488 req = qdf_mem_malloc(sizeof(*req));
489 if (!req)
490 return QDF_STATUS_E_NOMEM;
491
492 resp = qdf_mem_malloc(sizeof(*resp));
493 if (!resp) {
494 qdf_mem_free(req);
495 return QDF_STATUS_E_NOMEM;
496 }
497
498 req->cmd = (enum wifi_drv_qmi_ut_cmd_v01)cmd_info->cmd;
499 req->duration = cmd_info->duration;
500 req->flush_period = cmd_info->flush_period;
501 req->num_pkts = cmd_info->num_pkts;
502 req->buf_size = cmd_info->buf_size;
503 req->ether_type = cmd_info->ether_type;
504 for (i = 0; i < QDF_MAC_ADDR_SIZE; i++) {
505 req->src_mac[i] = cmd_info->src_mac.bytes[i];
506 req->dest_mac[i] = cmd_info->dest_mac.bytes[i];
507 }
508
509 if (cmd_info->cmd == WFDS_START_WHC) {
510 for (i = 0; i < QDF_IPV4_ADDR_SIZE; i++) {
511 req->src_ip_addr[i] = cmd_info->src_ip.bytes[i];
512 req->dest_ip_addr[i] = cmd_info->dest_ip.bytes[i];
513 }
514
515 req->dest_port = cmd_info->dest_port;
516 }
517
518 osif_debug("cmd: %u for duration: %u s, flush period: %u ms",
519 req->cmd, req->duration, req->flush_period);
520
521 status = os_if_qmi_txn_init(&qmi_wfds, &txn, wfds_gen_resp_msg_v01_ei,
522 resp);
523 if (QDF_IS_STATUS_ERROR(status)) {
524 osif_info("QMI txn for WFDS unit test cmd init failed %d",
525 status);
526 goto out;
527 }
528
529 status = os_if_qmi_send_request(&qmi_wfds, NULL, &txn,
530 QMI_WFDS_UT_CMD_REQ_V01,
531 WFDS_UT_CMD_REQ_MSG_V01_MAX_MSG_LEN,
532 wfds_ut_cmd_req_msg_v01_ei, req);
533 if (QDF_IS_STATUS_ERROR(status)) {
534 osif_info("QMI WFDS UT command request send failed %d",
535 status);
536 os_if_qmi_txn_cancel(&txn);
537 goto out;
538 }
539
540 status = os_if_qmi_txn_wait(&txn, QMI_WFDS_TIMEOUT_JF);
541 if (QDF_IS_STATUS_ERROR(status)) {
542 osif_info("Wait for unit test cmd response timed out %d",
543 status);
544 goto out;
545 }
546
547 qdf_assert(resp->resp.result == QMI_RESULT_SUCCESS_V01);
548
549 out:
550 qdf_mem_free(resp);
551 qdf_mem_free(req);
552
553 return status;
554 }
555
556 /**
557 * os_if_qmi_wfds_new_server() - New server callback triggered when service is
558 * up.
559 * @qmi_hdl: QMI client handle
560 * @qmi_svc: QMI service handle
561 *
562 * Returns: 0 on success else OS failure code
563 */
564 static int
os_if_qmi_wfds_new_server(struct qmi_handle * qmi_hdl,struct qmi_service * qmi_svc)565 os_if_qmi_wfds_new_server(struct qmi_handle *qmi_hdl,
566 struct qmi_service *qmi_svc)
567 {
568 QDF_STATUS status;
569
570 status = os_if_qmi_connect_to_svc(qmi_hdl, qmi_svc);
571 if (QDF_IS_STATUS_ERROR(status)) {
572 osif_err("Failed to connect to WFDS QMI service port");
573 return qdf_status_to_os_return(status);
574 }
575
576 status = ucfg_dp_wfds_new_server();
577
578 return qdf_status_to_os_return(status);
579 }
580
581 /**
582 * os_if_qmi_wfds_del_server() - Del server callback triggered when service is
583 * down.
584 * @qmi_hdl: QMI client handle
585 * @qmi_svc: QMI service handle
586 *
587 * Returns: None
588 */
589 static void
os_if_qmi_wfds_del_server(struct qmi_handle * qmi_hdl,struct qmi_service * qmi_svc)590 os_if_qmi_wfds_del_server(struct qmi_handle *qmi_hdl,
591 struct qmi_service *qmi_svc)
592 {
593 ucfg_dp_wfds_del_server();
594 }
595
596 static struct qmi_msg_handler qmi_wfds_msg_handler[] = {
597 {
598 .type = QMI_INDICATION,
599 .msg_id = QMI_WFDS_MEM_IND_V01,
600 .ei = wfds_mem_ind_msg_v01_ei,
601 .decoded_size = sizeof(struct wfds_mem_ind_msg_v01),
602 .fn = os_if_qmi_wfds_request_mem_ind_cb
603 },
604 {
605 .type = QMI_INDICATION,
606 .msg_id = QMI_WFDS_IPCC_MAP_N_CFG_IND_V01,
607 .ei = wfds_ipcc_map_n_cfg_ind_msg_v01_ei,
608 .decoded_size = sizeof(struct wfds_ipcc_map_n_cfg_ind_msg_v01),
609 .fn = os_if_wfds_ipcc_map_n_cfg_ind_cb
610 },
611 };
612
613 static struct qmi_ops qmi_wfds_ops = {
614 .new_server = os_if_qmi_wfds_new_server,
615 .del_server = os_if_qmi_wfds_del_server,
616 };
617
618 /**
619 * os_if_qmi_wfds_init() - Initialize WFDS QMI client
620 *
621 * Returns: QDF status
622 */
os_if_qmi_wfds_init(void)623 static QDF_STATUS os_if_qmi_wfds_init(void)
624 {
625 QDF_STATUS status;
626
627 status = os_if_qmi_handle_init(&qmi_wfds, QMI_WFDS_MAX_RECV_BUF_SIZE,
628 &qmi_wfds_ops, qmi_wfds_msg_handler);
629 if (QDF_IS_STATUS_ERROR(status)) {
630 osif_err("WFDS QMI handle init failed");
631 return status;
632 }
633
634 status = os_if_qmi_add_lookup(&qmi_wfds, WFDS_SERVICE_ID_V01,
635 WFDS_SERVICE_VERS_V01,
636 QMI_WFDS_SERVICE_INS_ID_V01);
637 if (QDF_IS_STATUS_ERROR(status)) {
638 osif_err("WFDS QMI add lookup failed");
639 os_if_qmi_handle_release(&qmi_wfds);
640 return status;
641 }
642
643 return status;
644 }
645
646 /**
647 * os_if_qmi_wfds_deinit() - Deinitialize WFDS QMI client
648 *
649 * Returns: None
650 */
os_if_qmi_wfds_deinit(void)651 static void os_if_qmi_wfds_deinit(void)
652 {
653 os_if_qmi_handle_release(&qmi_wfds);
654 }
655
os_if_qmi_wfds_register_callbacks(struct wlan_qmi_psoc_callbacks * cb_obj)656 void os_if_qmi_wfds_register_callbacks(struct wlan_qmi_psoc_callbacks *cb_obj)
657 {
658 cb_obj->qmi_wfds_init = os_if_qmi_wfds_init;
659 cb_obj->qmi_wfds_deinit = os_if_qmi_wfds_deinit;
660 cb_obj->qmi_wfds_send_config_msg = os_if_qmi_wfds_send_config_msg;
661 cb_obj->qmi_wfds_send_req_mem_msg = os_if_qmi_wfds_send_req_mem_msg;
662 cb_obj->qmi_wfds_send_ipcc_map_n_cfg_msg =
663 os_if_qmi_wfds_ipcc_map_n_cfg_msg;
664 cb_obj->qmi_wfds_send_misc_req_msg =
665 os_if_qmi_wfds_send_misc_req_msg;
666 }
667