LTS: Merge upstream-linux-4.4.y (4.4.210) into android-msm-wahoo-4.4

Merge upstream-linux-4.4.y LTS kernel (4.4.210) into M2S2 master kernel.

Bug: 146416723
Test: Manual testing, SST, vts/vts-kernel, pts/base, pts/postsubmit-long
Change-Id: Id6b2cff91207e76d910269f037aeef13b72c3bf6
Signed-off-by: Robin Peng <robinpeng@google.com>
diff --git a/drivers/char/diag/diag_memorydevice.c b/drivers/char/diag/diag_memorydevice.c
index 2d7bafb..2f68589 100644
--- a/drivers/char/diag/diag_memorydevice.c
+++ b/drivers/char/diag/diag_memorydevice.c
@@ -213,7 +213,10 @@
 			continue;
 
 		found = 1;
-		driver->data_ready[i] |= USER_SPACE_DATA_TYPE;
+		if (!(driver->data_ready[i] & USER_SPACE_DATA_TYPE)) {
+			driver->data_ready[i] |= USER_SPACE_DATA_TYPE;
+			atomic_inc(&driver->data_ready_notif[i]);
+		}
 		pr_debug("diag: wake up logging process\n");
 		wake_up_interruptible(&driver->wait_q);
 	}
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index d47b925..65db9f5 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -26,6 +26,8 @@
 #include <asm/atomic.h>
 #include "diagfwd_bridge.h"
 
+#define THRESHOLD_CLIENT_LIMIT	50
+
 /* Size of the USB buffers used for read and write*/
 #define USB_MAX_OUT_BUF 4096
 #define APPS_BUF_SIZE	4096
@@ -498,6 +500,7 @@
 	wait_queue_head_t wait_q;
 	struct diag_client_map *client_map;
 	int *data_ready;
+	atomic_t data_ready_notif[THRESHOLD_CLIENT_LIMIT];
 	int num_clients;
 	int polling_reg_flag;
 	int use_device_tree;
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 512b4f9..8c97324 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -138,7 +138,6 @@
 
 /* This is the max number of user-space clients supported at initialization*/
 static unsigned int max_clients = 15;
-static unsigned int threshold_client_limit = 50;
 module_param(max_clients, uint, 0);
 
 /* Timer variables */
@@ -345,7 +344,7 @@
 		if (i < driver->num_clients) {
 			diag_add_client(i, file);
 		} else {
-			if (i < threshold_client_limit) {
+			if (i < THRESHOLD_CLIENT_LIMIT) {
 				driver->num_clients++;
 				temp = krealloc(driver->client_map
 					, (driver->num_clients) * sizeof(struct
@@ -375,11 +374,17 @@
 			}
 		}
 		driver->data_ready[i] = 0x0;
+		atomic_set(&driver->data_ready_notif[i], 0);
 		driver->data_ready[i] |= MSG_MASKS_TYPE;
+		atomic_inc(&driver->data_ready_notif[i]);
 		driver->data_ready[i] |= EVENT_MASKS_TYPE;
+		atomic_inc(&driver->data_ready_notif[i]);
 		driver->data_ready[i] |= LOG_MASKS_TYPE;
+		atomic_inc(&driver->data_ready_notif[i]);
 		driver->data_ready[i] |= DCI_LOG_MASKS_TYPE;
+		atomic_inc(&driver->data_ready_notif[i]);
 		driver->data_ready[i] |= DCI_EVENT_MASKS_TYPE;
+		atomic_inc(&driver->data_ready_notif[i]);
 
 		if (driver->ref_count == 0)
 			diag_mempool_init();
@@ -1801,8 +1806,10 @@
 		mutex_unlock(&driver->diagchar_mutex);
 		return -EINVAL;
 	}
-
-	driver->data_ready[i] |= DEINIT_TYPE;
+	if (!(driver->data_ready[i] & DEINIT_TYPE)) {
+		driver->data_ready[i] |= DEINIT_TYPE;
+		atomic_inc(&driver->data_ready_notif[i]);
+	}
 	mutex_unlock(&driver->diagchar_mutex);
 	wake_up_interruptible(&driver->wait_q);
 
@@ -2905,16 +2912,6 @@
 	return 0;
 }
 
-static int check_data_ready(int index)
-{
-	int data_type = 0;
-
-	mutex_lock(&driver->diagchar_mutex);
-	data_type = driver->data_ready[index];
-	mutex_unlock(&driver->diagchar_mutex);
-	return data_type;
-}
-
 static ssize_t diagchar_read(struct file *file, char __user *buf, size_t count,
 			  loff_t *ppos)
 {
@@ -2943,7 +2940,8 @@
 		pr_err("diag: bad address from user side\n");
 		return -EFAULT;
 	}
-	wait_event_interruptible(driver->wait_q, (check_data_ready(index)) > 0);
+	wait_event_interruptible(driver->wait_q,
+			atomic_read(&driver->data_ready_notif[index]) > 0);
 
 	mutex_lock(&driver->diagchar_mutex);
 
@@ -2954,6 +2952,7 @@
 		/*Copy the type of data being passed*/
 		data_type = driver->data_ready[index] & USER_SPACE_DATA_TYPE;
 		driver->data_ready[index] ^= USER_SPACE_DATA_TYPE;
+		atomic_dec(&driver->data_ready_notif[index]);
 		COPY_USER_SPACE_OR_EXIT(buf, data_type, sizeof(int));
 		/* place holder for number of data field */
 		ret += sizeof(int);
@@ -2967,11 +2966,13 @@
 		/* In case, the thread wakes up and the logging mode is
 		not memory device any more, the condition needs to be cleared */
 		driver->data_ready[index] ^= USER_SPACE_DATA_TYPE;
+		atomic_dec(&driver->data_ready_notif[index]);
 	}
 
 	if (driver->data_ready[index] & HDLC_SUPPORT_TYPE) {
 		data_type = driver->data_ready[index] & HDLC_SUPPORT_TYPE;
 		driver->data_ready[index] ^= HDLC_SUPPORT_TYPE;
+		atomic_dec(&driver->data_ready_notif[index]);
 		COPY_USER_SPACE_OR_EXIT(buf, data_type, sizeof(int));
 		mutex_lock(&driver->md_session_lock);
 		session_info = diag_md_session_get_pid(current->tgid);
@@ -2993,6 +2994,7 @@
 		data_type = driver->data_ready[index] & DEINIT_TYPE;
 		COPY_USER_SPACE_OR_EXIT(buf, data_type, 4);
 		driver->data_ready[index] ^= DEINIT_TYPE;
+		atomic_dec(&driver->data_ready_notif[index]);
 		mutex_unlock(&driver->diagchar_mutex);
 		diag_remove_client_entry(file);
 		return ret;
@@ -3014,6 +3016,7 @@
 		if (write_len > 0)
 			ret += write_len;
 		driver->data_ready[index] ^= MSG_MASKS_TYPE;
+		atomic_dec(&driver->data_ready_notif[index]);
 		goto exit;
 	}
 
@@ -3047,6 +3050,7 @@
 		}
 		mutex_unlock(&driver->md_session_lock);
 		driver->data_ready[index] ^= EVENT_MASKS_TYPE;
+		atomic_dec(&driver->data_ready_notif[index]);
 		goto exit;
 	}
 
@@ -3066,6 +3070,7 @@
 		if (write_len > 0)
 			ret += write_len;
 		driver->data_ready[index] ^= LOG_MASKS_TYPE;
+		atomic_dec(&driver->data_ready_notif[index]);
 		goto exit;
 	}
 
@@ -3077,6 +3082,7 @@
 					*(driver->apps_req_buf),
 					driver->apps_req_buf_len);
 		driver->data_ready[index] ^= PKT_TYPE;
+		atomic_dec(&driver->data_ready_notif[index]);
 		driver->in_busy_pktdata = 0;
 		goto exit;
 	}
@@ -3088,6 +3094,7 @@
 		COPY_USER_SPACE_OR_EXIT(buf+4, *(driver->dci_pkt_buf),
 					driver->dci_pkt_length);
 		driver->data_ready[index] ^= DCI_PKT_TYPE;
+		atomic_dec(&driver->data_ready_notif[index]);
 		driver->in_busy_dcipktdata = 0;
 		goto exit;
 	}
@@ -3100,6 +3107,7 @@
 		COPY_USER_SPACE_OR_EXIT(buf + 8, (dci_ops_tbl[DCI_LOCAL_PROC].
 				event_mask_composite), DCI_EVENT_MASK_SIZE);
 		driver->data_ready[index] ^= DCI_EVENT_MASKS_TYPE;
+		atomic_dec(&driver->data_ready_notif[index]);
 		goto exit;
 	}
 
@@ -3111,6 +3119,7 @@
 		COPY_USER_SPACE_OR_EXIT(buf+8, (dci_ops_tbl[DCI_LOCAL_PROC].
 				log_mask_composite), DCI_LOG_MASK_SIZE);
 		driver->data_ready[index] ^= DCI_LOG_MASKS_TYPE;
+		atomic_dec(&driver->data_ready_notif[index]);
 		goto exit;
 	}
 
@@ -3165,6 +3174,7 @@
 			exit_stat = diag_copy_dci(buf, count, entry, &ret);
 			mutex_lock(&driver->diagchar_mutex);
 			driver->data_ready[index] ^= DCI_DATA_TYPE;
