xref: /wlan-dirver/qca-wifi-host-cmn/wmi/src/wmi_unified_twt_tlv.c (revision 97f44cd39e4ff816eaa1710279d28cf6b9e65ad9)
1 /*
2  * Copyright (c) 2018-2020 The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for
5  * any purpose with or without fee is hereby granted, provided that the
6  * above copyright notice and this permission notice appear in all
7  * copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <osdep.h>
20 #include "wmi.h"
21 #include "wmi_unified_priv.h"
22 #include "wmi_unified_twt_param.h"
23 #include "wmi_unified_twt_api.h"
24 
25 static QDF_STATUS send_twt_enable_cmd_tlv(wmi_unified_t wmi_handle,
26 			struct wmi_twt_enable_param *params)
27 {
28 	wmi_twt_enable_cmd_fixed_param *cmd;
29 	wmi_buf_t buf;
30 	QDF_STATUS status;
31 
32 	buf = wmi_buf_alloc(wmi_handle, sizeof(*cmd));
33 	if (!buf) {
34 		wmi_err("Failed to allocate memory");
35 		return QDF_STATUS_E_FAILURE;
36 	}
37 
38 	cmd = (wmi_twt_enable_cmd_fixed_param *) wmi_buf_data(buf);
39 	WMITLV_SET_HDR(&cmd->tlv_header,
40 			WMITLV_TAG_STRUC_wmi_twt_enable_cmd_fixed_param,
41 			WMITLV_GET_STRUCT_TLVLEN
42 			(wmi_twt_enable_cmd_fixed_param));
43 
44 	cmd->pdev_id =
45 		wmi_handle->ops->convert_pdev_id_host_to_target(
46 						wmi_handle,
47 						params->pdev_id);
48 	cmd->sta_cong_timer_ms =            params->sta_cong_timer_ms;
49 	cmd->mbss_support =                 params->mbss_support;
50 	cmd->default_slot_size =            params->default_slot_size;
51 	cmd->congestion_thresh_setup =      params->congestion_thresh_setup;
52 	cmd->congestion_thresh_teardown =   params->congestion_thresh_teardown;
53 	cmd->congestion_thresh_critical =   params->congestion_thresh_critical;
54 	cmd->interference_thresh_teardown =
55 					params->interference_thresh_teardown;
56 	cmd->interference_thresh_setup =    params->interference_thresh_setup;
57 	cmd->min_no_sta_setup =             params->min_no_sta_setup;
58 	cmd->min_no_sta_teardown =          params->min_no_sta_teardown;
59 	cmd->no_of_bcast_mcast_slots =      params->no_of_bcast_mcast_slots;
60 	cmd->min_no_twt_slots =             params->min_no_twt_slots;
61 	cmd->max_no_sta_twt =               params->max_no_sta_twt;
62 	cmd->mode_check_interval =          params->mode_check_interval;
63 	cmd->add_sta_slot_interval =        params->add_sta_slot_interval;
64 	cmd->remove_sta_slot_interval =     params->remove_sta_slot_interval;
65 
66 	TWT_EN_DIS_FLAGS_SET_BTWT(cmd->flags, params->b_twt_enable);
67 	TWT_EN_DIS_FLAGS_SET_L_MBSSID(cmd->flags,
68 				      params->b_twt_legacy_mbss_enable);
69 	TWT_EN_DIS_FLAGS_SET_AX_MBSSID(cmd->flags,
70 				       params->b_twt_ax_mbss_enable);
71 
72 	status = wmi_unified_cmd_send(wmi_handle, buf, sizeof(*cmd),
73 			WMI_TWT_ENABLE_CMDID);
74 	if (QDF_IS_STATUS_ERROR(status)) {
75 		wmi_err("Failed to send WMI_TWT_ENABLE_CMDID");
76 		wmi_buf_free(buf);
77 	}
78 
79 	return status;
80 }
81 
82 
83 static QDF_STATUS send_twt_disable_cmd_tlv(wmi_unified_t wmi_handle,
84 			struct wmi_twt_disable_param *params)
85 {
86 	wmi_twt_disable_cmd_fixed_param *cmd;
87 	wmi_buf_t buf;
88 	QDF_STATUS status;
89 
90 	buf = wmi_buf_alloc(wmi_handle, sizeof(*cmd));
91 	if (!buf) {
92 		wmi_err("Failed to allocate memory");
93 		return QDF_STATUS_E_FAILURE;
94 	}
95 
96 	cmd = (wmi_twt_disable_cmd_fixed_param *) wmi_buf_data(buf);
97 	WMITLV_SET_HDR(&cmd->tlv_header,
98 			WMITLV_TAG_STRUC_wmi_twt_disable_cmd_fixed_param,
99 			WMITLV_GET_STRUCT_TLVLEN
100 			(wmi_twt_disable_cmd_fixed_param));
101 
102 	cmd->pdev_id =
103 		wmi_handle->ops->convert_pdev_id_host_to_target(
104 						wmi_handle,
105 						params->pdev_id);
106 
107 	status = wmi_unified_cmd_send(wmi_handle, buf, sizeof(*cmd),
108 			WMI_TWT_DISABLE_CMDID);
109 	if (QDF_IS_STATUS_ERROR(status)) {
110 		wmi_err("Failed to send WMI_TWT_DISABLE_CMDID");
111 		wmi_buf_free(buf);
112 	}
113 
114 	return status;
115 }
116 
117 #ifdef WLAN_SUPPORT_BCAST_TWT
118 static void
119 twt_add_dialog_set_bcast_twt_params(struct wmi_twt_add_dialog_param *params,
120                 wmi_twt_add_dialog_cmd_fixed_param *cmd)
121 {
122 	TWT_FLAGS_SET_BTWT_ID0(cmd->flags, params->flag_b_twt_id0);
123 	cmd->b_twt_persistence = params->b_twt_persistence;
124 	cmd->b_twt_recommendation = params->b_twt_recommendation;
125 
126 	return;
127 }
128 #else
129 static void
130 twt_add_dialog_set_bcast_twt_params(struct wmi_twt_add_dialog_param *params,
131                 wmi_twt_add_dialog_cmd_fixed_param *cmd)
132 {
133 	return;
134 }
135 #endif
136 
137 static QDF_STATUS
138 send_twt_add_dialog_cmd_tlv(wmi_unified_t wmi_handle,
139 			    struct wmi_twt_add_dialog_param *params)
140 {
141 	wmi_twt_add_dialog_cmd_fixed_param *cmd;
142 	wmi_buf_t buf;
143 	QDF_STATUS status;
144 
145 	buf = wmi_buf_alloc(wmi_handle, sizeof(*cmd));
146 	if (!buf) {
147 		wmi_err("Failed to allocate memory");
148 		return QDF_STATUS_E_FAILURE;
149 	}
150 
151 	cmd = (wmi_twt_add_dialog_cmd_fixed_param *) wmi_buf_data(buf);
152 	WMITLV_SET_HDR(&cmd->tlv_header,
153 		       WMITLV_TAG_STRUC_wmi_twt_add_dialog_cmd_fixed_param,
154 		       WMITLV_GET_STRUCT_TLVLEN
155 		       (wmi_twt_add_dialog_cmd_fixed_param));
156 
157 	cmd->vdev_id = params->vdev_id;
158 	WMI_CHAR_ARRAY_TO_MAC_ADDR(params->peer_macaddr, &cmd->peer_macaddr);
159 	cmd->dialog_id =         params->dialog_id;
160 	cmd->wake_intvl_us =     params->wake_intvl_us;
161 	cmd->wake_intvl_mantis = params->wake_intvl_mantis;
162 	cmd->wake_dura_us =      params->wake_dura_us;
163 	cmd->sp_offset_us =      params->sp_offset_us;
164 	TWT_FLAGS_SET_CMD(cmd->flags, params->twt_cmd);
165 	TWT_FLAGS_SET_BROADCAST(cmd->flags, params->flag_bcast);
166 	TWT_FLAGS_SET_TRIGGER(cmd->flags, params->flag_trigger);
167 	TWT_FLAGS_SET_FLOW_TYPE(cmd->flags, params->flag_flow_type);
168 	TWT_FLAGS_SET_PROTECTION(cmd->flags, params->flag_protection);
169 
170 	twt_add_dialog_set_bcast_twt_params(params, cmd);
171 
172 	status = wmi_unified_cmd_send(wmi_handle, buf, sizeof(*cmd),
173 				      WMI_TWT_ADD_DIALOG_CMDID);
174 	if (QDF_IS_STATUS_ERROR(status)) {
175 		wmi_err("Failed to send WMI_TWT_ADD_DIALOG_CMDID");
176 		wmi_buf_free(buf);
177 	}
178 
179 	return status;
180 }
181 
182 #ifdef WLAN_SUPPORT_BCAST_TWT
183 static void
184 twt_del_dialog_set_bcast_twt_params(struct wmi_twt_del_dialog_param *params,
185                 wmi_twt_del_dialog_cmd_fixed_param *cmd)
186 {
187 	cmd->b_twt_persistence = params->b_twt_persistence;
188 	return;
189 }
190 #else
191 static void
192 twt_del_dialog_set_bcast_twt_params(struct wmi_twt_del_dialog_param *params,
193                 wmi_twt_del_dialog_cmd_fixed_param *cmd)
194 {
195 	return;
196 }
197 #endif
198 
199 static QDF_STATUS
200 send_twt_del_dialog_cmd_tlv(wmi_unified_t wmi_handle,
201 			    struct wmi_twt_del_dialog_param *params)
202 {
203 	wmi_twt_del_dialog_cmd_fixed_param *cmd;
204 	wmi_buf_t buf;
205 	QDF_STATUS status;
206 
207 	buf = wmi_buf_alloc(wmi_handle, sizeof(*cmd));
208 	if (!buf) {
209 		wmi_err("Failed to allocate memory");
210 		return QDF_STATUS_E_FAILURE;
211 	}
212 
213 	cmd = (wmi_twt_del_dialog_cmd_fixed_param *) wmi_buf_data(buf);
214 	WMITLV_SET_HDR(&cmd->tlv_header,
215 		       WMITLV_TAG_STRUC_wmi_twt_del_dialog_cmd_fixed_param,
216 		       WMITLV_GET_STRUCT_TLVLEN
217 		       (wmi_twt_del_dialog_cmd_fixed_param));
218 
219 	cmd->vdev_id = params->vdev_id;
220 	WMI_CHAR_ARRAY_TO_MAC_ADDR(params->peer_macaddr, &cmd->peer_macaddr);
221 	cmd->dialog_id = params->dialog_id;
222 
223 	twt_del_dialog_set_bcast_twt_params(params, cmd);
224 
225 	status = wmi_unified_cmd_send(wmi_handle, buf, sizeof(*cmd),
226 				      WMI_TWT_DEL_DIALOG_CMDID);
227 	if (QDF_IS_STATUS_ERROR(status)) {
228 		wmi_err("Failed to send WMI_TWT_DEL_DIALOG_CMDID");
229 		wmi_buf_free(buf);
230 	}
231 
232 	return status;
233 }
234 
235 static QDF_STATUS
236 send_twt_pause_dialog_cmd_tlv(wmi_unified_t wmi_handle,
237 			      struct wmi_twt_pause_dialog_cmd_param *params)
238 {
239 	wmi_twt_pause_dialog_cmd_fixed_param *cmd;
240 	wmi_buf_t buf;
241 	QDF_STATUS status;
242 
243 	buf = wmi_buf_alloc(wmi_handle, sizeof(*cmd));
244 	if (!buf) {
245 		wmi_err("Failed to allocate memory");
246 		return QDF_STATUS_E_FAILURE;
247 	}
248 
249 	cmd = (wmi_twt_pause_dialog_cmd_fixed_param *) wmi_buf_data(buf);
250 	WMITLV_SET_HDR(&cmd->tlv_header,
251 		       WMITLV_TAG_STRUC_wmi_twt_pause_dialog_cmd_fixed_param,
252 		       WMITLV_GET_STRUCT_TLVLEN
253 		       (wmi_twt_pause_dialog_cmd_fixed_param));
254 
255 	cmd->vdev_id = params->vdev_id;
256 	WMI_CHAR_ARRAY_TO_MAC_ADDR(params->peer_macaddr, &cmd->peer_macaddr);
257 	cmd->dialog_id = params->dialog_id;
258 
259 	status = wmi_unified_cmd_send(wmi_handle, buf, sizeof(*cmd),
260 				      WMI_TWT_PAUSE_DIALOG_CMDID);
261 	if (QDF_IS_STATUS_ERROR(status)) {
262 		wmi_err("Failed to send WMI_TWT_PAUSE_DIALOG_CMDID");
263 		wmi_buf_free(buf);
264 	}
265 
266 	return status;
267 }
268 
269 static QDF_STATUS send_twt_resume_dialog_cmd_tlv(wmi_unified_t wmi_handle,
270 			struct wmi_twt_resume_dialog_cmd_param *params)
271 {
272 	wmi_twt_resume_dialog_cmd_fixed_param *cmd;
273 	wmi_buf_t buf;
274 	QDF_STATUS status;
275 
276 	buf = wmi_buf_alloc(wmi_handle, sizeof(*cmd));
277 	if (!buf) {
278 		wmi_err("Failed to allocate memory");
279 		return QDF_STATUS_E_FAILURE;
280 	}
281 
282 	cmd = (wmi_twt_resume_dialog_cmd_fixed_param *) wmi_buf_data(buf);
283 	WMITLV_SET_HDR(&cmd->tlv_header,
284 			WMITLV_TAG_STRUC_wmi_twt_resume_dialog_cmd_fixed_param,
285 			WMITLV_GET_STRUCT_TLVLEN
286 			(wmi_twt_resume_dialog_cmd_fixed_param));
287 
288 	cmd->vdev_id = params->vdev_id;
289 	WMI_CHAR_ARRAY_TO_MAC_ADDR(params->peer_macaddr, &cmd->peer_macaddr);
290 	cmd->dialog_id = params->dialog_id;
291 	cmd->sp_offset_us = params->sp_offset_us;
292 	cmd->next_twt_size = params->next_twt_size;
293 
294 	status = wmi_unified_cmd_send(wmi_handle, buf, sizeof(*cmd),
295 						WMI_TWT_RESUME_DIALOG_CMDID);
296 	if (QDF_IS_STATUS_ERROR(status)) {
297 		wmi_err("Failed to send WMI_TWT_RESUME_DIALOG_CMDID");
298 		wmi_buf_free(buf);
299 	}
300 
301 	return status;
302 }
303 
304 #ifdef WLAN_SUPPORT_BCAST_TWT
305 static QDF_STATUS
306 send_twt_btwt_invite_sta_cmd_tlv(wmi_unified_t wmi_handle,
307 				 struct wmi_twt_btwt_invite_sta_cmd_param
308 				 *params)
309 {
310 	wmi_twt_btwt_invite_sta_cmd_fixed_param *cmd;
311 	wmi_buf_t buf;
312 	QDF_STATUS status;
313 
314 	buf = wmi_buf_alloc(wmi_handle, sizeof(*cmd));
315 	if (!buf) {
316 		wmi_err("Failed to allocate memory");
317 		return QDF_STATUS_E_FAILURE;
318 	}
319 
320 	cmd = (wmi_twt_btwt_invite_sta_cmd_fixed_param *)wmi_buf_data(buf);
321 	WMITLV_SET_HDR(&cmd->tlv_header,
322 		       WMITLV_TAG_STRUC_wmi_twt_btwt_invite_sta_cmd_fixed_param,
323 		       WMITLV_GET_STRUCT_TLVLEN
324 		       (wmi_twt_btwt_invite_sta_cmd_fixed_param));
325 
326 	cmd->vdev_id = params->vdev_id;
327 	WMI_CHAR_ARRAY_TO_MAC_ADDR(params->peer_macaddr, &cmd->peer_macaddr);
328 	cmd->dialog_id = params->dialog_id;
329 
330 	status = wmi_unified_cmd_send(wmi_handle, buf, sizeof(*cmd),
331 				      WMI_TWT_BTWT_INVITE_STA_CMDID);
332 	if (QDF_IS_STATUS_ERROR(status)) {
333 		wmi_buf_free(buf);
334 	}
335 
336 	return status;
337 }
338 
339 static QDF_STATUS
340 send_twt_btwt_remove_sta_cmd_tlv(wmi_unified_t wmi_handle,
341 				 struct wmi_twt_btwt_remove_sta_cmd_param
342 				 *params)
343 {
344 	wmi_twt_btwt_remove_sta_cmd_fixed_param *cmd;
345 	wmi_buf_t buf;
346 	QDF_STATUS status;
347 
348 	buf = wmi_buf_alloc(wmi_handle, sizeof(*cmd));
349 	if (!buf) {
350 		wmi_err("Failed to allocate memory");
351 		return QDF_STATUS_E_FAILURE;
352 	}
353 
354 	cmd = (wmi_twt_btwt_remove_sta_cmd_fixed_param *)wmi_buf_data(buf);
355 	WMITLV_SET_HDR(&cmd->tlv_header,
356 		       WMITLV_TAG_STRUC_wmi_twt_btwt_remove_sta_cmd_fixed_param,
357 		       WMITLV_GET_STRUCT_TLVLEN
358 		       (wmi_twt_btwt_remove_sta_cmd_fixed_param));
359 
360 	cmd->vdev_id = params->vdev_id;
361 	WMI_CHAR_ARRAY_TO_MAC_ADDR(params->peer_macaddr, &cmd->peer_macaddr);
362 	cmd->dialog_id = params->dialog_id;
363 
364 	status = wmi_unified_cmd_send(wmi_handle, buf, sizeof(*cmd),
365 				      WMI_TWT_BTWT_REMOVE_STA_CMDID);
366 	if (QDF_IS_STATUS_ERROR(status)) {
367 		wmi_buf_free(buf);
368 	}
369 
370 	return status;
371 }
372 #endif
373 
374 static QDF_STATUS extract_twt_enable_comp_event_tlv(wmi_unified_t wmi_handle,
375 		uint8_t *evt_buf,
376 		struct wmi_twt_enable_complete_event_param *params)
377 {
378 	WMI_TWT_ENABLE_COMPLETE_EVENTID_param_tlvs *param_buf;
379 	wmi_twt_enable_complete_event_fixed_param *ev;
380 
381 	param_buf = (WMI_TWT_ENABLE_COMPLETE_EVENTID_param_tlvs *)evt_buf;
382 	if (!param_buf) {
383 		wmi_err("evt_buf is NULL");
384 		return QDF_STATUS_E_INVAL;
385 	}
386 
387 	ev = param_buf->fixed_param;
388 
389 	params->pdev_id =
390 		wmi_handle->ops->convert_pdev_id_target_to_host(wmi_handle,
391 								ev->pdev_id);
392 	params->status = ev->status;
393 
394 	return QDF_STATUS_SUCCESS;
395 }
396 
397 static QDF_STATUS extract_twt_disable_comp_event_tlv(wmi_unified_t wmi_handle,
398 		uint8_t *evt_buf,
399 		struct wmi_twt_disable_complete_event *params)
400 {
401 	WMI_TWT_DISABLE_COMPLETE_EVENTID_param_tlvs *param_buf;
402 	wmi_twt_disable_complete_event_fixed_param *ev;
403 
404 	param_buf = (WMI_TWT_DISABLE_COMPLETE_EVENTID_param_tlvs *)evt_buf;
405 	if (!param_buf) {
406 		wmi_err("evt_buf is NULL");
407 		return QDF_STATUS_E_INVAL;
408 	}
409 
410 	ev = param_buf->fixed_param;
411 
412 #if 0
413 	params->pdev_id =
414 		wmi_handle->ops->convert_pdev_id_target_to_host(ev->pdev_id);
415 	params->status = ev->status;
416 #endif
417 
418 	return QDF_STATUS_SUCCESS;
419 }
420 
421 /**
422  * extract_twt_add_dialog_comp_event_tlv - Extacts twt add dialog complete wmi
423  * event from firmware
424  * @wmi_hande: WMI handle
425  * @evt_buf: Pointer to wmi event buf of twt add dialog complete event
426  * @params: Pointer to store the extracted parameters
427  *
428  * Return: QDF_STATUS_SUCCESS on success or QDF STATUS error values on failure
429  */
430 static QDF_STATUS extract_twt_add_dialog_comp_event_tlv(
431 		wmi_unified_t wmi_handle,
432 		uint8_t *evt_buf,
433 		struct wmi_twt_add_dialog_complete_event_param *params)
434 {
435 	WMI_TWT_ADD_DIALOG_COMPLETE_EVENTID_param_tlvs *param_buf;
436 	wmi_twt_add_dialog_complete_event_fixed_param *ev;
437 
438 	param_buf = (WMI_TWT_ADD_DIALOG_COMPLETE_EVENTID_param_tlvs *)evt_buf;
439 	if (!param_buf) {
440 		wmi_err("evt_buf is NULL");
441 		return QDF_STATUS_E_INVAL;
442 	}
443 
444 	ev = param_buf->fixed_param;
445 
446 	params->vdev_id = ev->vdev_id;
447 	WMI_MAC_ADDR_TO_CHAR_ARRAY(&ev->peer_macaddr, params->peer_macaddr);
448 	params->status = ev->status;
449 	params->dialog_id = ev->dialog_id;
450 	params->num_additional_twt_params = param_buf->num_twt_params;
451 
452 	return QDF_STATUS_SUCCESS;
453 }
454 
455 /**
456  * extract_twt_add_dialog_comp_additional_parameters() - Extracts additional twt
457  * twt parameters, as part of add dialog completion event
458  * @wmi_hdl: wmi handle
459  * @evt_buf: Pointer event buffer
460  * @evt_buf_len: length of the add dialog event buffer
461  * @idx: index of num_twt_params
462  * @additional_params: twt additional parameters to extract
463  *
464  * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_INVAL for failure
465  */
466 static QDF_STATUS extract_twt_add_dialog_comp_additional_parameters
467 (
468 	wmi_unified_t wmi_handle, uint8_t *evt_buf,
469 	uint32_t evt_buf_len, uint32_t idx,
470 	struct wmi_twt_add_dialog_additional_params *additional_params
471 )
472 {
473 	WMI_TWT_ADD_DIALOG_COMPLETE_EVENTID_param_tlvs *param_buf;
474 	wmi_twt_add_dialog_complete_event_fixed_param *ev;
475 	uint32_t flags = 0;
476 	uint32_t expected_len;
477 
478 	param_buf = (WMI_TWT_ADD_DIALOG_COMPLETE_EVENTID_param_tlvs *)evt_buf;
479 	if (!param_buf) {
480 		wmi_err("evt_buf is NULL");
481 		return QDF_STATUS_E_INVAL;
482 	}
483 
484 	ev = param_buf->fixed_param;
485 
486 	/*
487 	 * For Alternate values from AP, Firmware sends additional params
488 	 * with WMI_HOST_ADD_TWT_STATUS_DENIED
489 	 */
490 	if (ev->status != WMI_HOST_ADD_TWT_STATUS_OK &&
491 	    ev->status != WMI_HOST_ADD_TWT_STATUS_DENIED) {
492 		wmi_err("Status of add dialog complete is not success");
493 		return QDF_STATUS_E_INVAL;
494 	}
495 
496 	if (idx >= param_buf->num_twt_params) {
497 		wmi_err("Invalid idx %d while num_twt_params = %d",
498 			 idx, param_buf->num_twt_params);
499 		return QDF_STATUS_E_INVAL;
500 	}
501 
502 	if (!param_buf->twt_params) {
503 		wmi_err("Unable to extract additional twt parameters");
504 		return QDF_STATUS_E_INVAL;
505 	}
506 
507 	expected_len = (sizeof(wmi_twt_add_dialog_complete_event_fixed_param) +
508 			WMI_TLV_HDR_SIZE + (param_buf->num_twt_params *
509 			sizeof(wmi_twt_add_dialog_additional_params)));
510 
511 	if (evt_buf_len != expected_len) {
512 		wmi_err("Got invalid len data from FW %d expected %d",
513 			 evt_buf_len, expected_len);
514 		return QDF_STATUS_E_INVAL;
515 	}
516 
517 	flags = param_buf->twt_params[idx].flags;
518 	additional_params->twt_cmd = TWT_FLAGS_GET_CMD(flags);
519 	additional_params->bcast = TWT_FLAGS_GET_BROADCAST(flags);
520 	additional_params->trig_en = TWT_FLAGS_GET_TRIGGER(flags);
521 	additional_params->announce = TWT_FLAGS_GET_FLOW_TYPE(flags);
522 	additional_params->protection = TWT_FLAGS_GET_PROTECTION(flags);
523 	additional_params->b_twt_id0 = TWT_FLAGS_GET_BTWT_ID0(flags);
524 	additional_params->info_frame_disabled =
525 				TWT_FLAGS_GET_TWT_INFO_FRAME_DISABLED(flags);
526 	additional_params->wake_dur_us = param_buf->twt_params[idx].wake_dur_us;
527 	additional_params->wake_intvl_us =
528 				param_buf->twt_params[idx].wake_intvl_us;
529 	additional_params->sp_offset_us =
530 				param_buf->twt_params[idx].sp_offset_us;
531 	additional_params->sp_tsf_us_lo =
532 				param_buf->twt_params[idx].sp_tsf_us_lo;
533 	additional_params->sp_tsf_us_hi =
534 				param_buf->twt_params[idx].sp_tsf_us_hi;
535 
536 	return QDF_STATUS_SUCCESS;
537 }
538 
539 static QDF_STATUS extract_twt_del_dialog_comp_event_tlv(
540 		wmi_unified_t wmi_handle,
541 		uint8_t *evt_buf,
542 		struct wmi_twt_del_dialog_complete_event_param *params)
543 {
544 	WMI_TWT_DEL_DIALOG_COMPLETE_EVENTID_param_tlvs *param_buf;
545 	wmi_twt_del_dialog_complete_event_fixed_param *ev;
546 
547 	param_buf = (WMI_TWT_DEL_DIALOG_COMPLETE_EVENTID_param_tlvs *)evt_buf;
548 	if (!param_buf) {
549 		wmi_err("evt_buf is NULL");
550 		return QDF_STATUS_E_INVAL;
551 	}
552 
553 	ev = param_buf->fixed_param;
554 
555 	params->vdev_id = ev->vdev_id;
556 	WMI_MAC_ADDR_TO_CHAR_ARRAY(&ev->peer_macaddr, params->peer_macaddr);
557 	params->dialog_id = ev->dialog_id;
558 	params->status = ev->status;
559 
560 	return QDF_STATUS_SUCCESS;
561 }
562 
563 static QDF_STATUS extract_twt_pause_dialog_comp_event_tlv(
564 		wmi_unified_t wmi_handle,
565 		uint8_t *evt_buf,
566 		struct wmi_twt_pause_dialog_complete_event_param *params)
567 {
568 	WMI_TWT_PAUSE_DIALOG_COMPLETE_EVENTID_param_tlvs *param_buf;
569 	wmi_twt_pause_dialog_complete_event_fixed_param *ev;
570 
571 	param_buf = (WMI_TWT_PAUSE_DIALOG_COMPLETE_EVENTID_param_tlvs *)evt_buf;
572 	if (!param_buf) {
573 		wmi_err("evt_buf is NULL");
574 		return QDF_STATUS_E_INVAL;
575 	}
576 
577 	ev = param_buf->fixed_param;
578 
579 	params->vdev_id = ev->vdev_id;
580 	WMI_MAC_ADDR_TO_CHAR_ARRAY(&ev->peer_macaddr, params->peer_macaddr);
581 	params->status = ev->status;
582 	params->dialog_id = ev->dialog_id;
583 
584 	return QDF_STATUS_SUCCESS;
585 }
586 
587 static QDF_STATUS extract_twt_resume_dialog_comp_event_tlv(
588 		wmi_unified_t wmi_handle,
589 		uint8_t *evt_buf,
590 		struct wmi_twt_resume_dialog_complete_event_param *params)
591 {
592 	WMI_TWT_RESUME_DIALOG_COMPLETE_EVENTID_param_tlvs *param_buf;
593 	wmi_twt_resume_dialog_complete_event_fixed_param *ev;
594 
595 	param_buf =
596 		(WMI_TWT_RESUME_DIALOG_COMPLETE_EVENTID_param_tlvs *)evt_buf;
597 	if (!param_buf) {
598 		wmi_err("evt_buf is NULL");
599 		return QDF_STATUS_E_INVAL;
600 	}
601 
602 	ev = param_buf->fixed_param;
603 
604 	params->vdev_id = ev->vdev_id;
605 	WMI_MAC_ADDR_TO_CHAR_ARRAY(&ev->peer_macaddr, params->peer_macaddr);
606 	params->status = ev->status;
607 	params->dialog_id = ev->dialog_id;
608 
609 	return QDF_STATUS_SUCCESS;
610 }
611 
612 #ifdef WLAN_SUPPORT_BCAST_TWT
613 static QDF_STATUS
614 extract_twt_btwt_invite_sta_comp_event_tlv(
615 					   wmi_unified_t wmi_handle,
616 					   uint8_t *evt_buf,
617 					   struct
618 					   wmi_twt_btwt_invite_sta_complete_event_param
619 					   *params)
620 {
621 	WMI_TWT_BTWT_INVITE_STA_COMPLETE_EVENTID_param_tlvs *param_buf;
622 	wmi_twt_btwt_invite_sta_complete_event_fixed_param *ev;
623 
624 	param_buf =
625 		(WMI_TWT_BTWT_INVITE_STA_COMPLETE_EVENTID_param_tlvs *)evt_buf;
626 	if (!param_buf) {
627 		wmi_err("evt_buf is NULL");
628 		return QDF_STATUS_E_INVAL;
629 	}
630 
631 	ev = param_buf->fixed_param;
632 
633 	params->vdev_id = ev->vdev_id;
634 	WMI_MAC_ADDR_TO_CHAR_ARRAY(&ev->peer_macaddr, params->peer_macaddr);
635 	params->status = ev->status;
636 	params->dialog_id = ev->dialog_id;
637 
638 	return QDF_STATUS_SUCCESS;
639 }
640 
641 static QDF_STATUS
642 extract_twt_btwt_remove_sta_comp_event_tlv(
643 					   wmi_unified_t wmi_handle,
644 					   uint8_t *evt_buf,
645 					   struct
646 					   wmi_twt_btwt_remove_sta_complete_event_param
647 					   *params)
648 {
649 	WMI_TWT_BTWT_REMOVE_STA_COMPLETE_EVENTID_param_tlvs *param_buf;
650 	wmi_twt_btwt_remove_sta_complete_event_fixed_param *ev;
651 
652 	param_buf =
653 		(WMI_TWT_BTWT_REMOVE_STA_COMPLETE_EVENTID_param_tlvs *)evt_buf;
654 	if (!param_buf) {
655 		wmi_err("evt_buf is NULL");
656 		return QDF_STATUS_E_INVAL;
657 	}
658 
659 	ev = param_buf->fixed_param;
660 
661 	params->vdev_id = ev->vdev_id;
662 	WMI_MAC_ADDR_TO_CHAR_ARRAY(&ev->peer_macaddr, params->peer_macaddr);
663 	params->status = ev->status;
664 	params->dialog_id = ev->dialog_id;
665 
666 	return QDF_STATUS_SUCCESS;
667 }
668 #endif
669 
670 #ifdef WLAN_SUPPORT_BCAST_TWT
671 static void
672 wmi_twt_attach_bcast_twt_tlv(struct wmi_ops *ops)
673 {
674 	ops->send_twt_btwt_invite_sta_cmd = send_twt_btwt_invite_sta_cmd_tlv;
675 	ops->send_twt_btwt_remove_sta_cmd = send_twt_btwt_remove_sta_cmd_tlv;
676 	ops->extract_twt_btwt_invite_sta_comp_event =
677 				extract_twt_btwt_invite_sta_comp_event_tlv;
678 	ops->extract_twt_btwt_remove_sta_comp_event =
679 				extract_twt_btwt_remove_sta_comp_event_tlv;
680 
681 	return;
682 }
683 #else
684 static void
685 wmi_twt_attach_bcast_twt_tlv(struct wmi_ops *ops)
686 {
687 	return;
688 }
689 #endif
690 
691 static QDF_STATUS
692 extract_twt_session_stats_event_tlv(wmi_unified_t wmi_handle,
693 				    uint8_t *evt_buf,
694 				    struct wmi_twt_session_stats_event_param
695 				    *params)
696 {
697 	WMI_TWT_SESSION_STATS_EVENTID_param_tlvs *param_buf;
698 	wmi_pdev_twt_session_stats_event_fixed_param *ev;
699 
700 	param_buf =
701 		(WMI_TWT_SESSION_STATS_EVENTID_param_tlvs *)evt_buf;
702 	if (!param_buf) {
703 		wmi_err("evt_buf is NULL");
704 		return QDF_STATUS_E_INVAL;
705 	}
706 
707 	ev = param_buf->fixed_param;
708 	params->pdev_id = wmi_handle->ops->convert_pdev_id_target_to_host(
709 							wmi_handle,
710 							ev->pdev_id);
711 	params->num_sessions = param_buf->num_twt_sessions;
712 
713 	wmi_debug("pdev_id=%d, num of TWT sessions=%d",
714 		 params->pdev_id, params->num_sessions);
715 
716 	return QDF_STATUS_SUCCESS;
717 }
718 
719 static QDF_STATUS
720 extract_twt_session_stats_event_data(wmi_unified_t wmi_handle,
721 				     uint8_t *evt_buf,
722 				     struct wmi_twt_session_stats_event_param
723 				     *params,
724 				     struct wmi_host_twt_session_stats_info
725 				     *session,
726 				     uint32_t idx)
727 {
728 	WMI_TWT_SESSION_STATS_EVENTID_param_tlvs *param_buf;
729 	wmi_twt_session_stats_info *twt_session;
730 	uint32_t flags;
731 	wmi_mac_addr *m1;
732 	uint8_t *m2;
733 
734 	param_buf =
735 		(WMI_TWT_SESSION_STATS_EVENTID_param_tlvs *)evt_buf;
736 	if (!param_buf) {
737 		wmi_err("evt_buf is NULL");
738 		return QDF_STATUS_E_INVAL;
739 	}
740 
741 	if (idx >= param_buf->num_twt_sessions) {
742 		wmi_err("wrong idx, idx=%d, num_sessions=%d",
743 			 idx, param_buf->num_twt_sessions);
744 		return QDF_STATUS_E_INVAL;
745 	}
746 
747 	twt_session = &param_buf->twt_sessions[idx];
748 
749 	session->vdev_id = twt_session->vdev_id;
750 	m1 = &twt_session->peer_mac;
751 	m2 = session->peer_mac;
752 	WMI_MAC_ADDR_TO_CHAR_ARRAY(m1, m2);
753 	session->event_type = twt_session->event_type;
754 	flags = twt_session->flow_id_flags;
755 	session->flow_id = WMI_TWT_SESSION_FLAG_FLOW_ID_GET(flags);
756 	session->bcast = WMI_TWT_SESSION_FLAG_BCAST_TWT_GET(flags);
757 	session->trig = WMI_TWT_SESSION_FLAG_TRIGGER_TWT_GET(flags);
758 	session->announ = WMI_TWT_SESSION_FLAG_ANNOUN_TWT_GET(flags);
759 	session->protection = WMI_TWT_SESSION_FLAG_TWT_PROTECTION_GET(flags);
760 	session->info_frame_disabled =
761 			WMI_TWT_SESSION_FLAG_TWT_INFO_FRAME_DISABLED_GET(flags);
762 	session->dialog_id = twt_session->dialog_id;
763 	session->wake_dura_us = twt_session->wake_dura_us;
764 	session->wake_intvl_us = twt_session->wake_intvl_us;
765 	session->sp_offset_us = twt_session->sp_offset_us;
766 	session->sp_tsf_us_lo = twt_session->sp_tsf_us_lo;
767 	session->sp_tsf_us_hi = twt_session->sp_tsf_us_hi;
768 	wmi_debug("type=%d id=%d bcast=%d trig=%d announ=%d diagid=%d wake_dur=%ul wake_int=%ul offset=%ul",
769 		 session->event_type, session->flow_id,
770 		 session->bcast, session->trig,
771 		 session->announ, session->dialog_id, session->wake_dura_us,
772 		 session->wake_intvl_us, session->sp_offset_us);
773 
774 	return QDF_STATUS_SUCCESS;
775 }
776 
777 void wmi_twt_attach_tlv(wmi_unified_t wmi_handle)
778 {
779 	struct wmi_ops *ops = wmi_handle->ops;
780 
781 	ops->send_twt_enable_cmd = send_twt_enable_cmd_tlv;
782 	ops->send_twt_disable_cmd = send_twt_disable_cmd_tlv;
783 	ops->send_twt_add_dialog_cmd = send_twt_add_dialog_cmd_tlv;
784 	ops->send_twt_del_dialog_cmd = send_twt_del_dialog_cmd_tlv;
785 	ops->send_twt_pause_dialog_cmd = send_twt_pause_dialog_cmd_tlv;
786 	ops->send_twt_resume_dialog_cmd = send_twt_resume_dialog_cmd_tlv;
787 	ops->extract_twt_enable_comp_event = extract_twt_enable_comp_event_tlv;
788 	ops->extract_twt_disable_comp_event =
789 				extract_twt_disable_comp_event_tlv;
790 	ops->extract_twt_add_dialog_comp_event =
791 				extract_twt_add_dialog_comp_event_tlv;
792 	ops->extract_twt_add_dialog_comp_additional_params =
793 			extract_twt_add_dialog_comp_additional_parameters;
794 	ops->extract_twt_del_dialog_comp_event =
795 				extract_twt_del_dialog_comp_event_tlv;
796 	ops->extract_twt_pause_dialog_comp_event =
797 				extract_twt_pause_dialog_comp_event_tlv;
798 	ops->extract_twt_resume_dialog_comp_event =
799 				extract_twt_resume_dialog_comp_event_tlv;
800 	ops->extract_twt_session_stats_event =
801 				extract_twt_session_stats_event_tlv;
802 	ops->extract_twt_session_stats_data =
803 				extract_twt_session_stats_event_data;
804 
805 	wmi_twt_attach_bcast_twt_tlv(ops);
806 }
807