Merge "defconfig: msm: Enable CONFIG_DM_BOW for SDM670/710"
diff --git a/Documentation/devicetree/bindings/usb/dwc3.txt b/Documentation/devicetree/bindings/usb/dwc3.txt
index 83ecdc7..20abd3d 100644
--- a/Documentation/devicetree/bindings/usb/dwc3.txt
+++ b/Documentation/devicetree/bindings/usb/dwc3.txt
@@ -63,6 +63,7 @@
 	during bus suspend.
  - snps,usb3-u1u2-disable: If present, disable U1U2 low power modes in Superspeed mode
  - snps,usb2-l1-disable: If present, disable L1 low power modes in Highspeed mode
+ - normal-eps-in-gsi-mode: If present, two normal EPS (1 In, 1 Out) can be used in GSI mode
 
 This is usually a subnode to DWC3 glue to which it is connected.
 
diff --git a/arch/arm/boot/dts/qcom/sa415m-ttp.dtsi b/arch/arm/boot/dts/qcom/sa415m-ttp.dtsi
index e8fdc08..27d4437 100644
--- a/arch/arm/boot/dts/qcom/sa415m-ttp.dtsi
+++ b/arch/arm/boot/dts/qcom/sa415m-ttp.dtsi
@@ -44,6 +44,36 @@
 		enable-active-high;
 		gpio = <&tlmm 71 GPIO_ACTIVE_HIGH>;
 	};
+	cnss_pcie: qcom,cnss {
+		compatible = "qcom,cnss";
+		reg = <0x10000000 0x10000000>,
+		      <0x20000000 0x10000>;
+		reg-names = "smmu_iova_base", "smmu_iova_ipa";
+
+		wlan-en-gpio = <&tlmm 52 0>;
+		vdd-wlan-supply = <&vreg_wlan>;
+		vdd-wlan-xtal-supply = <&pmxpoorwills_l6>;
+		vdd-wlan-io-supply = <&pmxpoorwills_l6>;
+		qcom,notify-modem-status;
+		pinctrl-names = "wlan_en_active", "wlan_en_sleep";
+		pinctrl-0 = <&cnss_wlan_en_active>;
+		pinctrl-1 = <&cnss_wlan_en_sleep>;
+		qcom,wlan-rc-num = <0>;
+		qcom,wlan-ramdump-dynamic = <0x200000>;
+		qcom,smmu-s1-enable;
+		qcom,msm-bus,name = "msm-cnss";
+		qcom,msm-bus,num-cases = <4>;
+		qcom,msm-bus,num-paths = <2>;
+		qcom,msm-bus,vectors-KBps =
+				<45 512 0 0>, <1 512 0 0>,
+				/* Upto 200 Mbps */
+				<45 512 41421 655360>, <1 512 41421 655360>,
+				/* Upto 400 Mbps */
+				<45 512 98572 655360>, <1 512 98572 1600000>,
+				/* Upto 800 Mbps */
+				<45 512 207108 1146880>, <1 512 207108 3124992>;
+
+	};
 };
 
 &i2c_3 {
diff --git a/arch/arm/configs/sdxpoorwills-auto-perf_defconfig b/arch/arm/configs/sdxpoorwills-auto-perf_defconfig
index 1af9a91..b04fd97 100644
--- a/arch/arm/configs/sdxpoorwills-auto-perf_defconfig
+++ b/arch/arm/configs/sdxpoorwills-auto-perf_defconfig
@@ -180,6 +180,7 @@
 CONFIG_RFKILL=y
 CONFIG_IPC_ROUTER=y
 CONFIG_IPC_ROUTER_SECURITY=y
+CONFIG_IPC_ROUTER_NODE_ID=2
 CONFIG_REGMAP_ALLOW_WRITE_DEBUGFS=y
 CONFIG_DMA_CMA=y
 CONFIG_CMA_SIZE_MBYTES=12
diff --git a/arch/arm/configs/sdxpoorwills-auto_defconfig b/arch/arm/configs/sdxpoorwills-auto_defconfig
index 572c46b..3d0cca3 100644
--- a/arch/arm/configs/sdxpoorwills-auto_defconfig
+++ b/arch/arm/configs/sdxpoorwills-auto_defconfig
@@ -181,6 +181,7 @@
 CONFIG_RFKILL=y
 CONFIG_IPC_ROUTER=y
 CONFIG_IPC_ROUTER_SECURITY=y
+CONFIG_IPC_ROUTER_NODE_ID=2
 CONFIG_REGMAP_ALLOW_WRITE_DEBUGFS=y
 CONFIG_DMA_CMA=y
 CONFIG_CMA_SIZE_MBYTES=12
diff --git a/arch/arm/mach-qcom/board-sdm429.c b/arch/arm/mach-qcom/board-sdm429.c
index 6bdf0f4..3638c37 100644
--- a/arch/arm/mach-qcom/board-sdm429.c
+++ b/arch/arm/mach-qcom/board-sdm429.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018-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
@@ -18,6 +18,7 @@
 static const char *sdm429_dt_match[] __initconst = {
 	"qcom,sdm429",
 	"qcom,sda429",
+	"qcom,sdm429w",
 	NULL
 };
 
diff --git a/arch/arm64/boot/dts/qcom/msm8937-smp2p.dtsi b/arch/arm64/boot/dts/qcom/msm8937-smp2p.dtsi
index d5537e9..7b6d4d1 100644
--- a/arch/arm64/boot/dts/qcom/msm8937-smp2p.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8937-smp2p.dtsi
@@ -158,6 +158,21 @@
 		gpios = <&smp2pgpio_smp2p_2_out 0 0>;
 	};
 
