wlan: Add station id to mac address hash

Add hash table for station id to mac address
mapping. It avoids storing station id in (skb->data -1)
location between select_queue and hard_start_xmit
call which is required to enable GRO.
This hash is created in SAP/P2P-GO and IBSS mode only.

CRs-Fixed: 849908
Change-Id: I42d3bd8942e06088fee9fb08ea8ebb27353833e7
diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h
index fa1c59b..2ef0c3c 100644
--- a/CORE/HDD/inc/wlan_hdd_main.h
+++ b/CORE/HDD/inc/wlan_hdd_main.h
@@ -1066,6 +1066,15 @@
    struct work_struct  monTxWorkQueue;
    struct sk_buff *skb_to_tx;
 
+   /* sta_id to mac addr hash*/
+   spinlock_t sta_hash_lock;
+   tANI_U8 is_sta_id_hash_initialized;
+   struct sta_hash{
+      tANI_U16 mask;
+      tANI_U16 idx_bits;
+      hdd_list_t *bins;
+   } sta_id_hash;
+
    union {
       hdd_station_ctx_t station;
       hdd_ap_ctx_t  ap;
@@ -1633,4 +1642,31 @@
 
 v_U8_t hdd_is_fw_logging_enabled(void);
 v_U8_t hdd_is_fw_ev_logging_enabled(void);
+
+#define HDD_STA_ID_HASH_MULTIPLIER 2
+
+struct hdd_align_mac_addr_t {
+    uint16 bytes_ab;
+    uint16 bytes_cd;
+    uint16 bytes_ef;
+};
+
+typedef struct hdd_staid_hash_node
+{
+    hdd_list_node_t node;
+    v_U8_t sta_id;
+    v_MACADDR_t mac_addr;
+}hdd_staid_hash_node_t;
+
+/* sta_id hash related APIs */
+VOS_STATUS hdd_sta_id_hash_attach(hdd_adapter_t *pAdapter);
+VOS_STATUS hdd_sta_id_hash_detach(hdd_adapter_t *pAdapter);
+int hdd_sta_id_hash_calculate_index(hdd_adapter_t *pAdapter,
+                               v_MACADDR_t *mac_addr_in);
+VOS_STATUS hdd_sta_id_hash_add_entry(hdd_adapter_t *pAdapter,
+                                    v_U8_t sta_id, v_MACADDR_t *mac_addr);
+VOS_STATUS hdd_sta_id_hash_remove_entry(hdd_adapter_t *pAdapter,
+                                       v_U8_t sta_id, v_MACADDR_t *mac_addr);
+int hdd_sta_id_find_from_mac_addr(hdd_adapter_t *pAdapter,
+                                  v_MACADDR_t *mac_addr_in);
 #endif    // end #if !defined( WLAN_HDD_MAIN_H )
diff --git a/CORE/HDD/src/wlan_hdd_assoc.c b/CORE/HDD/src/wlan_hdd_assoc.c
index 48b0e1c..3e4d5ba 100644
--- a/CORE/HDD/src/wlan_hdd_assoc.c
+++ b/CORE/HDD/src/wlan_hdd_assoc.c
@@ -1165,6 +1165,20 @@
                    status = eHAL_STATUS_FAILURE;
                }
 
+               vstatus = hdd_sta_id_hash_remove_entry(pAdapter,
+                           sta_id, &pHddStaCtx->conn_info.peerMacAddress[i]);
+               if (vstatus != VOS_STATUS_SUCCESS) {
+                   hddLog(VOS_TRACE_LEVEL_ERROR,
+                             FL("Not able to remove staid hash %d"),
+                             sta_id);
+                   status = eHAL_STATUS_FAILURE;
+               } else {
+                   hddLog(VOS_TRACE_LEVEL_INFO,
+                         FL("ibss station removed sta_id %d mac:"
+                         MAC_ADDRESS_STR), sta_id,
+                         MAC_ADDR_ARRAY(pHddStaCtx->conn_info.peerMacAddress[i].bytes));
+               }
+
                /*set the staid and peer mac as 0, all other reset are
                 * done in hdd_connRemoveConnectInfo.
                 */
