1 /*
2 * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17 /**
18 * DOC: contains CoAP target if functions
19 */
20 #include <wlan_coap_main.h>
21 #include <target_if_coap.h>
22 #include <wmi_unified_coap_api.h>
23
24 /**
25 * target_if_wow_coap_buf_info_event_handler() - function to handle CoAP
26 * buf info event from firmware.
27 * @scn: scn handle
28 * @data: data buffer for event
29 * @datalen: data length
30 *
31 * Return: status of operation.
32 */
33 static int
target_if_wow_coap_buf_info_event_handler(ol_scn_t scn,uint8_t * data,uint32_t datalen)34 target_if_wow_coap_buf_info_event_handler(ol_scn_t scn, uint8_t *data,
35 uint32_t datalen)
36 {
37 QDF_STATUS status;
38 struct wlan_objmgr_psoc *psoc;
39 struct wmi_unified *wmi_handle;
40 struct wlan_objmgr_vdev *vdev = NULL;
41 struct wlan_coap_comp_priv *coap_priv;
42 struct coap_buf_info info = {0};
43 struct coap_buf_node *cur, *next;
44
45 if (!scn || !data) {
46 coap_err("scn: 0x%pK, data: 0x%pK", scn, data);
47 return -EINVAL;
48 }
49
50 psoc = target_if_get_psoc_from_scn_hdl(scn);
51 if (!psoc) {
52 coap_err("null psoc");
53 return -EINVAL;
54 }
55
56 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
57 if (!wmi_handle) {
58 coap_err("wmi_handle is null");
59 return -EINVAL;
60 }
61
62 qdf_list_create(&info.info_list, 0);
63 status = wmi_unified_coap_extract_buf_info(wmi_handle, data,
64 &info);
65 if (QDF_IS_STATUS_ERROR(status))
66 goto out;
67
68 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, info.vdev_id,
69 WLAN_COAP_ID);
70 if (!vdev) {
71 coap_err("vdev is NULL, vdev_id: %d", info.vdev_id);
72 status = QDF_STATUS_E_INVAL;
73 goto out;
74 }
75
76 coap_priv = wlan_get_vdev_coap_obj(vdev);
77 if (!coap_priv->cache_get_cbk || !coap_priv->cache_get_context) {
78 coap_err("req id %d: callback or context is NULL",
79 coap_priv->req_id);
80 status = QDF_STATUS_E_INVAL;
81 goto out;
82 }
83
84 coap_priv->cache_get_cbk(coap_priv->cache_get_context, &info);
85 out:
86 qdf_list_for_each_del(&info.info_list, cur, next, node) {
87 qdf_list_remove_node(&info.info_list, &cur->node);
88 qdf_mem_free(cur->payload);
89 qdf_mem_free(cur);
90 }
91
92 if (vdev)
93 wlan_objmgr_vdev_release_ref(vdev, WLAN_COAP_ID);
94 return qdf_status_to_os_return(status);
95 }
96
97 /**
98 * target_if_coap_register_event_handler() - Register CoAP related wmi events
99 * @psoc: psoc handle
100 *
101 * Register CoAP related WMI events
102 *
103 * return: QDF_STATUS
104 */
105 static QDF_STATUS
target_if_coap_register_event_handler(struct wlan_objmgr_psoc * psoc)106 target_if_coap_register_event_handler(struct wlan_objmgr_psoc *psoc)
107 {
108 QDF_STATUS ret_val;
109 struct wmi_unified *wmi_handle;
110
111 if (!psoc) {
112 coap_err("PSOC is NULL!");
113 return QDF_STATUS_E_NULL_VALUE;
114 }
115
116 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
117 if (!wmi_handle) {
118 coap_err("wmi_handle is null");
119 return QDF_STATUS_E_INVAL;
120 }
121
122 ret_val = wmi_unified_register_event_handler(wmi_handle,
123 wmi_wow_coap_buf_info_eventid,
124 target_if_wow_coap_buf_info_event_handler,
125 WMI_RX_WORK_CTX);
126 if (QDF_IS_STATUS_ERROR(ret_val))
127 coap_err("Failed to register coap buf info event cb");
128
129 return ret_val;
130 }
131
132 /**
133 * target_if_coap_unregister_event_handler() - Unregister CoAP related wmi
134 * events
135 * @psoc: psoc handle
136 *
137 * Register CoAP related WMI events
138 *
139 * return: QDF_STATUS
140 */
141 static QDF_STATUS
target_if_coap_unregister_event_handler(struct wlan_objmgr_psoc * psoc)142 target_if_coap_unregister_event_handler(struct wlan_objmgr_psoc *psoc)
143 {
144 struct wmi_unified *wmi_handle;
145
146 if (!psoc) {
147 coap_err("PSOC is NULL!");
148 return QDF_STATUS_E_INVAL;
149 }
150
151 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
152 if (!wmi_handle) {
153 coap_err("wmi_handle is null");
154 return QDF_STATUS_E_INVAL;
155 }
156 wmi_unified_unregister_event_handler(wmi_handle,
157 wmi_wow_coap_buf_info_eventid);
158
159 return QDF_STATUS_SUCCESS;
160 }
161
162 /**
163 * target_if_coap_offload_reply_enable() - enable CoAP offload reply
164 * @vdev: pointer to vdev object
165 * @param: parameters for CoAP offload reply
166 *
167 * Return: status of operation
168 */
169 static QDF_STATUS
target_if_coap_offload_reply_enable(struct wlan_objmgr_vdev * vdev,struct coap_offload_reply_param * param)170 target_if_coap_offload_reply_enable(struct wlan_objmgr_vdev *vdev,
171 struct coap_offload_reply_param *param)
172 {
173 wmi_unified_t wmi_handle;
174 struct wlan_objmgr_pdev *pdev;
175
176 pdev = wlan_vdev_get_pdev(vdev);
177 wmi_handle = GET_WMI_HDL_FROM_PDEV(pdev);
178 if (!wmi_handle) {
179 coap_err("Invalid PDEV WMI handle");
180 return QDF_STATUS_E_FAILURE;
181 }
182
183 return wmi_unified_coap_add_pattern_cmd(wmi_handle, param);
184 }
185
186 /**
187 * target_if_coap_offload_reply_disable() - disable CoAP offload reply
188 * @vdev: pointer to vdev object
189 * @req_id: request id
190 *
191 * Return: status of operation
192 */
193 static QDF_STATUS
target_if_coap_offload_reply_disable(struct wlan_objmgr_vdev * vdev,uint32_t req_id)194 target_if_coap_offload_reply_disable(struct wlan_objmgr_vdev *vdev,
195 uint32_t req_id)
196 {
197 wmi_unified_t wmi_handle;
198 struct wlan_objmgr_pdev *pdev;
199
200 pdev = wlan_vdev_get_pdev(vdev);
201 wmi_handle = GET_WMI_HDL_FROM_PDEV(pdev);
202 if (!wmi_handle) {
203 coap_err("Invalid PDEV WMI handle");
204 return QDF_STATUS_E_FAILURE;
205 }
206
207 return wmi_unified_coap_del_pattern_cmd(wmi_handle,
208 wlan_vdev_get_id(vdev),
209 req_id);
210 }
211
212 /**
213 * target_if_coap_offload_periodic_tx_enable() - enable CoAP offload
214 * periodic transmitting
215 * @vdev: pointer to vdev object
216 * @param: parameters for CoAP periodic transmitting
217 *
218 * Return: status of operation
219 */
220 static QDF_STATUS
target_if_coap_offload_periodic_tx_enable(struct wlan_objmgr_vdev * vdev,struct coap_offload_periodic_tx_param * param)221 target_if_coap_offload_periodic_tx_enable(struct wlan_objmgr_vdev *vdev,
222 struct coap_offload_periodic_tx_param *param)
223 {
224 wmi_unified_t wmi_handle;
225 struct wlan_objmgr_pdev *pdev;
226
227 pdev = wlan_vdev_get_pdev(vdev);
228 wmi_handle = GET_WMI_HDL_FROM_PDEV(pdev);
229 if (!wmi_handle) {
230 coap_err("Invalid PDEV WMI handle");
231 return QDF_STATUS_E_FAILURE;
232 }
233
234 return wmi_unified_coap_add_keepalive_pattern_cmd(wmi_handle, param);
235 }
236
237 /**
238 * target_if_coap_offload_periodic_tx_disable() - disable CoAP offload
239 * periodic transmitting
240 * @vdev: pointer to vdev object
241 * @req_id: request id
242 *
243 * Return: status of operation
244 */
245 static QDF_STATUS
target_if_coap_offload_periodic_tx_disable(struct wlan_objmgr_vdev * vdev,uint32_t req_id)246 target_if_coap_offload_periodic_tx_disable(struct wlan_objmgr_vdev *vdev,
247 uint32_t req_id)
248 {
249 wmi_unified_t wmi_handle;
250 struct wlan_objmgr_pdev *pdev;
251 uint8_t vdev_id;
252
253 pdev = wlan_vdev_get_pdev(vdev);
254 wmi_handle = GET_WMI_HDL_FROM_PDEV(pdev);
255 if (!wmi_handle) {
256 coap_err("Invalid PDEV WMI handle");
257 return QDF_STATUS_E_FAILURE;
258 }
259
260 vdev_id = wlan_vdev_get_id(vdev);
261 return wmi_unified_coap_del_keepalive_pattern_cmd(wmi_handle,
262 vdev_id, req_id);
263 }
264
265 /**
266 * target_if_coap_offload_cache_get() - get cached CoAP messages
267 * @vdev: pointer to vdev object
268 * @req_id: request id
269 *
270 * Return: status of operation
271 */
272 static QDF_STATUS
target_if_coap_offload_cache_get(struct wlan_objmgr_vdev * vdev,uint32_t req_id)273 target_if_coap_offload_cache_get(struct wlan_objmgr_vdev *vdev,
274 uint32_t req_id)
275 {
276 wmi_unified_t wmi_handle;
277 struct wlan_objmgr_pdev *pdev;
278
279 pdev = wlan_vdev_get_pdev(vdev);
280 wmi_handle = GET_WMI_HDL_FROM_PDEV(pdev);
281 if (!wmi_handle) {
282 coap_err("Invalid PDEV WMI handle");
283 return QDF_STATUS_E_FAILURE;
284 }
285
286 return wmi_unified_coap_cache_get(wmi_handle, wlan_vdev_get_id(vdev),
287 req_id);
288 }
289
290 QDF_STATUS
target_if_coap_register_tx_ops(struct wlan_lmac_if_tx_ops * tx_ops)291 target_if_coap_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
292 {
293 struct wlan_lmac_if_coap_tx_ops *coap_ops;
294
295 if (!tx_ops) {
296 coap_err("target if tx ops is NULL!");
297 return QDF_STATUS_E_INVAL;
298 }
299
300 coap_ops = &tx_ops->coap_ops;
301 coap_ops->attach = target_if_coap_register_event_handler;
302 coap_ops->detach = target_if_coap_unregister_event_handler;
303 coap_ops->offload_reply_enable =
304 target_if_coap_offload_reply_enable;
305 coap_ops->offload_reply_disable =
306 target_if_coap_offload_reply_disable;
307 coap_ops->offload_periodic_tx_enable =
308 target_if_coap_offload_periodic_tx_enable;
309 coap_ops->offload_periodic_tx_disable =
310 target_if_coap_offload_periodic_tx_disable;
311 coap_ops->offload_cache_get = target_if_coap_offload_cache_get;
312
313 return QDF_STATUS_SUCCESS;
314 }
315