+	smp2pgpio_sleepstate_2_out: qcom,smp2pgpio-sleepstate-gpio-2-out {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "sleepstate";
+		qcom,remote-pid = <2>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	qcom,smp2pgpio-sleepstate-2-out {
+		compatible = "qcom,smp2pgpio-sleepstate-out";
+		gpios = <&smp2pgpio_sleepstate_2_out 0 0>;
+	};
+
 	/* ssr - inbound entry from mss. */
 	smp2pgpio_ssr_smp2p_1_in: qcom,smp2pgpio-ssr-smp2p-1-in {
 		compatible = "qcom,smp2pgpio";
diff --git a/arch/arm64/boot/dts/qcom/sdm429w-regulator.dtsi b/arch/arm64/boot/dts/qcom/sdm429w-regulator.dtsi
index 0a06e2da..b4dd41e 100644
--- a/arch/arm64/boot/dts/qcom/sdm429w-regulator.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm429w-regulator.dtsi
@@ -111,7 +111,7 @@
 		status = "okay";
 		S5A: pm660_s5: regulator-s5 {
 			regulator-min-microvolt = <1040000>;
-			regulator-max-microvolt = <1350000>;
+			regulator-max-microvolt = <1420000>;
 			qcom,init-voltage = <1040000>;
 			status = "okay";
 		};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-rb3.dtsi b/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-rb3.dtsi
index 8aac76e..8f25cb0 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-rb3.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-rb3.dtsi
@@ -139,30 +139,30 @@
 		cam_clk-supply = <&titan_top_gdsc>;
 		regulator-names = "cam_vio", "cam_clk";
 		rgltr-cntrl-support;
-		rgltr-min-voltage = <1800000 0>;
-		rgltr-max-voltage = <1800000 0>;
-		rgltr-load-current = <80000  0>;
+		rgltr-min-voltage = <0 0>;
+		rgltr-max-voltage = <0 0>;
+		rgltr-load-current = <0 0>;
 		gpio-no-mux = <0>;
 		pinctrl-names = "cam_default", "cam_suspend";
-		pinctrl-0 = <&cam_sensor_mclk0_active
+		pinctrl-0 = <&cam_sensor_mclk2_active
 				&cam_sensor_rear4_active>;
-		pinctrl-1 = <&cam_sensor_mclk0_suspend
+		pinctrl-1 = <&cam_sensor_mclk2_suspend
 				&cam_sensor_rear4_suspend>;
-		gpios = <&tlmm 13 0>,
+		gpios = <&tlmm 15 0>,
 			<&tlmm 12 0>,
 			<&tlmm 69 0>;
 		gpio-reset = <1>;
 		gpio-custom1 = <2>;
 		gpio-req-tbl-num = <0 1 2>;
 		gpio-req-tbl-flags = <1 0 0>;
-		gpio-req-tbl-label = "CAMIF_MCLK0",
+		gpio-req-tbl-label = "CAMIF_MCLK4",
 					"CAM_RESET4",
 					"CAM_CUSTOM4";
 		sensor-position = <0>;
 		sensor-mode = <0>;
 		cci-master = <1>;
 		status = "ok";
-		clocks = <&clock_camcc CAM_CC_MCLK0_CLK>;
+		clocks = <&clock_camcc CAM_CC_MCLK2_CLK>;
 		clock-names = "cam_clk";
 		clock-cntl-level = "turbo";
 		clock-rates = <24000000>;
@@ -261,9 +261,9 @@
 		cam_clk-supply = <&titan_top_gdsc>;
 		regulator-names = "cam_vio", "cam_clk";
 		rgltr-cntrl-support;
-		rgltr-min-voltage = <1800000 0>;
-		rgltr-max-voltage = <1800000 0>;
-		rgltr-load-current = <100000 0>;
+		rgltr-min-voltage = <0 0>;
+		rgltr-max-voltage = <0 0>;
+		rgltr-load-current = <0 0>;
 		gpio-no-mux = <0>;
 		pinctrl-names = "cam_default", "cam_suspend";
 		pinctrl-0 = <&cam_sensor_mclk3_active
@@ -286,10 +286,10 @@
 		clock-rates = <24000000>;
 	};
 
-	qcom,cam-sensor@4 {
-		cell-index = <4>;
+	qcom,cam-sensor@6 {
+		cell-index = <6>;
 		compatible = "qcom,cam-sensor";
-		reg = <0x4>;
+		reg = <0x6>;
 		csiphy-sd-index = <2>;
 		sensor-position-roll = <270>;
 		sensor-position-pitch = <0>;
@@ -303,29 +303,29 @@
 		cam_clk-supply = <&titan_top_gdsc>;
 		regulator-names = "cam_vio", "cam_clk";
 		rgltr-cntrl-support;
-		rgltr-min-voltage = <1800000 0>;
-		rgltr-max-voltage = <1800000 0>;
-		rgltr-load-current = <80000  0>;
+		rgltr-min-voltage = <0 0>;
+		rgltr-max-voltage = <0 0>;
+		rgltr-load-current = <0 0>;
 		gpio-no-mux = <0>;
 		pinctrl-names = "cam_default", "cam_suspend";
-		pinctrl-0 = <&cam_sensor_mclk0_active
+		pinctrl-0 = <&cam_sensor_mclk2_active
 				&cam_sensor_rear4_active>;
-		pinctrl-1 = <&cam_sensor_mclk0_suspend
+		pinctrl-1 = <&cam_sensor_mclk2_suspend
 				&cam_sensor_rear4_suspend>;
-		gpios = <&tlmm 13 0>,
+		gpios = <&tlmm 15 0>,
 			<&tlmm 12 0>,
 			<&tlmm 69 0>;
 		gpio-reset = <1>;
 		gpio-custom1 = <2>;
 		gpio-req-tbl-num = <0 1 2>;
 		gpio-req-tbl-flags = <1 0 0>;
-		gpio-req-tbl-label = "CAMIF_MCLK0",
+		gpio-req-tbl-label = "CAMIF_MCLK4",
 					"CAM_RESET4",
 					"CAM_CUSTOM4";
 		sensor-mode = <0>;
 		cci-master = <1>;
 		status = "ok";
-		clocks = <&clock_camcc CAM_CC_MCLK0_CLK>;
+		clocks = <&clock_camcc CAM_CC_MCLK2_CLK>;
 		clock-names = "cam_clk";
 		clock-cntl-level = "turbo";
 		clock-rates = <24000000>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-v2.1-rb3.dtsi b/arch/arm64/boot/dts/qcom/sdm845-v2.1-rb3.dtsi
index dd1188b..e1159d3 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-v2.1-rb3.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-v2.1-rb3.dtsi
@@ -195,9 +195,8 @@
 
 		config {
 			pins = "gpio12","gpio69";
-			bias-pull-down; /* PULL DOWN */
+			bias-disable; /* No PULL */
 			drive-strength = <2>; /* 2 MA */
-			output-low;
 		};
 	};
 };
diff --git a/arch/arm64/configs/sdm670-perf_defconfig b/arch/arm64/configs/sdm670-perf_defconfig
index d80e603..d75479e 100755
--- a/arch/arm64/configs/sdm670-perf_defconfig
+++ b/arch/arm64/configs/sdm670-perf_defconfig
@@ -37,7 +37,6 @@
 # CONFIG_RD_LZ4 is not set
 CONFIG_KALLSYMS_ALL=y
 CONFIG_BPF_SYSCALL=y
-# CONFIG_MEMBARRIER is not set
 CONFIG_EMBEDDED=y
 # CONFIG_SLUB_DEBUG is not set
 # CONFIG_COMPAT_BRK is not set
@@ -72,12 +71,12 @@
 CONFIG_SWP_EMULATION=y
 CONFIG_CP15_BARRIER_EMULATION=y
 CONFIG_SETEND_EMULATION=y
+CONFIG_ARM64_SW_TTBR0_PAN=y
 # CONFIG_ARM64_VHE is not set
 CONFIG_RANDOMIZE_BASE=y
 # CONFIG_EFI is not set
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_COMPAT=y
-CONFIG_PM_AUTOSLEEP=y
 CONFIG_PM_WAKELOCKS=y
 CONFIG_PM_WAKELOCKS_LIMIT=0
 # CONFIG_PM_WAKELOCKS_GC is not set
@@ -94,6 +93,7 @@
 CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_XFRM_USER=y
+CONFIG_XFRM_INTERFACE=y
 CONFIG_XFRM_STATISTICS=y
 CONFIG_NET_KEY=y
 CONFIG_INET=y
@@ -296,6 +296,7 @@
 CONFIG_PPPOPNS=y
 CONFIG_PPP_ASYNC=y
 CONFIG_PPP_SYNC_TTY=y
+CONFIG_USB_RTL8152=y
 CONFIG_USB_LAN78XX=y
 CONFIG_USB_USBNET=y
 CONFIG_WCNSS_MEM_PRE_ALLOC=y
diff --git a/arch/arm64/configs/sdm670_defconfig b/arch/arm64/configs/sdm670_defconfig
index 33deb51..1eea891 100755
--- a/arch/arm64/configs/sdm670_defconfig
+++ b/arch/arm64/configs/sdm670_defconfig
@@ -39,7 +39,6 @@
 # CONFIG_RD_LZ4 is not set
 CONFIG_KALLSYMS_ALL=y
 CONFIG_BPF_SYSCALL=y
-# CONFIG_MEMBARRIER is not set
 CONFIG_EMBEDDED=y
 # CONFIG_COMPAT_BRK is not set
 CONFIG_PROFILING=y
@@ -77,11 +76,11 @@
 CONFIG_SWP_EMULATION=y
 CONFIG_CP15_BARRIER_EMULATION=y
 CONFIG_SETEND_EMULATION=y
+CONFIG_ARM64_SW_TTBR0_PAN=y
 # CONFIG_ARM64_VHE is not set
 CONFIG_RANDOMIZE_BASE=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_COMPAT=y
-CONFIG_PM_AUTOSLEEP=y
 CONFIG_PM_WAKELOCKS=y
 CONFIG_PM_WAKELOCKS_LIMIT=0
 # CONFIG_PM_WAKELOCKS_GC is not set
@@ -99,6 +98,7 @@
 CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_XFRM_USER=y
+CONFIG_XFRM_INTERFACE=y
 CONFIG_XFRM_STATISTICS=y
 CONFIG_NET_KEY=y
 CONFIG_INET=y
@@ -302,6 +302,7 @@
 CONFIG_PPPOPNS=y
 CONFIG_PPP_ASYNC=y
 CONFIG_PPP_SYNC_TTY=y
+CONFIG_USB_RTL8152=y
 CONFIG_USB_LAN78XX=y
 CONFIG_USB_USBNET=y
 CONFIG_WCNSS_MEM_PRE_ALLOC=y
diff --git a/arch/arm64/configs/sdm845-perf_defconfig b/arch/arm64/configs/sdm845-perf_defconfig
index 9e0c7a8..4529bfb 100755
--- a/arch/arm64/configs/sdm845-perf_defconfig
+++ b/arch/arm64/configs/sdm845-perf_defconfig
@@ -419,6 +419,7 @@
 CONFIG_USB_EHCI_HCD_PLATFORM=y
 CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_OHCI_HCD_PLATFORM=y
+CONFIG_USB_ACM=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_DWC3=y
 CONFIG_USB_DWC3_MSM=y
diff --git a/arch/arm64/configs/sdm845_defconfig b/arch/arm64/configs/sdm845_defconfig
index 99b464a..c063564 100755
--- a/arch/arm64/configs/sdm845_defconfig
+++ b/arch/arm64/configs/sdm845_defconfig
@@ -423,6 +423,7 @@
 CONFIG_USB_EHCI_HCD_PLATFORM=y
 CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_OHCI_HCD_PLATFORM=y
+CONFIG_USB_ACM=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_DWC3=y
 CONFIG_USB_DWC3_MSM=y
diff --git a/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
index 2b764d1..cfc474a 100644
--- a/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
+++ b/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
@@ -4686,6 +4686,13 @@
 		return -EFAULT;
 	}
 
