diff options
author | Kalle Valo <kvalo@codeaurora.org> | 2017-12-14 18:38:48 +0200 |
---|---|---|
committer | Kalle Valo <kvalo@codeaurora.org> | 2017-12-14 18:38:48 +0200 |
commit | 1dde35d0b8e3a9fbf24e13d16dc583f1cc5d027b (patch) | |
tree | 14418168dd854cc6a795cc200352646032c4e5bc /drivers/net | |
parent | 7de241f3b705396fe21f45d38ba1247c522aae81 (diff) | |
parent | 03a72288c546289cfa0eb1e3613fb9cdb302b4f9 (diff) |
Merge ath-next from git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
ath.git patches for 4.16. Major changes:
ath10k
* enable multiqueue support for all hw using mac80211 wake_tx_queue op
* new Kconfig option ATH10K_SPECTRAL to save RAM
* show tx stats on QCA9880
* new qcom,ath10k-calibration-variant DT entry
* WMI layer support for wcn3990
ath9k
* new Kconfig option ATH9K_COMMON_SPECTRAL to save RAM
wcn36xx
* hardware scan offload support
wil6210
* run-time PM support when interface is down
Diffstat (limited to 'drivers/net')
41 files changed, 1654 insertions, 337 deletions
diff --git a/drivers/net/wireless/ath/ath10k/Kconfig b/drivers/net/wireless/ath/ath10k/Kconfig index 87f56d0e17a6..deb5ae21a559 100644 --- a/drivers/net/wireless/ath/ath10k/Kconfig +++ b/drivers/net/wireless/ath/ath10k/Kconfig @@ -47,12 +47,19 @@ config ATH10K_DEBUG config ATH10K_DEBUGFS bool "Atheros ath10k debugfs support" depends on ATH10K && DEBUG_FS - select RELAY ---help--- Enabled debugfs support If unsure, say Y to make it easier to debug problems. +config ATH10K_SPECTRAL + bool "Atheros ath10k spectral scan support" + depends on ATH10K_DEBUGFS + select RELAY + default n + ---help--- + Say Y to enable access to the FFT/spectral data via debugfs. + config ATH10K_TRACING bool "Atheros ath10k tracing support" depends on ATH10K diff --git a/drivers/net/wireless/ath/ath10k/Makefile b/drivers/net/wireless/ath/ath10k/Makefile index 9492177e9063..8d9a59b7144e 100644 --- a/drivers/net/wireless/ath/ath10k/Makefile +++ b/drivers/net/wireless/ath/ath10k/Makefile @@ -15,7 +15,7 @@ ath10k_core-y += mac.o \ p2p.o \ swap.o -ath10k_core-$(CONFIG_ATH10K_DEBUGFS) += spectral.o +ath10k_core-$(CONFIG_ATH10K_SPECTRAL) += spectral.o ath10k_core-$(CONFIG_NL80211_TESTMODE) += testmode.o ath10k_core-$(CONFIG_ATH10K_TRACING) += trace.o ath10k_core-$(CONFIG_THERMAL) += thermal.o diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index b29fdbd21ead..6d065f8d7f78 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -75,6 +75,9 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .vht160_mcs_rx_highest = 0, .vht160_mcs_tx_highest = 0, .n_cipher_suites = 8, + .num_peers = TARGET_TLV_NUM_PEERS, + .ast_skid_limit = 0x10, + .num_wds_entries = 0x20, }, { .id = QCA9887_HW_1_0_VERSION, @@ -99,6 +102,9 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .vht160_mcs_rx_highest = 0, .vht160_mcs_tx_highest = 0, .n_cipher_suites = 8, + .num_peers = TARGET_TLV_NUM_PEERS, + .ast_skid_limit = 0x10, + .num_wds_entries = 0x20, }, { .id = QCA6174_HW_2_1_VERSION, @@ -122,6 +128,9 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .vht160_mcs_rx_highest = 0, .vht160_mcs_tx_highest = 0, .n_cipher_suites = 8, + .num_peers = TARGET_TLV_NUM_PEERS, + .ast_skid_limit = 0x10, + .num_wds_entries = 0x20, }, { .id = QCA6174_HW_2_1_VERSION, @@ -145,6 +154,9 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .vht160_mcs_rx_highest = 0, .vht160_mcs_tx_highest = 0, .n_cipher_suites = 8, + .num_peers = TARGET_TLV_NUM_PEERS, + .ast_skid_limit = 0x10, + .num_wds_entries = 0x20, }, { .id = QCA6174_HW_3_0_VERSION, @@ -168,6 +180,9 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .vht160_mcs_rx_highest = 0, .vht160_mcs_tx_highest = 0, .n_cipher_suites = 8, + .num_peers = TARGET_TLV_NUM_PEERS, + .ast_skid_limit = 0x10, + .num_wds_entries = 0x20, }, { .id = QCA6174_HW_3_2_VERSION, @@ -194,6 +209,9 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .vht160_mcs_rx_highest = 0, .vht160_mcs_tx_highest = 0, .n_cipher_suites = 8, + .num_peers = TARGET_TLV_NUM_PEERS, + .ast_skid_limit = 0x10, + .num_wds_entries = 0x20, }, { .id = QCA99X0_HW_2_0_DEV_VERSION, @@ -223,6 +241,9 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .vht160_mcs_rx_highest = 0, .vht160_mcs_tx_highest = 0, .n_cipher_suites = 11, + .num_peers = TARGET_TLV_NUM_PEERS, + .ast_skid_limit = 0x10, + .num_wds_entries = 0x20, }, { .id = QCA9984_HW_1_0_DEV_VERSION, @@ -257,6 +278,9 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .vht160_mcs_rx_highest = 1560, .vht160_mcs_tx_highest = 1560, .n_cipher_suites = 11, + .num_peers = TARGET_TLV_NUM_PEERS, + .ast_skid_limit = 0x10, + .num_wds_entries = 0x20, }, { .id = QCA9888_HW_2_0_DEV_VERSION, @@ -290,6 +314,9 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .vht160_mcs_rx_highest = 780, .vht160_mcs_tx_highest = 780, .n_cipher_suites = 11, + .num_peers = TARGET_TLV_NUM_PEERS, + .ast_skid_limit = 0x10, + .num_wds_entries = 0x20, }, { .id = QCA9377_HW_1_0_DEV_VERSION, @@ -313,6 +340,9 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .vht160_mcs_rx_highest = 0, .vht160_mcs_tx_highest = 0, .n_cipher_suites = 8, + .num_peers = TARGET_TLV_NUM_PEERS, + .ast_skid_limit = 0x10, + .num_wds_entries = 0x20, }, { .id = QCA9377_HW_1_1_DEV_VERSION, @@ -338,6 +368,9 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .vht160_mcs_rx_highest = 0, .vht160_mcs_tx_highest = 0, .n_cipher_suites = 8, + .num_peers = TARGET_TLV_NUM_PEERS, + .ast_skid_limit = 0x10, + .num_wds_entries = 0x20, }, { .id = QCA4019_HW_1_0_DEV_VERSION, @@ -368,6 +401,27 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .vht160_mcs_rx_highest = 0, .vht160_mcs_tx_highest = 0, .n_cipher_suites = 11, + .num_peers = TARGET_TLV_NUM_PEERS, + .ast_skid_limit = 0x10, + .num_wds_entries = 0x20, + }, + { + .id = WCN3990_HW_1_0_DEV_VERSION, + .dev_id = 0, + .name = "wcn3990 hw1.0", + .continuous_frag_desc = true, + .tx_chain_mask = 0x7, + .rx_chain_mask = 0x7, + .max_spatial_stream = 4, + .fw = { + .dir = WCN3990_HW_1_0_FW_DIR, + }, + .sw_decrypt_mcast_mgmt = true, + .hw_ops = &wcn3990_ops, + .decap_align_bytes = 1, + .num_peers = TARGET_HL_10_TLV_NUM_PEERS, + .ast_skid_limit = TARGET_HL_10_TLV_AST_SKID_LIMIT, + .num_wds_entries = TARGET_HL_10_TLV_NUM_WDS_ENTRIES, }, }; @@ -390,6 +444,7 @@ static const char *const ath10k_core_fw_feature_str[] = { [ATH10K_FW_FEATURE_SKIP_NULL_FUNC_WAR] = "skip-null-func-war", [ATH10K_FW_FEATURE_ALLOWS_MESH_BCAST] = "allows-mesh-bcast", [ATH10K_FW_FEATURE_NO_PS] = "no-ps", + [ATH10K_FW_FEATURE_MGMT_TX_BY_REF] = "mgmt-tx-by-reference", }; static unsigned int ath10k_core_get_fw_feature_str(char *buf, @@ -860,6 +915,28 @@ static int ath10k_core_check_smbios(struct ath10k *ar) return 0; } +static int ath10k_core_check_dt(struct ath10k *ar) +{ + struct device_node *node; + const char *variant = NULL; + + node = ar->dev->of_node; + if (!node) + return -ENOENT; + + of_property_read_string(node, "qcom,ath10k-calibration-variant", + &variant); + if (!variant) + return -ENODATA; + + if (strscpy(ar->id.bdf_ext, variant, sizeof(ar->id.bdf_ext)) < 0) + ath10k_dbg(ar, ATH10K_DBG_BOOT, + "bdf variant string is longer than the buffer can accommodate (variant: %s)\n", + variant); + + return 0; +} + static int ath10k_download_and_run_otp(struct ath10k *ar) { u32 result, address = ar->hw_params.patch_load_addr; @@ -1231,19 +1308,19 @@ static int ath10k_core_create_board_name(struct ath10k *ar, char *name, /* strlen(',variant=') + strlen(ar->id.bdf_ext) */ char variant[9 + ATH10K_SMBIOS_BDF_EXT_STR_LENGTH] = { 0 }; + if (ar->id.bdf_ext[0] != '\0') + scnprintf(variant, sizeof(variant), ",variant=%s", + ar->id.bdf_ext); + if (ar->id.bmi_ids_valid) { scnprintf(name, name_len, - "bus=%s,bmi-chip-id=%d,bmi-board-id=%d", + "bus=%s,bmi-chip-id=%d,bmi-board-id=%d%s", ath10k_bus_str(ar->hif.bus), ar->id.bmi_chip_id, - ar->id.bmi_board_id); + ar->id.bmi_board_id, variant); goto out; } - if (ar->id.bdf_ext[0] != '\0') - scnprintf(variant, sizeof(variant), ",variant=%s", - ar->id.bdf_ext); - scnprintf(name, name_len, "bus=%s,vendor=%04x,device=%04x,subsystem-vendor=%04x,subsystem-device=%04x%s", ath10k_bus_str(ar->hif.bus), @@ -2343,7 +2420,11 @@ static int ath10k_core_probe_fw(struct ath10k *ar) ret = ath10k_core_check_smbios(ar); if (ret) - ath10k_dbg(ar, ATH10K_DBG_BOOT, "bdf variant name not set.\n"); + ath10k_dbg(ar, ATH10K_DBG_BOOT, "SMBIOS bdf variant name not set.\n"); + + ret = ath10k_core_check_dt(ar); + if (ret) + ath10k_dbg(ar, ATH10K_DBG_BOOT, "DT bdf variant name not set.\n"); ret = ath10k_core_fetch_board_file(ar); if (ret) { diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 643041ef3271..631df2137e25 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -67,7 +67,6 @@ /* NAPI poll budget */ #define ATH10K_NAPI_BUDGET 64 -#define ATH10K_NAPI_QUOTA_LIMIT 60 /* SMBIOS type containing Board Data File Name Extension */ #define ATH10K_SMBIOS_BDF_EXT_TYPE 0xF8 @@ -364,11 +363,11 @@ struct ath10k_sta { struct rate_info txrate; struct work_struct update_wk; + u64 rx_duration; #ifdef CONFIG_MAC80211_DEBUGFS /* protected by conf_mutex */ bool aggr_mode; - u64 rx_duration; #endif }; @@ -463,7 +462,7 @@ struct ath10k_fw_crash_data { bool crashed_since_read; guid_t guid; - struct timespec timestamp; + struct timespec64 timestamp; __le32 registers[REG_DUMP_COUNT_QCA988X]; struct ath10k_ce_crash_data ce_crash_data[CE_COUNT_MAX]; }; @@ -488,7 +487,6 @@ struct ath10k_debug { /* protected by conf_mutex */ u64 fw_dbglog_mask; u32 fw_dbglog_level; - u32 pktlog_filter; u32 reg_addr; u32 nf_cal_period; void *cal_data; @@ -615,6 +613,9 @@ enum ath10k_fw_features { /* Firmware does not support power save in station mode. */ ATH10K_FW_FEATURE_NO_PS = 17, + /* Firmware allows management tx by reference instead of by value. */ + ATH10K_FW_FEATURE_MGMT_TX_BY_REF = 18, + /* keep last */ ATH10K_FW_FEATURE_COUNT, }; @@ -963,6 +964,7 @@ struct ath10k { } spectral; #endif + u32 pktlog_filter; struct { /* protected by conf_mutex */ struct ath10k_fw_components utf_mode_fw; diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index df514507d3f1..181fd8e2e615 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c @@ -720,7 +720,7 @@ ath10k_debug_get_new_fw_crash_data(struct ath10k *ar) crash_data->crashed_since_read = true; guid_gen(&crash_data->guid); - getnstimeofday(&crash_data->timestamp); + ktime_get_real_ts64(&crash_data->timestamp); return crash_data; } @@ -1950,14 +1950,14 @@ int ath10k_debug_start(struct ath10k *ar) ret); } - if (ar->debug.pktlog_filter) { + if (ar->pktlog_filter) { ret = ath10k_wmi_pdev_pktlog_enable(ar, - ar->debug.pktlog_filter); + ar->pktlog_filter); if (ret) /* not serious */ ath10k_warn(ar, "failed to enable pktlog filter %x: %d\n", - ar->debug.pktlog_filter, ret); + ar->pktlog_filter, ret); } else { ret = ath10k_wmi_pdev_pktlog_disable(ar); if (ret) @@ -2097,12 +2097,12 @@ static ssize_t ath10k_write_pktlog_filter(struct file *file, mutex_lock(&ar->conf_mutex); if (ar->state != ATH10K_STATE_ON) { - ar->debug.pktlog_filter = filter; + ar->pktlog_filter = filter; ret = count; goto out; } - if (filter == ar->debug.pktlog_filter) { + if (filter == ar->pktlog_filter) { ret = count; goto out; } @@ -2111,7 +2111,7 @@ static ssize_t ath10k_write_pktlog_filter(struct file *file, ret = ath10k_wmi_pdev_pktlog_enable(ar, filter); if (ret) { ath10k_warn(ar, "failed to enable pktlog filter %x: %d\n", - ar->debug.pktlog_filter, ret); + ar->pktlog_filter, ret); goto out; } } else { @@ -2122,7 +2122,7 @@ static ssize_t ath10k_write_pktlog_filter(struct file *file, } } - ar->debug.pktlog_filter = filter; + ar->pktlog_filter = filter; ret = count; out: @@ -2139,7 +2139,7 @@ static ssize_t ath10k_read_pktlog_filter(struct file *file, char __user *ubuf, mutex_lock(&ar->conf_mutex); len = scnprintf(buf, sizeof(buf) - len, "%08x\n", - ar->debug.pktlog_filter); + ar->pktlog_filter); mutex_unlock(&ar->conf_mutex); return simple_read_from_buffer(ubuf, count, ppos, buf, len); diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h index 548ad5483a4a..5e662994c49a 100644 --- a/drivers/net/wireless/ath/ath10k/debug.h +++ b/drivers/net/wireless/ath/ath10k/debug.h @@ -51,7 +51,8 @@ enum ath10k_pktlog_filter { ATH10K_PKTLOG_RCFIND = 0x000000004, ATH10K_PKTLOG_RCUPDATE = 0x000000008, ATH10K_PKTLOG_DBG_PRINT = 0x000000010, - ATH10K_PKTLOG_ANY = 0x00000001f, + ATH10K_PKTLOG_PEER_STATS = 0x000000040, + ATH10K_PKTLOG_ANY = 0x00000005f, }; enum ath10k_dbg_aggr_mode { @@ -60,6 +61,21 @@ enum ath10k_dbg_aggr_mode { ATH10K_DBG_AGGR_MODE_MAX, }; +/* Types of packet log events */ +enum ath_pktlog_type { + ATH_PKTLOG_TYPE_TX_CTRL = 1, + ATH_PKTLOG_TYPE_TX_STAT, +}; + +struct ath10k_pktlog_hdr { + __le16 flags; + __le16 missed_cnt; + __le16 log_type; /* Type of log information foll this header */ + __le16 size; /* Size of variable length log information in bytes */ + __le32 timestamp; + u8 payload[0]; +} __packed; + /* FIXME: How to calculate the buffer size sanely? */ #define ATH10K_FW_STATS_BUF_SIZE (1024 * 1024) @@ -190,9 +206,6 @@ void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct dentry *dir); void ath10k_sta_update_rx_duration(struct ath10k *ar, struct ath10k_fw_stats *stats); -void ath10k_sta_statistics(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - struct station_info *sinfo); #else static inline void ath10k_sta_update_rx_duration(struct ath10k *ar, diff --git a/drivers/net/wireless/ath/ath10k/debugfs_sta.c b/drivers/net/wireless/ath/ath10k/debugfs_sta.c index d59ac6b83340..ff96f70d2282 100644 --- a/drivers/net/wireless/ath/ath10k/debugfs_sta.c +++ b/drivers/net/wireless/ath/ath10k/debugfs_sta.c @@ -65,33 +65,6 @@ void ath10k_sta_update_rx_duration(struct ath10k *ar, ath10k_sta_update_stats_rx_duration(ar, stats); } -void ath10k_sta_statistics(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - struct station_info *sinfo) -{ - struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv; - struct ath10k *ar = arsta->arvif->ar; - - if (!ath10k_peer_stats_enabled(ar)) - return; - - sinfo->rx_duration = arsta->rx_duration; - sinfo->filled |= 1ULL << NL80211_STA_INFO_RX_DURATION; - - if (!arsta->txrate.legacy && !arsta->txrate.nss) - return; - - if (arsta->txrate.legacy) { - sinfo->txrate.legacy = arsta->txrate.legacy; - } else { - sinfo->txrate.mcs = arsta->txrate.mcs; - sinfo->txrate.nss = arsta->txrate.nss; - sinfo->txrate.bw = arsta->txrate.bw; - } - sinfo->txrate.flags = arsta->txrate.flags; - sinfo->filled |= 1ULL << NL80211_STA_INFO_TX_BITRATE; -} - static ssize_t ath10k_dbg_sta_read_aggr_mode(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index 6305308422c4..7bd93d627f6b 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h @@ -1497,6 +1497,23 @@ struct htt_peer_tx_stats { u8 payload[0]; } __packed; +#define ATH10K_10_2_TX_STATS_OFFSET 136 +#define PEER_STATS_FOR_NO_OF_PPDUS 4 + +struct ath10k_10_2_peer_tx_stats { + u8 ratecode[PEER_STATS_FOR_NO_OF_PPDUS]; + u8 success_pkts[PEER_STATS_FOR_NO_OF_PPDUS]; + __le16 success_bytes[PEER_STATS_FOR_NO_OF_PPDUS]; + u8 retry_pkts[PEER_STATS_FOR_NO_OF_PPDUS]; + __le16 retry_bytes[PEER_STATS_FOR_NO_OF_PPDUS]; + u8 failed_pkts[PEER_STATS_FOR_NO_OF_PPDUS]; + __le16 failed_bytes[PEER_STATS_FOR_NO_OF_PPDUS]; + u8 flags[PEER_STATS_FOR_NO_OF_PPDUS]; + __le32 tx_duration; + u8 tx_ppdu_cnt; + u8 peer_id; +} __packed; + union htt_rx_pn_t { /* WEP: 24-bit PN */ u32 pn24; @@ -1695,7 +1712,7 @@ struct ath10k_htt { /* This is used to group tx/rx completions separately and process them * in batches to reduce cache stalls */ - struct sk_buff_head rx_compl_q; + struct sk_buff_head rx_msdus_q; struct sk_buff_head rx_in_ord_compl_q; struct sk_buff_head tx_fetch_ind_q; diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 7d295ee71534..620ed7dca836 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -227,7 +227,7 @@ void ath10k_htt_rx_free(struct ath10k_htt *htt) { del_timer_sync(&htt->rx_ring.refill_retry_timer); - skb_queue_purge(&htt->rx_compl_q); + skb_queue_purge(&htt->rx_msdus_q); skb_queue_purge(&htt->rx_in_ord_compl_q); skb_queue_purge(&htt->tx_fetch_ind_q); @@ -515,7 +515,7 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt) htt->rx_ring.sw_rd_idx.msdu_payld = 0; hash_init(htt->rx_ring.skb_table); - skb_queue_head_init(&htt->rx_compl_q); + skb_queue_head_init(&htt->rx_msdus_q); skb_queue_head_init(&htt->rx_in_ord_compl_q); skb_queue_head_init(&htt->tx_fetch_ind_q); atomic_set(&htt->num_mpdus_ready, 0); @@ -974,16 +974,25 @@ static char *ath10k_get_tid(struct ieee80211_hdr *hdr, char *out, size_t size) return out; } -static void ath10k_process_rx(struct ath10k *ar, - struct ieee80211_rx_status *rx_status, - struct sk_buff *skb) +static void ath10k_htt_rx_h_queue_msdu(struct ath10k *ar, + struct ieee80211_rx_status *rx_status, + struct sk_buff *skb) +{ + struct ieee80211_rx_status *status; + + status = IEEE80211_SKB_RXCB(skb); + *status = *rx_status; + + __skb_queue_tail(&ar->htt.rx_msdus_q, skb); +} + +static void ath10k_process_rx(struct ath10k *ar, struct sk_buff *skb) { struct ieee80211_rx_status *status; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; char tid[32]; status = IEEE80211_SKB_RXCB(skb); - *status = *rx_status; ath10k_dbg(ar, ATH10K_DBG_DATA, "rx skb %pK len %u peer %pM %s %s sn %u %s%s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i mic-err %i amsdu-more %i\n", @@ -1517,7 +1526,7 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar, } } -static void ath10k_htt_rx_h_deliver(struct ath10k *ar, +static void ath10k_htt_rx_h_enqueue(struct ath10k *ar, struct sk_buff_head *amsdu, struct ieee80211_rx_status *status) { @@ -1540,7 +1549,7 @@ static void ath10k_htt_rx_h_deliver(struct ath10k *ar, status->flag |= RX_FLAG_ALLOW_SAME_PN; } - ath10k_process_rx(ar, status, msdu); + ath10k_htt_rx_h_queue_msdu(ar, status, msdu); } } @@ -1652,7 +1661,7 @@ static int ath10k_htt_rx_handle_amsdu(struct ath10k_htt *htt) struct ath10k *ar = htt->ar; struct ieee80211_rx_status *rx_status = &htt->rx_status; struct sk_buff_head amsdu; - int ret, num_msdus; + int ret; __skb_queue_head_init(&amsdu); @@ -1674,7 +1683,6 @@ 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 */ @@ -1683,9 +1691,9 @@ static int ath10k_htt_rx_handle_amsdu(struct ath10k_htt *htt) ath10k_htt_rx_h_filter(ar, &amsdu, rx_status); ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status, true); - ath10k_htt_rx_h_deliver(ar, &amsdu, rx_status); + ath10k_htt_rx_h_enqueue(ar, &amsdu, rx_status); - return num_msdus; + return 0; } static void ath10k_htt_rx_proc_rx_ind(struct ath10k_htt *htt, @@ -1893,15 +1901,14 @@ static void ath10k_htt_rx_h_rx_offload_prot(struct ieee80211_rx_status *status, RX_FLAG_MMIC_STRIPPED; } -static int ath10k_htt_rx_h_rx_offload(struct ath10k *ar, - struct sk_buff_head *list) +static void ath10k_htt_rx_h_rx_offload(struct ath10k *ar, + struct sk_buff_head *list) { struct ath10k_htt *htt = &ar->htt; struct ieee80211_rx_status *status = &htt->rx_status; struct htt_rx_offload_msdu *rx; struct sk_buff *msdu; size_t offset; - int num_msdu = 0; while ((msdu = __skb_dequeue(list))) { /* Offloaded frames don't have Rx descriptor. Instead they have @@ -1940,10 +1947,8 @@ static int ath10k_htt_rx_h_rx_offload(struct ath10k *ar, ath10k_htt_rx_h_rx_offload_prot(status, msdu); ath10k_htt_rx_h_channel(ar, status, NULL, rx->vdev_id); - ath10k_process_rx(ar, status, msdu); - num_msdu++; + ath10k_htt_rx_h_queue_msdu(ar, status, msdu); } - return num_msdu; } static int ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb) @@ -1959,7 +1964,7 @@ static int ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb) u8 tid; bool offload; bool frag; - int ret, num_msdus = 0; + int ret; lockdep_assert_held(&htt->rx_ring.lock); @@ -2001,7 +2006,7 @@ static int ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb) * separately. */ if (offload) - num_msdus = ath10k_htt_rx_h_rx_offload(ar, &list); + ath10k_htt_rx_h_rx_offload(ar, &list); while (!skb_queue_empty(&list)) { __skb_queue_head_init(&amsdu); @@ -2014,11 +2019,10 @@ static int ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb) * better to report something than nothing though. This * should still give an idea about rx rate to the user. */ - num_msdus += skb_queue_len(&amsdu); 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_deliver(ar, &amsdu, status); + ath10k_htt_rx_h_enqueue(ar, &amsdu, status); break; case -EAGAIN: /* fall through */ @@ -2030,7 +2034,7 @@ static int ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb) return -EIO; } } - return num_msdus; + return ret; } static void ath10k_htt_rx_tx_fetch_resp_id_confirm(struct ath10k *ar, @@ -2449,6 +2453,62 @@ out: rcu_read_unlock(); } +static void ath10k_fetch_10_2_tx_stats(struct ath10k *ar, u8 *data) +{ + struct ath10k_pktlog_hdr *hdr = (struct ath10k_pktlog_hdr *)data; + struct ath10k_per_peer_tx_stats *p_tx_stats = &ar->peer_tx_stats; + struct ath10k_10_2_peer_tx_stats *tx_stats; + struct ieee80211_sta *sta; + struct ath10k_peer *peer; + u16 log_type = __le16_to_cpu(hdr->log_type); + u32 peer_id = 0, i; + + if (log_type != ATH_PKTLOG_TYPE_TX_STAT) + return; + + tx_stats = (struct ath10k_10_2_peer_tx_stats *)((hdr->payload) + + ATH10K_10_2_TX_STATS_OFFSET); + + if (!tx_stats->tx_ppdu_cnt) + return; + + peer_id = tx_stats->peer_id; + + rcu_read_lock(); + spin_lock_bh(&ar->data_lock); + peer = ath10k_peer_find_by_id(ar, peer_id); + if (!peer) { + ath10k_warn(ar, "Invalid peer id %d in peer stats buffer\n", + peer_id); + goto out; + } + + sta = peer->sta; + for (i = 0; i < tx_stats->tx_ppdu_cnt; i++) { + p_tx_stats->succ_bytes = + __le16_to_cpu(tx_stats->success_bytes[i]); + p_tx_stats->retry_bytes = + __le16_to_cpu(tx_stats->retry_bytes[i]); + p_tx_stats->failed_bytes = + __le16_to_cpu(tx_stats->failed_bytes[i]); + p_t |