Merge "msm: fbdev: add safety check for msm fb data object"
diff --git a/arch/arm64/boot/dts/qcom/apq8009-robot-som-refboard.dts b/arch/arm64/boot/dts/qcom/apq8009-robot-som-refboard.dts
index 103ef7f..f57383c 100644
--- a/arch/arm64/boot/dts/qcom/apq8009-robot-som-refboard.dts
+++ b/arch/arm64/boot/dts/qcom/apq8009-robot-som-refboard.dts
@@ -387,6 +387,10 @@
 	status = "okay";
 };
 
+&mdss_fb0 {
+	/delete-node/ qcom,cont-splash-memory;
+};
+
 &mdss_mdp {
 	qcom,mdss-pref-prim-intf = "dsi";
 	status = "okay";
@@ -436,3 +440,5 @@
 		status = "okay";
 	};
 };
+
+/delete-node/ &cont_splash_mem;
diff --git a/arch/arm64/boot/dts/qcom/msm8953-ext-codec-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/msm8953-ext-codec-mtp-overlay.dts
index 1b09b3c..350d88a 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-ext-codec-mtp-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/msm8953-ext-codec-mtp-overlay.dts
@@ -1,5 +1,5 @@
 /*
- * 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
@@ -46,6 +46,7 @@
 	qcom,battery-data = <&mtp_batterydata>;
 	qcom,chg-led-sw-controls;
 	qcom,chg-led-support;
+	qcom,usbin-vadc = <&pmi8950_vadc>;
 };
 
 &int_codec {
diff --git a/arch/arm64/boot/dts/qcom/msm8953-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/msm8953-mtp-overlay.dts
index 00614b2..92cd98d 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-mtp-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/msm8953-mtp-overlay.dts
@@ -1,5 +1,5 @@
 /*
- * 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
@@ -44,4 +44,5 @@
 	qcom,battery-data = <&mtp_batterydata>;
 	qcom,chg-led-sw-controls;
 	qcom,chg-led-support;
+	qcom,usbin-vadc = <&pmi8950_vadc>;
 };
diff --git a/arch/arm64/boot/dts/qcom/msm8953-mtp.dts b/arch/arm64/boot/dts/qcom/msm8953-mtp.dts
index 9b20013..e936adf 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/msm8953-mtp.dts
@@ -48,6 +48,7 @@
 	qcom,battery-data = <&mtp_batterydata>;
 	qcom,chg-led-sw-controls;
 	qcom,chg-led-support;
+	qcom,usbin-vadc = <&pmi8950_vadc>;
 };
 &cci {
 	 qcom,camera@0 {
diff --git a/arch/arm64/boot/dts/qcom/sda429-bg-wtp-overlay.dts b/arch/arm64/boot/dts/qcom/sda429-bg-wtp-overlay.dts
index 9602dd8..d12b346 100644
--- a/arch/arm64/boot/dts/qcom/sda429-bg-wtp-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/sda429-bg-wtp-overlay.dts
@@ -24,6 +24,115 @@
 	qcom,pmic-id = <0x0002001b 0x0 0x0 0x0>;
 };
 
+&soc {
+
+	qcom,blackghost {
+		compatible = "qcom,pil-blackghost";
+		qcom,pil-force-shutdown;
+		qcom,firmware-name = "bg-wear";
+		/* GPIO inputs from blackghost */
+		qcom,bg2ap-status-gpio = <&msm_gpio 44 0>;
+		qcom,bg2ap-errfatal-gpio = <&msm_gpio 72 0>;
+		/* GPIO output to blackghost */
+		qcom,ap2bg-status-gpio = <&msm_gpio 61 0>;
+		qcom,ap2bg-errfatal-gpio = <&msm_gpio 62 0>;
+	};
+
+	qcom,msm-ssc-sensors {
+		compatible = "qcom,msm-ssc-sensors";
+	};
+
+	qcom,glink-bgcom-xprt-bg {
+		compatible = "qcom,glink-bgcom-xprt";
+		label = "bg";
+		qcom,qos-config = <&glink_qos_bg>;
+		qcom,ramp-time = <0x10>,
+				     <0x20>,
+				     <0x30>,
+				     <0x40>;
+	};
+
+	glink_qos_bg: qcom,glink-qos-config-bg {
+		compatible = "qcom,glink-qos-config";
+		qcom,flow-info = <0x80 0x0>,
+				 <0x70 0x1>,
+				 <0x60 0x2>,
+				 <0x50 0x3>;
+		qcom,mtu-size = <0x800>;
+		qcom,tput-stats-cycle = <0xa>;
+	};
+
+	qcom,glink_pkt {
+		compatible = "qcom,glinkpkt";
+
+		qcom,glinkpkt-bg-daemon {
+			qcom,glinkpkt-transport = "bgcom";
+			qcom,glinkpkt-edge = "bg";
+			qcom,glinkpkt-ch-name = "bg-daemon";
+			qcom,glinkpkt-dev-name = "glink_pkt_bg_daemon";
+		};
+
+		qcom,glinkpkt-bg-display-ctrl {
+			qcom,glinkpkt-transport = "bgcom";
+			qcom,glinkpkt-edge = "bg";
+			qcom,glinkpkt-ch-name = "display-ctrl";
+			qcom,glinkpkt-dev-name = "glink_pkt_bg_display_ctrl";
+		};
+
+		qcom,glinkpkt-bg-display-data {
+			qcom,glinkpkt-transport = "bgcom";
+			qcom,glinkpkt-edge = "bg";
+			qcom,glinkpkt-ch-name = "display-data";
+			qcom,glinkpkt-dev-name = "glink_pkt_bg_display_data";
+		};
+
+		qcom,glinkpkt-bg-rsb-ctrl {
+			qcom,glinkpkt-transport = "bgcom";
+			qcom,glinkpkt-edge = "bg";
+			qcom,glinkpkt-ch-name = "RSB_CTRL";
+			qcom,glinkpkt-dev-name = "glink_pkt_bg_rsb_ctrl";
+		};
+
+		qcom,glinkpkt-bg-sso-ctrl {
+			qcom,glinkpkt-transport = "bgcom";
+			qcom,glinkpkt-edge = "bg";
+			qcom,glinkpkt-ch-name = "sso-ctrl";
+			qcom,glinkpkt-dev-name = "glink_pkt_bg_sso_ctrl";
+		};
+
+		qcom,glinkpkt-bg-buzzer-ctrl {
+			qcom,glinkpkt-transport = "bgcom";
+			qcom,glinkpkt-edge = "bg";
+			qcom,glinkpkt-ch-name = "buzzer-ctrl";
+			qcom,glinkpkt-dev-name = "glink_pkt_bg_buzzer_ctrl";
+		};
+	};
+
+	spi@78B8000 {  /* BLSP1 QUP4 */
+		status = "ok";
+		qcom,bg-spi {
+			compatible = "qcom,bg-spi";
+			reg = <0>;
+			spi-max-frequency = <16000000>;
+			interrupt-parent = <&msm_gpio>;
+			qcom,irq-gpio = <&msm_gpio 43 1>;
+		};
+	};
+
+	qcom,bg-rsb {
+		compatible = "qcom,bg-rsb";
+		vdd-ldo1-supply = <&pm660_l11>;
+		vdd-ldo2-supply = <&pm660_l15>;
+	};
+
+	qcom,bg-daemon {
+		compatible = "qcom,bg-daemon";
+		qcom,bg-reset-gpio = <&pm660_gpios 5 0>;
+		ssr-reg1-supply = <&pm660_l3>;
+		ssr-reg2-supply = <&pm660_l9>;
+	};
+};
+
 &usb_otg {
 	HSUSB_3p3-supply = <&L16A>;
 };
