wlan: Report correct link speed for 11ac links

Changes to fix incorrect link speeds reported by
prima when gReportMaxLinkSpeed=2 and the device
connects in VHT 20/40/80 mode.

CRs-Fixed: 476974
Change-Id: I1a3bb37b196c989b6d98f2777ff24e56a33d7178
diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c
index 162aa4f..2e2a6d5 100644
--- a/CORE/HDD/src/wlan_hdd_cfg80211.c
+++ b/CORE/HDD/src/wlan_hdd_cfg80211.c
@@ -454,12 +454,14 @@
 
 #ifdef WLAN_FEATURE_11AC
 
-#define DATA_RATE_11AC_MCS_MASK    0x0F
+#define DATA_RATE_11AC_MCS_MASK    0x03
 
 struct index_vht_data_rate_type
 {
    v_U8_t   beacon_rate_index;
-   v_U16_t  supported_rate[2];
+   v_U16_t  supported_VHT80_rate[2];
+   v_U16_t  supported_VHT40_rate[2];
+   v_U16_t  supported_VHT20_rate[2];
 };
 
 typedef enum
@@ -473,17 +475,17 @@
 /* MCS Based VHT rate table */
 static struct index_vht_data_rate_type supported_vht_mcs_rate[] =
 {
-/* MCS  L80    S80 */
-   {0,  {293,  325}},
-   {1,  {585,  650}},
-   {2,  {878,  975}},
-   {3,  {1170, 1300}},
-   {4,  {1755, 1950}},
-   {5,  {2340, 2600}},
-   {6,  {2633, 2925}},
-   {7,  {2925, 3250}},
-   {8,  {3510, 3900}},
-   {9,  {3900, 4333}}
+/* MCS  L80    S80     L40   S40    L20   S40*/
+   {0,  {293,  325},  {135,  150},  {65,   72}},
+   {1,  {585,  650},  {270,  300},  {130,  144}},
+   {2,  {878,  975},  {405,  450},  {195,  217}},
+   {3,  {1170, 1300}, {540,  600},  {260,  289}},
+   {4,  {1755, 1950}, {810,  900},  {390,  433}},
+   {5,  {2340, 2600}, {1080, 1200}, {520,  578}},
+   {6,  {2633, 2925}, {1215, 1350}, {585,  650}},
+   {7,  {2925, 3250}, {1350, 1500}, {650,  722}},
+   {8,  {3510, 3900}, {1620, 1800}, {780,  867}},
+   {9,  {3900, 4333}, {1800, 2000}, {780,  867}}
 };
 #endif /* WLAN_FEATURE_11AC */
 
@@ -6353,7 +6355,6 @@
             /* Update MAX rate */
             maxRate = (currentRate > maxRate)?currentRate:maxRate;
         }
-
         /* Get MCS Rate Set -- but only if we are connected at MCS
            rates or if we are always reporting max speed or if we have
            good rssi */
@@ -6369,15 +6370,14 @@
             rateFlag = 0;
 #ifdef WLAN_FEATURE_11AC
             /* VHT80 rate has seperate rate table */
