WiFi-HAL: Use correct bandwidth to compute MCS for Tx stats

Get the bandwidth value from Tx stats try list based on total
tries and calculate rate based on its value.
Set the RSSI value for failed Tx packets to 255, which indicates
an invalid value.

Change-Id: I7c4b43268627eef1ae6576bd6afd37f1bf55c630
diff --git a/qcwcn/wifi_hal/common.h b/qcwcn/wifi_hal/common.h
index d60e990..038ae07 100644
--- a/qcwcn/wifi_hal/common.h
+++ b/qcwcn/wifi_hal/common.h
@@ -124,6 +124,7 @@
     u32 rx_buf_size_occupied;
     wifi_ring_buffer_entry *rx_aggr_pkts;
     rx_aggr_stats aggr_stats;
+    u32 prev_seq_no;
 } hal_info;
 
 wifi_error wifi_register_handler(wifi_handle handle, int cmd, nl_recvmsg_msg_cb_t func, void *arg);
diff --git a/qcwcn/wifi_hal/pkt_stats.h b/qcwcn/wifi_hal/pkt_stats.h
index 283c9ac..4b5f988 100644
--- a/qcwcn/wifi_hal/pkt_stats.h
+++ b/qcwcn/wifi_hal/pkt_stats.h
@@ -44,6 +44,9 @@
 #define PKTLOG_TYPE_RC_UPDATE       7
 #define PKTLOG_TYPE_TX_VIRT_ADDR    8
 #define PKTLOG_TYPE_MAX             9
+#define BW_OFFSET 8
+#define INVALID_RSSI 255
+#define EVENT_RX_PEERINFO_SIZE 64
 
 /* Format of the packet stats event*/
 typedef struct {
@@ -173,12 +176,13 @@
 /*Contains tx timestamp*/
 struct try_status {
     u32 timestamp                       : 23; //[22:0]
-    u32 reserved                        :  9; //[23]
+    u32 reserved1                       :  5; //[23]
+    u32 packet_bw                       :  2; //[29:28]
+    u32 reserved2                       :  2; //[31:30]
 } __attribute__((packed));
 
 struct try_list {
-    struct try_status try_00;
-    u32 reserved[15];
+    struct try_status try_st[16];
 } __attribute__((packed));
 
 
@@ -263,14 +267,14 @@
  */
 
 #define RING_BUF_ENTRY_SIZE 512
+#define PKT_STATS_BUF_SIZE 128
 struct pkt_stats_s {
     u8 tx_stats_events;
-    u32 prev_seq_no;
     /* TODO: Need to handle the case if size of the stats are more
      * than 512 bytes. Currently, the tx size is 34 bytes and ring buffer entry
      * size is 12 bytes.
      */
-    u8 tx_stats[RING_BUF_ENTRY_SIZE];
+    u8 tx_stats[PKT_STATS_BUF_SIZE];
     u8 num_msdu;
     u16 start_seq_num;
     u16 ba_seq_num;
@@ -281,6 +285,7 @@
     u32 shifted_bitmap_31_0;
     u32 shifted_bitmap_63_32;
     bool isBlockAck;
+    u8 tx_bandwidth;
 };
 
 typedef union {
diff --git a/qcwcn/wifi_hal/wifi_hal.cpp b/qcwcn/wifi_hal/wifi_hal.cpp
index 5b6da50..8ce5c94 100644
--- a/qcwcn/wifi_hal/wifi_hal.cpp
+++ b/qcwcn/wifi_hal/wifi_hal.cpp
@@ -466,7 +466,7 @@
     }
 
     info->rx_buf_size_allocated = MAX_RXMPDUS_PER_AMPDU * MAX_MSDUS_PER_MPDU
-                                  * RING_BUF_ENTRY_SIZE;
+                                  * PKT_STATS_BUF_SIZE;
 
     info->rx_aggr_pkts =
         (wifi_ring_buffer_entry  *)malloc(info->rx_buf_size_allocated);
diff --git a/qcwcn/wifi_hal/wifilogger_diag.cpp b/qcwcn/wifi_hal/wifilogger_diag.cpp
index f7b302c..447d67c 100644
--- a/qcwcn/wifi_hal/wifilogger_diag.cpp
+++ b/qcwcn/wifi_hal/wifilogger_diag.cpp
@@ -1142,6 +1142,19 @@
     wifi_ring_buffer_entry *pRingBufferEntry;
     u32 len_ring_buffer_entry = 0;
 
+    if (size == EVENT_RX_PEERINFO_SIZE) {
+        // TODO Parse the event later
+        return WIFI_SUCCESS;
+    }
+
+    if (size != sizeof(rb_pkt_stats_t)) {
+        ALOGE("%s Unexpected rx stats event length: %d", __FUNCTION__, size);
+        memset(info->rx_aggr_pkts, 0, info->rx_buf_size_occupied);
+        memset(&info->aggr_stats, 0, sizeof(rx_aggr_stats));
+        info->rx_buf_size_occupied = 0;
+        return WIFI_ERROR_UNKNOWN;
+    }
+
     len_ring_buffer_entry = sizeof(wifi_ring_buffer_entry)
                             + sizeof(wifi_ring_per_packet_status_entry)
                             + RX_HTT_HDR_STATUS_LEN;
@@ -1178,16 +1191,6 @@
     wifi_ring_per_packet_status_entry *rb_pkt_stats =
         (wifi_ring_per_packet_status_entry *)(pRingBufferEntry + 1);
 
-    if (size == 64) {
-        // TODO Parse the event later
-        return WIFI_SUCCESS;
-    }
-
-    if (size != sizeof(rb_pkt_stats_t)) {
-        ALOGE("%s Unexpected rx stats event length: %d", __FUNCTION__, size);
-        return WIFI_ERROR_UNKNOWN;
-    }
-
     memset(rb_pkt_stats, 0, sizeof(wifi_ring_per_packet_status_entry));
 
     /* Peer tx packet and it is an Rx packet for us */
@@ -1254,64 +1257,55 @@
     return status;
 }
 