diff --git a/arch/arm64/boot/dts/qcom/sdm429-bg-wdp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm429-bg-wdp-overlay.dts
index a7ce1bd..53229a0 100644
--- a/arch/arm64/boot/dts/qcom/sdm429-bg-wdp-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/sdm429-bg-wdp-overlay.dts
@@ -24,6 +24,115 @@
 	qcom,pmic-id = <0x0002001b 0x0 0x0 0x0>;
 };
 
+&soc {
+
+	qcom,blackghost {
+		compatible = "qcom,pil-blackghost";
+		qcom,pil-force-shutdown;
+		qcom,firmware-name = "bg-wear";
+		/* GPIO inputs from blackghost */
+		qcom,bg2ap-status-gpio = <&msm_gpio 44 0>;
+		qcom,bg2ap-errfatal-gpio = <&msm_gpio 72 0>;
+		/* GPIO output to blackghost */
+		qcom,ap2bg-status-gpio = <&msm_gpio 61 0>;
+		qcom,ap2bg-errfatal-gpio = <&msm_gpio 62 0>;
+	};
+
+	qcom,msm-ssc-sensors {
+		compatible = "qcom,msm-ssc-sensors";
+	};
+
+	qcom,glink-bgcom-xprt-bg {
+		compatible = "qcom,glink-bgcom-xprt";
+		label = "bg";
+		qcom,qos-config = <&glink_qos_bg>;
+		qcom,ramp-time = <0x10>,
+				     <0x20>,
+				     <0x30>,
+				     <0x40>;
+	};
+
+	glink_qos_bg: qcom,glink-qos-config-bg {
+		compatible = "qcom,glink-qos-config";
+		qcom,flow-info = <0x80 0x0>,
+				 <0x70 0x1>,
+				 <0x60 0x2>,
+				 <0x50 0x3>;
+		qcom,mtu-size = <0x800>;
+		qcom,tput-stats-cycle = <0xa>;
+	};
+
+	qcom,glink_pkt {
+		compatible = "qcom,glinkpkt";
+
+		qcom,glinkpkt-bg-daemon {
+			qcom,glinkpkt-transport = "bgcom";
+			qcom,glinkpkt-edge = "bg";
+			qcom,glinkpkt-ch-name = "bg-daemon";
+			qcom,glinkpkt-dev-name = "glink_pkt_bg_daemon";
+		};
+
+		qcom,glinkpkt-bg-display-ctrl {
+			qcom,glinkpkt-transport = "bgcom";
+			qcom,glinkpkt-edge = "bg";
+			qcom,glinkpkt-ch-name = "display-ctrl";
+			qcom,glinkpkt-dev-name = "glink_pkt_bg_display_ctrl";
+		};
+
+		qcom,glinkpkt-bg-display-data {
+			qcom,glinkpkt-transport = "bgcom";
+			qcom,glinkpkt-edge = "bg";
+			qcom,glinkpkt-ch-name = "display-data";
+			qcom,glinkpkt-dev-name = "glink_pkt_bg_display_data";
+		};
+
+		qcom,glinkpkt-bg-rsb-ctrl {
+			qcom,glinkpkt-transport = "bgcom";
+			qcom,glinkpkt-edge = "bg";
+			qcom,glinkpkt-ch-name = "RSB_CTRL";
+			qcom,glinkpkt-dev-name = "glink_pkt_bg_rsb_ctrl";
+		};
+
+		qcom,glinkpkt-bg-sso-ctrl {
+			qcom,glinkpkt-transport = "bgcom";
+			qcom,glinkpkt-edge = "bg";
+			qcom,glinkpkt-ch-name = "sso-ctrl";
+			qcom,glinkpkt-dev-name = "glink_pkt_bg_sso_ctrl";
+		};
+
+		qcom,glinkpkt-bg-buzzer-ctrl {
+			qcom,glinkpkt-transport = "bgcom";
+			qcom,glinkpkt-edge = "bg";
+			qcom,glinkpkt-ch-name = "buzzer-ctrl";
+			qcom,glinkpkt-dev-name = "glink_pkt_bg_buzzer_ctrl";
+		};
+	};
+
+	spi@78B8000 {  /* BLSP1 QUP4 */
+		status = "ok";
+		qcom,bg-spi {
+			compatible = "qcom,bg-spi";
+			reg = <0>;
+			spi-max-frequency = <16000000>;
+			interrupt-parent = <&msm_gpio>;
+			qcom,irq-gpio = <&msm_gpio 43 1>;
+		};
+	};
+
+	qcom,bg-rsb {
+		compatible = "qcom,bg-rsb";
+		vdd-ldo1-supply = <&pm660_l11>;
+		vdd-ldo2-supply = <&pm660_l15>;
+	};
+
+	qcom,bg-daemon {
+		compatible = "qcom,bg-daemon";
+		qcom,bg-reset-gpio = <&pm660_gpios 5 0>;
+		ssr-reg1-supply = <&pm660_l3>;
+		ssr-reg2-supply = <&pm660_l9>;
+	};
+};
+
 &usb_otg {
 	HSUSB_3p3-supply = <&L16A>;
 };
