Merge branch 'android-msm-wahoo-4.4-pi' into android-msm-wahoo-4.4-pi-qpr1

Bug: 112376366
Change-Id: Ia5a0b9f736d8c3cfc82e8dcfe69f2e842d4ffa46
Signed-off-by: Badhri Jagan Sridharan <badhri@google.com>
diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c
index 6675f6f..eaf5e36 100644
--- a/drivers/power/supply/qcom/smb-lib.c
+++ b/drivers/power/supply/qcom/smb-lib.c
@@ -10,6 +10,7 @@
  * GNU General Public License for more details.
  */
 
+#include <linux/module.h>
 #include <linux/device.h>
 #include <linux/ipc_logging.h>
 #include <linux/regmap.h>
@@ -61,6 +62,11 @@
 	} while (0)
 #define NUM_LOG_PAGES 10
 
+static bool enable_ovh = true;
+module_param_named(
+	enable_ovh, enable_ovh, bool, 0600
+);
+
 static bool is_secure(struct smb_charger *chg, int addr)
 {
 	if (addr == SHIP_MODE_REG || addr == FREQ_CLK_DIV_REG)
@@ -3598,7 +3604,7 @@
 						struct smb_charger *chg,
 						u8 stat)
 {
-	if (!chg->port_overheat_mitigation_enabled)
+	if (!chg->port_overheat_mitigation_enabled || !enable_ovh)
 		return;
 
 	cancel_delayed_work_sync(&chg->port_overheat_work);
@@ -4842,7 +4848,7 @@
 		smblib_err(chg, "USB port overheat detected, temp=%d\n", temp);
 
 	if (chg->port_overheat &&
-	    temp < chg->port_overheat_mitigation_end_temp) {
+	    (temp < chg->port_overheat_mitigation_end_temp || !enable_ovh)) {
 		/* check if the cable is still there */
 		mutex_lock(&chg->typec_pr_lock);
 		rc = port_overheat_probe_cc_status_locked(chg, &attached);
@@ -4853,7 +4859,7 @@
 			goto rerun;
 		}
 		/* temperature drops and cable unplugged */
-		if (!attached) {
+		if (!attached || !enable_ovh) {
 			smblib_err(chg, "Port overheat mitigation ends.\n");
 			rc = port_overheat_mitigation_end(chg);
 			if (rc < 0) {
@@ -4865,7 +4871,7 @@
 			}
 			chg->port_overheat = false;
 		}
-	} else if (!chg->port_overheat &&
+	} else if (!chg->port_overheat && enable_ovh &&
 		   temp > chg->port_overheat_mitigation_begin_temp) {
 		smblib_err(chg, "Port overheat mitigation begins.\n");
 		rc = port_overheat_mitigation_begin(chg);
diff --git a/drivers/staging/qcacld-3.0/core/hdd/inc/wlan_hdd_main.h b/drivers/staging/qcacld-3.0/core/hdd/inc/wlan_hdd_main.h
index b6bf79e..baa5f61 100644
--- a/drivers/staging/qcacld-3.0/core/hdd/inc/wlan_hdd_main.h
+++ b/drivers/staging/qcacld-3.0/core/hdd/inc/wlan_hdd_main.h
@@ -412,26 +412,6 @@
 	unsigned int magic;
 };
 
-struct linkspeedContext {
-	struct completion completion;
-	hdd_adapter_t *pAdapter;
-	unsigned int magic;
-};
-
-/**
- * struct random_mac_context - Context used with hdd_random_mac_callback
- * @random_mac_completion: Event on which hdd_set_random_mac will wait
- * @adapter: Pointer to adapter
- * @magic: For valid context this is set to ACTION_FRAME_RANDOM_CONTEXT_MAGIC
- * @set_random_addr: Status of random filter set
- */
-struct random_mac_context {
-	struct completion random_mac_completion;
-	hdd_adapter_t *adapter;
-	unsigned int magic;
-	bool set_random_addr;
-};
-
 extern spinlock_t hdd_context_lock;
 extern struct mutex hdd_init_deinit_lock;
 
@@ -439,12 +419,9 @@
 #define PEER_INFO_CONTEXT_MAGIC 0x50494E46  /* PEER_INFO(PINF) */
 #define POWER_CONTEXT_MAGIC 0x504F5752  /* POWR */
 #define SNR_CONTEXT_MAGIC   0x534E5200  /* SNR */
-#define LINK_CONTEXT_MAGIC  0x4C494E4B  /* LINKSPEED */
 #define LINK_STATUS_MAGIC   0x4C4B5354  /* LINKSTATUS(LNST) */
-#define TEMP_CONTEXT_MAGIC  0x74656d70   /* TEMP (temperature) */
 #define APF_CONTEXT_MAGIC 0x4575354    /* APF */
 #define POWER_STATS_MAGIC 0x14111990
-#define RCPI_CONTEXT_MAGIC  0x7778888  /* RCPI */
 #define ACTION_FRAME_RANDOM_CONTEXT_MAGIC 0x87878787
 
 /* MAX OS Q block time value in msec
@@ -1325,8 +1302,9 @@
 	struct net_device_stats stats;
 	/** HDD statistics*/
 	hdd_stats_t hdd_stats;
-	/** linkspeed statistics */
-	tSirLinkSpeedInfo ls_stats;
+
+	/* estimated link speed */
+	u32 estimated_linkspeed;
 	/* SAP peer station info */
 	struct sir_peer_sta_info peer_sta_info;
 
@@ -1495,14 +1473,8 @@
 	/* Time stamp for start RoC request */
 	uint64_t start_roc_ts;
 
-	/* State for synchronous OCB requests to WMI */
-	struct sir_ocb_set_config_response ocb_set_config_resp;
-	struct sir_ocb_get_tsf_timer_response ocb_get_tsf_timer_resp;
-	struct sir_dcc_get_stats_response *dcc_get_stats_resp;
-	struct sir_dcc_update_ndl_response dcc_update_ndl_resp;
-
-	/* MAC addresses used for OCB interfaces */
 #ifdef WLAN_FEATURE_DSRC
+	/* MAC addresses used for OCB interfaces */
 	struct qdf_mac_addr ocb_mac_address[QDF_MAX_CONCURRENCY_PERSONA];
 	int ocb_mac_addr_count;
 #endif
diff --git a/drivers/staging/qcacld-3.0/core/hdd/inc/wlan_hdd_wext.h b/drivers/staging/qcacld-3.0/core/hdd/inc/wlan_hdd_wext.h
index 7f20207..775f76c 100644
--- a/drivers/staging/qcacld-3.0/core/hdd/inc/wlan_hdd_wext.h
+++ b/drivers/staging/qcacld-3.0/core/hdd/inc/wlan_hdd_wext.h
@@ -374,8 +374,20 @@
 
 extern void *mem_alloc_copy_from_user_helper(const void *wrqu_data, size_t len);
 
-int wlan_hdd_get_linkspeed_for_peermac(hdd_adapter_t *pAdapter,
-					     struct qdf_mac_addr mac_address);
+/**
+ * wlan_hdd_get_linkspeed_for_peermac() - Get link speed for a peer
+ * @adapter: adapter upon which the peer is active
+ * @mac_address: MAC address of the peer
+ * @linkspeed: pointer to memory where returned link speed is to be placed
+ *
+ * This function will send a query to SME for the linkspeed of the
+ * given peer, and then wait for the callback to be invoked.
+ *
+ * Return: 0 if linkspeed data is available, negative errno otherwise
+ */
+int wlan_hdd_get_linkspeed_for_peermac(hdd_adapter_t *adapter,
+				       struct qdf_mac_addr *mac_address,
+				       uint32_t *linkspeed);
 void hdd_clear_roam_profile_ie(hdd_adapter_t *pAdapter);
 
 uint8_t *wlan_hdd_get_vendor_oui_ie_ptr(uint8_t *oui, uint8_t oui_size,
diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_cfg80211.c b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_cfg80211.c
index eaef455..c410f7f 100644
--- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_cfg80211.c
+++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_cfg80211.c
@@ -3994,6 +3994,10 @@
 	return -EINVAL;
 }
 
+struct peer_txrx_rate_priv {
+	struct sir_peer_info_ext peer_info_ext;
+};
+
 /**
  * hdd_get_peer_txrx_rate_cb() - get station's txrx rate callback
  * @peer_info: pointer of peer information
@@ -4005,66 +4009,33 @@
 static void hdd_get_peer_txrx_rate_cb(struct sir_peer_info_ext_resp *peer_info,
 		void *context)
 {
-	struct statsContext *get_txrx_rate_context;
-	struct sir_peer_info_ext *txrx_rate;
-	hdd_adapter_t *adapter;
-	uint8_t staid;
+	struct hdd_request *request;
+	struct peer_txrx_rate_priv *priv;
 
-	if ((peer_info == NULL) || (context == NULL)) {
-		hdd_err("Bad param, peer_info [%pK] context [%pK]",
-			peer_info, context);
-		return;
-	}
-
-	spin_lock(&hdd_context_lock);
-	/*
-	 * there is a race condition that exists between this callback
-	 * function and the caller since the caller could time out either
-	 * before or while this code is executing.  we use a spinlock to
-	 * serialize these actions
-	 */
-	get_txrx_rate_context = context;
-	if (get_txrx_rate_context->magic != PEER_INFO_CONTEXT_MAGIC) {
-		/*
-		 * the caller presumably timed out so there is nothing
-		 * we can do
-		 */
-		spin_unlock(&hdd_context_lock);
-		hdd_warn("Invalid context, magic [%08x]",
-			get_txrx_rate_context->magic);
+	if (NULL == peer_info) {
+		hdd_err("Bad param, peer_info [%pK]", peer_info);
 		return;
 	}
 
 	if (!peer_info->count) {
-		spin_unlock(&hdd_context_lock);
 		hdd_err("Fail to get remote peer info");
 		return;
 	}
 
-	adapter = get_txrx_rate_context->pAdapter;
-	txrx_rate = peer_info->info;
-	if (hdd_softap_get_sta_id(adapter,
-				&txrx_rate->peer_macaddr,
-				&staid) != QDF_STATUS_SUCCESS) {
-		spin_unlock(&hdd_context_lock);
-		hdd_err("Station MAC address does not matching");
+	request = hdd_request_get(context);
+	if (!request) {
+		hdd_err("Obsolete request");
 		return;
 	}
 
-	adapter->aStaInfo[staid].tx_rate = txrx_rate->tx_rate;
-	adapter->aStaInfo[staid].rx_rate = txrx_rate->rx_rate;
-	hdd_debug("%pM txrate %u rxrate %u",
-			txrx_rate->peer_macaddr.bytes,
-			adapter->aStaInfo[staid].tx_rate,
-			adapter->aStaInfo[staid].rx_rate);
+	priv = hdd_request_priv(request);
 
-	get_txrx_rate_context->magic = 0;
+	qdf_mem_copy(&priv->peer_info_ext,
+		     peer_info->info,
+		     sizeof(peer_info->info[0]));
 
-	/* notify the caller */
-	complete(&get_txrx_rate_context->completion);
-
-	/* serialization is complete */
-	spin_unlock(&hdd_context_lock);
+	hdd_request_complete(request);
+	hdd_request_put(request);
 }
 
 /**
@@ -4081,17 +4052,30 @@
 {
 	QDF_STATUS status;
 	int ret;
-	static struct statsContext context;
+	uint8_t staid;
+	void *cookie;
 	struct sir_peer_info_ext_req txrx_rate_req;
+	struct hdd_request *request;
+	struct peer_txrx_rate_priv *priv;
+	static const struct hdd_request_params params = {
+		.priv_size = sizeof(*priv),
+		.timeout_ms = WLAN_WAIT_TIME_STATS,
+	};
 
 	if (adapter == NULL) {
 		hdd_err("pAdapter is NULL");
 		return -EFAULT;
 	}
 
-	init_completion(&context.completion);
-	context.magic = PEER_INFO_CONTEXT_MAGIC;
-	context.pAdapter = adapter;
+	request = hdd_request_alloc(&params);
+	if (!request) {
+		hdd_err("%s: Request allocation failure",
+			__func__);
+		return -ENOMEM;
+	}
+
+	cookie = hdd_request_cookie(request);
+	priv = hdd_request_priv(request);
 
 	qdf_mem_copy(&(txrx_rate_req.peer_macaddr), &macaddress,
 				QDF_MAC_ADDR_SIZE);
@@ -4099,36 +4083,38 @@
 	txrx_rate_req.reset_after_request = 0;
 	status = sme_get_peer_info_ext(WLAN_HDD_GET_HAL_CTX(adapter),
 				&txrx_rate_req,
-				&context,
+				cookie,
 				hdd_get_peer_txrx_rate_cb);
 	if (status != QDF_STATUS_SUCCESS) {
 		hdd_err("Unable to retrieve statistics for txrx_rate");
 		ret = -EFAULT;
 	} else {
-		if (!wait_for_completion_timeout(&context.completion,
-				msecs_to_jiffies(WLAN_WAIT_TIME_STATS))) {
+		ret = hdd_request_wait_for_response(request);
+		if (ret) {
 			hdd_err("SME timed out while retrieving txrx_rate");
 			ret = -EFAULT;
 		} else {
-			ret = 0;
+			if (hdd_softap_get_sta_id(adapter,
+					&priv->peer_info_ext.peer_macaddr,
+					&staid) != QDF_STATUS_SUCCESS) {
+				hdd_err("Station MAC address does not matching");
+				ret = -EFAULT;
+			} else {
+				adapter->aStaInfo[staid].tx_rate =
+						priv->peer_info_ext.tx_rate;
+				adapter->aStaInfo[staid].rx_rate =
+						priv->peer_info_ext.rx_rate;
+
+				hdd_info("%pM tx rate %u rx rate %u",
+					priv->peer_info_ext.peer_macaddr.bytes,
+					adapter->aStaInfo[staid].tx_rate,
+					adapter->aStaInfo[staid].rx_rate);
+				ret = 0;
+			}
 		}
 	}
-	/*
-	 * either we never sent a request, we sent a request and received a
-	 * response or we sent a request and timed out.  if we never sent a
-	 * request or if we sent a request and got a response, we want to
-	 * clear the magic out of paranoia.  if we timed out there is a
-	 * race condition such that the callback function could be
-	 * executing at the same time we are. of primary concern is if the
-	 * callback function had already verified the "magic" but had not
-	 * yet set the completion variable when a timeout occurred. we
-	 * serialize these activities by invalidating the magic while
-	 * holding a shared spinlock which will cause us to block if the
-	 * callback is currently executing
-	 */
-	spin_lock(&hdd_context_lock);
-	context.magic = 0;
-	spin_unlock(&hdd_context_lock);
+
+	hdd_request_put(request);
 	return ret;
 }
 
diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_hostapd.c b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_hostapd.c
index 5607444..2de35cf 100644
--- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_hostapd.c
+++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_hostapd.c
@@ -5724,15 +5724,13 @@
 		hdd_err("Invalid peer macaddress");
 		return -EINVAL;
 	}
-	errno = wlan_hdd_get_linkspeed_for_peermac(pHostapdAdapter,
-						   macAddress);
-	if (errno) {
+	rc = wlan_hdd_get_linkspeed_for_peermac(pHostapdAdapter, &macAddress,
+						&link_speed);
+	if (rc) {
 		hdd_err("Unable to retrieve SME linkspeed: %d", errno);
-		return errno;
+		return rc;
 	}
 
-	link_speed = pHostapdAdapter->ls_stats.estLinkSpeed;
-
 	/* linkspeed in units of 500 kbps */
 	link_speed = link_speed / 500;
 	wrqu->data.length = len;
diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_ioctl.c b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_ioctl.c
index 115f18b..892da8f 100644
--- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_ioctl.c
+++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_ioctl.c
@@ -40,6 +40,7 @@
 #include <linux/ctype.h>
 #include "wma.h"
 #include "wlan_hdd_napi.h"
+#include "wlan_hdd_request_manager.h"
 
 #ifdef FEATURE_WLAN_ESE
 #include <sme_api.h>
@@ -153,138 +154,82 @@
 }
 
 #ifdef FEATURE_WLAN_ESE