+			atomic_dec(&driver->data_ready_notif[index]);
 			mutex_unlock(&driver->diagchar_mutex);
 			if (exit_stat == 1) {
 				put_task_struct(task_s);
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index c745024..ae450f3 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -225,6 +225,7 @@
 			 * situation.
 			 */
 			driver->data_ready[i] |= USER_SPACE_DATA_TYPE;
+			atomic_inc(&driver->data_ready_notif[i]);
 			pr_debug("diag: Force wakeup of logging process\n");
 			wake_up_interruptible(&driver->wait_q);
 			break;
@@ -499,8 +500,11 @@
 
 	mutex_lock(&driver->diagchar_mutex);
 	for (i = 0; i < driver->num_clients; i++)
-		if (driver->client_map[i].pid != 0)
+		if (driver->client_map[i].pid != 0 &&
+			!(driver->data_ready[i] & type)) {
 			driver->data_ready[i] |= type;
+			atomic_inc(&driver->data_ready_notif[i]);
+		}
 	wake_up_interruptible(&driver->wait_q);
 	mutex_unlock(&driver->diagchar_mutex);
 }
@@ -517,7 +521,11 @@
 				if (driver->client_map[j].pid != 0 &&
 					driver->client_map[j].pid ==
 					driver->md_session_map[i]->pid) {
-					driver->data_ready[j] |= type;
+					if (!(driver->data_ready[i] & type)) {
+						driver->data_ready[j] |= type;
+						atomic_inc(
+						&driver->data_ready_notif[j]);
+					}
 					break;
 				}
 			}
@@ -533,7 +541,10 @@
 	mutex_lock(&driver->diagchar_mutex);
 	for (i = 0; i < driver->num_clients; i++)
 		if (driver->client_map[i].pid == process_id) {
-			driver->data_ready[i] |= data_type;
+			if (!(driver->data_ready[i] & data_type)) {
+				driver->data_ready[i] |= data_type;
+				atomic_inc(&driver->data_ready_notif[i]);
+			}
 			break;
 		}
 	wake_up_interruptible(&driver->wait_q);
@@ -1727,6 +1738,10 @@
 							, GFP_KERNEL)) == NULL)
 		goto err;
 	kmemleak_not_leak(driver->data_ready);
+
+	for (i = 0; i < THRESHOLD_CLIENT_LIMIT; i++)
+		atomic_set(&driver->data_ready_notif[i], 0);
+
 	if (driver->apps_req_buf == NULL) {
 		driver->apps_req_buf = kzalloc(DIAG_MAX_REQ_SIZE, GFP_KERNEL);
 		if (!driver->apps_req_buf)
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index f53ae22..19e202f 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -2549,7 +2549,8 @@
 	if (!IS_ERR_OR_NULL(data->client.ihandle)) {
 		ion_unmap_kernel(qseecom.ion_clnt, data->client.ihandle);
 		ion_free(qseecom.ion_clnt, data->client.ihandle);
-		data->client.ihandle = NULL;
+		memset((void *)&data->client,
+			0, sizeof(struct qseecom_client_handle));
 	}
 	return ret;
 }
diff --git a/drivers/soc/qcom/msm_smem.c b/drivers/soc/qcom/msm_smem.c
index d06b872..b937218 100644
--- a/drivers/soc/qcom/msm_smem.c
+++ b/drivers/soc/qcom/msm_smem.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -182,6 +182,20 @@
 static int init_smem_remote_spinlock(void);
 
 /**
+ * smem_get_toc() - Used for getting partitions TOC
+ *
+ * @return - Base address off partitions TOC
+ *
+ * Helper function to get base address of partition TOC,
+ * that is present in top 4K of first smem region.
+ */
+static struct smem_toc __iomem *smem_get_toc(void)
+{
+	return smem_areas[0].virt_addr +
+	       smem_areas[0].size - 4 * 1024;
+}
+
+/**
  * is_probe_done() - Did the probe function successfully complete
  *
  * @return - true if probe successfully completed, false if otherwise
@@ -315,6 +329,7 @@
 	int use_spinlocks = spinlocks_initialized && use_rspinlock;
 	void *ret = 0;
 	unsigned long flags = 0;
+	uint32_t e_size;
 	int rc;
 
 	if (!skip_init_check && !smem_initialized_check())
@@ -333,7 +348,11 @@
 	if (toc[id].allocated) {
 		phys_addr_t phys_base;
 
-		*size = toc[id].size;
+		e_size = toc[id].size;
+		if (e_size > smem_ram_size)
+			return ret;
+		*size = e_size;
+
 		barrier();
 
 		phys_base = toc[id].reserved & BASE_ADDR_MASK;
@@ -368,12 +387,19 @@
 					bool skip_init_check,
 					bool use_rspinlock)
 {
-	struct smem_partition_header *hdr;
-	unsigned long lflags = 0;
-	void *item = NULL;
 	struct smem_partition_allocation_header *alloc_hdr;
+	struct smem_partition_header *hdr;
+	uint32_t offset_free_uncached;
+	struct smem_toc __iomem *toc;
+	uint32_t offset_free_cached;
+	unsigned long lflags = 0;
+	uint32_t partition_size;
 	uint32_t partition_num;
+	uint32_t padding_data;
+	uint32_t padding_hdr;
 	uint32_t a_hdr_size;
+	uint32_t item_size;
+	void *item = NULL;
 	int rc;
 
 	SMEM_DBG("%s(%u, %u, %u, %d, %d)\n", __func__, id, to_proc,
@@ -393,9 +419,13 @@
 		return NULL;
 	}
 
+	toc = smem_get_toc();
+
 	if (flags & SMEM_ANY_HOST_FLAG || !partitions[to_proc].offset) {
 		if (use_comm_partition) {
 			partition_num = comm_partition.partition_num;
+			partition_size =
+			readl_relaxed(&toc->entry[partition_num].size);
 			hdr = smem_areas[0].virt_addr + comm_partition.offset;
 		} else {
 			return __smem_get_entry_nonsecure(id, size,
@@ -403,6 +433,7 @@
 		}
 	} else {
 		partition_num = partitions[to_proc].partition_num;
+		partition_size = readl_relaxed(&toc->entry[partition_num].size);
 		hdr = smem_areas[0].virt_addr + partitions[to_proc].offset;
 	}
 	if (unlikely(!spinlocks_initialized)) {
@@ -433,11 +464,20 @@
 	if (flags & SMEM_ITEM_CACHED_FLAG) {
 		a_hdr_size = ALIGN(sizeof(*alloc_hdr),
 				partitions[to_proc].size_cacheline);
-		for (alloc_hdr = (void *)(hdr) + hdr->size - a_hdr_size;
+		offset_free_cached = hdr->offset_free_cached;
+		if (WARN_ON(offset_free_cached > partition_size))
+			return NULL;
+
+		for (alloc_hdr = (void *)(hdr) + partition_size - a_hdr_size;
 				(void *)(alloc_hdr) > (void *)(hdr) +
-					hdr->offset_free_cached;
+					offset_free_cached;
 				alloc_hdr = (void *)(alloc_hdr) -
-						alloc_hdr->size - a_hdr_size) {
+						item_size - a_hdr_size) {
+			item_size = alloc_hdr->size;
+			padding_data = alloc_hdr->padding_data;
+			if (WARN_ON(padding_data > item_size
+				    || item_size > partition_size))
+				return NULL;
 			if (alloc_hdr->canary != SMEM_ALLOCATION_CANARY) {
 				LOG_ERR(
 					"%s: SMEM corruption detected.  Partition %d to %d at %p\n",
@@ -450,20 +490,30 @@
 			}
 			if (alloc_hdr->smem_type == id) {
 				/* 8 byte alignment to match legacy */
