summaryrefslogtreecommitdiff
path: root/qcwcn/wifi_hal/wifilogger_diag.cpp
diff options
context:
space:
mode:
authorAjit Vaishya <ajitv@codeaurora.org>2019-02-26 18:25:55 +0530
committerAhmed ElArabawy <arabawy@google.com>2019-03-12 13:38:07 -0700
commit181078ab828d12786c457037cda2fa61a50ab188 (patch)
tree1cfb2baacdcb04518983a3353864247ed83035aa /qcwcn/wifi_hal/wifilogger_diag.cpp
parent74064d74227d7e64e962c82d79c491578acf714e (diff)
downloadwlan-181078ab828d12786c457037cda2fa61a50ab188.tar.gz
Wifi-hal: TX Per Packet stats for V2 version.
Current TX per packet stats parsing logic cannot be used to parse TX stats for packet log new version V2, because of packet log structre format is different. This changes introduces to parse new packet log version V2, based on required OFFSET from received TX payload. Support to read packet log version i.e V1/V2/V3 by reading firmare version. Bug: 118484168 Test: Regression test Change-Id: Ie5c508bb2fd3e00674dd807c3003b00857d3f070 CRs-Fixed: 2402099
Diffstat (limited to 'qcwcn/wifi_hal/wifilogger_diag.cpp')
-rw-r--r--qcwcn/wifi_hal/wifilogger_diag.cpp264
1 files changed, 254 insertions, 10 deletions
diff --git a/qcwcn/wifi_hal/wifilogger_diag.cpp b/qcwcn/wifi_hal/wifilogger_diag.cpp
index 34d8549..3714c54 100644
--- a/qcwcn/wifi_hal/wifilogger_diag.cpp
+++ b/qcwcn/wifi_hal/wifilogger_diag.cpp
@@ -1321,6 +1321,85 @@ static wifi_error update_stats_to_ring_buf(hal_info *info,
return WIFI_SUCCESS;
}
+static u16 get_rate_v1(u16 mcs_r)
+{
+ MCS mcs;
+ int index = 0;
+ u16 tx_rate = 0;
+ u8 nss;
+
+ mcs.mcs = mcs_r;
+ nss = mcs.mcs_s.nss + 1;
+
+ switch (mcs.mcs_s.preamble) {
+ case WIFI_HW_RATECODE_PREAM_OFDM:
+ for (index = 0; index < MAX_OFDM_MCS_IDX; index++) {
+ if ((mcs.mcs_s.rate & 0xF) == index)
+ tx_rate = (u16) ofdm_mcs_nss1[index].ofdm_rate[mcs.mcs_s.short_gi] / 1000;
+ }
+ break;
+ case WIFI_HW_RATECODE_PREAM_CCK:
+ for (index = 0; index < MAX_CCK_MCS_IDX; index++) {
+ if ((mcs.mcs_s.rate & 0xF) == index)
+ tx_rate = (u16) cck_mcs_nss1[index].cck_rate[mcs.mcs_s.short_gi] / 1000;
+ }
+ break;
+ case WIFI_HW_RATECODE_PREAM_HT:
+ if (nss == 1) {
+ for (index = 0; index < MAX_HT_MCS_IDX; index++) {
+ if (mcs.mcs_s.rate == index) {
+ if (mcs.mcs_s.bw == BW_20MHZ)
+ tx_rate = (u16) mcs_nss1[index].ht20_rate[mcs.mcs_s.short_gi] / 10;
+ if (mcs.mcs_s.bw == BW_40MHZ)
+ tx_rate = (u16) mcs_nss1[index].ht40_rate[mcs.mcs_s.short_gi] / 10;
+ }
+ }
+ } else if (nss == 2) {
+ for (index = 0; index < MAX_HT_MCS_IDX; index++) {
+ if (mcs.mcs_s.rate == index) {
+ if (mcs.mcs_s.bw == BW_20MHZ)
+ tx_rate = (u16) mcs_nss2[index].ht20_rate[mcs.mcs_s.short_gi] / 10;
+ if (mcs.mcs_s.bw == BW_40MHZ)
+ tx_rate = (u16) mcs_nss2[index].ht40_rate[mcs.mcs_s.short_gi] / 10;
+ }
+ }
+ } else {
+ ALOGE("Unexpected nss %d", nss);
+ }
+ break;
+ case WIFI_HW_RATECODE_PREAM_VHT:
+ if (nss == 1) {
+ for (index = 0; index < MAX_VHT_MCS_IDX; index++) {
+ if (mcs.mcs_s.rate == index) {
+ if (mcs.mcs_s.bw == BW_20MHZ)
+ tx_rate = (u16) vht_mcs_nss1[index].ht20_rate[mcs.mcs_s.short_gi] / 10;
+ if (mcs.mcs_s.bw == BW_40MHZ)
+ tx_rate = (u16) vht_mcs_nss1[index].ht40_rate[mcs.mcs_s.short_gi] / 10;
+ if (mcs.mcs_s.bw == BW_80MHZ)
+ tx_rate = (u16) vht_mcs_nss1[index].ht40_rate[mcs.mcs_s.short_gi] / 10;
+ }
+ }
+ } else if (nss == 2) {
+ for (index = 0; index < MAX_VHT_MCS_IDX; index++) {
+ if (mcs.mcs_s.rate == index) {
+ if (mcs.mcs_s.bw == BW_20MHZ)
+ tx_rate = (u16) vht_mcs_nss2[index].ht20_rate[mcs.mcs_s.short_gi] / 10;
+ if (mcs.mcs_s.bw == BW_40MHZ)
+ tx_rate = (u16) vht_mcs_nss2[index].ht40_rate[mcs.mcs_s.short_gi] / 10;
+ if (mcs.mcs_s.bw == BW_80MHZ)
+ tx_rate = (u16) vht_mcs_nss2[index].ht40_rate[mcs.mcs_s.short_gi] / 10;
+ }
+ }
+ } else {
+ ALOGE("Unexpected nss %d", nss);
+ }
+ break;
+ default:
+ ALOGE("Unexpected preamble %d", mcs.mcs_s.preamble);
+ }
+ return tx_rate;
+}
+
static u16 get_rate(u16 mcs_r)
{
u16 tx_rate = 0;
@@ -1551,6 +1630,25 @@ static wifi_error parse_rx_stats(hal_info *info, u8 *buf, u16 size)
return status;
}
+static u16 get_tx_mcs_v1(u8 *data)
+{
+ MCS mcs;
+ RATE_CODE rate_code;
+ u16 extended_flags;
+ mcs.mcs = 0;
+
+ rate_code = *((RATE_CODE*)(data + RATE_CODE_OFFSET));
+ extended_flags = *((u16*)(data + EXT_FLAGS_OFFSET));
+
+ mcs.mcs_s.rate = rate_code.rateCode & 0xF;
+ mcs.mcs_s.nss = (rate_code.rateCode >> 4) & 0x3;
+ mcs.mcs_s.preamble = (rate_code.rateCode >> 6) & 0x3;
+ mcs.mcs_s.short_gi = (((extended_flags >> 12) & 0x1) == 1) ? 1 : 0;
+ mcs.mcs_s.bw = (rate_code.flags >> 5) & 0x3;
+
+ return mcs.mcs;
+}
+
static u16 get_tx_mcs(u8 series,
struct tx_ppdu_start *ppdu_start)
{
@@ -2012,8 +2110,135 @@ static wifi_error parse_pkt_fate_stats(hal_info *info, u8 *buf, u16 size)
return WIFI_SUCCESS;
}
+/*
+ * ---------------------------------------------------------------------------------
+ * | pkt log | packet log data contain sub packet log info |
+ * | header |------------------------------------------------------------------|
+ * | | sub pkt log | sub pkt log | sub pkt log | sub pkt log | |
+ * | | header | data | header | data |..... |
+ * |--------------------------------------------------------------------------------
+ */
+static wifi_error parse_stats_sw_event(hal_info *info,
+ wh_pktlog_hdr_v2_t *pkt_stats_header)
+{
+ u32 pkt_stats_len;
+ int num_of_node = 0;
+ u8 *data;
+ u8 *node_pkt_data;
+ wh_pktlog_hdr_v2_t *pkt_stats_node_header;
+ int node_pkt_type,pkt_sub_type,node_pkt_len,i;
+ wifi_error status = WIFI_SUCCESS;
+ node_pkt_stats node_pkt_t;
+ wifi_ring_buffer_entry *pRingBufferEntry =
+ (wifi_ring_buffer_entry *)info->pkt_stats->tx_stats;
+
+ wifi_ring_per_packet_status_entry *rb_pkt_stats =
+ (wifi_ring_per_packet_status_entry *)(pRingBufferEntry + 1);
+
+ pkt_stats_len = pkt_stats_header->size;
+ data = ((u8 *)pkt_stats_header + sizeof(wh_pktlog_hdr_v2_t));
+ num_of_node = (pkt_stats_header->reserved >> 16) & 0xFFFF;
+ pkt_sub_type = pkt_stats_header->reserved & 0xFFFF;
+
+ do {
+ if (pkt_stats_len < sizeof(wh_pktlog_hdr_v2_t)) {
+ status = WIFI_ERROR_INVALID_ARGS;
+ break;
+ }
+ if (pkt_sub_type == 1) {
+ pkt_stats_node_header = (wh_pktlog_hdr_v2_t *)data;
+ if (pkt_stats_node_header) {
+ node_pkt_type = pkt_stats_node_header->log_type;
+ node_pkt_len = pkt_stats_node_header->size;
+ node_pkt_data = ((u8 *)pkt_stats_node_header + sizeof(wh_pktlog_hdr_v2_t));
+ switch (node_pkt_type) {
+ case PKTLOG_TYPE_TX_CTRL:
+ info->pkt_stats->tx_stats_events |= BIT(PKTLOG_TYPE_TX_CTRL);
+ break;
+ case PKTLOG_TYPE_TX_STAT:
+ {
+ memset(rb_pkt_stats, 0, sizeof(wifi_ring_per_packet_status_entry));
+ memset(&node_pkt_t, 0, sizeof(node_pkt_stats));
+ node_pkt_t.frm_ctrl = *((u16*)(node_pkt_data + FRAME_CTRL_OFFSET));
+ if (node_pkt_t.frm_ctrl & BIT(DATA_PROTECTED))
+ rb_pkt_stats->flags |= PER_PACKET_ENTRY_FLAGS_PROTECTED;
+ rb_pkt_stats->transmit_success_timestamp =
+ *((u64*)(node_pkt_data + TX_SUCCESS_TMS_OFFSET));
+ rb_pkt_stats->link_layer_transmit_sequence =
+ *((u16*)(node_pkt_data + LINK_LAYER_TX_SQN_OFFSET));
+ node_pkt_t.tx_ok = *((u8*)(node_pkt_data + TX_STATUS_OFFSET));
+ if (node_pkt_t.tx_ok == 0)
+ rb_pkt_stats->flags |= PER_PACKET_ENTRY_FLAGS_TX_SUCCESS;
+ rb_pkt_stats->rssi = *((u8*)(node_pkt_data + TX_RSSI_OFFSET));
+ rb_pkt_stats->num_retries = *((u8*)(node_pkt_data + NO_RETRIES_OFFSET));
+ node_pkt_t.qos_ctrl = *((u8*)(node_pkt_data + QOS_CTRL_OFFSET));
+ rb_pkt_stats->tid = node_pkt_t.qos_ctrl & 0xF;
+ rb_pkt_stats->MCS = get_tx_mcs_v1(node_pkt_data);
+ rb_pkt_stats->last_transmit_rate = get_rate_v1(rb_pkt_stats->MCS);
+ node_pkt_t.bmap_failed = *((u64*)(node_pkt_data + BMAP_FAILED_OFFSET));
+ node_pkt_t.bmap_enqueued = *((u64*)(node_pkt_data + BMAP_ENQUEUED_OFFSET));
+
+ info->pkt_stats->tx_stats_events |= BIT(PKTLOG_TYPE_TX_STAT);
+ rb_pkt_stats->flags |= PER_PACKET_ENTRY_FLAGS_80211_HEADER;
+ }
+ break;
+ }
+ if (info->pkt_stats->tx_stats_events & BIT(PKTLOG_TYPE_TX_STAT)) {
+ /* if bmap_enqueued is 1 ,Handle non aggregated cases */
+ if (node_pkt_t.bmap_enqueued == 1) {
+ status = update_stats_to_ring_buf(info,
+ (u8 *)pRingBufferEntry,
+ sizeof(wifi_ring_buffer_entry) +
+ sizeof(wifi_ring_per_packet_status_entry));
+ if (status != WIFI_SUCCESS) {
+ ALOGE("Failed to write into the ring buffer : %d", node_pkt_type);
+ }
+ } else {
+ /* if bmap_enqueued is more than 1 ,Handle aggregated cases */
+ for (i = 0; i < MAX_BA_WINDOW_SIZE; i++) {
+ if (((node_pkt_t.bmap_enqueued >> i) & 0x1) == 1) {
+ if (((node_pkt_t.bmap_failed >> i) & 0x1) == 1) {
+ rb_pkt_stats->flags &= ~PER_PACKET_ENTRY_FLAGS_TX_SUCCESS;
+ } else {
+ rb_pkt_stats->flags |= PER_PACKET_ENTRY_FLAGS_TX_SUCCESS;
+ }
+ status = update_stats_to_ring_buf(info,
+ (u8 *)pRingBufferEntry,
+ sizeof(wifi_ring_buffer_entry) +
+ sizeof(wifi_ring_per_packet_status_entry));
+ if (status != WIFI_SUCCESS) {
+ ALOGE("Failed to write into the ring buffer : %d", node_pkt_type);
+ break;
+ }
+ rb_pkt_stats->link_layer_transmit_sequence += 1;
+ }
+ }
+ }
+ }
+ }
+ pkt_stats_len = (pkt_stats_len - (sizeof(wh_pktlog_hdr_v2_t) + node_pkt_len));
+ data = (u8*) (data + sizeof(wh_pktlog_hdr_v2_t) + node_pkt_len);
+ info->pkt_stats->tx_stats_events = 0;
+ }
+ } while (pkt_stats_len > 0);
+ return status;
+}
+
+/* Added This function to parse stats based on PKT_LOG_V2 Version */
+static wifi_error parse_stats_record_v2(hal_info *info,
+ wh_pktlog_hdr_v2_t *pkt_stats_header)
+{
+ wifi_error status = WIFI_SUCCESS;
+
+ if (pkt_stats_header->log_type == PKTLOG_TYPE_PKT_SW_EVENT) {
+ status = parse_stats_sw_event(info, pkt_stats_header);
+ } else
+ ALOGE("%s: invalid log_type %d",__FUNCTION__, pkt_stats_header->log_type);
+
+ return status;
+}
-static wifi_error parse_stats_record(hal_info *info,
+static wifi_error parse_stats_record_v1(hal_info *info,
wh_pktlog_hdr_t *pkt_stats_header)
{
wifi_error status;
@@ -2056,6 +2281,7 @@ static wifi_error parse_stats_record(hal_info *info,
static wifi_error parse_stats(hal_info *info, u8 *data, u32 buflen)
{
wh_pktlog_hdr_t *pkt_stats_header;
+ wh_pktlog_hdr_v2_t *pkt_stats_header_t;
wifi_error status = WIFI_SUCCESS;
do {
@@ -2070,18 +2296,36 @@ static wifi_error parse_stats(hal_info *info, u8 *data, u32 buflen)
status = WIFI_ERROR_INVALID_ARGS;
break;
}
- status = parse_stats_record(info, pkt_stats_header);
- if (status != WIFI_SUCCESS) {
- ALOGE("Failed to parse the stats type : %d",
- pkt_stats_header->log_type);
- return status;
+ /* Pkt_log_V2 based packet parsing */
+ if (info->pkt_log_ver == PKT_LOG_V2) {
+ pkt_stats_header_t = (wh_pktlog_hdr_v2_t *)data;
+ status = parse_stats_record_v2(info, pkt_stats_header_t);
+ if (status != WIFI_SUCCESS) {
+ ALOGE("Failed to parse the stats type : %d",
+ pkt_stats_header_t->log_type);
+ return status;
+ }
+ /* Pkt_log_V1 based packet parsing */
+ } else {
+ status = parse_stats_record_v1(info, pkt_stats_header);
+ if (status != WIFI_SUCCESS) {
+ ALOGE("Failed to parse the stats type : %d",
+ pkt_stats_header->log_type);
+ return status;
+ }
}
- if (pkt_stats_header->flags & PKT_INFO_FLG_PKT_DUMP_V2){
+
+ if (info->pkt_log_ver == PKT_LOG_V1) {
+ if (pkt_stats_header->flags & PKT_INFO_FLG_PKT_DUMP_V2){
+ data += (sizeof(wh_pktlog_hdr_v2_t) + pkt_stats_header->size);
+ buflen -= (sizeof(wh_pktlog_hdr_v2_t) + pkt_stats_header->size);
+ } else {
+ data += (sizeof(wh_pktlog_hdr_t) + pkt_stats_header->size);
+ buflen -= (sizeof(wh_pktlog_hdr_t) + pkt_stats_header->size);
+ }
+ } else if (info->pkt_log_ver == PKT_LOG_V2) {
data += (sizeof(wh_pktlog_hdr_v2_t) + pkt_stats_header->size);
buflen -= (sizeof(wh_pktlog_hdr_v2_t) + pkt_stats_header->size);
- } else {
- data += (sizeof(wh_pktlog_hdr_t) + pkt_stats_header->size);
- buflen -= (sizeof(wh_pktlog_hdr_t) + pkt_stats_header->size);
}
} while (buflen > 0);