.. | .. |
---|
| 1 | +// SPDX-License-Identifier: ISC |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (c) 2005-2011 Atheros Communications Inc. |
---|
3 | 4 | * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. |
---|
4 | | - * Copyright (c) 2018, The Linux Foundation. All rights reserved. |
---|
5 | | - * |
---|
6 | | - * Permission to use, copy, modify, and/or distribute this software for any |
---|
7 | | - * purpose with or without fee is hereby granted, provided that the above |
---|
8 | | - * copyright notice and this permission notice appear in all copies. |
---|
9 | | - * |
---|
10 | | - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
---|
11 | | - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
---|
12 | | - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
---|
13 | | - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
---|
14 | | - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
---|
15 | | - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
---|
16 | | - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
---|
| 5 | + * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. |
---|
17 | 6 | */ |
---|
18 | 7 | #include "core.h" |
---|
19 | 8 | #include "debug.h" |
---|
20 | 9 | #include "mac.h" |
---|
21 | 10 | #include "hw.h" |
---|
22 | | -#include "mac.h" |
---|
23 | 11 | #include "wmi.h" |
---|
24 | 12 | #include "wmi-ops.h" |
---|
25 | 13 | #include "wmi-tlv.h" |
---|
26 | 14 | #include "p2p.h" |
---|
27 | 15 | #include "testmode.h" |
---|
| 16 | +#include <linux/bitfield.h> |
---|
28 | 17 | |
---|
29 | 18 | /***************/ |
---|
30 | 19 | /* TLV helpers */ |
---|
.. | .. |
---|
223 | 212 | return 0; |
---|
224 | 213 | } |
---|
225 | 214 | |
---|
| 215 | +static void ath10k_wmi_tlv_event_vdev_delete_resp(struct ath10k *ar, |
---|
| 216 | + struct sk_buff *skb) |
---|
| 217 | +{ |
---|
| 218 | + ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_VDEV_DELETE_RESP_EVENTID\n"); |
---|
| 219 | + complete(&ar->vdev_delete_done); |
---|
| 220 | +} |
---|
| 221 | + |
---|
| 222 | +static int ath10k_wmi_tlv_parse_peer_stats_info(struct ath10k *ar, u16 tag, u16 len, |
---|
| 223 | + const void *ptr, void *data) |
---|
| 224 | +{ |
---|
| 225 | + const struct wmi_tlv_peer_stats_info *stat = ptr; |
---|
| 226 | + struct ieee80211_sta *sta; |
---|
| 227 | + struct ath10k_sta *arsta; |
---|
| 228 | + |
---|
| 229 | + if (tag != WMI_TLV_TAG_STRUCT_PEER_STATS_INFO) |
---|
| 230 | + return -EPROTO; |
---|
| 231 | + |
---|
| 232 | + ath10k_dbg(ar, ATH10K_DBG_WMI, |
---|
| 233 | + "wmi tlv stats peer addr %pMF rx rate code 0x%x bit rate %d kbps\n", |
---|
| 234 | + stat->peer_macaddr.addr, |
---|
| 235 | + __le32_to_cpu(stat->last_rx_rate_code), |
---|
| 236 | + __le32_to_cpu(stat->last_rx_bitrate_kbps)); |
---|
| 237 | + |
---|
| 238 | + ath10k_dbg(ar, ATH10K_DBG_WMI, |
---|
| 239 | + "wmi tlv stats tx rate code 0x%x bit rate %d kbps\n", |
---|
| 240 | + __le32_to_cpu(stat->last_tx_rate_code), |
---|
| 241 | + __le32_to_cpu(stat->last_tx_bitrate_kbps)); |
---|
| 242 | + |
---|
| 243 | + rcu_read_lock(); |
---|
| 244 | + sta = ieee80211_find_sta_by_ifaddr(ar->hw, stat->peer_macaddr.addr, NULL); |
---|
| 245 | + if (!sta) { |
---|
| 246 | + rcu_read_unlock(); |
---|
| 247 | + ath10k_warn(ar, "not found station for peer stats\n"); |
---|
| 248 | + return -EINVAL; |
---|
| 249 | + } |
---|
| 250 | + |
---|
| 251 | + arsta = (struct ath10k_sta *)sta->drv_priv; |
---|
| 252 | + arsta->rx_rate_code = __le32_to_cpu(stat->last_rx_rate_code); |
---|
| 253 | + arsta->rx_bitrate_kbps = __le32_to_cpu(stat->last_rx_bitrate_kbps); |
---|
| 254 | + arsta->tx_rate_code = __le32_to_cpu(stat->last_tx_rate_code); |
---|
| 255 | + arsta->tx_bitrate_kbps = __le32_to_cpu(stat->last_tx_bitrate_kbps); |
---|
| 256 | + rcu_read_unlock(); |
---|
| 257 | + |
---|
| 258 | + return 0; |
---|
| 259 | +} |
---|
| 260 | + |
---|
| 261 | +static int ath10k_wmi_tlv_op_pull_peer_stats_info(struct ath10k *ar, |
---|
| 262 | + struct sk_buff *skb) |
---|
| 263 | +{ |
---|
| 264 | + const void **tb; |
---|
| 265 | + const struct wmi_tlv_peer_stats_info_ev *ev; |
---|
| 266 | + const void *data; |
---|
| 267 | + u32 num_peer_stats; |
---|
| 268 | + int ret; |
---|
| 269 | + |
---|
| 270 | + tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC); |
---|
| 271 | + if (IS_ERR(tb)) { |
---|
| 272 | + ret = PTR_ERR(tb); |
---|
| 273 | + ath10k_warn(ar, "failed to parse tlv: %d\n", ret); |
---|
| 274 | + return ret; |
---|
| 275 | + } |
---|
| 276 | + |
---|
| 277 | + ev = tb[WMI_TLV_TAG_STRUCT_PEER_STATS_INFO_EVENT]; |
---|
| 278 | + data = tb[WMI_TLV_TAG_ARRAY_STRUCT]; |
---|
| 279 | + |
---|
| 280 | + if (!ev || !data) { |
---|
| 281 | + kfree(tb); |
---|
| 282 | + return -EPROTO; |
---|
| 283 | + } |
---|
| 284 | + |
---|
| 285 | + num_peer_stats = __le32_to_cpu(ev->num_peers); |
---|
| 286 | + |
---|
| 287 | + ath10k_dbg(ar, ATH10K_DBG_WMI, |
---|
| 288 | + "wmi tlv peer stats info update peer vdev id %d peers %i more data %d\n", |
---|
| 289 | + __le32_to_cpu(ev->vdev_id), |
---|
| 290 | + num_peer_stats, |
---|
| 291 | + __le32_to_cpu(ev->more_data)); |
---|
| 292 | + |
---|
| 293 | + ret = ath10k_wmi_tlv_iter(ar, data, ath10k_wmi_tlv_len(data), |
---|
| 294 | + ath10k_wmi_tlv_parse_peer_stats_info, NULL); |
---|
| 295 | + if (ret) |
---|
| 296 | + ath10k_warn(ar, "failed to parse stats info tlv: %d\n", ret); |
---|
| 297 | + |
---|
| 298 | + kfree(tb); |
---|
| 299 | + return 0; |
---|
| 300 | +} |
---|
| 301 | + |
---|
| 302 | +static void ath10k_wmi_tlv_event_peer_stats_info(struct ath10k *ar, |
---|
| 303 | + struct sk_buff *skb) |
---|
| 304 | +{ |
---|
| 305 | + ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_PEER_STATS_INFO_EVENTID\n"); |
---|
| 306 | + ath10k_wmi_tlv_op_pull_peer_stats_info(ar, skb); |
---|
| 307 | + complete(&ar->peer_stats_info_complete); |
---|
| 308 | +} |
---|
| 309 | + |
---|
226 | 310 | static int ath10k_wmi_tlv_event_diag_data(struct ath10k *ar, |
---|
227 | 311 | struct sk_buff *skb) |
---|
228 | 312 | { |
---|
.. | .. |
---|
413 | 497 | return 0; |
---|
414 | 498 | } |
---|
415 | 499 | |
---|
| 500 | +static void ath10k_wmi_tlv_event_rfkill_state_change(struct ath10k *ar, |
---|
| 501 | + struct sk_buff *skb) |
---|
| 502 | +{ |
---|
| 503 | + const struct wmi_tlv_rfkill_state_change_ev *ev; |
---|
| 504 | + const void **tb; |
---|
| 505 | + bool radio; |
---|
| 506 | + int ret; |
---|
| 507 | + |
---|
| 508 | + tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC); |
---|
| 509 | + if (IS_ERR(tb)) { |
---|
| 510 | + ret = PTR_ERR(tb); |
---|
| 511 | + ath10k_warn(ar, |
---|
| 512 | + "failed to parse rfkill state change event: %d\n", |
---|
| 513 | + ret); |
---|
| 514 | + return; |
---|
| 515 | + } |
---|
| 516 | + |
---|
| 517 | + ev = tb[WMI_TLV_TAG_STRUCT_RFKILL_EVENT]; |
---|
| 518 | + if (!ev) { |
---|
| 519 | + kfree(tb); |
---|
| 520 | + return; |
---|
| 521 | + } |
---|
| 522 | + |
---|
| 523 | + ath10k_dbg(ar, ATH10K_DBG_MAC, |
---|
| 524 | + "wmi tlv rfkill state change gpio %d type %d radio_state %d\n", |
---|
| 525 | + __le32_to_cpu(ev->gpio_pin_num), |
---|
| 526 | + __le32_to_cpu(ev->int_type), |
---|
| 527 | + __le32_to_cpu(ev->radio_state)); |
---|
| 528 | + |
---|
| 529 | + radio = (__le32_to_cpu(ev->radio_state) == WMI_TLV_RFKILL_RADIO_STATE_ON); |
---|
| 530 | + |
---|
| 531 | + spin_lock_bh(&ar->data_lock); |
---|
| 532 | + |
---|
| 533 | + if (!radio) |
---|
| 534 | + ar->hw_rfkill_on = true; |
---|
| 535 | + |
---|
| 536 | + spin_unlock_bh(&ar->data_lock); |
---|
| 537 | + |
---|
| 538 | + /* notify cfg80211 radio state change */ |
---|
| 539 | + ath10k_mac_rfkill_enable_radio(ar, radio); |
---|
| 540 | + wiphy_rfkill_set_hw_state(ar->hw->wiphy, !radio); |
---|
| 541 | +} |
---|
| 542 | + |
---|
416 | 543 | static int ath10k_wmi_tlv_event_temperature(struct ath10k *ar, |
---|
417 | 544 | struct sk_buff *skb) |
---|
418 | 545 | { |
---|
.. | .. |
---|
475 | 602 | kfree(tb); |
---|
476 | 603 | } |
---|
477 | 604 | |
---|
| 605 | +static int ath10k_wmi_tlv_event_peer_delete_resp(struct ath10k *ar, |
---|
| 606 | + struct sk_buff *skb) |
---|
| 607 | +{ |
---|
| 608 | + struct wmi_peer_delete_resp_ev_arg *arg; |
---|
| 609 | + struct wmi_tlv *tlv_hdr; |
---|
| 610 | + |
---|
| 611 | + tlv_hdr = (struct wmi_tlv *)skb->data; |
---|
| 612 | + arg = (struct wmi_peer_delete_resp_ev_arg *)tlv_hdr->value; |
---|
| 613 | + |
---|
| 614 | + ath10k_dbg(ar, ATH10K_DBG_WMI, "vdev id %d", arg->vdev_id); |
---|
| 615 | + ath10k_dbg(ar, ATH10K_DBG_WMI, "peer mac addr %pM", &arg->peer_addr); |
---|
| 616 | + ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv peer delete response\n"); |
---|
| 617 | + |
---|
| 618 | + complete(&ar->peer_delete_done); |
---|
| 619 | + |
---|
| 620 | + return 0; |
---|
| 621 | +} |
---|
| 622 | + |
---|
478 | 623 | /***********/ |
---|
479 | 624 | /* TLV ops */ |
---|
480 | 625 | /***********/ |
---|
.. | .. |
---|
525 | 670 | case WMI_TLV_UPDATE_STATS_EVENTID: |
---|
526 | 671 | ath10k_wmi_event_update_stats(ar, skb); |
---|
527 | 672 | break; |
---|
| 673 | + case WMI_TLV_PEER_STATS_INFO_EVENTID: |
---|
| 674 | + ath10k_wmi_tlv_event_peer_stats_info(ar, skb); |
---|
| 675 | + break; |
---|
528 | 676 | case WMI_TLV_VDEV_START_RESP_EVENTID: |
---|
529 | 677 | ath10k_wmi_event_vdev_start_resp(ar, skb); |
---|
530 | 678 | break; |
---|
531 | 679 | case WMI_TLV_VDEV_STOPPED_EVENTID: |
---|
532 | 680 | ath10k_wmi_event_vdev_stopped(ar, skb); |
---|
| 681 | + break; |
---|
| 682 | + case WMI_TLV_VDEV_DELETE_RESP_EVENTID: |
---|
| 683 | + ath10k_wmi_tlv_event_vdev_delete_resp(ar, skb); |
---|
533 | 684 | break; |
---|
534 | 685 | case WMI_TLV_PEER_STA_KICKOUT_EVENTID: |
---|
535 | 686 | ath10k_wmi_event_peer_sta_kickout(ar, skb); |
---|
.. | .. |
---|
618 | 769 | case WMI_TLV_TX_PAUSE_EVENTID: |
---|
619 | 770 | ath10k_wmi_tlv_event_tx_pause(ar, skb); |
---|
620 | 771 | break; |
---|
| 772 | + case WMI_TLV_RFKILL_STATE_CHANGE_EVENTID: |
---|
| 773 | + ath10k_wmi_tlv_event_rfkill_state_change(ar, skb); |
---|
| 774 | + break; |
---|
621 | 775 | case WMI_TLV_PDEV_TEMPERATURE_EVENTID: |
---|
622 | 776 | ath10k_wmi_tlv_event_temperature(ar, skb); |
---|
623 | 777 | break; |
---|
624 | 778 | case WMI_TLV_TDLS_PEER_EVENTID: |
---|
625 | 779 | ath10k_wmi_event_tdls_peer(ar, skb); |
---|
626 | 780 | break; |
---|
| 781 | + case WMI_TLV_PEER_DELETE_RESP_EVENTID: |
---|
| 782 | + ath10k_wmi_tlv_event_peer_delete_resp(ar, skb); |
---|
| 783 | + break; |
---|
627 | 784 | case WMI_TLV_MGMT_TX_COMPLETION_EVENTID: |
---|
628 | 785 | ath10k_wmi_event_mgmt_tx_compl(ar, skb); |
---|
629 | 786 | break; |
---|
| 787 | + case WMI_TLV_MGMT_TX_BUNDLE_COMPLETION_EVENTID: |
---|
| 788 | + ath10k_wmi_event_mgmt_tx_bundle_compl(ar, skb); |
---|
| 789 | + break; |
---|
630 | 790 | default: |
---|
631 | | - ath10k_warn(ar, "Unknown eventid: %d\n", id); |
---|
| 791 | + ath10k_dbg(ar, ATH10K_DBG_WMI, "Unknown eventid: %d\n", id); |
---|
632 | 792 | break; |
---|
633 | 793 | } |
---|
634 | 794 | |
---|
.. | .. |
---|
688 | 848 | arg->desc_id = ev->desc_id; |
---|
689 | 849 | arg->status = ev->status; |
---|
690 | 850 | arg->pdev_id = ev->pdev_id; |
---|
| 851 | + arg->ppdu_id = ev->ppdu_id; |
---|
| 852 | + |
---|
| 853 | + if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map)) |
---|
| 854 | + arg->ack_rssi = ev->ack_rssi; |
---|
691 | 855 | |
---|
692 | 856 | kfree(tb); |
---|
| 857 | + return 0; |
---|
| 858 | +} |
---|
| 859 | + |
---|
| 860 | +struct wmi_tlv_tx_bundle_compl_parse { |
---|
| 861 | + const __le32 *num_reports; |
---|
| 862 | + const __le32 *desc_ids; |
---|
| 863 | + const __le32 *status; |
---|
| 864 | + const __le32 *ppdu_ids; |
---|
| 865 | + const __le32 *ack_rssi; |
---|
| 866 | + bool desc_ids_done; |
---|
| 867 | + bool status_done; |
---|
| 868 | + bool ppdu_ids_done; |
---|
| 869 | + bool ack_rssi_done; |
---|
| 870 | +}; |
---|
| 871 | + |
---|
| 872 | +static int |
---|
| 873 | +ath10k_wmi_tlv_mgmt_tx_bundle_compl_parse(struct ath10k *ar, u16 tag, u16 len, |
---|
| 874 | + const void *ptr, void *data) |
---|
| 875 | +{ |
---|
| 876 | + struct wmi_tlv_tx_bundle_compl_parse *bundle_tx_compl = data; |
---|
| 877 | + |
---|
| 878 | + switch (tag) { |
---|
| 879 | + case WMI_TLV_TAG_STRUCT_MGMT_TX_COMPL_BUNDLE_EVENT: |
---|
| 880 | + bundle_tx_compl->num_reports = ptr; |
---|
| 881 | + break; |
---|
| 882 | + case WMI_TLV_TAG_ARRAY_UINT32: |
---|
| 883 | + if (!bundle_tx_compl->desc_ids_done) { |
---|
| 884 | + bundle_tx_compl->desc_ids_done = true; |
---|
| 885 | + bundle_tx_compl->desc_ids = ptr; |
---|
| 886 | + } else if (!bundle_tx_compl->status_done) { |
---|
| 887 | + bundle_tx_compl->status_done = true; |
---|
| 888 | + bundle_tx_compl->status = ptr; |
---|
| 889 | + } else if (!bundle_tx_compl->ppdu_ids_done) { |
---|
| 890 | + bundle_tx_compl->ppdu_ids_done = true; |
---|
| 891 | + bundle_tx_compl->ppdu_ids = ptr; |
---|
| 892 | + } else if (!bundle_tx_compl->ack_rssi_done) { |
---|
| 893 | + bundle_tx_compl->ack_rssi_done = true; |
---|
| 894 | + bundle_tx_compl->ack_rssi = ptr; |
---|
| 895 | + } |
---|
| 896 | + break; |
---|
| 897 | + default: |
---|
| 898 | + break; |
---|
| 899 | + } |
---|
| 900 | + return 0; |
---|
| 901 | +} |
---|
| 902 | + |
---|
| 903 | +static int ath10k_wmi_tlv_op_pull_mgmt_tx_bundle_compl_ev( |
---|
| 904 | + struct ath10k *ar, struct sk_buff *skb, |
---|
| 905 | + struct wmi_tlv_mgmt_tx_bundle_compl_ev_arg *arg) |
---|
| 906 | +{ |
---|
| 907 | + struct wmi_tlv_tx_bundle_compl_parse bundle_tx_compl = { }; |
---|
| 908 | + int ret; |
---|
| 909 | + |
---|
| 910 | + ret = ath10k_wmi_tlv_iter(ar, skb->data, skb->len, |
---|
| 911 | + ath10k_wmi_tlv_mgmt_tx_bundle_compl_parse, |
---|
| 912 | + &bundle_tx_compl); |
---|
| 913 | + if (ret) { |
---|
| 914 | + ath10k_warn(ar, "failed to parse tlv: %d\n", ret); |
---|
| 915 | + return ret; |
---|
| 916 | + } |
---|
| 917 | + |
---|
| 918 | + if (!bundle_tx_compl.num_reports || !bundle_tx_compl.desc_ids || |
---|
| 919 | + !bundle_tx_compl.status) |
---|
| 920 | + return -EPROTO; |
---|
| 921 | + |
---|
| 922 | + arg->num_reports = *bundle_tx_compl.num_reports; |
---|
| 923 | + arg->desc_ids = bundle_tx_compl.desc_ids; |
---|
| 924 | + arg->status = bundle_tx_compl.status; |
---|
| 925 | + arg->ppdu_ids = bundle_tx_compl.ppdu_ids; |
---|
| 926 | + |
---|
| 927 | + if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map)) |
---|
| 928 | + arg->ack_rssi = bundle_tx_compl.ack_rssi; |
---|
| 929 | + |
---|
693 | 930 | return 0; |
---|
694 | 931 | } |
---|
695 | 932 | |
---|
.. | .. |
---|
701 | 938 | const struct wmi_tlv_mgmt_rx_ev *ev; |
---|
702 | 939 | const u8 *frame; |
---|
703 | 940 | u32 msdu_len; |
---|
704 | | - int ret; |
---|
| 941 | + int ret, i; |
---|
705 | 942 | |
---|
706 | 943 | tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC); |
---|
707 | 944 | if (IS_ERR(tb)) { |
---|
.. | .. |
---|
725 | 962 | arg->phy_mode = ev->phy_mode; |
---|
726 | 963 | arg->rate = ev->rate; |
---|
727 | 964 | |
---|
| 965 | + for (i = 0; i < ARRAY_SIZE(ev->rssi); i++) |
---|
| 966 | + arg->rssi[i] = ev->rssi[i]; |
---|
| 967 | + |
---|
728 | 968 | msdu_len = __le32_to_cpu(arg->buf_len); |
---|
729 | 969 | |
---|
730 | 970 | if (skb->len < (frame - skb->data) + msdu_len) { |
---|
.. | .. |
---|
747 | 987 | struct wmi_ch_info_ev_arg *arg) |
---|
748 | 988 | { |
---|
749 | 989 | const void **tb; |
---|
750 | | - const struct wmi_chan_info_event *ev; |
---|
| 990 | + const struct wmi_tlv_chan_info_event *ev; |
---|
751 | 991 | int ret; |
---|
752 | 992 | |
---|
753 | 993 | tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC); |
---|
.. | .. |
---|
769 | 1009 | arg->noise_floor = ev->noise_floor; |
---|
770 | 1010 | arg->rx_clear_count = ev->rx_clear_count; |
---|
771 | 1011 | arg->cycle_count = ev->cycle_count; |
---|
| 1012 | + if (test_bit(ATH10K_FW_FEATURE_SINGLE_CHAN_INFO_PER_CHANNEL, |
---|
| 1013 | + ar->running_fw->fw_file.fw_features)) |
---|
| 1014 | + arg->mac_clk_mhz = ev->mac_clk_mhz; |
---|
772 | 1015 | |
---|
773 | 1016 | kfree(tb); |
---|
774 | 1017 | return 0; |
---|
.. | .. |
---|
1104 | 1347 | arg->max_tx_power = ev->hw_max_tx_power; |
---|
1105 | 1348 | arg->ht_cap = ev->ht_cap_info; |
---|
1106 | 1349 | arg->vht_cap = ev->vht_cap_info; |
---|
| 1350 | + arg->vht_supp_mcs = ev->vht_supp_mcs; |
---|
1107 | 1351 | arg->sw_ver0 = ev->abi.abi_ver0; |
---|
1108 | 1352 | arg->sw_ver1 = ev->abi.abi_ver1; |
---|
1109 | 1353 | arg->fw_build = ev->fw_build_vers; |
---|
1110 | 1354 | arg->phy_capab = ev->phy_capability; |
---|
1111 | 1355 | arg->num_rf_chains = ev->num_rf_chains; |
---|
1112 | 1356 | arg->eeprom_rd = reg->eeprom_rd; |
---|
| 1357 | + arg->low_2ghz_chan = reg->low_2ghz_chan; |
---|
| 1358 | + arg->high_2ghz_chan = reg->high_2ghz_chan; |
---|
1113 | 1359 | arg->low_5ghz_chan = reg->low_5ghz_chan; |
---|
1114 | 1360 | arg->high_5ghz_chan = reg->high_5ghz_chan; |
---|
1115 | 1361 | arg->num_mem_reqs = ev->num_mem_reqs; |
---|
1116 | 1362 | arg->service_map = svc_bmap; |
---|
1117 | 1363 | arg->service_map_len = ath10k_wmi_tlv_len(svc_bmap); |
---|
| 1364 | + arg->sys_cap_info = ev->sys_cap_info; |
---|
1118 | 1365 | |
---|
1119 | 1366 | ret = ath10k_wmi_tlv_iter(ar, mem_reqs, ath10k_wmi_tlv_len(mem_reqs), |
---|
1120 | 1367 | ath10k_wmi_tlv_parse_mem_reqs, arg); |
---|
.. | .. |
---|
1233 | 1480 | { |
---|
1234 | 1481 | const void **tb; |
---|
1235 | 1482 | const struct wmi_tlv_stats_ev *ev; |
---|
| 1483 | + u32 num_peer_stats_extd; |
---|
1236 | 1484 | const void *data; |
---|
1237 | 1485 | u32 num_pdev_stats; |
---|
1238 | 1486 | u32 num_vdev_stats; |
---|
.. | .. |
---|
1240 | 1488 | u32 num_bcnflt_stats; |
---|
1241 | 1489 | u32 num_chan_stats; |
---|
1242 | 1490 | size_t data_len; |
---|
| 1491 | + u32 stats_id; |
---|
1243 | 1492 | int ret; |
---|
1244 | 1493 | int i; |
---|
1245 | 1494 | |
---|
.. | .. |
---|
1264 | 1513 | num_peer_stats = __le32_to_cpu(ev->num_peer_stats); |
---|
1265 | 1514 | num_bcnflt_stats = __le32_to_cpu(ev->num_bcnflt_stats); |
---|
1266 | 1515 | num_chan_stats = __le32_to_cpu(ev->num_chan_stats); |
---|
| 1516 | + stats_id = __le32_to_cpu(ev->stats_id); |
---|
| 1517 | + num_peer_stats_extd = __le32_to_cpu(ev->num_peer_stats_extd); |
---|
1267 | 1518 | |
---|
1268 | 1519 | ath10k_dbg(ar, ATH10K_DBG_WMI, |
---|
1269 | | - "wmi tlv stats update pdev %i vdev %i peer %i bcnflt %i chan %i\n", |
---|
| 1520 | + "wmi tlv stats update pdev %i vdev %i peer %i bcnflt %i chan %i peer_extd %i\n", |
---|
1270 | 1521 | num_pdev_stats, num_vdev_stats, num_peer_stats, |
---|
1271 | | - num_bcnflt_stats, num_chan_stats); |
---|
| 1522 | + num_bcnflt_stats, num_chan_stats, num_peer_stats_extd); |
---|
1272 | 1523 | |
---|
1273 | 1524 | for (i = 0; i < num_pdev_stats; i++) { |
---|
1274 | 1525 | const struct wmi_pdev_stats *src; |
---|
.. | .. |
---|
1333 | 1584 | |
---|
1334 | 1585 | ath10k_wmi_pull_peer_stats(&src->old, dst); |
---|
1335 | 1586 | dst->peer_rx_rate = __le32_to_cpu(src->peer_rx_rate); |
---|
| 1587 | + |
---|
| 1588 | + if (stats_id & WMI_TLV_STAT_PEER_EXTD) { |
---|
| 1589 | + const struct wmi_tlv_peer_stats_extd *extd; |
---|
| 1590 | + unsigned long rx_duration_high; |
---|
| 1591 | + |
---|
| 1592 | + extd = data + sizeof(*src) * (num_peer_stats - i - 1) |
---|
| 1593 | + + sizeof(*extd) * i; |
---|
| 1594 | + |
---|
| 1595 | + dst->rx_duration = __le32_to_cpu(extd->rx_duration); |
---|
| 1596 | + rx_duration_high = __le32_to_cpu |
---|
| 1597 | + (extd->rx_duration_high); |
---|
| 1598 | + |
---|
| 1599 | + if (test_bit(WMI_TLV_PEER_RX_DURATION_HIGH_VALID_BIT, |
---|
| 1600 | + &rx_duration_high)) { |
---|
| 1601 | + rx_duration_high = |
---|
| 1602 | + FIELD_GET(WMI_TLV_PEER_RX_DURATION_HIGH_MASK, |
---|
| 1603 | + rx_duration_high); |
---|
| 1604 | + dst->rx_duration |= (u64)rx_duration_high << |
---|
| 1605 | + WMI_TLV_PEER_RX_DURATION_SHIFT; |
---|
| 1606 | + } |
---|
| 1607 | + } |
---|
| 1608 | + |
---|
1336 | 1609 | list_add_tail(&dst->list, &stats->peers); |
---|
1337 | 1610 | } |
---|
1338 | 1611 | |
---|
.. | .. |
---|
1520 | 1793 | cmd->param_id = __cpu_to_le32(param_id); |
---|
1521 | 1794 | cmd->param_value = __cpu_to_le32(param_value); |
---|
1522 | 1795 | |
---|
1523 | | - ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pdev set param\n"); |
---|
| 1796 | + ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv pdev set param %d value 0x%x\n", |
---|
| 1797 | + param_id, param_value); |
---|
1524 | 1798 | return skb; |
---|
| 1799 | +} |
---|
| 1800 | + |
---|
| 1801 | +static void |
---|
| 1802 | +ath10k_wmi_tlv_put_host_mem_chunks(struct ath10k *ar, void *host_mem_chunks) |
---|
| 1803 | +{ |
---|
| 1804 | + struct host_memory_chunk_tlv *chunk; |
---|
| 1805 | + struct wmi_tlv *tlv; |
---|
| 1806 | + dma_addr_t paddr; |
---|
| 1807 | + int i; |
---|
| 1808 | + __le16 tlv_len, tlv_tag; |
---|
| 1809 | + |
---|
| 1810 | + tlv_tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_WLAN_HOST_MEMORY_CHUNK); |
---|
| 1811 | + tlv_len = __cpu_to_le16(sizeof(*chunk)); |
---|
| 1812 | + for (i = 0; i < ar->wmi.num_mem_chunks; i++) { |
---|
| 1813 | + tlv = host_mem_chunks; |
---|
| 1814 | + tlv->tag = tlv_tag; |
---|
| 1815 | + tlv->len = tlv_len; |
---|
| 1816 | + chunk = (void *)tlv->value; |
---|
| 1817 | + |
---|
| 1818 | + chunk->ptr = __cpu_to_le32(ar->wmi.mem_chunks[i].paddr); |
---|
| 1819 | + chunk->size = __cpu_to_le32(ar->wmi.mem_chunks[i].len); |
---|
| 1820 | + chunk->req_id = __cpu_to_le32(ar->wmi.mem_chunks[i].req_id); |
---|
| 1821 | + |
---|
| 1822 | + if (test_bit(WMI_SERVICE_SUPPORT_EXTEND_ADDRESS, |
---|
| 1823 | + ar->wmi.svc_map)) { |
---|
| 1824 | + paddr = ar->wmi.mem_chunks[i].paddr; |
---|
| 1825 | + chunk->ptr_high = __cpu_to_le32(upper_32_bits(paddr)); |
---|
| 1826 | + } |
---|
| 1827 | + |
---|
| 1828 | + ath10k_dbg(ar, ATH10K_DBG_WMI, |
---|
| 1829 | + "wmi-tlv chunk %d len %d, addr 0x%llx, id 0x%x\n", |
---|
| 1830 | + i, |
---|
| 1831 | + ar->wmi.mem_chunks[i].len, |
---|
| 1832 | + (unsigned long long)ar->wmi.mem_chunks[i].paddr, |
---|
| 1833 | + ar->wmi.mem_chunks[i].req_id); |
---|
| 1834 | + |
---|
| 1835 | + host_mem_chunks += sizeof(*tlv); |
---|
| 1836 | + host_mem_chunks += sizeof(*chunk); |
---|
| 1837 | + } |
---|
1525 | 1838 | } |
---|
1526 | 1839 | |
---|
1527 | 1840 | static struct sk_buff *ath10k_wmi_tlv_op_gen_init(struct ath10k *ar) |
---|
.. | .. |
---|
1530 | 1843 | struct wmi_tlv *tlv; |
---|
1531 | 1844 | struct wmi_tlv_init_cmd *cmd; |
---|
1532 | 1845 | struct wmi_tlv_resource_config *cfg; |
---|
1533 | | - struct wmi_host_mem_chunks *chunks; |
---|
| 1846 | + void *chunks; |
---|
1534 | 1847 | size_t len, chunks_len; |
---|
1535 | 1848 | void *ptr; |
---|
1536 | 1849 | |
---|
1537 | | - chunks_len = ar->wmi.num_mem_chunks * sizeof(struct host_memory_chunk); |
---|
| 1850 | + chunks_len = ar->wmi.num_mem_chunks * |
---|
| 1851 | + (sizeof(struct host_memory_chunk_tlv) + sizeof(*tlv)); |
---|
1538 | 1852 | len = (sizeof(*tlv) + sizeof(*cmd)) + |
---|
1539 | 1853 | (sizeof(*tlv) + sizeof(*cfg)) + |
---|
1540 | 1854 | (sizeof(*tlv) + chunks_len); |
---|
.. | .. |
---|
1577 | 1891 | |
---|
1578 | 1892 | cfg->num_vdevs = __cpu_to_le32(TARGET_TLV_NUM_VDEVS); |
---|
1579 | 1893 | |
---|
1580 | | - cfg->num_peers = __cpu_to_le32(ar->hw_params.num_peers); |
---|
| 1894 | + if (ar->hw_params.num_peers) |
---|
| 1895 | + cfg->num_peers = __cpu_to_le32(ar->hw_params.num_peers); |
---|
| 1896 | + else |
---|
| 1897 | + cfg->num_peers = __cpu_to_le32(TARGET_TLV_NUM_PEERS); |
---|
1581 | 1898 | cfg->ast_skid_limit = __cpu_to_le32(ar->hw_params.ast_skid_limit); |
---|
1582 | 1899 | cfg->num_wds_entries = __cpu_to_le32(ar->hw_params.num_wds_entries); |
---|
1583 | 1900 | |
---|
.. | .. |
---|
1590 | 1907 | } |
---|
1591 | 1908 | |
---|
1592 | 1909 | cfg->num_peer_keys = __cpu_to_le32(2); |
---|
1593 | | - cfg->num_tids = __cpu_to_le32(TARGET_TLV_NUM_TIDS); |
---|
| 1910 | + if (ar->hw_params.num_peers) |
---|
| 1911 | + cfg->num_tids = __cpu_to_le32(ar->hw_params.num_peers * 2); |
---|
| 1912 | + else |
---|
| 1913 | + cfg->num_tids = __cpu_to_le32(TARGET_TLV_NUM_TIDS); |
---|
1594 | 1914 | cfg->tx_chain_mask = __cpu_to_le32(0x7); |
---|
1595 | 1915 | cfg->rx_chain_mask = __cpu_to_le32(0x7); |
---|
1596 | 1916 | cfg->rx_timeout_pri[0] = __cpu_to_le32(0x64); |
---|
.. | .. |
---|
1611 | 1931 | cfg->rx_skip_defrag_timeout_dup_detection_check = __cpu_to_le32(0); |
---|
1612 | 1932 | cfg->vow_config = __cpu_to_le32(0); |
---|
1613 | 1933 | cfg->gtk_offload_max_vdev = __cpu_to_le32(2); |
---|
1614 | | - cfg->num_msdu_desc = __cpu_to_le32(TARGET_TLV_NUM_MSDU_DESC); |
---|
| 1934 | + cfg->num_msdu_desc = __cpu_to_le32(ar->htt.max_num_pending_tx); |
---|
1615 | 1935 | cfg->max_frag_entries = __cpu_to_le32(2); |
---|
1616 | 1936 | cfg->num_tdls_vdevs = __cpu_to_le32(TARGET_TLV_NUM_TDLS_VDEVS); |
---|
1617 | 1937 | cfg->num_tdls_conn_table_entries = __cpu_to_le32(0x20); |
---|
.. | .. |
---|
1626 | 1946 | cfg->num_ocb_vdevs = __cpu_to_le32(0); |
---|
1627 | 1947 | cfg->num_ocb_channels = __cpu_to_le32(0); |
---|
1628 | 1948 | cfg->num_ocb_schedules = __cpu_to_le32(0); |
---|
1629 | | - cfg->host_capab = __cpu_to_le32(0); |
---|
| 1949 | + cfg->host_capab = __cpu_to_le32(WMI_TLV_FLAG_MGMT_BUNDLE_TX_COMPL); |
---|
1630 | 1950 | |
---|
1631 | | - ath10k_wmi_put_host_mem_chunks(ar, chunks); |
---|
| 1951 | + if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map)) |
---|
| 1952 | + cfg->host_capab |= __cpu_to_le32(WMI_RSRC_CFG_FLAG_TX_ACK_RSSI); |
---|
| 1953 | + |
---|
| 1954 | + ath10k_wmi_tlv_put_host_mem_chunks(ar, chunks); |
---|
1632 | 1955 | |
---|
1633 | 1956 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv init\n"); |
---|
1634 | 1957 | return skb; |
---|
.. | .. |
---|
1772 | 2095 | return skb; |
---|
1773 | 2096 | } |
---|
1774 | 2097 | |
---|
| 2098 | +static int ath10k_wmi_tlv_op_get_vdev_subtype(struct ath10k *ar, |
---|
| 2099 | + enum wmi_vdev_subtype subtype) |
---|
| 2100 | +{ |
---|
| 2101 | + switch (subtype) { |
---|
| 2102 | + case WMI_VDEV_SUBTYPE_NONE: |
---|
| 2103 | + return WMI_TLV_VDEV_SUBTYPE_NONE; |
---|
| 2104 | + case WMI_VDEV_SUBTYPE_P2P_DEVICE: |
---|
| 2105 | + return WMI_TLV_VDEV_SUBTYPE_P2P_DEV; |
---|
| 2106 | + case WMI_VDEV_SUBTYPE_P2P_CLIENT: |
---|
| 2107 | + return WMI_TLV_VDEV_SUBTYPE_P2P_CLI; |
---|
| 2108 | + case WMI_VDEV_SUBTYPE_P2P_GO: |
---|
| 2109 | + return WMI_TLV_VDEV_SUBTYPE_P2P_GO; |
---|
| 2110 | + case WMI_VDEV_SUBTYPE_PROXY_STA: |
---|
| 2111 | + return WMI_TLV_VDEV_SUBTYPE_PROXY_STA; |
---|
| 2112 | + case WMI_VDEV_SUBTYPE_MESH_11S: |
---|
| 2113 | + return WMI_TLV_VDEV_SUBTYPE_MESH_11S; |
---|
| 2114 | + case WMI_VDEV_SUBTYPE_MESH_NON_11S: |
---|
| 2115 | + return -ENOTSUPP; |
---|
| 2116 | + } |
---|
| 2117 | + return -ENOTSUPP; |
---|
| 2118 | +} |
---|
| 2119 | + |
---|
1775 | 2120 | static struct sk_buff * |
---|
1776 | 2121 | ath10k_wmi_tlv_op_gen_vdev_create(struct ath10k *ar, |
---|
1777 | 2122 | u32 vdev_id, |
---|
.. | .. |
---|
1877 | 2222 | tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_CHANNEL); |
---|
1878 | 2223 | tlv->len = __cpu_to_le16(sizeof(*ch)); |
---|
1879 | 2224 | ch = (void *)tlv->value; |
---|
1880 | | - ath10k_wmi_put_wmi_channel(ch, &arg->channel); |
---|
| 2225 | + ath10k_wmi_put_wmi_channel(ar, ch, &arg->channel); |
---|
1881 | 2226 | |
---|
1882 | 2227 | ptr += sizeof(*tlv); |
---|
1883 | 2228 | ptr += sizeof(*ch); |
---|
.. | .. |
---|
1984 | 2329 | cmd->param_id = __cpu_to_le32(param_id); |
---|
1985 | 2330 | cmd->param_value = __cpu_to_le32(param_value); |
---|
1986 | 2331 | |
---|
1987 | | - ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev set param\n"); |
---|
| 2332 | + ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv vdev %d set param %d value 0x%x\n", |
---|
| 2333 | + vdev_id, param_id, param_value); |
---|
1988 | 2334 | return skb; |
---|
1989 | 2335 | } |
---|
1990 | 2336 | |
---|
.. | .. |
---|
1998 | 2344 | size_t len; |
---|
1999 | 2345 | void *ptr; |
---|
2000 | 2346 | |
---|
2001 | | - if (arg->key_cipher == WMI_CIPHER_NONE && arg->key_data != NULL) |
---|
| 2347 | + if (arg->key_cipher == ar->wmi_key_cipher[WMI_CIPHER_NONE] && |
---|
| 2348 | + arg->key_data) |
---|
2002 | 2349 | return ERR_PTR(-EINVAL); |
---|
2003 | | - if (arg->key_cipher != WMI_CIPHER_NONE && arg->key_data == NULL) |
---|
| 2350 | + if (arg->key_cipher != ar->wmi_key_cipher[WMI_CIPHER_NONE] && |
---|
| 2351 | + !arg->key_data) |
---|
2004 | 2352 | return ERR_PTR(-EINVAL); |
---|
2005 | 2353 | |
---|
2006 | 2354 | len = sizeof(*tlv) + sizeof(*cmd) + |
---|
.. | .. |
---|
2298 | 2646 | cmd->param_value = __cpu_to_le32(param_value); |
---|
2299 | 2647 | ether_addr_copy(cmd->peer_macaddr.addr, peer_addr); |
---|
2300 | 2648 | |
---|
2301 | | - ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv peer set param\n"); |
---|
| 2649 | + ath10k_dbg(ar, ATH10K_DBG_WMI, |
---|
| 2650 | + "wmi tlv vdev %d peer %pM set param %d value 0x%x\n", |
---|
| 2651 | + vdev_id, peer_addr, param_id, param_value); |
---|
2302 | 2652 | return skb; |
---|
2303 | 2653 | } |
---|
2304 | 2654 | |
---|
.. | .. |
---|
2512 | 2862 | tlv->len = __cpu_to_le16(sizeof(*ci)); |
---|
2513 | 2863 | ci = (void *)tlv->value; |
---|
2514 | 2864 | |
---|
2515 | | - ath10k_wmi_put_wmi_channel(ci, ch); |
---|
| 2865 | + ath10k_wmi_put_wmi_channel(ar, ci, ch); |
---|
2516 | 2866 | |
---|
2517 | 2867 | chans += sizeof(*tlv); |
---|
2518 | 2868 | chans += sizeof(*ci); |
---|
.. | .. |
---|
2646 | 2996 | return skb; |
---|
2647 | 2997 | } |
---|
2648 | 2998 | |
---|
| 2999 | +static struct sk_buff * |
---|
| 3000 | +ath10k_wmi_tlv_op_gen_request_peer_stats_info(struct ath10k *ar, |
---|
| 3001 | + u32 vdev_id, |
---|
| 3002 | + enum wmi_peer_stats_info_request_type type, |
---|
| 3003 | + u8 *addr, |
---|
| 3004 | + u32 reset) |
---|
| 3005 | +{ |
---|
| 3006 | + struct wmi_tlv_request_peer_stats_info *cmd; |
---|
| 3007 | + struct wmi_tlv *tlv; |
---|
| 3008 | + struct sk_buff *skb; |
---|
| 3009 | + |
---|
| 3010 | + skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd)); |
---|
| 3011 | + if (!skb) |
---|
| 3012 | + return ERR_PTR(-ENOMEM); |
---|
| 3013 | + |
---|
| 3014 | + tlv = (void *)skb->data; |
---|
| 3015 | + tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_REQUEST_PEER_STATS_INFO_CMD); |
---|
| 3016 | + tlv->len = __cpu_to_le16(sizeof(*cmd)); |
---|
| 3017 | + cmd = (void *)tlv->value; |
---|
| 3018 | + cmd->vdev_id = __cpu_to_le32(vdev_id); |
---|
| 3019 | + cmd->request_type = __cpu_to_le32(type); |
---|
| 3020 | + |
---|
| 3021 | + if (type == WMI_REQUEST_ONE_PEER_STATS_INFO) |
---|
| 3022 | + ether_addr_copy(cmd->peer_macaddr.addr, addr); |
---|
| 3023 | + |
---|
| 3024 | + cmd->reset_after_request = __cpu_to_le32(reset); |
---|
| 3025 | + ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv request peer stats info\n"); |
---|
| 3026 | + return skb; |
---|
| 3027 | +} |
---|
| 3028 | + |
---|
2649 | 3029 | static int |
---|
2650 | 3030 | ath10k_wmi_tlv_op_cleanup_mgmt_tx_send(struct ath10k *ar, |
---|
2651 | 3031 | struct sk_buff *msdu) |
---|
.. | .. |
---|
2704 | 3084 | arvif = (void *)cb->vif->drv_priv; |
---|
2705 | 3085 | vdev_id = arvif->vdev_id; |
---|
2706 | 3086 | |
---|
2707 | | - if (WARN_ON_ONCE(!ieee80211_is_mgmt(hdr->frame_control))) |
---|
| 3087 | + if (WARN_ON_ONCE(!ieee80211_is_mgmt(hdr->frame_control) && |
---|
| 3088 | + (!(ieee80211_is_nullfunc(hdr->frame_control) || |
---|
| 3089 | + ieee80211_is_qos_nullfunc(hdr->frame_control))))) |
---|
2708 | 3090 | return ERR_PTR(-EINVAL); |
---|
2709 | 3091 | |
---|
2710 | 3092 | len = sizeof(*cmd) + 2 * sizeof(*tlv); |
---|
.. | .. |
---|
3211 | 3593 | tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_CHANNEL); |
---|
3212 | 3594 | tlv->len = __cpu_to_le16(sizeof(*chan)); |
---|
3213 | 3595 | chan = (void *)tlv->value; |
---|
3214 | | - ath10k_wmi_put_wmi_channel(chan, &chan_arg[i]); |
---|
| 3596 | + ath10k_wmi_put_wmi_channel(ar, chan, &chan_arg[i]); |
---|
3215 | 3597 | |
---|
3216 | 3598 | ptr += sizeof(*tlv); |
---|
3217 | 3599 | ptr += sizeof(*chan); |
---|
.. | .. |
---|
3273 | 3655 | cmd = (void *)tlv->value; |
---|
3274 | 3656 | |
---|
3275 | 3657 | cmd->enable = __cpu_to_le32(1); |
---|
| 3658 | + if (!ar->bus_param.link_can_suspend) |
---|
| 3659 | + cmd->pause_iface_config = __cpu_to_le32(WOW_IFACE_PAUSE_DISABLED); |
---|
3276 | 3660 | |
---|
3277 | 3661 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv wow enable\n"); |
---|
3278 | 3662 | return skb; |
---|
.. | .. |
---|
3456 | 3840 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv wow del pattern vdev_id %d pattern_id %d\n", |
---|
3457 | 3841 | vdev_id, pattern_id); |
---|
3458 | 3842 | return skb; |
---|
| 3843 | +} |
---|
| 3844 | + |
---|
| 3845 | +/* Request FW to start PNO operation */ |
---|
| 3846 | +static struct sk_buff * |
---|
| 3847 | +ath10k_wmi_tlv_op_gen_config_pno_start(struct ath10k *ar, |
---|
| 3848 | + u32 vdev_id, |
---|
| 3849 | + struct wmi_pno_scan_req *pno) |
---|
| 3850 | +{ |
---|
| 3851 | + struct nlo_configured_parameters *nlo_list; |
---|
| 3852 | + struct wmi_tlv_wow_nlo_config_cmd *cmd; |
---|
| 3853 | + struct wmi_tlv *tlv; |
---|
| 3854 | + struct sk_buff *skb; |
---|
| 3855 | + __le32 *channel_list; |
---|
| 3856 | + u16 tlv_len; |
---|
| 3857 | + size_t len; |
---|
| 3858 | + void *ptr; |
---|
| 3859 | + u32 i; |
---|
| 3860 | + |
---|
| 3861 | + len = sizeof(*tlv) + sizeof(*cmd) + |
---|
| 3862 | + sizeof(*tlv) + |
---|
| 3863 | + /* TLV place holder for array of structures |
---|
| 3864 | + * nlo_configured_parameters(nlo_list) |
---|
| 3865 | + */ |
---|
| 3866 | + sizeof(*tlv); |
---|
| 3867 | + /* TLV place holder for array of uint32 channel_list */ |
---|
| 3868 | + |
---|
| 3869 | + len += sizeof(u32) * min_t(u8, pno->a_networks[0].channel_count, |
---|
| 3870 | + WMI_NLO_MAX_CHAN); |
---|
| 3871 | + len += sizeof(struct nlo_configured_parameters) * |
---|
| 3872 | + min_t(u8, pno->uc_networks_count, WMI_NLO_MAX_SSIDS); |
---|
| 3873 | + |
---|
| 3874 | + skb = ath10k_wmi_alloc_skb(ar, len); |
---|
| 3875 | + if (!skb) |
---|
| 3876 | + return ERR_PTR(-ENOMEM); |
---|
| 3877 | + |
---|
| 3878 | + ptr = (void *)skb->data; |
---|
| 3879 | + tlv = ptr; |
---|
| 3880 | + tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_NLO_CONFIG_CMD); |
---|
| 3881 | + tlv->len = __cpu_to_le16(sizeof(*cmd)); |
---|
| 3882 | + cmd = (void *)tlv->value; |
---|
| 3883 | + |
---|
| 3884 | + /* wmi_tlv_wow_nlo_config_cmd parameters*/ |
---|
| 3885 | + cmd->vdev_id = __cpu_to_le32(pno->vdev_id); |
---|
| 3886 | + cmd->flags = __cpu_to_le32(WMI_NLO_CONFIG_START | WMI_NLO_CONFIG_SSID_HIDE_EN); |
---|
| 3887 | + |
---|
| 3888 | + /* current FW does not support min-max range for dwell time */ |
---|
| 3889 | + cmd->active_dwell_time = __cpu_to_le32(pno->active_max_time); |
---|
| 3890 | + cmd->passive_dwell_time = __cpu_to_le32(pno->passive_max_time); |
---|
| 3891 | + |
---|
| 3892 | + if (pno->do_passive_scan) |
---|
| 3893 | + cmd->flags |= __cpu_to_le32(WMI_NLO_CONFIG_SCAN_PASSIVE); |
---|
| 3894 | + |
---|
| 3895 | + /* copy scan interval */ |
---|
| 3896 | + cmd->fast_scan_period = __cpu_to_le32(pno->fast_scan_period); |
---|
| 3897 | + cmd->slow_scan_period = __cpu_to_le32(pno->slow_scan_period); |
---|
| 3898 | + cmd->fast_scan_max_cycles = __cpu_to_le32(pno->fast_scan_max_cycles); |
---|
| 3899 | + cmd->delay_start_time = __cpu_to_le32(pno->delay_start_time); |
---|
| 3900 | + |
---|
| 3901 | + if (pno->enable_pno_scan_randomization) { |
---|
| 3902 | + cmd->flags |= __cpu_to_le32(WMI_NLO_CONFIG_SPOOFED_MAC_IN_PROBE_REQ | |
---|
| 3903 | + WMI_NLO_CONFIG_RANDOM_SEQ_NO_IN_PROBE_REQ); |
---|
| 3904 | + ether_addr_copy(cmd->mac_addr.addr, pno->mac_addr); |
---|
| 3905 | + ether_addr_copy(cmd->mac_mask.addr, pno->mac_addr_mask); |
---|
| 3906 | + } |
---|
| 3907 | + |
---|
| 3908 | + ptr += sizeof(*tlv); |
---|
| 3909 | + ptr += sizeof(*cmd); |
---|
| 3910 | + |
---|
| 3911 | + /* nlo_configured_parameters(nlo_list) */ |
---|
| 3912 | + cmd->no_of_ssids = __cpu_to_le32(min_t(u8, pno->uc_networks_count, |
---|
| 3913 | + WMI_NLO_MAX_SSIDS)); |
---|
| 3914 | + tlv_len = __le32_to_cpu(cmd->no_of_ssids) * |
---|
| 3915 | + sizeof(struct nlo_configured_parameters); |
---|
| 3916 | + |
---|
| 3917 | + tlv = ptr; |
---|
| 3918 | + tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT); |
---|
| 3919 | + tlv->len = __cpu_to_le16(tlv_len); |
---|
| 3920 | + |
---|
| 3921 | + ptr += sizeof(*tlv); |
---|
| 3922 | + nlo_list = ptr; |
---|
| 3923 | + for (i = 0; i < __le32_to_cpu(cmd->no_of_ssids); i++) { |
---|
| 3924 | + tlv = (struct wmi_tlv *)(&nlo_list[i].tlv_header); |
---|
| 3925 | + tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE); |
---|
| 3926 | + tlv->len = __cpu_to_le16(sizeof(struct nlo_configured_parameters) - |
---|
| 3927 | + sizeof(*tlv)); |
---|
| 3928 | + |
---|
| 3929 | + /* copy ssid and it's length */ |
---|
| 3930 | + nlo_list[i].ssid.valid = __cpu_to_le32(true); |
---|
| 3931 | + nlo_list[i].ssid.ssid.ssid_len = pno->a_networks[i].ssid.ssid_len; |
---|
| 3932 | + memcpy(nlo_list[i].ssid.ssid.ssid, |
---|
| 3933 | + pno->a_networks[i].ssid.ssid, |
---|
| 3934 | + __le32_to_cpu(nlo_list[i].ssid.ssid.ssid_len)); |
---|
| 3935 | + |
---|
| 3936 | + /* copy rssi threshold */ |
---|
| 3937 | + if (pno->a_networks[i].rssi_threshold && |
---|
| 3938 | + pno->a_networks[i].rssi_threshold > -300) { |
---|
| 3939 | + nlo_list[i].rssi_cond.valid = __cpu_to_le32(true); |
---|
| 3940 | + nlo_list[i].rssi_cond.rssi = |
---|
| 3941 | + __cpu_to_le32(pno->a_networks[i].rssi_threshold); |
---|
| 3942 | + } |
---|
| 3943 | + |
---|
| 3944 | + nlo_list[i].bcast_nw_type.valid = __cpu_to_le32(true); |
---|
| 3945 | + nlo_list[i].bcast_nw_type.bcast_nw_type = |
---|
| 3946 | + __cpu_to_le32(pno->a_networks[i].bcast_nw_type); |
---|
| 3947 | + } |
---|
| 3948 | + |
---|
| 3949 | + ptr += __le32_to_cpu(cmd->no_of_ssids) * sizeof(struct nlo_configured_parameters); |
---|
| 3950 | + |
---|
| 3951 | + /* copy channel info */ |
---|
| 3952 | + cmd->num_of_channels = __cpu_to_le32(min_t(u8, |
---|
| 3953 | + pno->a_networks[0].channel_count, |
---|
| 3954 | + WMI_NLO_MAX_CHAN)); |
---|
| 3955 | + |
---|
| 3956 | + tlv = ptr; |
---|
| 3957 | + tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_UINT32); |
---|
| 3958 | + tlv->len = __cpu_to_le16(__le32_to_cpu(cmd->num_of_channels) * |
---|
| 3959 | + sizeof(u_int32_t)); |
---|
| 3960 | + ptr += sizeof(*tlv); |
---|
| 3961 | + |
---|
| 3962 | + channel_list = (__le32 *)ptr; |
---|
| 3963 | + for (i = 0; i < __le32_to_cpu(cmd->num_of_channels); i++) |
---|
| 3964 | + channel_list[i] = __cpu_to_le32(pno->a_networks[0].channels[i]); |
---|
| 3965 | + |
---|
| 3966 | + ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv start pno config vdev_id %d\n", |
---|
| 3967 | + vdev_id); |
---|
| 3968 | + |
---|
| 3969 | + return skb; |
---|
| 3970 | +} |
---|
| 3971 | + |
---|
| 3972 | +/* Request FW to stop ongoing PNO operation */ |
---|
| 3973 | +static struct sk_buff *ath10k_wmi_tlv_op_gen_config_pno_stop(struct ath10k *ar, |
---|
| 3974 | + u32 vdev_id) |
---|
| 3975 | +{ |
---|
| 3976 | + struct wmi_tlv_wow_nlo_config_cmd *cmd; |
---|
| 3977 | + struct wmi_tlv *tlv; |
---|
| 3978 | + struct sk_buff *skb; |
---|
| 3979 | + void *ptr; |
---|
| 3980 | + size_t len; |
---|
| 3981 | + |
---|
| 3982 | + len = sizeof(*tlv) + sizeof(*cmd) + |
---|
| 3983 | + sizeof(*tlv) + |
---|
| 3984 | + /* TLV place holder for array of structures |
---|
| 3985 | + * nlo_configured_parameters(nlo_list) |
---|
| 3986 | + */ |
---|
| 3987 | + sizeof(*tlv); |
---|
| 3988 | + /* TLV place holder for array of uint32 channel_list */ |
---|
| 3989 | + skb = ath10k_wmi_alloc_skb(ar, len); |
---|
| 3990 | + if (!skb) |
---|
| 3991 | + return ERR_PTR(-ENOMEM); |
---|
| 3992 | + |
---|
| 3993 | + ptr = (void *)skb->data; |
---|
| 3994 | + tlv = ptr; |
---|
| 3995 | + tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_NLO_CONFIG_CMD); |
---|
| 3996 | + tlv->len = __cpu_to_le16(sizeof(*cmd)); |
---|
| 3997 | + cmd = (void *)tlv->value; |
---|
| 3998 | + |
---|
| 3999 | + cmd->vdev_id = __cpu_to_le32(vdev_id); |
---|
| 4000 | + cmd->flags = __cpu_to_le32(WMI_NLO_CONFIG_STOP); |
---|
| 4001 | + |
---|
| 4002 | + ptr += sizeof(*tlv); |
---|
| 4003 | + ptr += sizeof(*cmd); |
---|
| 4004 | + |
---|
| 4005 | + /* nlo_configured_parameters(nlo_list) */ |
---|
| 4006 | + tlv = ptr; |
---|
| 4007 | + tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT); |
---|
| 4008 | + tlv->len = __cpu_to_le16(0); |
---|
| 4009 | + |
---|
| 4010 | + ptr += sizeof(*tlv); |
---|
| 4011 | + |
---|
| 4012 | + /* channel list */ |
---|
| 4013 | + tlv = ptr; |
---|
| 4014 | + tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_UINT32); |
---|
| 4015 | + tlv->len = __cpu_to_le16(0); |
---|
| 4016 | + |
---|
| 4017 | + ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv stop pno config vdev_id %d\n", vdev_id); |
---|
| 4018 | + return skb; |
---|
| 4019 | +} |
---|
| 4020 | + |
---|
| 4021 | +static struct sk_buff * |
---|
| 4022 | +ath10k_wmi_tlv_op_gen_config_pno(struct ath10k *ar, u32 vdev_id, |
---|
| 4023 | + struct wmi_pno_scan_req *pno_scan) |
---|
| 4024 | +{ |
---|
| 4025 | + if (pno_scan->enable) |
---|
| 4026 | + return ath10k_wmi_tlv_op_gen_config_pno_start(ar, vdev_id, pno_scan); |
---|
| 4027 | + else |
---|
| 4028 | + return ath10k_wmi_tlv_op_gen_config_pno_stop(ar, vdev_id); |
---|
3459 | 4029 | } |
---|
3460 | 4030 | |
---|
3461 | 4031 | static struct sk_buff * |
---|
.. | .. |
---|
3686 | 4256 | .vdev_spectral_scan_configure_cmdid = WMI_TLV_SPECTRAL_SCAN_CONF_CMDID, |
---|
3687 | 4257 | .vdev_spectral_scan_enable_cmdid = WMI_TLV_SPECTRAL_SCAN_ENABLE_CMDID, |
---|
3688 | 4258 | .request_stats_cmdid = WMI_TLV_REQUEST_STATS_CMDID, |
---|
| 4259 | + .request_peer_stats_info_cmdid = WMI_TLV_REQUEST_PEER_STATS_INFO_CMDID, |
---|
3689 | 4260 | .set_arp_ns_offload_cmdid = WMI_TLV_SET_ARP_NS_OFFLOAD_CMDID, |
---|
3690 | 4261 | .network_list_offload_config_cmdid = |
---|
3691 | 4262 | WMI_TLV_NETWORK_LIST_OFFLOAD_CONFIG_CMDID, |
---|
.. | .. |
---|
3840 | 4411 | .wapi_mbssid_offset = WMI_PDEV_PARAM_UNSUPPORTED, |
---|
3841 | 4412 | .arp_srcaddr = WMI_PDEV_PARAM_UNSUPPORTED, |
---|
3842 | 4413 | .arp_dstaddr = WMI_PDEV_PARAM_UNSUPPORTED, |
---|
| 4414 | + .rfkill_config = WMI_TLV_PDEV_PARAM_HW_RFKILL_CONFIG, |
---|
| 4415 | + .rfkill_enable = WMI_TLV_PDEV_PARAM_RFKILL_ENABLE, |
---|
| 4416 | + .peer_stats_info_enable = WMI_TLV_PDEV_PARAM_PEER_STATS_INFO_ENABLE, |
---|
| 4417 | +}; |
---|
| 4418 | + |
---|
| 4419 | +static struct wmi_peer_param_map wmi_tlv_peer_param_map = { |
---|
| 4420 | + .smps_state = WMI_TLV_PEER_SMPS_STATE, |
---|
| 4421 | + .ampdu = WMI_TLV_PEER_AMPDU, |
---|
| 4422 | + .authorize = WMI_TLV_PEER_AUTHORIZE, |
---|
| 4423 | + .chan_width = WMI_TLV_PEER_CHAN_WIDTH, |
---|
| 4424 | + .nss = WMI_TLV_PEER_NSS, |
---|
| 4425 | + .use_4addr = WMI_TLV_PEER_USE_4ADDR, |
---|
| 4426 | + .membership = WMI_TLV_PEER_MEMBERSHIP, |
---|
| 4427 | + .user_pos = WMI_TLV_PEER_USERPOS, |
---|
| 4428 | + .crit_proto_hint_enabled = WMI_TLV_PEER_CRIT_PROTO_HINT_ENABLED, |
---|
| 4429 | + .tx_fail_cnt_thr = WMI_TLV_PEER_TX_FAIL_CNT_THR, |
---|
| 4430 | + .set_hw_retry_cts2s = WMI_TLV_PEER_SET_HW_RETRY_CTS2S, |
---|
| 4431 | + .ibss_atim_win_len = WMI_TLV_PEER_IBSS_ATIM_WINDOW_LENGTH, |
---|
| 4432 | + .phymode = WMI_TLV_PEER_PHYMODE, |
---|
| 4433 | + .use_fixed_power = WMI_TLV_PEER_USE_FIXED_PWR, |
---|
| 4434 | + .dummy_var = WMI_TLV_PEER_DUMMY_VAR, |
---|
3843 | 4435 | }; |
---|
3844 | 4436 | |
---|
3845 | 4437 | static struct wmi_vdev_param_map wmi_tlv_vdev_param_map = { |
---|
.. | .. |
---|
3924 | 4516 | .pull_scan = ath10k_wmi_tlv_op_pull_scan_ev, |
---|
3925 | 4517 | .pull_mgmt_rx = ath10k_wmi_tlv_op_pull_mgmt_rx_ev, |
---|
3926 | 4518 | .pull_mgmt_tx_compl = ath10k_wmi_tlv_op_pull_mgmt_tx_compl_ev, |
---|
| 4519 | + .pull_mgmt_tx_bundle_compl = ath10k_wmi_tlv_op_pull_mgmt_tx_bundle_compl_ev, |
---|
3927 | 4520 | .pull_ch_info = ath10k_wmi_tlv_op_pull_ch_info_ev, |
---|
3928 | 4521 | .pull_vdev_start = ath10k_wmi_tlv_op_pull_vdev_start_ev, |
---|
3929 | 4522 | .pull_peer_kick = ath10k_wmi_tlv_op_pull_peer_kick_ev, |
---|
.. | .. |
---|
3968 | 4561 | .gen_beacon_dma = ath10k_wmi_tlv_op_gen_beacon_dma, |
---|
3969 | 4562 | .gen_pdev_set_wmm = ath10k_wmi_tlv_op_gen_pdev_set_wmm, |
---|
3970 | 4563 | .gen_request_stats = ath10k_wmi_tlv_op_gen_request_stats, |
---|
| 4564 | + .gen_request_peer_stats_info = ath10k_wmi_tlv_op_gen_request_peer_stats_info, |
---|
3971 | 4565 | .gen_force_fw_hang = ath10k_wmi_tlv_op_gen_force_fw_hang, |
---|
3972 | 4566 | /* .gen_mgmt_tx = not implemented; HTT is used */ |
---|
3973 | 4567 | .gen_mgmt_tx_send = ath10k_wmi_tlv_op_gen_mgmt_tx_send, |
---|
.. | .. |
---|
3991 | 4585 | .gen_wow_host_wakeup_ind = ath10k_wmi_tlv_gen_wow_host_wakeup_ind, |
---|
3992 | 4586 | .gen_wow_add_pattern = ath10k_wmi_tlv_op_gen_wow_add_pattern, |
---|
3993 | 4587 | .gen_wow_del_pattern = ath10k_wmi_tlv_op_gen_wow_del_pattern, |
---|
| 4588 | + .gen_wow_config_pno = ath10k_wmi_tlv_op_gen_config_pno, |
---|
3994 | 4589 | .gen_update_fw_tdls_state = ath10k_wmi_tlv_op_gen_update_fw_tdls_state, |
---|
3995 | 4590 | .gen_tdls_peer_update = ath10k_wmi_tlv_op_gen_tdls_peer_update, |
---|
3996 | 4591 | .gen_adaptive_qcs = ath10k_wmi_tlv_op_gen_adaptive_qcs, |
---|
3997 | 4592 | .fw_stats_fill = ath10k_wmi_main_op_fw_stats_fill, |
---|
3998 | | - .get_vdev_subtype = ath10k_wmi_op_get_vdev_subtype, |
---|
| 4593 | + .get_vdev_subtype = ath10k_wmi_tlv_op_get_vdev_subtype, |
---|
3999 | 4594 | .gen_echo = ath10k_wmi_tlv_op_gen_echo, |
---|
4000 | 4595 | .gen_vdev_spectral_conf = ath10k_wmi_tlv_op_gen_vdev_spectral_conf, |
---|
4001 | 4596 | .gen_vdev_spectral_enable = ath10k_wmi_tlv_op_gen_vdev_spectral_enable, |
---|
.. | .. |
---|
4029 | 4624 | ar->wmi.cmd = &wmi_tlv_cmd_map; |
---|
4030 | 4625 | ar->wmi.vdev_param = &wmi_tlv_vdev_param_map; |
---|
4031 | 4626 | ar->wmi.pdev_param = &wmi_tlv_pdev_param_map; |
---|
| 4627 | + ar->wmi.peer_param = &wmi_tlv_peer_param_map; |
---|
4032 | 4628 | ar->wmi.ops = &wmi_tlv_ops; |
---|
4033 | 4629 | ar->wmi.peer_flags = &wmi_tlv_peer_flags_map; |
---|
4034 | 4630 | } |
---|