qcacld-3.0: Move sta_info from array based to hash based

Currently in hdd_adapter, the variable sta_info is an array of
hdd_station_info structured indexed by the sta_id. As sta_id is no
longer used this array based implementation becomes unnecessary.

Move the sta_info implementation to a hash table implementation.

Change-Id: I7d6fe04b7e0ab22615d431de9a10a4ad38ed65ba
CRs-Fixed: 2514280
diff --git a/Kbuild b/Kbuild
index 8fa2d1e..cbff722 100644
--- a/Kbuild
+++ b/Kbuild
@@ -77,6 +77,7 @@
 		$(HDD_SRC_DIR)/wlan_hdd_regulatory.o \
 		$(HDD_SRC_DIR)/wlan_hdd_scan.o \
 		$(HDD_SRC_DIR)/wlan_hdd_softap_tx_rx.o \
+		$(HDD_SRC_DIR)/wlan_hdd_sta_info.o \
 		$(HDD_SRC_DIR)/wlan_hdd_stats.o \
 		$(HDD_SRC_DIR)/wlan_hdd_trace.o \
 		$(HDD_SRC_DIR)/wlan_hdd_tx_rx.o \
diff --git a/components/mlme/dispatcher/inc/wlan_mlme_api.h b/components/mlme/dispatcher/inc/wlan_mlme_api.h
index b5e0a10..6baab17 100644
--- a/components/mlme/dispatcher/inc/wlan_mlme_api.h
+++ b/components/mlme/dispatcher/inc/wlan_mlme_api.h
@@ -555,7 +555,7 @@
 					   bool value);
 
 /**
- * wlan_mlme_is_sap_bcast_deauth_enabled() - get the enable/disable value
+ * wlan_mlme_get_sap_bcast_deauth_enabled() - get the enable/disable value
  *                                           for broadcast deauth in sap
  * @psoc: pointer to psoc object
  * @value: Value that needs to get from the caller
@@ -563,8 +563,8 @@
  * Return: QDF Status
  */
 QDF_STATUS
-wlan_mlme_is_sap_bcast_deauth_enabled(struct wlan_objmgr_psoc *psoc,
-				      bool *value);
+wlan_mlme_get_sap_bcast_deauth_enabled(struct wlan_objmgr_psoc *psoc,
+				       bool *value);
 
 /**
  * wlan_mlme_get_sap_allow_all_channels() - get the value of sap allow all
diff --git a/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h b/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h
index 7a070b6..0ed2480 100644
--- a/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h
+++ b/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h
@@ -1421,7 +1421,7 @@
 }
 
 /**
- * ucfg_mlme_is_sap_bcast_deauth_enabled() - get the sap bcast deauth
+ * ucfg_mlme_get_sap_bcast_deauth_enabled() - get the sap bcast deauth
  *                                           enabled value
  * @psoc: pointer to psoc object
  * @value: Value that needs to be get from the caller
@@ -1431,10 +1431,10 @@
  * Return: QDF Status
  */
 static inline QDF_STATUS
-ucfg_mlme_is_sap_bcast_deauth_enabled(struct wlan_objmgr_psoc *psoc,
-				      bool *value)
+ucfg_mlme_get_sap_bcast_deauth_enabled(struct wlan_objmgr_psoc *psoc,
+				       bool *value)
 {
-	return wlan_mlme_is_sap_bcast_deauth_enabled(psoc, value);
+	return wlan_mlme_get_sap_bcast_deauth_enabled(psoc, value);
 }
 
 /**
diff --git a/components/mlme/dispatcher/src/wlan_mlme_api.c b/components/mlme/dispatcher/src/wlan_mlme_api.c
index b9431ee..334074c 100644
--- a/components/mlme/dispatcher/src/wlan_mlme_api.c
+++ b/components/mlme/dispatcher/src/wlan_mlme_api.c
@@ -1716,8 +1716,8 @@
 }
 
 QDF_STATUS
-wlan_mlme_is_sap_bcast_deauth_enabled(struct wlan_objmgr_psoc *psoc,
-				      bool *value)
+wlan_mlme_get_sap_bcast_deauth_enabled(struct wlan_objmgr_psoc *psoc,
+				       bool *value)
 {
 	struct wlan_mlme_psoc_obj *mlme_obj;
 
diff --git a/core/hdd/inc/qc_sap_ioctl.h b/core/hdd/inc/qc_sap_ioctl.h
index f5d04b7..7226536 100644
--- a/core/hdd/inc/qc_sap_ioctl.h
+++ b/core/hdd/inc/qc_sap_ioctl.h
@@ -226,7 +226,7 @@
 	QCSAP_PARAM_CHAN_WIDTH,
 	QCSAP_PARAM_SET_TXRX_STATS,
 	QCASAP_SET_11AX_RATE,
-	QCASAP_SET_PEER_RATE,
+	QCASAP_SET_PEER_RATE, /* Not Supported */
 	QCASAP_PARAM_DCM,
 	QCASAP_PARAM_RANGE_EXT,
 	QCSAP_SET_DEFAULT_AMPDU,
diff --git a/core/hdd/inc/wlan_hdd_assoc.h b/core/hdd/inc/wlan_hdd_assoc.h
index 2aa5bc7..e625240 100644
--- a/core/hdd/inc/wlan_hdd_assoc.h
+++ b/core/hdd/inc/wlan_hdd_assoc.h
@@ -388,8 +388,17 @@
 					    const uint8_t numBss);
 #endif /* FEATURE_WLAN_ESE */
 
+/**
+ * hdd_change_peer_state() - change peer state
+ * @adapter: HDD adapter
+ * @peer_mac_addr: Peer MAC address
+ * @sta_state: peer state
+ * @roam_synch_in_progress: roam synch in progress
+ *
+ * Return: QDF status
+ */
 QDF_STATUS hdd_change_peer_state(struct hdd_adapter *adapter,
-				 uint8_t sta_id,
+				 uint8_t *peer_mac_addr,
 				 enum ol_txrx_peer_state sta_state,
 				 bool roam_synch_in_progress);
 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h
index da5af95..8895830 100644
--- a/core/hdd/inc/wlan_hdd_main.h
+++ b/core/hdd/inc/wlan_hdd_main.h
@@ -112,6 +112,8 @@
 #include "qdf_periodic_work.h"
 #endif
 
+#include "wlan_hdd_sta_info.h"
+
 /*
  * Preprocessor definitions and constants
  */
@@ -881,135 +883,6 @@
 };
 
 /**
- * struct dhcp_phase - Per Peer DHCP Phases
- * @DHCP_PHASE_ACK: upon receiving DHCP_ACK/NAK message in REQUEST phase or
- *         DHCP_DELINE message in OFFER phase
- * @DHCP_PHASE_DISCOVER: upon receiving DHCP_DISCOVER message in ACK phase
- * @DHCP_PHASE_OFFER: upon receiving DHCP_OFFER message in DISCOVER phase
- * @DHCP_PHASE_REQUEST: upon receiving DHCP_REQUEST message in OFFER phase or
- *         ACK phase (Renewal process)
- */
-enum dhcp_phase {
-	DHCP_PHASE_ACK,
-	DHCP_PHASE_DISCOVER,
-	DHCP_PHASE_OFFER,
-	DHCP_PHASE_REQUEST
-};
-
-/**
- * struct dhcp_nego_status - Per Peer DHCP Negotiation Status
- * @DHCP_NEGO_STOP: when the peer is in ACK phase or client disassociated
- * @DHCP_NEGO_IN_PROGRESS: when the peer is in DISCOVER or REQUEST
- *         (Renewal process) phase
- */
-enum dhcp_nego_status {
-	DHCP_NEGO_STOP,
-	DHCP_NEGO_IN_PROGRESS
-};
-
-/**
- * struct hdd_station_info - Per station structure kept in HDD for
- *                                     multiple station support for SoftAP
- * @in_use: Is the station entry in use?
- * @sta_id: Station ID reported back from HAL (through SAP).
- *           Broadcast uses station ID zero by default.
- * @sta_type: Type of station i.e. p2p client or infrastructure station
- * @sta_mac: MAC address of the station
- * @peer_state: Current Station state so HDD knows how to deal with packet
- *              queue. Most recent states used to change TLSHIM STA state.
- * @is_qos_enabled: Track QoS status of station
- * @is_deauth_in_progress: The station entry for which Deauth is in progress
- * @nss: Number of spatial streams supported
- * @rate_flags: Rate Flags for this connection
- * @ecsa_capable: Extended CSA capabilities
- * @max_phy_rate: Calcuated maximum phy rate based on mode, nss, mcs etc.
- * @tx_packets: Packets send to current station
- * @tx_bytes: Bytes send to current station
- * @rx_packets: Packets received from current station
- * @rx_bytes: Bytes received from current station
- * @last_tx_rx_ts: Last tx/rx timestamp with current station
- * @assoc_ts: Current station association timestamp
- * @tx_rate: Tx rate with current station reported from F/W
- * @rx_rate: Rx rate with current station reported from F/W
- * @ampdu: Ampdu enable or not of the station
- * @sgi_enable: Short GI enable or not of the station
- * @tx_stbc: Tx Space-time block coding enable/disable
- * @rx_stbc: Rx Space-time block coding enable/disable
- * @ch_width: Channel Width of the connection
- * @mode: Mode of the connection
- * @max_supp_idx: Max supported rate index of the station
- * @max_ext_idx: Max extended supported rate index of the station
- * @max_mcs_idx: Max supported mcs index of the station
- * @rx_mcs_map: VHT Rx mcs map
- * @tx_mcs_map: VHT Tx mcs map
- * @freq : Frequency of the current station
- * @dot11_mode: 802.11 Mode of the connection
- * @ht_present: HT caps present or not in the current station
- * @vht_present: VHT caps present or not in the current station
- * @ht_caps: HT capabilities of current station
- * @vht_caps: VHT capabilities of current station
- * @reason_code: Disconnection reason code for current station
- * @rssi: RSSI of the current station reported from F/W
- * @capability: Capability information of current station
- * @support_mode: Max supported mode of a station currently
- * connected to sap
- * @rx_retry_cnt: Number of rx retries received from current station
- *                Currently this feature is not supported from FW
- * @rx_mc_bc_cnt: Multicast broadcast packet count received from
- *                current station
- * MSB of rx_mc_bc_cnt indicates whether FW supports rx_mc_bc_cnt
- * feature or not, if first bit is 1 it indicates that FW supports this
- * feature, if it is 0 it indicates FW doesn't support this feature
- */
-struct hdd_station_info {
-	bool in_use;
-	uint8_t sta_id;
-	eStationType sta_type;
-	struct qdf_mac_addr sta_mac;
-	enum ol_txrx_peer_state peer_state;
-	bool is_qos_enabled;
-	bool is_deauth_in_progress;
-	uint8_t   nss;
-	uint32_t  rate_flags;
-	uint8_t   ecsa_capable;
-	uint32_t max_phy_rate;
-	uint32_t tx_packets;
-	uint64_t tx_bytes;
-	uint32_t rx_packets;
-	uint64_t rx_bytes;
-	qdf_time_t last_tx_rx_ts;
-	qdf_time_t assoc_ts;
-	qdf_time_t disassoc_ts;
-	uint32_t tx_rate;
-	uint32_t rx_rate;
-	bool ampdu;
-	bool sgi_enable;
-	bool tx_stbc;
-	bool rx_stbc;
-	tSirMacHTChannelWidth ch_width;
-	uint8_t mode;
-	uint8_t max_supp_idx;
-	uint8_t max_ext_idx;
-	uint8_t max_mcs_idx;
-	uint8_t rx_mcs_map;
-	uint8_t tx_mcs_map;
-	uint32_t freq;
-	uint8_t dot11_mode;
-	bool ht_present;
-	bool vht_present;
-	struct ieee80211_ht_cap ht_caps;
-	struct ieee80211_vht_cap vht_caps;
-	uint32_t reason_code;
-	int8_t rssi;
-	enum dhcp_phase dhcp_phase;
-	enum dhcp_nego_status dhcp_nego_status;
-	uint16_t capability;
-	uint8_t support_mode;
-	uint32_t rx_retry_cnt;
-	uint32_t rx_mc_bc_cnt;
-};
-
-/**
  * struct hdd_ap_ctx - SAP/P2PGO specific information
  * @hostapd_state: state control information
  * @dfs_cac_block_tx: Is data tramsmission blocked due to DFS CAC?
@@ -1264,10 +1137,14 @@
 
 	/** Multiple station supports */
 	/** Per-station structure */
-	spinlock_t sta_info_lock;        /* To protect access to station Info */
+
+	/* TODO: Will be removed as a part of next phase of clean up */
 	struct hdd_station_info sta_info[WLAN_MAX_STA_COUNT];
 	struct hdd_station_info cache_sta_info[WLAN_MAX_STA_COUNT];
 
+	/* TODO: _list from name will be removed after clean up */
+	struct hdd_sta_info_obj sta_info_list;
+	struct hdd_sta_info_obj cache_sta_info_list;
 
 #ifdef FEATURE_WLAN_WAPI
 	struct hdd_wapi_info wapi_info;
diff --git a/core/hdd/inc/wlan_hdd_softap_tx_rx.h b/core/hdd/inc/wlan_hdd_softap_tx_rx.h
index c110a7a..39b05c6 100644
--- a/core/hdd/inc/wlan_hdd_softap_tx_rx.h
+++ b/core/hdd/inc/wlan_hdd_softap_tx_rx.h
@@ -70,10 +70,9 @@
  * hdd_softap_init_tx_rx() - Initialize Tx/Rx module
  * @adapter: pointer to adapter context
  *
- * Return: QDF_STATUS_E_FAILURE if any errors encountered,
- *	   QDF_STATUS_SUCCESS otherwise
+ * Return: None
  */