+	/* To make sure num_out_res is same as allocated */
+	if (ctx_data->icp_dev_acquire_info->num_out_res !=
+		icp_dev_acquire_info.num_out_res) {
+		CAM_ERR(CAM_ICP, "num_out_res got changed");
+		return -EFAULT;
+	}
+
 	CAM_DBG(CAM_ICP, "%x %x %x %x %x %x %x",
 		ctx_data->icp_dev_acquire_info->dev_type,
 		ctx_data->icp_dev_acquire_info->in_res.format,
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/cam_eeprom_core.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/cam_eeprom_core.c
index 8f59ca3..06d6bd4 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/cam_eeprom_core.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/cam_eeprom_core.c
@@ -439,17 +439,32 @@
 	else if (cmm_hdr->cmd_type == CAMERA_SENSOR_CMD_TYPE_WAIT)
 		validate_size = sizeof(struct cam_cmd_unconditional_wait);
 
-	if (remain_buf_len < validate_size) {
+	if (remain_buf_len < validate_size ||
+	    *num_map >= (MSM_EEPROM_MAX_MEM_MAP_CNT *
+		MSM_EEPROM_MEMORY_MAP_MAX_SIZE)) {
 		CAM_ERR(CAM_EEPROM, "not enough buffer");
 		return -EINVAL;
 	}
 	switch (cmm_hdr->cmd_type) {
 	case CAMERA_SENSOR_CMD_TYPE_I2C_RNDM_WR:
 		i2c_random_wr = (struct cam_cmd_i2c_random_wr *)cmd_buf;
+
+		if (i2c_random_wr->header.count == 0 ||
+		    i2c_random_wr->header.count >= MSM_EEPROM_MAX_MEM_MAP_CNT ||
+		    (size_t)*num_map >= ((MSM_EEPROM_MAX_MEM_MAP_CNT *
+				MSM_EEPROM_MEMORY_MAP_MAX_SIZE) -
+				i2c_random_wr->header.count)) {
+			CAM_ERR(CAM_EEPROM, "OOB Error");
+			return -EINVAL;
+		}
 		cmd_length_in_bytes   = sizeof(struct cam_cmd_i2c_random_wr) +
 			((i2c_random_wr->header.count - 1) *
 			sizeof(struct i2c_random_wr_payload));
 
+		if (cmd_length_in_bytes > remain_buf_len) {
+			CAM_ERR(CAM_EEPROM, "Not enough buffer remaining");
+			return -EINVAL;
+		}
 		for (cnt = 0; cnt < (i2c_random_wr->header.count);
 			cnt++) {
 			map[*num_map + cnt].page.addr =
@@ -472,6 +487,11 @@
 		i2c_cont_rd = (struct cam_cmd_i2c_continuous_rd *)cmd_buf;
 		cmd_length_in_bytes = sizeof(struct cam_cmd_i2c_continuous_rd);
 
+		if (i2c_cont_rd->header.count >= U32_MAX - data->num_data) {
+			CAM_ERR(CAM_EEPROM,
+				"int overflow on eeprom memory block");
+			return -EINVAL;
+		}
 		map[*num_map].mem.addr = i2c_cont_rd->reg_addr;
 		map[*num_map].mem.addr_type = i2c_cont_rd->header.addr_type;
 		map[*num_map].mem.data_type = i2c_cont_rd->header.data_type;
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 02839e2..146fe3e 100755
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -1284,6 +1284,8 @@
 					"snps,usb3-u1u2-disable");
 	dwc->usb2_l1_disable = device_property_read_bool(dev,
 					"snps,usb2-l1-disable");
+	dwc->normal_eps_in_gsi_mode = device_property_read_bool(dev,
+					"normal-eps-in-gsi-mode");
 	if (dwc->enable_bus_suspend) {
 		pm_runtime_set_autosuspend_delay(dev, 500);
 		pm_runtime_use_autosuspend(dev);
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 89d7ee0..80386d2 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -620,6 +620,7 @@
  * @dbg_ep_events_ts: timestamp for previous event counters
  * @fifo_depth: allocated TXFIFO depth
  * @ep_cfg_init_params: Used by GSI EP to save EP_CFG init_cmd params
+ * @gsi_db_reg_addr: Address of GSI DB register mapped to this EP
  */
 struct dwc3_ep {
 	struct usb_ep		endpoint;
@@ -676,6 +677,7 @@
 	struct timespec		dbg_ep_events_ts;
 	int			fifo_depth;
 	struct dwc3_gadget_ep_cmd_params ep_cfg_init_params;
+	void __iomem		*gsi_db_reg_addr;
 };
 
 enum dwc3_phy {
@@ -989,6 +991,8 @@
  * @create_reg_debugfs: create debugfs entry to allow dwc3 register dump
  * @xhci_imod_value: imod value to use with xhci
  * @core_id: usb core id to differentiate different controller
+ * @normal_eps_in_gsi_mode: if true, two normal EPS (1 In, 1 Out) can be used in
+ *			    GSI mode
  */
 struct dwc3 {
 	struct usb_ctrlrequest	*ctrl_req;
@@ -1191,6 +1195,7 @@
 	u32			xhci_imod_value;
 	int			core_id;
 	int			retries_on_error;
+	bool			normal_eps_in_gsi_mode;
 };
 
 /* -------------------------------------------------------------------------- */
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index af704b7..37c4e7e 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -203,7 +203,7 @@
 	"ENABLE_GSI", "UPDATE_XFER", "RING_DB",
 	"END_XFER", "GET_CH_INFO", "GET_XFER_IDX", "PREPARE_TRBS",
 	"FREE_TRBS", "SET_CLR_BLOCK_DBL", "CHECK_FOR_SUSP",
-	"EP_DISABLE" };
+	"EP_DISABLE", "EP_UPDATE_DB" };
 
 /* Input bits to state machine (mdwc->inputs) */
 
@@ -312,6 +312,8 @@
 
 	u64			dummy_gsi_db;
 	dma_addr_t		dummy_gsi_db_dma;
+	u64			dummy_gevntcnt;
+	dma_addr_t		dummy_gevntcnt_dma;
 };
 
 #define USB_HSPHY_3P3_VOL_MIN		3050000 /* uV */
@@ -864,6 +866,7 @@
 	int last_trb_index = 0;
 	struct dwc3	*dwc = dep->dwc;
 	struct usb_gsi_request *request = ch_info->ch_req;
+	struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
 
 	/* Provide physical USB addresses for DEPCMD and GEVENTCNT registers */
 	ch_info->depcmd_low_addr = (u32)(dwc->reg_phys +
@@ -898,14 +901,28 @@
 	/* Store last 16 bits of LINK TRB address as per GSI hw requirement */
 	ch_info->last_trb_addr = (dwc3_trb_dma_offset(dep,
 			&dep->trb_pool[last_trb_index - 1]) & 0x0000FFFF);
-	ch_info->gevntcount_low_addr = (u32)(dwc->reg_phys +
-			DWC3_GEVNTCOUNT(ep->ep_intr_num));
-	ch_info->gevntcount_hi_addr = 0;
+	dev_dbg(dwc->dev, "depcmd_laddr=%x last_trb_addr=%x\n",
+		ch_info->depcmd_low_addr, ch_info->last_trb_addr);
 
-	dev_dbg(dwc->dev,
-	"depcmd_laddr=%x last_trb_addr=%x gevtcnt_laddr=%x gevtcnt_haddr=%x",
-		ch_info->depcmd_low_addr, ch_info->last_trb_addr,
-		ch_info->gevntcount_low_addr, ch_info->gevntcount_hi_addr);
+	/*
+	 * Check if NORMAL EP is used with GSI. In that case USB driver
+	 * processes events and GSI shouldn't access GEVNTCOUNT(0) register.
+	 */
+	if (ep->ep_intr_num) {
+		ch_info->gevntcount_low_addr = (u32)(dwc->reg_phys +
+			DWC3_GEVNTCOUNT(ep->ep_intr_num));
+		ch_info->gevntcount_hi_addr = 0;
+		dev_dbg(dwc->dev, "gevtcnt_laddr=%x gevtcnt_haddr=%x\n",
+		     ch_info->gevntcount_low_addr, ch_info->gevntcount_hi_addr);
+	} else {
+		ch_info->gevntcount_low_addr = (u32)mdwc->dummy_gevntcnt_dma;
+		ch_info->gevntcount_hi_addr =
+				(u32)((u64)mdwc->dummy_gevntcnt_dma >> 32);
+		dev_dbg(dwc->dev, "Dummy GEVNTCNT Addr %pK: %llx %x (LSB)\n",
+			&mdwc->dummy_gevntcnt,
+			(unsigned long long)mdwc->dummy_gevntcnt_dma,
+			(u32)mdwc->dummy_gevntcnt_dma);
+	}
 }
 
 /*
@@ -929,8 +946,15 @@
 	}
 
 	memset(&params, 0, sizeof(params));
-	params.param0 = GSI_TRB_ADDR_BIT_53_MASK | GSI_TRB_ADDR_BIT_55_MASK;
-	params.param0 |= (ep->ep_intr_num << 16);
+	/*
+	 * Check if NORMAL EP is used with GSI. In that case USB driver
+	 * updates GSI doorbell and USB GSI wrapper h/w isn't involved.
+	 */
+	if (ep->ep_intr_num) {
+		params.param0 = GSI_TRB_ADDR_BIT_53_MASK |
+				GSI_TRB_ADDR_BIT_55_MASK;
+		params.param0 |= (ep->ep_intr_num << 16);
+	}
 	params.param1 = lower_32_bits(dwc3_trb_dma_offset(dep,
 						&dep->trb_pool[0]));
 	cmd = DWC3_DEPCMD_STARTTRANSFER;
@@ -957,7 +981,18 @@
 	struct dwc3_ep *dep = to_dwc3_ep(ep);
 	struct dwc3	*dwc = dep->dwc;
 	struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
-	int n = ep->ep_intr_num - 1;
+	int n;
+
+	/*
+	 * Check if NORMAL EP is used with GSI. In that case USB driver
+	 * updates GSI doorbell and USB GSI wrapper h/w isn't involved.
+	 */
+	if (!ep->ep_intr_num) {
+		dev_dbg(mdwc->dev, "%s: is no-op for normal EP\n", __func__);
+		return;
+	}
+
+	n = ep->ep_intr_num - 1;
 
 	dwc3_msm_write_reg(mdwc->base, GSI_RING_BASE_ADDR_L(n),
 			dwc3_trb_dma_offset(dep, &dep->trb_pool[0]));
@@ -991,6 +1026,21 @@
 			dwc3_msm_read_reg(mdwc->base, GSI_DBL_ADDR_L(n)));
 }
 