@@ -2164,10 +2178,12 @@
   return FALSE.
 
   ===========================================================================*/
-static int roamSaveIbssStation( hdd_station_ctx_t *pHddStaCtx, v_U8_t staId, v_MACADDR_t *peerMacAddress )
+static int roamSaveIbssStation(hdd_adapter_t *pAdapter, v_U8_t staId, v_MACADDR_t *peerMacAddress)
 {
    int fSuccess = FALSE;
    int idx = 0;
+   VOS_STATUS status;
+   hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
 
    for ( idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++ )
    {
@@ -2182,6 +2198,18 @@
       }
    }
 
+   status = hdd_sta_id_hash_add_entry(pAdapter, staId, peerMacAddress);
+   if (status != VOS_STATUS_SUCCESS) {
+       hddLog(VOS_TRACE_LEVEL_ERROR,
+                 FL("Not able to add staid hash %d"), staId);
+       return FALSE;
+   }
+
+   hddLog(VOS_TRACE_LEVEL_INFO,
+             FL("New station added sta_id %d mac:"
+             MAC_ADDRESS_STR), staId,
+             MAC_ADDR_ARRAY(peerMacAddress->bytes));
+
    return( fSuccess );
 }
 /**============================================================================
@@ -2199,21 +2227,32 @@
    v_U8_t  del_idx   = 0;
    v_U8_t  empty_slots = 0;
    hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+   VOS_STATUS status;
 
    for ( idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++ )
    {
       if ( staId == pHddStaCtx->conn_info.staId[ idx ] )
       {
          pHddStaCtx->conn_info.staId[ idx ] = 0;
+         status = hdd_sta_id_hash_remove_entry(pAdapter,
+                  staId, &pHddStaCtx->conn_info.peerMacAddress[idx]);
+         if (status != VOS_STATUS_SUCCESS) {
+             hddLog(VOS_TRACE_LEVEL_ERROR,
+                      FL("Not able to remove staid hash %d"), staId );
+             fSuccess = FALSE;
+         } else {
+             hddLog(VOS_TRACE_LEVEL_INFO,
+                   FL("station removed sta_id %d mac:"
+                   MAC_ADDRESS_STR), staId,
+                   MAC_ADDR_ARRAY(pHddStaCtx->conn_info.peerMacAddress[idx].bytes));
 
-         vos_zero_macaddr( &pHddStaCtx->conn_info.peerMacAddress[ idx ] );
+             vos_zero_macaddr( &pHddStaCtx->conn_info.peerMacAddress[ idx ] );
 
-         fSuccess = TRUE;
-
-         // Note the deleted Index, if its 0 we need special handling
-         del_idx = idx;
-
-         empty_slots++;
+             fSuccess = TRUE;
+             // Note the deleted Index, if its 0 we need special handling
+             del_idx = idx;
+             empty_slots++;
+         }
       }
       else
       {
@@ -2568,7 +2607,7 @@
                     MAC_ADDR_ARRAY(pHddStaCtx->conn_info.bssId),
                     pRoamInfo->staId );
 
-         if ( !roamSaveIbssStation( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), pRoamInfo->staId, (v_MACADDR_t *)pRoamInfo->peerMac ) )
+         if ( !roamSaveIbssStation( pAdapter, pRoamInfo->staId, (v_MACADDR_t *)pRoamInfo->peerMac ) )
          {
             VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
                        "New IBSS peer but we already have the max we can handle.  Can't register this one" );
diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c
index c8ebdeb..40f4435 100644
--- a/CORE/HDD/src/wlan_hdd_cfg80211.c
+++ b/CORE/HDD/src/wlan_hdd_cfg80211.c
@@ -8093,6 +8093,12 @@
                 wdev->iftype = type;
                 hdd_set_ibss_ops( pAdapter );
                 hdd_ibss_init_tx_rx( pAdapter );
+
+                status = hdd_sta_id_hash_attach(pAdapter);
+                if (VOS_STATUS_SUCCESS != status) {
+                     hddLog(VOS_TRACE_LEVEL_ERROR,
+                            FL("Failed to initialize hash for IBSS"));
+                }
                 break;
 
             case NL80211_IFTYPE_AP:
@@ -8224,6 +8230,14 @@
                 }
                 hdd_set_conparam(1);
 
+                status = hdd_sta_id_hash_attach(pAdapter);
+                if (VOS_STATUS_SUCCESS != status)
+                {
+                    hddLog(VOS_TRACE_LEVEL_ERROR,
+                           FL("Failed to initialize hash for AP"));
+                    return -EINVAL;
+                }
+
                 /*interface type changed update in wiphy structure*/
                 if(wdev)
                 {
diff --git a/CORE/HDD/src/wlan_hdd_hostapd.c b/CORE/HDD/src/wlan_hdd_hostapd.c
index 7e2319f..70a76d4 100644
--- a/CORE/HDD/src/wlan_hdd_hostapd.c
+++ b/CORE/HDD/src/wlan_hdd_hostapd.c
@@ -4797,6 +4797,9 @@
        // Allocate the Wireless Extensions state structure
     phostapdBuf = WLAN_HDD_GET_HOSTAP_STATE_PTR( pAdapter );
 
+    spin_lock_init(&pAdapter->sta_hash_lock);
+    pAdapter->is_sta_id_hash_initialized = VOS_FALSE;
+
     sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
 
 #ifdef FEATURE_WLAN_CH_AVOID
diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c
index 8a6f62c..2cb2f3d 100755
--- a/CORE/HDD/src/wlan_hdd_main.c
+++ b/CORE/HDD/src/wlan_hdd_main.c
@@ -6318,6 +6318,9 @@
    VOS_STATUS status = VOS_STATUS_E_FAILURE;
    long rc = 0;
 
+   spin_lock_init( &pAdapter->sta_hash_lock);
+   pAdapter->is_sta_id_hash_initialized = VOS_FALSE;
+
    INIT_COMPLETION(pAdapter->session_open_comp_var);
    sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
    //Open a SME session for future operation
@@ -6929,6 +6932,15 @@
          if( VOS_STATUS_SUCCESS != status )
             goto err_free_netdev;
 
+         status = hdd_sta_id_hash_attach(pAdapter);
+         if (VOS_STATUS_SUCCESS != status)
+         {
+             hddLog(VOS_TRACE_LEVEL_FATAL,
+                    FL("failed to attach hash for session %d"), session_type);
+             hdd_deinit_adapter(pHddCtx, pAdapter, rtnl_held);
+             goto err_free_netdev;
+         }
+
          status = hdd_register_hostapd( pAdapter, rtnl_held );
          if( VOS_STATUS_SUCCESS != status )
          {
@@ -7207,6 +7219,7 @@
    union iwreq_data wrqu;
    v_U8_t retry = 0;
    long ret;
+   VOS_STATUS status;
 
    if (pHddCtx->isLogpInProgress) {
        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
@@ -7216,6 +7229,11 @@
 
    ENTER();
 
+   status = hdd_sta_id_hash_detach(pAdapter);
+   if (status != VOS_STATUS_SUCCESS)
+       hddLog(VOS_TRACE_LEVEL_ERROR,
+                 FL("sta id hash detach failed"));
+
    pScanInfo =  &pHddCtx->scan_info;
    switch(pAdapter->device_mode)
    {
@@ -7521,6 +7539,12 @@
       if(pAdapter->device_mode == WLAN_HDD_IBSS )
          hdd_ibss_deinit_tx_rx(pAdapter);
 
+      status = hdd_sta_id_hash_detach(pAdapter);
+      if (status != VOS_STATUS_SUCCESS)
+          hddLog(VOS_TRACE_LEVEL_ERROR,
+                 FL("sta id hash detach failed for session id %d"),
+                 pAdapter->sessionId);
+
       wlan_hdd_decr_active_session(pHddCtx, pAdapter->device_mode);
 
       if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
@@ -11517,6 +11541,286 @@
     return status;
 }
 
+static int hdd_log2_ceil(unsigned value)
+{
+    /* need to switch to unsigned math so that negative values
+     * will right-shift towards 0 instead of -1
+     */
+    unsigned tmp = value;
+    int log2 = -1;
+
+    if (value == 0)
+        return 0;
+
+    while (tmp) {
+        log2++;
+        tmp >>= 1;
+    }
+    if (1U << log2 != value)
+        log2++;
+
+    return log2;
+}
+
+/**
+ * hdd_sta_id_hash_attach() - initialize sta id to macaddr hash
+ * @pAdapter: adapter handle
+ *
+ * Return: vos status
+ */
+VOS_STATUS hdd_sta_id_hash_attach(hdd_adapter_t *pAdapter)
+{
+    int hash_elem, log2, i;
+
+    spin_lock_bh( &pAdapter->sta_hash_lock);
+    if (pAdapter->is_sta_id_hash_initialized == VOS_TRUE) {
+        spin_unlock_bh( &pAdapter->sta_hash_lock);
+        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                  "%s: hash already attached for session id %d",
+                  __func__, pAdapter->sessionId);
+        return VOS_STATUS_SUCCESS;
+    }
+    spin_unlock_bh( &pAdapter->sta_hash_lock);
+
+    hash_elem = WLAN_MAX_STA_COUNT;
+    hash_elem *= HDD_STA_ID_HASH_MULTIPLIER;
+    log2 = hdd_log2_ceil(hash_elem);
+    hash_elem = 1 << log2;
+
+    pAdapter->sta_id_hash.mask = hash_elem - 1;
+    pAdapter->sta_id_hash.idx_bits = log2;
+    pAdapter->sta_id_hash.bins =
+        vos_mem_malloc(hash_elem *sizeof(hdd_list_t));
+    if (!pAdapter->sta_id_hash.bins) {
+        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                  "%s: malloc failed for session %d",
+                  __func__, pAdapter->sessionId);
+        return VOS_STATUS_E_NOMEM;
+    }
+
+    for (i = 0; i < hash_elem; i++)
+        hdd_list_init(&pAdapter->sta_id_hash.bins[i], WLAN_MAX_STA_COUNT);
+
+    spin_lock_bh( &pAdapter->sta_hash_lock);
+    pAdapter->is_sta_id_hash_initialized = VOS_TRUE;
+    spin_unlock_bh( &pAdapter->sta_hash_lock);
+    VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+              "%s: Station ID Hash attached for session id %d",
+              __func__, pAdapter->sessionId);
+
+    return VOS_STATUS_SUCCESS;
+}
+
+/**
+ * hdd_sta_id_hash_detach() - deinit sta_id to macaddr hash
+ * @pAdapter: adapter handle
+ *
+ * Return: vos status
+ */
+VOS_STATUS hdd_sta_id_hash_detach(hdd_adapter_t *pAdapter)
+{
+    int hash_elem, i;
+    v_SIZE_t size;
+
+    spin_lock_bh( &pAdapter->sta_hash_lock);
+    if (pAdapter->is_sta_id_hash_initialized != VOS_TRUE) {
+        spin_unlock_bh( &pAdapter->sta_hash_lock);
+        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+                  "%s: hash not initialized for session id %d",
+                  __func__, pAdapter->sessionId);
+        return VOS_STATUS_SUCCESS;
+    }
+
+    pAdapter->is_sta_id_hash_initialized = VOS_FALSE;
+    spin_unlock_bh( &pAdapter->sta_hash_lock);
+
+    hash_elem = 1 << pAdapter->sta_id_hash.idx_bits;
+
+    /* free all station info*/
+    for (i = 0; i < hash_elem; i++) {
+        hdd_list_size(&pAdapter->sta_id_hash.bins[i], &size);
+        if (size != 0) {
+            VOS_STATUS status;
+            hdd_staid_hash_node_t *sta_info_node = NULL;
+            hdd_staid_hash_node_t *next_node = NULL;
+            status = hdd_list_peek_front ( &pAdapter->sta_id_hash.bins[i],
+                                           (hdd_list_node_t**) &sta_info_node );
+
+            while ( NULL != sta_info_node && VOS_STATUS_SUCCESS == status )
+            {
+                status = hdd_list_remove_node( &pAdapter->sta_id_hash.bins[i],
+                                               &sta_info_node->node);
+                vos_mem_free(sta_info_node);
+
+                status = hdd_list_peek_next (&pAdapter->sta_id_hash.bins[i],
+                                            (hdd_list_node_t*)sta_info_node,
+                                            (hdd_list_node_t**)&next_node);
+                sta_info_node = next_node;
+            }
+        }
+    }
+
+    vos_mem_free(pAdapter->sta_id_hash.bins);
+    VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+              "%s: Station ID Hash detached for session id %d",
+              __func__, pAdapter->sessionId);
+    return VOS_STATUS_SUCCESS;
+}
+
+/**
+ * hdd_sta_id_hash_calculate_index() - derive index from macaddr
+ * @pAdapter: adapter handle
+ * @mac_addr_in: input mac address
+ *
+ * Return: index derived from mac address
+ */
+int hdd_sta_id_hash_calculate_index(hdd_adapter_t *pAdapter,
+                               v_MACADDR_t *mac_addr_in)
+{
+    uint16 index;
+    struct hdd_align_mac_addr_t * mac_addr =
+                     (struct hdd_align_mac_addr_t *)mac_addr_in;
+
+    index = mac_addr->bytes_ab ^
+            mac_addr->bytes_cd ^ mac_addr->bytes_ef;
+    index ^= index >> pAdapter->sta_id_hash.idx_bits;
+    index &= pAdapter->sta_id_hash.mask;
+    return index;
+}
+
+/**
+ * hdd_sta_id_hash_add_entry() - add entry in hash
+ * @pAdapter: adapter handle
+ * @sta_id: station id
+ * @mac_addr: mac address
+ *
+ * Return: vos status
+ */
+VOS_STATUS hdd_sta_id_hash_add_entry(hdd_adapter_t *pAdapter,
+                                    v_U8_t sta_id, v_MACADDR_t *mac_addr)
+{
+    uint16 index;
+    hdd_staid_hash_node_t *sta_info_node = NULL;
+
+    spin_lock_bh( &pAdapter->sta_hash_lock);
+    if (pAdapter->is_sta_id_hash_initialized != VOS_TRUE) {
+        spin_unlock_bh( &pAdapter->sta_hash_lock);
+        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                  "%s: hash is not initialized for session id %d",
+                  __func__, pAdapter->sessionId);
+        return VOS_STATUS_E_FAILURE;
+    }
+
+    index = hdd_sta_id_hash_calculate_index(pAdapter, mac_addr);
+    sta_info_node = vos_mem_malloc(sizeof(hdd_staid_hash_node_t));
+    if (!sta_info_node) {
+        spin_unlock_bh( &pAdapter->sta_hash_lock);
+        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                  "%s: malloc failed", __func__);
+        return VOS_STATUS_E_NOMEM;
+    }
+
+    sta_info_node->sta_id = sta_id;
+    vos_mem_copy(&sta_info_node->mac_addr, mac_addr, sizeof(v_MACADDR_t));
+
+    hdd_list_insert_back ( &pAdapter->sta_id_hash.bins[index],
+                           (hdd_list_node_t*) sta_info_node );
+    spin_unlock_bh( &pAdapter->sta_hash_lock);
+    return VOS_STATUS_SUCCESS;
+}
+
+/**
+ * hdd_sta_id_hash_remove_entry() - remove entry from hash
+ * @pAdapter: adapter handle
+ * @sta_id: station id
+ * @mac_addr: mac address
+ *
+ * Return: vos status
+ */
+VOS_STATUS hdd_sta_id_hash_remove_entry(hdd_adapter_t *pAdapter,
+                                       v_U8_t sta_id, v_MACADDR_t *mac_addr)
+{
+    uint16 index;
+    VOS_STATUS status;
+    hdd_staid_hash_node_t *sta_info_node = NULL;
+    hdd_staid_hash_node_t *next_node = NULL;
+
+    spin_lock_bh( &pAdapter->sta_hash_lock);
+    if (pAdapter->is_sta_id_hash_initialized != VOS_TRUE) {
+        spin_unlock_bh( &pAdapter->sta_hash_lock);
+        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+                  "%s: hash is not initialized for session id %d",
+                  __func__, pAdapter->sessionId);
+        return VOS_STATUS_E_FAILURE;
+    }
+
+    index = hdd_sta_id_hash_calculate_index(pAdapter, mac_addr);
+    status = hdd_list_peek_front ( &pAdapter->sta_id_hash.bins[index],
+                                   (hdd_list_node_t**) &sta_info_node );
+
+    while ( NULL != sta_info_node && VOS_STATUS_SUCCESS == status )
+    {
+        if (sta_info_node->sta_id == sta_id) {
+            status = hdd_list_remove_node( &pAdapter->sta_id_hash.bins[index],
+                                       &sta_info_node->node);
+            vos_mem_free(sta_info_node);
+            break;
+        }
+        status = hdd_list_peek_next (&pAdapter->sta_id_hash.bins[index],
+                (hdd_list_node_t*)sta_info_node, (hdd_list_node_t**)&next_node);
+        sta_info_node = next_node;
+    }
+    spin_unlock_bh( &pAdapter->sta_hash_lock);
+    return status;
+}
+
+/**
+ * hdd_sta_id_find_from_mac_addr() - find sta id from mac address
+ * @pAdapter: adapter handle
+ * @mac_addr_in: mac address
+ *
+ * Return: station id
+ */
+int hdd_sta_id_find_from_mac_addr(hdd_adapter_t *pAdapter,
+                                  v_MACADDR_t *mac_addr_in)
+{
+    uint8 is_found = 0;
+    uint8 sta_id = HDD_WLAN_INVALID_STA_ID;
+    uint16 index;
+    VOS_STATUS status;
+    hdd_staid_hash_node_t *sta_info_node = NULL;
+    hdd_staid_hash_node_t *next_node = NULL;
+
+    spin_lock_bh( &pAdapter->sta_hash_lock);
+    if (pAdapter->is_sta_id_hash_initialized != VOS_TRUE) {
+        spin_unlock_bh( &pAdapter->sta_hash_lock);
+        hddLog(VOS_TRACE_LEVEL_ERROR,
+                  FL("hash is not initialized for session id %d"),
+                  pAdapter->sessionId);
+        return HDD_WLAN_INVALID_STA_ID;
+    }
+
+    index = hdd_sta_id_hash_calculate_index(pAdapter, mac_addr_in);
+    status = hdd_list_peek_front ( &pAdapter->sta_id_hash.bins[index],
+                                   (hdd_list_node_t**) &sta_info_node );
+
+    while ( NULL != sta_info_node && VOS_STATUS_SUCCESS == status )
+    {
+        if (vos_mem_compare(&sta_info_node->mac_addr,
+                            mac_addr_in, sizeof(v_MACADDR_t))) {
+            is_found = 1;
+            sta_id = sta_info_node->sta_id;
+            break;
+        }
+        status = hdd_list_peek_next (&pAdapter->sta_id_hash.bins[index],
+                                     (hdd_list_node_t*)sta_info_node,
+                                     (hdd_list_node_t**)&next_node);
+        sta_info_node = next_node;
+    }
+    spin_unlock_bh( &pAdapter->sta_hash_lock);
+    return sta_id;
+}
+
 //Register the module init/exit functions
 module_init(hdd_module_init);
 module_exit(hdd_module_exit);