-static void parse_tx_rate_and_mcs(struct tx_ppdu_start *ppdu_start,
-                                wifi_ring_per_packet_status_entry *rb_pkt_stats)
+static u16 get_tx_mcs(struct tx_ppdu_start *ppdu_start)
 {
     u16 tx_rate = 0;
     MCS mcs;
 
+    mcs.mcs = 0;
     if (ppdu_start->valid_s0_bw20) {
         mcs.mcs_s.rate      = ppdu_start->s0_bw20.rate;
         mcs.mcs_s.nss       = ppdu_start->s0_bw20.nss;
         mcs.mcs_s.preamble  = ppdu_start->s0_bw20.preamble_type;
-        mcs.mcs_s.bw        = BW_20_MHZ;
         mcs.mcs_s.short_gi  = ppdu_start->s0_bw20.short_gi;
     } else if (ppdu_start->valid_s0_bw40) {
         mcs.mcs_s.rate      = ppdu_start->s0_bw40.rate;
         mcs.mcs_s.nss       = ppdu_start->s0_bw40.nss;
         mcs.mcs_s.preamble  = ppdu_start->s0_bw40.preamble_type;
-        mcs.mcs_s.bw        = BW_40_MHZ;
         mcs.mcs_s.short_gi = ppdu_start->s0_bw40.short_gi;
     } else if (ppdu_start->valid_s0_bw80) {
         mcs.mcs_s.rate      = ppdu_start->s0_bw80.rate;
         mcs.mcs_s.nss       = ppdu_start->s0_bw80.nss;
         mcs.mcs_s.preamble  = ppdu_start->s0_bw80.preamble_type;
-        mcs.mcs_s.bw        = BW_80_MHZ;
         mcs.mcs_s.short_gi = ppdu_start->s0_bw80.short_gi;
     } else if (ppdu_start->valid_s0_bw160) {
         mcs.mcs_s.rate      = ppdu_start->s0_bw160.rate;
         mcs.mcs_s.nss       = ppdu_start->s0_bw160.nss;
         mcs.mcs_s.preamble  = ppdu_start->s0_bw160.preamble_type;
-        mcs.mcs_s.bw        = BW_160_MHZ;
         mcs.mcs_s.short_gi = ppdu_start->s0_bw160.short_gi;
     } else if (ppdu_start->valid_s1_bw20) {
         mcs.mcs_s.rate      = ppdu_start->s1_bw20.rate;
         mcs.mcs_s.nss       = ppdu_start->s1_bw20.nss;
         mcs.mcs_s.preamble  = ppdu_start->s1_bw20.preamble_type;
-        mcs.mcs_s.bw        = BW_20_MHZ;
         mcs.mcs_s.short_gi = ppdu_start->s1_bw20.short_gi;
     } else if (ppdu_start->valid_s1_bw40) {
         mcs.mcs_s.rate      = ppdu_start->s1_bw40.rate;
         mcs.mcs_s.nss       = ppdu_start->s1_bw40.nss;
         mcs.mcs_s.preamble  = ppdu_start->s1_bw40.preamble_type;
-        mcs.mcs_s.bw        = BW_40_MHZ;
         mcs.mcs_s.short_gi = ppdu_start->s1_bw40.short_gi;
     } else if (ppdu_start->valid_s1_bw80) {
         mcs.mcs_s.rate      = ppdu_start->s1_bw80.rate;
         mcs.mcs_s.nss       = ppdu_start->s1_bw80.nss;
         mcs.mcs_s.preamble  = ppdu_start->s1_bw80.preamble_type;
-        mcs.mcs_s.bw        = BW_80_MHZ;
         mcs.mcs_s.short_gi = ppdu_start->s1_bw80.short_gi;
     } else if (ppdu_start->valid_s1_bw160) {
         mcs.mcs_s.rate      = ppdu_start->s1_bw160.rate;
         mcs.mcs_s.nss       = ppdu_start->s1_bw160.nss;
         mcs.mcs_s.preamble  = ppdu_start->s1_bw160.preamble_type;
-        mcs.mcs_s.bw        = BW_160_MHZ;
         mcs.mcs_s.short_gi = ppdu_start->s1_bw160.short_gi;
     }
 
-    rb_pkt_stats->MCS = mcs.mcs;
-    rb_pkt_stats->last_transmit_rate = get_rate(mcs.mcs);
+    return mcs.mcs;
 }
 
 static void get_tx_aggr_stats(struct tx_ppdu_start *ppdu_start, hal_info *info)