-				*size = ALIGN(alloc_hdr->size -
-						alloc_hdr->padding_data, 8);
-				item = (void *)(alloc_hdr) - alloc_hdr->size;
+				*size = ALIGN(item_size - padding_data, 8);
+				item = (void *)(alloc_hdr) - item_size;
 				break;
 			}
 		}
 	} else {
+		offset_free_uncached = hdr->offset_free_uncached;
+		if (WARN_ON(offset_free_uncached > partition_size))
+			return NULL;
+
 		for (alloc_hdr = (void *)(hdr) + sizeof(*hdr);
 				(void *)(alloc_hdr) < (void *)(hdr) +
-					hdr->offset_free_uncached;
+					offset_free_uncached;
 				alloc_hdr = (void *)(alloc_hdr) +
 						sizeof(*alloc_hdr) +
-						alloc_hdr->padding_hdr +
-						alloc_hdr->size) {
+						padding_hdr +
+						item_size) {
+			padding_hdr = alloc_hdr->padding_hdr;
+			padding_data = alloc_hdr->padding_data;
+			item_size = alloc_hdr->size;
+			if (WARN_ON(padding_hdr > partition_size
+				    || item_size > partition_size
+				    || padding_data > item_size))
+				return NULL;
 			if (alloc_hdr->canary != SMEM_ALLOCATION_CANARY) {
 				LOG_ERR(
 					"%s: SMEM corruption detected.  Partition %d to %d at %p\n",
@@ -476,11 +526,10 @@
 			}
 			if (alloc_hdr->smem_type == id) {
 				/* 8 byte alignment to match legacy */
-				*size = ALIGN(alloc_hdr->size -
-						alloc_hdr->padding_data, 8);
+				*size = ALIGN(item_size - padding_data, 8);
 				item = (void *)(alloc_hdr) +
 						sizeof(*alloc_hdr) +
-						alloc_hdr->padding_hdr;
+						padding_hdr;
 				break;
 			}
 		}
@@ -569,10 +618,17 @@
 	void *smem_base = smem_ram_base;
 	struct smem_shared *shared = smem_base;
 	struct smem_heap_entry *toc = shared->heap_toc;
+	uint32_t free_offset, heap_remaining;
 	void *ret = NULL;
 
-	if (shared->heap_info.heap_remaining >= size_in) {
-		toc[id].offset = shared->heap_info.free_offset;
+	heap_remaining = shared->heap_info.heap_remaining;
+	free_offset = shared->heap_info.free_offset;
+	if (WARN_ON(heap_remaining > smem_ram_size
+		   || free_offset > smem_ram_size))
+		return NULL;
+
+	if (heap_remaining >= size_in) {
+		toc[id].offset = free_offset;
 		toc[id].size = size_in;
 		/*
 		 * wmb() is necessary to ensure the allocation data is
@@ -584,7 +640,7 @@
 
 		shared->heap_info.free_offset += size_in;
 		shared->heap_info.heap_remaining -= size_in;
-		ret = smem_base + toc[id].offset;
+		ret = smem_base + free_offset;
 		/*
 		 * wmb() is necessary to ensure the heap data is consistent
 		 * before continuing to prevent race conditions with remote
@@ -620,11 +676,15 @@
 	void *smem_base = smem_ram_base;
 	struct smem_partition_header *hdr;
 	struct smem_partition_allocation_header *alloc_hdr;
+	uint32_t offset_free_uncached;
+	struct smem_toc __iomem *toc;
+	uint32_t offset_free_cached;
+	uint32_t partition_size;
+	uint32_t partition_num;
 	uint32_t a_hdr_size;
 	uint32_t a_data_size;
 	uint32_t size_cacheline;
 	uint32_t free_space;
-	uint32_t partition_num;
 	void *ret = NULL;
 
 	if (to_proc == SMEM_COMM_HOST) {
@@ -651,27 +711,35 @@
 		BUG();
 	}
 
-	free_space = hdr->offset_free_cached -
-					hdr->offset_free_uncached;
+	toc = smem_get_toc();
+	partition_size = readl_relaxed(&toc->entry[partition_num].size);
+
+	offset_free_cached = hdr->offset_free_cached;
+	offset_free_uncached = hdr->offset_free_uncached;
+	if (WARN_ON(offset_free_uncached > offset_free_cached
+		    || offset_free_cached > partition_size))
+		return NULL;
+
+	free_space = offset_free_cached - offset_free_uncached;
 
 	if (flags & SMEM_ITEM_CACHED_FLAG) {
 		a_hdr_size = ALIGN(sizeof(*alloc_hdr), size_cacheline);
 		a_data_size = ALIGN(size_in, size_cacheline);
-		if (free_space < a_hdr_size + a_data_size) {
+		if (free_space < a_hdr_size + a_data_size
+		    || free_space < size_in) {
 			SMEM_INFO(
-				"%s: id %u not enough memory %u (required %u)\n",
-						__func__, id, free_space,
-						a_hdr_size + a_data_size);
+			"%s: id %u not enough memory %u	(required %u), (size_in %u)\n",
+				__func__, id, free_space,
+				a_hdr_size + a_data_size, size_in);
 			return ret;
 		}
-		alloc_hdr = (void *)(hdr) + hdr->offset_free_cached -
-								a_hdr_size;
+		alloc_hdr = (void *)(hdr) + offset_free_cached - a_hdr_size;
 		alloc_hdr->canary = SMEM_ALLOCATION_CANARY;
 		alloc_hdr->smem_type = id;
 		alloc_hdr->size = a_data_size;
 		alloc_hdr->padding_data = a_data_size - size_in;
 		alloc_hdr->padding_hdr = a_hdr_size - sizeof(*alloc_hdr);
-		hdr->offset_free_cached = hdr->offset_free_cached -
+		hdr->offset_free_cached = offset_free_cached -
 						a_hdr_size - a_data_size;
 		ret = (void *)(alloc_hdr) - a_data_size;
 		/*
@@ -686,20 +754,21 @@
 	} else {
 		a_hdr_size = sizeof(*alloc_hdr);
 		a_data_size = ALIGN(size_in, 8);
-		if (free_space < a_hdr_size + a_data_size) {
+		if (free_space < a_hdr_size + a_data_size
+		    || free_space < size_in) {
 			SMEM_INFO(
-				"%s: id %u not enough memory %u (required %u)\n",
-						__func__, id, free_space,
-						a_hdr_size + a_data_size);
+			"%s: id %u not enough memory %u	(required %u) (size_in %u)\n",
+					__func__, id, free_space,
+					a_hdr_size + a_data_size, size_in);
 			return ret;
 		}
-		alloc_hdr = (void *)(hdr) + hdr->offset_free_uncached;
+		alloc_hdr = (void *)(hdr) + offset_free_uncached;
 		alloc_hdr->canary = SMEM_ALLOCATION_CANARY;
 		alloc_hdr->smem_type = id;
 		alloc_hdr->size = a_data_size;
 		alloc_hdr->padding_data = a_data_size - size_in;
 		alloc_hdr->padding_hdr = a_hdr_size - sizeof(*alloc_hdr);
-		hdr->offset_free_uncached = hdr->offset_free_uncached +
+		hdr->offset_free_uncached = offset_free_uncached +
 						a_hdr_size + a_data_size;
 		ret = alloc_hdr + 1;
 	}
@@ -891,6 +960,12 @@
 {
 	struct smem_partition_header *hdr;
 	struct smem_shared *shared;
+	uint32_t offset_free_uncached;
+	struct smem_toc __iomem *toc;
+	uint32_t offset_free_cached;
+	uint32_t heap_remaining;
+	uint32_t p_size;
+	uint32_t p_num;
 
 	if (to_proc >= NUM_SMEM_SUBSYSTEMS) {
 		pr_err("%s: invalid to_proc:%d\n", __func__, to_proc);
@@ -905,11 +980,24 @@
 			return UINT_MAX;
 		}
 		hdr = smem_areas[0].virt_addr + partitions[to_proc].offset;
-		return hdr->offset_free_cached - hdr->offset_free_uncached;
-	} else {
-		shared = smem_ram_base;
-		return shared->heap_info.heap_remaining;
+		offset_free_cached = hdr->offset_free_cached;
+		offset_free_uncached = hdr->offset_free_uncached;
+
+		toc = smem_get_toc();
+		p_num = partitions[to_proc].partition_num;
+		p_size = readl_relaxed(&toc->entry[p_num].size);
+		if (WARN_ON(offset_free_uncached > offset_free_cached
+			    || offset_free_cached > p_size))
+			return -EINVAL;
+
+		return offset_free_cached - offset_free_uncached;
 	}
+	shared = smem_ram_base;
+	heap_remaining = shared->heap_info.heap_remaining;
+	if (WARN_ON(heap_remaining > smem_ram_size))
+		return -EINVAL;
+
+	return heap_remaining;
 }
 EXPORT_SYMBOL(smem_get_free_space);
 
@@ -1214,8 +1302,8 @@
 		LOG_ERR("Smem partition %d hdr magic is bad\n", num);
 		BUG();
 	}
-	if (!hdr->size) {
-		LOG_ERR("Smem partition %d size is 0\n", num);
+	if (hdr->size != entry->size) {
+		LOG_ERR("Smem partition %d size is invalid\n", num);
 		BUG();
 	}
 	if (hdr->offset_free_uncached > hdr->size) {
diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c
index 19019aa..2c77f90 100644
--- a/drivers/soc/qcom/smem.c
+++ b/drivers/soc/qcom/smem.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2015, Sony Mobile Communications AB.
- * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, 2019 The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -228,7 +228,7 @@
  * struct qcom_smem - device data for the smem device
  * @dev:	device pointer
  * @hwlock:	reference to a hwspinlock
- * @partitions:	list of pointers to partitions affecting the current
+ * @ptable_entries: list of pointers to partitions table entry of current
  *		processor/host
  * @num_regions: number of @regions
  * @regions:	list of the memory regions defining the shared memory
@@ -238,12 +238,24 @@
 
 	struct hwspinlock *hwlock;
 
-	struct smem_partition_header *partitions[SMEM_HOST_COUNT];
+	struct smem_ptable_entry *ptable_entries[SMEM_HOST_COUNT];
 
 	unsigned num_regions;
 	struct smem_region regions[0];
 };
 
+/* Pointer to the one and only smem handle */
+static struct qcom_smem *__smem;
+
+/* Timeout (ms) for the trylock of remote spinlocks */
+#define HWSPINLOCK_TIMEOUT	1000
+
+static struct smem_partition_header *
+ptable_entry_to_phdr(struct smem_ptable_entry *entry)
+{
+	return __smem->regions[0].virt_base + le32_to_cpu(entry->offset);
+}
+
 static struct smem_private_entry *
 phdr_to_last_private_entry(struct smem_partition_header *phdr)
 {
@@ -283,32 +295,33 @@
 	return p + sizeof(*e) + le16_to_cpu(e->padding_hdr);
 }
 
-/* Pointer to the one and only smem handle */
-static struct qcom_smem *__smem;
-
-/* Timeout (ms) for the trylock of remote spinlocks */
-#define HWSPINLOCK_TIMEOUT	1000
-
 static int qcom_smem_alloc_private(struct qcom_smem *smem,
-				   unsigned host,
+				   struct smem_ptable_entry *entry,
 				   unsigned item,
 				   size_t size)
 {
 	struct smem_partition_header *phdr;
 	struct smem_private_entry *hdr, *end;
+	struct smem_partition_header *phdr;
 	size_t alloc_size;
 	void *cached;
+	void *p_end;
 
-	phdr = smem->partitions[host];
+	phdr = ptable_entry_to_phdr(entry);
+	p_end = (void *)phdr + le32_to_cpu(entry->size);
+
 	hdr = phdr_to_first_private_entry(phdr);
 	end = phdr_to_last_private_entry(phdr);
 	cached = phdr_to_first_cached_entry(phdr);
 
+	if (WARN_ON((void *)end > p_end || (void *)cached > p_end))
+		return -EINVAL;
+
 	while (hdr < end) {
 		if (hdr->canary != SMEM_PRIVATE_CANARY) {
 			dev_err(smem->dev,
-				"Found invalid canary in host %d partition\n",
-				host);
+				"Found invalid canary in host %d:%d partition\n",
+				phdr->host0, phdr->host1);
 			return -EINVAL;
 		}
 
@@ -317,6 +330,8 @@
 
 		hdr = private_entry_next(hdr);
 	}
+	if (WARN_ON((void *)hdr > p_end))
+		return -EINVAL;
 
 	/* Check that we don't grow into the cached region */
 	alloc_size = sizeof(*hdr) + ALIGN(size, 8);
@@ -389,6 +404,7 @@
  */
 int qcom_smem_alloc(unsigned host, unsigned item, size_t size)
 {
+	struct smem_ptable_entry *entry;
 	unsigned long flags;
 	int ret;
 
@@ -407,10 +423,12 @@
 	if (ret)
 		return ret;
 
-	if (host < SMEM_HOST_COUNT && __smem->partitions[host])
-		ret = qcom_smem_alloc_private(__smem, host, item, size);
-	else
+	if (host < SMEM_HOST_COUNT && __smem->ptable_entries[host]) {
+		entry = __smem->ptable_entries[host];
+		ret = qcom_smem_alloc_private(__smem, entry, item, size);
+	} else {
 		ret = qcom_smem_alloc_global(__smem, item, size);
+	}
 
 	hwspin_unlock_irqrestore(__smem->hwlock, &flags);
 
@@ -422,9 +440,11 @@
 				  unsigned item,
 				  size_t *size)
 {
+	struct smem_global_entry *entry;
 	struct smem_header *header;
 	struct smem_region *area;
-	struct smem_global_entry *entry;
+	u64 entry_offset;
+	u32 e_size;
 	u32 aux_base;
 	unsigned i;
 
@@ -442,9 +462,16 @@
 		area = &smem->regions[i];
 
 		if (area->aux_base == aux_base || !aux_base) {
+			e_size = le32_to_cpu(entry->size);
+			entry_offset = le32_to_cpu(entry->offset);
+
+			if (WARN_ON(e_size + entry_offset > area->size))
+				return ERR_PTR(-EINVAL);
+
 			if (size != NULL)
-				*size = le32_to_cpu(entry->size);
-			return area->virt_base + le32_to_cpu(entry->offset);
+				*size = e_size;
+
+			return area->virt_base + entry_offset;
 		}
 	}
 
@@ -452,35 +479,58 @@
 }
 
 static void *qcom_smem_get_private(struct qcom_smem *smem,
-				   unsigned host,
+				   struct smem_ptable_entry *entry,
 				   unsigned item,
 				   size_t *size)
 {
 	struct smem_partition_header *phdr;
 	struct smem_private_entry *e, *end;
+	void *item_ptr, *p_end;
+	u32 partition_size;
+	u32 padding_data;
+	u32 e_size;
 
-	phdr = smem->partitions[host];
+	phdr = ptable_entry_to_phdr(entry);
+	partition_size = le32_to_cpu(entry->size);
+	p_end = (void *)phdr + partition_size;
+
 	e = phdr_to_first_private_entry(phdr);
 	end = phdr_to_last_private_entry(phdr);
 
+	if (WARN_ON((void *)end > p_end))
+		return ERR_PTR(-EINVAL);
+
 	while (e < end) {
 		if (e->canary != SMEM_PRIVATE_CANARY) {
 			dev_err(smem->dev,
-				"Found invalid canary in host %d partition\n",
-				host);
+				"Found invalid canary in host %d:%d partition\n",
+				phdr->host0, phdr->host1);
 			return ERR_PTR(-EINVAL);
 		}
 
 		if (le16_to_cpu(e->item) == item) {
-			if (size != NULL)
-				*size = le32_to_cpu(e->size) -
-					le16_to_cpu(e->padding_data);
+			if (size != NULL) {
+				e_size = le32_to_cpu(e->size);
+				padding_data = le16_to_cpu(e->padding_data);
 
-			return entry_to_item(e);
+				if (e_size < partition_size
+				    && padding_data < e_size)
+					*size = e_size - padding_data;
+				else
+					return ERR_PTR(-EINVAL);
+			}
+
+			item_ptr = entry_to_item(e);
+			if (WARN_ON(item_ptr > p_end))
+				return ERR_PTR(-EINVAL);
+
+			return item_ptr;
 		}
 
 		e = private_entry_next(e);
 	}
+	if (WARN_ON((void *)e > p_end))
+		return ERR_PTR(-EINVAL);
 
 	return ERR_PTR(-ENOENT);
 }
@@ -496,6 +546,7 @@
  */
 void *qcom_smem_get(unsigned host, unsigned item, size_t *size)
 {
+	struct smem_ptable_entry *entry;
 	unsigned long flags;
 	int ret;
 	void *ptr = ERR_PTR(-EPROBE_DEFER);
@@ -509,11 +560,12 @@
 	if (ret)
 		return ERR_PTR(ret);
 
-	if (host < SMEM_HOST_COUNT && __smem->partitions[host])
-		ptr = qcom_smem_get_private(__smem, host, item, size);
-	else
+	if (host < SMEM_HOST_COUNT && __smem->ptable_entries[host]) {
+		entry = __smem->ptable_entries[host];
+		ptr = qcom_smem_get_private(__smem, entry, item, size);
+	} else {
 		ptr = qcom_smem_get_global(__smem, item, size);
-
+	}
 	hwspin_unlock_irqrestore(__smem->hwlock, &flags);
 
 	return ptr;
@@ -531,19 +583,28 @@
 int qcom_smem_get_free_space(unsigned host)
 {
 	struct smem_partition_header *phdr;
+	struct smem_ptable_entry *entry;
 	struct smem_header *header;
 	unsigned ret;
 
 	if (!__smem)
 		return -EPROBE_DEFER;
 
-	if (host < SMEM_HOST_COUNT && __smem->partitions[host]) {
-		phdr = __smem->partitions[host];
+	if (host < SMEM_HOST_COUNT && __smem->ptable_entries[host]) {
+		entry = __smem->ptable_entries[host];
+		phdr = ptable_entry_to_phdr(entry);
+
 		ret = le32_to_cpu(phdr->offset_free_cached) -
 		      le32_to_cpu(phdr->offset_free_uncached);
+
+		if (ret > le32_to_cpu(entry->size))
+			return -EINVAL;
 	} else {
 		header = __smem->regions[0].virt_base;
 		ret = le32_to_cpu(header->available);
+
+		if (ret > __smem->regions[0].size)
+			return -EINVAL;
 	}
 
 	return ret;
@@ -616,7 +677,7 @@
 			return -EINVAL;
 		}
 
-		if (smem->partitions[remote_host]) {
+		if (smem->ptable_entries[remote_host]) {
 			dev_err(smem->dev,
 				"Already found a partition for host %d\n",
 				remote_host);
@@ -658,7 +719,7 @@
 			return -EINVAL;
 		}
 
-		smem->partitions[remote_host] = header;
+		smem->ptable_entries[remote_host] = entry;
 	}
 
 	return 0;
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 9895853..836ebc7 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
@@ -4616,6 +4616,18 @@
 			hdd_wait_for_sme_close_sesion(hdd_ctx, adapter, false);
 		break;
 
+	case QDF_MONITOR_MODE:
+		wlan_hdd_scan_abort(adapter);
+		hdd_deregister_tx_flow_control(adapter);
+
+		/*
+		 * It is possible that the caller of this function does not
+		 * wish to close the session
+		 */
+		if (bCloseSession)
+			hdd_wait_for_sme_close_sesion(hdd_ctx, adapter, true);
+		break;
+
 	case QDF_SAP_MODE:
 		hdd_ipa_flush(hdd_ctx);
 
diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_power.c b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_power.c
index 1d9e7c2..1eec69c 100644
--- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_power.c
+++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_power.c
@@ -79,6 +79,7 @@
 #include <wlan_logging_sock_svc.h>
 #include "cds_utils.h"
 #include "wlan_hdd_packet_filter_api.h"
+#include "cds_concurrency.h"
 
 /* Preprocessor definitions and constants */
 #define HDD_SSR_BRING_UP_TIME 30000
@@ -1949,6 +1950,11 @@
 	}
 	mutex_unlock(&pHddCtx->iface_change_lock);
 
+	if (cds_is_connection_in_progress(NULL, NULL)) {
+		hdd_err("Suspend rejected: conn in progress");
+		return -EINVAL;
+	}
+
 	/* If RADAR detection is in progress (HDD), prevent suspend. The flag
 	 * "dfs_cac_block_tx" is set to true when RADAR is found and stay true
 	 * until CAC is done for a SoftAP which is in started state.
diff --git a/drivers/staging/qcacld-3.0/core/mac/src/pe/rrm/rrm_api.c b/drivers/staging/qcacld-3.0/core/mac/src/pe/rrm/rrm_api.c
index 95e470f..f2db6e0c 100644
--- a/drivers/staging/qcacld-3.0/core/mac/src/pe/rrm/rrm_api.c
+++ b/drivers/staging/qcacld-3.0/core/mac/src/pe/rrm/rrm_api.c
@@ -1054,28 +1054,30 @@
  */
 static
 tSirRetStatus update_rrm_report(tpAniSirGlobal mac_ctx,
-				tpSirMacRadioMeasureReport report,
+				tpSirMacRadioMeasureReport *report,
 				tDot11fRadioMeasurementRequest *rrm_req,
 				uint8_t *num_report, int index)
 {
-	if (report == NULL) {
+	tpSirMacRadioMeasureReport rrm_report;
+
+	if (!*report) {
 		/*
 		 * Allocate memory to send reports for
 		 * any subsequent requests.
 		 */
-		report = qdf_mem_malloc(sizeof(*report) *
+		*report = qdf_mem_malloc(sizeof(tSirMacRadioMeasureReport) *
 			 (rrm_req->num_MeasurementRequest - index));
-		if (NULL == report) {
-			pe_err("Unable to allocate memory during RRM Req processing");
+		if (!*report) {
+			pe_err("Fail to alloc mem during RRM Req processing");
 			return eSIR_MEM_ALLOC_FAILED;
 		}
-		pe_debug("rrm beacon type incapable of %d report",
-			*num_report);
+		pe_debug("rrm beacon type incapable of %d report", *num_report);
 	}
-	report[*num_report].incapable = 1;
-	report[*num_report].type =
+	rrm_report = *report;
+	rrm_report[*num_report].incapable = 1;
+	rrm_report[*num_report].type =
 		rrm_req->MeasurementRequest[index].measurement_type;
-	report[*num_report].token =
+	rrm_report[*num_report].token =
 		 rrm_req->MeasurementRequest[index].measurement_token;
 	(*num_report)++;
 	return eSIR_SUCCESS;
@@ -1157,7 +1159,7 @@
 			break;
 		default:
 			/* Send a report with incapabale bit set. */
-			status = update_rrm_report(mac_ctx, report, rrm_req,
+			status = update_rrm_report(mac_ctx, &report, rrm_req,
 						   &num_report, i);
 			if (eSIR_SUCCESS != status)
 				return status;
diff --git a/drivers/staging/qcacld-3.0/core/sap/inc/sap_api.h b/drivers/staging/qcacld-3.0/core/sap/inc/sap_api.h
index 2292d8e..140a9e6 100644
--- a/drivers/staging/qcacld-3.0/core/sap/inc/sap_api.h
+++ b/drivers/staging/qcacld-3.0/core/sap/inc/sap_api.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -872,13 +872,6 @@
 #endif
 } tSap_SoftapStats, *tpSap_SoftapStats;
 
-#ifdef FEATURE_WLAN_CH_AVOID
-/* Store channel safety information */
-typedef struct {
-	uint16_t channelNumber;
-	bool isSafe;
-} sapSafeChannelType;
-#endif /* FEATURE_WLAN_CH_AVOID */
 void sap_cleanup_channel_list(void *sapContext);
 void sapCleanupAllChannelList(void);
 
diff --git a/drivers/staging/qcacld-3.0/core/sap/src/sap_ch_select.c b/drivers/staging/qcacld-3.0/core/sap/src/sap_ch_select.c
index f5048e89..c8a7955 100644
--- a/drivers/staging/qcacld-3.0/core/sap/src/sap_ch_select.c
+++ b/drivers/staging/qcacld-3.0/core/sap/src/sap_ch_select.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -128,52 +128,6 @@
 #define ACS_WEIGHT_SOFTAP_TX_POWER_THROUGHPUT_CFG(weights) \
 	(((weights) & 0xf00000) >> 20)
 
-#ifdef FEATURE_WLAN_CH_AVOID
-sapSafeChannelType safe_channels[NUM_CHANNELS] = {
-	{1, true},
-	{2, true},
-	{3, true},
-	{4, true},
-	{5, true},
-	{6, true},
-	{7, true},
-	{8, true},
-	{9, true},
-	{10, true},
-	{11, true},
-	{12, true},
-	{13, true},
-	{14, true},
-	{36, true},
-	{40, true},
-	{44, true},
-	{48, true},
-	{52, true},
-	{56, true},
-	{60, true},
-	{64, true},
-	{100, true},
-	{104, true},
-	{108, true},
-	{112, true},
-	{116, true},
-	{120, true},
-	{124, true},
-	{128, true},
-	{132, true},
-	{136, true},
-	{140, true},
-	{144, true},
-	{149, true},
-	{153, true},
-	{157, true},
-	{161, true},
-	{165, true},
-	{169, true},
-	{173, true},
-};
-#endif
-
 typedef struct {
 	uint16_t chStartNum;
 	uint32_t weight;
@@ -401,81 +355,6 @@
 }
 #endif /* FEATURE_AP_MCC_CH_AVOIDANCE */
 
-#ifdef FEATURE_WLAN_CH_AVOID
-/*==========================================================================
-   FUNCTION    sap_update_unsafe_channel_list
-
-   DESCRIPTION
-    Function  Undate unsafe channel list table
-
-   DEPENDENCIES
-    NA.
-
-   IN
-    SapContext pointer
-
-   RETURN VALUE
-    NULL
-   ============================================================================*/
-void sap_update_unsafe_channel_list(ptSapContext pSapCtx)
-{
-	uint16_t i, j;
-	uint16_t unsafe_channel_list[NUM_CHANNELS];
-	uint16_t unsafe_channel_count = 0;
-	qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
-
-	if (!qdf_ctx) {
-		QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_FATAL,
-			  "qdf_ctx is NULL");
-		return;
-	}
-
-	/* Flush, default set all channel safe */
-	for (i = 0; i < NUM_CHANNELS; i++) {
-		safe_channels[i].isSafe = true;
-	}
-
-	/* Try to find unsafe channel */
-#if defined(FEATURE_WLAN_STA_AP_MODE_DFS_DISABLE)
-	for (i = 0; i < NUM_CHANNELS; i++) {
-		if (pSapCtx->dfs_ch_disable == true) {
-			if (CDS_IS_DFS_CH(safe_channels[i].channelNumber)) {
-				safe_channels[i].isSafe = false;
-				QDF_TRACE(QDF_MODULE_ID_SAP,
-					QDF_TRACE_LEVEL_DEBUG,
-					"%s: DFS Ch %d is not safe in"
-					" Concurrent mode",
-					__func__,
-					safe_channels[i].channelNumber);
-			}
-		}
-	}
-#endif
-	pld_get_wlan_unsafe_channel(qdf_ctx->dev,
-				    unsafe_channel_list,
-				     &unsafe_channel_count,
-				     sizeof(unsafe_channel_list));
-
-	for (i = 0; i < unsafe_channel_count; i++) {
-		for (j = 0; j < NUM_CHANNELS; j++) {
-			if (safe_channels[j].channelNumber ==
-			    unsafe_channel_list[i]) {
-				/* Found unsafe channel, update it */
-				safe_channels[j].isSafe = false;
-				QDF_TRACE(QDF_MODULE_ID_SAP,
-					  QDF_TRACE_LEVEL_DEBUG,
-					  FL("CH %d is not safe"),
-					  unsafe_channel_list[i]);
-				break;
-			}
-		}
-	}
-
-	return;
-}
-
-#endif /* FEATURE_WLAN_CH_AVOID */
-
 /*==========================================================================
    FUNCTION    sap_cleanup_channel_list
 
@@ -635,9 +514,6 @@
 	uint16_t channelnum = 0;
 	tpAniSirGlobal pMac = PMAC_STRUCT(halHandle);
 	bool chSafe = true;
-#ifdef FEATURE_WLAN_CH_AVOID
-	uint16_t i;
-#endif
 	uint32_t dfs_master_cap_enabled;
 	bool include_dfs_ch = true;
 	bool sta_sap_scc_on_dfs_chan =
@@ -704,19 +580,8 @@
 			}
 		}
 
-#ifdef FEATURE_WLAN_CH_AVOID
-		for (i = 0; i < NUM_CHANNELS; i++) {
-			if ((safe_channels[i].channelNumber == *pChans) &&
-			    (false == safe_channels[i].isSafe)) {
-				QDF_TRACE(QDF_MODULE_ID_SAP,
-					  QDF_TRACE_LEVEL_DEBUG,
-					  "In %s, Ch %d is not safe", __func__,
-					  *pChans);
-				chSafe = false;
-				break;
-			}
-		}
-#endif /* FEATURE_WLAN_CH_AVOID */
+		if (!cds_is_safe_channel(*pChans))
+			chSafe = false;
 
 		/* OFDM rates are not supported on channel 14 */
 		if (*pChans == 14 &&
@@ -2556,101 +2421,6 @@
 	return false;
 }
 
-#ifdef FEATURE_WLAN_CH_AVOID
-/**
- * sap_select_channel_no_scan_result() - select SAP channel when no scan results
- * are available.
- * @sap_ctx: Sap context
- *
- * Returns: channel number if success, 0 otherwise
- */
-static uint8_t sap_select_channel_no_scan_result(tHalHandle hal,
-						 ptSapContext sap_ctx)
-{
-	enum channel_state ch_type;
-	uint8_t i, first_safe_ch_in_range = SAP_CHANNEL_NOT_SELECTED;
-	uint32_t dfs_master_cap_enabled;
-	uint32_t start_ch_num = sap_ctx->acs_cfg->start_ch;
-	uint32_t end_ch_num = sap_ctx->acs_cfg->end_ch;
-
-	QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO_HIGH,
-		  FL("start - end: %d - %d"), start_ch_num, end_ch_num);
-
-	sme_cfg_get_int(hal, WNI_CFG_DFS_MASTER_ENABLED,
-				&dfs_master_cap_enabled);
-
-	QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO_HIGH,
-		"%s: dfs_master %x", __func__, dfs_master_cap_enabled);
-
-	/* get a channel in PCL and within the range */
-	for (i = 0; i < sap_ctx->acs_cfg->pcl_ch_count; i++) {
-		if ((sap_ctx->acs_cfg->pcl_channels[i] < start_ch_num) ||
-		    (sap_ctx->acs_cfg->pcl_channels[i] > end_ch_num))
-			continue;
-
-		first_safe_ch_in_range = sap_ctx->acs_cfg->pcl_channels[i];
-		break;
-	}
-
-	if (SAP_CHANNEL_NOT_SELECTED != first_safe_ch_in_range)
-		return first_safe_ch_in_range;
-
-	for (i = 0; i < NUM_CHANNELS; i++) {
-		if ((safe_channels[i].channelNumber < start_ch_num) ||
-		    (safe_channels[i].channelNumber > end_ch_num))
-			continue;
-
-		ch_type = cds_get_channel_state(safe_channels[i].channelNumber);
-
-		if ((ch_type == CHANNEL_STATE_DISABLE) ||
-			(ch_type == CHANNEL_STATE_INVALID))
-			continue;
-		if ((!dfs_master_cap_enabled) &&
-			(CHANNEL_STATE_DFS == ch_type)) {
-			QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO_HIGH,
-				"%s: DFS master mode disabled. Skip DFS channel %d",
-				__func__, safe_channels[i].channelNumber);
-			continue;
-		}
-		if ((sap_ctx->dfs_mode == ACS_DFS_MODE_DISABLE) &&
-		    (CHANNEL_STATE_DFS == ch_type))
-			continue;
-
-		if (safe_channels[i].isSafe == true) {
-			QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO_HIGH,
-				FL("channel %d in the configuration is safe"),
-				safe_channels[i].channelNumber);
-			first_safe_ch_in_range = safe_channels[i].channelNumber;
-			break;
-		}
-
-		QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO_HIGH,
-			FL("channel %d in the configuration is unsafe"),
-			safe_channels[i].channelNumber);
-	}
-
-	/* if no channel selected return SAP_CHANNEL_NOT_SELECTED */
-	return first_safe_ch_in_range;
-}
-#else
-static uint8_t sap_select_channel_no_scan_result(tHalHandle hal,
-						 ptSapContext sap_ctx)
-{
-	uint32_t start_ch_num = sap_ctx->acs_cfg->start_ch;
-
-	QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO_HIGH,
-		  FL("start - end: %d - %d"),
-		  start_ch_num,
-		  sap_ctx->acs_cfg->end_ch);
-
-	sap_ctx->acs_cfg->pri_ch = start_ch_num;
-	sap_ctx->acs_cfg->ht_sec_ch = 0;
-
-	/* pick the first channel in configured range */
-	return start_ch_num;
-}
-#endif /* FEATURE_WLAN_CH_AVOID */
-
 /**
  * sap_select_channel() - select SAP channel
  * @hal: Pointer to HAL handle
@@ -2677,10 +2447,6 @@
 	QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO_HIGH,
 		  "In %s, Running SAP Ch Select", __func__);
 
-#ifdef FEATURE_WLAN_CH_AVOID
-	sap_update_unsafe_channel_list(sap_ctx);
-#endif
-
 	/*
 	 * If ACS weight is not enabled on noise_floor/channel_free/tx_power,
 	 * then skip acs process if no bss found.
@@ -2693,7 +2459,7 @@
 #ifndef SOFTAP_CHANNEL_RANGE
 		return SAP_CHANNEL_NOT_SELECTED;
 #else
-		return sap_select_channel_no_scan_result(hal, sap_ctx);
+		return sap_select_default_oper_chan(sap_ctx->acs_cfg);
 #endif
 	}
 
diff --git a/drivers/staging/qcacld-3.0/core/sap/src/sap_fsm.c b/drivers/staging/qcacld-3.0/core/sap/src/sap_fsm.c
index d33ee91..803054c 100644
--- a/drivers/staging/qcacld-3.0/core/sap/src/sap_fsm.c
+++ b/drivers/staging/qcacld-3.0/core/sap/src/sap_fsm.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -67,10 +67,6 @@
 /*----------------------------------------------------------------------------
  *  External declarations for global context
  * -------------------------------------------------------------------------*/