+static void dwc3_msm_gsi_db_update(struct dwc3_ep *dep, dma_addr_t offset)
+{
+	struct dwc3 *dwc = dep->dwc;
+	struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
+
+	if (!dep->gsi_db_reg_addr) {
+		dev_err(mdwc->dev, "Failed to update GSI DBL\n");
+		return;
+	}
+
+	writel_relaxed(offset, dep->gsi_db_reg_addr);
+	dev_dbg(mdwc->dev, "Writing TRB addr: %pa to %pK\n",
+		&offset, dep->gsi_db_reg_addr);
+}
+
 /*
 * Rings Doorbell for GSI Channel
 *
@@ -1016,6 +1066,8 @@
 		return;
 	}
 
+	dep->gsi_db_reg_addr = gsi_dbl_address_lsb;
+
 	gsi_dbl_address_msb = devm_ioremap_nocache(mdwc->dev,
 			request->db_reg_phs_addr_msb, sizeof(u32));
 	if (!gsi_dbl_address_msb) {
@@ -1399,6 +1451,15 @@
 	struct dwc3 *dwc = dep->dwc;
 	struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
 
+	/*
+	 * Check if NORMAL EP is used with GSI. In that case USB driver
+	 * updates GSI doorbell and USB GSI wrapper h/w isn't involved.
+	 */
+	if (!ep->ep_intr_num) {
+		dev_dbg(mdwc->dev, "%s: is no-op for normal EP\n", __func__);
+		return;
+	}
+
 	dwc3_msm_write_reg_field(mdwc->base,
 			GSI_GENERAL_CFG_REG, GSI_CLK_EN_MASK, 1);
 	dwc3_msm_write_reg_field(mdwc->base,
@@ -1435,6 +1496,12 @@
 	else
 		gsi_enable_ep_events(ep);
 
+	/* Nothing to be done if NORMAL EP is used with GSI */
+	if (!ep->ep_intr_num) {
+		dev_dbg(mdwc->dev, "%s: is no-op for normal EP\n", __func__);
+		return;
+	}
+
 	dwc3_msm_write_reg_field(mdwc->base,
 		GSI_GENERAL_CFG_REG, BLOCK_GSI_WR_GO_MASK, block_db);
 }