diff --git a/drivers/input/sensors/smi130/smi130_acc.c b/drivers/input/sensors/smi130/smi130_acc.c
index a63e08e..a6416e4 100644
--- a/drivers/input/sensors/smi130/smi130_acc.c
+++ b/drivers/input/sensors/smi130/smi130_acc.c
@@ -133,7 +133,7 @@
 #include <linux/delay.h>
 #include <asm/irq.h>
 #include <linux/math64.h>
-
+#include <linux/cpu.h>
 #ifdef CONFIG_HAS_EARLYSUSPEND
 #include <linux/earlysuspend.h>
 #endif
@@ -159,7 +159,7 @@
 
 #define SENSOR_NAME                 "smi130_acc"
 #define SMI130_ACC_USE_BASIC_I2C_FUNC        1
-
+#define SMI130_HRTIMER 1
 #define MSC_TIME                6
 #define ABSMIN                      -512
 #define ABSMAX                      512
@@ -1573,7 +1573,6 @@
 	struct mutex enable_mutex;
 	struct mutex mode_mutex;
 	struct delayed_work work;
-	struct work_struct irq_work;
 #ifdef CONFIG_HAS_EARLYSUSPEND
 	struct early_suspend early_suspend;
 #endif
@@ -1611,8 +1610,57 @@
 	struct input_dev *accbuf_dev;
 	int report_evt_cnt;
 #endif
+#ifdef SMI130_HRTIMER
+	struct hrtimer smi130_hrtimer;
+#endif
 };
 