-#ifdef FEATURE_WLAN_CH_AVOID
-extern sapSafeChannelType safe_channels[];
-#endif /* FEATURE_WLAN_CH_AVOID */
-
 /*----------------------------------------------------------------------------
  * Static Variable Definitions
  * -------------------------------------------------------------------------*/
@@ -2355,6 +2351,9 @@
 					"%s: Override ch %d to %d due to CC Intf",
 					__func__, sap_context->channel, con_ch);
 				sap_context->channel = con_ch;
+				if (CDS_IS_CHANNEL_24GHZ(con_ch))
+					sap_context->ch_params.ch_width =
+								CH_WIDTH_20MHZ;
 				cds_set_channel_params(sap_context->channel, 0,
 						&sap_context->ch_params);
 			}
@@ -2407,6 +2406,9 @@
 						__func__, sap_context->channel,
 						con_ch);
 				sap_context->channel = con_ch;
+				if (CDS_IS_CHANNEL_24GHZ(con_ch))
+					sap_context->ch_params.ch_width =
+								CH_WIDTH_20MHZ;
 				cds_set_channel_params(sap_context->channel, 0,
 						&sap_context->ch_params);
 			}
@@ -4866,9 +4868,7 @@
 	uint8_t end_ch_num, band_end_ch;
 	uint32_t en_lte_coex;
 	tHalHandle hal = CDS_GET_HAL_CB(sap_ctx->p_cds_gctx);