@@ -1368,6 +1362,18 @@
     }
 }
 
+static u16 get_bw(struct tx_ppdu_end *tx_ppdu_end)
+{
+    int try_list_index;
+
+    if (tx_ppdu_end->stat.total_tries > 0)
+        try_list_index = tx_ppdu_end->stat.total_tries - 1;
+    else
+        try_list_index = 0;
+
+    return tx_ppdu_end->try_list.try_st[try_list_index].packet_bw;
+}
+
 static wifi_error parse_tx_stats(hal_info *info, void *buf,
                                  u32 buflen, u8 logtype)
 {
@@ -1400,7 +1406,9 @@
                 = ppdu_start->start_seq_num;
             info->pkt_stats->start_seq_num = ppdu_start->start_seq_num;
             rb_pkt_stats->tid = ppdu_start->qos_ctl & 0xF;
-            parse_tx_rate_and_mcs(ppdu_start, rb_pkt_stats);
+            rb_pkt_stats->MCS = get_tx_mcs(ppdu_start) |
+                                (info->pkt_stats->tx_bandwidth << BW_OFFSET);
+            rb_pkt_stats->last_transmit_rate = get_rate(rb_pkt_stats->MCS);
 
             if (ppdu_start->ampdu)
                 get_tx_aggr_stats(ppdu_start, info);
@@ -1435,15 +1443,17 @@
             info->pkt_stats->ba_bitmap_63_32 =
                                               tx_ppdu_end->stat.ba_bitmap_63_32;
             rb_pkt_stats->transmit_success_timestamp =
-                tx_ppdu_end->try_list.try_00.timestamp;
+                tx_ppdu_end->try_list.try_st[0].timestamp;
             rb_pkt_stats->rssi = tx_ppdu_end->stat.ack_rssi_ave;
             rb_pkt_stats->num_retries = tx_ppdu_end->stat.total_tries;
+            info->pkt_stats->tx_bandwidth = get_bw(tx_ppdu_end);
 
             info->pkt_stats->tx_stats_events |=  BIT(PKTLOG_TYPE_TX_STAT);
         }
         break;
         case PKTLOG_TYPE_TX_MSDU_ID:
         {
+            memset(info->pkt_stats, 0, sizeof(struct pkt_stats_s));
             info->pkt_stats->num_msdu = *(u8 *)buf;
             info->pkt_stats->tx_stats_events =  BIT(PKTLOG_TYPE_TX_MSDU_ID);
         }
@@ -1471,6 +1481,8 @@
          */
 
         if (info->pkt_stats->num_msdu == 1) {
+            if (!(rb_pkt_stats->flags & PER_PACKET_ENTRY_FLAGS_TX_SUCCESS))
+                rb_pkt_stats->rssi = INVALID_RSSI;
             /* Handle non aggregated cases */
             status = update_stats_to_ring_buf(info,
                                      (u8 *)pRingBufferEntry,
@@ -1490,6 +1502,7 @@
                         } else {
                             rb_pkt_stats->flags &=
                                        ~PER_PACKET_ENTRY_FLAGS_TX_SUCCESS;
+                            rb_pkt_stats->rssi = INVALID_RSSI;
                         }
                     } else {
                         continue;
@@ -1504,6 +1517,7 @@
                         } else {
                             rb_pkt_stats->flags &=
                                        ~PER_PACKET_ENTRY_FLAGS_TX_SUCCESS;
+                            rb_pkt_stats->rssi = INVALID_RSSI;
                         }
                     } else {
                         continue;
@@ -1661,11 +1675,11 @@
                 ALOGV("diag event_type = %0x length = %d",
                       drv_msg->event_type, drv_msg->length);
                 if (drv_msg->event_type == WLAN_PKT_LOG_STATS) {
-                    if ((info->pkt_stats->prev_seq_no + 1) !=
+                    if ((info->prev_seq_no + 1) !=
                             drv_msg->u.pkt_stats_event.msg_seq_no) {
                         ALOGE("Few pkt stats messages missed: rcvd = %d, prev = %d",
                                 drv_msg->u.pkt_stats_event.msg_seq_no,
-                                info->pkt_stats->prev_seq_no);
+                                info->prev_seq_no);
                         if (info->pkt_stats->tx_stats_events) {
                             info->pkt_stats->tx_stats_events = 0;
                             memset(&info->pkt_stats->tx_stats, 0,
@@ -1673,7 +1687,7 @@
                         }
                     }
 
-                    info->pkt_stats->prev_seq_no =
+                    info->prev_seq_no =
                         drv_msg->u.pkt_stats_event.msg_seq_no;
                     status = parse_stats(info,
                             drv_msg->u.pkt_stats_event.payload,