Merge "msm: ipa: add support for WDI 3.0"
diff --git a/arch/arm64/boot/dts/qcom/sdm670.dtsi b/arch/arm64/boot/dts/qcom/sdm670.dtsi
index 0774aad..2ab77e5 100644
--- a/arch/arm64/boot/dts/qcom/sdm670.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670.dtsi
@@ -2437,7 +2437,7 @@
 			< MHZ_TO_MBPS(1804, 4) >; /* 6881 MB/s */
 	};
 
-	memlat_cpu4: qcom,memlat-cpu4 {
+	memlat_cpu6: qcom,memlat-cpu6 {
 		compatible = "qcom,devbw";
 		governor = "powersave";
 		qcom,src-dst-ports = <1 512>;
@@ -2459,9 +2459,9 @@
 
 	devfreq_memlat_0: qcom,cpu0-memlat-mon {
 		compatible = "qcom,arm-memlat-mon";
-		qcom,cpulist = <&CPU0 &CPU1 &CPU2 &CPU3>;
+		qcom,cpulist = <&CPU0 &CPU1 &CPU2 &CPU3 &CPU4 &CPU5>;
 		qcom,target-dev = <&memlat_cpu0>;
-		qcom,cachemiss-ev = <0x24>;
+		qcom,cachemiss-ev = <0x2a>;
 		qcom,core-dev-table =
 			<  748800 MHZ_TO_MBPS( 300, 4) >,
 			<  998400 MHZ_TO_MBPS( 451, 4) >,
@@ -2470,11 +2470,11 @@
 			< 1728000 MHZ_TO_MBPS(1017, 4) >;
 	};
 
-	devfreq_memlat_4: qcom,cpu4-memlat-mon {
+	devfreq_memlat_6: qcom,cpu6-memlat-mon {
 		compatible = "qcom,arm-memlat-mon";
-		qcom,cpulist = <&CPU4 &CPU5 &CPU6 &CPU7>;
-		qcom,target-dev = <&memlat_cpu4>;
-		qcom,cachemiss-ev = <0x24>;
+		qcom,cpulist = <&CPU6 &CPU7>;
+		qcom,target-dev = <&memlat_cpu6>;
+		qcom,cachemiss-ev = <0x2a>;
 		qcom,core-dev-table =
 			<  787200 MHZ_TO_MBPS( 300, 4) >,
 			< 1113600 MHZ_TO_MBPS( 547, 4) >,
@@ -2490,7 +2490,7 @@
 		governor = "performance";
 	};
 
-	l3_cpu4: qcom,l3-cpu4 {
+	l3_cpu6: qcom,l3-cpu6 {
 		compatible = "devfreq-simple-dev";
 		clock-names = "devfreq_clk";
 		clocks = <&clock_cpucc L3_CLUSTER1_VOTE_CLK>;
@@ -2499,7 +2499,7 @@
 
 	devfreq_l3lat_0: qcom,cpu0-l3lat-mon {
 		compatible = "qcom,arm-memlat-mon";
-		qcom,cpulist = <&CPU0 &CPU1 &CPU2 &CPU3>;
+		qcom,cpulist = <&CPU0 &CPU1 &CPU2 &CPU3 &CPU4 &CPU5>;
 		qcom,target-dev = <&l3_cpu0>;
 		qcom,cachemiss-ev = <0x17>;
 		qcom,core-dev-table =
@@ -2511,10 +2511,10 @@
 			< 1728000 1440000000 >;
 	};
 
-	devfreq_l3lat_4: qcom,cpu4-l3lat-mon {
+	devfreq_l3lat_6: qcom,cpu6-l3lat-mon {
 		compatible = "qcom,arm-memlat-mon";
-		qcom,cpulist = <&CPU4 &CPU5 &CPU6 &CPU7>;
-		qcom,target-dev = <&l3_cpu4>;
+		qcom,cpulist = <&CPU6 &CPU7>;
+		qcom,target-dev = <&l3_cpu6>;
 		qcom,cachemiss-ev = <0x17>;
 		qcom,core-dev-table =
 			< 1113600  566400000 >,
@@ -2551,7 +2551,7 @@
 				< 1209600 MHZ_TO_MBPS( 451, 4) >,
 				< 1612000 MHZ_TO_MBPS( 547, 4) >,
 				< 1728000 MHZ_TO_MBPS( 768, 4) >;
-			cpu-to-dev-map-4 =
+			cpu-to-dev-map-6 =
 				< 1113600 MHZ_TO_MBPS( 300, 4) >,
 				< 1344000 MHZ_TO_MBPS( 547, 4) >,
 				< 1728000 MHZ_TO_MBPS( 768, 4) >,
diff --git a/arch/arm64/configs/sdm670_defconfig b/arch/arm64/configs/sdm670_defconfig
index b0d0807..9a811a7 100644
--- a/arch/arm64/configs/sdm670_defconfig
+++ b/arch/arm64/configs/sdm670_defconfig
@@ -447,8 +447,6 @@
 CONFIG_EDAC_MM_EDAC=y
 CONFIG_EDAC_KRYO3XX_ARM64=y
 CONFIG_EDAC_KRYO3XX_ARM64_PANIC_ON_UE=y
-CONFIG_EDAC_QCOM_LLCC=y
-CONFIG_EDAC_QCOM_LLCC_PANIC_ON_UE=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_QPNP=y
 CONFIG_DMADEVICES=y
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 543f0a2..54e6486 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -1304,11 +1304,9 @@
 		mutex_unlock(&driver->md_session_lock);
 		return -ENOMEM;
 	}
-
 	new_session->peripheral_mask = 0;
 	new_session->pid = current->tgid;
 	new_session->task = current;
-
 	new_session->log_mask = kzalloc(sizeof(struct diag_mask_info),
 					GFP_KERNEL);
 	if (!new_session->log_mask) {
@@ -1426,7 +1424,6 @@
 struct diag_md_session_t *diag_md_session_get_pid(int pid)
 {
 	int i;
-
 	for (i = 0; i < NUM_MD_SESSIONS; i++) {
 		if (driver->md_session_map[i] &&
 		    driver->md_session_map[i]->pid == pid)
@@ -1542,7 +1539,10 @@
 		 * If this session owns all the requested peripherals, then
 		 * call function to switch the modes/masks for the md_session
 		 */
+		mutex_lock(&driver->md_session_lock);
 		session_info = diag_md_session_get_pid(current->tgid);
+		mutex_unlock(&driver->md_session_lock);
+
 		if (!session_info) {
 			*change_mode = 1;
 			return 0;
@@ -1571,7 +1571,9 @@
 		 * owned by this md session
 		 */
 		change_mask = driver->md_session_mask & param->peripheral_mask;
+		mutex_lock(&driver->md_session_lock);
 		session_info = diag_md_session_get_pid(current->tgid);
+		mutex_unlock(&driver->md_session_lock);
 
 		if (session_info) {
 			if ((session_info->peripheral_mask & change_mask)
@@ -1999,8 +2001,9 @@
 {
 	uint8_t hdlc_support;
 	struct diag_md_session_t *session_info = NULL;
-
+	mutex_lock(&driver->md_session_lock);
 	session_info = diag_md_session_get_pid(current->tgid);
+	mutex_unlock(&driver->md_session_lock);
 	if (copy_from_user(&hdlc_support, (void __user *)ioarg,
 				sizeof(uint8_t)))
 		return -EFAULT;
@@ -2768,10 +2771,13 @@
 	} else {
 		wait_event_interruptible(driver->wait_q,
 					 (driver->in_busy_pktdata == 0));
+		mutex_lock(&driver->md_session_lock);
 		info = diag_md_session_get_pid(current->tgid);
+		mutex_unlock(&driver->md_session_lock);
 		ret = diag_process_apps_pkt(user_space_data, len, info);
 		if (ret == 1)
-			diag_send_error_rsp((void *)(user_space_data), len);
+			diag_send_error_rsp((void *)(user_space_data), len,
+						info);
 	}
 fail:
 	diagmem_free(driver, user_space_data, mempool);
@@ -2835,7 +2841,9 @@
 
 	/* send masks to local processor now */
 	if (!remote_proc) {
+		mutex_lock(&driver->md_session_lock);
 		session_info = diag_md_session_get_pid(current->tgid);
+		mutex_unlock(&driver->md_session_lock);
 		if (!session_info) {
 			pr_err("diag:In %s request came from invalid md session pid:%d",
 				__func__, current->tgid);
@@ -3010,7 +3018,9 @@
 			goto exit;
 		/* place holder for number of data field */
 		ret += sizeof(int);
+		mutex_lock(&driver->md_session_lock);
 		session_info = diag_md_session_get_pid(current->tgid);
+		mutex_unlock(&driver->md_session_lock);
 		exit_stat = diag_md_copy_to_user(buf, &ret, count,
 						 session_info);
 		goto exit;
@@ -3028,7 +3038,9 @@
 		if (ret == -EFAULT)
 			goto exit;
 
+		mutex_lock(&driver->md_session_lock);
 		session_info = diag_md_session_get_pid(current->tgid);
+		mutex_unlock(&driver->md_session_lock);
 		if (session_info) {
 			COPY_USER_SPACE_OR_ERR(buf+4,
 					session_info->hdlc_disabled,
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index b59f245..fc67c1a 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -240,10 +240,11 @@
 	}
 }
 
-static void pack_rsp_and_send(unsigned char *buf, int len)
+static void pack_rsp_and_send(unsigned char *buf, int len,
+				struct diag_md_session_t *info)
 {
 	int err;
-	int retry_count = 0;
+	int retry_count = 0, i, rsp_ctxt;
 	uint32_t write_len = 0;
 	unsigned long flags;
 	unsigned char *rsp_ptr = driver->encoded_rsp_buf;
@@ -259,6 +260,26 @@
 	}
 
 	/*
+	 * Explicitly check for the Peripheral Modem here
+	 * is necessary till a way to identify a peripheral
+	 * if its supporting qshrink4 feature.
+	 */
+	if (info && info->peripheral_mask) {
+		if (info->peripheral_mask == DIAG_CON_ALL ||
+			(info->peripheral_mask & (1 << APPS_DATA)) ||
+			(info->peripheral_mask & (1 << PERIPHERAL_MODEM))) {
+			rsp_ctxt = SET_BUF_CTXT(APPS_DATA, TYPE_CMD, 1);
+		} else {
+			for (i = 0; i < NUM_MD_SESSIONS; i++) {
+				if (info->peripheral_mask & (1 << i))
+					break;
+			}
+		rsp_ctxt = SET_BUF_CTXT(i, TYPE_CMD, 1);
+		}
+	} else
+		rsp_ctxt = driver->rsp_buf_ctxt;
+
+	/*
 	 * Keep trying till we get the buffer back. It should probably
 	 * take one or two iterations. When this loops till UINT_MAX, it
 	 * means we did not get a write complete for the previous
@@ -299,8 +320,7 @@
 	*(uint8_t *)(rsp_ptr + write_len) = CONTROL_CHAR;
 	write_len += sizeof(uint8_t);
 
-	err = diag_mux_write(DIAG_LOCAL_PROC, rsp_ptr, write_len,
-			     driver->rsp_buf_ctxt);
+	err = diag_mux_write(DIAG_LOCAL_PROC, rsp_ptr, write_len, rsp_ctxt);
 	if (err) {
 		pr_err("diag: In %s, unable to write to mux, err: %d\n",
 		       __func__, err);
@@ -310,12 +330,13 @@
 	}
 }
 
-static void encode_rsp_and_send(unsigned char *buf, int len)
+static void encode_rsp_and_send(unsigned char *buf, int len,
+				struct diag_md_session_t *info)
 {
 	struct diag_send_desc_type send = { NULL, NULL, DIAG_STATE_START, 0 };
 	struct diag_hdlc_dest_type enc = { NULL, NULL, 0 };
 	unsigned char *rsp_ptr = driver->encoded_rsp_buf;
-	int err, retry_count = 0;
+	int err, i, rsp_ctxt, retry_count = 0;
 	unsigned long flags;
 
 	if (!rsp_ptr || !buf)
@@ -328,6 +349,26 @@
 	}
 
 	/*
+	 * Explicitly check for the Peripheral Modem here
+	 * is necessary till a way to identify a peripheral
+	 * if its supporting qshrink4 feature.
+	 */
+	if (info && info->peripheral_mask) {
+		if (info->peripheral_mask == DIAG_CON_ALL ||
+			(info->peripheral_mask & (1 << APPS_DATA)) ||
+			(info->peripheral_mask & (1 << PERIPHERAL_MODEM))) {
+			rsp_ctxt = SET_BUF_CTXT(APPS_DATA, TYPE_CMD, 1);
+		} else {
+			for (i = 0; i < NUM_MD_SESSIONS; i++) {
+				if (info->peripheral_mask & (1 << i))
+					break;
+			}
+		rsp_ctxt = SET_BUF_CTXT(i, TYPE_CMD, 1);
+		}
+	} else
+		rsp_ctxt = driver->rsp_buf_ctxt;
+
+	/*
 	 * Keep trying till we get the buffer back. It should probably
 	 * take one or two iterations. When this loops till UINT_MAX, it
 	 * means we did not get a write complete for the previous
@@ -370,7 +411,7 @@
 	diag_hdlc_encode(&send, &enc);
 	driver->encoded_rsp_len = (int)(enc.dest - (void *)rsp_ptr);
 	err = diag_mux_write(DIAG_LOCAL_PROC, rsp_ptr, driver->encoded_rsp_len,
-			     driver->rsp_buf_ctxt);
+			     rsp_ctxt);
 	if (err) {
 		pr_err("diag: In %s, Unable to write to device, err: %d\n",
 			__func__, err);
@@ -381,21 +422,23 @@
 	memset(buf, '\0', DIAG_MAX_RSP_SIZE);
 }
 
-void diag_send_rsp(unsigned char *buf, int len)
+static void diag_send_rsp(unsigned char *buf, int len,
+	struct diag_md_session_t *info)
 {
 	struct diag_md_session_t *session_info = NULL;
 	uint8_t hdlc_disabled;
 
-	session_info = diag_md_session_get_peripheral(APPS_DATA);
+	session_info = (info) ? info :
+				diag_md_session_get_peripheral(APPS_DATA);
 	if (session_info)
 		hdlc_disabled = session_info->hdlc_disabled;
 	else
 		hdlc_disabled = driver->hdlc_disabled;
 
 	if (hdlc_disabled)
-		pack_rsp_and_send(buf, len);
+		pack_rsp_and_send(buf, len, session_info);
 	else
-		encode_rsp_and_send(buf, len);
+		encode_rsp_and_send(buf, len, session_info);
 }
 
 void diag_update_pkt_buffer(unsigned char *buf, uint32_t len, int type)
@@ -926,7 +969,8 @@
 	return write_len;
 }
 
-void diag_send_error_rsp(unsigned char *buf, int len)
+void diag_send_error_rsp(unsigned char *buf, int len,
+			struct diag_md_session_t *info)
 {
 	/* -1 to accommodate the first byte 0x13 */
 	if (len > (DIAG_MAX_RSP_SIZE - 1)) {
@@ -936,7 +980,7 @@
 
 	*(uint8_t *)driver->apps_rsp_buf = DIAG_CMD_ERROR;
 	memcpy((driver->apps_rsp_buf + sizeof(uint8_t)), buf, len);
-	diag_send_rsp(driver->apps_rsp_buf, len + 1);
+	diag_send_rsp(driver->apps_rsp_buf, len + 1, info);
 }
 
 int diag_process_apps_pkt(unsigned char *buf, int len,
@@ -956,7 +1000,7 @@
 	/* Check if the command is a supported mask command */
 	mask_ret = diag_process_apps_masks(buf, len, info);
 	if (mask_ret > 0) {
-		diag_send_rsp(driver->apps_rsp_buf, mask_ret);
+		diag_send_rsp(driver->apps_rsp_buf, mask_ret, info);
 		return 0;
 	}
 
@@ -978,7 +1022,7 @@
 						   driver->apps_rsp_buf,
 						   DIAG_MAX_RSP_SIZE);
 		if (write_len > 0)
-			diag_send_rsp(driver->apps_rsp_buf, write_len);
+			diag_send_rsp(driver->apps_rsp_buf, write_len, info);
 		return 0;
 	}
 
@@ -988,13 +1032,15 @@
 		reg_item = container_of(temp_entry, struct diag_cmd_reg_t,
 								entry);
 		if (info) {
-			if (MD_PERIPHERAL_MASK(reg_item->proc) &
-				info->peripheral_mask)
+			if ((MD_PERIPHERAL_MASK(reg_item->proc) &
+				info->peripheral_mask) ||
+				(MD_PERIPHERAL_PD_MASK(reg_item->proc) &
+				info->peripheral_mask))
 				write_len = diag_send_data(reg_item, buf, len);
 		} else {
 			if (MD_PERIPHERAL_MASK(reg_item->proc) &
 				driver->logging_mask)
-				diag_send_error_rsp(buf, len);
+				diag_send_error_rsp(buf, len, info);
 			else
 				write_len = diag_send_data(reg_item, buf, len);
 		}
@@ -1010,13 +1056,13 @@
 		for (i = 0; i < 4; i++)
 			*(driver->apps_rsp_buf+i) = *(buf+i);
 		*(uint32_t *)(driver->apps_rsp_buf+4) = DIAG_MAX_REQ_SIZE;
-		diag_send_rsp(driver->apps_rsp_buf, 8);
+		diag_send_rsp(driver->apps_rsp_buf, 8, info);
 		return 0;
 	} else if ((*buf == 0x4b) && (*(buf+1) == 0x12) &&
 		(*(uint16_t *)(buf+2) == DIAG_DIAG_STM)) {
 		len = diag_process_stm_cmd(buf, driver->apps_rsp_buf);
 		if (len > 0) {
-			diag_send_rsp(driver->apps_rsp_buf, len);
+			diag_send_rsp(driver->apps_rsp_buf, len, info);
 			return 0;
 		}
 		return len;
@@ -1029,7 +1075,7 @@
 							driver->apps_rsp_buf,
 							DIAG_MAX_RSP_SIZE);
 		if (write_len > 0)
-			diag_send_rsp(driver->apps_rsp_buf, write_len);
+			diag_send_rsp(driver->apps_rsp_buf, write_len, info);
 		return 0;
 	}
 	/* Check for time sync switch command */
@@ -1040,7 +1086,7 @@
 							driver->apps_rsp_buf,
 							DIAG_MAX_RSP_SIZE);
 		if (write_len > 0)
-			diag_send_rsp(driver->apps_rsp_buf, write_len);
+			diag_send_rsp(driver->apps_rsp_buf, write_len, info);
 		return 0;
 	}
 	/* Check for diag id command */
@@ -1051,14 +1097,14 @@
 							driver->apps_rsp_buf,
 							DIAG_MAX_RSP_SIZE);
 		if (write_len > 0)
-			diag_send_rsp(driver->apps_rsp_buf, write_len);
+			diag_send_rsp(driver->apps_rsp_buf, write_len, info);
 		return 0;
 	}
 	/* Check for download command */
 	else if ((chk_apps_master()) && (*buf == 0x3A)) {
 		/* send response back */
 		driver->apps_rsp_buf[0] = *buf;
-		diag_send_rsp(driver->apps_rsp_buf, 1);
+		diag_send_rsp(driver->apps_rsp_buf, 1, info);
 		msleep(5000);
 		/* call download API */
 		msm_set_restart_mode(RESTART_DLOAD);
@@ -1078,7 +1124,7 @@
 			for (i = 0; i < 13; i++)
 				driver->apps_rsp_buf[i+3] = 0;
 
-			diag_send_rsp(driver->apps_rsp_buf, 16);
+			diag_send_rsp(driver->apps_rsp_buf, 16, info);
 			return 0;
 		}
 	}
@@ -1087,7 +1133,7 @@
 		(*(buf+2) == 0x04) && (*(buf+3) == 0x0)) {
 		memcpy(driver->apps_rsp_buf, buf, 4);
 		driver->apps_rsp_buf[4] = wrap_enabled;
-		diag_send_rsp(driver->apps_rsp_buf, 5);
+		diag_send_rsp(driver->apps_rsp_buf, 5, info);
 		return 0;
 	}
 	/* Wrap the Delayed Rsp ID */
@@ -1096,7 +1142,7 @@
 		wrap_enabled = true;
 		memcpy(driver->apps_rsp_buf, buf, 4);
 		driver->apps_rsp_buf[4] = wrap_count;
-		diag_send_rsp(driver->apps_rsp_buf, 6);
+		diag_send_rsp(driver->apps_rsp_buf, 6, info);
 		return 0;
 	}
 	/* Mobile ID Rsp */
@@ -1107,7 +1153,7 @@
 						   driver->apps_rsp_buf,
 						   DIAG_MAX_RSP_SIZE);
 		if (write_len > 0) {
-			diag_send_rsp(driver->apps_rsp_buf, write_len);
+			diag_send_rsp(driver->apps_rsp_buf, write_len, info);
 			return 0;
 		}
 	}
@@ -1127,7 +1173,7 @@
 			for (i = 0; i < 55; i++)
 				driver->apps_rsp_buf[i] = 0;
 
-			diag_send_rsp(driver->apps_rsp_buf, 55);
+			diag_send_rsp(driver->apps_rsp_buf, 55, info);
 			return 0;
 		}
 		/* respond to 0x7c command */
@@ -1140,14 +1186,14 @@
 							 chk_config_get_id();
 			*(unsigned char *)(driver->apps_rsp_buf + 12) = '\0';
 			*(unsigned char *)(driver->apps_rsp_buf + 13) = '\0';
-			diag_send_rsp(driver->apps_rsp_buf, 14);
+			diag_send_rsp(driver->apps_rsp_buf, 14, info);
 			return 0;
 		}
 	}
 	write_len = diag_cmd_chk_stats(buf, len, driver->apps_rsp_buf,
 				       DIAG_MAX_RSP_SIZE);
 	if (write_len > 0) {
-		diag_send_rsp(driver->apps_rsp_buf, write_len);
+		diag_send_rsp(driver->apps_rsp_buf, write_len, info);
 		return 0;
 	}
 	write_len = diag_cmd_disable_hdlc(buf, len, driver->apps_rsp_buf,
@@ -1159,7 +1205,7 @@
 		 * before disabling HDLC encoding on Apps processor.
 		 */
 		mutex_lock(&driver->hdlc_disable_mutex);
-		diag_send_rsp(driver->apps_rsp_buf, write_len);
+		diag_send_rsp(driver->apps_rsp_buf, write_len, info);
 		/*
 		 * Set the value of hdlc_disabled after sending the response to
 		 * the tools. This is required since the tools is expecting a
@@ -1179,7 +1225,7 @@
 
 	/* We have now come to the end of the function. */
 	if (chk_apps_only())
-		diag_send_error_rsp(buf, len);
+		diag_send_error_rsp(buf, len, info);
 
 	return 0;
 }