-#ifdef FEATURE_WLAN_CH_AVOID
 	uint8_t i;
-#endif
 	tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
 	tSapChSelSpectInfo spect_info_obj = { NULL, 0 };
 	uint16_t ch_width;
@@ -4970,13 +4970,6 @@
 				continue;
 		}
 
-#ifdef FEATURE_WLAN_CH_AVOID
-		for (i = 0; i < NUM_CHANNELS; i++) {
-			if (safe_channels[i].channelNumber ==
-			     CDS_CHANNEL_NUM(loop_count)) {
-				/* Check if channel is safe */
-				if (true == safe_channels[i].isSafe) {
-#endif
 #ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
 		uint8_t ch;
 
@@ -5013,12 +5006,6 @@
 		list[ch_count] = CDS_CHANNEL_NUM(loop_count);
 		ch_count++;
 #endif
-#ifdef FEATURE_WLAN_CH_AVOID
-				}
-				break;
-			}
-		}
-#endif
 	}
 
 	for (i = 0; i < ch_count; i++) {
diff --git a/drivers/staging/qcacld-3.0/core/sap/src/sap_internal.h b/drivers/staging/qcacld-3.0/core/sap/src/sap_internal.h
index 24991f1..5ad7c5f 100644
--- a/drivers/staging/qcacld-3.0/core/sap/src/sap_internal.h
+++ b/drivers/staging/qcacld-3.0/core/sap/src/sap_internal.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -374,10 +374,6 @@
 
 QDF_STATUS sap_release_global_lock(ptSapContext pSapCtx);
 
-#ifdef FEATURE_WLAN_CH_AVOID
-void sap_update_unsafe_channel_list(ptSapContext pSapCtx);
-#endif /* FEATURE_WLAN_CH_AVOID */
-
 uint8_t
 sap_indicate_radar(ptSapContext sapContext,
 		 tSirSmeDfsEventInd *dfs_event);
diff --git a/drivers/staging/qcacld-3.0/core/wma/src/wma_dev_if.c b/drivers/staging/qcacld-3.0/core/wma/src/wma_dev_if.c
index 0c8cc381..42c403b 100644
--- a/drivers/staging/qcacld-3.0/core/wma/src/wma_dev_if.c
+++ b/drivers/staging/qcacld-3.0/core/wma/src/wma_dev_if.c
@@ -570,6 +570,29 @@
 	iface->is_vdev_valid = false;
 }
 