-            if (rate_flags & eHAL_TX_RATE_VHT80)
+            if (rate_flags & (eHAL_TX_RATE_VHT20|eHAL_TX_RATE_VHT40|eHAL_TX_RATE_VHT80))
             {
-                currentRate = supported_vht_mcs_rate[pAdapter->hdd_stats.ClassA_stat.mcs_index].supported_rate[rateFlag];
                 ccmCfgGetInt(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_VHT_TX_MCS_MAP, &vht_mcs_map);
+                vhtMaxMcs = (eDataRate11ACMaxMcs)(vht_mcs_map & DATA_RATE_11AC_MCS_MASK );
                 if (rate_flags & eHAL_TX_RATE_SGI)
                 {
                     rateFlag |= 1;
                 }
-                vhtMaxMcs = (eDataRate11ACMaxMcs)(vht_mcs_map & DATA_RATE_11AC_MCS_MASK);
                 if (DATA_RATE_11AC_MAX_MCS_7 == vhtMaxMcs)
                 {
                     maxMCSIdx = 7;
@@ -6388,14 +6388,35 @@
                 }
                 else if (DATA_RATE_11AC_MAX_MCS_9 == vhtMaxMcs)
                 {
-                    maxMCSIdx = 9;
+                    //VHT20 is supporting 0~8
+                    if (rate_flags & eHAL_TX_RATE_VHT20)
+                        maxMCSIdx = 8;
+                    else
+                        maxMCSIdx = 9;
                 }
-                maxRate = supported_vht_mcs_rate[maxMCSIdx].supported_rate[rateFlag];
+
+                if (rate_flags & eHAL_TX_RATE_VHT80)
+                {
+                    currentRate = supported_vht_mcs_rate[pAdapter->hdd_stats.ClassA_stat.mcs_index].supported_VHT80_rate[rateFlag];
+                    maxRate = supported_vht_mcs_rate[maxMCSIdx].supported_VHT80_rate[rateFlag];
+                }
+                else if (rate_flags & eHAL_TX_RATE_VHT40)
+                {
+                    currentRate = supported_vht_mcs_rate[pAdapter->hdd_stats.ClassA_stat.mcs_index].supported_VHT40_rate[rateFlag];
+                    maxRate = supported_vht_mcs_rate[maxMCSIdx].supported_VHT40_rate[rateFlag];
+                }
+                else if (rate_flags & eHAL_TX_RATE_VHT20)
+                {
+                    currentRate = supported_vht_mcs_rate[pAdapter->hdd_stats.ClassA_stat.mcs_index].supported_VHT20_rate[rateFlag];
+                    maxRate = supported_vht_mcs_rate[maxMCSIdx].supported_VHT20_rate[rateFlag];
+                }
+
                 maxSpeedMCS = 1;
                 if (currentRate > maxRate)
                 {
                     maxRate = currentRate;
                 }
+
             }
             else
 #endif /* WLAN_FEATURE_11AC */
@@ -6430,6 +6451,13 @@
             }
         }
 
+        else if (!(rate_flags & eHAL_TX_RATE_LEGACY))
+        {
+            maxRate = myRate;
+            maxSpeedMCS = 1;
+            maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index;
+        }
+
         // make sure we report a value at least as big as our current rate
         if (((maxRate < myRate) && (0 == rssidx)) ||
              (0 == maxRate))
@@ -6446,7 +6474,7 @@
            }
         }
 
-        if ((!maxSpeedMCS) || (0 != rssidx))
+        if (rate_flags & eHAL_TX_RATE_LEGACY)
         {
             sinfo->txrate.legacy  = maxRate;
 #ifdef LINKSPEED_DEBUG_ENABLED
@@ -6461,26 +6489,31 @@
             if (rate_flags & eHAL_TX_RATE_VHT80)
             {
                 sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
+                sinfo->txrate.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
             }
-            else
-#endif /* WLAN_FEATURE_11AC */
+            else if (rate_flags & eHAL_TX_RATE_VHT40)
             {
-               sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
+                sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
+                sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
+            }
+            else if (rate_flags & eHAL_TX_RATE_VHT20)
+            {
+                sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
+            }
+#endif /* WLAN_FEATURE_11AC */
+            if (rate_flags & (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40))
+            {
+                sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
+                if (rate_flags & eHAL_TX_RATE_HT40)
+                {
+                    sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
+                }
             }
             if (rate_flags & eHAL_TX_RATE_SGI)
             {
                 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
             }
-            if (rate_flags & eHAL_TX_RATE_HT40)
-            {
-                sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
-            }
-#ifdef WLAN_FEATURE_11AC
-            else if (rate_flags & eHAL_TX_RATE_VHT80)
-            {
-                sinfo->txrate.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
-            }
-#endif /* WLAN_FEATURE_11AC */
+
 #ifdef LINKSPEED_DEBUG_ENABLED
             pr_info("Reporting MCS rate %d flags %x\n",
                     sinfo->txrate.mcs,