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