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