+#ifdef SMI130_HRTIMER
+static void smi130_set_cpu_idle_state(bool value)
+{
+	cpu_idle_poll_ctrl(value);
+}
+static enum hrtimer_restart smi130_timer_function(struct hrtimer *timer)
+{
+	smi130_set_cpu_idle_state(true);
+
+	return HRTIMER_NORESTART;
+}
+static void smi130_hrtimer_reset(struct smi130_acc_data *data)
+{
+	hrtimer_cancel(&data->smi130_hrtimer);
+	/*forward HRTIMER just before 1ms of irq arrival*/
+	hrtimer_forward(&data->smi130_hrtimer, ktime_get(),
+			ns_to_ktime(data->time_odr - 1000000));
+	hrtimer_restart(&data->smi130_hrtimer);
+}
+static void smi130_hrtimer_init(struct smi130_acc_data *data)
+{
+	hrtimer_init(&data->smi130_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+	data->smi130_hrtimer.function = smi130_timer_function;
+}
+static void smi130_hrtimer_cleanup(struct smi130_acc_data *data)
+{
+	hrtimer_cancel(&data->smi130_hrtimer);
+}
+#else
+static void smi130_set_cpu_idle_state(bool value)
+{
+}
+static void smi130_hrtimer_reset(struct smi130_acc_data *data)
+{
+
+}
+static void smi130_hrtimer_init(struct smi130_acc_data *data)
+{
+
+}
+static void smi130_hrtimer_remove(struct smi130_acc_data *data)
+{
+
+}
+#endif
+
 #ifdef CONFIG_HAS_EARLYSUSPEND
 static void smi130_acc_early_suspend(struct early_suspend *h);
 static void smi130_acc_late_resume(struct early_suspend *h);
@@ -3871,7 +3919,7 @@
 				signed char sensor_type, short *a_x)
 {
 	int comres = 0;
-	unsigned char data[2];
+	unsigned char data[2] = {0};
 
 	switch (sensor_type) {
 	case 0:
@@ -3940,7 +3988,7 @@
 				signed char sensor_type, short *a_y)
 {
 	int comres = 0;
-	unsigned char data[2];
+	unsigned char data[2] = {0};
 
 	switch (sensor_type) {
 	case 0:
@@ -3998,7 +4046,7 @@
 				signed char sensor_type, short *a_z)
 {
 	int comres = 0;
-	unsigned char data[2];
+	unsigned char data[2] = {0};
 
 	switch (sensor_type) {
 	case 0:
@@ -5087,7 +5135,7 @@
 		signed char sensor_type, struct smi130_accacc *acc)
 {
 	int comres = 0;
-	unsigned char data[6];
+	unsigned char data[6] = {0};
 	struct smi130_acc_data *client_data = i2c_get_clientdata(client);
 #ifndef SMI_ACC2X2_SENSOR_IDENTIFICATION_ENABLE
 	int bitwidth;
@@ -5381,7 +5429,7 @@
 	struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client);
 
 	size_t count = 0;
-	u8 reg[0x40];
+	u8 reg[0x40] = {0};
 	int i;
 
 	for (i = 0; i < 0x40; i++) {
@@ -6962,7 +7010,7 @@
 	if (!client_data->smi_acc_cachepool) {
 		PERR("smi_acc_cachepool cache create failed\n");
 		err = -ENOMEM;
-		goto clean_exit1;
+		return 0;
 	}
 	for (i = 0; i < SMI_ACC_MAXSAMPLE; i++) {
 		client_data->smi130_acc_samplist[i] =
@@ -6970,7 +7018,7 @@
 					GFP_KERNEL);
 		if (!client_data->smi130_acc_samplist[i]) {
 			err = -ENOMEM;
-			goto clean_exit2;
+			goto clean_exit1;
 		}
 	}
 
@@ -6978,7 +7026,7 @@
 	if (!client_data->accbuf_dev) {
 		err = -ENOMEM;
 		PERR("input device allocation failed\n");
-		goto clean_exit3;
+		goto clean_exit1;
 	}
 	client_data->accbuf_dev->name = "smi130_accbuf";
 	client_data->accbuf_dev->id.bustype = BUS_I2C;
@@ -6999,25 +7047,26 @@
 	if (err) {
 		PERR("unable to register input device %s\n",
 				client_data->accbuf_dev->name);
-		goto clean_exit3;
+		goto clean_exit2;
 	}
 
 	client_data->acc_buffer_smi130_samples = true;
 	client_data->acc_enable = false;
 
+	smi130_set_cpu_idle_state(true);
+
 	smi130_acc_set_mode(client, SMI_ACC2X2_MODE_NORMAL, 1);
 	smi130_acc_set_bandwidth(client, SMI_ACC2X2_BW_62_50HZ);
 	smi130_acc_set_range(client, SMI_ACC2X2_RANGE_2G);
 
 	return 1;
 
-clean_exit3:
-	input_free_device(client_data->accbuf_dev);
 clean_exit2:
+	input_free_device(client_data->accbuf_dev);
+clean_exit1:
 	for (i = 0; i < SMI_ACC_MAXSAMPLE; i++)
 		kmem_cache_free(client_data->smi_acc_cachepool,
 				client_data->smi130_acc_samplist[i]);
-clean_exit1:
 	kmem_cache_destroy(client_data->smi_acc_cachepool);
 	return 0;
 }
@@ -7044,10 +7093,9 @@
 }
 #endif
 
-static void smi130_acc_irq_work_func(struct work_struct *work)
+static irqreturn_t smi130_acc_irq_work_func(int irq, void *handle)
 {
-	struct smi130_acc_data *smi130_acc = container_of((struct work_struct *)work,
-			struct smi130_acc_data, irq_work);
+	struct smi130_acc_data *smi130_acc = handle;
 #ifdef CONFIG_DOUBLE_TAP
 	struct i2c_client *client = smi130_acc->smi130_acc_client;
 #endif
@@ -7092,8 +7140,10 @@
 		mutex_unlock(&smi130_acc->value_mutex);
 	}
 	store_acc_boot_sample(smi130_acc, acc.x, acc.y, acc.z, ts);
-#endif
 
+	smi130_set_cpu_idle_state(false);
+	return IRQ_HANDLED;
+#endif
 	smi130_acc_get_interruptstatus1(smi130_acc->smi130_acc_client, &status);
 	PDEBUG("smi130_acc_irq_work_func, status = 0x%x\n", status);
 
@@ -7246,10 +7296,9 @@
 	if (data->smi130_acc_client == NULL)
 		return IRQ_HANDLED;
 	data->timestamp = smi130_acc_get_alarm_timestamp();
+	smi130_hrtimer_reset(data);
 
-	schedule_work(&data->irq_work);
-
-	return IRQ_HANDLED;
+	return IRQ_WAKE_THREAD;
 }
 #endif /* defined(SMI_ACC2X2_ENABLE_INT1)||defined(SMI_ACC2X2_ENABLE_INT2) */
 
@@ -7363,7 +7412,6 @@
 	if (err)
 		PERR("could not request irq\n");
 
-	INIT_WORK(&data->irq_work, smi130_acc_irq_work_func);
 #endif
 
 #ifndef CONFIG_SMI_ACC_ENABLE_NEWDATA_INT
@@ -7558,9 +7606,11 @@
 		return -EINVAL;
 	data->IRQ = client->irq;
 	PDEBUG("data->IRQ = %d", data->IRQ);