@@ -1490,6 +1557,7 @@
 	struct gsi_channel_info *ch_info;
 	bool block_db;
 	unsigned long flags;
+	dma_addr_t offset;
 
 	dbg_log_string("%s(%d):%s", ep->name, ep->ep_num, gsi_op_to_string(op));
 
@@ -1555,6 +1623,10 @@
 	case GSI_EP_OP_DISABLE:
 		ret = ep->ops->disable(ep);
 		break;
+	case GSI_EP_OP_UPDATE_DB:
+		offset = *(dma_addr_t *)op_data;
+		dwc3_msm_gsi_db_update(dep, offset);
+		break;
 	default:
 		dev_err(mdwc->dev, "%s: Invalid opcode GSI EP\n", __func__);
 	}
@@ -2065,6 +2137,19 @@
 			dev_err(dwc->dev, "failed to map dummy doorbell buffer\n");
 			mdwc->dummy_gsi_db_dma = (dma_addr_t)NULL;
 		}
+
+		/*
+		 * Set-up dummy GEVNTCOUNT address to be passed on to GSI for
+		 * normal (non HW-accelerated) EPs.
+		 */
+		mdwc->dummy_gevntcnt_dma = dma_map_single(dwc->sysdev,
+						&mdwc->dummy_gevntcnt,
+						sizeof(mdwc->dummy_gevntcnt),
+						DMA_FROM_DEVICE);
+		if (dma_mapping_error(dwc->sysdev, mdwc->dummy_gevntcnt_dma)) {
+			dev_err(dwc->dev, "failed to map dummy geventcount\n");
+			mdwc->dummy_gevntcnt_dma = (dma_addr_t)NULL;
+		}
 		break;
 	case DWC3_GSI_EVT_BUF_SETUP:
 		dev_dbg(mdwc->dev, "DWC3_GSI_EVT_BUF_SETUP\n");
@@ -2138,6 +2223,12 @@
 				dma_free_coherent(dwc->sysdev, evt->length,
 							evt->buf, evt->dma);
 		}
