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