From 1445518f66b5f3d00bee5a10cf66fda0d0adae18 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ond=C5=99ej=20Jirman?= <megi@xff.cz>
Date: Mon, 14 Oct 2019 18:00:32 +0200
Subject: input: cyttsp4: Make the driver not hog the system's workqueue

The driver's work items can take 100's of ms, use a separate
thread for this.

Signed-off-by: Ondrej Jirman <megi@xff.cz>
---
 drivers/input/touchscreen/cyttsp4_core.c | 20 ++++++++++++++------
 drivers/input/touchscreen/cyttsp4_core.h |  3 ++-
 2 files changed, 16 insertions(+), 7 deletions(-)

diff --git a/drivers/input/touchscreen/cyttsp4_core.c b/drivers/input/touchscreen/cyttsp4_core.c
index d9243c9db69a..c353ac73c106 100644
--- a/drivers/input/touchscreen/cyttsp4_core.c
+++ b/drivers/input/touchscreen/cyttsp4_core.c
@@ -721,7 +721,7 @@ static void cyttsp4_queue_startup_(struct cyttsp4 *cd)
 {
 	if (cd->startup_state == STARTUP_NONE) {
 		cd->startup_state = STARTUP_QUEUED;
-		schedule_work(&cd->startup_work);
+		queue_work(cd->wq, &cd->startup_work);
 		dev_dbg(cd->dev, "%s: cyttsp4_startup queued\n", __func__);
 	} else {
 		dev_dbg(cd->dev, "%s: startup_state = %d\n", __func__,
@@ -1237,9 +1237,7 @@ static void cyttsp4_watchdog_timer(struct timer_list *t)
 
 	dev_vdbg(cd->dev, "%s: Watchdog timer triggered\n", __func__);
 
-	schedule_work(&cd->watchdog_work);
-
-	return;
+	queue_work(cd->wq, &cd->watchdog_work);
 }
 
 static int cyttsp4_request_exclusive(struct cyttsp4 *cd, void *ownptr,
@@ -2048,6 +2046,13 @@ struct cyttsp4 *cyttsp4_probe(const struct cyttsp4_bus_ops *ops,
 		goto error_disable_vdd;
 	}
 
+	cd->wq = alloc_workqueue("cyttsp4", WQ_SYSFS, 0);
+	if (!cd->wq) {
+		rc = -ENOMEM;
+		dev_err(dev, "failed to allocate workqueue\n");
+		goto error_disable_vdd;
+	}
+
 	/* Initialize device info */
 	cd->dev = dev;
 	cd->bus_ops = ops;
@@ -2071,7 +2076,7 @@ struct cyttsp4 *cyttsp4_probe(const struct cyttsp4_bus_ops *ops,
 	if (rc) {
 		dev_err(cd->dev, "failed to request IRQ %d, err: %d\n",
 			cd->irq, rc);
-		goto error_disable_vdd;
+		goto error_free_wq;
 	}
 
 	/* Setup watchdog timer */
@@ -2105,6 +2110,8 @@ struct cyttsp4 *cyttsp4_probe(const struct cyttsp4_bus_ops *ops,
 	cyttsp4_stop_wd_timer(cd);
 	pm_runtime_disable(dev);
 	cyttsp4_free_si_ptrs(cd);
+error_free_wq:
+	destroy_workqueue(cd->wq);
 error_disable_vdd:
 	gpiod_set_value_cansleep(cd->reset_gpio, 1);
 	gpiod_set_value_cansleep(cd->power_gpio, 0);
@@ -2132,8 +2139,9 @@ int cyttsp4_remove(struct cyttsp4 *cd)
 	pm_runtime_suspend(dev);
 	pm_runtime_disable(dev);
 
-	cancel_work_sync(&cd->startup_work);
 	cyttsp4_stop_wd_timer(cd);
+	cancel_work_sync(&cd->startup_work);
+	destroy_workqueue(cd->wq);
 	cyttsp4_free_si_ptrs(cd);
 	return 0;
 }
diff --git a/drivers/input/touchscreen/cyttsp4_core.h b/drivers/input/touchscreen/cyttsp4_core.h
index cff547979b28..ac2d7b303f39 100644
--- a/drivers/input/touchscreen/cyttsp4_core.h
+++ b/drivers/input/touchscreen/cyttsp4_core.h
@@ -62,7 +62,7 @@ enum cyttsp_cmd_bits {
 };
 
 /* Timeout in ms. */
-#define CY_WATCHDOG_TIMEOUT		1000
+#define CY_WATCHDOG_TIMEOUT		10000
 
 #define CY_MAX_PRINT_SIZE		512
 #ifdef VERBOSE_DEBUG
@@ -316,6 +316,7 @@ struct cyttsp4 {
 	enum cyttsp4_startup_state startup_state;
 	int int_status;
 	wait_queue_head_t wait_q;
+	struct workqueue_struct *wq;
 	int irq;
 	struct work_struct startup_work;
 	struct work_struct watchdog_work;
-- 
2.35.3

