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 */ 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 */ 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 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 */ 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 */ 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 */ 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 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 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 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 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 */ 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 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 */ 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 */ 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 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 */ 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 */ 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 */ 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 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 */ 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 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 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 */ 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 */ 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 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 */ 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 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 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 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 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 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 2211 static inline void wmi_icmp_offload_config_tlv(struct wmi_unified *wmi_handle) 2212 {} 2213 #endif /* WLAN_FEATURE_ICMP_OFFLOAD */ 2214 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