-	err = request_irq(data->IRQ, smi130_acc_irq_handler, IRQF_TRIGGER_RISING,
+	err = request_threaded_irq(data->IRQ, smi130_acc_irq_handler,
+			smi130_acc_irq_work_func, IRQF_TRIGGER_RISING,
 			"smi130_acc", data);
 
+	smi130_hrtimer_init(data);
 	err = smi130_acc_early_buff_init(client, data);
 	if (!err)
 		goto exit;
@@ -7676,6 +7726,7 @@
 	if (NULL == data)
 		return 0;
 
+	smi130_hrtimer_cleanup(data);
 	smi130_acc_input_cleanup(data);
 	smi130_acc_set_enable(&client->dev, 0);
 #ifdef CONFIG_HAS_EARLYSUSPEND
diff --git a/drivers/input/sensors/smi130/smi130_driver.c b/drivers/input/sensors/smi130/smi130_driver.c
index 42a0a57..3991ada 100644
--- a/drivers/input/sensors/smi130/smi130_driver.c
+++ b/drivers/input/sensors/smi130/smi130_driver.c
@@ -2879,7 +2879,7 @@
 	struct smi_client_data *client_data = input_get_drvdata(input);
 
 	ssize_t ret;
-	u8 reg_data[128], i;
+	u8 reg_data[128] = {0}, i;
 	int pos;
 
 	if (client_data == NULL) {
@@ -2913,7 +2913,8 @@
 	struct input_dev *input = to_input_dev(dev);
 	struct smi_client_data *client_data = input_get_drvdata(input);
 	ssize_t ret;
-	u8 reg_data[32];
+	u8 reg_data[32] = {0};
+
 	int i, j, status, digit;
 
 	if (client_data == NULL) {
diff --git a/drivers/input/sensors/smi130/smi130_gyro_driver.c b/drivers/input/sensors/smi130/smi130_gyro_driver.c
index fd9e87d..e497a0a8 100644
--- a/drivers/input/sensors/smi130/smi130_gyro_driver.c
+++ b/drivers/input/sensors/smi130/smi130_gyro_driver.c
@@ -290,7 +290,6 @@
 	ktime_t work_delay_kt;
 	uint8_t gpio_pin;
 	int16_t IRQ;
-	struct work_struct irq_work;
 #ifdef CONFIG_ENABLE_SMI_ACC_GYRO_BUFFERING
 	bool read_gyro_boot_sample;
 	int gyro_bufsample_cnt;
@@ -422,7 +421,7 @@
 static void smi_gyro_dump_reg(struct i2c_client *client)
 {
 	int i;
-	u8 dbg_buf[64];
+	u8 dbg_buf[64] = {0};
 	u8 dbg_buf_str[64 * 3 + 1] = "";
 
 	for (i = 0; i < BYTES_PER_LINE; i++) {
@@ -1788,7 +1787,7 @@
 	if (!client_data->smi_gyro_cachepool) {
 		PERR("smi_gyro_cachepool cache create failed\n");
 		err = -ENOMEM;
-		goto clean_exit1;
+		return 0;
 	}
 
 	for (i = 0; i < SMI_GYRO_MAXSAMPLE; i++) {
@@ -1797,7 +1796,7 @@
 					GFP_KERNEL);
 		if (!client_data->smi130_gyro_samplist[i]) {
 			err = -ENOMEM;
-			goto clean_exit2;
+			goto clean_exit1;
 		}
 	}
 
@@ -1806,7 +1805,7 @@
 	if (!client_data->gyrobuf_dev) {
 		err = -ENOMEM;
 		PERR("input device allocation failed\n");
-		goto clean_exit3;
+		goto clean_exit1;
 	}
 	client_data->gyrobuf_dev->name = "smi130_gyrobuf";
 	client_data->gyrobuf_dev->id.bustype = BUS_I2C;
@@ -1827,7 +1826,7 @@
 	if (err) {
 		PERR("unable to register input device %s\n",
 				client_data->gyrobuf_dev->name);
-		goto clean_exit3;
+		goto clean_exit2;
 	}
 
 	client_data->gyro_buffer_smi130_samples = true;
@@ -1852,13 +1851,12 @@
 
 	return 1;
 
-clean_exit3:
-	input_free_device(client_data->gyrobuf_dev);
 clean_exit2:
+	input_free_device(client_data->gyrobuf_dev);
+clean_exit1:
 	for (i = 0; i < SMI_GYRO_MAXSAMPLE; i++)
 		kmem_cache_free(client_data->smi_gyro_cachepool,
 				client_data->smi130_gyro_samplist[i]);
-clean_exit1:
 	kmem_cache_destroy(client_data->smi_gyro_cachepool);
 	return 0;
 }
@@ -1895,10 +1893,9 @@
 
 
 #if defined(SMI130_GYRO_ENABLE_INT1) || defined(SMI130_GYRO_ENABLE_INT2)
-static void smi130_gyro_irq_work_func(struct work_struct *work)
+static irqreturn_t smi130_gyro_irq_work_func(int irq, void *handle)
 {
-	struct smi_gyro_client_data *client_data = container_of(work,
-		struct smi_gyro_client_data, irq_work);
+	struct smi_gyro_client_data *client_data = handle;
 	struct smi130_gyro_data_t gyro_data;
 	struct timespec ts;
 	ts = ns_to_timespec(client_data->timestamp);
@@ -1919,14 +1916,14 @@
 	input_sync(client_data->input);
 	store_gyro_boot_sample(client_data, gyro_data.datax,
 			gyro_data.datay, gyro_data.dataz, ts);
+	return IRQ_HANDLED;
 }
 
 static irqreturn_t smi_gyro_irq_handler(int irq, void *handle)
 {
 	struct smi_gyro_client_data *client_data = handle;
 	client_data->timestamp= smi130_gyro_get_alarm_timestamp();
-	schedule_work(&client_data->irq_work);
-	return IRQ_HANDLED;
+	return IRQ_WAKE_THREAD;
 }
 #endif
 static int smi_gyro_probe(struct i2c_client *client, const struct i2c_device_id *id)
@@ -2098,13 +2095,12 @@
 			PDEBUG("request failed\n");
 		}
 		client_data->IRQ = gpio_to_irq(client_data->gpio_pin);
-		err = request_irq(client_data->IRQ, smi_gyro_irq_handler,
-				IRQF_TRIGGER_RISING,
-				SENSOR_NAME, client_data);
+		err = request_threaded_irq(client_data->IRQ,
+				smi_gyro_irq_handler, smi130_gyro_irq_work_func,
+				IRQF_TRIGGER_RISING, SENSOR_NAME, client_data);
 		if (err < 0)
 			PDEBUG("request handle failed\n");
 	}
-	INIT_WORK(&client_data->irq_work, smi130_gyro_irq_work_func);
 #endif
 
 	err = smi130_gyro_early_buff_init(client_data);
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c
index 9d1c5cc..736c594 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c
@@ -2786,7 +2786,7 @@
 	/* Set the exception path to AP */
 	for (client_idx = 0; client_idx < IPA_CLIENT_MAX; client_idx++) {
 		ep_idx = ipa3_get_ep_mapping(client_idx);
-		if (ep_idx == -1)
+		if (ep_idx == -1 || (ep_idx >= IPA3_MAX_NUM_PIPES))
 			continue;
 
 		/* disable statuses for all modem controlled prod pipes */
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index f656728..dc9c526 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -67,6 +67,12 @@
 /* Indicate backport support for processing user cell base hint */
 #define CFG80211_USER_HINT_CELL_BASE_SELF_MANAGED 1
 
+/* Indicate backport support for external authentication in AP mode */
+#define CFG80211_EXTERNAL_AUTH_AP_SUPPORT 1
+
+/* Indicate backport support for DH IE creation/update*/
+#define CFG80211_EXTERNAL_DH_UPDATE_SUPPORT 1
+
 /**
  * DOC: Introduction
  *
@@ -739,6 +745,17 @@
 };
 
 /**
+ * enum cfg80211_ap_settings_flags - AP settings flags
+ *
+ * Used by cfg80211_ap_settings
+ *
+ * @AP_SETTINGS_EXTERNAL_AUTH_SUPPORT: AP supports external authentication
+ */
+enum cfg80211_ap_settings_flags {
+	AP_SETTINGS_EXTERNAL_AUTH_SUPPORT = BIT(0),
+};
+
+/**
  * struct cfg80211_ap_settings - AP configuration
  *
  * Used to configure an AP interface.
@@ -763,6 +780,7 @@
  * @pbss: If set, start as a PCP instead of AP. Relevant for DMG
  *	networks.
  * @beacon_rate: bitrate to be used for beacons
+ * @flags: flags, as defined in enum cfg80211_ap_settings_flags
  */
 struct cfg80211_ap_settings {
 	struct cfg80211_chan_def chandef;
@@ -783,6 +801,7 @@
 	const struct cfg80211_acl_data *acl;
 	bool pbss;
 	struct cfg80211_bitrate_mask beacon_rate;
+	u32 flags;
 };
 
 /**
@@ -2582,6 +2601,7 @@
  *	use %WLAN_STATUS_UNSPECIFIED_FAILURE if user space cannot give you
  *	the real status code for failures. Used only for the authentication
  *	response command interface (user space to driver).
+ * @pmkid: The identifier to refer a PMKSA.
  */
 struct cfg80211_external_auth_params {
 	enum nl80211_external_auth_action action;
@@ -2589,6 +2609,33 @@
 	struct cfg80211_ssid ssid;
 	unsigned int key_mgmt_suite;
 	u16 status;
+	const u8 *pmkid;
+};
+
+/**
+ * struct cfg80211_update_owe_info - OWE Information
+ *
+ * This structure provides information needed for the drivers to offload OWE
+ * (Opportunistic Wireless Encryption) processing to the user space.
+ *
+ * Commonly used across update_owe_info request and event interfaces.
+ *
+ * @peer: MAC address of the peer device for which the OWE processing
+ *	has to be done.
+ * @status: status code, %WLAN_STATUS_SUCCESS for successful OWE info
+ *	processing, use %WLAN_STATUS_UNSPECIFIED_FAILURE if user space
+ *	cannot give you the real status code for failures. Used only for
+ *	OWE update request command interface (user space to driver).
+ * @ie: IEs obtained from the peer or constructed by the user space. These are
+ *	the IEs of the remote peer in the event from the host driver and
+ *	the constructed IEs by the user space in the request interface.
+ * @ie_len: Length of IEs in octets.
+ */
+struct cfg80211_update_owe_info {
+	u8 peer[ETH_ALEN] __aligned(2);
+	u16 status;
+	const u8 *ie;
+	size_t ie_len;
 };
 
 /**
@@ -2903,6 +2950,10 @@
  *
  * @external_auth: indicates result of offloaded authentication processing from
  *     user space
+ *
+ * @update_owe_info: Provide updated OWE info to driver. Driver implementing SME
+ *	but offloading OWE processing to the user space will get the updated
+ *	DH IE through this interface.
  */
 struct cfg80211_ops {
 	int	(*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -3189,6 +3240,8 @@
 					    const bool enabled);
 	int     (*external_auth)(struct wiphy *wiphy, struct net_device *dev,
 				 struct cfg80211_external_auth_params *params);
+	int	(*update_owe_info)(struct wiphy *wiphy, struct net_device *dev,
+				   struct cfg80211_update_owe_info *owe_info);
 };
 
 /*
@@ -6185,4 +6238,14 @@
 #define wiphy_WARN(wiphy, format, args...)			\
 	WARN(1, "wiphy: %s\n" format, wiphy_name(wiphy), ##args);
 
+/**
+ * cfg80211_update_owe_info_event - Notify the peer's OWE info to user space
+ * @netdev: network device
+ * @owe_info: peer's owe info
+ * @gfp: allocation flags
+ */
+void cfg80211_update_owe_info_event(struct net_device *netdev,
+				    struct cfg80211_update_owe_info *owe_info,
+				    gfp_t gfp);
+
 #endif /* __NET_CFG80211_H */
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 39f920c..31817b8 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -1018,6 +1018,11 @@
  *	indicated by %NL80211_ATTR_WIPHY_FREQ and other attributes
  *	determining the width and type.
  *
+ * @NL80211_CMD_UPDATE_OWE_INFO: This interface allows the host driver to
+ *	offload OWE processing to user space. This intends to support
+ *	OWE AKM by the host drivers that implement SME but rely
+ *	on the user space for the cryptographic/DH IE processing in AP mode.
+ *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
@@ -1238,6 +1243,8 @@
 
 	NL80211_CMD_NOTIFY_RADAR,
 
+	NL80211_CMD_UPDATE_OWE_INFO,
+
 	/* add new commands above here */
 
 	/* used to define NL80211_CMD_MAX below */
@@ -2179,10 +2186,10 @@
  *     &enum nl80211_external_auth_action value). This is used with the
  *     &NL80211_CMD_EXTERNAL_AUTH request event.
  * @NL80211_ATTR_EXTERNAL_AUTH_SUPPORT: Flag attribute indicating that the user
- *     space supports external authentication. This attribute shall be used
- *     only with %NL80211_CMD_CONNECT request. The driver may offload
- *     authentication processing to user space if this capability is indicated
- *     in NL80211_CMD_CONNECT requests from the user space.
+ *	space supports external authentication. This attribute shall be used
+ *	with %NL80211_CMD_CONNECT and %NL80211_CMD_START_AP request. The driver
+ *	may offload authentication processing to user space if this capability
+ *	is indicated in the respective requests from the user space.
  *
  * @NUM_NL80211_ATTR: total number of nl80211_attrs available
  * @NL80211_ATTR_MAX: highest attribute number currently defined
@@ -5264,9 +5271,14 @@
  * Used by cfg80211_rx_mgmt()
  *
  * @NL80211_RXMGMT_FLAG_ANSWERED: frame was answered by device/driver.
+ * @NL80211_RXMGMT_FLAG_EXTERNAL_AUTH: Host driver intends to offload
+ *	the authentication. Exclusively defined for host drivers that
+ *	advertises the SME functionality but would like the userspace
+ *	to handle certain authentication algorithms (e.g. SAE).
  */
 enum nl80211_rxmgmt_flags {
 	NL80211_RXMGMT_FLAG_ANSWERED = 1 << 0,
+	NL80211_RXMGMT_FLAG_EXTERNAL_AUTH = 1 << 1,
 };
 
 /*
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index d9332d1..71ef07a 100755
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -3989,6 +3989,9 @@
 			return PTR_ERR(params.acl);
 	}
 
+	if (info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT])
+		params.flags |= AP_SETTINGS_EXTERNAL_AUTH_SUPPORT;
+
 	wdev_lock(wdev);
 	err = rdev_start_ap(rdev, dev, &params);
 	if (!err) {
@@ -12055,7 +12058,9 @@
 	if (!rdev->ops->external_auth)
 		return -EOPNOTSUPP;
 
-	if (!info->attrs[NL80211_ATTR_SSID])
+	if (!info->attrs[NL80211_ATTR_SSID] &&
+	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
+	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
 		return -EINVAL;
 
 	if (!info->attrs[NL80211_ATTR_BSSID])
@@ -12066,21 +12071,52 @@
 
 	memset(&params, 0, sizeof(params));
 
-	params.ssid.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
-	if (params.ssid.ssid_len == 0 ||
-	    params.ssid.ssid_len > IEEE80211_MAX_SSID_LEN)
-		return -EINVAL;
-	memcpy(params.ssid.ssid, nla_data(info->attrs[NL80211_ATTR_SSID]),
-	       params.ssid.ssid_len);
+	if (info->attrs[NL80211_ATTR_SSID]) {
+		params.ssid.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
+		if (params.ssid.ssid_len == 0 ||
+		    params.ssid.ssid_len > IEEE80211_MAX_SSID_LEN)
+			return -EINVAL;
+		memcpy(params.ssid.ssid,
+		       nla_data(info->attrs[NL80211_ATTR_SSID]),
+		       params.ssid.ssid_len);
+	}
 
 	memcpy(params.bssid, nla_data(info->attrs[NL80211_ATTR_BSSID]),
 	       ETH_ALEN);
 
 	params.status = nla_get_u16(info->attrs[NL80211_ATTR_STATUS_CODE]);
 
+	if (info->attrs[NL80211_ATTR_PMKID])
+		params.pmkid = nla_data(info->attrs[NL80211_ATTR_PMKID]);
+
 	return rdev_external_auth(rdev, dev, &params);
 }
 
+static int nl80211_update_owe_info(struct sk_buff *skb, struct genl_info *info)
+{
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
+	struct cfg80211_update_owe_info owe_info;
+	struct net_device *dev = info->user_ptr[1];
+
+	if (!rdev->ops->update_owe_info)
+		return -EOPNOTSUPP;
+
+	if (!info->attrs[NL80211_ATTR_STATUS_CODE] ||
+	    !info->attrs[NL80211_ATTR_MAC])
+		return -EINVAL;
+
+	memset(&owe_info, 0, sizeof(owe_info));
+	owe_info.status = nla_get_u16(info->attrs[NL80211_ATTR_STATUS_CODE]);
+	nla_memcpy(owe_info.peer, info->attrs[NL80211_ATTR_MAC], ETH_ALEN);
+
+	if (info->attrs[NL80211_ATTR_IE]) {
+		owe_info.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
+		owe_info.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
+	}
+
+	return rdev_update_owe_info(rdev, dev, &owe_info);
+}
+
 #define NL80211_FLAG_NEED_WIPHY		0x01
 #define NL80211_FLAG_NEED_NETDEV	0x02
 #define NL80211_FLAG_NEED_RTNL		0x04
@@ -12978,6 +13014,13 @@
 		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
 				  NL80211_FLAG_NEED_RTNL,
 	},
+	{
+		.cmd = NL80211_CMD_UPDATE_OWE_INFO,
+		.doit = nl80211_update_owe_info,
+		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+				  NL80211_FLAG_NEED_RTNL,
+	},
 };
 
 /* notification functions */
@@ -15018,6 +15061,46 @@
 }
 EXPORT_SYMBOL(cfg80211_external_auth_request);
 
