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 for (i = 0; i < filter_param->multicast_addr_cnt; i++) { 675 WMI_CHAR_ARRAY_TO_MAC_ADDR(mac_addr_src_ptr, mac_addr_dst_ptr); 676 mac_addr_src_ptr += ATH_MAC_LEN; 677 mac_addr_dst_ptr++; 678 } 679 680 send_cmd: 681 wmi_mtrace(WMI_SET_MULTIPLE_MCAST_FILTER_CMDID, cmd->vdev_id, 0); 682 err = wmi_unified_cmd_send(wmi_handle, buf, 683 len, 684 WMI_SET_MULTIPLE_MCAST_FILTER_CMDID); 685 if (err) { 686 wmi_err("Failed to send set_param cmd"); 687 wmi_buf_free(buf); 688 return QDF_STATUS_E_FAILURE; 689 } 690 691 return QDF_STATUS_SUCCESS; 692 } 693 694 static QDF_STATUS send_conf_hw_filter_cmd_tlv(wmi_unified_t wmi, 695 struct pmo_hw_filter_params *req) 696 { 697 QDF_STATUS status; 698 wmi_hw_data_filter_cmd_fixed_param *cmd; 699 wmi_buf_t wmi_buf; 700 701 if (!req) { 702 wmi_err("req is null"); 703 return QDF_STATUS_E_INVAL; 704 } 705 706 wmi_buf = wmi_buf_alloc(wmi, sizeof(*cmd)); 707 if (!wmi_buf) { 708 return QDF_STATUS_E_NOMEM; 709 } 710 711 cmd = (wmi_hw_data_filter_cmd_fixed_param *)wmi_buf_data(wmi_buf); 712 WMITLV_SET_HDR(&cmd->tlv_header, 713 WMITLV_TAG_STRUC_wmi_hw_data_filter_cmd_fixed_param, 714 WMITLV_GET_STRUCT_TLVLEN(wmi_hw_data_filter_cmd_fixed_param)); 715 cmd->vdev_id = req->vdev_id; 716 cmd->enable = req->enable; 717 /* Set all modes in case of disable */ 718 if (!cmd->enable) 719 cmd->hw_filter_bitmap = ((uint32_t)~0U); 720 else 721 cmd->hw_filter_bitmap = req->mode_bitmap; 722 723 wmi_debug("Send %s hw filter mode: 0x%X for vdev id %d", 724 req->enable ? "enable" : "disable", req->mode_bitmap, 725 req->vdev_id); 726 727 wmi_mtrace(WMI_HW_DATA_FILTER_CMDID, cmd->vdev_id, 0); 728 status = wmi_unified_cmd_send(wmi, wmi_buf, sizeof(*cmd), 729 WMI_HW_DATA_FILTER_CMDID); 730 if (QDF_IS_STATUS_ERROR(status)) { 731 wmi_err("Failed to configure hw filter"); 732 wmi_buf_free(wmi_buf); 733 } 734 735 return status; 736 } 737 738 static void 739 fill_fils_tlv_params(WMI_GTK_OFFLOAD_CMD_fixed_param *cmd, 740 uint8_t vdev_id, 741 struct pmo_gtk_req *params) 742 { 743 uint8_t *buf_ptr; 744 wmi_gtk_offload_fils_tlv_param *ext_param; 745 746 buf_ptr = (uint8_t *) cmd + sizeof(*cmd); 747 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 748 sizeof(*ext_param)); 749 buf_ptr += WMI_TLV_HDR_SIZE; 750 751 ext_param = (wmi_gtk_offload_fils_tlv_param *)buf_ptr; 752 WMITLV_SET_HDR(&ext_param->tlv_header, 753 WMITLV_TAG_STRUC_wmi_gtk_offload_extended_tlv_param, 754 WMITLV_GET_STRUCT_TLVLEN( 755 wmi_gtk_offload_fils_tlv_param)); 756 ext_param->vdev_id = vdev_id; 757 ext_param->flags = cmd->flags; 758 ext_param->kek_len = params->kek_len; 759 qdf_mem_copy(ext_param->KEK, params->kek, params->kek_len); 760 qdf_mem_copy(ext_param->KCK, params->kck, 761 WMI_GTK_OFFLOAD_KCK_BYTES); 762 qdf_mem_copy(ext_param->replay_counter, ¶ms->replay_counter, 763 GTK_REPLAY_COUNTER_BYTES); 764 } 765 766 #ifdef WLAN_FEATURE_IGMP_OFFLOAD 767 /** 768 * send_igmp_offload_cmd_tlv() - send IGMP offload command to fw 769 * @wmi_handle: wmi handle 770 * @pmo_igmp_req: IGMP offload parameters 771 * 772 * Return: QDF status 773 */ 774 static 775 QDF_STATUS send_igmp_offload_cmd_tlv(wmi_unified_t wmi_handle, 776 struct pmo_igmp_offload_req *pmo_igmp_req) 777 { 778 wmi_buf_t buf; 779 uint8_t *buf_ptr; 780 int len; 781 int i = 0; 782 WMI_IPV4_ADDR *ipv4_list; 783 wmi_igmp_offload_fixed_param *cmd; 784 QDF_STATUS status = QDF_STATUS_SUCCESS; 785 786 len = sizeof(wmi_igmp_offload_fixed_param) + WMI_TLV_HDR_SIZE + 787 (pmo_igmp_req->num_grp_ip_address) * sizeof(WMI_IPV4_ADDR); 788 /* alloc wmi buffer */ 789 buf = wmi_buf_alloc(wmi_handle, len); 790 if (!buf) { 791 status = QDF_STATUS_E_NOMEM; 792 goto out; 793 } 794 buf_ptr = (uint8_t *)wmi_buf_data(buf); 795 cmd = (wmi_igmp_offload_fixed_param *)wmi_buf_data(buf); 796 797 WMITLV_SET_HDR(&cmd->tlv_header, 798 WMITLV_TAG_STRUC_wmi_igmp_offload_fixed_param, 799 WMITLV_GET_STRUCT_TLVLEN(wmi_igmp_offload_fixed_param)); 800 801 cmd->vdev_id = pmo_igmp_req->vdev_id; 802 cmd->enable = pmo_igmp_req->enable; 803 cmd->version_support_bitmask = 804 pmo_igmp_req->version_support; 805 806 buf_ptr += sizeof(*cmd); 807 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_FIXED_STRUC, 808 sizeof(WMI_IPV4_ADDR) * 809 pmo_igmp_req->num_grp_ip_address); 810 811 ipv4_list = (WMI_IPV4_ADDR *)(buf_ptr + WMI_TLV_HDR_SIZE); 812 813 while (i < pmo_igmp_req->num_grp_ip_address) { 814 qdf_mem_copy((void *)((*(ipv4_list + i)).address), 815 (void *)&(pmo_igmp_req->grp_ip_address[i]), 816 WMI_IPV4_ADDR_LEN); 817 wmi_debug("piv4[%d]:%x", i, *(uint32_t *)(ipv4_list + i)); 818 i++; 819 } 820 821 wmi_debug("VDEVID:%d, FLAG:x%x version support:%d", 822 cmd->vdev_id, cmd->enable, 823 cmd->version_support_bitmask); 824 825 /* send the wmi command */ 826 wmi_mtrace(WMI_VDEV_IGMP_OFFLOAD_CMDID, cmd->vdev_id, 0); 827 if (wmi_unified_cmd_send(wmi_handle, buf, len, 828 WMI_VDEV_IGMP_OFFLOAD_CMDID)) { 829 wmi_err("Failed to send WMI_VDEV_IGMP_OFFLOAD_CMDID"); 830 wmi_buf_free(buf); 831 status = QDF_STATUS_E_FAILURE; 832 } 833 out: 834 return status; 835 } 836 #endif 837 838 /** 839 * send_gtk_offload_cmd_tlv() - send GTK offload command to fw 840 * @wmi_handle: wmi handle 841 * @vdev_id: vdev id 842 * @params: GTK offload parameters 843 * @enable_offload: true to enable the offload 844 * @gtk_offload_opcode: GTK offload opcode 845 * 846 * Return: QDF status 847 */ 848 static 849 QDF_STATUS send_gtk_offload_cmd_tlv(wmi_unified_t wmi_handle, uint8_t vdev_id, 850 struct pmo_gtk_req *params, 851 bool enable_offload, 852 uint32_t gtk_offload_opcode) 853 { 854 int len; 855 uint8_t *buf_ptr; 856 wmi_buf_t buf; 857 WMI_GTK_OFFLOAD_CMD_fixed_param *cmd; 858 QDF_STATUS status = QDF_STATUS_SUCCESS; 859 860 len = sizeof(*cmd); 861 862 len += WMI_TLV_HDR_SIZE; 863 if (params->is_fils_connection) 864 len += sizeof(wmi_gtk_offload_fils_tlv_param); 865 866 if (params->kck_len > 16) 867 len += WMI_TLV_HDR_SIZE + 868 roundup(params->kek_len, sizeof(uint32_t)) + 869 WMI_TLV_HDR_SIZE + 870 roundup(params->kck_len, sizeof(uint32_t)); 871 872 /* alloc wmi buffer */ 873 buf = wmi_buf_alloc(wmi_handle, len); 874 if (!buf) { 875 status = QDF_STATUS_E_NOMEM; 876 goto out; 877 } 878 879 cmd = (WMI_GTK_OFFLOAD_CMD_fixed_param *) wmi_buf_data(buf); 880 WMITLV_SET_HDR(&cmd->tlv_header, 881 WMITLV_TAG_STRUC_WMI_GTK_OFFLOAD_CMD_fixed_param, 882 WMITLV_GET_STRUCT_TLVLEN 883 (WMI_GTK_OFFLOAD_CMD_fixed_param)); 884 885 buf_ptr = wmi_buf_data(buf); 886 cmd->vdev_id = vdev_id; 887 888 /* Request target to enable GTK offload */ 889 if (enable_offload == PMO_GTK_OFFLOAD_ENABLE) { 890 cmd->flags = gtk_offload_opcode; 891 892 /* Copy the keys and replay counter */ 893 qdf_mem_copy(cmd->KCK, params->kck, sizeof(cmd->KCK)); 894 qdf_mem_copy(cmd->KEK, params->kek, sizeof(cmd->KEK)); 895 qdf_mem_copy(cmd->replay_counter, ¶ms->replay_counter, 896 GTK_REPLAY_COUNTER_BYTES); 897 } else { 898 cmd->flags = gtk_offload_opcode; 899 } 900 901 buf_ptr = (uint8_t *)cmd + sizeof(*cmd); 902 903 if (params->is_fils_connection) { 904 fill_fils_tlv_params(cmd, vdev_id, params); 905 buf_ptr += sizeof(wmi_gtk_offload_fils_tlv_param); 906 } else { 907 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0); 908 buf_ptr += WMI_TLV_HDR_SIZE; 909 } 910 911 if (params->kck_len > 16) { 912 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, 913 roundup(params->kek_len, sizeof(uint32_t))); 914 buf_ptr += WMI_TLV_HDR_SIZE; 915 916 qdf_mem_copy(buf_ptr, params->kek, params->kek_len); 917 buf_ptr += roundup(params->kek_len, sizeof(uint32_t)); 918 919 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, 920 roundup(params->kck_len, sizeof(uint32_t))); 921 buf_ptr += WMI_TLV_HDR_SIZE; 922 923 qdf_mem_copy(buf_ptr, params->kck, params->kck_len); 924 buf_ptr += roundup(params->kck_len, sizeof(uint32_t)); 925 } 926 927 wmi_debug("VDEVID: %d, GTK_FLAGS: x%x kek len %d", 928 vdev_id, cmd->flags, params->kek_len); 929 /* send the wmi command */ 930 wmi_mtrace(WMI_GTK_OFFLOAD_CMDID, cmd->vdev_id, 0); 931 if (wmi_unified_cmd_send(wmi_handle, buf, len, 932 WMI_GTK_OFFLOAD_CMDID)) { 933 wmi_err("Failed to send WMI_GTK_OFFLOAD_CMDID"); 934 wmi_buf_free(buf); 935 status = QDF_STATUS_E_FAILURE; 936 } 937 938 out: 939 return status; 940 } 941 942 /** 943 * send_process_gtk_offload_getinfo_cmd_tlv() - send GTK offload cmd to fw 944 * @wmi_handle: wmi handle 945 * @vdev_id: vdev id 946 * @offload_req_opcode: GTK offload request opcode 947 * 948 * Return: QDF status 949 */ 950 static QDF_STATUS send_process_gtk_offload_getinfo_cmd_tlv( 951 wmi_unified_t wmi_handle, 952 uint8_t vdev_id, 953 uint64_t offload_req_opcode) 954 { 955 int len; 956 wmi_buf_t buf; 957 WMI_GTK_OFFLOAD_CMD_fixed_param *cmd; 958 QDF_STATUS status = QDF_STATUS_SUCCESS; 959 960 len = sizeof(*cmd); 961 962 /* alloc wmi buffer */ 963 buf = wmi_buf_alloc(wmi_handle, len); 964 if (!buf) { 965 status = QDF_STATUS_E_NOMEM; 966 goto out; 967 } 968 969 cmd = (WMI_GTK_OFFLOAD_CMD_fixed_param *) wmi_buf_data(buf); 970 WMITLV_SET_HDR(&cmd->tlv_header, 971 WMITLV_TAG_STRUC_WMI_GTK_OFFLOAD_CMD_fixed_param, 972 WMITLV_GET_STRUCT_TLVLEN 973 (WMI_GTK_OFFLOAD_CMD_fixed_param)); 974 975 /* Request for GTK offload status */ 976 cmd->flags = offload_req_opcode; 977 cmd->vdev_id = vdev_id; 978 979 /* send the wmi command */ 980 wmi_mtrace(WMI_GTK_OFFLOAD_CMDID, cmd->vdev_id, 0); 981 if (wmi_unified_cmd_send(wmi_handle, buf, len, 982 WMI_GTK_OFFLOAD_CMDID)) { 983 wmi_err("Failed to send WMI_GTK_OFFLOAD_CMDID for req info"); 984 wmi_buf_free(buf); 985 status = QDF_STATUS_E_FAILURE; 986 } 987 988 out: 989 return status; 990 } 991 992 /** 993 * send_enable_enhance_multicast_offload_tlv() - send enhance multicast offload 994 * @wmi_handle: wmi handle 995 * @vdev_id: vdev id 996 * @action: true for enable else false 997 * 998 * To enable enhance multicast offload to firmware 999 * when target goes to wow mode. 1000 * 1001 * Return: QDF Status 1002 */ 1003 1004 static 1005 QDF_STATUS send_enable_enhance_multicast_offload_tlv( 1006 wmi_unified_t wmi_handle, 1007 uint8_t vdev_id, bool action) 1008 { 1009 QDF_STATUS status; 1010 wmi_buf_t buf; 1011 wmi_config_enhanced_mcast_filter_cmd_fixed_param *cmd; 1012 1013 buf = wmi_buf_alloc(wmi_handle, sizeof(*cmd)); 1014 if (!buf) { 1015 return QDF_STATUS_E_NOMEM; 1016 } 1017 1018 cmd = (wmi_config_enhanced_mcast_filter_cmd_fixed_param *) 1019 wmi_buf_data(buf); 1020 1021 WMITLV_SET_HDR(&cmd->tlv_header, 1022 WMITLV_TAG_STRUC_wmi_config_enhanced_mcast_filter_fixed_param, 1023 WMITLV_GET_STRUCT_TLVLEN( 1024 wmi_config_enhanced_mcast_filter_cmd_fixed_param)); 1025 1026 cmd->vdev_id = vdev_id; 1027 cmd->enable = ((action == 0) ? ENHANCED_MCAST_FILTER_DISABLED : 1028 ENHANCED_MCAST_FILTER_ENABLED); 1029 wmi_debug("config enhance multicast offload action %d for vdev %d", 1030 action, vdev_id); 1031 wmi_mtrace(WMI_CONFIG_ENHANCED_MCAST_FILTER_CMDID, cmd->vdev_id, 0); 1032 status = wmi_unified_cmd_send(wmi_handle, buf, 1033 sizeof(*cmd), WMI_CONFIG_ENHANCED_MCAST_FILTER_CMDID); 1034 if (status != QDF_STATUS_SUCCESS) { 1035 wmi_buf_free(buf); 1036 wmi_err("Failed to send ENHANCED_MCAST_FILTER_CMDID"); 1037 } 1038 1039 return status; 1040 } 1041 1042 /** 1043 * extract_gtk_rsp_event_tlv() - extract gtk rsp params from event 1044 * @wmi_handle: wmi handle 1045 * @evt_buf: pointer to event buffer 1046 * @gtk_rsp_param: Pointer to extraction buffer 1047 * @len: length of the @evt_buf event buffer 1048 * 1049 * Return: QDF_STATUS_SUCCESS for success or error code 1050 */ 1051 static QDF_STATUS extract_gtk_rsp_event_tlv(wmi_unified_t wmi_handle, 1052 void *evt_buf, struct pmo_gtk_rsp_params *gtk_rsp_param, uint32_t len) 1053 { 1054 WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param *fixed_param; 1055 WMI_GTK_OFFLOAD_STATUS_EVENTID_param_tlvs *param_buf; 1056 1057 param_buf = (WMI_GTK_OFFLOAD_STATUS_EVENTID_param_tlvs *)evt_buf; 1058 if (!param_buf) { 1059 wmi_err("gtk param_buf is NULL"); 1060 return QDF_STATUS_E_INVAL; 1061 } 1062 1063 if (len < sizeof(WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param)) { 1064 wmi_err("Invalid length for GTK status"); 1065 return QDF_STATUS_E_INVAL; 1066 } 1067 1068 fixed_param = (WMI_GTK_OFFLOAD_STATUS_EVENT_fixed_param *) 1069 param_buf->fixed_param; 1070 1071 if (fixed_param->vdev_id >= WLAN_UMAC_PSOC_MAX_VDEVS) { 1072 wmi_err_rl("Invalid vdev_id %u", fixed_param->vdev_id); 1073 return QDF_STATUS_E_INVAL; 1074 } 1075 1076 gtk_rsp_param->vdev_id = fixed_param->vdev_id; 1077 gtk_rsp_param->status_flag = QDF_STATUS_SUCCESS; 1078 gtk_rsp_param->refresh_cnt = fixed_param->refresh_cnt; 1079 qdf_mem_copy(>k_rsp_param->replay_counter, 1080 &fixed_param->replay_counter, 1081 GTK_REPLAY_COUNTER_BYTES); 1082 1083 return QDF_STATUS_SUCCESS; 1084 1085 } 1086 1087 #ifdef FEATURE_WLAN_RA_FILTERING 1088 /** 1089 * send_wow_sta_ra_filter_cmd_tlv() - set RA filter pattern in fw 1090 * @wmi_handle: wmi handle 1091 * @vdev_id: vdev id 1092 * @default_pattern: default pattern 1093 * @rate_limit_interval: ra packets interval 1094 * 1095 * Return: QDF status 1096 */ 1097 static QDF_STATUS send_wow_sta_ra_filter_cmd_tlv(wmi_unified_t wmi_handle, 1098 uint8_t vdev_id, 1099 uint8_t default_pattern, 1100 uint16_t rate_limit_interval) 1101 { 1102 1103 WMI_WOW_ADD_PATTERN_CMD_fixed_param *cmd; 1104 wmi_buf_t buf; 1105 uint8_t *buf_ptr; 1106 int32_t len; 1107 int ret; 1108 1109 len = sizeof(WMI_WOW_ADD_PATTERN_CMD_fixed_param) + 1110 WMI_TLV_HDR_SIZE + 1111 0 * sizeof(WOW_BITMAP_PATTERN_T) + 1112 WMI_TLV_HDR_SIZE + 1113 0 * sizeof(WOW_IPV4_SYNC_PATTERN_T) + 1114 WMI_TLV_HDR_SIZE + 1115 0 * sizeof(WOW_IPV6_SYNC_PATTERN_T) + 1116 WMI_TLV_HDR_SIZE + 1117 0 * sizeof(WOW_MAGIC_PATTERN_CMD) + 1118 WMI_TLV_HDR_SIZE + 1119 0 * sizeof(uint32_t) + WMI_TLV_HDR_SIZE + 1 * sizeof(uint32_t); 1120 1121 buf = wmi_buf_alloc(wmi_handle, len); 1122 if (!buf) { 1123 return QDF_STATUS_E_NOMEM; 1124 } 1125 1126 cmd = (WMI_WOW_ADD_PATTERN_CMD_fixed_param *) wmi_buf_data(buf); 1127 buf_ptr = (uint8_t *) cmd; 1128 1129 WMITLV_SET_HDR(&cmd->tlv_header, 1130 WMITLV_TAG_STRUC_WMI_WOW_ADD_PATTERN_CMD_fixed_param, 1131 WMITLV_GET_STRUCT_TLVLEN 1132 (WMI_WOW_ADD_PATTERN_CMD_fixed_param)); 1133 cmd->vdev_id = vdev_id; 1134 cmd->pattern_id = default_pattern, 1135 cmd->pattern_type = WOW_IPV6_RA_PATTERN; 1136 buf_ptr += sizeof(WMI_WOW_ADD_PATTERN_CMD_fixed_param); 1137 1138 /* Fill TLV for WMITLV_TAG_STRUC_WOW_BITMAP_PATTERN_T but no data. */ 1139 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0); 1140 buf_ptr += WMI_TLV_HDR_SIZE; 1141 1142 /* Fill TLV for WMITLV_TAG_STRUC_WOW_IPV4_SYNC_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_IPV6_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_MAGIC_PATTERN_CMD 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 pattern_info_timeout but no data. */ 1155 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, 0); 1156 buf_ptr += WMI_TLV_HDR_SIZE; 1157 1158 /* Fill TLV for ra_ratelimit_interval. */ 1159 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, sizeof(uint32_t)); 1160 buf_ptr += WMI_TLV_HDR_SIZE; 1161 1162 *((uint32_t *) buf_ptr) = rate_limit_interval; 1163 1164 wmi_debug("send RA rate limit [%d] to fw vdev = %d", 1165 rate_limit_interval, vdev_id); 1166 1167 wmi_mtrace(WMI_WOW_ADD_WAKE_PATTERN_CMDID, cmd->vdev_id, 0); 1168 ret = wmi_unified_cmd_send(wmi_handle, buf, len, 1169 WMI_WOW_ADD_WAKE_PATTERN_CMDID); 1170 if (ret) { 1171 wmi_err("Failed to send RA rate limit to fw"); 1172 wmi_buf_free(buf); 1173 return QDF_STATUS_E_FAILURE; 1174 } 1175 1176 return QDF_STATUS_SUCCESS; 1177 } 1178 1179 void wmi_ra_filtering_attach_tlv(struct wmi_unified *wmi_handle) 1180 { 1181 struct wmi_ops *ops = wmi_handle->ops; 1182 1183 ops->send_wow_sta_ra_filter_cmd = send_wow_sta_ra_filter_cmd_tlv; 1184 } 1185 #endif /* FEATURE_WLAN_RA_FILTERING */ 1186 1187 /** 1188 * send_action_frame_patterns_cmd_tlv() - send wmi cmd of action filter params 1189 * @wmi_handle: wmi handler 1190 * @action_params: pointer to action_params 1191 * 1192 * Return: 0 for success, otherwise appropriate error code 1193 */ 1194 static QDF_STATUS send_action_frame_patterns_cmd_tlv(wmi_unified_t wmi_handle, 1195 struct pmo_action_wakeup_set_params *action_params) 1196 { 1197 WMI_WOW_SET_ACTION_WAKE_UP_CMD_fixed_param *cmd; 1198 wmi_buf_t buf; 1199 int i; 1200 int32_t err; 1201 uint32_t len = 0, *cmd_args; 1202 uint8_t *buf_ptr; 1203 1204 len = (PMO_SUPPORTED_ACTION_CATE * sizeof(uint32_t)) 1205 + WMI_TLV_HDR_SIZE + sizeof(*cmd); 1206 buf = wmi_buf_alloc(wmi_handle, len); 1207 if (!buf) { 1208 return QDF_STATUS_E_NOMEM; 1209 } 1210 cmd = (WMI_WOW_SET_ACTION_WAKE_UP_CMD_fixed_param *) wmi_buf_data(buf); 1211 buf_ptr = (uint8_t *)cmd; 1212 WMITLV_SET_HDR(&cmd->tlv_header, 1213 WMITLV_TAG_STRUC_wmi_wow_set_action_wake_up_cmd_fixed_param, 1214 WMITLV_GET_STRUCT_TLVLEN( 1215 WMI_WOW_SET_ACTION_WAKE_UP_CMD_fixed_param)); 1216 1217 cmd->vdev_id = action_params->vdev_id; 1218 cmd->operation = action_params->operation; 1219 1220 for (i = 0; i < MAX_SUPPORTED_ACTION_CATEGORY_ELE_LIST; i++) 1221 cmd->action_category_map[i] = 1222 action_params->action_category_map[i]; 1223 1224 buf_ptr += sizeof(WMI_WOW_SET_ACTION_WAKE_UP_CMD_fixed_param); 1225 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, 1226 (PMO_SUPPORTED_ACTION_CATE * sizeof(uint32_t))); 1227 buf_ptr += WMI_TLV_HDR_SIZE; 1228 cmd_args = (uint32_t *) buf_ptr; 1229 for (i = 0; i < PMO_SUPPORTED_ACTION_CATE; i++) 1230 cmd_args[i] = action_params->action_per_category[i]; 1231 1232 wmi_mtrace(WMI_WOW_SET_ACTION_WAKE_UP_CMDID, cmd->vdev_id, 0); 1233 err = wmi_unified_cmd_send(wmi_handle, buf, 1234 len, WMI_WOW_SET_ACTION_WAKE_UP_CMDID); 1235 if (err) { 1236 wmi_err("Failed to send ap_ps_egap cmd"); 1237 wmi_buf_free(buf); 1238 return QDF_STATUS_E_FAILURE; 1239 } 1240 1241 return QDF_STATUS_SUCCESS; 1242 } 1243 1244 #ifdef FEATURE_WLAN_LPHB 1245 /** 1246 * send_lphb_config_hbenable_cmd_tlv() - enable command of LPHB configuration 1247 * @wmi_handle: wmi handle 1248 * @params: LPHB configuration info 1249 * 1250 * Return: QDF status 1251 */ 1252 static QDF_STATUS send_lphb_config_hbenable_cmd_tlv(wmi_unified_t wmi_handle, 1253 wmi_hb_set_enable_cmd_fixed_param *params) 1254 { 1255 QDF_STATUS status; 1256 wmi_buf_t buf = NULL; 1257 uint8_t *buf_ptr; 1258 wmi_hb_set_enable_cmd_fixed_param *hb_enable_fp; 1259 int len = sizeof(wmi_hb_set_enable_cmd_fixed_param); 1260 1261 buf = wmi_buf_alloc(wmi_handle, len); 1262 if (!buf) { 1263 return QDF_STATUS_E_NOMEM; 1264 } 1265 1266 buf_ptr = (uint8_t *) wmi_buf_data(buf); 1267 hb_enable_fp = (wmi_hb_set_enable_cmd_fixed_param *) buf_ptr; 1268 WMITLV_SET_HDR(&hb_enable_fp->tlv_header, 1269 WMITLV_TAG_STRUC_wmi_hb_set_enable_cmd_fixed_param, 1270 WMITLV_GET_STRUCT_TLVLEN 1271 (wmi_hb_set_enable_cmd_fixed_param)); 1272 1273 /* fill in values */ 1274 hb_enable_fp->vdev_id = params->session; 1275 hb_enable_fp->enable = params->enable; 1276 hb_enable_fp->item = params->item; 1277 hb_enable_fp->session = params->session; 1278 1279 wmi_mtrace(WMI_HB_SET_ENABLE_CMDID, NO_SESSION, 0); 1280 status = wmi_unified_cmd_send(wmi_handle, buf, 1281 len, WMI_HB_SET_ENABLE_CMDID); 1282 if (QDF_IS_STATUS_ERROR(status)) { 1283 wmi_err("cmd_send WMI_HB_SET_ENABLE returned Error %d", 1284 status); 1285 wmi_buf_free(buf); 1286 } 1287 1288 return status; 1289 } 1290 1291 /** 1292 * send_lphb_config_tcp_params_cmd_tlv() - set tcp params of LPHB configuration 1293 * @wmi_handle: wmi handle 1294 * @lphb_conf_req: lphb config request 1295 * 1296 * Return: QDF status 1297 */ 1298 static QDF_STATUS send_lphb_config_tcp_params_cmd_tlv(wmi_unified_t wmi_handle, 1299 wmi_hb_set_tcp_params_cmd_fixed_param *lphb_conf_req) 1300 { 1301 QDF_STATUS status; 1302 wmi_buf_t buf = NULL; 1303 uint8_t *buf_ptr; 1304 wmi_hb_set_tcp_params_cmd_fixed_param *hb_tcp_params_fp; 1305 int len = sizeof(wmi_hb_set_tcp_params_cmd_fixed_param); 1306 1307 buf = wmi_buf_alloc(wmi_handle, len); 1308 if (!buf) { 1309 return QDF_STATUS_E_NOMEM; 1310 } 1311 1312 buf_ptr = (uint8_t *) wmi_buf_data(buf); 1313 hb_tcp_params_fp = (wmi_hb_set_tcp_params_cmd_fixed_param *) buf_ptr; 1314 WMITLV_SET_HDR(&hb_tcp_params_fp->tlv_header, 1315 WMITLV_TAG_STRUC_wmi_hb_set_tcp_params_cmd_fixed_param, 1316 WMITLV_GET_STRUCT_TLVLEN 1317 (wmi_hb_set_tcp_params_cmd_fixed_param)); 1318 1319 /* fill in values */ 1320 hb_tcp_params_fp->vdev_id = lphb_conf_req->vdev_id; 1321 hb_tcp_params_fp->srv_ip = lphb_conf_req->srv_ip; 1322 hb_tcp_params_fp->dev_ip = lphb_conf_req->dev_ip; 1323 hb_tcp_params_fp->seq = lphb_conf_req->seq; 1324 hb_tcp_params_fp->src_port = lphb_conf_req->src_port; 1325 hb_tcp_params_fp->dst_port = lphb_conf_req->dst_port; 1326 hb_tcp_params_fp->interval = lphb_conf_req->interval; 1327 hb_tcp_params_fp->timeout = lphb_conf_req->timeout; 1328 hb_tcp_params_fp->session = lphb_conf_req->session; 1329 qdf_mem_copy(&hb_tcp_params_fp->gateway_mac, 1330 &lphb_conf_req->gateway_mac, 1331 sizeof(hb_tcp_params_fp->gateway_mac)); 1332 1333 wmi_mtrace(WMI_HB_SET_TCP_PARAMS_CMDID, NO_SESSION, 0); 1334 status = wmi_unified_cmd_send(wmi_handle, buf, 1335 len, WMI_HB_SET_TCP_PARAMS_CMDID); 1336 if (QDF_IS_STATUS_ERROR(status)) { 1337 wmi_err("cmd_send WMI_HB_SET_TCP_PARAMS returned Error %d", 1338 status); 1339 wmi_buf_free(buf); 1340 } 1341 1342 return status; 1343 } 1344 1345 /** 1346 * send_lphb_config_tcp_pkt_filter_cmd_tlv() - configure tcp packet filter cmd 1347 * @wmi_handle: wmi handle 1348 * @g_hb_tcp_filter_fp: tcp packet filter params 1349 * 1350 * Return: QDF status 1351 */ 1352 static 1353 QDF_STATUS send_lphb_config_tcp_pkt_filter_cmd_tlv(wmi_unified_t wmi_handle, 1354 wmi_hb_set_tcp_pkt_filter_cmd_fixed_param *g_hb_tcp_filter_fp) 1355 { 1356 QDF_STATUS status; 1357 wmi_buf_t buf = NULL; 1358 uint8_t *buf_ptr; 1359 wmi_hb_set_tcp_pkt_filter_cmd_fixed_param *hb_tcp_filter_fp; 1360 int len = sizeof(wmi_hb_set_tcp_pkt_filter_cmd_fixed_param); 1361 1362 buf = wmi_buf_alloc(wmi_handle, len); 1363 if (!buf) { 1364 return QDF_STATUS_E_NOMEM; 1365 } 1366 1367 buf_ptr = (uint8_t *) wmi_buf_data(buf); 1368 hb_tcp_filter_fp = 1369 (wmi_hb_set_tcp_pkt_filter_cmd_fixed_param *) buf_ptr; 1370 WMITLV_SET_HDR(&hb_tcp_filter_fp->tlv_header, 1371 WMITLV_TAG_STRUC_wmi_hb_set_tcp_pkt_filter_cmd_fixed_param, 1372 WMITLV_GET_STRUCT_TLVLEN 1373 (wmi_hb_set_tcp_pkt_filter_cmd_fixed_param)); 1374 1375 /* fill in values */ 1376 hb_tcp_filter_fp->vdev_id = g_hb_tcp_filter_fp->vdev_id; 1377 hb_tcp_filter_fp->length = g_hb_tcp_filter_fp->length; 1378 hb_tcp_filter_fp->offset = g_hb_tcp_filter_fp->offset; 1379 hb_tcp_filter_fp->session = g_hb_tcp_filter_fp->session; 1380 memcpy((void *)&hb_tcp_filter_fp->filter, 1381 (void *)&g_hb_tcp_filter_fp->filter, 1382 WMI_WLAN_HB_MAX_FILTER_SIZE); 1383 1384 wmi_mtrace(WMI_HB_SET_TCP_PKT_FILTER_CMDID, NO_SESSION, 0); 1385 status = wmi_unified_cmd_send(wmi_handle, buf, 1386 len, WMI_HB_SET_TCP_PKT_FILTER_CMDID); 1387 if (QDF_IS_STATUS_ERROR(status)) { 1388 wmi_err("cmd_send WMI_HB_SET_TCP_PKT_FILTER returned Error %d", 1389 status); 1390 wmi_buf_free(buf); 1391 } 1392 1393 return status; 1394 } 1395 1396 /** 1397 * send_lphb_config_udp_params_cmd_tlv() - configure udp param command of LPHB 1398 * @wmi_handle: wmi handle 1399 * @lphb_conf_req: lphb config request 1400 * 1401 * Return: QDF status 1402 */ 1403 static QDF_STATUS send_lphb_config_udp_params_cmd_tlv(wmi_unified_t wmi_handle, 1404 wmi_hb_set_udp_params_cmd_fixed_param *lphb_conf_req) 1405 { 1406 QDF_STATUS status; 1407 wmi_buf_t buf = NULL; 1408 uint8_t *buf_ptr; 1409 wmi_hb_set_udp_params_cmd_fixed_param *hb_udp_params_fp; 1410 int len = sizeof(wmi_hb_set_udp_params_cmd_fixed_param); 1411 1412 buf = wmi_buf_alloc(wmi_handle, len); 1413 if (!buf) { 1414 return QDF_STATUS_E_NOMEM; 1415 } 1416 1417 buf_ptr = (uint8_t *) wmi_buf_data(buf); 1418 hb_udp_params_fp = (wmi_hb_set_udp_params_cmd_fixed_param *) buf_ptr; 1419 WMITLV_SET_HDR(&hb_udp_params_fp->tlv_header, 1420 WMITLV_TAG_STRUC_wmi_hb_set_udp_params_cmd_fixed_param, 1421 WMITLV_GET_STRUCT_TLVLEN 1422 (wmi_hb_set_udp_params_cmd_fixed_param)); 1423 1424 /* fill in values */ 1425 hb_udp_params_fp->vdev_id = lphb_conf_req->vdev_id; 1426 hb_udp_params_fp->srv_ip = lphb_conf_req->srv_ip; 1427 hb_udp_params_fp->dev_ip = lphb_conf_req->dev_ip; 1428 hb_udp_params_fp->src_port = lphb_conf_req->src_port; 1429 hb_udp_params_fp->dst_port = lphb_conf_req->dst_port; 1430 hb_udp_params_fp->interval = lphb_conf_req->interval; 1431 hb_udp_params_fp->timeout = lphb_conf_req->timeout; 1432 hb_udp_params_fp->session = lphb_conf_req->session; 1433 qdf_mem_copy(&hb_udp_params_fp->gateway_mac, 1434 &lphb_conf_req->gateway_mac, 1435 sizeof(lphb_conf_req->gateway_mac)); 1436 1437 wmi_mtrace(WMI_HB_SET_UDP_PARAMS_CMDID, NO_SESSION, 0); 1438 status = wmi_unified_cmd_send(wmi_handle, buf, 1439 len, WMI_HB_SET_UDP_PARAMS_CMDID); 1440 if (QDF_IS_STATUS_ERROR(status)) { 1441 wmi_err("cmd_send WMI_HB_SET_UDP_PARAMS returned Error %d", 1442 status); 1443 wmi_buf_free(buf); 1444 } 1445 1446 return status; 1447 } 1448 1449 /** 1450 * send_lphb_config_udp_pkt_filter_cmd_tlv() - configure udp pkt filter command 1451 * @wmi_handle: wmi handle 1452 * @lphb_conf_req: lphb config request 1453 * 1454 * Return: QDF status 1455 */ 1456 static 1457 QDF_STATUS send_lphb_config_udp_pkt_filter_cmd_tlv(wmi_unified_t wmi_handle, 1458 wmi_hb_set_udp_pkt_filter_cmd_fixed_param *lphb_conf_req) 1459 { 1460 QDF_STATUS status; 1461 wmi_buf_t buf = NULL; 1462 uint8_t *buf_ptr; 1463 wmi_hb_set_udp_pkt_filter_cmd_fixed_param *hb_udp_filter_fp; 1464 int len = sizeof(wmi_hb_set_udp_pkt_filter_cmd_fixed_param); 1465 1466 buf = wmi_buf_alloc(wmi_handle, len); 1467 if (!buf) { 1468 return QDF_STATUS_E_NOMEM; 1469 } 1470 1471 buf_ptr = (uint8_t *) wmi_buf_data(buf); 1472 hb_udp_filter_fp = 1473 (wmi_hb_set_udp_pkt_filter_cmd_fixed_param *) buf_ptr; 1474 WMITLV_SET_HDR(&hb_udp_filter_fp->tlv_header, 1475 WMITLV_TAG_STRUC_wmi_hb_set_udp_pkt_filter_cmd_fixed_param, 1476 WMITLV_GET_STRUCT_TLVLEN 1477 (wmi_hb_set_udp_pkt_filter_cmd_fixed_param)); 1478 1479 /* fill in values */ 1480 hb_udp_filter_fp->vdev_id = lphb_conf_req->vdev_id; 1481 hb_udp_filter_fp->length = lphb_conf_req->length; 1482 hb_udp_filter_fp->offset = lphb_conf_req->offset; 1483 hb_udp_filter_fp->session = lphb_conf_req->session; 1484 memcpy((void *)&hb_udp_filter_fp->filter, 1485 (void *)&lphb_conf_req->filter, 1486 WMI_WLAN_HB_MAX_FILTER_SIZE); 1487 1488 wmi_mtrace(WMI_HB_SET_UDP_PKT_FILTER_CMDID, NO_SESSION, 0); 1489 status = wmi_unified_cmd_send(wmi_handle, buf, 1490 len, WMI_HB_SET_UDP_PKT_FILTER_CMDID); 1491 if (QDF_IS_STATUS_ERROR(status)) { 1492 wmi_err("cmd_send WMI_HB_SET_UDP_PKT_FILTER returned Error %d", 1493 status); 1494 wmi_buf_free(buf); 1495 } 1496 1497 return status; 1498 } 1499 1500 void wmi_lphb_attach_tlv(struct wmi_unified *wmi_handle) 1501 { 1502 struct wmi_ops *ops = wmi_handle->ops; 1503 1504 ops->send_lphb_config_hbenable_cmd = 1505 send_lphb_config_hbenable_cmd_tlv; 1506 ops->send_lphb_config_tcp_params_cmd = 1507 send_lphb_config_tcp_params_cmd_tlv; 1508 ops->send_lphb_config_tcp_pkt_filter_cmd = 1509 send_lphb_config_tcp_pkt_filter_cmd_tlv; 1510 ops->send_lphb_config_udp_params_cmd = 1511 send_lphb_config_udp_params_cmd_tlv; 1512 ops->send_lphb_config_udp_pkt_filter_cmd = 1513 send_lphb_config_udp_pkt_filter_cmd_tlv; 1514 } 1515 #endif /* FEATURE_WLAN_LPHB */ 1516 1517 #ifdef WLAN_FEATURE_PACKET_FILTERING 1518 /** 1519 * send_enable_disable_packet_filter_cmd_tlv() - enable/disable packet filter 1520 * @wmi_handle: wmi handle 1521 * @vdev_id: vdev id 1522 * @enable: Flag to enable/disable packet filter 1523 * 1524 * Return: QDF_STATUS_SUCCESS for success or error code 1525 */ 1526 static QDF_STATUS send_enable_disable_packet_filter_cmd_tlv( 1527 wmi_unified_t wmi_handle, uint8_t vdev_id, bool enable) 1528 { 1529 int32_t len; 1530 int ret = 0; 1531 wmi_buf_t buf; 1532 WMI_PACKET_FILTER_ENABLE_CMD_fixed_param *cmd; 1533 1534 len = sizeof(WMI_PACKET_FILTER_ENABLE_CMD_fixed_param); 1535 1536 buf = wmi_buf_alloc(wmi_handle, len); 1537 if (!buf) { 1538 return QDF_STATUS_E_NOMEM; 1539 } 1540 1541 cmd = (WMI_PACKET_FILTER_ENABLE_CMD_fixed_param *) wmi_buf_data(buf); 1542 WMITLV_SET_HDR(&cmd->tlv_header, 1543 WMITLV_TAG_STRUC_wmi_packet_filter_enable_fixed_param, 1544 WMITLV_GET_STRUCT_TLVLEN( 1545 WMI_PACKET_FILTER_ENABLE_CMD_fixed_param)); 1546 1547 cmd->vdev_id = vdev_id; 1548 if (enable) 1549 cmd->enable = PACKET_FILTER_SET_ENABLE; 1550 else 1551 cmd->enable = PACKET_FILTER_SET_DISABLE; 1552 1553 wmi_err("Packet filter enable %d for vdev_id %d", cmd->enable, vdev_id); 1554 1555 wmi_mtrace(WMI_PACKET_FILTER_ENABLE_CMDID, cmd->vdev_id, 0); 1556 ret = wmi_unified_cmd_send(wmi_handle, buf, len, 1557 WMI_PACKET_FILTER_ENABLE_CMDID); 1558 if (ret) { 1559 wmi_err("Failed to send packet filter wmi cmd to fw"); 1560 wmi_buf_free(buf); 1561 } 1562 1563 return ret; 1564 } 1565 1566 /** 1567 * send_config_packet_filter_cmd_tlv() - configure packet filter in target 1568 * @wmi_handle: wmi handle 1569 * @vdev_id: vdev id 1570 * @rcv_filter_param: Packet filter parameters 1571 * @filter_id: Filter id 1572 * @enable: Flag to add/delete packet filter configuration 1573 * 1574 * Return: QDF_STATUS_SUCCESS for success or error code 1575 */ 1576 static QDF_STATUS send_config_packet_filter_cmd_tlv(wmi_unified_t wmi_handle, 1577 uint8_t vdev_id, struct pmo_rcv_pkt_fltr_cfg *rcv_filter_param, 1578 uint8_t filter_id, bool enable) 1579 { 1580 int len, i; 1581 int err = 0; 1582 wmi_buf_t buf; 1583 WMI_PACKET_FILTER_CONFIG_CMD_fixed_param *cmd; 1584 1585 /* allocate the memory */ 1586 len = sizeof(*cmd); 1587 buf = wmi_buf_alloc(wmi_handle, len); 1588 if (!buf) { 1589 return QDF_STATUS_E_NOMEM; 1590 } 1591 1592 cmd = (WMI_PACKET_FILTER_CONFIG_CMD_fixed_param *)wmi_buf_data(buf); 1593 WMITLV_SET_HDR(&cmd->tlv_header, 1594 WMITLV_TAG_STRUC_wmi_packet_filter_config_fixed_param, 1595 WMITLV_GET_STRUCT_TLVLEN 1596 (WMI_PACKET_FILTER_CONFIG_CMD_fixed_param)); 1597 1598 cmd->vdev_id = vdev_id; 1599 cmd->filter_id = filter_id; 1600 if (enable) 1601 cmd->filter_action = PACKET_FILTER_SET_ACTIVE; 1602 else 1603 cmd->filter_action = PACKET_FILTER_SET_INACTIVE; 1604 1605 if (enable) { 1606 cmd->num_params = QDF_MIN( 1607 WMI_PACKET_FILTER_MAX_CMP_PER_PACKET_FILTER, 1608 rcv_filter_param->num_params); 1609 cmd->filter_type = rcv_filter_param->filter_type; 1610 cmd->coalesce_time = rcv_filter_param->coalesce_time; 1611 1612 for (i = 0; i < cmd->num_params; i++) { 1613 cmd->paramsData[i].proto_type = 1614 rcv_filter_param->params_data[i].protocol_layer; 1615 cmd->paramsData[i].cmp_type = 1616 rcv_filter_param->params_data[i].compare_flag; 1617 cmd->paramsData[i].data_length = 1618 rcv_filter_param->params_data[i].data_length; 1619 cmd->paramsData[i].data_offset = 1620 rcv_filter_param->params_data[i].data_offset; 1621 memcpy(&cmd->paramsData[i].compareData, 1622 rcv_filter_param->params_data[i].compare_data, 1623 sizeof(cmd->paramsData[i].compareData)); 1624 memcpy(&cmd->paramsData[i].dataMask, 1625 rcv_filter_param->params_data[i].data_mask, 1626 sizeof(cmd->paramsData[i].dataMask)); 1627 } 1628 } 1629 1630 wmi_err("Packet filter action %d filter with id: %d, num_params=%d", 1631 cmd->filter_action, cmd->filter_id, cmd->num_params); 1632 /* send the command along with data */ 1633 wmi_mtrace(WMI_PACKET_FILTER_CONFIG_CMDID, cmd->vdev_id, 0); 1634 err = wmi_unified_cmd_send(wmi_handle, buf, len, 1635 WMI_PACKET_FILTER_CONFIG_CMDID); 1636 if (err) { 1637 wmi_err("Failed to send pkt_filter cmd"); 1638 wmi_buf_free(buf); 1639 return QDF_STATUS_E_FAILURE; 1640 } 1641 1642 return QDF_STATUS_SUCCESS; 1643 } 1644 1645 void wmi_packet_filtering_attach_tlv(struct wmi_unified *wmi_handle) 1646 { 1647 struct wmi_ops *ops = wmi_handle->ops; 1648 1649 ops->send_enable_disable_packet_filter_cmd = 1650 send_enable_disable_packet_filter_cmd_tlv; 1651 ops->send_config_packet_filter_cmd = 1652 send_config_packet_filter_cmd_tlv; 1653 } 1654 #endif /* WLAN_FEATURE_PACKET_FILTERING */ 1655 1656 /** 1657 * send_wow_delete_pattern_cmd_tlv() - delete wow pattern in target 1658 * @wmi_handle: wmi handle 1659 * @ptrn_id: pattern id 1660 * @vdev_id: vdev id 1661 * 1662 * Return: QDF status 1663 */ 1664 static QDF_STATUS send_wow_delete_pattern_cmd_tlv(wmi_unified_t wmi_handle, 1665 uint8_t ptrn_id, 1666 uint8_t vdev_id) 1667 { 1668 WMI_WOW_DEL_PATTERN_CMD_fixed_param *cmd; 1669 wmi_buf_t buf; 1670 int32_t len; 1671 int ret; 1672 1673 len = sizeof(WMI_WOW_DEL_PATTERN_CMD_fixed_param); 1674 1675 buf = wmi_buf_alloc(wmi_handle, len); 1676 if (!buf) { 1677 return QDF_STATUS_E_NOMEM; 1678 } 1679 1680 cmd = (WMI_WOW_DEL_PATTERN_CMD_fixed_param *) wmi_buf_data(buf); 1681 1682 WMITLV_SET_HDR(&cmd->tlv_header, 1683 WMITLV_TAG_STRUC_WMI_WOW_DEL_PATTERN_CMD_fixed_param, 1684 WMITLV_GET_STRUCT_TLVLEN( 1685 WMI_WOW_DEL_PATTERN_CMD_fixed_param)); 1686 cmd->vdev_id = vdev_id; 1687 cmd->pattern_id = ptrn_id; 1688 cmd->pattern_type = WOW_BITMAP_PATTERN; 1689 1690 wmi_mtrace(WMI_WOW_DEL_WAKE_PATTERN_CMDID, cmd->vdev_id, 0); 1691 ret = wmi_unified_cmd_send(wmi_handle, buf, len, 1692 WMI_WOW_DEL_WAKE_PATTERN_CMDID); 1693 if (ret) { 1694 wmi_err("Failed to delete wow ptrn from fw"); 1695 wmi_buf_free(buf); 1696 return QDF_STATUS_E_FAILURE; 1697 } 1698 1699 return QDF_STATUS_SUCCESS; 1700 } 1701 1702 #ifdef WMI_HOST_WAKEUP_OVER_QMI 1703 static inline 1704 QDF_STATUS wmi_unified_cmd_send_chk(struct wmi_unified *wmi_handle, 1705 wmi_buf_t buf, 1706 uint32_t buflen, uint32_t cmd_id) 1707 { 1708 wmi_debug("Send WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID over QMI"); 1709 return wmi_unified_cmd_send_over_qmi(wmi_handle, buf, 1710 buflen, cmd_id); 1711 } 1712 #else 1713 static inline 1714 QDF_STATUS wmi_unified_cmd_send_chk(struct wmi_unified *wmi_handle, 1715 wmi_buf_t buf, 1716 uint32_t buflen, uint32_t cmd_id) 1717 { 1718 return wmi_unified_cmd_send(wmi_handle, buf, 1719 buflen, cmd_id); 1720 } 1721 #endif 1722 1723 /** 1724 * send_host_wakeup_ind_to_fw_cmd_tlv() - send wakeup ind to fw 1725 * @wmi_handle: wmi handle 1726 * @tx_pending_ind: flag of TX has pending frames 1727 * 1728 * Sends host wakeup indication to FW. On receiving this indication, 1729 * FW will come out of WOW. 1730 * 1731 * Return: QDF status 1732 */ 1733 static QDF_STATUS send_host_wakeup_ind_to_fw_cmd_tlv(wmi_unified_t wmi_handle, 1734 bool tx_pending_ind) 1735 { 1736 wmi_wow_hostwakeup_from_sleep_cmd_fixed_param *cmd; 1737 wmi_buf_t buf; 1738 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS; 1739 int32_t len; 1740 int ret; 1741 1742 len = sizeof(wmi_wow_hostwakeup_from_sleep_cmd_fixed_param); 1743 1744 buf = wmi_buf_alloc(wmi_handle, len); 1745 if (!buf) { 1746 return QDF_STATUS_E_NOMEM; 1747 } 1748 1749 cmd = (wmi_wow_hostwakeup_from_sleep_cmd_fixed_param *) 1750 wmi_buf_data(buf); 1751 1752 if (tx_pending_ind) { 1753 wmi_debug("TX pending before WoW wake, indicate FW"); 1754 cmd->flags |= WMI_WOW_RESUME_FLAG_TX_DATA; 1755 } 1756 1757 WMITLV_SET_HDR(&cmd->tlv_header, 1758 WMITLV_TAG_STRUC_wmi_wow_hostwakeup_from_sleep_cmd_fixed_param, 1759 WMITLV_GET_STRUCT_TLVLEN 1760 (wmi_wow_hostwakeup_from_sleep_cmd_fixed_param)); 1761 1762 wmi_mtrace(WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID, NO_SESSION, 0); 1763 ret = wmi_unified_cmd_send_chk(wmi_handle, buf, len, 1764 WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID); 1765 if (ret) { 1766 wmi_err("Failed to send host wakeup indication to fw"); 1767 wmi_buf_free(buf); 1768 return QDF_STATUS_E_FAILURE; 1769 } 1770 1771 return qdf_status; 1772 } 1773 1774 /** 1775 * send_wow_timer_pattern_cmd_tlv() - set timer pattern tlv, so that firmware 1776 * will wake up host after specified time is elapsed 1777 * @wmi_handle: wmi handle 1778 * @vdev_id: vdev id 1779 * @cookie: value to identify reason why host set up wake call. 1780 * @time: time in ms 1781 * 1782 * Return: QDF status 1783 */ 1784 static QDF_STATUS send_wow_timer_pattern_cmd_tlv(wmi_unified_t wmi_handle, 1785 uint8_t vdev_id, uint32_t cookie, uint32_t time) 1786 { 1787 WMI_WOW_ADD_PATTERN_CMD_fixed_param *cmd; 1788 wmi_buf_t buf; 1789 uint8_t *buf_ptr; 1790 int32_t len; 1791 int ret; 1792 1793 len = sizeof(WMI_WOW_ADD_PATTERN_CMD_fixed_param) + 1794 WMI_TLV_HDR_SIZE + 0 * sizeof(WOW_BITMAP_PATTERN_T) + 1795 WMI_TLV_HDR_SIZE + 0 * sizeof(WOW_IPV4_SYNC_PATTERN_T) + 1796 WMI_TLV_HDR_SIZE + 0 * sizeof(WOW_IPV6_SYNC_PATTERN_T) + 1797 WMI_TLV_HDR_SIZE + 0 * sizeof(WOW_MAGIC_PATTERN_CMD) + 1798 WMI_TLV_HDR_SIZE + 1 * sizeof(uint32_t) + 1799 WMI_TLV_HDR_SIZE + 1 * sizeof(uint32_t); 1800 1801 buf = wmi_buf_alloc(wmi_handle, len); 1802 if (!buf) { 1803 return QDF_STATUS_E_NOMEM; 1804 } 1805 1806 cmd = (WMI_WOW_ADD_PATTERN_CMD_fixed_param *) wmi_buf_data(buf); 1807 buf_ptr = (uint8_t *) cmd; 1808 1809 WMITLV_SET_HDR(&cmd->tlv_header, 1810 WMITLV_TAG_STRUC_WMI_WOW_ADD_PATTERN_CMD_fixed_param, 1811 WMITLV_GET_STRUCT_TLVLEN 1812 (WMI_WOW_ADD_PATTERN_CMD_fixed_param)); 1813 cmd->vdev_id = vdev_id; 1814 cmd->pattern_id = cookie, 1815 cmd->pattern_type = WOW_TIMER_PATTERN; 1816 buf_ptr += sizeof(WMI_WOW_ADD_PATTERN_CMD_fixed_param); 1817 1818 /* Fill TLV for WMITLV_TAG_STRUC_WOW_BITMAP_PATTERN_T but no data. */ 1819 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0); 1820 buf_ptr += WMI_TLV_HDR_SIZE; 1821 1822 /* Fill TLV for WMITLV_TAG_STRUC_WOW_IPV4_SYNC_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_IPV6_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_MAGIC_PATTERN_CMD 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 pattern_info_timeout, and time value */ 1835 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, sizeof(uint32_t)); 1836 buf_ptr += WMI_TLV_HDR_SIZE; 1837 *((uint32_t *) buf_ptr) = time; 1838 buf_ptr += sizeof(uint32_t); 1839 1840 /* Fill TLV for ra_ratelimit_interval. with dummy 0 value */ 1841 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, sizeof(uint32_t)); 1842 buf_ptr += WMI_TLV_HDR_SIZE; 1843 *((uint32_t *) buf_ptr) = 0; 1844 1845 wmi_debug("send wake timer pattern with time[%d] to fw vdev = %d", 1846 time, vdev_id); 1847 1848 wmi_mtrace(WMI_WOW_ADD_WAKE_PATTERN_CMDID, cmd->vdev_id, 0); 1849 ret = wmi_unified_cmd_send(wmi_handle, buf, len, 1850 WMI_WOW_ADD_WAKE_PATTERN_CMDID); 1851 if (ret) { 1852 wmi_err("Failed to send wake timer pattern to fw"); 1853 wmi_buf_free(buf); 1854 return QDF_STATUS_E_FAILURE; 1855 } 1856 1857 return QDF_STATUS_SUCCESS; 1858 } 1859 1860 #ifdef WLAN_FEATURE_EXTWOW_SUPPORT 1861 /** 1862 * send_enable_ext_wow_cmd_tlv() - enable ext wow in fw 1863 * @wmi_handle: wmi handle 1864 * @params: ext wow params 1865 * 1866 * Return:0 for success or error code 1867 */ 1868 static QDF_STATUS send_enable_ext_wow_cmd_tlv(wmi_unified_t wmi_handle, 1869 struct ext_wow_params *params) 1870 { 1871 wmi_extwow_enable_cmd_fixed_param *cmd; 1872 wmi_buf_t buf; 1873 int32_t len; 1874 int ret; 1875 1876 len = sizeof(wmi_extwow_enable_cmd_fixed_param); 1877 buf = wmi_buf_alloc(wmi_handle, len); 1878 if (!buf) { 1879 return QDF_STATUS_E_NOMEM; 1880 } 1881 1882 cmd = (wmi_extwow_enable_cmd_fixed_param *) wmi_buf_data(buf); 1883 1884 WMITLV_SET_HDR(&cmd->tlv_header, 1885 WMITLV_TAG_STRUC_wmi_extwow_enable_cmd_fixed_param, 1886 WMITLV_GET_STRUCT_TLVLEN 1887 (wmi_extwow_enable_cmd_fixed_param)); 1888 1889 cmd->vdev_id = params->vdev_id; 1890 cmd->type = params->type; 1891 cmd->wakeup_pin_num = params->wakeup_pin_num; 1892 1893 wmi_debug("vdev_id %d type %d Wakeup_pin_num %x", 1894 cmd->vdev_id, cmd->type, cmd->wakeup_pin_num); 1895 1896 wmi_mtrace(WMI_EXTWOW_ENABLE_CMDID, cmd->vdev_id, 0); 1897 ret = wmi_unified_cmd_send(wmi_handle, buf, len, 1898 WMI_EXTWOW_ENABLE_CMDID); 1899 if (ret) { 1900 wmi_err("Failed to set EXTWOW Enable"); 1901 wmi_buf_free(buf); 1902 return QDF_STATUS_E_FAILURE; 1903 } 1904 1905 return QDF_STATUS_SUCCESS; 1906 1907 } 1908 1909 /** 1910 * send_set_app_type2_params_in_fw_cmd_tlv() - set app type2 params in fw 1911 * @wmi_handle: wmi handle 1912 * @appType2Params: app type2 params 1913 * 1914 * Return: QDF status 1915 */ 1916 static QDF_STATUS send_set_app_type2_params_in_fw_cmd_tlv(wmi_unified_t wmi_handle, 1917 struct app_type2_params *appType2Params) 1918 { 1919 wmi_extwow_set_app_type2_params_cmd_fixed_param *cmd; 1920 wmi_buf_t buf; 1921 int32_t len; 1922 int ret; 1923 1924 len = sizeof(wmi_extwow_set_app_type2_params_cmd_fixed_param); 1925 buf = wmi_buf_alloc(wmi_handle, len); 1926 if (!buf) { 1927 return QDF_STATUS_E_NOMEM; 1928 } 1929 1930 cmd = (wmi_extwow_set_app_type2_params_cmd_fixed_param *) 1931 wmi_buf_data(buf); 1932 1933 WMITLV_SET_HDR(&cmd->tlv_header, 1934 WMITLV_TAG_STRUC_wmi_extwow_set_app_type2_params_cmd_fixed_param, 1935 WMITLV_GET_STRUCT_TLVLEN 1936 (wmi_extwow_set_app_type2_params_cmd_fixed_param)); 1937 1938 cmd->vdev_id = appType2Params->vdev_id; 1939 1940 qdf_mem_copy(cmd->rc4_key, appType2Params->rc4_key, 16); 1941 cmd->rc4_key_len = appType2Params->rc4_key_len; 1942 1943 cmd->ip_id = appType2Params->ip_id; 1944 cmd->ip_device_ip = appType2Params->ip_device_ip; 1945 cmd->ip_server_ip = appType2Params->ip_server_ip; 1946 1947 cmd->tcp_src_port = appType2Params->tcp_src_port; 1948 cmd->tcp_dst_port = appType2Params->tcp_dst_port; 1949 cmd->tcp_seq = appType2Params->tcp_seq; 1950 cmd->tcp_ack_seq = appType2Params->tcp_ack_seq; 1951 1952 cmd->keepalive_init = appType2Params->keepalive_init; 1953 cmd->keepalive_min = appType2Params->keepalive_min; 1954 cmd->keepalive_max = appType2Params->keepalive_max; 1955 cmd->keepalive_inc = appType2Params->keepalive_inc; 1956 1957 WMI_CHAR_ARRAY_TO_MAC_ADDR(appType2Params->gateway_mac.bytes, 1958 &cmd->gateway_mac); 1959 cmd->tcp_tx_timeout_val = appType2Params->tcp_tx_timeout_val; 1960 cmd->tcp_rx_timeout_val = appType2Params->tcp_rx_timeout_val; 1961 1962 wmi_debug("vdev_id %d gateway_mac "QDF_MAC_ADDR_FMT" " 1963 "rc4_key %.16s rc4_key_len %u " 1964 "ip_id %x ip_device_ip %x ip_server_ip %x " 1965 "tcp_src_port %u tcp_dst_port %u tcp_seq %u " 1966 "tcp_ack_seq %u keepalive_init %u keepalive_min %u " 1967 "keepalive_max %u keepalive_inc %u " 1968 "tcp_tx_timeout_val %u tcp_rx_timeout_val %u", 1969 cmd->vdev_id, 1970 QDF_MAC_ADDR_REF(appType2Params->gateway_mac.bytes), 1971 cmd->rc4_key, cmd->rc4_key_len, 1972 cmd->ip_id, cmd->ip_device_ip, cmd->ip_server_ip, 1973 cmd->tcp_src_port, cmd->tcp_dst_port, cmd->tcp_seq, 1974 cmd->tcp_ack_seq, cmd->keepalive_init, cmd->keepalive_min, 1975 cmd->keepalive_max, cmd->keepalive_inc, 1976 cmd->tcp_tx_timeout_val, cmd->tcp_rx_timeout_val); 1977 1978 wmi_mtrace(WMI_EXTWOW_SET_APP_TYPE2_PARAMS_CMDID, cmd->vdev_id, 0); 1979 ret = wmi_unified_cmd_send(wmi_handle, buf, len, 1980 WMI_EXTWOW_SET_APP_TYPE2_PARAMS_CMDID); 1981 if (ret) { 1982 wmi_err("Failed to set APP TYPE2 PARAMS"); 1983 wmi_buf_free(buf); 1984 return QDF_STATUS_E_FAILURE; 1985 } 1986 1987 return QDF_STATUS_SUCCESS; 1988 1989 } 1990 1991 /** 1992 * send_app_type1_params_in_fw_cmd_tlv() - set app type1 params in fw 1993 * @wmi_handle: wmi handle 1994 * @app_type1_params: app type1 params 1995 * 1996 * Return: QDF status 1997 */ 1998 static QDF_STATUS send_app_type1_params_in_fw_cmd_tlv(wmi_unified_t wmi_handle, 1999 struct app_type1_params *app_type1_params) 2000 { 2001 wmi_extwow_set_app_type1_params_cmd_fixed_param *cmd; 2002 wmi_buf_t buf; 2003 int32_t len; 2004 int ret; 2005 2006 len = sizeof(wmi_extwow_set_app_type1_params_cmd_fixed_param); 2007 buf = wmi_buf_alloc(wmi_handle, len); 2008 if (!buf) { 2009 return QDF_STATUS_E_NOMEM; 2010 } 2011 2012 cmd = (wmi_extwow_set_app_type1_params_cmd_fixed_param *) 2013 wmi_buf_data(buf); 2014 2015 WMITLV_SET_HDR(&cmd->tlv_header, 2016 WMITLV_TAG_STRUC_wmi_extwow_set_app_type1_params_cmd_fixed_param, 2017 WMITLV_GET_STRUCT_TLVLEN 2018 (wmi_extwow_set_app_type1_params_cmd_fixed_param)); 2019 2020 cmd->vdev_id = app_type1_params->vdev_id; 2021 WMI_CHAR_ARRAY_TO_MAC_ADDR(app_type1_params->wakee_mac_addr.bytes, 2022 &cmd->wakee_mac); 2023 qdf_mem_copy(cmd->ident, app_type1_params->identification_id, 8); 2024 cmd->ident_len = app_type1_params->id_length; 2025 qdf_mem_copy(cmd->passwd, app_type1_params->password, 16); 2026 cmd->passwd_len = app_type1_params->pass_length; 2027 2028 wmi_debug("vdev_id %d wakee_mac_addr "QDF_MAC_ADDR_FMT" " 2029 "identification_id %.8s id_length %u " 2030 "password %.16s pass_length %u", 2031 cmd->vdev_id, 2032 QDF_MAC_ADDR_REF(app_type1_params->wakee_mac_addr.bytes), 2033 cmd->ident, cmd->ident_len, cmd->passwd, cmd->passwd_len); 2034 2035 wmi_mtrace(WMI_EXTWOW_SET_APP_TYPE1_PARAMS_CMDID, cmd->vdev_id, 0); 2036 ret = wmi_unified_cmd_send(wmi_handle, buf, len, 2037 WMI_EXTWOW_SET_APP_TYPE1_PARAMS_CMDID); 2038 if (ret) { 2039 wmi_err("Failed to set APP TYPE1 PARAMS"); 2040 wmi_buf_free(buf); 2041 return QDF_STATUS_E_FAILURE; 2042 } 2043 2044 return QDF_STATUS_SUCCESS; 2045 } 2046 2047 void wmi_extwow_attach_tlv(struct wmi_unified *wmi_handle) 2048 { 2049 struct wmi_ops *ops = wmi_handle->ops; 2050 2051 ops->send_enable_ext_wow_cmd = send_enable_ext_wow_cmd_tlv; 2052 ops->send_set_app_type2_params_in_fw_cmd = 2053 send_set_app_type2_params_in_fw_cmd_tlv; 2054 ops->send_app_type1_params_in_fw_cmd = 2055 send_app_type1_params_in_fw_cmd_tlv; 2056 } 2057 #endif /* WLAN_FEATURE_EXTWOW_SUPPORT */ 2058 2059 #ifdef WLAN_FEATURE_ICMP_OFFLOAD 2060 /** 2061 * send_icmp_ipv4_config_cmd_tlv() - send ICMP IPV4 offload command to fw 2062 * @wmi_handle: wmi handle 2063 * @pmo_icmp_req: ICMP offload parameters 2064 * 2065 * Return: QDF status 2066 */ 2067 static QDF_STATUS 2068 send_icmp_ipv4_config_cmd_tlv(wmi_unified_t wmi_handle, 2069 struct pmo_icmp_offload *pmo_icmp_req) 2070 { 2071 wmi_buf_t buf; 2072 wmi_icmp_offload_fixed_param *cmd; 2073 uint16_t len = sizeof(*cmd); 2074 QDF_STATUS status; 2075 2076 buf = wmi_buf_alloc(wmi_handle, len); 2077 if (!buf) { 2078 wmi_err_rl("Failed to allocate wmi buffer"); 2079 status = QDF_STATUS_E_NOMEM; 2080 return status; 2081 } 2082 cmd = (wmi_icmp_offload_fixed_param *)wmi_buf_data(buf); 2083 WMITLV_SET_HDR(&cmd->tlv_header, 2084 WMITLV_TAG_STRUC_wmi_icmp_offload_fixed_param, 2085 WMITLV_GET_STRUCT_TLVLEN(wmi_icmp_offload_fixed_param)); 2086 2087 cmd->vdev_id = pmo_icmp_req->vdev_id; 2088 cmd->enable = pmo_icmp_req->enable; 2089 cmd->valid_bitmask = 0; 2090 2091 WMI_SET_ICMP_OFFLOAD_IPV4_ENABLED_BIT(cmd->valid_bitmask); 2092 qdf_mem_copy(&cmd->ipv4_addr, pmo_icmp_req->ipv4_addr, 2093 QDF_IPV4_ADDR_SIZE); 2094 wmi_debug("ipv4:%pI4", &cmd->ipv4_addr); 2095 2096 wmi_mtrace(WMI_VDEV_ICMP_OFFLOAD_CMDID, cmd->vdev_id, 0); 2097 status = wmi_unified_cmd_send(wmi_handle, buf, len, 2098 WMI_VDEV_ICMP_OFFLOAD_CMDID); 2099 2100 if (QDF_IS_STATUS_ERROR(status)) 2101 wmi_buf_free(buf); 2102 2103 return status; 2104 } 2105 2106 /** 2107 * send_icmp_ipv6_config_cmd_tlv() - send ICMP IPV6 offload command to fw 2108 * @wmi_handle: wmi handle 2109 * @pmo_icmp_req: ICMP offload parameters 2110 * 2111 * Return: QDF status 2112 */ 2113 static QDF_STATUS 2114 send_icmp_ipv6_config_cmd_tlv(wmi_unified_t wmi_handle, 2115 struct pmo_icmp_offload *pmo_icmp_req) 2116 { 2117 wmi_buf_t buf; 2118 uint8_t *buf_ptr; 2119 uint16_t len; 2120 int i; 2121 WMI_IPV6_ADDR *ipv6_list; 2122 wmi_icmp_offload_fixed_param *cmd; 2123 QDF_STATUS status; 2124 2125 len = sizeof(wmi_icmp_offload_fixed_param) + WMI_TLV_HDR_SIZE + 2126 (pmo_icmp_req->ipv6_count) * sizeof(WMI_IPV6_ADDR); 2127 2128 buf = wmi_buf_alloc(wmi_handle, len); 2129 if (!buf) { 2130 wmi_err_rl("Failed to allocate wmi buffer"); 2131 status = QDF_STATUS_E_NOMEM; 2132 return status; 2133 } 2134 2135 buf_ptr = (uint8_t *)wmi_buf_data(buf); 2136 cmd = (wmi_icmp_offload_fixed_param *)wmi_buf_data(buf); 2137 WMITLV_SET_HDR(&cmd->tlv_header, 2138 WMITLV_TAG_STRUC_wmi_icmp_offload_fixed_param, 2139 WMITLV_GET_STRUCT_TLVLEN(wmi_icmp_offload_fixed_param)); 2140 2141 cmd->vdev_id = pmo_icmp_req->vdev_id; 2142 cmd->enable = pmo_icmp_req->enable; 2143 cmd->valid_bitmask = 0; 2144 2145 WMI_SET_ICMP_OFFLOAD_IPV6_ENABLED_BIT(cmd->valid_bitmask); 2146 buf_ptr += sizeof(*cmd); 2147 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_FIXED_STRUC, 2148 sizeof(WMI_IPV6_ADDR) * pmo_icmp_req->ipv6_count); 2149 ipv6_list = (WMI_IPV6_ADDR *)(buf_ptr + WMI_TLV_HDR_SIZE); 2150 2151 for (i = 0; i < pmo_icmp_req->ipv6_count; i++) { 2152 qdf_mem_copy(((*(ipv6_list + i)).address), 2153 &pmo_icmp_req->ipv6_addr[i], 2154 sizeof(WMI_IPV6_ADDR)); 2155 wmi_debug("ipv6_list[%d]:%pI6", i, (ipv6_list + i)); 2156 } 2157 2158 /* send the wmi command */ 2159 wmi_mtrace(WMI_VDEV_ICMP_OFFLOAD_CMDID, cmd->vdev_id, 0); 2160 status = wmi_unified_cmd_send(wmi_handle, buf, len, 2161 WMI_VDEV_ICMP_OFFLOAD_CMDID); 2162 2163 if (QDF_IS_STATUS_ERROR(status)) 2164 wmi_buf_free(buf); 2165 2166 return status; 2167 } 2168 2169 /** 2170 * send_icmp_offload_config_cmd_tlv() - send ICMP offload command to fw 2171 * @wmi_handle: wmi handle 2172 * @pmo_icmp_req: ICMP offload parameters 2173 * 2174 * Return: QDF status 2175 */ 2176 static QDF_STATUS 2177 send_icmp_offload_config_cmd_tlv(wmi_unified_t wmi_handle, 2178 struct pmo_icmp_offload *pmo_icmp_req) 2179 { 2180 QDF_STATUS status; 2181 2182 switch (pmo_icmp_req->trigger) { 2183 case pmo_ipv4_change_notify: 2184 status = send_icmp_ipv4_config_cmd_tlv(wmi_handle, 2185 pmo_icmp_req); 2186 break; 2187 case pmo_ipv6_change_notify: 2188 status = send_icmp_ipv6_config_cmd_tlv(wmi_handle, 2189 pmo_icmp_req); 2190 break; 2191 default: 2192 QDF_DEBUG_PANIC("Invalid ICMP trigger %d", 2193 pmo_icmp_req->trigger); 2194 status = QDF_STATUS_E_FAILURE; 2195 } 2196 2197 return status; 2198 } 2199 2200 static void wmi_icmp_offload_config_tlv(struct wmi_unified *wmi_handle) 2201 { 2202 struct wmi_ops *ops = wmi_handle->ops; 2203 2204 ops->send_icmp_offload_config_cmd = send_icmp_offload_config_cmd_tlv; 2205 } 2206 #else 2207 static inline void wmi_icmp_offload_config_tlv(struct wmi_unified *wmi_handle) 2208 {} 2209 #endif /* WLAN_FEATURE_ICMP_OFFLOAD */ 2210 2211 void wmi_pmo_attach_tlv(wmi_unified_t wmi_handle) 2212 { 2213 struct wmi_ops *ops = wmi_handle->ops; 2214 2215 ops->send_add_wow_wakeup_event_cmd = 2216 send_add_wow_wakeup_event_cmd_tlv; 2217 ops->send_wow_patterns_to_fw_cmd = send_wow_patterns_to_fw_cmd_tlv; 2218 ops->send_enable_arp_ns_offload_cmd = 2219 send_enable_arp_ns_offload_cmd_tlv; 2220 ops->send_add_clear_mcbc_filter_cmd = 2221 send_add_clear_mcbc_filter_cmd_tlv; 2222 ops->send_multiple_add_clear_mcbc_filter_cmd = 2223 send_multiple_add_clear_mcbc_filter_cmd_tlv; 2224 ops->send_conf_hw_filter_cmd = send_conf_hw_filter_cmd_tlv; 2225 ops->send_gtk_offload_cmd = send_gtk_offload_cmd_tlv; 2226 #ifdef WLAN_FEATURE_IGMP_OFFLOAD 2227 ops->send_igmp_offload_cmd = send_igmp_offload_cmd_tlv; 2228 #endif 2229 ops->send_process_gtk_offload_getinfo_cmd = 2230 send_process_gtk_offload_getinfo_cmd_tlv; 2231 ops->send_enable_enhance_multicast_offload_cmd = 2232 send_enable_enhance_multicast_offload_tlv; 2233 ops->extract_gtk_rsp_event = extract_gtk_rsp_event_tlv; 2234 ops->send_action_frame_patterns_cmd = 2235 send_action_frame_patterns_cmd_tlv; 2236 ops->send_wow_delete_pattern_cmd = send_wow_delete_pattern_cmd_tlv; 2237 ops->send_host_wakeup_ind_to_fw_cmd = 2238 send_host_wakeup_ind_to_fw_cmd_tlv; 2239 ops->send_wow_timer_pattern_cmd = send_wow_timer_pattern_cmd_tlv; 2240 2241 wmi_d0wow_attach_tlv(wmi_handle); 2242 wmi_ra_filtering_attach_tlv(wmi_handle); 2243 wmi_lphb_attach_tlv(wmi_handle); 2244 wmi_packet_filtering_attach_tlv(wmi_handle); 2245 wmi_extwow_attach_tlv(wmi_handle); 2246 wmi_icmp_offload_config_tlv(wmi_handle); 2247 } 2248