+		if (mdwc->dummy_gevntcnt_dma) {
+			dma_unmap_single(dwc->sysdev, mdwc->dummy_gevntcnt_dma,
+					 sizeof(mdwc->dummy_gevntcnt),
+					 DMA_FROM_DEVICE);
+			mdwc->dummy_gevntcnt_dma = (dma_addr_t)NULL;
+		}
 		if (mdwc->dummy_gsi_db_dma) {
 			dma_unmap_single(dwc->sysdev, mdwc->dummy_gsi_db_dma,
 					 sizeof(mdwc->dummy_gsi_db),
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index e8d270d..d0391b4 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -2390,8 +2390,8 @@
 
 /* -------------------------------------------------------------------------- */
 
-#define NUM_GSI_OUT_EPS	1
-#define NUM_GSI_IN_EPS	2
+#define NUM_GSI_OUT_EPS(dwc)	(dwc->normal_eps_in_gsi_mode ? 2 : 1)
+#define NUM_GSI_IN_EPS(dwc)	(dwc->normal_eps_in_gsi_mode ? 3 : 2)
 
 static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc,
 		u8 num, u32 direction)
@@ -2399,13 +2399,13 @@
 	struct dwc3_ep			*dep;
 	u8				i, gsi_ep_count, gsi_ep_index = 0;
 
-	gsi_ep_count = NUM_GSI_OUT_EPS + NUM_GSI_IN_EPS;
+	gsi_ep_count = NUM_GSI_OUT_EPS(dwc) + NUM_GSI_IN_EPS(dwc);
 	/* OUT GSI EPs based on direction field */
 	if (gsi_ep_count && !direction)
-		gsi_ep_count = NUM_GSI_OUT_EPS;
+		gsi_ep_count = NUM_GSI_OUT_EPS(dwc);
 	/* IN GSI EPs */
 	else if (gsi_ep_count && direction)
-		gsi_ep_count = NUM_GSI_IN_EPS;
+		gsi_ep_count = NUM_GSI_IN_EPS(dwc);
 
 	for (i = 0; i < num; i++) {
 		u8 epnum = (i << 1) | (direction ? 1 : 0);
@@ -2710,6 +2710,25 @@
 	return 1;
 }
 
+static void dwc3_gsi_ep_transfer_complete(struct dwc3 *dwc, struct dwc3_ep *dep)
+{
+	struct usb_ep *ep = &dep->endpoint;
+	struct dwc3_trb *trb;
+	dma_addr_t offset;
+
+	trb = &dep->trb_pool[dep->trb_dequeue];
+	while (trb->ctrl & DWC3_TRBCTL_LINK_TRB) {
+		dwc3_ep_inc_trb(&dep->trb_dequeue);
+		trb = &dep->trb_pool[dep->trb_dequeue];
+	}
+
+	if (!(trb->ctrl & DWC3_TRB_CTRL_HWO)) {
+		offset = dwc3_trb_dma_offset(dep, trb);
+		usb_gsi_ep_op(ep, (void *)&offset, GSI_EP_OP_UPDATE_DB);
+		dwc3_ep_inc_trb(&dep->trb_dequeue);
+	}
+}
+
 static void dwc3_endpoint_transfer_complete(struct dwc3 *dwc,
 		struct dwc3_ep *dep, const struct dwc3_event_depevt *event)
 {
@@ -2721,6 +2740,15 @@
 
 	if (event->status & DEPEVT_STATUS_BUSERR)
 		status = -ECONNRESET;
+	/*
+	 * Check if NORMAL EP is used with GSI.
+	 * In that case dwc3 driver recevies EP events from hardware and
+	 * updates GSI doorbell with completed TRB.
+	 */
+	if (dep->endpoint.ep_type == EP_TYPE_GSI) {
+		dwc3_gsi_ep_transfer_complete(dwc, dep);
+		return;
+	}
 
 	clean_busy = dwc3_cleanup_done_reqs(dwc, dep, event, status);
 	if (clean_busy && (!dep->endpoint.desc || is_xfer_complete ||
diff --git a/drivers/usb/gadget/function/f_gsi.c b/drivers/usb/gadget/function/f_gsi.c
index ffd5952..d58b20a 100644
--- a/drivers/usb/gadget/function/f_gsi.c
+++ b/drivers/usb/gadget/function/f_gsi.c
@@ -572,9 +572,11 @@
 			GSI_EP_OP_GET_CH_INFO);
 
 	log_event_dbg("%s: USB GSI IN OPS Completed", __func__);
-	in_params->client =
-		(gsi->prot_id != USB_PROT_DIAG_IPA) ? IPA_CLIENT_USB_CONS :
-						IPA_CLIENT_USB_DPL_CONS;
+	if (gsi->prot_id != USB_PROT_DIAG_IPA)
+		in_params->client = (gsi->prot_id != USB_PROT_RMNET_V2X_IPA) ?
+				IPA_CLIENT_USB_CONS : IPA_CLIENT_USB2_CONS;
+	else
+		in_params->client = IPA_CLIENT_USB_DPL_CONS;
 	in_params->ipa_ep_cfg.mode.mode = IPA_BASIC;
 	in_params->teth_prot = (enum ipa_usb_teth_prot)gsi->prot_id;
 	in_params->gevntcount_low_addr =
@@ -627,7 +629,8 @@
 		usb_gsi_ep_op(d_port->out_ep, (void *)&gsi_channel_info,
 				GSI_EP_OP_GET_CH_INFO);
 		log_event_dbg("%s: USB GSI OUT OPS Completed", __func__);
-		out_params->client = IPA_CLIENT_USB_PROD;
+		out_params->client = (gsi->prot_id != USB_PROT_RMNET_V2X_IPA) ?
+				     IPA_CLIENT_USB_PROD : IPA_CLIENT_USB2_PROD;
 		out_params->ipa_ep_cfg.mode.mode = IPA_BASIC;
 		out_params->teth_prot = (enum ipa_usb_teth_prot)gsi->prot_id;
 		out_params->gevntcount_low_addr =
@@ -1521,6 +1524,7 @@
 	case GSI_MBIM_GPS_USB_STATUS:
 		val = atomic_read(&gsi->connected);
 		if (gsi->prot_id == USB_PROT_RMNET_IPA ||
+				gsi->prot_id == USB_PROT_RMNET_V2X_IPA ||
 				gsi->prot_id == USB_PROT_RMNET_ETHER)
 			val = gsi->rmnet_dtr_status;
 
@@ -1701,6 +1705,9 @@
 	case USB_PROT_RMNET_IPA:
 		cdev_name = GSI_RMNET_CTRL_NAME;
 		break;
+	case USB_PROT_RMNET_V2X_IPA:
+		cdev_name = GSI_RMNET_V2X_CTRL_NAME;
+		break;
 	case USB_PROT_RMNET_ETHER:
 		cdev_name = ETHER_RMNET_CTRL_NAME;
 		break;
@@ -2190,6 +2197,7 @@
 			| USB_CDC_REQ_SET_CONTROL_LINE_STATE:
 		line_state = (w_value & GSI_CTRL_DTR ? true : false);
 		if (gsi->prot_id == USB_PROT_RMNET_IPA ||
+				gsi->prot_id == USB_PROT_RMNET_V2X_IPA ||
 				gsi->prot_id == USB_PROT_RMNET_ETHER)
 			gsi->rmnet_dtr_status = line_state;
 		log_event_dbg("%s: USB_CDC_REQ_SET_CONTROL_LINE_STATE DTR:%d\n",
@@ -2293,6 +2301,7 @@
 	/* RNDIS, RMNET and DPL only support alt 0*/
 	if (intf == gsi->ctrl_id || gsi->prot_id == USB_PROT_RNDIS_IPA ||
 			gsi->prot_id == USB_PROT_RMNET_IPA ||
+			gsi->prot_id == USB_PROT_RMNET_V2X_IPA ||
 			gsi->prot_id == USB_PROT_DIAG_IPA ||
 			is_ext_prot_ether(gsi->prot_id))
 		return 0;
@@ -2414,6 +2423,7 @@
 
 	/* Control interface has only altsetting 0 */
 	if (intf == gsi->ctrl_id || gsi->prot_id == USB_PROT_RMNET_IPA ||
+				gsi->prot_id == USB_PROT_RMNET_V2X_IPA ||
 				gsi->prot_id == USB_PROT_RMNET_ETHER) {
 		if (alt != 0)
 			goto fail;
@@ -2450,6 +2460,7 @@
 		/* for rndis and rmnet alt is always 0 update alt accordingly */
 		if (gsi->prot_id == USB_PROT_RNDIS_IPA ||
 				gsi->prot_id == USB_PROT_RMNET_IPA ||
+				gsi->prot_id == USB_PROT_RMNET_V2X_IPA ||
 				gsi->prot_id == USB_PROT_DIAG_IPA ||
 				is_ext_prot_ether(gsi->prot_id))
 			alt = 1;
@@ -2480,9 +2491,11 @@
 
 			/* Configure EPs for GSI */
 			if (gsi->d_port.in_ep &&
-				gsi->prot_id <= USB_PROT_DIAG_IPA) {
+				gsi->prot_id <= USB_PROT_RMNET_V2X_IPA) {
 				if (gsi->prot_id == USB_PROT_DIAG_IPA)
 					gsi->d_port.in_ep->ep_intr_num = 3;
+				else if (gsi->prot_id == USB_PROT_RMNET_V2X_IPA)
+					gsi->d_port.in_ep->ep_intr_num = 0;
 				else
 					gsi->d_port.in_ep->ep_intr_num = 2;
 				usb_gsi_ep_op(gsi->d_port.in_ep,
@@ -2491,8 +2504,11 @@
 			}
 
 			if (gsi->d_port.out_ep &&
-				gsi->prot_id <= USB_PROT_DIAG_IPA) {
-				gsi->d_port.out_ep->ep_intr_num = 1;
+				gsi->prot_id <= USB_PROT_RMNET_V2X_IPA) {
+				if (gsi->prot_id == USB_PROT_RMNET_V2X_IPA)
+					gsi->d_port.out_ep->ep_intr_num = 0;
+				else
+					gsi->d_port.out_ep->ep_intr_num = 1;
 				usb_gsi_ep_op(gsi->d_port.out_ep,
 					&gsi->d_port.out_request,
 						GSI_EP_OP_CONFIG);
@@ -2587,6 +2603,7 @@
 		rndis_uninit(gsi->params);
 
 	if (gsi->prot_id == USB_PROT_RMNET_IPA ||
+				gsi->prot_id == USB_PROT_RMNET_V2X_IPA ||
 				gsi->prot_id == USB_PROT_RMNET_ETHER)
 		gsi->rmnet_dtr_status = false;
 
@@ -2817,7 +2834,7 @@
 		info->data_nop_desc->bInterfaceNumber = gsi->data_id;
 
 	/* allocate instance-specific endpoints */
-	if (info->fs_in_desc && gsi->prot_id <= USB_PROT_DIAG_IPA) {
+	if (info->fs_in_desc && gsi->prot_id <= USB_PROT_RMNET_V2X_IPA) {
 		ep = usb_ep_autoconfig_by_name(cdev->gadget,
 				info->fs_in_desc, info->in_epname);
 		if (!ep)
@@ -2835,7 +2852,7 @@
 		}
 	}
 
-	if (info->fs_out_desc && gsi->prot_id <= USB_PROT_DIAG_IPA) {
+	if (info->fs_out_desc && gsi->prot_id <= USB_PROT_RMNET_V2X_IPA) {
 		ep = usb_ep_autoconfig_by_name(cdev->gadget,
 				info->fs_out_desc, info->out_epname);
 		if (!ep)
@@ -3011,6 +3028,7 @@
 
 
 	if (gsi->prot_id == USB_PROT_RMNET_IPA ||
+		gsi->prot_id == USB_PROT_RMNET_V2X_IPA ||
 		gsi->prot_id == USB_PROT_DIAG_IPA ||
 		is_ext_prot_ether(gsi->prot_id))
 		gsi->ctrl_id = -ENODEV;
@@ -3222,6 +3240,7 @@
 		}
 		break;
 	case USB_PROT_RMNET_IPA:
+	case USB_PROT_RMNET_V2X_IPA:
 	case USB_PROT_RMNET_ETHER:
 		info.string_defs = rmnet_gsi_string_defs;
 		info.data_desc = &rmnet_gsi_interface_desc;
@@ -3487,6 +3506,7 @@
 		gsi->function.strings = ecm_gsi_strings;
 		break;
 	case USB_PROT_RMNET_IPA:
+	case USB_PROT_RMNET_V2X_IPA:
 	case USB_PROT_RMNET_ETHER:
 		gsi->function.name = "rmnet";
 		gsi->function.strings = rmnet_gsi_strings;
@@ -3885,6 +3905,7 @@
 
 	switch (gsi->prot_id) {
 	case USB_PROT_RMNET_IPA:
+	case USB_PROT_RMNET_V2X_IPA:
 	case USB_PROT_RMNET_ETHER:
 		str = gsi->rmnet_dtr_status ? "connected" : "disconnected";
 		break;
diff --git a/drivers/usb/gadget/function/f_gsi.h b/drivers/usb/gadget/function/f_gsi.h
index b7e8fe8..02be58d 100644
--- a/drivers/usb/gadget/function/f_gsi.h
+++ b/drivers/usb/gadget/function/f_gsi.h
@@ -32,6 +32,7 @@
 #include "configfs.h"
 
 #define GSI_RMNET_CTRL_NAME "rmnet_ctrl"
+#define GSI_RMNET_V2X_CTRL_NAME "rmnet_v2x_ctrl"
 #define GSI_MBIM_CTRL_NAME "android_mbim"
 #define GSI_DPL_CTRL_NAME "dpl_ctrl"
 #define ETHER_RMNET_CTRL_NAME "rmnet_ctrl0"
@@ -125,6 +126,7 @@
 	USB_PROT_RMNET_IPA,
 	USB_PROT_MBIM_IPA,
 	USB_PROT_DIAG_IPA,
+	USB_PROT_RMNET_V2X_IPA,
 
 	/* non-accelerated */
 	USB_PROT_RMNET_ETHER,
@@ -339,6 +341,8 @@
 		return USB_PROT_MBIM_IPA;
 	if (!strncasecmp(name, "dpl", MAX_INST_NAME_LEN))
 		return USB_PROT_DIAG_IPA;
+	if (!strncasecmp(name, "rmnet.v2x", MAX_INST_NAME_LEN))
+		return USB_PROT_RMNET_V2X_IPA;
 	if (!strncasecmp(name, "rmnet.ether", MAX_INST_NAME_LEN))
 		return USB_PROT_RMNET_ETHER;
 	if (!strncasecmp(name, "dpl.ether", MAX_INST_NAME_LEN))
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 0e7cc71..d44905b 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -804,3 +804,9 @@
 	  This option is of interest only to developers who need to validate
 	  their USB hardware designs.  It is not needed for normal use.  If
 	  unsure, say N.
+
+config USB_UPD720X
+	tristate "Support for Renesas UPD720X XHCI USB controller"
+	---help---
+	  Enables support for the USB Host controller present on the
+	  Renesas UPD720X chipsets.
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 6ef785b..fc6981a 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -82,3 +82,4 @@
 obj-$(CONFIG_USB_HCD_SSB)	+= ssb-hcd.o
 obj-$(CONFIG_USB_FOTG210_HCD)	+= fotg210-hcd.o
 obj-$(CONFIG_USB_MAX3421_HCD)	+= max3421-hcd.o
+obj-$(CONFIG_USB_UPD720X)	+= xhci-fwdload.o
diff --git a/drivers/usb/host/pci-quirks.h b/drivers/usb/host/pci-quirks.h
index 6463fdb..38a91d8 100644
--- a/drivers/usb/host/pci-quirks.h
+++ b/drivers/usb/host/pci-quirks.h
@@ -15,6 +15,11 @@
 void usb_enable_intel_xhci_ports(struct pci_dev *xhci_pdev);
 void usb_disable_xhci_ports(struct pci_dev *xhci_pdev);
 void sb800_prefetch(struct device *dev, int on);
+#ifdef CONFIG_USB_UPD720X
+void upd720x_finish_download(struct pci_dev *pDev);
+#else
+#define upd720x_finish_download(pDev)
+#endif
 #else
 struct pci_dev;
 static inline void usb_amd_quirk_pll_disable(void) {}
@@ -23,6 +28,7 @@
 static inline void usb_amd_dev_put(void) {}
 static inline void usb_disable_xhci_ports(struct pci_dev *xhci_pdev) {}
 static inline void sb800_prefetch(struct device *dev, int on) {}
+#define upd720x_finish_download(pDev)
 #endif  /* CONFIG_PCI */
 
 #endif  /*  __LINUX_USB_PCI_QUIRKS_H  */
diff --git a/drivers/usb/host/xhci-fwdload.c b/drivers/usb/host/xhci-fwdload.c
new file mode 100644
index 0000000..f214e03
--- /dev/null
+++ b/drivers/usb/host/xhci-fwdload.c
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/errno.h>
+#include <linux/time.h>
+#include <linux/firmware.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <asm/dma-iommu.h>
+#include <linux/msm_dma_iommu_mapping.h>
+
+#define upd720x_firmware  "K2026090.mem"
+
+#define UPD_PCI_F4  0xF4
+
+#define UPD_PCI_F4_FWDOWNLOADENABLE  (0x0001)
+#define UPD_PCI_F4_FWDOWNLOADLOCK    (0x0002)
+#define UPD_PCI_F4_SETDATA0          (0x0100)
+#define UPD_PCI_F4_SETDATA1          (0x0200)
+#define UPD_PCI_F4_RESULT            (0x0070)
+
+#define UPD_PCI_F8  0xF8
+
+#define UPD_PCI_FC  0xFC
+
+enum SET_DATA {
+	SET_DATA_PAGE0,
+	SET_DATA_PAGE1
+};
+
+#define SMMU_BASE 0x10000000
+#define SMMU_SIZE 0x40000000
+
+struct firmware *fw_pointer;
+static struct dma_iommu_mapping *upd720x_smmu_init(struct device *dev)
+{
+	int rc = 0;
+	int atomic_ctx = 1;
+	int bypass_enable = 1;
+	struct dma_iommu_mapping *mapping = NULL;
+
+	mapping = arm_iommu_create_mapping(&platform_bus_type,
+		SMMU_BASE, SMMU_SIZE);
+	if (IS_ERR(mapping)) {
+		rc = PTR_ERR(mapping);
+		dev_err(dev, "create mapping failed, err = %d\n", rc);
+		return NULL;
+	}
+
+	rc = iommu_domain_set_attr(mapping->domain,
+		DOMAIN_ATTR_ATOMIC, &atomic_ctx);
+	if (rc) {
+		dev_err(dev, "Set atomic attribute to SMMU failed (%d)\n", rc);
+		arm_iommu_release_mapping(mapping);
+		return NULL;
+	}
+
+	rc = iommu_domain_set_attr(mapping->domain,
+		DOMAIN_ATTR_S1_BYPASS, &bypass_enable);
+	if (rc) {
+		dev_err(dev, "Set bypass attribute to SMMU failed (%d)\n", rc);
+		arm_iommu_release_mapping(mapping);
+		return NULL;
+	}
+
+	rc = arm_iommu_attach_device(dev, mapping);
+	if (rc) {
+		dev_err(dev, "arm_iommu_attach_device failed (%d)\n", rc);
+		arm_iommu_release_mapping(mapping);
+		return NULL;
+	}
+
+	pr_info("attached to IOMMU\n");
+	return mapping;
+}
+
+static void upd720x_smmu_deinit(struct device *dev)
+{
+	arm_iommu_detach_device(dev);
+	arm_iommu_release_mapping(to_dma_iommu_mapping(dev));
+}
+
+
+static int upd720x_download_enable(struct pci_dev *pDev)
+{
+	unsigned int read_data;
+	int result;
+
+	result = pci_read_config_dword(pDev, UPD_PCI_F4, &read_data);
+	pr_info("Set FW Download enable\n");
+	result = pci_write_config_dword(pDev, UPD_PCI_F4, read_data |
+		UPD_PCI_F4_FWDOWNLOADENABLE);
+	return result;
+}
+
+static int upd720x_download_lock(struct pci_dev *pDev)
+{
+	unsigned int read_data;
+	int result;
+
+	result = pci_read_config_dword(pDev, UPD_PCI_F4, &read_data);
+	pr_info("Set FW Download lock\n");
+	result = pci_write_config_dword(pDev, UPD_PCI_F4, read_data |
+		UPD_PCI_F4_FWDOWNLOADLOCK);
+	return result;
+}
+
+static int upd720x_set_data0(struct pci_dev *pDev)
+{
+	unsigned int read_data;
+	int result;
+
+	result = pci_read_config_dword(pDev, UPD_PCI_F4, &read_data);
+	result = pci_write_config_dword(pDev, UPD_PCI_F4,
+		(read_data & ~UPD_PCI_F4_SETDATA1) |
+		UPD_PCI_F4_SETDATA0);
+
+	return result;
+}
+
+static int upd720x_set_data1(struct pci_dev *pDev)
+{
+	unsigned int read_data;
+	int result;
+
+	result = pci_read_config_dword(pDev, UPD_PCI_F4, &read_data);
+	result = pci_write_config_dword(pDev, UPD_PCI_F4,
+		(read_data & ~UPD_PCI_F4_SETDATA0) |
+		UPD_PCI_F4_SETDATA1);
+
+	return result;
+}
+
+static int upd720x_download_clearcontrol(struct pci_dev *pDev)
+{
+	int read_buf;
+	int rc;
+
+	rc = pci_read_config_dword(pDev, UPD_PCI_F4, &read_buf);
+	if (rc == 0) {
+		rc = pci_write_config_dword(pDev, UPD_PCI_F4, read_buf &
+		~UPD_PCI_F4_FWDOWNLOADENABLE);
+	}
+	return rc;
+}
+int upd720x_firmware_download(struct pci_dev  *pDev,
+	unsigned char *pFWImage, unsigned int firmware_size)
+{
+	enum SET_DATA page = SET_DATA_PAGE0;
+	int offset;
+	unsigned int *image = (unsigned int *)pFWImage;
+	unsigned int fw_dwordsize   = firmware_size /
+		(sizeof(unsigned int) / sizeof(unsigned char));
+
+	if ((firmware_size %
+	(sizeof(unsigned int) / sizeof(unsigned char))) != 0)
+		fw_dwordsize++;
+
+	if (upd720x_download_enable(pDev) == -EFAULT) {
+		pr_info("Set FW Download Enable is timeout");
+		return -EFAULT;
+	}
+
+	for (offset = 0; offset < fw_dwordsize; offset++) {
+		switch (page) {
+		case SET_DATA_PAGE0:
+			pci_write_config_dword(pDev, UPD_PCI_F8, image[offset]);
+
+			if (upd720x_set_data0(pDev) == -EFAULT)
+				return -EFAULT;
+			page = SET_DATA_PAGE1;
+			break;
+
+		case SET_DATA_PAGE1:
+			pci_write_config_dword(pDev, UPD_PCI_FC, image[offset]);
+			if (upd720x_set_data1(pDev) == -EFAULT)
+				return -EFAULT;
+			page = SET_DATA_PAGE0;
+			break;
+		default:
+			break;
+		}
+	}
+
+	if (upd720x_download_clearcontrol(pDev) == -EFAULT)
+		return -EFAULT;
+
+	if (upd720x_download_lock(pDev) == -EFAULT)
+		return -EFAULT;
+
+	return 0;
+}
+
+int upd720x_finish_download(struct pci_dev *pDev)
+{
+	int result = -EFAULT;
+	char *firmwarename = upd720x_firmware;
+	int lc;
+	int ret;
+
+	if (!upd720x_smmu_init(&pDev->dev))
+		return -EFAULT;
+
+	for (lc = 0; (lc < 2) && (fw_pointer == NULL); lc++) {
+		ret = request_firmware((const struct firmware **)&fw_pointer,
+			firmwarename, &pDev->bus->dev);
+		if (ret == 0) {
+			result = upd720x_firmware_download(pDev,
+				(unsigned char *)fw_pointer->data,
+				fw_pointer->size);
+			break;
+		}
+		result = ret;
+	}
+	return result;
+}
+
+
+
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index b514055..3e6c437 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -192,8 +192,10 @@
 		xhci->quirks |= XHCI_BROKEN_STREAMS;
 	}
 	if (pdev->vendor == PCI_VENDOR_ID_RENESAS &&
-			pdev->device == 0x0014)
+			pdev->device == 0x0014) {
 		xhci->quirks |= XHCI_TRUST_TX_LENGTH;
+		upd720x_finish_download(pdev);
+	}
 	if (pdev->vendor == PCI_VENDOR_ID_RENESAS &&
 			pdev->device == 0x0015)
 		xhci->quirks |= XHCI_RESET_ON_RESUME;
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index 0267bed..418978e 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -67,6 +67,7 @@
 	GSI_EP_OP_SET_CLR_BLOCK_DBL,
 	GSI_EP_OP_CHECK_FOR_SUSPEND,
 	GSI_EP_OP_DISABLE,
+	GSI_EP_OP_UPDATE_DB,
 };
 
 /*
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 6f7d15a..87e674b 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -3914,6 +3914,7 @@
 {
 	struct sched_entity *left = __pick_first_entity(cfs_rq);
 	struct sched_entity *se;
+	bool strict_skip = false;
 
 	/*
 	 * If curr is set we have to see if its left of the leftmost entity
@@ -3933,13 +3934,15 @@
 
 		if (se == curr) {
 			second = __pick_first_entity(cfs_rq);
+			if (sched_feat(STRICT_SKIP_BUDDY))
+				strict_skip = true;
 		} else {
 			second = __pick_next_entity(se);
 			if (!second || (curr && entity_before(curr, second)))
 				second = curr;
 		}
 
-		if (second && (sched_feat(STRICT_SKIP_BUDDY) ||
+		if (second && (strict_skip ||
 		    wakeup_preempt_entity(second, left) < 1))
 			se = second;
 	}