diff --git a/CORE/HDD/src/wlan_hdd_softap_tx_rx.c b/CORE/HDD/src/wlan_hdd_softap_tx_rx.c
index 6c3b47a..a107b03 100644
--- a/CORE/HDD/src/wlan_hdd_softap_tx_rx.c
+++ b/CORE/HDD/src/wlan_hdd_softap_tx_rx.c
@@ -341,7 +341,7 @@
    }
    else
    {
-      STAId = *(v_U8_t *)(((v_U8_t *)(skb->data)) - 1);
+      STAId = hdd_sta_id_find_from_mac_addr(pAdapter, pDestMacAddress);
       if (STAId == HDD_WLAN_INVALID_STA_ID)
       {
          VOS_TRACE( VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_WARN,
@@ -938,8 +938,10 @@
 VOS_STATUS hdd_softap_init_tx_rx_sta( hdd_adapter_t *pAdapter, v_U8_t STAId, v_MACADDR_t *pmacAddrSTA)
 {
    v_U8_t i = 0;
+   VOS_STATUS status;
    v_CONTEXT_t pVosContext = ( WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
    ptSapContext pSapCtx = NULL;
+
    pSapCtx = VOS_GET_SAP_CB(pVosContext);
    if(pSapCtx == NULL){
        VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
@@ -967,6 +969,19 @@
    vos_copy_macaddr( &pSapCtx->aStaInfo[STAId].macAddrSTA, pmacAddrSTA);
 
    spin_unlock_bh( &pSapCtx->staInfo_lock );
+
+   status = hdd_sta_id_hash_add_entry(pAdapter, STAId, pmacAddrSTA);
+   if (status != VOS_STATUS_SUCCESS) {
+       VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
+                 FL("Not able to add staid hash %d"), STAId);
+       return VOS_STATUS_E_FAILURE;
+   }
+
+   VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
+             FL("New station added sta_id %d mac:"
+             MAC_ADDRESS_STR), STAId,
+             MAC_ADDR_ARRAY(pmacAddrSTA->bytes));
+
    return VOS_STATUS_SUCCESS;
 }
 
@@ -1012,6 +1027,20 @@
 
    pSapCtx->aStaInfo[STAId].isUsed = FALSE;
    pSapCtx->aStaInfo[STAId].isDeauthInProgress = FALSE;
+
+   status = hdd_sta_id_hash_remove_entry(pAdapter,
+                STAId, &pSapCtx->aStaInfo[STAId].macAddrSTA);
+   if (status != VOS_STATUS_SUCCESS) {
+       VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_ERROR,
+                 FL("Not able to remove staid hash %d"), STAId);
+       return VOS_STATUS_E_FAILURE;
+   }
+
+   VOS_TRACE(VOS_MODULE_ID_HDD_SAP_DATA, VOS_TRACE_LEVEL_INFO,
+             FL("station removed sta_id %d mac:"
+             MAC_ADDRESS_STR), STAId,
+             MAC_ADDR_ARRAY(pSapCtx->aStaInfo[STAId].macAddrSTA.bytes));
+
    /* if this STA had any of its WMM TX queues suspended, then the
       associated queue on the network interface was disabled.  check
       to see if that is the case, in which case we need to re-enable
diff --git a/CORE/HDD/src/wlan_hdd_tx_rx.c b/CORE/HDD/src/wlan_hdd_tx_rx.c
index 0035aa6..2acd82f 100644
--- a/CORE/HDD/src/wlan_hdd_tx_rx.c
+++ b/CORE/HDD/src/wlan_hdd_tx_rx.c
@@ -646,8 +646,7 @@
         return NETDEV_TX_OK;
     }
 
-     STAId = *(v_U8_t *)(((v_U8_t *)(skb->data)) - 1);
-
+     STAId = hdd_sta_id_find_from_mac_addr(pAdapter, pDestMacAddress);
      if ((STAId == HDD_WLAN_INVALID_STA_ID) &&
            (vos_is_macaddr_broadcast( pDestMacAddress ) ||
             vos_is_macaddr_group(pDestMacAddress)))
diff --git a/CORE/HDD/src/wlan_hdd_wmm.c b/CORE/HDD/src/wlan_hdd_wmm.c
index cecdd18..40f87b5 100644
--- a/CORE/HDD/src/wlan_hdd_wmm.c
+++ b/CORE/HDD/src/wlan_hdd_wmm.c
@@ -2091,7 +2091,6 @@
    hdd_adapter_t *pAdapter = (hdd_adapter_t *)netdev_priv(dev);
    hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
    v_U8_t STAId;
-   v_U8_t *pSTAId = (v_U8_t *)(((v_U8_t *)(skb->data)) - 1);
    v_CONTEXT_t pVosContext = ( WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
    ptSapContext pSapCtx = NULL;
    int status = 0;
@@ -2109,16 +2108,15 @@
    if(pSapCtx == NULL){
        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
                  FL("psapCtx is NULL"));
-       *pSTAId = HDD_WLAN_INVALID_STA_ID;
+       STAId = HDD_WLAN_INVALID_STA_ID;
        goto done;
    }
    /*Get the Station ID*/
-   if (VOS_STATUS_SUCCESS != hdd_softap_GetStaId(pAdapter, pDestMacAddress, &STAId))
-   {
-      VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
-            "%s: Failed to find right station", __func__);
-      *pSTAId = HDD_WLAN_INVALID_STA_ID;
-      goto done;
+   STAId = hdd_sta_id_find_from_mac_addr(pAdapter, pDestMacAddress);
+   if (STAId == HDD_WLAN_INVALID_STA_ID) {
+       VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
+                 "%s: Failed to find right station", __func__);
+       goto done;
    }
 
    spin_lock_bh( &pSapCtx->staInfo_lock );
@@ -2127,7 +2125,7 @@
       VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_INFO,
                    "%s: Station MAC address does not matching", __func__);
 
