.. | .. |
---|
| 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 | 5 | * Copyright (c) 2018-2019, 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. |
---|
17 | 6 | */ |
---|
18 | 7 | |
---|
19 | 8 | #include "mac.h" |
---|
.. | .. |
---|
22 | 11 | #include <net/mac80211.h> |
---|
23 | 12 | #include <linux/etherdevice.h> |
---|
24 | 13 | #include <linux/acpi.h> |
---|
| 14 | +#include <linux/of.h> |
---|
| 15 | +#include <linux/bitfield.h> |
---|
25 | 16 | |
---|
26 | 17 | #include "hif.h" |
---|
27 | 18 | #include "core.h" |
---|
.. | .. |
---|
30 | 21 | #include "htt.h" |
---|
31 | 22 | #include "txrx.h" |
---|
32 | 23 | #include "testmode.h" |
---|
33 | | -#include "wmi.h" |
---|
34 | 24 | #include "wmi-tlv.h" |
---|
35 | 25 | #include "wmi-ops.h" |
---|
36 | 26 | #include "wow.h" |
---|
.. | .. |
---|
157 | 147 | return 0; |
---|
158 | 148 | } |
---|
159 | 149 | |
---|
| 150 | +static int ath10k_mac_get_rate_hw_value(int bitrate) |
---|
| 151 | +{ |
---|
| 152 | + int i; |
---|
| 153 | + u8 hw_value_prefix = 0; |
---|
| 154 | + |
---|
| 155 | + if (ath10k_mac_bitrate_is_cck(bitrate)) |
---|
| 156 | + hw_value_prefix = WMI_RATE_PREAMBLE_CCK << 6; |
---|
| 157 | + |
---|
| 158 | + for (i = 0; i < ARRAY_SIZE(ath10k_rates); i++) { |
---|
| 159 | + if (ath10k_rates[i].bitrate == bitrate) |
---|
| 160 | + return hw_value_prefix | ath10k_rates[i].hw_value; |
---|
| 161 | + } |
---|
| 162 | + |
---|
| 163 | + return -EINVAL; |
---|
| 164 | +} |
---|
| 165 | + |
---|
160 | 166 | static int ath10k_mac_get_max_vht_mcs_map(u16 mcs_map, int nss) |
---|
161 | 167 | { |
---|
162 | 168 | switch ((mcs_map >> (2 * nss)) & 0x3) { |
---|
.. | .. |
---|
234 | 240 | |
---|
235 | 241 | switch (key->cipher) { |
---|
236 | 242 | case WLAN_CIPHER_SUITE_CCMP: |
---|
237 | | - arg.key_cipher = WMI_CIPHER_AES_CCM; |
---|
| 243 | + arg.key_cipher = ar->wmi_key_cipher[WMI_CIPHER_AES_CCM]; |
---|
238 | 244 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV_MGMT; |
---|
239 | 245 | break; |
---|
240 | 246 | case WLAN_CIPHER_SUITE_TKIP: |
---|
241 | | - arg.key_cipher = WMI_CIPHER_TKIP; |
---|
| 247 | + arg.key_cipher = ar->wmi_key_cipher[WMI_CIPHER_TKIP]; |
---|
242 | 248 | arg.key_txmic_len = 8; |
---|
243 | 249 | arg.key_rxmic_len = 8; |
---|
244 | 250 | break; |
---|
245 | 251 | case WLAN_CIPHER_SUITE_WEP40: |
---|
246 | 252 | case WLAN_CIPHER_SUITE_WEP104: |
---|
247 | | - arg.key_cipher = WMI_CIPHER_WEP; |
---|
| 253 | + arg.key_cipher = ar->wmi_key_cipher[WMI_CIPHER_WEP]; |
---|
248 | 254 | break; |
---|
249 | 255 | case WLAN_CIPHER_SUITE_CCMP_256: |
---|
250 | | - arg.key_cipher = WMI_CIPHER_AES_CCM; |
---|
| 256 | + arg.key_cipher = ar->wmi_key_cipher[WMI_CIPHER_AES_CCM]; |
---|
251 | 257 | break; |
---|
252 | 258 | case WLAN_CIPHER_SUITE_GCMP: |
---|
253 | 259 | case WLAN_CIPHER_SUITE_GCMP_256: |
---|
254 | | - arg.key_cipher = WMI_CIPHER_AES_GCM; |
---|
| 260 | + arg.key_cipher = ar->wmi_key_cipher[WMI_CIPHER_AES_GCM]; |
---|
| 261 | + key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV_MGMT; |
---|
255 | 262 | break; |
---|
256 | 263 | case WLAN_CIPHER_SUITE_BIP_GMAC_128: |
---|
257 | 264 | case WLAN_CIPHER_SUITE_BIP_GMAC_256: |
---|
.. | .. |
---|
268 | 275 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; |
---|
269 | 276 | |
---|
270 | 277 | if (cmd == DISABLE_KEY) { |
---|
271 | | - arg.key_cipher = WMI_CIPHER_NONE; |
---|
| 278 | + arg.key_cipher = ar->wmi_key_cipher[WMI_CIPHER_NONE]; |
---|
272 | 279 | arg.key_data = NULL; |
---|
273 | 280 | } |
---|
274 | 281 | |
---|
.. | .. |
---|
561 | 568 | case NL80211_CHAN_WIDTH_40: |
---|
562 | 569 | phymode = MODE_11NG_HT40; |
---|
563 | 570 | break; |
---|
564 | | - case NL80211_CHAN_WIDTH_5: |
---|
565 | | - case NL80211_CHAN_WIDTH_10: |
---|
566 | | - case NL80211_CHAN_WIDTH_80: |
---|
567 | | - case NL80211_CHAN_WIDTH_80P80: |
---|
568 | | - case NL80211_CHAN_WIDTH_160: |
---|
| 571 | + default: |
---|
569 | 572 | phymode = MODE_UNKNOWN; |
---|
570 | 573 | break; |
---|
571 | 574 | } |
---|
.. | .. |
---|
590 | 593 | case NL80211_CHAN_WIDTH_80P80: |
---|
591 | 594 | phymode = MODE_11AC_VHT80_80; |
---|
592 | 595 | break; |
---|
593 | | - case NL80211_CHAN_WIDTH_5: |
---|
594 | | - case NL80211_CHAN_WIDTH_10: |
---|
| 596 | + default: |
---|
595 | 597 | phymode = MODE_UNKNOWN; |
---|
596 | 598 | break; |
---|
597 | 599 | } |
---|
.. | .. |
---|
688 | 690 | *def = &conf->def; |
---|
689 | 691 | } |
---|
690 | 692 | |
---|
| 693 | +static void ath10k_wait_for_peer_delete_done(struct ath10k *ar, u32 vdev_id, |
---|
| 694 | + const u8 *addr) |
---|
| 695 | +{ |
---|
| 696 | + unsigned long time_left; |
---|
| 697 | + int ret; |
---|
| 698 | + |
---|
| 699 | + if (test_bit(WMI_SERVICE_SYNC_DELETE_CMDS, ar->wmi.svc_map)) { |
---|
| 700 | + ret = ath10k_wait_for_peer_deleted(ar, vdev_id, addr); |
---|
| 701 | + if (ret) { |
---|
| 702 | + ath10k_warn(ar, "failed wait for peer deleted"); |
---|
| 703 | + return; |
---|
| 704 | + } |
---|
| 705 | + |
---|
| 706 | + time_left = wait_for_completion_timeout(&ar->peer_delete_done, |
---|
| 707 | + 5 * HZ); |
---|
| 708 | + if (!time_left) |
---|
| 709 | + ath10k_warn(ar, "Timeout in receiving peer delete response\n"); |
---|
| 710 | + } |
---|
| 711 | +} |
---|
| 712 | + |
---|
691 | 713 | static int ath10k_peer_create(struct ath10k *ar, |
---|
692 | 714 | struct ieee80211_vif *vif, |
---|
693 | 715 | struct ieee80211_sta *sta, |
---|
.. | .. |
---|
732 | 754 | spin_unlock_bh(&ar->data_lock); |
---|
733 | 755 | ath10k_warn(ar, "failed to find peer %pM on vdev %i after creation\n", |
---|
734 | 756 | addr, vdev_id); |
---|
735 | | - ath10k_wmi_peer_delete(ar, vdev_id, addr); |
---|
| 757 | + ath10k_wait_for_peer_delete_done(ar, vdev_id, addr); |
---|
736 | 758 | return -ENOENT; |
---|
737 | 759 | } |
---|
738 | 760 | |
---|
.. | .. |
---|
814 | 836 | if (ret) |
---|
815 | 837 | return ret; |
---|
816 | 838 | |
---|
| 839 | + if (test_bit(WMI_SERVICE_SYNC_DELETE_CMDS, ar->wmi.svc_map)) { |
---|
| 840 | + unsigned long time_left; |
---|
| 841 | + |
---|
| 842 | + time_left = wait_for_completion_timeout |
---|
| 843 | + (&ar->peer_delete_done, 5 * HZ); |
---|
| 844 | + |
---|
| 845 | + if (!time_left) { |
---|
| 846 | + ath10k_warn(ar, "Timeout in receiving peer delete response\n"); |
---|
| 847 | + return -ETIMEDOUT; |
---|
| 848 | + } |
---|
| 849 | + } |
---|
| 850 | + |
---|
817 | 851 | ar->num_peers--; |
---|
818 | 852 | |
---|
819 | 853 | return 0; |
---|
820 | 854 | } |
---|
821 | 855 | |
---|
| 856 | +static void ath10k_peer_map_cleanup(struct ath10k *ar, struct ath10k_peer *peer) |
---|
| 857 | +{ |
---|
| 858 | + int peer_id, i; |
---|
| 859 | + |
---|
| 860 | + lockdep_assert_held(&ar->conf_mutex); |
---|
| 861 | + |
---|
| 862 | + for_each_set_bit(peer_id, peer->peer_ids, |
---|
| 863 | + ATH10K_MAX_NUM_PEER_IDS) { |
---|
| 864 | + ar->peer_map[peer_id] = NULL; |
---|
| 865 | + } |
---|
| 866 | + |
---|
| 867 | + /* Double check that peer is properly un-referenced from |
---|
| 868 | + * the peer_map |
---|
| 869 | + */ |
---|
| 870 | + for (i = 0; i < ARRAY_SIZE(ar->peer_map); i++) { |
---|
| 871 | + if (ar->peer_map[i] == peer) { |
---|
| 872 | + ath10k_warn(ar, "removing stale peer_map entry for %pM (ptr %pK idx %d)\n", |
---|
| 873 | + peer->addr, peer, i); |
---|
| 874 | + ar->peer_map[i] = NULL; |
---|
| 875 | + } |
---|
| 876 | + } |
---|
| 877 | + |
---|
| 878 | + list_del(&peer->list); |
---|
| 879 | + kfree(peer); |
---|
| 880 | + ar->num_peers--; |
---|
| 881 | +} |
---|
| 882 | + |
---|
822 | 883 | static void ath10k_peer_cleanup(struct ath10k *ar, u32 vdev_id) |
---|
823 | 884 | { |
---|
824 | 885 | struct ath10k_peer *peer, *tmp; |
---|
825 | | - int peer_id; |
---|
826 | | - int i; |
---|
827 | 886 | |
---|
828 | 887 | lockdep_assert_held(&ar->conf_mutex); |
---|
829 | 888 | |
---|
.. | .. |
---|
835 | 894 | ath10k_warn(ar, "removing stale peer %pM from vdev_id %d\n", |
---|
836 | 895 | peer->addr, vdev_id); |
---|
837 | 896 | |
---|
838 | | - for_each_set_bit(peer_id, peer->peer_ids, |
---|
839 | | - ATH10K_MAX_NUM_PEER_IDS) { |
---|
840 | | - ar->peer_map[peer_id] = NULL; |
---|
841 | | - } |
---|
842 | | - |
---|
843 | | - /* Double check that peer is properly un-referenced from |
---|
844 | | - * the peer_map |
---|
845 | | - */ |
---|
846 | | - for (i = 0; i < ARRAY_SIZE(ar->peer_map); i++) { |
---|
847 | | - if (ar->peer_map[i] == peer) { |
---|
848 | | - ath10k_warn(ar, "removing stale peer_map entry for %pM (ptr %pK idx %d)\n", |
---|
849 | | - peer->addr, peer, i); |
---|
850 | | - ar->peer_map[i] = NULL; |
---|
851 | | - } |
---|
852 | | - } |
---|
853 | | - |
---|
854 | | - list_del(&peer->list); |
---|
855 | | - kfree(peer); |
---|
856 | | - ar->num_peers--; |
---|
| 897 | + ath10k_peer_map_cleanup(ar, peer); |
---|
857 | 898 | } |
---|
858 | 899 | spin_unlock_bh(&ar->data_lock); |
---|
859 | 900 | } |
---|
.. | .. |
---|
948 | 989 | ath10k_mac_vif_beacon_free(arvif); |
---|
949 | 990 | |
---|
950 | 991 | if (arvif->beacon_buf) { |
---|
951 | | - dma_free_coherent(ar->dev, IEEE80211_MAX_FRAME_LEN, |
---|
952 | | - arvif->beacon_buf, arvif->beacon_paddr); |
---|
| 992 | + if (ar->bus_param.dev_type == ATH10K_DEV_TYPE_HL) |
---|
| 993 | + kfree(arvif->beacon_buf); |
---|
| 994 | + else |
---|
| 995 | + dma_free_coherent(ar->dev, IEEE80211_MAX_FRAME_LEN, |
---|
| 996 | + arvif->beacon_buf, |
---|
| 997 | + arvif->beacon_paddr); |
---|
953 | 998 | arvif->beacon_buf = NULL; |
---|
954 | 999 | } |
---|
955 | 1000 | } |
---|
.. | .. |
---|
1006 | 1051 | arg.channel.max_antenna_gain = channel->max_antenna_gain; |
---|
1007 | 1052 | |
---|
1008 | 1053 | reinit_completion(&ar->vdev_setup_done); |
---|
| 1054 | + reinit_completion(&ar->vdev_delete_done); |
---|
1009 | 1055 | |
---|
1010 | 1056 | ret = ath10k_wmi_vdev_start(ar, &arg); |
---|
1011 | 1057 | if (ret) { |
---|
.. | .. |
---|
1055 | 1101 | ar->monitor_vdev_id, ret); |
---|
1056 | 1102 | |
---|
1057 | 1103 | reinit_completion(&ar->vdev_setup_done); |
---|
| 1104 | + reinit_completion(&ar->vdev_delete_done); |
---|
1058 | 1105 | |
---|
1059 | 1106 | ret = ath10k_wmi_vdev_stop(ar, ar->monitor_vdev_id); |
---|
1060 | 1107 | if (ret) |
---|
1061 | | - ath10k_warn(ar, "failed to to request monitor vdev %i stop: %d\n", |
---|
| 1108 | + ath10k_warn(ar, "failed to request monitor vdev %i stop: %d\n", |
---|
1062 | 1109 | ar->monitor_vdev_id, ret); |
---|
1063 | 1110 | |
---|
1064 | 1111 | ret = ath10k_vdev_setup_sync(ar); |
---|
.. | .. |
---|
1396 | 1443 | lockdep_assert_held(&ar->conf_mutex); |
---|
1397 | 1444 | |
---|
1398 | 1445 | reinit_completion(&ar->vdev_setup_done); |
---|
| 1446 | + reinit_completion(&ar->vdev_delete_done); |
---|
1399 | 1447 | |
---|
1400 | 1448 | ret = ath10k_wmi_vdev_stop(ar, arvif->vdev_id); |
---|
1401 | 1449 | if (ret) { |
---|
.. | .. |
---|
1432 | 1480 | lockdep_assert_held(&ar->conf_mutex); |
---|
1433 | 1481 | |
---|
1434 | 1482 | reinit_completion(&ar->vdev_setup_done); |
---|
| 1483 | + reinit_completion(&ar->vdev_delete_done); |
---|
1435 | 1484 | |
---|
1436 | 1485 | arg.vdev_id = arvif->vdev_id; |
---|
1437 | 1486 | arg.dtim_period = arvif->dtim_period; |
---|
.. | .. |
---|
1981 | 2030 | if (!arvif->is_up) |
---|
1982 | 2031 | return; |
---|
1983 | 2032 | |
---|
1984 | | - if (!ieee80211_csa_is_complete(vif)) { |
---|
1985 | | - ieee80211_csa_update_counter(vif); |
---|
| 2033 | + if (!ieee80211_beacon_cntdwn_is_complete(vif)) { |
---|
| 2034 | + ieee80211_beacon_update_cntdwn(vif); |
---|
1986 | 2035 | |
---|
1987 | 2036 | ret = ath10k_mac_setup_bcn_tmpl(arvif); |
---|
1988 | 2037 | if (ret) |
---|
.. | .. |
---|
2430 | 2479 | idx_limit = -1; |
---|
2431 | 2480 | |
---|
2432 | 2481 | switch (idx_limit) { |
---|
2433 | | - case 0: /* fall through */ |
---|
2434 | | - case 1: /* fall through */ |
---|
2435 | | - case 2: /* fall through */ |
---|
2436 | | - case 3: /* fall through */ |
---|
2437 | | - case 4: /* fall through */ |
---|
2438 | | - case 5: /* fall through */ |
---|
2439 | | - case 6: /* fall through */ |
---|
| 2482 | + case 0: |
---|
| 2483 | + case 1: |
---|
| 2484 | + case 2: |
---|
| 2485 | + case 3: |
---|
| 2486 | + case 4: |
---|
| 2487 | + case 5: |
---|
| 2488 | + case 6: |
---|
2440 | 2489 | default: |
---|
2441 | 2490 | /* see ath10k_mac_can_set_bitrate_mask() */ |
---|
2442 | 2491 | WARN_ON(1); |
---|
2443 | | - /* fall through */ |
---|
| 2492 | + fallthrough; |
---|
2444 | 2493 | case -1: |
---|
2445 | 2494 | mcs = IEEE80211_VHT_MCS_NOT_SUPPORTED; |
---|
2446 | 2495 | break; |
---|
.. | .. |
---|
2462 | 2511 | return tx_mcs_set; |
---|
2463 | 2512 | } |
---|
2464 | 2513 | |
---|
| 2514 | +static u32 get_160mhz_nss_from_maxrate(int rate) |
---|
| 2515 | +{ |
---|
| 2516 | + u32 nss; |
---|
| 2517 | + |
---|
| 2518 | + switch (rate) { |
---|
| 2519 | + case 780: |
---|
| 2520 | + nss = 1; |
---|
| 2521 | + break; |
---|
| 2522 | + case 1560: |
---|
| 2523 | + nss = 2; |
---|
| 2524 | + break; |
---|
| 2525 | + case 2106: |
---|
| 2526 | + nss = 3; /* not support MCS9 from spec*/ |
---|
| 2527 | + break; |
---|
| 2528 | + case 3120: |
---|
| 2529 | + nss = 4; |
---|
| 2530 | + break; |
---|
| 2531 | + default: |
---|
| 2532 | + nss = 1; |
---|
| 2533 | + } |
---|
| 2534 | + |
---|
| 2535 | + return nss; |
---|
| 2536 | +} |
---|
| 2537 | + |
---|
2465 | 2538 | static void ath10k_peer_assoc_h_vht(struct ath10k *ar, |
---|
2466 | 2539 | struct ieee80211_vif *vif, |
---|
2467 | 2540 | struct ieee80211_sta *sta, |
---|
.. | .. |
---|
2469 | 2542 | { |
---|
2470 | 2543 | const struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap; |
---|
2471 | 2544 | struct ath10k_vif *arvif = (void *)vif->drv_priv; |
---|
| 2545 | + struct ath10k_hw_params *hw = &ar->hw_params; |
---|
2472 | 2546 | struct cfg80211_chan_def def; |
---|
2473 | 2547 | enum nl80211_band band; |
---|
2474 | 2548 | const u16 *vht_mcs_mask; |
---|
.. | .. |
---|
2535 | 2609 | arg->peer_vht_rates.tx_mcs_set = ath10k_peer_assoc_h_vht_limit( |
---|
2536 | 2610 | __le16_to_cpu(vht_cap->vht_mcs.tx_mcs_map), vht_mcs_mask); |
---|
2537 | 2611 | |
---|
2538 | | - ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vht peer %pM max_mpdu %d flags 0x%x\n", |
---|
2539 | | - sta->addr, arg->peer_max_mpdu, arg->peer_flags); |
---|
| 2612 | + /* Configure bandwidth-NSS mapping to FW |
---|
| 2613 | + * for the chip's tx chains setting on 160Mhz bw |
---|
| 2614 | + */ |
---|
| 2615 | + if (arg->peer_phymode == MODE_11AC_VHT160 || |
---|
| 2616 | + arg->peer_phymode == MODE_11AC_VHT80_80) { |
---|
| 2617 | + u32 rx_nss; |
---|
| 2618 | + u32 max_rate; |
---|
2540 | 2619 | |
---|
2541 | | - if (arg->peer_vht_rates.rx_max_rate && |
---|
2542 | | - (sta->vht_cap.cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK)) { |
---|
2543 | | - switch (arg->peer_vht_rates.rx_max_rate) { |
---|
2544 | | - case 1560: |
---|
2545 | | - /* Must be 2x2 at 160Mhz is all it can do. */ |
---|
2546 | | - arg->peer_bw_rxnss_override = 2; |
---|
2547 | | - break; |
---|
2548 | | - case 780: |
---|
2549 | | - /* Can only do 1x1 at 160Mhz (Long Guard Interval) */ |
---|
2550 | | - arg->peer_bw_rxnss_override = 1; |
---|
2551 | | - break; |
---|
| 2620 | + max_rate = arg->peer_vht_rates.rx_max_rate; |
---|
| 2621 | + rx_nss = get_160mhz_nss_from_maxrate(max_rate); |
---|
| 2622 | + |
---|
| 2623 | + if (rx_nss == 0) |
---|
| 2624 | + rx_nss = arg->peer_num_spatial_streams; |
---|
| 2625 | + else |
---|
| 2626 | + rx_nss = min(arg->peer_num_spatial_streams, rx_nss); |
---|
| 2627 | + |
---|
| 2628 | + max_rate = hw->vht160_mcs_tx_highest; |
---|
| 2629 | + rx_nss = min(rx_nss, get_160mhz_nss_from_maxrate(max_rate)); |
---|
| 2630 | + |
---|
| 2631 | + arg->peer_bw_rxnss_override = |
---|
| 2632 | + FIELD_PREP(WMI_PEER_NSS_MAP_ENABLE, 1) | |
---|
| 2633 | + FIELD_PREP(WMI_PEER_NSS_160MHZ_MASK, (rx_nss - 1)); |
---|
| 2634 | + |
---|
| 2635 | + if (arg->peer_phymode == MODE_11AC_VHT80_80) { |
---|
| 2636 | + arg->peer_bw_rxnss_override |= |
---|
| 2637 | + FIELD_PREP(WMI_PEER_NSS_80_80MHZ_MASK, (rx_nss - 1)); |
---|
2552 | 2638 | } |
---|
2553 | 2639 | } |
---|
| 2640 | + ath10k_dbg(ar, ATH10K_DBG_MAC, |
---|
| 2641 | + "mac vht peer %pM max_mpdu %d flags 0x%x peer_rx_nss_override 0x%x\n", |
---|
| 2642 | + sta->addr, arg->peer_max_mpdu, |
---|
| 2643 | + arg->peer_flags, arg->peer_bw_rxnss_override); |
---|
2554 | 2644 | } |
---|
2555 | 2645 | |
---|
2556 | 2646 | static void ath10k_peer_assoc_h_qos(struct ath10k *ar, |
---|
.. | .. |
---|
2702 | 2792 | ath10k_peer_assoc_h_crypto(ar, vif, sta, arg); |
---|
2703 | 2793 | ath10k_peer_assoc_h_rates(ar, vif, sta, arg); |
---|
2704 | 2794 | ath10k_peer_assoc_h_ht(ar, vif, sta, arg); |
---|
| 2795 | + ath10k_peer_assoc_h_phymode(ar, vif, sta, arg); |
---|
2705 | 2796 | ath10k_peer_assoc_h_vht(ar, vif, sta, arg); |
---|
2706 | 2797 | ath10k_peer_assoc_h_qos(ar, vif, sta, arg); |
---|
2707 | | - ath10k_peer_assoc_h_phymode(ar, vif, sta, arg); |
---|
2708 | 2798 | |
---|
2709 | 2799 | return 0; |
---|
2710 | 2800 | } |
---|
.. | .. |
---|
2732 | 2822 | return -EINVAL; |
---|
2733 | 2823 | |
---|
2734 | 2824 | return ath10k_wmi_peer_set_param(ar, arvif->vdev_id, addr, |
---|
2735 | | - WMI_PEER_SMPS_STATE, |
---|
| 2825 | + ar->wmi.peer_param->smps_state, |
---|
2736 | 2826 | ath10k_smps_map[smps]); |
---|
2737 | 2827 | } |
---|
2738 | 2828 | |
---|
.. | .. |
---|
2875 | 2965 | arvif->aid = bss_conf->aid; |
---|
2876 | 2966 | ether_addr_copy(arvif->bssid, bss_conf->bssid); |
---|
2877 | 2967 | |
---|
| 2968 | + ret = ath10k_wmi_pdev_set_param(ar, |
---|
| 2969 | + ar->wmi.pdev_param->peer_stats_info_enable, 1); |
---|
| 2970 | + if (ret) |
---|
| 2971 | + ath10k_warn(ar, "failed to enable peer stats info: %d\n", ret); |
---|
| 2972 | + |
---|
2878 | 2973 | ret = ath10k_wmi_vdev_up(ar, arvif->vdev_id, arvif->aid, arvif->bssid); |
---|
2879 | 2974 | if (ret) { |
---|
2880 | 2975 | ath10k_warn(ar, "failed to set vdev %d up: %d\n", |
---|
.. | .. |
---|
2889 | 2984 | * poked with peer param command. |
---|
2890 | 2985 | */ |
---|
2891 | 2986 | ret = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, arvif->bssid, |
---|
2892 | | - WMI_PEER_DUMMY_VAR, 1); |
---|
| 2987 | + ar->wmi.peer_param->dummy_var, 1); |
---|
2893 | 2988 | if (ret) { |
---|
2894 | 2989 | ath10k_warn(ar, "failed to poke peer %pM param for ps workaround on vdev %i: %d\n", |
---|
2895 | 2990 | arvif->bssid, arvif->vdev_id, ret); |
---|
.. | .. |
---|
2927 | 3022 | arvif->is_up = false; |
---|
2928 | 3023 | |
---|
2929 | 3024 | cancel_delayed_work_sync(&arvif->connection_loss_work); |
---|
| 3025 | +} |
---|
| 3026 | + |
---|
| 3027 | +static int ath10k_new_peer_tid_config(struct ath10k *ar, |
---|
| 3028 | + struct ieee80211_sta *sta, |
---|
| 3029 | + struct ath10k_vif *arvif) |
---|
| 3030 | +{ |
---|
| 3031 | + struct wmi_per_peer_per_tid_cfg_arg arg = {}; |
---|
| 3032 | + struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv; |
---|
| 3033 | + bool config_apply; |
---|
| 3034 | + int ret, i; |
---|
| 3035 | + |
---|
| 3036 | + for (i = 0; i < ATH10K_TID_MAX; i++) { |
---|
| 3037 | + config_apply = false; |
---|
| 3038 | + if (arvif->retry_long[i] || arvif->ampdu[i] || |
---|
| 3039 | + arvif->rate_ctrl[i] || arvif->rtscts[i]) { |
---|
| 3040 | + config_apply = true; |
---|
| 3041 | + arg.tid = i; |
---|
| 3042 | + arg.vdev_id = arvif->vdev_id; |
---|
| 3043 | + arg.retry_count = arvif->retry_long[i]; |
---|
| 3044 | + arg.aggr_control = arvif->ampdu[i]; |
---|
| 3045 | + arg.rate_ctrl = arvif->rate_ctrl[i]; |
---|
| 3046 | + arg.rcode_flags = arvif->rate_code[i]; |
---|
| 3047 | + |
---|
| 3048 | + if (arvif->rtscts[i]) |
---|
| 3049 | + arg.ext_tid_cfg_bitmap = |
---|
| 3050 | + WMI_EXT_TID_RTS_CTS_CONFIG; |
---|
| 3051 | + else |
---|
| 3052 | + arg.ext_tid_cfg_bitmap = 0; |
---|
| 3053 | + |
---|
| 3054 | + arg.rtscts_ctrl = arvif->rtscts[i]; |
---|
| 3055 | + } |
---|
| 3056 | + |
---|
| 3057 | + if (arvif->noack[i]) { |
---|
| 3058 | + arg.ack_policy = arvif->noack[i]; |
---|
| 3059 | + arg.rate_ctrl = WMI_TID_CONFIG_RATE_CONTROL_DEFAULT_LOWEST_RATE; |
---|
| 3060 | + arg.aggr_control = WMI_TID_CONFIG_AGGR_CONTROL_DISABLE; |
---|
| 3061 | + config_apply = true; |
---|
| 3062 | + } |
---|
| 3063 | + |
---|
| 3064 | + /* Assign default value(-1) to newly connected station. |
---|
| 3065 | + * This is to identify station specific tid configuration not |
---|
| 3066 | + * configured for the station. |
---|
| 3067 | + */ |
---|
| 3068 | + arsta->retry_long[i] = -1; |
---|
| 3069 | + arsta->noack[i] = -1; |
---|
| 3070 | + arsta->ampdu[i] = -1; |
---|
| 3071 | + |
---|
| 3072 | + if (!config_apply) |
---|
| 3073 | + continue; |
---|
| 3074 | + |
---|
| 3075 | + ether_addr_copy(arg.peer_macaddr.addr, sta->addr); |
---|
| 3076 | + |
---|
| 3077 | + ret = ath10k_wmi_set_per_peer_per_tid_cfg(ar, &arg); |
---|
| 3078 | + if (ret) { |
---|
| 3079 | + ath10k_warn(ar, "failed to set per tid retry/aggr config for sta %pM: %d\n", |
---|
| 3080 | + sta->addr, ret); |
---|
| 3081 | + return ret; |
---|
| 3082 | + } |
---|
| 3083 | + |
---|
| 3084 | + memset(&arg, 0, sizeof(arg)); |
---|
| 3085 | + } |
---|
| 3086 | + |
---|
| 3087 | + return 0; |
---|
2930 | 3088 | } |
---|
2931 | 3089 | |
---|
2932 | 3090 | static int ath10k_station_assoc(struct ath10k *ar, |
---|
.. | .. |
---|
2994 | 3152 | } |
---|
2995 | 3153 | } |
---|
2996 | 3154 | |
---|
2997 | | - return ret; |
---|
| 3155 | + if (!test_bit(WMI_SERVICE_PEER_TID_CONFIGS_SUPPORT, ar->wmi.svc_map)) |
---|
| 3156 | + return ret; |
---|
| 3157 | + |
---|
| 3158 | + return ath10k_new_peer_tid_config(ar, sta, arvif); |
---|
2998 | 3159 | } |
---|
2999 | 3160 | |
---|
3000 | 3161 | static int ath10k_station_disassoc(struct ath10k *ar, |
---|
.. | .. |
---|
3385 | 3546 | struct sk_buff *skb) |
---|
3386 | 3547 | { |
---|
3387 | 3548 | const struct ieee80211_hdr *hdr = (void *)skb->data; |
---|
| 3549 | + const struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb); |
---|
3388 | 3550 | __le16 fc = hdr->frame_control; |
---|
3389 | 3551 | |
---|
3390 | 3552 | if (!vif || vif->type == NL80211_IFTYPE_MONITOR) |
---|
.. | .. |
---|
3426 | 3588 | if (ieee80211_is_data_present(fc) && sta && sta->tdls) |
---|
3427 | 3589 | return ATH10K_HW_TXRX_ETHERNET; |
---|
3428 | 3590 | |
---|
3429 | | - if (test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) |
---|
| 3591 | + if (test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags) || |
---|
| 3592 | + skb_cb->flags & ATH10K_SKB_F_RAW_TX) |
---|
3430 | 3593 | return ATH10K_HW_TXRX_RAW; |
---|
3431 | 3594 | |
---|
3432 | 3595 | return ATH10K_HW_TXRX_NATIVE_WIFI; |
---|
.. | .. |
---|
3532 | 3695 | static void ath10k_mac_tx_h_fill_cb(struct ath10k *ar, |
---|
3533 | 3696 | struct ieee80211_vif *vif, |
---|
3534 | 3697 | struct ieee80211_txq *txq, |
---|
3535 | | - struct sk_buff *skb) |
---|
| 3698 | + struct ieee80211_sta *sta, |
---|
| 3699 | + struct sk_buff *skb, u16 airtime) |
---|
3536 | 3700 | { |
---|
3537 | 3701 | struct ieee80211_hdr *hdr = (void *)skb->data; |
---|
3538 | 3702 | struct ath10k_skb_cb *cb = ATH10K_SKB_CB(skb); |
---|
| 3703 | + const struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
---|
| 3704 | + bool is_data = ieee80211_is_data(hdr->frame_control) || |
---|
| 3705 | + ieee80211_is_data_qos(hdr->frame_control); |
---|
| 3706 | + struct ath10k_vif *arvif = (void *)vif->drv_priv; |
---|
| 3707 | + struct ath10k_sta *arsta; |
---|
| 3708 | + u8 tid, *qos_ctl; |
---|
| 3709 | + bool noack = false; |
---|
3539 | 3710 | |
---|
3540 | 3711 | cb->flags = 0; |
---|
3541 | 3712 | if (!ath10k_tx_h_use_hwcrypto(vif, skb)) |
---|
.. | .. |
---|
3544 | 3715 | if (ieee80211_is_mgmt(hdr->frame_control)) |
---|
3545 | 3716 | cb->flags |= ATH10K_SKB_F_MGMT; |
---|
3546 | 3717 | |
---|
3547 | | - if (ieee80211_is_data_qos(hdr->frame_control)) |
---|
| 3718 | + if (ieee80211_is_data_qos(hdr->frame_control)) { |
---|
3548 | 3719 | cb->flags |= ATH10K_SKB_F_QOS; |
---|
| 3720 | + qos_ctl = ieee80211_get_qos_ctl(hdr); |
---|
| 3721 | + tid = (*qos_ctl) & IEEE80211_QOS_CTL_TID_MASK; |
---|
| 3722 | + |
---|
| 3723 | + if (arvif->noack[tid] == WMI_PEER_TID_CONFIG_NOACK) |
---|
| 3724 | + noack = true; |
---|
| 3725 | + |
---|
| 3726 | + if (sta) { |
---|
| 3727 | + arsta = (struct ath10k_sta *)sta->drv_priv; |
---|
| 3728 | + |
---|
| 3729 | + if (arsta->noack[tid] == WMI_PEER_TID_CONFIG_NOACK) |
---|
| 3730 | + noack = true; |
---|
| 3731 | + |
---|
| 3732 | + if (arsta->noack[tid] == WMI_PEER_TID_CONFIG_ACK) |
---|
| 3733 | + noack = false; |
---|
| 3734 | + } |
---|
| 3735 | + |
---|
| 3736 | + if (noack) |
---|
| 3737 | + cb->flags |= ATH10K_SKB_F_NOACK_TID; |
---|
| 3738 | + } |
---|
| 3739 | + |
---|
| 3740 | + /* Data frames encrypted in software will be posted to firmware |
---|
| 3741 | + * with tx encap mode set to RAW. Ex: Multicast traffic generated |
---|
| 3742 | + * for a specific VLAN group will always be encrypted in software. |
---|
| 3743 | + */ |
---|
| 3744 | + if (is_data && ieee80211_has_protected(hdr->frame_control) && |
---|
| 3745 | + !info->control.hw_key) { |
---|
| 3746 | + cb->flags |= ATH10K_SKB_F_NO_HWCRYPT; |
---|
| 3747 | + cb->flags |= ATH10K_SKB_F_RAW_TX; |
---|
| 3748 | + } |
---|
3549 | 3749 | |
---|
3550 | 3750 | cb->vif = vif; |
---|
3551 | 3751 | cb->txq = txq; |
---|
| 3752 | + cb->airtime_est = airtime; |
---|
| 3753 | + if (sta) { |
---|
| 3754 | + arsta = (struct ath10k_sta *)sta->drv_priv; |
---|
| 3755 | + spin_lock_bh(&ar->data_lock); |
---|
| 3756 | + cb->ucast_cipher = arsta->ucast_cipher; |
---|
| 3757 | + spin_unlock_bh(&ar->data_lock); |
---|
| 3758 | + } |
---|
3552 | 3759 | } |
---|
3553 | 3760 | |
---|
3554 | 3761 | bool ath10k_mac_tx_frm_has_freq(struct ath10k *ar) |
---|
.. | .. |
---|
3648 | 3855 | { |
---|
3649 | 3856 | struct ieee80211_hw *hw = ar->hw; |
---|
3650 | 3857 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
---|
| 3858 | + const struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb); |
---|
3651 | 3859 | int ret; |
---|
3652 | 3860 | |
---|
3653 | 3861 | /* We should disable CCK RATE due to P2P */ |
---|
.. | .. |
---|
3665 | 3873 | ath10k_tx_h_8023(skb); |
---|
3666 | 3874 | break; |
---|
3667 | 3875 | case ATH10K_HW_TXRX_RAW: |
---|
3668 | | - if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) { |
---|
| 3876 | + if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags) && |
---|
| 3877 | + !(skb_cb->flags & ATH10K_SKB_F_RAW_TX)) { |
---|
3669 | 3878 | WARN_ON_ONCE(1); |
---|
3670 | 3879 | ieee80211_free_txskb(hw, skb); |
---|
3671 | 3880 | return -ENOTSUPP; |
---|
.. | .. |
---|
3876 | 4085 | |
---|
3877 | 4086 | static void ath10k_mac_txq_unref(struct ath10k *ar, struct ieee80211_txq *txq) |
---|
3878 | 4087 | { |
---|
3879 | | - struct ath10k_txq *artxq; |
---|
3880 | 4088 | struct ath10k_skb_cb *cb; |
---|
3881 | 4089 | struct sk_buff *msdu; |
---|
3882 | 4090 | int msdu_id; |
---|
3883 | 4091 | |
---|
3884 | 4092 | if (!txq) |
---|
3885 | 4093 | return; |
---|
3886 | | - |
---|
3887 | | - artxq = (void *)txq->drv_priv; |
---|
3888 | | - spin_lock_bh(&ar->txqs_lock); |
---|
3889 | | - if (!list_empty(&artxq->list)) |
---|
3890 | | - list_del_init(&artxq->list); |
---|
3891 | | - spin_unlock_bh(&ar->txqs_lock); |
---|
3892 | 4094 | |
---|
3893 | 4095 | spin_lock_bh(&ar->htt.tx_lock); |
---|
3894 | 4096 | idr_for_each_entry(&ar->htt.pending_tx, msdu, msdu_id) { |
---|
.. | .. |
---|
3929 | 4131 | struct ath10k_txq *artxq = (void *)txq->drv_priv; |
---|
3930 | 4132 | |
---|
3931 | 4133 | /* No need to get locks */ |
---|
3932 | | - |
---|
3933 | 4134 | if (ar->htt.tx_q_state.mode == HTT_TX_MODE_SWITCH_PUSH) |
---|
3934 | 4135 | return true; |
---|
3935 | 4136 | |
---|
.. | .. |
---|
3940 | 4141 | return true; |
---|
3941 | 4142 | |
---|
3942 | 4143 | return false; |
---|
| 4144 | +} |
---|
| 4145 | + |
---|
| 4146 | +/* Return estimated airtime in microsecond, which is calculated using last |
---|
| 4147 | + * reported TX rate. This is just a rough estimation because host driver has no |
---|
| 4148 | + * knowledge of the actual transmit rate, retries or aggregation. If actual |
---|
| 4149 | + * airtime can be reported by firmware, then delta between estimated and actual |
---|
| 4150 | + * airtime can be adjusted from deficit. |
---|
| 4151 | + */ |
---|
| 4152 | +#define IEEE80211_ATF_OVERHEAD 100 /* IFS + some slot time */ |
---|
| 4153 | +#define IEEE80211_ATF_OVERHEAD_IFS 16 /* IFS only */ |
---|
| 4154 | +static u16 ath10k_mac_update_airtime(struct ath10k *ar, |
---|
| 4155 | + struct ieee80211_txq *txq, |
---|
| 4156 | + struct sk_buff *skb) |
---|
| 4157 | +{ |
---|
| 4158 | + struct ath10k_sta *arsta; |
---|
| 4159 | + u32 pktlen; |
---|
| 4160 | + u16 airtime = 0; |
---|
| 4161 | + |
---|
| 4162 | + if (!txq || !txq->sta) |
---|
| 4163 | + return airtime; |
---|
| 4164 | + |
---|
| 4165 | + if (test_bit(WMI_SERVICE_REPORT_AIRTIME, ar->wmi.svc_map)) |
---|
| 4166 | + return airtime; |
---|
| 4167 | + |
---|
| 4168 | + spin_lock_bh(&ar->data_lock); |
---|
| 4169 | + arsta = (struct ath10k_sta *)txq->sta->drv_priv; |
---|
| 4170 | + |
---|
| 4171 | + pktlen = skb->len + 38; /* Assume MAC header 30, SNAP 8 for most case */ |
---|
| 4172 | + if (arsta->last_tx_bitrate) { |
---|
| 4173 | + /* airtime in us, last_tx_bitrate in 100kbps */ |
---|
| 4174 | + airtime = (pktlen * 8 * (1000 / 100)) |
---|
| 4175 | + / arsta->last_tx_bitrate; |
---|
| 4176 | + /* overhead for media access time and IFS */ |
---|
| 4177 | + airtime += IEEE80211_ATF_OVERHEAD_IFS; |
---|
| 4178 | + } else { |
---|
| 4179 | + /* This is mostly for throttle excessive BC/MC frames, and the |
---|
| 4180 | + * airtime/rate doesn't need be exact. Airtime of BC/MC frames |
---|
| 4181 | + * in 2G get some discount, which helps prevent very low rate |
---|
| 4182 | + * frames from being blocked for too long. |
---|
| 4183 | + */ |
---|
| 4184 | + airtime = (pktlen * 8 * (1000 / 100)) / 60; /* 6M */ |
---|
| 4185 | + airtime += IEEE80211_ATF_OVERHEAD; |
---|
| 4186 | + } |
---|
| 4187 | + spin_unlock_bh(&ar->data_lock); |
---|
| 4188 | + |
---|
| 4189 | + return airtime; |
---|
3943 | 4190 | } |
---|
3944 | 4191 | |
---|
3945 | 4192 | int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw, |
---|
.. | .. |
---|
3957 | 4204 | size_t skb_len; |
---|
3958 | 4205 | bool is_mgmt, is_presp; |
---|
3959 | 4206 | int ret; |
---|
| 4207 | + u16 airtime; |
---|
3960 | 4208 | |
---|
3961 | 4209 | spin_lock_bh(&ar->htt.tx_lock); |
---|
3962 | 4210 | ret = ath10k_htt_tx_inc_pending(htt); |
---|
.. | .. |
---|
3965 | 4213 | if (ret) |
---|
3966 | 4214 | return ret; |
---|
3967 | 4215 | |
---|
3968 | | - skb = ieee80211_tx_dequeue(hw, txq); |
---|
| 4216 | + skb = ieee80211_tx_dequeue_ni(hw, txq); |
---|
3969 | 4217 | if (!skb) { |
---|
3970 | 4218 | spin_lock_bh(&ar->htt.tx_lock); |
---|
3971 | 4219 | ath10k_htt_tx_dec_pending(htt); |
---|
.. | .. |
---|
3974 | 4222 | return -ENOENT; |
---|
3975 | 4223 | } |
---|
3976 | 4224 | |
---|
3977 | | - ath10k_mac_tx_h_fill_cb(ar, vif, txq, skb); |
---|
| 4225 | + airtime = ath10k_mac_update_airtime(ar, txq, skb); |
---|
| 4226 | + ath10k_mac_tx_h_fill_cb(ar, vif, txq, sta, skb, airtime); |
---|
3978 | 4227 | |
---|
3979 | 4228 | skb_len = skb->len; |
---|
3980 | 4229 | txmode = ath10k_mac_tx_h_get_txmode(ar, vif, sta, skb); |
---|
.. | .. |
---|
4016 | 4265 | return skb_len; |
---|
4017 | 4266 | } |
---|
4018 | 4267 | |
---|
4019 | | -void ath10k_mac_tx_push_pending(struct ath10k *ar) |
---|
| 4268 | +static int ath10k_mac_schedule_txq(struct ieee80211_hw *hw, u32 ac) |
---|
4020 | 4269 | { |
---|
4021 | | - struct ieee80211_hw *hw = ar->hw; |
---|
4022 | 4270 | struct ieee80211_txq *txq; |
---|
4023 | | - struct ath10k_txq *artxq; |
---|
4024 | | - struct ath10k_txq *last; |
---|
4025 | | - int ret; |
---|
4026 | | - int max; |
---|
| 4271 | + int ret = 0; |
---|
4027 | 4272 | |
---|
4028 | | - if (ar->htt.num_pending_tx >= (ar->htt.max_num_pending_tx / 2)) |
---|
4029 | | - return; |
---|
4030 | | - |
---|
4031 | | - spin_lock_bh(&ar->txqs_lock); |
---|
4032 | | - rcu_read_lock(); |
---|
4033 | | - |
---|
4034 | | - last = list_last_entry(&ar->txqs, struct ath10k_txq, list); |
---|
4035 | | - while (!list_empty(&ar->txqs)) { |
---|
4036 | | - artxq = list_first_entry(&ar->txqs, struct ath10k_txq, list); |
---|
4037 | | - txq = container_of((void *)artxq, struct ieee80211_txq, |
---|
4038 | | - drv_priv); |
---|
4039 | | - |
---|
4040 | | - /* Prevent aggressive sta/tid taking over tx queue */ |
---|
4041 | | - max = HTC_HOST_MAX_MSG_PER_TX_BUNDLE; |
---|
4042 | | - ret = 0; |
---|
4043 | | - while (ath10k_mac_tx_can_push(hw, txq) && max--) { |
---|
| 4273 | + ieee80211_txq_schedule_start(hw, ac); |
---|
| 4274 | + while ((txq = ieee80211_next_txq(hw, ac))) { |
---|
| 4275 | + while (ath10k_mac_tx_can_push(hw, txq)) { |
---|
4044 | 4276 | ret = ath10k_mac_tx_push_txq(hw, txq); |
---|
4045 | 4277 | if (ret < 0) |
---|
4046 | 4278 | break; |
---|
4047 | 4279 | } |
---|
4048 | | - |
---|
4049 | | - list_del_init(&artxq->list); |
---|
4050 | | - if (ret != -ENOENT) |
---|
4051 | | - list_add_tail(&artxq->list, &ar->txqs); |
---|
4052 | | - |
---|
| 4280 | + ieee80211_return_txq(hw, txq, false); |
---|
4053 | 4281 | ath10k_htt_tx_txq_update(hw, txq); |
---|
4054 | | - |
---|
4055 | | - if (artxq == last || (ret < 0 && ret != -ENOENT)) |
---|
| 4282 | + if (ret == -EBUSY) |
---|
4056 | 4283 | break; |
---|
4057 | 4284 | } |
---|
| 4285 | + ieee80211_txq_schedule_end(hw, ac); |
---|
4058 | 4286 | |
---|
| 4287 | + return ret; |
---|
| 4288 | +} |
---|
| 4289 | + |
---|
| 4290 | +void ath10k_mac_tx_push_pending(struct ath10k *ar) |
---|
| 4291 | +{ |
---|
| 4292 | + struct ieee80211_hw *hw = ar->hw; |
---|
| 4293 | + u32 ac; |
---|
| 4294 | + |
---|
| 4295 | + if (ar->htt.tx_q_state.mode != HTT_TX_MODE_SWITCH_PUSH) |
---|
| 4296 | + return; |
---|
| 4297 | + |
---|
| 4298 | + if (ar->htt.num_pending_tx >= (ar->htt.max_num_pending_tx / 2)) |
---|
| 4299 | + return; |
---|
| 4300 | + |
---|
| 4301 | + rcu_read_lock(); |
---|
| 4302 | + for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { |
---|
| 4303 | + if (ath10k_mac_schedule_txq(hw, ac) == -EBUSY) |
---|
| 4304 | + break; |
---|
| 4305 | + } |
---|
4059 | 4306 | rcu_read_unlock(); |
---|
4060 | | - spin_unlock_bh(&ar->txqs_lock); |
---|
4061 | 4307 | } |
---|
4062 | 4308 | EXPORT_SYMBOL(ath10k_mac_tx_push_pending); |
---|
4063 | 4309 | |
---|
.. | .. |
---|
4084 | 4330 | } else if (ar->scan.roc_notify) { |
---|
4085 | 4331 | ieee80211_remain_on_channel_expired(ar->hw); |
---|
4086 | 4332 | } |
---|
4087 | | - /* fall through */ |
---|
| 4333 | + fallthrough; |
---|
4088 | 4334 | case ATH10K_SCAN_STARTING: |
---|
4089 | 4335 | ar->scan.state = ATH10K_SCAN_IDLE; |
---|
4090 | 4336 | ar->scan_channel = NULL; |
---|
.. | .. |
---|
4244 | 4490 | bool is_mgmt; |
---|
4245 | 4491 | bool is_presp; |
---|
4246 | 4492 | int ret; |
---|
| 4493 | + u16 airtime; |
---|
4247 | 4494 | |
---|
4248 | | - ath10k_mac_tx_h_fill_cb(ar, vif, txq, skb); |
---|
| 4495 | + airtime = ath10k_mac_update_airtime(ar, txq, skb); |
---|
| 4496 | + ath10k_mac_tx_h_fill_cb(ar, vif, txq, sta, skb, airtime); |
---|
4249 | 4497 | |
---|
4250 | 4498 | txmode = ath10k_mac_tx_h_get_txmode(ar, vif, sta, skb); |
---|
4251 | 4499 | txpath = ath10k_mac_tx_h_get_txpath(ar, skb, txmode); |
---|
.. | .. |
---|
4296 | 4544 | struct ieee80211_txq *txq) |
---|
4297 | 4545 | { |
---|
4298 | 4546 | struct ath10k *ar = hw->priv; |
---|
4299 | | - struct ath10k_txq *artxq = (void *)txq->drv_priv; |
---|
4300 | | - struct ieee80211_txq *f_txq; |
---|
4301 | | - struct ath10k_txq *f_artxq; |
---|
4302 | | - int ret = 0; |
---|
4303 | | - int max = HTC_HOST_MAX_MSG_PER_TX_BUNDLE; |
---|
| 4547 | + int ret; |
---|
| 4548 | + u8 ac; |
---|
4304 | 4549 | |
---|
4305 | | - spin_lock_bh(&ar->txqs_lock); |
---|
4306 | | - if (list_empty(&artxq->list)) |
---|
4307 | | - list_add_tail(&artxq->list, &ar->txqs); |
---|
| 4550 | + ath10k_htt_tx_txq_update(hw, txq); |
---|
| 4551 | + if (ar->htt.tx_q_state.mode != HTT_TX_MODE_SWITCH_PUSH) |
---|
| 4552 | + return; |
---|
4308 | 4553 | |
---|
4309 | | - f_artxq = list_first_entry(&ar->txqs, struct ath10k_txq, list); |
---|
4310 | | - f_txq = container_of((void *)f_artxq, struct ieee80211_txq, drv_priv); |
---|
4311 | | - list_del_init(&f_artxq->list); |
---|
| 4554 | + ac = txq->ac; |
---|
| 4555 | + ieee80211_txq_schedule_start(hw, ac); |
---|
| 4556 | + txq = ieee80211_next_txq(hw, ac); |
---|
| 4557 | + if (!txq) |
---|
| 4558 | + goto out; |
---|
4312 | 4559 | |
---|
4313 | | - while (ath10k_mac_tx_can_push(hw, f_txq) && max--) { |
---|
4314 | | - ret = ath10k_mac_tx_push_txq(hw, f_txq); |
---|
| 4560 | + while (ath10k_mac_tx_can_push(hw, txq)) { |
---|
| 4561 | + ret = ath10k_mac_tx_push_txq(hw, txq); |
---|
4315 | 4562 | if (ret < 0) |
---|
4316 | 4563 | break; |
---|
4317 | 4564 | } |
---|
4318 | | - if (ret != -ENOENT) |
---|
4319 | | - list_add_tail(&f_artxq->list, &ar->txqs); |
---|
4320 | | - spin_unlock_bh(&ar->txqs_lock); |
---|
4321 | | - |
---|
4322 | | - ath10k_htt_tx_txq_update(hw, f_txq); |
---|
| 4565 | + ieee80211_return_txq(hw, txq, false); |
---|
4323 | 4566 | ath10k_htt_tx_txq_update(hw, txq); |
---|
| 4567 | +out: |
---|
| 4568 | + ieee80211_txq_schedule_end(hw, ac); |
---|
4324 | 4569 | } |
---|
4325 | 4570 | |
---|
4326 | 4571 | /* Must not be called with conf_mutex held as workers can use that also. */ |
---|
.. | .. |
---|
4379 | 4624 | return 0; |
---|
4380 | 4625 | } |
---|
4381 | 4626 | |
---|
4382 | | -static void ath10k_check_chain_mask(struct ath10k *ar, u32 cm, const char *dbg) |
---|
| 4627 | +static bool ath10k_check_chain_mask(struct ath10k *ar, u32 cm, const char *dbg) |
---|
4383 | 4628 | { |
---|
4384 | 4629 | /* It is not clear that allowing gaps in chainmask |
---|
4385 | 4630 | * is helpful. Probably it will not do what user |
---|
4386 | 4631 | * is hoping for, so warn in that case. |
---|
4387 | 4632 | */ |
---|
4388 | 4633 | if (cm == 15 || cm == 7 || cm == 3 || cm == 1 || cm == 0) |
---|
4389 | | - return; |
---|
| 4634 | + return true; |
---|
4390 | 4635 | |
---|
4391 | | - ath10k_warn(ar, "mac %s antenna chainmask may be invalid: 0x%x. Suggested values: 15, 7, 3, 1 or 0.\n", |
---|
| 4636 | + ath10k_warn(ar, "mac %s antenna chainmask is invalid: 0x%x. Suggested values: 15, 7, 3, 1 or 0.\n", |
---|
4392 | 4637 | dbg, cm); |
---|
| 4638 | + return false; |
---|
4393 | 4639 | } |
---|
4394 | 4640 | |
---|
4395 | 4641 | static int ath10k_mac_get_vht_cap_bf_sts(struct ath10k *ar) |
---|
.. | .. |
---|
4453 | 4699 | |
---|
4454 | 4700 | vht_cap.cap |= val; |
---|
4455 | 4701 | } |
---|
4456 | | - |
---|
4457 | | - /* Currently the firmware seems to be buggy, don't enable 80+80 |
---|
4458 | | - * mode until that's resolved. |
---|
4459 | | - */ |
---|
4460 | | - if ((ar->vht_cap_info & IEEE80211_VHT_CAP_SHORT_GI_160) && |
---|
4461 | | - (ar->vht_cap_info & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) == 0) |
---|
4462 | | - vht_cap.cap |= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ; |
---|
4463 | 4702 | |
---|
4464 | 4703 | mcs_map = 0; |
---|
4465 | 4704 | for (i = 0; i < 8; i++) { |
---|
.. | .. |
---|
4535 | 4774 | ht_cap.cap |= stbc; |
---|
4536 | 4775 | } |
---|
4537 | 4776 | |
---|
4538 | | - if (ar->ht_cap_info & WMI_HT_CAP_LDPC) |
---|
| 4777 | + if (ar->ht_cap_info & WMI_HT_CAP_LDPC || (ar->ht_cap_info & |
---|
| 4778 | + WMI_HT_CAP_RX_LDPC && (ar->ht_cap_info & WMI_HT_CAP_TX_LDPC))) |
---|
4539 | 4779 | ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING; |
---|
4540 | 4780 | |
---|
4541 | 4781 | if (ar->ht_cap_info & WMI_HT_CAP_L_SIG_TXOP_PROT) |
---|
.. | .. |
---|
4578 | 4818 | static int __ath10k_set_antenna(struct ath10k *ar, u32 tx_ant, u32 rx_ant) |
---|
4579 | 4819 | { |
---|
4580 | 4820 | int ret; |
---|
| 4821 | + bool is_valid_tx_chain_mask, is_valid_rx_chain_mask; |
---|
4581 | 4822 | |
---|
4582 | 4823 | lockdep_assert_held(&ar->conf_mutex); |
---|
4583 | 4824 | |
---|
4584 | | - ath10k_check_chain_mask(ar, tx_ant, "tx"); |
---|
4585 | | - ath10k_check_chain_mask(ar, rx_ant, "rx"); |
---|
| 4825 | + is_valid_tx_chain_mask = ath10k_check_chain_mask(ar, tx_ant, "tx"); |
---|
| 4826 | + is_valid_rx_chain_mask = ath10k_check_chain_mask(ar, rx_ant, "rx"); |
---|
| 4827 | + |
---|
| 4828 | + if (!is_valid_tx_chain_mask || !is_valid_rx_chain_mask) |
---|
| 4829 | + return -EINVAL; |
---|
4586 | 4830 | |
---|
4587 | 4831 | ar->cfg_tx_chainmask = tx_ant; |
---|
4588 | 4832 | ar->cfg_rx_chainmask = rx_ant; |
---|
.. | .. |
---|
4624 | 4868 | return ret; |
---|
4625 | 4869 | } |
---|
4626 | 4870 | |
---|
| 4871 | +static int __ath10k_fetch_bb_timing_dt(struct ath10k *ar, |
---|
| 4872 | + struct wmi_bb_timing_cfg_arg *bb_timing) |
---|
| 4873 | +{ |
---|
| 4874 | + struct device_node *node; |
---|
| 4875 | + const char *fem_name; |
---|
| 4876 | + int ret; |
---|
| 4877 | + |
---|
| 4878 | + node = ar->dev->of_node; |
---|
| 4879 | + if (!node) |
---|
| 4880 | + return -ENOENT; |
---|
| 4881 | + |
---|
| 4882 | + ret = of_property_read_string_index(node, "ext-fem-name", 0, &fem_name); |
---|
| 4883 | + if (ret) |
---|
| 4884 | + return -ENOENT; |
---|
| 4885 | + |
---|
| 4886 | + /* |
---|
| 4887 | + * If external Front End module used in hardware, then default base band timing |
---|
| 4888 | + * parameter cannot be used since they were fine tuned for reference hardware, |
---|
| 4889 | + * so choosing different value suitable for that external FEM. |
---|
| 4890 | + */ |
---|
| 4891 | + if (!strcmp("microsemi-lx5586", fem_name)) { |
---|
| 4892 | + bb_timing->bb_tx_timing = 0x00; |
---|
| 4893 | + bb_timing->bb_xpa_timing = 0x0101; |
---|
| 4894 | + } else { |
---|
| 4895 | + return -ENOENT; |
---|
| 4896 | + } |
---|
| 4897 | + |
---|
| 4898 | + ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot bb_tx_timing 0x%x bb_xpa_timing 0x%x\n", |
---|
| 4899 | + bb_timing->bb_tx_timing, bb_timing->bb_xpa_timing); |
---|
| 4900 | + return 0; |
---|
| 4901 | +} |
---|
| 4902 | + |
---|
| 4903 | +static int ath10k_mac_rfkill_config(struct ath10k *ar) |
---|
| 4904 | +{ |
---|
| 4905 | + u32 param; |
---|
| 4906 | + int ret; |
---|
| 4907 | + |
---|
| 4908 | + if (ar->hw_values->rfkill_pin == 0) { |
---|
| 4909 | + ath10k_warn(ar, "ath10k does not support hardware rfkill with this device\n"); |
---|
| 4910 | + return -EOPNOTSUPP; |
---|
| 4911 | + } |
---|
| 4912 | + |
---|
| 4913 | + ath10k_dbg(ar, ATH10K_DBG_MAC, |
---|
| 4914 | + "mac rfkill_pin %d rfkill_cfg %d rfkill_on_level %d", |
---|
| 4915 | + ar->hw_values->rfkill_pin, ar->hw_values->rfkill_cfg, |
---|
| 4916 | + ar->hw_values->rfkill_on_level); |
---|
| 4917 | + |
---|
| 4918 | + param = FIELD_PREP(WMI_TLV_RFKILL_CFG_RADIO_LEVEL, |
---|
| 4919 | + ar->hw_values->rfkill_on_level) | |
---|
| 4920 | + FIELD_PREP(WMI_TLV_RFKILL_CFG_GPIO_PIN_NUM, |
---|
| 4921 | + ar->hw_values->rfkill_pin) | |
---|
| 4922 | + FIELD_PREP(WMI_TLV_RFKILL_CFG_PIN_AS_GPIO, |
---|
| 4923 | + ar->hw_values->rfkill_cfg); |
---|
| 4924 | + |
---|
| 4925 | + ret = ath10k_wmi_pdev_set_param(ar, |
---|
| 4926 | + ar->wmi.pdev_param->rfkill_config, |
---|
| 4927 | + param); |
---|
| 4928 | + if (ret) { |
---|
| 4929 | + ath10k_warn(ar, |
---|
| 4930 | + "failed to set rfkill config 0x%x: %d\n", |
---|
| 4931 | + param, ret); |
---|
| 4932 | + return ret; |
---|
| 4933 | + } |
---|
| 4934 | + return 0; |
---|
| 4935 | +} |
---|
| 4936 | + |
---|
| 4937 | +int ath10k_mac_rfkill_enable_radio(struct ath10k *ar, bool enable) |
---|
| 4938 | +{ |
---|
| 4939 | + enum wmi_tlv_rfkill_enable_radio param; |
---|
| 4940 | + int ret; |
---|
| 4941 | + |
---|
| 4942 | + if (enable) |
---|
| 4943 | + param = WMI_TLV_RFKILL_ENABLE_RADIO_ON; |
---|
| 4944 | + else |
---|
| 4945 | + param = WMI_TLV_RFKILL_ENABLE_RADIO_OFF; |
---|
| 4946 | + |
---|
| 4947 | + ath10k_dbg(ar, ATH10K_DBG_MAC, "mac rfkill enable %d", param); |
---|
| 4948 | + |
---|
| 4949 | + ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->rfkill_enable, |
---|
| 4950 | + param); |
---|
| 4951 | + if (ret) { |
---|
| 4952 | + ath10k_warn(ar, "failed to set rfkill enable param %d: %d\n", |
---|
| 4953 | + param, ret); |
---|
| 4954 | + return ret; |
---|
| 4955 | + } |
---|
| 4956 | + |
---|
| 4957 | + return 0; |
---|
| 4958 | +} |
---|
| 4959 | + |
---|
4627 | 4960 | static int ath10k_start(struct ieee80211_hw *hw) |
---|
4628 | 4961 | { |
---|
4629 | 4962 | struct ath10k *ar = hw->priv; |
---|
4630 | 4963 | u32 param; |
---|
4631 | 4964 | int ret = 0; |
---|
| 4965 | + struct wmi_bb_timing_cfg_arg bb_timing = {0}; |
---|
4632 | 4966 | |
---|
4633 | 4967 | /* |
---|
4634 | 4968 | * This makes sense only when restarting hw. It is harmless to call |
---|
.. | .. |
---|
4657 | 4991 | goto err; |
---|
4658 | 4992 | } |
---|
4659 | 4993 | |
---|
4660 | | - ret = ath10k_hif_power_up(ar); |
---|
| 4994 | + spin_lock_bh(&ar->data_lock); |
---|
| 4995 | + |
---|
| 4996 | + if (ar->hw_rfkill_on) { |
---|
| 4997 | + ar->hw_rfkill_on = false; |
---|
| 4998 | + spin_unlock_bh(&ar->data_lock); |
---|
| 4999 | + goto err; |
---|
| 5000 | + } |
---|
| 5001 | + |
---|
| 5002 | + spin_unlock_bh(&ar->data_lock); |
---|
| 5003 | + |
---|
| 5004 | + ret = ath10k_hif_power_up(ar, ATH10K_FIRMWARE_MODE_NORMAL); |
---|
4661 | 5005 | if (ret) { |
---|
4662 | 5006 | ath10k_err(ar, "Could not init hif: %d\n", ret); |
---|
4663 | 5007 | goto err_off; |
---|
.. | .. |
---|
4668 | 5012 | if (ret) { |
---|
4669 | 5013 | ath10k_err(ar, "Could not init core: %d\n", ret); |
---|
4670 | 5014 | goto err_power_down; |
---|
| 5015 | + } |
---|
| 5016 | + |
---|
| 5017 | + if (ar->sys_cap_info & WMI_TLV_SYS_CAP_INFO_RFKILL) { |
---|
| 5018 | + ret = ath10k_mac_rfkill_config(ar); |
---|
| 5019 | + if (ret && ret != -EOPNOTSUPP) { |
---|
| 5020 | + ath10k_warn(ar, "failed to configure rfkill: %d", ret); |
---|
| 5021 | + goto err_core_stop; |
---|
| 5022 | + } |
---|
4671 | 5023 | } |
---|
4672 | 5024 | |
---|
4673 | 5025 | param = ar->wmi.pdev_param->pmf_qos; |
---|
.. | .. |
---|
4773 | 5125 | param = ar->wmi.pdev_param->enable_btcoex; |
---|
4774 | 5126 | if (test_bit(WMI_SERVICE_COEX_GPIO, ar->wmi.svc_map) && |
---|
4775 | 5127 | test_bit(ATH10K_FW_FEATURE_BTCOEX_PARAM, |
---|
4776 | | - ar->running_fw->fw_file.fw_features)) { |
---|
| 5128 | + ar->running_fw->fw_file.fw_features) && |
---|
| 5129 | + ar->coex_support) { |
---|
4777 | 5130 | ret = ath10k_wmi_pdev_set_param(ar, param, 0); |
---|
4778 | 5131 | if (ret) { |
---|
4779 | 5132 | ath10k_warn(ar, |
---|
.. | .. |
---|
4781 | 5134 | goto err_core_stop; |
---|
4782 | 5135 | } |
---|
4783 | 5136 | clear_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags); |
---|
| 5137 | + } |
---|
| 5138 | + |
---|
| 5139 | + if (test_bit(WMI_SERVICE_BB_TIMING_CONFIG_SUPPORT, ar->wmi.svc_map)) { |
---|
| 5140 | + ret = __ath10k_fetch_bb_timing_dt(ar, &bb_timing); |
---|
| 5141 | + if (!ret) { |
---|
| 5142 | + ret = ath10k_wmi_pdev_bb_timing(ar, &bb_timing); |
---|
| 5143 | + if (ret) { |
---|
| 5144 | + ath10k_warn(ar, |
---|
| 5145 | + "failed to set bb timings: %d\n", |
---|
| 5146 | + ret); |
---|
| 5147 | + goto err_core_stop; |
---|
| 5148 | + } |
---|
| 5149 | + } |
---|
4784 | 5150 | } |
---|
4785 | 5151 | |
---|
4786 | 5152 | ar->num_started_vdevs = 0; |
---|
.. | .. |
---|
4811 | 5177 | static void ath10k_stop(struct ieee80211_hw *hw) |
---|
4812 | 5178 | { |
---|
4813 | 5179 | struct ath10k *ar = hw->priv; |
---|
| 5180 | + u32 opt; |
---|
4814 | 5181 | |
---|
4815 | 5182 | ath10k_drain_tx(ar); |
---|
4816 | 5183 | |
---|
4817 | 5184 | mutex_lock(&ar->conf_mutex); |
---|
4818 | 5185 | if (ar->state != ATH10K_STATE_OFF) { |
---|
4819 | | - ath10k_halt(ar); |
---|
| 5186 | + if (!ar->hw_rfkill_on) { |
---|
| 5187 | + /* If the current driver state is RESTARTING but not yet |
---|
| 5188 | + * fully RESTARTED because of incoming suspend event, |
---|
| 5189 | + * then ath10k_halt() is already called via |
---|
| 5190 | + * ath10k_core_restart() and should not be called here. |
---|
| 5191 | + */ |
---|
| 5192 | + if (ar->state != ATH10K_STATE_RESTARTING) { |
---|
| 5193 | + ath10k_halt(ar); |
---|
| 5194 | + } else { |
---|
| 5195 | + /* Suspending here, because when in RESTARTING |
---|
| 5196 | + * state, ath10k_core_stop() skips |
---|
| 5197 | + * ath10k_wait_for_suspend(). |
---|
| 5198 | + */ |
---|
| 5199 | + opt = WMI_PDEV_SUSPEND_AND_DISABLE_INTR; |
---|
| 5200 | + ath10k_wait_for_suspend(ar, opt); |
---|
| 5201 | + } |
---|
| 5202 | + } |
---|
4820 | 5203 | ar->state = ATH10K_STATE_OFF; |
---|
4821 | 5204 | } |
---|
4822 | 5205 | mutex_unlock(&ar->conf_mutex); |
---|
.. | .. |
---|
4880 | 5263 | lockdep_assert_held(&ar->conf_mutex); |
---|
4881 | 5264 | |
---|
4882 | 5265 | list_for_each_entry(arvif, &ar->arvifs, list) { |
---|
4883 | | - if (arvif->txpower <= 0) |
---|
| 5266 | + /* txpower not initialized yet? */ |
---|
| 5267 | + if (arvif->txpower == INT_MIN) |
---|
4884 | 5268 | continue; |
---|
4885 | 5269 | |
---|
4886 | 5270 | if (txpower == -1) |
---|
.. | .. |
---|
5109 | 5493 | if (vif->type == NL80211_IFTYPE_ADHOC || |
---|
5110 | 5494 | vif->type == NL80211_IFTYPE_MESH_POINT || |
---|
5111 | 5495 | vif->type == NL80211_IFTYPE_AP) { |
---|
5112 | | - arvif->beacon_buf = dma_zalloc_coherent(ar->dev, |
---|
5113 | | - IEEE80211_MAX_FRAME_LEN, |
---|
5114 | | - &arvif->beacon_paddr, |
---|
5115 | | - GFP_ATOMIC); |
---|
| 5496 | + if (ar->bus_param.dev_type == ATH10K_DEV_TYPE_HL) { |
---|
| 5497 | + arvif->beacon_buf = kmalloc(IEEE80211_MAX_FRAME_LEN, |
---|
| 5498 | + GFP_KERNEL); |
---|
| 5499 | + |
---|
| 5500 | + /* Using a kernel pointer in place of a dma_addr_t |
---|
| 5501 | + * token can lead to undefined behavior if that |
---|
| 5502 | + * makes it into cache management functions. Use a |
---|
| 5503 | + * known-invalid address token instead, which |
---|
| 5504 | + * avoids the warning and makes it easier to catch |
---|
| 5505 | + * bugs if it does end up getting used. |
---|
| 5506 | + */ |
---|
| 5507 | + arvif->beacon_paddr = DMA_MAPPING_ERROR; |
---|
| 5508 | + } else { |
---|
| 5509 | + arvif->beacon_buf = |
---|
| 5510 | + dma_alloc_coherent(ar->dev, |
---|
| 5511 | + IEEE80211_MAX_FRAME_LEN, |
---|
| 5512 | + &arvif->beacon_paddr, |
---|
| 5513 | + GFP_ATOMIC); |
---|
| 5514 | + } |
---|
5116 | 5515 | if (!arvif->beacon_buf) { |
---|
5117 | 5516 | ret = -ENOMEM; |
---|
5118 | 5517 | ath10k_warn(ar, "failed to allocate beacon buffer: %d\n", |
---|
.. | .. |
---|
5140 | 5539 | ath10k_warn(ar, "failed to create WMI vdev %i: %d\n", |
---|
5141 | 5540 | arvif->vdev_id, ret); |
---|
5142 | 5541 | goto err; |
---|
| 5542 | + } |
---|
| 5543 | + |
---|
| 5544 | + if (test_bit(WMI_SERVICE_VDEV_DISABLE_4_ADDR_SRC_LRN_SUPPORT, |
---|
| 5545 | + ar->wmi.svc_map)) { |
---|
| 5546 | + vdev_param = ar->wmi.vdev_param->disable_4addr_src_lrn; |
---|
| 5547 | + ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, |
---|
| 5548 | + WMI_VDEV_DISABLE_4_ADDR_SRC_LRN); |
---|
| 5549 | + if (ret && ret != -EOPNOTSUPP) { |
---|
| 5550 | + ath10k_warn(ar, "failed to disable 4addr src lrn vdev %i: %d\n", |
---|
| 5551 | + arvif->vdev_id, ret); |
---|
| 5552 | + } |
---|
5143 | 5553 | } |
---|
5144 | 5554 | |
---|
5145 | 5555 | ar->free_vdev_map &= ~(1LL << arvif->vdev_id); |
---|
.. | .. |
---|
5271 | 5681 | goto err_peer_delete; |
---|
5272 | 5682 | } |
---|
5273 | 5683 | |
---|
| 5684 | + if (test_bit(WMI_SERVICE_RTT_RESPONDER_ROLE, ar->wmi.svc_map)) { |
---|
| 5685 | + vdev_param = ar->wmi.vdev_param->rtt_responder_role; |
---|
| 5686 | + ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, |
---|
| 5687 | + arvif->ftm_responder); |
---|
| 5688 | + |
---|
| 5689 | + /* It is harmless to not set FTM role. Do not warn */ |
---|
| 5690 | + if (ret && ret != -EOPNOTSUPP) |
---|
| 5691 | + ath10k_warn(ar, "failed to set vdev %i FTM Responder: %d\n", |
---|
| 5692 | + arvif->vdev_id, ret); |
---|
| 5693 | + } |
---|
| 5694 | + |
---|
5274 | 5695 | if (vif->type == NL80211_IFTYPE_MONITOR) { |
---|
5275 | 5696 | ar->monitor_arvif = arvif; |
---|
5276 | 5697 | ret = ath10k_monitor_recalc(ar); |
---|
.. | .. |
---|
5290 | 5711 | |
---|
5291 | 5712 | err_peer_delete: |
---|
5292 | 5713 | if (arvif->vdev_type == WMI_VDEV_TYPE_AP || |
---|
5293 | | - arvif->vdev_type == WMI_VDEV_TYPE_IBSS) |
---|
| 5714 | + arvif->vdev_type == WMI_VDEV_TYPE_IBSS) { |
---|
5294 | 5715 | ath10k_wmi_peer_delete(ar, arvif->vdev_id, vif->addr); |
---|
| 5716 | + ath10k_wait_for_peer_delete_done(ar, arvif->vdev_id, |
---|
| 5717 | + vif->addr); |
---|
| 5718 | + } |
---|
5295 | 5719 | |
---|
5296 | 5720 | err_vdev_delete: |
---|
5297 | 5721 | ath10k_wmi_vdev_delete(ar, arvif->vdev_id); |
---|
.. | .. |
---|
5302 | 5726 | |
---|
5303 | 5727 | err: |
---|
5304 | 5728 | if (arvif->beacon_buf) { |
---|
5305 | | - dma_free_coherent(ar->dev, IEEE80211_MAX_FRAME_LEN, |
---|
5306 | | - arvif->beacon_buf, arvif->beacon_paddr); |
---|
| 5729 | + if (ar->bus_param.dev_type == ATH10K_DEV_TYPE_HL) |
---|
| 5730 | + kfree(arvif->beacon_buf); |
---|
| 5731 | + else |
---|
| 5732 | + dma_free_coherent(ar->dev, IEEE80211_MAX_FRAME_LEN, |
---|
| 5733 | + arvif->beacon_buf, |
---|
| 5734 | + arvif->beacon_paddr); |
---|
5307 | 5735 | arvif->beacon_buf = NULL; |
---|
5308 | 5736 | } |
---|
5309 | 5737 | |
---|
.. | .. |
---|
5326 | 5754 | struct ath10k *ar = hw->priv; |
---|
5327 | 5755 | struct ath10k_vif *arvif = (void *)vif->drv_priv; |
---|
5328 | 5756 | struct ath10k_peer *peer; |
---|
| 5757 | + unsigned long time_left; |
---|
5329 | 5758 | int ret; |
---|
5330 | 5759 | int i; |
---|
5331 | 5760 | |
---|
.. | .. |
---|
5333 | 5762 | cancel_delayed_work_sync(&arvif->connection_loss_work); |
---|
5334 | 5763 | |
---|
5335 | 5764 | mutex_lock(&ar->conf_mutex); |
---|
5336 | | - |
---|
5337 | | - spin_lock_bh(&ar->data_lock); |
---|
5338 | | - ath10k_mac_vif_beacon_cleanup(arvif); |
---|
5339 | | - spin_unlock_bh(&ar->data_lock); |
---|
5340 | 5765 | |
---|
5341 | 5766 | ret = ath10k_spectral_vif_stop(arvif); |
---|
5342 | 5767 | if (ret) |
---|
.. | .. |
---|
5356 | 5781 | ath10k_warn(ar, "failed to submit AP/IBSS self-peer removal on vdev %i: %d\n", |
---|
5357 | 5782 | arvif->vdev_id, ret); |
---|
5358 | 5783 | |
---|
| 5784 | + ath10k_wait_for_peer_delete_done(ar, arvif->vdev_id, |
---|
| 5785 | + vif->addr); |
---|
5359 | 5786 | kfree(arvif->u.ap.noa_data); |
---|
5360 | 5787 | } |
---|
5361 | 5788 | |
---|
.. | .. |
---|
5366 | 5793 | if (ret) |
---|
5367 | 5794 | ath10k_warn(ar, "failed to delete WMI vdev %i: %d\n", |
---|
5368 | 5795 | arvif->vdev_id, ret); |
---|
| 5796 | + |
---|
| 5797 | + if (test_bit(WMI_SERVICE_SYNC_DELETE_CMDS, ar->wmi.svc_map)) { |
---|
| 5798 | + time_left = wait_for_completion_timeout(&ar->vdev_delete_done, |
---|
| 5799 | + ATH10K_VDEV_DELETE_TIMEOUT_HZ); |
---|
| 5800 | + if (time_left == 0) { |
---|
| 5801 | + ath10k_warn(ar, "Timeout in receiving vdev delete response\n"); |
---|
| 5802 | + goto out; |
---|
| 5803 | + } |
---|
| 5804 | + } |
---|
5369 | 5805 | |
---|
5370 | 5806 | /* Some firmware revisions don't notify host about self-peer removal |
---|
5371 | 5807 | * until after associated vdev is deleted. |
---|
.. | .. |
---|
5395 | 5831 | peer->vif = NULL; |
---|
5396 | 5832 | } |
---|
5397 | 5833 | } |
---|
| 5834 | + |
---|
| 5835 | + /* Clean this up late, less opportunity for firmware to access |
---|
| 5836 | + * DMA memory we have deleted. |
---|
| 5837 | + */ |
---|
| 5838 | + ath10k_mac_vif_beacon_cleanup(arvif); |
---|
5398 | 5839 | spin_unlock_bh(&ar->data_lock); |
---|
5399 | 5840 | |
---|
5400 | 5841 | ath10k_peer_cleanup(ar, arvif->vdev_id); |
---|
.. | .. |
---|
5417 | 5858 | |
---|
5418 | 5859 | ath10k_mac_txq_unref(ar, vif->txq); |
---|
5419 | 5860 | |
---|
| 5861 | +out: |
---|
5420 | 5862 | mutex_unlock(&ar->conf_mutex); |
---|
5421 | 5863 | } |
---|
5422 | 5864 | |
---|
.. | .. |
---|
5453 | 5895 | mutex_unlock(&ar->conf_mutex); |
---|
5454 | 5896 | } |
---|
5455 | 5897 | |
---|
| 5898 | +static void ath10k_recalculate_mgmt_rate(struct ath10k *ar, |
---|
| 5899 | + struct ieee80211_vif *vif, |
---|
| 5900 | + struct cfg80211_chan_def *def) |
---|
| 5901 | +{ |
---|
| 5902 | + struct ath10k_vif *arvif = (void *)vif->drv_priv; |
---|
| 5903 | + const struct ieee80211_supported_band *sband; |
---|
| 5904 | + u8 basic_rate_idx; |
---|
| 5905 | + int hw_rate_code; |
---|
| 5906 | + u32 vdev_param; |
---|
| 5907 | + u16 bitrate; |
---|
| 5908 | + int ret; |
---|
| 5909 | + |
---|
| 5910 | + lockdep_assert_held(&ar->conf_mutex); |
---|
| 5911 | + |
---|
| 5912 | + sband = ar->hw->wiphy->bands[def->chan->band]; |
---|
| 5913 | + basic_rate_idx = ffs(vif->bss_conf.basic_rates) - 1; |
---|
| 5914 | + bitrate = sband->bitrates[basic_rate_idx].bitrate; |
---|
| 5915 | + |
---|
| 5916 | + hw_rate_code = ath10k_mac_get_rate_hw_value(bitrate); |
---|
| 5917 | + if (hw_rate_code < 0) { |
---|
| 5918 | + ath10k_warn(ar, "bitrate not supported %d\n", bitrate); |
---|
| 5919 | + return; |
---|
| 5920 | + } |
---|
| 5921 | + |
---|
| 5922 | + vdev_param = ar->wmi.vdev_param->mgmt_rate; |
---|
| 5923 | + ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, |
---|
| 5924 | + hw_rate_code); |
---|
| 5925 | + if (ret) |
---|
| 5926 | + ath10k_warn(ar, "failed to set mgmt tx rate %d\n", ret); |
---|
| 5927 | +} |
---|
| 5928 | + |
---|
5456 | 5929 | static void ath10k_bss_info_changed(struct ieee80211_hw *hw, |
---|
5457 | 5930 | struct ieee80211_vif *vif, |
---|
5458 | 5931 | struct ieee80211_bss_conf *info, |
---|
.. | .. |
---|
5463 | 5936 | struct cfg80211_chan_def def; |
---|
5464 | 5937 | u32 vdev_param, pdev_param, slottime, preamble; |
---|
5465 | 5938 | u16 bitrate, hw_value; |
---|
5466 | | - u8 rate; |
---|
5467 | | - int rateidx, ret = 0; |
---|
| 5939 | + u8 rate, rateidx; |
---|
| 5940 | + int ret = 0, mcast_rate; |
---|
5468 | 5941 | enum nl80211_band band; |
---|
5469 | 5942 | |
---|
5470 | 5943 | mutex_lock(&ar->conf_mutex); |
---|
.. | .. |
---|
5543 | 6016 | |
---|
5544 | 6017 | if (changed & BSS_CHANGED_BSSID && !is_zero_ether_addr(info->bssid)) |
---|
5545 | 6018 | ether_addr_copy(arvif->bssid, info->bssid); |
---|
| 6019 | + |
---|
| 6020 | + if (changed & BSS_CHANGED_FTM_RESPONDER && |
---|
| 6021 | + arvif->ftm_responder != info->ftm_responder && |
---|
| 6022 | + test_bit(WMI_SERVICE_RTT_RESPONDER_ROLE, ar->wmi.svc_map)) { |
---|
| 6023 | + arvif->ftm_responder = info->ftm_responder; |
---|
| 6024 | + |
---|
| 6025 | + vdev_param = ar->wmi.vdev_param->rtt_responder_role; |
---|
| 6026 | + ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, |
---|
| 6027 | + arvif->ftm_responder); |
---|
| 6028 | + |
---|
| 6029 | + ath10k_dbg(ar, ATH10K_DBG_MAC, |
---|
| 6030 | + "mac vdev %d ftm_responder %d:ret %d\n", |
---|
| 6031 | + arvif->vdev_id, arvif->ftm_responder, ret); |
---|
| 6032 | + } |
---|
5546 | 6033 | |
---|
5547 | 6034 | if (changed & BSS_CHANGED_BEACON_ENABLED) |
---|
5548 | 6035 | ath10k_control_beaconing(arvif, info); |
---|
.. | .. |
---|
5636 | 6123 | if (changed & BSS_CHANGED_MCAST_RATE && |
---|
5637 | 6124 | !ath10k_mac_vif_chan(arvif->vif, &def)) { |
---|
5638 | 6125 | band = def.chan->band; |
---|
5639 | | - rateidx = vif->bss_conf.mcast_rate[band] - 1; |
---|
| 6126 | + mcast_rate = vif->bss_conf.mcast_rate[band]; |
---|
| 6127 | + if (mcast_rate > 0) |
---|
| 6128 | + rateidx = mcast_rate - 1; |
---|
| 6129 | + else |
---|
| 6130 | + rateidx = ffs(vif->bss_conf.basic_rates) - 1; |
---|
5640 | 6131 | |
---|
5641 | 6132 | if (ar->phy_capability & WHAL_WLAN_11A_CAPABILITY) |
---|
5642 | 6133 | rateidx += ATH10K_MAC_FIRST_OFDM_RATE_IDX; |
---|
.. | .. |
---|
5670 | 6161 | "failed to set bcast rate on vdev %i: %d\n", |
---|
5671 | 6162 | arvif->vdev_id, ret); |
---|
5672 | 6163 | } |
---|
| 6164 | + |
---|
| 6165 | + if (changed & BSS_CHANGED_BASIC_RATES && |
---|
| 6166 | + !ath10k_mac_vif_chan(arvif->vif, &def)) |
---|
| 6167 | + ath10k_recalculate_mgmt_rate(ar, vif, &def); |
---|
5673 | 6168 | |
---|
5674 | 6169 | mutex_unlock(&ar->conf_mutex); |
---|
5675 | 6170 | } |
---|
.. | .. |
---|
5715 | 6210 | ath10k_mac_tdls_vif_stations_count_iter, |
---|
5716 | 6211 | &data); |
---|
5717 | 6212 | return data.num_tdls_stations; |
---|
5718 | | -} |
---|
5719 | | - |
---|
5720 | | -static void ath10k_mac_tdls_vifs_count_iter(void *data, u8 *mac, |
---|
5721 | | - struct ieee80211_vif *vif) |
---|
5722 | | -{ |
---|
5723 | | - struct ath10k_vif *arvif = (void *)vif->drv_priv; |
---|
5724 | | - int *num_tdls_vifs = data; |
---|
5725 | | - |
---|
5726 | | - if (vif->type != NL80211_IFTYPE_STATION) |
---|
5727 | | - return; |
---|
5728 | | - |
---|
5729 | | - if (ath10k_mac_tdls_vif_stations_count(arvif->ar->hw, vif) > 0) |
---|
5730 | | - (*num_tdls_vifs)++; |
---|
5731 | | -} |
---|
5732 | | - |
---|
5733 | | -static int ath10k_mac_tdls_vifs_count(struct ieee80211_hw *hw) |
---|
5734 | | -{ |
---|
5735 | | - int num_tdls_vifs = 0; |
---|
5736 | | - |
---|
5737 | | - ieee80211_iterate_active_interfaces_atomic(hw, |
---|
5738 | | - IEEE80211_IFACE_ITER_NORMAL, |
---|
5739 | | - ath10k_mac_tdls_vifs_count_iter, |
---|
5740 | | - &num_tdls_vifs); |
---|
5741 | | - return num_tdls_vifs; |
---|
5742 | 6213 | } |
---|
5743 | 6214 | |
---|
5744 | 6215 | static int ath10k_hw_scan(struct ieee80211_hw *hw, |
---|
.. | .. |
---|
5905 | 6376 | { |
---|
5906 | 6377 | struct ath10k *ar = hw->priv; |
---|
5907 | 6378 | struct ath10k_vif *arvif = (void *)vif->drv_priv; |
---|
| 6379 | + struct ath10k_sta *arsta; |
---|
5908 | 6380 | struct ath10k_peer *peer; |
---|
5909 | 6381 | const u8 *peer_addr; |
---|
5910 | 6382 | bool is_wep = key->cipher == WLAN_CIPHER_SUITE_WEP40 || |
---|
.. | .. |
---|
5929 | 6401 | |
---|
5930 | 6402 | mutex_lock(&ar->conf_mutex); |
---|
5931 | 6403 | |
---|
5932 | | - if (sta) |
---|
| 6404 | + if (sta) { |
---|
| 6405 | + arsta = (struct ath10k_sta *)sta->drv_priv; |
---|
5933 | 6406 | peer_addr = sta->addr; |
---|
5934 | | - else if (arvif->vdev_type == WMI_VDEV_TYPE_STA) |
---|
| 6407 | + spin_lock_bh(&ar->data_lock); |
---|
| 6408 | + arsta->ucast_cipher = key->cipher; |
---|
| 6409 | + spin_unlock_bh(&ar->data_lock); |
---|
| 6410 | + } else if (arvif->vdev_type == WMI_VDEV_TYPE_STA) { |
---|
5935 | 6411 | peer_addr = vif->bss_conf.bssid; |
---|
5936 | | - else |
---|
| 6412 | + } else { |
---|
5937 | 6413 | peer_addr = vif->addr; |
---|
| 6414 | + } |
---|
5938 | 6415 | |
---|
5939 | 6416 | key->hw_key_idx = key->keyidx; |
---|
5940 | 6417 | |
---|
.. | .. |
---|
6038 | 6515 | |
---|
6039 | 6516 | if (sta && sta->tdls) |
---|
6040 | 6517 | ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr, |
---|
6041 | | - WMI_PEER_AUTHORIZE, 1); |
---|
| 6518 | + ar->wmi.peer_param->authorize, 1); |
---|
| 6519 | + else if (sta && cmd == SET_KEY && (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) |
---|
| 6520 | + ath10k_wmi_peer_set_param(ar, arvif->vdev_id, peer_addr, |
---|
| 6521 | + ar->wmi.peer_param->authorize, 1); |
---|
6042 | 6522 | |
---|
6043 | 6523 | exit: |
---|
6044 | 6524 | mutex_unlock(&ar->conf_mutex); |
---|
.. | .. |
---|
6129 | 6609 | sta->addr, bw, mode); |
---|
6130 | 6610 | |
---|
6131 | 6611 | err = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr, |
---|
6132 | | - WMI_PEER_PHYMODE, mode); |
---|
| 6612 | + ar->wmi.peer_param->phymode, mode); |
---|
6133 | 6613 | if (err) { |
---|
6134 | 6614 | ath10k_warn(ar, "failed to update STA %pM peer phymode %d: %d\n", |
---|
6135 | 6615 | sta->addr, mode, err); |
---|
.. | .. |
---|
6137 | 6617 | } |
---|
6138 | 6618 | |
---|
6139 | 6619 | err = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr, |
---|
6140 | | - WMI_PEER_CHAN_WIDTH, bw); |
---|
| 6620 | + ar->wmi.peer_param->chan_width, bw); |
---|
6141 | 6621 | if (err) |
---|
6142 | 6622 | ath10k_warn(ar, "failed to update STA %pM peer bw %d: %d\n", |
---|
6143 | 6623 | sta->addr, bw, err); |
---|
.. | .. |
---|
6148 | 6628 | sta->addr, nss); |
---|
6149 | 6629 | |
---|
6150 | 6630 | err = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr, |
---|
6151 | | - WMI_PEER_NSS, nss); |
---|
| 6631 | + ar->wmi.peer_param->nss, nss); |
---|
6152 | 6632 | if (err) |
---|
6153 | 6633 | ath10k_warn(ar, "failed to update STA %pM nss %d: %d\n", |
---|
6154 | 6634 | sta->addr, nss, err); |
---|
.. | .. |
---|
6159 | 6639 | sta->addr, smps); |
---|
6160 | 6640 | |
---|
6161 | 6641 | err = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr, |
---|
6162 | | - WMI_PEER_SMPS_STATE, smps); |
---|
| 6642 | + ar->wmi.peer_param->smps_state, smps); |
---|
6163 | 6643 | if (err) |
---|
6164 | 6644 | ath10k_warn(ar, "failed to update STA %pM smps %d: %d\n", |
---|
6165 | 6645 | sta->addr, smps, err); |
---|
.. | .. |
---|
6210 | 6690 | ar->num_stations--; |
---|
6211 | 6691 | } |
---|
6212 | 6692 | |
---|
| 6693 | +static int ath10k_sta_set_txpwr(struct ieee80211_hw *hw, |
---|
| 6694 | + struct ieee80211_vif *vif, |
---|
| 6695 | + struct ieee80211_sta *sta) |
---|
| 6696 | +{ |
---|
| 6697 | + struct ath10k *ar = hw->priv; |
---|
| 6698 | + struct ath10k_vif *arvif = (void *)vif->drv_priv; |
---|
| 6699 | + int ret = 0; |
---|
| 6700 | + s16 txpwr; |
---|
| 6701 | + |
---|
| 6702 | + if (sta->txpwr.type == NL80211_TX_POWER_AUTOMATIC) { |
---|
| 6703 | + txpwr = 0; |
---|
| 6704 | + } else { |
---|
| 6705 | + txpwr = sta->txpwr.power; |
---|
| 6706 | + if (!txpwr) |
---|
| 6707 | + return -EINVAL; |
---|
| 6708 | + } |
---|
| 6709 | + |
---|
| 6710 | + if (txpwr > ATH10K_TX_POWER_MAX_VAL || txpwr < ATH10K_TX_POWER_MIN_VAL) |
---|
| 6711 | + return -EINVAL; |
---|
| 6712 | + |
---|
| 6713 | + mutex_lock(&ar->conf_mutex); |
---|
| 6714 | + |
---|
| 6715 | + ret = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr, |
---|
| 6716 | + ar->wmi.peer_param->use_fixed_power, txpwr); |
---|
| 6717 | + if (ret) { |
---|
| 6718 | + ath10k_warn(ar, "failed to set tx power for station ret: %d\n", |
---|
| 6719 | + ret); |
---|
| 6720 | + goto out; |
---|
| 6721 | + } |
---|
| 6722 | + |
---|
| 6723 | +out: |
---|
| 6724 | + mutex_unlock(&ar->conf_mutex); |
---|
| 6725 | + return ret; |
---|
| 6726 | +} |
---|
| 6727 | + |
---|
| 6728 | +struct ath10k_mac_iter_tid_conf_data { |
---|
| 6729 | + struct ieee80211_vif *curr_vif; |
---|
| 6730 | + struct ath10k *ar; |
---|
| 6731 | + bool reset_config; |
---|
| 6732 | +}; |
---|
| 6733 | + |
---|
| 6734 | +static bool |
---|
| 6735 | +ath10k_mac_bitrate_mask_has_single_rate(struct ath10k *ar, |
---|
| 6736 | + enum nl80211_band band, |
---|
| 6737 | + const struct cfg80211_bitrate_mask *mask, |
---|
| 6738 | + int *vht_num_rates) |
---|
| 6739 | +{ |
---|
| 6740 | + int num_rates = 0; |
---|
| 6741 | + int i, tmp; |
---|
| 6742 | + |
---|
| 6743 | + num_rates += hweight32(mask->control[band].legacy); |
---|
| 6744 | + |
---|
| 6745 | + for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++) |
---|
| 6746 | + num_rates += hweight8(mask->control[band].ht_mcs[i]); |
---|
| 6747 | + |
---|
| 6748 | + *vht_num_rates = 0; |
---|
| 6749 | + for (i = 0; i < ARRAY_SIZE(mask->control[band].vht_mcs); i++) { |
---|
| 6750 | + tmp = hweight16(mask->control[band].vht_mcs[i]); |
---|
| 6751 | + num_rates += tmp; |
---|
| 6752 | + *vht_num_rates += tmp; |
---|
| 6753 | + } |
---|
| 6754 | + |
---|
| 6755 | + return num_rates == 1; |
---|
| 6756 | +} |
---|
| 6757 | + |
---|
| 6758 | +static int |
---|
| 6759 | +ath10k_mac_bitrate_mask_get_single_rate(struct ath10k *ar, |
---|
| 6760 | + enum nl80211_band band, |
---|
| 6761 | + const struct cfg80211_bitrate_mask *mask, |
---|
| 6762 | + u8 *rate, u8 *nss, bool vht_only) |
---|
| 6763 | +{ |
---|
| 6764 | + int rate_idx; |
---|
| 6765 | + int i; |
---|
| 6766 | + u16 bitrate; |
---|
| 6767 | + u8 preamble; |
---|
| 6768 | + u8 hw_rate; |
---|
| 6769 | + |
---|
| 6770 | + if (vht_only) |
---|
| 6771 | + goto next; |
---|
| 6772 | + |
---|
| 6773 | + if (hweight32(mask->control[band].legacy) == 1) { |
---|
| 6774 | + rate_idx = ffs(mask->control[band].legacy) - 1; |
---|
| 6775 | + |
---|
| 6776 | + if (ar->phy_capability & WHAL_WLAN_11A_CAPABILITY) |
---|
| 6777 | + rate_idx += ATH10K_MAC_FIRST_OFDM_RATE_IDX; |
---|
| 6778 | + |
---|
| 6779 | + hw_rate = ath10k_wmi_legacy_rates[rate_idx].hw_value; |
---|
| 6780 | + bitrate = ath10k_wmi_legacy_rates[rate_idx].bitrate; |
---|
| 6781 | + |
---|
| 6782 | + if (ath10k_mac_bitrate_is_cck(bitrate)) |
---|
| 6783 | + preamble = WMI_RATE_PREAMBLE_CCK; |
---|
| 6784 | + else |
---|
| 6785 | + preamble = WMI_RATE_PREAMBLE_OFDM; |
---|
| 6786 | + |
---|
| 6787 | + *nss = 1; |
---|
| 6788 | + *rate = preamble << 6 | |
---|
| 6789 | + (*nss - 1) << 4 | |
---|
| 6790 | + hw_rate << 0; |
---|
| 6791 | + |
---|
| 6792 | + return 0; |
---|
| 6793 | + } |
---|
| 6794 | + |
---|
| 6795 | + for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++) { |
---|
| 6796 | + if (hweight8(mask->control[band].ht_mcs[i]) == 1) { |
---|
| 6797 | + *nss = i + 1; |
---|
| 6798 | + *rate = WMI_RATE_PREAMBLE_HT << 6 | |
---|
| 6799 | + (*nss - 1) << 4 | |
---|
| 6800 | + (ffs(mask->control[band].ht_mcs[i]) - 1); |
---|
| 6801 | + |
---|
| 6802 | + return 0; |
---|
| 6803 | + } |
---|
| 6804 | + } |
---|
| 6805 | + |
---|
| 6806 | +next: |
---|
| 6807 | + for (i = 0; i < ARRAY_SIZE(mask->control[band].vht_mcs); i++) { |
---|
| 6808 | + if (hweight16(mask->control[band].vht_mcs[i]) == 1) { |
---|
| 6809 | + *nss = i + 1; |
---|
| 6810 | + *rate = WMI_RATE_PREAMBLE_VHT << 6 | |
---|
| 6811 | + (*nss - 1) << 4 | |
---|
| 6812 | + (ffs(mask->control[band].vht_mcs[i]) - 1); |
---|
| 6813 | + |
---|
| 6814 | + return 0; |
---|
| 6815 | + } |
---|
| 6816 | + } |
---|
| 6817 | + |
---|
| 6818 | + return -EINVAL; |
---|
| 6819 | +} |
---|
| 6820 | + |
---|
| 6821 | +static int ath10k_mac_validate_rate_mask(struct ath10k *ar, |
---|
| 6822 | + struct ieee80211_sta *sta, |
---|
| 6823 | + u32 rate_ctrl_flag, u8 nss) |
---|
| 6824 | +{ |
---|
| 6825 | + if (nss > sta->rx_nss) { |
---|
| 6826 | + ath10k_warn(ar, "Invalid nss field, configured %u limit %u\n", |
---|
| 6827 | + nss, sta->rx_nss); |
---|
| 6828 | + return -EINVAL; |
---|
| 6829 | + } |
---|
| 6830 | + |
---|
| 6831 | + if (ATH10K_HW_PREAMBLE(rate_ctrl_flag) == WMI_RATE_PREAMBLE_VHT) { |
---|
| 6832 | + if (!sta->vht_cap.vht_supported) { |
---|
| 6833 | + ath10k_warn(ar, "Invalid VHT rate for sta %pM\n", |
---|
| 6834 | + sta->addr); |
---|
| 6835 | + return -EINVAL; |
---|
| 6836 | + } |
---|
| 6837 | + } else if (ATH10K_HW_PREAMBLE(rate_ctrl_flag) == WMI_RATE_PREAMBLE_HT) { |
---|
| 6838 | + if (!sta->ht_cap.ht_supported || sta->vht_cap.vht_supported) { |
---|
| 6839 | + ath10k_warn(ar, "Invalid HT rate for sta %pM\n", |
---|
| 6840 | + sta->addr); |
---|
| 6841 | + return -EINVAL; |
---|
| 6842 | + } |
---|
| 6843 | + } else { |
---|
| 6844 | + if (sta->ht_cap.ht_supported || sta->vht_cap.vht_supported) |
---|
| 6845 | + return -EINVAL; |
---|
| 6846 | + } |
---|
| 6847 | + |
---|
| 6848 | + return 0; |
---|
| 6849 | +} |
---|
| 6850 | + |
---|
| 6851 | +static int |
---|
| 6852 | +ath10k_mac_tid_bitrate_config(struct ath10k *ar, |
---|
| 6853 | + struct ieee80211_vif *vif, |
---|
| 6854 | + struct ieee80211_sta *sta, |
---|
| 6855 | + u32 *rate_ctrl_flag, u8 *rate_ctrl, |
---|
| 6856 | + enum nl80211_tx_rate_setting txrate_type, |
---|
| 6857 | + const struct cfg80211_bitrate_mask *mask) |
---|
| 6858 | +{ |
---|
| 6859 | + struct cfg80211_chan_def def; |
---|
| 6860 | + enum nl80211_band band; |
---|
| 6861 | + u8 nss, rate; |
---|
| 6862 | + int vht_num_rates, ret; |
---|
| 6863 | + |
---|
| 6864 | + if (WARN_ON(ath10k_mac_vif_chan(vif, &def))) |
---|
| 6865 | + return -EINVAL; |
---|
| 6866 | + |
---|
| 6867 | + if (txrate_type == NL80211_TX_RATE_AUTOMATIC) { |
---|
| 6868 | + *rate_ctrl = WMI_TID_CONFIG_RATE_CONTROL_AUTO; |
---|
| 6869 | + *rate_ctrl_flag = 0; |
---|
| 6870 | + return 0; |
---|
| 6871 | + } |
---|
| 6872 | + |
---|
| 6873 | + band = def.chan->band; |
---|
| 6874 | + |
---|
| 6875 | + if (!ath10k_mac_bitrate_mask_has_single_rate(ar, band, mask, |
---|
| 6876 | + &vht_num_rates)) { |
---|
| 6877 | + return -EINVAL; |
---|
| 6878 | + } |
---|
| 6879 | + |
---|
| 6880 | + ret = ath10k_mac_bitrate_mask_get_single_rate(ar, band, mask, |
---|
| 6881 | + &rate, &nss, false); |
---|
| 6882 | + if (ret) { |
---|
| 6883 | + ath10k_warn(ar, "failed to get single rate: %d\n", |
---|
| 6884 | + ret); |
---|
| 6885 | + return ret; |
---|
| 6886 | + } |
---|
| 6887 | + |
---|
| 6888 | + *rate_ctrl_flag = rate; |
---|
| 6889 | + |
---|
| 6890 | + if (sta && ath10k_mac_validate_rate_mask(ar, sta, *rate_ctrl_flag, nss)) |
---|
| 6891 | + return -EINVAL; |
---|
| 6892 | + |
---|
| 6893 | + if (txrate_type == NL80211_TX_RATE_FIXED) |
---|
| 6894 | + *rate_ctrl = WMI_TID_CONFIG_RATE_CONTROL_FIXED_RATE; |
---|
| 6895 | + else if (txrate_type == NL80211_TX_RATE_LIMITED && |
---|
| 6896 | + (test_bit(WMI_SERVICE_EXT_PEER_TID_CONFIGS_SUPPORT, |
---|
| 6897 | + ar->wmi.svc_map))) |
---|
| 6898 | + *rate_ctrl = WMI_PEER_TID_CONFIG_RATE_UPPER_CAP; |
---|
| 6899 | + else |
---|
| 6900 | + return -EOPNOTSUPP; |
---|
| 6901 | + |
---|
| 6902 | + return 0; |
---|
| 6903 | +} |
---|
| 6904 | + |
---|
| 6905 | +static int ath10k_mac_set_tid_config(struct ath10k *ar, struct ieee80211_sta *sta, |
---|
| 6906 | + struct ieee80211_vif *vif, u32 changed, |
---|
| 6907 | + struct wmi_per_peer_per_tid_cfg_arg *arg) |
---|
| 6908 | +{ |
---|
| 6909 | + struct ath10k_vif *arvif = (void *)vif->drv_priv; |
---|
| 6910 | + struct ath10k_sta *arsta; |
---|
| 6911 | + int ret; |
---|
| 6912 | + |
---|
| 6913 | + if (sta) { |
---|
| 6914 | + if (!sta->wme) |
---|
| 6915 | + return -ENOTSUPP; |
---|
| 6916 | + |
---|
| 6917 | + arsta = (struct ath10k_sta *)sta->drv_priv; |
---|
| 6918 | + |
---|
| 6919 | + if (changed & BIT(NL80211_TID_CONFIG_ATTR_NOACK)) { |
---|
| 6920 | + if ((arsta->retry_long[arg->tid] > 0 || |
---|
| 6921 | + arsta->rate_code[arg->tid] > 0 || |
---|
| 6922 | + arsta->ampdu[arg->tid] == |
---|
| 6923 | + WMI_TID_CONFIG_AGGR_CONTROL_ENABLE) && |
---|
| 6924 | + arg->ack_policy == WMI_PEER_TID_CONFIG_NOACK) { |
---|
| 6925 | + changed &= ~BIT(NL80211_TID_CONFIG_ATTR_NOACK); |
---|
| 6926 | + arg->ack_policy = 0; |
---|
| 6927 | + arg->aggr_control = 0; |
---|
| 6928 | + arg->rate_ctrl = 0; |
---|
| 6929 | + arg->rcode_flags = 0; |
---|
| 6930 | + } |
---|
| 6931 | + } |
---|
| 6932 | + |
---|
| 6933 | + if (changed & BIT(NL80211_TID_CONFIG_ATTR_AMPDU_CTRL)) { |
---|
| 6934 | + if (arsta->noack[arg->tid] == WMI_PEER_TID_CONFIG_NOACK || |
---|
| 6935 | + arvif->noack[arg->tid] == WMI_PEER_TID_CONFIG_NOACK) { |
---|
| 6936 | + arg->aggr_control = 0; |
---|
| 6937 | + changed &= ~BIT(NL80211_TID_CONFIG_ATTR_RETRY_LONG); |
---|
| 6938 | + } |
---|
| 6939 | + } |
---|
| 6940 | + |
---|
| 6941 | + if (changed & (BIT(NL80211_TID_CONFIG_ATTR_TX_RATE) | |
---|
| 6942 | + BIT(NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE))) { |
---|
| 6943 | + if (arsta->noack[arg->tid] == WMI_PEER_TID_CONFIG_NOACK || |
---|
| 6944 | + arvif->noack[arg->tid] == WMI_PEER_TID_CONFIG_NOACK) { |
---|
| 6945 | + arg->rate_ctrl = 0; |
---|
| 6946 | + arg->rcode_flags = 0; |
---|
| 6947 | + } |
---|
| 6948 | + } |
---|
| 6949 | + |
---|
| 6950 | + ether_addr_copy(arg->peer_macaddr.addr, sta->addr); |
---|
| 6951 | + |
---|
| 6952 | + ret = ath10k_wmi_set_per_peer_per_tid_cfg(ar, arg); |
---|
| 6953 | + if (ret) |
---|
| 6954 | + return ret; |
---|
| 6955 | + |
---|
| 6956 | + /* Store the configured parameters in success case */ |
---|
| 6957 | + if (changed & BIT(NL80211_TID_CONFIG_ATTR_NOACK)) { |
---|
| 6958 | + arsta->noack[arg->tid] = arg->ack_policy; |
---|
| 6959 | + arg->ack_policy = 0; |
---|
| 6960 | + arg->aggr_control = 0; |
---|
| 6961 | + arg->rate_ctrl = 0; |
---|
| 6962 | + arg->rcode_flags = 0; |
---|
| 6963 | + } |
---|
| 6964 | + |
---|
| 6965 | + if (changed & BIT(NL80211_TID_CONFIG_ATTR_RETRY_LONG)) { |
---|
| 6966 | + arsta->retry_long[arg->tid] = arg->retry_count; |
---|
| 6967 | + arg->retry_count = 0; |
---|
| 6968 | + } |
---|
| 6969 | + |
---|
| 6970 | + if (changed & BIT(NL80211_TID_CONFIG_ATTR_AMPDU_CTRL)) { |
---|
| 6971 | + arsta->ampdu[arg->tid] = arg->aggr_control; |
---|
| 6972 | + arg->aggr_control = 0; |
---|
| 6973 | + } |
---|
| 6974 | + |
---|
| 6975 | + if (changed & (BIT(NL80211_TID_CONFIG_ATTR_TX_RATE) | |
---|
| 6976 | + BIT(NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE))) { |
---|
| 6977 | + arsta->rate_ctrl[arg->tid] = arg->rate_ctrl; |
---|
| 6978 | + arg->rate_ctrl = 0; |
---|
| 6979 | + arg->rcode_flags = 0; |
---|
| 6980 | + } |
---|
| 6981 | + |
---|
| 6982 | + if (changed & BIT(NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL)) { |
---|
| 6983 | + arsta->rtscts[arg->tid] = arg->rtscts_ctrl; |
---|
| 6984 | + arg->ext_tid_cfg_bitmap = 0; |
---|
| 6985 | + } |
---|
| 6986 | + } else { |
---|
| 6987 | + if (changed & BIT(NL80211_TID_CONFIG_ATTR_NOACK)) { |
---|
| 6988 | + if ((arvif->retry_long[arg->tid] || |
---|
| 6989 | + arvif->rate_code[arg->tid] || |
---|
| 6990 | + arvif->ampdu[arg->tid] == |
---|
| 6991 | + WMI_TID_CONFIG_AGGR_CONTROL_ENABLE) && |
---|
| 6992 | + arg->ack_policy == WMI_PEER_TID_CONFIG_NOACK) { |
---|
| 6993 | + changed &= ~BIT(NL80211_TID_CONFIG_ATTR_NOACK); |
---|
| 6994 | + } else { |
---|
| 6995 | + arvif->noack[arg->tid] = arg->ack_policy; |
---|
| 6996 | + arvif->ampdu[arg->tid] = arg->aggr_control; |
---|
| 6997 | + arvif->rate_ctrl[arg->tid] = arg->rate_ctrl; |
---|
| 6998 | + } |
---|
| 6999 | + } |
---|
| 7000 | + |
---|
| 7001 | + if (changed & BIT(NL80211_TID_CONFIG_ATTR_RETRY_LONG)) { |
---|
| 7002 | + if (arvif->noack[arg->tid] == WMI_PEER_TID_CONFIG_NOACK) |
---|
| 7003 | + changed &= ~BIT(NL80211_TID_CONFIG_ATTR_RETRY_LONG); |
---|
| 7004 | + else |
---|
| 7005 | + arvif->retry_long[arg->tid] = arg->retry_count; |
---|
| 7006 | + } |
---|
| 7007 | + |
---|
| 7008 | + if (changed & BIT(NL80211_TID_CONFIG_ATTR_AMPDU_CTRL)) { |
---|
| 7009 | + if (arvif->noack[arg->tid] == WMI_PEER_TID_CONFIG_NOACK) |
---|
| 7010 | + changed &= ~BIT(NL80211_TID_CONFIG_ATTR_AMPDU_CTRL); |
---|
| 7011 | + else |
---|
| 7012 | + arvif->ampdu[arg->tid] = arg->aggr_control; |
---|
| 7013 | + } |
---|
| 7014 | + |
---|
| 7015 | + if (changed & (BIT(NL80211_TID_CONFIG_ATTR_TX_RATE) | |
---|
| 7016 | + BIT(NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE))) { |
---|
| 7017 | + if (arvif->noack[arg->tid] == WMI_PEER_TID_CONFIG_NOACK) { |
---|
| 7018 | + changed &= ~(BIT(NL80211_TID_CONFIG_ATTR_TX_RATE) | |
---|
| 7019 | + BIT(NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE)); |
---|
| 7020 | + } else { |
---|
| 7021 | + arvif->rate_ctrl[arg->tid] = arg->rate_ctrl; |
---|
| 7022 | + arvif->rate_code[arg->tid] = arg->rcode_flags; |
---|
| 7023 | + } |
---|
| 7024 | + } |
---|
| 7025 | + |
---|
| 7026 | + if (changed & BIT(NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL)) { |
---|
| 7027 | + arvif->rtscts[arg->tid] = arg->rtscts_ctrl; |
---|
| 7028 | + arg->ext_tid_cfg_bitmap = 0; |
---|
| 7029 | + } |
---|
| 7030 | + |
---|
| 7031 | + if (changed) |
---|
| 7032 | + arvif->tid_conf_changed[arg->tid] |= changed; |
---|
| 7033 | + } |
---|
| 7034 | + |
---|
| 7035 | + return 0; |
---|
| 7036 | +} |
---|
| 7037 | + |
---|
| 7038 | +static int |
---|
| 7039 | +ath10k_mac_parse_tid_config(struct ath10k *ar, |
---|
| 7040 | + struct ieee80211_sta *sta, |
---|
| 7041 | + struct ieee80211_vif *vif, |
---|
| 7042 | + struct cfg80211_tid_cfg *tid_conf, |
---|
| 7043 | + struct wmi_per_peer_per_tid_cfg_arg *arg) |
---|
| 7044 | +{ |
---|
| 7045 | + u32 changed = tid_conf->mask; |
---|
| 7046 | + int ret = 0, i = 0; |
---|
| 7047 | + |
---|
| 7048 | + if (!changed) |
---|
| 7049 | + return -EINVAL; |
---|
| 7050 | + |
---|
| 7051 | + while (i < ATH10K_TID_MAX) { |
---|
| 7052 | + if (!(tid_conf->tids & BIT(i))) { |
---|
| 7053 | + i++; |
---|
| 7054 | + continue; |
---|
| 7055 | + } |
---|
| 7056 | + |
---|
| 7057 | + arg->tid = i; |
---|
| 7058 | + |
---|
| 7059 | + if (changed & BIT(NL80211_TID_CONFIG_ATTR_NOACK)) { |
---|
| 7060 | + if (tid_conf->noack == NL80211_TID_CONFIG_ENABLE) { |
---|
| 7061 | + arg->ack_policy = WMI_PEER_TID_CONFIG_NOACK; |
---|
| 7062 | + arg->rate_ctrl = |
---|
| 7063 | + WMI_TID_CONFIG_RATE_CONTROL_DEFAULT_LOWEST_RATE; |
---|
| 7064 | + arg->aggr_control = |
---|
| 7065 | + WMI_TID_CONFIG_AGGR_CONTROL_DISABLE; |
---|
| 7066 | + } else { |
---|
| 7067 | + arg->ack_policy = |
---|
| 7068 | + WMI_PEER_TID_CONFIG_ACK; |
---|
| 7069 | + arg->rate_ctrl = |
---|
| 7070 | + WMI_TID_CONFIG_RATE_CONTROL_AUTO; |
---|
| 7071 | + arg->aggr_control = |
---|
| 7072 | + WMI_TID_CONFIG_AGGR_CONTROL_ENABLE; |
---|
| 7073 | + } |
---|
| 7074 | + } |
---|
| 7075 | + |
---|
| 7076 | + if (changed & BIT(NL80211_TID_CONFIG_ATTR_RETRY_LONG)) |
---|
| 7077 | + arg->retry_count = tid_conf->retry_long; |
---|
| 7078 | + |
---|
| 7079 | + if (changed & BIT(NL80211_TID_CONFIG_ATTR_AMPDU_CTRL)) { |
---|
| 7080 | + if (tid_conf->noack == NL80211_TID_CONFIG_ENABLE) |
---|
| 7081 | + arg->aggr_control = WMI_TID_CONFIG_AGGR_CONTROL_ENABLE; |
---|
| 7082 | + else |
---|
| 7083 | + arg->aggr_control = WMI_TID_CONFIG_AGGR_CONTROL_DISABLE; |
---|
| 7084 | + } |
---|
| 7085 | + |
---|
| 7086 | + if (changed & (BIT(NL80211_TID_CONFIG_ATTR_TX_RATE) | |
---|
| 7087 | + BIT(NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE))) { |
---|
| 7088 | + ret = ath10k_mac_tid_bitrate_config(ar, vif, sta, |
---|
| 7089 | + &arg->rcode_flags, |
---|
| 7090 | + &arg->rate_ctrl, |
---|
| 7091 | + tid_conf->txrate_type, |
---|
| 7092 | + &tid_conf->txrate_mask); |
---|
| 7093 | + if (ret) { |
---|
| 7094 | + ath10k_warn(ar, "failed to configure bitrate mask %d\n", |
---|
| 7095 | + ret); |
---|
| 7096 | + arg->rcode_flags = 0; |
---|
| 7097 | + arg->rate_ctrl = 0; |
---|
| 7098 | + } |
---|
| 7099 | + } |
---|
| 7100 | + |
---|
| 7101 | + if (changed & BIT(NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL)) { |
---|
| 7102 | + if (tid_conf->rtscts) |
---|
| 7103 | + arg->rtscts_ctrl = tid_conf->rtscts; |
---|
| 7104 | + |
---|
| 7105 | + arg->ext_tid_cfg_bitmap = WMI_EXT_TID_RTS_CTS_CONFIG; |
---|
| 7106 | + } |
---|
| 7107 | + |
---|
| 7108 | + ret = ath10k_mac_set_tid_config(ar, sta, vif, changed, arg); |
---|
| 7109 | + if (ret) |
---|
| 7110 | + return ret; |
---|
| 7111 | + i++; |
---|
| 7112 | + } |
---|
| 7113 | + |
---|
| 7114 | + return ret; |
---|
| 7115 | +} |
---|
| 7116 | + |
---|
| 7117 | +static int ath10k_mac_reset_tid_config(struct ath10k *ar, |
---|
| 7118 | + struct ieee80211_sta *sta, |
---|
| 7119 | + struct ath10k_vif *arvif, |
---|
| 7120 | + u8 tids) |
---|
| 7121 | +{ |
---|
| 7122 | + struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv; |
---|
| 7123 | + struct wmi_per_peer_per_tid_cfg_arg arg; |
---|
| 7124 | + int ret = 0, i = 0; |
---|
| 7125 | + |
---|
| 7126 | + arg.vdev_id = arvif->vdev_id; |
---|
| 7127 | + while (i < ATH10K_TID_MAX) { |
---|
| 7128 | + if (!(tids & BIT(i))) { |
---|
| 7129 | + i++; |
---|
| 7130 | + continue; |
---|
| 7131 | + } |
---|
| 7132 | + |
---|
| 7133 | + arg.tid = i; |
---|
| 7134 | + arg.ack_policy = WMI_PEER_TID_CONFIG_ACK; |
---|
| 7135 | + arg.retry_count = ATH10K_MAX_RETRY_COUNT; |
---|
| 7136 | + arg.rate_ctrl = WMI_TID_CONFIG_RATE_CONTROL_AUTO; |
---|
| 7137 | + arg.aggr_control = WMI_TID_CONFIG_AGGR_CONTROL_ENABLE; |
---|
| 7138 | + arg.rtscts_ctrl = WMI_TID_CONFIG_RTSCTS_CONTROL_ENABLE; |
---|
| 7139 | + arg.ext_tid_cfg_bitmap = WMI_EXT_TID_RTS_CTS_CONFIG; |
---|
| 7140 | + |
---|
| 7141 | + ether_addr_copy(arg.peer_macaddr.addr, sta->addr); |
---|
| 7142 | + |
---|
| 7143 | + ret = ath10k_wmi_set_per_peer_per_tid_cfg(ar, &arg); |
---|
| 7144 | + if (ret) |
---|
| 7145 | + return ret; |
---|
| 7146 | + |
---|
| 7147 | + if (!arvif->tids_rst) { |
---|
| 7148 | + arsta->retry_long[i] = -1; |
---|
| 7149 | + arsta->noack[i] = -1; |
---|
| 7150 | + arsta->ampdu[i] = -1; |
---|
| 7151 | + arsta->rate_code[i] = -1; |
---|
| 7152 | + arsta->rate_ctrl[i] = 0; |
---|
| 7153 | + arsta->rtscts[i] = -1; |
---|
| 7154 | + } else { |
---|
| 7155 | + arvif->retry_long[i] = 0; |
---|
| 7156 | + arvif->noack[i] = 0; |
---|
| 7157 | + arvif->ampdu[i] = 0; |
---|
| 7158 | + arvif->rate_code[i] = 0; |
---|
| 7159 | + arvif->rate_ctrl[i] = 0; |
---|
| 7160 | + arvif->rtscts[i] = 0; |
---|
| 7161 | + } |
---|
| 7162 | + |
---|
| 7163 | + i++; |
---|
| 7164 | + } |
---|
| 7165 | + |
---|
| 7166 | + return ret; |
---|
| 7167 | +} |
---|
| 7168 | + |
---|
| 7169 | +static void ath10k_sta_tid_cfg_wk(struct work_struct *wk) |
---|
| 7170 | +{ |
---|
| 7171 | + struct wmi_per_peer_per_tid_cfg_arg arg = {}; |
---|
| 7172 | + struct ieee80211_sta *sta; |
---|
| 7173 | + struct ath10k_sta *arsta; |
---|
| 7174 | + struct ath10k_vif *arvif; |
---|
| 7175 | + struct ath10k *ar; |
---|
| 7176 | + bool config_apply; |
---|
| 7177 | + int ret, i; |
---|
| 7178 | + u32 changed; |
---|
| 7179 | + u8 nss; |
---|
| 7180 | + |
---|
| 7181 | + arsta = container_of(wk, struct ath10k_sta, tid_config_wk); |
---|
| 7182 | + sta = container_of((void *)arsta, struct ieee80211_sta, drv_priv); |
---|
| 7183 | + arvif = arsta->arvif; |
---|
| 7184 | + ar = arvif->ar; |
---|
| 7185 | + |
---|
| 7186 | + mutex_lock(&ar->conf_mutex); |
---|
| 7187 | + |
---|
| 7188 | + if (arvif->tids_rst) { |
---|
| 7189 | + ret = ath10k_mac_reset_tid_config(ar, sta, arvif, |
---|
| 7190 | + arvif->tids_rst); |
---|
| 7191 | + goto exit; |
---|
| 7192 | + } |
---|
| 7193 | + |
---|
| 7194 | + ether_addr_copy(arg.peer_macaddr.addr, sta->addr); |
---|
| 7195 | + |
---|
| 7196 | + for (i = 0; i < ATH10K_TID_MAX; i++) { |
---|
| 7197 | + config_apply = false; |
---|
| 7198 | + changed = arvif->tid_conf_changed[i]; |
---|
| 7199 | + |
---|
| 7200 | + if (changed & BIT(NL80211_TID_CONFIG_ATTR_NOACK)) { |
---|
| 7201 | + if (arsta->noack[i] != -1) { |
---|
| 7202 | + arg.ack_policy = 0; |
---|
| 7203 | + } else { |
---|
| 7204 | + config_apply = true; |
---|
| 7205 | + arg.ack_policy = arvif->noack[i]; |
---|
| 7206 | + arg.aggr_control = arvif->ampdu[i]; |
---|
| 7207 | + arg.rate_ctrl = arvif->rate_ctrl[i]; |
---|
| 7208 | + } |
---|
| 7209 | + } |
---|
| 7210 | + |
---|
| 7211 | + if (changed & BIT(NL80211_TID_CONFIG_ATTR_RETRY_LONG)) { |
---|
| 7212 | + if (arsta->retry_long[i] != -1 || |
---|
| 7213 | + arsta->noack[i] == WMI_PEER_TID_CONFIG_NOACK || |
---|
| 7214 | + arvif->noack[i] == WMI_PEER_TID_CONFIG_NOACK) { |
---|
| 7215 | + arg.retry_count = 0; |
---|
| 7216 | + } else { |
---|
| 7217 | + arg.retry_count = arvif->retry_long[i]; |
---|
| 7218 | + config_apply = true; |
---|
| 7219 | + } |
---|
| 7220 | + } |
---|
| 7221 | + |
---|
| 7222 | + if (changed & BIT(NL80211_TID_CONFIG_ATTR_AMPDU_CTRL)) { |
---|
| 7223 | + if (arsta->ampdu[i] != -1 || |
---|
| 7224 | + arsta->noack[i] == WMI_PEER_TID_CONFIG_NOACK || |
---|
| 7225 | + arvif->noack[i] == WMI_PEER_TID_CONFIG_NOACK) { |
---|
| 7226 | + arg.aggr_control = 0; |
---|
| 7227 | + } else { |
---|
| 7228 | + arg.aggr_control = arvif->ampdu[i]; |
---|
| 7229 | + config_apply = true; |
---|
| 7230 | + } |
---|
| 7231 | + } |
---|
| 7232 | + |
---|
| 7233 | + if (changed & (BIT(NL80211_TID_CONFIG_ATTR_TX_RATE) | |
---|
| 7234 | + BIT(NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE))) { |
---|
| 7235 | + nss = ATH10K_HW_NSS(arvif->rate_code[i]); |
---|
| 7236 | + ret = ath10k_mac_validate_rate_mask(ar, sta, |
---|
| 7237 | + arvif->rate_code[i], |
---|
| 7238 | + nss); |
---|
| 7239 | + if (ret && |
---|
| 7240 | + arvif->rate_ctrl[i] > WMI_TID_CONFIG_RATE_CONTROL_AUTO) { |
---|
| 7241 | + arg.rate_ctrl = 0; |
---|
| 7242 | + arg.rcode_flags = 0; |
---|
| 7243 | + } |
---|
| 7244 | + |
---|
| 7245 | + if (arsta->rate_ctrl[i] > |
---|
| 7246 | + WMI_TID_CONFIG_RATE_CONTROL_AUTO || |
---|
| 7247 | + arsta->noack[i] == WMI_PEER_TID_CONFIG_NOACK || |
---|
| 7248 | + arvif->noack[i] == WMI_PEER_TID_CONFIG_NOACK) { |
---|
| 7249 | + arg.rate_ctrl = 0; |
---|
| 7250 | + arg.rcode_flags = 0; |
---|
| 7251 | + } else { |
---|
| 7252 | + arg.rate_ctrl = arvif->rate_ctrl[i]; |
---|
| 7253 | + arg.rcode_flags = arvif->rate_code[i]; |
---|
| 7254 | + config_apply = true; |
---|
| 7255 | + } |
---|
| 7256 | + } |
---|
| 7257 | + |
---|
| 7258 | + if (changed & BIT(NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL)) { |
---|
| 7259 | + if (arsta->rtscts[i]) { |
---|
| 7260 | + arg.rtscts_ctrl = 0; |
---|
| 7261 | + arg.ext_tid_cfg_bitmap = 0; |
---|
| 7262 | + } else { |
---|
| 7263 | + arg.rtscts_ctrl = arvif->rtscts[i] - 1; |
---|
| 7264 | + arg.ext_tid_cfg_bitmap = |
---|
| 7265 | + WMI_EXT_TID_RTS_CTS_CONFIG; |
---|
| 7266 | + config_apply = true; |
---|
| 7267 | + } |
---|
| 7268 | + } |
---|
| 7269 | + |
---|
| 7270 | + arg.tid = i; |
---|
| 7271 | + |
---|
| 7272 | + if (config_apply) { |
---|
| 7273 | + ret = ath10k_wmi_set_per_peer_per_tid_cfg(ar, &arg); |
---|
| 7274 | + if (ret) |
---|
| 7275 | + ath10k_warn(ar, "failed to set per tid config for sta %pM: %d\n", |
---|
| 7276 | + sta->addr, ret); |
---|
| 7277 | + } |
---|
| 7278 | + |
---|
| 7279 | + arg.ack_policy = 0; |
---|
| 7280 | + arg.retry_count = 0; |
---|
| 7281 | + arg.aggr_control = 0; |
---|
| 7282 | + arg.rate_ctrl = 0; |
---|
| 7283 | + arg.rcode_flags = 0; |
---|
| 7284 | + } |
---|
| 7285 | + |
---|
| 7286 | +exit: |
---|
| 7287 | + mutex_unlock(&ar->conf_mutex); |
---|
| 7288 | +} |
---|
| 7289 | + |
---|
| 7290 | +static void ath10k_mac_vif_stations_tid_conf(void *data, |
---|
| 7291 | + struct ieee80211_sta *sta) |
---|
| 7292 | +{ |
---|
| 7293 | + struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv; |
---|
| 7294 | + struct ath10k_mac_iter_tid_conf_data *iter_data = data; |
---|
| 7295 | + struct ieee80211_vif *sta_vif = arsta->arvif->vif; |
---|
| 7296 | + |
---|
| 7297 | + if (sta_vif != iter_data->curr_vif || !sta->wme) |
---|
| 7298 | + return; |
---|
| 7299 | + |
---|
| 7300 | + ieee80211_queue_work(iter_data->ar->hw, &arsta->tid_config_wk); |
---|
| 7301 | +} |
---|
| 7302 | + |
---|
6213 | 7303 | static int ath10k_sta_state(struct ieee80211_hw *hw, |
---|
6214 | 7304 | struct ieee80211_vif *vif, |
---|
6215 | 7305 | struct ieee80211_sta *sta, |
---|
.. | .. |
---|
6227 | 7317 | new_state == IEEE80211_STA_NONE) { |
---|
6228 | 7318 | memset(arsta, 0, sizeof(*arsta)); |
---|
6229 | 7319 | arsta->arvif = arvif; |
---|
| 7320 | + arsta->peer_ps_state = WMI_PEER_PS_STATE_DISABLED; |
---|
6230 | 7321 | INIT_WORK(&arsta->update_wk, ath10k_sta_rc_update_wk); |
---|
| 7322 | + INIT_WORK(&arsta->tid_config_wk, ath10k_sta_tid_cfg_wk); |
---|
6231 | 7323 | |
---|
6232 | 7324 | for (i = 0; i < ARRAY_SIZE(sta->txq); i++) |
---|
6233 | 7325 | ath10k_mac_txq_init(sta->txq[i]); |
---|
.. | .. |
---|
6235 | 7327 | |
---|
6236 | 7328 | /* cancel must be done outside the mutex to avoid deadlock */ |
---|
6237 | 7329 | if ((old_state == IEEE80211_STA_NONE && |
---|
6238 | | - new_state == IEEE80211_STA_NOTEXIST)) |
---|
| 7330 | + new_state == IEEE80211_STA_NOTEXIST)) { |
---|
6239 | 7331 | cancel_work_sync(&arsta->update_wk); |
---|
| 7332 | + cancel_work_sync(&arsta->tid_config_wk); |
---|
| 7333 | + } |
---|
6240 | 7334 | |
---|
6241 | 7335 | mutex_lock(&ar->conf_mutex); |
---|
6242 | 7336 | |
---|
.. | .. |
---|
6247 | 7341 | */ |
---|
6248 | 7342 | enum wmi_peer_type peer_type = WMI_PEER_TYPE_DEFAULT; |
---|
6249 | 7343 | u32 num_tdls_stations; |
---|
6250 | | - u32 num_tdls_vifs; |
---|
6251 | 7344 | |
---|
6252 | 7345 | ath10k_dbg(ar, ATH10K_DBG_MAC, |
---|
6253 | 7346 | "mac vdev %d peer create %pM (new sta) sta %d / %d peer %d / %d\n", |
---|
.. | .. |
---|
6256 | 7349 | ar->num_peers + 1, ar->max_num_peers); |
---|
6257 | 7350 | |
---|
6258 | 7351 | num_tdls_stations = ath10k_mac_tdls_vif_stations_count(hw, vif); |
---|
6259 | | - num_tdls_vifs = ath10k_mac_tdls_vifs_count(hw); |
---|
6260 | 7352 | |
---|
6261 | 7353 | if (sta->tdls) { |
---|
6262 | 7354 | if (num_tdls_stations >= ar->max_num_tdls_vdevs) { |
---|
.. | .. |
---|
6276 | 7368 | goto exit; |
---|
6277 | 7369 | } |
---|
6278 | 7370 | |
---|
| 7371 | + if (ath10k_debug_is_extd_tx_stats_enabled(ar)) { |
---|
| 7372 | + arsta->tx_stats = kzalloc(sizeof(*arsta->tx_stats), |
---|
| 7373 | + GFP_KERNEL); |
---|
| 7374 | + if (!arsta->tx_stats) { |
---|
| 7375 | + ath10k_mac_dec_num_stations(arvif, sta); |
---|
| 7376 | + ret = -ENOMEM; |
---|
| 7377 | + goto exit; |
---|
| 7378 | + } |
---|
| 7379 | + } |
---|
| 7380 | + |
---|
6279 | 7381 | ret = ath10k_peer_create(ar, vif, sta, arvif->vdev_id, |
---|
6280 | 7382 | sta->addr, peer_type); |
---|
6281 | 7383 | if (ret) { |
---|
6282 | 7384 | ath10k_warn(ar, "failed to add peer %pM for vdev %d when adding a new sta: %i\n", |
---|
6283 | 7385 | sta->addr, arvif->vdev_id, ret); |
---|
6284 | 7386 | ath10k_mac_dec_num_stations(arvif, sta); |
---|
| 7387 | + kfree(arsta->tx_stats); |
---|
6285 | 7388 | goto exit; |
---|
6286 | 7389 | } |
---|
6287 | 7390 | |
---|
.. | .. |
---|
6294 | 7397 | spin_unlock_bh(&ar->data_lock); |
---|
6295 | 7398 | ath10k_peer_delete(ar, arvif->vdev_id, sta->addr); |
---|
6296 | 7399 | ath10k_mac_dec_num_stations(arvif, sta); |
---|
| 7400 | + kfree(arsta->tx_stats); |
---|
6297 | 7401 | ret = -ENOENT; |
---|
6298 | 7402 | goto exit; |
---|
6299 | 7403 | } |
---|
.. | .. |
---|
6314 | 7418 | ath10k_peer_delete(ar, arvif->vdev_id, |
---|
6315 | 7419 | sta->addr); |
---|
6316 | 7420 | ath10k_mac_dec_num_stations(arvif, sta); |
---|
| 7421 | + kfree(arsta->tx_stats); |
---|
6317 | 7422 | goto exit; |
---|
6318 | 7423 | } |
---|
6319 | 7424 | |
---|
.. | .. |
---|
6325 | 7430 | sta->addr, arvif->vdev_id, ret); |
---|
6326 | 7431 | ath10k_peer_delete(ar, arvif->vdev_id, sta->addr); |
---|
6327 | 7432 | ath10k_mac_dec_num_stations(arvif, sta); |
---|
| 7433 | + kfree(arsta->tx_stats); |
---|
6328 | 7434 | |
---|
6329 | 7435 | if (num_tdls_stations != 0) |
---|
6330 | 7436 | goto exit; |
---|
.. | .. |
---|
6371 | 7477 | /* Clean up the peer object as well since we |
---|
6372 | 7478 | * must have failed to do this above. |
---|
6373 | 7479 | */ |
---|
6374 | | - list_del(&peer->list); |
---|
6375 | | - ar->peer_map[i] = NULL; |
---|
6376 | | - kfree(peer); |
---|
6377 | | - ar->num_peers--; |
---|
| 7480 | + ath10k_peer_map_cleanup(ar, peer); |
---|
6378 | 7481 | } |
---|
6379 | 7482 | } |
---|
6380 | 7483 | spin_unlock_bh(&ar->data_lock); |
---|
| 7484 | + |
---|
| 7485 | + if (ath10k_debug_is_extd_tx_stats_enabled(ar)) { |
---|
| 7486 | + kfree(arsta->tx_stats); |
---|
| 7487 | + arsta->tx_stats = NULL; |
---|
| 7488 | + } |
---|
6381 | 7489 | |
---|
6382 | 7490 | for (i = 0; i < ARRAY_SIZE(sta->txq); i++) |
---|
6383 | 7491 | ath10k_mac_txq_unref(ar, sta->txq[i]); |
---|
.. | .. |
---|
6628 | 7736 | return ret; |
---|
6629 | 7737 | } |
---|
6630 | 7738 | |
---|
6631 | | -#define ATH10K_ROC_TIMEOUT_HZ (2 * HZ) |
---|
6632 | | - |
---|
6633 | 7739 | static int ath10k_remain_on_channel(struct ieee80211_hw *hw, |
---|
6634 | 7740 | struct ieee80211_vif *vif, |
---|
6635 | 7741 | struct ieee80211_channel *chan, |
---|
.. | .. |
---|
6718 | 7824 | return ret; |
---|
6719 | 7825 | } |
---|
6720 | 7826 | |
---|
6721 | | -static int ath10k_cancel_remain_on_channel(struct ieee80211_hw *hw) |
---|
| 7827 | +static int ath10k_cancel_remain_on_channel(struct ieee80211_hw *hw, |
---|
| 7828 | + struct ieee80211_vif *vif) |
---|
6722 | 7829 | { |
---|
6723 | 7830 | struct ath10k *ar = hw->priv; |
---|
6724 | 7831 | |
---|
.. | .. |
---|
6780 | 7887 | return -EOPNOTSUPP; |
---|
6781 | 7888 | } |
---|
6782 | 7889 | |
---|
6783 | | -static void ath10k_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
---|
6784 | | - u32 queues, bool drop) |
---|
| 7890 | +void ath10k_mac_wait_tx_complete(struct ath10k *ar) |
---|
6785 | 7891 | { |
---|
6786 | | - struct ath10k *ar = hw->priv; |
---|
6787 | 7892 | bool skip; |
---|
6788 | 7893 | long time_left; |
---|
6789 | 7894 | |
---|
6790 | 7895 | /* mac80211 doesn't care if we really xmit queued frames or not |
---|
6791 | 7896 | * we'll collect those frames either way if we stop/delete vdevs |
---|
6792 | 7897 | */ |
---|
6793 | | - if (drop) |
---|
6794 | | - return; |
---|
6795 | | - |
---|
6796 | | - mutex_lock(&ar->conf_mutex); |
---|
6797 | 7898 | |
---|
6798 | 7899 | if (ar->state == ATH10K_STATE_WEDGED) |
---|
6799 | | - goto skip; |
---|
| 7900 | + return; |
---|
6800 | 7901 | |
---|
6801 | 7902 | time_left = wait_event_timeout(ar->htt.empty_tx_wq, ({ |
---|
6802 | 7903 | bool empty; |
---|
.. | .. |
---|
6815 | 7916 | if (time_left == 0 || skip) |
---|
6816 | 7917 | ath10k_warn(ar, "failed to flush transmit queue (skip %i ar-state %i): %ld\n", |
---|
6817 | 7918 | skip, ar->state, time_left); |
---|
| 7919 | +} |
---|
6818 | 7920 | |
---|
6819 | | -skip: |
---|
| 7921 | +static void ath10k_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
---|
| 7922 | + u32 queues, bool drop) |
---|
| 7923 | +{ |
---|
| 7924 | + struct ath10k *ar = hw->priv; |
---|
| 7925 | + struct ath10k_vif *arvif; |
---|
| 7926 | + u32 bitmap; |
---|
| 7927 | + |
---|
| 7928 | + if (drop) { |
---|
| 7929 | + if (vif && vif->type == NL80211_IFTYPE_STATION) { |
---|
| 7930 | + bitmap = ~(1 << WMI_MGMT_TID); |
---|
| 7931 | + list_for_each_entry(arvif, &ar->arvifs, list) { |
---|
| 7932 | + if (arvif->vdev_type == WMI_VDEV_TYPE_STA) |
---|
| 7933 | + ath10k_wmi_peer_flush(ar, arvif->vdev_id, |
---|
| 7934 | + arvif->bssid, bitmap); |
---|
| 7935 | + } |
---|
| 7936 | + ath10k_htt_flush_tx(&ar->htt); |
---|
| 7937 | + } |
---|
| 7938 | + return; |
---|
| 7939 | + } |
---|
| 7940 | + |
---|
| 7941 | + mutex_lock(&ar->conf_mutex); |
---|
| 7942 | + ath10k_mac_wait_tx_complete(ar); |
---|
6820 | 7943 | mutex_unlock(&ar->conf_mutex); |
---|
6821 | 7944 | } |
---|
6822 | 7945 | |
---|
.. | .. |
---|
6925 | 8048 | } |
---|
6926 | 8049 | |
---|
6927 | 8050 | static bool |
---|
6928 | | -ath10k_mac_bitrate_mask_has_single_rate(struct ath10k *ar, |
---|
6929 | | - enum nl80211_band band, |
---|
6930 | | - const struct cfg80211_bitrate_mask *mask) |
---|
6931 | | -{ |
---|
6932 | | - int num_rates = 0; |
---|
6933 | | - int i; |
---|
6934 | | - |
---|
6935 | | - num_rates += hweight32(mask->control[band].legacy); |
---|
6936 | | - |
---|
6937 | | - for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++) |
---|
6938 | | - num_rates += hweight8(mask->control[band].ht_mcs[i]); |
---|
6939 | | - |
---|
6940 | | - for (i = 0; i < ARRAY_SIZE(mask->control[band].vht_mcs); i++) |
---|
6941 | | - num_rates += hweight16(mask->control[band].vht_mcs[i]); |
---|
6942 | | - |
---|
6943 | | - return num_rates == 1; |
---|
6944 | | -} |
---|
6945 | | - |
---|
6946 | | -static bool |
---|
6947 | 8051 | ath10k_mac_bitrate_mask_get_single_nss(struct ath10k *ar, |
---|
6948 | 8052 | enum nl80211_band band, |
---|
6949 | 8053 | const struct cfg80211_bitrate_mask *mask, |
---|
.. | .. |
---|
6990 | 8094 | *nss = fls(ht_nss_mask); |
---|
6991 | 8095 | |
---|
6992 | 8096 | return true; |
---|
6993 | | -} |
---|
6994 | | - |
---|
6995 | | -static int |
---|
6996 | | -ath10k_mac_bitrate_mask_get_single_rate(struct ath10k *ar, |
---|
6997 | | - enum nl80211_band band, |
---|
6998 | | - const struct cfg80211_bitrate_mask *mask, |
---|
6999 | | - u8 *rate, u8 *nss) |
---|
7000 | | -{ |
---|
7001 | | - int rate_idx; |
---|
7002 | | - int i; |
---|
7003 | | - u16 bitrate; |
---|
7004 | | - u8 preamble; |
---|
7005 | | - u8 hw_rate; |
---|
7006 | | - |
---|
7007 | | - if (hweight32(mask->control[band].legacy) == 1) { |
---|
7008 | | - rate_idx = ffs(mask->control[band].legacy) - 1; |
---|
7009 | | - |
---|
7010 | | - if (ar->phy_capability & WHAL_WLAN_11A_CAPABILITY) |
---|
7011 | | - rate_idx += ATH10K_MAC_FIRST_OFDM_RATE_IDX; |
---|
7012 | | - |
---|
7013 | | - hw_rate = ath10k_wmi_legacy_rates[rate_idx].hw_value; |
---|
7014 | | - bitrate = ath10k_wmi_legacy_rates[rate_idx].bitrate; |
---|
7015 | | - |
---|
7016 | | - if (ath10k_mac_bitrate_is_cck(bitrate)) |
---|
7017 | | - preamble = WMI_RATE_PREAMBLE_CCK; |
---|
7018 | | - else |
---|
7019 | | - preamble = WMI_RATE_PREAMBLE_OFDM; |
---|
7020 | | - |
---|
7021 | | - *nss = 1; |
---|
7022 | | - *rate = preamble << 6 | |
---|
7023 | | - (*nss - 1) << 4 | |
---|
7024 | | - hw_rate << 0; |
---|
7025 | | - |
---|
7026 | | - return 0; |
---|
7027 | | - } |
---|
7028 | | - |
---|
7029 | | - for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++) { |
---|
7030 | | - if (hweight8(mask->control[band].ht_mcs[i]) == 1) { |
---|
7031 | | - *nss = i + 1; |
---|
7032 | | - *rate = WMI_RATE_PREAMBLE_HT << 6 | |
---|
7033 | | - (*nss - 1) << 4 | |
---|
7034 | | - (ffs(mask->control[band].ht_mcs[i]) - 1); |
---|
7035 | | - |
---|
7036 | | - return 0; |
---|
7037 | | - } |
---|
7038 | | - } |
---|
7039 | | - |
---|
7040 | | - for (i = 0; i < ARRAY_SIZE(mask->control[band].vht_mcs); i++) { |
---|
7041 | | - if (hweight16(mask->control[band].vht_mcs[i]) == 1) { |
---|
7042 | | - *nss = i + 1; |
---|
7043 | | - *rate = WMI_RATE_PREAMBLE_VHT << 6 | |
---|
7044 | | - (*nss - 1) << 4 | |
---|
7045 | | - (ffs(mask->control[band].vht_mcs[i]) - 1); |
---|
7046 | | - |
---|
7047 | | - return 0; |
---|
7048 | | - } |
---|
7049 | | - } |
---|
7050 | | - |
---|
7051 | | - return -EINVAL; |
---|
7052 | 8097 | } |
---|
7053 | 8098 | |
---|
7054 | 8099 | static int ath10k_mac_set_fixed_rate_params(struct ath10k_vif *arvif, |
---|
.. | .. |
---|
7098 | 8143 | static bool |
---|
7099 | 8144 | ath10k_mac_can_set_bitrate_mask(struct ath10k *ar, |
---|
7100 | 8145 | enum nl80211_band band, |
---|
7101 | | - const struct cfg80211_bitrate_mask *mask) |
---|
| 8146 | + const struct cfg80211_bitrate_mask *mask, |
---|
| 8147 | + bool allow_pfr) |
---|
7102 | 8148 | { |
---|
7103 | 8149 | int i; |
---|
7104 | 8150 | u16 vht_mcs; |
---|
.. | .. |
---|
7117 | 8163 | case BIT(10) - 1: |
---|
7118 | 8164 | break; |
---|
7119 | 8165 | default: |
---|
7120 | | - ath10k_warn(ar, "refusing bitrate mask with missing 0-7 VHT MCS rates\n"); |
---|
| 8166 | + if (!allow_pfr) |
---|
| 8167 | + ath10k_warn(ar, "refusing bitrate mask with missing 0-7 VHT MCS rates\n"); |
---|
7121 | 8168 | return false; |
---|
7122 | 8169 | } |
---|
7123 | 8170 | } |
---|
| 8171 | + |
---|
| 8172 | + return true; |
---|
| 8173 | +} |
---|
| 8174 | + |
---|
| 8175 | +static bool ath10k_mac_set_vht_bitrate_mask_fixup(struct ath10k *ar, |
---|
| 8176 | + struct ath10k_vif *arvif, |
---|
| 8177 | + struct ieee80211_sta *sta) |
---|
| 8178 | +{ |
---|
| 8179 | + int err; |
---|
| 8180 | + u8 rate = arvif->vht_pfr; |
---|
| 8181 | + |
---|
| 8182 | + /* skip non vht and multiple rate peers */ |
---|
| 8183 | + if (!sta->vht_cap.vht_supported || arvif->vht_num_rates != 1) |
---|
| 8184 | + return false; |
---|
| 8185 | + |
---|
| 8186 | + err = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr, |
---|
| 8187 | + WMI_PEER_PARAM_FIXED_RATE, rate); |
---|
| 8188 | + if (err) |
---|
| 8189 | + ath10k_warn(ar, "failed to enable STA %pM peer fixed rate: %d\n", |
---|
| 8190 | + sta->addr, err); |
---|
7124 | 8191 | |
---|
7125 | 8192 | return true; |
---|
7126 | 8193 | } |
---|
.. | .. |
---|
7135 | 8202 | if (arsta->arvif != arvif) |
---|
7136 | 8203 | return; |
---|
7137 | 8204 | |
---|
| 8205 | + if (ath10k_mac_set_vht_bitrate_mask_fixup(ar, arvif, sta)) |
---|
| 8206 | + return; |
---|
| 8207 | + |
---|
7138 | 8208 | spin_lock_bh(&ar->data_lock); |
---|
7139 | 8209 | arsta->changed |= IEEE80211_RC_SUPP_RATES_CHANGED; |
---|
7140 | 8210 | spin_unlock_bh(&ar->data_lock); |
---|
7141 | 8211 | |
---|
7142 | 8212 | ieee80211_queue_work(ar->hw, &arsta->update_wk); |
---|
| 8213 | +} |
---|
| 8214 | + |
---|
| 8215 | +static void ath10k_mac_clr_bitrate_mask_iter(void *data, |
---|
| 8216 | + struct ieee80211_sta *sta) |
---|
| 8217 | +{ |
---|
| 8218 | + struct ath10k_vif *arvif = data; |
---|
| 8219 | + struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv; |
---|
| 8220 | + struct ath10k *ar = arvif->ar; |
---|
| 8221 | + int err; |
---|
| 8222 | + |
---|
| 8223 | + /* clear vht peers only */ |
---|
| 8224 | + if (arsta->arvif != arvif || !sta->vht_cap.vht_supported) |
---|
| 8225 | + return; |
---|
| 8226 | + |
---|
| 8227 | + err = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr, |
---|
| 8228 | + WMI_PEER_PARAM_FIXED_RATE, |
---|
| 8229 | + WMI_FIXED_RATE_NONE); |
---|
| 8230 | + if (err) |
---|
| 8231 | + ath10k_warn(ar, "failed to clear STA %pM peer fixed rate: %d\n", |
---|
| 8232 | + sta->addr, err); |
---|
7143 | 8233 | } |
---|
7144 | 8234 | |
---|
7145 | 8235 | static int ath10k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw, |
---|
.. | .. |
---|
7158 | 8248 | u8 ldpc; |
---|
7159 | 8249 | int single_nss; |
---|
7160 | 8250 | int ret; |
---|
| 8251 | + int vht_num_rates, allow_pfr; |
---|
| 8252 | + u8 vht_pfr; |
---|
| 8253 | + bool update_bitrate_mask = true; |
---|
7161 | 8254 | |
---|
7162 | 8255 | if (ath10k_mac_vif_chan(vif, &def)) |
---|
7163 | 8256 | return -EPERM; |
---|
.. | .. |
---|
7171 | 8264 | if (sgi == NL80211_TXRATE_FORCE_LGI) |
---|
7172 | 8265 | return -EINVAL; |
---|
7173 | 8266 | |
---|
7174 | | - if (ath10k_mac_bitrate_mask_has_single_rate(ar, band, mask)) { |
---|
| 8267 | + allow_pfr = test_bit(ATH10K_FW_FEATURE_PEER_FIXED_RATE, |
---|
| 8268 | + ar->normal_mode_fw.fw_file.fw_features); |
---|
| 8269 | + if (allow_pfr) { |
---|
| 8270 | + mutex_lock(&ar->conf_mutex); |
---|
| 8271 | + ieee80211_iterate_stations_atomic(ar->hw, |
---|
| 8272 | + ath10k_mac_clr_bitrate_mask_iter, |
---|
| 8273 | + arvif); |
---|
| 8274 | + mutex_unlock(&ar->conf_mutex); |
---|
| 8275 | + } |
---|
| 8276 | + |
---|
| 8277 | + if (ath10k_mac_bitrate_mask_has_single_rate(ar, band, mask, |
---|
| 8278 | + &vht_num_rates)) { |
---|
7175 | 8279 | ret = ath10k_mac_bitrate_mask_get_single_rate(ar, band, mask, |
---|
7176 | | - &rate, &nss); |
---|
| 8280 | + &rate, &nss, |
---|
| 8281 | + false); |
---|
7177 | 8282 | if (ret) { |
---|
7178 | 8283 | ath10k_warn(ar, "failed to get single rate for vdev %i: %d\n", |
---|
7179 | 8284 | arvif->vdev_id, ret); |
---|
.. | .. |
---|
7189 | 8294 | max(ath10k_mac_max_ht_nss(ht_mcs_mask), |
---|
7190 | 8295 | ath10k_mac_max_vht_nss(vht_mcs_mask))); |
---|
7191 | 8296 | |
---|
7192 | | - if (!ath10k_mac_can_set_bitrate_mask(ar, band, mask)) |
---|
7193 | | - return -EINVAL; |
---|
| 8297 | + if (!ath10k_mac_can_set_bitrate_mask(ar, band, mask, |
---|
| 8298 | + allow_pfr)) { |
---|
| 8299 | + u8 vht_nss; |
---|
| 8300 | + |
---|
| 8301 | + if (!allow_pfr || vht_num_rates != 1) |
---|
| 8302 | + return -EINVAL; |
---|
| 8303 | + |
---|
| 8304 | + /* Reach here, firmware supports peer fixed rate and has |
---|
| 8305 | + * single vht rate, and don't update vif birate_mask, as |
---|
| 8306 | + * the rate only for specific peer. |
---|
| 8307 | + */ |
---|
| 8308 | + ath10k_mac_bitrate_mask_get_single_rate(ar, band, mask, |
---|
| 8309 | + &vht_pfr, |
---|
| 8310 | + &vht_nss, |
---|
| 8311 | + true); |
---|
| 8312 | + update_bitrate_mask = false; |
---|
| 8313 | + } else { |
---|
| 8314 | + vht_pfr = 0; |
---|
| 8315 | + } |
---|
7194 | 8316 | |
---|
7195 | 8317 | mutex_lock(&ar->conf_mutex); |
---|
7196 | 8318 | |
---|
7197 | | - arvif->bitrate_mask = *mask; |
---|
| 8319 | + if (update_bitrate_mask) |
---|
| 8320 | + arvif->bitrate_mask = *mask; |
---|
| 8321 | + arvif->vht_num_rates = vht_num_rates; |
---|
| 8322 | + arvif->vht_pfr = vht_pfr; |
---|
7198 | 8323 | ieee80211_iterate_stations_atomic(ar->hw, |
---|
7199 | 8324 | ath10k_mac_set_bitrate_mask_iter, |
---|
7200 | 8325 | arvif); |
---|
.. | .. |
---|
7697 | 8822 | arvif->vdev_id, ret); |
---|
7698 | 8823 | } |
---|
7699 | 8824 | |
---|
7700 | | - if (ath10k_peer_stats_enabled(ar)) { |
---|
| 8825 | + if (ath10k_peer_stats_enabled(ar) && |
---|
| 8826 | + ar->hw_params.tx_stats_over_pktlog) { |
---|
7701 | 8827 | ar->pktlog_filter |= ATH10K_PKTLOG_PEER_STATS; |
---|
7702 | 8828 | ret = ath10k_wmi_pdev_pktlog_enable(ar, |
---|
7703 | 8829 | ar->pktlog_filter); |
---|
.. | .. |
---|
7791 | 8917 | peer->removed = true; |
---|
7792 | 8918 | } |
---|
7793 | 8919 | |
---|
| 8920 | +/* HT MCS parameters with Nss = 1 */ |
---|
| 8921 | +static const struct ath10k_index_ht_data_rate_type supported_ht_mcs_rate_nss1[] = { |
---|
| 8922 | + /* MCS L20 L40 S20 S40 */ |
---|
| 8923 | + {0, { 65, 135, 72, 150} }, |
---|
| 8924 | + {1, { 130, 270, 144, 300} }, |
---|
| 8925 | + {2, { 195, 405, 217, 450} }, |
---|
| 8926 | + {3, { 260, 540, 289, 600} }, |
---|
| 8927 | + {4, { 390, 810, 433, 900} }, |
---|
| 8928 | + {5, { 520, 1080, 578, 1200} }, |
---|
| 8929 | + {6, { 585, 1215, 650, 1350} }, |
---|
| 8930 | + {7, { 650, 1350, 722, 1500} } |
---|
| 8931 | +}; |
---|
| 8932 | + |
---|
| 8933 | +/* HT MCS parameters with Nss = 2 */ |
---|
| 8934 | +static const struct ath10k_index_ht_data_rate_type supported_ht_mcs_rate_nss2[] = { |
---|
| 8935 | + /* MCS L20 L40 S20 S40 */ |
---|
| 8936 | + {0, {130, 270, 144, 300} }, |
---|
| 8937 | + {1, {260, 540, 289, 600} }, |
---|
| 8938 | + {2, {390, 810, 433, 900} }, |
---|
| 8939 | + {3, {520, 1080, 578, 1200} }, |
---|
| 8940 | + {4, {780, 1620, 867, 1800} }, |
---|
| 8941 | + {5, {1040, 2160, 1156, 2400} }, |
---|
| 8942 | + {6, {1170, 2430, 1300, 2700} }, |
---|
| 8943 | + {7, {1300, 2700, 1444, 3000} } |
---|
| 8944 | +}; |
---|
| 8945 | + |
---|
| 8946 | +/* MCS parameters with Nss = 1 */ |
---|
| 8947 | +static const struct ath10k_index_vht_data_rate_type supported_vht_mcs_rate_nss1[] = { |
---|
| 8948 | + /* MCS L80 S80 L40 S40 L20 S20 */ |
---|
| 8949 | + {0, {293, 325}, {135, 150}, {65, 72} }, |
---|
| 8950 | + {1, {585, 650}, {270, 300}, {130, 144} }, |
---|
| 8951 | + {2, {878, 975}, {405, 450}, {195, 217} }, |
---|
| 8952 | + {3, {1170, 1300}, {540, 600}, {260, 289} }, |
---|
| 8953 | + {4, {1755, 1950}, {810, 900}, {390, 433} }, |
---|
| 8954 | + {5, {2340, 2600}, {1080, 1200}, {520, 578} }, |
---|
| 8955 | + {6, {2633, 2925}, {1215, 1350}, {585, 650} }, |
---|
| 8956 | + {7, {2925, 3250}, {1350, 1500}, {650, 722} }, |
---|
| 8957 | + {8, {3510, 3900}, {1620, 1800}, {780, 867} }, |
---|
| 8958 | + {9, {3900, 4333}, {1800, 2000}, {780, 867} } |
---|
| 8959 | +}; |
---|
| 8960 | + |
---|
| 8961 | +/*MCS parameters with Nss = 2 */ |
---|
| 8962 | +static const struct ath10k_index_vht_data_rate_type supported_vht_mcs_rate_nss2[] = { |
---|
| 8963 | + /* MCS L80 S80 L40 S40 L20 S20 */ |
---|
| 8964 | + {0, {585, 650}, {270, 300}, {130, 144} }, |
---|
| 8965 | + {1, {1170, 1300}, {540, 600}, {260, 289} }, |
---|
| 8966 | + {2, {1755, 1950}, {810, 900}, {390, 433} }, |
---|
| 8967 | + {3, {2340, 2600}, {1080, 1200}, {520, 578} }, |
---|
| 8968 | + {4, {3510, 3900}, {1620, 1800}, {780, 867} }, |
---|
| 8969 | + {5, {4680, 5200}, {2160, 2400}, {1040, 1156} }, |
---|
| 8970 | + {6, {5265, 5850}, {2430, 2700}, {1170, 1300} }, |
---|
| 8971 | + {7, {5850, 6500}, {2700, 3000}, {1300, 1444} }, |
---|
| 8972 | + {8, {7020, 7800}, {3240, 3600}, {1560, 1733} }, |
---|
| 8973 | + {9, {7800, 8667}, {3600, 4000}, {1560, 1733} } |
---|
| 8974 | +}; |
---|
| 8975 | + |
---|
| 8976 | +static void ath10k_mac_get_rate_flags_ht(struct ath10k *ar, u32 rate, u8 nss, u8 mcs, |
---|
| 8977 | + u8 *flags, u8 *bw) |
---|
| 8978 | +{ |
---|
| 8979 | + struct ath10k_index_ht_data_rate_type *mcs_rate; |
---|
| 8980 | + u8 index; |
---|
| 8981 | + size_t len_nss1 = ARRAY_SIZE(supported_ht_mcs_rate_nss1); |
---|
| 8982 | + size_t len_nss2 = ARRAY_SIZE(supported_ht_mcs_rate_nss2); |
---|
| 8983 | + |
---|
| 8984 | + if (mcs >= (len_nss1 + len_nss2)) { |
---|
| 8985 | + ath10k_warn(ar, "not supported mcs %d in current rate table", mcs); |
---|
| 8986 | + return; |
---|
| 8987 | + } |
---|
| 8988 | + |
---|
| 8989 | + mcs_rate = (struct ath10k_index_ht_data_rate_type *) |
---|
| 8990 | + ((nss == 1) ? &supported_ht_mcs_rate_nss1 : |
---|
| 8991 | + &supported_ht_mcs_rate_nss2); |
---|
| 8992 | + |
---|
| 8993 | + if (mcs >= len_nss1) |
---|
| 8994 | + index = mcs - len_nss1; |
---|
| 8995 | + else |
---|
| 8996 | + index = mcs; |
---|
| 8997 | + |
---|
| 8998 | + if (rate == mcs_rate[index].supported_rate[0]) { |
---|
| 8999 | + *bw = RATE_INFO_BW_20; |
---|
| 9000 | + } else if (rate == mcs_rate[index].supported_rate[1]) { |
---|
| 9001 | + *bw |= RATE_INFO_BW_40; |
---|
| 9002 | + } else if (rate == mcs_rate[index].supported_rate[2]) { |
---|
| 9003 | + *bw |= RATE_INFO_BW_20; |
---|
| 9004 | + *flags |= RATE_INFO_FLAGS_SHORT_GI; |
---|
| 9005 | + } else if (rate == mcs_rate[index].supported_rate[3]) { |
---|
| 9006 | + *bw |= RATE_INFO_BW_40; |
---|
| 9007 | + *flags |= RATE_INFO_FLAGS_SHORT_GI; |
---|
| 9008 | + } else { |
---|
| 9009 | + ath10k_warn(ar, "invalid ht params rate %d 100kbps nss %d mcs %d", |
---|
| 9010 | + rate, nss, mcs); |
---|
| 9011 | + } |
---|
| 9012 | +} |
---|
| 9013 | + |
---|
| 9014 | +static void ath10k_mac_get_rate_flags_vht(struct ath10k *ar, u32 rate, u8 nss, u8 mcs, |
---|
| 9015 | + u8 *flags, u8 *bw) |
---|
| 9016 | +{ |
---|
| 9017 | + struct ath10k_index_vht_data_rate_type *mcs_rate; |
---|
| 9018 | + |
---|
| 9019 | + mcs_rate = (struct ath10k_index_vht_data_rate_type *) |
---|
| 9020 | + ((nss == 1) ? &supported_vht_mcs_rate_nss1 : |
---|
| 9021 | + &supported_vht_mcs_rate_nss2); |
---|
| 9022 | + |
---|
| 9023 | + if (rate == mcs_rate[mcs].supported_VHT80_rate[0]) { |
---|
| 9024 | + *bw = RATE_INFO_BW_80; |
---|
| 9025 | + } else if (rate == mcs_rate[mcs].supported_VHT80_rate[1]) { |
---|
| 9026 | + *bw = RATE_INFO_BW_80; |
---|
| 9027 | + *flags |= RATE_INFO_FLAGS_SHORT_GI; |
---|
| 9028 | + } else if (rate == mcs_rate[mcs].supported_VHT40_rate[0]) { |
---|
| 9029 | + *bw = RATE_INFO_BW_40; |
---|
| 9030 | + } else if (rate == mcs_rate[mcs].supported_VHT40_rate[1]) { |
---|
| 9031 | + *bw = RATE_INFO_BW_40; |
---|
| 9032 | + *flags |= RATE_INFO_FLAGS_SHORT_GI; |
---|
| 9033 | + } else if (rate == mcs_rate[mcs].supported_VHT20_rate[0]) { |
---|
| 9034 | + *bw = RATE_INFO_BW_20; |
---|
| 9035 | + } else if (rate == mcs_rate[mcs].supported_VHT20_rate[1]) { |
---|
| 9036 | + *bw = RATE_INFO_BW_20; |
---|
| 9037 | + *flags |= RATE_INFO_FLAGS_SHORT_GI; |
---|
| 9038 | + } else { |
---|
| 9039 | + ath10k_warn(ar, "invalid vht params rate %d 100kbps nss %d mcs %d", |
---|
| 9040 | + rate, nss, mcs); |
---|
| 9041 | + } |
---|
| 9042 | +} |
---|
| 9043 | + |
---|
| 9044 | +static void ath10k_mac_get_rate_flags(struct ath10k *ar, u32 rate, |
---|
| 9045 | + enum ath10k_phy_mode mode, u8 nss, u8 mcs, |
---|
| 9046 | + u8 *flags, u8 *bw) |
---|
| 9047 | +{ |
---|
| 9048 | + if (mode == ATH10K_PHY_MODE_HT) { |
---|
| 9049 | + *flags = RATE_INFO_FLAGS_MCS; |
---|
| 9050 | + ath10k_mac_get_rate_flags_ht(ar, rate, nss, mcs, flags, bw); |
---|
| 9051 | + } else if (mode == ATH10K_PHY_MODE_VHT) { |
---|
| 9052 | + *flags = RATE_INFO_FLAGS_VHT_MCS; |
---|
| 9053 | + ath10k_mac_get_rate_flags_vht(ar, rate, nss, mcs, flags, bw); |
---|
| 9054 | + } |
---|
| 9055 | +} |
---|
| 9056 | + |
---|
| 9057 | +static void ath10k_mac_parse_bitrate(struct ath10k *ar, u32 rate_code, |
---|
| 9058 | + u32 bitrate_kbps, struct rate_info *rate) |
---|
| 9059 | +{ |
---|
| 9060 | + enum ath10k_phy_mode mode = ATH10K_PHY_MODE_LEGACY; |
---|
| 9061 | + enum wmi_rate_preamble preamble = WMI_TLV_GET_HW_RC_PREAM_V1(rate_code); |
---|
| 9062 | + u8 nss = WMI_TLV_GET_HW_RC_NSS_V1(rate_code) + 1; |
---|
| 9063 | + u8 mcs = WMI_TLV_GET_HW_RC_RATE_V1(rate_code); |
---|
| 9064 | + u8 flags = 0, bw = 0; |
---|
| 9065 | + |
---|
| 9066 | + ath10k_dbg(ar, ATH10K_DBG_MAC, "mac parse rate code 0x%x bitrate %d kbps\n", |
---|
| 9067 | + rate_code, bitrate_kbps); |
---|
| 9068 | + |
---|
| 9069 | + if (preamble == WMI_RATE_PREAMBLE_HT) |
---|
| 9070 | + mode = ATH10K_PHY_MODE_HT; |
---|
| 9071 | + else if (preamble == WMI_RATE_PREAMBLE_VHT) |
---|
| 9072 | + mode = ATH10K_PHY_MODE_VHT; |
---|
| 9073 | + |
---|
| 9074 | + ath10k_mac_get_rate_flags(ar, bitrate_kbps / 100, mode, nss, mcs, &flags, &bw); |
---|
| 9075 | + |
---|
| 9076 | + ath10k_dbg(ar, ATH10K_DBG_MAC, |
---|
| 9077 | + "mac parse bitrate preamble %d mode %d nss %d mcs %d flags %x bw %d\n", |
---|
| 9078 | + preamble, mode, nss, mcs, flags, bw); |
---|
| 9079 | + |
---|
| 9080 | + rate->flags = flags; |
---|
| 9081 | + rate->bw = bw; |
---|
| 9082 | + rate->legacy = bitrate_kbps / 100; |
---|
| 9083 | + rate->nss = nss; |
---|
| 9084 | + rate->mcs = mcs; |
---|
| 9085 | +} |
---|
| 9086 | + |
---|
| 9087 | +static void ath10k_mac_sta_get_peer_stats_info(struct ath10k *ar, |
---|
| 9088 | + struct ieee80211_sta *sta, |
---|
| 9089 | + struct station_info *sinfo) |
---|
| 9090 | +{ |
---|
| 9091 | + struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv; |
---|
| 9092 | + struct ath10k_peer *peer; |
---|
| 9093 | + unsigned long time_left; |
---|
| 9094 | + int ret; |
---|
| 9095 | + |
---|
| 9096 | + if (!(ar->hw_params.supports_peer_stats_info && |
---|
| 9097 | + arsta->arvif->vdev_type == WMI_VDEV_TYPE_STA)) |
---|
| 9098 | + return; |
---|
| 9099 | + |
---|
| 9100 | + spin_lock_bh(&ar->data_lock); |
---|
| 9101 | + peer = ath10k_peer_find(ar, arsta->arvif->vdev_id, sta->addr); |
---|
| 9102 | + spin_unlock_bh(&ar->data_lock); |
---|
| 9103 | + if (!peer) |
---|
| 9104 | + return; |
---|
| 9105 | + |
---|
| 9106 | + reinit_completion(&ar->peer_stats_info_complete); |
---|
| 9107 | + |
---|
| 9108 | + ret = ath10k_wmi_request_peer_stats_info(ar, |
---|
| 9109 | + arsta->arvif->vdev_id, |
---|
| 9110 | + WMI_REQUEST_ONE_PEER_STATS_INFO, |
---|
| 9111 | + arsta->arvif->bssid, |
---|
| 9112 | + 0); |
---|
| 9113 | + if (ret && ret != -EOPNOTSUPP) { |
---|
| 9114 | + ath10k_warn(ar, "could not request peer stats info: %d\n", ret); |
---|
| 9115 | + return; |
---|
| 9116 | + } |
---|
| 9117 | + |
---|
| 9118 | + time_left = wait_for_completion_timeout(&ar->peer_stats_info_complete, 3 * HZ); |
---|
| 9119 | + if (time_left == 0) { |
---|
| 9120 | + ath10k_warn(ar, "timed out waiting peer stats info\n"); |
---|
| 9121 | + return; |
---|
| 9122 | + } |
---|
| 9123 | + |
---|
| 9124 | + if (arsta->rx_rate_code != 0 && arsta->rx_bitrate_kbps != 0) { |
---|
| 9125 | + ath10k_mac_parse_bitrate(ar, arsta->rx_rate_code, |
---|
| 9126 | + arsta->rx_bitrate_kbps, |
---|
| 9127 | + &sinfo->rxrate); |
---|
| 9128 | + |
---|
| 9129 | + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BITRATE); |
---|
| 9130 | + arsta->rx_rate_code = 0; |
---|
| 9131 | + arsta->rx_bitrate_kbps = 0; |
---|
| 9132 | + } |
---|
| 9133 | + |
---|
| 9134 | + if (arsta->tx_rate_code != 0 && arsta->tx_bitrate_kbps != 0) { |
---|
| 9135 | + ath10k_mac_parse_bitrate(ar, arsta->tx_rate_code, |
---|
| 9136 | + arsta->tx_bitrate_kbps, |
---|
| 9137 | + &sinfo->txrate); |
---|
| 9138 | + |
---|
| 9139 | + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE); |
---|
| 9140 | + arsta->tx_rate_code = 0; |
---|
| 9141 | + arsta->tx_bitrate_kbps = 0; |
---|
| 9142 | + } |
---|
| 9143 | +} |
---|
| 9144 | + |
---|
7794 | 9145 | static void ath10k_sta_statistics(struct ieee80211_hw *hw, |
---|
7795 | 9146 | struct ieee80211_vif *vif, |
---|
7796 | 9147 | struct ieee80211_sta *sta, |
---|
.. | .. |
---|
7802 | 9153 | if (!ath10k_peer_stats_enabled(ar)) |
---|
7803 | 9154 | return; |
---|
7804 | 9155 | |
---|
| 9156 | + mutex_lock(&ar->conf_mutex); |
---|
| 9157 | + ath10k_debug_fw_stats_request(ar); |
---|
| 9158 | + mutex_unlock(&ar->conf_mutex); |
---|
| 9159 | + |
---|
7805 | 9160 | sinfo->rx_duration = arsta->rx_duration; |
---|
7806 | 9161 | sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_DURATION); |
---|
7807 | 9162 | |
---|
7808 | | - if (!arsta->txrate.legacy && !arsta->txrate.nss) |
---|
7809 | | - return; |
---|
7810 | | - |
---|
7811 | | - if (arsta->txrate.legacy) { |
---|
7812 | | - sinfo->txrate.legacy = arsta->txrate.legacy; |
---|
7813 | | - } else { |
---|
7814 | | - sinfo->txrate.mcs = arsta->txrate.mcs; |
---|
7815 | | - sinfo->txrate.nss = arsta->txrate.nss; |
---|
7816 | | - sinfo->txrate.bw = arsta->txrate.bw; |
---|
| 9163 | + if (arsta->txrate.legacy || arsta->txrate.nss) { |
---|
| 9164 | + if (arsta->txrate.legacy) { |
---|
| 9165 | + sinfo->txrate.legacy = arsta->txrate.legacy; |
---|
| 9166 | + } else { |
---|
| 9167 | + sinfo->txrate.mcs = arsta->txrate.mcs; |
---|
| 9168 | + sinfo->txrate.nss = arsta->txrate.nss; |
---|
| 9169 | + sinfo->txrate.bw = arsta->txrate.bw; |
---|
| 9170 | + } |
---|
| 9171 | + sinfo->txrate.flags = arsta->txrate.flags; |
---|
| 9172 | + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE); |
---|
7817 | 9173 | } |
---|
7818 | | - sinfo->txrate.flags = arsta->txrate.flags; |
---|
7819 | | - sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE); |
---|
| 9174 | + |
---|
| 9175 | + if (ar->htt.disable_tx_comp) { |
---|
| 9176 | + sinfo->tx_failed = arsta->tx_failed; |
---|
| 9177 | + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED); |
---|
| 9178 | + } |
---|
| 9179 | + |
---|
| 9180 | + sinfo->tx_retries = arsta->tx_retries; |
---|
| 9181 | + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_RETRIES); |
---|
| 9182 | + |
---|
| 9183 | + ath10k_mac_sta_get_peer_stats_info(ar, sta, sinfo); |
---|
| 9184 | +} |
---|
| 9185 | + |
---|
| 9186 | +static int ath10k_mac_op_set_tid_config(struct ieee80211_hw *hw, |
---|
| 9187 | + struct ieee80211_vif *vif, |
---|
| 9188 | + struct ieee80211_sta *sta, |
---|
| 9189 | + struct cfg80211_tid_config *tid_config) |
---|
| 9190 | +{ |
---|
| 9191 | + struct ath10k *ar = hw->priv; |
---|
| 9192 | + struct ath10k_vif *arvif = (void *)vif->drv_priv; |
---|
| 9193 | + struct ath10k_mac_iter_tid_conf_data data = {}; |
---|
| 9194 | + struct wmi_per_peer_per_tid_cfg_arg arg = {}; |
---|
| 9195 | + int ret, i; |
---|
| 9196 | + |
---|
| 9197 | + mutex_lock(&ar->conf_mutex); |
---|
| 9198 | + arg.vdev_id = arvif->vdev_id; |
---|
| 9199 | + |
---|
| 9200 | + arvif->tids_rst = 0; |
---|
| 9201 | + memset(arvif->tid_conf_changed, 0, sizeof(arvif->tid_conf_changed)); |
---|
| 9202 | + |
---|
| 9203 | + for (i = 0; i < tid_config->n_tid_conf; i++) { |
---|
| 9204 | + ret = ath10k_mac_parse_tid_config(ar, sta, vif, |
---|
| 9205 | + &tid_config->tid_conf[i], |
---|
| 9206 | + &arg); |
---|
| 9207 | + if (ret) |
---|
| 9208 | + goto exit; |
---|
| 9209 | + } |
---|
| 9210 | + |
---|
| 9211 | + if (sta) |
---|
| 9212 | + goto exit; |
---|
| 9213 | + |
---|
| 9214 | + ret = 0; |
---|
| 9215 | + arvif->tids_rst = 0; |
---|
| 9216 | + data.curr_vif = vif; |
---|
| 9217 | + data.ar = ar; |
---|
| 9218 | + |
---|
| 9219 | + ieee80211_iterate_stations_atomic(hw, ath10k_mac_vif_stations_tid_conf, |
---|
| 9220 | + &data); |
---|
| 9221 | + |
---|
| 9222 | +exit: |
---|
| 9223 | + mutex_unlock(&ar->conf_mutex); |
---|
| 9224 | + return ret; |
---|
| 9225 | +} |
---|
| 9226 | + |
---|
| 9227 | +static int ath10k_mac_op_reset_tid_config(struct ieee80211_hw *hw, |
---|
| 9228 | + struct ieee80211_vif *vif, |
---|
| 9229 | + struct ieee80211_sta *sta, |
---|
| 9230 | + u8 tids) |
---|
| 9231 | +{ |
---|
| 9232 | + struct ath10k_vif *arvif = (void *)vif->drv_priv; |
---|
| 9233 | + struct ath10k_mac_iter_tid_conf_data data = {}; |
---|
| 9234 | + struct ath10k *ar = hw->priv; |
---|
| 9235 | + int ret = 0; |
---|
| 9236 | + |
---|
| 9237 | + mutex_lock(&ar->conf_mutex); |
---|
| 9238 | + |
---|
| 9239 | + if (sta) { |
---|
| 9240 | + arvif->tids_rst = 0; |
---|
| 9241 | + ret = ath10k_mac_reset_tid_config(ar, sta, arvif, tids); |
---|
| 9242 | + goto exit; |
---|
| 9243 | + } |
---|
| 9244 | + |
---|
| 9245 | + arvif->tids_rst = tids; |
---|
| 9246 | + data.curr_vif = vif; |
---|
| 9247 | + data.ar = ar; |
---|
| 9248 | + ieee80211_iterate_stations_atomic(hw, ath10k_mac_vif_stations_tid_conf, |
---|
| 9249 | + &data); |
---|
| 9250 | + |
---|
| 9251 | +exit: |
---|
| 9252 | + mutex_unlock(&ar->conf_mutex); |
---|
| 9253 | + return ret; |
---|
7820 | 9254 | } |
---|
7821 | 9255 | |
---|
7822 | 9256 | static const struct ieee80211_ops ath10k_ops = { |
---|
.. | .. |
---|
7835 | 9269 | .set_key = ath10k_set_key, |
---|
7836 | 9270 | .set_default_unicast_key = ath10k_set_default_unicast_key, |
---|
7837 | 9271 | .sta_state = ath10k_sta_state, |
---|
| 9272 | + .sta_set_txpwr = ath10k_sta_set_txpwr, |
---|
7838 | 9273 | .conf_tx = ath10k_conf_tx, |
---|
7839 | 9274 | .remain_on_channel = ath10k_remain_on_channel, |
---|
7840 | 9275 | .cancel_remain_on_channel = ath10k_cancel_remain_on_channel, |
---|
.. | .. |
---|
7861 | 9296 | .switch_vif_chanctx = ath10k_mac_op_switch_vif_chanctx, |
---|
7862 | 9297 | .sta_pre_rcu_remove = ath10k_mac_op_sta_pre_rcu_remove, |
---|
7863 | 9298 | .sta_statistics = ath10k_sta_statistics, |
---|
| 9299 | + .set_tid_config = ath10k_mac_op_set_tid_config, |
---|
| 9300 | + .reset_tid_config = ath10k_mac_op_reset_tid_config, |
---|
7864 | 9301 | |
---|
7865 | 9302 | CFG80211_TESTMODE_CMD(ath10k_tm_cmd) |
---|
7866 | 9303 | |
---|
.. | .. |
---|
8155 | 9592 | .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | |
---|
8156 | 9593 | BIT(NL80211_CHAN_WIDTH_20) | |
---|
8157 | 9594 | BIT(NL80211_CHAN_WIDTH_40) | |
---|
8158 | | - BIT(NL80211_CHAN_WIDTH_80), |
---|
| 9595 | + BIT(NL80211_CHAN_WIDTH_80) | |
---|
| 9596 | + BIT(NL80211_CHAN_WIDTH_80P80) | |
---|
| 9597 | + BIT(NL80211_CHAN_WIDTH_160), |
---|
| 9598 | +#endif |
---|
| 9599 | + }, |
---|
| 9600 | +}; |
---|
| 9601 | + |
---|
| 9602 | +static const struct |
---|
| 9603 | +ieee80211_iface_combination ath10k_10_4_bcn_int_if_comb[] = { |
---|
| 9604 | + { |
---|
| 9605 | + .limits = ath10k_10_4_if_limits, |
---|
| 9606 | + .n_limits = ARRAY_SIZE(ath10k_10_4_if_limits), |
---|
| 9607 | + .max_interfaces = 16, |
---|
| 9608 | + .num_different_channels = 1, |
---|
| 9609 | + .beacon_int_infra_match = true, |
---|
| 9610 | + .beacon_int_min_gcd = 100, |
---|
| 9611 | +#ifdef CONFIG_ATH10K_DFS_CERTIFIED |
---|
| 9612 | + .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | |
---|
| 9613 | + BIT(NL80211_CHAN_WIDTH_20) | |
---|
| 9614 | + BIT(NL80211_CHAN_WIDTH_40) | |
---|
| 9615 | + BIT(NL80211_CHAN_WIDTH_80) | |
---|
| 9616 | + BIT(NL80211_CHAN_WIDTH_80P80) | |
---|
| 9617 | + BIT(NL80211_CHAN_WIDTH_160), |
---|
8159 | 9618 | #endif |
---|
8160 | 9619 | }, |
---|
8161 | 9620 | }; |
---|
.. | .. |
---|
8232 | 9691 | |
---|
8233 | 9692 | static int ath10k_mac_get_wrdd_regulatory(struct ath10k *ar, u16 *rd) |
---|
8234 | 9693 | { |
---|
8235 | | - struct pci_dev __maybe_unused *pdev = to_pci_dev(ar->dev); |
---|
8236 | 9694 | acpi_handle root_handle; |
---|
8237 | 9695 | acpi_handle handle; |
---|
8238 | 9696 | struct acpi_buffer wrdd = {ACPI_ALLOCATE_BUFFER, NULL}; |
---|
.. | .. |
---|
8240 | 9698 | u32 alpha2_code; |
---|
8241 | 9699 | char alpha2[3]; |
---|
8242 | 9700 | |
---|
8243 | | - root_handle = ACPI_HANDLE(&pdev->dev); |
---|
| 9701 | + root_handle = ACPI_HANDLE(ar->dev); |
---|
8244 | 9702 | if (!root_handle) |
---|
8245 | 9703 | return -EOPNOTSUPP; |
---|
8246 | 9704 | |
---|
.. | .. |
---|
8322 | 9780 | void *channels; |
---|
8323 | 9781 | int ret; |
---|
8324 | 9782 | |
---|
| 9783 | + if (!is_valid_ether_addr(ar->mac_addr)) { |
---|
| 9784 | + ath10k_warn(ar, "invalid MAC address; choosing random\n"); |
---|
| 9785 | + eth_random_addr(ar->mac_addr); |
---|
| 9786 | + } |
---|
8325 | 9787 | SET_IEEE80211_PERM_ADDR(ar->hw, ar->mac_addr); |
---|
8326 | 9788 | |
---|
8327 | 9789 | SET_IEEE80211_DEV(ar->hw, ar->dev); |
---|
.. | .. |
---|
8427 | 9889 | ar->hw->wiphy->max_scan_ssids = WLAN_SCAN_PARAMS_MAX_SSID; |
---|
8428 | 9890 | ar->hw->wiphy->max_scan_ie_len = WLAN_SCAN_PARAMS_MAX_IE_LEN; |
---|
8429 | 9891 | |
---|
| 9892 | + if (test_bit(WMI_SERVICE_NLO, ar->wmi.svc_map)) { |
---|
| 9893 | + ar->hw->wiphy->max_sched_scan_ssids = WMI_PNO_MAX_SUPP_NETWORKS; |
---|
| 9894 | + ar->hw->wiphy->max_match_sets = WMI_PNO_MAX_SUPP_NETWORKS; |
---|
| 9895 | + ar->hw->wiphy->max_sched_scan_ie_len = WMI_PNO_MAX_IE_LENGTH; |
---|
| 9896 | + ar->hw->wiphy->max_sched_scan_plans = WMI_PNO_MAX_SCHED_SCAN_PLANS; |
---|
| 9897 | + ar->hw->wiphy->max_sched_scan_plan_interval = |
---|
| 9898 | + WMI_PNO_MAX_SCHED_SCAN_PLAN_INT; |
---|
| 9899 | + ar->hw->wiphy->max_sched_scan_plan_iterations = |
---|
| 9900 | + WMI_PNO_MAX_SCHED_SCAN_PLAN_ITRNS; |
---|
| 9901 | + ar->hw->wiphy->features |= NL80211_FEATURE_ND_RANDOM_MAC_ADDR; |
---|
| 9902 | + } |
---|
| 9903 | + |
---|
8430 | 9904 | ar->hw->vif_data_size = sizeof(struct ath10k_vif); |
---|
8431 | 9905 | ar->hw->sta_data_size = sizeof(struct ath10k_sta); |
---|
8432 | 9906 | ar->hw->txq_data_size = sizeof(struct ath10k_txq); |
---|
.. | .. |
---|
8475 | 9949 | wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_VHT_IBSS); |
---|
8476 | 9950 | wiphy_ext_feature_set(ar->hw->wiphy, |
---|
8477 | 9951 | NL80211_EXT_FEATURE_SET_SCAN_DWELL); |
---|
| 9952 | + wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_AQL); |
---|
8478 | 9953 | |
---|
| 9954 | + if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map) || |
---|
| 9955 | + test_bit(WMI_SERVICE_HTT_MGMT_TX_COMP_VALID_FLAGS, ar->wmi.svc_map)) |
---|
| 9956 | + wiphy_ext_feature_set(ar->hw->wiphy, |
---|
| 9957 | + NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT); |
---|
| 9958 | + |
---|
| 9959 | + if (ath10k_peer_stats_enabled(ar) || |
---|
| 9960 | + test_bit(WMI_SERVICE_REPORT_AIRTIME, ar->wmi.svc_map)) |
---|
| 9961 | + wiphy_ext_feature_set(ar->hw->wiphy, |
---|
| 9962 | + NL80211_EXT_FEATURE_AIRTIME_FAIRNESS); |
---|
| 9963 | + |
---|
| 9964 | + if (test_bit(WMI_SERVICE_RTT_RESPONDER_ROLE, ar->wmi.svc_map)) |
---|
| 9965 | + wiphy_ext_feature_set(ar->hw->wiphy, |
---|
| 9966 | + NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER); |
---|
| 9967 | + |
---|
| 9968 | + if (test_bit(WMI_SERVICE_TX_PWR_PER_PEER, ar->wmi.svc_map)) |
---|
| 9969 | + wiphy_ext_feature_set(ar->hw->wiphy, |
---|
| 9970 | + NL80211_EXT_FEATURE_STA_TX_PWR); |
---|
| 9971 | + |
---|
| 9972 | + if (test_bit(WMI_SERVICE_PEER_TID_CONFIGS_SUPPORT, ar->wmi.svc_map)) { |
---|
| 9973 | + ar->hw->wiphy->tid_config_support.vif |= |
---|
| 9974 | + BIT(NL80211_TID_CONFIG_ATTR_NOACK) | |
---|
| 9975 | + BIT(NL80211_TID_CONFIG_ATTR_RETRY_SHORT) | |
---|
| 9976 | + BIT(NL80211_TID_CONFIG_ATTR_RETRY_LONG) | |
---|
| 9977 | + BIT(NL80211_TID_CONFIG_ATTR_AMPDU_CTRL) | |
---|
| 9978 | + BIT(NL80211_TID_CONFIG_ATTR_TX_RATE) | |
---|
| 9979 | + BIT(NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE); |
---|
| 9980 | + |
---|
| 9981 | + if (test_bit(WMI_SERVICE_EXT_PEER_TID_CONFIGS_SUPPORT, |
---|
| 9982 | + ar->wmi.svc_map)) { |
---|
| 9983 | + ar->hw->wiphy->tid_config_support.vif |= |
---|
| 9984 | + BIT(NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL); |
---|
| 9985 | + } |
---|
| 9986 | + |
---|
| 9987 | + ar->hw->wiphy->tid_config_support.peer = |
---|
| 9988 | + ar->hw->wiphy->tid_config_support.vif; |
---|
| 9989 | + ar->hw->wiphy->max_data_retry_count = ATH10K_MAX_RETRY_COUNT; |
---|
| 9990 | + } else { |
---|
| 9991 | + ar->ops->set_tid_config = NULL; |
---|
| 9992 | + } |
---|
8479 | 9993 | /* |
---|
8480 | 9994 | * on LL hardware queues are managed entirely by the FW |
---|
8481 | 9995 | * so we only advertise to mac we can do the queues thing |
---|
.. | .. |
---|
8519 | 10033 | ar->hw->wiphy->iface_combinations = ath10k_10_4_if_comb; |
---|
8520 | 10034 | ar->hw->wiphy->n_iface_combinations = |
---|
8521 | 10035 | ARRAY_SIZE(ath10k_10_4_if_comb); |
---|
| 10036 | + if (test_bit(WMI_SERVICE_VDEV_DIFFERENT_BEACON_INTERVAL_SUPPORT, |
---|
| 10037 | + ar->wmi.svc_map)) { |
---|
| 10038 | + ar->hw->wiphy->iface_combinations = |
---|
| 10039 | + ath10k_10_4_bcn_int_if_comb; |
---|
| 10040 | + ar->hw->wiphy->n_iface_combinations = |
---|
| 10041 | + ARRAY_SIZE(ath10k_10_4_bcn_int_if_comb); |
---|
| 10042 | + } |
---|
8522 | 10043 | break; |
---|
8523 | 10044 | case ATH10K_FW_WMI_OP_VERSION_UNSET: |
---|
8524 | 10045 | case ATH10K_FW_WMI_OP_VERSION_MAX: |
---|
.. | .. |
---|
8578 | 10099 | |
---|
8579 | 10100 | wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); |
---|
8580 | 10101 | |
---|
| 10102 | + ar->hw->weight_multiplier = ATH10K_AIRTIME_WEIGHT_MULTIPLIER; |
---|
| 10103 | + |
---|
8581 | 10104 | ret = ieee80211_register_hw(ar->hw); |
---|
8582 | 10105 | if (ret) { |
---|
8583 | 10106 | ath10k_err(ar, "failed to register ieee80211: %d\n", ret); |
---|
8584 | 10107 | goto err_dfs_detector_exit; |
---|
8585 | 10108 | } |
---|
8586 | 10109 | |
---|
| 10110 | + if (test_bit(WMI_SERVICE_PER_PACKET_SW_ENCRYPT, ar->wmi.svc_map)) { |
---|
| 10111 | + ar->hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN); |
---|
| 10112 | + ar->hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_AP_VLAN); |
---|
| 10113 | + } |
---|
| 10114 | + |
---|
8587 | 10115 | if (!ath_is_world_regd(&ar->ath_common.regulatory)) { |
---|
8588 | 10116 | ret = regulatory_hint(ar->hw->wiphy, |
---|
8589 | 10117 | ar->ath_common.regulatory.alpha2); |
---|