+void cfg80211_update_owe_info_event(struct net_device *netdev,
+				    struct cfg80211_update_owe_info *owe_info,
+				    gfp_t gfp)
+{
+	struct wiphy *wiphy = netdev->ieee80211_ptr->wiphy;
+	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
+	struct sk_buff *msg;
+	void *hdr;
+
+	trace_cfg80211_update_owe_info_event(wiphy, netdev, owe_info);
+
+	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
+	if (!msg)
+		return;
+
+	hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_UPDATE_OWE_INFO);
+	if (!hdr)
+		goto nla_put_failure;
+
+	if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
+	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
+	    nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, owe_info->peer))
+		goto nla_put_failure;
+
+	if (!owe_info->ie_len ||
+	    nla_put(msg, NL80211_ATTR_IE, owe_info->ie_len, owe_info->ie))
+		goto nla_put_failure;
+
+	genlmsg_end(msg, hdr);
+
+	genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
+				NL80211_MCGRP_MLME, gfp);
+	return;
+
+nla_put_failure:
+	genlmsg_cancel(msg, hdr);
+	nlmsg_free(msg);
+}
+EXPORT_SYMBOL(cfg80211_update_owe_info_event);
+
 /* initialisation/exit functions */
 
 int nl80211_init(void)
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
index 091806d..a0ff6b1 100644
--- a/net/wireless/rdev-ops.h
+++ b/net/wireless/rdev-ops.h
@@ -1168,4 +1168,17 @@
 	return ret;
 }
 
