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