xref: /wlan-dirver/qca-wifi-host-cmn/target_if/ftm/src/target_if_ftm.c (revision 302a1d9701784af5f4797b1a9fe07ae820b51907)
1 /*
2  * Copyright (c) 2018 The Linux Foundation. All rights reserved.
3  *
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 /**
21  * DOC: offload lmac interface APIs definitions for FTM
22  */
23 
24 #include <qdf_status.h>
25 #include <target_if_ftm.h>
26 #include <wmi_unified_priv.h>
27 #include <wlan_objmgr_psoc_obj.h>
28 #include <target_if.h>
29 #include <wlan_lmac_if_def.h>
30 #include <wlan_ftm_ucfg_api.h>
31 
32 static inline struct wlan_lmac_if_ftm_rx_ops *
33 target_if_ftm_get_rx_ops(struct wlan_objmgr_psoc *psoc)
34 {
35 	return &psoc->soc_cb.rx_ops.ftm_rx_ops;
36 }
37 
38 static int
39 target_if_ftm_process_utf_event(ol_scn_t sc, uint8_t *event_buf, uint32_t len)
40 {
41 	struct wlan_objmgr_psoc *psoc;
42 	struct wlan_objmgr_pdev *pdev;
43 	struct wmi_host_pdev_utf_event event;
44 	struct wlan_lmac_if_ftm_rx_ops *ftm_rx_ops;
45 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
46 	uint32_t pdev_id;
47 	struct wmi_unified *wmi_handle;
48 
49 	psoc = target_if_get_psoc_from_scn_hdl(sc);
50 	if (!psoc) {
51 		ftm_err("null psoc");
52 		return QDF_STATUS_E_INVAL;
53 	}
54 
55 	status = wlan_objmgr_psoc_try_get_ref(psoc, WLAN_FTM_ID);
56 	if (QDF_IS_STATUS_ERROR(status)) {
57 		ftm_err("unable to get psoc reference");
58 		return QDF_STATUS_E_INVAL;
59 	}
60 
61 	event.datalen = len;
62 
63 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
64 	if (!wmi_handle) {
65 		ftm_err("Invalid WMI handle");
66 		wlan_objmgr_psoc_release_ref(psoc, WLAN_FTM_ID);
67 		return QDF_STATUS_E_INVAL;
68 	}
69 
70 	if (wmi_extract_pdev_utf_event(wmi_handle, event_buf, &event)
71 	    != QDF_STATUS_SUCCESS) {
72 		ftm_err("Extracting utf event failed");
73 		wlan_objmgr_psoc_release_ref(psoc, WLAN_FTM_ID);
74 		return QDF_STATUS_E_INVAL;
75 	}
76 
77 	pdev_id = event.pdev_id;
78 	pdev = wlan_objmgr_get_pdev_by_id(psoc, pdev_id, WLAN_FTM_ID);
79 	if (!pdev) {
80 		pdev_id = TGT_WMI_PDEV_ID_SOC;
81 		ftm_debug("Can't find pdev by pdev_id %d, try soc_id",
82 			  event.pdev_id);
83 		pdev = wlan_objmgr_get_pdev_by_id(psoc, pdev_id, WLAN_FTM_ID);
84 		if (!pdev) {
85 			ftm_err("null pdev");
86 			wlan_objmgr_psoc_release_ref(psoc, WLAN_FTM_ID);
87 			return QDF_STATUS_E_INVAL;
88 		}
89 	}
90 
91 	ftm_rx_ops = target_if_ftm_get_rx_ops(psoc);
92 
93 	if (ftm_rx_ops->ftm_ev_handler) {
94 		status = ftm_rx_ops->ftm_ev_handler(pdev,
95 				event.data, event.datalen);
96 		if (QDF_IS_STATUS_ERROR(status))
97 			status = QDF_STATUS_E_INVAL;
98 	} else {
99 		status = QDF_STATUS_E_INVAL;
100 	}
101 
102 	wlan_objmgr_pdev_release_ref(pdev, WLAN_FTM_ID);
103 	wlan_objmgr_psoc_release_ref(psoc, WLAN_FTM_ID);
104 
105 	return status;
106 }
107 
108 QDF_STATUS target_if_ftm_cmd_send(struct wlan_objmgr_pdev *pdev,
109 				  uint8_t *buf, uint32_t len,
110 				  uint8_t pdev_id)
111 {
112 	QDF_STATUS ret;
113 	wmi_unified_t handle;
114 	struct pdev_utf_params param;
115 
116 	if (!pdev) {
117 		target_if_err("null pdev");
118 		return QDF_STATUS_E_FAILURE;
119 	}
120 
121 	handle = get_wmi_unified_hdl_from_pdev(pdev);
122 	if (!handle) {
123 		target_if_err("null handle");
124 		return QDF_STATUS_E_FAILURE;
125 	}
126 	param.utf_payload = buf;
127 	param.len = len;
128 
129 	ret = wmi_unified_pdev_utf_cmd_send(handle, &param, pdev_id);
130 	if (QDF_IS_STATUS_ERROR(ret))
131 		ftm_err("wmi utf cmd send failed, ret: %d", ret);
132 
133 	return ret;
134 }
135 
136 QDF_STATUS target_if_ftm_attach(struct wlan_objmgr_psoc *psoc)
137 {
138 	int ret;
139 	wmi_unified_t handle;
140 
141 	if (!psoc) {
142 		target_if_err("null psoc");
143 		return QDF_STATUS_E_FAILURE;
144 	}
145 
146 	handle = get_wmi_unified_hdl_from_psoc(psoc);
147 	if (!handle) {
148 		target_if_err("null handle");
149 		return QDF_STATUS_E_FAILURE;
150 	}
151 	ret = wmi_unified_register_event_handler(handle,
152 			wmi_pdev_utf_event_id,
153 			target_if_ftm_process_utf_event,
154 			WMI_RX_UMAC_CTX);
155 	if (ret) {
156 		ftm_err("wmi event registration failed, ret: %d", ret);
157 		return QDF_STATUS_E_FAILURE;
158 	}
159 
160 	return QDF_STATUS_SUCCESS;
161 }
162 
163 QDF_STATUS target_if_ftm_detach(struct wlan_objmgr_psoc *psoc)
164 
165 {
166 	int ret;
167 	wmi_unified_t handle;
168 
169 	if (!psoc) {
170 		target_if_err("null psoc");
171 		return QDF_STATUS_E_FAILURE;
172 	}
173 
174 	handle = get_wmi_unified_hdl_from_psoc(psoc);
175 	if (!handle) {
176 		target_if_err("null handle");
177 		return QDF_STATUS_E_FAILURE;
178 	}
179 	ret = wmi_unified_unregister_event_handler(handle,
180 						   wmi_pdev_utf_event_id);
181 
182 	if (ret) {
183 		ftm_err("wmi event deregistration failed, ret: %d", ret);
184 		return QDF_STATUS_E_FAILURE;
185 	}
186 
187 	return QDF_STATUS_SUCCESS;
188 }
189 
190 QDF_STATUS target_if_ftm_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
191 {
192 	struct wlan_lmac_if_ftm_tx_ops *ftm_tx_ops;
193 
194 	if (!tx_ops) {
195 		ftm_err("invalid tx_ops");
196 		return QDF_STATUS_E_FAILURE;
197 	}
198 
199 	ftm_tx_ops = &tx_ops->ftm_tx_ops;
200 	ftm_tx_ops->ftm_attach = target_if_ftm_attach;
201 	ftm_tx_ops->ftm_detach = target_if_ftm_detach;
202 	ftm_tx_ops->ftm_cmd_send = target_if_ftm_cmd_send;
203 
204 	return QDF_STATUS_SUCCESS;
205 }
206