+static inline int rdev_update_owe_info(struct cfg80211_registered_device *rdev,
+				       struct net_device *dev,
+				       struct cfg80211_update_owe_info *oweinfo)
+{
+	int ret = -EOPNOTSUPP;
+
+	trace_rdev_update_owe_info(&rdev->wiphy, dev, oweinfo);
+	if (rdev->ops->update_owe_info)
+		ret = rdev->ops->update_owe_info(&rdev->wiphy, dev, oweinfo);
+	trace_rdev_return_int(&rdev->wiphy, ret);
+	return ret;
+}
+
 #endif /* __CFG80211_RDEV_OPS */
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index 80ea75a..ef56df5 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -3090,6 +3090,44 @@
 		  WIPHY_PR_ARG, NETDEV_PR_ARG,
 		  BOOL_TO_STR(__entry->enabled))
 );
+
+TRACE_EVENT(rdev_update_owe_info,
+	    TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+		     struct cfg80211_update_owe_info *owe_info),
+	    TP_ARGS(wiphy, netdev, owe_info),
+	    TP_STRUCT__entry(WIPHY_ENTRY
+			     NETDEV_ENTRY
+			     MAC_ENTRY(peer)
+			     __field(u16, status)
+			     __dynamic_array(u8, ie, owe_info->ie_len)),
+	    TP_fast_assign(WIPHY_ASSIGN;
+			   NETDEV_ASSIGN;
+			   MAC_ASSIGN(peer, owe_info->peer);
+			   __entry->status = owe_info->status;
+			   memcpy(__get_dynamic_array(ie),
+				  owe_info->ie, owe_info->ie_len);),
+	    TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", peer: " MAC_PR_FMT
+		  " status %d", WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer),
+		  __entry->status)
+);
+
+TRACE_EVENT(cfg80211_update_owe_info_event,
+	    TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+		     struct cfg80211_update_owe_info *owe_info),
+	    TP_ARGS(wiphy, netdev, owe_info),
+	    TP_STRUCT__entry(WIPHY_ENTRY
+			     NETDEV_ENTRY
+			     MAC_ENTRY(peer)
+			     __dynamic_array(u8, ie, owe_info->ie_len)),
+	    TP_fast_assign(WIPHY_ASSIGN;
+			   NETDEV_ASSIGN;
+			   MAC_ASSIGN(peer, owe_info->peer);
+			   memcpy(__get_dynamic_array(ie), owe_info->ie,
+				  owe_info->ie_len);),
+	    TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", peer: " MAC_PR_FMT,
+		      WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer))
+);
+
 #endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */
 
 #undef TRACE_INCLUDE_PATH