1*5113495bSYour Name /*
2*5113495bSYour Name * Copyright (c) 2013-2020 The Linux Foundation. All rights reserved.
3*5113495bSYour Name * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4*5113495bSYour Name *
5*5113495bSYour Name * Permission to use, copy, modify, and/or distribute this software for
6*5113495bSYour Name * any purpose with or without fee is hereby granted, provided that the
7*5113495bSYour Name * above copyright notice and this permission notice appear in all
8*5113495bSYour Name * copies.
9*5113495bSYour Name *
10*5113495bSYour Name * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11*5113495bSYour Name * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12*5113495bSYour Name * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13*5113495bSYour Name * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14*5113495bSYour Name * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15*5113495bSYour Name * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16*5113495bSYour Name * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17*5113495bSYour Name * PERFORMANCE OF THIS SOFTWARE.
18*5113495bSYour Name */
19*5113495bSYour Name
20*5113495bSYour Name #include <osdep.h>
21*5113495bSYour Name #include <wmi.h>
22*5113495bSYour Name #include <wmi_unified_priv.h>
23*5113495bSYour Name #include <wlan_ocb_public_structs.h>
24*5113495bSYour Name #include <wmi_unified_ocb_api.h>
25*5113495bSYour Name
26*5113495bSYour Name /**
27*5113495bSYour Name * send_ocb_set_utc_time_cmd_tlv() - send the UTC time to the firmware
28*5113495bSYour Name * @wmi_handle: pointer to the wmi handle
29*5113495bSYour Name * @utc: pointer to the UTC time struct
30*5113495bSYour Name *
31*5113495bSYour Name * Return: 0 on success
32*5113495bSYour Name */
send_ocb_set_utc_time_cmd_tlv(wmi_unified_t wmi_handle,struct ocb_utc_param * utc)33*5113495bSYour Name static QDF_STATUS send_ocb_set_utc_time_cmd_tlv(wmi_unified_t wmi_handle,
34*5113495bSYour Name struct ocb_utc_param *utc)
35*5113495bSYour Name {
36*5113495bSYour Name QDF_STATUS ret;
37*5113495bSYour Name wmi_ocb_set_utc_time_cmd_fixed_param *cmd;
38*5113495bSYour Name uint8_t *buf_ptr;
39*5113495bSYour Name uint32_t len, i;
40*5113495bSYour Name wmi_buf_t buf;
41*5113495bSYour Name
42*5113495bSYour Name len = sizeof(*cmd);
43*5113495bSYour Name buf = wmi_buf_alloc(wmi_handle, len);
44*5113495bSYour Name if (!buf) {
45*5113495bSYour Name return QDF_STATUS_E_NOMEM;
46*5113495bSYour Name }
47*5113495bSYour Name
48*5113495bSYour Name buf_ptr = (uint8_t *)wmi_buf_data(buf);
49*5113495bSYour Name cmd = (wmi_ocb_set_utc_time_cmd_fixed_param *)buf_ptr;
50*5113495bSYour Name WMITLV_SET_HDR(&cmd->tlv_header,
51*5113495bSYour Name WMITLV_TAG_STRUC_wmi_ocb_set_utc_time_cmd_fixed_param,
52*5113495bSYour Name WMITLV_GET_STRUCT_TLVLEN(wmi_ocb_set_utc_time_cmd_fixed_param));
53*5113495bSYour Name cmd->vdev_id = utc->vdev_id;
54*5113495bSYour Name
55*5113495bSYour Name for (i = 0; i < SIZE_UTC_TIME; i++)
56*5113495bSYour Name WMI_UTC_TIME_SET(cmd, i, utc->utc_time[i]);
57*5113495bSYour Name
58*5113495bSYour Name for (i = 0; i < SIZE_UTC_TIME_ERROR; i++)
59*5113495bSYour Name WMI_TIME_ERROR_SET(cmd, i, utc->time_error[i]);
60*5113495bSYour Name
61*5113495bSYour Name wmi_mtrace(WMI_OCB_SET_UTC_TIME_CMDID, cmd->vdev_id, 0);
62*5113495bSYour Name ret = wmi_unified_cmd_send(wmi_handle, buf, len,
63*5113495bSYour Name WMI_OCB_SET_UTC_TIME_CMDID);
64*5113495bSYour Name if (QDF_IS_STATUS_ERROR(ret)) {
65*5113495bSYour Name wmi_err("Failed to set OCB UTC time");
66*5113495bSYour Name wmi_buf_free(buf);
67*5113495bSYour Name }
68*5113495bSYour Name
69*5113495bSYour Name return ret;
70*5113495bSYour Name }
71*5113495bSYour Name
72*5113495bSYour Name /**
73*5113495bSYour Name * send_ocb_start_timing_advert_cmd_tlv() - start sending the timing advertisement
74*5113495bSYour Name * frames on a channel
75*5113495bSYour Name * @wmi_handle: pointer to the wmi handle
76*5113495bSYour Name * @timing_advert: pointer to the timing advertisement struct
77*5113495bSYour Name *
78*5113495bSYour Name * Return: 0 on success
79*5113495bSYour Name */
send_ocb_start_timing_advert_cmd_tlv(wmi_unified_t wmi_handle,struct ocb_timing_advert_param * timing_advert)80*5113495bSYour Name static QDF_STATUS send_ocb_start_timing_advert_cmd_tlv(wmi_unified_t wmi_handle,
81*5113495bSYour Name struct ocb_timing_advert_param *timing_advert)
82*5113495bSYour Name {
83*5113495bSYour Name QDF_STATUS ret;
84*5113495bSYour Name wmi_ocb_start_timing_advert_cmd_fixed_param *cmd;
85*5113495bSYour Name uint8_t *buf_ptr;
86*5113495bSYour Name uint32_t len, len_template;
87*5113495bSYour Name wmi_buf_t buf;
88*5113495bSYour Name
89*5113495bSYour Name len = sizeof(*cmd) +
90*5113495bSYour Name WMI_TLV_HDR_SIZE;
91*5113495bSYour Name
92*5113495bSYour Name len_template = timing_advert->template_length;
93*5113495bSYour Name /* Add padding to the template if needed */
94*5113495bSYour Name if (len_template % 4 != 0)
95*5113495bSYour Name len_template += 4 - (len_template % 4);
96*5113495bSYour Name len += len_template;
97*5113495bSYour Name
98*5113495bSYour Name buf = wmi_buf_alloc(wmi_handle, len);
99*5113495bSYour Name if (!buf) {
100*5113495bSYour Name return QDF_STATUS_E_NOMEM;
101*5113495bSYour Name }
102*5113495bSYour Name
103*5113495bSYour Name buf_ptr = (uint8_t *)wmi_buf_data(buf);
104*5113495bSYour Name cmd = (wmi_ocb_start_timing_advert_cmd_fixed_param *)buf_ptr;
105*5113495bSYour Name WMITLV_SET_HDR(&cmd->tlv_header,
106*5113495bSYour Name WMITLV_TAG_STRUC_wmi_ocb_start_timing_advert_cmd_fixed_param,
107*5113495bSYour Name WMITLV_GET_STRUCT_TLVLEN(
108*5113495bSYour Name wmi_ocb_start_timing_advert_cmd_fixed_param));
109*5113495bSYour Name cmd->vdev_id = timing_advert->vdev_id;
110*5113495bSYour Name cmd->repeat_rate = timing_advert->repeat_rate;
111*5113495bSYour Name cmd->channel_freq = timing_advert->chan_freq;
112*5113495bSYour Name cmd->timestamp_offset = timing_advert->timestamp_offset;
113*5113495bSYour Name cmd->time_value_offset = timing_advert->time_value_offset;
114*5113495bSYour Name cmd->timing_advert_template_length = timing_advert->template_length;
115*5113495bSYour Name buf_ptr += sizeof(*cmd);
116*5113495bSYour Name
117*5113495bSYour Name /* Add the timing advert template */
118*5113495bSYour Name WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE,
119*5113495bSYour Name len_template);
120*5113495bSYour Name qdf_mem_copy(buf_ptr + WMI_TLV_HDR_SIZE,
121*5113495bSYour Name (uint8_t *)timing_advert->template_value,
122*5113495bSYour Name timing_advert->template_length);
123*5113495bSYour Name
124*5113495bSYour Name wmi_mtrace(WMI_OCB_START_TIMING_ADVERT_CMDID, cmd->vdev_id, 0);
125*5113495bSYour Name ret = wmi_unified_cmd_send(wmi_handle, buf, len,
126*5113495bSYour Name WMI_OCB_START_TIMING_ADVERT_CMDID);
127*5113495bSYour Name if (QDF_IS_STATUS_ERROR(ret)) {
128*5113495bSYour Name wmi_err("Failed to start OCB timing advert");
129*5113495bSYour Name wmi_buf_free(buf);
130*5113495bSYour Name }
131*5113495bSYour Name
132*5113495bSYour Name return ret;
133*5113495bSYour Name }
134*5113495bSYour Name
135*5113495bSYour Name /**
136*5113495bSYour Name * send_ocb_stop_timing_advert_cmd_tlv() - stop sending the timing advertisement frames
137*5113495bSYour Name * on a channel
138*5113495bSYour Name * @wmi_handle: pointer to the wmi handle
139*5113495bSYour Name * @timing_advert: pointer to the timing advertisement struct
140*5113495bSYour Name *
141*5113495bSYour Name * Return: 0 on success
142*5113495bSYour Name */
send_ocb_stop_timing_advert_cmd_tlv(wmi_unified_t wmi_handle,struct ocb_timing_advert_param * timing_advert)143*5113495bSYour Name static QDF_STATUS send_ocb_stop_timing_advert_cmd_tlv(wmi_unified_t wmi_handle,
144*5113495bSYour Name struct ocb_timing_advert_param *timing_advert)
145*5113495bSYour Name {
146*5113495bSYour Name QDF_STATUS ret;
147*5113495bSYour Name wmi_ocb_stop_timing_advert_cmd_fixed_param *cmd;
148*5113495bSYour Name uint8_t *buf_ptr;
149*5113495bSYour Name uint32_t len;
150*5113495bSYour Name wmi_buf_t buf;
151*5113495bSYour Name
152*5113495bSYour Name len = sizeof(*cmd);
153*5113495bSYour Name buf = wmi_buf_alloc(wmi_handle, len);
154*5113495bSYour Name if (!buf) {
155*5113495bSYour Name return QDF_STATUS_E_NOMEM;
156*5113495bSYour Name }
157*5113495bSYour Name
158*5113495bSYour Name buf_ptr = (uint8_t *)wmi_buf_data(buf);
159*5113495bSYour Name cmd = (wmi_ocb_stop_timing_advert_cmd_fixed_param *)buf_ptr;
160*5113495bSYour Name WMITLV_SET_HDR(&cmd->tlv_header,
161*5113495bSYour Name WMITLV_TAG_STRUC_wmi_ocb_stop_timing_advert_cmd_fixed_param,
162*5113495bSYour Name WMITLV_GET_STRUCT_TLVLEN(
163*5113495bSYour Name wmi_ocb_stop_timing_advert_cmd_fixed_param));
164*5113495bSYour Name cmd->vdev_id = timing_advert->vdev_id;
165*5113495bSYour Name cmd->channel_freq = timing_advert->chan_freq;
166*5113495bSYour Name
167*5113495bSYour Name wmi_mtrace(WMI_OCB_STOP_TIMING_ADVERT_CMDID, cmd->vdev_id, 0);
168*5113495bSYour Name ret = wmi_unified_cmd_send(wmi_handle, buf, len,
169*5113495bSYour Name WMI_OCB_STOP_TIMING_ADVERT_CMDID);
170*5113495bSYour Name if (QDF_IS_STATUS_ERROR(ret)) {
171*5113495bSYour Name wmi_err("Failed to stop OCB timing advert");
172*5113495bSYour Name wmi_buf_free(buf);
173*5113495bSYour Name }
174*5113495bSYour Name
175*5113495bSYour Name return ret;
176*5113495bSYour Name }
177*5113495bSYour Name
178*5113495bSYour Name /**
179*5113495bSYour Name * send_ocb_get_tsf_timer_cmd_tlv() - get ocb tsf timer val
180*5113495bSYour Name * @wmi_handle: pointer to the wmi handle
181*5113495bSYour Name * @vdev_id: vdev identifier
182*5113495bSYour Name *
183*5113495bSYour Name * Return: 0 on success
184*5113495bSYour Name */
send_ocb_get_tsf_timer_cmd_tlv(wmi_unified_t wmi_handle,uint8_t vdev_id)185*5113495bSYour Name static QDF_STATUS send_ocb_get_tsf_timer_cmd_tlv(wmi_unified_t wmi_handle,
186*5113495bSYour Name uint8_t vdev_id)
187*5113495bSYour Name {
188*5113495bSYour Name QDF_STATUS ret;
189*5113495bSYour Name wmi_ocb_get_tsf_timer_cmd_fixed_param *cmd;
190*5113495bSYour Name uint8_t *buf_ptr;
191*5113495bSYour Name wmi_buf_t buf;
192*5113495bSYour Name int32_t len;
193*5113495bSYour Name
194*5113495bSYour Name len = sizeof(*cmd);
195*5113495bSYour Name buf = wmi_buf_alloc(wmi_handle, len);
196*5113495bSYour Name if (!buf) {
197*5113495bSYour Name return QDF_STATUS_E_NOMEM;
198*5113495bSYour Name }
199*5113495bSYour Name buf_ptr = (uint8_t *)wmi_buf_data(buf);
200*5113495bSYour Name
201*5113495bSYour Name cmd = (wmi_ocb_get_tsf_timer_cmd_fixed_param *)buf_ptr;
202*5113495bSYour Name qdf_mem_zero(cmd, len);
203*5113495bSYour Name WMITLV_SET_HDR(&cmd->tlv_header,
204*5113495bSYour Name WMITLV_TAG_STRUC_wmi_ocb_get_tsf_timer_cmd_fixed_param,
205*5113495bSYour Name WMITLV_GET_STRUCT_TLVLEN(
206*5113495bSYour Name wmi_ocb_get_tsf_timer_cmd_fixed_param));
207*5113495bSYour Name cmd->vdev_id = vdev_id;
208*5113495bSYour Name
209*5113495bSYour Name /* Send the WMI command */
210*5113495bSYour Name wmi_mtrace(WMI_OCB_GET_TSF_TIMER_CMDID, cmd->vdev_id, 0);
211*5113495bSYour Name ret = wmi_unified_cmd_send(wmi_handle, buf, len,
212*5113495bSYour Name WMI_OCB_GET_TSF_TIMER_CMDID);
213*5113495bSYour Name /* If there is an error, set the completion event */
214*5113495bSYour Name if (QDF_IS_STATUS_ERROR(ret)) {
215*5113495bSYour Name wmi_err("Failed to send WMI message: %d", ret);
216*5113495bSYour Name wmi_buf_free(buf);
217*5113495bSYour Name }
218*5113495bSYour Name
219*5113495bSYour Name return ret;
220*5113495bSYour Name }
221*5113495bSYour Name
222*5113495bSYour Name /**
223*5113495bSYour Name * send_dcc_get_stats_cmd_tlv() - get the DCC channel stats
224*5113495bSYour Name * @wmi_handle: pointer to the wmi handle
225*5113495bSYour Name * @get_stats_param: pointer to the dcc stats
226*5113495bSYour Name *
227*5113495bSYour Name * Return: 0 on success
228*5113495bSYour Name */
send_dcc_get_stats_cmd_tlv(wmi_unified_t wmi_handle,struct ocb_dcc_get_stats_param * get_stats_param)229*5113495bSYour Name static QDF_STATUS send_dcc_get_stats_cmd_tlv(wmi_unified_t wmi_handle,
230*5113495bSYour Name struct ocb_dcc_get_stats_param *get_stats_param)
231*5113495bSYour Name {
232*5113495bSYour Name QDF_STATUS ret;
233*5113495bSYour Name wmi_dcc_get_stats_cmd_fixed_param *cmd;
234*5113495bSYour Name wmi_dcc_channel_stats_request *channel_stats_array;
235*5113495bSYour Name wmi_buf_t buf;
236*5113495bSYour Name uint8_t *buf_ptr;
237*5113495bSYour Name uint32_t len;
238*5113495bSYour Name uint32_t i;
239*5113495bSYour Name
240*5113495bSYour Name /* Validate the input */
241*5113495bSYour Name if (get_stats_param->request_array_len !=
242*5113495bSYour Name get_stats_param->channel_count * sizeof(*channel_stats_array)) {
243*5113495bSYour Name wmi_err("Invalid parameter");
244*5113495bSYour Name return QDF_STATUS_E_INVAL;
245*5113495bSYour Name }
246*5113495bSYour Name
247*5113495bSYour Name /* Allocate memory for the WMI command */
248*5113495bSYour Name len = sizeof(*cmd) + WMI_TLV_HDR_SIZE +
249*5113495bSYour Name get_stats_param->request_array_len;
250*5113495bSYour Name
251*5113495bSYour Name buf = wmi_buf_alloc(wmi_handle, len);
252*5113495bSYour Name if (!buf) {
253*5113495bSYour Name return QDF_STATUS_E_NOMEM;
254*5113495bSYour Name }
255*5113495bSYour Name
256*5113495bSYour Name buf_ptr = wmi_buf_data(buf);
257*5113495bSYour Name qdf_mem_zero(buf_ptr, len);
258*5113495bSYour Name
259*5113495bSYour Name /* Populate the WMI command */
260*5113495bSYour Name cmd = (wmi_dcc_get_stats_cmd_fixed_param *)buf_ptr;
261*5113495bSYour Name buf_ptr += sizeof(*cmd);
262*5113495bSYour Name
263*5113495bSYour Name WMITLV_SET_HDR(&cmd->tlv_header,
264*5113495bSYour Name WMITLV_TAG_STRUC_wmi_dcc_get_stats_cmd_fixed_param,
265*5113495bSYour Name WMITLV_GET_STRUCT_TLVLEN(
266*5113495bSYour Name wmi_dcc_get_stats_cmd_fixed_param));
267*5113495bSYour Name cmd->vdev_id = get_stats_param->vdev_id;
268*5113495bSYour Name cmd->num_channels = get_stats_param->channel_count;
269*5113495bSYour Name
270*5113495bSYour Name WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
271*5113495bSYour Name get_stats_param->request_array_len);
272*5113495bSYour Name buf_ptr += WMI_TLV_HDR_SIZE;
273*5113495bSYour Name
274*5113495bSYour Name channel_stats_array = (wmi_dcc_channel_stats_request *)buf_ptr;
275*5113495bSYour Name qdf_mem_copy(channel_stats_array, get_stats_param->request_array,
276*5113495bSYour Name get_stats_param->request_array_len);
277*5113495bSYour Name for (i = 0; i < cmd->num_channels; i++)
278*5113495bSYour Name WMITLV_SET_HDR(&channel_stats_array[i].tlv_header,
279*5113495bSYour Name WMITLV_TAG_STRUC_wmi_dcc_channel_stats_request,
280*5113495bSYour Name WMITLV_GET_STRUCT_TLVLEN(
281*5113495bSYour Name wmi_dcc_channel_stats_request));
282*5113495bSYour Name
283*5113495bSYour Name /* Send the WMI command */
284*5113495bSYour Name wmi_mtrace(WMI_DCC_GET_STATS_CMDID, cmd->vdev_id, 0);
285*5113495bSYour Name ret = wmi_unified_cmd_send(wmi_handle, buf, len,
286*5113495bSYour Name WMI_DCC_GET_STATS_CMDID);
287*5113495bSYour Name
288*5113495bSYour Name if (QDF_IS_STATUS_ERROR(ret)) {
289*5113495bSYour Name wmi_err("Failed to send WMI message: %d", ret);
290*5113495bSYour Name wmi_buf_free(buf);
291*5113495bSYour Name }
292*5113495bSYour Name
293*5113495bSYour Name return ret;
294*5113495bSYour Name }
295*5113495bSYour Name
296*5113495bSYour Name /**
297*5113495bSYour Name * send_dcc_clear_stats_cmd_tlv() - command to clear the DCC stats
298*5113495bSYour Name * @wmi_handle: pointer to the wmi handle
299*5113495bSYour Name * @vdev_id: vdev id
300*5113495bSYour Name * @dcc_stats_bitmap: dcc status bitmap
301*5113495bSYour Name *
302*5113495bSYour Name * Return: 0 on success
303*5113495bSYour Name */
send_dcc_clear_stats_cmd_tlv(wmi_unified_t wmi_handle,uint32_t vdev_id,uint32_t dcc_stats_bitmap)304*5113495bSYour Name static QDF_STATUS send_dcc_clear_stats_cmd_tlv(wmi_unified_t wmi_handle,
305*5113495bSYour Name uint32_t vdev_id, uint32_t dcc_stats_bitmap)
306*5113495bSYour Name {
307*5113495bSYour Name QDF_STATUS ret;
308*5113495bSYour Name wmi_dcc_clear_stats_cmd_fixed_param *cmd;
309*5113495bSYour Name wmi_buf_t buf;
310*5113495bSYour Name uint8_t *buf_ptr;
311*5113495bSYour Name uint32_t len;
312*5113495bSYour Name
313*5113495bSYour Name /* Allocate memory for the WMI command */
314*5113495bSYour Name len = sizeof(*cmd);
315*5113495bSYour Name
316*5113495bSYour Name buf = wmi_buf_alloc(wmi_handle, len);
317*5113495bSYour Name if (!buf) {
318*5113495bSYour Name return QDF_STATUS_E_NOMEM;
319*5113495bSYour Name }
320*5113495bSYour Name
321*5113495bSYour Name buf_ptr = wmi_buf_data(buf);
322*5113495bSYour Name qdf_mem_zero(buf_ptr, len);
323*5113495bSYour Name
324*5113495bSYour Name /* Populate the WMI command */
325*5113495bSYour Name cmd = (wmi_dcc_clear_stats_cmd_fixed_param *)buf_ptr;
326*5113495bSYour Name
327*5113495bSYour Name WMITLV_SET_HDR(&cmd->tlv_header,
328*5113495bSYour Name WMITLV_TAG_STRUC_wmi_dcc_clear_stats_cmd_fixed_param,
329*5113495bSYour Name WMITLV_GET_STRUCT_TLVLEN(
330*5113495bSYour Name wmi_dcc_clear_stats_cmd_fixed_param));
331*5113495bSYour Name cmd->vdev_id = vdev_id;
332*5113495bSYour Name cmd->dcc_stats_bitmap = dcc_stats_bitmap;
333*5113495bSYour Name
334*5113495bSYour Name /* Send the WMI command */
335*5113495bSYour Name wmi_mtrace(WMI_DCC_CLEAR_STATS_CMDID, cmd->vdev_id, 0);
336*5113495bSYour Name ret = wmi_unified_cmd_send(wmi_handle, buf, len,
337*5113495bSYour Name WMI_DCC_CLEAR_STATS_CMDID);
338*5113495bSYour Name if (QDF_IS_STATUS_ERROR(ret)) {
339*5113495bSYour Name wmi_err("Failed to send the WMI command");
340*5113495bSYour Name wmi_buf_free(buf);
341*5113495bSYour Name }
342*5113495bSYour Name
343*5113495bSYour Name return ret;
344*5113495bSYour Name }
345*5113495bSYour Name
346*5113495bSYour Name /**
347*5113495bSYour Name * send_dcc_update_ndl_cmd_tlv() - command to update the NDL data
348*5113495bSYour Name * @wmi_handle: pointer to the wmi handle
349*5113495bSYour Name * @update_ndl_param: pointer to the request parameters
350*5113495bSYour Name *
351*5113495bSYour Name * Return: 0 on success
352*5113495bSYour Name */
send_dcc_update_ndl_cmd_tlv(wmi_unified_t wmi_handle,struct ocb_dcc_update_ndl_param * update_ndl_param)353*5113495bSYour Name static QDF_STATUS send_dcc_update_ndl_cmd_tlv(wmi_unified_t wmi_handle,
354*5113495bSYour Name struct ocb_dcc_update_ndl_param *update_ndl_param)
355*5113495bSYour Name {
356*5113495bSYour Name QDF_STATUS qdf_status;
357*5113495bSYour Name wmi_dcc_update_ndl_cmd_fixed_param *cmd;
358*5113495bSYour Name wmi_dcc_ndl_chan *ndl_chan_array;
359*5113495bSYour Name wmi_dcc_ndl_active_state_config *ndl_active_state_array;
360*5113495bSYour Name uint32_t active_state_count;
361*5113495bSYour Name wmi_buf_t buf;
362*5113495bSYour Name uint8_t *buf_ptr;
363*5113495bSYour Name uint32_t len;
364*5113495bSYour Name uint32_t i;
365*5113495bSYour Name
366*5113495bSYour Name /* validate the input */
367*5113495bSYour Name if (update_ndl_param->dcc_ndl_chan_list_len !=
368*5113495bSYour Name update_ndl_param->channel_count * sizeof(*ndl_chan_array)) {
369*5113495bSYour Name wmi_err("Invalid parameter");
370*5113495bSYour Name return QDF_STATUS_E_INVAL;
371*5113495bSYour Name }
372*5113495bSYour Name active_state_count = 0;
373*5113495bSYour Name ndl_chan_array = update_ndl_param->dcc_ndl_chan_list;
374*5113495bSYour Name for (i = 0; i < update_ndl_param->channel_count; i++)
375*5113495bSYour Name active_state_count +=
376*5113495bSYour Name WMI_NDL_NUM_ACTIVE_STATE_GET(&ndl_chan_array[i]);
377*5113495bSYour Name if (update_ndl_param->dcc_ndl_active_state_list_len !=
378*5113495bSYour Name active_state_count * sizeof(*ndl_active_state_array)) {
379*5113495bSYour Name wmi_err("Invalid parameter");
380*5113495bSYour Name return QDF_STATUS_E_INVAL;
381*5113495bSYour Name }
382*5113495bSYour Name
383*5113495bSYour Name /* Allocate memory for the WMI command */
384*5113495bSYour Name len = sizeof(*cmd) +
385*5113495bSYour Name WMI_TLV_HDR_SIZE + update_ndl_param->dcc_ndl_chan_list_len +
386*5113495bSYour Name WMI_TLV_HDR_SIZE +
387*5113495bSYour Name update_ndl_param->dcc_ndl_active_state_list_len;
388*5113495bSYour Name
389*5113495bSYour Name buf = wmi_buf_alloc(wmi_handle, len);
390*5113495bSYour Name if (!buf) {
391*5113495bSYour Name return QDF_STATUS_E_NOMEM;
392*5113495bSYour Name }
393*5113495bSYour Name
394*5113495bSYour Name buf_ptr = wmi_buf_data(buf);
395*5113495bSYour Name qdf_mem_zero(buf_ptr, len);
396*5113495bSYour Name
397*5113495bSYour Name /* Populate the WMI command */
398*5113495bSYour Name cmd = (wmi_dcc_update_ndl_cmd_fixed_param *)buf_ptr;
399*5113495bSYour Name buf_ptr += sizeof(*cmd);
400*5113495bSYour Name
401*5113495bSYour Name WMITLV_SET_HDR(&cmd->tlv_header,
402*5113495bSYour Name WMITLV_TAG_STRUC_wmi_dcc_update_ndl_cmd_fixed_param,
403*5113495bSYour Name WMITLV_GET_STRUCT_TLVLEN(
404*5113495bSYour Name wmi_dcc_update_ndl_cmd_fixed_param));
405*5113495bSYour Name cmd->vdev_id = update_ndl_param->vdev_id;
406*5113495bSYour Name cmd->num_channel = update_ndl_param->channel_count;
407*5113495bSYour Name
408*5113495bSYour Name WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
409*5113495bSYour Name update_ndl_param->dcc_ndl_chan_list_len);
410*5113495bSYour Name buf_ptr += WMI_TLV_HDR_SIZE;
411*5113495bSYour Name
412*5113495bSYour Name ndl_chan_array = (wmi_dcc_ndl_chan *)buf_ptr;
413*5113495bSYour Name qdf_mem_copy(ndl_chan_array, update_ndl_param->dcc_ndl_chan_list,
414*5113495bSYour Name update_ndl_param->dcc_ndl_chan_list_len);
415*5113495bSYour Name for (i = 0; i < cmd->num_channel; i++)
416*5113495bSYour Name WMITLV_SET_HDR(&ndl_chan_array[i].tlv_header,
417*5113495bSYour Name WMITLV_TAG_STRUC_wmi_dcc_ndl_chan,
418*5113495bSYour Name WMITLV_GET_STRUCT_TLVLEN(
419*5113495bSYour Name wmi_dcc_ndl_chan));
420*5113495bSYour Name buf_ptr += update_ndl_param->dcc_ndl_chan_list_len;
421*5113495bSYour Name
422*5113495bSYour Name WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
423*5113495bSYour Name update_ndl_param->dcc_ndl_active_state_list_len);
424*5113495bSYour Name buf_ptr += WMI_TLV_HDR_SIZE;
425*5113495bSYour Name
426*5113495bSYour Name ndl_active_state_array = (wmi_dcc_ndl_active_state_config *)buf_ptr;
427*5113495bSYour Name qdf_mem_copy(ndl_active_state_array,
428*5113495bSYour Name update_ndl_param->dcc_ndl_active_state_list,
429*5113495bSYour Name update_ndl_param->dcc_ndl_active_state_list_len);
430*5113495bSYour Name for (i = 0; i < active_state_count; i++) {
431*5113495bSYour Name WMITLV_SET_HDR(&ndl_active_state_array[i].tlv_header,
432*5113495bSYour Name WMITLV_TAG_STRUC_wmi_dcc_ndl_active_state_config,
433*5113495bSYour Name WMITLV_GET_STRUCT_TLVLEN(
434*5113495bSYour Name wmi_dcc_ndl_active_state_config));
435*5113495bSYour Name }
436*5113495bSYour Name buf_ptr += update_ndl_param->dcc_ndl_active_state_list_len;
437*5113495bSYour Name
438*5113495bSYour Name /* Send the WMI command */
439*5113495bSYour Name wmi_mtrace(WMI_DCC_UPDATE_NDL_CMDID, cmd->vdev_id, 0);
440*5113495bSYour Name qdf_status = wmi_unified_cmd_send(wmi_handle, buf, len,
441*5113495bSYour Name WMI_DCC_UPDATE_NDL_CMDID);
442*5113495bSYour Name /* If there is an error, set the completion event */
443*5113495bSYour Name if (QDF_IS_STATUS_ERROR(qdf_status)) {
444*5113495bSYour Name wmi_err("Failed to send WMI message: %d", qdf_status);
445*5113495bSYour Name wmi_buf_free(buf);
446*5113495bSYour Name }
447*5113495bSYour Name
448*5113495bSYour Name return qdf_status;
449*5113495bSYour Name }
450*5113495bSYour Name
451*5113495bSYour Name /**
452*5113495bSYour Name * send_ocb_set_config_cmd_tlv() - send the OCB config to the FW
453*5113495bSYour Name * @wmi_handle: pointer to the wmi handle
454*5113495bSYour Name * @config: the OCB configuration
455*5113495bSYour Name *
456*5113495bSYour Name * Return: 0 on success
457*5113495bSYour Name */
send_ocb_set_config_cmd_tlv(wmi_unified_t wmi_handle,struct ocb_config * config)458*5113495bSYour Name static QDF_STATUS send_ocb_set_config_cmd_tlv(wmi_unified_t wmi_handle,
459*5113495bSYour Name struct ocb_config *config)
460*5113495bSYour Name {
461*5113495bSYour Name QDF_STATUS ret;
462*5113495bSYour Name wmi_ocb_set_config_cmd_fixed_param *cmd;
463*5113495bSYour Name wmi_channel *chan;
464*5113495bSYour Name wmi_ocb_channel *ocb_chan;
465*5113495bSYour Name wmi_qos_parameter *qos_param;
466*5113495bSYour Name wmi_dcc_ndl_chan *ndl_chan;
467*5113495bSYour Name wmi_dcc_ndl_active_state_config *ndl_active_config;
468*5113495bSYour Name wmi_ocb_schedule_element *sched_elem;
469*5113495bSYour Name uint8_t *buf_ptr;
470*5113495bSYour Name wmi_buf_t buf;
471*5113495bSYour Name int32_t len;
472*5113495bSYour Name int32_t i, j, active_state_count;
473*5113495bSYour Name
474*5113495bSYour Name /*
475*5113495bSYour Name * Validate the dcc_ndl_chan_list_len and count the number of active
476*5113495bSYour Name * states. Validate dcc_ndl_active_state_list_len.
477*5113495bSYour Name */
478*5113495bSYour Name active_state_count = 0;
479*5113495bSYour Name if (config->dcc_ndl_chan_list_len) {
480*5113495bSYour Name if (!config->dcc_ndl_chan_list ||
481*5113495bSYour Name config->dcc_ndl_chan_list_len !=
482*5113495bSYour Name config->channel_count * sizeof(wmi_dcc_ndl_chan)) {
483*5113495bSYour Name wmi_err("NDL channel is invalid. List len: %d",
484*5113495bSYour Name config->dcc_ndl_chan_list_len);
485*5113495bSYour Name return QDF_STATUS_E_INVAL;
486*5113495bSYour Name }
487*5113495bSYour Name
488*5113495bSYour Name for (i = 0, ndl_chan = config->dcc_ndl_chan_list;
489*5113495bSYour Name i < config->channel_count; ++i, ++ndl_chan)
490*5113495bSYour Name active_state_count +=
491*5113495bSYour Name WMI_NDL_NUM_ACTIVE_STATE_GET(ndl_chan);
492*5113495bSYour Name
493*5113495bSYour Name if (active_state_count) {
494*5113495bSYour Name if (!config->dcc_ndl_active_state_list ||
495*5113495bSYour Name config->dcc_ndl_active_state_list_len !=
496*5113495bSYour Name active_state_count *
497*5113495bSYour Name sizeof(wmi_dcc_ndl_active_state_config)) {
498*5113495bSYour Name wmi_err("NDL active state is invalid");
499*5113495bSYour Name return QDF_STATUS_E_INVAL;
500*5113495bSYour Name }
501*5113495bSYour Name }
502*5113495bSYour Name }
503*5113495bSYour Name
504*5113495bSYour Name len = sizeof(*cmd) +
505*5113495bSYour Name WMI_TLV_HDR_SIZE + config->channel_count *
506*5113495bSYour Name sizeof(wmi_channel) +
507*5113495bSYour Name WMI_TLV_HDR_SIZE + config->channel_count *
508*5113495bSYour Name sizeof(wmi_ocb_channel) +
509*5113495bSYour Name WMI_TLV_HDR_SIZE + config->channel_count *
510*5113495bSYour Name sizeof(wmi_qos_parameter) * WMI_MAX_NUM_AC +
511*5113495bSYour Name WMI_TLV_HDR_SIZE + config->dcc_ndl_chan_list_len +
512*5113495bSYour Name WMI_TLV_HDR_SIZE + active_state_count *
513*5113495bSYour Name sizeof(wmi_dcc_ndl_active_state_config) +
514*5113495bSYour Name WMI_TLV_HDR_SIZE + config->schedule_size *
515*5113495bSYour Name sizeof(wmi_ocb_schedule_element);
516*5113495bSYour Name buf = wmi_buf_alloc(wmi_handle, len);
517*5113495bSYour Name if (!buf) {
518*5113495bSYour Name return QDF_STATUS_E_NOMEM;
519*5113495bSYour Name }
520*5113495bSYour Name
521*5113495bSYour Name buf_ptr = (uint8_t *)wmi_buf_data(buf);
522*5113495bSYour Name cmd = (wmi_ocb_set_config_cmd_fixed_param *)buf_ptr;
523*5113495bSYour Name WMITLV_SET_HDR(&cmd->tlv_header,
524*5113495bSYour Name WMITLV_TAG_STRUC_wmi_ocb_set_config_cmd_fixed_param,
525*5113495bSYour Name WMITLV_GET_STRUCT_TLVLEN(wmi_ocb_set_config_cmd_fixed_param));
526*5113495bSYour Name cmd->vdev_id = config->vdev_id;
527*5113495bSYour Name cmd->channel_count = config->channel_count;
528*5113495bSYour Name cmd->schedule_size = config->schedule_size;
529*5113495bSYour Name cmd->flags = config->flags;
530*5113495bSYour Name buf_ptr += sizeof(*cmd);
531*5113495bSYour Name
532*5113495bSYour Name /* Add the wmi_channel info */
533*5113495bSYour Name WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
534*5113495bSYour Name config->channel_count * sizeof(wmi_channel));
535*5113495bSYour Name buf_ptr += WMI_TLV_HDR_SIZE;
536*5113495bSYour Name for (i = 0; i < config->channel_count; i++) {
537*5113495bSYour Name chan = (wmi_channel *)buf_ptr;
538*5113495bSYour Name WMITLV_SET_HDR(&chan->tlv_header,
539*5113495bSYour Name WMITLV_TAG_STRUC_wmi_channel,
540*5113495bSYour Name WMITLV_GET_STRUCT_TLVLEN(wmi_channel));
541*5113495bSYour Name chan->mhz = config->channels[i].chan_freq;
542*5113495bSYour Name chan->band_center_freq1 = config->channels[i].chan_freq;
543*5113495bSYour Name chan->band_center_freq2 = 0;
544*5113495bSYour Name chan->info = 0;
545*5113495bSYour Name
546*5113495bSYour Name WMI_SET_CHANNEL_MODE(chan, config->channels[i].ch_mode);
547*5113495bSYour Name WMI_SET_CHANNEL_MAX_POWER(chan, config->channels[i].max_pwr);
548*5113495bSYour Name WMI_SET_CHANNEL_MIN_POWER(chan, config->channels[i].min_pwr);
549*5113495bSYour Name WMI_SET_CHANNEL_MAX_TX_POWER(chan, config->channels[i].max_pwr);
550*5113495bSYour Name WMI_SET_CHANNEL_REG_POWER(chan, config->channels[i].reg_pwr);
551*5113495bSYour Name WMI_SET_CHANNEL_ANTENNA_MAX(chan,
552*5113495bSYour Name config->channels[i].antenna_max);
553*5113495bSYour Name
554*5113495bSYour Name if (config->channels[i].bandwidth < 10)
555*5113495bSYour Name WMI_SET_CHANNEL_FLAG(chan, WMI_CHAN_FLAG_QUARTER_RATE);
556*5113495bSYour Name else if (config->channels[i].bandwidth < 20)
557*5113495bSYour Name WMI_SET_CHANNEL_FLAG(chan, WMI_CHAN_FLAG_HALF_RATE);
558*5113495bSYour Name buf_ptr += sizeof(*chan);
559*5113495bSYour Name }
560*5113495bSYour Name
561*5113495bSYour Name /* Add the wmi_ocb_channel info */
562*5113495bSYour Name WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
563*5113495bSYour Name config->channel_count * sizeof(wmi_ocb_channel));
564*5113495bSYour Name buf_ptr += WMI_TLV_HDR_SIZE;
565*5113495bSYour Name for (i = 0; i < config->channel_count; i++) {
566*5113495bSYour Name ocb_chan = (wmi_ocb_channel *)buf_ptr;
567*5113495bSYour Name WMITLV_SET_HDR(&ocb_chan->tlv_header,
568*5113495bSYour Name WMITLV_TAG_STRUC_wmi_ocb_channel,
569*5113495bSYour Name WMITLV_GET_STRUCT_TLVLEN(wmi_ocb_channel));
570*5113495bSYour Name ocb_chan->bandwidth = config->channels[i].bandwidth;
571*5113495bSYour Name WMI_CHAR_ARRAY_TO_MAC_ADDR(
572*5113495bSYour Name config->channels[i].mac_address.bytes,
573*5113495bSYour Name &ocb_chan->mac_address);
574*5113495bSYour Name buf_ptr += sizeof(*ocb_chan);
575*5113495bSYour Name }
576*5113495bSYour Name
577*5113495bSYour Name /* Add the wmi_qos_parameter info */
578*5113495bSYour Name WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
579*5113495bSYour Name config->channel_count * sizeof(wmi_qos_parameter)*WMI_MAX_NUM_AC);
580*5113495bSYour Name buf_ptr += WMI_TLV_HDR_SIZE;
581*5113495bSYour Name /* WMI_MAX_NUM_AC parameters for each channel */
582*5113495bSYour Name for (i = 0; i < config->channel_count; i++) {
583*5113495bSYour Name for (j = 0; j < WMI_MAX_NUM_AC; j++) {
584*5113495bSYour Name qos_param = (wmi_qos_parameter *)buf_ptr;
585*5113495bSYour Name WMITLV_SET_HDR(&qos_param->tlv_header,
586*5113495bSYour Name WMITLV_TAG_STRUC_wmi_qos_parameter,
587*5113495bSYour Name WMITLV_GET_STRUCT_TLVLEN(wmi_qos_parameter));
588*5113495bSYour Name qos_param->aifsn =
589*5113495bSYour Name config->channels[i].qos_params[j].aifsn;
590*5113495bSYour Name qos_param->cwmin =
591*5113495bSYour Name config->channels[i].qos_params[j].cwmin;
592*5113495bSYour Name qos_param->cwmax =
593*5113495bSYour Name config->channels[i].qos_params[j].cwmax;
594*5113495bSYour Name buf_ptr += sizeof(*qos_param);
595*5113495bSYour Name }
596*5113495bSYour Name }
597*5113495bSYour Name
598*5113495bSYour Name /* Add the wmi_dcc_ndl_chan (per channel) */
599*5113495bSYour Name WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
600*5113495bSYour Name config->dcc_ndl_chan_list_len);
601*5113495bSYour Name buf_ptr += WMI_TLV_HDR_SIZE;
602*5113495bSYour Name if (config->dcc_ndl_chan_list_len) {
603*5113495bSYour Name ndl_chan = (wmi_dcc_ndl_chan *)buf_ptr;
604*5113495bSYour Name qdf_mem_copy(ndl_chan, config->dcc_ndl_chan_list,
605*5113495bSYour Name config->dcc_ndl_chan_list_len);
606*5113495bSYour Name for (i = 0; i < config->channel_count; i++)
607*5113495bSYour Name WMITLV_SET_HDR(&(ndl_chan[i].tlv_header),
608*5113495bSYour Name WMITLV_TAG_STRUC_wmi_dcc_ndl_chan,
609*5113495bSYour Name WMITLV_GET_STRUCT_TLVLEN(wmi_dcc_ndl_chan));
610*5113495bSYour Name buf_ptr += config->dcc_ndl_chan_list_len;
611*5113495bSYour Name }
612*5113495bSYour Name
613*5113495bSYour Name /* Add the wmi_dcc_ndl_active_state_config */
614*5113495bSYour Name WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, active_state_count *
615*5113495bSYour Name sizeof(wmi_dcc_ndl_active_state_config));
616*5113495bSYour Name buf_ptr += WMI_TLV_HDR_SIZE;
617*5113495bSYour Name if (active_state_count) {
618*5113495bSYour Name ndl_active_config = (wmi_dcc_ndl_active_state_config *)buf_ptr;
619*5113495bSYour Name qdf_mem_copy(ndl_active_config,
620*5113495bSYour Name config->dcc_ndl_active_state_list,
621*5113495bSYour Name active_state_count * sizeof(*ndl_active_config));
622*5113495bSYour Name for (i = 0; i < active_state_count; ++i)
623*5113495bSYour Name WMITLV_SET_HDR(&(ndl_active_config[i].tlv_header),
624*5113495bSYour Name WMITLV_TAG_STRUC_wmi_dcc_ndl_active_state_config,
625*5113495bSYour Name WMITLV_GET_STRUCT_TLVLEN(
626*5113495bSYour Name wmi_dcc_ndl_active_state_config));
627*5113495bSYour Name buf_ptr += active_state_count *
628*5113495bSYour Name sizeof(*ndl_active_config);
629*5113495bSYour Name }
630*5113495bSYour Name
631*5113495bSYour Name /* Add the wmi_ocb_schedule_element info */
632*5113495bSYour Name WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
633*5113495bSYour Name config->schedule_size * sizeof(wmi_ocb_schedule_element));
634*5113495bSYour Name buf_ptr += WMI_TLV_HDR_SIZE;
635*5113495bSYour Name for (i = 0; i < config->schedule_size; i++) {
636*5113495bSYour Name sched_elem = (wmi_ocb_schedule_element *)buf_ptr;
637*5113495bSYour Name WMITLV_SET_HDR(&sched_elem->tlv_header,
638*5113495bSYour Name WMITLV_TAG_STRUC_wmi_ocb_schedule_element,
639*5113495bSYour Name WMITLV_GET_STRUCT_TLVLEN(wmi_ocb_schedule_element));
640*5113495bSYour Name sched_elem->channel_freq = config->schedule[i].chan_freq;
641*5113495bSYour Name sched_elem->total_duration = config->schedule[i].total_duration;
642*5113495bSYour Name sched_elem->guard_interval = config->schedule[i].guard_interval;
643*5113495bSYour Name buf_ptr += sizeof(*sched_elem);
644*5113495bSYour Name }
645*5113495bSYour Name
646*5113495bSYour Name wmi_mtrace(WMI_OCB_SET_CONFIG_CMDID, cmd->vdev_id, 0);
647*5113495bSYour Name ret = wmi_unified_cmd_send(wmi_handle, buf, len,
648*5113495bSYour Name WMI_OCB_SET_CONFIG_CMDID);
649*5113495bSYour Name if (QDF_IS_STATUS_ERROR(ret)) {
650*5113495bSYour Name wmi_err("Failed to set OCB config");
651*5113495bSYour Name wmi_buf_free(buf);
652*5113495bSYour Name }
653*5113495bSYour Name
654*5113495bSYour Name return ret;
655*5113495bSYour Name }
656*5113495bSYour Name
657*5113495bSYour Name /**
658*5113495bSYour Name * extract_ocb_channel_config_resp_tlv() - extract ocb channel config resp
659*5113495bSYour Name * @wmi_handle: wmi handle
660*5113495bSYour Name * @evt_buf: wmi event buffer
661*5113495bSYour Name * @status: status buffer
662*5113495bSYour Name *
663*5113495bSYour Name * Return: QDF_STATUS_SUCCESS on success
664*5113495bSYour Name */
extract_ocb_channel_config_resp_tlv(wmi_unified_t wmi_handle,void * evt_buf,uint32_t * status)665*5113495bSYour Name static QDF_STATUS extract_ocb_channel_config_resp_tlv(wmi_unified_t wmi_handle,
666*5113495bSYour Name void *evt_buf,
667*5113495bSYour Name uint32_t *status)
668*5113495bSYour Name {
669*5113495bSYour Name WMI_OCB_SET_CONFIG_RESP_EVENTID_param_tlvs *param_tlvs;
670*5113495bSYour Name wmi_ocb_set_config_resp_event_fixed_param *fix_param;
671*5113495bSYour Name
672*5113495bSYour Name param_tlvs = evt_buf;
673*5113495bSYour Name fix_param = param_tlvs->fixed_param;
674*5113495bSYour Name
675*5113495bSYour Name *status = fix_param->status;
676*5113495bSYour Name return QDF_STATUS_SUCCESS;
677*5113495bSYour Name }
678*5113495bSYour Name
679*5113495bSYour Name /**
680*5113495bSYour Name * extract_ocb_tsf_timer_tlv() - extract TSF timer from event buffer
681*5113495bSYour Name * @wmi_handle: wmi handle
682*5113495bSYour Name * @evt_buf: wmi event buffer
683*5113495bSYour Name * @resp: response buffer
684*5113495bSYour Name *
685*5113495bSYour Name * Return: QDF_STATUS_SUCCESS on success
686*5113495bSYour Name */
extract_ocb_tsf_timer_tlv(wmi_unified_t wmi_handle,void * evt_buf,struct ocb_get_tsf_timer_response * resp)687*5113495bSYour Name static QDF_STATUS extract_ocb_tsf_timer_tlv(wmi_unified_t wmi_handle,
688*5113495bSYour Name void *evt_buf, struct ocb_get_tsf_timer_response *resp)
689*5113495bSYour Name {
690*5113495bSYour Name WMI_OCB_GET_TSF_TIMER_RESP_EVENTID_param_tlvs *param_tlvs;
691*5113495bSYour Name wmi_ocb_get_tsf_timer_resp_event_fixed_param *fix_param;
692*5113495bSYour Name
693*5113495bSYour Name param_tlvs = evt_buf;
694*5113495bSYour Name fix_param = param_tlvs->fixed_param;
695*5113495bSYour Name resp->vdev_id = fix_param->vdev_id;
696*5113495bSYour Name resp->timer_high = fix_param->tsf_timer_high;
697*5113495bSYour Name resp->timer_low = fix_param->tsf_timer_low;
698*5113495bSYour Name
699*5113495bSYour Name return QDF_STATUS_SUCCESS;
700*5113495bSYour Name }
701*5113495bSYour Name
702*5113495bSYour Name /**
703*5113495bSYour Name * extract_ocb_ndl_resp_tlv() - extract TSF timer from event buffer
704*5113495bSYour Name * @wmi_handle: wmi handle
705*5113495bSYour Name * @evt_buf: wmi event buffer
706*5113495bSYour Name * @resp: response buffer
707*5113495bSYour Name *
708*5113495bSYour Name * Return: QDF_STATUS_SUCCESS on success
709*5113495bSYour Name */
extract_ocb_ndl_resp_tlv(wmi_unified_t wmi_handle,void * evt_buf,struct ocb_dcc_update_ndl_response * resp)710*5113495bSYour Name static QDF_STATUS extract_ocb_ndl_resp_tlv(wmi_unified_t wmi_handle,
711*5113495bSYour Name void *evt_buf, struct ocb_dcc_update_ndl_response *resp)
712*5113495bSYour Name {
713*5113495bSYour Name WMI_DCC_UPDATE_NDL_RESP_EVENTID_param_tlvs *param_tlvs;
714*5113495bSYour Name wmi_dcc_update_ndl_resp_event_fixed_param *fix_param;
715*5113495bSYour Name
716*5113495bSYour Name param_tlvs = evt_buf;
717*5113495bSYour Name fix_param = param_tlvs->fixed_param;
718*5113495bSYour Name resp->vdev_id = fix_param->vdev_id;
719*5113495bSYour Name resp->status = fix_param->status;
720*5113495bSYour Name return QDF_STATUS_SUCCESS;
721*5113495bSYour Name }
722*5113495bSYour Name
723*5113495bSYour Name /**
724*5113495bSYour Name * extract_ocb_dcc_stats_tlv() - extract DCC stats from event buffer
725*5113495bSYour Name * @wmi_handle: wmi handle
726*5113495bSYour Name * @evt_buf: wmi event buffer
727*5113495bSYour Name * @resp: response buffer
728*5113495bSYour Name *
729*5113495bSYour Name * Since length of stats is variable, buffer for DCC stats will be allocated
730*5113495bSYour Name * in this function. The caller must free the buffer.
731*5113495bSYour Name *
732*5113495bSYour Name * Return: QDF_STATUS_SUCCESS on success
733*5113495bSYour Name */
extract_ocb_dcc_stats_tlv(wmi_unified_t wmi_handle,void * evt_buf,struct ocb_dcc_get_stats_response ** resp)734*5113495bSYour Name static QDF_STATUS extract_ocb_dcc_stats_tlv(wmi_unified_t wmi_handle,
735*5113495bSYour Name void *evt_buf, struct ocb_dcc_get_stats_response **resp)
736*5113495bSYour Name {
737*5113495bSYour Name struct ocb_dcc_get_stats_response *response;
738*5113495bSYour Name WMI_DCC_GET_STATS_RESP_EVENTID_param_tlvs *param_tlvs;
739*5113495bSYour Name wmi_dcc_get_stats_resp_event_fixed_param *fix_param;
740*5113495bSYour Name
741*5113495bSYour Name param_tlvs = (WMI_DCC_GET_STATS_RESP_EVENTID_param_tlvs *)evt_buf;
742*5113495bSYour Name fix_param = param_tlvs->fixed_param;
743*5113495bSYour Name
744*5113495bSYour Name /* Allocate and populate the response */
745*5113495bSYour Name if (fix_param->num_channels > ((WMI_SVC_MSG_MAX_SIZE -
746*5113495bSYour Name sizeof(*fix_param)) / sizeof(wmi_dcc_ndl_stats_per_channel)) ||
747*5113495bSYour Name fix_param->num_channels > param_tlvs->num_stats_per_channel_list) {
748*5113495bSYour Name wmi_warn("Too many channels:%d actual:%d",
749*5113495bSYour Name fix_param->num_channels,
750*5113495bSYour Name param_tlvs->num_stats_per_channel_list);
751*5113495bSYour Name *resp = NULL;
752*5113495bSYour Name return QDF_STATUS_E_INVAL;
753*5113495bSYour Name }
754*5113495bSYour Name response = qdf_mem_malloc(sizeof(*response) + fix_param->num_channels *
755*5113495bSYour Name sizeof(wmi_dcc_ndl_stats_per_channel));
756*5113495bSYour Name *resp = response;
757*5113495bSYour Name if (!response)
758*5113495bSYour Name return QDF_STATUS_E_NOMEM;
759*5113495bSYour Name
760*5113495bSYour Name response->vdev_id = fix_param->vdev_id;
761*5113495bSYour Name response->num_channels = fix_param->num_channels;
762*5113495bSYour Name response->channel_stats_array_len =
763*5113495bSYour Name fix_param->num_channels *
764*5113495bSYour Name sizeof(wmi_dcc_ndl_stats_per_channel);
765*5113495bSYour Name response->channel_stats_array = ((uint8_t *)response) +
766*5113495bSYour Name sizeof(*response);
767*5113495bSYour Name qdf_mem_copy(response->channel_stats_array,
768*5113495bSYour Name param_tlvs->stats_per_channel_list,
769*5113495bSYour Name response->channel_stats_array_len);
770*5113495bSYour Name
771*5113495bSYour Name return QDF_STATUS_SUCCESS;
772*5113495bSYour Name }
773*5113495bSYour Name
wmi_ocb_attach_tlv(wmi_unified_t wmi_handle)774*5113495bSYour Name void wmi_ocb_attach_tlv(wmi_unified_t wmi_handle)
775*5113495bSYour Name {
776*5113495bSYour Name struct wmi_ops *ops = wmi_handle->ops;
777*5113495bSYour Name
778*5113495bSYour Name ops->send_ocb_set_utc_time_cmd = send_ocb_set_utc_time_cmd_tlv;
779*5113495bSYour Name ops->send_ocb_get_tsf_timer_cmd = send_ocb_get_tsf_timer_cmd_tlv;
780*5113495bSYour Name ops->send_dcc_clear_stats_cmd = send_dcc_clear_stats_cmd_tlv;
781*5113495bSYour Name ops->send_dcc_get_stats_cmd = send_dcc_get_stats_cmd_tlv;
782*5113495bSYour Name ops->send_dcc_update_ndl_cmd = send_dcc_update_ndl_cmd_tlv;
783*5113495bSYour Name ops->send_ocb_set_config_cmd = send_ocb_set_config_cmd_tlv;
784*5113495bSYour Name ops->send_ocb_stop_timing_advert_cmd =
785*5113495bSYour Name send_ocb_stop_timing_advert_cmd_tlv;
786*5113495bSYour Name ops->send_ocb_start_timing_advert_cmd =
787*5113495bSYour Name send_ocb_start_timing_advert_cmd_tlv;
788*5113495bSYour Name ops->extract_ocb_chan_config_resp =
789*5113495bSYour Name extract_ocb_channel_config_resp_tlv;
790*5113495bSYour Name ops->extract_ocb_tsf_timer = extract_ocb_tsf_timer_tlv;
791*5113495bSYour Name ops->extract_dcc_update_ndl_resp = extract_ocb_ndl_resp_tlv;
792*5113495bSYour Name ops->extract_dcc_stats = extract_ocb_dcc_stats_tlv;
793*5113495bSYour Name }
794