-QDF_STATUS hdd_softap_init_tx_rx(struct hdd_adapter *adapter);
+void hdd_softap_init_tx_rx(struct hdd_adapter *adapter);
 
 /**
  * hdd_softap_deinit_tx_rx() - Deinitialize Tx/Rx module
@@ -87,28 +86,15 @@
 /**
  * hdd_softap_init_tx_rx_sta() - Initialize Tx/Rx for a softap station
  * @adapter: pointer to adapter context
- * @sta_id: Station ID to initialize
  * @sta_mac: pointer to the MAC address of the station
  *
  * Return: QDF_STATUS_E_FAILURE if any errors encountered,
  *	   QDF_STATUS_SUCCESS otherwise
  */
 QDF_STATUS hdd_softap_init_tx_rx_sta(struct hdd_adapter *adapter,
-				     uint8_t sta_id,
 				     struct qdf_mac_addr *sta_mac);
 
 /**
- * hdd_softap_deinit_tx_rx_sta() - Deinitialize Tx/Rx for a softap station
- * @adapter: pointer to adapter context
- * @sta_id: Station ID to deinitialize
- *
- * Return: QDF_STATUS_E_FAILURE if any errors encountered,
- *	   QDF_STATUS_SUCCESS otherwise
- */
-QDF_STATUS hdd_softap_deinit_tx_rx_sta(struct hdd_adapter *adapter,
-				       uint8_t sta_id);
-
-/**
  * hdd_softap_rx_packet_cbk() - Receive packet handler
  * @adapter_context: pointer to HDD adapter
  * @rx_buf: pointer to rx qdf_nbuf chain
@@ -125,14 +111,12 @@
 /**
  * hdd_softap_deregister_sta() - Deregister a STA with the Data Path
  * @adapter: pointer to adapter context
- * @sta_id: Station ID to deregister
- * @mac_addr: Peer mac address
+ * @sta_info: pointer to HDD station info structure
  *
  * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error
  */
 QDF_STATUS hdd_softap_deregister_sta(struct hdd_adapter *adapter,
-				     uint8_t sta_id,
-				     struct qdf_mac_addr mac_addr);
+				     struct hdd_station_info *sta_info);
 
 /**
  * hdd_softap_register_sta() - Register a SoftAP STA
@@ -182,20 +166,6 @@
 				       struct qdf_mac_addr *sta_mac,
 				       enum ol_txrx_peer_state state);
 
-/**
- * hdd_softap_get_sta_id() - Find station ID from MAC address
- * @adapter: pointer to adapter context
- * @sta_mac: MAC address of the destination
- * @sta_id: Station ID associated with the MAC address
- *
- * Return: QDF_STATUS_SUCCESS if a match was found, in which case
- *	   @sta_id is populated, QDF_STATUS_E_FAILURE if a match is
- *	   not found
- */
-QDF_STATUS hdd_softap_get_sta_id(struct hdd_adapter *adapter,
-				 struct qdf_mac_addr *sta_mac,
-				 uint8_t *sta_id);
-
 #ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL
 /**
  * hdd_softap_tx_resume_timer_expired_handler() - TX Q resume timer handler
@@ -235,20 +205,39 @@
 /**
  * hdd_post_dhcp_ind() - Send DHCP START/STOP indication to FW
  * @adapter: pointer to hdd adapter
- * @sta_id: peer station ID
+ * @mac_addr: mac address
  * @type: WMA message type
  *
  * Return: error number
  */
 int hdd_post_dhcp_ind(struct hdd_adapter *adapter,
-		      uint8_t sta_id, uint16_t type);
+		      uint8_t *mac_addr, uint16_t type);
 
 /**
- * hdd_softap_inspect_dhcp_packet() -  Inspect DHCP packet
+ * hdd_softap_inspect_dhcp_packet() - Inspect DHCP packet
  * @adapter: pointer to hdd adapter
  * @skb: pointer to OS packet (sk_buff)
  * @dir: direction
  *
+ * Inspect the Tx/Rx frame, and send DHCP START/STOP notification to the FW
+ * through WMI message, during DHCP based IP address acquisition phase.
+ *
+ * - Send DHCP_START notification to FW when SAP gets DHCP Discovery
+ * - Send DHCP_STOP notification to FW when SAP sends DHCP ACK/NAK
+ *
+ * DHCP subtypes are determined by a status octet in the DHCP Message type
+ * option (option code 53 (0x35)).
+ *
+ * Each peer will be in one of 4 DHCP phases, starts from QDF_DHCP_PHASE_ACK,
+ * and transitioned per DHCP message type as it arrives.
+ *
+ * - QDF_DHCP_PHASE_DISCOVER: upon receiving DHCP_DISCOVER message in ACK phase
+ * - QDF_DHCP_PHASE_OFFER: upon receiving DHCP_OFFER message in DISCOVER phase
+ * - QDF_DHCP_PHASE_REQUEST: upon receiving DHCP_REQUEST message in OFFER phase
+ *	or ACK phase (Renewal process)
+ * - QDF_DHCP_PHASE_ACK : upon receiving DHCP_ACK/NAK message in REQUEST phase
+ *	or DHCP_DELINE message in OFFER phase
+ *
  * Return: error number
  */
 int hdd_softap_inspect_dhcp_packet(struct hdd_adapter *adapter,
@@ -257,7 +246,7 @@
 #else
 static inline
 int hdd_post_dhcp_ind(struct hdd_adapter *adapter,
-		      uint8_t sta_id, uint16_t type)
+		      uint8_t *mac_addr, uint16_t type)
 {
 	return 0;
 }
diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c
index 744fcad..fd810be 100644
--- a/core/hdd/src/wlan_hdd_assoc.c
+++ b/core/hdd/src/wlan_hdd_assoc.c
@@ -69,6 +69,7 @@
 #include <wlan_cfg80211_crypto.h>
 #include <wlan_crypto_global_api.h>
 #include "wlan_blm_ucfg_api.h"
+#include "wlan_hdd_sta_info.h"
 
 /* These are needed to recognize WPA and RSN suite types */
 #define HDD_WPA_OUI_SIZE 4
@@ -1935,47 +1936,29 @@
 	complete(&adapter->sta_authorized_event);
 }
 
