summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/ath/ath10k/htt_rx.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-04-03 14:04:18 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2018-04-03 14:04:18 -0700
commit5bb053bef82523a8fd78d650bca81c9f114fa276 (patch)
tree58c2fe47f60bb69230bb05d57a6c9e3f47f7b1fe /drivers/net/wireless/ath/ath10k/htt_rx.c
parentbb2407a7219760926760f0448fddf00d625e5aec (diff)
parent159f02977b2feb18a4bece5e586c838a6d26d44b (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
Pull networking updates from David Miller: 1) Support offloading wireless authentication to userspace via NL80211_CMD_EXTERNAL_AUTH, from Srinivas Dasari. 2) A lot of work on network namespace setup/teardown from Kirill Tkhai. Setup and cleanup of namespaces now all run asynchronously and thus performance is significantly increased. 3) Add rx/tx timestamping support to mv88e6xxx driver, from Brandon Streiff. 4) Support zerocopy on RDS sockets, from Sowmini Varadhan. 5) Use denser instruction encoding in x86 eBPF JIT, from Daniel Borkmann. 6) Support hw offload of vlan filtering in mvpp2 dreiver, from Maxime Chevallier. 7) Support grafting of child qdiscs in mlxsw driver, from Nogah Frankel. 8) Add packet forwarding tests to selftests, from Ido Schimmel. 9) Deal with sub-optimal GSO packets better in BBR congestion control, from Eric Dumazet. 10) Support 5-tuple hashing in ipv6 multipath routing, from David Ahern. 11) Add path MTU tests to selftests, from Stefano Brivio. 12) Various bits of IPSEC offloading support for mlx5, from Aviad Yehezkel, Yossi Kuperman, and Saeed Mahameed. 13) Support RSS spreading on ntuple filters in SFC driver, from Edward Cree. 14) Lots of sockmap work from John Fastabend. Applications can use eBPF to filter sendmsg and sendpage operations. 15) In-kernel receive TLS support, from Dave Watson. 16) Add XDP support to ixgbevf, this is significant because it should allow optimized XDP usage in various cloud environments. From Tony Nguyen. 17) Add new Intel E800 series "ice" ethernet driver, from Anirudh Venkataramanan et al. 18) IP fragmentation match offload support in nfp driver, from Pieter Jansen van Vuuren. 19) Support XDP redirect in i40e driver, from Björn Töpel. 20) Add BPF_RAW_TRACEPOINT program type for accessing the arguments of tracepoints in their raw form, from Alexei Starovoitov. 21) Lots of striding RQ improvements to mlx5 driver with many performance improvements, from Tariq Toukan. 22) Use rhashtable for inet frag reassembly, from Eric Dumazet. * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1678 commits) net: mvneta: improve suspend/resume net: mvneta: split rxq/txq init and txq deinit into SW and HW parts ipv6: frags: fix /proc/sys/net/ipv6/ip6frag_low_thresh net: bgmac: Fix endian access in bgmac_dma_tx_ring_free() net: bgmac: Correctly annotate register space route: check sysctl_fib_multipath_use_neigh earlier than hash fix typo in command value in drivers/net/phy/mdio-bitbang. sky2: Increase D3 delay to sky2 stops working after suspend net/mlx5e: Set EQE based as default TX interrupt moderation mode ibmvnic: Disable irqs before exiting reset from closed state net: sched: do not emit messages while holding spinlock vlan: also check phy_driver ts_info for vlan's real device Bluetooth: Mark expected switch fall-throughs Bluetooth: Set HCI_QUIRK_SIMULTANEOUS_DISCOVERY for BTUSB_QCA_ROME Bluetooth: btrsi: remove unused including <linux/version.h> Bluetooth: hci_bcm: Remove DMI quirk for the MINIX Z83-4 sh_eth: kill useless check in __sh_eth_get_regs() sh_eth: add sh_eth_cpu_data::no_xdfar flag ipv6: factorize sk_wmem_alloc updates done by __ip6_append_data() ipv4: factorize sk_wmem_alloc updates done by __ip_append_data() ...
Diffstat (limited to 'drivers/net/wireless/ath/ath10k/htt_rx.c')
-rw-r--r--drivers/net/wireless/ath/ath10k/htt_rx.c113
1 files changed, 85 insertions, 28 deletions
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 6d96f9560950..5e02e26158f6 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -723,6 +724,28 @@ struct amsdu_subframe_hdr {
#define GROUP_ID_IS_SU_MIMO(x) ((x) == 0 || (x) == 63)
+static inline u8 ath10k_bw_to_mac80211_bw(u8 bw)
+{
+ u8 ret = 0;
+
+ switch (bw) {
+ case 0:
+ ret = RATE_INFO_BW_20;
+ break;
+ case 1:
+ ret = RATE_INFO_BW_40;
+ break;
+ case 2:
+ ret = RATE_INFO_BW_80;
+ break;
+ case 3:
+ ret = RATE_INFO_BW_160;
+ break;
+ }
+
+ return ret;
+}
+
static void ath10k_htt_rx_h_rates(struct ath10k *ar,
struct ieee80211_rx_status *status,
struct htt_rx_desc *rxd)
@@ -825,23 +848,7 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar,
if (sgi)
status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
- switch (bw) {
- /* 20MHZ */
- case 0:
- break;
- /* 40MHZ */
- case 1:
- status->bw = RATE_INFO_BW_40;
- break;
- /* 80MHZ */
- case 2:
- status->bw = RATE_INFO_BW_80;
- break;
- case 3:
- status->bw = RATE_INFO_BW_160;
- break;
- }
-
+ status->bw = ath10k_bw_to_mac80211_bw(bw);
status->encoding = RX_ENC_VHT;
break;
default:
@@ -1502,7 +1509,9 @@ static void ath10k_htt_rx_h_csum_offload(struct sk_buff *msdu)
static void ath10k_htt_rx_h_mpdu(struct ath10k *ar,
struct sk_buff_head *amsdu,
struct ieee80211_rx_status *status,
- bool fill_crypt_header)
+ bool fill_crypt_header,
+ u8 *rx_hdr,
+ enum ath10k_pkt_rx_err *err)
{
struct sk_buff *first;
struct sk_buff *last;
@@ -1538,6 +1547,9 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar,
hdr = (void *)rxd->rx_hdr_status;
memcpy(first_hdr, hdr, RX_HTT_HDR_STATUS_LEN);
+ if (rx_hdr)
+ memcpy(rx_hdr, hdr, RX_HTT_HDR_STATUS_LEN);
+
/* Each A-MSDU subframe will use the original header as the base and be
* reported as a separate MSDU so strip the A-MSDU bit from QoS Ctl.
*/
@@ -1581,6 +1593,17 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar,
if (has_tkip_err)
status->flag |= RX_FLAG_MMIC_ERROR;
+ if (err) {
+ if (has_fcs_err)
+ *err = ATH10K_PKT_RX_ERR_FCS;
+ else if (has_tkip_err)
+ *err = ATH10K_PKT_RX_ERR_TKIP;
+ else if (has_crypto_err)
+ *err = ATH10K_PKT_RX_ERR_CRYPT;
+ else if (has_peer_idx_invalid)
+ *err = ATH10K_PKT_RX_ERR_PEER_IDX_INVAL;
+ }
+
/* Firmware reports all necessary management frames via WMI already.
* They are not reported to monitor interfaces at all so pass the ones
* coming via HTT to monitor interfaces instead. This simplifies
@@ -1651,11 +1674,13 @@ static void ath10k_htt_rx_h_enqueue(struct ath10k *ar,
}
}
-static int ath10k_unchain_msdu(struct sk_buff_head *amsdu)
+static int ath10k_unchain_msdu(struct sk_buff_head *amsdu,
+ unsigned long int *unchain_cnt)
{
struct sk_buff *skb, *first;
int space;
int total_len = 0;
+ int amsdu_len = skb_queue_len(amsdu);
/* TODO: Might could optimize this by using
* skb_try_coalesce or similar method to
@@ -1691,11 +1716,16 @@ static int ath10k_unchain_msdu(struct sk_buff_head *amsdu)
}
__skb_queue_head(amsdu, first);
+
+ *unchain_cnt += amsdu_len - 1;
+
return 0;
}
static void ath10k_htt_rx_h_unchain(struct ath10k *ar,
- struct sk_buff_head *amsdu)
+ struct sk_buff_head *amsdu,
+ unsigned long int *drop_cnt,
+ unsigned long int *unchain_cnt)
{
struct sk_buff *first;
struct htt_rx_desc *rxd;
@@ -1713,11 +1743,12 @@ static void ath10k_htt_rx_h_unchain(struct ath10k *ar,
*/
if (decap != RX_MSDU_DECAP_RAW ||
skb_queue_len(amsdu) != 1 + rxd->frag_info.ring2_more_count) {
+ *drop_cnt += skb_queue_len(amsdu);
__skb_queue_purge(amsdu);
return;
}
- ath10k_unchain_msdu(amsdu);
+ ath10k_unchain_msdu(amsdu, unchain_cnt);
}
static bool ath10k_htt_rx_amsdu_allowed(struct ath10k *ar,
@@ -1743,7 +1774,8 @@ static bool ath10k_htt_rx_amsdu_allowed(struct ath10k *ar,
static void ath10k_htt_rx_h_filter(struct ath10k *ar,
struct sk_buff_head *amsdu,
- struct ieee80211_rx_status *rx_status)
+ struct ieee80211_rx_status *rx_status,
+ unsigned long int *drop_cnt)
{
if (skb_queue_empty(amsdu))
return;
@@ -1751,6 +1783,9 @@ static void ath10k_htt_rx_h_filter(struct ath10k *ar,
if (ath10k_htt_rx_amsdu_allowed(ar, amsdu, rx_status))
return;
+ if (drop_cnt)
+ *drop_cnt += skb_queue_len(amsdu);
+
__skb_queue_purge(amsdu);
}
@@ -1760,6 +1795,12 @@ static int ath10k_htt_rx_handle_amsdu(struct ath10k_htt *htt)
struct ieee80211_rx_status *rx_status = &htt->rx_status;
struct sk_buff_head amsdu;
int ret;
+ unsigned long int drop_cnt = 0;
+ unsigned long int unchain_cnt = 0;
+ unsigned long int drop_cnt_filter = 0;
+ unsigned long int msdus_to_queue, num_msdus;
+ enum ath10k_pkt_rx_err err = ATH10K_PKT_RX_ERR_MAX;
+ u8 first_hdr[RX_HTT_HDR_STATUS_LEN];
__skb_queue_head_init(&amsdu);
@@ -1781,16 +1822,23 @@ static int ath10k_htt_rx_handle_amsdu(struct ath10k_htt *htt)
return ret;
}
+ num_msdus = skb_queue_len(&amsdu);
+
ath10k_htt_rx_h_ppdu(ar, &amsdu, rx_status, 0xffff);
/* only for ret = 1 indicates chained msdus */
if (ret > 0)
- ath10k_htt_rx_h_unchain(ar, &amsdu);
+ ath10k_htt_rx_h_unchain(ar, &amsdu, &drop_cnt, &unchain_cnt);
- ath10k_htt_rx_h_filter(ar, &amsdu, rx_status);
- ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status, true);
+ ath10k_htt_rx_h_filter(ar, &amsdu, rx_status, &drop_cnt_filter);
+ ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status, true, first_hdr, &err);
+ msdus_to_queue = skb_queue_len(&amsdu);
ath10k_htt_rx_h_enqueue(ar, &amsdu, rx_status);
+ ath10k_sta_update_rx_tid_stats(ar, first_hdr, num_msdus, err,
+ unchain_cnt, drop_cnt, drop_cnt_filter,
+ msdus_to_queue);
+
return 0;
}
@@ -1801,9 +1849,14 @@ static void ath10k_htt_rx_proc_rx_ind(struct ath10k_htt *htt,
struct htt_rx_indication_mpdu_range *mpdu_ranges;
int num_mpdu_ranges;
int i, mpdu_count = 0;
+ u16 peer_id;
+ u8 tid;
num_mpdu_ranges = MS(__le32_to_cpu(rx->hdr.info1),
HTT_RX_INDICATION_INFO1_NUM_MPDU_RANGES);
+ peer_id = __le16_to_cpu(rx->hdr.peer_id);
+ tid = MS(rx->hdr.info0, HTT_RX_INDICATION_INFO0_EXT_TID);
+
mpdu_ranges = htt_rx_ind_get_mpdu_ranges(rx);
ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt rx ind: ",
@@ -1815,6 +1868,9 @@ static void ath10k_htt_rx_proc_rx_ind(struct ath10k_htt *htt,
mpdu_count += mpdu_ranges[i].mpdu_count;
atomic_add(mpdu_count, &htt->num_mpdus_ready);
+
+ ath10k_sta_update_rx_tid_stats_ampdu(ar, peer_id, tid, mpdu_ranges,
+ num_mpdu_ranges);
}
static void ath10k_htt_rx_tx_compl_ind(struct ath10k *ar,
@@ -2124,8 +2180,9 @@ static int ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb)
* should still give an idea about rx rate to the user.
*/
ath10k_htt_rx_h_ppdu(ar, &amsdu, status, vdev_id);
- ath10k_htt_rx_h_filter(ar, &amsdu, status);
- ath10k_htt_rx_h_mpdu(ar, &amsdu, status, false);
+ ath10k_htt_rx_h_filter(ar, &amsdu, status, NULL);
+ ath10k_htt_rx_h_mpdu(ar, &amsdu, status, false, NULL,
+ NULL);
ath10k_htt_rx_h_enqueue(ar, &amsdu, status);
break;
case -EAGAIN:
@@ -2499,7 +2556,7 @@ ath10k_update_per_peer_tx_stats(struct ath10k *ar,
arsta->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
arsta->txrate.nss = txrate.nss;
- arsta->txrate.bw = txrate.bw + RATE_INFO_BW_20;
+ arsta->txrate.bw = ath10k_bw_to_mac80211_bw(txrate.bw);
}
static void ath10k_htt_fetch_peer_stats(struct ath10k *ar,