diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath10k/htt_rx.c')
| -rw-r--r-- | drivers/net/wireless/ath/ath10k/htt_rx.c | 103 |
1 files changed, 76 insertions, 27 deletions
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index f42bac204ef8..4fc885617de1 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c | |||
| @@ -1,19 +1,8 @@ | |||
| 1 | // SPDX-License-Identifier: ISC | ||
| 1 | /* | 2 | /* |
| 2 | * Copyright (c) 2005-2011 Atheros Communications Inc. | 3 | * Copyright (c) 2005-2011 Atheros Communications Inc. |
| 3 | * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. | 4 | * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. |
| 4 | * Copyright (c) 2018, The Linux Foundation. All rights reserved. | 5 | * Copyright (c) 2018, The Linux Foundation. All rights reserved. |
| 5 | * | ||
| 6 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 7 | * purpose with or without fee is hereby granted, provided that the above | ||
| 8 | * copyright notice and this permission notice appear in all copies. | ||
| 9 | * | ||
| 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
| 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
| 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
| 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 17 | */ | 6 | */ |
| 18 | 7 | ||
| 19 | #include "core.h" | 8 | #include "core.h" |
| @@ -265,7 +254,7 @@ int ath10k_htt_rx_ring_refill(struct ath10k *ar) | |||
| 265 | struct ath10k_htt *htt = &ar->htt; | 254 | struct ath10k_htt *htt = &ar->htt; |
| 266 | int ret; | 255 | int ret; |
| 267 | 256 | ||
| 268 | if (ar->dev_type == ATH10K_DEV_TYPE_HL) | 257 | if (ar->bus_param.dev_type == ATH10K_DEV_TYPE_HL) |
| 269 | return 0; | 258 | return 0; |
| 270 | 259 | ||
| 271 | spin_lock_bh(&htt->rx_ring.lock); | 260 | spin_lock_bh(&htt->rx_ring.lock); |
| @@ -282,7 +271,7 @@ int ath10k_htt_rx_ring_refill(struct ath10k *ar) | |||
| 282 | 271 | ||
| 283 | void ath10k_htt_rx_free(struct ath10k_htt *htt) | 272 | void ath10k_htt_rx_free(struct ath10k_htt *htt) |
| 284 | { | 273 | { |
| 285 | if (htt->ar->dev_type == ATH10K_DEV_TYPE_HL) | 274 | if (htt->ar->bus_param.dev_type == ATH10K_DEV_TYPE_HL) |
| 286 | return; | 275 | return; |
| 287 | 276 | ||
| 288 | del_timer_sync(&htt->rx_ring.refill_retry_timer); | 277 | del_timer_sync(&htt->rx_ring.refill_retry_timer); |
| @@ -760,7 +749,7 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt) | |||
| 760 | size_t size; | 749 | size_t size; |
| 761 | struct timer_list *timer = &htt->rx_ring.refill_retry_timer; | 750 | struct timer_list *timer = &htt->rx_ring.refill_retry_timer; |
| 762 | 751 | ||
| 763 | if (ar->dev_type == ATH10K_DEV_TYPE_HL) | 752 | if (ar->bus_param.dev_type == ATH10K_DEV_TYPE_HL) |
| 764 | return 0; | 753 | return 0; |
| 765 | 754 | ||
| 766 | htt->rx_confused = false; | 755 | htt->rx_confused = false; |
| @@ -1905,7 +1894,7 @@ static void ath10k_htt_rx_h_enqueue(struct ath10k *ar, | |||
| 1905 | } | 1894 | } |
| 1906 | 1895 | ||
| 1907 | static int ath10k_unchain_msdu(struct sk_buff_head *amsdu, | 1896 | static int ath10k_unchain_msdu(struct sk_buff_head *amsdu, |
| 1908 | unsigned long int *unchain_cnt) | 1897 | unsigned long *unchain_cnt) |
| 1909 | { | 1898 | { |
| 1910 | struct sk_buff *skb, *first; | 1899 | struct sk_buff *skb, *first; |
| 1911 | int space; | 1900 | int space; |
| @@ -1954,8 +1943,8 @@ static int ath10k_unchain_msdu(struct sk_buff_head *amsdu, | |||
| 1954 | 1943 | ||
| 1955 | static void ath10k_htt_rx_h_unchain(struct ath10k *ar, | 1944 | static void ath10k_htt_rx_h_unchain(struct ath10k *ar, |
| 1956 | struct sk_buff_head *amsdu, | 1945 | struct sk_buff_head *amsdu, |
| 1957 | unsigned long int *drop_cnt, | 1946 | unsigned long *drop_cnt, |
| 1958 | unsigned long int *unchain_cnt) | 1947 | unsigned long *unchain_cnt) |
| 1959 | { | 1948 | { |
| 1960 | struct sk_buff *first; | 1949 | struct sk_buff *first; |
| 1961 | struct htt_rx_desc *rxd; | 1950 | struct htt_rx_desc *rxd; |
| @@ -2005,7 +1994,7 @@ static bool ath10k_htt_rx_amsdu_allowed(struct ath10k *ar, | |||
| 2005 | static void ath10k_htt_rx_h_filter(struct ath10k *ar, | 1994 | static void ath10k_htt_rx_h_filter(struct ath10k *ar, |
| 2006 | struct sk_buff_head *amsdu, | 1995 | struct sk_buff_head *amsdu, |
| 2007 | struct ieee80211_rx_status *rx_status, | 1996 | struct ieee80211_rx_status *rx_status, |
| 2008 | unsigned long int *drop_cnt) | 1997 | unsigned long *drop_cnt) |
| 2009 | { | 1998 | { |
| 2010 | if (skb_queue_empty(amsdu)) | 1999 | if (skb_queue_empty(amsdu)) |
| 2011 | return; | 2000 | return; |
| @@ -2025,10 +2014,10 @@ static int ath10k_htt_rx_handle_amsdu(struct ath10k_htt *htt) | |||
| 2025 | struct ieee80211_rx_status *rx_status = &htt->rx_status; | 2014 | struct ieee80211_rx_status *rx_status = &htt->rx_status; |
| 2026 | struct sk_buff_head amsdu; | 2015 | struct sk_buff_head amsdu; |
| 2027 | int ret; | 2016 | int ret; |
| 2028 | unsigned long int drop_cnt = 0; | 2017 | unsigned long drop_cnt = 0; |
| 2029 | unsigned long int unchain_cnt = 0; | 2018 | unsigned long unchain_cnt = 0; |
| 2030 | unsigned long int drop_cnt_filter = 0; | 2019 | unsigned long drop_cnt_filter = 0; |
| 2031 | unsigned long int msdus_to_queue, num_msdus; | 2020 | unsigned long msdus_to_queue, num_msdus; |
| 2032 | enum ath10k_pkt_rx_err err = ATH10K_PKT_RX_ERR_MAX; | 2021 | enum ath10k_pkt_rx_err err = ATH10K_PKT_RX_ERR_MAX; |
| 2033 | u8 first_hdr[RX_HTT_HDR_STATUS_LEN]; | 2022 | u8 first_hdr[RX_HTT_HDR_STATUS_LEN]; |
| 2034 | 2023 | ||
| @@ -2220,8 +2209,12 @@ static void ath10k_htt_rx_tx_compl_ind(struct ath10k *ar, | |||
| 2220 | int status = MS(resp->data_tx_completion.flags, HTT_DATA_TX_STATUS); | 2209 | int status = MS(resp->data_tx_completion.flags, HTT_DATA_TX_STATUS); |
| 2221 | __le16 msdu_id, *msdus; | 2210 | __le16 msdu_id, *msdus; |
| 2222 | bool rssi_enabled = false; | 2211 | bool rssi_enabled = false; |
| 2223 | u8 msdu_count = 0; | 2212 | u8 msdu_count = 0, num_airtime_records, tid; |
| 2224 | int i; | 2213 | int i; |
| 2214 | struct htt_data_tx_compl_ppdu_dur *ppdu_info; | ||
| 2215 | struct ath10k_peer *peer; | ||
| 2216 | u16 ppdu_info_offset = 0, peer_id; | ||
| 2217 | u32 tx_duration; | ||
| 2225 | 2218 | ||
| 2226 | switch (status) { | 2219 | switch (status) { |
| 2227 | case HTT_DATA_TX_STATUS_NO_ACK: | 2220 | case HTT_DATA_TX_STATUS_NO_ACK: |
| @@ -2245,12 +2238,12 @@ static void ath10k_htt_rx_tx_compl_ind(struct ath10k *ar, | |||
| 2245 | resp->data_tx_completion.num_msdus); | 2238 | resp->data_tx_completion.num_msdus); |
| 2246 | 2239 | ||
| 2247 | msdu_count = resp->data_tx_completion.num_msdus; | 2240 | msdu_count = resp->data_tx_completion.num_msdus; |
| 2241 | msdus = resp->data_tx_completion.msdus; | ||
| 2248 | 2242 | ||
| 2249 | if (resp->data_tx_completion.flags2 & HTT_TX_CMPL_FLAG_DATA_RSSI) | 2243 | if (resp->data_tx_completion.flags2 & HTT_TX_CMPL_FLAG_DATA_RSSI) |
| 2250 | rssi_enabled = true; | 2244 | rssi_enabled = true; |
| 2251 | 2245 | ||
| 2252 | for (i = 0; i < msdu_count; i++) { | 2246 | for (i = 0; i < msdu_count; i++) { |
| 2253 | msdus = resp->data_tx_completion.msdus; | ||
| 2254 | msdu_id = msdus[i]; | 2247 | msdu_id = msdus[i]; |
| 2255 | tx_done.msdu_id = __le16_to_cpu(msdu_id); | 2248 | tx_done.msdu_id = __le16_to_cpu(msdu_id); |
| 2256 | 2249 | ||
| @@ -2282,6 +2275,50 @@ static void ath10k_htt_rx_tx_compl_ind(struct ath10k *ar, | |||
| 2282 | ath10k_txrx_tx_unref(htt, &tx_done); | 2275 | ath10k_txrx_tx_unref(htt, &tx_done); |
| 2283 | } | 2276 | } |
| 2284 | } | 2277 | } |
| 2278 | |||
| 2279 | if (!(resp->data_tx_completion.flags2 & HTT_TX_CMPL_FLAG_PPDU_DURATION_PRESENT)) | ||
| 2280 | return; | ||
| 2281 | |||
| 2282 | ppdu_info_offset = (msdu_count & 0x01) ? msdu_count + 1 : msdu_count; | ||
| 2283 | |||
| 2284 | if (rssi_enabled) | ||
| 2285 | ppdu_info_offset += ppdu_info_offset; | ||
| 2286 | |||
| 2287 | if (resp->data_tx_completion.flags2 & | ||
| 2288 | (HTT_TX_CMPL_FLAG_PPID_PRESENT | HTT_TX_CMPL_FLAG_PA_PRESENT)) | ||
| 2289 | ppdu_info_offset += 2; | ||
| 2290 | |||
| 2291 | ppdu_info = (struct htt_data_tx_compl_ppdu_dur *)&msdus[ppdu_info_offset]; | ||
| 2292 | num_airtime_records = FIELD_GET(HTT_TX_COMPL_PPDU_DUR_INFO0_NUM_ENTRIES_MASK, | ||
| 2293 | __le32_to_cpu(ppdu_info->info0)); | ||
| 2294 | |||
| 2295 | for (i = 0; i < num_airtime_records; i++) { | ||
| 2296 | struct htt_data_tx_ppdu_dur *ppdu_dur; | ||
| 2297 | u32 info0; | ||
| 2298 | |||
| 2299 | ppdu_dur = &ppdu_info->ppdu_dur[i]; | ||
| 2300 | info0 = __le32_to_cpu(ppdu_dur->info0); | ||
| 2301 | |||
| 2302 | peer_id = FIELD_GET(HTT_TX_PPDU_DUR_INFO0_PEER_ID_MASK, | ||
| 2303 | info0); | ||
| 2304 | rcu_read_lock(); | ||
| 2305 | spin_lock_bh(&ar->data_lock); | ||
| 2306 | |||
| 2307 | peer = ath10k_peer_find_by_id(ar, peer_id); | ||
| 2308 | if (!peer) { | ||
| 2309 | spin_unlock_bh(&ar->data_lock); | ||
| 2310 | rcu_read_unlock(); | ||
| 2311 | continue; | ||
| 2312 | } | ||
| 2313 | |||
| 2314 | tid = FIELD_GET(HTT_TX_PPDU_DUR_INFO0_TID_MASK, info0); | ||
| 2315 | tx_duration = __le32_to_cpu(ppdu_dur->tx_duration); | ||
| 2316 | |||
| 2317 | ieee80211_sta_register_airtime(peer->sta, tid, tx_duration, 0); | ||
| 2318 | |||
| 2319 | spin_unlock_bh(&ar->data_lock); | ||
| 2320 | rcu_read_unlock(); | ||
| 2321 | } | ||
| 2285 | } | 2322 | } |
| 2286 | 2323 | ||
| 2287 | static void ath10k_htt_rx_addba(struct ath10k *ar, struct htt_resp *resp) | 2324 | static void ath10k_htt_rx_addba(struct ath10k *ar, struct htt_resp *resp) |
| @@ -2596,6 +2633,7 @@ static void ath10k_htt_rx_tx_fetch_ind(struct ath10k *ar, struct sk_buff *skb) | |||
| 2596 | u8 tid; | 2633 | u8 tid; |
| 2597 | int ret; | 2634 | int ret; |
| 2598 | int i; | 2635 | int i; |
| 2636 | bool may_tx; | ||
| 2599 | 2637 | ||
| 2600 | ath10k_dbg(ar, ATH10K_DBG_HTT, "htt rx tx fetch ind\n"); | 2638 | ath10k_dbg(ar, ATH10K_DBG_HTT, "htt rx tx fetch ind\n"); |
| 2601 | 2639 | ||
| @@ -2668,8 +2706,13 @@ static void ath10k_htt_rx_tx_fetch_ind(struct ath10k *ar, struct sk_buff *skb) | |||
| 2668 | num_msdus = 0; | 2706 | num_msdus = 0; |
| 2669 | num_bytes = 0; | 2707 | num_bytes = 0; |
| 2670 | 2708 | ||
| 2709 | ieee80211_txq_schedule_start(hw, txq->ac); | ||
| 2710 | may_tx = ieee80211_txq_may_transmit(hw, txq); | ||
| 2671 | while (num_msdus < max_num_msdus && | 2711 | while (num_msdus < max_num_msdus && |
| 2672 | num_bytes < max_num_bytes) { | 2712 | num_bytes < max_num_bytes) { |
| 2713 | if (!may_tx) | ||
| 2714 | break; | ||
| 2715 | |||
| 2673 | ret = ath10k_mac_tx_push_txq(hw, txq); | 2716 | ret = ath10k_mac_tx_push_txq(hw, txq); |
| 2674 | if (ret < 0) | 2717 | if (ret < 0) |
| 2675 | break; | 2718 | break; |
| @@ -2677,6 +2720,8 @@ static void ath10k_htt_rx_tx_fetch_ind(struct ath10k *ar, struct sk_buff *skb) | |||
| 2677 | num_msdus++; | 2720 | num_msdus++; |
| 2678 | num_bytes += ret; | 2721 | num_bytes += ret; |
| 2679 | } | 2722 | } |
| 2723 | ieee80211_return_txq(hw, txq); | ||
| 2724 | ieee80211_txq_schedule_end(hw, txq->ac); | ||
| 2680 | 2725 | ||
| 2681 | record->num_msdus = cpu_to_le16(num_msdus); | 2726 | record->num_msdus = cpu_to_le16(num_msdus); |
| 2682 | record->num_bytes = cpu_to_le32(num_bytes); | 2727 | record->num_bytes = cpu_to_le32(num_bytes); |
| @@ -2975,6 +3020,8 @@ ath10k_accumulate_per_peer_tx_stats(struct ath10k *ar, | |||
| 2975 | STATS_OP_FMT(RETRY).rate_table[0][idx] += pstats->retry_bytes; | 3020 | STATS_OP_FMT(RETRY).rate_table[0][idx] += pstats->retry_bytes; |
| 2976 | STATS_OP_FMT(RETRY).rate_table[1][idx] += pstats->retry_pkts; | 3021 | STATS_OP_FMT(RETRY).rate_table[1][idx] += pstats->retry_pkts; |
| 2977 | } | 3022 | } |
| 3023 | |||
| 3024 | tx_stats->tx_duration += pstats->duration; | ||
| 2978 | } | 3025 | } |
| 2979 | 3026 | ||
| 2980 | static void | 3027 | static void |
| @@ -3070,6 +3117,7 @@ ath10k_update_per_peer_tx_stats(struct ath10k *ar, | |||
| 3070 | 3117 | ||
| 3071 | arsta->txrate.nss = txrate.nss; | 3118 | arsta->txrate.nss = txrate.nss; |
| 3072 | arsta->txrate.bw = ath10k_bw_to_mac80211_bw(txrate.bw); | 3119 | arsta->txrate.bw = ath10k_bw_to_mac80211_bw(txrate.bw); |
| 3120 | arsta->last_tx_bitrate = cfg80211_calculate_bitrate(&arsta->txrate); | ||
| 3073 | if (sgi) | 3121 | if (sgi) |
| 3074 | arsta->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; | 3122 | arsta->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; |
| 3075 | 3123 | ||
| @@ -3141,6 +3189,7 @@ static void ath10k_htt_fetch_peer_stats(struct ath10k *ar, | |||
| 3141 | p_tx_stats->succ_pkts = __le16_to_cpu(tx_stats->succ_pkts); | 3189 | p_tx_stats->succ_pkts = __le16_to_cpu(tx_stats->succ_pkts); |
| 3142 | p_tx_stats->retry_pkts = __le16_to_cpu(tx_stats->retry_pkts); | 3190 | p_tx_stats->retry_pkts = __le16_to_cpu(tx_stats->retry_pkts); |
| 3143 | p_tx_stats->failed_pkts = __le16_to_cpu(tx_stats->failed_pkts); | 3191 | p_tx_stats->failed_pkts = __le16_to_cpu(tx_stats->failed_pkts); |
| 3192 | p_tx_stats->duration = __le16_to_cpu(tx_stats->tx_duration); | ||
| 3144 | 3193 | ||
| 3145 | ath10k_update_per_peer_tx_stats(ar, sta, p_tx_stats); | 3194 | ath10k_update_per_peer_tx_stats(ar, sta, p_tx_stats); |
| 3146 | } | 3195 | } |
| @@ -3234,7 +3283,7 @@ bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) | |||
| 3234 | break; | 3283 | break; |
| 3235 | } | 3284 | } |
| 3236 | case HTT_T2H_MSG_TYPE_RX_IND: | 3285 | case HTT_T2H_MSG_TYPE_RX_IND: |
| 3237 | if (ar->dev_type == ATH10K_DEV_TYPE_HL) | 3286 | if (ar->bus_param.dev_type == ATH10K_DEV_TYPE_HL) |
| 3238 | return ath10k_htt_rx_proc_rx_ind_hl(htt, | 3287 | return ath10k_htt_rx_proc_rx_ind_hl(htt, |
| 3239 | &resp->rx_ind_hl, | 3288 | &resp->rx_ind_hl, |
| 3240 | skb); | 3289 | skb); |
| @@ -3530,7 +3579,7 @@ void ath10k_htt_set_rx_ops(struct ath10k_htt *htt) | |||
| 3530 | { | 3579 | { |
| 3531 | struct ath10k *ar = htt->ar; | 3580 | struct ath10k *ar = htt->ar; |
| 3532 | 3581 | ||
| 3533 | if (ar->dev_type == ATH10K_DEV_TYPE_HL) | 3582 | if (ar->bus_param.dev_type == ATH10K_DEV_TYPE_HL) |
| 3534 | htt->rx_ops = &htt_rx_ops_hl; | 3583 | htt->rx_ops = &htt_rx_ops_hl; |
| 3535 | else if (ar->hw_params.target_64bit) | 3584 | else if (ar->hw_params.target_64bit) |
| 3536 | htt->rx_ops = &htt_rx_ops_64; | 3585 | htt->rx_ops = &htt_rx_ops_64; |
