Merge branch 'android-msm-barbet-4.19-sc-security' into android-msm-barbet-4.19-sc

Nov 2021.1

Bug: 198397628
Change-Id: I657688f1d4c9812e5463a7eae23e758cc1ceaba7
diff --git a/Documentation/ABI/testing/sysfs-class-udc b/Documentation/ABI/testing/sysfs-class-udc
new file mode 100644
index 0000000..3119a04
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-udc
@@ -0,0 +1,16 @@
+What:		/sys/class/udc/<udc name>/device/usb_data_enabled
+Date:		December 2020
+Contact:	"Ray Chi" <raychi@google.com>
+Description:
+		The attribute can allow user space can check and modify
+		the value to enable or disable usb functionality. Therefore,
+		if the attritube is set to 0, USB host and USB peripheral
+		modes wouldn't be working.
+
+		Example:
+		Enable USB data functionality
+		# echo 1 > /sys/class/udc/.../device/usb_data_enabled
+
+		Disable USB data functionality
+		# echo 0 > /sys/class/udc/.../device/usb_data_enabled
+
diff --git a/arch/arm64/boot/dts/google/lito-redbull-battery.dtsi b/arch/arm64/boot/dts/google/lito-redbull-battery.dtsi
index 61cad1b..8c630de 100644
--- a/arch/arm64/boot/dts/google/lito-redbull-battery.dtsi
+++ b/arch/arm64/boot/dts/google/lito-redbull-battery.dtsi
@@ -55,11 +55,12 @@
 			   "batt-id";
 	qcom,cl-feedback-on;
 	qcom,qg-ext-sns;
-	qcom,cl-max-increment = <5>;
-	qcom,cl-max-decrement = <10>;
+	qcom,cl-max-increment = <3>;
+	qcom,cl-max-decrement = <5>;
 	qcom,cl-min-limit = <500>;
 	qcom,cl-max-limit = <0>;
 	qcom,cl-min-delta-batt-soc = <10>;
+	google,cl-degrade = <50>;
 	qcom,cl-wt-enable;
 	qcom,vbatt-cutoff-mv = <3300>;
 	qcom,vbatt-low-mv = <3500>;
@@ -213,6 +214,7 @@
 		google,bd-recharge-soc = <79>;
 		/* Enable TEMP-DEFEND */
 		google,bd-temp-enable;