-      *pSTAId = HDD_WLAN_INVALID_STA_ID;
+      STAId = HDD_WLAN_INVALID_STA_ID;
       goto release_lock;
    }
    if (pSapCtx->aStaInfo[STAId].isUsed && pSapCtx->aStaInfo[STAId].isQosEnabled && (HDD_WMM_USER_MODE_NO_QOS != pHddCtx->cfg_ini->WmmMode))
@@ -2143,7 +2141,6 @@
          ac = hddWmmUpToAcMap[up];
       }
    }
-   *pSTAId = STAId;
 
 release_lock:
     spin_unlock_bh( &pSapCtx->staInfo_lock );
@@ -2189,23 +2186,19 @@
    /*Get the Station ID*/
    if (WLAN_HDD_IBSS == pAdapter->device_mode)
    {
-       v_U8_t *pSTAId = (v_U8_t *)(((v_U8_t *)(skb->data)) - 1);
        v_MACADDR_t *pDestMacAddress = (v_MACADDR_t*)skb->data;
+       v_U8_t STAId;
 
-       if ( VOS_STATUS_SUCCESS !=
-            hdd_Ibss_GetStaId(&pAdapter->sessionCtx.station,
-                               pDestMacAddress, pSTAId))
+       STAId = hdd_sta_id_find_from_mac_addr(pAdapter, pDestMacAddress);
+       if ((STAId == HDD_WLAN_INVALID_STA_ID) &&
+            !vos_is_macaddr_broadcast( pDestMacAddress ) &&
+            !vos_is_macaddr_group(pDestMacAddress))
        {
-          *pSTAId = HDD_WLAN_INVALID_STA_ID;
-          if ( !vos_is_macaddr_broadcast( pDestMacAddress ) &&
-                             !vos_is_macaddr_group(pDestMacAddress))
-          {
-              VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+           VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
                      "%s: Failed to find right station pDestMacAddress: "
                      MAC_ADDRESS_STR , __func__,
                      MAC_ADDR_ARRAY(pDestMacAddress->bytes));
-              goto done;
-          }
+           goto done;
        }
    }
    /* All traffic will get equal opportuniy to transmit data frames. */