+struct tsm_priv {
+	tAniTrafStrmMetrics tsm_metrics;
+};
+
 static void hdd_get_tsm_stats_cb(tAniTrafStrmMetrics tsm_metrics,
 				 const uint32_t staId, void *context)
 {
-	struct statsContext *stats_context = NULL;
-	hdd_adapter_t *adapter = NULL;
+	struct hdd_request *request;
+	struct tsm_priv *priv;
 
-	if (NULL == context) {
-		hdd_err("Bad param, context [%pK]", context);
+	request = hdd_request_get(context);
+	if (!request) {
+		hdd_err("Obsolete request");
 		return;
 	}
 
-	/*
-	 * there is a race condition that exists between this callback
-	 * function and the caller since the caller could time out either
-	 * before or while this code is executing.  we use a spinlock to
-	 * serialize these actions
-	 */
-	spin_lock(&hdd_context_lock);
-
-	stats_context = context;
-	adapter = stats_context->pAdapter;
-	if ((NULL == adapter) ||
-	    (STATS_CONTEXT_MAGIC != stats_context->magic)) {
-		/*
-		 * the caller presumably timed out so there is
-		 * nothing we can do
-		 */
-		spin_unlock(&hdd_context_lock);
-		hdd_warn("Invalid context, adapter [%pK] magic [%08x]",
-			  adapter, stats_context->magic);
-		return;
-	}
-
-	/* context is valid so caller is still waiting */
-
-	/* paranoia: invalidate the magic */
-	stats_context->magic = 0;
-
-	/* copy over the tsm stats */
-	adapter->tsmStats.UplinkPktQueueDly = tsm_metrics.UplinkPktQueueDly;
-	qdf_mem_copy(adapter->tsmStats.UplinkPktQueueDlyHist,
-		     tsm_metrics.UplinkPktQueueDlyHist,
-		     sizeof(adapter->tsmStats.UplinkPktQueueDlyHist) /
-		     sizeof(adapter->tsmStats.UplinkPktQueueDlyHist[0]));
-	adapter->tsmStats.UplinkPktTxDly = tsm_metrics.UplinkPktTxDly;
-	adapter->tsmStats.UplinkPktLoss = tsm_metrics.UplinkPktLoss;
-	adapter->tsmStats.UplinkPktCount = tsm_metrics.UplinkPktCount;
-	adapter->tsmStats.RoamingCount = tsm_metrics.RoamingCount;
-	adapter->tsmStats.RoamingDly = tsm_metrics.RoamingDly;
-
-	/* notify the caller */
-	complete(&stats_context->completion);
-
-	/* serialization is complete */
-	spin_unlock(&hdd_context_lock);
+	priv = hdd_request_priv(request);
+	priv->tsm_metrics = tsm_metrics;
+	hdd_request_complete(request);
+	hdd_request_put(request);
+	EXIT();
 }
 
-static
-QDF_STATUS hdd_get_tsm_stats(hdd_adapter_t *adapter,
+static int hdd_get_tsm_stats(hdd_adapter_t *adapter,
 			     const uint8_t tid,
 			     tAniTrafStrmMetrics *tsm_metrics)
 {
-	hdd_station_ctx_t *hdd_sta_ctx = NULL;
-	QDF_STATUS hstatus;
-	QDF_STATUS vstatus = QDF_STATUS_SUCCESS;
-	unsigned long rc;
-	static struct statsContext context;
-	hdd_context_t *hdd_ctx = NULL;
+	hdd_context_t *hdd_ctx;
+	hdd_station_ctx_t *hdd_sta_ctx;
+	QDF_STATUS status;
+	int ret;
+	void *cookie;
+	struct hdd_request *request;
+	struct tsm_priv *priv;
+	static const struct hdd_request_params params = {
+		.priv_size = sizeof(*priv),
+		.timeout_ms = WLAN_WAIT_TIME_STATS,
+	};
 
 	if (NULL == adapter) {
 		hdd_err("adapter is NULL");
-		return QDF_STATUS_E_FAULT;
+		return -EINVAL;
 	}
 
 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
 	hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
 
-	/* we are connected prepare our callback context */
-	init_completion(&context.completion);
-	context.pAdapter = adapter;
-	context.magic = STATS_CONTEXT_MAGIC;
+	request = hdd_request_alloc(&params);
+	if (!request) {
+		hdd_err("Request allocation failure");
+		return -ENOMEM;
+	}
+	cookie = hdd_request_cookie(request);
 
-	/* query tsm stats */
-	hstatus = sme_get_tsm_stats(hdd_ctx->hHal, hdd_get_tsm_stats_cb,
-				    hdd_sta_ctx->conn_info.staId[0],
-				    hdd_sta_ctx->conn_info.bssId,
-				    &context, hdd_ctx->pcds_context, tid);
-	if (QDF_STATUS_SUCCESS != hstatus) {
-		hdd_err("Unable to retrieve statistics");
-		vstatus = QDF_STATUS_E_FAULT;
-	} else {
-		/* request was sent -- wait for the response */
-		rc = wait_for_completion_timeout(&context.completion,
-				msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
-		if (!rc) {
-			hdd_err("SME timed out while retrieving statistics");
-			vstatus = QDF_STATUS_E_TIMEOUT;
-		}
+	status = sme_get_tsm_stats(hdd_ctx->hHal, hdd_get_tsm_stats_cb,
+				   hdd_sta_ctx->conn_info.staId[0],
+				   hdd_sta_ctx->conn_info.bssId,
+				   cookie, hdd_ctx->pcds_context, tid);
+	if (QDF_STATUS_SUCCESS != status) {
+		hdd_err("Unable to retrieve tsm statistics");
+		ret = qdf_status_to_os_return(status);
+		goto cleanup;
 	}
 
-	/*
-	 * either we never sent a request, we sent a request and received a
-	 * response or we sent a request and timed out.  if we never sent a
-	 * request or if we sent a request and got a response, we want to
-	 * clear the magic out of paranoia.  if we timed out there is a
-	 * race condition such that the callback function could be
-	 * executing at the same time we are. of primary concern is if the
-	 * callback function had already verified the "magic" but had not
-	 * yet set the completion variable when a timeout occurred. we
-	 * serialize these activities by invalidating the magic while
-	 * holding a shared spinlock which will cause us to block if the
-	 * callback is currently executing
-	 */
-	spin_lock(&hdd_context_lock);
-	context.magic = 0;
-	spin_unlock(&hdd_context_lock);
-
-	if (QDF_STATUS_SUCCESS == vstatus) {
-		tsm_metrics->UplinkPktQueueDly =
-			adapter->tsmStats.UplinkPktQueueDly;
-		qdf_mem_copy(tsm_metrics->UplinkPktQueueDlyHist,
-			     adapter->tsmStats.UplinkPktQueueDlyHist,
-			     sizeof(adapter->tsmStats.UplinkPktQueueDlyHist) /
-			     sizeof(adapter->tsmStats.
-				    UplinkPktQueueDlyHist[0]));
-		tsm_metrics->UplinkPktTxDly = adapter->tsmStats.UplinkPktTxDly;
-		tsm_metrics->UplinkPktLoss = adapter->tsmStats.UplinkPktLoss;
-		tsm_metrics->UplinkPktCount = adapter->tsmStats.UplinkPktCount;
-		tsm_metrics->RoamingCount = adapter->tsmStats.RoamingCount;
-		tsm_metrics->RoamingDly = adapter->tsmStats.RoamingDly;
+	ret = hdd_request_wait_for_response(request);
+	if (ret) {
+		hdd_err("SME timed out while retrieving tsm statistics");
+		goto cleanup;
 	}
-	return vstatus;
+
+	priv = hdd_request_priv(request);
+	*tsm_metrics = priv->tsm_metrics;
+
+cleanup:
+	hdd_request_put(request);
+	return ret;
 }
 #endif /*FEATURE_WLAN_ESE */
 
@@ -5413,7 +5358,7 @@
 	int len = 0;
 	uint8_t tid = 0;
 	hdd_station_ctx_t *pHddStaCtx;
-	tAniTrafStrmMetrics tsm_metrics;
+	tAniTrafStrmMetrics tsm_metrics = {0};
 
 	if ((QDF_STA_MODE != adapter->device_mode) &&
 	    (QDF_P2P_CLIENT_MODE != adapter->device_mode)) {
@@ -5456,10 +5401,9 @@
 	}
 	hdd_debug("Received Command to get tsm stats tid = %d",
 		 tid);
-	if (QDF_STATUS_SUCCESS !=
-	    hdd_get_tsm_stats(adapter, tid, &tsm_metrics)) {
+	ret = hdd_get_tsm_stats(adapter, tid, &tsm_metrics);
+	if (ret) {
 		hdd_err("failed to get tsm stats");
-		ret = -EFAULT;
 		goto exit;
 	}
 	hdd_debug(
diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_main.c b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_main.c
index cf2b709..4112efd 100644
--- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_main.c
+++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_main.c
@@ -1205,7 +1205,8 @@
 	if (sme_cfg_get_str(hdd_ctx->hHal, WNI_CFG_SUPPORTED_MCS_SET, mcs_set,
 			    &value) == QDF_STATUS_SUCCESS) {
 		hdd_debug("Read MCS rate set");
-
+		if (cfg->num_rf_chains > SIZE_OF_SUPPORTED_MCS_SET)
+			cfg->num_rf_chains = SIZE_OF_SUPPORTED_MCS_SET;
 		if (pconfig->enable2x2) {
 			for (value = 0; value < cfg->num_rf_chains; value++)
 				mcs_set[value] =
diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_ocb.c b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_ocb.c
index a613d10..f8ec040 100644
--- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_ocb.c
+++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_ocb.c
@@ -37,6 +37,7 @@
 #include "wlan_hdd_ocb.h"
 #include "wlan_hdd_trace.h"
 #include "wlan_tgt_def_config.h"
+#include "wlan_hdd_request_manager.h"
 #include "sch_api.h"
 #include "wma_api.h"
 #include "ol_txrx.h"
@@ -50,20 +51,6 @@
 
 /* Maximum time(ms) to wait for OCB operations */
 #define WLAN_WAIT_TIME_OCB_CMD 1500
-#define HDD_OCB_MAGIC 0x489a154f
-
-/**
- * struct hdd_ocb_ctxt - Context for OCB operations
- * adapter: the ocb adapter
- * completion_evt: the completion event
- * status: status of the request
- */
-struct hdd_ocb_ctxt {
-	uint32_t magic;
-	hdd_adapter_t *adapter;
-	struct completion completion_evt;
-	int status;
-};
 
 /**
  * hdd_set_dot11p_config() - Set 802.11p config flag
@@ -348,6 +335,11 @@
 	return NULL;
 }
 
+struct hdd_ocb_set_config_priv {
+	int status;
+};
+
+
 /**
  * hdd_ocb_set_config_callback() - OCB set config callback function
  * @context_ptr: OCB call context
@@ -358,47 +350,27 @@
  */
 static void hdd_ocb_set_config_callback(void *context_ptr, void *response_ptr)
 {
-	struct hdd_ocb_ctxt *context = context_ptr;
-	struct sir_ocb_set_config_response *resp = response_ptr;
+	struct hdd_request *hdd_request;
+	struct hdd_ocb_set_config_priv *priv;
+	struct sir_ocb_set_config_response *response = response_ptr;
 
-	if (!context)
+	hdd_request = hdd_request_get(context_ptr);
+	if (!hdd_request) {
+		hdd_err("Obsolete request");
 		return;
-
-	if (resp && resp->status)
-		hdd_warn("Operation failed: %d", resp->status);
-
-	spin_lock(&hdd_context_lock);
-	if (context->magic == HDD_OCB_MAGIC) {
-		hdd_adapter_t *adapter = context->adapter;
-
-		if (!resp) {
-			context->status = -EINVAL;
-			complete(&context->completion_evt);
-			spin_unlock(&hdd_context_lock);
-			return;
-		}
-
-		context->adapter->ocb_set_config_resp = *resp;
-		spin_unlock(&hdd_context_lock);
-		if (!resp->status) {
-			/*
-			 * OCB set config command successful.
-			 * Open the TX data path
-			 */
-			if (!hdd_ocb_register_sta(adapter)) {
-				wlan_hdd_netif_queue_control(adapter,
-					WLAN_START_ALL_NETIF_QUEUE_N_CARRIER,
-					WLAN_CONTROL_PATH);
-			}
-		}
-
-		spin_lock(&hdd_context_lock);
-		if (context->magic == HDD_OCB_MAGIC)
-			complete(&context->completion_evt);
-		spin_unlock(&hdd_context_lock);
-	} else {
-		spin_unlock(&hdd_context_lock);
 	}
+	priv = hdd_request_priv(hdd_request);
+
+	if (response && response->status)
+		hdd_warn("Operation failed: %d", response->status);
+
+	if (response && (0 == response->status))
+		priv->status = 0;
+	else
+		priv->status = -EINVAL;
+
+	hdd_request_complete(hdd_request);
+	hdd_request_put(hdd_request);
 }
 
 /**
@@ -412,59 +384,70 @@
 				  struct sir_ocb_config *config)
 {
 	int rc;
-	QDF_STATUS qdf_status;
-	struct hdd_ocb_ctxt context = {0};
+	QDF_STATUS status;
+	hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+	void *cookie;
+	struct hdd_request *hdd_request;
+	struct hdd_ocb_set_config_priv *priv;
+	static const struct hdd_request_params params = {
+		.priv_size = sizeof(*priv),
+		.timeout_ms = WLAN_WAIT_TIME_OCB_CMD,
+	};
 
 	if (hdd_ocb_validate_config(adapter, config)) {
 		hdd_err("The configuration is invalid");
 		return -EINVAL;
 	}
 
-	init_completion(&context.completion_evt);
-	context.adapter = adapter;
-	context.magic = HDD_OCB_MAGIC;
+	hdd_request = hdd_request_alloc(&params);
+	if (!hdd_request) {
+		hdd_err("Request allocation failure");
+		return -ENOMEM;
+	}
+	cookie = hdd_request_cookie(hdd_request);
 
-	hdd_info("Disabling queues");
+	hdd_debug("Disabling queues");
 	wlan_hdd_netif_queue_control(adapter,
 				     WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER,
 				     WLAN_CONTROL_PATH);
 
-	/* Call the SME API to set the config */
-	qdf_status = sme_ocb_set_config(
-		((hdd_context_t *)adapter->pHddCtx)->hHal, &context,
-		hdd_ocb_set_config_callback, config);
-	if (qdf_status != QDF_STATUS_SUCCESS) {
-		hdd_err("Error calling SME function.");
-		/* Convert from qdf_status to errno */
-		return -EINVAL;
+	status = sme_ocb_set_config(hdd_ctx->hHal, cookie,
+				    hdd_ocb_set_config_callback,
+				    config);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		hdd_err("Failed to set channel config.");
+		/* Convert from eHalStatus to errno */
+		rc = qdf_status_to_os_return(status);
+		goto end;
 	}
 
 	/* Wait for the function to complete. */
-	rc = wait_for_completion_timeout(&context.completion_evt,
-		msecs_to_jiffies(WLAN_WAIT_TIME_OCB_CMD));
-	if (rc == 0) {
-		rc = -ETIMEDOUT;
-		goto end;
-	}
-	rc = 0;
-
-	if (context.status) {
-		rc = context.status;
+	rc = hdd_request_wait_for_response(hdd_request);
+	if (rc) {
+		hdd_err("Operation timed out");
 		goto end;
 	}
 
-	if (adapter->ocb_set_config_resp.status) {
-		rc = -EINVAL;
+	priv = hdd_request_priv(hdd_request);
+	rc = priv->status;
+	if (rc) {
+		hdd_err("Operation failed: %d", rc);
 		goto end;
 	}
 
+	/*
+	 * OCB set config command successful.
+	 * Open the TX data path
+	 */
+	if (!hdd_ocb_register_sta(adapter))
+		wlan_hdd_netif_queue_control(adapter,
+					     WLAN_START_ALL_NETIF_QUEUE_N_CARRIER,
+					     WLAN_CONTROL_PATH);
+
 	/* fall through */
 end:
-	spin_lock(&hdd_context_lock);
-	context.magic = 0;
-	spin_unlock(&hdd_context_lock);
-	if (rc)
-		hdd_err("Operation failed: %d", rc);
+	hdd_request_put(hdd_request);
+
 	return rc;
 }
 
@@ -1314,6 +1297,11 @@
 	return ret;
 }
 
+struct hdd_ocb_get_tsf_timer_priv {
+	struct sir_ocb_get_tsf_timer_response response;
+	int status;
+};
+
 /**
  * hdd_ocb_get_tsf_timer_callback() - Callback to get TSF command
  * @context_ptr: request context
@@ -1322,23 +1310,67 @@
 static void hdd_ocb_get_tsf_timer_callback(void *context_ptr,
 					   void *response_ptr)
 {
-	struct hdd_ocb_ctxt *context = context_ptr;
+	struct hdd_request *hdd_request;
+	struct hdd_ocb_get_tsf_timer_priv *priv;
 	struct sir_ocb_get_tsf_timer_response *response = response_ptr;
 
-	if (!context)
+	hdd_request = hdd_request_get(context_ptr);
+	if (!hdd_request) {
+		hdd_err("Obsolete request");
 		return;
-
-	spin_lock(&hdd_context_lock);
-	if (context->magic == HDD_OCB_MAGIC) {
-		if (response) {
-			context->adapter->ocb_get_tsf_timer_resp = *response;
-			context->status = 0;
-		} else {
-			context->status = -EINVAL;
-		}
-		complete(&context->completion_evt);
 	}
-	spin_unlock(&hdd_context_lock);
+
+	if (response) {
+		priv->response = *response;
+		priv->status = 0;
+	} else {
+		priv->status = -EINVAL;
+	}
+	hdd_request_complete(hdd_request);
+	hdd_request_put(hdd_request);
+}
+
+static int
+hdd_ocb_get_tsf_timer_reply(struct wiphy *wiphy,
+			    struct sir_ocb_get_tsf_timer_response *response)
+{
+	uint32_t nl_buf_len;
+	struct sk_buff *nl_resp;
+	int rc;
+
+	/* Allocate the buffer for the response. */
+	nl_buf_len = NLMSG_HDRLEN;
+	nl_buf_len += 2 * (NLA_HDRLEN + sizeof(uint32_t));
+	nl_resp = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, nl_buf_len);
+	if (!nl_resp) {
+		hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
+		return -ENOMEM;
+	}
+
+	/* Populate the response. */
+	rc = nla_put_u32(nl_resp,
+			 QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_TIMER_HIGH,
+			 response->timer_high);
+	if (rc)
+		goto end;
+	rc = nla_put_u32(nl_resp,
+			 QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_TIMER_LOW,
+			 response->timer_low);
+	if (rc)
+		goto end;
+
+	/* Send the response. */
+	rc = cfg80211_vendor_cmd_reply(nl_resp);
+	nl_resp = NULL;
+	if (rc) {
+		hdd_err("cfg80211_vendor_cmd_reply failed: %d", rc);
+		goto end;
+	}
+end:
+	if (nl_resp)
+		kfree_skb(nl_resp);
+
+	return rc;
 }
 
 /**
@@ -1356,18 +1388,25 @@
 				      const void *data,
 				      int data_len)
 {
-	struct sk_buff *nl_resp = 0;
 	hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
 	struct net_device *dev = wdev->netdev;
 	hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
-	int rc = -EINVAL;
+	int rc;
 	struct sir_ocb_get_tsf_timer request = {0};
-	struct hdd_ocb_ctxt context = {0};
+	QDF_STATUS status;
+	void *cookie;
+	struct hdd_request *hdd_request;
+	struct hdd_ocb_get_tsf_timer_priv *priv;
+	static const struct hdd_request_params params = {
+		.priv_size = sizeof(*priv),
+		.timeout_ms = WLAN_WAIT_TIME_OCB_CMD,
+	};
 
 	ENTER_DEV(dev);
 
-	if (wlan_hdd_validate_context(hdd_ctx))
-		return -EINVAL;
+	rc = wlan_hdd_validate_context(hdd_ctx);
+	if (rc)
+		return rc;
 
 	if (adapter->device_mode != QDF_OCB_MODE) {
 		hdd_err("Device not in OCB mode!");
@@ -1379,77 +1418,52 @@
 		return -EINVAL;
 	}
 
-	/* Initialize the callback context */
-	init_completion(&context.completion_evt);
-	context.adapter = adapter;
-	context.magic = HDD_OCB_MAGIC;
+	hdd_request = hdd_request_alloc(&params);
+	if (!hdd_request) {
+		hdd_err("Request allocation failure");
+		return -ENOMEM;
+	}
+	cookie = hdd_request_cookie(hdd_request);
 
 	request.vdev_id = adapter->sessionId;
 	/* Call the SME function */
-	rc = sme_ocb_get_tsf_timer(hdd_ctx->hHal, &context,
-				   hdd_ocb_get_tsf_timer_callback,
-				   &request);
+	status = sme_ocb_get_tsf_timer(hdd_ctx->hHal, cookie,
+				       hdd_ocb_get_tsf_timer_callback,
+				       &request);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		hdd_err("Failed to get tsf timer.");
+		rc = qdf_status_to_os_return(status);
+		goto end;
+	}
+
+	rc = hdd_request_wait_for_response(hdd_request);
 	if (rc) {
-		hdd_err("Error calling SME function");
-		/* Need to convert from qdf_status to errno. */
-		return -EINVAL;
-	}
-
-	rc = wait_for_completion_timeout(&context.completion_evt,
-		msecs_to_jiffies(WLAN_WAIT_TIME_OCB_CMD));
-	if (rc == 0) {
 		hdd_err("Operation timed out");
-		rc = -ETIMEDOUT;
-		goto end;
-	}
-	rc = 0;
-
-	if (context.status) {
-		hdd_err("Operation failed: %d", context.status);
-		rc = context.status;
 		goto end;
 	}
 
-	/* Allocate the buffer for the response. */
-	nl_resp = cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
-		2 * sizeof(uint32_t) + NLMSG_HDRLEN);
-
-	if (!nl_resp) {
-		hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
-		rc = -ENOMEM;
+	priv = hdd_request_priv(hdd_request);
+	rc = priv->status;
+	if (rc) {
+		hdd_err("Operation failed: %d", rc);
 		goto end;
 	}
 
 	hdd_debug("Got TSF timer response, high=%d, low=%d",
-	       adapter->ocb_get_tsf_timer_resp.timer_high,
-	       adapter->ocb_get_tsf_timer_resp.timer_low);
-
-	/* Populate the response. */
-	rc = nla_put_u32(nl_resp,
-			QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_TIMER_HIGH,
-			adapter->ocb_get_tsf_timer_resp.timer_high);
-	if (rc)
-		goto end;
-	rc = nla_put_u32(nl_resp,
-			    QCA_WLAN_VENDOR_ATTR_OCB_GET_TSF_RESP_TIMER_LOW,
-			    adapter->ocb_get_tsf_timer_resp.timer_low);
-	if (rc)
-		goto end;
+		priv->response.timer_high,
+		priv->response.timer_low);
 
 	/* Send the response. */
-	rc = cfg80211_vendor_cmd_reply(nl_resp);
-	nl_resp = NULL;
+	rc = hdd_ocb_get_tsf_timer_reply(wiphy, &priv->response);
 	if (rc) {
-		hdd_err("cfg80211_vendor_cmd_reply failed: %d", rc);
+		hdd_err("hdd_ocb_get_tsf_timer_reply failed: %d", rc);
 		goto end;
 	}
 
+	/* fall through */
 end:
-	spin_lock(&hdd_context_lock);
-	context.magic = 0;
-	spin_unlock(&hdd_context_lock);
-	if (nl_resp)
-		kfree_skb(nl_resp);
+	hdd_request_put(hdd_request);
+
 	return rc;
 }
 
@@ -1477,6 +1491,19 @@
 	return ret;
 }
 
+struct hdd_dcc_stats_priv {
+	struct sir_dcc_get_stats_response *response;
+	int status;
+};
+
+static void hdd_dcc_get_stats_dealloc(void *context_ptr)
+{
+	struct hdd_dcc_stats_priv *priv = context_ptr;
+
+	qdf_mem_free(priv->response);
+	priv->response = NULL;
+}
+
 /**
  * hdd_dcc_get_stats_callback() - Callback to get stats command
  * @context_ptr: request context
@@ -1484,46 +1511,86 @@
  */
 static void hdd_dcc_get_stats_callback(void *context_ptr, void *response_ptr)
 {
-	struct hdd_ocb_ctxt *context = context_ptr;
+	struct hdd_request *hdd_request;
+	struct hdd_dcc_stats_priv *priv;
 	struct sir_dcc_get_stats_response *response = response_ptr;
 	struct sir_dcc_get_stats_response *hdd_resp;
 
-	if (!context)
+	hdd_request = hdd_request_get(context_ptr);
+	if (!hdd_request) {
+		hdd_err("Obsolete request");
 		return;
-
-	spin_lock(&hdd_context_lock);
-	if (context->magic == HDD_OCB_MAGIC) {
-		if (response) {
-			/*
-			 * If the response is hanging around from the previous
-			 * request, delete it
-			 */
-			if (context->adapter->dcc_get_stats_resp) {
-				qdf_mem_free(
-				    context->adapter->dcc_get_stats_resp);
-			}
-			context->adapter->dcc_get_stats_resp =
-				qdf_mem_malloc(sizeof(
-				    *context->adapter->dcc_get_stats_resp) +
-				    response->channel_stats_array_len);
-			if (context->adapter->dcc_get_stats_resp) {
-				hdd_resp = context->adapter->dcc_get_stats_resp;
-				*hdd_resp = *response;
-				hdd_resp->channel_stats_array =
-					(void *)hdd_resp + sizeof(*hdd_resp);
-				qdf_mem_copy(hdd_resp->channel_stats_array,
-					     response->channel_stats_array,
-					     response->channel_stats_array_len);
-				context->status = 0;
-			} else {
-				context->status = -ENOMEM;
-			}
-		} else {
-			context->status = -EINVAL;
-		}
-		complete(&context->completion_evt);
 	}
-	spin_unlock(&hdd_context_lock);
+
+	priv = hdd_request_priv(hdd_request);
+	if (!response) {
+		priv->status = -EINVAL;
+		goto end;
+	}
+
+	priv->response = qdf_mem_malloc(sizeof(*response) +
+					response->channel_stats_array_len);
+	if (!priv->response) {
+		priv->status = -ENOMEM;
+		goto end;
+	}
+
+	hdd_resp = priv->response;
+	*hdd_resp = *response;
+	hdd_resp->channel_stats_array = (void *)hdd_resp + sizeof(*hdd_resp);
+	qdf_mem_copy(hdd_resp->channel_stats_array,
+		     response->channel_stats_array,
+		     response->channel_stats_array_len);
+	priv->status = 0;
+
+end:
+	hdd_request_complete(hdd_request);
+	hdd_request_put(hdd_request);
+}
+
+static int
+hdd_dcc_get_stats_send_reply(struct wiphy *wiphy,
+			     struct sir_dcc_get_stats_response *response)
+{
+	uint32_t nl_buf_len;
+	struct sk_buff *nl_resp;
+	int rc;
+
+	/* Allocate the buffer for the response. */
+	nl_buf_len = NLMSG_HDRLEN;
+	nl_buf_len += NLA_HDRLEN + sizeof(uint32_t);
+	nl_buf_len += NLA_HDRLEN + response->channel_stats_array_len;
+	nl_resp = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, nl_buf_len);
+	if (!nl_resp) {
+		hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
+		return -ENOMEM;
+	}
+
+	/* Populate the response. */
+	rc = nla_put_u32(nl_resp,
+			 QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_RESP_CHANNEL_COUNT,
+			 response->num_channels);
+	if (rc)
+		goto end;
+	rc = nla_put(nl_resp,
+		     QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_RESP_STATS_ARRAY,
+		     response->channel_stats_array_len,
+		     response->channel_stats_array);
+	if (rc)
+		goto end;
+
+	/* Send the response. */
+	rc = cfg80211_vendor_cmd_reply(nl_resp);
+	nl_resp = NULL;
+	if (rc) {
+		hdd_err("cfg80211_vendor_cmd_reply failed: %d", rc);
+		goto end;
+	}
+end:
+	if (nl_resp)
+		kfree_skb(nl_resp);
+
+	return rc;
 }
 
 /**
@@ -1547,15 +1614,23 @@
 	struct net_device *dev = wdev->netdev;
 	hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_MAX + 1];
-	struct sk_buff *nl_resp = 0;
-	int rc = -EINVAL;
+	int rc;
 	struct sir_dcc_get_stats request = {0};
-	struct hdd_ocb_ctxt context = {0};
+	QDF_STATUS status;
+	void *cookie;
+	struct hdd_request *hdd_request;
+	struct hdd_dcc_stats_priv *priv;
+	static const struct hdd_request_params params = {
+		.priv_size = sizeof(*priv),
+		.timeout_ms = WLAN_WAIT_TIME_OCB_CMD,
+		.dealloc = hdd_dcc_get_stats_dealloc,
+	};
 
 	ENTER_DEV(dev);
 
-	if (wlan_hdd_validate_context(hdd_ctx))
-		return -EINVAL;
+	rc = wlan_hdd_validate_context(hdd_ctx);
+	if (rc)
+		return rc;
 
 	if (adapter->device_mode != QDF_OCB_MODE) {
 		hdd_err("Device not in OCB mode!");
@@ -1588,10 +1663,12 @@
 	request_array = nla_data(
 		tb[QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_REQUEST_ARRAY]);
 
-	/* Initialize the callback context */
-	init_completion(&context.completion_evt);
-	context.adapter = adapter;
-	context.magic = HDD_OCB_MAGIC;
+	hdd_request = hdd_request_alloc(&params);
+	if (!hdd_request) {
+		hdd_err("Request allocation failure");
+		return -ENOMEM;
+	}
+	cookie = hdd_request_cookie(hdd_request);
 
 	request.vdev_id = adapter->sessionId;
 	request.channel_count = channel_count;
@@ -1599,76 +1676,40 @@
 	request.request_array = request_array;
 
 	/* Call the SME function. */
-	rc = sme_dcc_get_stats(hdd_ctx->hHal, &context,
-			       hdd_dcc_get_stats_callback,
-			       &request);
-	if (rc) {
-		hdd_err("Error calling SME function");
-		/* Need to convert from qdf_status to errno. */
-		return -EINVAL;
+	status = sme_dcc_get_stats(hdd_ctx->hHal, cookie,
+				   hdd_dcc_get_stats_callback,
+				   &request);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		hdd_err("Error calling SME function.");
+		rc = qdf_status_to_os_return(status);
+		goto end;
 	}
 
 	/* Wait for the function to complete. */
-	rc = wait_for_completion_timeout(&context.completion_evt,
-				msecs_to_jiffies(WLAN_WAIT_TIME_OCB_CMD));
-	if (rc == 0) {
+	rc = hdd_request_wait_for_response(hdd_request);
+	if (rc) {
+		hdd_err("Operation timed out");
+		goto end;
+	}
+
+	priv = hdd_request_priv(hdd_request);
+	rc = priv->status;
+	if (rc) {
 		hdd_err("Operation failed: %d", rc);
-		rc = -ETIMEDOUT;
 		goto end;
 	}
 
-	if (context.status) {
-		hdd_err("There was error: %d", context.status);
-		rc = context.status;
-		goto end;
-	}
-
-	if (!adapter->dcc_get_stats_resp) {
-		hdd_err("The response was NULL");
-		rc = -EINVAL;
-		goto end;
-	}
-
-	/* Allocate the buffer for the response. */
-	nl_resp = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(uint32_t) +
-		adapter->dcc_get_stats_resp->channel_stats_array_len +
-		NLMSG_HDRLEN);
-	if (!nl_resp) {
-		hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
-		rc = -ENOMEM;
-		goto end;
-	}
-
-	/* Populate the response. */
-	rc = nla_put_u32(nl_resp,
-			 QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_RESP_CHANNEL_COUNT,
-			 adapter->dcc_get_stats_resp->num_channels);
-	if (rc)
-		goto end;
-	rc = nla_put(nl_resp,
-		     QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_RESP_STATS_ARRAY,
-		     adapter->dcc_get_stats_resp->channel_stats_array_len,
-		     adapter->dcc_get_stats_resp->channel_stats_array);
-	if (rc)
-		goto end;
-
 	/* Send the response. */
-	rc = cfg80211_vendor_cmd_reply(nl_resp);
-	nl_resp = NULL;
+	rc = hdd_dcc_get_stats_send_reply(wiphy, priv->response);
 	if (rc) {
-		hdd_err("cfg80211_vendor_cmd_reply failed: %d", rc);
+		hdd_err("hdd_dcc_get_stats_send_reply failed: %d", rc);
 		goto end;
 	}
 
 	/* fall through */
 end:
-	spin_lock(&hdd_context_lock);
-	context.magic = 0;
-	qdf_mem_free(adapter->dcc_get_stats_resp);
-	adapter->dcc_get_stats_resp = NULL;
-	spin_unlock(&hdd_context_lock);
-	if (nl_resp)
-		kfree_skb(nl_resp);
+	hdd_request_put(hdd_request);
+
 	return rc;
 }
 
@@ -1779,6 +1820,10 @@
 	return ret;
 }
 
+struct hdd_dcc_update_ndl_priv {
+	int status;
+};
+
 /**
  * hdd_dcc_update_ndl_callback() - Callback to update NDL command
  * @context_ptr: request context
@@ -1786,23 +1831,22 @@
  */
 static void hdd_dcc_update_ndl_callback(void *context_ptr, void *response_ptr)
 {
-	struct hdd_ocb_ctxt *context = context_ptr;
+	struct hdd_request *hdd_request;
+	struct hdd_dcc_update_ndl_priv *priv;
 	struct sir_dcc_update_ndl_response *response = response_ptr;
 
-	if (!context)
+	hdd_request = hdd_request_get(context_ptr);
+	if (!hdd_request) {
+		hdd_err("Obsolete request");
 		return;
-
-	spin_lock(&hdd_context_lock);
-	if (context->magic == HDD_OCB_MAGIC) {
-		if (response) {
-			context->adapter->dcc_update_ndl_resp = *response;
-			context->status = 0;
-		} else {
-			context->status = -EINVAL;
-		}
-		complete(&context->completion_evt);
 	}
-	spin_unlock(&hdd_context_lock);
+	priv = hdd_request_priv(hdd_request);
+	if (response && (0 == response->status))
+		priv->status = 0;
+	else
+		priv->status = -EINVAL;
+	hdd_request_complete(hdd_request);
+	hdd_request_put(hdd_request);
 }
 
 /**
@@ -1829,17 +1873,25 @@
 	void *ndl_channel_array;
 	uint32_t ndl_active_state_array_len;
 	void *ndl_active_state_array;
-	int rc = -EINVAL;
-	struct hdd_ocb_ctxt context = {0};
+	int rc;
+	QDF_STATUS status;
+	void *cookie;
+	struct hdd_request *hdd_request;
+	struct hdd_dcc_update_ndl_priv *priv;
+	static const struct hdd_request_params params = {
+		.priv_size = sizeof(*priv),
+		.timeout_ms = WLAN_WAIT_TIME_OCB_CMD,
+	};
 
 	ENTER_DEV(dev);
 
-	if (wlan_hdd_validate_context(hdd_ctx))
-		goto end;
+	rc = wlan_hdd_validate_context(hdd_ctx);
+	if (rc)
+		return rc;
 
 	if (adapter->device_mode != QDF_OCB_MODE) {
 		hdd_err("Device not in OCB mode!");
-		goto end;
+		return -EINVAL;
 	}
 
 	if (!wma_is_vdev_up(adapter->sessionId)) {
@@ -1851,7 +1903,7 @@
 	if (hdd_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_DCC_UPDATE_NDL_MAX, data,
 			  data_len, qca_wlan_vendor_dcc_update_ndl)) {
 		hdd_err("Invalid ATTR");
-		goto end;
+		return -EINVAL;
 	}
 
 	/* Verify that the parameter is present */
@@ -1873,10 +1925,12 @@
 	ndl_active_state_array = nla_data(
 		tb[QCA_WLAN_VENDOR_ATTR_DCC_UPDATE_NDL_ACTIVE_STATE_ARRAY]);
 
-	/* Initialize the callback context */
-	init_completion(&context.completion_evt);
-	context.adapter = adapter;
-	context.magic = HDD_OCB_MAGIC;
+	hdd_request = hdd_request_alloc(&params);
+	if (!hdd_request) {
+		hdd_err("Request allocation failure");
+		return -ENOMEM;
+	}
+	cookie = hdd_request_cookie(hdd_request);
 
 	/* Copy the parameters to the request structure. */
 	request.vdev_id = adapter->sessionId;
@@ -1887,43 +1941,33 @@
 	request.dcc_ndl_active_state_list = ndl_active_state_array;
 
 	/* Call the SME function */
-	rc = sme_dcc_update_ndl(hdd_ctx->hHal, &context,
-				hdd_dcc_update_ndl_callback,
-				&request);
-	if (rc) {
+	status = sme_dcc_update_ndl(hdd_ctx->hHal, cookie,
+				    hdd_dcc_update_ndl_callback,
+				    &request);
+	if (QDF_IS_STATUS_ERROR(status)) {
 		hdd_err("Error calling SME function.");
-		/* Convert from qdf_status to errno */
-		return -EINVAL;
+		rc = qdf_status_to_os_return(status);
+		goto end;
 	}
 
 	/* Wait for the function to complete. */
-	rc = wait_for_completion_timeout(&context.completion_evt,
-		msecs_to_jiffies(WLAN_WAIT_TIME_OCB_CMD));
-	if (rc == 0) {
+	rc = hdd_request_wait_for_response(hdd_request);
+	if (rc) {
 		hdd_err("Operation timed out");
-		rc = -ETIMEDOUT;
-		goto end;
-	}
-	rc = 0;
-
-	if (context.status) {
-		hdd_err("Operation failed: %d", context.status);
-		rc = context.status;
 		goto end;
 	}
 
-	if (adapter->dcc_update_ndl_resp.status) {
-		hdd_err("Operation returned: %d",
-		       adapter->dcc_update_ndl_resp.status);
-		rc = -EINVAL;
+	priv = hdd_request_priv(hdd_request);
+	rc = priv->status;
+	if (rc) {
+		hdd_err("Operation failed: %d", rc);
 		goto end;
 	}
 
 	/* fall through */
 end:
-	spin_lock(&hdd_context_lock);
-	context.magic = 0;
-	spin_unlock(&hdd_context_lock);
+	hdd_request_put(hdd_request);
+
 	return rc;
 }
 
diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_p2p.c b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_p2p.c
index 18871727..e3259d3 100644
--- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_p2p.c
+++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_p2p.c
@@ -53,6 +53,7 @@
 #include "cds_sched.h"
 #include "cds_concurrency.h"
 #include "cds_utils.h"
+#include "wlan_hdd_request_manager.h"
 
 /* Ms to Time Unit Micro Sec */
 #define MS_TO_TU_MUS(x)   ((x) * 1024)
@@ -180,6 +181,10 @@
 		return false;
 }
 
+struct random_mac_priv {
+	bool set_random_addr;
+};
+
 /**
  * hdd_random_mac_callback() - Callback invoked from wmi layer
  * @set_random_addr: Status of random mac filter set operation
@@ -192,31 +197,20 @@
  */
 static void hdd_random_mac_callback(bool set_random_addr, void *context)
 {
-	struct random_mac_context *rnd_ctx;
-	hdd_adapter_t *adapter;
+	struct hdd_request *request;
+	struct random_mac_priv *priv;
 
-	if (!context) {
-		hdd_err("Bad param, pContext");
+	request = hdd_request_get(context);
+	if (!request) {
+		hdd_err("invalid request");
 		return;
 	}
 
-	rnd_ctx = context;
-	adapter = rnd_ctx->adapter;
+	priv = hdd_request_priv(request);
+	priv->set_random_addr = set_random_addr;
 
-	spin_lock(&hdd_context_lock);
-	if ((!adapter) ||
-	    (rnd_ctx->magic != ACTION_FRAME_RANDOM_CONTEXT_MAGIC)) {
-		spin_unlock(&hdd_context_lock);
-		hdd_err("Invalid context, magic [%08x]", rnd_ctx->magic);
-		return;
-	}
-
-	rnd_ctx->magic = 0;
-	if (set_random_addr)
-		rnd_ctx->set_random_addr = true;
-
-	complete(&rnd_ctx->random_mac_completion);
-	spin_unlock(&hdd_context_lock);
+	hdd_request_complete(request);
+	hdd_request_put(request);
 }
 
 /**
@@ -231,11 +225,17 @@
 			       uint8_t *random_mac_addr,
 			       uint32_t freq)
 {
-	struct random_mac_context context;
 	hdd_context_t *hdd_ctx;
 	QDF_STATUS sme_status;
 	unsigned long rc;
+	void *cookie;
 	bool status = false;
+	struct hdd_request     *request;
+	struct random_mac_priv *priv;
+	static const struct hdd_request_params params = {
+		.priv_size = sizeof(*priv),
+		.timeout_ms = WLAN_WAIT_TIME_SET_RND,
+	};
 
 	ENTER();
 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
@@ -244,30 +244,33 @@
 		return false;
 	}
 
-	init_completion(&context.random_mac_completion);
-	context.adapter = adapter;
-	context.magic = ACTION_FRAME_RANDOM_CONTEXT_MAGIC;
-	context.set_random_addr = false;
+	request = hdd_request_alloc(&params);
+	if (!request) {
+		hdd_err("Request allocation failure");
+		return false;
+	}
+
+	cookie = hdd_request_cookie(request);
 
 	sme_status = sme_set_random_mac(hdd_ctx->hHal, hdd_random_mac_callback,
 				     adapter->sessionId, random_mac_addr, freq,
-				     &context);
+				     cookie);
 
 	if (sme_status != QDF_STATUS_SUCCESS) {
 		hdd_err("Unable to set random mac");
 	} else {
-		rc = wait_for_completion_timeout(&context.random_mac_completion,
-				msecs_to_jiffies(WLAN_WAIT_TIME_SET_RND));
-		if (!rc)
+		rc = hdd_request_wait_for_response(request);
+		if (rc) {
 			hdd_err("SME timed out while setting random mac");
+		} else {
+			priv = hdd_request_priv(request);
+			status = priv->set_random_addr;
+		}
 	}
 
-	spin_lock(&hdd_context_lock);
-	context.magic = 0;
-	status = context.set_random_addr;
-	spin_unlock(&hdd_context_lock);
-
+	hdd_request_put(request);
 	EXIT();
+
 	return status;
 }
 
diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_stats.c b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_stats.c
index c8d1d45..b9f52a1 100644
--- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_stats.c
+++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_stats.c
@@ -34,6 +34,7 @@
 #include "hif.h"
 #include "wlan_hdd_hostapd.h"
 #include "wlan_hdd_debugfs_llstat.h"
+#include "wlan_hdd_request_manager.h"
 #include "wma_api.h"
 #include "wma.h"
 
@@ -3794,77 +3795,58 @@
 			flags);
 }
 
+struct peer_info_priv {
+	struct sir_peer_sta_ext_info peer_sta_ext_info;
+};
+
 /**
  * wlan_hdd_get_peer_info_cb() - get peer info callback
  * @sta_info: pointer of peer information
  * @context: get peer info callback context
  *
- * This function will fill stats info of AP Context
+ * This function will fill stats info to peer info priv
  *
  */
 static void wlan_hdd_get_peer_info_cb(struct sir_peer_info_ext_resp *sta_info,
-		void *context)
+				      void *context)
 {
-	struct statsContext *get_peer_info_context;
-	struct sir_peer_info_ext *peer_info;
-	hdd_adapter_t *adapter;
-	hdd_ap_ctx_t *ap_ctx;
+	struct hdd_request *request;
+	struct peer_info_priv *priv;
+	uint8_t sta_num;
 
-	if ((sta_info == NULL) || (context == NULL)) {
-		hdd_err("Bad param, sta_info [%pK] context [%pK]",
-			sta_info, context);
-		return;
-	}
-
-	spin_lock(&hdd_context_lock);
-	/*
-	 * there is a race condition that exists between this callback
-	 * function and the caller since the caller could time out either
-	 * before or while this code is executing.  we use a spinlock to
-	 * serialize these actions
-	 */
-	get_peer_info_context = context;
-	if (PEER_INFO_CONTEXT_MAGIC !=
-			get_peer_info_context->magic) {
-		/*
-		 * the caller presumably timed out so there is nothing
-		 * we can do
-		 */
-		spin_unlock(&hdd_context_lock);
-		hdd_warn("Invalid context, magic [%08x]",
-			get_peer_info_context->magic);
+	if (!sta_info) {
+		hdd_err("Bad param, sta_info [%pK]",
+			sta_info);
 		return;
 	}
 
 	if (!sta_info->count) {
-		spin_unlock(&hdd_context_lock);
 		hdd_err("Fail to get remote peer info");
 		return;
 	}
 
-	adapter = get_peer_info_context->pAdapter;
-	ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
-	qdf_mem_zero(&ap_ctx->txrx_stats,
-			sizeof(ap_ctx->txrx_stats));
+	if (sta_info->count > MAX_PEER_STA) {
+		hdd_warn("Exceed max peer number %d", sta_info->count);
+		sta_num = MAX_PEER_STA;
+	} else {
+		sta_num = sta_info->count;
+	}
 
-	peer_info = sta_info->info;
-	ap_ctx->txrx_stats.tx_packets = peer_info->tx_packets;
-	ap_ctx->txrx_stats.tx_bytes = peer_info->tx_bytes;
-	ap_ctx->txrx_stats.rx_packets = peer_info->rx_packets;
-	ap_ctx->txrx_stats.rx_bytes = peer_info->rx_bytes;
-	ap_ctx->txrx_stats.tx_retries = peer_info->tx_retries;
-	ap_ctx->txrx_stats.tx_failed = peer_info->tx_failed;
-	ap_ctx->txrx_stats.rssi =
-		peer_info->rssi + WLAN_HDD_TGT_NOISE_FLOOR_DBM;
-	wlan_hdd_fill_rate_info(ap_ctx, peer_info);
+	request = hdd_request_get(context);
+	if (!request) {
+		hdd_err("Obsolete request");
+		return;
+	}
 
-	get_peer_info_context->magic = 0;
+	priv = hdd_request_priv(request);
 
-	/* notify the caller */
-	complete(&get_peer_info_context->completion);
+	priv->peer_sta_ext_info.sta_num = sta_num;
+	qdf_mem_copy(&priv->peer_sta_ext_info.info,
+		     sta_info->info,
+		     sta_num * sizeof(sta_info->info[0]));
 
-	/* serialization is complete */
-	spin_unlock(&hdd_context_lock);
+	hdd_request_complete(request);
+	hdd_request_put(request);
 }
 
 /**
@@ -3880,54 +3862,77 @@
 					struct qdf_mac_addr macaddress)
 {
 	QDF_STATUS status;
+	void *cookie;
 	int ret;
-	static struct statsContext context;
+	hdd_ap_ctx_t *ap_ctx = NULL;
 	struct sir_peer_info_ext_req peer_info_req;
+	struct hdd_request *request;
+	struct peer_info_priv *priv;
+	static const struct hdd_request_params params = {
+		.priv_size = sizeof(*priv),
+		.timeout_ms = WLAN_WAIT_TIME_STATS,
+	};
 
-	if (adapter == NULL) {
-		hdd_err("pAdapter is NULL");
+	if (!adapter) {
+		hdd_err("adapter is NULL");
 		return -EFAULT;
 	}
 
-	init_completion(&context.completion);
-	context.magic = PEER_INFO_CONTEXT_MAGIC;
-	context.pAdapter = adapter;
+	request = hdd_request_alloc(&params);
+	if (!request) {
+		hdd_err("Request allocation failure");
+		return -ENOMEM;
+	}
 
-	qdf_mem_copy(&(peer_info_req.peer_macaddr), &macaddress,
-			QDF_MAC_ADDR_SIZE);
+	cookie = hdd_request_cookie(request);
+	priv = hdd_request_priv(request);
+
+	qdf_mem_copy(&peer_info_req.peer_macaddr, &macaddress,
+		     QDF_MAC_ADDR_SIZE);
 	peer_info_req.sessionid = adapter->sessionId;
 	peer_info_req.reset_after_request = 0;
 	status = sme_get_peer_info_ext(WLAN_HDD_GET_HAL_CTX(adapter),
-			&peer_info_req,
-			&context,
-			wlan_hdd_get_peer_info_cb);
+				       &peer_info_req,
+				       cookie,
+				       wlan_hdd_get_peer_info_cb);
 	if (status != QDF_STATUS_SUCCESS) {
 		hdd_err("Unable to retrieve statistics for peer info");
 		ret = -EFAULT;
 	} else {
-		if (!wait_for_completion_timeout(&context.completion,
-				msecs_to_jiffies(WLAN_WAIT_TIME_STATS))) {
+		ret = hdd_request_wait_for_response(request);
+		if (ret) {
 			hdd_err("SME timed out while retrieving peer info");
 			ret = -EFAULT;
-		} else
+		} else {
+			/* only support one peer by now */
+			ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
+			qdf_mem_zero(&ap_ctx->txrx_stats,
+				     sizeof(struct hdd_fw_txrx_stats));
+
+			ap_ctx->txrx_stats.tx_packets =
+				priv->peer_sta_ext_info.info[0].tx_packets;
+			ap_ctx->txrx_stats.tx_bytes =
+				priv->peer_sta_ext_info.info[0].tx_bytes;
+			ap_ctx->txrx_stats.rx_packets =
+				priv->peer_sta_ext_info.info[0].rx_packets;
+			ap_ctx->txrx_stats.rx_bytes =
+				priv->peer_sta_ext_info.info[0].rx_bytes;
+			ap_ctx->txrx_stats.tx_retries =
+				priv->peer_sta_ext_info.info[0].tx_retries;
+			ap_ctx->txrx_stats.tx_failed =
+				priv->peer_sta_ext_info.info[0].tx_failed;
+			ap_ctx->txrx_stats.rssi =
+				priv->peer_sta_ext_info.info[0].rssi +
+				WLAN_HDD_TGT_NOISE_FLOOR_DBM;
+			wlan_hdd_fill_rate_info(ap_ctx,
+				&priv->peer_sta_ext_info.info[0]);
 			ret = 0;
+
+		}
 	}
-	/*
-	 * either we never sent a request, we sent a request and received a
-	 * response or we sent a request and timed out.  if we never sent a
-	 * request or if we sent a request and got a response, we want to
-	 * clear the magic out of paranoia.  if we timed out there is a
-	 * race condition such that the callback function could be
-	 * executing at the same time we are. of primary concern is if the
-	 * callback function had already verified the "magic" but had not
-	 * yet set the completion variable when a timeout occurred. we
-	 * serialize these activities by invalidating the magic while
-	 * holding a shared spinlock which will cause us to block if the
-	 * callback is currently executing
-	 */
-	spin_lock(&hdd_context_lock);
-	context.magic = 0;
-	spin_unlock(&hdd_context_lock);
+
+	hdd_request_put(request);
+
 	return ret;
 }
 
@@ -4939,59 +4944,37 @@
 
 /**
  * wlan_hdd_get_rcpi_cb() - callback function for rcpi response
- * @context: Pointer to rcpi context
- * @rcpi_req: Pointer to rcpi response
+ * @context: used to refer cookie in hdd request manager
+ * @mac_addr: destination mac address for which RCPI is computed
+ * @rcpi: RCPI value from firmware
+ * @status: status of RCPI computation
  *
  * Return: None
  */
 static void wlan_hdd_get_rcpi_cb(void *context, struct qdf_mac_addr mac_addr,
 				 int32_t rcpi, QDF_STATUS status)
 {
-	hdd_adapter_t *adapter;
-	struct statsContext *rcpi_context;
+	struct hdd_request *request;
+	struct rcpi_info *priv;
 
-	if (!context) {
-		hdd_err("No rcpi context");
+	request = hdd_request_get(context);
+	if (!request) {
+		hdd_err("Obsolete RCPI request");
 		return;
 	}
 
-	rcpi_context = context;
-	adapter = rcpi_context->pAdapter;
-	if (adapter->magic != WLAN_HDD_ADAPTER_MAGIC) {
-		hdd_err("Invalid adapter magic");
-		return;
+	priv = hdd_request_priv(request);
+	priv->mac_addr = mac_addr;
+
+	if (!QDF_IS_STATUS_SUCCESS(status)) {
+		priv->rcpi = 0;
+		hdd_err("Error in computing RCPI");
+	} else {
+		priv->rcpi = rcpi;
 	}
 
-	/*
-	 * there is a race condition that exists between this callback
-	 * function and the caller since the caller could time out
-	 * either before or while this code is executing.  we use a
-	 * spinlock to serialize these actions
-	 */
-	spin_lock(&hdd_context_lock);
-	if (rcpi_context->magic != RCPI_CONTEXT_MAGIC) {
-		/*
-		 * the caller presumably timed out so there is nothing
-		 * we can do
-		 */
-		spin_unlock(&hdd_context_lock);
-		hdd_warn("Invalid RCPI context magic");
-		return;
-	}
-
-	rcpi_context->magic = 0;
-	adapter->rcpi.mac_addr = mac_addr;
-	if (status != QDF_STATUS_SUCCESS)
-		/* peer rcpi is not available for requested mac addr */
-		adapter->rcpi.rcpi = 0;
-	else
-		adapter->rcpi.rcpi = rcpi;
-
-	/* notify the caller */
-	complete(&rcpi_context->completion);
-
-	/* serialization is complete */
-	spin_unlock(&hdd_context_lock);
+	hdd_request_complete(request);
+	hdd_request_put(request);
 }
 
 /**
@@ -5009,12 +4992,17 @@
 			       enum rcpi_measurement_type measurement_type)
 {
 	hdd_context_t *hdd_ctx;
-	static struct statsContext rcpi_context;
-	int status = 0;
-	unsigned long rc;
+	int status = 0, ret = 0;
 	struct qdf_mac_addr mac_addr;
 	QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
 	struct sme_rcpi_req *rcpi_req;
+	void *cookie;
+	struct rcpi_info *priv;
+	struct hdd_request *request;
+	static const struct hdd_request_params params = {
+		.priv_size = sizeof(*priv),
+		.timeout_ms = WLAN_WAIT_TIME_RCPI,
+	};
 	bool reassoc;
 
 	ENTER();
@@ -5060,47 +5048,51 @@
 		return -EINVAL;
 	}
 
-	init_completion(&rcpi_context.completion);
-	rcpi_context.pAdapter = adapter;
-	rcpi_context.magic = RCPI_CONTEXT_MAGIC;
+	request = hdd_request_alloc(&params);
+	if (!request) {
+		hdd_err("Request allocation failure");
+		qdf_mem_free(rcpi_req);
+		return -ENOMEM;
+	}
+	cookie = hdd_request_cookie(request);
 
 	rcpi_req->mac_addr = mac_addr;
 	rcpi_req->session_id = adapter->sessionId;
 	rcpi_req->measurement_type = measurement_type;
 	rcpi_req->rcpi_callback = wlan_hdd_get_rcpi_cb;
-	rcpi_req->rcpi_context = &rcpi_context;
+	rcpi_req->rcpi_context = cookie;
 
 	qdf_status = sme_get_rcpi(hdd_ctx->hHal, rcpi_req);
-	if (qdf_status != QDF_STATUS_SUCCESS) {
+	if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
 		hdd_err("Unable to retrieve RCPI");
 		status = qdf_status_to_os_return(qdf_status);
-	} else {
-		/* request was sent -- wait for the response */
-		rc = wait_for_completion_timeout(&rcpi_context.completion,
-					msecs_to_jiffies(WLAN_WAIT_TIME_RCPI));
-		if (!rc) {
-			hdd_err("SME timed out while retrieving RCPI");
-			status = -EINVAL;
-		}
+		goto out;
 	}
+
+	/* request was sent -- wait for the response */
+	ret = hdd_request_wait_for_response(request);
+	if (ret) {
+		hdd_err("SME timed out while retrieving RCPI");
+		status = -EINVAL;
+		goto out;
+	}
+
+	/* update the adapter with the fresh results */
+	priv = hdd_request_priv(request);
+	adapter->rcpi.mac_addr = priv->mac_addr;
+	adapter->rcpi.rcpi = priv->rcpi;
+
+	if (qdf_mem_cmp(&mac_addr, &priv->mac_addr, sizeof(mac_addr))) {
+		hdd_err("mis match of mac addr from call-back");
+		status = -EINVAL;
+		goto out;
+	}
+
+	*rcpi_value = adapter->rcpi.rcpi;
+	hdd_debug("RCPI = %d", *rcpi_value);
+out:
 	qdf_mem_free(rcpi_req);
-
-	spin_lock(&hdd_context_lock);
-	rcpi_context.magic = 0;
-	spin_unlock(&hdd_context_lock);
-
-	if (status) {
-		hdd_err("rcpi computation is failed");
-	} else {
-		if (qdf_mem_cmp(&mac_addr, &adapter->rcpi.mac_addr,
-		    sizeof(mac_addr))) {
-			hdd_err("mac addr is not matching from call-back");
-			status = -EINVAL;
-		} else {
-			*rcpi_value = adapter->rcpi.rcpi;
-			hdd_debug("RCPI = %d", *rcpi_value);
-		}
-	}
+	hdd_request_put(request);
 
 	EXIT();
 	return status;
diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_wext.c b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_wext.c
index a384cab..aeadc0f 100644
--- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_wext.c
+++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_wext.c
@@ -52,6 +52,7 @@
 #include <wlan_hdd_wmm.h>
 #include "utils_api.h"
 #include "wlan_hdd_p2p.h"
+#include "wlan_hdd_request_manager.h"
 #ifdef FEATURE_WLAN_TDLS
 #include "wlan_hdd_tdls.h"
 #endif
@@ -94,6 +95,7 @@
 #include "wlan_hdd_lro.h"
 #include "cds_utils.h"
 #include "wlan_hdd_packet_filter_api.h"
+#include "wlan_hdd_request_manager.h"
 
 #define HDD_FINISH_ULA_TIME_OUT         800
 #define HDD_SET_MCBC_FILTERS_TO_FW      1
@@ -3448,129 +3450,37 @@
 	return rsnType;
 }
 
+struct rssi_priv {
+	int8_t rssi;
+};
+
 /**
  * hdd_get_rssi_cb() - "Get RSSI" callback function
  * @rssi: Current RSSI of the station
- * @staId: ID of the station
- * @pContext: opaque context originally passed to SME.  HDD always passes
+ * @sta_id: ID of the station
+ * @context: opaque context originally passed to SME.  HDD always passes
  *	a &struct statsContext
  *
  * Return: None
  */
-static void hdd_get_rssi_cb(int8_t rssi, uint32_t staId, void *pContext)
+static void hdd_get_rssi_cb(int8_t rssi, uint32_t sta_id, void *context)
 {
-	struct statsContext *pStatsContext;
-	hdd_adapter_t *pAdapter;
-	hdd_station_ctx_t *pHddStaCtx;
+	struct hdd_request *request;
+	struct rssi_priv *priv;
 
-	if (NULL == pContext) {
-		hdd_err("Bad param");
+	hdd_info("%s: rssi [%d] sta_id [%d] context [%pK]\n",
+		 __func__, (int)rssi, (int)sta_id, context);
+
+	request = hdd_request_get(context);
+	if (!request) {
+		hdd_err("%s: Obsolete request", __func__);
 		return;
 	}
 
-	pStatsContext = pContext;
-	pAdapter = pStatsContext->pAdapter;
-
-	if (!pAdapter) {
-		hdd_err("Invalid pAdapter");
-		return;
-	}
-
-	pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
-
-	pAdapter->rssi = rssi;
-
-	/* for new connection there might be no valid previous RSSI
-	 * Do not keep hdd_get_rssi_snr_by_bssid under spin_lock
-	 * because it accesses scan cache in pMac which is mutex
-	 * protected
-	 */
-	if (!pAdapter->rssi)
-		hdd_get_rssi_snr_by_bssid(pAdapter,
-			pHddStaCtx->conn_info.bssId.bytes,
-			&pAdapter->rssi, NULL);
-
-
-	/* there is a race condition that exists between this callback
-	 * function and the caller since the caller could time out
-	 * either before or while this code is executing.  we use a
-	 * spinlock to serialize these actions
-	 */
-	spin_lock(&hdd_context_lock);
-
-	if (pStatsContext->magic != PEER_INFO_CONTEXT_MAGIC) {
-		/* the caller presumably timed out so there is nothing
-		 * we can do
-		 */
-		spin_unlock(&hdd_context_lock);
-		hdd_warn("Invalid context, magic [%08x]",
-				pStatsContext->magic);
-		return;
-	}
-
-	/* context is valid so caller is still waiting */
-
-	/* paranoia: invalidate the magic */
-	pStatsContext->magic = 0;
-	/* notify the caller */
-	complete(&pStatsContext->completion);
-
-	/* serialization is complete */
-	spin_unlock(&hdd_context_lock);
-}
-
-/**
- * hdd_get_snr_cb() - "Get SNR" callback function
- * @snr: Current SNR of the station
- * @staId: ID of the station
- * @pContext: opaque context originally passed to SME.  HDD always passes
- *	a &struct statsContext
- *
- * Return: None
- */
-static void hdd_get_snr_cb(int8_t snr, uint32_t staId, void *pContext)
-{
-	struct statsContext *pStatsContext;
-	hdd_adapter_t *pAdapter;
-
-	if (NULL == pContext) {
-		hdd_err("Bad param");
-		return;
-	}
-
-	pStatsContext = pContext;
-	pAdapter = pStatsContext->pAdapter;
-
-	/* there is a race condition that exists between this callback
-	 * function and the caller since the caller could time out
-	 * either before or while this code is executing.  we use a
-	 * spinlock to serialize these actions
-	 */
-	spin_lock(&hdd_context_lock);
-
-	if ((NULL == pAdapter) || (SNR_CONTEXT_MAGIC != pStatsContext->magic)) {
-		/* the caller presumably timed out so there is nothing
-		 * we can do
-		 */
-		spin_unlock(&hdd_context_lock);
-		hdd_warn("Invalid context, pAdapter [%pK] magic [%08x]",
-			 pAdapter, pStatsContext->magic);
-		return;
-	}
-
-	/* context is valid so caller is still waiting */
-
-	/* paranoia: invalidate the magic */
-	pStatsContext->magic = 0;
-
-	/* copy over the snr */
-	pAdapter->snr = snr;
-
-	/* notify the caller */
-	complete(&pStatsContext->completion);
-
-	/* serialization is complete */
-	spin_unlock(&hdd_context_lock);
+	priv = hdd_request_priv(request);
+	priv->rssi = rssi;
+	hdd_request_complete(request);
+	hdd_request_put(request);
 }
 
 /**
@@ -3582,11 +3492,17 @@
  */
 QDF_STATUS wlan_hdd_get_rssi(hdd_adapter_t *pAdapter, int8_t *rssi_value)
 {
-	static struct statsContext context;
 	hdd_context_t *pHddCtx;
 	hdd_station_ctx_t *pHddStaCtx;
 	QDF_STATUS hstatus;
-	unsigned long rc;
+	int ret;
+	void *cookie;
+	struct hdd_request *request;
+	struct rssi_priv *priv;
+	static const struct hdd_request_params params = {
+		.priv_size = sizeof(*priv),
+		.timeout_ms = WLAN_WAIT_TIME_STATS,
+	};
 
 	if (NULL == pAdapter) {
 		hdd_err("Invalid context, pAdapter");
@@ -3616,44 +3532,52 @@
 		return QDF_STATUS_SUCCESS;
 	}
 
-	init_completion(&context.completion);
-	context.pAdapter = pAdapter;
-	context.magic = PEER_INFO_CONTEXT_MAGIC;
+	request = hdd_request_alloc(&params);
+	if (!request) {
+		hdd_err("%s: Request allocation failure, return cached RSSI",
+			__func__);
+		*rssi_value = pAdapter->rssi;
+		return QDF_STATUS_SUCCESS;
+	}
+	cookie = hdd_request_cookie(request);
 
 	hstatus = sme_get_rssi(pHddCtx->hHal, hdd_get_rssi_cb,
 			       pHddStaCtx->conn_info.staId[0],
 			       pHddStaCtx->conn_info.bssId, pAdapter->rssi,
-			       &context, pHddCtx->pcds_context);
+			       cookie, pHddCtx->pcds_context);
 	if (QDF_STATUS_SUCCESS != hstatus) {
 		hdd_err("Unable to retrieve RSSI");
 		/* we'll returned a cached value below */
 	} else {
 		/* request was sent -- wait for the response */
-		rc = wait_for_completion_timeout(&context.completion,
-						 msecs_to_jiffies
-							 (WLAN_WAIT_TIME_STATS));
-		if (!rc) {
-			hdd_err("SME timed out while retrieving RSSI");
-			/* we'll now returned a cached value below */
+		ret = hdd_request_wait_for_response(request);
+		if (ret) {
+			hdd_warn("SME timed out while retrieving RSSI");
+			/* we'll returned a cached value below */
+		} else {
+			/* update the adapter with the fresh results */
+			priv = hdd_request_priv(request);
+
+			pAdapter->rssi = priv->rssi;
+
+			/*
+			 * for new connection there might be no valid previous
+			 * RSSI.
+			 */
+			if (!pAdapter->rssi) {
+				hdd_get_rssi_snr_by_bssid(pAdapter,
+					pHddStaCtx->conn_info.bssId.bytes,
+					&pAdapter->rssi, NULL);
+			}
 		}
 	}
 
-	/* either we never sent a request, we sent a request and
-	 * received a response or we sent a request and timed out.  if
-	 * we never sent a request or if we sent a request and got a
-	 * response, we want to clear the magic out of paranoia.  if
-	 * we timed out there is a race condition such that the
-	 * callback function could be executing at the same time we
-	 * are. of primary concern is if the callback function had
-	 * already verified the "magic" but had not yet set the
-	 * completion variable when a timeout occurred. we serialize
-	 * these activities by invalidating the magic while holding a
-	 * shared spinlock which will cause us to block if the
-	 * callback is currently executing
+	/*
+	 * either we never sent a request, we sent a request and
+	 * received a response or we sent a request and timed out.
+	 * regardless we are done with the request.
 	 */
-	spin_lock(&hdd_context_lock);
-	context.magic = 0;
-	spin_unlock(&hdd_context_lock);
+	hdd_request_put(request);
 
 	*rssi_value = pAdapter->rssi;
 	hdd_debug("RSSI = %d", *rssi_value);
@@ -3661,6 +3585,40 @@
 	return QDF_STATUS_SUCCESS;
 }
 
+struct snr_priv {
+	int8_t snr;
+};
+
+/**
+ * hdd_get_snr_cb() - "Get SNR" callback function
+ * @snr: Current SNR of the station
+ * @sta_id: ID of the station
+ * @context: opaque context originally passed to SME.  HDD always passes
+ *	     a cookie for the request context
+ *
+ * Return: None
+ */
+static void hdd_get_snr_cb(int8_t snr, uint32_t sta_id, void *context)
+{
+	struct hdd_request *request;
+	struct snr_priv *priv;
+
+	hdd_info("%s: snr [%d] sta_id [%d] context [%pK]\n",
+		 __func__, (int)snr, (int)sta_id, context);
+
+	request = hdd_request_get(context);
+	if (!request) {
+		hdd_err("%s: Obsolete request", __func__);
+		return;
+	}
+
+	/* propagate response back to requesting thread */
+	priv = hdd_request_priv(request);
+	priv->snr = snr;
+	hdd_request_complete(request);
+	hdd_request_put(request);
+}
+
 /**
  * wlan_hdd_get_snr() - Get the current SNR
  * @pAdapter: adapter upon which the measurement is requested
@@ -3670,12 +3628,18 @@
  */
 QDF_STATUS wlan_hdd_get_snr(hdd_adapter_t *pAdapter, int8_t *snr)
 {
-	static struct statsContext context;
 	hdd_context_t *pHddCtx;
 	hdd_station_ctx_t *pHddStaCtx;
 	QDF_STATUS hstatus;
-	unsigned long rc;
 	int valid;
+	int ret;
+	void *cookie;
+	struct hdd_request *request;
+	struct snr_priv *priv;
+	static const struct hdd_request_params params = {
+		.priv_size = sizeof(*priv),
+		.timeout_ms = WLAN_WAIT_TIME_STATS,
+	};
 
 	ENTER();
 
@@ -3692,182 +3656,130 @@
 
 	pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
 
-	init_completion(&context.completion);
-	context.pAdapter = pAdapter;
-	context.magic = SNR_CONTEXT_MAGIC;
+	request = hdd_request_alloc(&params);
+	if (!request) {
+		hdd_err("%s: Request allocation failure", __func__);
+		return QDF_STATUS_E_FAULT;
+	}
+	cookie = hdd_request_cookie(request);
 
 	hstatus = sme_get_snr(pHddCtx->hHal, hdd_get_snr_cb,
 			      pHddStaCtx->conn_info.staId[0],
-			      pHddStaCtx->conn_info.bssId, &context);
+			      pHddStaCtx->conn_info.bssId, cookie);
 	if (QDF_STATUS_SUCCESS != hstatus) {
 		hdd_err("Unable to retrieve RSSI");
 		/* we'll returned a cached value below */
 	} else {
 		/* request was sent -- wait for the response */
-		rc = wait_for_completion_timeout(&context.completion,
-						 msecs_to_jiffies
-							 (WLAN_WAIT_TIME_STATS));
-		if (!rc) {
+		ret = hdd_request_wait_for_response(request);
+		if (ret) {
 			hdd_err("SME timed out while retrieving SNR");
 			/* we'll now returned a cached value below */
+		} else {
+			/* update the adapter with the fresh results */
+			priv = hdd_request_priv(request);
+			pAdapter->snr = priv->snr;
 		}
 	}
 
-	/* either we never sent a request, we sent a request and
-	 * received a response or we sent a request and timed out.  if
-	 * we never sent a request or if we sent a request and got a
-	 * response, we want to clear the magic out of paranoia.  if
-	 * we timed out there is a race condition such that the
-	 * callback function could be executing at the same time we
-	 * are. of primary concern is if the callback function had
-	 * already verified the "magic" but had not yet set the
-	 * completion variable when a timeout occurred. we serialize
-	 * these activities by invalidating the magic while holding a
-	 * shared spinlock which will cause us to block if the
-	 * callback is currently executing
+	/*
+	 * either we never sent a request, we sent a request and
+	 * received a response or we sent a request and timed out.
+	 * regardless we are done with the request.
 	 */
-	spin_lock(&hdd_context_lock);
-	context.magic = 0;
-	spin_unlock(&hdd_context_lock);
+	hdd_request_put(request);
 
 	*snr = pAdapter->snr;
 	EXIT();
 	return QDF_STATUS_SUCCESS;
 }
 
-/**
- * hdd_get_link_speed_cb() - Get link speed callback function
- * @pLinkSpeed: pointer to the link speed record
- * @pContext: pointer to the user context passed to SME
- *
- * This function is passed as the callback function to
- * sme_get_link_speed() by wlan_hdd_get_linkspeed_for_peermac().  By
- * agreement a &struct linkspeedContext is passed as @pContext.  If
- * the context is valid, then the contents of @pLinkSpeed are copied
- * into the adapter record referenced by @pContext where they can be
- * subsequently retrieved.  If the context is invalid, then this
- * function does nothing since it is assumed the caller has already
- * timed-out and destroyed the context.
- *
- * Return: None.
- */
+struct linkspeed_priv {
+	tSirLinkSpeedInfo linkspeed_info;
+};
+
 static void
-hdd_get_link_speed_cb(tSirLinkSpeedInfo *pLinkSpeed, void *pContext)
+hdd_get_link_speed_cb(tSirLinkSpeedInfo *linkspeed_info, void *context)
 {
-	struct linkspeedContext *pLinkSpeedContext;
-	hdd_adapter_t *pAdapter;
+	struct hdd_request *request;
+	struct linkspeed_priv *priv;
 
-	if ((NULL == pLinkSpeed) || (NULL == pContext)) {
-		hdd_err("Bad param, pLinkSpeed [%pK] pContext [%pK]",
-			pLinkSpeed, pContext);
-		return;
-	}
-	spin_lock(&hdd_context_lock);
-	pLinkSpeedContext = pContext;
-	pAdapter = pLinkSpeedContext->pAdapter;
-
-	/* there is a race condition that exists between this callback
-	 * function and the caller since the caller could time out either
-	 * before or while this code is executing.  we use a spinlock to
-	 * serialize these actions
-	 */
-
-	if ((NULL == pAdapter) ||
-	    (LINK_CONTEXT_MAGIC != pLinkSpeedContext->magic)) {
-		/* the caller presumably timed out so there is nothing
-		 * we can do
-		 */
-		spin_unlock(&hdd_context_lock);
-		hdd_warn("Invalid context, pAdapter [%pK] magic [%08x]",
-			 pAdapter, pLinkSpeedContext->magic);
+	if (!linkspeed_info) {
+		hdd_err("NULL linkspeed");
 		return;
 	}
 
-	/* context is valid so caller is still waiting */
+	request = hdd_request_get(context);
+	if (!request) {
+		hdd_err("Obsolete request");
+		return;
+	}
 
-	/* paranoia: invalidate the magic */
-	pLinkSpeedContext->magic = 0;
-
-	/* copy over the stats. do so as a struct copy */
-	pAdapter->ls_stats = *pLinkSpeed;
-
-	/* notify the caller */
-	complete(&pLinkSpeedContext->completion);
-
-	/* serialization is complete */
-	spin_unlock(&hdd_context_lock);
+	priv = hdd_request_priv(request);
+	priv->linkspeed_info = *linkspeed_info;
+	hdd_request_complete(request);
+	hdd_request_put(request);
 }
 
-/**
- * wlan_hdd_get_linkspeed_for_peermac() - Get link speed for a peer
- * @pAdapter: adapter upon which the peer is active
- * @macAddress: MAC address of the peer
- *
- * This function will send a query to SME for the linkspeed of the
- * given peer, and then wait for the callback to be invoked.
- *
- * Return: Errno
- */
-int wlan_hdd_get_linkspeed_for_peermac(hdd_adapter_t *pAdapter,
-				       struct qdf_mac_addr macAddress)
+int wlan_hdd_get_linkspeed_for_peermac(hdd_adapter_t *adapter,
+				       struct qdf_mac_addr *mac_address,
+				       uint32_t *linkspeed)
 {
+	int ret;
 	QDF_STATUS status;
-	int errno;
-	unsigned long rc;
-	static struct linkspeedContext context;
-	tSirLinkSpeedInfo *linkspeed_req;
+	void *cookie;
+	tSirLinkSpeedInfo *linkspeed_info;
+	struct hdd_request *request;
+	struct linkspeed_priv *priv;
+	static const struct hdd_request_params params = {
+		.priv_size = sizeof(*priv),
+		.timeout_ms = WLAN_WAIT_TIME_STATS,
+	};
 
-	if (NULL == pAdapter) {
-		hdd_err("pAdapter is NULL");
+	if ((!adapter) || (!linkspeed)) {
+		hdd_err("NULL argument");
 		return -EINVAL;
 	}
 
-	linkspeed_req = qdf_mem_malloc(sizeof(*linkspeed_req));
-	if (NULL == linkspeed_req) {
-		hdd_err("Request Buffer Alloc Fail");
-		return -ENOMEM;
+	request = hdd_request_alloc(&params);
+	if (!request) {
+		hdd_err("Request allocation failure");
+		ret = -ENOMEM;
+		goto return_cached_value;
 	}
 
-	init_completion(&context.completion);
-	context.pAdapter = pAdapter;
-	context.magic = LINK_CONTEXT_MAGIC;
+	cookie = hdd_request_cookie(request);
+	priv = hdd_request_priv(request);
 
-	qdf_copy_macaddr(&linkspeed_req->peer_macaddr, &macAddress);
-	status = sme_get_link_speed(WLAN_HDD_GET_HAL_CTX(pAdapter),
-				    linkspeed_req,
-				    &context, hdd_get_link_speed_cb);
-	qdf_mem_free(linkspeed_req);
-	errno = qdf_status_to_os_return(status);
-	if (errno) {
+	linkspeed_info = &priv->linkspeed_info;
+	qdf_copy_macaddr(&linkspeed_info->peer_macaddr, mac_address);
+	status = sme_get_link_speed(WLAN_HDD_GET_HAL_CTX(adapter),
+				    linkspeed_info,
+				    cookie, hdd_get_link_speed_cb);
+	if (QDF_IS_STATUS_ERROR(status)) {
 		hdd_err("Unable to retrieve statistics for link speed");
-	} else {
-		rc = wait_for_completion_timeout
-			(&context.completion,
-			 msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
-		if (!rc) {
-			hdd_err("SME timed out while retrieving link speed");
-			errno = -ETIMEDOUT;
-		}
+		ret = qdf_status_to_os_return(status);
+		goto cleanup;
 	}
+	ret = hdd_request_wait_for_response(request);
+	if (ret) {
+		hdd_err("SME timed out while retrieving link speed");
+		goto cleanup;
+	}
+	adapter->estimated_linkspeed = linkspeed_info->estLinkSpeed;
 
-	/* either we never sent a request, we sent a request and
-	 * received a response or we sent a request and timed out.  if
-	 * we never sent a request or if we sent a request and got a
-	 * response, we want to clear the magic out of paranoia.  if
-	 * we timed out there is a race condition such that the
-	 * callback function could be executing at the same time we
-	 * are. of primary concern is if the callback function had
-	 * already verified the "magic" but had not yet set the
-	 * completion variable when a timeout occurred. we serialize
-	 * these activities by invalidating the magic while holding a
-	 * shared spinlock which will cause us to block if the
-	 * callback is currently executing
+cleanup:
+	/*
+	 * either we never sent a request, we sent a request and
+	 * received a response or we sent a request and timed out.
+	 * regardless we are done with the request.
 	 */
-	spin_lock(&hdd_context_lock);
-	context.magic = 0;
-	spin_unlock(&hdd_context_lock);
+	hdd_request_put(request);
 
-	return errno;
+return_cached_value:
+	*linkspeed = adapter->estimated_linkspeed;
+
+	return ret;
 }
 
 /**
@@ -3908,12 +3820,12 @@
 
 		qdf_copy_macaddr(&bssid, &hdd_stactx->conn_info.bssId);
 
-		errno = wlan_hdd_get_linkspeed_for_peermac(sta_adapter, bssid);
+		errno = wlan_hdd_get_linkspeed_for_peermac(sta_adapter, &bssid,
+							   link_speed);
 		if (errno) {
 			hdd_err("Unable to retrieve SME linkspeed: %d", errno);
 			return errno;
 		}
-		*link_speed = sta_adapter->ls_stats.estLinkSpeed;
 		/* linkspeed in units of 500 kbps */
 		*link_speed = (*link_speed) / 500;
 	}
@@ -3921,6 +3833,10 @@
 	return 0;
 }
 
+struct peer_rssi_priv {
+	struct sir_peer_sta_info peer_sta_info;
+};
+
 /**
  * hdd_get_peer_rssi_cb() - get peer station's rssi callback
  * @sta_rssi: pointer of peer information
@@ -3933,72 +3849,41 @@
 static void hdd_get_peer_rssi_cb(struct sir_peer_info_resp *sta_rssi,
 							void *context)
 {
-	struct statsContext *get_rssi_context;
+	struct hdd_request *request;
 	struct sir_peer_info *rssi_info;
-	uint8_t peer_num, i;
-	hdd_adapter_t *padapter;
-	hdd_station_info_t *stainfo;
+	struct peer_rssi_priv *priv;
+	uint8_t peer_num;
 
-	if ((sta_rssi == NULL) || (context == NULL)) {
-		hdd_err("Bad param, sta_rssi [%pK] context [%pK]",
-			sta_rssi, context);
+	if (sta_rssi == NULL) {
+		hdd_err("Bad param, sta_rssi [%pK]", sta_rssi);
 		return;
 	}
 
-	spin_lock(&hdd_context_lock);
-	/*
-	 * there is a race condition that exists between this callback
-	 * function and the caller since the caller could time out either
-	 * before or while this code is executing.  we use a spinlock to
-	 * serialize these actions
-	 */
-	get_rssi_context = (struct statsContext *)context;
-	padapter = get_rssi_context->pAdapter;
-	if (get_rssi_context->magic != PEER_INFO_CONTEXT_MAGIC ||
-	    !padapter) {
-		/*
-		 * the caller presumably timed out so there is nothing
-		 * we can do
-		 */
-		spin_unlock(&hdd_context_lock);
-		hdd_warn("Invalid context, magic [%08x], adapter [%pK]",
-			get_rssi_context->magic, padapter);
+	request = hdd_request_get(context);
+	if (!request) {
+		hdd_err("Obsolete request.");
 		return;
 	}
 
+	priv = hdd_request_priv(request);
+
 	peer_num = sta_rssi->count;
 	rssi_info = sta_rssi->info;
-	get_rssi_context->magic = 0;
 
 	hdd_debug("%d peers", peer_num);
 
 	if (peer_num > MAX_PEER_STA) {
-		hdd_warn("Exceed max peer sta to handle one time %d", peer_num);
+		hdd_warn("Exceed max peer sta to handle one time %d",
+			 peer_num);
 		peer_num = MAX_PEER_STA;
 	}
 
-	qdf_mem_copy(padapter->peer_sta_info.info, rssi_info,
-		peer_num * sizeof(*rssi_info));
-	padapter->peer_sta_info.sta_num = peer_num;
+	qdf_mem_copy(priv->peer_sta_info.info, rssi_info,
+		     peer_num * sizeof(*rssi_info));
+	priv->peer_sta_info.sta_num = peer_num;
 
-	for (i = 0; i < peer_num; i++) {
-		stainfo = hdd_get_stainfo(padapter->cache_sta_info,
-					  rssi_info[i].peer_macaddr);
-		if (stainfo) {
-			stainfo->rssi = rssi_info[i].rssi;
-			stainfo->tx_rate = rssi_info[i].tx_rate;
-			stainfo->rx_rate = rssi_info[i].rx_rate;
-			hdd_info("rssi:%d tx_rate:%u rx_rate:%u %pM",
-				 stainfo->rssi, stainfo->tx_rate,
-				 stainfo->rx_rate, stainfo->macAddrSTA.bytes);
-		}
-	}
-
-	/* notify the caller */
-	complete(&get_rssi_context->completion);
-
-	/* serialization is complete */
-	spin_unlock(&hdd_context_lock);
+	hdd_request_complete(request);
+	hdd_request_put(request);
 }
 
 int wlan_hdd_get_peer_rssi(hdd_adapter_t *adapter,
@@ -4006,62 +3891,55 @@
 			   int request_source)
 {
 	QDF_STATUS status;
+	void *cookie;
 	int ret;
-	static struct statsContext context;
 	struct sir_peer_info_req rssi_req;
+	struct hdd_request *request;
+	struct peer_rssi_priv *priv;
+	static const struct hdd_request_params params = {
+		.priv_size = sizeof(*priv),
+		.timeout_ms = WLAN_WAIT_TIME_STATS,
+	};
 
 	if (!adapter || !macaddress) {
-		hdd_err("pAdapter [%pK], macaddress [%pK]", adapter, macaddress);
+		hdd_err("adapter [%pK], macaddress [%pK]",
+			adapter, macaddress);
 		return -EFAULT;
 	}
 
-	init_completion(&context.completion);
-	context.magic = PEER_INFO_CONTEXT_MAGIC;
-	context.pAdapter = adapter;
+	request = hdd_request_alloc(&params);
+	if (!request) {
+		hdd_err("Request allocation failure");
+		return -ENOMEM;
+	}
+
+	cookie = hdd_request_cookie(request);
 
 	qdf_mem_copy(&(rssi_req.peer_macaddr), macaddress,
-				QDF_MAC_ADDR_SIZE);
+		     QDF_MAC_ADDR_SIZE);
 	rssi_req.sessionid = adapter->sessionId;
 	status = sme_get_peer_info(WLAN_HDD_GET_HAL_CTX(adapter),
-				rssi_req,
-				&context,
-				hdd_get_peer_rssi_cb);
+				   rssi_req,
+				   cookie,
+				   hdd_get_peer_rssi_cb);
 	if (status != QDF_STATUS_SUCCESS) {
 		hdd_err("Unable to retrieve statistics for rssi");
 		ret = -EFAULT;
-	}
-
-	else if (request_source != HDD_WLAN_GET_PEER_RSSI_SOURCE_DRIVER) {
-		if (!wait_for_completion_timeout(&context.completion,
-				msecs_to_jiffies(WLAN_WAIT_TIME_STATS))) {
+	} else if (request_source != HDD_WLAN_GET_PEER_RSSI_SOURCE_DRIVER) {
+		ret = hdd_request_wait_for_response(request);
+		if (ret) {
 			hdd_err("SME timed out while retrieving rssi");
 			ret = -EFAULT;
 		} else {
+			priv = hdd_request_priv(request);
+			adapter->peer_sta_info = priv->peer_sta_info;
 			ret = 0;
 		}
-		goto set_magic;
 	} else {
 		ret = 0;
-		return ret;
 	}
-set_magic:
-	/*
-	 * either we never sent a request, we sent a request and received a
-	 * response or we sent a request and timed out.  if we never sent a
-	 * request or if we sent a request and got a response, we want to
-	 * clear the magic out of paranoia.  if we timed out there is a
-	 * race condition such that the callback function could be
-	 * executing at the same time we are. of primary concern is if the
-	 * callback function had already verified the "magic" but had not
-	 * yet set the completion variable when a timeout occurred. we
-	 * serialize these activities by invalidating the magic while
-	 * holding a shared spinlock which will cause us to block if the
-	 * callback is currently executing
-	 */
 
-	spin_lock(&hdd_context_lock);
-	context.magic = 0;
-	spin_unlock(&hdd_context_lock);
+	hdd_request_put(request);
 
 	return ret;
 }
@@ -6087,60 +5965,43 @@
 	return ret;
 }
 
+struct class_a_stats {
+	tCsrGlobalClassAStatsInfo class_a_stats;
+};
+
 /**
  * hdd_get_class_a_statistics_cb() - Get Class A stats callback function
- * @pStats: pointer to Class A stats
- * @pContext: user context originally registered with SME
+ * @stats: pointer to Class A stats
+ * @context: user context originally registered with SME (always the
+ *	cookie from the request context)
  *
  * Return: None
  */
-static void hdd_get_class_a_statistics_cb(void *pStats, void *pContext)
+static void hdd_get_class_a_statistics_cb(void *stats, void *context)
 {
-	struct statsContext *pStatsContext;
-	tCsrGlobalClassAStatsInfo *pClassAStats;
-	hdd_adapter_t *pAdapter;
+	struct hdd_request *request;
+	struct class_a_stats *priv;
+	tCsrGlobalClassAStatsInfo *returned_stats;
 
-	if ((NULL == pStats) || (NULL == pContext)) {
-		hdd_err("Bad param, pStats [%pK] pContext [%pK]",
-			pStats, pContext);
+	ENTER();
+	if ((NULL == stats) || (NULL == context)) {
+		hdd_err("Bad param, stats [%p] context [%p]",
+			stats, context);
 		return;
 	}
 
-	pClassAStats = pStats;
-	pStatsContext = pContext;
-	pAdapter = pStatsContext->pAdapter;
-
-	/* there is a race condition that exists between this callback
-	 * function and the caller since the caller could time out
-	 * either before or while this code is executing.  we use a
-	 * spinlock to serialize these actions
-	 */
-	spin_lock(&hdd_context_lock);
-
-	if ((NULL == pAdapter) ||
-	    (STATS_CONTEXT_MAGIC != pStatsContext->magic)) {
-		/* the caller presumably timed out so there is nothing
-		 * we can do
-		 */
-		spin_unlock(&hdd_context_lock);
-		hdd_warn("Invalid context, pAdapter [%pK] magic [%08x]",
-			 pAdapter, pStatsContext->magic);
+	request = hdd_request_get(context);
+	if (!request) {
+		hdd_err("Obsolete request");
 		return;
 	}
 
-	/* context is valid so caller is still waiting */
-
-	/* paranoia: invalidate the magic */
-	pStatsContext->magic = 0;
-
-	/* copy over the stats. do so as a struct copy */
-	pAdapter->hdd_stats.ClassA_stat = *pClassAStats;
-
-	/* notify the caller */
-	complete(&pStatsContext->completion);
-
-	/* serialization is complete */
-	spin_unlock(&hdd_context_lock);
+	returned_stats = stats;
+	priv = hdd_request_priv(request);
+	priv->class_a_stats = *returned_stats;
+	hdd_request_complete(request);
+	hdd_request_put(request);
+	EXIT();
 }
 
 /**
@@ -6153,8 +6014,14 @@
 {
 	hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
 	QDF_STATUS hstatus;
-	unsigned long rc;
-	static struct statsContext context;
+	int ret;
+	void *cookie;
+	struct hdd_request *request;
+	struct class_a_stats *priv;
+	static const struct hdd_request_params params = {
+		.priv_size = sizeof(*priv),
+		.timeout_ms = WLAN_WAIT_TIME_STATS,
+	};
 
 	if (NULL == pAdapter) {
 		hdd_err("pAdapter is NULL");
@@ -6166,10 +6033,13 @@
 		return QDF_STATUS_SUCCESS;
 	}
 
-	/* we are connected so prepare our callback context */
-	init_completion(&context.completion);
-	context.pAdapter = pAdapter;
-	context.magic = STATS_CONTEXT_MAGIC;
+	request = hdd_request_alloc(&params);
+	if (!request) {
+		hdd_err("Request allocation failure");
+		return QDF_STATUS_E_NOMEM;
+	}
+	cookie = hdd_request_cookie(request);
+
 	/* query only for Class A statistics (which include link speed) */
 	hstatus = sme_get_statistics(WLAN_HDD_GET_HAL_CTX(pAdapter),
 				     eCSR_HDD, SME_GLOBAL_CLASSA_STATS,
@@ -6177,100 +6047,80 @@
 				     0, /* not periodic */
 				     false, /* non-cached results */
 				     pHddStaCtx->conn_info.staId[0],
-				     &context, pAdapter->sessionId);
+				     cookie, pAdapter->sessionId);
 	if (QDF_STATUS_SUCCESS != hstatus) {
 		hdd_debug("Unable to retrieve Class A statistics");
-		/* we'll returned a cached value below */
-	} else {
-		/* request was sent -- wait for the response */
-		rc = wait_for_completion_timeout
-			(&context.completion,
-			 msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
-		if (!rc)
-			hdd_warn("SME timed out while retrieving Class A statistics");
+		goto return_cached_results;
+	}
+	/* request was sent -- wait for the response */
+	ret = hdd_request_wait_for_response(request);
+	if (ret) {
+		hdd_warn("SME timed out while retrieving Class A statistics");
+		goto return_cached_results;
 	}
 
-	/* either we never sent a request, we sent a request and
-	 * received a response or we sent a request and timed out.  if
-	 * we never sent a request or if we sent a request and got a
-	 * response, we want to clear the magic out of paranoia.  if
-	 * we timed out there is a race condition such that the
-	 * callback function could be executing at the same time we
-	 * are. of primary concern is if the callback function had
-	 * already verified the "magic" but had not yet set the
-	 * completion variable when a timeout occurred. we serialize
-	 * these activities by invalidating the magic while holding a
-	 * shared spinlock which will cause us to block if the
-	 * callback is currently executing
-	 */
-	spin_lock(&hdd_context_lock);
-	context.magic = 0;
-	spin_unlock(&hdd_context_lock);
+	/* update the adapter with the fresh results */
+	priv = hdd_request_priv(request);
+	pAdapter->hdd_stats.ClassA_stat = priv->class_a_stats;
 
-	/* either callback updated pAdapter stats or it has cached data */
+return_cached_results:
+	/*
+	 * either we never sent a request, we sent a request and
+	 * received a response or we sent a request and timed out.
+	 * regardless we are done with the request.
+	 */
+	hdd_request_put(request);
+
 	return QDF_STATUS_SUCCESS;
 }
 
+struct station_stats {
+	tCsrSummaryStatsInfo summary_stats;
+	tCsrGlobalClassAStatsInfo class_a_stats;
+	struct csr_per_chain_rssi_stats_info per_chain_rssi_stats;
+};
+
 /**
  * hdd_get_station_statistics_cb() - Get stats callback function
- * @pStats: pointer to Class A stats
- * @pContext: user context originally registered with SME
+ * @stats: pointer to combined station stats
+ * @context: user context originally registered with SME (always the
+ *	cookie from the request context)
  *
  * Return: None
  */
-static void hdd_get_station_statistics_cb(void *pStats, void *pContext)
+static void hdd_get_station_statistics_cb(void *stats, void *context)
 {
-	struct statsContext *pStatsContext;
-	tCsrSummaryStatsInfo *pSummaryStats;
-	tCsrGlobalClassAStatsInfo *pClassAStats;
+	struct hdd_request *request;
+	struct station_stats *priv;
+	tCsrSummaryStatsInfo *summary_stats;
+	tCsrGlobalClassAStatsInfo *class_a_stats;
 	struct csr_per_chain_rssi_stats_info *per_chain_rssi_stats;
-	hdd_adapter_t *pAdapter;
 
-	if ((NULL == pStats) || (NULL == pContext)) {
-		hdd_err("Bad param, pStats [%pK] pContext [%pK]",
-			pStats, pContext);
+	if ((NULL == stats) || (NULL == context)) {
+		hdd_err("Bad param, pStats [%p] pContext [%p]",
+			stats, context);
 		return;
 	}
 
-	/* there is a race condition that exists between this callback
-	 * function and the caller since the caller could time out
-	 * either before or while this code is executing.  we use a
-	 * spinlock to serialize these actions
-	 */
-	spin_lock(&hdd_context_lock);
+	request = hdd_request_get(context);
+	if (!request) {
+		hdd_err("Obsolete request");
+		return;
+	}
 
-	pSummaryStats = (tCsrSummaryStatsInfo *) pStats;
-	pClassAStats = (tCsrGlobalClassAStatsInfo *) (pSummaryStats + 1);
+	summary_stats = (tCsrSummaryStatsInfo *) stats;
+	class_a_stats = (tCsrGlobalClassAStatsInfo *) (summary_stats + 1);
 	per_chain_rssi_stats = (struct csr_per_chain_rssi_stats_info *)
-				(pClassAStats + 1);
-	pStatsContext = pContext;
-	pAdapter = pStatsContext->pAdapter;
-	if ((NULL == pAdapter) ||
-	    (STATS_CONTEXT_MAGIC != pStatsContext->magic)) {
-		/* the caller presumably timed out so there is nothing
-		 * we can do
-		 */
-		spin_unlock(&hdd_context_lock);
-		hdd_warn("Invalid context, pAdapter [%pK] magic [%08x]",
-			 pAdapter, pStatsContext->magic);
-		return;
-	}
-
-	/* context is valid so caller is still waiting */
-
-	/* paranoia: invalidate the magic */
-	pStatsContext->magic = 0;
+				(class_a_stats + 1);
+	priv = hdd_request_priv(request);
 
 	/* copy over the stats. do so as a struct copy */
-	pAdapter->hdd_stats.summary_stat = *pSummaryStats;
-	pAdapter->hdd_stats.ClassA_stat = *pClassAStats;
-	pAdapter->hdd_stats.per_chain_rssi_stats = *per_chain_rssi_stats;
+	priv->summary_stats = *summary_stats;
+	priv->class_a_stats = *class_a_stats;
+	priv->per_chain_rssi_stats = *per_chain_rssi_stats;
 
-	/* notify the caller */
-	complete(&pStatsContext->completion);
-
-	/* serialization is complete */
-	spin_unlock(&hdd_context_lock);
+	hdd_request_complete(request);
+	hdd_request_put(request);
 }
 
 /**
@@ -6283,18 +6133,26 @@
 {
 	hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
 	QDF_STATUS hstatus;
-	unsigned long rc;
-	static struct statsContext context;
+	int ret;
+	void *cookie;
+	struct hdd_request *request;
+	struct station_stats *priv;
+	static const struct hdd_request_params params = {
+		.priv_size = sizeof(*priv),
+		.timeout_ms = WLAN_WAIT_TIME_STATS,
+	};
 
 	if (NULL == pAdapter) {
 		hdd_err("pAdapter is NULL");
 		return QDF_STATUS_SUCCESS;
 	}
 
-	/* we are connected so prepare our callback context */
-	init_completion(&context.completion);
-	context.pAdapter = pAdapter;
-	context.magic = STATS_CONTEXT_MAGIC;
+	request = hdd_request_alloc(&params);
+	if (!request) {
+		hdd_err("Request allocation failure");
+		return QDF_STATUS_E_NOMEM;
+	}
+	cookie = hdd_request_cookie(request);
 
 	/* query only for Summary & Class A statistics */
 	hstatus = sme_get_statistics(WLAN_HDD_GET_HAL_CTX(pAdapter),
@@ -6306,36 +6164,32 @@
 				     0, /* not periodic */
 				     false, /* non-cached results */
 				     pHddStaCtx->conn_info.staId[0],
-				     &context, pAdapter->sessionId);
+				     cookie, pAdapter->sessionId);
 	if (QDF_STATUS_SUCCESS != hstatus) {
 		hdd_err("Unable to retrieve statistics");
 		/* we'll return with cached values */
 	} else {
 		/* request was sent -- wait for the response */
-		rc = wait_for_completion_timeout
-			(&context.completion,
-			 msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
-
-		if (!rc)
-			hdd_err("SME timed out while retrieving statistics");
+		ret = hdd_request_wait_for_response(request);
+		if (ret) {
+			hdd_warn("SME timed out while retrieving statistics");
+			/* we'll returned a cached value below */
+		} else {
+			/* update the adapter with the fresh results */
+			priv = hdd_request_priv(request);
+			pAdapter->hdd_stats.summary_stat = priv->summary_stats;
+			pAdapter->hdd_stats.ClassA_stat = priv->class_a_stats;
+			pAdapter->hdd_stats.per_chain_rssi_stats =
+				priv->per_chain_rssi_stats;
+		}
 	}
 
-	/* either we never sent a request, we sent a request and
-	 * received a response or we sent a request and timed out.  if
-	 * we never sent a request or if we sent a request and got a
-	 * response, we want to clear the magic out of paranoia.  if
-	 * we timed out there is a race condition such that the
-	 * callback function could be executing at the same time we
-	 * are. of primary concern is if the callback function had
-	 * already verified the "magic" but had not yet set the
-	 * completion variable when a timeout occurred. we serialize
-	 * these activities by invalidating the magic while holding a
-	 * shared spinlock which will cause us to block if the
-	 * callback is currently executing
+	/*
+	 * either we never sent a request, we sent a request and
+	 * received a response or we sent a request and timed out.
+	 * regardless we are done with the request.
 	 */
-	spin_lock(&hdd_context_lock);
-	context.magic = 0;
-	spin_unlock(&hdd_context_lock);
+	hdd_request_put(request);
 
 	/* either callback updated pAdapter stats or it has cached data */
 	return QDF_STATUS_SUCCESS;
@@ -7587,10 +7441,14 @@
 	return retval;
 }
 
+struct temperature_priv {
+	int temperature;
+};
+
 /**
  * hdd_get_temperature_cb() - "Get Temperature" callback function
  * @temperature: measured temperature
- * @pContext: callback context
+ * @context: callback context
  *
  * This function is passed to sme_get_temperature() as the callback
  * function to be invoked when the temperature measurement is
@@ -7598,30 +7456,24 @@
  *
  * Return: None
  */
-static void hdd_get_temperature_cb(int temperature, void *pContext)
+static void hdd_get_temperature_cb(int temperature, void *context)
 {
-	struct statsContext *pTempContext;
-	hdd_adapter_t *pAdapter;
+	struct hdd_request *request;
+	struct temperature_priv *priv;
 
 	ENTER();
-	if (NULL == pContext) {
-		hdd_err("pContext is NULL");
-		return;
-	}
-	pTempContext = pContext;
-	pAdapter = pTempContext->pAdapter;
-	spin_lock(&hdd_context_lock);
-	if ((NULL == pAdapter) || (TEMP_CONTEXT_MAGIC != pTempContext->magic)) {
-		spin_unlock(&hdd_context_lock);
-		hdd_warn("Invalid context, pAdapter [%pK] magic [%08x]",
-		       pAdapter, pTempContext->magic);
-		return;
-	}
-	if (temperature != 0)
-		pAdapter->temperature = temperature;
 
-	complete(&pTempContext->completion);
-	spin_unlock(&hdd_context_lock);
+	request = hdd_request_get(context);
+	if (!request) {
+		hdd_err("Obsolete request");
+		return;
+	}
+
+	priv = hdd_request_priv(request);
+	priv->temperature = temperature;
+	hdd_request_complete(request);
+	hdd_request_put(request);
+
 	EXIT();
 }
 
@@ -7634,35 +7486,54 @@
  * returned, otherwise a negative errno is returned.
  *
  */
-int wlan_hdd_get_temperature(hdd_adapter_t *pAdapter, int *temperature)
+int wlan_hdd_get_temperature(hdd_adapter_t *p_adapter, int *temperature)
 {
 	QDF_STATUS status;
-	static struct statsContext tempContext;
-	unsigned long rc;
+	int ret;
+	void *cookie;
+	struct hdd_request *request;
+	struct temperature_priv *priv;
+	static const struct hdd_request_params params = {
+		.priv_size = sizeof(*priv),
+		.timeout_ms = WLAN_WAIT_TIME_STATS,
+	};
 
 	ENTER();
-	if (NULL == pAdapter) {
+	if (!p_adapter) {
 		hdd_err("pAdapter is NULL");
 		return -EPERM;
 	}
-	init_completion(&tempContext.completion);
-	tempContext.pAdapter = pAdapter;
-	tempContext.magic = TEMP_CONTEXT_MAGIC;
-	status = sme_get_temperature(WLAN_HDD_GET_HAL_CTX(pAdapter),
-				     &tempContext, hdd_get_temperature_cb);
+
+	request = hdd_request_alloc(&params);
+	if (!request) {
+		hdd_err("Request allocation failure");
+		return -ENOMEM;
+	}
+	cookie = hdd_request_cookie(request);
+	status = sme_get_temperature(WLAN_HDD_GET_HAL_CTX(p_adapter),
+				     cookie, hdd_get_temperature_cb);
 	if (QDF_STATUS_SUCCESS != status) {
 		hdd_err("Unable to retrieve temperature");
 	} else {
-		rc = wait_for_completion_timeout(&tempContext.completion,
-						 msecs_to_jiffies
-							 (WLAN_WAIT_TIME_STATS));
-		if (!rc)
+		ret = hdd_request_wait_for_response(request);
+		if (ret) {
 			hdd_err("SME timed out while retrieving temperature");
+		} else {
+			/* update the adapter with the fresh results */
+			priv = hdd_request_priv(request);
+			if (priv->temperature)
+				p_adapter->temperature = priv->temperature;
+		}
 	}
-	spin_lock(&hdd_context_lock);
-	tempContext.magic = 0;
-	spin_unlock(&hdd_context_lock);
-	*temperature = pAdapter->temperature;
+
+	/*
+	 * either we never sent a request, we sent a request and
+	 * received a response or we sent a request and timed out.
+	 * regardless we are done with the request.
+	 */
+	hdd_request_put(request);
+
+	*temperature = p_adapter->temperature;
 	EXIT();
 	return 0;
 }
diff --git a/drivers/staging/qcacld-3.0/core/mac/inc/qwlan_version.h b/drivers/staging/qcacld-3.0/core/mac/inc/qwlan_version.h
index 13b0d49..7ed3f2e 100644
--- a/drivers/staging/qcacld-3.0/core/mac/inc/qwlan_version.h
+++ b/drivers/staging/qcacld-3.0/core/mac/inc/qwlan_version.h
@@ -41,9 +41,9 @@
 #define QWLAN_VERSION_MAJOR            5
 #define QWLAN_VERSION_MINOR            2
 #define QWLAN_VERSION_PATCH            1
-#define QWLAN_VERSION_EXTRA            "J"
+#define QWLAN_VERSION_EXTRA            "K"
 #define QWLAN_VERSION_BUILD            1
 
-#define QWLAN_VERSIONSTR               "5.2.1.1J.1"
+#define QWLAN_VERSIONSTR               "5.2.1.1K"
 
 #endif /* QWLAN_VERSION_H */
diff --git a/drivers/staging/qcacld-3.0/core/mac/inc/sir_api.h b/drivers/staging/qcacld-3.0/core/mac/inc/sir_api.h
index f797380..4212816 100644
--- a/drivers/staging/qcacld-3.0/core/mac/inc/sir_api.h
+++ b/drivers/staging/qcacld-3.0/core/mac/inc/sir_api.h
@@ -4549,6 +4549,17 @@
 	struct sir_peer_info info[MAX_PEER_STA];
 };
 
+/**
+ * @sta_num: number of peer station which has valid info
+ * @info: peer extended information
+ *
+ * all SAP peer station's extended information retrieved
+ */
+struct sir_peer_sta_ext_info {
+	uint8_t sta_num;
+	struct sir_peer_info_ext info[MAX_PEER_STA];
+};
+
 typedef struct sSirAddPeriodicTxPtrn {
 	/* MAC Address for the adapter */
 	struct qdf_mac_addr mac_address;
diff --git a/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_fils.c b/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_fils.c
index 57c2624..018dde3 100644
--- a/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_fils.c
+++ b/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_fils.c
@@ -349,6 +349,13 @@
 
 		pe_debug("tlv type %x len %u total %u",
 			tlv->type, tlv->length, data_len);
+
+		if (tlv->length > (data_len - 2)) {
+			pe_err("tlv len %d greater data_len %d",
+				tlv->length, data_len);
+			return 0;
+		}
+
 		switch (tlv->type) {
 		case SIR_FILS_EAP_TLV_KEYNAME_NAI:
 			auth_info->keyname = qdf_mem_malloc(tlv->length);
diff --git a/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_sme_req_messages.c
index dddffac..0c5681d 100644
--- a/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_sme_req_messages.c
+++ b/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_sme_req_messages.c
@@ -5808,8 +5808,18 @@
 		if (update_ie->append) {
 			/*
 			 * In case of append, allocate new memory
-			 * with combined length
+			 * with combined length.
+			 * Multiple back to back append commands
+			 * can lead to a huge length.So, check
+			 * for the validity of the length.
 			 */
+			if (addn_ie->probeRespDataLen >
+				(USHRT_MAX - update_ie->ieBufferlength)) {
+				pe_err("IE Length overflow, curr:%d, new:%d",
+					addn_ie->probeRespDataLen,
+					update_ie->ieBufferlength);
+				goto end;
+			}
 			new_length = update_ie->ieBufferlength +
 				addn_ie->probeRespDataLen;
 			new_ptr = qdf_mem_malloc(new_length);
diff --git a/drivers/staging/qcacld-3.0/core/mac/src/sys/legacy/src/utils/src/dot11f.c b/drivers/staging/qcacld-3.0/core/mac/src/sys/legacy/src/utils/src/dot11f.c
index e9d9713..4c83e58 100644
--- a/drivers/staging/qcacld-3.0/core/mac/src/sys/legacy/src/utils/src/dot11f.c
+++ b/drivers/staging/qcacld-3.0/core/mac/src/sys/legacy/src/utils/src/dot11f.c
@@ -344,7 +344,7 @@
 	pBufRemaining += len + 2;
 	len += 2;
 	while (len < nBuf) {
-		pIe = find_ie_defn(pCtx, pBufRemaining, nBuf + len, IEs);
+		pIe = find_ie_defn(pCtx, pBufRemaining, nBuf - len, IEs);
 		if (NULL == pIe)
 			break;
 		if (pIe->eid == pIeFirst->eid)
@@ -353,6 +353,8 @@
 		pBufRemaining += *(pBufRemaining + 1) + 2;
 	}
 
+	if ((len > 0xFF) || (len > nBuf))
+		return DOT11F_INTERNAL_ERROR;
 	*pnConsumed = len;
 	return DOT11F_PARSE_SUCCESS;
 
@@ -9984,11 +9986,15 @@
 		}
 
 		if (pIe) {
-			if (nBufRemaining < pIe->minSize - pIe->noui - 2U) {
-				FRAMES_LOG3(pCtx, FRLOGW, FRFL("The IE %s must be "
-					"at least %d bytes in size, but there are onl"
-					"y %d bytes remaining in this frame.\n"),
-					pIe->name, pIe->minSize, nBufRemaining);
+			if ((nBufRemaining < pIe->minSize - pIe->noui - 2U) ||
+			    (len < pIe->minSize - pIe->noui - 2U)) {
+				FRAMES_LOG4(pCtx, FRLOGW, FRFL("The IE %s must "
+					"be at least %d bytes in size, but "
+					"there are only %d bytes remaining in "
+					"this frame or the IE reports a size "
+					"of %d bytes.\n"),
+					pIe->name, pIe->minSize, nBufRemaining,
+					(len + pIe->noui + 2U));
 				FRAMES_DUMP(pCtx, FRLOG1, pBuf, nBuf);
 				status |= DOT11F_INCOMPLETE_IE;
 				FRAMES_DBG_BREAK();
diff --git a/drivers/staging/qcacld-3.0/core/mac/src/sys/legacy/src/utils/src/parser_api.c b/drivers/staging/qcacld-3.0/core/mac/src/sys/legacy/src/utils/src/parser_api.c
index 7e7d13d..d575705 100644
--- a/drivers/staging/qcacld-3.0/core/mac/src/sys/legacy/src/utils/src/parser_api.c
+++ b/drivers/staging/qcacld-3.0/core/mac/src/sys/legacy/src/utils/src/parser_api.c
@@ -2360,6 +2360,7 @@
 				 tDot11fIEfils_indication *fils_indication)
 {
 	uint8_t *data;
+	uint8_t remaining_data = fils_indication->num_variable_data;
 
 	data = fils_indication->variable_data;
 	fils_ind->is_present = true;
@@ -2372,18 +2373,37 @@
 	fils_ind->is_pk_auth_supported =
 			fils_indication->is_pk_auth_supported;
 	if (fils_indication->is_cache_id_present) {
+		if (remaining_data < SIR_CACHE_IDENTIFIER_LEN) {
+			pe_err("Failed to copy Cache Identifier, Invalid remaining data %d",
+				remaining_data);
+			return;
+		}
 		fils_ind->cache_identifier.is_present = true;
 		qdf_mem_copy(fils_ind->cache_identifier.identifier,
 				data, SIR_CACHE_IDENTIFIER_LEN);
 		data = data + SIR_CACHE_IDENTIFIER_LEN;
+		remaining_data = remaining_data - SIR_CACHE_IDENTIFIER_LEN;
 	}
 	if (fils_indication->is_hessid_present) {
+		if (remaining_data < SIR_HESSID_LEN) {
+			pe_err("Failed to copy HESSID, Invalid remaining data %d",
+				remaining_data);
+			return;
+		}
 		fils_ind->hessid.is_present = true;
 		qdf_mem_copy(fils_ind->hessid.hessid,
 				data, SIR_HESSID_LEN);
 		data = data + SIR_HESSID_LEN;
+		remaining_data = remaining_data - SIR_HESSID_LEN;
 	}
 	if (fils_indication->realm_identifiers_cnt) {
+		if (remaining_data < (fils_indication->realm_identifiers_cnt *
+		    SIR_REALM_LEN)) {
+			pe_err("Failed to copy Realm Identifier, Invalid remaining data %d realm_cnt %d",
+				remaining_data,
+				fils_indication->realm_identifiers_cnt);
+			return;
+		}
 		fils_ind->realm_identifier.is_present = true;
 		fils_ind->realm_identifier.realm_cnt =
 			fils_indication->realm_identifiers_cnt;
@@ -3173,8 +3193,7 @@
 		for (cnt = 0; cnt < ar->num_WMMTSPEC; cnt++) {
 			qdf_mem_copy(&pAssocRsp->TSPECInfo[cnt],
 					&ar->WMMTSPEC[cnt],
-					(sizeof(tDot11fIEWMMTSPEC) *
-					 ar->num_WMMTSPEC));
+					sizeof(tDot11fIEWMMTSPEC));
 		}
 		pAssocRsp->tspecPresent = true;
 	}
diff --git a/drivers/staging/qcacld-3.0/core/mac/src/sys/legacy/src/utils/src/utils_parser.c b/drivers/staging/qcacld-3.0/core/mac/src/sys/legacy/src/utils/src/utils_parser.c
index f8aa5659..26bf304 100644
--- a/drivers/staging/qcacld-3.0/core/mac/src/sys/legacy/src/utils/src/utils_parser.c
+++ b/drivers/staging/qcacld-3.0/core/mac/src/sys/legacy/src/utils/src/utils_parser.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -140,7 +140,7 @@
 {
 	/* This is awful, I know, but the old code just rammed the IE into */
 	/* an opaque array.  Note that we need to explicitly add the vendorIE and OUI ! */
-	uint8_t curAddIELen = pOld->length;
+	uint16_t curAddIELen = pOld->length;
 
 	pOld->length = curAddIELen + pNew->num_data + 6;
 	pOld->addIEdata[curAddIELen++] = 0xdd;
@@ -159,7 +159,7 @@
 {
 	/* This is awful, I know, but the old code just rammed the IE into */
 	/* an opaque array.  Note that we need to explicitly add the vendorIE and OUI ! */
-	uint8_t curAddIELen = pOld->length;
+	uint16_t curAddIELen = pOld->length;
 
 	pOld->length = curAddIELen + pNew->num_data + 6;
 	pOld->addIEdata[curAddIELen++] = 0xdd;
@@ -179,7 +179,7 @@
 {
 	/* This is awful, I know, but the old code just rammed the IE into */
 	/* an opaque array.  Note that we need to explicitly add the vendorIE and OUI ! */
-	uint8_t curAddIELen = pOld->length;
+	uint16_t curAddIELen = pOld->length;
 
 	pOld->length = curAddIELen + pNew->num_data + 6;
 	pOld->addIEdata[curAddIELen++] = 0xdd;
diff --git a/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_api_roam.c b/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_api_roam.c
index 88aa4dd..b1e125a 100644
--- a/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_api_roam.c
+++ b/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_api_roam.c
@@ -11812,9 +11812,10 @@
 	pIbssLog->eventId = WLAN_IBSS_EVENT_COALESCING;
 	if (pNewBss) {
 		qdf_copy_macaddr(&pIbssLog->bssid, &pNewBss->bssId);
-		if (pNewBss->ssId.length)
-			qdf_mem_copy(pIbssLog->ssid, pNewBss->ssId.ssId,
-				     pNewBss->ssId.length);
+		if (pNewBss->ssId.length > HOST_LOG_MAX_SSID_SIZE)
+			pNewBss->ssId.length = HOST_LOG_MAX_SSID_SIZE;
+		qdf_mem_copy(pIbssLog->ssid, pNewBss->ssId.ssId,
+			     pNewBss->ssId.length);
 		pIbssLog->operatingChannel = pNewBss->channelNumber;
 	}
 	if (IS_SIR_STATUS_SUCCESS(wlan_cfg_get_int(mac_ctx,
diff --git a/drivers/staging/qcacld-3.0/core/wma/src/wma_features.c b/drivers/staging/qcacld-3.0/core/wma/src/wma_features.c
index c9b74e3..73d42db 100644
--- a/drivers/staging/qcacld-3.0/core/wma/src/wma_features.c
+++ b/drivers/staging/qcacld-3.0/core/wma/src/wma_features.c
@@ -10685,7 +10685,9 @@
 	encrypt_decrypt_rsp_params.vdev_id = data_event->vdev_id;
 	encrypt_decrypt_rsp_params.status = data_event->status;
 
-	if (data_event->data_length > param_buf->num_enc80211_frame) {
+	if ((data_event->data_length > param_buf->num_enc80211_frame) ||
+	    (data_event->data_length > WMI_SVC_MSG_MAX_SIZE - WMI_TLV_HDR_SIZE -
+	     sizeof(*data_event))) {
 		WMA_LOGE("FW msg data_len %d more than TLV hdr %d",
 			 data_event->data_length,
 			 param_buf->num_enc80211_frame);
diff --git a/drivers/staging/qcacld-3.0/core/wma/src/wma_mgmt.c b/drivers/staging/qcacld-3.0/core/wma/src/wma_mgmt.c
index ea1b718..1e12bb3 100644
--- a/drivers/staging/qcacld-3.0/core/wma/src/wma_mgmt.c
+++ b/drivers/staging/qcacld-3.0/core/wma/src/wma_mgmt.c
@@ -3297,6 +3297,13 @@
 			cds_pkt_return_packet(rx_pkt);
 			return -EINVAL;
 		}
+	if (qdf_nbuf_len(wbuf) < (sizeof(*wh) + IEEE80211_CCMP_HEADERLEN +
+						IEEE80211_CCMP_MICLEN)) {
+		WMA_LOGE("Buffer length less than expected %d ",
+						(int)qdf_nbuf_len(wbuf));
+		cds_pkt_return_packet(rx_pkt);
+		return -EINVAL;
+	}
 
 		orig_hdr = (uint8_t *) qdf_nbuf_data(wbuf);
 		/* Pointer to head of CCMP header */
@@ -3481,6 +3488,7 @@
 }
 
 #define RATE_LIMIT 16
+#define RESERVE_BYTES   100
 /**
  * wma_mgmt_rx_process() - process management rx frame.
  * @handle: wma handle
@@ -3616,9 +3624,28 @@
 		qdf_mem_free(rx_pkt);
 		return -EINVAL;
 	}
-
-	/* Why not just use rx_event->hdr.buf_len? */
-	wbuf = qdf_nbuf_alloc(NULL, roundup(hdr->buf_len, 4), 0, 4, false);
+	/*
+	 * Allocate the memory for this rx packet, add extra 100 bytes for:-
+	 *
+	 * 1.  Filling the missing RSN capabilites by some APs, which fill the
+	 *     RSN IE length as extra 2 bytes but dont fill the IE data with
+	 *     capabilities, resulting in failure in unpack core due to length
+	 *     mismatch. Check sir_validate_and_rectify_ies for more info.
+	 *
+	 * 2.  In the API wma_process_rmf_frame(), the driver trims the CCMP
+	 *     header by overwriting the IEEE header to memory occupied by CCMP
+	 *     header, but an overflow is possible if the memory allocated to
+	 *     frame is less than the sizeof(struct ieee80211_frame) +CCMP
+	 *     HEADER len, so allocating 100 bytes would solve this issue too.
+	 *
+	 * 3.  CCMP header is pointing to orig_hdr +
+	 *     sizeof(struct ieee80211_frame) which could also result in OOB
+	 *     access, if the data len is less than
+	 *     sizeof(struct ieee80211_frame), allocating extra bytes would
+	 *     result in solving this issue too.
+	 */
+	wbuf = qdf_nbuf_alloc(NULL, roundup(hdr->buf_len + RESERVE_BYTES,
+							4), 0, 4, false);
 	if (!wbuf) {
 		WMA_LOGE("%s: Failed to allocate wbuf for mgmt rx len(%u)",
 			    __func__, hdr->buf_len);
@@ -3629,6 +3656,9 @@
 	qdf_nbuf_put_tail(wbuf, hdr->buf_len);
 	qdf_nbuf_set_protocol(wbuf, ETH_P_CONTROL);
 	wh = (struct ieee80211_frame *)qdf_nbuf_data(wbuf);
+	qdf_mem_zero(((uint8_t *)wh + hdr->buf_len), roundup(hdr->buf_len +
+							RESERVE_BYTES, 4) -
+							hdr->buf_len);
 
 	rx_pkt->pkt_meta.mpdu_hdr_ptr = qdf_nbuf_data(wbuf);
 	rx_pkt->pkt_meta.mpdu_data_ptr = rx_pkt->pkt_meta.mpdu_hdr_ptr +
diff --git a/drivers/video/fbdev/msm/mdss_dsi_panel.c b/drivers/video/fbdev/msm/mdss_dsi_panel.c
index 6d9d2c7..18b68f0 100644
--- a/drivers/video/fbdev/msm/mdss_dsi_panel.c
+++ b/drivers/video/fbdev/msm/mdss_dsi_panel.c
@@ -327,10 +327,12 @@
 
 	irq = gpio_to_irq(ctrl_pdata->disp_err_detect_gpio);
 
-	if (enable)
+	if (enable) {
 		enable_irq(irq);
-	else
+	} else {
 		disable_irq(irq);
+		cancel_delayed_work_sync(&ctrl_pdata->err_int_work);
+	}
 	pr_debug(" %s : enable(%d)\n", __func__, enable);
 }
 
@@ -522,8 +524,6 @@
 			gpio_set_value(ctrl_pdata->lcd_mode_sel_gpio, 0);
 			gpio_free(ctrl_pdata->lcd_mode_sel_gpio);
 		}
-		if (pinfo->err_detect_enabled)
-			mdss_dsi_err_detect_irq_control(ctrl_pdata, false);
 	}
 
 exit:
@@ -1091,6 +1091,9 @@
 			goto end;
 	}
 
+	if (pinfo->err_detect_enabled)
+		mdss_dsi_err_detect_irq_control(ctrl, false);
+
 	if (ctrl->off_cmds.cmd_cnt)
 		mdss_dsi_panel_cmds_send(ctrl, &ctrl->off_cmds, CMD_REQ_COMMIT);
 
diff --git a/drivers/video/fbdev/msm/mdss_dsi_status.c b/drivers/video/fbdev/msm/mdss_dsi_status.c
index c6801ea..9089340 100644
--- a/drivers/video/fbdev/msm/mdss_dsi_status.c
+++ b/drivers/video/fbdev/msm/mdss_dsi_status.c
@@ -177,23 +177,35 @@
 int disp_read_err_register(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
 {
 	struct dcs_cmd_req cmdreq;
-	char rx_buf[1] = {0x0};
+	/*
+	 * setting a non-zero default value, if for some reason unable to read
+	 * back the value it should be treated as failure
+	 */
+	char rx_buf[1] = {0xFF};
 	char err_read_dcs_cmd[2] = {0x9F, 0x00}; /* DTYPE_DCS_READ */
 	struct dsi_cmd_desc err_read_dsi_cmd_desc = {
 		{DTYPE_DCS_READ, 1, 0, 1, 5, sizeof(err_read_dcs_cmd)},
 		err_read_dcs_cmd
 	};
+	int ret;
 
 	memset(&cmdreq, 0, sizeof(cmdreq));
 	cmdreq.cmds = &err_read_dsi_cmd_desc;
 	cmdreq.cmds_cnt = 1;
+	/* make sure there is no ongoing transfer while checking error status */
 	cmdreq.flags = CMD_REQ_RX | CMD_REQ_COMMIT | CMD_REQ_HS_MODE |
-			CMD_CLK_CTRL;
+			CMD_CLK_CTRL | CMD_REQ_MDP_IDLE;
 	cmdreq.rlen = 1;
 	cmdreq.cb = NULL;
 	cmdreq.rbuf = rx_buf;
 
-	mdss_dsi_cmdlist_put(ctrl_pdata, &cmdreq);
+	ret = mdss_dsi_cmdlist_put(ctrl_pdata, &cmdreq);
+	if (ret != cmdreq.rlen) {
+		pr_warn("%s: unable to read panel status (%d)\n",
+			__func__, ret);
+		return -EINVAL;
+	}
+
 	pr_info("%s: Reg[0x%x]=0x%x\n", __func__,
 		err_read_dcs_cmd[0], rx_buf[0]);