+		google,bd-temp-dry-run;
 	};
 
 	google_charger_pd_5v: google,charger_pd_5v {
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c
index 0ffd25fa..2b2ce7a 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c
@@ -709,6 +709,7 @@
 	u32 pyld_sz;
 	u64 uptr = 0;
 	u8 *param = NULL;
+	u8 *param2 = NULL;
 	u8 *kptr = NULL;
 
 	if (copy_from_user(header, (const void __user *)arg,
@@ -747,11 +748,20 @@
 		retval = -EFAULT;
 		goto free_param_kptr;
 	}
+
+	param2 = memdup_user((const void __user *)arg,
+		sizeof(struct ipa_ioc_add_rt_rule_v2));
+	if (IS_ERR(param2)) {
+		retval = -EFAULT;
+		goto free_param_kptr;
+	}
+
+
 	/* add check in case user-space module compromised */
-	if (unlikely(((struct ipa_ioc_add_rt_rule_v2 *)param)->num_rules
+	if (unlikely(((struct ipa_ioc_add_rt_rule_v2 *)param2)->num_rules
 		!= pre_entry)) {
 		IPAERR_RL("current %d pre %d\n",
-			((struct ipa_ioc_add_rt_rule_v2 *)param)->
+			((struct ipa_ioc_add_rt_rule_v2 *)param2)->
 				num_rules, pre_entry);
 			retval = -EFAULT;
 			goto free_param_kptr;
@@ -795,6 +805,8 @@
 free_param_kptr:
 	if (!IS_ERR(param))
 		kfree(param);
+	if (!IS_ERR(param2))
+		kfree(param2);
 	kfree(kptr);
 
 	return retval;
@@ -810,6 +822,7 @@
 	u32 pyld_sz;
 	u64 uptr = 0;
 	u8 *param = NULL;
+	u8 *param2 = NULL;
 	u8 *kptr = NULL;
 
 	if (copy_from_user(header,
@@ -851,11 +864,20 @@
 		retval = -EFAULT;
 		goto free_param_kptr;
 	}
+
+	param2 = memdup_user((const void __user *)arg,
+		sizeof(struct ipa_ioc_add_rt_rule_ext_v2));
+	if (IS_ERR(param2)) {
+		retval = -EFAULT;
+		goto free_param_kptr;
+	}
+
+
 	/* add check in case user-space module compromised */
-	if (unlikely(((struct ipa_ioc_add_rt_rule_ext_v2 *)param)->num_rules
+	if (unlikely(((struct ipa_ioc_add_rt_rule_ext_v2 *)param2)->num_rules
 		!= pre_entry)) {
 		IPAERR_RL("current %d pre %d\n",
-			((struct ipa_ioc_add_rt_rule_ext_v2 *)param)->
+			((struct ipa_ioc_add_rt_rule_ext_v2 *)param2)->
 				num_rules, pre_entry);
 			retval = -EFAULT;
 			goto free_param_kptr;
@@ -901,6 +923,8 @@
 free_param_kptr:
 	if (!IS_ERR(param))
 		kfree(param);
+	if (!IS_ERR(param2))
+		kfree(param2);
 	kfree(kptr);
 
 	return retval;
@@ -916,6 +940,7 @@
 	u32 pyld_sz;
 	u64 uptr = 0;
 	u8 *param = NULL;
+	u8 *param2 = NULL;
 	u8 *kptr = NULL;
 
 	if (copy_from_user(header, (const void __user *)arg,
@@ -956,11 +981,19 @@
 		retval = -EFAULT;
 		goto free_param_kptr;
 	}
+
+	param2 = memdup_user((const void __user *)arg,
+		sizeof(struct ipa_ioc_add_rt_rule_after_v2));
+	if (IS_ERR(param2)) {
+		retval = -EFAULT;
+		goto free_param_kptr;
+	}
+
 	/* add check in case user-space module compromised */
-	if (unlikely(((struct ipa_ioc_add_rt_rule_after_v2 *)param)->num_rules
+	if (unlikely(((struct ipa_ioc_add_rt_rule_after_v2 *)param2)->num_rules
 		!= pre_entry)) {
 		IPAERR_RL("current %d pre %d\n",
-			((struct ipa_ioc_add_rt_rule_after_v2 *)param)->
+			((struct ipa_ioc_add_rt_rule_after_v2 *)param2)->
 				num_rules, pre_entry);
 			retval = -EFAULT;
 			goto free_param_kptr;
@@ -1004,6 +1037,8 @@
 free_param_kptr:
 	if (!IS_ERR(param))
 		kfree(param);
+	if (!IS_ERR(param2))
+		kfree(param2);
 	kfree(kptr);
 
 	return retval;
@@ -1019,6 +1054,7 @@
 	u32 pyld_sz;
 	u64 uptr = 0;
 	u8 *param = NULL;
+	u8 *param2 = NULL;
 	u8 *kptr = NULL;
 
 	if (copy_from_user(header, (const void __user *)arg,
@@ -1059,11 +1095,19 @@
 		retval = -EFAULT;
 		goto free_param_kptr;
 	}
+
+	param2 = memdup_user((const void __user *)arg,
+		sizeof(struct ipa_ioc_mdfy_rt_rule_v2));
+	if (IS_ERR(param2)) {
+		retval = -EFAULT;
+		goto free_param_kptr;
+	}
+
 	/* add check in case user-space module compromised */
-	if (unlikely(((struct ipa_ioc_mdfy_rt_rule_v2 *)param)->num_rules
+	if (unlikely(((struct ipa_ioc_mdfy_rt_rule_v2 *)param2)->num_rules
 		!= pre_entry)) {
 		IPAERR_RL("current %d pre %d\n",
-			((struct ipa_ioc_mdfy_rt_rule_v2 *)param)->
+			((struct ipa_ioc_mdfy_rt_rule_v2 *)param2)->
 				num_rules, pre_entry);
 			retval = -EFAULT;
 			goto free_param_kptr;
@@ -1107,6 +1151,8 @@
 free_param_kptr:
 	if (!IS_ERR(param))
 		kfree(param);
+	if (!IS_ERR(param2))
+		kfree(param2);
 	kfree(kptr);
 
 	return retval;
@@ -1122,6 +1168,7 @@
 	u32 pyld_sz;
 	u64 uptr = 0;
 	u8 *param = NULL;
+	u8 *param2 = NULL;
 	u8 *kptr = NULL;
 
 	if (copy_from_user(header, (const void __user *)arg,
@@ -1161,11 +1208,19 @@
 		retval = -EFAULT;
 		goto free_param_kptr;
 	}
+
+	param2 = memdup_user((const void __user *)arg,
+		sizeof(struct ipa_ioc_add_flt_rule_v2));
+	if (IS_ERR(param2)) {
+		retval = -EFAULT;
+		goto free_param_kptr;
+	}
+
 	/* add check in case user-space module compromised */
-	if (unlikely(((struct ipa_ioc_add_flt_rule_v2 *)param)->num_rules
+	if (unlikely(((struct ipa_ioc_add_flt_rule_v2 *)param2)->num_rules
 		!= pre_entry)) {
 		IPAERR_RL("current %d pre %d\n",
-			((struct ipa_ioc_add_flt_rule_v2 *)param)->
+			((struct ipa_ioc_add_flt_rule_v2 *)param2)->
 				num_rules, pre_entry);
 			retval = -EFAULT;
 			goto free_param_kptr;
@@ -1208,6 +1263,8 @@
 free_param_kptr:
 	if (!IS_ERR(param))
 		kfree(param);
+	if (!IS_ERR(param2))
+		kfree(param2);
 	kfree(kptr);
 
 	return retval;
@@ -1223,6 +1280,7 @@
 	u32 pyld_sz;
 	u64 uptr = 0;
 	u8 *param = NULL;
+	u8 *param2 = NULL;
 	u8 *kptr = NULL;
 
 	if (copy_from_user(header, (const void __user *)arg,
@@ -1263,11 +1321,19 @@
 		retval = -EFAULT;
 		goto free_param_kptr;
 	}
+
+	param2 = memdup_user((const void __user *)arg,
+		sizeof(struct ipa_ioc_add_flt_rule_after_v2));
+	if (IS_ERR(param2)) {
+		retval = -EFAULT;
+		goto free_param_kptr;
+	}
+
 	/* add check in case user-space module compromised */
-	if (unlikely(((struct ipa_ioc_add_flt_rule_after_v2 *)param)->num_rules
+	if (unlikely(((struct ipa_ioc_add_flt_rule_after_v2 *)param2)->num_rules
 		!= pre_entry)) {
 		IPAERR_RL("current %d pre %d\n",
-			((struct ipa_ioc_add_flt_rule_after_v2 *)param)->
+			((struct ipa_ioc_add_flt_rule_after_v2 *)param2)->
 				num_rules, pre_entry);
 			retval = -EFAULT;
 			goto free_param_kptr;
@@ -1311,6 +1377,8 @@
 free_param_kptr:
 	if (!IS_ERR(param))
 		kfree(param);
+	if (!IS_ERR(param2))
+		kfree(param2);
 	kfree(kptr);
 
 	return retval;
@@ -1326,6 +1394,7 @@
 	u32 pyld_sz;
 	u64 uptr = 0;
 	u8 *param = NULL;
+	u8 *param2 = NULL;
 	u8 *kptr = NULL;
 
 	if (copy_from_user(header, (const void __user *)arg,
@@ -1366,11 +1435,19 @@
 		retval = -EFAULT;
 		goto free_param_kptr;
 	}
+
+	param2 = memdup_user((const void __user *)arg,
+		sizeof(struct ipa_ioc_mdfy_flt_rule_v2));
+	if (IS_ERR(param2)) {
+		retval = -EFAULT;
+		goto free_param_kptr;
+	}
+
 	/* add check in case user-space module compromised */
-	if (unlikely(((struct ipa_ioc_mdfy_flt_rule_v2 *)param)->num_rules
+	if (unlikely(((struct ipa_ioc_mdfy_flt_rule_v2 *)param2)->num_rules
 		!= pre_entry)) {
 		IPAERR_RL("current %d pre %d\n",
-			((struct ipa_ioc_mdfy_flt_rule_v2 *)param)->
+			((struct ipa_ioc_mdfy_flt_rule_v2 *)param2)->
 				num_rules, pre_entry);
 			retval = -EFAULT;
 			goto free_param_kptr;
@@ -1414,6 +1491,8 @@
 free_param_kptr:
 	if (!IS_ERR(param))
 		kfree(param);
+	if (!IS_ERR(param2))
+		kfree(param2);
 	kfree(kptr);
 
 	return retval;
diff --git a/drivers/power/supply/google/google_battery.c b/drivers/power/supply/google/google_battery.c
index 24174b2..5206a61 100644
--- a/drivers/power/supply/google/google_battery.c
+++ b/drivers/power/supply/google/google_battery.c
@@ -2741,6 +2741,12 @@
 	ssoc_state->buck_enabled = ben;
 }
 
+static void bd_trickle_reset(struct batt_ssoc_state *ssoc_state)
+{
+	ssoc_state->bd_trickle_cnt = 0;
+	ssoc_state->disconnect_time = 0;
+}
+
 /* called holding chg_lock */
 static int batt_chg_logic(struct batt_drv *batt_drv)
 {
@@ -4128,6 +4134,26 @@
 
 static DEVICE_ATTR_RW(bd_trickle_reset_sec);
 
+static ssize_t bd_clear_store(struct device *dev,
+			      struct device_attribute *attr,
+			      const char *buf, size_t count)
+{
+	struct power_supply *psy = container_of(dev, struct power_supply, dev);
+	struct batt_drv *batt_drv = power_supply_get_drvdata(psy);
+	int ret = 0, val = 0;
+
+	ret = kstrtoint(buf, 0, &val);
+	if (ret < 0)
+		return ret;
+
+	if (val)
+		bd_trickle_reset(&batt_drv->ssoc_state);
+
+	return count;
+}
+
+static DEVICE_ATTR_WO(bd_clear);
+
 static ssize_t health_safety_margin_show(struct device *dev,
 				   struct device_attribute *attr, char *buf)
 {
@@ -4181,6 +4207,7 @@
 	&dev_attr_bd_trickle_recharge_soc.attr,
 	&dev_attr_bd_trickle_dry_run.attr,
 	&dev_attr_bd_trickle_reset_sec.attr,
+	&dev_attr_bd_clear.attr,
 	&dev_attr_health_safety_margin.attr,
 	NULL,
 };
diff --git a/drivers/power/supply/google/google_charger.c b/drivers/power/supply/google/google_charger.c
index 304cc9d..18a7fab 100644
--- a/drivers/power/supply/google/google_charger.c
+++ b/drivers/power/supply/google/google_charger.c
@@ -2691,6 +2691,40 @@
 
 static DEVICE_ATTR_RW(bd_temp_dry_run);
 
+static ssize_t bd_clear_store(struct device *dev, struct device_attribute *attr,
+			      const char *buf, size_t count)
+{
+	struct chg_drv *chg_drv = dev_get_drvdata(dev);
+	int ret = 0, val = 0;
+
+	ret = kstrtoint(buf, 0, &val);
+	if (ret < 0)
+		return ret;
+
+	if (!val)
+		return ret;
+
+	mutex_lock(&chg_drv->bd_lock);
+
+	ret = bd_batt_set_state(chg_drv, false, -1);
+	if (ret < 0)
+		pr_err("MSC_BD set_batt_state (%d)\n", ret);
+
+	bd_reset(&chg_drv->bd_state);
+
+	if (chg_drv->chg_psy)
+		power_supply_changed(chg_drv->chg_psy);
+
+	mutex_unlock(&chg_drv->bd_lock);
+
+	if (chg_drv->bat_psy)
+		power_supply_changed(chg_drv->bat_psy);
+
+	return count;
+}
+
+static DEVICE_ATTR_WO(bd_clear);
+
 /* TODO: now created in qcom code, create in chg_create_votables() */
 static int chg_find_votables(struct chg_drv *chg_drv)
 {
@@ -3178,6 +3212,12 @@
 		return ret;
 	}
 
+	ret = device_create_file(chg_drv->device, &dev_attr_bd_clear);
+	if (ret != 0) {
+		pr_err("Failed to create bd_clear files, ret=%d\n", ret);
+		return ret;
+	}
+
 	de = debugfs_create_dir("google_charger", 0);
 
 	if (!de)
diff --git a/drivers/power/supply/qcom/fg-alg.c b/drivers/power/supply/qcom/fg-alg.c
index 0159f15..0352382 100644
--- a/drivers/power/supply/qcom/fg-alg.c
+++ b/drivers/power/supply/qcom/fg-alg.c
@@ -12,6 +12,8 @@
 #include <linux/slab.h>
 #include <linux/sort.h>
 #include "fg-alg.h"
+#include "qg-sdam.h"
+#include "qg-reg.h"
 
 #define FULL_SOC_RAW		255
 #define CAPACITY_DELTA_DECIPCT	500
@@ -294,6 +296,22 @@
 	return 0;
 }
 
+static int read_cycle_count(void)
+{
+	u16 count[BUCKET_COUNT];
+	int id, rc;
+	int64_t temp = 0;
+
+	rc = qg_sdam_multibyte_read(QG_SDAM_CYCLE_COUNT_OFFSET, (u8 *)count,
+				    sizeof(count));
+	if (rc < 0)
+		return -EINVAL;
+	for (id = 0; id < BUCKET_COUNT; id++)
+		temp += count[id];
+
+	return (temp / 100);
+}
+
 /* Capacity learning algorithm APIs */
 
 /**
@@ -331,13 +349,29 @@
 	else
 		cl->learned_cap_uah = cl->final_cap_uah;
 
+	if (cl->dt.cap_degrade > 0) {
+		int count = read_cycle_count();
+
+		if (count >= 0) {
+			min_dec_val = (int64_t)cl->nom_cap_uah *
+				      (1000 - (cl->dt.cap_degrade *
+					       ((count / 100) + 1)));
+			min_dec_val = div64_u64(min_dec_val, 1000);
+			if (cl->learned_cap_uah < min_dec_val) {
+				pr_err("capacity %lld below degrade %lld\n",
+				       cl->learned_cap_uah, min_dec_val);
+				cl->learned_cap_uah = min_dec_val;
+			}
+		}
+	}
+
 	if (cl->dt.max_cap_limit >= 0) {
 		max_inc_val = (int64_t)cl->nom_cap_uah * (1000 +
 				cl->dt.max_cap_limit);
 		max_inc_val = div64_u64(max_inc_val, 1000);
-		if (cl->final_cap_uah > max_inc_val) {
+		if (cl->learned_cap_uah > max_inc_val) {
 			pr_debug("learning capacity %lld goes above max limit %lld\n",
-				cl->final_cap_uah, max_inc_val);
+				cl->learned_cap_uah, max_inc_val);
 			cl->learned_cap_uah = max_inc_val;
 		}
 	}
@@ -346,9 +380,9 @@
 		min_dec_val = (int64_t)cl->nom_cap_uah * (1000 -
 				cl->dt.min_cap_limit);
 		min_dec_val = div64_u64(min_dec_val, 1000);
-		if (cl->final_cap_uah < min_dec_val) {
+		if (cl->learned_cap_uah < min_dec_val) {
 			pr_debug("learning capacity %lld goes below min limit %lld\n",
-				cl->final_cap_uah, min_dec_val);
+				cl->learned_cap_uah, min_dec_val);
 			cl->learned_cap_uah = min_dec_val;
 		}
 	}
@@ -541,6 +575,9 @@
 {
 	int rc;
 
+	if (cl->cl_skip == true)
+		return -ENODATA;
+
 	rc = cap_learning_process_full_data(cl, batt_soc_cp);
 	if (rc < 0) {
 		pr_debug("Error in processing cap learning full data, rc=%d\n",
@@ -630,6 +667,8 @@
 		if (charge_status == POWER_SUPPLY_STATUS_CHARGING) {
 			rc = cap_learning_begin(cl, batt_soc_cp);
 			cl->active = (rc == 0);
+			if (cl->active)
+				cl->cl_skip = false;
 		} else {
 			if (charge_status == POWER_SUPPLY_STATUS_DISCHARGING ||
 				charge_done)
diff --git a/drivers/power/supply/qcom/fg-alg.h b/drivers/power/supply/qcom/fg-alg.h
index 34442c7..df9b3e8 100644
--- a/drivers/power/supply/qcom/fg-alg.h
+++ b/drivers/power/supply/qcom/fg-alg.h
@@ -41,6 +41,7 @@
 	int	max_cap_dec;
 	int	max_cap_limit;
 	int	min_cap_limit;
+	int	cap_degrade;
 	int	skew_decipct;
 	int	min_delta_batt_soc;
 	int	ibat_flt_thr_ma;
@@ -59,6 +60,7 @@
 	int64_t			learned_cap_uah;
 	int64_t			delta_cap_uah;
 	bool			active;
+	bool			cl_skip;
 	struct mutex		lock;
 	struct cl_params	dt;
 	bool (*ok_to_begin)(void *data);
diff --git a/drivers/power/supply/qcom/qpnp-qg.c b/drivers/power/supply/qcom/qpnp-qg.c
index da4777b..f6ff7a2 100644
--- a/drivers/power/supply/qcom/qpnp-qg.c
+++ b/drivers/power/supply/qcom/qpnp-qg.c
@@ -1309,7 +1309,9 @@
 		} else if (input_present && cc_soc_delta > MAX_CC_SOC_DELTA) {
 			pr_info("cc_soc %d exceeds FULL, calibrate qg_soc\n",
 				chip->udata.param[QG_CC_SOC].data);
-			qg_trigger_good_ocv(chip);
+			rc = qg_trigger_good_ocv(chip);
+			if (rc == 0)
+				chip->cl->cl_skip = true;
 		} else {
 			chip->cc_soc = chip->udata.param[QG_CC_SOC].data;
 		}
@@ -4394,6 +4396,12 @@
 	else
 		chip->cl->dt.max_cap_limit = temp;
 
+	rc = of_property_read_u32(node, "google,cl-degrade", &temp);
+	if (rc < 0)
+		chip->cl->dt.cap_degrade = 0;
+	else
+		chip->cl->dt.cap_degrade = temp;
+
 	chip->cl->dt.min_delta_batt_soc = DEFAULT_CL_DELTA_BATT_SOC;
 	/* read from DT property and update, if value exists */
 	of_property_read_u32(node, "qcom,cl-min-delta-batt-soc",
diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c
index 74542a9..1fc4243 100644
--- a/drivers/power/supply/qcom/smb5-lib.c
+++ b/drivers/power/supply/qcom/smb5-lib.c
@@ -2473,7 +2473,7 @@
 	if (stat & BAT_TEMP_STATUS_TOO_COLD_BIT)
 		val->intval = POWER_SUPPLY_HEALTH_COLD;
 	else if (stat & BAT_TEMP_STATUS_TOO_HOT_BIT)
-		val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
+		val->intval = POWER_SUPPLY_HEALTH_HOT;
 	else if (stat & BAT_TEMP_STATUS_COLD_SOFT_BIT)
 		val->intval = POWER_SUPPLY_HEALTH_COOL;
 	else if (stat & BAT_TEMP_STATUS_HOT_SOFT_BIT)
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index 6fc1f87..51ed1c9 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -360,6 +360,7 @@
 	u64			dummy_gsi_db;
 	dma_addr_t		dummy_gsi_db_dma;
 	int			orientation_override;
+	bool usb_data_enabled;
 };
 
 #define USB_HSPHY_3P3_VOL_MIN		3050000 /* uV */
@@ -3275,6 +3276,9 @@
 	if (!edev || !mdwc)
 		return NOTIFY_DONE;
 
+	if (!mdwc->usb_data_enabled)
+		return NOTIFY_DONE;
+
 	dwc = platform_get_drvdata(mdwc->dwc3);
 
 	dbg_event(0xFF, "extcon idx", enb->idx);
@@ -3336,6 +3340,9 @@
 	if (!edev || !mdwc)
 		return NOTIFY_DONE;
 
+	if (!mdwc->usb_data_enabled)
+		return NOTIFY_DONE;
+
 	dwc = platform_get_drvdata(mdwc->dwc3);
 
 	dbg_event(0xFF, "extcon idx", enb->idx);
@@ -3693,6 +3700,34 @@
 }
 static DEVICE_ATTR_RW(auto_vbus_src_sel_threshold);
 
+static ssize_t usb_data_enabled_show(struct device *dev,
+				     struct device_attribute *attr, char *buf)
+{
+	struct dwc3_msm *mdwc = dev_get_drvdata(dev);
+
+	return sysfs_emit(buf, "%s\n",
+			  mdwc->usb_data_enabled ? "enabled" : "disabled");
+}
+
+static ssize_t usb_data_enabled_store(struct device *dev,
+				      struct device_attribute *attr,
+				      const char *buf, size_t count)
+{
+	struct dwc3_msm *mdwc = dev_get_drvdata(dev);
+
+	if (kstrtobool(buf, &mdwc->usb_data_enabled))
+		return -EINVAL;
+
+	if (!mdwc->usb_data_enabled) {
+		mdwc->vbus_active = false;
+		mdwc->id_state = DWC3_ID_FLOAT;
+		dwc3_ext_event_notify(mdwc);
+	}
+
+	return count;
+}
+static DEVICE_ATTR_RW(usb_data_enabled);
+
 static int dwc3_msm_probe(struct platform_device *pdev)
 {
 	struct device_node *node = pdev->dev.of_node, *dwc3_node;
@@ -4065,12 +4100,15 @@
 		dwc3_ext_event_notify(mdwc);
 	}
 
+	/* set the initial value */
+	mdwc->usb_data_enabled = true;
 	device_create_file(&pdev->dev, &dev_attr_orientation);
 	device_create_file(&pdev->dev, &dev_attr_mode);
 	device_create_file(&pdev->dev, &dev_attr_speed);
 	device_create_file(&pdev->dev, &dev_attr_usb_compliance_mode);
 	device_create_file(&pdev->dev, &dev_attr_bus_vote);
 	device_create_file(&pdev->dev, &dev_attr_auto_vbus_src_sel_threshold);
+	device_create_file(&pdev->dev, &dev_attr_usb_data_enabled);
 
 	return 0;
 
@@ -4100,6 +4138,7 @@
 	}
 
 	device_remove_file(&pdev->dev, &dev_attr_auto_vbus_src_sel_threshold);
+	device_create_file(&pdev->dev, &dev_attr_usb_data_enabled);
 
 	if (mdwc->usb_psy)
 		power_supply_put(mdwc->usb_psy);
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index be9a51e..3011668 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1830,19 +1830,11 @@
 			 */
 			list_for_each_entry_safe(r, t, &dep->started_list, list)
 				dwc3_gadget_move_cancelled_request(r);
-			/* If GEN1 controller then cleanup the cancelled
-			 * requests from here as check for
-			 * DWC3_EP_END_TRANSFER_PENDING in EPCMDCMPLT
-			 * will prevent the request on cancelled list from
-			 * getting cleared there.
-			 */
-			if (!(dep->flags & DWC3_EP_END_TRANSFER_PENDING)) {
-				dbg_log_string("%s:giveback all request\n",
-								     __func__);
-				dwc3_gadget_ep_cleanup_cancelled_requests(dep);
-			}
 
-			goto out0;
+			if (dep->flags & DWC3_EP_TRANSFER_STARTED)
+				goto out0;
+			else
+				goto out1;
 		}
 		dev_err_ratelimited(dwc->dev, "request %pK was not queued to %s\n",
 				request, ep->name);
@@ -1850,6 +1842,7 @@
 		goto out0;
 	}
 
+out1:
 	dbg_ep_dequeue(dep->number, req);
 	dwc3_gadget_ep_skip_trbs(dep, req);
 	dwc3_gadget_giveback(dep, req, -ECONNRESET);
@@ -3293,12 +3286,8 @@
 	case DWC3_DEPEVT_EPCMDCMPLT:
 		dep->dbg_ep_events.epcmdcomplete++;
 		cmd = DEPEVT_PARAMETER_CMD(event->parameters);
-		/* Prevent GEN1 controllers to cleanup cancelled
-		 * request twice (one from error path in kick_transfer
-		 * another from here).
-		 */
-		if (cmd == DWC3_DEPCMD_ENDTRANSFER &&
-			(dep->flags & DWC3_EP_END_TRANSFER_PENDING)) {
+
+		if (cmd == DWC3_DEPCMD_ENDTRANSFER) {
 			dep->flags &= ~(DWC3_EP_END_TRANSFER_PENDING |
 					DWC3_EP_TRANSFER_STARTED);
 			dwc3_gadget_ep_cleanup_cancelled_requests(dep);
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index ff03d8a..497a723 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -2587,6 +2587,8 @@
 		return true;
 	if (f2fs_is_atomic_file(inode))
 		return true;
+	if (is_sbi_flag_set(sbi, SBI_NEED_FSCK))
+		return true;
 
 	/* swap file is migrating in aligned write mode */
 	if (is_inode_flag_set(inode, FI_ALIGNED_WRITE))
@@ -3949,6 +3951,8 @@
 		get_page(newpage);
 	}
 
+	/* guarantee to start from no stale private field */
+	set_page_private(newpage, 0);
 	if (PagePrivate(page)) {
 		set_page_private(newpage, page_private(page));
 		SetPagePrivate(newpage);
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index ca637cd..b8dee37 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -1331,7 +1331,8 @@
 #define PAGE_PRIVATE_GET_FUNC(name, flagname) \
 static inline bool page_private_##name(struct page *page) \
 { \
-	return test_bit(PAGE_PRIVATE_NOT_POINTER, &page_private(page)) && \
+	return PagePrivate(page) && \
+		test_bit(PAGE_PRIVATE_NOT_POINTER, &page_private(page)) && \
 		test_bit(PAGE_PRIVATE_##flagname, &page_private(page)); \
 }
 
@@ -1341,6 +1342,7 @@
 	if (!PagePrivate(page)) { \
 		get_page(page); \
 		SetPagePrivate(page); \
+		set_page_private(page, 0); \
 	} \
 	set_bit(PAGE_PRIVATE_NOT_POINTER, &page_private(page)); \
 	set_bit(PAGE_PRIVATE_##flagname, &page_private(page)); \
@@ -1399,6 +1401,7 @@
 	if (!PagePrivate(page)) {
 		get_page(page);
 		SetPagePrivate(page);
+		set_page_private(page, 0);
 	}
 	set_bit(PAGE_PRIVATE_NOT_POINTER, &page_private(page));
 	page_private(page) |= data << PAGE_PRIVATE_MAX;
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index 4a7cd4b..cdc3e0a 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -552,7 +552,7 @@
 	int i;
 
 	ni->nid = nid;
-
+retry:
 	/* Check nat cache */
 	down_read(&nm_i->nat_tree_lock);
 	e = __lookup_nat_cache(nm_i, nid);
@@ -564,10 +564,19 @@
 		return 0;
 	}
 
-	memset(&ne, 0, sizeof(struct f2fs_nat_entry));
+	/*
+	 * Check current segment summary by trying to grab journal_rwsem first.
+	 * This sem is on the critical path on the checkpoint requiring the
+	 * above nat_tree_lock. Therefore, we should retry, if we failed to grab
+	 * here while not bothering checkpoint.
+	 */
+	if (!rwsem_is_locked(&sbi->cp_global_sem)) {
+		down_read(&curseg->journal_rwsem);
+	} else if (!down_read_trylock(&curseg->journal_rwsem)) {
+		up_read(&nm_i->nat_tree_lock);
+		goto retry;
+	}
 
-	/* Check current segment summary */
-	down_read(&curseg->journal_rwsem);
 	i = f2fs_lookup_journal_in_cursum(journal, NAT_JOURNAL, nid, 0);
 	if (i >= 0) {
 		ne = nat_in_journal(journal, i);
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index c961aed..ad214ee 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -3562,7 +3562,7 @@
 		goto drop_bio;
 	}
 
-	if (is_sbi_flag_set(sbi, SBI_NEED_FSCK) || f2fs_cp_error(sbi)) {
+	if (f2fs_cp_error(sbi)) {
 		err = -EIO;
 		goto drop_bio;
 	}