+/*
+ * wma_handle_monitor_mode_vdev_detach() - Stop and down monitor mode vdev
+ * @wma_handle: wma handle
+ * @vdev_id: used to get wma interface txrx node
+ *
+ * Monitor mode is unconneted mode, so do explicit vdev stop and down
+ *
+ * Return: None
+ */
+static void wma_handle_monitor_mode_vdev_detach(tp_wma_handle wma,
+						uint8_t vdev_id)
+{
+	if (wma_send_vdev_stop_to_fw(wma, vdev_id)) {
+		WMA_LOGE("%s: %d Failed to send vdev stop", __func__, __LINE__);
+		wma_remove_vdev_req(wma, vdev_id,
+				    WMA_TARGET_REQ_TYPE_VDEV_STOP);
+	}
+
+	if (wma_send_vdev_down_to_fw(wma, vdev_id) != QDF_STATUS_SUCCESS)
+		WMA_LOGE("Failed to send vdev down cmd: vdev %d", vdev_id);
+}
+
+
 static QDF_STATUS wma_handle_vdev_detach(tp_wma_handle wma_handle,
 			struct del_sta_self_params *del_sta_self_req_param,
 			uint8_t generate_rsp)
@@ -579,6 +602,9 @@
 	struct wma_txrx_node *iface = &wma_handle->interfaces[vdev_id];
 	struct wma_target_req *msg = NULL;
 
