1 /*
2 * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
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 #include <osdep.h>
21 #include "wmi.h"
22 #include "wmi_unified_priv.h"
23 #include "wmi_unified_pmo_api.h"
24
25 #ifdef FEATURE_WLAN_D0WOW
26 /**
27 * send_d0wow_enable_cmd_tlv() - WMI d0 wow enable function
28 * @wmi_handle: handle to WMI.
29 * @mac_id: radio context
30 *
31 * Return: 0 on success and error code on failure.
32 */
send_d0wow_enable_cmd_tlv(wmi_unified_t wmi_handle,uint8_t mac_id)33 static QDF_STATUS send_d0wow_enable_cmd_tlv(wmi_unified_t wmi_handle,
34 uint8_t mac_id)
35 {
36 wmi_d0_wow_enable_disable_cmd_fixed_param *cmd;
37 wmi_buf_t buf;
38 int32_t len;
39 QDF_STATUS status;
40
41 len = sizeof(wmi_d0_wow_enable_disable_cmd_fixed_param);
42
43 buf = wmi_buf_alloc(wmi_handle, len);
44 if (!buf) {
45 return QDF_STATUS_E_NOMEM;
46 }
47 cmd = (wmi_d0_wow_enable_disable_cmd_fixed_param *) wmi_buf_data(buf);
48 WMITLV_SET_HDR(&cmd->tlv_header,
49 WMITLV_TAG_STRUC_wmi_d0_wow_enable_disable_cmd_fixed_param,
50 WMITLV_GET_STRUCT_TLVLEN
51 (wmi_d0_wow_enable_disable_cmd_fixed_param));
52
53 cmd->enable = true;
54
55 wmi_mtrace(WMI_D0_WOW_ENABLE_DISABLE_CMDID, NO_SESSION, 0);
56 status = wmi_unified_cmd_send(wmi_handle, buf, len,
57 WMI_D0_WOW_ENABLE_DISABLE_CMDID);
58 if (QDF_IS_STATUS_ERROR(status))
59 wmi_buf_free(buf);
60
61 return status;
62 }
63
64 /**
65 * send_d0wow_disable_cmd_tlv() - WMI d0 wow disable function
66 * @wmi_handle: handle to WMI.
67 * @mac_id: radio context
68 *
69 * Return: 0 on success and error code on failure.
70 */
send_d0wow_disable_cmd_tlv(wmi_unified_t wmi_handle,uint8_t mac_id)71 static QDF_STATUS send_d0wow_disable_cmd_tlv(wmi_unified_t wmi_handle,
72 uint8_t mac_id)
73 {
74 wmi_d0_wow_enable_disable_cmd_fixed_param *cmd;
75 wmi_buf_t buf;
76 int32_t len;
77 QDF_STATUS status;
78
79 len = sizeof(wmi_d0_wow_enable_disable_cmd_fixed_param);
80
81 buf = wmi_buf_alloc(wmi_handle, len);
82 if (!buf) {
83 return QDF_STATUS_E_NOMEM;
84 }
85 cmd = (wmi_d0_wow_enable_disable_cmd_fixed_param *) wmi_buf_data(buf);
86 WMITLV_SET_HDR(&cmd->tlv_header,
87 WMITLV_TAG_STRUC_wmi_d0_wow_enable_disable_cmd_fixed_param,
88 WMITLV_GET_STRUCT_TLVLEN
89 (wmi_d0_wow_enable_disable_cmd_fixed_param));
90
91 cmd->enable = false;
92
93 wmi_mtrace(WMI_D0_WOW_ENABLE_DISABLE_CMDID, NO_SESSION, 0);
94 status = wmi_unified_cmd_send(wmi_handle, buf, len,
95 WMI_D0_WOW_ENABLE_DISABLE_CMDID);
96 if (QDF_IS_STATUS_ERROR(status))
97 wmi_buf_free(buf);
98
99 return status;
100 }
101
wmi_d0wow_attach_tlv(struct wmi_unified * wmi_handle)102 void wmi_d0wow_attach_tlv(struct wmi_unified *wmi_handle)
103 {
104 struct wmi_ops *ops = wmi_handle->ops;
105
106 ops->send_d0wow_enable_cmd = send_d0wow_enable_cmd_tlv;
107 ops->send_d0wow_disable_cmd = send_d0wow_disable_cmd_tlv;
108 }
109 #endif /* FEATURE_WLAN_D0WOW */
110
111 /**
112 * send_add_wow_wakeup_event_cmd_tlv() - Configures wow wakeup events.
113 * @wmi_handle: wmi handle
114 * @vdev_id: vdev id
115 * @bitmap: Event bitmap
116 * @enable: enable/disable
117 *
118 * Return: QDF status
119 */
send_add_wow_wakeup_event_cmd_tlv(wmi_unified_t wmi_handle,uint32_t vdev_id,uint32_t * bitmap,bool enable)120 static QDF_STATUS send_add_wow_wakeup_event_cmd_tlv(wmi_unified_t wmi_handle,
121 uint32_t vdev_id,
122 uint32_t *bitmap,
123 bool enable)
124 {
125 WMI_WOW_ADD_DEL_EVT_CMD_fixed_param *cmd;
126 uint16_t len;
127 wmi_buf_t buf;
128 int ret;
129
130 len = sizeof(WMI_WOW_ADD_DEL_EVT_CMD_fixed_param);
131 buf = wmi_buf_alloc(wmi_handle, len);
132 if (!buf) {
133 return QDF_STATUS_E_NOMEM;
134 }
135 cmd = (WMI_WOW_ADD_DEL_EVT_CMD_fixed_param *) wmi_buf_data(buf);
136 WMITLV_SET_HDR(&cmd->tlv_header,
137 WMITLV_TAG_STRUC_WMI_WOW_ADD_DEL_EVT_CMD_fixed_param,
138 WMITLV_GET_STRUCT_TLVLEN
139 (WMI_WOW_ADD_DEL_EVT_CMD_fixed_param));
140 cmd->vdev_id = vdev_id;
141 cmd->is_add = enable;
142 qdf_mem_copy(&(cmd->event_bitmaps[0]), bitmap, sizeof(uint32_t) *
143 WMI_WOW_MAX_EVENT_BM_LEN);
144
145 wmi_debug("Wakeup pattern 0x%x%x%x%x %s in fw", cmd->event_bitmaps[0],
146 cmd->event_bitmaps[1], cmd->event_bitmaps[2],
147 cmd->event_bitmaps[3], enable ? "enabled" : "disabled");
148
149 wmi_mtrace(WMI_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID, cmd->vdev_id, 0);
150 ret = wmi_unified_cmd_send(wmi_handle, buf, len,
151 WMI_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID);
152 if (ret) {
153 wmi_err("Failed to config wow wakeup event");
154 wmi_buf_free(buf);
155 return QDF_STATUS_E_FAILURE;
156 }
157
158 return QDF_STATUS_SUCCESS;
159 }
160
161 /**
162 * send_wow_patterns_to_fw_cmd_tlv() - Sends WOW patterns to FW.
163 * @wmi_handle: wmi handle
164 * @vdev_id: vdev id
165 * @ptrn_id: pattern id
166 * @ptrn: pattern
167 * @ptrn_len: pattern length
168 * @ptrn_offset: pattern offset
169 * @mask: mask
170 * @mask_len: mask length
171 * @user: true for user configured pattern and false for default pattern
172 * @default_patterns: default patterns
173 *
174 * Return: QDF status
175 */
send_wow_patterns_to_fw_cmd_tlv(wmi_unified_t wmi_handle,uint8_t vdev_id,uint8_t ptrn_id,const uint8_t * ptrn,uint8_t ptrn_len,uint8_t ptrn_offset,const uint8_t * mask,uint8_t mask_len,bool user,uint8_t default_patterns)176 static QDF_STATUS send_wow_patterns_to_fw_cmd_tlv(wmi_unified_t wmi_handle,
177 uint8_t vdev_id, uint8_t ptrn_id,
178 const uint8_t *ptrn, uint8_t ptrn_len,
179 uint8_t ptrn_offset, const uint8_t *mask,
180 uint8_t mask_len, bool user,
181 uint8_t default_patterns)
182 {
183 WMI_WOW_ADD_PATTERN_CMD_fixed_param *cmd;
184 WOW_BITMAP_PATTERN_T *bitmap_pattern;
185 wmi_buf_t buf;
186 uint8_t *buf_ptr;
187 int32_t len;
188 int ret;
189
190 len = sizeof(WMI_WOW_ADD_PATTERN_CMD_fixed_param) +
191 WMI_TLV_HDR_SIZE +
192 1 * sizeof(WOW_BITMAP_PATTERN_T) +
193 WMI_TLV_HDR_SIZE +
194 0 * sizeof(WOW_IPV4_SYNC_PATTERN_T) +
195 WMI_TLV_HDR_SIZE +
196 0 * sizeof(WOW_IPV6_SYNC_PATTERN_T) +
197 WMI_TLV_HDR_SIZE +
198 0 * sizeof(WOW_MAGIC_PATTERN_CMD) +
199 WMI_TLV_HDR_SIZE +
200 0 * sizeof(uint32_t) + WMI_TLV_HDR_SIZE + 1 * sizeof(uint32_t);
201
202 buf = wmi_buf_alloc(wmi_handle, len);
203 if (!buf) {
204 return QDF_STATUS_E_NOMEM;
205 }
206
207 cmd = (WMI_WOW_ADD_PATTERN_CMD_fixed_param *) wmi_buf_data(buf);
208 buf_ptr = (uint8_t *) cmd;
209
210 WMITLV_SET_HDR(&cmd->tlv_header,
211 WMITLV_TAG_STRUC_WMI_WOW_ADD_PATTERN_CMD_fixed_param,
212 WMITLV_GET_STRUCT_TLVLEN
213 (WMI_WOW_ADD_PATTERN_CMD_fixed_param));
214 cmd->vdev_id = vdev_id;
215 cmd->pattern_id = ptrn_id;
216
217 cmd->pattern_type = WOW_BITMAP_PATTERN;
218 buf_ptr += sizeof(WMI_WOW_ADD_PATTERN_CMD_fixed_param);
219
220 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
221 sizeof(WOW_BITMAP_PATTERN_T));
222 buf_ptr += WMI_TLV_HDR_SIZE;
223 bitmap_pattern = (WOW_BITMAP_PATTERN_T *) buf_ptr;
224
225 WMITLV_SET_HDR(&bitmap_pattern->tlv_header,
226 WMITLV_TAG_STRUC_WOW_BITMAP_PATTERN_T,
227 WMITLV_GET_STRUCT_TLVLEN(WOW_BITMAP_PATTERN_T));
228
229 qdf_mem_copy(&bitmap_pattern->patternbuf[0], ptrn, ptrn_len);
230 qdf_mem_copy(&bitmap_pattern->bitmaskbuf[0], mask, mask_len);
231
232 bitmap_pattern->pattern_offset = ptrn_offset;
233 bitmap_pattern->pattern_len = ptrn_len;
234
235 if (bitmap_pattern->pattern_len > WOW_DEFAULT_BITMAP_PATTERN_SIZE)
236 bitmap_pattern->pattern_len = WOW_DEFAULT_BITMAP_PATTERN_SIZE;
237
238 if (bitmap_pattern->pattern_len > WOW_DEFAULT_BITMASK_SIZE)
239 bitmap_pattern->pattern_len = WOW_DEFAULT_BITMASK_SIZE;
240
241 bitmap_pattern->bitmask_len = bitmap_pattern->pattern_len;
242 bitmap_pattern->pattern_id = ptrn_id;
243
244 wmi_debug("vdev: %d, ptrn id: %d, ptrn len: %d, ptrn offset: %d user %d",
245 cmd->vdev_id, cmd->pattern_id, bitmap_pattern->pattern_len,
246 bitmap_pattern->pattern_offset, user);
247 wmi_debug("Pattern: ");
248 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_DEBUG,
249 &bitmap_pattern->patternbuf[0],
250 bitmap_pattern->pattern_len);
251
252 wmi_debug("Mask: ");
253 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_DEBUG,
254 &bitmap_pattern->bitmaskbuf[0],
255 bitmap_pattern->pattern_len);
256
257 buf_ptr += sizeof(WOW_BITMAP_PATTERN_T);
258
259 /* Fill TLV for WMITLV_TAG_STRUC_WOW_IPV4_SYNC_PATTERN_T but no data. */
260 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
261 buf_ptr += WMI_TLV_HDR_SIZE;
262
263 /* Fill TLV for WMITLV_TAG_STRUC_WOW_IPV6_SYNC_PATTERN_T but no data. */
264 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
265 buf_ptr += WMI_TLV_HDR_SIZE;
266
267 /* Fill TLV for WMITLV_TAG_STRUC_WOW_MAGIC_PATTERN_CMD but no data. */
268 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
269 buf_ptr += WMI_TLV_HDR_SIZE;
270
271 /* Fill TLV for pattern_info_timeout but no data. */
272 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, 0);
273 buf_ptr += WMI_TLV_HDR_SIZE;
274
275 /* Fill TLV for ratelimit_interval with dummy data as this fix elem */
276 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, 1 * sizeof(uint32_t));
277 buf_ptr += WMI_TLV_HDR_SIZE;
278 *(uint32_t *) buf_ptr = 0;
279
280 wmi_mtrace(WMI_WOW_ADD_WAKE_PATTERN_CMDID, cmd->vdev_id, 0);
281 ret = wmi_unified_cmd_send(wmi_handle, buf, len,
282 WMI_WOW_ADD_WAKE_PATTERN_CMDID);
283 if (ret) {
284 wmi_err("Failed to send wow ptrn to fw");
285 wmi_buf_free(buf);
286 return QDF_STATUS_E_FAILURE;
287 }
288
289 return QDF_STATUS_SUCCESS;
290 }
291
292 /**
293 * fill_arp_offload_params_tlv() - Fill ARP offload data
294 * @wmi_handle: wmi handle
295 * @offload_req: offload request
296 * @buf_ptr: buffer pointer
297 *
298 * To fill ARP offload data to firmware
299 * when target goes to wow mode.
300 *
301 * Return: None
302 */
fill_arp_offload_params_tlv(wmi_unified_t wmi_handle,struct pmo_arp_offload_params * offload_req,uint8_t ** buf_ptr)303 static void fill_arp_offload_params_tlv(wmi_unified_t wmi_handle,
304 struct pmo_arp_offload_params *offload_req, uint8_t **buf_ptr)
305 {
306
307 int i;
308 WMI_ARP_OFFLOAD_TUPLE *arp_tuple;
309 bool enable_or_disable = offload_req->enable;
310
311 WMITLV_SET_HDR(*buf_ptr, WMITLV_TAG_ARRAY_STRUC,
312 (WMI_MAX_ARP_OFFLOADS*sizeof(WMI_ARP_OFFLOAD_TUPLE)));
313 *buf_ptr += WMI_TLV_HDR_SIZE;
314 for (i = 0; i < WMI_MAX_ARP_OFFLOADS; i++) {
315 arp_tuple = (WMI_ARP_OFFLOAD_TUPLE *)*buf_ptr;
316 WMITLV_SET_HDR(&arp_tuple->tlv_header,
317 WMITLV_TAG_STRUC_WMI_ARP_OFFLOAD_TUPLE,
318 WMITLV_GET_STRUCT_TLVLEN(WMI_ARP_OFFLOAD_TUPLE));
319
320 /* Fill data for ARP and NS in the first tuple for LA */
321 if ((enable_or_disable & PMO_OFFLOAD_ENABLE) && (i == 0)) {
322 /* Copy the target ip addr and flags */
323 arp_tuple->flags = WMI_ARPOFF_FLAGS_VALID;
324 qdf_mem_copy(&arp_tuple->target_ipaddr,
325 offload_req->host_ipv4_addr,
326 WMI_IPV4_ADDR_LEN);
327 wmi_debug("ARPOffload IP4 address: %pI4",
328 offload_req->host_ipv4_addr);
329 }
330 *buf_ptr += sizeof(WMI_ARP_OFFLOAD_TUPLE);
331 }
332 }
333
334 #ifdef WLAN_NS_OFFLOAD
335 /**
336 * fill_ns_offload_params_tlv() - Fill NS offload data
337 * @wmi_handle: wmi handle
338 * @ns_req: offload request
339 * @buf_ptr: buffer pointer
340 *
341 * To fill NS offload data to firmware
342 * when target goes to wow mode.
343 *
344 * Return: None
345 */
fill_ns_offload_params_tlv(wmi_unified_t wmi_handle,struct pmo_ns_offload_params * ns_req,uint8_t ** buf_ptr)346 static void fill_ns_offload_params_tlv(wmi_unified_t wmi_handle,
347 struct pmo_ns_offload_params *ns_req, uint8_t **buf_ptr)
348 {
349
350 int i;
351 WMI_NS_OFFLOAD_TUPLE *ns_tuple;
352
353 WMITLV_SET_HDR(*buf_ptr, WMITLV_TAG_ARRAY_STRUC,
354 (WMI_MAX_NS_OFFLOADS * sizeof(WMI_NS_OFFLOAD_TUPLE)));
355 *buf_ptr += WMI_TLV_HDR_SIZE;
356 for (i = 0; i < WMI_MAX_NS_OFFLOADS; i++) {
357 ns_tuple = (WMI_NS_OFFLOAD_TUPLE *)*buf_ptr;
358 WMITLV_SET_HDR(&ns_tuple->tlv_header,
359 WMITLV_TAG_STRUC_WMI_NS_OFFLOAD_TUPLE,
360 (sizeof(WMI_NS_OFFLOAD_TUPLE) - WMI_TLV_HDR_SIZE));
361
362 /*
363 * Fill data only for NS offload in the first ARP tuple for LA
364 */
365 if ((ns_req->enable & PMO_OFFLOAD_ENABLE)) {
366 ns_tuple->flags |= WMI_NSOFF_FLAGS_VALID;
367 /* Copy the target/solicitation/remote ip addr */
368 if (ns_req->target_ipv6_addr_valid[i])
369 qdf_mem_copy(&ns_tuple->target_ipaddr[0],
370 &ns_req->target_ipv6_addr[i],
371 sizeof(WMI_IPV6_ADDR));
372 qdf_mem_copy(&ns_tuple->solicitation_ipaddr,
373 &ns_req->self_ipv6_addr[i],
374 sizeof(WMI_IPV6_ADDR));
375 if (ns_req->target_ipv6_addr_ac_type[i]) {
376 ns_tuple->flags |=
377 WMI_NSOFF_FLAGS_IS_IPV6_ANYCAST;
378 }
379 wmi_debug("Index %d NS solicitedIp %pI6, targetIp %pI6",
380 i, &ns_req->self_ipv6_addr[i],
381 &ns_req->target_ipv6_addr[i]);
382
383 /* target MAC is optional, check if it is valid,
384 * if this is not valid, the target will use the known
385 * local MAC address rather than the tuple
386 */
387 WMI_CHAR_ARRAY_TO_MAC_ADDR(
388 ns_req->self_macaddr.bytes,
389 &ns_tuple->target_mac);
390 if ((ns_tuple->target_mac.mac_addr31to0 != 0) ||
391 (ns_tuple->target_mac.mac_addr47to32 != 0)) {
392 ns_tuple->flags |= WMI_NSOFF_FLAGS_MAC_VALID;
393 }
394 }
395 *buf_ptr += sizeof(WMI_NS_OFFLOAD_TUPLE);
396 }
397 }
398
399 /**
400 * fill_nsoffload_ext_tlv() - Fill NS offload ext data
401 * @wmi_handle: wmi handle
402 * @ns_req: offload request
403 * @buf_ptr: buffer pointer
404 *
405 * To fill extended NS offload extended data to firmware
406 * when target goes to wow mode.
407 *
408 * Return: None
409 */
fill_nsoffload_ext_tlv(wmi_unified_t wmi_handle,struct pmo_ns_offload_params * ns_req,uint8_t ** buf_ptr)410 static void fill_nsoffload_ext_tlv(wmi_unified_t wmi_handle,
411 struct pmo_ns_offload_params *ns_req, uint8_t **buf_ptr)
412 {
413 int i;
414 WMI_NS_OFFLOAD_TUPLE *ns_tuple;
415 uint32_t count, num_ns_ext_tuples;
416
417 count = ns_req->num_ns_offload_count;
418 num_ns_ext_tuples = ns_req->num_ns_offload_count -
419 WMI_MAX_NS_OFFLOADS;
420
421 /* Populate extended NS offload tuples */
422 WMITLV_SET_HDR(*buf_ptr, WMITLV_TAG_ARRAY_STRUC,
423 (num_ns_ext_tuples * sizeof(WMI_NS_OFFLOAD_TUPLE)));
424 *buf_ptr += WMI_TLV_HDR_SIZE;
425 for (i = WMI_MAX_NS_OFFLOADS; i < count; i++) {
426 ns_tuple = (WMI_NS_OFFLOAD_TUPLE *)*buf_ptr;
427 WMITLV_SET_HDR(&ns_tuple->tlv_header,
428 WMITLV_TAG_STRUC_WMI_NS_OFFLOAD_TUPLE,
429 (sizeof(WMI_NS_OFFLOAD_TUPLE)-WMI_TLV_HDR_SIZE));
430
431 /*
432 * Fill data only for NS offload in the first ARP tuple for LA
433 */
434 if ((ns_req->enable & PMO_OFFLOAD_ENABLE)) {
435 ns_tuple->flags |= WMI_NSOFF_FLAGS_VALID;
436 /* Copy the target/solicitation/remote ip addr */
437 if (ns_req->target_ipv6_addr_valid[i])
438 qdf_mem_copy(&ns_tuple->target_ipaddr[0],
439 &ns_req->target_ipv6_addr[i],
440 sizeof(WMI_IPV6_ADDR));
441 qdf_mem_copy(&ns_tuple->solicitation_ipaddr,
442 &ns_req->self_ipv6_addr[i],
443 sizeof(WMI_IPV6_ADDR));
444 if (ns_req->target_ipv6_addr_ac_type[i]) {
445 ns_tuple->flags |=
446 WMI_NSOFF_FLAGS_IS_IPV6_ANYCAST;
447 }
448 wmi_debug("Index %d NS solicitedIp %pI6, targetIp %pI6",
449 i, &ns_req->self_ipv6_addr[i],
450 &ns_req->target_ipv6_addr[i]);
451
452 /* target MAC is optional, check if it is valid,
453 * if this is not valid, the target will use the
454 * known local MAC address rather than the tuple
455 */
456 WMI_CHAR_ARRAY_TO_MAC_ADDR(
457 ns_req->self_macaddr.bytes,
458 &ns_tuple->target_mac);
459 if ((ns_tuple->target_mac.mac_addr31to0 != 0) ||
460 (ns_tuple->target_mac.mac_addr47to32 != 0)) {
461 ns_tuple->flags |= WMI_NSOFF_FLAGS_MAC_VALID;
462 }
463 }
464 *buf_ptr += sizeof(WMI_NS_OFFLOAD_TUPLE);
465 }
466 }
467 #else
fill_ns_offload_params_tlv(wmi_unified_t wmi_handle,struct pmo_ns_offload_params * ns_req,uint8_t ** buf_ptr)468 static void fill_ns_offload_params_tlv(wmi_unified_t wmi_handle,
469 struct pmo_ns_offload_params *ns_req, uint8_t **buf_ptr)
470 {
471 }
472
fill_nsoffload_ext_tlv(wmi_unified_t wmi_handle,struct pmo_ns_offload_params * ns_req,uint8_t ** buf_ptr)473 static void fill_nsoffload_ext_tlv(wmi_unified_t wmi_handle,
474 struct pmo_ns_offload_params *ns_req, uint8_t **buf_ptr)
475 {
476 }
477 #endif
478
479 /**
480 * send_enable_arp_ns_offload_cmd_tlv() - enable ARP NS offload
481 * @wmi_handle: wmi handle
482 * @arp_offload_req: arp offload request
483 * @ns_offload_req: ns offload request
484 * @vdev_id: vdev ID
485 *
486 * To configure ARP NS off load data to firmware
487 * when target goes to wow mode.
488 *
489 * Return: QDF Status
490 */
send_enable_arp_ns_offload_cmd_tlv(wmi_unified_t wmi_handle,struct pmo_arp_offload_params * arp_offload_req,struct pmo_ns_offload_params * ns_offload_req,uint8_t vdev_id)491 static QDF_STATUS send_enable_arp_ns_offload_cmd_tlv(wmi_unified_t wmi_handle,
492 struct pmo_arp_offload_params *arp_offload_req,
493 struct pmo_ns_offload_params *ns_offload_req,
494 uint8_t vdev_id)
495 {
496 int32_t res;
497 WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param *cmd;
498 uint8_t *buf_ptr;
499 wmi_buf_t buf;
500 int32_t len;
501 uint32_t count = 0, num_ns_ext_tuples = 0;
502
503 count = ns_offload_req->num_ns_offload_count;
504
505 /*
506 * TLV place holder size for array of NS tuples
507 * TLV place holder size for array of ARP tuples
508 */
509 len = sizeof(WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param) +
510 WMI_TLV_HDR_SIZE +
511 WMI_MAX_NS_OFFLOADS * sizeof(WMI_NS_OFFLOAD_TUPLE) +
512 WMI_TLV_HDR_SIZE +
513 WMI_MAX_ARP_OFFLOADS * sizeof(WMI_ARP_OFFLOAD_TUPLE);
514
515 /*
516 * If there are more than WMI_MAX_NS_OFFLOADS addresses then allocate
517 * extra length for extended NS offload tuples which follows ARP offload
518 * tuples. Host needs to fill this structure in following format:
519 * 2 NS ofload tuples
520 * 2 ARP offload tuples
521 * N numbers of extended NS offload tuples if HDD has given more than
522 * 2 NS offload addresses
523 */
524 if (count > WMI_MAX_NS_OFFLOADS) {
525 num_ns_ext_tuples = count - WMI_MAX_NS_OFFLOADS;
526 len += WMI_TLV_HDR_SIZE + num_ns_ext_tuples
527 * sizeof(WMI_NS_OFFLOAD_TUPLE);
528 }
529
530 buf = wmi_buf_alloc(wmi_handle, len);
531 if (!buf) {
532 return QDF_STATUS_E_NOMEM;
533 }
534
535 buf_ptr = (uint8_t *) wmi_buf_data(buf);
536 cmd = (WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param *) buf_ptr;
537 WMITLV_SET_HDR(&cmd->tlv_header,
538 WMITLV_TAG_STRUC_WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param,
539 WMITLV_GET_STRUCT_TLVLEN
540 (WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param));
541 cmd->flags = 0;
542 cmd->vdev_id = vdev_id;
543 cmd->num_ns_ext_tuples = num_ns_ext_tuples;
544
545 wmi_debug("ARP NS Offload vdev_id: %d", cmd->vdev_id);
546
547 buf_ptr += sizeof(WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param);
548 fill_ns_offload_params_tlv(wmi_handle, ns_offload_req, &buf_ptr);
549 fill_arp_offload_params_tlv(wmi_handle, arp_offload_req, &buf_ptr);
550 if (num_ns_ext_tuples)
551 fill_nsoffload_ext_tlv(wmi_handle, ns_offload_req, &buf_ptr);
552
553 wmi_mtrace(WMI_SET_ARP_NS_OFFLOAD_CMDID, cmd->vdev_id, 0);
554 res = wmi_unified_cmd_send(wmi_handle, buf, len,
555 WMI_SET_ARP_NS_OFFLOAD_CMDID);
556 if (res) {
557 wmi_err("Failed to enable ARP NDP/NSffload");
558 wmi_buf_free(buf);
559 return QDF_STATUS_E_FAILURE;
560 }
561
562 return QDF_STATUS_SUCCESS;
563 }
564
565 /**
566 * send_add_clear_mcbc_filter_cmd_tlv() - set mcast filter command to fw
567 * @wmi_handle: wmi handle
568 * @vdev_id: vdev id
569 * @multicast_addr: mcast address
570 * @clearList: clear list flag
571 *
572 * Return: QDF_STATUS_SUCCESS for success or error code
573 */
send_add_clear_mcbc_filter_cmd_tlv(wmi_unified_t wmi_handle,uint8_t vdev_id,struct qdf_mac_addr multicast_addr,bool clearList)574 static QDF_STATUS send_add_clear_mcbc_filter_cmd_tlv(wmi_unified_t wmi_handle,
575 uint8_t vdev_id,
576 struct qdf_mac_addr multicast_addr,
577 bool clearList)
578 {
579 WMI_SET_MCASTBCAST_FILTER_CMD_fixed_param *cmd;
580 wmi_buf_t buf;
581 int err;
582
583 buf = wmi_buf_alloc(wmi_handle, sizeof(*cmd));
584 if (!buf) {
585 return QDF_STATUS_E_NOMEM;
586 }
587
588 cmd = (WMI_SET_MCASTBCAST_FILTER_CMD_fixed_param *) wmi_buf_data(buf);
589 qdf_mem_zero(cmd, sizeof(*cmd));
590
591 WMITLV_SET_HDR(&cmd->tlv_header,
592 WMITLV_TAG_STRUC_WMI_SET_MCASTBCAST_FILTER_CMD_fixed_param,
593 WMITLV_GET_STRUCT_TLVLEN
594 (WMI_SET_MCASTBCAST_FILTER_CMD_fixed_param));
595 cmd->action =
596 (clearList ? WMI_MCAST_FILTER_DELETE : WMI_MCAST_FILTER_SET);
597 cmd->vdev_id = vdev_id;
598 WMI_CHAR_ARRAY_TO_MAC_ADDR(multicast_addr.bytes, &cmd->mcastbdcastaddr);
599
600 wmi_debug("Action:%d; vdev_id:%d; clearList:%d; MCBC MAC Addr: "QDF_MAC_ADDR_FMT,
601 cmd->action, vdev_id, clearList,
602 QDF_MAC_ADDR_REF(multicast_addr.bytes));
603
604 wmi_mtrace(WMI_SET_MCASTBCAST_FILTER_CMDID, cmd->vdev_id, 0);
605 err = wmi_unified_cmd_send(wmi_handle, buf,
606 sizeof(*cmd),
607 WMI_SET_MCASTBCAST_FILTER_CMDID);
608 if (err) {
609 wmi_err("Failed to send set_param cmd");
610 wmi_buf_free(buf);
611 return QDF_STATUS_E_FAILURE;
612 }
613
614 return QDF_STATUS_SUCCESS;
615 }
616
617 /**
618 * send_multiple_add_clear_mcbc_filter_cmd_tlv() - send multiple mcast filter
619 * command to fw
620 * @wmi_handle: wmi handle
621 * @vdev_id: vdev id
622 * @filter_param: mcast filter params
623 *
624 * Return: QDF_STATUS_SUCCESS for success or error code
625 */
send_multiple_add_clear_mcbc_filter_cmd_tlv(wmi_unified_t wmi_handle,uint8_t vdev_id,struct pmo_mcast_filter_params * filter_param)626 static QDF_STATUS send_multiple_add_clear_mcbc_filter_cmd_tlv(
627 wmi_unified_t wmi_handle,
628 uint8_t vdev_id,
629 struct pmo_mcast_filter_params *filter_param)
630
631 {
632 WMI_SET_MULTIPLE_MCAST_FILTER_CMD_fixed_param *cmd;
633 uint8_t *buf_ptr;
634 wmi_buf_t buf;
635 int err;
636 int i;
637 uint8_t *mac_addr_src_ptr = NULL;
638 wmi_mac_addr *mac_addr_dst_ptr;
639 uint32_t len = sizeof(*cmd) + WMI_TLV_HDR_SIZE +
640 sizeof(wmi_mac_addr) * filter_param->multicast_addr_cnt;
641
642 buf = wmi_buf_alloc(wmi_handle, len);
643 if (!buf) {
644 return QDF_STATUS_E_NOMEM;
645 }
646
647 buf_ptr = (uint8_t *) wmi_buf_data(buf);
648 cmd = (WMI_SET_MULTIPLE_MCAST_FILTER_CMD_fixed_param *)
649 wmi_buf_data(buf);
650 qdf_mem_zero(cmd, sizeof(*cmd));
651
652 WMITLV_SET_HDR(&cmd->tlv_header,
653 WMITLV_TAG_STRUC_wmi_set_multiple_mcast_filter_cmd_fixed_param,
654 WMITLV_GET_STRUCT_TLVLEN
655 (WMI_SET_MULTIPLE_MCAST_FILTER_CMD_fixed_param));
656 cmd->operation =
657 ((filter_param->action == 0) ? WMI_MULTIPLE_MCAST_FILTER_DELETE
658 : WMI_MULTIPLE_MCAST_FILTER_ADD);
659 cmd->vdev_id = vdev_id;
660 cmd->num_mcastaddrs = filter_param->multicast_addr_cnt;
661
662 buf_ptr += sizeof(*cmd);
663 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_FIXED_STRUC,
664 sizeof(wmi_mac_addr) *
665 filter_param->multicast_addr_cnt);
666
667 if (filter_param->multicast_addr_cnt == 0)
668 goto send_cmd;
669
670 mac_addr_src_ptr = (uint8_t *)&filter_param->multicast_addr;
671 mac_addr_dst_ptr = (wmi_mac_addr *)
672 (buf_ptr + WMI_TLV_HDR_SIZE);
673
674 wmi_debug("multicast addr cnt: %u", filter_param->multicast_addr_cnt);
675 for (i = 0; i < filter_param->multicast_addr_cnt; i++) {
676 WMI_CHAR_ARRAY_TO_MAC_ADDR(mac_addr_src_ptr, mac_addr_dst_ptr);
677 wmi_nofl_debug("mac addr[%d]: " QDF_MAC_ADDR_FMT, i,
678 QDF_MAC_ADDR_REF(
679 filter_param->multicast_addr[i].bytes));
680 mac_addr_src_ptr += ATH_MAC_LEN;
681 mac_addr_dst_ptr++;
682 }
683
684 send_cmd:
685 wmi_mtrace(WMI_SET_MULTIPLE_MCAST_FILTER_CMDID, cmd->vdev_id, 0);
686 err = wmi_unified_cmd_send(wmi_handle, buf,
687 len,
688 WMI_SET_MULTIPLE_MCAST_FILTER_CMDID);
689 if (err) {
690 wmi_err("Failed to send set_param cmd");
691 wmi_buf_free(buf);
692 return QDF_STATUS_E_FAILURE;
693 }
694
695 return QDF_STATUS_SUCCESS;
696 }
697
send_conf_hw_filter_cmd_tlv(wmi_unified_t wmi,struct pmo_hw_filter_params * req)698 static QDF_STATUS send_conf_hw_filter_cmd_tlv(wmi_unified_t wmi,
699 struct pmo_hw_filter_params *req)
700 {
701 QDF_STATUS status;
702 wmi_hw_data_filter_cmd_fixed_param *cmd;
703 wmi_buf_t wmi_buf;
704
705 if (!req) {
706 wmi_err("req is null");
707 return QDF_STATUS_E_INVAL;
708 }
709
710 wmi_buf = wmi_buf_alloc(wmi, sizeof(*cmd));
711 if (!wmi_buf) {
712 return QDF_STATUS_E_NOMEM;
713 }
714
715 cmd = (wmi_hw_data_filter_cmd_fixed_param *)wmi_buf_data(wmi_buf);
716 WMITLV_SET_HDR(&cmd->tlv_header,
717 WMITLV_TAG_STRUC_wmi_hw_data_filter_cmd_fixed_param,
718 WMITLV_GET_STRUCT_TLVLEN(wmi_hw_data_filter_cmd_fixed_param));
719 cmd->vdev_id = req->vdev_id;
720 cmd->enable = req->enable;
721 /* Set all modes in case of disable */
722 if (!cmd->enable)
723 cmd->hw_filter_bitmap = ((uint32_t)~0U);
724 else
725 cmd->hw_filter_bitmap = req->mode_bitmap;
726
727 wmi_debug("Send %s hw filter mode: 0x%X for vdev id %d",
728 req->enable ? "enable" : "disable", req->mode_bitmap,
729 req->vdev_id);
730
731 wmi_mtrace(WMI_HW_DATA_FILTER_CMDID, cmd->vdev_id, 0);
732 status = wmi_unified_cmd_send(wmi, wmi_buf, sizeof(*cmd),
733 WMI_HW_DATA_FILTER_CMDID);
734 if (QDF_IS_STATUS_ERROR(status)) {
735 wmi_err("Failed to configure hw filter");
736 wmi_buf_free(wmi_buf);
737 }
738
739 return status;
740 }
741
742 static void
fill_fils_tlv_params(WMI_GTK_OFFLOAD_CMD_fixed_param * cmd,uint8_t vdev_id,struct pmo_gtk_req * params)743 fill_fils_tlv_params(WMI_GTK_OFFLOAD_CMD_fixed_param *cmd,
744 uint8_t vdev_id,
745 struct pmo_gtk_req *params)
746 {
747 uint8_t *buf_ptr;
748 wmi_gtk_offload_fils_tlv_param *ext_param;
749
750 buf_ptr = (uint8_t *) cmd + sizeof(*cmd);
751 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
752 sizeof(*ext_param));
753 buf_ptr += WMI_TLV_HDR_SIZE;
754
755 ext_param = (wmi_gtk_offload_fils_tlv_param *)buf_ptr;
756 WMITLV_SET_HDR(&ext_param->tlv_header,
757 WMITLV_TAG_STRUC_wmi_gtk_offload_extended_tlv_param,
758 WMITLV_GET_STRUCT_TLVLEN(
759 wmi_gtk_offload_fils_tlv_param));
760 ext_param->vdev_id = vdev_id;
761 ext_param->flags = cmd->flags;
762 ext_param->kek_len = params->kek_len;
763 qdf_mem_copy(ext_param->KEK, params->kek, params->kek_len);
764 qdf_mem_copy(ext_param->KCK, params->kck,
765 WMI_GTK_OFFLOAD_KCK_BYTES);
766 qdf_mem_copy(ext_param->replay_counter, ¶ms->replay_counter,
767 GTK_REPLAY_COUNTER_BYTES);
768 }
769
770 #ifdef WLAN_FEATURE_IGMP_OFFLOAD
771 /**
772 * send_igmp_offload_cmd_tlv() - send IGMP offload command to fw
773 * @wmi_handle: wmi handle
774 * @pmo_igmp_req: IGMP offload parameters
775 *
776 * Return: QDF status
777 */
778 static
send_igmp_offload_cmd_tlv(wmi_unified_t wmi_handle,struct pmo_igmp_offload_req * pmo_igmp_req)779 QDF_STATUS send_igmp_offload_cmd_tlv(wmi_unified_t wmi_handle,
780 struct pmo_igmp_offload_req *pmo_igmp_req)
781 {
782 wmi_buf_t buf;
783 uint8_t *buf_ptr;
784 int len;
785 int i = 0;
786 WMI_IPV4_ADDR *ipv4_list;
787 wmi_igmp_offload_fixed_param *cmd;
788 QDF_STATUS status = QDF_STATUS_SUCCESS;
789
790 len = sizeof(wmi_igmp_offload_fixed_param) + WMI_TLV_HDR_SIZE +
791 (pmo_igmp_req->num_grp_ip_address) * sizeof(WMI_IPV4_ADDR);
792 /* alloc wmi buffer */
793 buf = wmi_buf_alloc(wmi_handle, len);
794 if (!buf) {
795 status = QDF_STATUS_E_NOMEM;
796 goto out;
797 }
798 buf_ptr = (uint8_t *)wmi_buf_data(buf);
799 cmd = (wmi_igmp_offload_fixed_param *)wmi_buf_data(buf);
800
801 WMITLV_SET_HDR(&cmd->tlv_header,
802 WMITLV_TAG_STRUC_wmi_igmp_offload_fixed_param,
803 WMITLV_GET_STRUCT_TLVLEN(wmi_igmp_offload_fixed_param));
804
805 cmd->vdev_id = pmo_igmp_req->vdev_id;
806 cmd->enable = pmo_igmp_req->enable;
807 cmd->version_support_bitmask =
808 pmo_igmp_req->version_support;
809
810 buf_ptr += sizeof(*cmd);
811 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_FIXED_STRUC,
812 sizeof(WMI_IPV4_ADDR) *
813 pmo_igmp_req->num_grp_ip_address);
814
815 ipv4_list = (WMI_IPV4_ADDR *)(buf_ptr + WMI_TLV_HDR_SIZE);
816
817 while (i < pmo_igmp_req->num_grp_ip_address) {
818 qdf_mem_copy((void *)((*(ipv4_list + i)).address),
819 (void *)&(pmo_igmp_req->grp_ip_address[i]),
820 WMI_IPV4_ADDR_LEN);
821 wmi_debug("piv4[%d]:%x", i, *(uint32_t *)(ipv4_list + i));
822 i++;
823 }
824
825 wmi_debug("VDEVID:%d, FLAG:x%x version support:%d",
826 cmd->vdev_id, cmd->enable,
827 cmd->version_support_bitmask);
828
829 /* send the wmi command */
830 wmi_mtrace(WMI_VDEV_IGMP_OFFLOAD_CMDID, cmd->vdev_id, 0);
831 if (wmi_unified_cmd_send(wmi_handle, buf, len,
832 WMI_VDEV_IGMP_OFFLOAD_CMDID)) {
833 wmi_err("Failed to send WMI_VDEV_IGMP_OFFLOAD_CMDID");
834 wmi_buf_free(buf);
835 status = QDF_STATUS_E_FAILURE;
836 }
837 out:
838 return status;
839 }
840 #endif
841
842 /**
843 * send_gtk_offload_cmd_tlv() - send GTK offload command to fw
844 * @wmi_handle: wmi handle
845 * @vdev_id: vdev id
846 * @params: GTK offload parameters
847 * @enable_offload: true to enable the offload
848 * @gtk_offload_opcode: GTK offload opcode
849 *
850 * Return: QDF status
851 */
852 static
send_gtk_offload_cmd_tlv(wmi_unified_t wmi_handle,uint8_t vdev_id,struct pmo_gtk_req * params,bool enable_offload,uint32_t gtk_offload_opcode)853 QDF_STATUS send_gtk_offload_cmd_tlv(wmi_unified_t wmi_handle, uint8_t vdev_id,
854 struct pmo_gtk_req *params,
855 bool enable_offload,
856 uint32_t gtk_offload_opcode)
857 {
858 int len;
859 uint8_t *buf_ptr;
860 wmi_buf_t buf;
861 WMI_GTK_OFFLOAD_CMD_fixed_param *cmd;
862 QDF_STATUS status = QDF_STATUS_SUCCESS;
863
864 len = sizeof(*cmd);
865
866 len += WMI_TLV_HDR_SIZE;
867 if (params->is_fils_connection)
868 len += sizeof(wmi_gtk_offload_fils_tlv_param);
869
870 if (params->kck_len > 16)
871 len += WMI_TLV_HDR_SIZE +
872 roundup(params->kek_len, sizeof(uint32_t)) +
873 WMI_TLV_HDR_SIZE +
874 roundup(params->kck_len, sizeof(uint32_t));
875
876 /* alloc wmi buffer */
877 buf = wmi_buf_alloc(wmi_handle, len);
878 if (!buf) {
879 status = QDF_STATUS_E_NOMEM;
880 goto out;
881 }
882
883 cmd = (WMI_GTK_OFFLOAD_CMD_fixed_param *) wmi_buf_data(buf);
884 WMITLV_SET_HDR(&cmd->tlv_header,
885 WMITLV_TAG_STRUC_WMI_GTK_OFFLOAD_CMD_fixed_param,
886 WMITLV_GET_STRUCT_TLVLEN
887 (WMI_GTK_OFFLOAD_CMD_fixed_param));
888
889 buf_ptr = wmi_buf_data(buf);
890 cmd->vdev_id = vdev_id;
891
892 /* Request target to enable GTK offload */
893 if (enable_offload == PMO_GTK_OFFLOAD_ENABLE) {
894 cmd->flags = gtk_offload_opcode;
895
896 /* Copy the keys and replay counter */
897 qdf_mem_copy(cmd->KCK, params->kck, sizeof(cmd->KCK));
898 qdf_mem_copy(cmd->KEK, params->kek, sizeof(cmd->KEK));
899 qdf_mem_copy(cmd->replay_counter, ¶ms->replay_counter,
900 GTK_REPLAY_COUNTER_BYTES);
901 } else {
902 cmd->flags = gtk_offload_opcode;
903 }
904
905 buf_ptr = (uint8_t *)cmd + sizeof(*cmd);
906
907 if (params->is_fils_connection) {
908 fill_fils_tlv_params(cmd, vdev_id, params);
909 buf_ptr += sizeof(wmi_gtk_offload_fils_tlv_param);
910 } else {
911 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
912 buf_ptr += WMI_TLV_HDR_SIZE;
913 }
914
915 if (params->kck_len > 16) {
916 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE,
917 roundup(params->kek_len, sizeof(uint32_t)));
918 buf_ptr += WMI_TLV_HDR_SIZE;
919
920 qdf_mem_copy(buf_ptr, params->kek, params->kek_len);
921 buf_ptr += roundup(params->kek_len, sizeof(uint32_t));
922
923 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE,
924 roundup(params->kck_len, sizeof(uint32_t)));
925 buf_ptr += WMI_TLV_HDR_SIZE;
926
927 qdf_mem_copy(buf_ptr, params->kck, params->kck_len);
928 buf_ptr += roundup(params->kck_len, sizeof(uint32_t));
929 }
930
931 wmi_debug("VDEVID: %d, GTK_FLAGS: x%x kek len %d",
932 vdev_id, cmd->flags, params->kek_len);
933 /* send the wmi command */
934 wmi_mtrace(WMI_GTK_OFFLOAD_CMDID, cmd->vdev_id, 0);
935 if (wmi_unified_cmd_send(wmi_handle, buf, len,
936 WMI_GTK_OFFLOAD_CMDID)) {
937 wmi_err("Failed to send WMI_GTK_OFFLOAD_CMDID");
938 wmi_buf_free(buf);
939 status = QDF_STATUS_E_FAILURE;
940 }
941
942 out:
943 return status;
944 }
945
946 /**
947 * send_process_gtk_offload_getinfo_cmd_tlv() - send GTK offload cmd to fw
948 * @wmi_handle: wmi handle
949 * @vdev_id: vdev id
950 * @offload_req_opcode: GTK offload request opcode
951 *
952 * Return: QDF status
953 */
send_process_gtk_offload_getinfo_cmd_tlv(wmi_unified_t wmi_handle,uint8_t vdev_id,uint64_t offload_req_opcode)954 static QDF_STATUS send_process_gtk_offload_getinfo_cmd_tlv(
955 wmi_unified_t wmi_handle,
956 uint8_t vdev_id,
957 uint64_t offload_req_opcode)
958 {
959 int len;
960 wmi_buf_t buf;
961 WMI_GTK_OFFLOAD_CMD_fixed_param *cmd;
962 QDF_STATUS status = QDF_STATUS_SUCCESS;
963
964 len = sizeof(*cmd);
965
966 /* alloc wmi buffer */
967 buf = wmi_buf_alloc(wmi_handle, len);
968 if (!buf) {
969 status = QDF_STATUS_E_NOMEM;
970 goto out;
971 }
972
973 cmd = (WMI_GTK_OFFLOAD_CMD_fixed_param *) wmi_buf_data(buf);
974 WMITLV_SET_HDR(&cmd->tlv_header,
975 WMITLV_TAG_STRUC_WMI_GTK_OFFLOAD_CMD_fixed_param,
976 WMITLV_GET_STRUCT_TLVLEN
977 (WMI_GTK_OFFLOAD_CMD_fixed_param));
978
979 /* Request for GTK offload status */
980 cmd->flags = offload_req_opcode;
981 cmd->vdev_id = vdev_id;
982
983 /* send the wmi command */
984 wmi_mtrace(WMI_GTK_OFFLOAD_CMDID, cmd->vdev_id, 0);
985 if (wmi_unified_cmd_send(wmi_handle, buf, len,
986 WMI_GTK_OFFLOAD_CMDID)) {
987 wmi_err("Failed to send WMI_GTK_OFFLOAD_CMDID for req info");
988 wmi_buf_free(buf);
989 status = QDF_STATUS_E_FAILURE;
990 }
991
992 out:
993 return status;
994 }
995
996 /**
997 * send_enable_enhance_multicast_offload_tlv() - send enhance multicast offload
998 * @wmi_handle: wmi handle
999 * @vdev_id: vdev id
1000 * @action: true for enable else false
1001 *
1002 * To enable enhance multicast offload to firmware
1003 * when target goes to wow mode.
1004 *
1005 * Return: QDF Status
1006 */
1007
1008 static
send_enable_enhance_multicast_offload_tlv(wmi_unified_t wmi_handle,uint8_t vdev_id,bool action)1009 QDF_STATUS send_enable_enhance_multicast_offload_tlv(
1010 wmi_unified_t wmi_handle,
1011 uint8_t vdev_id, bool action)
1012 {
1013 QDF_STATUS status;
1014 wmi_buf_t buf;
1015 wmi_config_enhanced_mcast_filter_cmd_fixed_param *cmd;
1016
1017 buf = wmi_buf_alloc(wmi_handle, sizeof(*cmd));
1018 if (!buf) {
1019 return QDF_STATUS_E_NOMEM;
1020 }
1021
1022 cmd = (wmi_config_enhanced_mcast_filter_cmd_fixed_param *)
1023 wmi_buf_data(buf);
1024
1025 WMITLV_SET_HDR(&cmd->tlv_header,
1026 WMITLV_TAG_STRUC_wmi_config_enhanced_mcast_filter_fixed_param,
1027 WMITLV_GET_STRUCT_TLVLEN(
1028 wmi_config_enhanced_mcast_filter_cmd_fixed_param));
1029
1030 cmd->vdev_id = vdev_id;
1031 cmd->enable = ((action == 0) ? ENHANCED_MCAST_FILTER_DISABLED :
1032 ENHANCED_MCAST_FILTER_ENABLED);
1033 wmi_debug("config enhance multicast offload action %d for vdev %d",
1034 action, vdev_id);
1035 wmi_mtrace(WMI_CONFIG_ENHANCED_MCAST_FILTER_CMDID, cmd->vdev_id, 0);
1036 status = wmi_unified_cmd_send(wmi_handle, buf,
1037 sizeof(*cmd), WMI_CONFIG_ENHANCED_MCAST_FILTER_CMDID);
1038 if (status != QDF_STATUS_SUCCESS) {
1039 wmi_buf_free(buf);
1040 wmi_err("Failed to send ENHANCED_MCAST_FILTER_CMDID");
1041 }
1042
1043 return status;
1044 }
1045
1046 /**
1047 * extract_gtk_rsp_event_tlv() - extract gtk rsp params from event
1048 * @wmi_handle: wmi handle
1049 * @evt_buf: pointer to event buffer
1050 * @gtk_rsp_param: Pointer to extraction buffer
1051 * @len: length of the @evt_buf event buffer
1052 *
1053 * Return: QDF_STATUS_SUCCESS for success or error code
1054 */
extract_gtk_rsp_event_tlv(wmi_unified_t wmi_handle,void * evt_buf,struct pmo_gtk_rsp_params * gtk_rsp_param,uint32_t len)1055 static QDF_STATUS extract_gtk_rsp_event_tlv(wmi_unified_t wmi_handle,
1056 void *evt_buf, struct pmo_gtk_rsp_params *gtk_rsp_param, uint32_t len)
1057 {
1058 WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param *fixed_param;
1059 WMI_GTK_OFFLOAD_STATUS_EVENTID_param_tlvs *param_buf;
1060
1061 param_buf = (WMI_GTK_OFFLOAD_STATUS_EVENTID_param_tlvs *)evt_buf;
1062 if (!param_buf) {
1063 wmi_err("gtk param_buf is NULL");
1064 return QDF_STATUS_E_INVAL;
1065 }
1066
1067 if (len < sizeof(WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param)) {
1068 wmi_err("Invalid length for GTK status");
1069 return QDF_STATUS_E_INVAL;
1070 }
1071
1072 fixed_param = (WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param *)
1073 param_buf->fixed_param;
1074
1075 if (fixed_param->vdev_id >= WLAN_UMAC_PSOC_MAX_VDEVS) {
1076 wmi_err_rl("Invalid vdev_id %u", fixed_param->vdev_id);
1077 return QDF_STATUS_E_INVAL;
1078 }
1079
1080 gtk_rsp_param->vdev_id = fixed_param->vdev_id;
1081 gtk_rsp_param->status_flag = QDF_STATUS_SUCCESS;
1082 gtk_rsp_param->refresh_cnt = fixed_param->refresh_cnt;
1083 qdf_mem_copy(>k_rsp_param->replay_counter,
1084 &fixed_param->replay_counter,
1085 GTK_REPLAY_COUNTER_BYTES);
1086
1087 return QDF_STATUS_SUCCESS;
1088
1089 }
1090
1091 #ifdef FEATURE_WLAN_RA_FILTERING
1092 /**
1093 * send_wow_sta_ra_filter_cmd_tlv() - set RA filter pattern in fw
1094 * @wmi_handle: wmi handle
1095 * @vdev_id: vdev id
1096 * @default_pattern: default pattern
1097 * @rate_limit_interval: ra packets interval
1098 *
1099 * Return: QDF status
1100 */
send_wow_sta_ra_filter_cmd_tlv(wmi_unified_t wmi_handle,uint8_t vdev_id,uint8_t default_pattern,uint16_t rate_limit_interval)1101 static QDF_STATUS send_wow_sta_ra_filter_cmd_tlv(wmi_unified_t wmi_handle,
1102 uint8_t vdev_id,
1103 uint8_t default_pattern,
1104 uint16_t rate_limit_interval)
1105 {
1106
1107 WMI_WOW_ADD_PATTERN_CMD_fixed_param *cmd;
1108 wmi_buf_t buf;
1109 uint8_t *buf_ptr;
1110 int32_t len;
1111 int ret;
1112
1113 len = sizeof(WMI_WOW_ADD_PATTERN_CMD_fixed_param) +
1114 WMI_TLV_HDR_SIZE +
1115 0 * sizeof(WOW_BITMAP_PATTERN_T) +
1116 WMI_TLV_HDR_SIZE +
1117 0 * sizeof(WOW_IPV4_SYNC_PATTERN_T) +
1118 WMI_TLV_HDR_SIZE +
1119 0 * sizeof(WOW_IPV6_SYNC_PATTERN_T) +
1120 WMI_TLV_HDR_SIZE +
1121 0 * sizeof(WOW_MAGIC_PATTERN_CMD) +
1122 WMI_TLV_HDR_SIZE +
1123 0 * sizeof(uint32_t) + WMI_TLV_HDR_SIZE + 1 * sizeof(uint32_t);
1124
1125 buf = wmi_buf_alloc(wmi_handle, len);
1126 if (!buf) {
1127 return QDF_STATUS_E_NOMEM;
1128 }
1129
1130 cmd = (WMI_WOW_ADD_PATTERN_CMD_fixed_param *) wmi_buf_data(buf);
1131 buf_ptr = (uint8_t *) cmd;
1132
1133 WMITLV_SET_HDR(&cmd->tlv_header,
1134 WMITLV_TAG_STRUC_WMI_WOW_ADD_PATTERN_CMD_fixed_param,
1135 WMITLV_GET_STRUCT_TLVLEN
1136 (WMI_WOW_ADD_PATTERN_CMD_fixed_param));
1137 cmd->vdev_id = vdev_id;
1138 cmd->pattern_id = default_pattern,
1139 cmd->pattern_type = WOW_IPV6_RA_PATTERN;
1140 buf_ptr += sizeof(WMI_WOW_ADD_PATTERN_CMD_fixed_param);
1141
1142 /* Fill TLV for WMITLV_TAG_STRUC_WOW_BITMAP_PATTERN_T but no data. */
1143 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
1144 buf_ptr += WMI_TLV_HDR_SIZE;
1145
1146 /* Fill TLV for WMITLV_TAG_STRUC_WOW_IPV4_SYNC_PATTERN_T but no data. */
1147 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
1148 buf_ptr += WMI_TLV_HDR_SIZE;
1149
1150 /* Fill TLV for WMITLV_TAG_STRUC_WOW_IPV6_SYNC_PATTERN_T but no data. */
1151 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
1152 buf_ptr += WMI_TLV_HDR_SIZE;
1153
1154 /* Fill TLV for WMITLV_TAG_STRUC_WOW_MAGIC_PATTERN_CMD but no data. */
1155 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
1156 buf_ptr += WMI_TLV_HDR_SIZE;
1157
1158 /* Fill TLV for pattern_info_timeout but no data. */
1159 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, 0);
1160 buf_ptr += WMI_TLV_HDR_SIZE;
1161
1162 /* Fill TLV for ra_ratelimit_interval. */
1163 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, sizeof(uint32_t));
1164 buf_ptr += WMI_TLV_HDR_SIZE;
1165
1166 *((uint32_t *) buf_ptr) = rate_limit_interval;
1167
1168 wmi_debug("send RA rate limit [%d] to fw vdev = %d",
1169 rate_limit_interval, vdev_id);
1170
1171 wmi_mtrace(WMI_WOW_ADD_WAKE_PATTERN_CMDID, cmd->vdev_id, 0);
1172 ret = wmi_unified_cmd_send(wmi_handle, buf, len,
1173 WMI_WOW_ADD_WAKE_PATTERN_CMDID);
1174 if (ret) {
1175 wmi_err("Failed to send RA rate limit to fw");
1176 wmi_buf_free(buf);
1177 return QDF_STATUS_E_FAILURE;
1178 }
1179
1180 return QDF_STATUS_SUCCESS;
1181 }
1182
wmi_ra_filtering_attach_tlv(struct wmi_unified * wmi_handle)1183 void wmi_ra_filtering_attach_tlv(struct wmi_unified *wmi_handle)
1184 {
1185 struct wmi_ops *ops = wmi_handle->ops;
1186
1187 ops->send_wow_sta_ra_filter_cmd = send_wow_sta_ra_filter_cmd_tlv;
1188 }
1189 #endif /* FEATURE_WLAN_RA_FILTERING */
1190
1191 /**
1192 * send_action_frame_patterns_cmd_tlv() - send wmi cmd of action filter params
1193 * @wmi_handle: wmi handler
1194 * @action_params: pointer to action_params
1195 *
1196 * Return: 0 for success, otherwise appropriate error code
1197 */
send_action_frame_patterns_cmd_tlv(wmi_unified_t wmi_handle,struct pmo_action_wakeup_set_params * action_params)1198 static QDF_STATUS send_action_frame_patterns_cmd_tlv(wmi_unified_t wmi_handle,
1199 struct pmo_action_wakeup_set_params *action_params)
1200 {
1201 WMI_WOW_SET_ACTION_WAKE_UP_CMD_fixed_param *cmd;
1202 wmi_buf_t buf;
1203 int i;
1204 int32_t err;
1205 uint32_t len = 0, *cmd_args;
1206 uint8_t *buf_ptr;
1207
1208 len = (PMO_SUPPORTED_ACTION_CATE * sizeof(uint32_t))
1209 + WMI_TLV_HDR_SIZE + sizeof(*cmd);
1210 buf = wmi_buf_alloc(wmi_handle, len);
1211 if (!buf) {
1212 return QDF_STATUS_E_NOMEM;
1213 }
1214 cmd = (WMI_WOW_SET_ACTION_WAKE_UP_CMD_fixed_param *) wmi_buf_data(buf);
1215 buf_ptr = (uint8_t *)cmd;
1216 WMITLV_SET_HDR(&cmd->tlv_header,
1217 WMITLV_TAG_STRUC_wmi_wow_set_action_wake_up_cmd_fixed_param,
1218 WMITLV_GET_STRUCT_TLVLEN(
1219 WMI_WOW_SET_ACTION_WAKE_UP_CMD_fixed_param));
1220
1221 cmd->vdev_id = action_params->vdev_id;
1222 cmd->operation = action_params->operation;
1223
1224 for (i = 0; i < MAX_SUPPORTED_ACTION_CATEGORY_ELE_LIST; i++)
1225 cmd->action_category_map[i] =
1226 action_params->action_category_map[i];
1227
1228 buf_ptr += sizeof(WMI_WOW_SET_ACTION_WAKE_UP_CMD_fixed_param);
1229 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32,
1230 (PMO_SUPPORTED_ACTION_CATE * sizeof(uint32_t)));
1231 buf_ptr += WMI_TLV_HDR_SIZE;
1232 cmd_args = (uint32_t *) buf_ptr;
1233 for (i = 0; i < PMO_SUPPORTED_ACTION_CATE; i++)
1234 cmd_args[i] = action_params->action_per_category[i];
1235
1236 wmi_mtrace(WMI_WOW_SET_ACTION_WAKE_UP_CMDID, cmd->vdev_id, 0);
1237 err = wmi_unified_cmd_send(wmi_handle, buf,
1238 len, WMI_WOW_SET_ACTION_WAKE_UP_CMDID);
1239 if (err) {
1240 wmi_err("Failed to send ap_ps_egap cmd");
1241 wmi_buf_free(buf);
1242 return QDF_STATUS_E_FAILURE;
1243 }
1244
1245 return QDF_STATUS_SUCCESS;
1246 }
1247
1248 #ifdef FEATURE_WLAN_LPHB
1249 /**
1250 * send_lphb_config_hbenable_cmd_tlv() - enable command of LPHB configuration
1251 * @wmi_handle: wmi handle
1252 * @params: LPHB configuration info
1253 *
1254 * Return: QDF status
1255 */
send_lphb_config_hbenable_cmd_tlv(wmi_unified_t wmi_handle,wmi_hb_set_enable_cmd_fixed_param * params)1256 static QDF_STATUS send_lphb_config_hbenable_cmd_tlv(wmi_unified_t wmi_handle,
1257 wmi_hb_set_enable_cmd_fixed_param *params)
1258 {
1259 QDF_STATUS status;
1260 wmi_buf_t buf = NULL;
1261 uint8_t *buf_ptr;
1262 wmi_hb_set_enable_cmd_fixed_param *hb_enable_fp;
1263 int len = sizeof(wmi_hb_set_enable_cmd_fixed_param);
1264
1265 buf = wmi_buf_alloc(wmi_handle, len);
1266 if (!buf) {
1267 return QDF_STATUS_E_NOMEM;
1268 }
1269
1270 buf_ptr = (uint8_t *) wmi_buf_data(buf);
1271 hb_enable_fp = (wmi_hb_set_enable_cmd_fixed_param *) buf_ptr;
1272 WMITLV_SET_HDR(&hb_enable_fp->tlv_header,
1273 WMITLV_TAG_STRUC_wmi_hb_set_enable_cmd_fixed_param,
1274 WMITLV_GET_STRUCT_TLVLEN
1275 (wmi_hb_set_enable_cmd_fixed_param));
1276
1277 /* fill in values */
1278 hb_enable_fp->vdev_id = params->session;
1279 hb_enable_fp->enable = params->enable;
1280 hb_enable_fp->item = params->item;
1281 hb_enable_fp->session = params->session;
1282
1283 wmi_mtrace(WMI_HB_SET_ENABLE_CMDID, NO_SESSION, 0);
1284 status = wmi_unified_cmd_send(wmi_handle, buf,
1285 len, WMI_HB_SET_ENABLE_CMDID);
1286 if (QDF_IS_STATUS_ERROR(status)) {
1287 wmi_err("cmd_send WMI_HB_SET_ENABLE returned Error %d",
1288 status);
1289 wmi_buf_free(buf);
1290 }
1291
1292 return status;
1293 }
1294
1295 /**
1296 * send_lphb_config_tcp_params_cmd_tlv() - set tcp params of LPHB configuration
1297 * @wmi_handle: wmi handle
1298 * @lphb_conf_req: lphb config request
1299 *
1300 * Return: QDF status
1301 */
send_lphb_config_tcp_params_cmd_tlv(wmi_unified_t wmi_handle,wmi_hb_set_tcp_params_cmd_fixed_param * lphb_conf_req)1302 static QDF_STATUS send_lphb_config_tcp_params_cmd_tlv(wmi_unified_t wmi_handle,
1303 wmi_hb_set_tcp_params_cmd_fixed_param *lphb_conf_req)
1304 {
1305 QDF_STATUS status;
1306 wmi_buf_t buf = NULL;
1307 uint8_t *buf_ptr;
1308 wmi_hb_set_tcp_params_cmd_fixed_param *hb_tcp_params_fp;
1309 int len = sizeof(wmi_hb_set_tcp_params_cmd_fixed_param);
1310
1311 buf = wmi_buf_alloc(wmi_handle, len);
1312 if (!buf) {
1313 return QDF_STATUS_E_NOMEM;
1314 }
1315
1316 buf_ptr = (uint8_t *) wmi_buf_data(buf);
1317 hb_tcp_params_fp = (wmi_hb_set_tcp_params_cmd_fixed_param *) buf_ptr;
1318 WMITLV_SET_HDR(&hb_tcp_params_fp->tlv_header,
1319 WMITLV_TAG_STRUC_wmi_hb_set_tcp_params_cmd_fixed_param,
1320 WMITLV_GET_STRUCT_TLVLEN
1321 (wmi_hb_set_tcp_params_cmd_fixed_param));
1322
1323 /* fill in values */
1324 hb_tcp_params_fp->vdev_id = lphb_conf_req->vdev_id;
1325 hb_tcp_params_fp->srv_ip = lphb_conf_req->srv_ip;
1326 hb_tcp_params_fp->dev_ip = lphb_conf_req->dev_ip;
1327 hb_tcp_params_fp->seq = lphb_conf_req->seq;
1328 hb_tcp_params_fp->src_port = lphb_conf_req->src_port;
1329 hb_tcp_params_fp->dst_port = lphb_conf_req->dst_port;
1330 hb_tcp_params_fp->interval = lphb_conf_req->interval;
1331 hb_tcp_params_fp->timeout = lphb_conf_req->timeout;
1332 hb_tcp_params_fp->session = lphb_conf_req->session;
1333 qdf_mem_copy(&hb_tcp_params_fp->gateway_mac,
1334 &lphb_conf_req->gateway_mac,
1335 sizeof(hb_tcp_params_fp->gateway_mac));
1336
1337 wmi_mtrace(WMI_HB_SET_TCP_PARAMS_CMDID, NO_SESSION, 0);
1338 status = wmi_unified_cmd_send(wmi_handle, buf,
1339 len, WMI_HB_SET_TCP_PARAMS_CMDID);
1340 if (QDF_IS_STATUS_ERROR(status)) {
1341 wmi_err("cmd_send WMI_HB_SET_TCP_PARAMS returned Error %d",
1342 status);
1343 wmi_buf_free(buf);
1344 }
1345
1346 return status;
1347 }
1348
1349 /**
1350 * send_lphb_config_tcp_pkt_filter_cmd_tlv() - configure tcp packet filter cmd
1351 * @wmi_handle: wmi handle
1352 * @g_hb_tcp_filter_fp: tcp packet filter params
1353 *
1354 * Return: QDF status
1355 */
1356 static
send_lphb_config_tcp_pkt_filter_cmd_tlv(wmi_unified_t wmi_handle,wmi_hb_set_tcp_pkt_filter_cmd_fixed_param * g_hb_tcp_filter_fp)1357 QDF_STATUS send_lphb_config_tcp_pkt_filter_cmd_tlv(wmi_unified_t wmi_handle,
1358 wmi_hb_set_tcp_pkt_filter_cmd_fixed_param *g_hb_tcp_filter_fp)
1359 {
1360 QDF_STATUS status;
1361 wmi_buf_t buf = NULL;
1362 uint8_t *buf_ptr;
1363 wmi_hb_set_tcp_pkt_filter_cmd_fixed_param *hb_tcp_filter_fp;
1364 int len = sizeof(wmi_hb_set_tcp_pkt_filter_cmd_fixed_param);
1365
1366 buf = wmi_buf_alloc(wmi_handle, len);
1367 if (!buf) {
1368 return QDF_STATUS_E_NOMEM;
1369 }
1370
1371 buf_ptr = (uint8_t *) wmi_buf_data(buf);
1372 hb_tcp_filter_fp =
1373 (wmi_hb_set_tcp_pkt_filter_cmd_fixed_param *) buf_ptr;
1374 WMITLV_SET_HDR(&hb_tcp_filter_fp->tlv_header,
1375 WMITLV_TAG_STRUC_wmi_hb_set_tcp_pkt_filter_cmd_fixed_param,
1376 WMITLV_GET_STRUCT_TLVLEN
1377 (wmi_hb_set_tcp_pkt_filter_cmd_fixed_param));
1378
1379 /* fill in values */
1380 hb_tcp_filter_fp->vdev_id = g_hb_tcp_filter_fp->vdev_id;
1381 hb_tcp_filter_fp->length = g_hb_tcp_filter_fp->length;
1382 hb_tcp_filter_fp->offset = g_hb_tcp_filter_fp->offset;
1383 hb_tcp_filter_fp->session = g_hb_tcp_filter_fp->session;
1384 memcpy((void *)&hb_tcp_filter_fp->filter,
1385 (void *)&g_hb_tcp_filter_fp->filter,
1386 WMI_WLAN_HB_MAX_FILTER_SIZE);
1387
1388 wmi_mtrace(WMI_HB_SET_TCP_PKT_FILTER_CMDID, NO_SESSION, 0);
1389 status = wmi_unified_cmd_send(wmi_handle, buf,
1390 len, WMI_HB_SET_TCP_PKT_FILTER_CMDID);
1391 if (QDF_IS_STATUS_ERROR(status)) {
1392 wmi_err("cmd_send WMI_HB_SET_TCP_PKT_FILTER returned Error %d",
1393 status);
1394 wmi_buf_free(buf);
1395 }
1396
1397 return status;
1398 }
1399
1400 /**
1401 * send_lphb_config_udp_params_cmd_tlv() - configure udp param command of LPHB
1402 * @wmi_handle: wmi handle
1403 * @lphb_conf_req: lphb config request
1404 *
1405 * Return: QDF status
1406 */
send_lphb_config_udp_params_cmd_tlv(wmi_unified_t wmi_handle,wmi_hb_set_udp_params_cmd_fixed_param * lphb_conf_req)1407 static QDF_STATUS send_lphb_config_udp_params_cmd_tlv(wmi_unified_t wmi_handle,
1408 wmi_hb_set_udp_params_cmd_fixed_param *lphb_conf_req)
1409 {
1410 QDF_STATUS status;
1411 wmi_buf_t buf = NULL;
1412 uint8_t *buf_ptr;
1413 wmi_hb_set_udp_params_cmd_fixed_param *hb_udp_params_fp;
1414 int len = sizeof(wmi_hb_set_udp_params_cmd_fixed_param);
1415
1416 buf = wmi_buf_alloc(wmi_handle, len);
1417 if (!buf) {
1418 return QDF_STATUS_E_NOMEM;
1419 }
1420
1421 buf_ptr = (uint8_t *) wmi_buf_data(buf);
1422 hb_udp_params_fp = (wmi_hb_set_udp_params_cmd_fixed_param *) buf_ptr;
1423 WMITLV_SET_HDR(&hb_udp_params_fp->tlv_header,
1424 WMITLV_TAG_STRUC_wmi_hb_set_udp_params_cmd_fixed_param,
1425 WMITLV_GET_STRUCT_TLVLEN
1426 (wmi_hb_set_udp_params_cmd_fixed_param));
1427
1428 /* fill in values */
1429 hb_udp_params_fp->vdev_id = lphb_conf_req->vdev_id;
1430 hb_udp_params_fp->srv_ip = lphb_conf_req->srv_ip;
1431 hb_udp_params_fp->dev_ip = lphb_conf_req->dev_ip;
1432 hb_udp_params_fp->src_port = lphb_conf_req->src_port;
1433 hb_udp_params_fp->dst_port = lphb_conf_req->dst_port;
1434 hb_udp_params_fp->interval = lphb_conf_req->interval;
1435 hb_udp_params_fp->timeout = lphb_conf_req->timeout;
1436 hb_udp_params_fp->session = lphb_conf_req->session;
1437 qdf_mem_copy(&hb_udp_params_fp->gateway_mac,
1438 &lphb_conf_req->gateway_mac,
1439 sizeof(lphb_conf_req->gateway_mac));
1440
1441 wmi_mtrace(WMI_HB_SET_UDP_PARAMS_CMDID, NO_SESSION, 0);
1442 status = wmi_unified_cmd_send(wmi_handle, buf,
1443 len, WMI_HB_SET_UDP_PARAMS_CMDID);
1444 if (QDF_IS_STATUS_ERROR(status)) {
1445 wmi_err("cmd_send WMI_HB_SET_UDP_PARAMS returned Error %d",
1446 status);
1447 wmi_buf_free(buf);
1448 }
1449
1450 return status;
1451 }
1452
1453 /**
1454 * send_lphb_config_udp_pkt_filter_cmd_tlv() - configure udp pkt filter command
1455 * @wmi_handle: wmi handle
1456 * @lphb_conf_req: lphb config request
1457 *
1458 * Return: QDF status
1459 */
1460 static
send_lphb_config_udp_pkt_filter_cmd_tlv(wmi_unified_t wmi_handle,wmi_hb_set_udp_pkt_filter_cmd_fixed_param * lphb_conf_req)1461 QDF_STATUS send_lphb_config_udp_pkt_filter_cmd_tlv(wmi_unified_t wmi_handle,
1462 wmi_hb_set_udp_pkt_filter_cmd_fixed_param *lphb_conf_req)
1463 {
1464 QDF_STATUS status;
1465 wmi_buf_t buf = NULL;
1466 uint8_t *buf_ptr;
1467 wmi_hb_set_udp_pkt_filter_cmd_fixed_param *hb_udp_filter_fp;
1468 int len = sizeof(wmi_hb_set_udp_pkt_filter_cmd_fixed_param);
1469
1470 buf = wmi_buf_alloc(wmi_handle, len);
1471 if (!buf) {
1472 return QDF_STATUS_E_NOMEM;
1473 }
1474
1475 buf_ptr = (uint8_t *) wmi_buf_data(buf);
1476 hb_udp_filter_fp =
1477 (wmi_hb_set_udp_pkt_filter_cmd_fixed_param *) buf_ptr;
1478 WMITLV_SET_HDR(&hb_udp_filter_fp->tlv_header,
1479 WMITLV_TAG_STRUC_wmi_hb_set_udp_pkt_filter_cmd_fixed_param,
1480 WMITLV_GET_STRUCT_TLVLEN
1481 (wmi_hb_set_udp_pkt_filter_cmd_fixed_param));
1482
1483 /* fill in values */
1484 hb_udp_filter_fp->vdev_id = lphb_conf_req->vdev_id;
1485 hb_udp_filter_fp->length = lphb_conf_req->length;
1486 hb_udp_filter_fp->offset = lphb_conf_req->offset;
1487 hb_udp_filter_fp->session = lphb_conf_req->session;
1488 memcpy((void *)&hb_udp_filter_fp->filter,
1489 (void *)&lphb_conf_req->filter,
1490 WMI_WLAN_HB_MAX_FILTER_SIZE);
1491
1492 wmi_mtrace(WMI_HB_SET_UDP_PKT_FILTER_CMDID, NO_SESSION, 0);
1493 status = wmi_unified_cmd_send(wmi_handle, buf,
1494 len, WMI_HB_SET_UDP_PKT_FILTER_CMDID);
1495 if (QDF_IS_STATUS_ERROR(status)) {
1496 wmi_err("cmd_send WMI_HB_SET_UDP_PKT_FILTER returned Error %d",
1497 status);
1498 wmi_buf_free(buf);
1499 }
1500
1501 return status;
1502 }
1503
wmi_lphb_attach_tlv(struct wmi_unified * wmi_handle)1504 void wmi_lphb_attach_tlv(struct wmi_unified *wmi_handle)
1505 {
1506 struct wmi_ops *ops = wmi_handle->ops;
1507
1508 ops->send_lphb_config_hbenable_cmd =
1509 send_lphb_config_hbenable_cmd_tlv;
1510 ops->send_lphb_config_tcp_params_cmd =
1511 send_lphb_config_tcp_params_cmd_tlv;
1512 ops->send_lphb_config_tcp_pkt_filter_cmd =
1513 send_lphb_config_tcp_pkt_filter_cmd_tlv;
1514 ops->send_lphb_config_udp_params_cmd =
1515 send_lphb_config_udp_params_cmd_tlv;
1516 ops->send_lphb_config_udp_pkt_filter_cmd =
1517 send_lphb_config_udp_pkt_filter_cmd_tlv;
1518 }
1519 #endif /* FEATURE_WLAN_LPHB */
1520
1521 #ifdef WLAN_FEATURE_PACKET_FILTERING
1522 /**
1523 * send_enable_disable_packet_filter_cmd_tlv() - enable/disable packet filter
1524 * @wmi_handle: wmi handle
1525 * @vdev_id: vdev id
1526 * @enable: Flag to enable/disable packet filter
1527 *
1528 * Return: QDF_STATUS_SUCCESS for success or error code
1529 */
send_enable_disable_packet_filter_cmd_tlv(wmi_unified_t wmi_handle,uint8_t vdev_id,bool enable)1530 static QDF_STATUS send_enable_disable_packet_filter_cmd_tlv(
1531 wmi_unified_t wmi_handle, uint8_t vdev_id, bool enable)
1532 {
1533 int32_t len;
1534 int ret = 0;
1535 wmi_buf_t buf;
1536 WMI_PACKET_FILTER_ENABLE_CMD_fixed_param *cmd;
1537
1538 len = sizeof(WMI_PACKET_FILTER_ENABLE_CMD_fixed_param);
1539
1540 buf = wmi_buf_alloc(wmi_handle, len);
1541 if (!buf) {
1542 return QDF_STATUS_E_NOMEM;
1543 }
1544
1545 cmd = (WMI_PACKET_FILTER_ENABLE_CMD_fixed_param *) wmi_buf_data(buf);
1546 WMITLV_SET_HDR(&cmd->tlv_header,
1547 WMITLV_TAG_STRUC_wmi_packet_filter_enable_fixed_param,
1548 WMITLV_GET_STRUCT_TLVLEN(
1549 WMI_PACKET_FILTER_ENABLE_CMD_fixed_param));
1550
1551 cmd->vdev_id = vdev_id;
1552 if (enable)
1553 cmd->enable = PACKET_FILTER_SET_ENABLE;
1554 else
1555 cmd->enable = PACKET_FILTER_SET_DISABLE;
1556
1557 wmi_err("Packet filter enable %d for vdev_id %d", cmd->enable, vdev_id);
1558
1559 wmi_mtrace(WMI_PACKET_FILTER_ENABLE_CMDID, cmd->vdev_id, 0);
1560 ret = wmi_unified_cmd_send(wmi_handle, buf, len,
1561 WMI_PACKET_FILTER_ENABLE_CMDID);
1562 if (ret) {
1563 wmi_err("Failed to send packet filter wmi cmd to fw");
1564 wmi_buf_free(buf);
1565 }
1566
1567 return ret;
1568 }
1569
1570 /**
1571 * send_config_packet_filter_cmd_tlv() - configure packet filter in target
1572 * @wmi_handle: wmi handle
1573 * @vdev_id: vdev id
1574 * @rcv_filter_param: Packet filter parameters
1575 * @filter_id: Filter id
1576 * @enable: Flag to add/delete packet filter configuration
1577 *
1578 * Return: QDF_STATUS_SUCCESS for success or error code
1579 */
send_config_packet_filter_cmd_tlv(wmi_unified_t wmi_handle,uint8_t vdev_id,struct pmo_rcv_pkt_fltr_cfg * rcv_filter_param,uint8_t filter_id,bool enable)1580 static QDF_STATUS send_config_packet_filter_cmd_tlv(wmi_unified_t wmi_handle,
1581 uint8_t vdev_id, struct pmo_rcv_pkt_fltr_cfg *rcv_filter_param,
1582 uint8_t filter_id, bool enable)
1583 {
1584 int len, i;
1585 int err = 0;
1586 wmi_buf_t buf;
1587 WMI_PACKET_FILTER_CONFIG_CMD_fixed_param *cmd;
1588
1589 /* allocate the memory */
1590 len = sizeof(*cmd);
1591 buf = wmi_buf_alloc(wmi_handle, len);
1592 if (!buf) {
1593 return QDF_STATUS_E_NOMEM;
1594 }
1595
1596 cmd = (WMI_PACKET_FILTER_CONFIG_CMD_fixed_param *)wmi_buf_data(buf);
1597 WMITLV_SET_HDR(&cmd->tlv_header,
1598 WMITLV_TAG_STRUC_wmi_packet_filter_config_fixed_param,
1599 WMITLV_GET_STRUCT_TLVLEN
1600 (WMI_PACKET_FILTER_CONFIG_CMD_fixed_param));
1601
1602 cmd->vdev_id = vdev_id;
1603 cmd->filter_id = filter_id;
1604 if (enable)
1605 cmd->filter_action = PACKET_FILTER_SET_ACTIVE;
1606 else
1607 cmd->filter_action = PACKET_FILTER_SET_INACTIVE;
1608
1609 if (enable) {
1610 cmd->num_params = QDF_MIN(
1611 WMI_PACKET_FILTER_MAX_CMP_PER_PACKET_FILTER,
1612 rcv_filter_param->num_params);
1613 cmd->filter_type = rcv_filter_param->filter_type;
1614 cmd->coalesce_time = rcv_filter_param->coalesce_time;
1615
1616 for (i = 0; i < cmd->num_params; i++) {
1617 cmd->paramsData[i].proto_type =
1618 rcv_filter_param->params_data[i].protocol_layer;
1619 cmd->paramsData[i].cmp_type =
1620 rcv_filter_param->params_data[i].compare_flag;
1621 cmd->paramsData[i].data_length =
1622 rcv_filter_param->params_data[i].data_length;
1623 cmd->paramsData[i].data_offset =
1624 rcv_filter_param->params_data[i].data_offset;
1625 memcpy(&cmd->paramsData[i].compareData,
1626 rcv_filter_param->params_data[i].compare_data,
1627 sizeof(cmd->paramsData[i].compareData));
1628 memcpy(&cmd->paramsData[i].dataMask,
1629 rcv_filter_param->params_data[i].data_mask,
1630 sizeof(cmd->paramsData[i].dataMask));
1631 }
1632 }
1633
1634 wmi_err("Packet filter action %d filter with id: %d, num_params=%d",
1635 cmd->filter_action, cmd->filter_id, cmd->num_params);
1636 /* send the command along with data */
1637 wmi_mtrace(WMI_PACKET_FILTER_CONFIG_CMDID, cmd->vdev_id, 0);
1638 err = wmi_unified_cmd_send(wmi_handle, buf, len,
1639 WMI_PACKET_FILTER_CONFIG_CMDID);
1640 if (err) {
1641 wmi_err("Failed to send pkt_filter cmd");
1642 wmi_buf_free(buf);
1643 return QDF_STATUS_E_FAILURE;
1644 }
1645
1646 return QDF_STATUS_SUCCESS;
1647 }
1648
wmi_packet_filtering_attach_tlv(struct wmi_unified * wmi_handle)1649 void wmi_packet_filtering_attach_tlv(struct wmi_unified *wmi_handle)
1650 {
1651 struct wmi_ops *ops = wmi_handle->ops;
1652
1653 ops->send_enable_disable_packet_filter_cmd =
1654 send_enable_disable_packet_filter_cmd_tlv;
1655 ops->send_config_packet_filter_cmd =
1656 send_config_packet_filter_cmd_tlv;
1657 }
1658 #endif /* WLAN_FEATURE_PACKET_FILTERING */
1659
1660 /**
1661 * send_wow_delete_pattern_cmd_tlv() - delete wow pattern in target
1662 * @wmi_handle: wmi handle
1663 * @ptrn_id: pattern id
1664 * @vdev_id: vdev id
1665 *
1666 * Return: QDF status
1667 */
send_wow_delete_pattern_cmd_tlv(wmi_unified_t wmi_handle,uint8_t ptrn_id,uint8_t vdev_id)1668 static QDF_STATUS send_wow_delete_pattern_cmd_tlv(wmi_unified_t wmi_handle,
1669 uint8_t ptrn_id,
1670 uint8_t vdev_id)
1671 {
1672 WMI_WOW_DEL_PATTERN_CMD_fixed_param *cmd;
1673 wmi_buf_t buf;
1674 int32_t len;
1675 int ret;
1676
1677 len = sizeof(WMI_WOW_DEL_PATTERN_CMD_fixed_param);
1678
1679 buf = wmi_buf_alloc(wmi_handle, len);
1680 if (!buf) {
1681 return QDF_STATUS_E_NOMEM;
1682 }
1683
1684 cmd = (WMI_WOW_DEL_PATTERN_CMD_fixed_param *) wmi_buf_data(buf);
1685
1686 WMITLV_SET_HDR(&cmd->tlv_header,
1687 WMITLV_TAG_STRUC_WMI_WOW_DEL_PATTERN_CMD_fixed_param,
1688 WMITLV_GET_STRUCT_TLVLEN(
1689 WMI_WOW_DEL_PATTERN_CMD_fixed_param));
1690 cmd->vdev_id = vdev_id;
1691 cmd->pattern_id = ptrn_id;
1692 cmd->pattern_type = WOW_BITMAP_PATTERN;
1693
1694 wmi_mtrace(WMI_WOW_DEL_WAKE_PATTERN_CMDID, cmd->vdev_id, 0);
1695 ret = wmi_unified_cmd_send(wmi_handle, buf, len,
1696 WMI_WOW_DEL_WAKE_PATTERN_CMDID);
1697 if (ret) {
1698 wmi_err("Failed to delete wow ptrn from fw");
1699 wmi_buf_free(buf);
1700 return QDF_STATUS_E_FAILURE;
1701 }
1702
1703 return QDF_STATUS_SUCCESS;
1704 }
1705
1706 #ifdef WMI_HOST_WAKEUP_OVER_QMI
1707 static inline
wmi_unified_cmd_send_chk(struct wmi_unified * wmi_handle,wmi_buf_t buf,uint32_t buflen,uint32_t cmd_id)1708 QDF_STATUS wmi_unified_cmd_send_chk(struct wmi_unified *wmi_handle,
1709 wmi_buf_t buf,
1710 uint32_t buflen, uint32_t cmd_id)
1711 {
1712 wmi_debug("Send WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID over QMI");
1713 return wmi_unified_cmd_send_over_qmi(wmi_handle, buf,
1714 buflen, cmd_id);
1715 }
1716 #else
1717 static inline
wmi_unified_cmd_send_chk(struct wmi_unified * wmi_handle,wmi_buf_t buf,uint32_t buflen,uint32_t cmd_id)1718 QDF_STATUS wmi_unified_cmd_send_chk(struct wmi_unified *wmi_handle,
1719 wmi_buf_t buf,
1720 uint32_t buflen, uint32_t cmd_id)
1721 {
1722 return wmi_unified_cmd_send(wmi_handle, buf,
1723 buflen, cmd_id);
1724 }
1725 #endif
1726
1727 /**
1728 * send_host_wakeup_ind_to_fw_cmd_tlv() - send wakeup ind to fw
1729 * @wmi_handle: wmi handle
1730 * @tx_pending_ind: flag of TX has pending frames
1731 *
1732 * Sends host wakeup indication to FW. On receiving this indication,
1733 * FW will come out of WOW.
1734 *
1735 * Return: QDF status
1736 */
send_host_wakeup_ind_to_fw_cmd_tlv(wmi_unified_t wmi_handle,bool tx_pending_ind)1737 static QDF_STATUS send_host_wakeup_ind_to_fw_cmd_tlv(wmi_unified_t wmi_handle,
1738 bool tx_pending_ind)
1739 {
1740 wmi_wow_hostwakeup_from_sleep_cmd_fixed_param *cmd;
1741 wmi_buf_t buf;
1742 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
1743 int32_t len;
1744 int ret;
1745
1746 len = sizeof(wmi_wow_hostwakeup_from_sleep_cmd_fixed_param);
1747
1748 buf = wmi_buf_alloc(wmi_handle, len);
1749 if (!buf) {
1750 return QDF_STATUS_E_NOMEM;
1751 }
1752
1753 cmd = (wmi_wow_hostwakeup_from_sleep_cmd_fixed_param *)
1754 wmi_buf_data(buf);
1755
1756 if (tx_pending_ind) {
1757 wmi_debug("TX pending before WoW wake, indicate FW");
1758 cmd->flags |= WMI_WOW_RESUME_FLAG_TX_DATA;
1759 }
1760
1761 WMITLV_SET_HDR(&cmd->tlv_header,
1762 WMITLV_TAG_STRUC_wmi_wow_hostwakeup_from_sleep_cmd_fixed_param,
1763 WMITLV_GET_STRUCT_TLVLEN
1764 (wmi_wow_hostwakeup_from_sleep_cmd_fixed_param));
1765
1766 wmi_mtrace(WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID, NO_SESSION, 0);
1767 ret = wmi_unified_cmd_send_chk(wmi_handle, buf, len,
1768 WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID);
1769 if (ret) {
1770 wmi_err("Failed to send host wakeup indication to fw");
1771 wmi_buf_free(buf);
1772 return QDF_STATUS_E_FAILURE;
1773 }
1774
1775 return qdf_status;
1776 }
1777
1778 /**
1779 * send_wow_timer_pattern_cmd_tlv() - set timer pattern tlv, so that firmware
1780 * will wake up host after specified time is elapsed
1781 * @wmi_handle: wmi handle
1782 * @vdev_id: vdev id
1783 * @cookie: value to identify reason why host set up wake call.
1784 * @time: time in ms
1785 *
1786 * Return: QDF status
1787 */
send_wow_timer_pattern_cmd_tlv(wmi_unified_t wmi_handle,uint8_t vdev_id,uint32_t cookie,uint32_t time)1788 static QDF_STATUS send_wow_timer_pattern_cmd_tlv(wmi_unified_t wmi_handle,
1789 uint8_t vdev_id, uint32_t cookie, uint32_t time)
1790 {
1791 WMI_WOW_ADD_PATTERN_CMD_fixed_param *cmd;
1792 wmi_buf_t buf;
1793 uint8_t *buf_ptr;
1794 int32_t len;
1795 int ret;
1796
1797 len = sizeof(WMI_WOW_ADD_PATTERN_CMD_fixed_param) +
1798 WMI_TLV_HDR_SIZE + 0 * sizeof(WOW_BITMAP_PATTERN_T) +
1799 WMI_TLV_HDR_SIZE + 0 * sizeof(WOW_IPV4_SYNC_PATTERN_T) +
1800 WMI_TLV_HDR_SIZE + 0 * sizeof(WOW_IPV6_SYNC_PATTERN_T) +
1801 WMI_TLV_HDR_SIZE + 0 * sizeof(WOW_MAGIC_PATTERN_CMD) +
1802 WMI_TLV_HDR_SIZE + 1 * sizeof(uint32_t) +
1803 WMI_TLV_HDR_SIZE + 1 * sizeof(uint32_t);
1804
1805 buf = wmi_buf_alloc(wmi_handle, len);
1806 if (!buf) {
1807 return QDF_STATUS_E_NOMEM;
1808 }
1809
1810 cmd = (WMI_WOW_ADD_PATTERN_CMD_fixed_param *) wmi_buf_data(buf);
1811 buf_ptr = (uint8_t *) cmd;
1812
1813 WMITLV_SET_HDR(&cmd->tlv_header,
1814 WMITLV_TAG_STRUC_WMI_WOW_ADD_PATTERN_CMD_fixed_param,
1815 WMITLV_GET_STRUCT_TLVLEN
1816 (WMI_WOW_ADD_PATTERN_CMD_fixed_param));
1817 cmd->vdev_id = vdev_id;
1818 cmd->pattern_id = cookie,
1819 cmd->pattern_type = WOW_TIMER_PATTERN;
1820 buf_ptr += sizeof(WMI_WOW_ADD_PATTERN_CMD_fixed_param);
1821
1822 /* Fill TLV for WMITLV_TAG_STRUC_WOW_BITMAP_PATTERN_T but no data. */
1823 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
1824 buf_ptr += WMI_TLV_HDR_SIZE;
1825
1826 /* Fill TLV for WMITLV_TAG_STRUC_WOW_IPV4_SYNC_PATTERN_T but no data. */
1827 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
1828 buf_ptr += WMI_TLV_HDR_SIZE;
1829
1830 /* Fill TLV for WMITLV_TAG_STRUC_WOW_IPV6_SYNC_PATTERN_T but no data. */
1831 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
1832 buf_ptr += WMI_TLV_HDR_SIZE;
1833
1834 /* Fill TLV for WMITLV_TAG_STRUC_WOW_MAGIC_PATTERN_CMD but no data. */
1835 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0);
1836 buf_ptr += WMI_TLV_HDR_SIZE;
1837
1838 /* Fill TLV for pattern_info_timeout, and time value */
1839 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, sizeof(uint32_t));
1840 buf_ptr += WMI_TLV_HDR_SIZE;
1841 *((uint32_t *) buf_ptr) = time;
1842 buf_ptr += sizeof(uint32_t);
1843
1844 /* Fill TLV for ra_ratelimit_interval. with dummy 0 value */
1845 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, sizeof(uint32_t));
1846 buf_ptr += WMI_TLV_HDR_SIZE;
1847 *((uint32_t *) buf_ptr) = 0;
1848
1849 wmi_debug("send wake timer pattern with time[%d] to fw vdev = %d",
1850 time, vdev_id);
1851
1852 wmi_mtrace(WMI_WOW_ADD_WAKE_PATTERN_CMDID, cmd->vdev_id, 0);
1853 ret = wmi_unified_cmd_send(wmi_handle, buf, len,
1854 WMI_WOW_ADD_WAKE_PATTERN_CMDID);
1855 if (ret) {
1856 wmi_err("Failed to send wake timer pattern to fw");
1857 wmi_buf_free(buf);
1858 return QDF_STATUS_E_FAILURE;
1859 }
1860
1861 return QDF_STATUS_SUCCESS;
1862 }
1863
1864 #ifdef WLAN_FEATURE_EXTWOW_SUPPORT
1865 /**
1866 * send_enable_ext_wow_cmd_tlv() - enable ext wow in fw
1867 * @wmi_handle: wmi handle
1868 * @params: ext wow params
1869 *
1870 * Return:0 for success or error code
1871 */
send_enable_ext_wow_cmd_tlv(wmi_unified_t wmi_handle,struct ext_wow_params * params)1872 static QDF_STATUS send_enable_ext_wow_cmd_tlv(wmi_unified_t wmi_handle,
1873 struct ext_wow_params *params)
1874 {
1875 wmi_extwow_enable_cmd_fixed_param *cmd;
1876 wmi_buf_t buf;
1877 int32_t len;
1878 int ret;
1879
1880 len = sizeof(wmi_extwow_enable_cmd_fixed_param);
1881 buf = wmi_buf_alloc(wmi_handle, len);
1882 if (!buf) {
1883 return QDF_STATUS_E_NOMEM;
1884 }
1885
1886 cmd = (wmi_extwow_enable_cmd_fixed_param *) wmi_buf_data(buf);
1887
1888 WMITLV_SET_HDR(&cmd->tlv_header,
1889 WMITLV_TAG_STRUC_wmi_extwow_enable_cmd_fixed_param,
1890 WMITLV_GET_STRUCT_TLVLEN
1891 (wmi_extwow_enable_cmd_fixed_param));
1892
1893 cmd->vdev_id = params->vdev_id;
1894 cmd->type = params->type;
1895 cmd->wakeup_pin_num = params->wakeup_pin_num;
1896
1897 wmi_debug("vdev_id %d type %d Wakeup_pin_num %x",
1898 cmd->vdev_id, cmd->type, cmd->wakeup_pin_num);
1899
1900 wmi_mtrace(WMI_EXTWOW_ENABLE_CMDID, cmd->vdev_id, 0);
1901 ret = wmi_unified_cmd_send(wmi_handle, buf, len,
1902 WMI_EXTWOW_ENABLE_CMDID);
1903 if (ret) {
1904 wmi_err("Failed to set EXTWOW Enable");
1905 wmi_buf_free(buf);
1906 return QDF_STATUS_E_FAILURE;
1907 }
1908
1909 return QDF_STATUS_SUCCESS;
1910
1911 }
1912
1913 /**
1914 * send_set_app_type2_params_in_fw_cmd_tlv() - set app type2 params in fw
1915 * @wmi_handle: wmi handle
1916 * @appType2Params: app type2 params
1917 *
1918 * Return: QDF status
1919 */
send_set_app_type2_params_in_fw_cmd_tlv(wmi_unified_t wmi_handle,struct app_type2_params * appType2Params)1920 static QDF_STATUS send_set_app_type2_params_in_fw_cmd_tlv(wmi_unified_t wmi_handle,
1921 struct app_type2_params *appType2Params)
1922 {
1923 wmi_extwow_set_app_type2_params_cmd_fixed_param *cmd;
1924 wmi_buf_t buf;
1925 int32_t len;
1926 int ret;
1927
1928 len = sizeof(wmi_extwow_set_app_type2_params_cmd_fixed_param);
1929 buf = wmi_buf_alloc(wmi_handle, len);
1930 if (!buf) {
1931 return QDF_STATUS_E_NOMEM;
1932 }
1933
1934 cmd = (wmi_extwow_set_app_type2_params_cmd_fixed_param *)
1935 wmi_buf_data(buf);
1936
1937 WMITLV_SET_HDR(&cmd->tlv_header,
1938 WMITLV_TAG_STRUC_wmi_extwow_set_app_type2_params_cmd_fixed_param,
1939 WMITLV_GET_STRUCT_TLVLEN
1940 (wmi_extwow_set_app_type2_params_cmd_fixed_param));
1941
1942 cmd->vdev_id = appType2Params->vdev_id;
1943
1944 qdf_mem_copy(cmd->rc4_key, appType2Params->rc4_key, 16);
1945 cmd->rc4_key_len = appType2Params->rc4_key_len;
1946
1947 cmd->ip_id = appType2Params->ip_id;
1948 cmd->ip_device_ip = appType2Params->ip_device_ip;
1949 cmd->ip_server_ip = appType2Params->ip_server_ip;
1950
1951 cmd->tcp_src_port = appType2Params->tcp_src_port;
1952 cmd->tcp_dst_port = appType2Params->tcp_dst_port;
1953 cmd->tcp_seq = appType2Params->tcp_seq;
1954 cmd->tcp_ack_seq = appType2Params->tcp_ack_seq;
1955
1956 cmd->keepalive_init = appType2Params->keepalive_init;
1957 cmd->keepalive_min = appType2Params->keepalive_min;
1958 cmd->keepalive_max = appType2Params->keepalive_max;
1959 cmd->keepalive_inc = appType2Params->keepalive_inc;
1960
1961 WMI_CHAR_ARRAY_TO_MAC_ADDR(appType2Params->gateway_mac.bytes,
1962 &cmd->gateway_mac);
1963 cmd->tcp_tx_timeout_val = appType2Params->tcp_tx_timeout_val;
1964 cmd->tcp_rx_timeout_val = appType2Params->tcp_rx_timeout_val;
1965
1966 wmi_debug("vdev_id %d gateway_mac "QDF_MAC_ADDR_FMT" "
1967 "rc4_key %.16s rc4_key_len %u "
1968 "ip_id %x ip_device_ip %x ip_server_ip %x "
1969 "tcp_src_port %u tcp_dst_port %u tcp_seq %u "
1970 "tcp_ack_seq %u keepalive_init %u keepalive_min %u "
1971 "keepalive_max %u keepalive_inc %u "
1972 "tcp_tx_timeout_val %u tcp_rx_timeout_val %u",
1973 cmd->vdev_id,
1974 QDF_MAC_ADDR_REF(appType2Params->gateway_mac.bytes),
1975 cmd->rc4_key, cmd->rc4_key_len,
1976 cmd->ip_id, cmd->ip_device_ip, cmd->ip_server_ip,
1977 cmd->tcp_src_port, cmd->tcp_dst_port, cmd->tcp_seq,
1978 cmd->tcp_ack_seq, cmd->keepalive_init, cmd->keepalive_min,
1979 cmd->keepalive_max, cmd->keepalive_inc,
1980 cmd->tcp_tx_timeout_val, cmd->tcp_rx_timeout_val);
1981
1982 wmi_mtrace(WMI_EXTWOW_SET_APP_TYPE2_PARAMS_CMDID, cmd->vdev_id, 0);
1983 ret = wmi_unified_cmd_send(wmi_handle, buf, len,
1984 WMI_EXTWOW_SET_APP_TYPE2_PARAMS_CMDID);
1985 if (ret) {
1986 wmi_err("Failed to set APP TYPE2 PARAMS");
1987 wmi_buf_free(buf);
1988 return QDF_STATUS_E_FAILURE;
1989 }
1990
1991 return QDF_STATUS_SUCCESS;
1992
1993 }
1994
1995 /**
1996 * send_app_type1_params_in_fw_cmd_tlv() - set app type1 params in fw
1997 * @wmi_handle: wmi handle
1998 * @app_type1_params: app type1 params
1999 *
2000 * Return: QDF status
2001 */
send_app_type1_params_in_fw_cmd_tlv(wmi_unified_t wmi_handle,struct app_type1_params * app_type1_params)2002 static QDF_STATUS send_app_type1_params_in_fw_cmd_tlv(wmi_unified_t wmi_handle,
2003 struct app_type1_params *app_type1_params)
2004 {
2005 wmi_extwow_set_app_type1_params_cmd_fixed_param *cmd;
2006 wmi_buf_t buf;
2007 int32_t len;
2008 int ret;
2009
2010 len = sizeof(wmi_extwow_set_app_type1_params_cmd_fixed_param);
2011 buf = wmi_buf_alloc(wmi_handle, len);
2012 if (!buf) {
2013 return QDF_STATUS_E_NOMEM;
2014 }
2015
2016 cmd = (wmi_extwow_set_app_type1_params_cmd_fixed_param *)
2017 wmi_buf_data(buf);
2018
2019 WMITLV_SET_HDR(&cmd->tlv_header,
2020 WMITLV_TAG_STRUC_wmi_extwow_set_app_type1_params_cmd_fixed_param,
2021 WMITLV_GET_STRUCT_TLVLEN
2022 (wmi_extwow_set_app_type1_params_cmd_fixed_param));
2023
2024 cmd->vdev_id = app_type1_params->vdev_id;
2025 WMI_CHAR_ARRAY_TO_MAC_ADDR(app_type1_params->wakee_mac_addr.bytes,
2026 &cmd->wakee_mac);
2027 qdf_mem_copy(cmd->ident, app_type1_params->identification_id, 8);
2028 cmd->ident_len = app_type1_params->id_length;
2029 qdf_mem_copy(cmd->passwd, app_type1_params->password, 16);
2030 cmd->passwd_len = app_type1_params->pass_length;
2031
2032 wmi_debug("vdev_id %d wakee_mac_addr "QDF_MAC_ADDR_FMT" "
2033 "identification_id %.8s id_length %u "
2034 "password %.16s pass_length %u",
2035 cmd->vdev_id,
2036 QDF_MAC_ADDR_REF(app_type1_params->wakee_mac_addr.bytes),
2037 cmd->ident, cmd->ident_len, cmd->passwd, cmd->passwd_len);
2038
2039 wmi_mtrace(WMI_EXTWOW_SET_APP_TYPE1_PARAMS_CMDID, cmd->vdev_id, 0);
2040 ret = wmi_unified_cmd_send(wmi_handle, buf, len,
2041 WMI_EXTWOW_SET_APP_TYPE1_PARAMS_CMDID);
2042 if (ret) {
2043 wmi_err("Failed to set APP TYPE1 PARAMS");
2044 wmi_buf_free(buf);
2045 return QDF_STATUS_E_FAILURE;
2046 }
2047
2048 return QDF_STATUS_SUCCESS;
2049 }
2050
wmi_extwow_attach_tlv(struct wmi_unified * wmi_handle)2051 void wmi_extwow_attach_tlv(struct wmi_unified *wmi_handle)
2052 {
2053 struct wmi_ops *ops = wmi_handle->ops;
2054
2055 ops->send_enable_ext_wow_cmd = send_enable_ext_wow_cmd_tlv;
2056 ops->send_set_app_type2_params_in_fw_cmd =
2057 send_set_app_type2_params_in_fw_cmd_tlv;
2058 ops->send_app_type1_params_in_fw_cmd =
2059 send_app_type1_params_in_fw_cmd_tlv;
2060 }
2061 #endif /* WLAN_FEATURE_EXTWOW_SUPPORT */
2062
2063 #ifdef WLAN_FEATURE_ICMP_OFFLOAD
2064 /**
2065 * send_icmp_ipv4_config_cmd_tlv() - send ICMP IPV4 offload command to fw
2066 * @wmi_handle: wmi handle
2067 * @pmo_icmp_req: ICMP offload parameters
2068 *
2069 * Return: QDF status
2070 */
2071 static QDF_STATUS
send_icmp_ipv4_config_cmd_tlv(wmi_unified_t wmi_handle,struct pmo_icmp_offload * pmo_icmp_req)2072 send_icmp_ipv4_config_cmd_tlv(wmi_unified_t wmi_handle,
2073 struct pmo_icmp_offload *pmo_icmp_req)
2074 {
2075 wmi_buf_t buf;
2076 wmi_icmp_offload_fixed_param *cmd;
2077 uint16_t len = sizeof(*cmd);
2078 QDF_STATUS status;
2079
2080 buf = wmi_buf_alloc(wmi_handle, len);
2081 if (!buf) {
2082 wmi_err_rl("Failed to allocate wmi buffer");
2083 status = QDF_STATUS_E_NOMEM;
2084 return status;
2085 }
2086 cmd = (wmi_icmp_offload_fixed_param *)wmi_buf_data(buf);
2087 WMITLV_SET_HDR(&cmd->tlv_header,
2088 WMITLV_TAG_STRUC_wmi_icmp_offload_fixed_param,
2089 WMITLV_GET_STRUCT_TLVLEN(wmi_icmp_offload_fixed_param));
2090
2091 cmd->vdev_id = pmo_icmp_req->vdev_id;
2092 cmd->enable = pmo_icmp_req->enable;
2093 cmd->valid_bitmask = 0;
2094
2095 WMI_SET_ICMP_OFFLOAD_IPV4_ENABLED_BIT(cmd->valid_bitmask);
2096 qdf_mem_copy(&cmd->ipv4_addr, pmo_icmp_req->ipv4_addr,
2097 QDF_IPV4_ADDR_SIZE);
2098 wmi_debug("ipv4:%pI4", &cmd->ipv4_addr);
2099
2100 wmi_mtrace(WMI_VDEV_ICMP_OFFLOAD_CMDID, cmd->vdev_id, 0);
2101 status = wmi_unified_cmd_send(wmi_handle, buf, len,
2102 WMI_VDEV_ICMP_OFFLOAD_CMDID);
2103
2104 if (QDF_IS_STATUS_ERROR(status))
2105 wmi_buf_free(buf);
2106
2107 return status;
2108 }
2109
2110 /**
2111 * send_icmp_ipv6_config_cmd_tlv() - send ICMP IPV6 offload command to fw
2112 * @wmi_handle: wmi handle
2113 * @pmo_icmp_req: ICMP offload parameters
2114 *
2115 * Return: QDF status
2116 */
2117 static QDF_STATUS
send_icmp_ipv6_config_cmd_tlv(wmi_unified_t wmi_handle,struct pmo_icmp_offload * pmo_icmp_req)2118 send_icmp_ipv6_config_cmd_tlv(wmi_unified_t wmi_handle,
2119 struct pmo_icmp_offload *pmo_icmp_req)
2120 {
2121 wmi_buf_t buf;
2122 uint8_t *buf_ptr;
2123 uint16_t len;
2124 int i;
2125 WMI_IPV6_ADDR *ipv6_list;
2126 wmi_icmp_offload_fixed_param *cmd;
2127 QDF_STATUS status;
2128
2129 len = sizeof(wmi_icmp_offload_fixed_param) + WMI_TLV_HDR_SIZE +
2130 (pmo_icmp_req->ipv6_count) * sizeof(WMI_IPV6_ADDR);
2131
2132 buf = wmi_buf_alloc(wmi_handle, len);
2133 if (!buf) {
2134 wmi_err_rl("Failed to allocate wmi buffer");
2135 status = QDF_STATUS_E_NOMEM;
2136 return status;
2137 }
2138
2139 buf_ptr = (uint8_t *)wmi_buf_data(buf);
2140 cmd = (wmi_icmp_offload_fixed_param *)wmi_buf_data(buf);
2141 WMITLV_SET_HDR(&cmd->tlv_header,
2142 WMITLV_TAG_STRUC_wmi_icmp_offload_fixed_param,
2143 WMITLV_GET_STRUCT_TLVLEN(wmi_icmp_offload_fixed_param));
2144
2145 cmd->vdev_id = pmo_icmp_req->vdev_id;
2146 cmd->enable = pmo_icmp_req->enable;
2147 cmd->valid_bitmask = 0;
2148
2149 WMI_SET_ICMP_OFFLOAD_IPV6_ENABLED_BIT(cmd->valid_bitmask);
2150 buf_ptr += sizeof(*cmd);
2151 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_FIXED_STRUC,
2152 sizeof(WMI_IPV6_ADDR) * pmo_icmp_req->ipv6_count);
2153 ipv6_list = (WMI_IPV6_ADDR *)(buf_ptr + WMI_TLV_HDR_SIZE);
2154
2155 for (i = 0; i < pmo_icmp_req->ipv6_count; i++) {
2156 qdf_mem_copy(((*(ipv6_list + i)).address),
2157 &pmo_icmp_req->ipv6_addr[i],
2158 sizeof(WMI_IPV6_ADDR));
2159 wmi_debug("ipv6_list[%d]:%pI6", i, (ipv6_list + i));
2160 }
2161
2162 /* send the wmi command */
2163 wmi_mtrace(WMI_VDEV_ICMP_OFFLOAD_CMDID, cmd->vdev_id, 0);
2164 status = wmi_unified_cmd_send(wmi_handle, buf, len,
2165 WMI_VDEV_ICMP_OFFLOAD_CMDID);
2166
2167 if (QDF_IS_STATUS_ERROR(status))
2168 wmi_buf_free(buf);
2169
2170 return status;
2171 }
2172
2173 /**
2174 * send_icmp_offload_config_cmd_tlv() - send ICMP offload command to fw
2175 * @wmi_handle: wmi handle
2176 * @pmo_icmp_req: ICMP offload parameters
2177 *
2178 * Return: QDF status
2179 */
2180 static QDF_STATUS
send_icmp_offload_config_cmd_tlv(wmi_unified_t wmi_handle,struct pmo_icmp_offload * pmo_icmp_req)2181 send_icmp_offload_config_cmd_tlv(wmi_unified_t wmi_handle,
2182 struct pmo_icmp_offload *pmo_icmp_req)
2183 {
2184 QDF_STATUS status;
2185
2186 switch (pmo_icmp_req->trigger) {
2187 case pmo_ipv4_change_notify:
2188 status = send_icmp_ipv4_config_cmd_tlv(wmi_handle,
2189 pmo_icmp_req);
2190 break;
2191 case pmo_ipv6_change_notify:
2192 status = send_icmp_ipv6_config_cmd_tlv(wmi_handle,
2193 pmo_icmp_req);
2194 break;
2195 default:
2196 QDF_DEBUG_PANIC("Invalid ICMP trigger %d",
2197 pmo_icmp_req->trigger);
2198 status = QDF_STATUS_E_FAILURE;
2199 }
2200
2201 return status;
2202 }
2203
wmi_icmp_offload_config_tlv(struct wmi_unified * wmi_handle)2204 static void wmi_icmp_offload_config_tlv(struct wmi_unified *wmi_handle)
2205 {
2206 struct wmi_ops *ops = wmi_handle->ops;
2207
2208 ops->send_icmp_offload_config_cmd = send_icmp_offload_config_cmd_tlv;
2209 }
2210 #else
wmi_icmp_offload_config_tlv(struct wmi_unified * wmi_handle)2211 static inline void wmi_icmp_offload_config_tlv(struct wmi_unified *wmi_handle)
2212 {}
2213 #endif /* WLAN_FEATURE_ICMP_OFFLOAD */
2214
wmi_pmo_attach_tlv(wmi_unified_t wmi_handle)2215 void wmi_pmo_attach_tlv(wmi_unified_t wmi_handle)
2216 {
2217 struct wmi_ops *ops = wmi_handle->ops;
2218
2219 ops->send_add_wow_wakeup_event_cmd =
2220 send_add_wow_wakeup_event_cmd_tlv;
2221 ops->send_wow_patterns_to_fw_cmd = send_wow_patterns_to_fw_cmd_tlv;
2222 ops->send_enable_arp_ns_offload_cmd =
2223 send_enable_arp_ns_offload_cmd_tlv;
2224 ops->send_add_clear_mcbc_filter_cmd =
2225 send_add_clear_mcbc_filter_cmd_tlv;
2226 ops->send_multiple_add_clear_mcbc_filter_cmd =
2227 send_multiple_add_clear_mcbc_filter_cmd_tlv;
2228 ops->send_conf_hw_filter_cmd = send_conf_hw_filter_cmd_tlv;
2229 ops->send_gtk_offload_cmd = send_gtk_offload_cmd_tlv;
2230 #ifdef WLAN_FEATURE_IGMP_OFFLOAD
2231 ops->send_igmp_offload_cmd = send_igmp_offload_cmd_tlv;
2232 #endif
2233 ops->send_process_gtk_offload_getinfo_cmd =
2234 send_process_gtk_offload_getinfo_cmd_tlv;
2235 ops->send_enable_enhance_multicast_offload_cmd =
2236 send_enable_enhance_multicast_offload_tlv;
2237 ops->extract_gtk_rsp_event = extract_gtk_rsp_event_tlv;
2238 ops->send_action_frame_patterns_cmd =
2239 send_action_frame_patterns_cmd_tlv;
2240 ops->send_wow_delete_pattern_cmd = send_wow_delete_pattern_cmd_tlv;
2241 ops->send_host_wakeup_ind_to_fw_cmd =
2242 send_host_wakeup_ind_to_fw_cmd_tlv;
2243 ops->send_wow_timer_pattern_cmd = send_wow_timer_pattern_cmd_tlv;
2244
2245 wmi_d0wow_attach_tlv(wmi_handle);
2246 wmi_ra_filtering_attach_tlv(wmi_handle);
2247 wmi_lphb_attach_tlv(wmi_handle);
2248 wmi_packet_filtering_attach_tlv(wmi_handle);
2249 wmi_extwow_attach_tlv(wmi_handle);
2250 wmi_icmp_offload_config_tlv(wmi_handle);
2251 }
2252