@@ -1262,7 +1308,7 @@
 	 * recovery algorithm. Send an error response if the
 	 * packet is not in expected format.
 	 */
-	diag_send_error_rsp(driver->hdlc_buf, driver->hdlc_buf_len);
+	diag_send_error_rsp(driver->hdlc_buf, driver->hdlc_buf_len, info);
 	driver->hdlc_buf_len = 0;
 end:
 	mutex_unlock(&driver->diag_hdlc_mutex);
@@ -1535,7 +1581,7 @@
 
 		if (actual_pkt->start != CONTROL_CHAR) {
 			diag_hdlc_start_recovery(buf, len, info);
-			diag_send_error_rsp(buf, len);
+			diag_send_error_rsp(buf, len, info);
 			goto end;
 		}
 		mutex_lock(&driver->hdlc_recovery_mutex);
@@ -1625,15 +1671,14 @@
 	case TYPE_CMD:
 		if (peripheral >= 0 && peripheral < NUM_PERIPHERALS) {
 			diagfwd_write_done(peripheral, type, num);
-		} else if (peripheral == APPS_DATA) {
+		}
+		if (peripheral == APPS_DATA ||
+				ctxt == DIAG_MEMORY_DEVICE_MODE) {
 			spin_lock_irqsave(&driver->rsp_buf_busy_lock, flags);
 			driver->rsp_buf_busy = 0;
 			driver->encoded_rsp_len = 0;
 			spin_unlock_irqrestore(&driver->rsp_buf_busy_lock,
 					       flags);
-		} else {
-			pr_err_ratelimited("diag: Invalid peripheral %d in %s, type: %d\n",
-					   peripheral, __func__, type);
 		}
 		break;
 	default:
diff --git a/drivers/char/diag/diagfwd.h b/drivers/char/diag/diagfwd.h
index 677099f..0e0bf2d 100644
--- a/drivers/char/diag/diagfwd.h
+++ b/drivers/char/diag/diagfwd.h
@@ -47,7 +47,8 @@
 void diag_update_sleeping_process(int process_id, int data_type);
 int diag_process_apps_pkt(unsigned char *buf, int len,
 			  struct diag_md_session_t *info);
-void diag_send_error_rsp(unsigned char *buf, int len);
+void diag_send_error_rsp(unsigned char *buf, int len,
+			 struct diag_md_session_t *info);
 void diag_update_pkt_buffer(unsigned char *buf, uint32_t len, int type);
 int diag_process_stm_cmd(unsigned char *buf, unsigned char *dest_buf);
 void diag_md_hdlc_reset_timer_func(unsigned long pid);
diff --git a/drivers/char/diag/diagfwd_peripheral.c b/drivers/char/diag/diagfwd_peripheral.c
index 0703c38..4d4b660 100644
--- a/drivers/char/diag/diagfwd_peripheral.c
+++ b/drivers/char/diag/diagfwd_peripheral.c
@@ -222,12 +222,22 @@
 	struct diagfwd_info *fwd_info = NULL;
 
 	peripheral = GET_BUF_PERIPHERAL(ctxt);
