Merge android12-gs-pixel-5.10-sc-v2 into android12-gs-pixel-5.10-sc-qpr3

Signed-off-by: Robin Peng <robinpeng@google.com>
Change-Id: I34620ef29bcf37b428ee852d3d2bfa18bf18381a
diff --git a/lwis_device.h b/lwis_device.h
index 6ecfb44..e97f257 100644
--- a/lwis_device.h
+++ b/lwis_device.h
@@ -247,6 +247,8 @@
 	int pm_hibernation;
 	/* Is device read only */
 	bool is_read_only;
+	/* Adjust thread priority */
+	int adjust_thread_priority;
 };
 
 /*
diff --git a/lwis_dt.c b/lwis_dt.c
index b31e043..76fac6e 100644
--- a/lwis_dt.c
+++ b/lwis_dt.c
@@ -815,11 +815,9 @@
 
 static int parse_pm_hibernation(struct lwis_device *lwis_dev)
 {
-	struct device *dev;
 	struct device_node *dev_node;
 
-	dev = &(lwis_dev->plat_dev->dev);
-	dev_node = dev->of_node;
+	dev_node = lwis_dev->plat_dev->dev.of_node;
 	lwis_dev->pm_hibernation = 1;
 
 	of_property_read_u32(dev_node, "pm-hibernation", &lwis_dev->pm_hibernation);
@@ -838,6 +836,18 @@
 	return 0;
 }
 
+static int parse_thread_priority(struct lwis_device *lwis_dev)
+{
+	struct device_node *dev_node;
+
+	dev_node = lwis_dev->plat_dev->dev.of_node;
+	lwis_dev->adjust_thread_priority = 0;
+
+	of_property_read_u32(dev_node, "thread-priority", &lwis_dev->adjust_thread_priority);
+
+	return 0;
+}
+
 int lwis_base_parse_dt(struct lwis_device *lwis_dev)
 {
 	struct device *dev;
@@ -940,6 +950,8 @@
 
 	parse_access_mode(lwis_dev);
 
+	parse_thread_priority(lwis_dev);
+
 	parse_bitwidths(lwis_dev);
 
 	iommus = of_find_property(dev_node, "iommus", &iommus_len);
diff --git a/lwis_transaction.c b/lwis_transaction.c
index ba1d41d..0895123 100644
--- a/lwis_transaction.c
+++ b/lwis_transaction.c
@@ -370,7 +370,14 @@
 	INIT_LIST_HEAD(&client->transaction_process_queue_tasklet);
 	tasklet_init(&client->transaction_tasklet, transaction_tasklet_func, (unsigned long)client);
 	INIT_LIST_HEAD(&client->transaction_process_queue);
-	client->transaction_wq = create_workqueue("lwistran");
+	if (client->lwis_dev->adjust_thread_priority != 0) {
+		/* Since I2C transactions can only be executed in workqueues, putting them in high
+		 * priority to avoid scheduling delays. */
+		client->transaction_wq = alloc_ordered_workqueue(
+			"lwistran-i2c", __WQ_LEGACY | WQ_MEM_RECLAIM | WQ_HIGHPRI);
+	} else {
+		client->transaction_wq = create_workqueue("lwistran");
+	}
 	INIT_WORK(&client->transaction_work, transaction_work_func);
 	client->transaction_counter = 0;
 	hash_init(client->transaction_list);