Loading drivers/net/wireless/ath/ath10k/core.c +34 −7 Original line number Diff line number Diff line Loading @@ -377,6 +377,7 @@ static const char *const ath10k_core_fw_feature_str[] = { [ATH10K_FW_FEATURE_BTCOEX_PARAM] = "btcoex-param", [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", }; static unsigned int ath10k_core_get_fw_feature_str(char *buf, Loading Loading @@ -847,6 +848,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; Loading Loading @@ -1218,19 +1241,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), Loading Loading @@ -2330,7 +2353,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) { Loading drivers/net/wireless/ath/ath10k/core.h +3 −0 Original line number Diff line number Diff line Loading @@ -610,6 +610,9 @@ enum ath10k_fw_features { */ ATH10K_FW_FEATURE_ALLOWS_MESH_BCAST = 16, /* Firmware does not support power save in station mode. */ ATH10K_FW_FEATURE_NO_PS = 17, /* keep last */ ATH10K_FW_FEATURE_COUNT, }; Loading drivers/net/wireless/ath/ath10k/debug.h +17 −1 Original line number Diff line number Diff line Loading @@ -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 { Loading @@ -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) Loading drivers/net/wireless/ath/ath10k/htt.h +17 −0 Original line number Diff line number Diff line Loading @@ -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; Loading drivers/net/wireless/ath/ath10k/htt_rx.c +60 −0 Original line number Diff line number Diff line Loading @@ -2431,6 +2431,62 @@ static void ath10k_htt_fetch_peer_stats(struct ath10k *ar, 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_tx_stats->ratecode = tx_stats->ratecode[i]; p_tx_stats->flags = tx_stats->flags[i]; p_tx_stats->succ_pkts = tx_stats->success_pkts[i]; p_tx_stats->retry_pkts = tx_stats->retry_pkts[i]; p_tx_stats->failed_pkts = tx_stats->failed_pkts[i]; ath10k_update_per_peer_tx_stats(ar, sta, p_tx_stats); } spin_unlock_bh(&ar->data_lock); rcu_read_unlock(); return; out: spin_unlock_bh(&ar->data_lock); rcu_read_unlock(); } bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) { struct ath10k_htt *htt = &ar->htt; Loading Loading @@ -2548,6 +2604,10 @@ bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) skb->len - offsetof(struct htt_resp, pktlog_msg.payload)); if (ath10k_peer_stats_enabled(ar)) ath10k_fetch_10_2_tx_stats(ar, resp->pktlog_msg.payload); break; } case HTT_T2H_MSG_TYPE_RX_FLUSH: { Loading Loading
drivers/net/wireless/ath/ath10k/core.c +34 −7 Original line number Diff line number Diff line Loading @@ -377,6 +377,7 @@ static const char *const ath10k_core_fw_feature_str[] = { [ATH10K_FW_FEATURE_BTCOEX_PARAM] = "btcoex-param", [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", }; static unsigned int ath10k_core_get_fw_feature_str(char *buf, Loading Loading @@ -847,6 +848,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; Loading Loading @@ -1218,19 +1241,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), Loading Loading @@ -2330,7 +2353,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) { Loading
drivers/net/wireless/ath/ath10k/core.h +3 −0 Original line number Diff line number Diff line Loading @@ -610,6 +610,9 @@ enum ath10k_fw_features { */ ATH10K_FW_FEATURE_ALLOWS_MESH_BCAST = 16, /* Firmware does not support power save in station mode. */ ATH10K_FW_FEATURE_NO_PS = 17, /* keep last */ ATH10K_FW_FEATURE_COUNT, }; Loading
drivers/net/wireless/ath/ath10k/debug.h +17 −1 Original line number Diff line number Diff line Loading @@ -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 { Loading @@ -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) Loading
drivers/net/wireless/ath/ath10k/htt.h +17 −0 Original line number Diff line number Diff line Loading @@ -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; Loading
drivers/net/wireless/ath/ath10k/htt_rx.c +60 −0 Original line number Diff line number Diff line Loading @@ -2431,6 +2431,62 @@ static void ath10k_htt_fetch_peer_stats(struct ath10k *ar, 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_tx_stats->ratecode = tx_stats->ratecode[i]; p_tx_stats->flags = tx_stats->flags[i]; p_tx_stats->succ_pkts = tx_stats->success_pkts[i]; p_tx_stats->retry_pkts = tx_stats->retry_pkts[i]; p_tx_stats->failed_pkts = tx_stats->failed_pkts[i]; ath10k_update_per_peer_tx_stats(ar, sta, p_tx_stats); } spin_unlock_bh(&ar->data_lock); rcu_read_unlock(); return; out: spin_unlock_bh(&ar->data_lock); rcu_read_unlock(); } bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) { struct ath10k_htt *htt = &ar->htt; Loading Loading @@ -2548,6 +2604,10 @@ bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) skb->len - offsetof(struct htt_resp, pktlog_msg.payload)); if (ath10k_peer_stats_enabled(ar)) ath10k_fetch_10_2_tx_stats(ar, resp->pktlog_msg.payload); break; } case HTT_T2H_MSG_TYPE_RX_FLUSH: { Loading