-	if (peripheral < 0 || peripheral > NUM_PERIPHERALS)
+
+	/* Check for peripheral value within bounds
+	 * of peripherals and UPD combined.
+	 */
+	if (peripheral < 0 || peripheral > NUM_MD_SESSIONS)
 		return -EINVAL;
 
 	if (peripheral == APPS_DATA)
 		return peripheral;
 
+	/* With peripheral value bound checked
+	 * return user pd value.
+	 */
+	if (peripheral > NUM_PERIPHERALS)
+		return peripheral;
+
 	type = GET_BUF_TYPE(ctxt);
 	if (type < 0 || type >= NUM_TYPES)
 		return -EINVAL;
diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c
index 68611b6..31539e4 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc.c
@@ -846,7 +846,8 @@
 
 	/* For decoder No need to sanity till LOAD_RESOURCES */
 	if (inst->session_type == MSM_VIDC_DECODER &&
-			inst->state < MSM_VIDC_LOAD_RESOURCES_DONE) {
+			(inst->state < MSM_VIDC_LOAD_RESOURCES_DONE ||
+			inst->state >= MSM_VIDC_RELEASE_RESOURCES_DONE)) {
 		dprintk(VIDC_DBG,
 			"No need to verify buffer counts : %pK\n", inst);
 		return 0;
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_clocks.c b/drivers/media/platform/msm/vidc/msm_vidc_clocks.c
index f2f6d58..2ca4385 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_clocks.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_clocks.c
@@ -652,7 +652,9 @@
 
 	operating_rate = operating_rate >> 16;
 
-	if ((curr_operating_rate + ops_left) >= operating_rate) {
+	if ((curr_operating_rate + ops_left) >= operating_rate ||
+			!msm_vidc_clock_scaling ||
+			inst->clk_data.buffer_counter < DCVS_FTB_WINDOW) {
 		dprintk(VIDC_DBG,
 			"Requestd operating rate is valid %u\n",
 			operating_rate);
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_platform.c b/drivers/media/platform/msm/vidc/msm_vidc_platform.c
index 56524ccd4..1818788 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_platform.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_platform.c
@@ -66,6 +66,7 @@
 	CODEC_ENTRY(V4L2_PIX_FMT_H264, MSM_VIDC_ENCODER, 125, 675, 320),
 	CODEC_ENTRY(V4L2_PIX_FMT_HEVC, MSM_VIDC_ENCODER, 125, 675, 320),
 	CODEC_ENTRY(V4L2_PIX_FMT_VP8, MSM_VIDC_ENCODER, 125, 675, 320),
+	CODEC_ENTRY(V4L2_PIX_FMT_TME, MSM_VIDC_ENCODER, 0, 540, 540),
 	CODEC_ENTRY(V4L2_PIX_FMT_MPEG2, MSM_VIDC_DECODER, 50, 200, 200),
 	CODEC_ENTRY(V4L2_PIX_FMT_H264, MSM_VIDC_DECODER, 50, 200, 200),
 	CODEC_ENTRY(V4L2_PIX_FMT_HEVC, MSM_VIDC_DECODER, 50, 200, 200),
diff --git a/drivers/power/supply/qcom/fg-core.h b/drivers/power/supply/qcom/fg-core.h
index 3ca5def..7c10e63 100644
--- a/drivers/power/supply/qcom/fg-core.h
+++ b/drivers/power/supply/qcom/fg-core.h
@@ -426,6 +426,7 @@
 	int			batt_id_ohms;
 	int			ki_coeff_full_soc;
 	int			charge_status;
+	int			prev_charge_status;
 	int			charge_done;
 	int			charge_type;
 	int			online_status;
diff --git a/drivers/power/supply/qcom/fg-util.c b/drivers/power/supply/qcom/fg-util.c
index fc60b26..622bfad 100644
--- a/drivers/power/supply/qcom/fg-util.c
+++ b/drivers/power/supply/qcom/fg-util.c
@@ -266,8 +266,7 @@
 int fg_sram_write(struct fg_chip *chip, u16 address, u8 offset,
 			u8 *val, int len, int flags)
 {
-	int rc = 0;
-	bool tried_again = false;
+	int rc = 0, tries = 0;
 	bool atomic_access = false;
 
 	if (!chip)
@@ -292,7 +291,7 @@
 		enable_irq(chip->irqs[SOC_UPDATE_IRQ].irq);
 		atomic_access = true;
 	}
-wait:
+
 	/*
 	 * Atomic access mean waiting upon SOC_UPDATE interrupt from
 	 * FG_ALG and do the transaction after that. This is to make
@@ -301,16 +300,20 @@
 	 * FG cycle (~1.47 seconds).
 	 */
 	if (atomic_access) {
-		/* Wait for SOC_UPDATE completion */
-		rc = wait_for_completion_interruptible_timeout(
-			&chip->soc_update,
-			msecs_to_jiffies(SOC_UPDATE_WAIT_MS));
+		for (tries = 0; tries < 2; tries++) {
+			/* Wait for SOC_UPDATE completion */
+			rc = wait_for_completion_interruptible_timeout(
+				&chip->soc_update,
+				msecs_to_jiffies(SOC_UPDATE_WAIT_MS));
+			if (rc > 0) {
+				rc = 0;
+				break;
+			} else if (!rc) {
+				rc = -ETIMEDOUT;
+			}
+		}
 
-		/* If we were interrupted wait again one more time. */
-		if (rc == -ERESTARTSYS && !tried_again) {
-			tried_again = true;
-			goto wait;
-		} else if (rc <= 0) {
+		if (rc < 0) {
 			pr_err("wait for soc_update timed out rc=%d\n", rc);
 			goto out;
 		}
diff --git a/drivers/power/supply/qcom/qpnp-fg-gen3.c b/drivers/power/supply/qcom/qpnp-fg-gen3.c
index fc34a8c9..48e42f2 100644
--- a/drivers/power/supply/qcom/qpnp-fg-gen3.c
+++ b/drivers/power/supply/qcom/qpnp-fg-gen3.c
@@ -562,6 +562,21 @@
 	return 0;
 }
 
+#define BATT_SOC_32BIT	GENMASK(31, 0)
+static int fg_get_charge_counter_shadow(struct fg_chip *chip, int *val)
+{
+	int rc, batt_soc;
+
+	rc = fg_get_sram_prop(chip, FG_SRAM_BATT_SOC, &batt_soc);
+	if (rc < 0) {
+		pr_err("Error in getting BATT_SOC, rc=%d\n", rc);
+		return rc;
+	}
+
+	*val = div_u64((u32)batt_soc * chip->cl.learned_cc_uah, BATT_SOC_32BIT);
+	return 0;
+}
+
 static int fg_get_charge_counter(struct fg_chip *chip, int *val)
 {
 	int rc, cc_soc;
@@ -1148,7 +1163,7 @@
 		enable_irq_wake(chip->irqs[BATT_MISSING_IRQ].irq);
 	} else {
 		disable_irq_wake(chip->irqs[BATT_MISSING_IRQ].irq);
-		disable_irq(chip->irqs[BATT_MISSING_IRQ].irq);
+		disable_irq_nosync(chip->irqs[BATT_MISSING_IRQ].irq);
 	}
 
 	return 0;
@@ -1167,7 +1182,7 @@
 		enable_irq_wake(chip->irqs[BSOC_DELTA_IRQ].irq);
 	} else {
 		disable_irq_wake(chip->irqs[BSOC_DELTA_IRQ].irq);
-		disable_irq(chip->irqs[BSOC_DELTA_IRQ].irq);
+		disable_irq_nosync(chip->irqs[BSOC_DELTA_IRQ].irq);
 	}
 
 	return 0;
@@ -1249,6 +1264,21 @@
 	return true;
 }
 
+static int fg_prime_cc_soc_sw(struct fg_chip *chip, int cc_soc_sw)
+{
+	int rc;
+
+	rc = fg_sram_write(chip, chip->sp[FG_SRAM_CC_SOC_SW].addr_word,
+		chip->sp[FG_SRAM_CC_SOC_SW].addr_byte, (u8 *)&cc_soc_sw,
+		chip->sp[FG_SRAM_CC_SOC_SW].len, FG_IMA_ATOMIC);
+	if (rc < 0)
+		pr_err("Error in writing cc_soc_sw, rc=%d\n", rc);
+	else
+		fg_dbg(chip, FG_STATUS, "cc_soc_sw: %x\n", cc_soc_sw);
+
+	return rc;
+}
+
 static int fg_save_learned_cap_to_sram(struct fg_chip *chip)
 {
 	int16_t cc_mah;
@@ -1434,7 +1464,6 @@
 	return 0;
 }
 
-#define BATT_SOC_32BIT	GENMASK(31, 0)
 static int fg_cap_learning_begin(struct fg_chip *chip, u32 batt_soc)
 {
 	int rc, cc_soc_sw, batt_soc_msb;
@@ -1453,16 +1482,13 @@
 	/* Prime cc_soc_sw with battery SOC when capacity learning begins */
 	cc_soc_sw = div64_s64((int64_t)batt_soc * CC_SOC_30BIT,
 				BATT_SOC_32BIT);
-	rc = fg_sram_write(chip, chip->sp[FG_SRAM_CC_SOC_SW].addr_word,
-		chip->sp[FG_SRAM_CC_SOC_SW].addr_byte, (u8 *)&cc_soc_sw,
-		chip->sp[FG_SRAM_CC_SOC_SW].len, FG_IMA_ATOMIC);
+	rc = fg_prime_cc_soc_sw(chip, cc_soc_sw);
 	if (rc < 0) {
 		pr_err("Error in writing cc_soc_sw, rc=%d\n", rc);
 		goto out;
 	}
 
 	chip->cl.init_cc_soc_sw = cc_soc_sw;
-	chip->cl.active = true;
 	fg_dbg(chip, FG_CAP_LEARN, "Capacity learning started @ battery SOC %d init_cc_soc_sw:%d\n",
 		batt_soc_msb, chip->cl.init_cc_soc_sw);
 out:
@@ -1482,9 +1508,7 @@
 
 	/* Write a FULL value to cc_soc_sw */
 	cc_soc_sw = CC_SOC_30BIT;
-	rc = fg_sram_write(chip, chip->sp[FG_SRAM_CC_SOC_SW].addr_word,
-		chip->sp[FG_SRAM_CC_SOC_SW].addr_byte, (u8 *)&cc_soc_sw,
-		chip->sp[FG_SRAM_CC_SOC_SW].len, FG_IMA_ATOMIC);
+	rc = fg_prime_cc_soc_sw(chip, cc_soc_sw);
 	if (rc < 0) {
 		pr_err("Error in writing cc_soc_sw, rc=%d\n", rc);
 		goto out;
@@ -1497,8 +1521,9 @@
 
 static void fg_cap_learning_update(struct fg_chip *chip)
 {
-	int rc, batt_soc, batt_soc_msb;
+	int rc, batt_soc, batt_soc_msb, cc_soc_sw;
 	bool input_present = is_input_present(chip);
+	bool prime_cc = false;
 
 	mutex_lock(&chip->cl.lock);
 
@@ -1511,6 +1536,9 @@
 		goto out;
 	}
 
+	if (chip->charge_status == chip->prev_charge_status)
+		goto out;
+
 	rc = fg_get_sram_prop(chip, FG_SRAM_BATT_SOC, &batt_soc);
 	if (rc < 0) {
 		pr_err("Error in getting ACT_BATT_CAP, rc=%d\n", rc);
@@ -1526,8 +1554,12 @@
 		if (chip->charge_status == POWER_SUPPLY_STATUS_CHARGING) {
 			rc = fg_cap_learning_begin(chip, batt_soc);
 			chip->cl.active = (rc == 0);
+		} else {
+			if ((chip->charge_status ==
+					POWER_SUPPLY_STATUS_DISCHARGING) ||
+					chip->charge_done)
+				prime_cc = true;
 		}
-
 	} else {
 		if (chip->charge_done) {
 			rc = fg_cap_learning_done(chip);
@@ -1545,6 +1577,7 @@
 					 batt_soc_msb);
 				chip->cl.active = false;
 				chip->cl.init_cc_uah = 0;
+				prime_cc = true;
 			}
 		}
 
@@ -1561,10 +1594,29 @@
 					batt_soc_msb);
 				chip->cl.active = false;
 				chip->cl.init_cc_uah = 0;
+				prime_cc = true;
 			}
 		}
 	}
 