+	if (cds_get_conparam() == QDF_GLOBAL_MONITOR_MODE)
+		wma_handle_monitor_mode_vdev_detach(wma_handle, vdev_id);
+
 	status = wmi_unified_vdev_delete_send(wma_handle->wmi_handle, vdev_id);
 	if (QDF_IS_STATUS_ERROR(status)) {
 		WMA_LOGE("Unable to remove an interface");
@@ -685,9 +711,10 @@
 	if (iface->type == WMI_VDEV_TYPE_STA)
 		wma_pno_stop(wma_handle, vdev_id);
 
-	/* P2P Device */
-	if ((iface->type == WMI_VDEV_TYPE_AP) &&
-	    (iface->sub_type == WMI_UNIFIED_VDEV_SUBTYPE_P2P_DEVICE)) {
+	if (((iface->type == WMI_VDEV_TYPE_AP) &&
+	    (iface->sub_type == WMI_UNIFIED_VDEV_SUBTYPE_P2P_DEVICE)) ||
+	    (iface->type == WMI_VDEV_TYPE_OCB) ||
+	    (iface->type == WMI_VDEV_TYPE_MONITOR)) {
 		status = wma_self_peer_remove(wma_handle,
 					pdel_sta_self_req_param, generateRsp);
 		if ((status != QDF_STATUS_SUCCESS) && generateRsp) {
@@ -1909,6 +1936,10 @@
 		return -EINVAL;
 	}
 
+	/* Ignore stop_response in Monitor mode */
+	if (cds_get_conparam() == QDF_GLOBAL_MONITOR_MODE)
+		return  QDF_STATUS_SUCCESS;
+
 	iface = &wma->interfaces[resp_event->vdev_id];
 	/*
 	 * Reset the rmfEnabled as there might be MGMT action frames
diff --git a/net/core/sockev_nlmcast.c b/net/core/sockev_nlmcast.c
index 749ffb8..b9a47d4 100644
--- a/net/core/sockev_nlmcast.c
+++ b/net/core/sockev_nlmcast.c
@@ -68,14 +68,17 @@
 	struct nlmsghdr *nlh;
 	struct sknlsockevmsg *smsg;
 	struct socket *sock;
+	struct sock *sk;
 
 	sock = (struct socket *)data;
-	if (socknlmsgsk == 0)
-		goto done;
-	if ((socknlmsgsk == NULL) || (sock == NULL) || (sock->sk == NULL))
+	if (!socknlmsgsk || !sock)
 		goto done;
 
-	if (sock->sk->sk_family != AF_INET && sock->sk->sk_family != AF_INET6)
+	sk = sock->sk;
+	if (!sk)
+		goto done;
+
+	if (sk->sk_family != AF_INET && sk->sk_family != AF_INET6)
 		goto done;
 
 	if (event != SOCKEV_BIND && event != SOCKEV_LISTEN)
@@ -96,12 +99,11 @@
 	smsg = nlmsg_data(nlh);
 	smsg->pid = current->pid;
 	_sockev_event(event, smsg->event, sizeof(smsg->event));
-	smsg->skfamily = sock->sk->sk_family;
-	smsg->skstate = sock->sk->sk_state;
-	smsg->skprotocol = sock->sk->sk_protocol;
-	smsg->sktype = sock->sk->sk_type;
-	smsg->skflags = sock->sk->sk_flags;
-
+	smsg->skfamily = sk->sk_family;
+	smsg->skstate = sk->sk_state;
+	smsg->skprotocol = sk->sk_protocol;
+	smsg->sktype = sk->sk_type;
+	smsg->skflags = sk->sk_flags;
 	nlmsg_notify(socknlmsgsk, skb, 0, SKNLGRP_SOCKEV, 0, GFP_KERNEL);
 done:
 	return 0;
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-loopback-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-loopback-v2.c
index b8610b5..307480d 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-loopback-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-loopback-v2.c
@@ -1,5 +1,5 @@
-/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
-
+/* Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
+*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * only version 2 as published by the Free Software Foundation.
@@ -136,6 +136,7 @@
 		goto done;
 	}
 
+	mutex_lock(&loopback_session_lock);
 	pr_debug("%s: mute=%d\n", __func__, mute);
 	hfp_tx_mute = mute;
 	for (n = 0; n < LOOPBACK_SESSION_MAX; n++) {
@@ -148,6 +149,7 @@
 			pr_err("%s: Send mute command failed rc=%d\n",
 				__func__, ret);
 	}
+	mutex_unlock(&loopback_session_lock);
 done:
 	return ret;
 }
@@ -350,6 +352,8 @@
 
 	if (pcm->audio_client == NULL)
 		return;
+
+	mutex_lock(&loopback_session_lock);
 	q6asm_cmd(pcm->audio_client, CMD_CLOSE);
 
 	if (pcm->playback_substream != NULL) {
@@ -364,6 +368,7 @@
 	}
 	q6asm_audio_client_free(pcm->audio_client);
 	pcm->audio_client = NULL;
+	mutex_unlock(&loopback_session_lock);
 }
 
 static int msm_pcm_close(struct snd_pcm_substream *substream)
@@ -494,12 +499,15 @@
 		rc = -ENODEV;
 		goto exit;
 	}
+	mutex_lock(&loopback_session_lock);
 	prtd = substream->runtime->private_data;
 	if (!prtd) {
 		rc = -ENODEV;
+		mutex_unlock(&loopback_session_lock);
 		goto exit;
 	}
 	rc = pcm_loopback_set_volume(prtd, volume);
+	mutex_unlock(&loopback_session_lock);
 
 exit:
 	return rc;
@@ -520,12 +528,15 @@
 		rc = -ENODEV;
 		goto exit;
 	}
+	mutex_lock(&loopback_session_lock);
 	prtd = substream->runtime->private_data;
 	if (!prtd) {
 		rc = -ENODEV;
+		mutex_unlock(&loopback_session_lock);
 		goto exit;
 	}
 	ucontrol->value.integer.value[0] = prtd->volume;
+	mutex_unlock(&loopback_session_lock);
 
 exit:
 	return rc;
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c
index 69d8bca..3f55335 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017, 2019 The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -15,6 +15,7 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/time.h>
+#include <linux/mutex.h>
 #include <linux/wait.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
@@ -583,6 +584,7 @@
 
 static int msm_pcm_close(struct snd_pcm_substream *substream)
 {
+	struct msm_plat_data *pdata = NULL;
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
 	struct msm_audio *prtd = runtime->private_data;
@@ -591,6 +593,20 @@
 	int dir = 0;
 	int ret = 0;
 
+	if (!soc_prtd) {
+		pr_debug("%s private_data not found\n",
+			__func__);
+		return 0;
+	}
+
+	pdata = (struct msm_plat_data *)
+			dev_get_drvdata(soc_prtd->platform->dev);
+	if (!pdata) {
+		pr_err("%s: pdata not found\n", __func__);
+		return -ENODEV;
+	}
+
+	mutex_lock(&pdata->lock);
 	if (ac) {
 		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 			dir = IN;
@@ -625,6 +641,7 @@
 					 SNDRV_PCM_STREAM_CAPTURE);
 	kfree(prtd);
 	runtime->private_data = NULL;
+	mutex_unlock(&pdata->lock);
 
 	return 0;
 }
@@ -649,8 +666,10 @@
 		      struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_pcm_volume *vol = snd_kcontrol_chip(kcontrol);
+	struct msm_plat_data *pdata = NULL;
 	struct snd_pcm_substream *substream =
 		vol->pcm->streams[vol->stream].substream;
+	struct snd_soc_pcm_runtime *soc_prtd = NULL;
 	struct msm_audio *prtd;
 
 	pr_debug("%s\n", __func__);
@@ -658,13 +677,24 @@
 		pr_err("%s substream not found\n", __func__);
 		return -ENODEV;
 	}
-	if (!substream->runtime) {
-		pr_err("%s substream runtime not found\n", __func__);
+	soc_prtd = substream->private_data;
+	if (!substream->runtime || !soc_prtd) {
+		pr_debug("%s substream runtime or private_data not found\n",
+				 __func__);
 		return 0;
 	}
+
+	pdata = (struct msm_plat_data *)
+			dev_get_drvdata(soc_prtd->platform->dev);
+	if (!pdata) {
+		pr_err("%s: pdata not found\n", __func__);
+		return -ENODEV;
+	}
+	mutex_lock(&pdata->lock);
 	prtd = substream->runtime->private_data;
 	if (prtd)
 		ucontrol->value.integer.value[0] = prtd->volume;
+	mutex_unlock(&pdata->lock);
 	return 0;
 }
 
@@ -673,8 +703,10 @@
 {
 	int rc = 0;
 	struct snd_pcm_volume *vol = snd_kcontrol_chip(kcontrol);
+	struct msm_plat_data *pdata = NULL;
 	struct snd_pcm_substream *substream =
 		vol->pcm->streams[vol->stream].substream;
+	struct snd_soc_pcm_runtime *soc_prtd = NULL;
 	struct msm_audio *prtd;
 	int volume = ucontrol->value.integer.value[0];
 
@@ -683,15 +715,26 @@
 		pr_err("%s substream not found\n", __func__);
 		return -ENODEV;
 	}
-	if (!substream->runtime) {
-		pr_err("%s substream runtime not found\n", __func__);
+	soc_prtd = substream->private_data;
+	if (!substream->runtime || !soc_prtd) {
+		pr_err("%s substream runtime or private_data not found\n",
+				 __func__);
 		return 0;
 	}
+
+	pdata = (struct msm_plat_data *)
+			dev_get_drvdata(soc_prtd->platform->dev);
+	if (!pdata) {
+		pr_err("%s: pdata not found\n", __func__);
+		return -ENODEV;
+	}
+	mutex_lock(&pdata->lock);
 	prtd = substream->runtime->private_data;
 	if (prtd) {
 		rc = msm_pcm_set_volume(prtd, volume);
 		prtd->volume = volume;
 	}
+	mutex_unlock(&pdata->lock);
 	return rc;
 }
 
@@ -1255,6 +1298,8 @@
 
 	pdata->perf_mode = perf_mode;
 
+	mutex_init(&pdata->lock);
+
 	dev_set_drvdata(&pdev->dev, pdata);
 
 	dev_dbg(&pdev->dev, "%s: dev name %s\n",
@@ -1275,6 +1320,7 @@
 
 	dev_dbg(&pdev->dev, "Pull mode remove\n");
 	pdata = dev_get_drvdata(&pdev->dev);
+	mutex_destroy(&pdata->lock);
 	devm_kfree(&pdev->dev, pdata);
 	snd_soc_unregister_platform(&pdev->dev);
 	return 0;
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
index 2175202..0a20cfc 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
@@ -16,6 +16,7 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/time.h>
+#include <linux/mutex.h>
 #include <linux/wait.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
@@ -814,13 +815,21 @@
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
 	struct msm_audio *prtd = runtime->private_data;
-	struct msm_plat_data *pdata;
+	struct msm_plat_data *pdata = NULL;
 	uint32_t timeout;
 	int dir = 0;
 	int ret = 0;
 
 	pr_debug("%s: cmd_pending 0x%lx\n", __func__, prtd->cmd_pending);
 
+	pdata = (struct msm_plat_data *)
+			dev_get_drvdata(soc_prtd->platform->dev);
+	if (!pdata) {
+		pr_err("%s: platform data is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	mutex_lock(&pdata->lock);
 	if (prtd->audio_client) {
 		dir = IN;
 
@@ -828,12 +837,9 @@
 		 * Unvote to downgrade the Rx thread priority from
 		 * RT Thread for Low-Latency use case.
 		 */
-		pdata = (struct msm_plat_data *)
-			dev_get_drvdata(soc_prtd->platform->dev);
-		if (pdata) {
-			if (pdata->perf_mode == LOW_LATENCY_PCM_MODE)
-				apr_end_rx_rt(prtd->audio_client->apr);
-		}
+		if (pdata->perf_mode == LOW_LATENCY_PCM_MODE)
+			apr_end_rx_rt(prtd->audio_client->apr);
+
 		/* determine timeout length */
 		if (runtime->frame_bits == 0 || runtime->rate == 0) {
 			timeout = CMD_EOS_MIN_TIMEOUT_LENGTH;
@@ -862,7 +868,7 @@
 						SNDRV_PCM_STREAM_PLAYBACK);
 	kfree(prtd);
 	runtime->private_data = NULL;
-
+	mutex_unlock(&pdata->lock);
 	return 0;
 }
 
@@ -956,8 +962,18 @@
 	struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
 	struct msm_audio *prtd = runtime->private_data;
 	int dir = OUT;
+	struct msm_plat_data *pdata = NULL;
 
 	pr_debug("%s\n", __func__);
+
+	pdata = (struct msm_plat_data *)
+			dev_get_drvdata(soc_prtd->platform->dev);
+	if (!pdata) {
+		pr_err("%s: platform data is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	mutex_lock(&pdata->lock);
 	if (prtd->audio_client) {
 		q6asm_cmd(prtd->audio_client, CMD_CLOSE);
 		q6asm_audio_client_buf_free_contiguous(dir,
@@ -969,6 +985,7 @@
 		SNDRV_PCM_STREAM_CAPTURE);
 	kfree(prtd);
 	runtime->private_data = NULL;
+	mutex_unlock(&pdata->lock);
 
 	return 0;
 }
@@ -1107,10 +1124,10 @@
 
 	if (!pdata) {
 		pr_err("%s pdata is NULL\n", __func__);
-		ret = -ENODEV;
-		goto done;
+		return -ENODEV;
 	}
 
+	mutex_lock(&pdata->lock);
 	substream = pdata->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
 	if (!substream) {
 		pr_err("%s substream not found\n", __func__);
@@ -1159,6 +1176,7 @@
 		pr_err("%s: failed to register pp event. err = %d\n",
 			__func__, ret);
 done:
+	mutex_unlock(&pdata->lock);
 	return ret;
 }
 
@@ -1296,8 +1314,10 @@
 		      struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_pcm_volume *vol = snd_kcontrol_chip(kcontrol);
+	struct msm_plat_data *pdata = NULL;
 	struct snd_pcm_substream *substream =
 		vol->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
+	struct snd_soc_pcm_runtime *soc_prtd = NULL;
 	struct msm_audio *prtd;
 
 	pr_debug("%s\n", __func__);
@@ -1305,13 +1325,25 @@
 		pr_err("%s substream not found\n", __func__);
 		return -ENODEV;
 	}
-	if (!substream->runtime) {
-		pr_err("%s substream runtime not found\n", __func__);
+	soc_prtd = substream->private_data;
+	if (!substream->runtime || !soc_prtd) {
+		pr_debug("%s substream runtime or private_data not found\n",
+				 __func__);
 		return 0;
 	}
+
+	pdata = (struct msm_plat_data *)
+			dev_get_drvdata(soc_prtd->platform->dev);
+	if (!pdata) {
+		pr_err("%s: pdata not found\n", __func__);
+		return -ENODEV;
+	}
+
+	mutex_lock(&pdata->lock);
 	prtd = substream->runtime->private_data;
 	if (prtd)
 		ucontrol->value.integer.value[0] = prtd->volume;
+	mutex_unlock(&pdata->lock);
 	return 0;
 }
 
@@ -1323,6 +1355,8 @@
 	struct snd_pcm_substream *substream =
 		vol->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
 	struct msm_audio *prtd;
+	struct snd_soc_pcm_runtime *soc_prtd = NULL;
+	struct msm_plat_data *pdata = NULL;
 	int volume = ucontrol->value.integer.value[0];
 
 	pr_debug("%s: volume : 0x%x\n", __func__, volume);
@@ -1334,11 +1368,26 @@
 		pr_err("%s substream runtime not found\n", __func__);
 		return 0;
 	}
+
+	soc_prtd = substream->private_data;
+	if (!soc_prtd) {
+		pr_err("%s: soc_prtd is NULL\n", __func__);
+		return -ENODEV;
+	}
+	pdata = (struct msm_plat_data *)
+			dev_get_drvdata(soc_prtd->platform->dev);
+	if (!pdata) {
+		pr_err("%s: pdata not found\n", __func__);
+		return -ENODEV;
+	}
+
+	mutex_lock(&pdata->lock);
 	prtd = substream->runtime->private_data;
 	if (prtd) {
 		rc = msm_pcm_set_volume(prtd, volume);
 		prtd->volume = volume;
 	}
+	mutex_unlock(&pdata->lock);
 	return rc;
 }
 
@@ -1396,9 +1445,11 @@
 		pr_err("%s substream runtime not found\n", __func__);
 		return 0;
 	}