-/**
- * hdd_change_peer_state() - change peer state
- * @adapter: HDD adapter
- * @sta_state: peer state
- * @roam_synch_in_progress: roam synch in progress
- *
- * Return: QDF status
- */
 QDF_STATUS hdd_change_peer_state(struct hdd_adapter *adapter,
-				 uint8_t sta_id,
+				 uint8_t *peer_mac,
 				 enum ol_txrx_peer_state sta_state,
 				 bool roam_synch_in_progress)
 {
 	QDF_STATUS err;
-	uint8_t *peer_mac_addr;
 	void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
 	void *peer;
+	/* Will be removed as a part of clean up */
+	uint8_t sta_id;
 
 	if (!pdev) {
 		hdd_err("Failed to get txrx context");
 		return QDF_STATUS_E_FAULT;
 	}
 
-	if (sta_id >= WLAN_MAX_STA_COUNT) {
-		hdd_err("Invalid sta id: %d", sta_id);
-		return QDF_STATUS_E_INVAL;
-	}
-
-	peer = cdp_peer_find_by_local_id(soc,
-			(struct cdp_pdev *)pdev, sta_id);
+	peer = cdp_peer_find_by_addr(soc, (struct cdp_pdev *)pdev,
+				     peer_mac, &sta_id);
 	if (!peer)
 		return QDF_STATUS_E_FAULT;
 
-	peer_mac_addr = cdp_peer_get_peer_mac_addr(soc, peer);
-	if (!peer_mac_addr) {
-		hdd_err("peer mac addr is NULL");
-		return QDF_STATUS_E_FAULT;
-	}
-
-	err = cdp_peer_state_update(soc, pdev, peer_mac_addr, sta_state);
+	err = cdp_peer_state_update(soc, pdev, peer_mac, sta_state);
 	if (err != QDF_STATUS_SUCCESS) {
 		hdd_err("peer state update failed");
 		return QDF_STATUS_E_FAULT;
@@ -1994,7 +1977,8 @@
 		INIT_COMPLETION(adapter->sta_authorized_event);
 #endif
 
-		err = sme_set_peer_authorized(peer_mac_addr,
+		err = sme_set_peer_authorized(
+				peer_mac,
 				hdd_set_peer_authorized_event,
 				adapter->vdev_id);
 		if (err != QDF_STATUS_SUCCESS) {
@@ -2062,6 +2046,32 @@
 }
 
 /**
+ * hdd_conn_change_peer_state() - Change the state of the peer
+ * @adapter: pointer to adapter
+ * @roam_info: pointer to roam info
+ * @mac_addr: peer mac address
+ *
+ * Return: QDF_STATUS enumeration
+ */
+#ifdef WLAN_FEATURE_ROAM_OFFLOAD
+static QDF_STATUS hdd_conn_change_peer_state(struct hdd_adapter *adapter,
+					     struct csr_roam_info *roam_info,
+					     uint8_t *mac_addr)
+{
+	return hdd_change_peer_state(adapter, mac_addr, OL_TXRX_PEER_STATE_AUTH,
+				     roam_info->roamSynchInProgress);
+}
+#else
+static QDF_STATUS hdd_conn_change_peer_state(struct hdd_adapter *adapter,
+					     struct csr_roam_info *roam_info,
+					     uint8_t *mac_addr)
+{
+	return hdd_change_peer_state(adapter, mac_addr, OL_TXRX_PEER_STATE_AUTH,
+				     false);
+}
+#endif
+
+/**
  * hdd_roam_register_sta() - register station
  * @adapter: pointer to adapter
  * @roam_info: pointer to roam info
@@ -2153,30 +2163,20 @@
 		 * Connections that do not need Upper layer auth, transition
 		 * TLSHIM directly to 'Authenticated' state
 		 */
-		qdf_status =
-			hdd_change_peer_state(adapter, txrx_desc.sta_id,
-						OL_TXRX_PEER_STATE_AUTH,
-#ifdef WLAN_FEATURE_ROAM_OFFLOAD
-						roam_info->roamSynchInProgress
-#else
-						false
-#endif
-						);
+		qdf_status = hdd_conn_change_peer_state(
+						adapter, roam_info,
+						txrx_desc.peer_addr.bytes);
 
 		hdd_conn_set_authenticated(adapter, true);
 		hdd_objmgr_set_peer_mlme_auth_state(adapter->vdev, true);
 	} else {
 		hdd_debug("ULA auth StaId= %d. Changing TL state to CONNECTED at Join time",
 			 sta_ctx->conn_info.sta_id[0]);
-		qdf_status =
-			hdd_change_peer_state(adapter, txrx_desc.sta_id,
-						OL_TXRX_PEER_STATE_CONN,
-#ifdef WLAN_FEATURE_ROAM_OFFLOAD
-						roam_info->roamSynchInProgress
-#else
-						false
-#endif
-						);
+
+		qdf_status = hdd_conn_change_peer_state(
+						adapter, roam_info,
+						txrx_desc.peer_addr.bytes);
+
 		hdd_conn_set_authenticated(adapter, false);
 		hdd_objmgr_set_peer_mlme_auth_state(adapter->vdev, false);
 	}
@@ -2448,38 +2448,6 @@
 
 #ifdef QCA_IBSS_SUPPORT
 /**
- * hdd_get_ibss_peer_sta_id() - get sta id for IBSS peer
- * @hddstactx: pointer to HDD sta context
- * @roaminfo: pointer to roaminfo structure
- *
- * This function returns sta_id for IBSS peer. If peer is broadcast
- * MAC address return self sta_id(0) else find the peer sta id of
- * the peer.
- *
- * Return: sta_id (HDD_WLAN_INVALID_STA_ID if peer not found).
- */
-static uint8_t hdd_get_ibss_peer_sta_id(struct hdd_station_ctx *hddstactx,
-					struct csr_roam_info *roaminfo)
-{
-	uint8_t sta_id = HDD_WLAN_INVALID_STA_ID;
-	QDF_STATUS status;
-
-	if (qdf_is_macaddr_broadcast(&roaminfo->peerMac)) {
-		sta_id = 0;
-	} else {
-		status = hdd_get_peer_sta_id(hddstactx,
-				&roaminfo->peerMac, &sta_id);
-		if (status != QDF_STATUS_SUCCESS) {
-			hdd_err("Unable to find station ID for "
-				QDF_MAC_ADDR_STR,
-				QDF_MAC_ADDR_ARRAY(roaminfo->peerMac.bytes));
-		}
-	}
-
-	return sta_id;
-}
-
-/**
  * hdd_roam_ibss_indication_handler() - update the status of the IBSS
  * @adapter: pointer to adapter
  * @roam_info: pointer to roam info
@@ -2694,8 +2662,8 @@
 						 struct csr_roam_info *roaminfo)
 {
 	QDF_STATUS status;
+	uint8_t *mac_addr;
 	uint32_t timeout, auto_bmps_timer_val;
-	uint8_t sta_id = HDD_WLAN_INVALID_STA_ID;
 	struct hdd_station_ctx *hddstactx =
 		WLAN_HDD_GET_STATION_CTX_PTR(adapter);
 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
@@ -2707,17 +2675,19 @@
 		(auto_bmps_timer_val * 1000);
 
 	if (QDF_IBSS_MODE == adapter->device_mode)
-		sta_id = hdd_get_ibss_peer_sta_id(hddstactx, roaminfo);
+		mac_addr = roaminfo->peerMac.bytes;
 	else
-		sta_id = hddstactx->conn_info.sta_id[0];
+		mac_addr = hddstactx->conn_info.bssid.bytes;
 
-	hdd_debug("Changing Peer state to AUTHENTICATED for StaId = %d",
-		  sta_id);
+	hdd_debug("Changing Peer state to AUTHENTICATED for Sta = "
+		  QDF_MAC_ADDR_STR, QDF_MAC_ADDR_ARRAY(mac_addr));
 
 	/* Connections that do not need Upper layer authentication,
 	 * transition TL to 'Authenticated' state after the keys are set
 	 */
-	status = hdd_change_peer_state(adapter, sta_id, OL_TXRX_PEER_STATE_AUTH,
+
+	status = hdd_change_peer_state(adapter, mac_addr,
+				       OL_TXRX_PEER_STATE_AUTH,
 				       hdd_is_roam_sync_in_progress(roaminfo));
 	hdd_conn_set_authenticated(adapter, true);
 	hdd_objmgr_set_peer_mlme_auth_state(adapter->vdev, true);
@@ -3443,7 +3413,7 @@
 			if (roam_info->fAuthRequired) {
 				qdf_status =
 					hdd_change_peer_state(adapter,
-						sta_ctx->conn_info.sta_id[0],
+						roam_info->bssid.bytes,
 						OL_TXRX_PEER_STATE_CONN,
 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
 						roam_info->roamSynchInProgress
@@ -3460,7 +3430,7 @@
 					  sta_ctx->conn_info.sta_id[0]);
 				qdf_status =
 					hdd_change_peer_state(adapter,
-						sta_ctx->conn_info.sta_id[0],
+						roam_info->bssid.bytes,
 						OL_TXRX_PEER_STATE_AUTH,
 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
 						roam_info->roamSynchInProgress
diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c
index 46e382d..85638c2 100644
--- a/core/hdd/src/wlan_hdd_cfg80211.c
+++ b/core/hdd/src/wlan_hdd_cfg80211.c
@@ -142,6 +142,7 @@
 #include "wlan_hdd_hw_capability.h"
 #include "wlan_hdd_oemdata.h"
 #include "os_if_fwol.h"
+#include "wlan_hdd_sta_info.h"
 
 #define g_mode_rates_size (12)
 #define a_mode_rates_size (8)
@@ -9865,9 +9866,9 @@
 	struct net_device *dev = wdev->netdev;
 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
 	struct hdd_station_ctx *hdd_sta_ctx;
+	struct hdd_station_info *sta_info;
 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MAX+1];
 	uint8_t peer_mac[QDF_MAC_ADDR_SIZE];
-	uint32_t sta_id;
 	struct sk_buff *reply_skb;
 	uint32_t rate_flags = 0;
 	uint8_t nss;
@@ -9925,26 +9926,24 @@
 	} else if (adapter->device_mode == QDF_P2P_GO_MODE ||
 		   adapter->device_mode == QDF_SAP_MODE) {
 
-		for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
-			if (adapter->sta_info[sta_id].in_use &&
-			    !qdf_is_macaddr_broadcast(
-				&adapter->sta_info[sta_id].sta_mac) &&
-			    !qdf_mem_cmp(
-				&adapter->sta_info[sta_id].sta_mac.bytes,
-				peer_mac, QDF_MAC_ADDR_SIZE))
-				break;
-		}
-
-		if (WLAN_MAX_STA_COUNT == sta_id) {
-			hdd_err("No active peer with mac="QDF_MAC_ADDR_STR,
-			       QDF_MAC_ADDR_ARRAY(peer_mac));
+		if (QDF_IS_ADDR_BROADCAST(peer_mac)) {
+			hdd_err("Ignore bcast/self sta");
 			return -EINVAL;
 		}
 
-		nss = adapter->sta_info[sta_id].nss;
+		sta_info = hdd_get_sta_info_by_mac(&adapter->sta_info_list,
+						   peer_mac);
+
+		if (!sta_info) {
+			hdd_err("No active peer with mac = " QDF_MAC_ADDR_STR,
+				QDF_MAC_ADDR_ARRAY(peer_mac));
+			return -EINVAL;
+		}
+
+		nss = sta_info->nss;
 		freq = cds_chan_to_freq(
 			(WLAN_HDD_GET_AP_CTX_PTR(adapter))->operating_channel);
-		rate_flags = adapter->sta_info[sta_id].rate_flags;
+		rate_flags = sta_info->rate_flags;
 	} else {
 		hdd_err("Not Associated! with mac "QDF_MAC_ADDR_STR,
 		       QDF_MAC_ADDR_ARRAY(peer_mac));
@@ -20961,6 +20960,110 @@
 }
 
 /**
+ * hdd_softap_deauth_current_sta() - Deauth current sta
+ * @sta_info: pointer to the current station info structure
+ * @adapter: pointer to adapter structure
+ * @hdd_ctx: pointer to hdd context
+ * @hapd_state: pointer to hostapd state structure
+ * @param: pointer to del sta params
+ *
+ * Return: QDF_STATUS on success, corresponding QDF failure status on failure
+ */
+static
+QDF_STATUS hdd_softap_deauth_current_sta(struct hdd_adapter *adapter,
+					 struct hdd_station_info *sta_info,
+					 struct hdd_hostapd_state *hapd_state,
+					 struct csr_del_sta_params *param)
+{
+	qdf_event_t *disassoc_event = &hapd_state->qdf_sta_disassoc_event;
+	struct hdd_context *hdd_ctx;
+	QDF_STATUS qdf_status;
+
+	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+	if (!hdd_ctx) {
+		hdd_err("hdd_ctx is NULL");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
+		return QDF_STATUS_E_INVAL;
+
+	qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
+
+	if (!qdf_is_macaddr_broadcast(&sta_info->sta_mac))
+		sme_send_disassoc_req_frame(hdd_ctx->mac_handle,
+					    adapter->vdev_id,
+					    (uint8_t *)&param->peerMacAddr,
+					    param->reason_code, 0);
+
+	qdf_status = hdd_softap_sta_deauth(adapter, param);
+
+	if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
+		sta_info->is_deauth_in_progress = true;
+		qdf_status = qdf_wait_for_event_completion(
+						disassoc_event,
+						SME_PEER_DISCONNECT_TIMEOUT);
+		if (!QDF_IS_STATUS_SUCCESS(qdf_status))
+			hdd_warn("Deauth time expired");
+	} else {
+		sta_info->is_deauth_in_progress = false;
+		hdd_debug("STA removal failed for ::" QDF_MAC_ADDR_STR,
+			  QDF_MAC_ADDR_ARRAY(sta_info->sta_mac.bytes));
+		return QDF_STATUS_E_NOENT;
+	}
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * hdd_softap_deauth_all_sta() - Deauth all sta in the sta list
+ * @hdd_ctx: pointer to hdd context
+ * @adapter: pointer to adapter structure
+ * @hapd_state: pointer to hostapd state structure
+ * @param: pointer to del sta params
+ *
+ * Return: QDF_STATUS on success, corresponding QDF failure status on failure
+ */
+static
+QDF_STATUS hdd_softap_deauth_all_sta(struct hdd_adapter *adapter,
+				     struct hdd_hostapd_state *hapd_state,
+				     struct csr_del_sta_params *param)
+{
+	uint8_t index = 0;
+	QDF_STATUS status;
+	bool is_sap_bcast_deauth_enabled = false;
+	struct hdd_context *hdd_ctx;
+	struct hdd_station_info *sta_info;
+
+	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+	if (!hdd_ctx) {
+		hdd_err("hdd_ctx is NULL");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	ucfg_mlme_get_sap_bcast_deauth_enabled(hdd_ctx->psoc,
+					       &is_sap_bcast_deauth_enabled);
+
+	hdd_debug("sap_bcast_deauth_enabled %d", is_sap_bcast_deauth_enabled);
+
+	if (is_sap_bcast_deauth_enabled)
+		return QDF_STATUS_E_INVAL;
+
+	hdd_for_each_station(adapter->sta_info_list, sta_info, index) {
+		if (!sta_info->is_deauth_in_progress) {
+			hdd_debug("Delete STA with MAC:" QDF_MAC_ADDR_STR,
+				  QDF_MAC_ADDR_ARRAY(sta_info->sta_mac.bytes));
+			status =
+			    hdd_softap_deauth_current_sta(adapter, sta_info,
+							  hapd_state, param);
+			if (QDF_IS_STATUS_ERROR(status))
+				return status;
+		}
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
  * __wlan_hdd_cfg80211_del_station() - delete station v2
  * @wiphy: Pointer to wiphy
  * @dev: Underlying net device
@@ -20975,11 +21078,10 @@
 {
 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
 	struct hdd_context *hdd_ctx;
-	QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
 	struct hdd_hostapd_state *hapd_state;
-	uint8_t sta_id;
 	uint8_t *mac;
 	mac_handle_t mac_handle;
+	struct hdd_station_info *sta_info;
 
 	hdd_enter();
 
@@ -21004,123 +21106,43 @@
 	mac = (uint8_t *) param->peerMacAddr.bytes;
 	mac_handle = hdd_ctx->mac_handle;
 
-	if ((QDF_SAP_MODE == adapter->device_mode) ||
-	    (QDF_P2P_GO_MODE == adapter->device_mode)) {
+	if (QDF_SAP_MODE != adapter->device_mode &&
+	    QDF_P2P_GO_MODE != adapter->device_mode)
+		goto fn_end;
 
-		hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
-		if (!hapd_state) {
-			hdd_err("Hostapd State is Null");
-			return 0;
-		}
+	hapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
+	if (!hapd_state) {
+		hdd_err("Hostapd State is Null");
+		return 0;
+	}
 
-		if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *) mac)) {
-			uint16_t i;
+	if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *)mac)) {
+		if (!QDF_IS_STATUS_SUCCESS(hdd_softap_deauth_all_sta(adapter,
+								     hapd_state,
+								     param)))
+			goto fn_end;
+	} else {
+		sta_info = hdd_get_sta_info_by_mac(&adapter->sta_info_list,
+						   mac);
 
-			bool is_sap_bcast_deauth_enabled = false;
-
-			ucfg_mlme_is_sap_bcast_deauth_enabled(
-					hdd_ctx->psoc,
-					&is_sap_bcast_deauth_enabled);
-			hdd_debug("is_sap_bcast_deauth_enabled %d",
-				  is_sap_bcast_deauth_enabled);
-
-			if (is_sap_bcast_deauth_enabled)
-				goto fn_end;
-
-			for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
-				if ((adapter->sta_info[i].in_use) &&
-				    (!adapter->sta_info[i].
-				     is_deauth_in_progress)) {
-					qdf_mem_copy(
-						mac,
-						adapter->sta_info[i].
-							sta_mac.bytes,
-						QDF_MAC_ADDR_SIZE);
-
-					hdd_debug("Delete STA with MAC::"
-						  QDF_MAC_ADDR_STR,
-					       QDF_MAC_ADDR_ARRAY(mac));
-
-					if (hdd_ctx->dev_dfs_cac_status ==
-							DFS_CAC_IN_PROGRESS)
-						goto fn_end;
-
-					qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
-					qdf_status =
-						hdd_softap_sta_deauth(adapter,
-							param);
-					if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
-						adapter->sta_info[i].
-						is_deauth_in_progress = true;
-						qdf_status =
-							qdf_wait_for_event_completion(
-							 &hapd_state->
-							 qdf_sta_disassoc_event,
-							 SME_PEER_DISCONNECT_TIMEOUT);
-						if (!QDF_IS_STATUS_SUCCESS(
-								qdf_status))
-							hdd_warn("Deauth wait time expired");
-					}
-				}
-			}
-		} else {
-			qdf_status =
-				hdd_softap_get_sta_id(adapter,
-					      (struct qdf_mac_addr *) mac,
-					      &sta_id);
-			if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
-				hdd_debug("Skip DEL STA as this is not used::"
-					  QDF_MAC_ADDR_STR,
-				       QDF_MAC_ADDR_ARRAY(mac));
-				return -ENOENT;
-			}
-
-			if (adapter->sta_info[sta_id].is_deauth_in_progress ==
-			    true) {
-				hdd_debug("Skip DEL STA as deauth is in progress::"
-					  QDF_MAC_ADDR_STR,
-					  QDF_MAC_ADDR_ARRAY(mac));
-				return -ENOENT;
-			}
-
-			adapter->sta_info[sta_id].is_deauth_in_progress = true;
-
-			hdd_debug("ucast, Delete STA with MAC:" QDF_MAC_ADDR_STR,
+		if (!sta_info) {
+			hdd_debug("Skip DEL STA as this is not used::"
+				  QDF_MAC_ADDR_STR,
 				  QDF_MAC_ADDR_ARRAY(mac));
-
-			/* Case: SAP in ACS selected DFS ch and client connected
-			 * Now Radar detected. Then if random channel is another
-			 * DFS ch then new CAC is initiated and no TX allowed.
-			 * So do not send any mgmt frames as it will timeout
-			 * during CAC.
-			 */
-
-			if (hdd_ctx->dev_dfs_cac_status == DFS_CAC_IN_PROGRESS)
-				goto fn_end;
-
-			qdf_event_reset(&hapd_state->qdf_sta_disassoc_event);
-			sme_send_disassoc_req_frame(mac_handle,
-					adapter->vdev_id,
-					(uint8_t *)&param->peerMacAddr,
-					param->reason_code, 0);
-			qdf_status = hdd_softap_sta_deauth(adapter,
-							   param);
-			if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
-				adapter->sta_info[sta_id].is_deauth_in_progress =
-					false;
-				hdd_debug("STA removal failed for ::"
-					  QDF_MAC_ADDR_STR,
-				       QDF_MAC_ADDR_ARRAY(mac));
-				return -ENOENT;
-			}
-			qdf_status = qdf_wait_for_event_completion(
-					&hapd_state->
-					qdf_sta_disassoc_event,
-					SME_PEER_DISCONNECT_TIMEOUT);
-			if (!QDF_IS_STATUS_SUCCESS(qdf_status))
-				hdd_warn("Deauth wait time expired");
-
+			return -ENOENT;
 		}
+
+		if (sta_info->is_deauth_in_progress) {
+			hdd_debug("Skip DEL STA as deauth is in progress::"
+				  QDF_MAC_ADDR_STR,
+				  QDF_MAC_ADDR_ARRAY(mac));
+			return -ENOENT;
+		}
+
+		hdd_debug("ucast, Delete STA with MAC:" QDF_MAC_ADDR_STR,
+			  QDF_MAC_ADDR_ARRAY(mac));
+		hdd_softap_deauth_current_sta(adapter, sta_info, hapd_state,
+					      param);
 	}
 
 fn_end:
diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c
index f8e9f93..b39d622 100644
--- a/core/hdd/src/wlan_hdd_hostapd.c
+++ b/core/hdd/src/wlan_hdd_hostapd.c
@@ -91,6 +91,7 @@
 #include "wlan_fwol_ucfg_api.h"
 #include "nan_ucfg_api.h"
 #include <wlan_reg_services_api.h>
+#include "wlan_hdd_sta_info.h"
 
 #define ACS_SCAN_EXPIRY_TIMEOUT_S 4
 
@@ -740,19 +741,15 @@
 	return errno;
 }
 
-static void hdd_clear_sta(struct hdd_adapter *adapter, uint8_t sta_id)
+static void hdd_clear_sta(struct hdd_adapter *adapter,
+			  struct hdd_station_info *sta_info)
 {
 	struct hdd_ap_ctx *ap_ctx;
-	struct hdd_station_info *sta_info;
 	struct csr_del_sta_params del_sta_params;
 
 	ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
 
-	if (sta_id == ap_ctx->broadcast_sta_id)
-		return;
-
-	sta_info = &adapter->sta_info[sta_id];
-	if (!sta_info->in_use)
+	if (qdf_is_macaddr_broadcast(&sta_info->sta_mac))
 		return;
 
 	wlansap_populate_del_sta_params(sta_info->sta_mac.bytes,
@@ -765,11 +762,14 @@
 
 static void hdd_clear_all_sta(struct hdd_adapter *adapter)
 {
-	uint8_t sta_id;
+	uint8_t index = 0;
+	struct hdd_station_info *sta_info;
 
 	hdd_enter_dev(adapter->dev);
-	for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++)
-		hdd_clear_sta(adapter, sta_id);
+
+	hdd_for_each_station(adapter->sta_info_list, sta_info, index) {
+		hdd_clear_sta(adapter, sta_info);
+	}
 }
 
 static int hdd_stop_bss_link(struct hdd_adapter *adapter)
@@ -1452,7 +1452,8 @@
 		return;
 	}
 