+	/*
+	 * Prime CC_SOC_SW when the device is not charging or during charge
+	 * termination when the capacity learning is not active.
+	 */
+
+	if (prime_cc) {
+		if (chip->charge_done)
+			cc_soc_sw = CC_SOC_30BIT;
+		else
+			cc_soc_sw = div_u64((u32)batt_soc *
+					CC_SOC_30BIT, BATT_SOC_32BIT);
+
+		rc = fg_prime_cc_soc_sw(chip, cc_soc_sw);
+		if (rc < 0)
+			pr_err("Error in writing cc_soc_sw, rc=%d\n",
+				rc);
+	}
+
 out:
 	mutex_unlock(&chip->cl.lock);
 }
@@ -1779,7 +1831,8 @@
 			fg_dbg(chip, FG_STATUS, "Terminated charging @ SOC%d\n",
 				msoc);
 		}
-	} else if (msoc_raw <= recharge_soc && chip->charge_full) {
+	} else if ((msoc_raw <= recharge_soc || !chip->charge_done)
+			&& chip->charge_full) {
 		if (chip->dt.linearize_soc) {
 			chip->delta_soc = FULL_CAPACITY - msoc;
 
@@ -2563,7 +2616,7 @@
 	}
 
 	fg_ttf_update(chip);
-
+	chip->prev_charge_status = chip->charge_status;
 out:
 	fg_dbg(chip, FG_POWER_SUPPLY, "charge_status:%d charge_type:%d charge_done:%d\n",
 		chip->charge_status, chip->charge_type, chip->charge_done);
@@ -3555,6 +3608,9 @@
 	case POWER_SUPPLY_PROP_CHARGE_COUNTER:
 		rc = fg_get_charge_counter(chip, &pval->intval);
 		break;
+	case POWER_SUPPLY_PROP_CHARGE_COUNTER_SHADOW:
+		rc = fg_get_charge_counter_shadow(chip, &pval->intval);
+		break;
 	case POWER_SUPPLY_PROP_TIME_TO_FULL_AVG:
 		rc = fg_get_time_to_full(chip, &pval->intval);
 		break;
@@ -3765,6 +3821,7 @@
 	POWER_SUPPLY_PROP_CHARGE_NOW,
 	POWER_SUPPLY_PROP_CHARGE_FULL,
 	POWER_SUPPLY_PROP_CHARGE_COUNTER,
+	POWER_SUPPLY_PROP_CHARGE_COUNTER_SHADOW,
 	POWER_SUPPLY_PROP_TIME_TO_FULL_AVG,
 	POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
 	POWER_SUPPLY_PROP_SOC_REPORTING_READY,
@@ -5000,6 +5057,7 @@
 	chip->debug_mask = &fg_gen3_debug_mask;
 	chip->irqs = fg_irqs;
 	chip->charge_status = -EINVAL;
+	chip->prev_charge_status = -EINVAL;
 	chip->ki_coeff_full_soc = -EINVAL;
 	chip->online_status = -EINVAL;
 	chip->regmap = dev_get_regmap(chip->dev->parent, NULL);
diff --git a/include/net/neighbour.h b/include/net/neighbour.h
index 8b68384..ddfb742 100644
--- a/include/net/neighbour.h
+++ b/include/net/neighbour.h
@@ -62,6 +62,7 @@
 	NEIGH_VAR_GC_THRESH1,
 	NEIGH_VAR_GC_THRESH2,
 	NEIGH_VAR_GC_THRESH3,
+	NEIGH_VAR_PROBE,
 	NEIGH_VAR_MAX
 };
 
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 8495824..b6fdf29 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -106,7 +106,7 @@
 #endif
 
 #define SNDRV_PCM_IOCTL1_RESET		0