+	mutex_lock(&pdata->lock);
 	prtd = substream->runtime->private_data;
 	if (prtd)
 		ucontrol->value.integer.value[0] = prtd->compress_enable;
+	mutex_unlock(&pdata->lock);
 	return 0;
 }
 
@@ -1427,12 +1478,14 @@
 		pr_err("%s substream runtime not found\n", __func__);
 		return 0;
 	}
+	mutex_lock(&pdata->lock);
 	prtd = substream->runtime->private_data;
 	if (prtd) {
 		pr_debug("%s: setting compress flag to 0x%x\n",
 		__func__, compress);
 		prtd->compress_enable = compress;
 	}
+	mutex_unlock(&pdata->lock);
 	return rc;
 }
 
@@ -1501,15 +1554,30 @@
 	struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
 	unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
 	struct snd_pcm_substream *substream;
+	struct snd_soc_pcm_runtime *rtd = NULL;
+	struct msm_plat_data *pdata = NULL;
 	struct msm_audio *prtd;
 
 	pr_debug("%s", __func__);
 	substream = snd_pcm_chmap_substream(info, idx);
 	if (!substream)
 		return -ENODEV;
-	if (!substream->runtime)
+
+	rtd = substream->private_data;
+	if (rtd) {
+		pdata = (struct msm_plat_data *)
+					dev_get_drvdata(rtd->platform->dev);
+		if (!pdata) {
+			pr_err("%s: pdata not found\n", __func__);
+			return -ENODEV;
+		}
+	}
+
+	if (!substream->runtime || !rtd)
 		return 0;
 
+	mutex_lock(&pdata->lock);
+
 	prtd = substream->runtime->private_data;
 	if (prtd) {
 		prtd->set_channel_map = true;
@@ -1517,6 +1585,7 @@
 				prtd->channel_map[i] =
 				(char)(ucontrol->value.integer.value[i]);
 	}
+	mutex_unlock(&pdata->lock);
 	return 0;
 }
 
@@ -1528,16 +1597,30 @@
 	unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
 	struct snd_pcm_substream *substream;
 	struct msm_audio *prtd;
+	struct snd_soc_pcm_runtime *rtd = NULL;
+	struct msm_plat_data *pdata = NULL;
 
 	pr_debug("%s", __func__);
 	substream = snd_pcm_chmap_substream(info, idx);
 	if (!substream)
 		return -ENODEV;
+
+	rtd = substream->private_data;
+	if (rtd) {
+		pdata = (struct msm_plat_data *)
+			dev_get_drvdata(rtd->platform->dev);
+		if (!pdata) {
+			pr_err("%s: pdata not found\n", __func__);
+			return -ENODEV;
+		}
+	}
+
 	memset(ucontrol->value.integer.value, 0,
 		sizeof(ucontrol->value.integer.value));
-	if (!substream->runtime)
+	if (!substream->runtime || !rtd)
 		return 0; /* no channels set */
 
+	mutex_lock(&pdata->lock);
 	prtd = substream->runtime->private_data;
 
 	if (prtd && prtd->set_channel_map == true) {
@@ -1549,6 +1632,7 @@
 			ucontrol->value.integer.value[i] = 0;
 	}
 
+	mutex_unlock(&pdata->lock);
 	return 0;
 }
 
@@ -1873,6 +1957,7 @@
 	else
 		pdata->perf_mode = LEGACY_PCM_MODE;
 
+	mutex_init(&pdata->lock);
 	dev_set_drvdata(&pdev->dev, pdata);
 
 
@@ -1887,6 +1972,7 @@
 	struct msm_plat_data *pdata;
 
 	pdata = dev_get_drvdata(&pdev->dev);
+	mutex_destroy(&pdata->lock);
 	kfree(pdata);
 	snd_soc_unregister_platform(&pdev->dev);
 	return 0;
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h
index f5ff63f..6a732f7 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h
@@ -125,6 +125,7 @@
 struct msm_plat_data {
 	int perf_mode;
 	struct snd_pcm *pcm;
+	struct mutex lock;
 };
 
 #endif /*_MSM_PCM_H*/