-	stainfo = &adapter->sta_info[event->staId];
+	stainfo = hdd_get_sta_info_by_mac(&adapter->sta_info_list,
+					  event->staMac.bytes);
 
 	if (!stainfo) {
 		hdd_err("invalid stainfo");
@@ -1748,6 +1749,7 @@
 	bool legacy_phymode;
 	tSap_StationDisassocCompleteEvent *disassoc_comp;
 	struct hdd_station_info *stainfo, *cache_stainfo;
+	uint8_t index = 0;
 	mac_handle_t mac_handle;
 	struct sap_config *sap_config;
 
@@ -2228,7 +2230,14 @@
 		if (QDF_IS_STATUS_SUCCESS(qdf_status))
 			hdd_fill_station_info(adapter, event);
 
-		adapter->sta_info[sta_id].ecsa_capable = event->ecsa_capable;
+		stainfo = hdd_get_sta_info_by_mac(
+					&adapter->sta_info_list,
+					(uint8_t *)&wrqu.addr.sa_data);
+
+		if (stainfo)
+			stainfo->ecsa_capable = event->ecsa_capable;
+		else
+			hdd_err("Station not found");
 
 		if (ucfg_ipa_is_enabled()) {
 			status = ucfg_ipa_wlan_evt(hdd_ctx->pdev,
@@ -2339,48 +2348,40 @@
 		else
 			hdd_debug(" MAC initiated disassociation");
 		we_event = IWEVEXPIRED;
-		qdf_status =
-			hdd_softap_get_sta_id(adapter,
-					      &sap_event->sapevt.
-					      sapStationDisassocCompleteEvent.staMac,
-					      &sta_id);
-		if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
-			hdd_err("Failed to find sta id status: %d", qdf_status);
-			return QDF_STATUS_E_FAILURE;
-		}
 
 		DPTRACE(qdf_dp_trace_mgmt_pkt(QDF_DP_TRACE_MGMT_PACKET_RECORD,
 			adapter->vdev_id,
 			QDF_TRACE_DEFAULT_PDEV_ID,
 			QDF_PROTO_TYPE_MGMT, QDF_PROTO_MGMT_DISASSOC));
 
-		stainfo = hdd_get_stainfo(adapter->sta_info,
-					  disassoc_comp->staMac);
-		if (stainfo) {
-			/* Send DHCP STOP indication to FW */
-			stainfo->dhcp_phase = DHCP_PHASE_ACK;
-			if (stainfo->dhcp_nego_status ==
-						DHCP_NEGO_IN_PROGRESS)
-				hdd_post_dhcp_ind(adapter, sta_id,
-						  WMA_DHCP_STOP_IND);
-			stainfo->dhcp_nego_status = DHCP_NEGO_STOP;
+		stainfo = hdd_get_sta_info_by_mac(&adapter->sta_info_list,
+						  disassoc_comp->staMac.bytes);
+		if (!stainfo) {
+			hdd_err("Failed to find the right station");
+			return QDF_STATUS_E_INVAL;
 		}
-		/* STA id will be removed as a part of Phase 2 cleanup */
-		hdd_softap_deregister_sta(adapter, sta_id,
-					  disassoc_comp->staMac);
+
+		/* Send DHCP STOP indication to FW */
+		stainfo->dhcp_phase = DHCP_PHASE_ACK;
+		if (stainfo->dhcp_nego_status ==
+					DHCP_NEGO_IN_PROGRESS)
+			hdd_post_dhcp_ind(adapter,
+					  disassoc_comp->staMac.bytes,
+					  WMA_DHCP_STOP_IND);
+		stainfo->dhcp_nego_status = DHCP_NEGO_STOP;
+
+		hdd_softap_deregister_sta(adapter, stainfo);
 
 		ap_ctx->ap_active = false;
-		spin_lock_bh(&adapter->sta_info_lock);
-		for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
-			if (adapter->sta_info[i].in_use
-			    && i !=
-			    (WLAN_HDD_GET_AP_CTX_PTR(adapter))->
-			    broadcast_sta_id) {
+
+		hdd_for_each_station(adapter->sta_info_list, stainfo,
+				     index) {
+			if (!qdf_is_macaddr_broadcast(
+			    &stainfo->sta_mac)) {
 				ap_ctx->ap_active = true;
 				break;
 			}
 		}
-		spin_unlock_bh(&adapter->sta_info_lock);
 
 #ifdef FEATURE_WLAN_AUTO_SHUTDOWN
 		wlan_hdd_auto_shutdown_enable(hdd_ctx, true);
@@ -3353,10 +3354,12 @@
 	hdd_register_hostapd_wext(adapter->dev);
 
 	/* Initialize the data path module */
-	status = hdd_softap_init_tx_rx(adapter);
-	if (!QDF_IS_STATUS_SUCCESS(status)) {
-		hdd_err("hdd_softap_init_tx_rx failed");
-		goto error_release_sap_session;
+	hdd_softap_init_tx_rx(adapter);
+
+	status = hdd_sta_info_init(&adapter->sta_info_list);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		hdd_err("sta info init failed");
+		goto error_release_softap_tx_rx;
 	}
 
 	status = hdd_wmm_adapter_init(adapter);
@@ -3394,12 +3397,13 @@
 
 	/* rcpi info initialization */
 	qdf_mem_zero(&adapter->rcpi, sizeof(adapter->rcpi));
-
 	hdd_exit();
 
 	return status;
 
 error_release_wmm:
+	hdd_sta_info_deinit(&adapter->sta_info_list);
+error_release_softap_tx_rx:
 	hdd_softap_deinit_tx_rx(adapter);
 error_release_sap_session:
 	hdd_unregister_wext(adapter->dev);
@@ -6590,8 +6594,9 @@
 void hdd_sap_indicate_disconnect_for_sta(struct hdd_adapter *adapter)
 {
 	struct sap_event sap_event;
-	int sta_id;
+	uint8_t index = 0;
 	struct sap_context *sap_ctx;
+	struct hdd_station_info *sta_info;
 
 	hdd_enter();
 
@@ -6601,31 +6606,24 @@
 		return;
 	}
 
-	for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
-		if (adapter->sta_info[sta_id].in_use) {
-			hdd_debug("sta_id: %d in_use: %d %pK",
-				 sta_id, adapter->sta_info[sta_id].in_use,
-				 adapter);
+	hdd_for_each_station(adapter->sta_info_list, sta_info, index) {
+		hdd_debug("sta_mac: " QDF_MAC_ADDR_STR,
+			  QDF_MAC_ADDR_ARRAY(sta_info->sta_mac.bytes));
 
-			if (qdf_is_macaddr_broadcast(
-				&adapter->sta_info[sta_id].sta_mac))
-				continue;
+		if (qdf_is_macaddr_broadcast(&sta_info->sta_mac))
+			continue;
 
-			sap_event.sapHddEventCode = eSAP_STA_DISASSOC_EVENT;
-			qdf_mem_copy(
-				&sap_event.sapevt.
-				sapStationDisassocCompleteEvent.staMac,
-				&adapter->sta_info[sta_id].sta_mac,
-				sizeof(struct qdf_mac_addr));
-			sap_event.sapevt.sapStationDisassocCompleteEvent.
-			reason =
+		sap_event.sapHddEventCode = eSAP_STA_DISASSOC_EVENT;
+
+		qdf_mem_copy(
+		     &sap_event.sapevt.sapStationDisassocCompleteEvent.staMac,
+		     &sta_info->sta_mac, sizeof(struct qdf_mac_addr));
+
+		sap_event.sapevt.sapStationDisassocCompleteEvent.reason =
 				eSAP_MAC_INITATED_DISASSOC;
-			sap_event.sapevt.sapStationDisassocCompleteEvent.
-			status_code =
+		sap_event.sapevt.sapStationDisassocCompleteEvent.status_code =
 				QDF_STATUS_E_RESOURCES;
-			hdd_hostapd_sap_event_cb(&sap_event,
-					sap_ctx->user_context);
-		}
+		hdd_hostapd_sap_event_cb(&sap_event, sap_ctx->user_context);
 	}
 
 	hdd_exit();
@@ -6634,7 +6632,8 @@
 bool hdd_is_peer_associated(struct hdd_adapter *adapter,
 			    struct qdf_mac_addr *mac_addr)
 {
-	uint32_t cnt;
+	uint8_t index = 0;
+	bool is_associated = false;
 	struct hdd_station_info *sta_info;
 
 	if (!adapter || !mac_addr) {
@@ -6642,17 +6641,13 @@
 		return false;
 	}
 
-	sta_info = adapter->sta_info;
-	spin_lock_bh(&adapter->sta_info_lock);
-	for (cnt = 0; cnt < WLAN_MAX_STA_COUNT; cnt++) {
-		if ((sta_info[cnt].in_use) &&
-		    !qdf_mem_cmp(&(sta_info[cnt].sta_mac), mac_addr,
-		    QDF_MAC_ADDR_SIZE))
+	hdd_for_each_station(adapter->sta_info_list, sta_info, index) {
+		if (!qdf_mem_cmp(&sta_info->sta_mac, mac_addr,
+				 QDF_MAC_ADDR_SIZE)) {
+			is_associated = true;
 			break;
+		}
 	}
-	spin_unlock_bh(&adapter->sta_info_lock);
-	if (cnt != WLAN_MAX_STA_COUNT)
-		return true;
 
-	return false;
+	return is_associated;
 }
diff --git a/core/hdd/src/wlan_hdd_hostapd_wext.c b/core/hdd/src/wlan_hdd_hostapd_wext.c
index 42aab67..0f0ead6 100644
--- a/core/hdd/src/wlan_hdd_hostapd_wext.c
+++ b/core/hdd/src/wlan_hdd_hostapd_wext.c
@@ -43,6 +43,7 @@
 #include <wlan_cfg80211_mc_cp_stats.h>
 #include "wlan_mlme_ucfg_api.h"
 #include "wlan_reg_ucfg_api.h"
+#include "wlan_hdd_sta_info.h"
 #define WE_WLAN_VERSION     1
 
 /* WEXT limitation: MAX allowed buf len for any *
@@ -144,7 +145,7 @@
 	struct cdp_pdev *pdev = NULL;
 	void *soc = NULL;
 	struct cdp_txrx_stats_req req = {0};
-	uint8_t count = 0;
+	uint8_t index = 0;
 	struct hdd_station_info *sta_info;
 
 	hdd_enter_dev(dev);
@@ -171,23 +172,21 @@
 		req.mac_id = value[2];
 		hdd_info("QCSAP_PARAM_SET_TXRX_STATS stats_id: %d mac_id: %d",
 			req.stats, req.mac_id);
-		sta_info = adapter->sta_info;
+
 		if (value[1] == CDP_TXRX_STATS_28) {
 			req.peer_addr = (char *)&adapter->mac_addr;
 			ret = cdp_txrx_stats_request(soc, vdev, &req);
 
-			for (count = 0; count < WLAN_MAX_STA_COUNT; count++) {
-				if (sta_info->in_use) {
-					hdd_debug("sta: %d: bss_id: %pM",
-						  sta_info->sta_id,
-						  (void *)&sta_info->sta_mac);
-					req.peer_addr =
-						(char *)&sta_info->sta_mac;
-					ret = cdp_txrx_stats_request(soc, vdev,
-								     &req);
-				}
+			hdd_for_each_station(adapter->sta_info_list, sta_info,
+					     index) {
+				hdd_debug("bss_id: " QDF_MAC_ADDR_STR,
+					  QDF_MAC_ADDR_ARRAY(
+					  sta_info->sta_mac.bytes));
 
-				sta_info++;
+				req.peer_addr = (char *)
+					&sta_info->sta_mac;
+				ret = cdp_txrx_stats_request(
+					soc, vdev, &req);
 			}
 		} else {
 			ret = cdp_txrx_stats_request(soc, vdev, &req);
@@ -339,72 +338,6 @@
 	return QDF_STATUS_SUCCESS;
 }
 
-/**
- * hdd_get_aid_rc() - Get AID and rate code passed from user
- * @aid: pointer to AID
- * @rc: pointer to rate code
- * @set_value: value passed from user
- *
- * If target is 11ax capable, set_value will have AID left shifted 16 bits
- * and 16 bits for rate code. If the target is not 11ax capable, rate code
- * will only be 8 bits.
- *
- * Return: None
- */
-static void hdd_get_aid_rc(uint8_t *aid, uint16_t *rc, int set_value)
-{
-	uint8_t rc_bits;
-
-	if (sme_is_feature_supported_by_fw(DOT11AX))
-		rc_bits = 16;
-	else
-		rc_bits = 8;
-
-	*aid = set_value >> rc_bits;
-	*rc = set_value & ((1 << (rc_bits + 1)) - 1);
-}
-
-/**
- * hdd_set_peer_rate() - set peer rate
- * @adapter: adapter being modified
- * @set_value: rate code with AID
- *
- * Return: 0 on success, negative errno on failure
- */
-static int hdd_set_peer_rate(struct hdd_adapter *adapter, int set_value)
-{
-	uint8_t aid, *peer_mac;
-	uint16_t rc;
-	QDF_STATUS status;
-
-	if (adapter->device_mode != QDF_SAP_MODE) {
-		hdd_err("Invalid devicde mode - %d", adapter->device_mode);
-		return -EINVAL;
-	}
-
-	hdd_get_aid_rc(&aid, &rc, set_value);
-
-	if ((adapter->sta_info[aid].in_use) &&
-	    (OL_TXRX_PEER_STATE_CONN == adapter->sta_info[aid].peer_state)) {
-		peer_mac =
-		    (uint8_t *)&(adapter->sta_info[aid].sta_mac.bytes[0]);
-		hdd_info("Peer AID: %d MAC_ADDR: "QDF_MAC_ADDR_STR,
-			 aid, QDF_MAC_ADDR_ARRAY(peer_mac));
-	} else {
-		hdd_err("No matching peer found for AID: %d", aid);
-		return -EINVAL;
-	}
-
-	status = sme_set_peer_param(peer_mac, WMI_PEER_PARAM_FIXED_RATE,
-				    rc, adapter->vdev_id);
-	if (status != QDF_STATUS_SUCCESS) {
-		hdd_err("Failed to set peer fixed rate - status: %d", status);
-		return -EIO;
-	}
-
-	return 0;
-}
-
 int
 static __iw_softap_setparam(struct net_device *dev,
 			    struct iw_request_info *info,
@@ -1053,9 +986,6 @@
 					&adapter->session.ap.
 					sap_config);
 		break;
-	case QCASAP_SET_PEER_RATE:
-		ret = hdd_set_peer_rate(adapter, set_value);
-		break;
 	case QCASAP_PARAM_DCM:
 		hdd_debug("Set WMI_VDEV_PARAM_HE_DCM: %d", set_value);
 		ret = wma_cli_set_command(adapter->vdev_id,
@@ -1749,10 +1679,10 @@
 				       union iwreq_data *wrqu, char *extra)
 {
 	struct hdd_adapter *adapter = (netdev_priv(dev));
-	struct hdd_station_info *sta_info = adapter->sta_info;
+	struct hdd_station_info *sta_info;
 	struct hdd_context *hdd_ctx;
 	char *buf;
-	int cnt = 0;
+	int index = 0;
 	int left;
 	int ret;
 	/* maclist_index must be u32 to match userspace */
@@ -1799,18 +1729,14 @@
 	maclist_index = sizeof(maclist_index);
 	left = wrqu->data.length - maclist_index;
 
-	spin_lock_bh(&adapter->sta_info_lock);
-	while ((cnt < WLAN_MAX_STA_COUNT) && (left >= QDF_MAC_ADDR_SIZE)) {
-		if ((sta_info[cnt].in_use) &&
-		    (!qdf_is_macaddr_broadcast(&sta_info[cnt].sta_mac))) {
-			memcpy(&buf[maclist_index], &(sta_info[cnt].sta_mac),
+	hdd_for_each_station(adapter->sta_info_list, sta_info, index) {
+		if (!qdf_is_macaddr_broadcast(&sta_info->sta_mac)) {
+			memcpy(&buf[maclist_index], &sta_info->sta_mac,
 			       QDF_MAC_ADDR_SIZE);
 			maclist_index += QDF_MAC_ADDR_SIZE;
 			left -= QDF_MAC_ADDR_SIZE;
 		}
-		cnt++;
 	}
-	spin_unlock_bh(&adapter->sta_info_lock);
 
 	*((u32 *) buf) = maclist_index;
 	wrqu->data.length = maclist_index;
@@ -2295,30 +2221,24 @@
 				   uint8_t *buf,
 				   int size)
 {
-	int i;
+	uint8_t index = 0;
 	int written;
-	uint8_t bc_sta_id;
+	struct hdd_station_info *sta;
 
 	hdd_enter();
 
-	bc_sta_id = WLAN_HDD_GET_AP_CTX_PTR(adapter)->broadcast_sta_id;
-
 	written = scnprintf(buf, size, "\nstaId staAddress\n");
-	for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
-		struct hdd_station_info *sta = &adapter->sta_info[i];
 
+	hdd_for_each_station(adapter->sta_info_list, sta, index) {
 		if (written >= size - 1)
 			break;
 
-		if (!sta->in_use)
-			continue;
-
-		if (i == bc_sta_id)
+		if (QDF_IS_ADDR_BROADCAST(sta->sta_mac.bytes))
 			continue;
 
 		written += scnprintf(buf + written, size - written,
-				     "%5d "QDF_MAC_ADDR_STR" ecsa=%d\n",
-				     sta->sta_id,
+				     QDF_MAC_ADDR_STR
+				     " ecsa=%d\n",
 				     sta->sta_mac.bytes[0],
 				     sta->sta_mac.bytes[1],
 				     sta->sta_mac.bytes[2],
@@ -2527,7 +2447,8 @@
 	struct qdf_mac_addr mac_address;
 	char macaddr_string[MAC_ADDRESS_STR_LEN + 1];
 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
-	int rc, ret, i;
+	int rc, ret;
+	uint8_t index = 0;
 
 	hdd_enter_dev(dev);
 
@@ -2567,14 +2488,12 @@
 	 * link speed for first connected client will be returned.
 	 */
 	if (wrqu->data.length < 17 || !QDF_IS_STATUS_SUCCESS(status)) {
-		for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
-			if (adapter->sta_info[i].in_use &&
-			    (!qdf_is_macaddr_broadcast
-				  (&adapter->sta_info[i].sta_mac))) {
-				qdf_copy_macaddr(
-					&mac_address,
-					&adapter->sta_info[i].
-					 sta_mac);
+		struct hdd_station_info *sta_info;
+
+		hdd_for_each_station(adapter->sta_info_list, sta_info, index) {
+			if (!qdf_is_macaddr_broadcast(&sta_info->sta_mac)) {
+				qdf_copy_macaddr(&mac_address,
+						 &sta_info->sta_mac);
 				status = QDF_STATUS_SUCCESS;
 				break;
 			}
@@ -3248,12 +3167,6 @@
 	}
 	,
 	{
-		QCASAP_SET_PEER_RATE,
-		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
-		0, "set_peer_rate"
-	}
-	,
-	{
 		QCASAP_PARAM_DCM,
 		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
 		0, "enable_dcm"
diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c
index fba90be..e01d0ab 100644
--- a/core/hdd/src/wlan_hdd_main.c
+++ b/core/hdd/src/wlan_hdd_main.c
@@ -173,6 +173,7 @@
 #include "wlan_blm_ucfg_api.h"
 #include "ol_txrx.h"
 #include "nan_ucfg_api.h"
+#include "wlan_hdd_sta_info.h"
 
 #ifdef MODULE
 #define WLAN_MODULE_NAME  module_name(THIS_MODULE)
@@ -4854,6 +4855,10 @@
 	hdd_apf_context_destroy(adapter);
 	qdf_spinlock_destroy(&adapter->vdev_lock);
 
+	if (adapter->device_mode == QDF_SAP_MODE ||
+	    adapter->device_mode == QDF_P2P_GO_MODE)
+		hdd_sta_info_deinit(&adapter->sta_info_list);
+
 	wlan_hdd_debugfs_csr_deinit(adapter);
 	if (adapter->device_mode == QDF_STA_MODE)
 		hdd_sysfs_destroy_adapter_root_obj(adapter);
@@ -6182,9 +6187,10 @@
 	struct hdd_adapter *adapter;
 	struct hdd_station_ctx *sta_ctx;
 	struct qdf_mac_addr peer_macaddr;
-	int sta_id;
 	bool value;
 	struct wlan_objmgr_vdev *vdev;
+	uint8_t index = 0;
+	struct hdd_station_info *sta_info;
 
 	hdd_enter();
 
@@ -6287,19 +6293,17 @@
 
 		} else if (adapter->device_mode == QDF_P2P_GO_MODE) {
 			clear_bit(SOFTAP_BSS_STARTED, &adapter->event_flags);
-			for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT;
-			     sta_id++) {
-				struct hdd_station_info sta =
-					adapter->sta_info[sta_id];
-				if (sta.in_use) {
-					hdd_debug("[SSR] deregister STA with ID %d",
-						  sta_id);
-					/* STA id will be removed */
-					hdd_softap_deregister_sta(adapter,
-								  sta_id,
-								  sta.sta_mac);
-					sta.in_use = 0;
-				}
+
+			hdd_for_each_station(adapter->sta_info_list, sta_info,
+					     index) {
+				hdd_debug(
+				    "[SSR] deregister STA MAC:"
+				    QDF_MAC_ADDR_STR,
+				    QDF_MAC_ADDR_ARRAY(
+				    sta_info->sta_mac.bytes));
+				hdd_softap_deregister_sta(
+						adapter,
+						sta_info);
 			}
 		}
 
@@ -6316,6 +6320,10 @@
 		hdd_stop_tsf_sync(adapter);
 
 		hdd_softap_deinit_tx_rx(adapter);
+		if (adapter->device_mode == QDF_SAP_MODE ||
+		    adapter->device_mode == QDF_P2P_GO_MODE)
+			hdd_sta_info_deinit(&adapter->sta_info_list);
+
 		hdd_deregister_hl_netdev_fc_timer(adapter);
 		hdd_deregister_tx_flow_control(adapter);
 
@@ -15433,10 +15441,11 @@
 {
 	struct hdd_station_ctx *hdd_sta_ctx = NULL;
 	struct hdd_adapter *adapter = NULL;
-	uint8_t sta_id = 0;
+	uint8_t index = 0;
 	uint8_t *sta_mac = NULL;
 	struct hdd_context *hdd_ctx;
 	mac_handle_t mac_handle;
+	struct hdd_station_info *sta_info = NULL;
 
 	hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
 	if (!hdd_ctx) {
@@ -15483,6 +15492,7 @@
 			}
 			return true;
 		}
+
 		if ((QDF_STA_MODE == adapter->device_mode) ||
 			(QDF_P2P_CLIENT_MODE == adapter->device_mode) ||
 			(QDF_P2P_DEVICE_MODE == adapter->device_mode)) {
@@ -15505,23 +15515,22 @@
 			}
 		} else if ((QDF_SAP_MODE == adapter->device_mode) ||
 				(QDF_P2P_GO_MODE == adapter->device_mode)) {
-			for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT;
-				sta_id++) {
-				if (!((adapter->sta_info[sta_id].in_use)
-				    && (OL_TXRX_PEER_STATE_CONN ==
-				    adapter->sta_info[sta_id].peer_state)))
+			hdd_for_each_station(adapter->sta_info_list, sta_info,
+					     index) {
+				if (sta_info->peer_state !=
+					OL_TXRX_PEER_STATE_CONN)
 					continue;
 
-				sta_mac = (uint8_t *)
-						&(adapter->sta_info[sta_id].
-							sta_mac.bytes[0]);
+				sta_mac = sta_info->sta_mac.bytes;
 				hdd_debug("client " QDF_MAC_ADDR_STR
-				" of SAP/GO is in middle of WPS/EAPOL exchange",
-				QDF_MAC_ADDR_ARRAY(sta_mac));
+					  " of SAP/GO is in middle of WPS/EAPOL exchange",
+					  QDF_MAC_ADDR_ARRAY(sta_mac));
 				if (out_vdev_id && out_reason) {
 					*out_vdev_id = adapter->vdev_id;
-					*out_reason = SAP_EAPOL_IN_PROGRESS;
+					*out_reason =
+						SAP_EAPOL_IN_PROGRESS;
 				}
+
 				return true;
 			}
 			if (hdd_ctx->connection_in_progress) {
diff --git a/core/hdd/src/wlan_hdd_softap_tx_rx.c b/core/hdd/src/wlan_hdd_softap_tx_rx.c
index f4d018d..fa41309 100644
--- a/core/hdd/src/wlan_hdd_softap_tx_rx.c
+++ b/core/hdd/src/wlan_hdd_softap_tx_rx.c
@@ -44,7 +44,7 @@
 #include "wlan_ipa_ucfg_api.h"
 #include "wlan_policy_mgr_ucfg.h"
 #include <wma_types.h>
-#include <sap_internal.h>
+#include "wlan_hdd_sta_info.h"
 
 /* Preprocessor definitions and constants */
 #undef QCA_HDD_SAP_DUMP_SK_BUFF
@@ -246,13 +246,14 @@
  *
  * Return: error number
  */
-int hdd_post_dhcp_ind(struct hdd_adapter *adapter,
-			     uint8_t sta_id, uint16_t type)
+int hdd_post_dhcp_ind(struct hdd_adapter *adapter, uint8_t *mac_addr,
+		      uint16_t type)
 {
 	tAniDHCPInd pmsg;
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
 
-	hdd_debug("Post DHCP indication,sta_id=%d,  type=%d", sta_id, type);
+	hdd_debug("Post DHCP indication,sta_mac=" QDF_MAC_ADDR_STR
+		  " ,  type=%d", QDF_MAC_ADDR_ARRAY(mac_addr), type);
 
 	if (!adapter) {
 		hdd_err("NULL adapter");
@@ -266,7 +267,7 @@
 		     adapter->mac_addr.bytes,
 		     QDF_MAC_ADDR_SIZE);
 	qdf_mem_copy(pmsg.peerMacAddr.bytes,
-		     adapter->sta_info[sta_id].sta_mac.bytes,
+		     mac_addr,
 		     QDF_MAC_ADDR_SIZE);
 
 	status = wma_process_dhcp_ind(cds_get_context(QDF_MODULE_ID_WMA),
@@ -292,8 +293,7 @@
 static void hdd_softap_notify_dhcp_ind(void *context, struct sk_buff *netbuf)
 {
 	struct hdd_ap_ctx *hdd_ap_ctx;
-	struct qdf_mac_addr *dest_mac_addr;
-	uint8_t sta_id;
+	uint8_t *dest_mac_addr;
 	struct hdd_adapter *adapter = context;
 
 	if (hdd_validate_adapter(adapter))
@@ -305,59 +305,20 @@
 		return;
 	}
 
-	dest_mac_addr = (struct qdf_mac_addr *)(netbuf->data +
-						DHCP_CLIENT_MAC_ADDR_OFFSET);
+	dest_mac_addr = netbuf->data + DHCP_CLIENT_MAC_ADDR_OFFSET;
 
-	if (QDF_STATUS_SUCCESS !=
-		    hdd_softap_get_sta_id(adapter,
-					  dest_mac_addr, &sta_id)) {
-		QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA,
-			  QDF_TRACE_LEVEL_INFO_HIGH,
-			  "%s: Failed to find right station", __func__);
-		return;
-	}
-
-	hdd_post_dhcp_ind(adapter, sta_id, WMA_DHCP_STOP_IND);
+	hdd_post_dhcp_ind(adapter, dest_mac_addr, WMA_DHCP_STOP_IND);
 }
 
-/**
- * hdd_softap_inspect_dhcp_packet() - Inspect DHCP packet
- * @adapter: pointer to hdd adapter
- * @skb: pointer to OS packet (sk_buff)
- * @dir: direction
- *
- * Inspect the Tx/Rx frame, and send DHCP START/STOP notification to the FW
- * through WMI message, during DHCP based IP address acquisition phase.
- *
- * - Send DHCP_START notification to FW when SAP gets DHCP Discovery
- * - Send DHCP_STOP notification to FW when SAP sends DHCP ACK/NAK
- *
- * DHCP subtypes are determined by a status octet in the DHCP Message type
- * option (option code 53 (0x35)).
- *
- * Each peer will be in one of 4 DHCP phases, starts from QDF_DHCP_PHASE_ACK,
- * and transitioned per DHCP message type as it arrives.
- *
- * - QDF_DHCP_PHASE_DISCOVER: upon receiving DHCP_DISCOVER message in ACK phase
- * - QDF_DHCP_PHASE_OFFER: upon receiving DHCP_OFFER message in DISCOVER phase
- * - QDF_DHCP_PHASE_REQUEST: upon receiving DHCP_REQUEST message in OFFER phase
- *	or ACK phase (Renewal process)
- * - QDF_DHCP_PHASE_ACK : upon receiving DHCP_ACK/NAK message in REQUEST phase
- *	or DHCP_DELINE message in OFFER phase
- *
- * Return: error number
- */
 int hdd_softap_inspect_dhcp_packet(struct hdd_adapter *adapter,
 				   struct sk_buff *skb,
 				   enum qdf_proto_dir dir)
 {
 	enum qdf_proto_subtype subtype = QDF_PROTO_INVALID;
 	struct hdd_station_info *hdd_sta_info;
-	uint8_t sta_id;
 	int errno = 0;
-	struct qdf_mac_addr *src_mac;
-	QDF_STATUS status;
-
+	struct qdf_mac_addr *src_mac, *macaddr =
+		(struct qdf_mac_addr *)(skb->data + QDF_NBUF_SRC_MAC_OFFSET);
 
 	if (((adapter->device_mode == QDF_SAP_MODE) ||
 	     (adapter->device_mode == QDF_P2P_GO_MODE)) &&
@@ -367,14 +328,15 @@
 
 		src_mac = (struct qdf_mac_addr *)(skb->data +
 						  DHCP_CLIENT_MAC_ADDR_OFFSET);
-		status = hdd_softap_get_sta_id(adapter, src_mac, &sta_id);
-		if (status != QDF_STATUS_SUCCESS) {
-			hdd_err("invalid station id");
-			return -EINVAL;
-		}
 
 		subtype = qdf_nbuf_get_dhcp_subtype(skb);
-		hdd_sta_info = &adapter->sta_info[sta_id];
+		hdd_sta_info = hdd_get_sta_info_by_mac(&adapter->sta_info_list,
+						       macaddr->bytes);
+
+		if (!hdd_sta_info) {
+			hdd_err("Station not found");
+			return -EINVAL;
+		}
 
 		hdd_debug("ENTER: type=%d, phase=%d, nego_status=%d",
 			  subtype,
@@ -386,8 +348,10 @@
 			if (dir != QDF_RX)
 				break;
 			if (hdd_sta_info->dhcp_nego_status == DHCP_NEGO_STOP)
-				errno = hdd_post_dhcp_ind(adapter, sta_id,
-							   WMA_DHCP_START_IND);
+				errno =	hdd_post_dhcp_ind(
+						adapter,
+						hdd_sta_info->sta_mac.bytes,
+						WMA_DHCP_START_IND);
 			hdd_sta_info->dhcp_phase = DHCP_PHASE_DISCOVER;
 			hdd_sta_info->dhcp_nego_status = DHCP_NEGO_IN_PROGRESS;
 			break;
@@ -398,8 +362,10 @@
 			if (dir != QDF_RX)
 				break;
 			if (hdd_sta_info->dhcp_nego_status == DHCP_NEGO_STOP)
-				errno = hdd_post_dhcp_ind(adapter, sta_id,
-							   WMA_DHCP_START_IND);
+				errno = hdd_post_dhcp_ind(
+						adapter,
+						hdd_sta_info->sta_mac.bytes,
+						WMA_DHCP_START_IND);
 			hdd_sta_info->dhcp_nego_status = DHCP_NEGO_IN_PROGRESS;
 		case QDF_PROTO_DHCP_DECLINE:
 			if (dir == QDF_RX)
@@ -453,9 +419,11 @@
 	struct hdd_adapter *adapter = (struct hdd_adapter *) netdev_priv(dev);
 	struct hdd_ap_ctx *ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
 	struct hdd_context *hdd_ctx = adapter->hdd_ctx;
-	struct qdf_mac_addr *dest_mac_addr;
-	uint8_t sta_id;
+	struct qdf_mac_addr *dest_mac_addr, *mac_addr;
+	static struct qdf_mac_addr bcast_mac_addr = QDF_MAC_ADDR_BCAST_INIT;
+
 	uint32_t num_seg;
+	struct hdd_station_info *sta_info;
 
 	++adapter->hdd_stats.tx_rx_stats.tx_called;
 	adapter->hdd_stats.tx_rx_stats.cont_txtimeout_cnt = 0;
@@ -505,53 +473,41 @@
 
 	dest_mac_addr = (struct qdf_mac_addr *)skb->data;
 
-	if (QDF_NBUF_CB_GET_IS_BCAST(skb) ||
-	    QDF_NBUF_CB_GET_IS_MCAST(skb)) {
-		/* The BC/MC station ID is assigned during BSS
-		 * starting phase.  SAP will return the station ID
-		 * used for BC/MC traffic.
-		 */
-		sta_id = ap_ctx->broadcast_sta_id;
-	} else {
-		if (QDF_STATUS_SUCCESS !=
-			 hdd_softap_get_sta_id(adapter,
-				 dest_mac_addr, &sta_id)) {
+	/* In case of mcast, fetch the bcast sta_info. Else use the pkt addr */
+	if (QDF_NBUF_CB_GET_IS_MCAST(skb))
+		mac_addr = &bcast_mac_addr;
+	else
+		mac_addr = dest_mac_addr;
+
+	sta_info = hdd_get_sta_info_by_mac(&adapter->sta_info_list,
+					   mac_addr->bytes);
+
+	if (!QDF_NBUF_CB_GET_IS_BCAST(skb) && !QDF_NBUF_CB_GET_IS_MCAST(skb)) {
+		if (!sta_info) {
 			QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA,
 				  QDF_TRACE_LEVEL_INFO_HIGH,
 				  "%s: Failed to find right station", __func__);
 			goto drop_pkt;
 		}
 
-		if (sta_id >= WLAN_MAX_STA_COUNT) {
+		if (sta_info->is_deauth_in_progress) {
 			QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA,
 				  QDF_TRACE_LEVEL_INFO_HIGH,
-				  "%s: Failed to find right station", __func__);
-			goto drop_pkt;
-		} else if (!adapter->sta_info[sta_id].in_use) {
-			QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA,
-				  QDF_TRACE_LEVEL_INFO_HIGH,
-				  "%s: STA %d is unregistered", __func__,
-				  sta_id);
-			goto drop_pkt;
-		} else if (adapter->sta_info[sta_id].
-							is_deauth_in_progress) {
-			QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA,
-				  QDF_TRACE_LEVEL_INFO_HIGH,
-				  "%s: STA %d deauth in progress", __func__,
-				  sta_id);
+				  "%s: STA " QDF_MAC_ADDR_STR
+				  "deauth in progress", __func__,
+				  QDF_MAC_ADDR_ARRAY(sta_info->sta_mac.bytes));
 			goto drop_pkt;
 		}
 
-		if ((OL_TXRX_PEER_STATE_CONN !=
-		     adapter->sta_info[sta_id].peer_state)
-		    && (OL_TXRX_PEER_STATE_AUTH !=
-			adapter->sta_info[sta_id].peer_state)) {
+		if (sta_info->peer_state != OL_TXRX_PEER_STATE_CONN &&
+		    sta_info->peer_state != OL_TXRX_PEER_STATE_AUTH) {
 			QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA,
 				  QDF_TRACE_LEVEL_INFO_HIGH,
 				  "%s: Station not connected yet", __func__);
 			goto drop_pkt;
-		} else if (OL_TXRX_PEER_STATE_CONN ==
-			   adapter->sta_info[sta_id].peer_state) {
+		}
+
+		if (sta_info->peer_state == OL_TXRX_PEER_STATE_CONN) {
 			if (ntohs(skb->protocol) != HDD_ETHERTYPE_802_1_X) {
 				QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA,
 					  QDF_TRACE_LEVEL_INFO_HIGH,
@@ -600,18 +556,21 @@
 	qdf_net_buf_debug_acquire_skb(skb, __FILE__, __LINE__);
 
 	adapter->stats.tx_bytes += skb->len;
-	adapter->sta_info[sta_id].tx_bytes += skb->len;
 
-	if (qdf_nbuf_is_tso(skb)) {
-		num_seg = qdf_nbuf_get_tso_num_seg(skb);
-		adapter->stats.tx_packets += num_seg;
-		adapter->sta_info[sta_id].tx_packets += num_seg;
-	} else {
-		++adapter->stats.tx_packets;
-		adapter->sta_info[sta_id].tx_packets++;
-		hdd_ctx->no_tx_offload_pkt_cnt++;
+	if (sta_info) {
+		sta_info->tx_bytes += skb->len;
+
+		if (qdf_nbuf_is_tso(skb)) {
+			num_seg = qdf_nbuf_get_tso_num_seg(skb);
+			adapter->stats.tx_packets += num_seg;
+			sta_info->tx_packets += num_seg;
+		} else {
+			++adapter->stats.tx_packets;
+			sta_info->tx_packets++;
+			hdd_ctx->no_tx_offload_pkt_cnt++;
+		}
+		sta_info->last_tx_rx_ts = qdf_system_ticks();
 	}
-	adapter->sta_info[sta_id].last_tx_rx_ts = qdf_system_ticks();
 
 	QDF_NBUF_CB_TX_EXTRA_FRAG_FLAGS_NOTIFY_COMP(skb) = 0;
 
@@ -639,8 +598,9 @@
 	if (adapter->tx_fn(adapter->txrx_vdev,
 		 (qdf_nbuf_t)skb) != NULL) {
 		QDF_TRACE(QDF_MODULE_ID_HDD_SAP_DATA, QDF_TRACE_LEVEL_INFO_HIGH,
-			  "%s: Failed to send packet to txrx for sta_id:%d",
-			  __func__, sta_id);
+			  "%s: Failed to send packet to txrx for sta: "
+			  QDF_MAC_ADDR_STR, __func__,
+			  QDF_MAC_ADDR_ARRAY(dest_mac_addr->bytes));
 		++adapter->hdd_stats.tx_rx_stats.tx_dropped_ac[ac];
 		goto drop_pkt_and_release_skb;
 	}
@@ -756,22 +716,9 @@
 	osif_vdev_sync_op_stop(vdev_sync);
 }
 
-QDF_STATUS hdd_softap_init_tx_rx(struct hdd_adapter *adapter)
+void hdd_softap_init_tx_rx(struct hdd_adapter *adapter)
 {
-	QDF_STATUS status = QDF_STATUS_SUCCESS;
-
-	uint8_t STAId = 0;
-
 	qdf_mem_zero(&adapter->stats, sizeof(struct net_device_stats));
-
-	spin_lock_init(&adapter->sta_info_lock);
-
-	for (STAId = 0; STAId < WLAN_MAX_STA_COUNT; STAId++) {
-		qdf_mem_zero(&adapter->sta_info[STAId],
-			     sizeof(struct hdd_station_info));
-	}
-
-	return status;
 }
 
 QDF_STATUS hdd_softap_deinit_tx_rx(struct hdd_adapter *adapter)
@@ -787,47 +734,34 @@
 }
 
 QDF_STATUS hdd_softap_init_tx_rx_sta(struct hdd_adapter *adapter,
-				     uint8_t sta_id,
 				     struct qdf_mac_addr *sta_mac)
 {
-	spin_lock_bh(&adapter->sta_info_lock);
-	if (adapter->sta_info[sta_id].in_use) {
-		spin_unlock_bh(&adapter->sta_info_lock);
-		hdd_err("Reinit of in use station %d", sta_id);
+	struct hdd_station_info *sta_info;
+	QDF_STATUS status;
+
+	sta_info = hdd_get_sta_info_by_mac(&adapter->sta_info_list,
+					   sta_mac->bytes);
+
+	if (sta_info) {
+		hdd_err("Reinit of in use station " QDF_MAC_ADDR_STR,
+			QDF_MAC_ADDR_ARRAY(sta_mac->bytes));
 		return QDF_STATUS_E_FAILURE;
 	}
 
-	qdf_mem_zero(&adapter->sta_info[sta_id],
-		     sizeof(struct hdd_station_info));
+	sta_info = qdf_mem_malloc(sizeof(struct hdd_station_info));
+	if (!sta_info)
+		return QDF_STATUS_E_NOMEM;
 
-	adapter->sta_info[sta_id].in_use = true;
-	adapter->sta_info[sta_id].is_deauth_in_progress = false;
-	qdf_copy_macaddr(&adapter->sta_info[sta_id].sta_mac, sta_mac);
+	sta_info->is_deauth_in_progress = false;
+	qdf_mem_copy(&sta_info->sta_mac, sta_mac, sizeof(struct qdf_mac_addr));
 
-	spin_unlock_bh(&adapter->sta_info_lock);
-	return QDF_STATUS_SUCCESS;
-}
-
-QDF_STATUS hdd_softap_deinit_tx_rx_sta(struct hdd_adapter *adapter,
-				       uint8_t sta_id)
-{
-	QDF_STATUS status = QDF_STATUS_SUCCESS;
-	struct hdd_hostapd_state *hostapd_state;
-
-	hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter);
-
-	spin_lock_bh(&adapter->sta_info_lock);
-
-	if (false == adapter->sta_info[sta_id].in_use) {
-		spin_unlock_bh(&adapter->sta_info_lock);
-		hdd_err("Deinit station not inited %d", sta_id);
-		return QDF_STATUS_E_FAILURE;
+	status = hdd_sta_info_attach(&adapter->sta_info_list, sta_info);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		hdd_err("Failed to attach station: " QDF_MAC_ADDR_STR,
+			QDF_MAC_ADDR_ARRAY(sta_mac->bytes));
+		qdf_mem_free(sta_info);
 	}
 
-	adapter->sta_info[sta_id].in_use = false;
-	adapter->sta_info[sta_id].is_deauth_in_progress = false;
-
-	spin_unlock_bh(&adapter->sta_info_lock);
 	return status;
 }
 
@@ -889,7 +823,7 @@
 	struct sk_buff *next = NULL;
 	struct hdd_context *hdd_ctx = NULL;
 	struct qdf_mac_addr *src_mac;
-	uint8_t sta_id;
+	struct hdd_station_info *sta_info;
 
 	/* Sanity check on inputs */
 	if (unlikely((!adapter_context) || (!rx_buf))) {
@@ -945,16 +879,14 @@
 		/* Send DHCP Indication to FW */
 		src_mac = (struct qdf_mac_addr *)(skb->data +
 						  QDF_NBUF_SRC_MAC_OFFSET);
-		if (QDF_STATUS_SUCCESS ==
-			hdd_softap_get_sta_id(adapter, src_mac, &sta_id)) {
-			if (sta_id < WLAN_MAX_STA_COUNT) {
-				adapter->sta_info[sta_id].rx_packets++;
-				adapter->sta_info[sta_id].rx_bytes += skb->len;
-				adapter->sta_info[sta_id].last_tx_rx_ts =
-					qdf_system_ticks();
-				hdd_softap_inspect_dhcp_packet(adapter, skb,
-							       QDF_RX);
-			}
+		sta_info = hdd_get_sta_info_by_mac(&adapter->sta_info_list,
+						   (uint8_t *)src_mac);
+
+		if (sta_info) {
+			sta_info->rx_packets++;
+			sta_info->rx_bytes += skb->len;
+			sta_info->last_tx_rx_ts = qdf_system_ticks();
+			hdd_softap_inspect_dhcp_packet(adapter, skb, QDF_RX);
 		}
 
 		hdd_event_eapol_log(skb, QDF_RX);
@@ -1002,11 +934,11 @@
 }
 
 QDF_STATUS hdd_softap_deregister_sta(struct hdd_adapter *adapter,
-				     uint8_t sta_id,
-				     struct qdf_mac_addr mac_addr)
+				     struct hdd_station_info *sta_info)
 {
 	QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
 	struct hdd_context *hdd_ctx;
+	struct qdf_mac_addr *mac_addr;
 
 	if (!adapter) {
 		hdd_err("NULL adapter");
@@ -1018,40 +950,55 @@
 		return QDF_STATUS_E_INVAL;
 	}
 
-	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
-
-	if (sta_id >= WLAN_MAX_STA_COUNT) {
-		hdd_err("Error: Invalid sta_id: %u", sta_id);
+	if (!sta_info) {
+		hdd_err("Invalid station");
 		return QDF_STATUS_E_INVAL;
 	}
 
+	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+
+	if (!hdd_ctx) {
+		hdd_err("HDD context is null");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	/*
+	 * If the address is a broadcast address then the CDP layers expects
+	 * the self mac address of the adapter.
+	 */
+	if (QDF_IS_ADDR_BROADCAST(sta_info->sta_mac.bytes))
+		mac_addr = &adapter->mac_addr;
+	else
+		mac_addr = &sta_info->sta_mac;
+
 	/* Clear station in TL and then update HDD data
 	 * structures. This helps to block RX frames from other
 	 * station to this station.
 	 */
-	qdf_status = cdp_clear_peer(cds_get_context(QDF_MODULE_ID_SOC),
+
+	hdd_debug("Deregistering sta: " QDF_MAC_ADDR_STR,
+		  QDF_MAC_ADDR_ARRAY(sta_info->sta_mac.bytes));
+
+	qdf_status = cdp_clear_peer(
+			cds_get_context(QDF_MODULE_ID_SOC),
 			(struct cdp_pdev *)cds_get_context(QDF_MODULE_ID_TXRX),
-			mac_addr);
+			*mac_addr);
 	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
-		hdd_err("cdp_clear_peer failed for staID %d, Status=%d [0x%08X]",
-			sta_id, qdf_status, qdf_status);
+		hdd_err("cdp_clear_peer failed for sta: " QDF_MAC_ADDR_STR
+			", Status=%d [0x%08X]",
+			QDF_MAC_ADDR_ARRAY(mac_addr->bytes), qdf_status,
+			qdf_status);
 	}
 
-	if (adapter->sta_info[sta_id].in_use) {
-		if (ucfg_ipa_is_enabled()) {
-			if (ucfg_ipa_wlan_evt(hdd_ctx->pdev, adapter->dev,
-					  adapter->device_mode,
-					  adapter->vdev_id,
-					  WLAN_IPA_CLIENT_DISCONNECT,
-					  adapter->sta_info[sta_id].sta_mac.
-					  bytes) != QDF_STATUS_SUCCESS)
-				hdd_err("WLAN_CLIENT_DISCONNECT event failed");
-		}
-		spin_lock_bh(&adapter->sta_info_lock);
-		qdf_mem_zero(&adapter->sta_info[sta_id],
-			     sizeof(struct hdd_station_info));
-		spin_unlock_bh(&adapter->sta_info_lock);
+	if (ucfg_ipa_is_enabled()) {
+		if (ucfg_ipa_wlan_evt(hdd_ctx->pdev, adapter->dev,
+				      adapter->device_mode,
+				      adapter->vdev_id,
+				      WLAN_IPA_CLIENT_DISCONNECT,
+				      mac_addr->bytes) != QDF_STATUS_SUCCESS)
+			hdd_err("WLAN_CLIENT_DISCONNECT event failed");
 	}
+	hdd_sta_info_detach(&adapter->sta_info_list, sta_info);
 
 	ucfg_mlme_update_oce_flags(hdd_ctx->pdev);
 
@@ -1073,42 +1020,43 @@
 	void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
 	struct cdp_vdev *txrx_vdev = NULL;
 	struct hdd_ap_ctx *ap_ctx;
-
-	hdd_info("STA:%u, Auth:%u, Priv:%u, WMM:%u",
-		 sta_id, auth_required, privacy_required, wmm_enabled);
+	struct hdd_station_info *sta_info;
 
 	ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
-	if (!ap_ctx)
-		hdd_err("Invalid AP context");
-
-	if (sta_id >= WLAN_MAX_STA_COUNT) {
-		hdd_err("Error: Invalid sta_id: %u", sta_id);
-		return qdf_status;
-	}
 
 	/*
 	 * Clean up old entry if it is not cleaned up properly
 	 */
-	if (adapter->sta_info[sta_id].in_use) {
-		hdd_info("clean up old entry for STA %d", sta_id);
-		hdd_softap_deregister_sta(adapter, sta_id,
-					  adapter->sta_info[sta_id].sta_mac);
+
+	sta_info = hdd_get_sta_info_by_mac(&adapter->sta_info_list,
+					   sta_mac->bytes);
+	if (sta_info) {
+		hdd_info("clean up old entry for STA MAC " QDF_MAC_ADDR_STR,
+			 QDF_MAC_ADDR_ARRAY(sta_mac->bytes));
+		hdd_softap_deregister_sta(adapter, sta_info);
 	}
 
 	/* Get the Station ID from the one saved during the association. */
 	txrx_desc.sta_id = sta_id;
-
 	/*
 	 * If the address is a broadcast address, then provide the self mac addr
 	 * to the data path. Else provide the mac address of the connected peer.
 	 */
 	if (qdf_is_macaddr_broadcast(sta_mac) && ap_ctx)
-		qdf_copy_macaddr(&txrx_desc.peer_addr,
-				 &ap_ctx->sap_context->bssid);
+		qdf_mem_copy(&txrx_desc.peer_addr, &adapter->mac_addr,
+			     QDF_MAC_ADDR_SIZE);
 	else
-		qdf_copy_macaddr(&txrx_desc.peer_addr, sta_mac);
+		qdf_mem_copy(&txrx_desc.peer_addr, sta_mac,
+			     QDF_MAC_ADDR_SIZE);
 
-	qdf_status = hdd_softap_init_tx_rx_sta(adapter, sta_id, sta_mac);
+	qdf_status = hdd_softap_init_tx_rx_sta(adapter, sta_mac);
+	sta_info = hdd_get_sta_info_by_mac(&adapter->sta_info_list,
+					   sta_mac->bytes);
+
+	if (!sta_info) {
+		hdd_err("STA not found");
+		return QDF_STATUS_E_INVAL;
+	}
 
 	txrx_desc.is_qos_enabled = wmm_enabled;
 
@@ -1156,32 +1104,38 @@
 	 * put TL directly into 'authenticated' state
 	 */
 
-	adapter->sta_info[sta_id].sta_id = sta_id;
-	adapter->sta_info[sta_id].is_qos_enabled = wmm_enabled;
+	sta_info->is_qos_enabled = wmm_enabled;
 
 	if (!auth_required) {
-		hdd_info("open/shared auth StaId= %d.  Changing TL state to AUTHENTICATED at Join time",
-			 adapter->sta_info[sta_id].sta_id);
+		hdd_info("open/shared auth STA MAC= " QDF_MAC_ADDR_STR
+			 ".  Changing TL state to AUTHENTICATED at Join time",
+			 QDF_MAC_ADDR_ARRAY(sta_info->sta_mac.bytes));
 
 		/* Connections that do not need Upper layer auth,
 		 * transition TL directly to 'Authenticated' state.
 		 */
-		qdf_status = hdd_change_peer_state(adapter, txrx_desc.sta_id,
-						OL_TXRX_PEER_STATE_AUTH, false);
+		qdf_status = hdd_change_peer_state(adapter,
+						   txrx_desc.peer_addr.bytes,
+						   OL_TXRX_PEER_STATE_AUTH,
+						   false);
 
-		adapter->sta_info[sta_id].peer_state = OL_TXRX_PEER_STATE_AUTH;
+		sta_info->peer_state = OL_TXRX_PEER_STATE_AUTH;
 		if (!qdf_is_macaddr_broadcast(sta_mac))
 			qdf_status = wlan_hdd_send_sta_authorized_event(
 							adapter, hdd_ctx,
 							sta_mac);
 	} else {
 
-		hdd_info("ULA auth StaId= %d.  Changing TL state to CONNECTED at Join time",
-			 adapter->sta_info[sta_id].sta_id);
+		hdd_info("ULA auth STA MAC = " QDF_MAC_ADDR_STR
+			 ".  Changing TL state to CONNECTED at Join time",
+			 QDF_MAC_ADDR_ARRAY(sta_info->sta_mac.bytes));
 
-		qdf_status = hdd_change_peer_state(adapter, txrx_desc.sta_id,
-						OL_TXRX_PEER_STATE_CONN, false);
-		adapter->sta_info[sta_id].peer_state = OL_TXRX_PEER_STATE_CONN;
+		qdf_status = hdd_change_peer_state(adapter,
+						   txrx_desc.peer_addr.bytes,
+						   OL_TXRX_PEER_STATE_CONN,
+						   false);
+
+		sta_info->peer_state = OL_TXRX_PEER_STATE_CONN;
 	}
 
 	hdd_debug("Enabling queues");
@@ -1221,28 +1175,15 @@
 	return qdf_status;
 }
 
-/**
- * hdd_softap_deregister_bc_sta() - Deregister the SoftAP broadcast STA
- * @adapter: pointer to adapter context
- *
- * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error
- */
-static QDF_STATUS hdd_softap_deregister_bc_sta(struct hdd_adapter *adapter)
-{
-	struct hdd_ap_ctx *ap_ctx;
-
-	ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
-
-	return hdd_softap_deregister_sta(adapter, ap_ctx->broadcast_sta_id,
-					 adapter->mac_addr);
-}
-
 QDF_STATUS hdd_softap_stop_bss(struct hdd_adapter *adapter)
 {
 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
-	uint8_t sta_id = 0, indoor_chnl_marking = 0;
+	uint8_t indoor_chnl_marking = 0;
 	struct hdd_context *hdd_ctx;
 	struct hdd_ap_ctx *ap_ctx;
+	uint16_t index;
+	struct hdd_station_info *sta_info;
+	struct hdd_sta_info_entry *tmp;
 
 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
 	ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
@@ -1255,24 +1196,17 @@
 	 * driver unload in progress check otherwise it can lead to peer
 	 * object leak
 	 */
-	status = hdd_softap_deregister_bc_sta(adapter);
 
-	if (!QDF_IS_STATUS_SUCCESS(status))
-		hdd_err("Failed to deregister BC sta Id %d",
-			ap_ctx->broadcast_sta_id);
+	hdd_for_each_station_safe(adapter->sta_info_list, sta_info,
+				  index, tmp) {
+		status = hdd_softap_deregister_sta(adapter,
+						   sta_info);
 
-	for (sta_id = 0; sta_id < WLAN_MAX_STA_COUNT; sta_id++) {
-		/* This excludes BC sta as it is already deregistered */
-		if (adapter->sta_info[sta_id].in_use) {
-			status = hdd_softap_deregister_sta(
-					adapter, sta_id,
-					adapter->sta_info[sta_id].sta_mac);
-			if (!QDF_IS_STATUS_SUCCESS(status)) {
-				hdd_err("Failed to deregister sta Id %d",
-					sta_id);
-			}
-		}
+		if (QDF_IS_STATUS_ERROR(status) && sta_info)
+			hdd_err("Deregistering STA " QDF_MAC_ADDR_STR " failed",
+				QDF_MAC_ADDR_ARRAY(sta_info->sta_mac.bytes));
 	}
+
 	if (adapter->device_mode == QDF_SAP_MODE &&
 	    !hdd_ctx->config->disable_channel)
 		wlan_hdd_restore_channels(hdd_ctx, true);
@@ -1301,31 +1235,34 @@
 				       struct qdf_mac_addr *sta_mac,
 				       enum ol_txrx_peer_state state)
 {
-	uint8_t sta_id = WLAN_MAX_STA_COUNT;
 	QDF_STATUS qdf_status;
+	struct hdd_station_info *sta_info;
+	struct qdf_mac_addr mac_addr;
 
 	hdd_enter_dev(adapter->dev);
 
-	qdf_status = hdd_softap_get_sta_id(adapter, sta_mac, &sta_id);
-	if (QDF_STATUS_SUCCESS != qdf_status) {
-		hdd_err("Failed to find right station");
-		return qdf_status;
+	sta_info = hdd_get_sta_info_by_mac(&adapter->sta_info_list,
+					   sta_mac->bytes);
+
+	if (!sta_info) {
+		hdd_err("Failed to find right station MAC: " QDF_MAC_ADDR_STR,
+			QDF_MAC_ADDR_ARRAY(sta_mac->bytes));
+		return QDF_STATUS_E_INVAL;
 	}
 
-	if (false ==
-	    qdf_is_macaddr_equal(&adapter->sta_info[sta_id].sta_mac,
-				 sta_mac)) {
-		hdd_err("Station %u MAC address not matching", sta_id);
-		return QDF_STATUS_E_FAILURE;
-	}
+	if (qdf_is_macaddr_broadcast(&sta_info->sta_mac))
+		qdf_mem_copy(&mac_addr, &adapter->mac_addr, QDF_MAC_ADDR_SIZE);
+	else
+		qdf_mem_copy(&mac_addr, sta_mac, QDF_MAC_ADDR_SIZE);
 
 	qdf_status =
-		hdd_change_peer_state(adapter, sta_id, state, false);
-	hdd_info("Station %u changed to state %d", sta_id, state);
+		hdd_change_peer_state(adapter, mac_addr.bytes,
+				      state, false);
+	hdd_info("Station " QDF_MAC_ADDR_STR " changed to state %d",
+		 QDF_MAC_ADDR_ARRAY(mac_addr.bytes), state);
 
 	if (QDF_STATUS_SUCCESS == qdf_status) {
-		adapter->sta_info[sta_id].peer_state =
-			OL_TXRX_PEER_STATE_AUTH;
+		sta_info->peer_state = OL_TXRX_PEER_STATE_AUTH;
 		p2p_peer_authorized(adapter->vdev, sta_mac->bytes);
 	}
 
@@ -1333,20 +1270,3 @@
 	return qdf_status;
 }
 
-QDF_STATUS hdd_softap_get_sta_id(struct hdd_adapter *adapter,
-				 struct qdf_mac_addr *sta_mac,
-				 uint8_t *sta_id)
-{
-	uint8_t i;
-
-	for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
-		if (!qdf_mem_cmp
-			(&adapter->sta_info[i].sta_mac, sta_mac,
-			QDF_MAC_ADDR_SIZE) && adapter->sta_info[i].in_use) {
-			*sta_id = i;
-			return QDF_STATUS_SUCCESS;
-		}
-	}
-
-	return QDF_STATUS_E_FAILURE;
-}
diff --git a/core/hdd/src/wlan_hdd_sta_info.c b/core/hdd/src/wlan_hdd_sta_info.c
new file mode 100644
index 0000000..961b05f
--- /dev/null
+++ b/core/hdd/src/wlan_hdd_sta_info.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2019 The Linux Foundation. All rights reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * DOC: wlan_hdd_sta_info.c
+ *
+ * Store and manage station info structure.
+ *
+ */
+
+#include "wlan_hdd_sta_info.h"
+#include <wlan_hdd_includes.h>
+
+/* Generate a numeric constant to form the key to be provided for hashing */
+#define WLAN_HDD_STA_INFO_HASH(addr) \
+	(((const uint8_t *)addr)[QDF_MAC_ADDR_SIZE - 1])
+
+QDF_STATUS hdd_sta_info_init(struct hdd_sta_info_obj *sta_info_container)
+{
+	if (!sta_info_container) {
+		hdd_err("Parameter null");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	qdf_spinlock_create(&sta_info_container->sta_obj_lock);
+	qdf_ht_init(sta_info_container->sta_obj);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+void hdd_sta_info_deinit(struct hdd_sta_info_obj *sta_info_container)
+{
+	if (!sta_info_container) {
+		hdd_err("Parameter null");
+		return;
+	}
+
+	qdf_ht_deinit(sta_info_container->sta_obj);
+	qdf_spinlock_destroy(&sta_info_container->sta_obj_lock);
+}
+
+QDF_STATUS hdd_sta_info_attach(struct hdd_sta_info_obj *sta_info_container,
+			       struct hdd_station_info *sta_info)
+{
+	if (!sta_info_container || !sta_info) {
+		hdd_err("Parameter(s) null");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	qdf_spin_lock_bh(&sta_info_container->sta_obj_lock);
+
+	qdf_ht_add(sta_info_container->sta_obj, &sta_info->sta_node,
+		   WLAN_HDD_STA_INFO_HASH(sta_info->sta_mac.bytes));
+
+	qdf_spin_unlock_bh(&sta_info_container->sta_obj_lock);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+void hdd_sta_info_detach(struct hdd_sta_info_obj *sta_info_container,
+			 struct hdd_station_info *sta_info)
+{
+	if (!sta_info_container || !sta_info) {
+		hdd_err("Parameter(s) null");
+		return;
+	}
+
+	qdf_spin_lock_bh(&sta_info_container->sta_obj_lock);
+
+	qdf_ht_remove(&sta_info->sta_node);
+
+	qdf_spin_unlock_bh(&sta_info_container->sta_obj_lock);
+
+	qdf_mem_free(sta_info);
+	sta_info = NULL;
+}
+
+struct hdd_station_info *hdd_get_sta_info_by_mac(
+				struct hdd_sta_info_obj *sta_info_container,
+				const uint8_t *mac_addr)
+{
+	struct hdd_station_info *sta_info = NULL;
+
+	if (!mac_addr || !sta_info_container) {
+		hdd_err("Parameter(s) null");
+		return NULL;
+	}
+
+	qdf_spin_lock_bh(&sta_info_container->sta_obj_lock);
+
+	qdf_ht_for_each_in_bucket(sta_info_container->sta_obj, sta_info,
+				  sta_node, WLAN_HDD_STA_INFO_HASH(mac_addr)) {
+		if (qdf_is_macaddr_equal(&sta_info->sta_mac,
+					 (struct qdf_mac_addr *)mac_addr)) {
+			qdf_spin_unlock_bh(&sta_info_container->sta_obj_lock);
+			return sta_info;
+		}
+	}
+
+	qdf_spin_unlock_bh(&sta_info_container->sta_obj_lock);
+
+	return NULL;
+}
diff --git a/core/hdd/src/wlan_hdd_sta_info.h b/core/hdd/src/wlan_hdd_sta_info.h
new file mode 100644
index 0000000..9e98adc
--- /dev/null
+++ b/core/hdd/src/wlan_hdd_sta_info.h
@@ -0,0 +1,270 @@
+/*
+ * Copyright (c) 2019 The Linux Foundation. All rights reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ * DOC: wlan_hdd_sta_info.h
+ *
+ * Store and manage station info structure.
+ *
+ */
+#if !defined(__WLAN_HDD_STA_INFO_H)
+#define __WLAN_HDD_STA_INFO_H
+
+#include "qdf_lock.h"
+#include "qdf_types.h"
+#include "qdf_hashtable.h"
+#include "sap_api.h"
+#include "cdp_txrx_cmn_struct.h"
+#include "sir_mac_prot_def.h"
+#include <linux/ieee80211.h>
+
+/* A bucket size of 2^4 = 16 */
+#define WLAN_HDD_STA_INFO_SIZE 4
+
+/* Opaque handle for abstraction */
+#define hdd_sta_info_entry qdf_ht_entry
+
+/**
+ * struct dhcp_phase - Per Peer DHCP Phases
+ * @DHCP_PHASE_ACK: upon receiving DHCP_ACK/NAK message in REQUEST phase or
+ *         DHCP_DELINE message in OFFER phase
+ * @DHCP_PHASE_DISCOVER: upon receiving DHCP_DISCOVER message in ACK phase
+ * @DHCP_PHASE_OFFER: upon receiving DHCP_OFFER message in DISCOVER phase
+ * @DHCP_PHASE_REQUEST: upon receiving DHCP_REQUEST message in OFFER phase or
+ *         ACK phase (Renewal process)
+ */
+enum dhcp_phase {
+	DHCP_PHASE_ACK,
+	DHCP_PHASE_DISCOVER,
+	DHCP_PHASE_OFFER,
+	DHCP_PHASE_REQUEST
+};
+
+/**
+ * struct dhcp_nego_status - Per Peer DHCP Negotiation Status
+ * @DHCP_NEGO_STOP: when the peer is in ACK phase or client disassociated
+ * @DHCP_NEGO_IN_PROGRESS: when the peer is in DISCOVER or REQUEST
+ *         (Renewal process) phase
+ */
+enum dhcp_nego_status {
+	DHCP_NEGO_STOP,
+	DHCP_NEGO_IN_PROGRESS
+};
+
+/**
+ * struct hdd_station_info - Per station structure kept in HDD for
+ *                                     multiple station support for SoftAP
+ * @in_use: Is the station entry in use?
+ * @sta_id: Station ID reported back from HAL (through SAP).
+ *           Broadcast uses station ID zero by default.
+ * @sta_type: Type of station i.e. p2p client or infrastructure station
+ * @sta_mac: MAC address of the station
+ * @peer_state: Current Station state so HDD knows how to deal with packet
+ *              queue. Most recent states used to change TLSHIM STA state.
+ * @is_qos_enabled: Track QoS status of station
+ * @is_deauth_in_progress: The station entry for which Deauth is in progress
+ * @nss: Number of spatial streams supported
+ * @rate_flags: Rate Flags for this connection
+ * @ecsa_capable: Extended CSA capabilities
+ * @max_phy_rate: Calcuated maximum phy rate based on mode, nss, mcs etc.
+ * @tx_packets: Packets send to current station
+ * @tx_bytes: Bytes send to current station
+ * @rx_packets: Packets received from current station
+ * @rx_bytes: Bytes received from current station
+ * @last_tx_rx_ts: Last tx/rx timestamp with current station
+ * @assoc_ts: Current station association timestamp
+ * @tx_rate: Tx rate with current station reported from F/W
+ * @rx_rate: Rx rate with current station reported from F/W
+ * @ampdu: Ampdu enable or not of the station
+ * @sgi_enable: Short GI enable or not of the station
+ * @tx_stbc: Tx Space-time block coding enable/disable
+ * @rx_stbc: Rx Space-time block coding enable/disable
+ * @ch_width: Channel Width of the connection
+ * @mode: Mode of the connection
+ * @max_supp_idx: Max supported rate index of the station
+ * @max_ext_idx: Max extended supported rate index of the station
+ * @max_mcs_idx: Max supported mcs index of the station
+ * @rx_mcs_map: VHT Rx mcs map
+ * @tx_mcs_map: VHT Tx mcs map
+ * @freq : Frequency of the current station
+ * @dot11_mode: 802.11 Mode of the connection
+ * @ht_present: HT caps present or not in the current station
+ * @vht_present: VHT caps present or not in the current station
+ * @ht_caps: HT capabilities of current station
+ * @vht_caps: VHT capabilities of current station
+ * @reason_code: Disconnection reason code for current station
+ * @rssi: RSSI of the current station reported from F/W
+ * @capability: Capability information of current station
+ * @support_mode: Max supported mode of a station currently
+ * connected to sap
+ * @rx_retry_cnt: Number of rx retries received from current station
+ *                Currently this feature is not supported from FW
+ * @rx_mc_bc_cnt: Multicast broadcast packet count received from
+ *                current station
+ * MSB of rx_mc_bc_cnt indicates whether FW supports rx_mc_bc_cnt
+ * feature or not, if first bit is 1 it indicates that FW supports this
+ * feature, if it is 0 it indicates FW doesn't support this feature
+ * @sta_info: The sta_info node for the station info list maintained in adapter
+ */
+struct hdd_station_info {
+	bool in_use;
+	uint8_t sta_id;
+	eStationType sta_type;
+	struct qdf_mac_addr sta_mac;
+	enum ol_txrx_peer_state peer_state;
+	bool is_qos_enabled;
+	bool is_deauth_in_progress;
+	uint8_t   nss;
+	uint32_t  rate_flags;
+	uint8_t   ecsa_capable;
+	uint32_t max_phy_rate;
+	uint32_t tx_packets;
+	uint64_t tx_bytes;
+	uint32_t rx_packets;
+	uint64_t rx_bytes;
+	qdf_time_t last_tx_rx_ts;
+	qdf_time_t assoc_ts;
+	qdf_time_t disassoc_ts;
+	uint32_t tx_rate;
+	uint32_t rx_rate;
+	bool ampdu;
+	bool sgi_enable;
+	bool tx_stbc;
+	bool rx_stbc;
+	tSirMacHTChannelWidth ch_width;
+	uint8_t mode;
+	uint8_t max_supp_idx;
+	uint8_t max_ext_idx;
+	uint8_t max_mcs_idx;
+	uint8_t rx_mcs_map;
+	uint8_t tx_mcs_map;
+	uint32_t freq;
+	uint8_t dot11_mode;
+	bool ht_present;
+	bool vht_present;
+	struct ieee80211_ht_cap ht_caps;
+	struct ieee80211_vht_cap vht_caps;
+	uint32_t reason_code;
+	int8_t rssi;
+	enum dhcp_phase dhcp_phase;
+	enum dhcp_nego_status dhcp_nego_status;
+	uint16_t capability;
+	uint8_t support_mode;
+	uint32_t rx_retry_cnt;
+	uint32_t rx_mc_bc_cnt;
+	struct qdf_ht_entry sta_node;
+};
+
+/**
+ * struct hdd_sta_info_obj - Station info container structure
+ * @sta_obj: The sta info object that stores the sta_info
+ * @sta_obj_lock: Lock to protect the sta_obj read/write access
+ */
+struct hdd_sta_info_obj {
+	qdf_ht_declare(sta_obj, WLAN_HDD_STA_INFO_SIZE);
+	qdf_spinlock_t sta_obj_lock;
+};
+
+/**
+ * hdd_for_each_station - Iterate over each station stored in the sta info
+ *                        container
+ * @sta_info_container: The station info container obj that stores and maintains
+ *                      the sta_info obj.
+ * @sta_info: The station info structure that acts as the iterator object.
+ * @index: The current index in which the current station is present.
+ *
+ * The sta_info will contain the structure that is fetched for that particular
+ * iteration. The index of the current iterator object in the container
+ * represents the bucket at which the given station info is stored.
+ */
+#define hdd_for_each_station(sta_info_container, sta_info, index) \
+	  qdf_ht_for_each(sta_info_container.sta_obj, index, sta_info, sta_node)
+
+/**
+ * hdd_for_each_station_safe - Iterate over each station stored in the sta info
+ *                           container being safe for removal of the sta info
+ * @sta_info_container: The station info container obj that stores and maintains
+ *                      the sta_info obj.
+ * @sta_info: The station info structure that acts as the iterator object.
+ * @index: The current index in which the current station is present.
+ * @tmp: A &struct for temporary storage
+ *
+ * The sta_info will contain the structure that is fetched for that particular
+ * iteration. The index of the current iterator object in the container
+ * represents the bucket at which the given station info is stored.
+ */
+#define hdd_for_each_station_safe(sta_info_container, sta_info, index, tmp) \
+	qdf_ht_for_each_safe(sta_info_container.sta_obj, index, tmp, \
+			     sta_info, sta_node)
+
+/**
+ * wlan_sta_info_init() - Initialise the wlan hdd station info container obj
+ * @sta_info_container: The station info container obj that stores and maintains
+ *                      the sta_info obj.
+ *
+ * Return: QDF_STATUS_SUCCESS on success, failure code otherwise
+ */
+QDF_STATUS hdd_sta_info_init(struct hdd_sta_info_obj *sta_info_container);
+
+/**
+ * wlan_sta_info_deinit() - Deinit the wlan hdd station info container obj
+ * @sta_info_container: The station info container obj that stores and maintains
+ *                      the sta_info obj.
+ *
+ * Return: None
+ */
+void hdd_sta_info_deinit(struct hdd_sta_info_obj *sta_info_container);
+
+/**
+ * hdd_sta_info_detach() - Detach the station info structure from the list
+ * @sta_info_container: The station info container obj that stores and maintains
+ *                      the sta_info obj.
+ * @sta_info: The station info structure that has to be detached from the
+ *            container object.
+ *
+ * Return: None
+ */
+void hdd_sta_info_detach(struct hdd_sta_info_obj *sta_info_container,
+			 struct hdd_station_info *sta_info);
+
+/**
+ * hdd_sta_info_attach() - Attach the station info structure into the list
+ * @sta_info_container: The station info container obj that stores and maintains
+ *                      the sta_info obj.
+ * @sta_info: The station info structure that is to be attached to the
+ *            container object.
+ *
+ * Return: QDF STATUS SUCCESS on successful attach, error code otherwise
+ */
+QDF_STATUS hdd_sta_info_attach(struct hdd_sta_info_obj *sta_info_container,
+			       struct hdd_station_info *sta_info);
+
+/**
+ * hdd_get_sta_info_by_mac() - Find the sta_info structure by mac addr
+ * @sta_info_container: The station info container obj that stores and maintains
+ *                      the sta_info obj.
+ * @mac_addr: The mac addr by which the sta_info has to be fetched.
+ *
+ * Return: Pointer to the hdd_station_info structure which contains the mac
+ *         address passed
+ */
+struct hdd_station_info *hdd_get_sta_info_by_mac(
+				struct hdd_sta_info_obj *sta_info_container,
+				const uint8_t *mac_addr);
+
+#endif /* __WLAN_HDD_STA_INFO_H */
diff --git a/core/hdd/src/wlan_hdd_station_info.c b/core/hdd/src/wlan_hdd_station_info.c
index 601fcd1..48da5ca 100644
--- a/core/hdd/src/wlan_hdd_station_info.c
+++ b/core/hdd/src/wlan_hdd_station_info.c
@@ -34,6 +34,7 @@
 #include <wlan_hdd_hostapd.h>
 #include <wlan_hdd_station_info.h>
 #include "wlan_mlme_ucfg_api.h"
+#include "wlan_hdd_sta_info.h"
 
 /*
  * define short names for the global vendor params
@@ -1225,10 +1226,11 @@
 				  struct hdd_adapter *adapter,
 				  struct qdf_mac_addr mac_addr)
 {
-	struct hdd_station_info *stainfo = hdd_get_stainfo(adapter->sta_info,
-							   mac_addr);
 	int status = 0;
 	bool is_associated = false;
+	struct hdd_station_info *stainfo =
+			hdd_get_sta_info_by_mac(&adapter->sta_info_list,
+						mac_addr.bytes);
 
 	if (!stainfo) {
 		status = hdd_get_cached_station_remote(hdd_ctx, adapter,
diff --git a/core/hdd/src/wlan_hdd_stats.c b/core/hdd/src/wlan_hdd_stats.c
index cf4faa8..66d0c9c 100644
--- a/core/hdd/src/wlan_hdd_stats.c
+++ b/core/hdd/src/wlan_hdd_stats.c
@@ -40,6 +40,7 @@
 #include "wlan_cp_stats_mc_ucfg_api.h"
 #include "wlan_mlme_ucfg_api.h"
 #include "wlan_mlme_ucfg_api.h"
+#include "wlan_hdd_sta_info.h"
 
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) && !defined(WITH_BACKPORTS)
 #define HDD_INFO_SIGNAL                 STATION_INFO_SIGNAL
@@ -3908,7 +3909,6 @@
 	struct sir_peer_info_ext peer_info;
 	struct hdd_fw_txrx_stats txrx_stats;
 	int status;
-	int i;
 
 	status = wlan_hdd_validate_context(hddctx);
 	if (status != 0)
@@ -3916,15 +3916,7 @@
 
 	hdd_debug("get peer %pM info", mac);
 
-	for (i = 0; i < WLAN_MAX_STA_COUNT; i++) {
-		if (!qdf_mem_cmp(adapter->sta_info[i].sta_mac.bytes,
-				 mac,
-				 QDF_MAC_ADDR_SIZE)) {
-			stainfo = &adapter->sta_info[i];
-			break;
-		}
-	}
-
+	stainfo = hdd_get_sta_info_by_mac(&adapter->sta_info_list, mac);
 	if (!stainfo) {
 		hdd_err("peer %pM not found", mac);
 		return -EINVAL;