-#define SNDRV_PCM_IOCTL1_INFO		1
+/* 1 is absent slot. */
 #define SNDRV_PCM_IOCTL1_CHANNEL_INFO	2
 #define SNDRV_PCM_IOCTL1_GSTATE		3
 #define SNDRV_PCM_IOCTL1_FIFO_SIZE	4
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 227c249..62893eb 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -56,6 +56,7 @@
 static void neigh_update_notify(struct neighbour *neigh);
 static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev);
 
+static unsigned int neigh_probe_enable;
 #ifdef CONFIG_PROC_FS
 static const struct file_operations neigh_stat_seq_fops;
 #endif
@@ -1258,9 +1259,20 @@
 {
 	struct neighbour *neigh = __neigh_lookup(tbl, saddr, dev,
 						 lladdr || !dev->addr_len);
-	if (neigh)
-		neigh_update(neigh, lladdr, NUD_STALE,
-			     NEIGH_UPDATE_F_OVERRIDE);
+	if (neigh) {
+		if (neigh_probe_enable) {
+			if (!(neigh->nud_state == NUD_REACHABLE)) {
+				neigh_update(neigh, lladdr, NUD_STALE,
+					     NEIGH_UPDATE_F_OVERRIDE);
+				write_lock(&neigh->lock);
+				neigh_probe(neigh);
+				neigh_update_notify(neigh);
+			}
+		} else {
+			neigh_update(neigh, lladdr, NUD_STALE,
+				     NEIGH_UPDATE_F_OVERRIDE);
+		}
+	}
 	return neigh;
 }
 EXPORT_SYMBOL(neigh_event_ns);
