xref: /wlan-driver/qcacld-3.0/os_if/qmi/src/os_if_qmi_wfds.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
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