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