@@ -3107,6 +3119,12 @@
 			.extra2		= &int_max,
 			.proc_handler	= proc_dointvec_minmax,
 		},
+		[NEIGH_VAR_PROBE] = {
+			.procname	= "neigh_probe",
+			.maxlen		= sizeof(int),
+			.mode		= 0644,
+			.proc_handler	= proc_dointvec,
+		},
 		{},
 	},
 };
@@ -3142,6 +3160,7 @@
 		t->neigh_vars[NEIGH_VAR_GC_THRESH1].data = &tbl->gc_thresh1;
 		t->neigh_vars[NEIGH_VAR_GC_THRESH2].data = &tbl->gc_thresh2;
 		t->neigh_vars[NEIGH_VAR_GC_THRESH3].data = &tbl->gc_thresh3;
+		t->neigh_vars[NEIGH_VAR_PROBE].data  = &neigh_probe_enable;
 	}
 
 	if (handler) {
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 6faddfb..f8d0bd8 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -1857,8 +1857,6 @@
 		      unsigned int cmd, void *arg)
 {
 	switch (cmd) {
-	case SNDRV_PCM_IOCTL1_INFO:
-		return 0;
 	case SNDRV_PCM_IOCTL1_RESET:
 		return snd_pcm_lib_ioctl_reset(substream, arg);
 	case SNDRV_PCM_IOCTL1_CHANNEL_INFO:
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 3d9ff6d..8e5649a 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -197,7 +197,6 @@
 
 int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info)
 {
-	struct snd_pcm_runtime *runtime;
 	struct snd_pcm *pcm = substream->pcm;
 	struct snd_pcm_str *pstr = substream->pstr;
 
@@ -213,12 +212,7 @@
 	info->subdevices_count = pstr->substream_count;
 	info->subdevices_avail = pstr->substream_count - pstr->substream_opened;
 	strlcpy(info->subname, substream->name, sizeof(info->subname));
-	runtime = substream->runtime;
-	/* AB: FIXME!!! This is definitely nonsense */
-	if (runtime) {
-		info->sync = runtime->sync;
-		substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_INFO, info);
-	}
+
 	return 0;
 }
 
diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c
index 19d6af8..fc9c9b0 100644
--- a/sound/soc/soc-ops.c
+++ b/sound/soc/soc-ops.c
@@ -379,7 +379,7 @@
 	unsigned int rshift = mc->rshift;
 	int max = mc->max;
 	int min = mc->min;
-	int mask = (1 << (fls(min + max) - 1)) - 1;
+	unsigned int mask = (1 << (fls(min + max) - 1)) - 1;
 	unsigned int val;
 	int ret;
 
@@ -424,7 +424,7 @@
 	unsigned int rshift = mc->rshift;
 	int max = mc->max;
 	int min = mc->min;
-	int mask = (1 << (fls(min + max) - 1)) - 1;
+	unsigned int mask = (1 << (fls(min + max) - 1)) - 1;
 	int err = 0;
 	unsigned int val, val_mask, val2 = 0;