1 /* 2 * Copyright (c) 2005-2011 Atheros Communications Inc. 3 * Copyright (c) 2011-2014 Qualcomm Atheros, Inc. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 #include "core.h" 18 #include "debug.h" 19 #include "hw.h" 20 #include "wmi.h" 21 #include "wmi-ops.h" 22 #include "wmi-tlv.h" 23 24 /***************/ 25 /* TLV helpers */ 26 /**************/ 27 28 struct wmi_tlv_policy { 29 size_t min_len; 30 }; 31 32 static const struct wmi_tlv_policy wmi_tlv_policies[] = { 33 [WMI_TLV_TAG_ARRAY_BYTE] 34 = { .min_len = sizeof(u8) }, 35 [WMI_TLV_TAG_ARRAY_UINT32] 36 = { .min_len = sizeof(u32) }, 37 [WMI_TLV_TAG_STRUCT_SCAN_EVENT] 38 = { .min_len = sizeof(struct wmi_scan_event) }, 39 [WMI_TLV_TAG_STRUCT_MGMT_RX_HDR] 40 = { .min_len = sizeof(struct wmi_tlv_mgmt_rx_ev) }, 41 [WMI_TLV_TAG_STRUCT_CHAN_INFO_EVENT] 42 = { .min_len = sizeof(struct wmi_chan_info_event) }, 43 [WMI_TLV_TAG_STRUCT_VDEV_START_RESPONSE_EVENT] 44 = { .min_len = sizeof(struct wmi_vdev_start_response_event) }, 45 [WMI_TLV_TAG_STRUCT_PEER_STA_KICKOUT_EVENT] 46 = { .min_len = sizeof(struct wmi_peer_sta_kickout_event) }, 47 [WMI_TLV_TAG_STRUCT_HOST_SWBA_EVENT] 48 = { .min_len = sizeof(struct wmi_host_swba_event) }, 49 [WMI_TLV_TAG_STRUCT_TIM_INFO] 50 = { .min_len = sizeof(struct wmi_tim_info) }, 51 [WMI_TLV_TAG_STRUCT_P2P_NOA_INFO] 52 = { .min_len = sizeof(struct wmi_p2p_noa_info) }, 53 [WMI_TLV_TAG_STRUCT_SERVICE_READY_EVENT] 54 = { .min_len = sizeof(struct wmi_tlv_svc_rdy_ev) }, 55 [WMI_TLV_TAG_STRUCT_HAL_REG_CAPABILITIES] 56 = { .min_len = sizeof(struct hal_reg_capabilities) }, 57 [WMI_TLV_TAG_STRUCT_WLAN_HOST_MEM_REQ] 58 = { .min_len = sizeof(struct wlan_host_mem_req) }, 59 [WMI_TLV_TAG_STRUCT_READY_EVENT] 60 = { .min_len = sizeof(struct wmi_tlv_rdy_ev) }, 61 [WMI_TLV_TAG_STRUCT_OFFLOAD_BCN_TX_STATUS_EVENT] 62 = { .min_len = sizeof(struct wmi_tlv_bcn_tx_status_ev) }, 63 [WMI_TLV_TAG_STRUCT_DIAG_DATA_CONTAINER_EVENT] 64 = { .min_len = sizeof(struct wmi_tlv_diag_data_ev) }, 65 }; 66 67 static int 68 ath10k_wmi_tlv_iter(struct ath10k *ar, const void *ptr, size_t len, 69 int (*iter)(struct ath10k *ar, u16 tag, u16 len, 70 const void *ptr, void *data), 71 void *data) 72 { 73 const void *begin = ptr; 74 const struct wmi_tlv *tlv; 75 u16 tlv_tag, tlv_len; 76 int ret; 77 78 while (len > 0) { 79 if (len < sizeof(*tlv)) { 80 ath10k_dbg(ar, ATH10K_DBG_WMI, 81 "wmi tlv parse failure at byte %zd (%zu bytes left, %zu expected)\n", 82 ptr - begin, len, sizeof(*tlv)); 83 return -EINVAL; 84 } 85 86 tlv = ptr; 87 tlv_tag = __le16_to_cpu(tlv->tag); 88 tlv_len = __le16_to_cpu(tlv->len); 89 ptr += sizeof(*tlv); 90 len -= sizeof(*tlv); 91 92 if (tlv_len > len) { 93 ath10k_dbg(ar, ATH10K_DBG_WMI, 94 "wmi tlv parse failure of tag %hhu at byte %zd (%zu bytes left, %hhu expected)\n", 95 tlv_tag, ptr - begin, len, tlv_len); 96 return -EINVAL; 97 } 98 99 if (tlv_tag < ARRAY_SIZE(wmi_tlv_policies) && 100 wmi_tlv_policies[tlv_tag].min_len && 101 wmi_tlv_policies[tlv_tag].min_len > tlv_len) { 102 ath10k_dbg(ar, ATH10K_DBG_WMI, 103 "wmi tlv parse failure of tag %hhu at byte %zd (%hhu bytes is less than min length %zu)\n", 104 tlv_tag, ptr - begin, tlv_len, 105 wmi_tlv_policies[tlv_tag].min_len); 106 return -EINVAL; 107 } 108 109 ret = iter(ar, tlv_tag, tlv_len, ptr, data); 110 if (ret) 111 return ret; 112 113 ptr += tlv_len; 114 len -= tlv_len; 115 } 116 117 return 0; 118 } 119 120 static int ath10k_wmi_tlv_iter_parse(struct ath10k *ar, u16 tag, u16 len, 121 const void *ptr, void *data) 122 { 123 const void **tb = data; 124 125 if (tag < WMI_TLV_TAG_MAX) 126 tb[tag] = ptr; 127 128 return 0; 129 } 130 131 static int ath10k_wmi_tlv_parse(struct ath10k *ar, const void **tb, 132 const void *ptr, size_t len) 133 { 134 return ath10k_wmi_tlv_iter(ar, ptr, len, ath10k_wmi_tlv_iter_parse, 135 (void *)tb); 136 } 137 138 static const void ** 139 ath10k_wmi_tlv_parse_alloc(struct ath10k *ar, const void *ptr, 140 size_t len, gfp_t gfp) 141 { 142 const void **tb; 143 int ret; 144 145 tb = kzalloc(sizeof(*tb) * WMI_TLV_TAG_MAX, gfp); 146 if (!tb) 147 return ERR_PTR(-ENOMEM); 148 149 ret = ath10k_wmi_tlv_parse(ar, tb, ptr, len); 150 if (ret) { 151 kfree(tb); 152 return ERR_PTR(ret); 153 } 154 155 return tb; 156 } 157 158 static u16 ath10k_wmi_tlv_len(const void *ptr) 159 { 160 return __le16_to_cpu((((const struct wmi_tlv *)ptr) - 1)->len); 161 } 162 163 /**************/ 164 /* TLV events */ 165 /**************/ 166 static int ath10k_wmi_tlv_event_bcn_tx_status(struct ath10k *ar, 167 struct sk_buff *skb) 168 { 169 const void **tb; 170 const struct wmi_tlv_bcn_tx_status_ev *ev; 171 u32 vdev_id, tx_status; 172 int ret; 173 174 tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC); 175 if (IS_ERR(tb)) { 176 ret = PTR_ERR(tb); 177 ath10k_warn(ar, "failed to parse tlv: %d\n", ret); 178 return ret; 179 } 180 181 ev = tb[WMI_TLV_TAG_STRUCT_OFFLOAD_BCN_TX_STATUS_EVENT]; 182 if (!ev) { 183 kfree(tb); 184 return -EPROTO; 185 } 186 187 tx_status = __le32_to_cpu(ev->tx_status); 188 vdev_id = __le32_to_cpu(ev->vdev_id); 189 190 switch (tx_status) { 191 case WMI_TLV_BCN_TX_STATUS_OK: 192 break; 193 case WMI_TLV_BCN_TX_STATUS_XRETRY: 194 case WMI_TLV_BCN_TX_STATUS_DROP: 195 case WMI_TLV_BCN_TX_STATUS_FILTERED: 196 /* FIXME: It's probably worth telling mac80211 to stop the 197 * interface as it is crippled. 198 */ 199 ath10k_warn(ar, "received bcn tmpl tx status on vdev %i: %d", 200 vdev_id, tx_status); 201 break; 202 } 203 204 kfree(tb); 205 return 0; 206 } 207 208 static int ath10k_wmi_tlv_event_diag_data(struct ath10k *ar, 209 struct sk_buff *skb) 210 { 211 const void **tb; 212 const struct wmi_tlv_diag_data_ev *ev; 213 const struct wmi_tlv_diag_item *item; 214 const void *data; 215 int ret, num_items, len; 216 217 tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC); 218 if (IS_ERR(tb)) { 219 ret = PTR_ERR(tb); 220 ath10k_warn(ar, "failed to parse tlv: %d\n", ret); 221 return ret; 222 } 223 224 ev = tb[WMI_TLV_TAG_STRUCT_DIAG_DATA_CONTAINER_EVENT]; 225 data = tb[WMI_TLV_TAG_ARRAY_BYTE]; 226 if (!ev || !data) { 227 kfree(tb); 228 return -EPROTO; 229 } 230 231 num_items = __le32_to_cpu(ev->num_items); 232 len = ath10k_wmi_tlv_len(data); 233 234 while (num_items--) { 235 if (len == 0) 236 break; 237 if (len < sizeof(*item)) { 238 ath10k_warn(ar, "failed to parse diag data: can't fit item header\n"); 239 break; 240 } 241 242 item = data; 243 244 if (len < sizeof(*item) + __le16_to_cpu(item->len)) { 245 ath10k_warn(ar, "failed to parse diag data: item is too long\n"); 246 break; 247 } 248 249 trace_ath10k_wmi_diag_container(ar, 250 item->type, 251 __le32_to_cpu(item->timestamp), 252 __le32_to_cpu(item->code), 253 __le16_to_cpu(item->len), 254 item->payload); 255 256 len -= sizeof(*item); 257 len -= roundup(__le16_to_cpu(item->len), 4); 258 259 data += sizeof(*item); 260 data += roundup(__le16_to_cpu(item->len), 4); 261 } 262 263 if (num_items != -1 || len != 0) 264 ath10k_warn(ar, "failed to parse diag data event: num_items %d len %d\n", 265 num_items, len); 266 267 kfree(tb); 268 return 0; 269 } 270 271 static int ath10k_wmi_tlv_event_diag(struct ath10k *ar, 272 struct sk_buff *skb) 273 { 274 const void **tb; 275 const void *data; 276 int ret, len; 277 278 tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC); 279 if (IS_ERR(tb)) { 280 ret = PTR_ERR(tb); 281 ath10k_warn(ar, "failed to parse tlv: %d\n", ret); 282 return ret; 283 } 284 285 data = tb[WMI_TLV_TAG_ARRAY_BYTE]; 286 if (!data) { 287 kfree(tb); 288 return -EPROTO; 289 } 290 len = ath10k_wmi_tlv_len(data); 291 292 ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv diag event len %d\n", len); 293 trace_ath10k_wmi_diag(ar, data, len); 294 295 kfree(tb); 296 return 0; 297 } 298 299 /***********/ 300 /* TLV ops */ 301 /***********/ 302 303 static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb) 304 { 305 struct wmi_cmd_hdr *cmd_hdr; 306 enum wmi_tlv_event_id id; 307 308 cmd_hdr = (struct wmi_cmd_hdr *)skb->data; 309 id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID); 310 311 if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL) 312 return; 313 314 trace_ath10k_wmi_event(ar, id, skb->data, skb->len); 315 316 switch (id) { 317 case WMI_TLV_MGMT_RX_EVENTID: 318 ath10k_wmi_event_mgmt_rx(ar, skb); 319 /* mgmt_rx() owns the skb now! */ 320 return; 321 case WMI_TLV_SCAN_EVENTID: 322 ath10k_wmi_event_scan(ar, skb); 323 break; 324 case WMI_TLV_CHAN_INFO_EVENTID: 325 ath10k_wmi_event_chan_info(ar, skb); 326 break; 327 case WMI_TLV_ECHO_EVENTID: 328 ath10k_wmi_event_echo(ar, skb); 329 break; 330 case WMI_TLV_DEBUG_MESG_EVENTID: 331 ath10k_wmi_event_debug_mesg(ar, skb); 332 break; 333 case WMI_TLV_UPDATE_STATS_EVENTID: 334 ath10k_wmi_event_update_stats(ar, skb); 335 break; 336 case WMI_TLV_VDEV_START_RESP_EVENTID: 337 ath10k_wmi_event_vdev_start_resp(ar, skb); 338 break; 339 case WMI_TLV_VDEV_STOPPED_EVENTID: 340 ath10k_wmi_event_vdev_stopped(ar, skb); 341 break; 342 case WMI_TLV_PEER_STA_KICKOUT_EVENTID: 343 ath10k_wmi_event_peer_sta_kickout(ar, skb); 344 break; 345 case WMI_TLV_HOST_SWBA_EVENTID: 346 ath10k_wmi_event_host_swba(ar, skb); 347 break; 348 case WMI_TLV_TBTTOFFSET_UPDATE_EVENTID: 349 ath10k_wmi_event_tbttoffset_update(ar, skb); 350 break; 351 case WMI_TLV_PHYERR_EVENTID: 352 ath10k_wmi_event_phyerr(ar, skb); 353 break; 354 case WMI_TLV_ROAM_EVENTID: 355 ath10k_wmi_event_roam(ar, skb); 356 break; 357 case WMI_TLV_PROFILE_MATCH: 358 ath10k_wmi_event_profile_match(ar, skb); 359 break; 360 case WMI_TLV_DEBUG_PRINT_EVENTID: 361 ath10k_wmi_event_debug_print(ar, skb); 362 break; 363 case WMI_TLV_PDEV_QVIT_EVENTID: 364 ath10k_wmi_event_pdev_qvit(ar, skb); 365 break; 366 case WMI_TLV_WLAN_PROFILE_DATA_EVENTID: 367 ath10k_wmi_event_wlan_profile_data(ar, skb); 368 break; 369 case WMI_TLV_RTT_MEASUREMENT_REPORT_EVENTID: 370 ath10k_wmi_event_rtt_measurement_report(ar, skb); 371 break; 372 case WMI_TLV_TSF_MEASUREMENT_REPORT_EVENTID: 373 ath10k_wmi_event_tsf_measurement_report(ar, skb); 374 break; 375 case WMI_TLV_RTT_ERROR_REPORT_EVENTID: 376 ath10k_wmi_event_rtt_error_report(ar, skb); 377 break; 378 case WMI_TLV_WOW_WAKEUP_HOST_EVENTID: 379 ath10k_wmi_event_wow_wakeup_host(ar, skb); 380 break; 381 case WMI_TLV_DCS_INTERFERENCE_EVENTID: 382 ath10k_wmi_event_dcs_interference(ar, skb); 383 break; 384 case WMI_TLV_PDEV_TPC_CONFIG_EVENTID: 385 ath10k_wmi_event_pdev_tpc_config(ar, skb); 386 break; 387 case WMI_TLV_PDEV_FTM_INTG_EVENTID: 388 ath10k_wmi_event_pdev_ftm_intg(ar, skb); 389 break; 390 case WMI_TLV_GTK_OFFLOAD_STATUS_EVENTID: 391 ath10k_wmi_event_gtk_offload_status(ar, skb); 392 break; 393 case WMI_TLV_GTK_REKEY_FAIL_EVENTID: 394 ath10k_wmi_event_gtk_rekey_fail(ar, skb); 395 break; 396 case WMI_TLV_TX_DELBA_COMPLETE_EVENTID: 397 ath10k_wmi_event_delba_complete(ar, skb); 398 break; 399 case WMI_TLV_TX_ADDBA_COMPLETE_EVENTID: 400 ath10k_wmi_event_addba_complete(ar, skb); 401 break; 402 case WMI_TLV_VDEV_INSTALL_KEY_COMPLETE_EVENTID: 403 ath10k_wmi_event_vdev_install_key_complete(ar, skb); 404 break; 405 case WMI_TLV_SERVICE_READY_EVENTID: 406 ath10k_wmi_event_service_ready(ar, skb); 407 break; 408 case WMI_TLV_READY_EVENTID: 409 ath10k_wmi_event_ready(ar, skb); 410 break; 411 case WMI_TLV_OFFLOAD_BCN_TX_STATUS_EVENTID: 412 ath10k_wmi_tlv_event_bcn_tx_status(ar, skb); 413 break; 414 case WMI_TLV_DIAG_DATA_CONTAINER_EVENTID: 415 ath10k_wmi_tlv_event_diag_data(ar, skb); 416 break; 417 case WMI_TLV_DIAG_EVENTID: 418 ath10k_wmi_tlv_event_diag(ar, skb); 419 break; 420 default: 421 ath10k_warn(ar, "Unknown eventid: %d\n", id); 422 break; 423 } 424 425 dev_kfree_skb(skb); 426 } 427 428 static int ath10k_wmi_tlv_op_pull_scan_ev(struct ath10k *ar, 429 struct sk_buff *skb, 430 struct wmi_scan_ev_arg *arg) 431 { 432 const void **tb; 433 const struct wmi_scan_event *ev; 434 int ret; 435 436 tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC); 437 if (IS_ERR(tb)) { 438 ret = PTR_ERR(tb); 439 ath10k_warn(ar, "failed to parse tlv: %d\n", ret); 440 return ret; 441 } 442 443 ev = tb[WMI_TLV_TAG_STRUCT_SCAN_EVENT]; 444 if (!ev) { 445 kfree(tb); 446 return -EPROTO; 447 } 448 449 arg->event_type = ev->event_type; 450 arg->reason = ev->reason; 451 arg->channel_freq = ev->channel_freq; 452 arg->scan_req_id = ev->scan_req_id; 453 arg->scan_id = ev->scan_id; 454 arg->vdev_id = ev->vdev_id; 455 456 kfree(tb); 457 return 0; 458 } 459 460 static int ath10k_wmi_tlv_op_pull_mgmt_rx_ev(struct ath10k *ar, 461 struct sk_buff *skb, 462 struct wmi_mgmt_rx_ev_arg *arg) 463 { 464 const void **tb; 465 const struct wmi_tlv_mgmt_rx_ev *ev; 466 const u8 *frame; 467 u32 msdu_len; 468 int ret; 469 470 tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC); 471 if (IS_ERR(tb)) { 472 ret = PTR_ERR(tb); 473 ath10k_warn(ar, "failed to parse tlv: %d\n", ret); 474 return ret; 475 } 476 477 ev = tb[WMI_TLV_TAG_STRUCT_MGMT_RX_HDR]; 478 frame = tb[WMI_TLV_TAG_ARRAY_BYTE]; 479 480 if (!ev || !frame) { 481 kfree(tb); 482 return -EPROTO; 483 } 484 485 arg->channel = ev->channel; 486 arg->buf_len = ev->buf_len; 487 arg->status = ev->status; 488 arg->snr = ev->snr; 489 arg->phy_mode = ev->phy_mode; 490 arg->rate = ev->rate; 491 492 msdu_len = __le32_to_cpu(arg->buf_len); 493 494 if (skb->len < (frame - skb->data) + msdu_len) { 495 kfree(tb); 496 return -EPROTO; 497 } 498 499 /* shift the sk_buff to point to `frame` */ 500 skb_trim(skb, 0); 501 skb_put(skb, frame - skb->data); 502 skb_pull(skb, frame - skb->data); 503 skb_put(skb, msdu_len); 504 505 kfree(tb); 506 return 0; 507 } 508 509 static int ath10k_wmi_tlv_op_pull_ch_info_ev(struct ath10k *ar, 510 struct sk_buff *skb, 511 struct wmi_ch_info_ev_arg *arg) 512 { 513 const void **tb; 514 const struct wmi_chan_info_event *ev; 515 int ret; 516 517 tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC); 518 if (IS_ERR(tb)) { 519 ret = PTR_ERR(tb); 520 ath10k_warn(ar, "failed to parse tlv: %d\n", ret); 521 return ret; 522 } 523 524 ev = tb[WMI_TLV_TAG_STRUCT_CHAN_INFO_EVENT]; 525 if (!ev) { 526 kfree(tb); 527 return -EPROTO; 528 } 529 530 arg->err_code = ev->err_code; 531 arg->freq = ev->freq; 532 arg->cmd_flags = ev->cmd_flags; 533 arg->noise_floor = ev->noise_floor; 534 arg->rx_clear_count = ev->rx_clear_count; 535 arg->cycle_count = ev->cycle_count; 536 537 kfree(tb); 538 return 0; 539 } 540 541 static int 542 ath10k_wmi_tlv_op_pull_vdev_start_ev(struct ath10k *ar, struct sk_buff *skb, 543 struct wmi_vdev_start_ev_arg *arg) 544 { 545 const void **tb; 546 const struct wmi_vdev_start_response_event *ev; 547 int ret; 548 549 tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC); 550 if (IS_ERR(tb)) { 551 ret = PTR_ERR(tb); 552 ath10k_warn(ar, "failed to parse tlv: %d\n", ret); 553 return ret; 554 } 555 556 ev = tb[WMI_TLV_TAG_STRUCT_VDEV_START_RESPONSE_EVENT]; 557 if (!ev) { 558 kfree(tb); 559 return -EPROTO; 560 } 561 562 skb_pull(skb, sizeof(*ev)); 563 arg->vdev_id = ev->vdev_id; 564 arg->req_id = ev->req_id; 565 arg->resp_type = ev->resp_type; 566 arg->status = ev->status; 567 568 kfree(tb); 569 return 0; 570 } 571 572 static int ath10k_wmi_tlv_op_pull_peer_kick_ev(struct ath10k *ar, 573 struct sk_buff *skb, 574 struct wmi_peer_kick_ev_arg *arg) 575 { 576 const void **tb; 577 const struct wmi_peer_sta_kickout_event *ev; 578 int ret; 579 580 tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC); 581 if (IS_ERR(tb)) { 582 ret = PTR_ERR(tb); 583 ath10k_warn(ar, "failed to parse tlv: %d\n", ret); 584 return ret; 585 } 586 587 ev = tb[WMI_TLV_TAG_STRUCT_PEER_STA_KICKOUT_EVENT]; 588 if (!ev) { 589 kfree(tb); 590 return -EPROTO; 591 } 592 593 arg->mac_addr = ev->peer_macaddr.addr; 594 595 kfree(tb); 596 return 0; 597 } 598 599 struct wmi_tlv_swba_parse { 600 const struct wmi_host_swba_event *ev; 601 bool tim_done; 602 bool noa_done; 603 size_t n_tim; 604 size_t n_noa; 605 struct wmi_swba_ev_arg *arg; 606 }; 607 608 static int ath10k_wmi_tlv_swba_tim_parse(struct ath10k *ar, u16 tag, u16 len, 609 const void *ptr, void *data) 610 { 611 struct wmi_tlv_swba_parse *swba = data; 612 613 if (tag != WMI_TLV_TAG_STRUCT_TIM_INFO) 614 return -EPROTO; 615 616 if (swba->n_tim >= ARRAY_SIZE(swba->arg->tim_info)) 617 return -ENOBUFS; 618 619 swba->arg->tim_info[swba->n_tim++] = ptr; 620 return 0; 621 } 622 623 static int ath10k_wmi_tlv_swba_noa_parse(struct ath10k *ar, u16 tag, u16 len, 624 const void *ptr, void *data) 625 { 626 struct wmi_tlv_swba_parse *swba = data; 627 628 if (tag != WMI_TLV_TAG_STRUCT_P2P_NOA_INFO) 629 return -EPROTO; 630 631 if (swba->n_noa >= ARRAY_SIZE(swba->arg->noa_info)) 632 return -ENOBUFS; 633 634 swba->arg->noa_info[swba->n_noa++] = ptr; 635 return 0; 636 } 637 638 static int ath10k_wmi_tlv_swba_parse(struct ath10k *ar, u16 tag, u16 len, 639 const void *ptr, void *data) 640 { 641 struct wmi_tlv_swba_parse *swba = data; 642 int ret; 643 644 switch (tag) { 645 case WMI_TLV_TAG_STRUCT_HOST_SWBA_EVENT: 646 swba->ev = ptr; 647 break; 648 case WMI_TLV_TAG_ARRAY_STRUCT: 649 if (!swba->tim_done) { 650 swba->tim_done = true; 651 ret = ath10k_wmi_tlv_iter(ar, ptr, len, 652 ath10k_wmi_tlv_swba_tim_parse, 653 swba); 654 if (ret) 655 return ret; 656 } else if (!swba->noa_done) { 657 swba->noa_done = true; 658 ret = ath10k_wmi_tlv_iter(ar, ptr, len, 659 ath10k_wmi_tlv_swba_noa_parse, 660 swba); 661 if (ret) 662 return ret; 663 } 664 break; 665 default: 666 break; 667 } 668 return 0; 669 } 670 671 static int ath10k_wmi_tlv_op_pull_swba_ev(struct ath10k *ar, 672 struct sk_buff *skb, 673 struct wmi_swba_ev_arg *arg) 674 { 675 struct wmi_tlv_swba_parse swba = { .arg = arg }; 676 u32 map; 677 size_t n_vdevs; 678 int ret; 679 680 ret = ath10k_wmi_tlv_iter(ar, skb->data, skb->len, 681 ath10k_wmi_tlv_swba_parse, &swba); 682 if (ret) { 683 ath10k_warn(ar, "failed to parse tlv: %d\n", ret); 684 return ret; 685 } 686 687 if (!swba.ev) 688 return -EPROTO; 689 690 arg->vdev_map = swba.ev->vdev_map; 691 692 for (map = __le32_to_cpu(arg->vdev_map), n_vdevs = 0; map; map >>= 1) 693 if (map & BIT(0)) 694 n_vdevs++; 695 696 if (n_vdevs != swba.n_tim || 697 n_vdevs != swba.n_noa) 698 return -EPROTO; 699 700 return 0; 701 } 702 703 static int ath10k_wmi_tlv_op_pull_phyerr_ev(struct ath10k *ar, 704 struct sk_buff *skb, 705 struct wmi_phyerr_ev_arg *arg) 706 { 707 const void **tb; 708 const struct wmi_tlv_phyerr_ev *ev; 709 const void *phyerrs; 710 int ret; 711 712 tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC); 713 if (IS_ERR(tb)) { 714 ret = PTR_ERR(tb); 715 ath10k_warn(ar, "failed to parse tlv: %d\n", ret); 716 return ret; 717 } 718 719 ev = tb[WMI_TLV_TAG_STRUCT_COMB_PHYERR_RX_HDR]; 720 phyerrs = tb[WMI_TLV_TAG_ARRAY_BYTE]; 721 722 if (!ev || !phyerrs) { 723 kfree(tb); 724 return -EPROTO; 725 } 726 727 arg->num_phyerrs = ev->num_phyerrs; 728 arg->tsf_l32 = ev->tsf_l32; 729 arg->tsf_u32 = ev->tsf_u32; 730 arg->buf_len = ev->buf_len; 731 arg->phyerrs = phyerrs; 732 733 kfree(tb); 734 return 0; 735 } 736 737 #define WMI_TLV_ABI_VER_NS0 0x5F414351 738 #define WMI_TLV_ABI_VER_NS1 0x00004C4D 739 #define WMI_TLV_ABI_VER_NS2 0x00000000 740 #define WMI_TLV_ABI_VER_NS3 0x00000000 741 742 #define WMI_TLV_ABI_VER0_MAJOR 1 743 #define WMI_TLV_ABI_VER0_MINOR 0 744 #define WMI_TLV_ABI_VER0 ((((WMI_TLV_ABI_VER0_MAJOR) << 24) & 0xFF000000) | \ 745 (((WMI_TLV_ABI_VER0_MINOR) << 0) & 0x00FFFFFF)) 746 #define WMI_TLV_ABI_VER1 53 747 748 static int 749 ath10k_wmi_tlv_parse_mem_reqs(struct ath10k *ar, u16 tag, u16 len, 750 const void *ptr, void *data) 751 { 752 struct wmi_svc_rdy_ev_arg *arg = data; 753 int i; 754 755 if (tag != WMI_TLV_TAG_STRUCT_WLAN_HOST_MEM_REQ) 756 return -EPROTO; 757 758 for (i = 0; i < ARRAY_SIZE(arg->mem_reqs); i++) { 759 if (!arg->mem_reqs[i]) { 760 arg->mem_reqs[i] = ptr; 761 return 0; 762 } 763 } 764 765 return -ENOMEM; 766 } 767 768 static int ath10k_wmi_tlv_op_pull_svc_rdy_ev(struct ath10k *ar, 769 struct sk_buff *skb, 770 struct wmi_svc_rdy_ev_arg *arg) 771 { 772 const void **tb; 773 const struct hal_reg_capabilities *reg; 774 const struct wmi_tlv_svc_rdy_ev *ev; 775 const __le32 *svc_bmap; 776 const struct wlan_host_mem_req *mem_reqs; 777 int ret; 778 779 tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC); 780 if (IS_ERR(tb)) { 781 ret = PTR_ERR(tb); 782 ath10k_warn(ar, "failed to parse tlv: %d\n", ret); 783 return ret; 784 } 785 786 ev = tb[WMI_TLV_TAG_STRUCT_SERVICE_READY_EVENT]; 787 reg = tb[WMI_TLV_TAG_STRUCT_HAL_REG_CAPABILITIES]; 788 svc_bmap = tb[WMI_TLV_TAG_ARRAY_UINT32]; 789 mem_reqs = tb[WMI_TLV_TAG_ARRAY_STRUCT]; 790 791 if (!ev || !reg || !svc_bmap || !mem_reqs) { 792 kfree(tb); 793 return -EPROTO; 794 } 795 796 /* This is an internal ABI compatibility check for WMI TLV so check it 797 * here instead of the generic WMI code. 798 */ 799 ath10k_dbg(ar, ATH10K_DBG_WMI, 800 "wmi tlv abi 0x%08x ?= 0x%08x, 0x%08x ?= 0x%08x, 0x%08x ?= 0x%08x, 0x%08x ?= 0x%08x, 0x%08x ?= 0x%08x\n", 801 __le32_to_cpu(ev->abi.abi_ver0), WMI_TLV_ABI_VER0, 802 __le32_to_cpu(ev->abi.abi_ver_ns0), WMI_TLV_ABI_VER_NS0, 803 __le32_to_cpu(ev->abi.abi_ver_ns1), WMI_TLV_ABI_VER_NS1, 804 __le32_to_cpu(ev->abi.abi_ver_ns2), WMI_TLV_ABI_VER_NS2, 805 __le32_to_cpu(ev->abi.abi_ver_ns3), WMI_TLV_ABI_VER_NS3); 806 807 if (__le32_to_cpu(ev->abi.abi_ver0) != WMI_TLV_ABI_VER0 || 808 __le32_to_cpu(ev->abi.abi_ver_ns0) != WMI_TLV_ABI_VER_NS0 || 809 __le32_to_cpu(ev->abi.abi_ver_ns1) != WMI_TLV_ABI_VER_NS1 || 810 __le32_to_cpu(ev->abi.abi_ver_ns2) != WMI_TLV_ABI_VER_NS2 || 811 __le32_to_cpu(ev->abi.abi_ver_ns3) != WMI_TLV_ABI_VER_NS3) { 812 kfree(tb); 813 return -ENOTSUPP; 814 } 815 816 arg->min_tx_power = ev->hw_min_tx_power; 817 arg->max_tx_power = ev->hw_max_tx_power; 818 arg->ht_cap = ev->ht_cap_info; 819 arg->vht_cap = ev->vht_cap_info; 820 arg->sw_ver0 = ev->abi.abi_ver0; 821 arg->sw_ver1 = ev->abi.abi_ver1; 822 arg->fw_build = ev->fw_build_vers; 823 arg->phy_capab = ev->phy_capability; 824 arg->num_rf_chains = ev->num_rf_chains; 825 arg->eeprom_rd = reg->eeprom_rd; 826 arg->num_mem_reqs = ev->num_mem_reqs; 827 arg->service_map = svc_bmap; 828 arg->service_map_len = ath10k_wmi_tlv_len(svc_bmap); 829 830 ret = ath10k_wmi_tlv_iter(ar, mem_reqs, ath10k_wmi_tlv_len(mem_reqs), 831 ath10k_wmi_tlv_parse_mem_reqs, arg); 832 if (ret) { 833 kfree(tb); 834 ath10k_warn(ar, "failed to parse mem_reqs tlv: %d\n", ret); 835 return ret; 836 } 837 838 kfree(tb); 839 return 0; 840 } 841 842 static int ath10k_wmi_tlv_op_pull_rdy_ev(struct ath10k *ar, 843 struct sk_buff *skb, 844 struct wmi_rdy_ev_arg *arg) 845 { 846 const void **tb; 847 const struct wmi_tlv_rdy_ev *ev; 848 int ret; 849 850 tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC); 851 if (IS_ERR(tb)) { 852 ret = PTR_ERR(tb); 853 ath10k_warn(ar, "failed to parse tlv: %d\n", ret); 854 return ret; 855 } 856 857 ev = tb[WMI_TLV_TAG_STRUCT_READY_EVENT]; 858 if (!ev) { 859 kfree(tb); 860 return -EPROTO; 861 } 862 863 arg->sw_version = ev->abi.abi_ver0; 864 arg->abi_version = ev->abi.abi_ver1; 865 arg->status = ev->status; 866 arg->mac_addr = ev->mac_addr.addr; 867 868 kfree(tb); 869 return 0; 870 } 871 872 static int ath10k_wmi_tlv_op_pull_fw_stats(struct ath10k *ar, 873 struct sk_buff *skb, 874 struct ath10k_fw_stats *stats) 875 { 876 const void **tb; 877 const struct wmi_stats_event *ev; 878 const void *data; 879 u32 num_pdev_stats, num_vdev_stats, num_peer_stats; 880 size_t data_len; 881 int ret; 882 883 tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC); 884 if (IS_ERR(tb)) { 885 ret = PTR_ERR(tb); 886 ath10k_warn(ar, "failed to parse tlv: %d\n", ret); 887 return ret; 888 } 889 890 ev = tb[WMI_TLV_TAG_STRUCT_STATS_EVENT]; 891 data = tb[WMI_TLV_TAG_ARRAY_BYTE]; 892 893 if (!ev || !data) { 894 kfree(tb); 895 return -EPROTO; 896 } 897 898 data_len = ath10k_wmi_tlv_len(data); 899 num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats); 900 num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats); 901 num_peer_stats = __le32_to_cpu(ev->num_peer_stats); 902 903 WARN_ON(1); /* FIXME: not implemented yet */ 904 905 kfree(tb); 906 return 0; 907 } 908 909 static struct sk_buff * 910 ath10k_wmi_tlv_op_gen_pdev_suspend(struct ath10k *ar, u32 opt) 911 { 912 struct wmi_tlv_pdev_suspend *cmd; 913 struct wmi_tlv *tlv; 914 struct sk_buff *skb; 915 916 skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd)); 917 if (!skb) 918 return ERR_PTR(-ENOMEM); 919 920 tlv = (void *)skb->data; 921 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_SUSPEND_CMD); 922 tlv->len = __cpu_to_le16(sizeof(*cmd)); 923 cmd = (void *)tlv->value; 924 cmd->opt = __cpu_to_le32(opt); 925 926 ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pdev suspend\n"); 927 return skb; 928 } 929 930 static struct sk_buff * 931 ath10k_wmi_tlv_op_gen_pdev_resume(struct ath10k *ar) 932 { 933 struct wmi_tlv_resume_cmd *cmd; 934 struct wmi_tlv *tlv; 935 struct sk_buff *skb; 936 937 skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd)); 938 if (!skb) 939 return ERR_PTR(-ENOMEM); 940 941 tlv = (void *)skb->data; 942 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_RESUME_CMD); 943 tlv->len = __cpu_to_le16(sizeof(*cmd)); 944 cmd = (void *)tlv->value; 945 cmd->reserved = __cpu_to_le32(0); 946 947 ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pdev resume\n"); 948 return skb; 949 } 950 951 static struct sk_buff * 952 ath10k_wmi_tlv_op_gen_pdev_set_rd(struct ath10k *ar, 953 u16 rd, u16 rd2g, u16 rd5g, 954 u16 ctl2g, u16 ctl5g, 955 enum wmi_dfs_region dfs_reg) 956 { 957 struct wmi_tlv_pdev_set_rd_cmd *cmd; 958 struct wmi_tlv *tlv; 959 struct sk_buff *skb; 960 961 skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd)); 962 if (!skb) 963 return ERR_PTR(-ENOMEM); 964 965 tlv = (void *)skb->data; 966 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_SET_REGDOMAIN_CMD); 967 tlv->len = __cpu_to_le16(sizeof(*cmd)); 968 cmd = (void *)tlv->value; 969 cmd->regd = __cpu_to_le32(rd); 970 cmd->regd_2ghz = __cpu_to_le32(rd2g); 971 cmd->regd_5ghz = __cpu_to_le32(rd5g); 972 cmd->conform_limit_2ghz = __cpu_to_le32(rd2g); 973 cmd->conform_limit_5ghz = __cpu_to_le32(rd5g); 974 975 ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pdev set rd\n"); 976 return skb; 977 } 978 979 static struct sk_buff * 980 ath10k_wmi_tlv_op_gen_pdev_set_param(struct ath10k *ar, u32 param_id, 981 u32 param_value) 982 { 983 struct wmi_tlv_pdev_set_param_cmd *cmd; 984 struct wmi_tlv *tlv; 985 struct sk_buff *skb; 986 987 skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd)); 988 if (!skb) 989 return ERR_PTR(-ENOMEM); 990 991 tlv = (void *)skb->data; 992 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_SET_PARAM_CMD); 993 tlv->len = __cpu_to_le16(sizeof(*cmd)); 994 cmd = (void *)tlv->value; 995 cmd->param_id = __cpu_to_le32(param_id); 996 cmd->param_value = __cpu_to_le32(param_value); 997 998 ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pdev set param\n"); 999 return skb; 1000 } 1001 1002 static struct sk_buff *ath10k_wmi_tlv_op_gen_init(struct ath10k *ar) 1003 { 1004 struct sk_buff *skb; 1005 struct wmi_tlv *tlv; 1006 struct wmi_tlv_init_cmd *cmd; 1007 struct wmi_tlv_resource_config *cfg; 1008 struct wmi_host_mem_chunks *chunks; 1009 size_t len, chunks_len; 1010 void *ptr; 1011 1012 chunks_len = ar->wmi.num_mem_chunks * sizeof(struct host_memory_chunk); 1013 len = (sizeof(*tlv) + sizeof(*cmd)) + 1014 (sizeof(*tlv) + sizeof(*cfg)) + 1015 (sizeof(*tlv) + chunks_len); 1016 1017 skb = ath10k_wmi_alloc_skb(ar, len); 1018 if (!skb) 1019 return ERR_PTR(-ENOMEM); 1020 1021 ptr = skb->data; 1022 1023 tlv = ptr; 1024 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_INIT_CMD); 1025 tlv->len = __cpu_to_le16(sizeof(*cmd)); 1026 cmd = (void *)tlv->value; 1027 ptr += sizeof(*tlv); 1028 ptr += sizeof(*cmd); 1029 1030 tlv = ptr; 1031 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_RESOURCE_CONFIG); 1032 tlv->len = __cpu_to_le16(sizeof(*cfg)); 1033 cfg = (void *)tlv->value; 1034 ptr += sizeof(*tlv); 1035 ptr += sizeof(*cfg); 1036 1037 tlv = ptr; 1038 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT); 1039 tlv->len = __cpu_to_le16(chunks_len); 1040 chunks = (void *)tlv->value; 1041 1042 ptr += sizeof(*tlv); 1043 ptr += chunks_len; 1044 1045 cmd->abi.abi_ver0 = __cpu_to_le32(WMI_TLV_ABI_VER0); 1046 cmd->abi.abi_ver1 = __cpu_to_le32(WMI_TLV_ABI_VER1); 1047 cmd->abi.abi_ver_ns0 = __cpu_to_le32(WMI_TLV_ABI_VER_NS0); 1048 cmd->abi.abi_ver_ns1 = __cpu_to_le32(WMI_TLV_ABI_VER_NS1); 1049 cmd->abi.abi_ver_ns2 = __cpu_to_le32(WMI_TLV_ABI_VER_NS2); 1050 cmd->abi.abi_ver_ns3 = __cpu_to_le32(WMI_TLV_ABI_VER_NS3); 1051 cmd->num_host_mem_chunks = __cpu_to_le32(ar->wmi.num_mem_chunks); 1052 1053 cfg->num_vdevs = __cpu_to_le32(TARGET_TLV_NUM_VDEVS); 1054 cfg->num_peers = __cpu_to_le32(TARGET_TLV_NUM_PEERS); 1055 1056 if (test_bit(WMI_SERVICE_RX_FULL_REORDER, ar->wmi.svc_map)) { 1057 cfg->num_offload_peers = __cpu_to_le32(3); 1058 cfg->num_offload_reorder_bufs = __cpu_to_le32(3); 1059 } else { 1060 cfg->num_offload_peers = __cpu_to_le32(0); 1061 cfg->num_offload_reorder_bufs = __cpu_to_le32(0); 1062 } 1063 1064 cfg->num_peer_keys = __cpu_to_le32(2); 1065 cfg->num_tids = __cpu_to_le32(TARGET_TLV_NUM_TIDS); 1066 cfg->ast_skid_limit = __cpu_to_le32(0x10); 1067 cfg->tx_chain_mask = __cpu_to_le32(0x7); 1068 cfg->rx_chain_mask = __cpu_to_le32(0x7); 1069 cfg->rx_timeout_pri[0] = __cpu_to_le32(0x64); 1070 cfg->rx_timeout_pri[1] = __cpu_to_le32(0x64); 1071 cfg->rx_timeout_pri[2] = __cpu_to_le32(0x64); 1072 cfg->rx_timeout_pri[3] = __cpu_to_le32(0x28); 1073 cfg->rx_decap_mode = __cpu_to_le32(1); 1074 cfg->scan_max_pending_reqs = __cpu_to_le32(4); 1075 cfg->bmiss_offload_max_vdev = __cpu_to_le32(3); 1076 cfg->roam_offload_max_vdev = __cpu_to_le32(3); 1077 cfg->roam_offload_max_ap_profiles = __cpu_to_le32(8); 1078 cfg->num_mcast_groups = __cpu_to_le32(0); 1079 cfg->num_mcast_table_elems = __cpu_to_le32(0); 1080 cfg->mcast2ucast_mode = __cpu_to_le32(0); 1081 cfg->tx_dbg_log_size = __cpu_to_le32(0x400); 1082 cfg->num_wds_entries = __cpu_to_le32(0x20); 1083 cfg->dma_burst_size = __cpu_to_le32(0); 1084 cfg->mac_aggr_delim = __cpu_to_le32(0); 1085 cfg->rx_skip_defrag_timeout_dup_detection_check = __cpu_to_le32(0); 1086 cfg->vow_config = __cpu_to_le32(0); 1087 cfg->gtk_offload_max_vdev = __cpu_to_le32(2); 1088 cfg->num_msdu_desc = __cpu_to_le32(TARGET_TLV_NUM_MSDU_DESC); 1089 cfg->max_frag_entries = __cpu_to_le32(2); 1090 cfg->num_tdls_vdevs = __cpu_to_le32(1); 1091 cfg->num_tdls_conn_table_entries = __cpu_to_le32(0x20); 1092 cfg->beacon_tx_offload_max_vdev = __cpu_to_le32(2); 1093 cfg->num_multicast_filter_entries = __cpu_to_le32(5); 1094 cfg->num_wow_filters = __cpu_to_le32(0x16); 1095 cfg->num_keep_alive_pattern = __cpu_to_le32(6); 1096 cfg->keep_alive_pattern_size = __cpu_to_le32(0); 1097 cfg->max_tdls_concurrent_sleep_sta = __cpu_to_le32(1); 1098 cfg->max_tdls_concurrent_buffer_sta = __cpu_to_le32(1); 1099 1100 ath10k_wmi_put_host_mem_chunks(ar, chunks); 1101 1102 ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv init\n"); 1103 return skb; 1104 } 1105 1106 static struct sk_buff * 1107 ath10k_wmi_tlv_op_gen_start_scan(struct ath10k *ar, 1108 const struct wmi_start_scan_arg *arg) 1109 { 1110 struct wmi_tlv_start_scan_cmd *cmd; 1111 struct wmi_tlv *tlv; 1112 struct sk_buff *skb; 1113 size_t len, chan_len, ssid_len, bssid_len, ie_len; 1114 __le32 *chans; 1115 struct wmi_ssid *ssids; 1116 struct wmi_mac_addr *addrs; 1117 void *ptr; 1118 int i, ret; 1119 1120 ret = ath10k_wmi_start_scan_verify(arg); 1121 if (ret) 1122 return ERR_PTR(ret); 1123 1124 chan_len = arg->n_channels * sizeof(__le32); 1125 ssid_len = arg->n_ssids * sizeof(struct wmi_ssid); 1126 bssid_len = arg->n_bssids * sizeof(struct wmi_mac_addr); 1127 ie_len = roundup(arg->ie_len, 4); 1128 len = (sizeof(*tlv) + sizeof(*cmd)) + 1129 (arg->n_channels ? sizeof(*tlv) + chan_len : 0) + 1130 (arg->n_ssids ? sizeof(*tlv) + ssid_len : 0) + 1131 (arg->n_bssids ? sizeof(*tlv) + bssid_len : 0) + 1132 (arg->ie_len ? sizeof(*tlv) + ie_len : 0); 1133 1134 skb = ath10k_wmi_alloc_skb(ar, len); 1135 if (!skb) 1136 return ERR_PTR(-ENOMEM); 1137 1138 ptr = (void *)skb->data; 1139 tlv = ptr; 1140 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_START_SCAN_CMD); 1141 tlv->len = __cpu_to_le16(sizeof(*cmd)); 1142 cmd = (void *)tlv->value; 1143 1144 ath10k_wmi_put_start_scan_common(&cmd->common, arg); 1145 cmd->burst_duration_ms = __cpu_to_le32(0); 1146 cmd->num_channels = __cpu_to_le32(arg->n_channels); 1147 cmd->num_ssids = __cpu_to_le32(arg->n_ssids); 1148 cmd->num_bssids = __cpu_to_le32(arg->n_bssids); 1149 cmd->ie_len = __cpu_to_le32(arg->ie_len); 1150 cmd->num_probes = __cpu_to_le32(3); 1151 1152 /* FIXME: There are some scan flag inconsistencies across firmwares, 1153 * e.g. WMI-TLV inverts the logic behind the following flag. 1154 */ 1155 cmd->common.scan_ctrl_flags ^= __cpu_to_le32(WMI_SCAN_FILTER_PROBE_REQ); 1156 1157 ptr += sizeof(*tlv); 1158 ptr += sizeof(*cmd); 1159 1160 tlv = ptr; 1161 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_UINT32); 1162 tlv->len = __cpu_to_le16(chan_len); 1163 chans = (void *)tlv->value; 1164 for (i = 0; i < arg->n_channels; i++) 1165 chans[i] = __cpu_to_le32(arg->channels[i]); 1166 1167 ptr += sizeof(*tlv); 1168 ptr += chan_len; 1169 1170 tlv = ptr; 1171 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_FIXED_STRUCT); 1172 tlv->len = __cpu_to_le16(ssid_len); 1173 ssids = (void *)tlv->value; 1174 for (i = 0; i < arg->n_ssids; i++) { 1175 ssids[i].ssid_len = __cpu_to_le32(arg->ssids[i].len); 1176 memcpy(ssids[i].ssid, arg->ssids[i].ssid, arg->ssids[i].len); 1177 } 1178 1179 ptr += sizeof(*tlv); 1180 ptr += ssid_len; 1181 1182 tlv = ptr; 1183 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_FIXED_STRUCT); 1184 tlv->len = __cpu_to_le16(bssid_len); 1185 addrs = (void *)tlv->value; 1186 for (i = 0; i < arg->n_bssids; i++) 1187 ether_addr_copy(addrs[i].addr, arg->bssids[i].bssid); 1188 1189 ptr += sizeof(*tlv); 1190 ptr += bssid_len; 1191 1192 tlv = ptr; 1193 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE); 1194 tlv->len = __cpu_to_le16(ie_len); 1195 memcpy(tlv->value, arg->ie, arg->ie_len); 1196 1197 ptr += sizeof(*tlv); 1198 ptr += ie_len; 1199 1200 ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv start scan\n"); 1201 return skb; 1202 } 1203 1204 static struct sk_buff * 1205 ath10k_wmi_tlv_op_gen_stop_scan(struct ath10k *ar, 1206 const struct wmi_stop_scan_arg *arg) 1207 { 1208 struct wmi_stop_scan_cmd *cmd; 1209 struct wmi_tlv *tlv; 1210 struct sk_buff *skb; 1211 u32 scan_id; 1212 u32 req_id; 1213 1214 if (arg->req_id > 0xFFF) 1215 return ERR_PTR(-EINVAL); 1216 if (arg->req_type == WMI_SCAN_STOP_ONE && arg->u.scan_id > 0xFFF) 1217 return ERR_PTR(-EINVAL); 1218 1219 skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd)); 1220 if (!skb) 1221 return ERR_PTR(-ENOMEM); 1222 1223 scan_id = arg->u.scan_id; 1224 scan_id |= WMI_HOST_SCAN_REQ_ID_PREFIX; 1225 1226 req_id = arg->req_id; 1227 req_id |= WMI_HOST_SCAN_REQUESTOR_ID_PREFIX; 1228 1229 tlv = (void *)skb->data; 1230 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STOP_SCAN_CMD); 1231 tlv->len = __cpu_to_le16(sizeof(*cmd)); 1232 cmd = (void *)tlv->value; 1233 cmd->req_type = __cpu_to_le32(arg->req_type); 1234 cmd->vdev_id = __cpu_to_le32(arg->u.vdev_id); 1235 cmd->scan_id = __cpu_to_le32(scan_id); 1236 cmd->scan_req_id = __cpu_to_le32(req_id); 1237 1238 ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv stop scan\n"); 1239 return skb; 1240 } 1241 1242 static struct sk_buff * 1243 ath10k_wmi_tlv_op_gen_vdev_create(struct ath10k *ar, 1244 u32 vdev_id, 1245 enum wmi_vdev_type vdev_type, 1246 enum wmi_vdev_subtype vdev_subtype, 1247 const u8 mac_addr[ETH_ALEN]) 1248 { 1249 struct wmi_vdev_create_cmd *cmd; 1250 struct wmi_tlv *tlv; 1251 struct sk_buff *skb; 1252 1253 skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd)); 1254 if (!skb) 1255 return ERR_PTR(-ENOMEM); 1256 1257 tlv = (void *)skb->data; 1258 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_CREATE_CMD); 1259 tlv->len = __cpu_to_le16(sizeof(*cmd)); 1260 cmd = (void *)tlv->value; 1261 cmd->vdev_id = __cpu_to_le32(vdev_id); 1262 cmd->vdev_type = __cpu_to_le32(vdev_type); 1263 cmd->vdev_subtype = __cpu_to_le32(vdev_subtype); 1264 ether_addr_copy(cmd->vdev_macaddr.addr, mac_addr); 1265 1266 ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev create\n"); 1267 return skb; 1268 } 1269 1270 static struct sk_buff * 1271 ath10k_wmi_tlv_op_gen_vdev_delete(struct ath10k *ar, u32 vdev_id) 1272 { 1273 struct wmi_vdev_delete_cmd *cmd; 1274 struct wmi_tlv *tlv; 1275 struct sk_buff *skb; 1276 1277 skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd)); 1278 if (!skb) 1279 return ERR_PTR(-ENOMEM); 1280 1281 tlv = (void *)skb->data; 1282 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_DELETE_CMD); 1283 tlv->len = __cpu_to_le16(sizeof(*cmd)); 1284 cmd = (void *)tlv->value; 1285 cmd->vdev_id = __cpu_to_le32(vdev_id); 1286 1287 ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev delete\n"); 1288 return skb; 1289 } 1290 1291 static struct sk_buff * 1292 ath10k_wmi_tlv_op_gen_vdev_start(struct ath10k *ar, 1293 const struct wmi_vdev_start_request_arg *arg, 1294 bool restart) 1295 { 1296 struct wmi_tlv_vdev_start_cmd *cmd; 1297 struct wmi_channel *ch; 1298 struct wmi_p2p_noa_descriptor *noa; 1299 struct wmi_tlv *tlv; 1300 struct sk_buff *skb; 1301 size_t len; 1302 void *ptr; 1303 u32 flags = 0; 1304 1305 if (WARN_ON(arg->ssid && arg->ssid_len == 0)) 1306 return ERR_PTR(-EINVAL); 1307 if (WARN_ON(arg->hidden_ssid && !arg->ssid)) 1308 return ERR_PTR(-EINVAL); 1309 if (WARN_ON(arg->ssid_len > sizeof(cmd->ssid.ssid))) 1310 return ERR_PTR(-EINVAL); 1311 1312 len = (sizeof(*tlv) + sizeof(*cmd)) + 1313 (sizeof(*tlv) + sizeof(*ch)) + 1314 (sizeof(*tlv) + 0); 1315 skb = ath10k_wmi_alloc_skb(ar, len); 1316 if (!skb) 1317 return ERR_PTR(-ENOMEM); 1318 1319 if (arg->hidden_ssid) 1320 flags |= WMI_VDEV_START_HIDDEN_SSID; 1321 if (arg->pmf_enabled) 1322 flags |= WMI_VDEV_START_PMF_ENABLED; 1323 1324 ptr = (void *)skb->data; 1325 1326 tlv = ptr; 1327 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_START_REQUEST_CMD); 1328 tlv->len = __cpu_to_le16(sizeof(*cmd)); 1329 cmd = (void *)tlv->value; 1330 cmd->vdev_id = __cpu_to_le32(arg->vdev_id); 1331 cmd->bcn_intval = __cpu_to_le32(arg->bcn_intval); 1332 cmd->dtim_period = __cpu_to_le32(arg->dtim_period); 1333 cmd->flags = __cpu_to_le32(flags); 1334 cmd->bcn_tx_rate = __cpu_to_le32(arg->bcn_tx_rate); 1335 cmd->bcn_tx_power = __cpu_to_le32(arg->bcn_tx_power); 1336 cmd->disable_hw_ack = __cpu_to_le32(arg->disable_hw_ack); 1337 1338 if (arg->ssid) { 1339 cmd->ssid.ssid_len = __cpu_to_le32(arg->ssid_len); 1340 memcpy(cmd->ssid.ssid, arg->ssid, arg->ssid_len); 1341 } 1342 1343 ptr += sizeof(*tlv); 1344 ptr += sizeof(*cmd); 1345 1346 tlv = ptr; 1347 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_CHANNEL); 1348 tlv->len = __cpu_to_le16(sizeof(*ch)); 1349 ch = (void *)tlv->value; 1350 ath10k_wmi_put_wmi_channel(ch, &arg->channel); 1351 1352 ptr += sizeof(*tlv); 1353 ptr += sizeof(*ch); 1354 1355 tlv = ptr; 1356 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT); 1357 tlv->len = 0; 1358 noa = (void *)tlv->value; 1359 1360 /* Note: This is a nested TLV containing: 1361 * [wmi_tlv][wmi_p2p_noa_descriptor][wmi_tlv].. 1362 */ 1363 1364 ptr += sizeof(*tlv); 1365 ptr += 0; 1366 1367 ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev start\n"); 1368 return skb; 1369 } 1370 1371 static struct sk_buff * 1372 ath10k_wmi_tlv_op_gen_vdev_stop(struct ath10k *ar, u32 vdev_id) 1373 { 1374 struct wmi_vdev_stop_cmd *cmd; 1375 struct wmi_tlv *tlv; 1376 struct sk_buff *skb; 1377 1378 skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd)); 1379 if (!skb) 1380 return ERR_PTR(-ENOMEM); 1381 1382 tlv = (void *)skb->data; 1383 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_STOP_CMD); 1384 tlv->len = __cpu_to_le16(sizeof(*cmd)); 1385 cmd = (void *)tlv->value; 1386 cmd->vdev_id = __cpu_to_le32(vdev_id); 1387 1388 ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev stop\n"); 1389 return skb; 1390 } 1391 1392 static struct sk_buff * 1393 ath10k_wmi_tlv_op_gen_vdev_up(struct ath10k *ar, u32 vdev_id, u32 aid, 1394 const u8 *bssid) 1395 1396 { 1397 struct wmi_vdev_up_cmd *cmd; 1398 struct wmi_tlv *tlv; 1399 struct sk_buff *skb; 1400 1401 skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd)); 1402 if (!skb) 1403 return ERR_PTR(-ENOMEM); 1404 1405 tlv = (void *)skb->data; 1406 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_UP_CMD); 1407 tlv->len = __cpu_to_le16(sizeof(*cmd)); 1408 cmd = (void *)tlv->value; 1409 cmd->vdev_id = __cpu_to_le32(vdev_id); 1410 cmd->vdev_assoc_id = __cpu_to_le32(aid); 1411 ether_addr_copy(cmd->vdev_bssid.addr, bssid); 1412 1413 ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev up\n"); 1414 return skb; 1415 } 1416 1417 static struct sk_buff * 1418 ath10k_wmi_tlv_op_gen_vdev_down(struct ath10k *ar, u32 vdev_id) 1419 { 1420 struct wmi_vdev_down_cmd *cmd; 1421 struct wmi_tlv *tlv; 1422 struct sk_buff *skb; 1423 1424 skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd)); 1425 if (!skb) 1426 return ERR_PTR(-ENOMEM); 1427 1428 tlv = (void *)skb->data; 1429 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_DOWN_CMD); 1430 tlv->len = __cpu_to_le16(sizeof(*cmd)); 1431 cmd = (void *)tlv->value; 1432 cmd->vdev_id = __cpu_to_le32(vdev_id); 1433 1434 ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev down\n"); 1435 return skb; 1436 } 1437 1438 static struct sk_buff * 1439 ath10k_wmi_tlv_op_gen_vdev_set_param(struct ath10k *ar, u32 vdev_id, 1440 u32 param_id, u32 param_value) 1441 { 1442 struct wmi_vdev_set_param_cmd *cmd; 1443 struct wmi_tlv *tlv; 1444 struct sk_buff *skb; 1445 1446 skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd)); 1447 if (!skb) 1448 return ERR_PTR(-ENOMEM); 1449 1450 tlv = (void *)skb->data; 1451 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_SET_PARAM_CMD); 1452 tlv->len = __cpu_to_le16(sizeof(*cmd)); 1453 cmd = (void *)tlv->value; 1454 cmd->vdev_id = __cpu_to_le32(vdev_id); 1455 cmd->param_id = __cpu_to_le32(param_id); 1456 cmd->param_value = __cpu_to_le32(param_value); 1457 1458 ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev set param\n"); 1459 return skb; 1460 } 1461 1462 static struct sk_buff * 1463 ath10k_wmi_tlv_op_gen_vdev_install_key(struct ath10k *ar, 1464 const struct wmi_vdev_install_key_arg *arg) 1465 { 1466 struct wmi_vdev_install_key_cmd *cmd; 1467 struct wmi_tlv *tlv; 1468 struct sk_buff *skb; 1469 size_t len; 1470 void *ptr; 1471 1472 if (arg->key_cipher == WMI_CIPHER_NONE && arg->key_data != NULL) 1473 return ERR_PTR(-EINVAL); 1474 if (arg->key_cipher != WMI_CIPHER_NONE && arg->key_data == NULL) 1475 return ERR_PTR(-EINVAL); 1476 1477 len = sizeof(*tlv) + sizeof(*cmd) + 1478 sizeof(*tlv) + roundup(arg->key_len, sizeof(__le32)); 1479 skb = ath10k_wmi_alloc_skb(ar, len); 1480 if (!skb) 1481 return ERR_PTR(-ENOMEM); 1482 1483 ptr = (void *)skb->data; 1484 tlv = ptr; 1485 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_INSTALL_KEY_CMD); 1486 tlv->len = __cpu_to_le16(sizeof(*cmd)); 1487 cmd = (void *)tlv->value; 1488 cmd->vdev_id = __cpu_to_le32(arg->vdev_id); 1489 cmd->key_idx = __cpu_to_le32(arg->key_idx); 1490 cmd->key_flags = __cpu_to_le32(arg->key_flags); 1491 cmd->key_cipher = __cpu_to_le32(arg->key_cipher); 1492 cmd->key_len = __cpu_to_le32(arg->key_len); 1493 cmd->key_txmic_len = __cpu_to_le32(arg->key_txmic_len); 1494 cmd->key_rxmic_len = __cpu_to_le32(arg->key_rxmic_len); 1495 1496 if (arg->macaddr) 1497 ether_addr_copy(cmd->peer_macaddr.addr, arg->macaddr); 1498 1499 ptr += sizeof(*tlv); 1500 ptr += sizeof(*cmd); 1501 1502 tlv = ptr; 1503 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE); 1504 tlv->len = __cpu_to_le16(roundup(arg->key_len, sizeof(__le32))); 1505 if (arg->key_data) 1506 memcpy(tlv->value, arg->key_data, arg->key_len); 1507 1508 ptr += sizeof(*tlv); 1509 ptr += roundup(arg->key_len, sizeof(__le32)); 1510 1511 ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev install key\n"); 1512 return skb; 1513 } 1514 1515 static void *ath10k_wmi_tlv_put_uapsd_ac(struct ath10k *ar, void *ptr, 1516 const struct wmi_sta_uapsd_auto_trig_arg *arg) 1517 { 1518 struct wmi_sta_uapsd_auto_trig_param *ac; 1519 struct wmi_tlv *tlv; 1520 1521 tlv = ptr; 1522 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STA_UAPSD_AUTO_TRIG_PARAM); 1523 tlv->len = __cpu_to_le16(sizeof(*ac)); 1524 ac = (void *)tlv->value; 1525 1526 ac->wmm_ac = __cpu_to_le32(arg->wmm_ac); 1527 ac->user_priority = __cpu_to_le32(arg->user_priority); 1528 ac->service_interval = __cpu_to_le32(arg->service_interval); 1529 ac->suspend_interval = __cpu_to_le32(arg->suspend_interval); 1530 ac->delay_interval = __cpu_to_le32(arg->delay_interval); 1531 1532 ath10k_dbg(ar, ATH10K_DBG_WMI, 1533 "wmi tlv vdev sta uapsd auto trigger ac %d prio %d svc int %d susp int %d delay int %d\n", 1534 ac->wmm_ac, ac->user_priority, ac->service_interval, 1535 ac->suspend_interval, ac->delay_interval); 1536 1537 return ptr + sizeof(*tlv) + sizeof(*ac); 1538 } 1539 1540 static struct sk_buff * 1541 ath10k_wmi_tlv_op_gen_vdev_sta_uapsd(struct ath10k *ar, u32 vdev_id, 1542 const u8 peer_addr[ETH_ALEN], 1543 const struct wmi_sta_uapsd_auto_trig_arg *args, 1544 u32 num_ac) 1545 { 1546 struct wmi_sta_uapsd_auto_trig_cmd_fixed_param *cmd; 1547 struct wmi_sta_uapsd_auto_trig_param *ac; 1548 struct wmi_tlv *tlv; 1549 struct sk_buff *skb; 1550 size_t len; 1551 size_t ac_tlv_len; 1552 void *ptr; 1553 int i; 1554 1555 ac_tlv_len = num_ac * (sizeof(*tlv) + sizeof(*ac)); 1556 len = sizeof(*tlv) + sizeof(*cmd) + 1557 sizeof(*tlv) + ac_tlv_len; 1558 skb = ath10k_wmi_alloc_skb(ar, len); 1559 if (!skb) 1560 return ERR_PTR(-ENOMEM); 1561 1562 ptr = (void *)skb->data; 1563 tlv = ptr; 1564 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STA_UAPSD_AUTO_TRIG_CMD); 1565 tlv->len = __cpu_to_le16(sizeof(*cmd)); 1566 cmd = (void *)tlv->value; 1567 cmd->vdev_id = __cpu_to_le32(vdev_id); 1568 cmd->num_ac = __cpu_to_le32(num_ac); 1569 ether_addr_copy(cmd->peer_macaddr.addr, peer_addr); 1570 1571 ptr += sizeof(*tlv); 1572 ptr += sizeof(*cmd); 1573 1574 tlv = ptr; 1575 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT); 1576 tlv->len = __cpu_to_le16(ac_tlv_len); 1577 ac = (void *)tlv->value; 1578 1579 ptr += sizeof(*tlv); 1580 for (i = 0; i < num_ac; i++) 1581 ptr = ath10k_wmi_tlv_put_uapsd_ac(ar, ptr, &args[i]); 1582 1583 ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev sta uapsd auto trigger\n"); 1584 return skb; 1585 } 1586 1587 static void *ath10k_wmi_tlv_put_wmm(void *ptr, 1588 const struct wmi_wmm_params_arg *arg) 1589 { 1590 struct wmi_wmm_params *wmm; 1591 struct wmi_tlv *tlv; 1592 1593 tlv = ptr; 1594 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_WMM_PARAMS); 1595 tlv->len = __cpu_to_le16(sizeof(*wmm)); 1596 wmm = (void *)tlv->value; 1597 ath10k_wmi_set_wmm_param(wmm, arg); 1598 1599 return ptr + sizeof(*tlv) + sizeof(*wmm); 1600 } 1601 1602 static struct sk_buff * 1603 ath10k_wmi_tlv_op_gen_vdev_wmm_conf(struct ath10k *ar, u32 vdev_id, 1604 const struct wmi_wmm_params_all_arg *arg) 1605 { 1606 struct wmi_tlv_vdev_set_wmm_cmd *cmd; 1607 struct wmi_wmm_params *wmm; 1608 struct wmi_tlv *tlv; 1609 struct sk_buff *skb; 1610 size_t len; 1611 void *ptr; 1612 1613 len = (sizeof(*tlv) + sizeof(*cmd)) + 1614 (4 * (sizeof(*tlv) + sizeof(*wmm))); 1615 skb = ath10k_wmi_alloc_skb(ar, len); 1616 if (!skb) 1617 return ERR_PTR(-ENOMEM); 1618 1619 ptr = (void *)skb->data; 1620 tlv = ptr; 1621 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VDEV_SET_WMM_PARAMS_CMD); 1622 tlv->len = __cpu_to_le16(sizeof(*cmd)); 1623 cmd = (void *)tlv->value; 1624 cmd->vdev_id = __cpu_to_le32(vdev_id); 1625 1626 ptr += sizeof(*tlv); 1627 ptr += sizeof(*cmd); 1628 1629 ptr = ath10k_wmi_tlv_put_wmm(ptr, &arg->ac_be); 1630 ptr = ath10k_wmi_tlv_put_wmm(ptr, &arg->ac_bk); 1631 ptr = ath10k_wmi_tlv_put_wmm(ptr, &arg->ac_vi); 1632 ptr = ath10k_wmi_tlv_put_wmm(ptr, &arg->ac_vo); 1633 1634 ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev wmm conf\n"); 1635 return skb; 1636 } 1637 1638 static struct sk_buff * 1639 ath10k_wmi_tlv_op_gen_sta_keepalive(struct ath10k *ar, 1640 const struct wmi_sta_keepalive_arg *arg) 1641 { 1642 struct wmi_tlv_sta_keepalive_cmd *cmd; 1643 struct wmi_sta_keepalive_arp_resp *arp; 1644 struct sk_buff *skb; 1645 struct wmi_tlv *tlv; 1646 void *ptr; 1647 size_t len; 1648 1649 len = sizeof(*tlv) + sizeof(*cmd) + 1650 sizeof(*tlv) + sizeof(*arp); 1651 skb = ath10k_wmi_alloc_skb(ar, len); 1652 if (!skb) 1653 return ERR_PTR(-ENOMEM); 1654 1655 ptr = (void *)skb->data; 1656 tlv = ptr; 1657 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STA_KEEPALIVE_CMD); 1658 tlv->len = __cpu_to_le16(sizeof(*cmd)); 1659 cmd = (void *)tlv->value; 1660 cmd->vdev_id = __cpu_to_le32(arg->vdev_id); 1661 cmd->enabled = __cpu_to_le32(arg->enabled); 1662 cmd->method = __cpu_to_le32(arg->method); 1663 cmd->interval = __cpu_to_le32(arg->interval); 1664 1665 ptr += sizeof(*tlv); 1666 ptr += sizeof(*cmd); 1667 1668 tlv = ptr; 1669 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STA_KEEPALVE_ARP_RESPONSE); 1670 tlv->len = __cpu_to_le16(sizeof(*arp)); 1671 arp = (void *)tlv->value; 1672 1673 arp->src_ip4_addr = arg->src_ip4_addr; 1674 arp->dest_ip4_addr = arg->dest_ip4_addr; 1675 ether_addr_copy(arp->dest_mac_addr.addr, arg->dest_mac_addr); 1676 1677 ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv sta keepalive vdev %d enabled %d method %d inverval %d\n", 1678 arg->vdev_id, arg->enabled, arg->method, arg->interval); 1679 return skb; 1680 } 1681 1682 static struct sk_buff * 1683 ath10k_wmi_tlv_op_gen_peer_create(struct ath10k *ar, u32 vdev_id, 1684 const u8 peer_addr[ETH_ALEN]) 1685 { 1686 struct wmi_tlv_peer_create_cmd *cmd; 1687 struct wmi_tlv *tlv; 1688 struct sk_buff *skb; 1689 1690 skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd)); 1691 if (!skb) 1692 return ERR_PTR(-ENOMEM); 1693 1694 tlv = (void *)skb->data; 1695 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PEER_CREATE_CMD); 1696 tlv->len = __cpu_to_le16(sizeof(*cmd)); 1697 cmd = (void *)tlv->value; 1698 cmd->vdev_id = __cpu_to_le32(vdev_id); 1699 cmd->peer_type = __cpu_to_le32(WMI_TLV_PEER_TYPE_DEFAULT); /* FIXME */ 1700 ether_addr_copy(cmd->peer_addr.addr, peer_addr); 1701 1702 ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv peer create\n"); 1703 return skb; 1704 } 1705 1706 static struct sk_buff * 1707 ath10k_wmi_tlv_op_gen_peer_delete(struct ath10k *ar, u32 vdev_id, 1708 const u8 peer_addr[ETH_ALEN]) 1709 { 1710 struct wmi_peer_delete_cmd *cmd; 1711 struct wmi_tlv *tlv; 1712 struct sk_buff *skb; 1713 1714 skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd)); 1715 if (!skb) 1716 return ERR_PTR(-ENOMEM); 1717 1718 tlv = (void *)skb->data; 1719 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PEER_DELETE_CMD); 1720 tlv->len = __cpu_to_le16(sizeof(*cmd)); 1721 cmd = (void *)tlv->value; 1722 cmd->vdev_id = __cpu_to_le32(vdev_id); 1723 ether_addr_copy(cmd->peer_macaddr.addr, peer_addr); 1724 1725 ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv peer delete\n"); 1726 return skb; 1727 } 1728 1729 static struct sk_buff * 1730 ath10k_wmi_tlv_op_gen_peer_flush(struct ath10k *ar, u32 vdev_id, 1731 const u8 peer_addr[ETH_ALEN], u32 tid_bitmap) 1732 { 1733 struct wmi_peer_flush_tids_cmd *cmd; 1734 struct wmi_tlv *tlv; 1735 struct sk_buff *skb; 1736 1737 skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd)); 1738 if (!skb) 1739 return ERR_PTR(-ENOMEM); 1740 1741 tlv = (void *)skb->data; 1742 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PEER_FLUSH_TIDS_CMD); 1743 tlv->len = __cpu_to_le16(sizeof(*cmd)); 1744 cmd = (void *)tlv->value; 1745 cmd->vdev_id = __cpu_to_le32(vdev_id); 1746 cmd->peer_tid_bitmap = __cpu_to_le32(tid_bitmap); 1747 ether_addr_copy(cmd->peer_macaddr.addr, peer_addr); 1748 1749 ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv peer flush\n"); 1750 return skb; 1751 } 1752 1753 static struct sk_buff * 1754 ath10k_wmi_tlv_op_gen_peer_set_param(struct ath10k *ar, u32 vdev_id, 1755 const u8 *peer_addr, 1756 enum wmi_peer_param param_id, 1757 u32 param_value) 1758 { 1759 struct wmi_peer_set_param_cmd *cmd; 1760 struct wmi_tlv *tlv; 1761 struct sk_buff *skb; 1762 1763 skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd)); 1764 if (!skb) 1765 return ERR_PTR(-ENOMEM); 1766 1767 tlv = (void *)skb->data; 1768 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PEER_SET_PARAM_CMD); 1769 tlv->len = __cpu_to_le16(sizeof(*cmd)); 1770 cmd = (void *)tlv->value; 1771 cmd->vdev_id = __cpu_to_le32(vdev_id); 1772 cmd->param_id = __cpu_to_le32(param_id); 1773 cmd->param_value = __cpu_to_le32(param_value); 1774 ether_addr_copy(cmd->peer_macaddr.addr, peer_addr); 1775 1776 ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv peer set param\n"); 1777 return skb; 1778 } 1779 1780 static struct sk_buff * 1781 ath10k_wmi_tlv_op_gen_peer_assoc(struct ath10k *ar, 1782 const struct wmi_peer_assoc_complete_arg *arg) 1783 { 1784 struct wmi_tlv_peer_assoc_cmd *cmd; 1785 struct wmi_vht_rate_set *vht_rate; 1786 struct wmi_tlv *tlv; 1787 struct sk_buff *skb; 1788 size_t len, legacy_rate_len, ht_rate_len; 1789 void *ptr; 1790 1791 if (arg->peer_mpdu_density > 16) 1792 return ERR_PTR(-EINVAL); 1793 if (arg->peer_legacy_rates.num_rates > MAX_SUPPORTED_RATES) 1794 return ERR_PTR(-EINVAL); 1795 if (arg->peer_ht_rates.num_rates > MAX_SUPPORTED_RATES) 1796 return ERR_PTR(-EINVAL); 1797 1798 legacy_rate_len = roundup(arg->peer_legacy_rates.num_rates, 1799 sizeof(__le32)); 1800 ht_rate_len = roundup(arg->peer_ht_rates.num_rates, sizeof(__le32)); 1801 len = (sizeof(*tlv) + sizeof(*cmd)) + 1802 (sizeof(*tlv) + legacy_rate_len) + 1803 (sizeof(*tlv) + ht_rate_len) + 1804 (sizeof(*tlv) + sizeof(*vht_rate)); 1805 skb = ath10k_wmi_alloc_skb(ar, len); 1806 if (!skb) 1807 return ERR_PTR(-ENOMEM); 1808 1809 ptr = (void *)skb->data; 1810 tlv = ptr; 1811 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PEER_ASSOC_COMPLETE_CMD); 1812 tlv->len = __cpu_to_le16(sizeof(*cmd)); 1813 cmd = (void *)tlv->value; 1814 1815 cmd->vdev_id = __cpu_to_le32(arg->vdev_id); 1816 cmd->new_assoc = __cpu_to_le32(arg->peer_reassoc ? 0 : 1); 1817 cmd->assoc_id = __cpu_to_le32(arg->peer_aid); 1818 cmd->flags = __cpu_to_le32(arg->peer_flags); 1819 cmd->caps = __cpu_to_le32(arg->peer_caps); 1820 cmd->listen_intval = __cpu_to_le32(arg->peer_listen_intval); 1821 cmd->ht_caps = __cpu_to_le32(arg->peer_ht_caps); 1822 cmd->max_mpdu = __cpu_to_le32(arg->peer_max_mpdu); 1823 cmd->mpdu_density = __cpu_to_le32(arg->peer_mpdu_density); 1824 cmd->rate_caps = __cpu_to_le32(arg->peer_rate_caps); 1825 cmd->nss = __cpu_to_le32(arg->peer_num_spatial_streams); 1826 cmd->vht_caps = __cpu_to_le32(arg->peer_vht_caps); 1827 cmd->phy_mode = __cpu_to_le32(arg->peer_phymode); 1828 cmd->num_legacy_rates = __cpu_to_le32(arg->peer_legacy_rates.num_rates); 1829 cmd->num_ht_rates = __cpu_to_le32(arg->peer_ht_rates.num_rates); 1830 ether_addr_copy(cmd->mac_addr.addr, arg->addr); 1831 1832 ptr += sizeof(*tlv); 1833 ptr += sizeof(*cmd); 1834 1835 tlv = ptr; 1836 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE); 1837 tlv->len = __cpu_to_le16(legacy_rate_len); 1838 memcpy(tlv->value, arg->peer_legacy_rates.rates, 1839 arg->peer_legacy_rates.num_rates); 1840 1841 ptr += sizeof(*tlv); 1842 ptr += legacy_rate_len; 1843 1844 tlv = ptr; 1845 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE); 1846 tlv->len = __cpu_to_le16(ht_rate_len); 1847 memcpy(tlv->value, arg->peer_ht_rates.rates, 1848 arg->peer_ht_rates.num_rates); 1849 1850 ptr += sizeof(*tlv); 1851 ptr += ht_rate_len; 1852 1853 tlv = ptr; 1854 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_VHT_RATE_SET); 1855 tlv->len = __cpu_to_le16(sizeof(*vht_rate)); 1856 vht_rate = (void *)tlv->value; 1857 1858 vht_rate->rx_max_rate = __cpu_to_le32(arg->peer_vht_rates.rx_max_rate); 1859 vht_rate->rx_mcs_set = __cpu_to_le32(arg->peer_vht_rates.rx_mcs_set); 1860 vht_rate->tx_max_rate = __cpu_to_le32(arg->peer_vht_rates.tx_max_rate); 1861 vht_rate->tx_mcs_set = __cpu_to_le32(arg->peer_vht_rates.tx_mcs_set); 1862 1863 ptr += sizeof(*tlv); 1864 ptr += sizeof(*vht_rate); 1865 1866 ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv peer assoc\n"); 1867 return skb; 1868 } 1869 1870 static struct sk_buff * 1871 ath10k_wmi_tlv_op_gen_set_psmode(struct ath10k *ar, u32 vdev_id, 1872 enum wmi_sta_ps_mode psmode) 1873 { 1874 struct wmi_sta_powersave_mode_cmd *cmd; 1875 struct wmi_tlv *tlv; 1876 struct sk_buff *skb; 1877 1878 skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd)); 1879 if (!skb) 1880 return ERR_PTR(-ENOMEM); 1881 1882 tlv = (void *)skb->data; 1883 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STA_POWERSAVE_MODE_CMD); 1884 tlv->len = __cpu_to_le16(sizeof(*cmd)); 1885 cmd = (void *)tlv->value; 1886 cmd->vdev_id = __cpu_to_le32(vdev_id); 1887 cmd->sta_ps_mode = __cpu_to_le32(psmode); 1888 1889 ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv set psmode\n"); 1890 return skb; 1891 } 1892 1893 static struct sk_buff * 1894 ath10k_wmi_tlv_op_gen_set_sta_ps(struct ath10k *ar, u32 vdev_id, 1895 enum wmi_sta_powersave_param param_id, 1896 u32 param_value) 1897 { 1898 struct wmi_sta_powersave_param_cmd *cmd; 1899 struct wmi_tlv *tlv; 1900 struct sk_buff *skb; 1901 1902 skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd)); 1903 if (!skb) 1904 return ERR_PTR(-ENOMEM); 1905 1906 tlv = (void *)skb->data; 1907 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_STA_POWERSAVE_PARAM_CMD); 1908 tlv->len = __cpu_to_le16(sizeof(*cmd)); 1909 cmd = (void *)tlv->value; 1910 cmd->vdev_id = __cpu_to_le32(vdev_id); 1911 cmd->param_id = __cpu_to_le32(param_id); 1912 cmd->param_value = __cpu_to_le32(param_value); 1913 1914 ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv set sta ps\n"); 1915 return skb; 1916 } 1917 1918 static struct sk_buff * 1919 ath10k_wmi_tlv_op_gen_set_ap_ps(struct ath10k *ar, u32 vdev_id, const u8 *mac, 1920 enum wmi_ap_ps_peer_param param_id, u32 value) 1921 { 1922 struct wmi_ap_ps_peer_cmd *cmd; 1923 struct wmi_tlv *tlv; 1924 struct sk_buff *skb; 1925 1926 if (!mac) 1927 return ERR_PTR(-EINVAL); 1928 1929 skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd)); 1930 if (!skb) 1931 return ERR_PTR(-ENOMEM); 1932 1933 tlv = (void *)skb->data; 1934 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_AP_PS_PEER_CMD); 1935 tlv->len = __cpu_to_le16(sizeof(*cmd)); 1936 cmd = (void *)tlv->value; 1937 cmd->vdev_id = __cpu_to_le32(vdev_id); 1938 cmd->param_id = __cpu_to_le32(param_id); 1939 cmd->param_value = __cpu_to_le32(value); 1940 ether_addr_copy(cmd->peer_macaddr.addr, mac); 1941 1942 ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv ap ps param\n"); 1943 return skb; 1944 } 1945 1946 static struct sk_buff * 1947 ath10k_wmi_tlv_op_gen_scan_chan_list(struct ath10k *ar, 1948 const struct wmi_scan_chan_list_arg *arg) 1949 { 1950 struct wmi_tlv_scan_chan_list_cmd *cmd; 1951 struct wmi_channel *ci; 1952 struct wmi_channel_arg *ch; 1953 struct wmi_tlv *tlv; 1954 struct sk_buff *skb; 1955 size_t chans_len, len; 1956 int i; 1957 void *ptr, *chans; 1958 1959 chans_len = arg->n_channels * (sizeof(*tlv) + sizeof(*ci)); 1960 len = (sizeof(*tlv) + sizeof(*cmd)) + 1961 (sizeof(*tlv) + chans_len); 1962 1963 skb = ath10k_wmi_alloc_skb(ar, len); 1964 if (!skb) 1965 return ERR_PTR(-ENOMEM); 1966 1967 ptr = (void *)skb->data; 1968 tlv = ptr; 1969 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_SCAN_CHAN_LIST_CMD); 1970 tlv->len = __cpu_to_le16(sizeof(*cmd)); 1971 cmd = (void *)tlv->value; 1972 cmd->num_scan_chans = __cpu_to_le32(arg->n_channels); 1973 1974 ptr += sizeof(*tlv); 1975 ptr += sizeof(*cmd); 1976 1977 tlv = ptr; 1978 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT); 1979 tlv->len = __cpu_to_le16(chans_len); 1980 chans = (void *)tlv->value; 1981 1982 for (i = 0; i < arg->n_channels; i++) { 1983 ch = &arg->channels[i]; 1984 1985 tlv = chans; 1986 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_CHANNEL); 1987 tlv->len = __cpu_to_le16(sizeof(*ci)); 1988 ci = (void *)tlv->value; 1989 1990 ath10k_wmi_put_wmi_channel(ci, ch); 1991 1992 chans += sizeof(*tlv); 1993 chans += sizeof(*ci); 1994 } 1995 1996 ptr += sizeof(*tlv); 1997 ptr += chans_len; 1998 1999 ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv scan chan list\n"); 2000 return skb; 2001 } 2002 2003 static struct sk_buff * 2004 ath10k_wmi_tlv_op_gen_beacon_dma(struct ath10k *ar, u32 vdev_id, 2005 const void *bcn, size_t bcn_len, 2006 u32 bcn_paddr, bool dtim_zero, 2007 bool deliver_cab) 2008 2009 { 2010 struct wmi_bcn_tx_ref_cmd *cmd; 2011 struct wmi_tlv *tlv; 2012 struct sk_buff *skb; 2013 struct ieee80211_hdr *hdr; 2014 u16 fc; 2015 2016 skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd)); 2017 if (!skb) 2018 return ERR_PTR(-ENOMEM); 2019 2020 hdr = (struct ieee80211_hdr *)bcn; 2021 fc = le16_to_cpu(hdr->frame_control); 2022 2023 tlv = (void *)skb->data; 2024 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_BCN_SEND_FROM_HOST_CMD); 2025 tlv->len = __cpu_to_le16(sizeof(*cmd)); 2026 cmd = (void *)tlv->value; 2027 cmd->vdev_id = __cpu_to_le32(vdev_id); 2028 cmd->data_len = __cpu_to_le32(bcn_len); 2029 cmd->data_ptr = __cpu_to_le32(bcn_paddr); 2030 cmd->msdu_id = 0; 2031 cmd->frame_control = __cpu_to_le32(fc); 2032 cmd->flags = 0; 2033 2034 if (dtim_zero) 2035 cmd->flags |= __cpu_to_le32(WMI_BCN_TX_REF_FLAG_DTIM_ZERO); 2036 2037 if (deliver_cab) 2038 cmd->flags |= __cpu_to_le32(WMI_BCN_TX_REF_FLAG_DELIVER_CAB); 2039 2040 ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv beacon dma\n"); 2041 return skb; 2042 } 2043 2044 static struct sk_buff * 2045 ath10k_wmi_tlv_op_gen_pdev_set_wmm(struct ath10k *ar, 2046 const struct wmi_wmm_params_all_arg *arg) 2047 { 2048 struct wmi_tlv_pdev_set_wmm_cmd *cmd; 2049 struct wmi_wmm_params *wmm; 2050 struct wmi_tlv *tlv; 2051 struct sk_buff *skb; 2052 size_t len; 2053 void *ptr; 2054 2055 len = (sizeof(*tlv) + sizeof(*cmd)) + 2056 (4 * (sizeof(*tlv) + sizeof(*wmm))); 2057 skb = ath10k_wmi_alloc_skb(ar, len); 2058 if (!skb) 2059 return ERR_PTR(-ENOMEM); 2060 2061 ptr = (void *)skb->data; 2062 2063 tlv = ptr; 2064 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_SET_WMM_PARAMS_CMD); 2065 tlv->len = __cpu_to_le16(sizeof(*cmd)); 2066 cmd = (void *)tlv->value; 2067 2068 /* nothing to set here */ 2069 2070 ptr += sizeof(*tlv); 2071 ptr += sizeof(*cmd); 2072 2073 ptr = ath10k_wmi_tlv_put_wmm(ptr, &arg->ac_be); 2074 ptr = ath10k_wmi_tlv_put_wmm(ptr, &arg->ac_bk); 2075 ptr = ath10k_wmi_tlv_put_wmm(ptr, &arg->ac_vi); 2076 ptr = ath10k_wmi_tlv_put_wmm(ptr, &arg->ac_vo); 2077 2078 ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pdev set wmm\n"); 2079 return skb; 2080 } 2081 2082 static struct sk_buff * 2083 ath10k_wmi_tlv_op_gen_request_stats(struct ath10k *ar, 2084 enum wmi_stats_id stats_id) 2085 { 2086 struct wmi_request_stats_cmd *cmd; 2087 struct wmi_tlv *tlv; 2088 struct sk_buff *skb; 2089 2090 skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd)); 2091 if (!skb) 2092 return ERR_PTR(-ENOMEM); 2093 2094 tlv = (void *)skb->data; 2095 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_REQUEST_STATS_CMD); 2096 tlv->len = __cpu_to_le16(sizeof(*cmd)); 2097 cmd = (void *)tlv->value; 2098 cmd->stats_id = __cpu_to_le32(stats_id); 2099 2100 ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv request stats\n"); 2101 return skb; 2102 } 2103 2104 static struct sk_buff * 2105 ath10k_wmi_tlv_op_gen_force_fw_hang(struct ath10k *ar, 2106 enum wmi_force_fw_hang_type type, 2107 u32 delay_ms) 2108 { 2109 struct wmi_force_fw_hang_cmd *cmd; 2110 struct wmi_tlv *tlv; 2111 struct sk_buff *skb; 2112 2113 skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd)); 2114 if (!skb) 2115 return ERR_PTR(-ENOMEM); 2116 2117 tlv = (void *)skb->data; 2118 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_FORCE_FW_HANG_CMD); 2119 tlv->len = __cpu_to_le16(sizeof(*cmd)); 2120 cmd = (void *)tlv->value; 2121 cmd->type = __cpu_to_le32(type); 2122 cmd->delay_ms = __cpu_to_le32(delay_ms); 2123 2124 ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv force fw hang\n"); 2125 return skb; 2126 } 2127 2128 static struct sk_buff * 2129 ath10k_wmi_tlv_op_gen_dbglog_cfg(struct ath10k *ar, u32 module_enable, 2130 u32 log_level) { 2131 struct wmi_tlv_dbglog_cmd *cmd; 2132 struct wmi_tlv *tlv; 2133 struct sk_buff *skb; 2134 size_t len, bmap_len; 2135 u32 value; 2136 void *ptr; 2137 2138 if (module_enable) { 2139 value = WMI_TLV_DBGLOG_LOG_LEVEL_VALUE( 2140 module_enable, 2141 WMI_TLV_DBGLOG_LOG_LEVEL_VERBOSE); 2142 } else { 2143 value = WMI_TLV_DBGLOG_LOG_LEVEL_VALUE( 2144 WMI_TLV_DBGLOG_ALL_MODULES, 2145 WMI_TLV_DBGLOG_LOG_LEVEL_WARN); 2146 } 2147 2148 bmap_len = 0; 2149 len = sizeof(*tlv) + sizeof(*cmd) + sizeof(*tlv) + bmap_len; 2150 skb = ath10k_wmi_alloc_skb(ar, len); 2151 if (!skb) 2152 return ERR_PTR(-ENOMEM); 2153 2154 ptr = (void *)skb->data; 2155 2156 tlv = ptr; 2157 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_DEBUG_LOG_CONFIG_CMD); 2158 tlv->len = __cpu_to_le16(sizeof(*cmd)); 2159 cmd = (void *)tlv->value; 2160 cmd->param = __cpu_to_le32(WMI_TLV_DBGLOG_PARAM_LOG_LEVEL); 2161 cmd->value = __cpu_to_le32(value); 2162 2163 ptr += sizeof(*tlv); 2164 ptr += sizeof(*cmd); 2165 2166 tlv = ptr; 2167 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_UINT32); 2168 tlv->len = __cpu_to_le16(bmap_len); 2169 2170 /* nothing to do here */ 2171 2172 ptr += sizeof(*tlv); 2173 ptr += sizeof(bmap_len); 2174 2175 ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv dbglog value 0x%08x\n", value); 2176 return skb; 2177 } 2178 2179 static struct sk_buff * 2180 ath10k_wmi_tlv_op_gen_pktlog_enable(struct ath10k *ar, u32 filter) 2181 { 2182 struct wmi_tlv_pktlog_enable *cmd; 2183 struct wmi_tlv *tlv; 2184 struct sk_buff *skb; 2185 void *ptr; 2186 size_t len; 2187 2188 len = sizeof(*tlv) + sizeof(*cmd); 2189 skb = ath10k_wmi_alloc_skb(ar, len); 2190 if (!skb) 2191 return ERR_PTR(-ENOMEM); 2192 2193 ptr = (void *)skb->data; 2194 tlv = ptr; 2195 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_PKTLOG_ENABLE_CMD); 2196 tlv->len = __cpu_to_le16(sizeof(*cmd)); 2197 cmd = (void *)tlv->value; 2198 cmd->filter = __cpu_to_le32(filter); 2199 2200 ptr += sizeof(*tlv); 2201 ptr += sizeof(*cmd); 2202 2203 ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pktlog enable filter 0x%08x\n", 2204 filter); 2205 return skb; 2206 } 2207 2208 static struct sk_buff * 2209 ath10k_wmi_tlv_op_gen_pktlog_disable(struct ath10k *ar) 2210 { 2211 struct wmi_tlv_pktlog_disable *cmd; 2212 struct wmi_tlv *tlv; 2213 struct sk_buff *skb; 2214 void *ptr; 2215 size_t len; 2216 2217 len = sizeof(*tlv) + sizeof(*cmd); 2218 skb = ath10k_wmi_alloc_skb(ar, len); 2219 if (!skb) 2220 return ERR_PTR(-ENOMEM); 2221 2222 ptr = (void *)skb->data; 2223 tlv = ptr; 2224 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_PKTLOG_DISABLE_CMD); 2225 tlv->len = __cpu_to_le16(sizeof(*cmd)); 2226 cmd = (void *)tlv->value; 2227 2228 ptr += sizeof(*tlv); 2229 ptr += sizeof(*cmd); 2230 2231 ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pktlog disable\n"); 2232 return skb; 2233 } 2234 2235 static struct sk_buff * 2236 ath10k_wmi_tlv_op_gen_bcn_tmpl(struct ath10k *ar, u32 vdev_id, 2237 u32 tim_ie_offset, struct sk_buff *bcn, 2238 u32 prb_caps, u32 prb_erp, void *prb_ies, 2239 size_t prb_ies_len) 2240 { 2241 struct wmi_tlv_bcn_tmpl_cmd *cmd; 2242 struct wmi_tlv_bcn_prb_info *info; 2243 struct wmi_tlv *tlv; 2244 struct sk_buff *skb; 2245 void *ptr; 2246 size_t len; 2247 2248 if (WARN_ON(prb_ies_len > 0 && !prb_ies)) 2249 return ERR_PTR(-EINVAL); 2250 2251 len = sizeof(*tlv) + sizeof(*cmd) + 2252 sizeof(*tlv) + sizeof(*info) + prb_ies_len + 2253 sizeof(*tlv) + roundup(bcn->len, 4); 2254 skb = ath10k_wmi_alloc_skb(ar, len); 2255 if (!skb) 2256 return ERR_PTR(-ENOMEM); 2257 2258 ptr = (void *)skb->data; 2259 tlv = ptr; 2260 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_BCN_TMPL_CMD); 2261 tlv->len = __cpu_to_le16(sizeof(*cmd)); 2262 cmd = (void *)tlv->value; 2263 cmd->vdev_id = __cpu_to_le32(vdev_id); 2264 cmd->tim_ie_offset = __cpu_to_le32(tim_ie_offset); 2265 cmd->buf_len = __cpu_to_le32(bcn->len); 2266 2267 ptr += sizeof(*tlv); 2268 ptr += sizeof(*cmd); 2269 2270 /* FIXME: prb_ies_len should be probably aligned to 4byte boundary but 2271 * then it is then impossible to pass original ie len. 2272 * This chunk is not used yet so if setting probe resp template yields 2273 * problems with beaconing or crashes firmware look here. 2274 */ 2275 tlv = ptr; 2276 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_BCN_PRB_INFO); 2277 tlv->len = __cpu_to_le16(sizeof(*info) + prb_ies_len); 2278 info = (void *)tlv->value; 2279 info->caps = __cpu_to_le32(prb_caps); 2280 info->erp = __cpu_to_le32(prb_erp); 2281 memcpy(info->ies, prb_ies, prb_ies_len); 2282 2283 ptr += sizeof(*tlv); 2284 ptr += sizeof(*info); 2285 ptr += prb_ies_len; 2286 2287 tlv = ptr; 2288 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE); 2289 tlv->len = __cpu_to_le16(roundup(bcn->len, 4)); 2290 memcpy(tlv->value, bcn->data, bcn->len); 2291 2292 /* FIXME: Adjust TSF? */ 2293 2294 ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv bcn tmpl vdev_id %i\n", 2295 vdev_id); 2296 return skb; 2297 } 2298 2299 static struct sk_buff * 2300 ath10k_wmi_tlv_op_gen_prb_tmpl(struct ath10k *ar, u32 vdev_id, 2301 struct sk_buff *prb) 2302 { 2303 struct wmi_tlv_prb_tmpl_cmd *cmd; 2304 struct wmi_tlv_bcn_prb_info *info; 2305 struct wmi_tlv *tlv; 2306 struct sk_buff *skb; 2307 void *ptr; 2308 size_t len; 2309 2310 len = sizeof(*tlv) + sizeof(*cmd) + 2311 sizeof(*tlv) + sizeof(*info) + 2312 sizeof(*tlv) + roundup(prb->len, 4); 2313 skb = ath10k_wmi_alloc_skb(ar, len); 2314 if (!skb) 2315 return ERR_PTR(-ENOMEM); 2316 2317 ptr = (void *)skb->data; 2318 tlv = ptr; 2319 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PRB_TMPL_CMD); 2320 tlv->len = __cpu_to_le16(sizeof(*cmd)); 2321 cmd = (void *)tlv->value; 2322 cmd->vdev_id = __cpu_to_le32(vdev_id); 2323 cmd->buf_len = __cpu_to_le32(prb->len); 2324 2325 ptr += sizeof(*tlv); 2326 ptr += sizeof(*cmd); 2327 2328 tlv = ptr; 2329 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_BCN_PRB_INFO); 2330 tlv->len = __cpu_to_le16(sizeof(*info)); 2331 info = (void *)tlv->value; 2332 info->caps = 0; 2333 info->erp = 0; 2334 2335 ptr += sizeof(*tlv); 2336 ptr += sizeof(*info); 2337 2338 tlv = ptr; 2339 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE); 2340 tlv->len = __cpu_to_le16(roundup(prb->len, 4)); 2341 memcpy(tlv->value, prb->data, prb->len); 2342 2343 ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv prb tmpl vdev_id %i\n", 2344 vdev_id); 2345 return skb; 2346 } 2347 2348 static struct sk_buff * 2349 ath10k_wmi_tlv_op_gen_p2p_go_bcn_ie(struct ath10k *ar, u32 vdev_id, 2350 const u8 *p2p_ie) 2351 { 2352 struct wmi_tlv_p2p_go_bcn_ie *cmd; 2353 struct wmi_tlv *tlv; 2354 struct sk_buff *skb; 2355 void *ptr; 2356 size_t len; 2357 2358 len = sizeof(*tlv) + sizeof(*cmd) + 2359 sizeof(*tlv) + roundup(p2p_ie[1] + 2, 4); 2360 skb = ath10k_wmi_alloc_skb(ar, len); 2361 if (!skb) 2362 return ERR_PTR(-ENOMEM); 2363 2364 ptr = (void *)skb->data; 2365 tlv = ptr; 2366 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_P2P_GO_SET_BEACON_IE); 2367 tlv->len = __cpu_to_le16(sizeof(*cmd)); 2368 cmd = (void *)tlv->value; 2369 cmd->vdev_id = __cpu_to_le32(vdev_id); 2370 cmd->ie_len = __cpu_to_le32(p2p_ie[1] + 2); 2371 2372 ptr += sizeof(*tlv); 2373 ptr += sizeof(*cmd); 2374 2375 tlv = ptr; 2376 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE); 2377 tlv->len = __cpu_to_le16(roundup(p2p_ie[1] + 2, 4)); 2378 memcpy(tlv->value, p2p_ie, p2p_ie[1] + 2); 2379 2380 ptr += sizeof(*tlv); 2381 ptr += roundup(p2p_ie[1] + 2, 4); 2382 2383 ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv p2p go bcn ie for vdev %i\n", 2384 vdev_id); 2385 return skb; 2386 } 2387 2388 /****************/ 2389 /* TLV mappings */ 2390 /****************/ 2391 2392 static struct wmi_cmd_map wmi_tlv_cmd_map = { 2393 .init_cmdid = WMI_TLV_INIT_CMDID, 2394 .start_scan_cmdid = WMI_TLV_START_SCAN_CMDID, 2395 .stop_scan_cmdid = WMI_TLV_STOP_SCAN_CMDID, 2396 .scan_chan_list_cmdid = WMI_TLV_SCAN_CHAN_LIST_CMDID, 2397 .scan_sch_prio_tbl_cmdid = WMI_TLV_SCAN_SCH_PRIO_TBL_CMDID, 2398 .pdev_set_regdomain_cmdid = WMI_TLV_PDEV_SET_REGDOMAIN_CMDID, 2399 .pdev_set_channel_cmdid = WMI_TLV_PDEV_SET_CHANNEL_CMDID, 2400 .pdev_set_param_cmdid = WMI_TLV_PDEV_SET_PARAM_CMDID, 2401 .pdev_pktlog_enable_cmdid = WMI_TLV_PDEV_PKTLOG_ENABLE_CMDID, 2402 .pdev_pktlog_disable_cmdid = WMI_TLV_PDEV_PKTLOG_DISABLE_CMDID, 2403 .pdev_set_wmm_params_cmdid = WMI_TLV_PDEV_SET_WMM_PARAMS_CMDID, 2404 .pdev_set_ht_cap_ie_cmdid = WMI_TLV_PDEV_SET_HT_CAP_IE_CMDID, 2405 .pdev_set_vht_cap_ie_cmdid = WMI_TLV_PDEV_SET_VHT_CAP_IE_CMDID, 2406 .pdev_set_dscp_tid_map_cmdid = WMI_TLV_PDEV_SET_DSCP_TID_MAP_CMDID, 2407 .pdev_set_quiet_mode_cmdid = WMI_TLV_PDEV_SET_QUIET_MODE_CMDID, 2408 .pdev_green_ap_ps_enable_cmdid = WMI_TLV_PDEV_GREEN_AP_PS_ENABLE_CMDID, 2409 .pdev_get_tpc_config_cmdid = WMI_TLV_PDEV_GET_TPC_CONFIG_CMDID, 2410 .pdev_set_base_macaddr_cmdid = WMI_TLV_PDEV_SET_BASE_MACADDR_CMDID, 2411 .vdev_create_cmdid = WMI_TLV_VDEV_CREATE_CMDID, 2412 .vdev_delete_cmdid = WMI_TLV_VDEV_DELETE_CMDID, 2413 .vdev_start_request_cmdid = WMI_TLV_VDEV_START_REQUEST_CMDID, 2414 .vdev_restart_request_cmdid = WMI_TLV_VDEV_RESTART_REQUEST_CMDID, 2415 .vdev_up_cmdid = WMI_TLV_VDEV_UP_CMDID, 2416 .vdev_stop_cmdid = WMI_TLV_VDEV_STOP_CMDID, 2417 .vdev_down_cmdid = WMI_TLV_VDEV_DOWN_CMDID, 2418 .vdev_set_param_cmdid = WMI_TLV_VDEV_SET_PARAM_CMDID, 2419 .vdev_install_key_cmdid = WMI_TLV_VDEV_INSTALL_KEY_CMDID, 2420 .peer_create_cmdid = WMI_TLV_PEER_CREATE_CMDID, 2421 .peer_delete_cmdid = WMI_TLV_PEER_DELETE_CMDID, 2422 .peer_flush_tids_cmdid = WMI_TLV_PEER_FLUSH_TIDS_CMDID, 2423 .peer_set_param_cmdid = WMI_TLV_PEER_SET_PARAM_CMDID, 2424 .peer_assoc_cmdid = WMI_TLV_PEER_ASSOC_CMDID, 2425 .peer_add_wds_entry_cmdid = WMI_TLV_PEER_ADD_WDS_ENTRY_CMDID, 2426 .peer_remove_wds_entry_cmdid = WMI_TLV_PEER_REMOVE_WDS_ENTRY_CMDID, 2427 .peer_mcast_group_cmdid = WMI_TLV_PEER_MCAST_GROUP_CMDID, 2428 .bcn_tx_cmdid = WMI_TLV_BCN_TX_CMDID, 2429 .pdev_send_bcn_cmdid = WMI_TLV_PDEV_SEND_BCN_CMDID, 2430 .bcn_tmpl_cmdid = WMI_TLV_BCN_TMPL_CMDID, 2431 .bcn_filter_rx_cmdid = WMI_TLV_BCN_FILTER_RX_CMDID, 2432 .prb_req_filter_rx_cmdid = WMI_TLV_PRB_REQ_FILTER_RX_CMDID, 2433 .mgmt_tx_cmdid = WMI_TLV_MGMT_TX_CMDID, 2434 .prb_tmpl_cmdid = WMI_TLV_PRB_TMPL_CMDID, 2435 .addba_clear_resp_cmdid = WMI_TLV_ADDBA_CLEAR_RESP_CMDID, 2436 .addba_send_cmdid = WMI_TLV_ADDBA_SEND_CMDID, 2437 .addba_status_cmdid = WMI_TLV_ADDBA_STATUS_CMDID, 2438 .delba_send_cmdid = WMI_TLV_DELBA_SEND_CMDID, 2439 .addba_set_resp_cmdid = WMI_TLV_ADDBA_SET_RESP_CMDID, 2440 .send_singleamsdu_cmdid = WMI_TLV_SEND_SINGLEAMSDU_CMDID, 2441 .sta_powersave_mode_cmdid = WMI_TLV_STA_POWERSAVE_MODE_CMDID, 2442 .sta_powersave_param_cmdid = WMI_TLV_STA_POWERSAVE_PARAM_CMDID, 2443 .sta_mimo_ps_mode_cmdid = WMI_TLV_STA_MIMO_PS_MODE_CMDID, 2444 .pdev_dfs_enable_cmdid = WMI_TLV_PDEV_DFS_ENABLE_CMDID, 2445 .pdev_dfs_disable_cmdid = WMI_TLV_PDEV_DFS_DISABLE_CMDID, 2446 .roam_scan_mode = WMI_TLV_ROAM_SCAN_MODE, 2447 .roam_scan_rssi_threshold = WMI_TLV_ROAM_SCAN_RSSI_THRESHOLD, 2448 .roam_scan_period = WMI_TLV_ROAM_SCAN_PERIOD, 2449 .roam_scan_rssi_change_threshold = 2450 WMI_TLV_ROAM_SCAN_RSSI_CHANGE_THRESHOLD, 2451 .roam_ap_profile = WMI_TLV_ROAM_AP_PROFILE, 2452 .ofl_scan_add_ap_profile = WMI_TLV_ROAM_AP_PROFILE, 2453 .ofl_scan_remove_ap_profile = WMI_TLV_OFL_SCAN_REMOVE_AP_PROFILE, 2454 .ofl_scan_period = WMI_TLV_OFL_SCAN_PERIOD, 2455 .p2p_dev_set_device_info = WMI_TLV_P2P_DEV_SET_DEVICE_INFO, 2456 .p2p_dev_set_discoverability = WMI_TLV_P2P_DEV_SET_DISCOVERABILITY, 2457 .p2p_go_set_beacon_ie = WMI_TLV_P2P_GO_SET_BEACON_IE, 2458 .p2p_go_set_probe_resp_ie = WMI_TLV_P2P_GO_SET_PROBE_RESP_IE, 2459 .p2p_set_vendor_ie_data_cmdid = WMI_TLV_P2P_SET_VENDOR_IE_DATA_CMDID, 2460 .ap_ps_peer_param_cmdid = WMI_TLV_AP_PS_PEER_PARAM_CMDID, 2461 .ap_ps_peer_uapsd_coex_cmdid = WMI_TLV_AP_PS_PEER_UAPSD_COEX_CMDID, 2462 .peer_rate_retry_sched_cmdid = WMI_TLV_PEER_RATE_RETRY_SCHED_CMDID, 2463 .wlan_profile_trigger_cmdid = WMI_TLV_WLAN_PROFILE_TRIGGER_CMDID, 2464 .wlan_profile_set_hist_intvl_cmdid = 2465 WMI_TLV_WLAN_PROFILE_SET_HIST_INTVL_CMDID, 2466 .wlan_profile_get_profile_data_cmdid = 2467 WMI_TLV_WLAN_PROFILE_GET_PROFILE_DATA_CMDID, 2468 .wlan_profile_enable_profile_id_cmdid = 2469 WMI_TLV_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID, 2470 .wlan_profile_list_profile_id_cmdid = 2471 WMI_TLV_WLAN_PROFILE_LIST_PROFILE_ID_CMDID, 2472 .pdev_suspend_cmdid = WMI_TLV_PDEV_SUSPEND_CMDID, 2473 .pdev_resume_cmdid = WMI_TLV_PDEV_RESUME_CMDID, 2474 .add_bcn_filter_cmdid = WMI_TLV_ADD_BCN_FILTER_CMDID, 2475 .rmv_bcn_filter_cmdid = WMI_TLV_RMV_BCN_FILTER_CMDID, 2476 .wow_add_wake_pattern_cmdid = WMI_TLV_WOW_ADD_WAKE_PATTERN_CMDID, 2477 .wow_del_wake_pattern_cmdid = WMI_TLV_WOW_DEL_WAKE_PATTERN_CMDID, 2478 .wow_enable_disable_wake_event_cmdid = 2479 WMI_TLV_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID, 2480 .wow_enable_cmdid = WMI_TLV_WOW_ENABLE_CMDID, 2481 .wow_hostwakeup_from_sleep_cmdid = 2482 WMI_TLV_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID, 2483 .rtt_measreq_cmdid = WMI_TLV_RTT_MEASREQ_CMDID, 2484 .rtt_tsf_cmdid = WMI_TLV_RTT_TSF_CMDID, 2485 .vdev_spectral_scan_configure_cmdid = WMI_TLV_SPECTRAL_SCAN_CONF_CMDID, 2486 .vdev_spectral_scan_enable_cmdid = WMI_TLV_SPECTRAL_SCAN_ENABLE_CMDID, 2487 .request_stats_cmdid = WMI_TLV_REQUEST_STATS_CMDID, 2488 .set_arp_ns_offload_cmdid = WMI_TLV_SET_ARP_NS_OFFLOAD_CMDID, 2489 .network_list_offload_config_cmdid = 2490 WMI_TLV_NETWORK_LIST_OFFLOAD_CONFIG_CMDID, 2491 .gtk_offload_cmdid = WMI_TLV_GTK_OFFLOAD_CMDID, 2492 .csa_offload_enable_cmdid = WMI_TLV_CSA_OFFLOAD_ENABLE_CMDID, 2493 .csa_offload_chanswitch_cmdid = WMI_TLV_CSA_OFFLOAD_CHANSWITCH_CMDID, 2494 .chatter_set_mode_cmdid = WMI_TLV_CHATTER_SET_MODE_CMDID, 2495 .peer_tid_addba_cmdid = WMI_TLV_PEER_TID_ADDBA_CMDID, 2496 .peer_tid_delba_cmdid = WMI_TLV_PEER_TID_DELBA_CMDID, 2497 .sta_dtim_ps_method_cmdid = WMI_TLV_STA_DTIM_PS_METHOD_CMDID, 2498 .sta_uapsd_auto_trig_cmdid = WMI_TLV_STA_UAPSD_AUTO_TRIG_CMDID, 2499 .sta_keepalive_cmd = WMI_TLV_STA_KEEPALIVE_CMDID, 2500 .echo_cmdid = WMI_TLV_ECHO_CMDID, 2501 .pdev_utf_cmdid = WMI_TLV_PDEV_UTF_CMDID, 2502 .dbglog_cfg_cmdid = WMI_TLV_DBGLOG_CFG_CMDID, 2503 .pdev_qvit_cmdid = WMI_TLV_PDEV_QVIT_CMDID, 2504 .pdev_ftm_intg_cmdid = WMI_TLV_PDEV_FTM_INTG_CMDID, 2505 .vdev_set_keepalive_cmdid = WMI_TLV_VDEV_SET_KEEPALIVE_CMDID, 2506 .vdev_get_keepalive_cmdid = WMI_TLV_VDEV_GET_KEEPALIVE_CMDID, 2507 .force_fw_hang_cmdid = WMI_TLV_FORCE_FW_HANG_CMDID, 2508 .gpio_config_cmdid = WMI_TLV_GPIO_CONFIG_CMDID, 2509 .gpio_output_cmdid = WMI_TLV_GPIO_OUTPUT_CMDID, 2510 .pdev_get_temperature_cmdid = WMI_TLV_CMD_UNSUPPORTED, 2511 .vdev_set_wmm_params_cmdid = WMI_TLV_VDEV_SET_WMM_PARAMS_CMDID, 2512 }; 2513 2514 static struct wmi_pdev_param_map wmi_tlv_pdev_param_map = { 2515 .tx_chain_mask = WMI_TLV_PDEV_PARAM_TX_CHAIN_MASK, 2516 .rx_chain_mask = WMI_TLV_PDEV_PARAM_RX_CHAIN_MASK, 2517 .txpower_limit2g = WMI_TLV_PDEV_PARAM_TXPOWER_LIMIT2G, 2518 .txpower_limit5g = WMI_TLV_PDEV_PARAM_TXPOWER_LIMIT5G, 2519 .txpower_scale = WMI_TLV_PDEV_PARAM_TXPOWER_SCALE, 2520 .beacon_gen_mode = WMI_TLV_PDEV_PARAM_BEACON_GEN_MODE, 2521 .beacon_tx_mode = WMI_TLV_PDEV_PARAM_BEACON_TX_MODE, 2522 .resmgr_offchan_mode = WMI_TLV_PDEV_PARAM_RESMGR_OFFCHAN_MODE, 2523 .protection_mode = WMI_TLV_PDEV_PARAM_PROTECTION_MODE, 2524 .dynamic_bw = WMI_TLV_PDEV_PARAM_DYNAMIC_BW, 2525 .non_agg_sw_retry_th = WMI_TLV_PDEV_PARAM_NON_AGG_SW_RETRY_TH, 2526 .agg_sw_retry_th = WMI_TLV_PDEV_PARAM_AGG_SW_RETRY_TH, 2527 .sta_kickout_th = WMI_TLV_PDEV_PARAM_STA_KICKOUT_TH, 2528 .ac_aggrsize_scaling = WMI_TLV_PDEV_PARAM_AC_AGGRSIZE_SCALING, 2529 .ltr_enable = WMI_TLV_PDEV_PARAM_LTR_ENABLE, 2530 .ltr_ac_latency_be = WMI_TLV_PDEV_PARAM_LTR_AC_LATENCY_BE, 2531 .ltr_ac_latency_bk = WMI_TLV_PDEV_PARAM_LTR_AC_LATENCY_BK, 2532 .ltr_ac_latency_vi = WMI_TLV_PDEV_PARAM_LTR_AC_LATENCY_VI, 2533 .ltr_ac_latency_vo = WMI_TLV_PDEV_PARAM_LTR_AC_LATENCY_VO, 2534 .ltr_ac_latency_timeout = WMI_TLV_PDEV_PARAM_LTR_AC_LATENCY_TIMEOUT, 2535 .ltr_sleep_override = WMI_TLV_PDEV_PARAM_LTR_SLEEP_OVERRIDE, 2536 .ltr_rx_override = WMI_TLV_PDEV_PARAM_LTR_RX_OVERRIDE, 2537 .ltr_tx_activity_timeout = WMI_TLV_PDEV_PARAM_LTR_TX_ACTIVITY_TIMEOUT, 2538 .l1ss_enable = WMI_TLV_PDEV_PARAM_L1SS_ENABLE, 2539 .dsleep_enable = WMI_TLV_PDEV_PARAM_DSLEEP_ENABLE, 2540 .pcielp_txbuf_flush = WMI_TLV_PDEV_PARAM_PCIELP_TXBUF_FLUSH, 2541 .pcielp_txbuf_watermark = WMI_TLV_PDEV_PARAM_PCIELP_TXBUF_TMO_EN, 2542 .pcielp_txbuf_tmo_en = WMI_TLV_PDEV_PARAM_PCIELP_TXBUF_TMO_EN, 2543 .pcielp_txbuf_tmo_value = WMI_TLV_PDEV_PARAM_PCIELP_TXBUF_TMO_VALUE, 2544 .pdev_stats_update_period = WMI_TLV_PDEV_PARAM_PDEV_STATS_UPDATE_PERIOD, 2545 .vdev_stats_update_period = WMI_TLV_PDEV_PARAM_VDEV_STATS_UPDATE_PERIOD, 2546 .peer_stats_update_period = WMI_TLV_PDEV_PARAM_PEER_STATS_UPDATE_PERIOD, 2547 .bcnflt_stats_update_period = 2548 WMI_TLV_PDEV_PARAM_BCNFLT_STATS_UPDATE_PERIOD, 2549 .pmf_qos = WMI_TLV_PDEV_PARAM_PMF_QOS, 2550 .arp_ac_override = WMI_TLV_PDEV_PARAM_ARP_AC_OVERRIDE, 2551 .dcs = WMI_TLV_PDEV_PARAM_DCS, 2552 .ani_enable = WMI_TLV_PDEV_PARAM_ANI_ENABLE, 2553 .ani_poll_period = WMI_TLV_PDEV_PARAM_ANI_POLL_PERIOD, 2554 .ani_listen_period = WMI_TLV_PDEV_PARAM_ANI_LISTEN_PERIOD, 2555 .ani_ofdm_level = WMI_TLV_PDEV_PARAM_ANI_OFDM_LEVEL, 2556 .ani_cck_level = WMI_TLV_PDEV_PARAM_ANI_CCK_LEVEL, 2557 .dyntxchain = WMI_TLV_PDEV_PARAM_DYNTXCHAIN, 2558 .proxy_sta = WMI_TLV_PDEV_PARAM_PROXY_STA, 2559 .idle_ps_config = WMI_TLV_PDEV_PARAM_IDLE_PS_CONFIG, 2560 .power_gating_sleep = WMI_TLV_PDEV_PARAM_POWER_GATING_SLEEP, 2561 .fast_channel_reset = WMI_TLV_PDEV_PARAM_UNSUPPORTED, 2562 .burst_dur = WMI_TLV_PDEV_PARAM_BURST_DUR, 2563 .burst_enable = WMI_TLV_PDEV_PARAM_BURST_ENABLE, 2564 .cal_period = WMI_PDEV_PARAM_UNSUPPORTED, 2565 }; 2566 2567 static struct wmi_vdev_param_map wmi_tlv_vdev_param_map = { 2568 .rts_threshold = WMI_TLV_VDEV_PARAM_RTS_THRESHOLD, 2569 .fragmentation_threshold = WMI_TLV_VDEV_PARAM_FRAGMENTATION_THRESHOLD, 2570 .beacon_interval = WMI_TLV_VDEV_PARAM_BEACON_INTERVAL, 2571 .listen_interval = WMI_TLV_VDEV_PARAM_LISTEN_INTERVAL, 2572 .multicast_rate = WMI_TLV_VDEV_PARAM_MULTICAST_RATE, 2573 .mgmt_tx_rate = WMI_TLV_VDEV_PARAM_MGMT_TX_RATE, 2574 .slot_time = WMI_TLV_VDEV_PARAM_SLOT_TIME, 2575 .preamble = WMI_TLV_VDEV_PARAM_PREAMBLE, 2576 .swba_time = WMI_TLV_VDEV_PARAM_SWBA_TIME, 2577 .wmi_vdev_stats_update_period = WMI_TLV_VDEV_STATS_UPDATE_PERIOD, 2578 .wmi_vdev_pwrsave_ageout_time = WMI_TLV_VDEV_PWRSAVE_AGEOUT_TIME, 2579 .wmi_vdev_host_swba_interval = WMI_TLV_VDEV_HOST_SWBA_INTERVAL, 2580 .dtim_period = WMI_TLV_VDEV_PARAM_DTIM_PERIOD, 2581 .wmi_vdev_oc_scheduler_air_time_limit = 2582 WMI_TLV_VDEV_OC_SCHEDULER_AIR_TIME_LIMIT, 2583 .wds = WMI_TLV_VDEV_PARAM_WDS, 2584 .atim_window = WMI_TLV_VDEV_PARAM_ATIM_WINDOW, 2585 .bmiss_count_max = WMI_TLV_VDEV_PARAM_BMISS_COUNT_MAX, 2586 .bmiss_first_bcnt = WMI_TLV_VDEV_PARAM_BMISS_FIRST_BCNT, 2587 .bmiss_final_bcnt = WMI_TLV_VDEV_PARAM_BMISS_FINAL_BCNT, 2588 .feature_wmm = WMI_TLV_VDEV_PARAM_FEATURE_WMM, 2589 .chwidth = WMI_TLV_VDEV_PARAM_CHWIDTH, 2590 .chextoffset = WMI_TLV_VDEV_PARAM_CHEXTOFFSET, 2591 .disable_htprotection = WMI_TLV_VDEV_PARAM_DISABLE_HTPROTECTION, 2592 .sta_quickkickout = WMI_TLV_VDEV_PARAM_STA_QUICKKICKOUT, 2593 .mgmt_rate = WMI_TLV_VDEV_PARAM_MGMT_RATE, 2594 .protection_mode = WMI_TLV_VDEV_PARAM_PROTECTION_MODE, 2595 .fixed_rate = WMI_TLV_VDEV_PARAM_FIXED_RATE, 2596 .sgi = WMI_TLV_VDEV_PARAM_SGI, 2597 .ldpc = WMI_TLV_VDEV_PARAM_LDPC, 2598 .tx_stbc = WMI_TLV_VDEV_PARAM_TX_STBC, 2599 .rx_stbc = WMI_TLV_VDEV_PARAM_RX_STBC, 2600 .intra_bss_fwd = WMI_TLV_VDEV_PARAM_INTRA_BSS_FWD, 2601 .def_keyid = WMI_TLV_VDEV_PARAM_DEF_KEYID, 2602 .nss = WMI_TLV_VDEV_PARAM_NSS, 2603 .bcast_data_rate = WMI_TLV_VDEV_PARAM_BCAST_DATA_RATE, 2604 .mcast_data_rate = WMI_TLV_VDEV_PARAM_MCAST_DATA_RATE, 2605 .mcast_indicate = WMI_TLV_VDEV_PARAM_MCAST_INDICATE, 2606 .dhcp_indicate = WMI_TLV_VDEV_PARAM_DHCP_INDICATE, 2607 .unknown_dest_indicate = WMI_TLV_VDEV_PARAM_UNKNOWN_DEST_INDICATE, 2608 .ap_keepalive_min_idle_inactive_time_secs = 2609 WMI_TLV_VDEV_PARAM_AP_KEEPALIVE_MIN_IDLE_INACTIVE_TIME_SECS, 2610 .ap_keepalive_max_idle_inactive_time_secs = 2611 WMI_TLV_VDEV_PARAM_AP_KEEPALIVE_MAX_IDLE_INACTIVE_TIME_SECS, 2612 .ap_keepalive_max_unresponsive_time_secs = 2613 WMI_TLV_VDEV_PARAM_AP_KEEPALIVE_MAX_UNRESPONSIVE_TIME_SECS, 2614 .ap_enable_nawds = WMI_TLV_VDEV_PARAM_AP_ENABLE_NAWDS, 2615 .mcast2ucast_set = WMI_TLV_VDEV_PARAM_UNSUPPORTED, 2616 .enable_rtscts = WMI_TLV_VDEV_PARAM_ENABLE_RTSCTS, 2617 .txbf = WMI_TLV_VDEV_PARAM_TXBF, 2618 .packet_powersave = WMI_TLV_VDEV_PARAM_PACKET_POWERSAVE, 2619 .drop_unencry = WMI_TLV_VDEV_PARAM_DROP_UNENCRY, 2620 .tx_encap_type = WMI_TLV_VDEV_PARAM_TX_ENCAP_TYPE, 2621 .ap_detect_out_of_sync_sleeping_sta_time_secs = 2622 WMI_TLV_VDEV_PARAM_UNSUPPORTED, 2623 }; 2624 2625 static const struct wmi_ops wmi_tlv_ops = { 2626 .rx = ath10k_wmi_tlv_op_rx, 2627 .map_svc = wmi_tlv_svc_map, 2628 2629 .pull_scan = ath10k_wmi_tlv_op_pull_scan_ev, 2630 .pull_mgmt_rx = ath10k_wmi_tlv_op_pull_mgmt_rx_ev, 2631 .pull_ch_info = ath10k_wmi_tlv_op_pull_ch_info_ev, 2632 .pull_vdev_start = ath10k_wmi_tlv_op_pull_vdev_start_ev, 2633 .pull_peer_kick = ath10k_wmi_tlv_op_pull_peer_kick_ev, 2634 .pull_swba = ath10k_wmi_tlv_op_pull_swba_ev, 2635 .pull_phyerr = ath10k_wmi_tlv_op_pull_phyerr_ev, 2636 .pull_svc_rdy = ath10k_wmi_tlv_op_pull_svc_rdy_ev, 2637 .pull_rdy = ath10k_wmi_tlv_op_pull_rdy_ev, 2638 .pull_fw_stats = ath10k_wmi_tlv_op_pull_fw_stats, 2639 2640 .gen_pdev_suspend = ath10k_wmi_tlv_op_gen_pdev_suspend, 2641 .gen_pdev_resume = ath10k_wmi_tlv_op_gen_pdev_resume, 2642 .gen_pdev_set_rd = ath10k_wmi_tlv_op_gen_pdev_set_rd, 2643 .gen_pdev_set_param = ath10k_wmi_tlv_op_gen_pdev_set_param, 2644 .gen_init = ath10k_wmi_tlv_op_gen_init, 2645 .gen_start_scan = ath10k_wmi_tlv_op_gen_start_scan, 2646 .gen_stop_scan = ath10k_wmi_tlv_op_gen_stop_scan, 2647 .gen_vdev_create = ath10k_wmi_tlv_op_gen_vdev_create, 2648 .gen_vdev_delete = ath10k_wmi_tlv_op_gen_vdev_delete, 2649 .gen_vdev_start = ath10k_wmi_tlv_op_gen_vdev_start, 2650 .gen_vdev_stop = ath10k_wmi_tlv_op_gen_vdev_stop, 2651 .gen_vdev_up = ath10k_wmi_tlv_op_gen_vdev_up, 2652 .gen_vdev_down = ath10k_wmi_tlv_op_gen_vdev_down, 2653 .gen_vdev_set_param = ath10k_wmi_tlv_op_gen_vdev_set_param, 2654 .gen_vdev_install_key = ath10k_wmi_tlv_op_gen_vdev_install_key, 2655 .gen_vdev_wmm_conf = ath10k_wmi_tlv_op_gen_vdev_wmm_conf, 2656 .gen_peer_create = ath10k_wmi_tlv_op_gen_peer_create, 2657 .gen_peer_delete = ath10k_wmi_tlv_op_gen_peer_delete, 2658 .gen_peer_flush = ath10k_wmi_tlv_op_gen_peer_flush, 2659 .gen_peer_set_param = ath10k_wmi_tlv_op_gen_peer_set_param, 2660 .gen_peer_assoc = ath10k_wmi_tlv_op_gen_peer_assoc, 2661 .gen_set_psmode = ath10k_wmi_tlv_op_gen_set_psmode, 2662 .gen_set_sta_ps = ath10k_wmi_tlv_op_gen_set_sta_ps, 2663 .gen_set_ap_ps = ath10k_wmi_tlv_op_gen_set_ap_ps, 2664 .gen_scan_chan_list = ath10k_wmi_tlv_op_gen_scan_chan_list, 2665 .gen_beacon_dma = ath10k_wmi_tlv_op_gen_beacon_dma, 2666 .gen_pdev_set_wmm = ath10k_wmi_tlv_op_gen_pdev_set_wmm, 2667 .gen_request_stats = ath10k_wmi_tlv_op_gen_request_stats, 2668 .gen_force_fw_hang = ath10k_wmi_tlv_op_gen_force_fw_hang, 2669 /* .gen_mgmt_tx = not implemented; HTT is used */ 2670 .gen_dbglog_cfg = ath10k_wmi_tlv_op_gen_dbglog_cfg, 2671 .gen_pktlog_enable = ath10k_wmi_tlv_op_gen_pktlog_enable, 2672 .gen_pktlog_disable = ath10k_wmi_tlv_op_gen_pktlog_disable, 2673 /* .gen_pdev_set_quiet_mode not implemented */ 2674 /* .gen_pdev_get_temperature not implemented */ 2675 /* .gen_addba_clear_resp not implemented */ 2676 /* .gen_addba_send not implemented */ 2677 /* .gen_addba_set_resp not implemented */ 2678 /* .gen_delba_send not implemented */ 2679 .gen_bcn_tmpl = ath10k_wmi_tlv_op_gen_bcn_tmpl, 2680 .gen_prb_tmpl = ath10k_wmi_tlv_op_gen_prb_tmpl, 2681 .gen_p2p_go_bcn_ie = ath10k_wmi_tlv_op_gen_p2p_go_bcn_ie, 2682 .gen_vdev_sta_uapsd = ath10k_wmi_tlv_op_gen_vdev_sta_uapsd, 2683 .gen_sta_keepalive = ath10k_wmi_tlv_op_gen_sta_keepalive, 2684 }; 2685 2686 /************/ 2687 /* TLV init */ 2688 /************/ 2689 2690 void ath10k_wmi_tlv_attach(struct ath10k *ar) 2691 { 2692 ar->wmi.cmd = &wmi_tlv_cmd_map; 2693 ar->wmi.vdev_param = &wmi_tlv_vdev_param_map; 2694 ar->wmi.pdev_param = &wmi_tlv_pdev_param_map; 2695 ar->wmi.ops = &wmi_tlv_ops; 2696 } 2697